DiscordCoreAPI
A Discord bot library written in C++, with custom asynchronous coroutines.
Loading...
Searching...
No Matches
DiscordCoreClient.hpp
Go to the documentation of this file.
1/*
2 MIT License
3
4 DiscordCoreAPI, A bot library for Discord, written in C++, and featuring explicit multithreading through the usage of custom, asynchronous C++ CoRoutines.
5
6 Copyright 2022, 2023 Chris M. (RealTimeChris)
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in all
16 copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 SOFTWARE.
25*/
26/// DiscordCoreClient.hpp - Header file for the main/exposed discord_core_client class.
27/// May 12, 2021 Chris M.
28/// https://discordcoreapi.com
29/// \file DiscordCoreClient.hpp
30#pragma once
31
61
62namespace discord_core_api {
63
64 class sigtermerror : public dca_exception {
65 public:
66 inline sigtermerror(jsonifier::string_view message, std::source_location location = std::source_location::current()) : dca_exception{ message, location } {};
67 };
68
69 class sigsegverror : public dca_exception {
70 public:
71 inline sigsegverror(jsonifier::string_view message, std::source_location location = std::source_location::current()) : dca_exception{ message, location } {};
72 };
73
74 class siginterror : public dca_exception {
75 public:
76 inline siginterror(jsonifier::string_view message, std::source_location location = std::source_location::current()) : dca_exception{ message, location } {};
77 };
78
79 class sigillerror : public dca_exception {
80 public:
81 inline sigillerror(jsonifier::string_view message, std::source_location location = std::source_location::current()) : dca_exception{ message, location } {};
82 };
83
84 class sigabrterror : public dca_exception {
85 public:
86 inline sigabrterror(jsonifier::string_view message, std::source_location location = std::source_location::current()) : dca_exception{ message, location } {};
87 };
88
89 class sigfpeerror : public dca_exception {
90 public:
91 inline sigfpeerror(jsonifier::string_view message, std::source_location location = std::source_location::current()) : dca_exception{ message, location } {};
92 };
93
94 using sound_cloud_apimap = unordered_map<uint64_t, unique_ptr<discord_core_internal::sound_cloud_api>>;
95
96 using you_tube_apimap = unordered_map<uint64_t, unique_ptr<discord_core_internal::you_tube_api>>;
97
98 using voice_connections_map = unordered_map<uint64_t, unique_ptr<voice_connection>>;
99
100 using song_apimap = unordered_map<uint64_t, unique_ptr<song_api>>;
101
102 template<typename... arg_types> using time_elapsed_handler = std::function<void(arg_types...)>;
103
104 template<typename... arg_types>
105 inline static co_routine<void, false> threadFunction(time_elapsed_handler<arg_types...> timeElapsedHandler, bool repeated, int64_t timeInterval, arg_types... args) {
106 auto threadHandle = co_await newThreadAwaitable<void, false>();
107 stop_watch<milliseconds> stopWatch{ milliseconds{ timeInterval } };
108 stopWatch.reset();
109 do {
110 std::this_thread::sleep_for(milliseconds{ static_cast<int64_t>(std::ceil(static_cast<float>(timeInterval) * 10.0f / 100.0f)) });
111 while (!stopWatch.hasTimeElapsed() && !threadHandle.promise().stopRequested()) {
112 std::this_thread::sleep_for(1ms);
113 }
114 stopWatch.reset();
115 if (threadHandle.promise().stopRequested()) {
116 co_return;
117 }
118 try {
119 timeElapsedHandler(args...);
120 } catch (const dca_exception& error) {
121 message_printer::printError<print_message_type::general>(error.what());
122 }
123 if (threadHandle.promise().stopRequested()) {
124 co_return;
125 }
126 std::this_thread::sleep_for(1ms);
127 } while (repeated);
128 co_return;
129 };
130
131 template<typename... arg_types> inline static void executeFunctionAfterTimePeriod(time_elapsed_handler<arg_types...> timeElapsedHandler, int64_t timeDelay, bool repeated,
132 bool blockForCompletion, arg_types... args) {
133 auto newThread = threadFunction<arg_types...>(timeElapsedHandler, repeated, timeDelay, args...);
134 if (blockForCompletion) {
135 newThread.get();
136 }
137 }
138
139 /**
140 * \addtogroup main_endpoints
141 * @{
142 */
143 /// @brief discord_core_client - the main class for this library.
144 class DiscordCoreAPI_Dll discord_core_client {
145 public:
147 friend class discord_core_internal::base_socket_agent;
148 friend class discord_core_internal::websocket_core;
149 friend class voice_connection;
150 friend class guild_data;
151 friend class bot_user;
152 friend class guilds;
153
154 static discord_core_internal::sound_cloud_api& getSoundCloudAPI(snowflake guildId);
155
156 static discord_core_internal::you_tube_api& getYouTubeAPI(snowflake guildId);
157
158 static voice_connection& getVoiceConnection(snowflake guildId);
159
160 static song_api& getSongAPI(snowflake guildId);
161
162 static discord_core_client* getInstance();
163
164 /// @brief discord_core_client constructor.
165 /// @param configData a discord_core_client_config structure to select various library options.
167
168 /// @brief For registering a function with the command_controller.
169 /// @param functionNames a vector containing the possible names for activating this command/function.
170 /// @param baseFunction a unique_ptr to the command to be registered.
171 /// @param commandData a create_application_command_data structure describing the current function.
172 /// @param alwaysRegister whether or not it gets registered every time the bot boots up, or only when it's missing from the bot's list of
173 /// registered commands.
174 void registerFunction(const jsonifier::vector<jsonifier::string>& functionNames, unique_ptr<base_function> baseFunction, create_application_command_data commandData,
175 bool alwaysRegister = false);
176
177 /// @brief For collecting a reference to the command_controller.
178 /// @return command_controller& a reference to the command_controller.
179 command_controller& getCommandController();
180
181 /// @brief For collecting a reference to the config_manager.
182 /// @return config_manager& a reference to the config_manager.
183 const config_manager& getConfigManager() const;
184
185 /// @brief For collecting a reference to the event_manager.
186 /// @return event_manager& a reference to the event_manager.
187 event_manager& getEventManager();
188
189 /// @brief For collecting, the total time in milliseconds that this bot has been up for.
190 /// @return milliseconds a size, in milliseconds, since the bot has come online.
191 milliseconds getTotalUpTime();
192
193 /// @brief For collecting a copy of the current bot's user_data.
194 /// @return bot_user an instance of bot_user.
195 static bot_user getBotUser();
196
197 /// @brief Executes the library, and waits for completion.
198 void runBot();
199
201
202 protected:
203 inline static unique_ptr<discord_core_client> instancePtr{};
204 static bot_user currentUser;
205
206 discord_core_client& operator=(discord_core_client&&) = delete;
208
209 discord_core_client& operator=(const discord_core_client&) = delete;
211
212 unordered_map<uint64_t, unique_ptr<discord_core_internal::base_socket_agent>> baseSocketAgentsMap{};
213 std::deque<create_application_command_data> commandsToRegister{};
215 stop_watch<milliseconds> connectionStopWatch01{ 5000ms };
216#if defined(_WIN32)
217 discord_core_internal::wsadata_wrapper theWSAData{};
218#endif
219 std::atomic_uint64_t currentlyConnectingShard{};
220 std::atomic_bool areWeReadyToConnect{ false };
221 command_controller commandController{};
222 milliseconds startupTimeSinceEpoch{};
223 config_manager configManager{};
224 event_manager eventManager{};///< An event-manager, for hooking into discord-api-events sent over the websockets.
225
226 bool areWeFullyConnected();
227
228 void registerFunctionsInternal();
229
230 gateway_bot_data getGateWayBot();
231
232 bool instantiateWebSockets();
233 };
234 /**@}*/
235}// namespace discord_core_api
A type of user_data, to represent the bot and some of its associated endpoints.
return_type get()
Gets the resulting value of the co_routine.
Definition: CoRoutine.hpp:191
A class for handling commands from user input.
discord_core_client - the main class for this library.
A websocket client, for communication via a tcp-connection.
Class for handling the assignment of event-handling functions.int32_t.
A discord guild. used to connect to/disconnect from voice.
An interface class for the guild_data related discord endpoints.
A class representing a snowflake identifier with various operations.
Definition: Base.hpp:680
A class representing the song apis.
Definition: SongAPI.hpp:45
A smart pointer class that provides unique ownership semantics.
Definition: UniquePtr.hpp:44
voice_connection class - represents the connection to a given voice channel_data.
The main namespace for the forward-facing interfaces.
dca_exception(jsonifier::string_view error, std::source_location location=std::source_location::current())
Constructor to create a dca_exception with an error message and optional source location.
Definition: Base.hpp:824
Configuration data for the library's main class, discord_core_client.
Definition: Utilities.hpp:237
Data from the get_gateway_bot endpoint.