DiscordCoreAPI
A Discord bot library written in C++, with custom asynchronous coroutines.
Loading...
Searching...
No Matches
GuildMemberEntities.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/// GuildMemberEntities.cpp - Source file for the guild_member_data related classes and structs.
27/// May 13, 2021
28/// https://discordcoreapi.com
29/// \file GuildMemberEntities.cpp
30
35
36namespace jsonifier {
37
38 template<> struct core<discord_core_api::add_guild_member_data> {
39 using value_type = discord_core_api::add_guild_member_data;
40 static constexpr auto parseValue = createValue("roles", &value_type::roles, "access_token", &value_type::accessToken, "guild_id", &value_type::guildId, "user_id",
41 &value_type::userId, "nick", &value_type::nick, "mute", &value_type::mute, "deaf", &value_type::deaf);
42 };
43
44 template<> struct core<discord_core_api::modify_current_guild_member_data> {
45 using value_type = discord_core_api::modify_current_guild_member_data;
46 static constexpr auto parseValue = createValue("nick", &value_type::nick);
47 };
48
49 template<> struct core<discord_core_api::modify_guild_member_data> {
50 using value_type = discord_core_api::modify_guild_member_data;
51 static constexpr auto parseValue = createValue("deaf", &value_type::deaf, "mute", &value_type::mute, "nick", &value_type::nick, "roles", &value_type::roleIds, "channel_id",
52 &value_type::channelId, "flags", &value_type::flags);
53 };
54}
55
56namespace discord_core_api {
57
58 modify_guild_member_data::modify_guild_member_data(const guild_member_data& other) {
60 this->roleIds = other.roles;
61 if (roleIds.size() == 0) {
62 jsonifierExcludedKeys.emplace("roles");
63 }
64 this->deaf = other.deaf;
65 this->mute = other.mute;
66 this->nick = other.nick;
67 this->flags = static_cast<uint32_t>(other.flags);
68 this->guildId = other.guildId;
69 this->guildMemberId = other.user.id;
70 }
71
72 guild_member_cache_data& guild_member_cache_data::operator=(const guild_member_data& other) {
73 if (static_cast<int64_t>(other.flags) != 0) {
74 flags = other.flags;
75 }
76 setFlagValue(guild_member_flags::Pending, other.pending);
77 setFlagValue(guild_member_flags::Deaf, other.deaf);
78 setFlagValue(guild_member_flags::Mute, other.mute);
79 if (other.permissions.operator std::string_view() != "") {
80 permissionsVal = other.permissions;
81 }
82 if (other.joinedAt != "") {
83 joinedAt = other.joinedAt;
84 }
85 if (other.user.id != 0) {
86 user.id = other.user.id;
87 }
88 if (other.guildId != 0) {
89 guildId = other.guildId;
90 }
91 if (other.avatar != "") {
92 avatar = other.avatar;
93 }
94 if (other.roles.size() > 0) {
95 roles = other.roles;
96 }
97 if (other.nick != "") {
98 nick = other.nick;
99 }
100 return *this;
101 };
102
103 guild_member_cache_data::guild_member_cache_data(const guild_member_data& other) {
104 *this = other;
105 }
106
107 guild_member_cache_data& guild_member_cache_data::operator=(guild_member_data&& other) noexcept {
108 if (static_cast<int64_t>(other.flags) != 0) {
109 flags = other.flags;
110 }
111 setFlagValue(guild_member_flags::Pending, other.pending);
112 setFlagValue(guild_member_flags::Deaf, other.deaf);
113 setFlagValue(guild_member_flags::Mute, other.mute);
114 if (other.permissions.operator std::string_view() != "") {
115 permissionsVal = std::move(other.permissions);
116 }
117 if (other.joinedAt != "") {
118 joinedAt = std::move(other.joinedAt);
119 }
120 if (other.avatar != "") {
121 avatar = std::move(other.avatar);
122 }
123 if (other.roles.size() > 0) {
124 roles = std::move(other.roles);
125 }
126 if (other.nick != "") {
127 nick = std::move(other.nick);
128 }
129 if (other.user.id != 0) {
130 user.id = other.user.id;
131 }
132 if (other.guildId != 0) {
133 guildId = other.guildId;
134 }
135 return *this;
136 };
137
138 guild_member_cache_data::operator guild_member_data() {
139 guild_member_data returnData{};
140 returnData.permissions = permissionsVal.operator jsonifier::string();
141 returnData.pending = getFlagValue(guild_member_flags::Pending);
142 returnData.deaf = getFlagValue(guild_member_flags::Deaf);
143 returnData.mute = getFlagValue(guild_member_flags::Mute);
144 returnData.joinedAt = joinedAt.operator jsonifier::string();
145 returnData.guildId = guildId;
146 returnData.user.id = user.id;
147 returnData.avatar = avatar;
148 returnData.roles = roles;
149 returnData.flags = flags;
150 returnData.nick = nick;
151 return returnData;
152 }
153
154 guild_member_cache_data::guild_member_cache_data(guild_member_data&& other) noexcept {
155 *this = std::move(other);
156 }
157
158 void guild_members::initialize(discord_core_internal::https_client* client, config_manager* configManagerNew) {
159 guild_members::doWeCacheGuildMembersBool = configManagerNew->doWeCacheGuildMembers();
160 guild_members::doWeCacheVoiceStatesBool = configManagerNew->doWeCacheVoiceStates();
161 guild_members::httpsClient = client;
162 }
163
165 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Get_Guild_Member };
167 workload.workloadClass = discord_core_internal::https_workload_class::Get;
168 workload.relativePath = "/guilds/" + dataPackage.guildId + "/members/" + dataPackage.guildMemberId;
169 workload.callStack = "guild_members::getGuildMemberAsync()";
170 guild_member_data data{};
171 data.user.id = dataPackage.guildMemberId;
172 data.guildId = dataPackage.guildId;
173 two_id_key key{ data };
174 if (cache.contains(key)) {
175 data = cache[key];
176 }
177 guild_members::httpsClient->submitWorkloadAndGetResult(std::move(workload), data);
178 if (doWeCacheGuildMembersBool) {
179 insertGuildMember(static_cast<guild_member_cache_data>(data));
180 }
181 co_return data;
182 }
183
185 guild_member_cache_data data{};
186 data.user.id = dataPackage.guildMemberId;
187 data.guildId = dataPackage.guildId;
188 two_id_key key{ data };
189 if (cache.contains(key)) {
190 return cache[key];
191 } else {
192 return getGuildMemberAsync(dataPackage).get();
193 }
194 }
195
197 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Get_Guild_Members };
199 workload.workloadClass = discord_core_internal::https_workload_class::Get;
200 workload.relativePath = "/guilds/" + dataPackage.guildId + "/members";
201 if (dataPackage.after != 0) {
202 workload.relativePath += "?after=" + dataPackage.after;
203 if (dataPackage.limit != 0) {
204 workload.relativePath += "&limit=" + jsonifier::toString(dataPackage.limit);
205 }
206 } else if (dataPackage.limit != 0) {
207 workload.relativePath += "?limit=" + jsonifier::toString(dataPackage.limit);
208 }
209 workload.callStack = "guild_members::listGuildMembersAsync()";
210 jsonifier::vector<guild_member_data> returnData{};
211 guild_members::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
212 co_return returnData;
213 }
214
216 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Get_Search_Guild_Members };
218 workload.workloadClass = discord_core_internal::https_workload_class::Get;
219 workload.relativePath = "/guilds/" + dataPackage.guildId + "/members/search";
220 if (dataPackage.query != "") {
221 workload.relativePath += "?query=" + dataPackage.query;
222 if (dataPackage.limit != 0) {
223 workload.relativePath += "&limit=" + jsonifier::toString(dataPackage.limit);
224 }
225 } else if (dataPackage.limit != 0) {
226 workload.relativePath += "?limit=" + jsonifier::toString(dataPackage.limit);
227 }
228 workload.callStack = "guild_members::searchGuildMembersAsync()";
229 jsonifier::vector<guild_member_data> returnData{};
230 guild_members::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
231 co_return returnData;
232 }
233
235 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Put_Guild_Member };
237 workload.workloadClass = discord_core_internal::https_workload_class::Put;
238 workload.relativePath = "/guilds/" + dataPackage.guildId + "/members/" + dataPackage.userId;
239 parser.serializeJson(dataPackage, workload.content);
240 workload.callStack = "guild_members::addGuildMemberAsync()";
241 guild_member_data returnData{};
242 guild_members::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
243 co_return returnData;
244 }
245
247 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Patch_Current_Guild_Member };
249 workload.workloadClass = discord_core_internal::https_workload_class::Patch;
250 workload.relativePath = "/guilds/" + dataPackage.guildId + "/members/@me";
251 parser.serializeJson(dataPackage, workload.content);
252 workload.callStack = "guild_members::modifyCurrentGuildMemberAsync()";
253 if (dataPackage.reason != "") {
254 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
255 }
256 guild_member_data returnData{};
257 guild_members::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
258 co_return returnData;
259 }
260
262 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Patch_Guild_Member };
264 workload.workloadClass = discord_core_internal::https_workload_class::Patch;
265 if (dataPackage.communicationDisabledUntil.operator jsonifier::string_base<char>() == "") {
266 dataPackage.jsonifierExcludedKeys.emplace("communication_disabled_until");
267 }
268 if (dataPackage.channelId.operator jsonifier::string_base<char>() == "0" || dataPackage.channelId.operator const uint64_t &() == 0) {
269 dataPackage.jsonifierExcludedKeys.emplace("channel_id");
270 dataPackage.jsonifierExcludedKeys.emplace("mute");
271 dataPackage.jsonifierExcludedKeys.emplace("deaf");
272 }
273 if (dataPackage.flags == 0) {
274 dataPackage.jsonifierExcludedKeys.emplace("flags");
275 }
276 workload.relativePath = "/guilds/" + dataPackage.guildId + "/members/" + dataPackage.guildMemberId;
277 parser.serializeJson(dataPackage, workload.content);
278 workload.callStack = "guild_members::modifyGuildMemberAsync()";
279 if (dataPackage.reason != "") {
280 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
281 }
282 guild_member_data data{};
283 data.user.id = dataPackage.guildMemberId;
284 data.guildId = dataPackage.guildId;
285 two_id_key key{ data };
286 if (cache.contains(key)) {
287 data = cache[key];
288 }
289 try {
290 guild_members::httpsClient->submitWorkloadAndGetResult(std::move(workload), data);
291 } catch (const std::runtime_error& error) {
292 std::cout << error.what() << std::endl;
293 }
294 if (doWeCacheGuildMembersBool) {
295 insertGuildMember(static_cast<guild_member_cache_data>(data));
296 }
297 co_return data;
298 }
299
301 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Delete_Guild_Member };
302 co_await newThreadAwaitable<void>();
303 workload.workloadClass = discord_core_internal::https_workload_class::Delete;
304 workload.relativePath = "/guilds/" + dataPackage.guildId + "/members/" + dataPackage.guildMemberId;
305 workload.callStack = "guild_members::removeGuildMemberAsync()";
306 if (dataPackage.reason != "") {
307 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
308 }
309 guild_members::httpsClient->submitWorkloadAndGetResult(std::move(workload));
310 co_return;
311 }
312
315 get_guild_member_data dataNew{ .guildMemberId = dataPackage.guildMemberId, .guildId = dataPackage.guildId };
316 guild_member_data guildMember = guild_members::getCachedGuildMember(dataNew);
317 modify_guild_member_data dataPackage01{ guildMember };
318 dataPackage01.deaf = guildMember.getFlagValue(guild_member_flags::Deaf);
319 dataPackage01.guildId = guildMember.guildId;
320 dataPackage01.guildMemberId = guildMember.user.id;
321 dataPackage01.mute = guildMember.getFlagValue(guild_member_flags::Mute);
322 for (auto& value: guildMember.roles) {
323 dataPackage01.roleIds.emplace_back(value);
324 }
325 dataPackage01.nick = guildMember.nick;
326 dataPackage01.reason = dataPackage.reason;
327 time_stamp timeStamp{};
328 switch (dataPackage.numOfMinutesToTimeoutFor) {
330 auto string = timeStamp.convertToFutureISO8601TimeStamp(0, 0, 1, 0, 0, time_format::long_date_time);
331 dataPackage01.communicationDisabledUntil = string;
332 break;
333 }
335 auto string = timeStamp.convertToFutureISO8601TimeStamp(5, 0, 0, 0, 0, time_format::long_date_time);
336 dataPackage01.communicationDisabledUntil = string;
337 break;
338 }
340 auto string = timeStamp.convertToFutureISO8601TimeStamp(0, 1, 0, 0, 0, time_format::long_date_time);
341 dataPackage01.communicationDisabledUntil = string;
342 break;
343 }
345 auto string = timeStamp.convertToFutureISO8601TimeStamp(10, 0, 0, 0, 0, time_format::long_date_time);
346 dataPackage01.communicationDisabledUntil = string;
347 break;
348 }
350 auto string = timeStamp.convertToFutureISO8601TimeStamp(0, 0, 7, 0, 0, time_format::long_date_time);
351 dataPackage01.communicationDisabledUntil = string;
352 break;
353 }
355 auto string = timeStamp.convertToFutureISO8601TimeStamp(1, 0, 0, 0, 0, time_format::long_date_time);
356 dataPackage01.communicationDisabledUntil = string;
357 break;
358 }
360 auto string = timeStamp.convertToFutureISO8601TimeStamp(0, 0, 0, 0, 0, time_format::long_date_time);
361 dataPackage01.communicationDisabledUntil = string;
362 break;
363 }
364 }
365 guild_members::modifyGuildMemberAsync(dataPackage01).get();
366 co_return guildMember;
367 }
368
370 if (vsCache.contains(key)) {
371 return vsCache[key];
372 } else {
373 return {};
374 }
375 }
376
377 void guild_members::removeGuildMember(const two_id_key& key) {
378 cache.erase(key);
379 };
380
381 void guild_members::removeVoiceState(const two_id_key& key) {
382 vsCache.erase(key);
383 }
384
385 bool guild_members::doWeCacheGuildMembers() {
386 return guild_members::doWeCacheGuildMembersBool;
387 }
388
389 bool guild_members::doWeCacheVoiceStates() {
390 return guild_members::doWeCacheVoiceStatesBool;
391 }
392
393 object_cache<voice_state_data_light> guild_members::vsCache{};
394 object_cache<guild_member_cache_data> guild_members::cache{};
395 discord_core_internal::https_client* guild_members::httpsClient{};
396 bool guild_members::doWeCacheGuildMembersBool{};
397 bool guild_members::doWeCacheVoiceStatesBool{};
398};
A co_routine - representing a potentially asynchronous operation/function.
Data structure representing a single guild_member_data.
jsonifier::string nick
Their nick/display name.
icon_hash avatar
This guild_member_data's guild avatar.
time_stamp joinedAt
When they joined the guild.
user_id_base user
The user id for this guild_member_data.
permissions permissionsVal
Their base-level permissions in the guild.
guild_member_flags flags
Guild_member_data flags.
jsonifier::vector< snowflake > roles
The guild roGuildMemberDatales that they have.
Data structure representing a single guild_member_data.
jsonifier::vector< snowflake > roles
Array of role object ids.
snowflake guildId
The guild that this member belongs to.
permissions_parse permissions
Total permissions of the member in the channel, including overwrites.
user_data user
The user this guild member represents.
jsonifier::string nick
This user's guild nickname.
static co_routine< guild_member_data > modifyCurrentGuildMemberAsync(modify_current_guild_member_data dataPackage)
Modifies the current guild_member_data's properties.
static co_routine< guild_member_data > getGuildMemberAsync(get_guild_member_data dataPackage)
Collects a guild_member from the discord servers.
static co_routine< guild_member_data > addGuildMemberAsync(add_guild_member_data dataPackage)
Adds a guild_member to a chosen guild.
static co_routine< guild_member_data > modifyGuildMemberAsync(modify_guild_member_data dataPackage)
Modifies a guild_member's properties.
static co_routine< guild_member_data > timeoutGuildMemberAsync(timeout_guild_member_data dataPackage)
Times-out a chosen guild_member_data from a chosen guild.
static co_routine< void > removeGuildMemberAsync(remove_guild_member_data dataPackage)
Removes a chosen guild_member_data from a chosen guild.
static guild_member_cache_data getCachedGuildMember(get_guild_member_data dataPackage)
Collects a guild_member from the library's cache.
static co_routine< jsonifier::vector< guild_member_data > > listGuildMembersAsync(list_guild_members_data dataPackage)
Lists all of the guild_members of a chosen guild.
static voice_state_data_light getVoiceStateData(const two_id_key &voiceState)
Collect a given guild_member's voice state data.
static co_routine< jsonifier::vector< guild_member_data > > searchGuildMembersAsync(search_guild_members_data dataPackage)
Searches for a list of guild_members of a chosen guild.
A template class representing an object cache.
An interface class for the role_data related discord endpoints.
uint64_t id
The snowflake id.
Definition Base.hpp:832
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...
@ long_date_time
"Tuesday, 20 April 2021 16:20" - Long Date/Time
Definition Base.hpp:336
The main namespace for the forward-facing interfaces.
For adding a new guild_member_data to a chosen guild.
snowflake userId
The user_data id of the user you wish to add.
snowflake guildId
The guild to add the new guild_member_data to.
For getting a guild_member, from the library's cache or discord server.
snowflake guildMemberId
The user id of the desired guild_member_data.
snowflake guildId
The id of the guild from which you would like to acquire a member.
For listing the guild_members of a chosen guild.
snowflake after
The highest user id in the previous page.
int32_t limit
Max number of members to return (1 - 1000).
snowflake guildId
Guild from which to list the guild_members.
For modifying the current guild_member_data's values.
jsonifier::string reason
A reason for modifying the current user's values.
snowflake guildId
The guild within which to modify the current user's values.
For modifying a guild_member's values.
snowflake guildId
The id of the guild for which you would like to modify a member.
jsonifier::string communicationDisabledUntil
When the user's timeout will expire and the user will be able to communicate in the guild again.
jsonifier::vector< snowflake > roleIds
A collection of role_data id's to be applied to them.
bool deaf
Whether or not to deafen them, in voice.
bool mute
Whether or not to mute them in voice.
snowflake channelId
The current voice channel_data, if applicaple.
jsonifier::string reason
Reason for modifying this guild_member_data.
jsonifier::string nick
Their new display/nick name.
snowflake guildMemberId
The user id of the desired guild memeber.
For removing a guild_member from a chosen guild.
snowflake guildMemberId
snowflake of the chosen guild_member_data to kick.
snowflake guildId
Guild from which to kick the chosen guild_member_data.
jsonifier::string reason
Reason for kicking the guild_member_data.
For searching for one or more guild_members within a chosen guild.
int32_t limit
Max number of members to return (1 - 1000).
snowflake guildId
Guild within which to search for the guild_members.
jsonifier::string query
Query jsonifier::string to match username(s) and nickname(s) against.
jsonifier::string reason
Reason for timing them out.
snowflake guildMemberId
The id of the guild_member_data to be timed-out.
snowflake guildId
The id of the guild from which you would like to acquire a member.
timeout_durations numOfMinutesToTimeoutFor
The number of minutes to time-out the guild_member_data for.
snowflake channelId
The channel_data id this user_data is connected to.