Compare commits

...

3 Commits

4 changed files with 85 additions and 65 deletions

View File

@ -7,5 +7,4 @@
#include <utils/functions.hpp> #include <utils/functions.hpp>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <memory>
#endif #endif

View File

@ -1,26 +1,53 @@
#ifndef GATEWAY_WEBSOCKET_HPP_ #ifndef GATEWAY_WEBSOCKET_HPP_
#define GATEWAY_WEBSOCKET_HPP_ #define GATEWAY_WEBSOCKET_HPP_
#include <includes.hpp> #include <includes.hpp>
#include <thread>
#include <ixwebsocket/IXNetSystem.h> #include <ixwebsocket/IXNetSystem.h>
#include <ixwebsocket/IXWebSocket.h> #include <ixwebsocket/IXWebSocket.h>
class WebSocket { class EventEmitter {
private:
using eventHandlers = std::function<void(const nlohmann::json&)>;
std::unordered_map<std::string, std::list<eventHandlers>> handlers;
protected:
void emit(const std::string& event, const nlohmann::json& data) {
if (handlers.find(event) != handlers.end()) {
for (const auto& handler : handlers[event]) {
handler(data);
}
}
}
public:
void on(const std::string& event, eventHandlers handler) {
handlers[event].emplace_back(handler);
}
void once(const std::string& event, eventHandlers handler) {
auto wrappedHandler = [this, event, handler](const nlohmann::json& data) {
handler(data);
off(event, handler);
};
handlers[event].emplace_back(wrappedHandler);
}
void off(const std::string& event, eventHandlers handler) {
if (handlers.find(event) != handlers.end()) {
auto& vec = handlers[event];
vec.erase(std::remove_if(vec.begin(), vec.end(), [&handler](const eventHandlers& h) {
return h.target<eventHandlers>() == handler.target<eventHandlers>();
}), vec.end());
}
}
};
class WebSocket : public EventEmitter {
private: private:
bool isBot;
int intents;
std::string token; std::string token;
int intents;
bool isBot;
ix::WebSocket webSocket; ix::WebSocket webSocket;
nlohmann::json payload = { {"op", 1},{"d", nullptr} }, id; const nlohmann::json payload = { {"op", 1}, {"d", nullptr} };
std::unordered_map<std::string, std::function<void(const nlohmann::json&)>> eventHandlers;
WebSocket& operator=(const WebSocket&) = delete; WebSocket& operator=(const WebSocket&) = delete;
WebSocket& operator=(WebSocket&&) = delete; WebSocket& operator=(WebSocket&&) = delete;
WebSocket(WebSocket&&) = delete; WebSocket(WebSocket&&) = delete;
WebSocket(const WebSocket&) = delete; WebSocket(const WebSocket&) = delete;
explicit WebSocket(const std::string& token, const int& intents, const bool& isBot) { WebSocket(const std::string& token = "", const int& intents = 0, const bool& isBot = true) : token(token), intents(intents), isBot(isBot) {
WebSocket::token = token; nlohmann::json id = {
WebSocket::intents = intents;
WebSocket::isBot = isBot;
id = {
{"op", 2}, {"op", 2},
{"d", { {"d", {
{"token", token}, {"token", token},
@ -30,12 +57,12 @@ private:
{"browser", "firefox"}, {"browser", "firefox"},
{"device", "firefox"} {"device", "firefox"}
}}, }},
//{"compress", 1}, {"compress", 1},
{"presence", { {"presence", {
{"activities", nlohmann::json::array({ {"activities", nlohmann::json::array({
{ {
//{"name", "asdsadsadsadsa"}, {"name", "meow"},
//{"type", 2} {"type", 2}
} }
})}, })},
{"status", "idle"}, {"status", "idle"},
@ -46,10 +73,11 @@ private:
}; };
ix::initNetSystem(); ix::initNetSystem();
webSocket.setUrl("wss://gateway.discord.gg/?v=10&encoding=json"); webSocket.setUrl("wss://gateway.discord.gg/?v=10&encoding=json");
webSocket.disableAutomaticReconnection(); //webSocket.disableAutomaticReconnection();
Log::create(INFO, WEBSOCKET, "ixwebsocket init"); Log::create(INFO, WEBSOCKET, "ixwebsocket init");
webSocket.setOnMessageCallback([this, res = nlohmann::json(), heartbeat_interval = 1000, connected = false](const ix::WebSocketMessagePtr& msg) mutable { webSocket.setOnMessageCallback([this, res = nlohmann::json(), heartbeat_interval = 0, connected = false, id](const ix::WebSocketMessagePtr& msg) mutable {
if (msg->type == ix::WebSocketMessageType::Message) { switch (msg->type) {
case ix::WebSocketMessageType::Message:
res = nlohmann::json::parse(msg->str); res = nlohmann::json::parse(msg->str);
Log::create(INFO, WEBSOCKET, res["op"].dump() + " " + res["t"].dump()); Log::create(INFO, WEBSOCKET, res["op"].dump() + " " + res["t"].dump());
switch (res["op"].get<int>()) { switch (res["op"].get<int>()) {
@ -64,35 +92,34 @@ private:
} }
}).detach(); }).detach();
break; break;
case 0: case 0: emit(res["t"].get<std::string>(), res); break;
if (eventHandlers.find(res["t"].get<std::string>()) != eventHandlers.end()) {
eventHandlers[res["t"].get<std::string>()](res);
} }
break; break;
} case ix::WebSocketMessageType::Error:
} else if (msg->type == ix::WebSocketMessageType::Error) {
std::cout << msg->errorInfo.reason << std::endl; std::cout << msg->errorInfo.reason << std::endl;
exit(-1); exit(-1);
break;
default:
break;
} }
}); });
webSocket.start(); webSocket.start();
} }
public: public:
/* [[maybe_unused]]
void sendPresenceUpdate(int statusType, const std::string& activityName) { void sendPresenceUpdate(const int& statusType, const std::string& activityName) {
json prsUpdate = { nlohmann::json prsUpdate = {
{"op", 3}, {"op", 3},
{"d", { {"d", {
{"since", 0}, {"since", 0},
{"activities", json::array({{"name", activityName}, {"type", 2}})}, {"activities", nlohmann::json::array({{"name", activityName}, {"type", 2}})},
{"status", statusType == 1 ? "online" : "idle"}, {"status", statusType == 1 ? "online" : "idle"},
{"afk", false} {"afk", false}
}} }}
}; };
webSocket.send(prsUpdate.dump()); webSocket.send(prsUpdate.dump());
} }
*/ static WebSocket& getInstance(const std::string& token = "", const int& intents = 0, const bool& bot = true) {
static WebSocket& getInstance(const std::string& token = "", const int intents = 0, bool bot = true) {
Log::create(INFO, WEBSOCKET, "Instance event"); Log::create(INFO, WEBSOCKET, "Instance event");
static WebSocket instance(token, intents, bot); static WebSocket instance(token, intents, bot);
return instance; return instance;
@ -107,18 +134,8 @@ public:
int getIntents() const { int getIntents() const {
return WebSocket::intents; return WebSocket::intents;
} }
void on(const std::string& event, std::function<void(const nlohmann::json&)> handler) {
eventHandlers[event] = [handler](const nlohmann::json& message) {
handler(message.get<nlohmann::json>());
};
}
void once(const std::string& event, std::function<void(const nlohmann::json&)> handler) {
eventHandlers[event] = [event, handler, isCalled = false](const nlohmann::json& message) mutable {
isCalled ? handler(message.get<nlohmann::json>()), true : isCalled = true;
};
}
void start() { void start() {
while (1) std::this_thread::sleep_for(std::chrono::milliseconds(100)); while (1) std::this_thread::sleep_for(std::chrono::milliseconds(1));
} }
}; };
#endif #endif

