DiscordCoreAPI
A Discord bot library written in C++, with custom asynchronous coroutines.
Loading...
Searching...
No Matches
RoleEntities.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/// RoleEntities.cpp - Source file for the role_data related classes and structs.
27/// May 13, 2021
28/// https://discordcoreapi.com
29/// \file RoleEntities.cpp
30
34
35namespace jsonifier {
36
37 template<> struct core<discord_core_api::modify_guild_role_positions_data> {
38 using value_type = discord_core_api::modify_guild_role_positions_data;
39 static constexpr auto parseValue = createValue("guild_id", &value_type::guildId, "id", &value_type::roleId, "positions", &value_type::rolePositions, "reason",
40 &value_type::reason, "position", &value_type::newPosition);
41 };
42
43 template<> struct core<discord_core_api::modify_guild_role_data> {
44 using value_type = discord_core_api::modify_guild_role_data;
45 static constexpr auto parseValue = createValue("color", &value_type::hexColorValue, "hoist", &value_type::hoist, "id", &value_type::roleId, "mentionable",
46 &value_type::mentionable, "name", &value_type::name, "permissions", &value_type::permissions, "unicode_emoji", &value_type::unicodeEmoji,
47 "guild_id", &value_type::guildId, "icon", &value_type::icon);
48 };
49
50 template<> struct core<discord_core_api::create_guild_role_data> {
51 using value_type = discord_core_api::create_guild_role_data;
52 static constexpr auto parseValue = createValue("color", &value_type::hexColorValue, "hoist", &value_type::hoist, "id", &value_type::guildId, "mentionable",
53 &value_type::mentionable, "name", &value_type::name, "permissions", &value_type::permissions, "position", &value_type::position,
54 "unicode_emoji", &value_type::unicodeEmoji, "icon", &value_type::icon);
55 };
56
57 template<> struct core<discord_core_api::role_position_data> {
58 using value_type = discord_core_api::role_position_data;
59 static constexpr auto parseValue = createValue("position", &value_type::rolePosition, "id", &value_type::roleId);
60 };
61}
62
63namespace discord_core_api {
64
65 role_cache_data& role_cache_data::operator=(const role_data& other) {
66 flags = other.flags;
67 setFlagValue<role_flags>(role_flags::mentionable, other.mentionable);
68 setFlagValue<role_flags>(role_flags::managed, other.managed);
69 setFlagValue<role_flags>(role_flags::hoist, other.hoist);
70 if (other.unicodeEmoji != "") {
71 unicodeEmoji = other.unicodeEmoji;
72 }
73 if (other.permissions.operator std::string_view() != "") {
74 permissionsVal = other.permissions;
75 }
76 if (other.position != 0) {
77 position = other.position;
78 }
79 if (other.color != 0) {
80 color = other.color;
81 }
82 if (other.name != "") {
83 name = other.name;
84 }
85 if (other.id != 0) {
86 id = other.id;
87 }
88 return *this;
89 }
90
91 role_cache_data::role_cache_data(const role_data& other) {
92 *this = other;
93 }
94
95 role_cache_data& role_cache_data::operator=(role_data&& other) noexcept {
96 flags = other.flags;
97 setFlagValue<role_flags>(role_flags::mentionable, other.mentionable);
98 setFlagValue<role_flags>(role_flags::managed, other.managed);
99 setFlagValue<role_flags>(role_flags::hoist, other.hoist);
100 if (other.unicodeEmoji != "") {
101 unicodeEmoji = std::move(other.unicodeEmoji);
102 }
103 if (other.permissions.operator std::string_view() != "") {
104 permissionsVal = std::move(other.permissions);
105 }
106 if (other.name != "") {
107 name = std::move(other.name);
108 }
109 if (other.position != 0) {
110 position = other.position;
111 }
112 if (other.color != 0) {
113 color = other.color;
114 }
115 if (other.id != 0) {
116 id = other.id;
117 }
118 return *this;
119 }
120
121 role_cache_data::operator role_data() {
122 role_data returnData{};
123 returnData.mentionable = getFlagValue<role_flags>(role_flags::mentionable);
124 returnData.managed = getFlagValue<role_flags>(role_flags::managed);
125 returnData.hoist = getFlagValue<role_flags>(role_flags::hoist);
126 returnData.permissions = permissionsVal.operator jsonifier::string();
127 returnData.unicodeEmoji = unicodeEmoji;
128 returnData.position = position;
129 returnData.flags = flags;
130 returnData.color = color;
131 returnData.name = name;
132 returnData.id = id;
133 return returnData;
134 }
135
136 role_cache_data::role_cache_data(role_data&& other) noexcept {
137 *this = std::move(other);
138 }
139
140 role_data::role_data(snowflake newId) {
141 id = newId;
142 }
143
144 void roles::initialize(discord_core_internal::https_client* client, config_manager* configManagerNew) {
145 roles::doWeCacheRolesBool = configManagerNew->doWeCacheRoles();
146 roles::httpsClient = client;
147 }
148
150 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Put_Guild_Member_Role };
151 co_await newThreadAwaitable<void>();
152 workload.workloadClass = discord_core_internal::https_workload_class::Put;
153 workload.relativePath = "/guilds/" + dataPackage.guildId + "/members/" + dataPackage.userId + "/roles/" + dataPackage.roleId;
154 workload.callStack = "roles::addGuildMemberRoleAsync()";
155 if (dataPackage.reason != "") {
156 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
157 }
158 roles::httpsClient->submitWorkloadAndGetResult(std::move(workload));
159 co_return;
160 }
161
163 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Delete_Guild_Member_Role };
164 co_await newThreadAwaitable<void>();
165 workload.workloadClass = discord_core_internal::https_workload_class::Delete;
166 workload.relativePath = "/guilds/" + dataPackage.guildId + "/members/" + dataPackage.userId + "/roles/" + dataPackage.roleId;
167 workload.callStack = "roles::removeGuildMemberRoleAsync()";
168 if (dataPackage.reason != "") {
169 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
170 }
171 roles::httpsClient->submitWorkloadAndGetResult(std::move(workload));
172 co_return;
173 }
174
176 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Get_Guild_Roles };
178 if (dataPackage.guildId == 0) {
179 throw dca_exception{ "roles::getGuildRolesAsync() error: sorry, but you forgot to set the guildId!" };
180 }
181 workload.workloadClass = discord_core_internal::https_workload_class::Get;
182 workload.relativePath = "/guilds/" + dataPackage.guildId + "/roles";
183 workload.callStack = "roles::getGuildRolesAsync()";
184 jsonifier::vector<role_data> returnData{};
185 roles::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
186 co_return returnData;
187 }
188
190 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Post_Guild_Role };
192 workload.workloadClass = discord_core_internal::https_workload_class::Post;
193 workload.relativePath = "/guilds/" + dataPackage.guildId + "/roles";
194 parser.serializeJson(dataPackage, workload.content);
195 workload.callStack = "roles::createGuildRoleAsync()";
196 if (dataPackage.reason != "") {
197 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
198 }
199 role_data returnData{};
200 roles::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
201 modify_guild_role_positions_data newDataPackage{};
202 newDataPackage.guildId = dataPackage.guildId;
203 newDataPackage.newPosition = dataPackage.position;
204 newDataPackage.roleId = returnData.id;
205 auto results = modifyGuildRolePositionsAsync(newDataPackage).get();
206 for (auto& value: results) {
207 if (value.id == returnData.id) {
208 returnData = value;
209 }
210 }
211 co_return returnData;
212 }
213
215 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Patch_Guild_Role_Positions };
217 jsonifier::vector<role_data> currentRoles = roles::getGuildRolesAsync({ .guildId = dataPackage.guildId }).get();
218 role_data newRole = roles::getCachedRole({ .roleId = dataPackage.roleId });
219 for (auto& value: currentRoles) {
220 if (value.id == newRole.id) {
221 continue;
222 }
223 role_position_data newData;
224 if (newRole.position < dataPackage.newPosition) {
225 if (value.position <= dataPackage.newPosition && value.position > newRole.position) {
226 newData.roleId = value.id;
227 newData.rolePosition = value.position - 1;
228 dataPackage.rolePositions.emplace_back(newData);
229 }
230 } else {
231 if (value.position >= dataPackage.newPosition && value.position < newRole.position) {
232 newData.roleId = value.id;
233 newData.rolePosition = value.position + 1;
234 dataPackage.rolePositions.emplace_back(newData);
235 }
236 }
237 }
238 role_position_data newDataPos;
239 newDataPos.roleId = dataPackage.roleId;
240 newDataPos.rolePosition = dataPackage.newPosition;
241 dataPackage.rolePositions.emplace_back(newDataPos);
242 workload.workloadClass = discord_core_internal::https_workload_class::Patch;
243 workload.relativePath = "/guilds/" + dataPackage.guildId + "/roles";
244 parser.serializeJson(dataPackage, workload.content);
245 workload.callStack = "roles::modifyGuildRolePositionsAsync()";
246 if (dataPackage.reason != "") {
247 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
248 }
249 jsonifier::vector<role_data> returnData{};
250 roles::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
251 co_return returnData;
252 }
253
255 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Patch_Guild_Role };
257 workload.workloadClass = discord_core_internal::https_workload_class::Patch;
258 workload.relativePath = "/guilds/" + dataPackage.guildId + "/roles/" + dataPackage.roleId;
259 parser.serializeJson(dataPackage, workload.content);
260 workload.callStack = "roles::modifyGuildRoleAsync()";
261 if (dataPackage.reason != "") {
262 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
263 }
264 role_data data{ dataPackage.roleId };
265 if (cache.contains(data.id)) {
266 data = cache[data.id];
267 }
268 roles::httpsClient->submitWorkloadAndGetResult(std::move(workload), data);
269 if (doWeCacheRolesBool) {
270 insertRole(static_cast<role_cache_data>(data));
271 }
272 co_return data;
273 }
274
276 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Delete_Guild_Role };
277 co_await newThreadAwaitable<void>();
278 workload.workloadClass = discord_core_internal::https_workload_class::Delete;
279 workload.relativePath = "/guilds/" + dataPackage.guildId + "/roles/" + dataPackage.roleId;
280 workload.callStack = "roles::removeGuildRoleAsync()";
281 if (dataPackage.reason != "") {
282 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
283 }
284 roles::httpsClient->submitWorkloadAndGetResult(std::move(workload));
285 co_return;
286 }
287
290 jsonifier::vector<role_data> rolesVector = getGuildRolesAsync({ .guildId = dataPackage.guildId }).get();
291 jsonifier::vector<role_data> rolesVectorNew{};
292 for (auto& value: rolesVector) {
293 for (auto& value2: dataPackage.guildMember.roles) {
294 if (value2 == value.id) {
295 rolesVectorNew.emplace_back(value);
296 }
297 }
298 }
299 co_return std::move(rolesVectorNew);
300 }
301
304 auto roles = getGuildRolesAsync({ .guildId = dataPackage.guildId }).get();
305 if (dataPackage.guildId == 0) {
306 throw dca_exception{ "roles::getRoleAsync() error: sorry, but you forgot to set the guildId!" };
307 }
308 role_data data{ dataPackage.roleId };
309 if (cache.contains(data.id)) {
310 data = cache[data.id];
311 }
312 for (auto& value: roles) {
313 if (value.id == dataPackage.roleId) {
314 data = std::move(value);
315 }
316 }
317 if (doWeCacheRolesBool) {
318 insertRole(static_cast<role_cache_data>(data));
319 }
320 co_return data;
321 }
322
324 if (cache.contains(dataPackage.roleId)) {
325 return cache[dataPackage.roleId];
326 } else {
327 return getRoleAsync({ .guildId = dataPackage.guildId, .roleId = dataPackage.roleId }).get();
328 }
329 }
330
331 void roles::removeRole(const role_cache_data& roleId) {
332 cache.erase(roleId);
333 };
334
335 bool roles::doWeCacheRoles() {
336 return roles::doWeCacheRolesBool;
337 }
338
339 discord_core_internal::https_client* roles::httpsClient{};
340 object_cache<role_cache_data> roles::cache{};
341 bool roles::doWeCacheRolesBool{};
342};
A co_routine - representing a potentially asynchronous operation/function.
jsonifier::vector< snowflake > roles
Array of role object ids.
A template class representing an object cache.
Data structure representing a single role_data.
jsonifier::string name
The role_data's name.
uint32_t position
Its position amongst the rest of the guild's roles.
jsonifier::string unicodeEmoji
Emoji representing the role_data.
permissions permissionsVal
The role_data's base guild permissions.
uint32_t color
The role_data's color.
bool mentionable
Whether this role is mentionable.
uint32_t position
Position of this role.
static co_routine< role_data > createGuildRoleAsync(create_guild_role_data dataPackage)
Creates a new role_data within the given guild.
static co_routine< void > addGuildMemberRoleAsync(add_guild_member_role_data dataPackage)
Adds a role_data to a chosen guild member.
static co_routine< jsonifier::vector< role_data > > getGuildMemberRolesAsync(get_guild_member_roles_data dataPackage)
Collects the roles that a guild_member has.
static co_routine< void > removeGuildRoleAsync(remove_guild_role_data dataPackage)
Removes a given role from a guild.
static co_routine< role_data > getRoleAsync(get_role_data dataPackage)
Collects a role_data from the discord servers.
static co_routine< jsonifier::vector< role_data > > modifyGuildRolePositionsAsync(modify_guild_role_positions_data dataPackage)
Updates a role_data's positions.
static co_routine< role_data > modifyGuildRoleAsync(modify_guild_role_data dataPackage)
Updates a given role's properties.
static co_routine< void > removeGuildMemberRoleAsync(remove_guild_member_role_data dataPackage)
Removes a given role from a chosen guild_member_data.
static role_cache_data getCachedRole(get_role_data dataPackage)
Collects a given role from the library's cache.
static co_routine< jsonifier::vector< role_data > > getGuildRolesAsync(get_guild_roles_data dataPackage)
Collects the roles that a guild has.
A class representing a snowflake identifier with various operations.
Definition Base.hpp:701
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...
The main namespace for the forward-facing interfaces.
For addin a role_data to a guild_member.
snowflake guildId
The id of the guild within which to assign the role_data.
snowflake userId
The id of the user_data to whom to assign the role_data.
jsonifier::string reason
Reason for adding the guild_member_data's role_data.
snowflake roleId
The id of the role_data to be assigned.
For creating a new role_data within a chosen guild.
uint32_t position
The position amongst the other roles.
snowflake guildId
Which guild to make the role_data in.
jsonifier::string reason
Reason for creating the role_data.
For getting a chosen guild_member_data's roles.
snowflake guildId
Which guild to collect their roles from.
guild_member_data guildMember
Which guild member to collect the roles from.
For getting a chosen guild's roles.
snowflake guildId
Guild id for which guild to get the roles from.
For getting a role_data from the library's cache, or the discord server.
snowflake roleId
Which role_data to collect.
snowflake guildId
Which guild to collect the role_data from.
For updating a role_data's options within a chosen guild.
jsonifier::string reason
< reason for modifying the role_data.
snowflake roleId
The id of the role_data to update.
snowflake guildId
The id of the guild within which to update the role_data.
For updating the role_data positions.
jsonifier::string reason
Reason for modifying the role_data positions.
snowflake guildId
The guild within which to move the role_data.
snowflake roleId
The id of the role_data to move.
uint32_t newPosition
The new position of the role_data.
For removing a role_data from a guild_member.
jsonifier::string reason
Reason for removing the guild_member_data's role_data.
snowflake roleId
The id of the role_data to be removed.
snowflake userId
The id of the user_data from whom to remove the role_data.
snowflake guildId
The id of the guild within which to remove the role_data.
For removing a role_data from a chosen guild.
snowflake guildId
The id of the guild from which to remove the role_data.
jsonifier::string reason
Reason for removing this role_data.
snowflake roleId
The id of the role_data to remove.
uint32_t rolePosition
The new role_data position.
snowflake roleId
The role_data to update.