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:
Андреев Григорий 2024-08-15 13:39:42 +03:00
parent 7a1bfd81f3
commit ef3af2ec45
6 changed files with 205 additions and 103 deletions

View File

@ -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)
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)
О том как работает всё остальное можно только догадываться.

View File

@ -141,7 +141,11 @@ struct CAWebChat {
T.external_deps = {
CTargetDependenceOnExternalLibrary{"sqlite3"}
};
T.units = {"main.cpp"};
T.units = {
"main.cpp",
"initialize.cpp",
"run.cpp",
};
for (std::string& u: T.units)
u = "web_chat/" + u;
T.include_pr = "web_chat";

9
src/web_chat/actions.h Normal file
View 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

View File

@ -0,0 +1,5 @@
#include "actions.h"
void initialize_website(const json::JSON& config, const std::string& root_pw) {
}

View File

@ -1,122 +1,39 @@
#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 <engine_engine_number_9/os_utils.h>
#include <assert.h>
#include <sqlite3.h>
#include <jsonincpp/string_representation.h>
#include <libregexis024vm/vm_opcodes.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;
}
#include "actions.h"
void usage(char** argv) {
printf("Usage: %s <file with settings>\n", argv[0]);
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){
try {
een9_ASSERT_pl(argc > 0);
if (argc < 1 + 1)
if (argc != 1 + 2)
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]);
usage(argv);
}
std::string config_file = argv[1];
std::string cmd = argv[2];
std::string config_text;
een9::readFile(config_file, config_text);
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");
const json::JSON config = json::parse_str_flawless(config_text);
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"}
} },
});
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);
if (cmd == "initialize") {
const char* ROOT_PW = getenv("ROOT_PW");
een9_ASSERT(ROOT_PW, "No root password specified."
"Assign desired root password value to environment variable ROOT_PW");
std::string root_pw = ROOT_PW;
initialize_website(config, root_pw);
} else if (cmd == "run") {
run_website(config);
} else
een9_THROW("unknown action (known are 'run', 'initialize')");
} catch (std::exception& e) {
printf("System failure\n%s\n", e.what());
}

103
src/web_chat/run.cpp Normal file
View 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);
}