This commit is contained in:
fluttershy 2025-01-30 23:05:59 +05:00
parent d75860b300
commit 5a34d87814
19 changed files with 96 additions and 27788 deletions

6
.clang-tidy Normal file
View File

@ -0,0 +1,6 @@
Checks: >
clang-analyzer-*,
modernize-*,
performance-*,
bugprone-*,
cppcoreguidelines-*

View File

@ -4,23 +4,18 @@ project(sparkle)
#target_precompile_headers(${PROJECT_NAME} PRIVATE pch.h) #target_precompile_headers(${PROJECT_NAME} PRIVATE pch.h)
include(GoogleTest) #include(GoogleTest)
#set(CMAKE_EXPORT_COMPILE_COMMANDS OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)
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) #set(TESTS ${CMAKE_SOURCE_DIR}/tests)
set(ADDITIONAL_CXX_FLAGS_DEBUG "-march=native -O0 -pipe -Wall -Wextra -Wpedantic -Werror -Wconversion -Wuninitialized -Wsign-conversion -Wshadow -fsanitize=address") #-Werror
set(ADDITIONAL_CXX_FLAGS_RELEASE "-march=native -O2 -pipe -Wall -Wextra -Wpedantic -Werror -Wconversion -Wuninitialized -Wsign-conversion -Wshadow -flto=full") set(ADDITIONAL_CXX_FLAGS_DEBUG "-march=native -O0 -pipe -Wall -Wextra -Wpedantic -Wconversion -Wuninitialized -Wsign-conversion -Wshadow -fsanitize=address")
set(ADDITIONAL_CXX_FLAGS_RELEASE "-march=native -O2 -pipe -Wall -Wextra -Wpedantic -Wconversion -Wuninitialized -Wsign-conversion -Wshadow -flto=full")
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE "${ADDITIONAL_CXX_FLAGS_RELEASE}")
message(STATUS "cflags: ${CMAKE_CXX_FLAGS_RELEASE}")
endif()
if(CMAKE_BUILD_TYPE) if(CMAKE_BUILD_TYPE)
if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(CMAKE_BUILD_TYPE STREQUAL "Debug")
@ -32,6 +27,10 @@ if(CMAKE_BUILD_TYPE)
set(CMAKE_CXX_FLAGS_RELEASE "${ADDITIONAL_CXX_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS_RELEASE "${ADDITIONAL_CXX_FLAGS_RELEASE}")
message(STATUS "cflags: ${CMAKE_CXX_FLAGS_RELEASE}") message(STATUS "cflags: ${CMAKE_CXX_FLAGS_RELEASE}")
endif() endif()
elseif(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE "${ADDITIONAL_CXX_FLAGS_RELEASE}")
message(STATUS "cflags: ${CMAKE_CXX_FLAGS_RELEASE}")
endif() endif()
file(GLOB NETWORK_SOURCES libs/network/*.cpp) file(GLOB NETWORK_SOURCES libs/network/*.cpp)
@ -53,12 +52,6 @@ message(STATUS "Current compiler: ${CMAKE_CXX_COMPILER}")
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
add_executable(${PROJECT_NAME} ${SOURCE} ${NETWORK_SOURCES} ${WEBSOCKET_SOURCES}) add_executable(${PROJECT_NAME} ${SOURCE} ${NETWORK_SOURCES} ${WEBSOCKET_SOURCES})
#add_library(sparkles STATIC ${SOURCE})
#add_executable(tests ${TESTS}/tests.cpp)
#enable_testing()
#add_test(NAME NetworkManagerTest COMMAND tests)
target_include_directories(${PROJECT_NAME} PRIVATE target_include_directories(${PROJECT_NAME} PRIVATE
${LIBS} ${LIBS}
@ -72,6 +65,13 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
${CURL_LIBRARIES} ${CURL_LIBRARIES}
) )
#add_library(sparkles STATIC ${SOURCE})
#add_executable(tests ${TESTS}/tests.cpp)
#enable_testing()
#add_test(NAME NetworkManagerTest COMMAND tests)
#target_include_directories(tests PRIVATE #target_include_directories(tests PRIVATE
# ${LIBS} # ${LIBS}
# ${INCLUDE} # ${INCLUDE}

View File

@ -6,7 +6,8 @@ Library for creating Discord bots.
### Required Libraries ### Required Libraries
- `curl` - `curl`
- `ixwebsocket` - `ixwebsocket`
- `nlohmann-json`
- `cxxopts`
### Build Instructions ### Build Instructions
```sh ```sh
git clone http://applejack.ygg/fluttershy/sparkle.git && cd sparkle git clone http://applejack.ygg/fluttershy/sparkle.git && cd sparkle

View File

@ -1,11 +1,11 @@
#ifndef INCLUDE_INCLUDES_HPP_ #ifndef INCLUDE_INCLUDES_HPP_
#define INCLUDE_INCLUDES_HPP_ #define INCLUDE_INCLUDES_HPP_
#include <utils/types.hpp> #include <utils/types.hpp>
#include <utils/json.hpp> #include <nlohmann/json.hpp>
#include <utils/log.hpp> #include <utils/log.hpp>
#include <utils/enums.hpp> #include <utils/enums.hpp>
#include <utils/functions.hpp> #include <utils/functions.hpp>
#include <utils/cxxopts.hpp> #include <cxxopts.hpp>
#include <iostream> #include <iostream>
#include <string> #include <string>
#endif #endif

View File

@ -8,7 +8,7 @@ private:
WebSocket& web; WebSocket& web;
NetworkManager& req; NetworkManager& req;
public: public:
__deprecated_t("requires update") _deprecated_t("requires update")
struct Channel { struct Channel {
std::string channel_id; std::string channel_id;
std::string global_name; std::string global_name;
@ -38,7 +38,7 @@ public:
isPinned(functions::testValue<bool>(data, { "d", "pinned" }).value_or(false)), isPinned(functions::testValue<bool>(data, { "d", "pinned" }).value_or(false)),
isBot(functions::testValue<bool>(data, { "d", "author", "bot" }).value_or(false)) { isBot(functions::testValue<bool>(data, { "d", "author", "bot" }).value_or(false)) {
} }
std::string send(const nlohmann::json& msg) { auto send(const nlohmann::json& msg) -> std::string {
return req.request(HttpMethods::POST, DiscordEndpoints::details::latest + "/channels/" + data["d"]["channel_id"].get<std::string>() + "/messages", msg.dump()); return req.request(HttpMethods::POST, DiscordEndpoints::details::latest + "/channels/" + data["d"]["channel_id"].get<std::string>() + "/messages", msg.dump());
} }
}; };

View File

@ -9,7 +9,7 @@ private:
public: public:
Discord(const nlohmann::json& data) : data(data), net(std::make_tuple(std::make_unique<Args>(data)...)) {} Discord(const nlohmann::json& data) : data(data), net(std::make_tuple(std::make_unique<Args>(data)...)) {}
template<class T> template<class T>
__deprecated_t("Use ctx() instead") _deprecated_t("Use ctx() instead")
auto& get() const { auto& get() const {
return *std::get<std::unique_ptr<T>>(net); return *std::get<std::unique_ptr<T>>(net);
} }

View File

@ -8,11 +8,11 @@ private:
WebSocket& web; WebSocket& web;
NetworkManager& req; NetworkManager& req;
public: public:
Message(const nlohmann::json& data) : data(data), web(WebSocket::getInstance()), req(NetworkManager::getInstance()) {}; Message(const nlohmann::json& json) : data(json), web(WebSocket::getInstance()), req(NetworkManager::getInstance()) {};
std::string send(const std::string& id, const nlohmann::json& msg) { auto send(const std::string& id, const nlohmann::json& msg) -> std::string {
return req.request(HttpMethods::POST, DiscordEndpoints::details::latest + "/channels/" + id + "/messages", msg.dump()); return req.request(HttpMethods::POST, DiscordEndpoints::details::latest + "/channels/" + id + "/messages", msg.dump());
} }
std::string getMessages(const std::string& id, const std::string& count, const std::string& before = "") { auto getMessages(const std::string& id, const std::string& count, const std::string& before = "") -> std::string {
if (before.empty()) { if (before.empty()) {
return req.request(HttpMethods::GET, DiscordEndpoints::details::latest + "/channels/" + id + "/messages?limit=" + count); return req.request(HttpMethods::GET, DiscordEndpoints::details::latest + "/channels/" + id + "/messages?limit=" + count);
} else { } else {
@ -20,10 +20,10 @@ public:
} }
return ""; return "";
} }
std::string deleteMessage(const std::string& channel_id, const std::string& message_id) { auto deleteMessage(const std::string& channel_id, const std::string& message_id) -> std::string {
return req.request(HttpMethods::DELETE, DiscordEndpoints::details::latest + "/channels/" + channel_id + "/messages/" + message_id); return req.request(HttpMethods::DELETE, DiscordEndpoints::details::latest + "/channels/" + channel_id + "/messages/" + message_id);
} }
nlohmann::json pack(const nlohmann::json& key, const std::string& value) const { _nodiscard auto pack(const nlohmann::json& key, const std::string& value) const -> nlohmann::json {
return { { key, value } }; return { { key, value } };
} }
struct Api { struct Api {
@ -34,8 +34,5 @@ public:
return req.getLatency(); return req.getLatency();
} }
}; };
std::string str() const {
return std::string(data);
}
}; };
#endif #endif

View File

@ -17,7 +17,7 @@ public:
} }
} }
bool isBot; bool isBot;
nlohmann::json extract(const std::vector<std::string>& keys) { auto extract(const std::vector<std::string>& keys) -> nlohmann::json {
std::vector<std::string> d = { "d" }; std::vector<std::string> d = { "d" };
d.insert(d.end(), keys.begin(), keys.end()); d.insert(d.end(), keys.begin(), keys.end());
nlohmann::json current = data; nlohmann::json current = data;
@ -30,7 +30,7 @@ public:
} }
return current; return current;
}; };
std::string me() { auto me() -> std::string {
return req.request(HttpMethods::GET, DiscordEndpoints::details::latest + "/users/@me"); return req.request(HttpMethods::GET, DiscordEndpoints::details::latest + "/users/@me");
} }
}; };

View File

@ -1,8 +1,8 @@
#include "network.hpp" #include "network.hpp"
NetworkManager::NetworkManager() : web(WebSocket::getInstance()) { NetworkManager::NetworkManager() : curl(curl_easy_init()), res(CURLE_OK), 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) { if (!curl) {
Log::create(CRITICAL, NETWORK, "Failed to initialize CURL"); Log::create(CRITICAL, NETWORK, "Failed to initialize CURL");
abort(); abort();
@ -14,19 +14,19 @@ NetworkManager::~NetworkManager() {
} }
curl_global_cleanup(); curl_global_cleanup();
} }
unsigned long NetworkManager::WriteCallback(void* contents, unsigned long size, unsigned long nmemb, void* userp) { auto NetworkManager::WriteCallback(void* contents, unsigned long size, unsigned long nmemb, void* userp) -> unsigned long {
((std::string*)userp)->append((char*)contents, size * nmemb); (static_cast<std::string*>(userp))->append(static_cast<char*>(contents), size * nmemb);
return size * nmemb; return size * nmemb;
} }
NetworkManager& NetworkManager::getInstance() { auto NetworkManager::getInstance() -> NetworkManager& {
Log::create(INFO, NETWORK, "Instance event"); Log::create(INFO, NETWORK, "Instance event");
static NetworkManager instance; static NetworkManager instance;
return instance; return instance;
} }
unsigned long NetworkManager::getLatency() const { auto NetworkManager::getLatency() const -> unsigned long {
return 0; return 0;
} }
std::string NetworkManager::request(const std::string& method, const std::string& path, const std::string& data) { auto NetworkManager::request(const std::string& method, const std::string& path, const std::string& data) -> std::string {
std::string response; std::string response;
if (curl) { if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, path.c_str()); curl_easy_setopt(curl, CURLOPT_URL, path.c_str());
@ -41,7 +41,8 @@ std::string NetworkManager::request(const std::string& method, const std::string
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_3ONLY); curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_3ONLY);
if ((res = curl_easy_perform(curl)) != 0) { res = curl_easy_perform(curl);
if (res != 0) {
Log::create(ERROR, NETWORK, "curl_easy_perform() failed: " + std::string(curl_easy_strerror(res))); Log::create(ERROR, NETWORK, "curl_easy_perform() failed: " + std::string(curl_easy_strerror(res)));
} }
curl_slist_free_all(headers); curl_slist_free_all(headers);

View File

@ -8,16 +8,16 @@ private:
CURL* curl; CURL* curl;
CURLcode res; CURLcode res;
WebSocket& web; WebSocket& web;
NetworkManager& operator=(const NetworkManager&) = delete; auto operator=(const NetworkManager&) -> NetworkManager& = delete;
NetworkManager& operator=(NetworkManager&&) = delete; auto operator=(NetworkManager&&) -> NetworkManager& = delete;
NetworkManager(NetworkManager&&) = delete; NetworkManager(NetworkManager&&) = delete;
NetworkManager(const NetworkManager&) = delete; NetworkManager(const NetworkManager&) = delete;
NetworkManager(); NetworkManager();
~NetworkManager(); ~NetworkManager();
static unsigned long WriteCallback(void* contents, unsigned long size, unsigned long nmemb, void* userp); static auto WriteCallback(void* contents, unsigned long size, unsigned long nmemb, void* userp) -> unsigned long;
public: public:
static NetworkManager& getInstance(); static auto getInstance() -> NetworkManager&;
unsigned long getLatency() const; [[nodiscard]] auto getLatency() const -> unsigned long;
std::string request(const std::string& method, const std::string& path, const std::string& data = ""); auto request(const std::string& method, const std::string& path, const std::string& data = "") -> std::string;
}; };
#endif #endif

View File

@ -1,7 +1,6 @@
#include "websocket.hpp" #include "websocket.hpp"
void EventEmitter::emit(const std::string& event, const nlohmann::json& data) { void EventEmitter::emit(const std::string& event, const nlohmann::json& data) {
auto it = handlers.find(event); if (auto it = handlers.find(event); it != handlers.end()) {
if (it != handlers.end()) {
for (const auto& handler : it->second) { for (const auto& handler : it->second) {
handler(data); handler(data);
} }
@ -15,12 +14,12 @@ void EventEmitter::getEvents() {
Log::create(CRITICAL, WEBSOCKET, "End of list"); Log::create(CRITICAL, WEBSOCKET, "End of list");
} }
void EventEmitter::start() const { void EventEmitter::start() const {
while (1) std::this_thread::sleep_for(std::chrono::milliseconds(1)); while (true) std::this_thread::sleep_for(std::chrono::milliseconds(1));
} }
void EventEmitter::on(const std::string& event, eventHandlers handler) { void EventEmitter::on(const std::string& event, eventHandlers handler) {
handlers[event].emplace_back(std::move(handler)); handlers[event].emplace_back(std::move(handler));
} }
void EventEmitter::once(const std::string& event, eventHandlers handler) { void EventEmitter::once(const std::string& event, const eventHandlers& handler) {
auto wrappedHandler = [this, event, handler](const nlohmann::json& data) { auto wrappedHandler = [this, event, handler](const nlohmann::json& data) {
handler(data); handler(data);
off(event, handler); off(event, handler);
@ -36,13 +35,12 @@ void EventEmitter::off(const std::string& event, eventHandlers handler) {
}), vec.end()); }), vec.end());
} }
} }
WebSocket::WebSocket(const std::string& token, const int& intents, const bool& isBot) : token(token), intents(intents), isBot(isBot) { WebSocket::WebSocket(const std::string& token, int intents, bool isBot) : token(token), intents(intents), isBot(isBot) {
nlohmann::json id = { nlohmann::json id = {
{"op", GatewayOpcodes::Identify}, {"op", GatewayOpcodes::Identify},
{"d", { {"d", {
{"token", token}, {"token", token},
{"intents", intents}, {"intents", intents},
//{"shard", {{0}}},
{"properties", { {"properties", {
{"os", "linux"}, {"os", "linux"},
{"browser", "firefox"}, {"browser", "firefox"},
@ -74,7 +72,7 @@ WebSocket::WebSocket(const std::string& token, const int& intents, const bool& i
switch (res["op"].get<GatewayOpcodes>()) { switch (res["op"].get<GatewayOpcodes>()) {
case GatewayOpcodes::Hello: case GatewayOpcodes::Hello:
heartbeat_interval = res["d"]["heartbeat_interval"].get<int>(); heartbeat_interval = res["d"]["heartbeat_interval"].get<int>();
!connected ? connected = true, webSocket.send(id.dump()) : 0; !connected ? connected = true, webSocket.send(id.dump()) : false;
std::thread([this, &heartbeat_interval, &connected]() { std::thread([this, &heartbeat_interval, &connected]() {
while (connected && heartbeat_interval != -1) { while (connected && heartbeat_interval != -1) {
Log::create(INFO, WEBSOCKET, "Heartbeat " + std::to_string(heartbeat_interval)); Log::create(INFO, WEBSOCKET, "Heartbeat " + std::to_string(heartbeat_interval));
@ -102,7 +100,7 @@ WebSocket::WebSocket(const std::string& token, const int& intents, const bool& i
}); });
webSocket.start(); webSocket.start();
} }
WebSocket& WebSocket::getInstance(const std::string& token, const int& intents, const bool& bot) { auto WebSocket::getInstance(const std::string& token, int intents, bool bot) -> WebSocket& {
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;
@ -111,14 +109,13 @@ WebSocket::~WebSocket() {
webSocket.close(); webSocket.close();
ix::uninitNetSystem(); ix::uninitNetSystem();
} }
std::string WebSocket::getToken() const { auto WebSocket::getToken() const -> std::string {
return this->isBot ? std::string("Bot " + this->token) : this->token; return this->isBot ? std::string("Bot " + this->token) : this->token;
} }
int WebSocket::getIntents() const { auto WebSocket::getIntents() const -> int {
return this->intents; return this->intents;
} }
__maybe_unused _maybe_unused void WebSocket::sendPresenceUpdate(const char* statusType, const std::string& activityName, const int& activityType) {
void WebSocket::sendPresenceUpdate(const char* statusType, const std::string& activityName, const int& activityType) {
nlohmann::json prsUpdate = { nlohmann::json prsUpdate = {
{"op", 3}, {"op", 3},
{"d", { {"d", {

View File

@ -13,7 +13,7 @@ public:
void getEvents(); void getEvents();
void start() const; void start() const;
void on(const std::string& event, eventHandlers handler); void on(const std::string& event, eventHandlers handler);
void once(const std::string& event, eventHandlers handler); void once(const std::string& event, const eventHandlers& handler);
void off(const std::string& event, eventHandlers handler); void off(const std::string& event, eventHandlers handler);
}; };
class WebSocket : public EventEmitter { class WebSocket : public EventEmitter {
@ -23,17 +23,16 @@ private:
bool isBot; bool isBot;
ix::WebSocket webSocket; ix::WebSocket webSocket;
const nlohmann::json payload = { {"op", GatewayOpcodes::Heartbeat}, {"d", nullptr} }; const nlohmann::json payload = { {"op", GatewayOpcodes::Heartbeat}, {"d", nullptr} };
WebSocket& operator=(const WebSocket&) = delete; WebSocket(const std::string& token, int intents, bool isBot);
WebSocket& operator=(WebSocket&&) = delete; public:
auto operator=(const WebSocket&)->WebSocket & = delete;
auto operator=(WebSocket&&)->WebSocket & = delete;
WebSocket(WebSocket&&) = delete; WebSocket(WebSocket&&) = delete;
WebSocket(const WebSocket&) = delete; WebSocket(const WebSocket&) = delete;
WebSocket(const std::string& token, const int& intents, const bool& isBot); _maybe_unused void sendPresenceUpdate(const char* statusType, const std::string& activityName, const int& activityType);
public: static auto getInstance(const std::string& token = "", int intents = 0, bool bot = true) -> WebSocket&;
__maybe_unused
void sendPresenceUpdate(const char* statusType, const std::string& activityName, const int& activityType);
static WebSocket& getInstance(const std::string& token = "", const int& intents = 0, const bool& bot = true);
~WebSocket(); ~WebSocket();
std::string getToken() const; auto getToken() const->std::string;
int getIntents() const; auto getIntents() const -> int;
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
#ifndef UTILS_EVENTS_HPP_ #ifndef UTILS_EVENTS_HPP_
#define UTILS_EVENTS_HPP_ #define UTILS_EVENTS_HPP_
#include <string>
struct GatewayEvents { struct GatewayEvents {
static constexpr const char* APPLICATION_COMMAND_PERMISSIONS_UPDATE = "APPLICATION_COMMAND_PERMISSIONS_UPDATE"; static constexpr const char* APPLICATION_COMMAND_PERMISSIONS_UPDATE = "APPLICATION_COMMAND_PERMISSIONS_UPDATE";
static constexpr const char* AUTO_MODERATION_ACTION_EXECUTION = "AUTO_MODERATION_ACTION_EXECUTION"; static constexpr const char* AUTO_MODERATION_ACTION_EXECUTION = "AUTO_MODERATION_ACTION_EXECUTION";
@ -110,7 +111,7 @@ struct StatusType {
static inline const char* DND = "dnd"; static inline const char* DND = "dnd";
static inline const char* Invisible = "invisible"; static inline const char* Invisible = "invisible";
}; };
enum ActivityType { enum ActivityType : unsigned char {
Playing, Playing,
Streaming, Streaming,
Listening, Listening,
@ -144,10 +145,10 @@ enum GatewayIntents {
MessageContent = 32768, MessageContent = 32768,
AllIntents = 131071 AllIntents = 131071
}; };
enum DiscordTime { enum DiscordTime : long {
Epoch = 1420070400000, Epoch = 1420070400000,
}; };
enum GatewayOpcodes { enum GatewayOpcodes : unsigned char {
Dispatch, Dispatch,
Heartbeat, Heartbeat,
Identify, Identify,

View File

@ -1,12 +1,14 @@
#ifndef UTILS_FUNCTIONS_HPP_ #ifndef UTILS_FUNCTIONS_HPP_
#define UTILS_FUNCTIONS_HPP_ #define UTILS_FUNCTIONS_HPP_
#include <optional> #include <optional>
#include <string>
#include <nlohmann/json.hpp>
struct functions { struct functions {
static inline std::string isNull(const nlohmann::json& str) { static inline auto isNull(const nlohmann::json& str) -> std::string {
return str.is_null() ? str.dump() : str.get<std::string>(); return str.is_null() ? str.dump() : str.get<std::string>();
} }
template<typename T> template<typename T>
static std::optional<T> testValue(const nlohmann::json& data, const std::vector<std::string>& keys) { static auto testValue(const nlohmann::json& data, const std::vector<std::string>& keys) -> std::optional<T> {
const nlohmann::json* current = &data; const nlohmann::json* current = &data;
for (const auto& key : keys) { for (const auto& key : keys) {
if (current->contains(key)) { if (current->contains(key)) {

File diff suppressed because it is too large Load Diff

View File

@ -6,12 +6,11 @@
#include <iomanip> #include <iomanip>
#include <ctime> #include <ctime>
#include <utils/types.hpp> #include <utils/types.hpp>
enum level { INFO, WARNING, ERROR, CRITICAL }; enum level : unsigned char { INFO, WARNING, ERROR, CRITICAL };
enum type { WEBSOCKET, NETWORK, API }; enum type : unsigned char { WEBSOCKET, NETWORK, API };
class Log { class Log {
public: public:
__maybe_unused _maybe_unused static void create(_maybe_unused const level& lvl, _maybe_unused const type& t, _maybe_unused const std::string& message) {
static void create(__maybe_unused const level& lvl, __maybe_unused const type& t, __maybe_unused const std::string& message) {
#ifdef DEBUG #ifdef DEBUG
std::string color; std::string color;
switch (lvl) { switch (lvl) {
@ -33,10 +32,10 @@ public:
case CRITICAL: color = "\033[31;1;2m"; break; case CRITICAL: color = "\033[31;1;2m"; break;
default: color = "\033[0m"; break; default: color = "\033[0m"; break;
} }
std::cout << color << "[" << getCurrentTime() << "][" << str(t) << "][" << str(lvl) << "] \033[0m" << message << "\033[0m" << std::endl; std::cout << color << "[" << getCurrentTime() << "][" << str(t) << "][" << str(lvl) << "] \033[0m" << message << "\033[0m" << '\n';
} }
private: private:
static const std::string getCurrentTime() { static auto getCurrentTime() -> const std::string {
std::time_t now_c = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); std::time_t now_c = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
std::tm* timer = std::localtime(&now_c); std::tm* timer = std::localtime(&now_c);
std::ostringstream oss; std::ostringstream oss;
@ -46,7 +45,7 @@ private:
<< timer->tm_sec; << timer->tm_sec;
return oss.str(); return oss.str();
} }
static std::string str(const level& lvl) noexcept { static auto str(const level& lvl) noexcept -> std::string {
switch (lvl) { switch (lvl) {
case INFO: return "INFO"; case INFO: return "INFO";
case WARNING: return "WARNING"; case WARNING: return "WARNING";
@ -55,7 +54,7 @@ private:
default: return "UNKNOWN"; default: return "UNKNOWN";
} }
} }
static std::string str(const type& t) { static auto str(const type& t) -> std::string {
switch (t) { switch (t) {
case WEBSOCKET: return "WEBSOCKET"; case WEBSOCKET: return "WEBSOCKET";
case NETWORK: return "NETWORK"; case NETWORK: return "NETWORK";
@ -64,5 +63,4 @@ private:
} }
} }
}; };
#endif #endif

View File

@ -1,7 +1,7 @@
#ifndef UTILS_TYPES_HPP_ #ifndef UTILS_TYPES_HPP_
#define UTILS_TYPES_HPP_ #define UTILS_TYPES_HPP_
#define __maybe_unused [[maybe_unused]] #define _maybe_unused [[maybe_unused]]
#define __deprecated_t(text) [[deprecated(text)]] #define _deprecated_t(text) [[deprecated(text)]]
#define __deprecated [[deprecated]] #define _deprecated [[deprecated]]
#define __nodiscard [[nodiscard]] #define _nodiscard [[nodiscard]]
#endif #endif

View File

@ -19,7 +19,7 @@ int main(int argc, char* argv[]) {
return 0; return 0;
} }
if (!result.contains("token")) { if (!result.count("token")) {
std::cout << "\033[31mError: no token provided.\033[0m" << std::endl; std::cout << "\033[31mError: no token provided.\033[0m" << std::endl;
std::cout << options.help() << std::endl; std::cout << options.help() << std::endl;
return -1; return -1;
@ -32,12 +32,13 @@ int main(int argc, char* argv[]) {
std::cout << std::boolalpha << user->isBot << std::endl; std::cout << std::boolalpha << user->isBot << std::endl;
std::cout << nlohmann::json::parse(user->me())["username"].get<std::string>() << std::endl; std::cout << nlohmann::json::parse(user->me())["username"].get<std::string>() << std::endl;
}); });
bot->on(GatewayEvents::MESSAGE_CREATE, [bot](const Discord<Message, User, Author>& msg) { bot->on(GatewayEvents::MESSAGE_CREATE, [bot](const Discord<Message, User, Author>& msg) {
auto& [message, user, author] = msg.ctx(); auto& [message, user, author] = msg.ctx();
if (!author->isBot) { if (!author->isBot) {
message->send("939957962972229634", message->pack("content", std::to_string(user->isBot))); message->send("939957962972229634", message->pack("content", std::to_string(user->isBot)));
bot->getEvents(); bot->getEvents();
//bot->sendPresenceUpdate(StatusType::DND, "meow", ActivityType::Streaming); bot->sendPresenceUpdate(StatusType::DND, "meow", ActivityType::Listening);
} }
}); });