Advertisement
Guest User

Untitled

a guest
Aug 13th, 2022
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.93 KB | None | 0 0
  1. #include <iostream>
  2. #include <uwebsockets/App.h>
  3. #include <nlohmann/json.hpp>
  4. using namespace std;
  5. using json = nlohmann::json;
  6.  
  7. // Структура, где мы будем хранить информацию о каждом подключившемся
  8. struct UserData {
  9.     int id;
  10.     string name;
  11. };
  12.  
  13. // Чтобы записывать типы покороче
  14. typedef uWS::WebSocket<false, true, UserData>* websock;
  15.  
  16. // "отправить приватное сообщение" = PRIVATE_MSG
  17. // JSON {"command": "PRIVATE_MSG", "user_to": 11, "text" : "Эй привет 11ый!"}
  18. void process_private_msg(websock ws, json parsed_data) {
  19.     UserData* data = ws->getUserData(); // Получаем информацию о текущему пользовале
  20.  
  21.     json payload;
  22.     payload["command"] = "PRIVATE_MSG";
  23.     payload["user_from"] = data->id;
  24.     payload["text"] = parsed_data["text"];
  25.  
  26.     ws->publish("USER_" + to_string(parsed_data["user_to"]), payload.dump());
  27. }
  28.  
  29. // JSON {"command": "PUBLIC_MSG", "text" : "Всем приветы в этом чате!"}
  30. void process_public_msg(websock ws, json parsed_data) {
  31.     UserData* data = ws->getUserData();
  32.  
  33.     json payload = {
  34.         {"command", "PUBLIC_MSG"},
  35.         {"text", parsed_data["text"]},
  36.         {"user_from", data->id}
  37.     };
  38.  
  39.     ws->publish("PUBLIC_CHANNEL", payload.dump());
  40. }
  41.  
  42. // Кто в онлайне, а кто в оффлайне?
  43. // {"command": "STATUS", "online": True/False, "user_id": 10}
  44. string user_status(UserData* data, bool online) {
  45.     json payload = {
  46.         {"command", "STATUS"},
  47.         {"online", online},
  48.         {"user_id", data->id},
  49.         {"name", data->name}
  50.     };
  51.     return payload.dump();
  52. }
  53.  
  54. // Карта, ключ = айди пользователя, значения = данные пользователя
  55. map<int, UserData*> all_users;
  56.  
  57. int main()
  58. {
  59.     int latest_user_id = 10; // ID последнего подключившегося
  60.     uWS::App app = uWS::App(); // Создали приложение
  61.    
  62.     // Создали раздел "/" на сайте
  63.     app.get("/", [](auto *response, auto *request) {
  64.         response->writeHeader("Content-Type", "text/html; charset=ut8"); // Отдаем ХТМЛ
  65.         response->end("Hello, this is <b>SkillChat</b> Server C++ 5000"); // <- Вот этот ХТМЛ
  66.     });
  67.  
  68.     app.ws<UserData>("/*", {
  69.         // "[]() {}" - Лямбда - функция
  70.         // открытие соединения
  71.         // Назначить ID
  72.         // Сообщить всем что человек (такой-то) подключился
  73.         .open = [&latest_user_id](websock ws) {
  74.             UserData* data = ws->getUserData(); // Получаем данные пользователя
  75.             data->id = latest_user_id++; // Каждому следующему подключив. будет назначен следующий АЙди
  76.            
  77.             data->name = "UnnamedUser#" + to_string(data->id); // Даем временное имя
  78.            
  79.             all_users[data->id] = data; // Положить информацию о пользователе в карту
  80.  
  81.             cout << "New user connected: " << data->id << endl;
  82.  
  83.             ws->subscribe("USER_" + to_string(data->id)); // Каждого пользователя подписываем на личный канал
  84.  
  85.             ws->publish("PUBLIC_CHANNEL", user_status(data, true)); // Уведомляем всех что "новичок" подключился
  86.  
  87.             ws->subscribe("PUBLIC_CHANNEL"); // Всех-всех-всех подписываем на публичный канал
  88.  
  89.             for (auto item : all_users) {
  90.                 //item.second UserData*
  91.                 //item.first int == id
  92.                 ws->send(user_status(item.second, true), uWS::OpCode::TEXT);
  93.             }
  94.             // ToDo: уведомим новичка о всех "старичках" в чате
  95.         },
  96.         // при получении информации от клиента
  97.         // "отправить публичное сообщение" = PUBLIC_MSG
  98.         // "представиться" = SET_NAME
  99.  
  100.         .message = [](websock ws, string_view message, uWS::OpCode opcode) {
  101.             // ToDO: предусмотреть обработку исключений
  102.             json parsed_data = json::parse(message); // Распарсить JSON
  103.             string command = parsed_data["command"];
  104.  
  105.             cout << "Got command " << command << endl;
  106.  
  107.             if (command == "PRIVATE_MSG") {
  108.                 process_private_msg(ws, parsed_data);
  109.             }
  110.  
  111.             if (command == "PUBLIC_MSG") {
  112.                 process_public_msg(ws, parsed_data);
  113.             }
  114.  
  115.             // ToDo: command "SET_NAME"
  116.         },
  117.         // при закрытии соединения
  118.         // Сообщить всем что человек (такой-то) отключился
  119.         .close = [](websock ws, int, string_view) {
  120.             UserData* data = ws->getUserData();
  121.             // ToDo: Всем сообщить что пользователь отключился
  122.             ws->publish("PUBLIC_CHANNEL", user_status(data, false));
  123.             all_users.erase(data->id); // Стираем пользователя
  124.         },
  125.     });
  126.    
  127.     app.listen(9001, [](auto *) {});
  128.     app.run();
  129. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement