DiscordCoreAPI
A Discord bot library written in C++, with custom asynchronous coroutines.
Loading...
Searching...
No Matches
ChannelEntities.cpp
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/// ChannelEntities.cpp - Source file for the classes related classes and structs.
27/// May 13, 2021
28/// https://discordcoreapi.com
29/// \file ChannelEntities.cpp
30
34
35namespace jsonifier {
36
37 template<> struct core<discord_core_api::edit_channel_permission_overwrites_data> {
39 static constexpr auto parseValue = createObject("allow", &value_type::allow, "deny", &value_type::deny, "channel_id", &value_type::channelId, "reason", &value_type::reason,
40 "type", &value_type::type, "id", &value_type::roleOrUserId);
41 };
42
43 template<> struct core<discord_core_api::create_channel_invite_data> {
45 static constexpr auto parseValue = createObject("channel_id", &value_type::channelId, "max_uses", &value_type::maxUses, "max_age", &value_type::maxAge, "temporary",
46 &value_type::temporary, "unique", &value_type::unique, "target_type", &value_type::targetType, "target_user_id", &value_type::targetUserId, "target_application_id",
47 &value_type::targetApplicationId, "reason", &value_type::reason);
48 };
49
50 template<> struct core<discord_core_api::create_guild_channel_data> {
52 static constexpr auto parseValue = createObject("name", &value_type::name, "type", &value_type::type, "position", &value_type::position, "parent_id", &value_type::parentId,
53 "permission_overwrites", &value_type::permissionOverwrites, "nsfw", &value_type::nsfw, "rate_limit_per_user", &value_type::rateLimitPerUser, "topic",
54 &value_type::topic, "user_limit", &value_type::userLimit, "bitrate", &value_type::bitrate, "default_auto_archive_duration", &value_type::defaultAutoArchiveDuration,
55 "guild_id", &value_type::guildId, "reason", &value_type::reason);
56 };
57
58 template<> struct core<discord_core_api::modify_guild_channel_position_data> {
60 static constexpr auto parseValue =
61 createObject("id", &value_type::id, "position", &value_type::position, "parent_id", &value_type::parentId, "lock_permissions", &value_type::lockPermissions);
62 };
63
64 template<> struct core<discord_core_api::modify_guild_channel_positions_data> {
66 static constexpr auto parseValue = createArray(&value_type::modifyChannelData);
67 };
68
69 template<> struct core<discord_core_api::modify_channel_data> {
71 static constexpr auto parseValue = createObject("channel_id", &value_type::channelId, "channel_data", &value_type::channelData, "reason", &value_type::reason);
72 };
73
74 template<> struct core<discord_core_api::create_dmchannel_data> {
76 static constexpr auto parseValue = createObject("user_id", &value_type::userId);
77 };
78
79 template<> struct core<discord_core_api::follow_news_channel_data> {
81 static constexpr auto parseValue = createObject("channel_id", &value_type::channelId, "target_channel_id", &value_type::targetChannelId);
82 };
83
84 template<> struct core<discord_core_api::update_channel_data> {
86 static constexpr auto parseValue = createObject("permission_overwrites", &value_type::permissionOverwrites, "default_auto_archive_duration",
87 &value_type::defaultAutoArchiveDuration, "video_quality_mode", &value_type::videoQualityMode, "rate_limit_per_user", &value_type::rateLimitPerUser, "bitrate",
88 &value_type::bitrate, "parent_id", &value_type::parentId, "rtc_region", &value_type::rtcRgion, "user_limit", &value_type::userLimit, "topic", &value_type::topic,
89 "position", &value_type::position, "type", &value_type::type, "name", &value_type::name, "nsfw", &value_type::nsfw);
90 };
91}
92
93namespace discord_core_api {
94
95 channel_data::channel_data(snowflake newId) {
96 id = newId;
97 }
98
99 channel_cache_data& channel_cache_data::operator=(const channel_data& other) {
100 if (other.permissionOverwrites.size() > 0) {
101 permissionOverwrites = other.permissionOverwrites;
102 }
103 if (static_cast<int64_t>(other.flags) != 0) {
104 flags = other.flags;
105 }
106 setFlagValue(channel_flags::managed, other.managed);
107 setFlagValue(channel_flags::nsfw, other.nsfw);
108 if (other.memberCount != 0) {
109 memberCount = other.memberCount;
110 }
111 if (other.parentId != 0) {
112 parentId = other.parentId;
113 }
114 if (other.position != 0) {
115 position = other.position;
116 }
117 if (other.guildId != 0) {
118 guildId = other.guildId;
119 }
120 if (other.ownerId != 0) {
121 ownerId = other.ownerId;
122 }
123 if (other.topic != "") {
124 topic = other.topic;
125 }
126 if (other.name != "") {
127 name = other.name;
128 }
129 if (other.id != 0) {
130 id = other.id;
131 }
132 type = other.type;
133 return *this;
134 }
135
136 channel_cache_data::channel_cache_data(const channel_data& other) {
137 *this = other;
138 }
139
140 channel_cache_data& channel_cache_data::operator=(channel_data&& other) noexcept {
141 if (other.permissionOverwrites.size() > 0) {
142 permissionOverwrites = std::move(other.permissionOverwrites);
143 }
144 if (static_cast<int64_t>(other.flags) != 0) {
145 flags = other.flags;
146 }
147 setFlagValue(channel_flags::managed, other.managed);
148 setFlagValue(channel_flags::nsfw, other.nsfw);
149 if (other.memberCount != 0) {
150 memberCount = other.memberCount;
151 }
152 if (other.topic != "") {
153 topic = std::move(other.topic);
154 }
155 if (other.name != "") {
156 name = std::move(other.name);
157 }
158 if (other.parentId != 0) {
159 parentId = other.parentId;
160 }
161 if (other.position != 0) {
162 position = other.position;
163 }
164 if (other.guildId != 0) {
165 guildId = other.guildId;
166 }
167 if (other.ownerId != 0) {
168 ownerId = other.ownerId;
169 }
170 if (other.id != 0) {
171 id = other.id;
172 }
173 type = other.type;
174 return *this;
175 }
176
177 channel_cache_data::operator channel_data() {
178 channel_data returnData{};
179 returnData.managed = getFlagValue(channel_flags::managed);
180 returnData.permissionOverwrites = permissionOverwrites;
181 returnData.nsfw = getFlagValue(channel_flags::nsfw);
182 returnData.topic = topic;
183 returnData.name = name;
184 returnData.memberCount = memberCount;
185 returnData.parentId = parentId;
186 returnData.position = position;
187 returnData.guildId = guildId;
188 returnData.ownerId = ownerId;
189 returnData.flags = flags;
190 returnData.type = type;
191 returnData.id = id;
192 return returnData;
193 }
194
195 channel_cache_data::channel_cache_data(channel_data&& other) noexcept {
196 *this = std::move(other);
197 }
198
199 jsonifier::string channel_data::getIconUrl() {
200 jsonifier::string stringNew{ "https://cdn.discordapp.com/" };
201 stringNew += "splashes/" + id.operator jsonifier::string() + "/" + icon + ".png";
202 return stringNew;
203 }
204
205 modify_channel_data::modify_channel_data(channel_data newData) {
206 channelData.parentId = newData.parentId.operator jsonifier::string();
207 channelData.nsfw = newData.getFlagValue(channel_flags::nsfw);
208 channelData.permissionOverwrites = newData.permissionOverwrites;
209 channelData.rateLimitPerUser = newData.rateLimitPerUser;
210 channelData.userLimit = newData.userLimit;
211 channelData.rtcRgion = newData.rtcRegion;
212 channelData.position = newData.position;
213 channelData.topic = newData.topic;
214 channelData.name = newData.name;
215 channelData.type = newData.type;
216 };
217
218 void channels::initialize(discord_core_internal::https_client* client, config_manager* configManagerNew) {
219 channels::doWeCacheChannelsBool = configManagerNew->doWeCacheChannels();
220 channels::httpsClient = client;
221 }
222
224 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Get_Channel };
225 co_await newThreadAwaitable<channel_data>();
226 workload.workloadClass = discord_core_internal::https_workload_class::Get;
227 workload.relativePath = "/channels/" + dataPackage.channelId;
228 workload.callStack = "channels::getChannelAsync()";
229 channel_data data{ dataPackage.channelId };
230 if (cache.contains(data.id)) {
231 data = cache[data.id];
232 }
233 channels::httpsClient->submitWorkloadAndGetResult(std::move(workload), data);
234 if (doWeCacheChannelsBool) {
235 insertChannel(static_cast<channel_cache_data>(data));
236 }
237 co_return data;
238 }
239
241 if (channels::cache.contains(dataPackage.channelId)) {
242 return cache[dataPackage.channelId];
243 } else {
244 return getChannelAsync({ .channelId = dataPackage.channelId }).get();
245 }
246 }
247
249 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Patch_Channel };
250 co_await newThreadAwaitable<channel_data>();
251 workload.workloadClass = discord_core_internal::https_workload_class::Patch;
252 workload.relativePath = "/channels/" + dataPackage.channelId;
253 parser.serializeJson<true>(dataPackage, workload.content);
254 workload.callStack = "channels::modifyChannelAsync()";
255 if (dataPackage.reason != "") {
256 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
257 }
258 channel_data data{ dataPackage.channelId };
259 if (cache.contains(data.id)) {
260 data = cache[data.id];
261 }
262 channels::httpsClient->submitWorkloadAndGetResult(std::move(workload), data);
263 if (doWeCacheChannelsBool) {
264 insertChannel(static_cast<channel_cache_data>(data));
265 }
266 co_return data;
267 }
268
270 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Delete_Channel };
271 co_await newThreadAwaitable<void>();
272 workload.workloadClass = discord_core_internal::https_workload_class::Delete;
273 workload.relativePath = "/channels/" + dataPackage.channelId;
274 workload.callStack = "channels::deleteOrCloseAChannelAsync()";
275 if (dataPackage.reason != "") {
276 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
277 }
278 channels::httpsClient->submitWorkloadAndGetResult(std::move(workload));
279 co_return;
280 }
281
283 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Put_Channel_Permission_Overwrites };
284 co_await newThreadAwaitable<void>();
285 workload.workloadClass = discord_core_internal::https_workload_class::Put;
286 workload.relativePath = "/channels/" + dataPackage.channelId + "/permissions/" + dataPackage.roleOrUserId;
287 parser.serializeJson<true>(dataPackage, workload.content);
288 workload.callStack = "channels::editChannelPermissionOverwritesAsync()";
289 if (dataPackage.reason != "") {
290 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
291 }
292 channels::httpsClient->submitWorkloadAndGetResult(std::move(workload));
293 co_return;
294 }
295
297 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Get_Channel_Invites };
298 co_await newThreadAwaitable<jsonifier::vector<invite_data>>();
299 workload.workloadClass = discord_core_internal::https_workload_class::Get;
300 workload.relativePath = "/channels/" + dataPackage.channelId + "/invites";
301 workload.callStack = "channels::getChannelInvitesAsync()";
302 jsonifier::vector<invite_data> returnData{};
303 channels::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
304 co_return returnData;
305 }
306
308 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Post_Channel_Invite };
309 co_await newThreadAwaitable<invite_data>();
310 workload.workloadClass = discord_core_internal::https_workload_class::Post;
311 workload.relativePath = "/channels/" + dataPackage.channelId + "/invites";
312 parser.serializeJson<true>(dataPackage, workload.content);
313 workload.callStack = "channels::createChannelInviteAsync()";
314 if (dataPackage.reason != "") {
315 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
316 }
317 invite_data returnData{};
318 channels::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
319 co_return returnData;
320 }
321
323 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Delete_Channel_Permission_Overwrites };
324 co_await newThreadAwaitable<void>();
325 workload.workloadClass = discord_core_internal::https_workload_class::Delete;
326 workload.relativePath = "/channels/" + dataPackage.channelId + "/permissions/" + dataPackage.roleOrUserId;
327 workload.callStack = "channels::deleteChannelPermissionOverwritesAsync()";
328 if (dataPackage.reason != "") {
329 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
330 }
331 channels::httpsClient->submitWorkloadAndGetResult(std::move(workload));
332 co_return;
333 }
334
336 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Post_Follow_News_Channel };
337 co_await newThreadAwaitable<channel_data>();
338 workload.workloadClass = discord_core_internal::https_workload_class::Post;
339 workload.relativePath = "/channels/" + dataPackage.channelId + "/followers";
340 parser.serializeJson<true>(dataPackage, workload.content);
341 workload.callStack = "channels::followNewsChannelAsync()";
342 channel_data returnData{};
343 channels::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
344 co_return returnData;
345 }
346
348 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Post_Trigger_Typing_Indicator };
349 co_await newThreadAwaitable<void>();
350 workload.workloadClass = discord_core_internal::https_workload_class::Post;
351 workload.relativePath = "/channels/" + dataPackage.channelId + "/typing";
352 workload.callStack = "channels::triggerTypingIndicatorAsync()";
353 channels::httpsClient->submitWorkloadAndGetResult(std::move(workload));
354 co_return;
355 }
356
358 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Get_Guild_Channels };
359 co_await newThreadAwaitable<jsonifier::vector<channel_data>>();
360 workload.workloadClass = discord_core_internal::https_workload_class::Get;
361 workload.relativePath = "/guilds/" + dataPackage.guildId + "/channels";
362 workload.callStack = "channels::getGuildChannelsAsync()";
363 jsonifier::vector<channel_data> returnData{};
364 channels::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
365 co_return returnData;
366 }
367
369 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Post_Guild_Channel };
370 co_await newThreadAwaitable<channel_data>();
371 workload.workloadClass = discord_core_internal::https_workload_class::Post;
372 workload.relativePath = "/guilds/" + dataPackage.guildId + "/channels";
373 parser.serializeJson<true>(dataPackage, workload.content);
374 workload.callStack = "channels::createGuildChannelAsync()";
375 if (dataPackage.reason != "") {
376 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
377 }
378 channel_data returnData{};
379 channels::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
380 co_return returnData;
381 }
382
384 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Patch_Guild_Channel_Positions };
385 co_await newThreadAwaitable<void>();
386 workload.workloadClass = discord_core_internal::https_workload_class::Patch;
387 workload.relativePath = "/guilds/" + dataPackage.guildId + "/channels";
388 parser.serializeJson<true>(dataPackage, workload.content);
389 workload.callStack = "channels::modifyGuildChannelPositionsAsync()";
390 if (dataPackage.reason != "") {
391 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
392 }
393 channels::httpsClient->submitWorkloadAndGetResult(std::move(workload));
394 co_return;
395 }
396
398 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Post_Create_User_Dm };
399 co_await newThreadAwaitable<channel_data>();
400 workload.workloadClass = discord_core_internal::https_workload_class::Post;
401 workload.relativePath = "/users/@me/channels";
402 workload.callStack = "channels::createDMChannelAsync()";
403 parser.serializeJson<true>(dataPackage, workload.content);
404 channel_data returnData{};
405 channels::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
406 co_return returnData;
407 }
408
410 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Get_Voice_Regions };
411 co_await newThreadAwaitable<jsonifier::vector<voice_region_data>>();
412 workload.workloadClass = discord_core_internal::https_workload_class::Get;
413 workload.relativePath = "/voice/regions";
414 workload.callStack = "channels::getVoiceRegionsAsync()";
415 jsonifier::vector<voice_region_data> returnData{};
416 channels::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
417 co_return returnData;
418 }
419
420 void channels::removeChannel(const channel_cache_data& channelId) {
421 channels::cache.erase(channelId);
422 };
423
424 bool channels::doWeCacheChannels() {
425 return channels::doWeCacheChannelsBool;
426 }
427
428 object_cache<channel_cache_data> channels::cache{};
429 discord_core_internal::https_client* channels::httpsClient{};
430 bool channels::doWeCacheChannelsBool{};
431}
Data structure representing a single channel_data.
uint32_t position
The position of the channel_data, in the guild's channel_data list.
jsonifier::string topic
channel_data topic.
snowflake ownerId
snowflake of the channel_data's owner.
channel_type type
The type of the channel_data.
jsonifier::string name
Name of the channel_data.
uint32_t memberCount
count of members active in the channel_data.
snowflake guildId
snowflake of the channel_data's guild, if applicable.
channel_flags flags
Flags combined as a bitmask.
jsonifier::vector< over_write_data > permissionOverwrites
Permission overwrites.
snowflake parentId
snowflake of the channel_data's parent channel_data/category.
jsonifier::string icon
Icon hash of the group dm.
bool managed
For group dm channels: whether the channel is managed by an application via the gdm....
static co_routine< void > deleteOrCloseChannelAsync(const delete_or_close_channel_data dataPackage)
Delete a channel, or close a protected message.
static co_routine< void > editChannelPermissionOverwritesAsync(const edit_channel_permission_overwrites_data dataPackage)
Edit the given jsonifier::string overwrites for a given user or role_data.
static co_routine< jsonifier::vector< channel_data > > getGuildChannelsAsync(const get_guild_channels_data dataPackage)
Collects a list of channels from a chosen guild_data.
static channel_cache_data getCachedChannel(const get_channel_data dataPackage)
Collects a channel from the library's cache.
static co_routine< jsonifier::vector< voice_region_data > > getVoiceRegionsAsync()
Collect a list of voice regions that are usable for the rtc-region option of a given channel.
static co_routine< channel_data > getChannelAsync(const get_channel_data dataPackage)
Collects a channel from the discord servers.
static co_routine< jsonifier::vector< invite_data > > getChannelInvitesAsync(const get_channel_invites_data dataPackage)
Collects a vector of the invites to a given channel.
static co_routine< void > deleteChannelPermissionOverwritesAsync(const delete_channel_permission_overwrites_data dataPackage)
Delete the given jsonifier::string overwrites for a given user or role_data.
static co_routine< channel_data > createDMChannelAsync(const create_dmchannel_data dataPackage)
Collect a direct-message_data channel between the bot and the user_data.
static co_routine< channel_data > followNewsChannelAsync(const follow_news_channel_data dataPackage)
Follows a given new channel_data with another channel_data.
static co_routine< channel_data > createGuildChannelAsync(const create_guild_channel_data dataPackage)
Creates a new channel_data within a chosen guild_data.
static co_routine< void > triggerTypingIndicatorAsync(const trigger_typing_indicator_data dataPackage)
Triggers the typing indicator for the bot in the given channel.
static co_routine< invite_data > createChannelInviteAsync(const create_channel_invite_data dataPackage)
Creates an invite to a selected channel_data.
static co_routine< channel_data > modifyChannelAsync(const modify_channel_data dataPackage)
Modifies a channel's properties.
static co_routine< void > modifyGuildChannelPositionsAsync(const modify_guild_channel_positions_data dataPackage)
Re-orders the channel_data positions, within a chosen guild_data.
A co_routine - representing a potentially asynchronous operation/function.
Definition: CoRoutine.hpp:83
The main namespace for the forward-facing interfaces.
For creating an invite to a given channel.
snowflake channelId
The id of the channel_data to create the invite for.
jsonifier::string reason
Reason for creating the invite.
For collecting a direct-messaging channel_data.
For creating a new channel_data within a chosen guild_data.
jsonifier::string reason
Reason for creating the channel_data.
snowflake guildId
The guild_data within which to create the channel_data.
For deleting the permission_types overwrites of a given channel for a given role or user_data.
jsonifier::string reason
Reason for deleting these permission overwrites.
snowflake roleOrUserId
The role_data or user_data id for whom to delete the permission_types overwrites.
snowflake channelId
The id of the channel_data to modify permissions for.
For deleting or closing a channel.
snowflake channelId
The id of the channel_data to close/delete.
jsonifier::string reason
The reason for deleting/closing the channel_data.
For editing the permission_types overwrites of a given channel, for a given role or user_data.
snowflake roleOrUserId
The role_data or user_data snowflake to modify the permissions for.
jsonifier::string reason
Reason for editing the permission overwrites.
snowflake channelId
The channel_data id of the desired channel_data to modify the permissions for.
For following a news channel_data.
For collecting a channel from discord's servers.
snowflake channelId
The id of the channel_data to acquire.
For collecting the invites to a given channel.
For acquiring a list of channels from a chosen guild_data.
snowflake guildId
The guild_data from which to collect the channels from.
For modifying a channel's properties.
update_channel_data channelData
The responseData of the channel_data to be updated.
snowflake channelId
The id of the channel_data to modify.
jsonifier::string reason
A reason for modifying the channel_data.
For modifying the channel_data position responseData of a single channel_data.
For modifying the current positions of one or more channels in the guild_data.
jsonifier::string reason
Reason for re-ordering the channel_data positions.
snowflake guildId
Guild within which to re-order the channel_data positions.
For triggering the typing indicator in a given channel.
For updating/modifying a given channel's properties.