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 DCA_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 DCA_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 DCA_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 DCA_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 DCA_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 DCA_INLINE sigfpeerror(jsonifier::string_view message, std::source_location location = std::source_location::current()) : dca_exception{ message, location } {};
92 };
93
94 using sound_cloud_api_map = unordered_map<uint64_t, unique_ptr<discord_core_internal::sound_cloud_api>>;
95
96 using you_tube_api_map = 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_api_map = 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, typename function_type>
105 DCA_INLINE static co_routine<void, false> threadFunction(function_type 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) {
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, typename function_type> DCA_INLINE static void executeFunctionAfterTimePeriod(function_type timeElapsedHandler,
132 int64_t timeDelay, bool repeated, bool blockForCompletion, arg_types... args) {
133 auto newThread = threadFunction(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:
146 friend class discord_core_internal::websocket_client;
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.
166 discord_core_client(const discord_core_client_config& configData);
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,
175 const create_application_command_data& commandData, 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
200 ~discord_core_client();
201
202 protected:
203 DCA_INLINE static unique_ptr<discord_core_client> instancePtr{};
204 static bot_user currentUser;
205
206 discord_core_client& operator=(discord_core_client&&) = delete;
207 discord_core_client(discord_core_client&&) = delete;
208
209 discord_core_client& operator=(const discord_core_client&) = delete;
210 discord_core_client(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{};
214 unique_ptr<discord_core_internal::https_client> httpsClient{};
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 co_routine - representing a potentially asynchronous operation/function.
discord_core_client - the main class for this library.
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.
Definition Base.hpp:252
@ guilds
Intent for receipt of guild information.
DCA_INLINE auto newThreadAwaitable()
An awaitable that can be used to launch the co_routine onto a new thread - as well as return the hand...
The main namespace for the forward-facing interfaces.
An exception class derived from std::runtime_error for dca-related exceptions.
Definition Base.hpp:841
DCA_INLINE 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:845