38 voice_connections_map voiceConnectionMap{};
39 sound_cloud_api_map soundCloudAPIMap{};
40 you_tube_api_map youtubeAPIMap{};
41 song_api_map songAPIMap{};
42 std::atomic_bool doWeQuit{};
44 discord_core_internal::sound_cloud_api& discord_core_client::getSoundCloudAPI(
snowflake guildId) {
45 if (!soundCloudAPIMap.contains(guildId.operator
const uint64_t&())) {
48 return *soundCloudAPIMap[guildId.operator
const uint64_t&()].get();
51 discord_core_internal::you_tube_api& discord_core_client::getYouTubeAPI(
snowflake guildId) {
52 if (!youtubeAPIMap.contains(guildId.operator
const uint64_t&())) {
55 return *youtubeAPIMap[guildId.operator
const uint64_t&()].get();
59 if (!voiceConnectionMap.contains(guildId.operator
const uint64_t&())) {
60 uint64_t theShardId{ (guildId.operator
const uint64_t&() >> 22) % getInstance()->configManager.getTotalShardCount() };
61 uint64_t baseSocketIndex{ theShardId % getInstance()->baseSocketAgentsMap.size() };
62 voiceConnectionMap[guildId.operator
const uint64_t&()] =
65 return *voiceConnectionMap[guildId.operator
const uint64_t&()].get();
69 if (!songAPIMap.contains(guildId.operator
const uint64_t&())) {
72 return *songAPIMap[guildId.operator
const uint64_t&()].get();
76 return instancePtr.get();
80 void atexitHandler() noexcept {
81 doWeQuit.store(
true, std::memory_order_release);
84 void signalHandler(int32_t value)
noexcept {
114 instancePtr.reset(
this);
115 std::atexit(&atexitHandler);
116 std::signal(SIGTERM, &signalHandler);
117 std::signal(SIGSEGV, &signalHandler);
118 std::signal(SIGINT, &signalHandler);
119 std::signal(SIGILL, &signalHandler);
120 std::signal(SIGABRT, &signalHandler);
121 std::signal(SIGFPE, &signalHandler);
123 if (!discord_core_internal::ssl_context_holder::initialize()) {
127 if (sodium_init() == -1) {
132 application_commands::initialize(httpsClient.get());
133 auto_moderation_rules::initialize(httpsClient.get());
134 channels::initialize(httpsClient.get(), &configManager);
135 guilds::initialize(httpsClient.get(), &configManager);
136 guild_members::initialize(httpsClient.get(), &configManager);
137 guild_scheduled_events::initialize(httpsClient.get());
138 interactions::initialize(httpsClient.get());
139 messages::initialize(httpsClient.get());
140 reactions::initialize(httpsClient.get());
141 roles::initialize(httpsClient.get(), &configManager);
142 stickers::initialize(httpsClient.get());
143 stage_instances::initialize(httpsClient.get());
144 threads::initialize(httpsClient.get());
145 web_hooks::initialize(httpsClient.get());
146 users::initialize(httpsClient.get(), &configManager);
150 return configManager;
154 return discord_core_client::currentUser;
159 if (!instantiateWebSockets()) {
160 doWeQuit.store(
true, std::memory_order_release);
164 std::this_thread::sleep_for(1ms);
166 registerFunctionsInternal();
167 while (!doWeQuit.load(std::memory_order_acquire)) {
168 std::this_thread::sleep_for(1ms);
170 }
catch (
const dca_exception& error) {
177 create_application_command_data commandData{ commandDataNew };
178 commandData.alwaysRegister = alwaysRegister;
179 commandController.registerFunction(functionNames, std::move(baseFunction));
180 commandsToRegister.emplace_back(commandData);
184 return commandController;
192 return std::chrono::duration_cast<milliseconds>(sys_clock::now().time_since_epoch()) - startupTimeSinceEpoch;
195 void discord_core_client::registerFunctionsInternal() {
197 jsonifier::vector<application_command_data> theCommands{
200 while (commandsToRegister.size() > 0) {
201 create_application_command_data data = commandsToRegister.front();
202 commandsToRegister.pop_front();
204 if (data.alwaysRegister) {
205 if (data.guildId != 0) {
211 jsonifier::vector<application_command_data> guildCommands{};
212 if (data.guildId != 0) {
217 for (
auto& value: theCommands) {
223 for (
auto& value: guildCommands) {
231 if (data.guildId != 0) {
238 }
catch (dca_exception& error) {
247 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Get_Gateway_Bot };
248 workload.workloadClass = discord_core_internal::https_workload_class::Get;
249 workload.relativePath =
"/gateway/bot";
250 workload.callStack =
"discord_core_client::getGateWayBot()";
251 gateway_bot_data data{};
252 httpsClient->submitWorkloadAndGetResult(workload, data);
256 bool discord_core_client::instantiateWebSockets() {
257 gateway_bot_data gatewayData{};
259 gatewayData = getGateWayBot();
260 }
catch (
const discord_core_internal::https_error& error) {
265 if (gatewayData.url ==
"") {
267 "properly set your bot token?");
268 std::this_thread::sleep_for(5s);
271 if (configManager.getStartingShard() + configManager.getShardCountForThisProcess() > configManager.getTotalShardCount()) {
273 std::this_thread::sleep_for(5s);
276 uint64_t workerCount = configManager.getTotalShardCount() <= std::jthread::hardware_concurrency() ? configManager.getTotalShardCount()
277 :
static_cast<uint64_t
>(std::jthread::hardware_concurrency());
279 if (configManager.getConnectionAddress() ==
"") {
280 configManager.setConnectionAddress(gatewayData.url.substr(gatewayData.url.find(
"wss://") + jsonifier::string{
"wss://" }.size()));
282 if (configManager.getConnectionPort() == 0) {
283 configManager.setConnectionPort(443);
285 areWeReadyToConnect.store(
false, std::memory_order_release);
286 baseSocketAgentsMap.reserve(workerCount);
287 for (uint64_t x = 0; x < configManager.getTotalShardCount(); ++x) {
288 if (baseSocketAgentsMap.size() < workerCount) {
290 baseSocketAgentsMap[x]->shardMap.reserve(configManager.getTotalShardCount() / workerCount);
292 baseSocketAgentsMap[x % workerCount]->shardMap[x] = discord_core_internal::websocket_client{ x, &doWeQuit };
294 areWeReadyToConnect.store(
true, std::memory_order_release);
295 while (!areWeFullyConnected()) {
296 std::this_thread::sleep_for(1ms);
298 for (
auto& value: configManager.getFunctionsToExecute()) {
299 executeFunctionAfterTimePeriod(value.function, value.intervalInMs, value.repeated,
false,
this);
301 startupTimeSinceEpoch = std::chrono::duration_cast<milliseconds>(sys_clock::now().time_since_epoch());
305 bool discord_core_client::areWeFullyConnected() {
306 for (
auto& [key, value]: baseSocketAgentsMap) {
307 for (
auto& [keyNew, valueNew]: value->shardMap) {
308 if (!valueNew.areWeConnected()) {
316 discord_core_client::~discord_core_client() {
317 instancePtr.release();
320 bot_user discord_core_client::currentUser{};
static co_routine< jsonifier::vector< application_command_data > > getGlobalApplicationCommandsAsync(get_global_application_commands_data dataPackage)
Get all of the global application_commands for this bot.
static co_routine< jsonifier::vector< application_command_data > > getGuildApplicationCommandsAsync(get_guild_application_commands_data dataPackage)
Get all of the guild application_commands for a single guild for this bot.
static co_routine< application_command_data > createGlobalApplicationCommandAsync(create_global_application_command_data dataPackage)
Create a global application_command_data for this bot.
static co_routine< application_command_data > createGuildApplicationCommandAsync(create_guild_application_command_data dataPackage)
Create a guild application_command_data for a single server for this bot.
A type of user_data, to represent the bot and some of its associated endpoints.
A class for handling commands from user input.
discord_core_client - the main class for this library.
command_controller & getCommandController()
For collecting a reference to the command_controller.
event_manager & getEventManager()
For collecting a reference to the event_manager.
void runBot()
Executes the library, and waits for completion.
discord_core_client(const discord_core_client_config &configData)
discord_core_client constructor.
void registerFunction(const jsonifier::vector< jsonifier::string > &functionNames, unique_ptr< base_function > &&baseFunction, const create_application_command_data &commandData, bool alwaysRegister=false)
For registering a function with the command_controller.
static bot_user getBotUser()
For collecting a copy of the current bot's user_data.
milliseconds getTotalUpTime()
For collecting, the total time in milliseconds that this bot has been up for.
event_manager eventManager
An event-manager, for hooking into discord-api-events sent over the websockets.
const config_manager & getConfigManager() const
For collecting a reference to the config_manager.
Class for handling the assignment of event-handling functions.int32_t.
static DCA_INLINE void printError(const string_type &what, std::source_location where=std::source_location::current())
Print an error message of the specified type.
static DCA_INLINE void initialize(const value_type &other)
Initialize the message_printer with configuration settings and output/error streams.
A class representing a snowflake identifier with various operations.
A class representing the song apis.
A smart pointer class that provides unique ownership semantics.
snowflake id
The user's id.
voice_connection class - represents the connection to a given voice channel_data.
DCA_INLINE unique_ptr< value_type, deleter > makeUnique(arg_types &&... args)
Helper function to create a unique_ptr for a non-array object.
The main namespace for the forward-facing interfaces.
For creating an application command.
Configuration data for the library's main class, discord_core_client.
Data from the get_gateway_bot endpoint.