DiscordCoreAPI
A Discord bot library written in C++, with custom asynchronous coroutines.
Loading...
Searching...
No Matches
MessageEntities.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/// MessageEntities.cpp - Source file for the message_data related classes and structs.
27/// May 13, 2021
28/// https://discordcoreapi.com
29/// \file MessageEntities.cpp
30
36
37namespace jsonifier {
38
39 template<> struct core<discord_core_api::message_response_base> {
40 using value_type = discord_core_api::message_response_base;
41 static constexpr auto parseValue =
42 createValue("components", &value_type::components, "allowed_mentions", &value_type::allowedMentions, "embeds", &value_type::embeds,
43 "custom_id", &value_type::customId, "content", &value_type::content, "title", &value_type::title, "flags", &value_type::flags, "tts", &value_type::tts);
44 };
45
46 template<> struct core<discord_core_api::create_message_data> {
47 using value_type = discord_core_api::create_message_data;
48 static constexpr auto parseValue =
49 createValue("components", &value_type::components, "allowed_mentions", &value_type::allowedMentions, "embeds", &value_type::embeds,
50 "custom_id", &value_type::customId, "content", &value_type::content, "title", &value_type::title, "flags", &value_type::flags, "tts", &value_type::tts);
51 };
52
53 template<> struct core<discord_core_api::edit_message_data> {
54 using value_type = discord_core_api::edit_message_data;
55 static constexpr auto parseValue =
56 createValue("components", &value_type::components, "allowed_mentions", &value_type::allowedMentions, "embeds", &value_type::embeds,
57 "custom_id", &value_type::customId, "content", &value_type::content, "title", &value_type::title, "flags", &value_type::flags, "tts", &value_type::tts);
58 };
59
60 template<> struct core<discord_core_api::delete_messages_bulk_data> {
61 using value_type = discord_core_api::delete_messages_bulk_data;
62 static constexpr auto parseValue = createValue("messages", &value_type::messageIds);
63 };
64}
65
66namespace discord_core_api {
67
68 template<> unordered_map<jsonifier::string, unbounded_message_block<message_data>*> object_collector<message_data>::objectsBuffersMap{};
69
70 template<> object_collector<message_data>::object_collector() {
71 collectorId = jsonifier::toString(std::chrono::duration_cast<milliseconds>(sys_clock::now().time_since_epoch()).count());
72 object_collector::objectsBuffersMap[collectorId] = &objectsBuffer;
73 };
74
75 template<> void object_collector<message_data>::run(std::coroutine_handle<
76 typename discord_core_api::co_routine<discord_core_api::object_collector<discord_core_api::message_data>::object_collector_return_data, false>::promise_type>& coroHandle) {
77 int64_t startingTime = static_cast<int64_t>(std::chrono::duration_cast<milliseconds>(sys_clock::now().time_since_epoch()).count());
78 int64_t elapsedTime{};
79 while (elapsedTime < msToCollectFor && !coroHandle.promise().stopRequested()) {
80 message_data message{};
81 waitForTimeToPass<message_data>(objectsBuffer, message, static_cast<uint64_t>(msToCollectFor - static_cast<uint64_t>(elapsedTime)));
82 if (filteringFunction(message)) {
83 objectReturnData.objects.emplace_back(message);
84 }
85 if (static_cast<int32_t>(objectReturnData.objects.size()) >= quantityOfObjectsToCollect) {
86 break;
87 }
88
89 elapsedTime = std::chrono::duration_cast<milliseconds>(sys_clock::now().time_since_epoch()).count() - startingTime;
90 }
91 }
92
94 int32_t msToCollectForNew, object_filter<message_data> filteringFunctionNew) {
96 quantityOfObjectsToCollect = quantityToCollect;
97 filteringFunction = filteringFunctionNew;
98 msToCollectFor = msToCollectForNew;
99
100 run(coroHandle);
101 co_return objectReturnData;
102 }
103
104 template<> object_collector<message_data>::~object_collector() {
105 if (object_collector::objectsBuffersMap.contains(collectorId)) {
106 object_collector::objectsBuffersMap.erase(collectorId);
107 }
108 };
109
110 create_message_data::create_message_data(const snowflake channelIdNew) {
111 channelId = channelIdNew;
112 }
113
114 create_message_data::create_message_data(respond_to_input_event_data dataPackage) {
115 channelId = dataPackage.channelId;
116 addAllowedMentions(dataPackage.allowedMentions);
117 for (auto& value: dataPackage.components) {
118 components.emplace_back(value);
119 }
120 addContent(dataPackage.content);
121 for (auto& value: dataPackage.embeds) {
122 embeds.emplace_back(value);
123 }
124 tts = dataPackage.tts;
125 }
126
127 create_message_data::create_message_data(message_data dataPackage) {
128 channelId = dataPackage.channelId;
129 messageReference.channelId = dataPackage.channelId;
130 messageReference.messageId = dataPackage.id;
131 messageReference.guildId = dataPackage.guildId;
132 tts = dataPackage.tts;
133 }
134
135 create_message_data::create_message_data(input_event_data dataPackage) {
136 channelId = dataPackage.getChannelData().id;
137 }
138
139 send_dmdata::send_dmdata(respond_to_input_event_data dataPackage) {
140 targetUserId = dataPackage.targetUserId;
141 addAllowedMentions(dataPackage.allowedMentions);
142 for (auto& value: dataPackage.components) {
143 components.emplace_back(value);
144 }
145 addContent(dataPackage.content);
146 for (auto& value: dataPackage.embeds) {
147 embeds.emplace_back(value);
148 }
149 channelId = dataPackage.targetUserId;
150 tts = dataPackage.tts;
151 }
152
153 edit_message_data::edit_message_data(input_event_data dataPackage) {
154 channelId = dataPackage.getChannelData().id;
155 messageId = dataPackage.getMessageData().id;
156 }
157
158 edit_message_data::edit_message_data(respond_to_input_event_data dataPackage) {
159 allowedMentions = dataPackage.allowedMentions;
160 channelId = dataPackage.channelId;
161 messageId = dataPackage.messageId;
162 for (auto& value: dataPackage.components) {
163 components.emplace_back(value);
164 }
165 content = dataPackage.content;
166 for (auto& value: dataPackage.embeds) {
167 embeds.emplace_back(value);
168 }
169 }
170
171 delete_message_data::delete_message_data(const message_data& messageToDelete) {
172 channelId = messageToDelete.channelId;
173 timeStamp = messageToDelete.timeStamp;
174 messageId = messageToDelete.id;
175 }
176
177 void messages::initialize(discord_core_internal::https_client* client) {
178 messages::httpsClient = client;
179 }
180
182 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Get_Messages };
184 workload.workloadClass = discord_core_internal::https_workload_class::Get;
185 workload.relativePath = "/channels/" + dataPackage.channelId + "/messages";
186 if (dataPackage.aroundThisId != 0) {
187 workload.relativePath += "?around=" + dataPackage.aroundThisId;
188 if (dataPackage.limit != 0) {
189 workload.relativePath += "&limit=" + jsonifier::toString(dataPackage.limit);
190 } else {
191 workload.relativePath += "&limit=1";
192 }
193 } else if (dataPackage.beforeThisId != 0) {
194 workload.relativePath += "?before=" + dataPackage.beforeThisId;
195 if (dataPackage.limit != 0) {
196 workload.relativePath += "&limit=" + jsonifier::toString(dataPackage.limit);
197 } else {
198 workload.relativePath += "&limit=1";
199 }
200 } else if (dataPackage.afterThisId != 0) {
201 workload.relativePath += "?after=" + dataPackage.afterThisId;
202 if (dataPackage.limit != 0) {
203 workload.relativePath += "&limit=" + jsonifier::toString(dataPackage.limit);
204 } else {
205 workload.relativePath += "&limit=1";
206 }
207 } else {
208 if (dataPackage.limit != 0) {
209 workload.relativePath += "?limit=" + jsonifier::toString(dataPackage.limit);
210 } else {
211 workload.relativePath += "&limit=1";
212 }
213 }
214 workload.callStack = "messages::getMessagesAsync()";
215 jsonifier::vector<message_data> returnData{};
216 messages::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
217 std::cout << "CURRENT RESULTS: " << returnData.at(0).timeStamp << std::endl;
218 co_return returnData;
219 }
220
222 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Get_Message };
224 workload.workloadClass = discord_core_internal::https_workload_class::Get;
225 workload.relativePath = "/channels/" + dataPackage.channelId + "/messages/" + dataPackage.id;
226 workload.callStack = "messages::getMessageAsync()";
227 message_data returnData{};
228 messages::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
229 co_return returnData;
230 }
231
233 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Post_Message };
235 workload.workloadClass = discord_core_internal::https_workload_class::Post;
236 workload.relativePath = "/channels/" + dataPackage.channelId + "/messages";
237 if (dataPackage.files.size() > 0) {
238 workload.payloadType = discord_core_internal::payload_type::Multipart_Form;
239 parser.serializeJson(dataPackage, workload.content);
240 } else {
241 parser.serializeJson(dataPackage, workload.content);
242 }
243 workload.callStack = "messages::createMessageAsync()";
244 message_data returnData{};
245 messages::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
246 co_return returnData;
247 }
248
250 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Crosspost_Message };
252 workload.workloadClass = discord_core_internal::https_workload_class::Post;
253 workload.relativePath = "/channels/" + dataPackage.channelId + "/messages/" + dataPackage.messageId + "/crosspost";
254 workload.callStack = "messages::crosspostMessageAsync()";
255 message_data returnData{};
256 messages::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
257 co_return returnData;
258 }
259
261 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Patch_Message };
263 workload.workloadClass = discord_core_internal::https_workload_class::Patch;
264 workload.relativePath = "/channels/" + dataPackage.channelId + "/messages/" + dataPackage.messageId;
265 if (dataPackage.files.size() > 0) {
266 workload.payloadType = discord_core_internal::payload_type::Multipart_Form;
267 parser.serializeJson(dataPackage, workload.content);
268 } else {
269 parser.serializeJson(dataPackage, workload.content);
270 }
271 workload.callStack = "messages::editMessageAsync()";
272 message_data returnData{};
273 messages::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
274 co_return returnData;
275 }
276
278 discord_core_internal::https_workload_data workload{};
279 bool hasTimeElapsedNew = dataPackage.timeStamp.hasTimeElapsed(14, 0, 0);
280 if (!hasTimeElapsedNew) {
281 workload = discord_core_internal::https_workload_type::Delete_Message;
282 } else {
283 workload = discord_core_internal::https_workload_type::Delete_Message_Old;
284 }
285 co_await newThreadAwaitable<void>();
286 if (dataPackage.timeDelay > 0) {
287 std::this_thread::sleep_for(milliseconds{ dataPackage.timeDelay });
288 }
289 workload.workloadClass = discord_core_internal::https_workload_class::Delete;
290 workload.relativePath = "/channels/" + dataPackage.channelId + "/messages/" + dataPackage.messageId;
291 workload.callStack = "messages::deleteMessageAsync()";
292 if (dataPackage.reason != "") {
293 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
294 }
295 messages::httpsClient->submitWorkloadAndGetResult(std::move(workload));
296 co_return;
297 }
298
300 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Bulk_Delete_Messages };
301 co_await newThreadAwaitable<void>();
302 workload.workloadClass = discord_core_internal::https_workload_class::Post;
303 workload.relativePath = "/channels/" + dataPackage.channelId + "/messages/bulk-delete";
304 parser.serializeJson(dataPackage, workload.content);
305 if (dataPackage.reason != "") {
306 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
307 }
308 messages::httpsClient->submitWorkloadAndGetResult(std::move(workload));
309 co_return;
310 }
311
313 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Get_Pinned_Messages };
315 workload.workloadClass = discord_core_internal::https_workload_class::Get;
316 workload.relativePath = "/channels/" + dataPackage.channelId + "/pins";
317 workload.callStack = "messages::getPinnedMessagesAsync()";
318 jsonifier::vector<message_data> returnData{};
319 messages::httpsClient->submitWorkloadAndGetResult(std::move(workload), returnData);
320 co_return returnData;
321 }
322
324 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Put_Pin_Message };
325 co_await newThreadAwaitable<void>();
326 workload.workloadClass = discord_core_internal::https_workload_class::Put;
327 workload.relativePath = "/channels/" + dataPackage.channelId + "/pins/" + dataPackage.messageId;
328 workload.callStack = "messages::pinMessageAsync()";
329 if (dataPackage.reason != "") {
330 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
331 }
332 messages::httpsClient->submitWorkloadAndGetResult(std::move(workload));
333 co_return;
334 }
335
337 discord_core_internal::https_workload_data workload{ discord_core_internal::https_workload_type::Delete_Pin_Message };
338 co_await newThreadAwaitable<void>();
339 workload.workloadClass = discord_core_internal::https_workload_class::Delete;
340 workload.relativePath = "/channels/" + dataPackage.channelId + "/pins/" + dataPackage.messageId;
341 workload.callStack = "messages::unpinMessageAsync()";
342 if (dataPackage.reason != "") {
343 workload.headersToInsert["x-audit-log-reason"] = dataPackage.reason;
344 }
345 messages::httpsClient->submitWorkloadAndGetResult(std::move(workload));
346 co_return;
347 }
348
349 discord_core_internal::https_client* messages::httpsClient{};
350}
A co_routine - representing a potentially asynchronous operation/function.
Data representing an input-event, which is any message or interaction that is coming into the bot as ...
The core of a message's data structure.
message_response_base & addAllowedMentions(const allowed_mentions_data &dataPackage)
For setting the allowable mentions in a response.
message_response_base & addContent(const jsonifier::string &dataPackage)
For setting the message content in a response.
static co_routine< void > deleteMessagesBulkAsync(delete_messages_bulk_data dataPackage)
Deletes a collection of messages.
static co_routine< message_data > getMessageAsync(get_message_data dataPackage)
Collects a message from the discord servers.
static co_routine< void > pinMessageAsync(pin_message_data dataPackage)
Pins a message to a given channel.
static co_routine< message_data > createMessageAsync(create_message_data dataPackage)
Creates a new message_data.
static co_routine< jsonifier::vector< message_data > > getPinnedMessagesAsync(get_pinned_messages_data dataPackage)
Collects a collection of pinned messages from the discord servers.
static co_routine< jsonifier::vector< message_data > > getMessagesAsync(get_messages_data dataPackage)
Collects a collection of message from the discord servers.
static co_routine< message_data > editMessageAsync(edit_message_data dataPackage)
Edit a message.
static co_routine< void > unpinMessageAsync(unpin_message_data dataPackage)
Unpins a message from a given channel.
static co_routine< message_data > crosspostMessageAsync(crosspost_message_data dataPackage)
Crossposts a message from a news channel_data to the following channels.
static co_routine< void > deleteMessageAsync(delete_message_data dataPackage)
Deletes a message.
co_routine< object_collector_return_data, false > collectObjects(int32_t quantityToCollect, int32_t msToCollectForNew, object_filter< value_type > filteringFunctionNew)
Begin waiting for objects.
Data for responding to an input-event.
A class representing a snowflake identifier with various operations.
Definition Base.hpp:701
DCA_INLINE bool hasTimeElapsed(int64_t days, int64_t hours, int64_t minutes) const
Checks if a certain time duration has elapsed.
Definition Base.hpp:440
std::function< bool(value_type)> object_filter
Typedef for the message filter.
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.
snowflake messageId
snowflake of the message to be crossposted.
snowflake channelId
channel_data within which to crosspost the message from.
snowflake messageId
The message snowflake of the message to delete.
snowflake channelId
The channel snowflake of the message to delete.
jsonifier::string reason
The reason for deleting the message_data.
int32_t timeDelay
Number of milliseconds to wait before deleting the message_data.
time_stamp timeStamp
The created-at timeStamp of the original message.
snowflake channelId
channel_data within which to delete the messages.
jsonifier::string reason
The reason for deleting the messages.
snowflake id
The id of the message to collect.
snowflake channelId
The channel_data from which to collect the message_data.
For getting a collection of messages.
snowflake aroundThisId
Around this id.
snowflake beforeThisId
Before this id.
int32_t limit
Limit of messages to collect.
snowflake channelId
channel_data from which to collect the messages.
For getting a collection of pinned messages.
snowflake channelId
The channel_data from which to collect pinned messages.
For pinning a single message_data.
snowflake messageId
The message which you would like to pin.
snowflake channelId
The channel_data within which to pin the message_data.
jsonifier::string reason
Reason for pinning this message_data.
For unpinning a single message_data.
jsonifier::string reason
Reason for pinning this message_data.
snowflake channelId
The channel_data within which to unpin the message_data.
snowflake messageId
The message which you would like to unpin.