View File

@ -10,12 +10,13 @@ private:
WebSocket& web; WebSocket& web;
std::chrono::duration<double, std::milli> duration; std::chrono::duration<double, std::milli> duration;
NetworkManager& operator=(const NetworkManager&) = delete; NetworkManager& operator=(const NetworkManager&) = delete;
NetworkManager& operator=(NetworkManager&&) = delete;
NetworkManager(NetworkManager&&) = delete;
NetworkManager(const NetworkManager&) = delete; NetworkManager(const NetworkManager&) = delete;
NetworkManager() : web(WebSocket::getInstance()) { NetworkManager() : web(WebSocket::getInstance()) {
Log::create(INFO, NETWORK, "Network init"); Log::create(INFO, NETWORK, "Network init");
curl_global_init(CURL_GLOBAL_DEFAULT); curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init(); if (!(curl = curl_easy_init())) {
if (!curl) {
Log::create(CRITICAL, NETWORK, "Failed to initialize CURL"); Log::create(CRITICAL, NETWORK, "Failed to initialize CURL");
abort(); abort();
} }

View File

@ -3,7 +3,6 @@
#include <includes.hpp> #include <includes.hpp>
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
cxxopts::Options options("sparkle", "WIP discord bot library in C++"); cxxopts::Options options("sparkle", "WIP discord bot library in C++");
options.add_options() options.add_options()
("h,help", "Print help") ("h,help", "Print help")
("V,version", "Show version information") ("V,version", "Show version information")
@ -12,9 +11,10 @@ int main(int argc, char* argv[]) {
auto result = options.parse(argc, argv); auto result = options.parse(argc, argv);
if (result.count("version")) { if (result.count("version")) {
std::cout << "sparkle version 0.1" << std::endl; std::cout << "sparkle version 0.3" << std::endl;
return 0; return 0;
} }
if (result.count("help")) { if (result.count("help")) {
std::cout << options.help() << std::endl; std::cout << options.help() << std::endl;
return 0; return 0;
@ -36,10 +36,13 @@ int main(int argc, char* argv[]) {
bot->on(GatewayEvents::MESSAGE_CREATE, [](const Discord<Message, User, Author>& msg) { bot->on(GatewayEvents::MESSAGE_CREATE, [](const Discord<Message, User, Author>& msg) {
const auto& [message, user, author] = msg.ctx(); const auto& [message, user, author] = msg.ctx();
if (!author->isBot) { if (!author->isBot) {
message->send("939957962972229634", message->pack("content", author->avatar)); message->send("939957962972229634", message->pack("content", author->channel_id));
} }
}); });
bot->on(GatewayEvents::MESSAGE_REACTION_ADD, [](const Discord<Message>& msg) {
const auto& [message] = msg.ctx();
message->send("939957962972229634", message->pack("content", "test"));
});
bot->start(); bot->start();
return 0; return 0;
} }