Compare commits
No commits in common. "caf9cd17af514901b3d395bb00a8bc16e3f0bc27" and "e9efb4b12ca869a606c0d456829742e59709e2bb" have entirely different histories.
caf9cd17af
...
e9efb4b12c
@ -2,64 +2,34 @@ cmake_minimum_required(VERSION 3.10)
|
|||||||
|
|
||||||
project(sparkle)
|
project(sparkle)
|
||||||
|
|
||||||
include(GoogleTest)
|
|
||||||
|
|
||||||
set(SOURCE sources/main.cpp)
|
set(SOURCE sources/main.cpp)
|
||||||
set(LIBS ${CMAKE_SOURCE_DIR}/libs/)
|
set(LIBS ${CMAKE_SOURCE_DIR}/libs/)
|
||||||
set(INCLUDE ${CMAKE_SOURCE_DIR}/include/)
|
set(INCLUDE ${CMAKE_SOURCE_DIR}/include/)
|
||||||
set(TESTS ${CMAKE_SOURCE_DIR}/tests)
|
|
||||||
|
|
||||||
find_package(CURL REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
find_path(IXWEBSOCKET_INCLUDE_DIR ixwebsocket)
|
find_path(IXWEBSOCKET_INCLUDE_DIR ixwebsocket)
|
||||||
find_library(IXWEBSOCKET_LIBRARIES ixwebsocket)
|
find_library(IXWEBSOCKET_LIBRARIES ixwebsocket)
|
||||||
|
|
||||||
message(STATUS "IXWEBSOCKET_LIBRARIES: ${IXWEBSOCKET_LIBRARIES}")
|
|
||||||
message(STATUS "CURL_LIBRARIES: ${CURL_LIBRARIES}")
|
|
||||||
|
|
||||||
|
|
||||||
if(NOT IXWEBSOCKET_INCLUDE_DIR OR NOT IXWEBSOCKET_LIBRARIES)
|
if(NOT IXWEBSOCKET_INCLUDE_DIR OR NOT IXWEBSOCKET_LIBRARIES)
|
||||||
message(FATAL_ERROR "ixwebsocket not found")
|
message(FATAL_ERROR "ixwebsocket not found")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT CURL_INCLUDE_DIRS OR NOT CURL_LIBRARIES)
|
if(NOT OPENSSL_INCLUDE_DIR OR NOT OPENSSL_LIBRARIES)
|
||||||
message(FATAL_ERROR "curl not found")
|
message(FATAL_ERROR "openssl not found")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${SOURCE})
|
add_executable(${PROJECT_NAME} ${SOURCE})
|
||||||
#add_library(sparkles STATIC ${SOURCE})
|
|
||||||
add_executable(tests ${TESTS}/tests.cpp)
|
|
||||||
|
|
||||||
#enable_testing()
|
|
||||||
|
|
||||||
add_test(NAME network COMMAND tests)
|
|
||||||
|
|
||||||
#target_include_directories(sparkles PRIVATE ${LIBS} ${INCLUDE} ${IXWEBSOCKET_INCLUDE_DIR} ${CURL_INCLUDE_DIRS})
|
|
||||||
|
|
||||||
#target_link_libraries(sparkles PRIVATE ${IXWEBSOCKET_LIBRARIES} ${CURL_LIBRARIES})
|
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||||
${LIBS}
|
${LIBS}
|
||||||
${INCLUDE}
|
${INCLUDE}
|
||||||
|
${OPENSSL_INCLUDE_DIR}
|
||||||
${IXWEBSOCKET_INCLUDE_DIR}
|
${IXWEBSOCKET_INCLUDE_DIR}
|
||||||
${CURL_INCLUDE_DIRS}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||||
|
${OPENSSL_LIBRARIES}
|
||||||
${IXWEBSOCKET_LIBRARIES}
|
${IXWEBSOCKET_LIBRARIES}
|
||||||
${CURL_LIBRARIES}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(tests PRIVATE
|
|
||||||
${LIBS}
|
|
||||||
${INCLUDE}
|
|
||||||
${IXWEBSOCKET_INCLUDE_DIR}
|
|
||||||
${CURL_INCLUDE_DIRS}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(tests gtest
|
|
||||||
${IXWEBSOCKET_LIBRARIES}
|
|
||||||
${CURL_LIBRARIES}
|
|
||||||
gtest_main
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
@ -1,34 +1,89 @@
|
|||||||
#ifndef TLS_NETWORK_HPP_
|
#ifndef TLS_NETWORK_HPP_
|
||||||
#define TLS_NETWORK_HPP_
|
#define TLS_NETWORK_HPP_
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
#include <includes.h>
|
#include <includes.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <utils/types.hpp>
|
||||||
#include <gateway/Websocket.hpp>
|
#include <gateway/Websocket.hpp>
|
||||||
#include <curl/curl.h>
|
|
||||||
using std::string, std::cout, std::endl, nlohmann::json;
|
using std::string, std::cout, std::endl, nlohmann::json;
|
||||||
class NetworkManager {
|
class NetworkManager {
|
||||||
private:
|
private:
|
||||||
CURL* curl;
|
|
||||||
CURLcode res;
|
|
||||||
WebSocket& web;
|
WebSocket& web;
|
||||||
|
SSL_CTX* ctx;
|
||||||
|
int sock = -1;
|
||||||
|
std::unique_ptr<SSL, decltype(&SSL_free)> ssl = { nullptr, &SSL_free };
|
||||||
|
void handleSSLInitErrors() {
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
void createSSLConnection(const std::string& hostname, const std::string& port) {
|
||||||
|
Logs::create(INFO, NETWORK, "SSL connection");
|
||||||
|
addrinfo hints = { 0 }, *res = { 0 };
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
if (getaddrinfo(hostname.c_str(), port.c_str(), &hints, &res) != 0) {
|
||||||
|
Logs::create(ERROR, NETWORK, "Failed to get address info for " + hostname + ":" + port);
|
||||||
|
handleSSLInitErrors();
|
||||||
|
}
|
||||||
|
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||||
|
if (sock == -1) {
|
||||||
|
Logs::create(ERROR, NETWORK, "Socket error");
|
||||||
|
close(sock);
|
||||||
|
handleSSLInitErrors();
|
||||||
|
}
|
||||||
|
if (connect(sock, res->ai_addr, res->ai_addrlen) == -1) {
|
||||||
|
Logs::create(ERROR, NETWORK, "Failed to connect to " + hostname + ":" + port);
|
||||||
|
close(sock);
|
||||||
|
handleSSLInitErrors();
|
||||||
|
}
|
||||||
|
ssl.reset(SSL_new(ctx));
|
||||||
|
if (!ssl) {
|
||||||
|
Logs::create(ERROR, NETWORK, "Failed to create SSL structure");
|
||||||
|
close(sock);
|
||||||
|
handleSSLInitErrors();
|
||||||
|
}
|
||||||
|
SSL_set_fd(ssl.get(), sock);
|
||||||
|
if (SSL_connect(ssl.get()) != 1) {
|
||||||
|
Logs::create(ERROR, NETWORK, "SSL connection failed");
|
||||||
|
close(sock);
|
||||||
|
handleSSLInitErrors();
|
||||||
|
}
|
||||||
|
freeaddrinfo(res);
|
||||||
|
}
|
||||||
NetworkManager& operator=(const NetworkManager&) = delete;
|
NetworkManager& operator=(const NetworkManager&) = delete;
|
||||||
NetworkManager(const NetworkManager&) = delete;
|
NetworkManager(const NetworkManager&) = delete;
|
||||||
NetworkManager() : web(WebSocket::getInstance()) {
|
NetworkManager() : web(WebSocket::getInstance()) {
|
||||||
Logs::create(INFO, NETWORK, "Network init");
|
Logs::create(INFO, NETWORK, "Network init");
|
||||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
if (!ctx) {
|
||||||
curl = curl_easy_init();
|
ctx = SSL_CTX_new(TLS_client_method());
|
||||||
if (!curl) {
|
if (!ctx) {
|
||||||
Logs::create(ERROR, NETWORK, "Failed to initialize CURL");
|
Logs::create(ERROR, NETWORK, "Failed to create SSL context");
|
||||||
abort();
|
handleSSLInitErrors();
|
||||||
|
}
|
||||||
|
OPENSSL_init_ssl(0, 0);
|
||||||
|
OPENSSL_add_all_algorithms_noconf();
|
||||||
|
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
|
||||||
|
SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);
|
||||||
|
createSSLConnection("discord.com", "443");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~NetworkManager() {
|
std::string extract(const std::string& httpResponse) {
|
||||||
if (curl) {
|
unsigned long pos = httpResponse.find("\r\n\r\n");
|
||||||
curl_easy_cleanup(curl);
|
if (pos != std::string::npos) {
|
||||||
|
std::string json, chunkSizeStr;
|
||||||
|
std::istringstream stream(httpResponse.substr(pos + 4));
|
||||||
|
while (std::getline(stream, chunkSizeStr)) {
|
||||||
|
unsigned long chunkSize = std::stoul(chunkSizeStr, nullptr, 16);
|
||||||
|
if (chunkSize == 0) break;
|
||||||
|
std::string chunk(chunkSize, '\0');
|
||||||
|
stream.read(&chunk[0], chunkSize);
|
||||||
|
json.append(chunk);
|
||||||
|
stream.ignore(2);
|
||||||
}
|
}
|
||||||
curl_global_cleanup();
|
return json;
|
||||||
}
|
}
|
||||||
static unsigned long WriteCallback(void* contents, unsigned long size, unsigned long nmemb, void* userp) {
|
return "";
|
||||||
((std::string*)userp)->append((char*)contents, size * nmemb);
|
|
||||||
return size * nmemb;
|
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
static NetworkManager& getInstance() {
|
static NetworkManager& getInstance() {
|
||||||
@ -36,24 +91,44 @@ public:
|
|||||||
static NetworkManager instance;
|
static NetworkManager instance;
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
std::string request(const std::string& method, const std::string& path, const std::string& data = "") {
|
~NetworkManager() {
|
||||||
std::string response;
|
if (ctx) SSL_CTX_free(ctx);
|
||||||
if (curl) {
|
close(sock);
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, string("https://discord.com" + path).c_str());
|
|
||||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method.c_str());
|
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
|
|
||||||
curl_slist* headers = curl_slist_append(headers, "Accept: application/json");
|
|
||||||
headers = curl_slist_append(headers, "Content-Type: application/json");
|
|
||||||
headers = curl_slist_append(headers, ("Authorization: " + web.getToken()).c_str());
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
|
|
||||||
res = curl_easy_perform(curl);
|
|
||||||
if (res != 0) Logs::create(ERROR, NETWORK, "curl_easy_perform() failed: " + std::string(curl_easy_strerror(res)));
|
|
||||||
curl_slist_free_all(headers);
|
|
||||||
}
|
}
|
||||||
return response;
|
std::string request(const std::string& method, const std::string& path, const std::string& data = "", bool closeConnection = true) {
|
||||||
|
if (closeConnection) createSSLConnection("discord.com", "443");
|
||||||
|
auto net = [this, method, path, data, closeConnection, result = std::string("")]() mutable -> std::string {
|
||||||
|
std::string request = method + " " + path + " HTTP/1.1\r\n";
|
||||||
|
request += "Host: discord.com\r\n";
|
||||||
|
request += "Accept: application/json\r\n";
|
||||||
|
request += "Content-Type: application/json\r\n";
|
||||||
|
request += "Authorization: " + web.getToken() + "\r\n";
|
||||||
|
request += "Content-Length: " + std::to_string(data.length()) + "\r\n";
|
||||||
|
if (closeConnection) {
|
||||||
|
request += "Connection: close\r\n\r\n";
|
||||||
|
} else {
|
||||||
|
request += "Connection: keep-alive\r\n\r\n";
|
||||||
|
}
|
||||||
|
request += data;
|
||||||
|
if (SSL_write(ssl.get(), request.c_str(), request.length()) <= 0) {
|
||||||
|
Logs::create(ERROR, NETWORK, "Failed to send request");
|
||||||
|
handleSSLInitErrors();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
Logs::create(INFO, NETWORK, "Request " + method + " " + path);
|
||||||
|
if (closeConnection) {
|
||||||
|
std::vector<char> buffer(1024);
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = SSL_read(ssl.get(), buffer.data(), buffer.size())) > 0) {
|
||||||
|
result.append(buffer.data(), bytesRead);
|
||||||
|
if (bytesRead == buffer.size()) {
|
||||||
|
buffer.resize(buffer.size() * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return extract(result);
|
||||||
|
};
|
||||||
|
return net();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
@ -2,41 +2,15 @@
|
|||||||
#include <includes.h>
|
#include <includes.h>
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
if (argc != 3) return -1;
|
if (argc != 3) return -1;
|
||||||
WebSocket* bot = &WebSocket::getInstance(argv[2], GatewayIntents::AllIntents, false);
|
WebSocket* bot = &WebSocket::getInstance(argv[2], GatewayIntents::AllIntents);
|
||||||
bot->on(GatewayEvents::READY, [](const Bot<Message, User, Author>& msg) {
|
bot->on(GatewayEvents::READY, [](const Bot<Message, User, Author>& msg) {
|
||||||
std::string lastID = "1292591828888977589";
|
if (!g(2, msg.net)->isBot()) {
|
||||||
while (true) {
|
cout << g(0, msg.net)->send("939957962972229634", j("content", "asd")) << endl;
|
||||||
std::vector<std::string> ids;
|
|
||||||
std::cout << "Last ID: " << lastID << std::endl;
|
|
||||||
json js = json::parse(g(0, msg.net)->getMessages("956854968260890654", "100", lastID));
|
|
||||||
if (js.is_array() && !js.empty()) {
|
|
||||||
for (const auto& message : js) {
|
|
||||||
if (message["author"]["id"] == "956790566463614986") {
|
|
||||||
std::cout << "My message ID: " << message["id"].get<std::string>() << std::endl;
|
|
||||||
ids.push_back(message["id"].get<std::string>());
|
|
||||||
}
|
}
|
||||||
lastID = message["id"].get<std::string>();
|
});
|
||||||
}
|
bot->on(GatewayEvents::MESSAGE_CREATE, [](const Bot<Message, User, Author>& msg) {
|
||||||
if (ids.size() > 1) {
|
if (!g(2, msg.net)->isBot()) {
|
||||||
for (size_t x = 0; x < ids.size(); x++) {
|
cout << g(0, msg.net)->send("939957962972229634", j("content", g(2, msg.net)->content())) << endl;
|
||||||
try {
|
|
||||||
json jss = json::parse(g(0, msg.net)->deleteMessage("956854968260890654", ids[x]));
|
|
||||||
if (jss["code"].get<string>() == "20028") {
|
|
||||||
std::this_thread::sleep_for(10s);
|
|
||||||
}
|
|
||||||
std::cout << "Delete response: " << jss["message"] << ":" << jss["code"] << std::endl;
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
std::cout << "DELETED" << std::endl;
|
|
||||||
}
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cout << "No messages found or error in response." << std::endl;
|
|
||||||
}
|
|
||||||
//std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
bot->start();
|
bot->start();
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
int add(int a, int b) {
|
|
||||||
return a + b;
|
|
||||||
}
|
|
||||||
TEST(AddTest, PositiveNumbers) {
|
|
||||||
EXPECT_EQ(add(1, 2), 3);
|
|
||||||
EXPECT_EQ(add(2, 3), 5);
|
|
||||||
}
|
|
||||||
TEST(AddTest, NegativeNumbers) {
|
|
||||||
EXPECT_EQ(add(-1, -1), -2);
|
|
||||||
EXPECT_EQ(add(-1, 1), 0);
|
|
||||||
}
|
|
Reference in New Issue
Block a user