code cleanup

This commit is contained in:
fluttershy 2025-01-13 14:40:21 +05:00
parent 209f2134ae
commit 52696a58c6
6 changed files with 120 additions and 85 deletions

View File

@ -3,8 +3,8 @@
#include <string> #include <string>
#include <exception> #include <exception>
#include <iostream> #include <iostream>
#include <tls/network.hpp> #include <tls/Network.hpp>
#include <gateway/websocket.hpp> #include <gateway/Websocket.hpp>
#include <utils/types.hpp> #include <utils/types.hpp>
using std::string; using std::string;
using std::cout; using std::cout;
@ -15,7 +15,7 @@ private:
WebSocket& web; WebSocket& web;
NetworkManager& req; NetworkManager& req;
public: public:
Channel(const json& data) : data(data), web(*WebSocket::getInstance()), req(*NetworkManager::getInstance()) {} Channel(const json& data) : data(data), web(WebSocket::getInstance()), req(NetworkManager::getInstance()) {}
string send(const json& msg) const { string send(const json& msg) const {
return req.request("POST", dapi + "/channels/" + data["d"]["channel_id"].get<string>() + "/messages", msg.dump()); return req.request("POST", dapi + "/channels/" + data["d"]["channel_id"].get<string>() + "/messages", msg.dump());
} }

View File

@ -4,8 +4,8 @@
#include <string> #include <string>
#include <exception> #include <exception>
#include <iostream> #include <iostream>
#include <tls/network.hpp> #include <tls/Network.hpp>
#include <gateway/websocket.hpp> #include <gateway/Websocket.hpp>
using std::string; using std::string;
using std::cout; using std::cout;
using std::endl; using std::endl;
@ -15,9 +15,21 @@ private:
WebSocket& web; WebSocket& web;
NetworkManager& req; NetworkManager& req;
public: public:
Message(const json& data) : data(data), web(*WebSocket::getInstance()), req(*NetworkManager::getInstance()) {}; Message(const json& data) : data(data), web(WebSocket::getInstance()), req(NetworkManager::getInstance()) {};
string send(const string& id, const json& msg) { string send(const string& id, const json& msg) {
return req.request("POST", dapi + "/channels/" + id + "/messages", msg.dump()); return req.request("POST", dapi + "/channels/" + id + "/messages", msg.dump());
} }
string getMessages(const string& id, const string& count, const string& before = "") {
if (before.empty()) {
return req.request("GET", dapi + "/channels/" + id + "/messages?limit=" + count);
}
else {
return req.request("GET", dapi + "/channels/" + id + "/messages?before=" + before + "&limit=" + count);
}
return "pizda";
}
string deleteMessage(const string& channel_id, const string& message_id) {
return req.request("DELETE", dapi + "/channels/" + channel_id + "/messages/" + message_id);
}
}; };
#endif #endif

View File

