Advertisement
Guest User

Untitled

a guest
Dec 10th, 2022
299
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.16 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. // user13 => server: {"command": "public_msg", "text": "Всем приветы в этом чате"}
  9. // server => all users {"command": "public_msg", "text": "...", user_from: 13}
  10. // data, ws
  11.  
  12. void process_public_msg(auto data, auto* ws) {
  13.     int user_id = ws->getUserData()->user_id;
  14.     json payload = {
  15.         {"command", data["command"]},
  16.         {"text", data["text"]},
  17.         {"user_from", user_id}
  18.     };
  19.     ws->publish("public", payload.dump());
  20.     cout << "User sent Public Message " << user_id << endl;
  21. }
  22.  
  23. // Приватные сообщения
  24. // user10 => server {"command": "private_msg", "text": "...", user_to: 20}
  25. // server => user20 {"command": "private_msg", "text": "...", user_from: 10}
  26. void process_private_msg(auto data, auto* ws) {
  27.     int user_id = ws->getUserData()->user_id;
  28.     json payload = {
  29.         {"command", data["command"]},
  30.         {"text", data["text"]},
  31.         {"user_from", user_id},
  32.     };
  33.     int user_to = data["user_to"];
  34.     ws->publish("user" + to_string(user_to), payload.dump());
  35.     cout << "User sent Private Message " << user_id << endl;
  36. }
  37.  
  38.  
  39. // {"command": "set_name", name:""}
  40. void process_set_name(auto data, auto* ws) {
  41.     int user_id = ws->getUserData()->user_id;
  42.     ws->getUserData()->name = data["name"];
  43.     cout << "User Set their Name " << user_id << endl;
  44. }
  45.  
  46.  
  47.  
  48. // Возможность указать имя command:set_name
  49. // Оповещение о подключениях command:status (список людей онлайн)
  50. // 1. Подключение нового пользователя (public)
  51. // 2. Отключение пользователя (public)
  52. // 3. Свежеподключившимся пользователям сообщить о всех кто уже онлайн  (личный)
  53. // 4. В случае смены имени (public)
  54. // server => public {"command":"status", "user_id": 11, "online": True/False, "name": "Mike"}
  55.  
  56. string process_status(auto data, bool online) {
  57.     json payload = {
  58.         {"command","status"},
  59.         {"user_id",data->user_id},
  60.         {"name", data->name},
  61.         {"online", online}
  62.     };
  63.     return payload.dump();
  64. }
  65.  
  66. struct UserData {
  67.     int user_id;
  68.     string name;
  69. };
  70.  
  71. map<int, UserData*> online_users;
  72.  
  73. int main()
  74. {
  75.     int latest_user_id = 10;
  76.  
  77.  
  78.     uWS::App app = uWS::App().ws<UserData>("/*", {
  79.         .idleTimeout = 300, // 5 min
  80.         // Вызывается при новом подключении
  81.         .open = [&latest_user_id](auto* ws) {
  82.             UserData* data = ws->getUserData();
  83.             data->user_id = latest_user_id++;
  84.             data->name = "noname";
  85.  
  86.             cout << "New user connected: " << data->user_id << endl;
  87.             ws->subscribe("public"); // подписываем всех на канал(топик) паблик
  88.             ws->subscribe("user" + to_string(data->user_id)); // подписываем на персональны топик
  89.            
  90.             ws->publish("public", process_status(data, true));
  91.  
  92.             for (auto entry : online_users) {
  93.                 ws->send(process_status(entry.second, true), uWS::OpCode::TEXT);
  94.             }
  95.  
  96.             online_users[data->user_id] = data;
  97.         },
  98.         // При получении данных от клиента
  99.         .message = [](auto* ws, std::string_view data, uWS::OpCode opCode) {
  100.             json parsed_data = json::parse(data); // ToDo: check format / handle exception
  101.  
  102.             if (parsed_data["command"] == "public_msg") {
  103.                 process_public_msg(parsed_data, ws);
  104.             }
  105.  
  106.             if (parsed_data["command"] == "private_msg") {
  107.                 process_private_msg(parsed_data, ws);
  108.             }
  109.  
  110.             if (parsed_data["command"] == "set_name") {
  111.                 process_set_name(parsed_data, ws);
  112.                 auto* data = ws->getUserData();
  113.                 ws->publish("public", process_status(data, true));
  114.             }
  115.  
  116.         },
  117.         .close = [](auto* ws, int /*code*/, std::string_view /*message*/) {
  118.             UserData *data = ws->getUserData();
  119.             online_users.erase(data->user_id);
  120.             //app.publish("public", process_status(data, false), uWS::OpCode::TEXT);
  121.         }
  122.     }).listen(9001, [](auto* listen_socket) {
  123.         if (listen_socket) {
  124.             std::cout << "Listening on port " << 9001 << std::endl;
  125.         } // http://localhost:9001/
  126.     }).run();
  127. }
  128.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement