UF CHANGED README UUUUFH UH UH AAAAAAAAA I- I am COOOOMMITTING YEEEAAH! YEAH ANOTHER README CHANGE THIS IS THE UF- UH -AH I'M DOING SO MUCH JOB
This commit is contained in:
		
							parent
							
								
									7a1bfd81f3
								
							
						
					
					
						commit
						ef3af2ec45
					
				
							
								
								
									
										68
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								README.md
									
									
									
									
									
								
							| @ -1,6 +1,60 @@ | |||||||
| # ИУ9-21Б Вэб-чат C.A | # IU9 C.A. WEB CHAT | ||||||
| 
 | 
 | ||||||
| Сделан на летней практике 5-ю первокурсниками ИУ9  | C.A. stands for Collarbone Annihilation. | ||||||
|  | 
 | ||||||
|  | Сделан на летней практике 5-ю первокурсниками из ИУ9-21Б. | ||||||
|  | 
 | ||||||
|  | # Dependencies | ||||||
|  | 
 | ||||||
|  | iu9-ca-web-chat использует | ||||||
|  | - C++ | ||||||
|  | - [regexis024-build-system]( | ||||||
|  |   https://peppermintgingerbread.zip/collarbone-annihilation/regexis024-build-system | ||||||
|  |   ) | ||||||
|  | - [libregexis024]( | ||||||
|  |   https://peppermintgingerbread.zip/kme-devline/libregexis024 | ||||||
|  |   ) | ||||||
|  | - [libjsonincpp]( | ||||||
|  |   https://peppermintgingerbread.zip/collarbone-annihilation/libjsonincpp | ||||||
|  |   ) | ||||||
|  | - [sqlite3]( | ||||||
|  |   https://www.sqlite.org | ||||||
|  |   ) | ||||||
|  | - pkg-config и pkg-config файлики для всех этих зависимостей | ||||||
|  | 
 | ||||||
|  | Сервис так же использует библиотеки engine_engine_number_9 и new_york_transit_line, | ||||||
|  | размещённые прямо в репозитории. | ||||||
|  | 
 | ||||||
|  | Работает только на unix системах. | ||||||
|  | 
 | ||||||
|  | # Compilation | ||||||
|  | 
 | ||||||
|  | ```sh | ||||||
|  | ./building/build_build_sytem.sh | ||||||
|  | ./building/main bi ./ "absolute/path/to/installation/root" | ||||||
|  | ``` | ||||||
|  | # Usage | ||||||
|  | 
 | ||||||
|  | Помимо самого бинарника нужен файл с настройками сервиса. Формат настроек: JSON. | ||||||
|  | Комментарии не поддерживаются. Пример такого файла находится в example/config.json. | ||||||
|  | Вместе с бинарным фалом так же распространяются ассеты, необъходимые для работы сайта. | ||||||
|  | Их можно найти в папке assets. В настроках (поле `["assets"]`) указывается путь до | ||||||
|  | папки с ассетами. Путь может быть как абсолютным, так и относительным к рабочей директории. | ||||||
|  | Поле настроек `["database"]` указывает как соединиться с базой данных. | ||||||
|  | Поддерживается только база данных sqlite. Поддерживается только хранение в файле. | ||||||
|  | Поле `["database"]["file"]` указывает путь где хранится sqlite база данных. | ||||||
|  | 
 | ||||||
|  | Перед тем как использовать сервис нужно его проинициализировать (а точнее проинициализировать | ||||||
|  | базу данных): | ||||||
|  | 
 | ||||||
|  | `ROOT_PW="<your desired root password>" iu9-ca-web-chat /path/to/config.json initialize` | ||||||
|  | 
 | ||||||
|  | Переменная окружения `ROOT_PW` читается для устаановки пароля root пользователю раз и навсегда. | ||||||
|  | Далее можно запускать сервис: | ||||||
|  | 
 | ||||||
|  | `iu9-ca-web-chat /path/to/config.json run` | ||||||
|  | 
 | ||||||
|  | Для остановки сервиса киньте ему SIGTERM или SIGINT. | ||||||
| 
 | 
 | ||||||
| # Список участников | # Список участников | ||||||
| 
 | 
 | ||||||
| @ -10,3 +64,13 @@ | |||||||
| 4. [Каримов Адель](https://gitflic.ru/user/ra1n) | 4. [Каримов Адель](https://gitflic.ru/user/ra1n) | ||||||
| 5. [Яковлев Антон](https://gitflic.ru/user/yakovlevanton) | 5. [Яковлев Антон](https://gitflic.ru/user/yakovlevanton) | ||||||
| 
 | 
 | ||||||
|  | # Комментарии (для разработчиков) | ||||||
|  | 
 | ||||||
|  | Зачем писать комментарии в коде, если можно их вынести в отдельные пдф-ки? | ||||||
|  | 
 | ||||||
|  | - [API сервиса]( | ||||||
|  |   https://peppermintgingerbread.zip/collarbone-annihilation/iu9-ca-chat-api) | ||||||
|  | - [Доки New York Transit Line]( | ||||||
|  |   https://peppermintgingerbread.zip/collarbone-annihilation/new_york_transit_line_documentation_rus) | ||||||
|  | 
 | ||||||
|  | О том как работает всё остальное можно только догадываться. | ||||||
|  | |||||||
| @ -141,7 +141,11 @@ struct CAWebChat { | |||||||
|             T.external_deps = { |             T.external_deps = { | ||||||
|                 CTargetDependenceOnExternalLibrary{"sqlite3"} |                 CTargetDependenceOnExternalLibrary{"sqlite3"} | ||||||
|             }; |             }; | ||||||
|             T.units = {"main.cpp"}; |             T.units = { | ||||||
|  |                 "main.cpp", | ||||||
|  |                 "initialize.cpp", | ||||||
|  |                 "run.cpp", | ||||||
|  |             }; | ||||||
|             for (std::string& u: T.units) |             for (std::string& u: T.units) | ||||||
|                 u = "web_chat/" + u; |                 u = "web_chat/" + u; | ||||||
|             T.include_pr = "web_chat"; |             T.include_pr = "web_chat"; | ||||||
|  | |||||||
							
								
								
									
										9
									
								
								src/web_chat/actions.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/web_chat/actions.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | #ifndef IU9_CA_WEB_CHAT_ACTIONS_H | ||||||
|  | #define IU9_CA_WEB_CHAT_ACTIONS_H | ||||||
|  | 
 | ||||||
|  | #include <jsonincpp/jsonobj.h> | ||||||
|  | 
 | ||||||
|  | void run_website(const json::JSON& config); | ||||||
|  | void initialize_website(const json::JSON& config, const std::string& root_pw); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										5
									
								
								src/web_chat/initialize.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/web_chat/initialize.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | #include "actions.h" | ||||||
|  | 
 | ||||||
|  | void initialize_website(const json::JSON& config, const std::string& root_pw) { | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -1,122 +1,39 @@ | |||||||
| #include <engine_engine_number_9/baza_throw.h> | #include <engine_engine_number_9/baza_throw.h> | ||||||
| #include <engine_engine_number_9/running_mainloop.h> | #include <engine_engine_number_9/os_utils.h> | ||||||
| #include <engine_engine_number_9/http_structures/response_gen.h> |  | ||||||
| #include <signal.h> |  | ||||||
| #include <engine_engine_number_9/connecting_assets/static_asset_manager.h> |  | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
| #include <sqlite3.h> |  | ||||||
| #include <jsonincpp/string_representation.h> | #include <jsonincpp/string_representation.h> | ||||||
| #include <libregexis024vm/vm_opcodes.h> | #include "actions.h" | ||||||
| #include <engine_engine_number_9/form_data_structure/urlencoded_query.h> |  | ||||||
| #include <new_york_transit_line/templater.h> |  | ||||||
| 
 |  | ||||||
| bool termination = false; |  | ||||||
| 
 |  | ||||||
| void sigterm_action(int) { |  | ||||||
|     termination = true; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void usage(char** argv) { | void usage(char** argv) { | ||||||
|     printf("Usage: %s <file with settings>\n", argv[0]); |     printf("Usage: %s <file with settings>\n", argv[0]); | ||||||
|     exit(1); |     exit(1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::string unsafe_client_request_stringification(const een9::ClientRequest& req) { |  | ||||||
|     std::string text = "\n\nGot some cool stuff\n"; |  | ||||||
|     text += (req.method + " " + req.uri_path + " " + req.http_version + "\n"); |  | ||||||
|     for (auto& p: req.headers) { |  | ||||||
|         text += p.first; text += ": "; text += p.second; text += "\n"; |  | ||||||
|     } |  | ||||||
|     text += "Body\n"; text += req.body; text += "\n"; |  | ||||||
|     return text; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char** argv){ | int main(int argc, char** argv){ | ||||||
|     try { |     try { | ||||||
|         een9_ASSERT_pl(argc > 0); |         een9_ASSERT_pl(argc > 0); | ||||||
|         if (argc < 1 + 1) |         if (argc != 1 + 2) | ||||||
|             usage(argv); |             usage(argv); | ||||||
|         if (!een9::isRegularFile(argv[1]) || !een9::endsIn(argv[1], ".json")) { |         std::string config_file = argv[1]; | ||||||
|  |         if (!een9::isRegularFile(config_file) || !een9::endsIn(config_file, ".json")) { | ||||||
|             printf("\"%s\" is not a json file\n", argv[1]); |             printf("\"%s\" is not a json file\n", argv[1]); | ||||||
|             usage(argv); |             usage(argv); | ||||||
|         } |         } | ||||||
|         std::string config_file = argv[1]; |         std::string cmd = argv[2]; | ||||||
| 
 |  | ||||||
|         std::string config_text; |         std::string config_text; | ||||||
|         een9::readFile(config_file, config_text); |         een9::readFile(config_file, config_text); | ||||||
|         json::JSON config = json::parse_str_flawless(config_text); |         const json::JSON config = json::parse_str_flawless(config_text); | ||||||
|         een9_ASSERT(config.isDictionary(), "config root is not dictionary"); |  | ||||||
|         een9_ASSERT(config["assets"].g().isString(), "config[\"\assets\"] is not string"); |  | ||||||
|         std::string assets_dir = config["assets"].g().asString(); |  | ||||||
|         een9_ASSERT(een9::isDirectory(assets_dir), "\"" + assets_dir + "\" is not a directory"); |  | ||||||
| 
 | 
 | ||||||
|         een9::StaticAssetManagerSlaveModule samI; |         if (cmd == "initialize") { | ||||||
|         samI.update({ |             const char* ROOT_PW = getenv("ROOT_PW"); | ||||||
|             een9::StaticAssetManagerRule{assets_dir + "/css", "/assets/css", {{".css", "text/css"}} }, |             een9_ASSERT(ROOT_PW, "No root password specified." | ||||||
|             een9::StaticAssetManagerRule{assets_dir + "/js", "/assets/js", {{".js", "text/js"}} }, |                                  "Assign desired root password value to environment variable ROOT_PW"); | ||||||
|             een9::StaticAssetManagerRule{assets_dir + "/img", "/assets/img", { |             std::string root_pw = ROOT_PW; | ||||||
|                 {".jpg", "image/jpg"}, {".png", "image/png"}, {".svg", "image/svg+xml"} |             initialize_website(config, root_pw); | ||||||
|             } }, |         } else if (cmd == "run") { | ||||||
|         }); |             run_website(config); | ||||||
| 
 |         } else | ||||||
|         json::JSON& config_presentation = config["presentation"].g(); |             een9_THROW("unknown action (known are 'run', 'initialize')"); | ||||||
| 
 |  | ||||||
|         /* Because templaters use libjsonincpp, they can't be READ by two thread simultaneously */ |  | ||||||
|         std::vector<std::unique_ptr<nytl::Templater>> templaters_copies(8); |  | ||||||
|         for (int i = 0; i < 8; i++) { |  | ||||||
|             templaters_copies[i] = std::make_unique<nytl::Templater>( |  | ||||||
|                 nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}}); |  | ||||||
|             templaters_copies[i]->update(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // printf("%s\n", templaters_copies[0]->render("list-rooms", {&config_presentation}).c_str());
 |  | ||||||
|         // return 0;
 |  | ||||||
| 
 |  | ||||||
|         een9::MainloopParameters params; |  | ||||||
|         params.guest_core = [&samI, &templaters_copies, config_presentation] |  | ||||||
|         (const een9::SlaveTask& task, const een9::ClientRequest& req, een9::worker_id_t worker_id) -> std::string { |  | ||||||
|             een9_ASSERT_pl(0 <= worker_id && worker_id < templaters_copies.size()); |  | ||||||
|             nytl::Templater& templater = *templaters_copies[worker_id]; |  | ||||||
|             een9::StaticAsset sa; |  | ||||||
|             int ret; |  | ||||||
|             // printf("%s", unsafe_client_request_stringification(req).c_str());
 |  | ||||||
|             // if (req.uri_path == "/output") {
 |  | ||||||
|             //     std::string text = unsafe_client_request_stringification(req);
 |  | ||||||
|             //     return een9::form_http_server_response_200("text/plain", text);
 |  | ||||||
|             // }
 |  | ||||||
|             auto rteee = [&](const std::string& el_name, bool pass_phr) -> std::string { |  | ||||||
|                 std::string page = templater.render(el_name, |  | ||||||
|                     pass_phr ? std::vector<const json::JSON*>{&config_presentation} : std::vector<const json::JSON*>{}); |  | ||||||
|                 return een9::form_http_server_response_200("text/html", page); |  | ||||||
|             }; |  | ||||||
|             if (req.uri_path == "/" || req.uri_path == "/list-rooms") { |  | ||||||
|                 return rteee("list-rooms", true); |  | ||||||
|             } |  | ||||||
|             if (req.uri_path == "/chat") { |  | ||||||
|                 return rteee("chat", false); |  | ||||||
|             } |  | ||||||
|             if (req.uri_path == "/profile") { |  | ||||||
|                 return rteee("profile", false); |  | ||||||
|             } |  | ||||||
|             if (req.uri_path == "/registration") { |  | ||||||
|                 return rteee("registration", false); |  | ||||||
|             } |  | ||||||
|             /* Trying to interpret request as asset lookup */ |  | ||||||
|             ret = samI.get_asset(req.uri_path, sa); |  | ||||||
|             if (ret >= 0) { |  | ||||||
|                 return een9::form_http_server_response_200(sa.type, sa.content); |  | ||||||
|             } |  | ||||||
|             return een9::form_http_server_response_404("text/html", "<h1> Not found! </h1>"); |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         params.ports_to_listen = {1025}; |  | ||||||
|         params.slave_number = 8; |  | ||||||
|         params.open_admin_listener = false; |  | ||||||
| 
 |  | ||||||
|         signal(SIGINT, sigterm_action); |  | ||||||
|         signal(SIGTERM, sigterm_action); |  | ||||||
| 
 |  | ||||||
|         een9::electric_boogaloo(params, termination); |  | ||||||
|     } catch (std::exception& e) { |     } catch (std::exception& e) { | ||||||
|         printf("System failure\n%s\n", e.what()); |         printf("System failure\n%s\n", e.what()); | ||||||
|     } |     } | ||||||
|  | |||||||
							
								
								
									
										103
									
								
								src/web_chat/run.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/web_chat/run.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | |||||||
|  | #include "actions.h" | ||||||
|  | 
 | ||||||
|  | #include <engine_engine_number_9/baza_throw.h> | ||||||
|  | #include <engine_engine_number_9/running_mainloop.h> | ||||||
|  | #include <engine_engine_number_9/http_structures/response_gen.h> | ||||||
|  | #include <signal.h> | ||||||
|  | #include <engine_engine_number_9/connecting_assets/static_asset_manager.h> | ||||||
|  | #include <assert.h> | ||||||
|  | #include <engine_engine_number_9/form_data_structure/urlencoded_query.h> | ||||||
|  | #include <new_york_transit_line/templater.h> | ||||||
|  | #include <sqlite3.h> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | bool termination = false; | ||||||
|  | 
 | ||||||
|  | void sigterm_action(int) { | ||||||
|  |     termination = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::string unsafe_client_request_stringification(const een9::ClientRequest& req) { | ||||||
|  |     std::string text = "\n\nGot some cool stuff\n"; | ||||||
|  |     text += (req.method + " " + req.uri_path + " " + req.http_version + "\n"); | ||||||
|  |     for (auto& p: req.headers) { | ||||||
|  |         text += p.first; text += ": "; text += p.second; text += "\n"; | ||||||
|  |     } | ||||||
|  |     text += "Body\n"; text += req.body; text += "\n"; | ||||||
|  |     return text; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void run_website(const json::JSON& config) { | ||||||
|  |     een9_ASSERT(config["assets"].g().isString(), "config[\"\assets\"] is not string"); | ||||||
|  |     std::string assets_dir = config["assets"].g().asString(); | ||||||
|  |     een9_ASSERT(een9::isDirectory(assets_dir), "\"" + assets_dir + "\" is not a directory"); | ||||||
|  | 
 | ||||||
|  |     een9::StaticAssetManagerSlaveModule samI; | ||||||
|  |         samI.update({ | ||||||
|  |             een9::StaticAssetManagerRule{assets_dir + "/css", "/assets/css", {{".css", "text/css"}} }, | ||||||
|  |             een9::StaticAssetManagerRule{assets_dir + "/js", "/assets/js", {{".js", "text/js"}} }, | ||||||
|  |             een9::StaticAssetManagerRule{assets_dir + "/img", "/assets/img", { | ||||||
|  |                 {".jpg", "image/jpg"}, {".png", "image/png"}, {".svg", "image/svg+xml"} | ||||||
|  |             } }, | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         const json::JSON& config_presentation = config["presentation"].g(); | ||||||
|  | 
 | ||||||
|  |         /* Because templaters use libjsonincpp, they can't be READ by two thread simultaneously */ | ||||||
|  |         std::vector<std::unique_ptr<nytl::Templater>> templaters_copies(8); | ||||||
|  |         for (int i = 0; i < 8; i++) { | ||||||
|  |             templaters_copies[i] = std::make_unique<nytl::Templater>( | ||||||
|  |                 nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}}); | ||||||
|  |             templaters_copies[i]->update(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // printf("%s\n", templaters_copies[0]->render("list-rooms", {&config_presentation}).c_str());
 | ||||||
|  |         // return 0;
 | ||||||
|  | 
 | ||||||
|  |         een9::MainloopParameters params; | ||||||
|  |         params.guest_core = [&samI, &templaters_copies, config_presentation] | ||||||
|  |         (const een9::SlaveTask& task, const een9::ClientRequest& req, een9::worker_id_t worker_id) -> std::string { | ||||||
|  |             een9_ASSERT_pl(0 <= worker_id && worker_id < templaters_copies.size()); | ||||||
|  |             nytl::Templater& templater = *templaters_copies[worker_id]; | ||||||
|  |             een9::StaticAsset sa; | ||||||
|  |             int ret; | ||||||
|  |             // printf("%s", unsafe_client_request_stringification(req).c_str());
 | ||||||
|  |             // if (req.uri_path == "/output") {
 | ||||||
|  |             //     std::string text = unsafe_client_request_stringification(req);
 | ||||||
|  |             //     return een9::form_http_server_response_200("text/plain", text);
 | ||||||
|  |             // }
 | ||||||
|  |             auto rteee = [&](const std::string& el_name, bool pass_phr) -> std::string { | ||||||
|  |                 std::string page = templater.render(el_name, | ||||||
|  |                     pass_phr ? std::vector<const json::JSON*>{&config_presentation} : std::vector<const json::JSON*>{}); | ||||||
|  |                 return een9::form_http_server_response_200("text/html", page); | ||||||
|  |             }; | ||||||
|  |             if (req.uri_path == "/" || req.uri_path == "/list-rooms") { | ||||||
|  |                 return rteee("list-rooms", true); | ||||||
|  |             } | ||||||
|  |             if (req.uri_path == "/chat") { | ||||||
|  |                 return rteee("chat", false); | ||||||
|  |             } | ||||||
|  |             if (req.uri_path == "/profile") { | ||||||
|  |                 return rteee("profile", false); | ||||||
|  |             } | ||||||
|  |             if (req.uri_path == "/registration") { | ||||||
|  |                 return rteee("registration", false); | ||||||
|  |             } | ||||||
|  |             /* Trying to interpret request as asset lookup */ | ||||||
|  |             ret = samI.get_asset(req.uri_path, sa); | ||||||
|  |             if (ret >= 0) { | ||||||
|  |                 return een9::form_http_server_response_200(sa.type, sa.content); | ||||||
|  |             } | ||||||
|  |             return een9::form_http_server_response_404("text/html", "<h1> Not found! </h1>"); | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         params.ports_to_listen = {1025}; | ||||||
|  |         params.slave_number = 8; | ||||||
|  |         params.open_admin_listener = false; | ||||||
|  | 
 | ||||||
|  |         signal(SIGINT, sigterm_action); | ||||||
|  |         signal(SIGTERM, sigterm_action); | ||||||
|  | 
 | ||||||
|  |         een9::electric_boogaloo(params, termination); | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user