@ -2,10 +2,10 @@
#define API_USER_HPP_ #define API_USER_HPP_
#include <utils/types.hpp> #include <utils/types.hpp>
#include <string> #include <string>
#include <exception>
#include <iostream> #include <iostream>
#include <tls/network.hpp> #include <tls/Network.hpp>
#include <gateway/websocket.hpp> #include <gateway/Websocket.hpp>
#include <vector>
using std::string; using std::string;
using std::cout; using std::cout;
using std::endl; using std::endl;
@ -15,12 +15,23 @@ private:
WebSocket& web; WebSocket& web;
NetworkManager& req; NetworkManager& req;
public: public:
User(const json& data) : data(data), web(*WebSocket::getInstance()), req(*NetworkManager::getInstance()) {} User(const json& data = "") : data(data), web(WebSocket::getInstance()), req(NetworkManager::getInstance()) {}
string id() { json extract(const std::vector<string>& keys) {
return data["d"]["author"]["id"]; std::vector<string> d = { "d" };
d.insert(d.end(), keys.begin(), keys.end());
json current = data;
for (const auto& key : d) {
if (current.contains(key)) {
current = current[key];
}
else {
return "Key not found.";
}
}
return current;
} }
string me() const { virtual string me() {
return req.request("GET", dapi + "/users/@me", ""); return req.request("GET", dapi + "/users/@me");
} }
bool isBot() { bool isBot() {
try { try {

View File

@ -91,18 +91,18 @@ private:
{VOICE_STATE_UPDATE, "VOICE_STATE_UPDATE"}, {VOICE_STATE_UPDATE, "VOICE_STATE_UPDATE"},
{WEBHOOKS_UPDATE, "WEBHOOKS_UPDATE"} {WEBHOOKS_UPDATE, "WEBHOOKS_UPDATE"}
}}; }};
bool connected = false; bool connected = false, isBot;
static bool initialized, isBot; int intents;
static WebSocket* instance; std::string token;
static int i;
static std::string t;
ix::WebSocket webSocket; ix::WebSocket webSocket;
int heartbeat_interval, lastS; int heartbeat_interval, lastS;
json payload = { {"op", 1},{"d", nullptr} }, id, res; json payload = { {"op", 1},{"d", nullptr} }, id, res;
std::unordered_map<std::string_view, std::function<void(const json&)>> eventHandlers; std::unordered_map<std::string_view, std::function<void(const json&)>> eventHandlers;
WebSocket& operator=(const WebSocket&) = delete;
WebSocket(const WebSocket&) = delete;
WebSocket(const std::string& token, const int& intents, bool& isBot) : lastS(0), heartbeat_interval(-1) { WebSocket(const std::string& token, const int& intents, bool& isBot) : lastS(0), heartbeat_interval(-1) {
WebSocket::t = token; WebSocket::token = token;
WebSocket::i = intents; WebSocket::intents = intents;
WebSocket::isBot = isBot; WebSocket::isBot = isBot;
id = { id = {
{"op", 2}, {"op", 2},
@ -139,7 +139,12 @@ private:
case 10: case 10:
heartbeat_interval = res["d"]["heartbeat_interval"].get<int>(); heartbeat_interval = res["d"]["heartbeat_interval"].get<int>();
!connected ? connected = true, webSocket.send(id.dump()) : false; !connected ? connected = true, webSocket.send(id.dump()) : false;
start_heartbeat(); std::thread([this]() {
while (connected && heartbeat_interval != -1) {
std::this_thread::sleep_for(milliseconds(heartbeat_interval));
webSocket.send(payload.dump());
}
}).detach();
break; break;
case 0: case 0:
if (eventHandlers.find(res["t"].get<std::string>()) != eventHandlers.end()) { if (eventHandlers.find(res["t"].get<std::string>()) != eventHandlers.end()) {
@ -152,6 +157,7 @@ private:
webSocket.start(); webSocket.start();
} }
public: public:
/*
void sendPresenceUpdate(int statusType, const std::string& activityName) { void sendPresenceUpdate(int statusType, const std::string& activityName) {
json prsUpdate = { json prsUpdate = {
{"op", 3}, {"op", 3},
@ -164,14 +170,9 @@ public:
}; };
webSocket.send(prsUpdate.dump()); webSocket.send(prsUpdate.dump());
} }
static WebSocket* getInstance(const std::string& token = "", const int intents = 0, bool bot = true) { */
if (!instance) { static WebSocket& getInstance(const std::string& token = "", const int intents = 0, bool bot = true) {
if (token.empty() || intents == 0) { static WebSocket instance(token, intents, bot);
throw std::invalid_argument("Token or intents is empty.");
}
instance = new WebSocket(token, intents, bot);
initialized = true;
}
return instance; return instance;
} }
~WebSocket() { ~WebSocket() {
@ -179,10 +180,10 @@ public:
ix::uninitNetSystem(); ix::uninitNetSystem();
} }
std::string getToken() const { std::string getToken() const {
return isBot ? std::string("Bot " + WebSocket::t) : WebSocket::t; return isBot ? std::string("Bot " + WebSocket::token) : WebSocket::token;
} }
int getIntents() const { int getIntents() const {
return WebSocket::i; return WebSocket::intents;
} }
void on(const int event, std::function<void(const json&)> handler) { void on(const int event, std::function<void(const json&)> handler) {
eventHandlers[events[event].second] = [handler](const json& message) { eventHandlers[events[event].second] = [handler](const json& message) {
@ -199,21 +200,8 @@ public:
} }
}; };
} }
void start_heartbeat() {
std::thread([this]() {
while (connected && heartbeat_interval != -1) {
std::this_thread::sleep_for(milliseconds(heartbeat_interval));
webSocket.send(payload.dump());
}
}).detach();
}
void start() { void start() {
while (1) std::this_thread::sleep_for(1ms); while (1) std::this_thread::sleep_for(1ms);
} }
}; };
WebSocket* WebSocket::instance = nullptr;
std::string WebSocket::t = "";
int WebSocket::i = 0;
bool WebSocket::initialized = false;
bool WebSocket::isBot = true;
#endif #endif

View File

@ -7,27 +7,23 @@
#include <string> #include <string>
#include <net/if.h> #include <net/if.h>
#include <netdb.h> #include <netdb.h>
#include <unistd.h>
#include <utils/types.hpp> #include <utils/types.hpp>
#include <gateway/websocket.hpp> #include <gateway/Websocket.hpp>
using std::cout; using std::cout;
using std::cerr; using std::cerr;
using std::endl; using std::endl;
class NetworkManager { class NetworkManager {
private: private:
WebSocket& web; WebSocket& web;
static NetworkManager* instance;
SSL_CTX* ctx; SSL_CTX* ctx;
int sock = -1; int sock = -1;
std::string result;
std::unique_ptr<SSL, decltype(&SSL_free)> ssl = { nullptr, &SSL_free }; std::unique_ptr<SSL, decltype(&SSL_free)> ssl = { nullptr, &SSL_free };
void handleSSLInitErrors() { void handleSSLInitErrors() {
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
abort(); abort();
} }
void createSSLConnection(const std::string& hostname, const std::string& port) { void createSSLConnection(const std::string& hostname, const std::string& port) {
addrinfo hints = { 0 }, * res = { 0 }; addrinfo hints = { 0 }, *res = { 0 };
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(hostname.c_str(), port.c_str(), &hints, &res) != 0) { if (getaddrinfo(hostname.c_str(), port.c_str(), &hints, &res) != 0) {
cerr << "Failed to get address info for " << hostname << ":" << port << endl; cerr << "Failed to get address info for " << hostname << ":" << port << endl;
@ -57,7 +53,9 @@ private:
} }
freeaddrinfo(res); freeaddrinfo(res);
} }
NetworkManager() : ctx(nullptr), result(""), web(*WebSocket::getInstance()) { NetworkManager& operator=(const NetworkManager&) = delete;
NetworkManager(const NetworkManager&) = delete;
NetworkManager() : ctx(nullptr), web(WebSocket::getInstance()) {
if (!ctx) { if (!ctx) {
ctx = SSL_CTX_new(TLS_client_method()); ctx = SSL_CTX_new(TLS_client_method());
if (!ctx) { if (!ctx) {
@ -71,22 +69,49 @@ private:
createSSLConnection("discord.com", "443"); createSSLConnection("discord.com", "443");
} }
} }
public: std::string parseJson(const std::string& response) {
static NetworkManager* getInstance() { unsigned long jsonStart = response.find("\r\n\r\n");
if (!instance) { if (jsonStart == std::string::npos) {
instance = new NetworkManager(); return "";
} }
jsonStart += 4;
std::string jsonString = response.substr(jsonStart);
unsigned long jsonBegin = jsonString.find('['), jsonEnd = jsonString.rfind(']');
if (jsonBegin == std::string::npos || jsonEnd == std::string::npos || jsonEnd < jsonBegin) {
return "";
}
jsonString = jsonString.substr(jsonBegin, jsonEnd - jsonBegin + 1);
jsonString.erase(std::remove(jsonString.begin(), jsonString.end(), '\r'), jsonString.end());
jsonString.erase(std::remove(jsonString.begin(), jsonString.end(), '\t'), jsonString.end());
jsonString.erase(std::remove(jsonString.begin(), jsonString.end(), '\n'), jsonString.end());
jsonString.erase(std::remove(jsonString.begin(), jsonString.end(), '\\'), jsonString.end());
jsonString.erase(std::remove(jsonString.begin(), jsonString.end(), '\''), jsonString.end());
jsonString.erase(std::remove(jsonString.begin(), jsonString.end(), ' '), jsonString.end());
try {
nlohmann::json jsonData = nlohmann::json::parse(jsonString);
return jsonData.dump();
}
catch (const nlohmann::json::parse_error& e) {
return "";
}
}
public:
static NetworkManager& getInstance() {
static NetworkManager instance;
return instance; return instance;
} }
~NetworkManager() { ~NetworkManager() {
if (ctx) SSL_CTX_free(ctx); if (ctx) SSL_CTX_free(ctx);
close(sock); close(sock);
} }
const std::string& request(const std::string& method, const std::string& path, const std::string& data) { std::string request(const std::string& method, const std::string& path, const std::string& data = "") {
auto net = [this, method, path, data, bytesRead = 0, request = std::string("")]() mutable -> void { #ifdef DEBUG
request = method + " " + path + " HTTP/1.1\r\nHost: discord.com\r\nAccept: application/json\r\nContent-Type: application/json\r\n"; createSSLConnection("discord.com", "443");
request += "Authorization: " + web.getToken() + "\r\n"; #endif
request += "Content-Length: " + std::to_string(data.length()) + "\r\n"; std::string result;
auto net = [this, method, path, data, &result]() mutable {
std::string request = method + " " + path + " HTTP/1.1\r\nHost: discord.com\r\nAccept: application/json\r\nContent-Type: application/json\r\n";
request += "Authorization: " + web.getToken() + "\r\nContent-Length: " + std::to_string(data.length()) + "\r\n";
#ifdef DEBUG #ifdef DEBUG
request += "Connection: close\r\n\r\n"; request += "Connection: close\r\n\r\n";
#elif defined(RELEASE) #elif defined(RELEASE)
@ -94,21 +119,26 @@ public:
#endif #endif
request += data; request += data;
if (SSL_write(ssl.get(), request.c_str(), request.length()) <= 0) { if (SSL_write(ssl.get(), request.c_str(), request.length()) <= 0) {
cerr << "Failed to send request" << endl; std::cerr << "Failed to send request" << std::endl;
handleSSLInitErrors(); handleSSLInitErrors();
} }
chngcol("REQUEST: " + path, 192, 255, 0);
#ifdef DEBUG #ifdef DEBUG
cout << request << endl; std::vector<char> buffer(1024);
char buffer[4096]; int bytesRead;
while ((bytesRead = SSL_read(ssl.get(), buffer, sizeof(buffer))) > 0) { while ((bytesRead = SSL_read(ssl.get(), buffer.data(), buffer.size())) > 0) {
result.append(buffer); result.append(buffer.data(), bytesRead);
if (bytesRead == buffer.size()) {
buffer.resize(buffer.size() * 2);
}
} }
#endif #endif
}; };
net(); net();
#ifdef DEBUG
return parseJson(result);
#elif defined(RELEASE)
return result; return result;
#endif
} }
}; };
NetworkManager* NetworkManager::instance = nullptr;
#endif #endif

View File

@ -1,34 +1,28 @@
#define RELEASE #define RELEASE
#include <utils/json.hpp> #include <utils/json.hpp>
#include <utils/enums.hpp> #include <utils/enums.hpp>
#include <tls/network.hpp> #include <tls/Network.hpp>
#include <gateway/websocket.hpp> #include <gateway/Websocket.hpp>
#include <utils/types.hpp> #include <utils/types.hpp>
#include <api/Bot.hpp> #include <api/Bot.hpp>
#include <api/Channel.hpp> #include <api/Channel.hpp>
#include <api/Message.hpp> #include <api/Message.hpp>
#include <api/Embed.hpp> #include <api/Embed.hpp>
#include <api/Author.hpp> #include <api/Author.hpp>
#include <api/User.hpp>
#include <utils/types.hpp> #include <utils/types.hpp>
using namespace std;
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if (argc != 5) return -1; if (argc != 3) return -1;
WebSocket* bot = WebSocket::getInstance(argv[2], stoi(argv[4]), true); WebSocket* bot = &WebSocket::getInstance(argv[2], 131071);
bot->on(GatewayEvents::READY, [](const Bot<Message>& b) { bot->on(GatewayEvents::READY, [](const Bot<Message, User, Author>& b) {
cout << "started" << endl; g(0, b.net)->send("939957962972229634", j("content", "started"));
}); });
bot->on(GatewayEvents::MESSAGE_CREATE, [](const Bot<Message, Author, EmbedBuilder>& msg) { bot->on(GatewayEvents::MESSAGE_CREATE, [](const Bot<Message, User, Author>& b) {
if (g(1, msg.net)->isBot() == false) { if (!g(2, b.net)->isBot()) {
g(0, msg.net)->send("939957962972229634", j("content", g(1, msg.net)->content())); g(0, b.net)->send("939957962972229634", j("content", g(2, b.net)->content()));
cout << g(1, b.net)->extract({ "content" }).get<string>() << endl;
} }
}); });
bot->on(GatewayEvents::MESSAGE_REACTION_REMOVE, [](const Bot<Message>& msg) {
g(0, msg.net)->send("939957962972229634",
j("content", "bye"));
});
bot->on(GatewayEvents::MESSAGE_REACTION_ADD, [](const Bot<Message>& msg) {
g(0, msg.net)->send("939957962972229634", j("content", "hello"));
});
bot->start(); bot->start();
return 0; return 0;
} }