cleanup and remove all uneeded stuff
This commit is contained in:
parent
8dfa0e5f2b
commit
9d66c12590
1669
dpp/appcommand.h
1669
dpp/appcommand.h
File diff suppressed because it is too large
Load Diff
@ -1,523 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <dpp/integration.h>
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/managed.h>
|
||||
#include <dpp/utility.h>
|
||||
#include <dpp/user.h>
|
||||
#include <dpp/guild.h>
|
||||
#include <dpp/permissions.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/json_interface.h>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief status of a member of a team who maintain a bot/application
|
||||
*/
|
||||
enum team_member_status : uint8_t {
|
||||
/**
|
||||
* @brief User was invited to the team.
|
||||
*/
|
||||
tms_invited = 1,
|
||||
/**
|
||||
* @brief User has accepted membership onto the team.
|
||||
*/
|
||||
tms_accepted = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Flags for a bot or application
|
||||
*/
|
||||
enum application_flags : uint32_t {
|
||||
/**
|
||||
* @brief Indicates if an app uses the Auto Moderation API
|
||||
*/
|
||||
apf_application_automod_rule_create_badge = (1 << 6),
|
||||
|
||||
/**
|
||||
* @brief Has gateway presence intent
|
||||
*/
|
||||
apf_gateway_presence = (1 << 12),
|
||||
|
||||
/**
|
||||
* @brief Has gateway presence intent for <100 guilds
|
||||
*/
|
||||
apf_gateway_presence_limited = (1 << 13),
|
||||
|
||||
/**
|
||||
* @brief Has guild members intent
|
||||
*/
|
||||
apf_gateway_guild_members = (1 << 14),
|
||||
|
||||
/**
|
||||
* @brief Has guild members intent for <100 guilds
|
||||
*/
|
||||
apf_gateway_guild_members_limited = (1 << 15),
|
||||
|
||||
/**
|
||||
* @brief Verification is pending
|
||||
*/
|
||||
apf_verification_pending_guild_limit = (1 << 16),
|
||||
|
||||
/**
|
||||
* @brief Embedded
|
||||
*/
|
||||
apf_embedded = (1 << 17),
|
||||
|
||||
/**
|
||||
* @brief Has approval for message content
|
||||
*/
|
||||
apf_gateway_message_content = (1 << 18),
|
||||
|
||||
/**
|
||||
* @brief Has message content, but <100 guilds
|
||||
*/
|
||||
apf_gateway_message_content_limited = (1 << 19),
|
||||
|
||||
/**
|
||||
* @brief Indicates if the app has registered global application commands
|
||||
*/
|
||||
apf_application_command_badge = (1 << 23)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents the settings for the bot/application's in-app authorization link
|
||||
*/
|
||||
struct DPP_EXPORT application_install_params {
|
||||
/**
|
||||
* @brief A bitmask of dpp::permissions to request for the bot role.
|
||||
*/
|
||||
permission permissions;
|
||||
|
||||
/**
|
||||
* @brief The scopes as strings to add the application to the server with.
|
||||
*
|
||||
* @see https://discord.com/developers/docs/topics/oauth2#shared-resources-oauth2-scopes
|
||||
*/
|
||||
std::vector<std::string> scopes;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Team member role types for application team members.
|
||||
*
|
||||
* These are hard coded to string forms by discord. If further types are added,
|
||||
* this enum will be extended to support them.
|
||||
*/
|
||||
enum team_member_role_t : uint8_t {
|
||||
/**
|
||||
* @brief Team owner.
|
||||
*/
|
||||
tmr_owner,
|
||||
|
||||
/**
|
||||
* @brief Team admin.
|
||||
*/
|
||||
tmr_admin,
|
||||
|
||||
/**
|
||||
* @brief Developer
|
||||
*/
|
||||
tmr_developer,
|
||||
|
||||
/**
|
||||
* @brief Read-Only
|
||||
*/
|
||||
tmr_readonly,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a team member on a team who maintain a bot/application
|
||||
*/
|
||||
class DPP_EXPORT team_member {
|
||||
public:
|
||||
/**
|
||||
* @brief The user's membership state on the team.
|
||||
*/
|
||||
team_member_status membership_state;
|
||||
|
||||
/**
|
||||
* @brief Will always be "".
|
||||
*/
|
||||
std::string permissions;
|
||||
|
||||
/**
|
||||
* @brief The id of the parent team of which they are a member.
|
||||
*/
|
||||
snowflake team_id;
|
||||
|
||||
/**
|
||||
* @brief The avatar, discriminator, id, and username, of the user.
|
||||
*/
|
||||
user member_user;
|
||||
|
||||
/**
|
||||
* @brief The role of the user in the team.
|
||||
*/
|
||||
team_member_role_t member_role;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a team of users who maintain a bot/application
|
||||
*/
|
||||
class DPP_EXPORT app_team {
|
||||
public:
|
||||
/**
|
||||
* @brief A hash of the image of the team's icon (may be empty).
|
||||
*/
|
||||
utility::iconhash icon;
|
||||
|
||||
/**
|
||||
* @brief The id of the team.
|
||||
*/
|
||||
snowflake id;
|
||||
|
||||
/**
|
||||
* @brief The members of the team.
|
||||
*/
|
||||
std::vector<team_member> members;
|
||||
|
||||
/**
|
||||
* @brief The name of the team.
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* @brief The user id of the current team owner.
|
||||
*/
|
||||
snowflake owner_user_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Status indicating whether event webhooks are enabled or disabled for an application.
|
||||
*/
|
||||
enum application_event_webhook_status: uint8_t {
|
||||
/**
|
||||
* @brief Webhook events are disabled by developer
|
||||
*/
|
||||
ews_disabled = 1,
|
||||
/**
|
||||
* @brief Webhook events are enabled by developer
|
||||
*/
|
||||
ews_enabled = 2,
|
||||
/**
|
||||
* @brief Webhook events are disabled by Discord, usually due to inactivity
|
||||
*/
|
||||
ews_disabled_by_discord = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Configuration object for an app installation
|
||||
*/
|
||||
struct DPP_EXPORT integration_configuration {
|
||||
application_install_params oauth2_install_params;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The application class represents details of a bot application
|
||||
*/
|
||||
class DPP_EXPORT application : public managed, public json_interface<application> {
|
||||
protected:
|
||||
friend struct json_interface<application>;
|
||||
|
||||
/** Read class values from json object
|
||||
* @param j A json object to read from
|
||||
* @return A reference to self
|
||||
*/
|
||||
application& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The name of the app.
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* @brief The icon hash of the app (may be empty).
|
||||
*/
|
||||
utility::iconhash icon;
|
||||
|
||||
/**
|
||||
* @brief The description of the app.
|
||||
*/
|
||||
std::string description;
|
||||
|
||||
/**
|
||||
* @brief Optional: an array of rpc origin urls, if rpc is enabled.
|
||||
*/
|
||||
std::vector<std::string> rpc_origins;
|
||||
|
||||
/**
|
||||
* @brief When false, only app owner add the bot to guilds.
|
||||
*/
|
||||
bool bot_public;
|
||||
|
||||
/**
|
||||
* @brief When true, the app's bot will only join upon completion of the full oauth2 code grant flow
|
||||
*/
|
||||
bool bot_require_code_grant;
|
||||
|
||||
/**
|
||||
* @brief Optional: Partial user object for the bot user associated with the app.
|
||||
*/
|
||||
user bot;
|
||||
|
||||
/**
|
||||
* @brief Optional: the url of the app's terms of service.
|
||||
*/
|
||||
std::string terms_of_service_url;
|
||||
|
||||
/**
|
||||
* @brief Optional: the url of the app's privacy policy.
|
||||
*/
|
||||
std::string privacy_policy_url;
|
||||
|
||||
/**
|
||||
* @brief Optional: partial user object containing info on the owner of the application.
|
||||
*/
|
||||
user owner;
|
||||
|
||||
/**
|
||||
* @brief If this application is a game sold on Discord, this field will be the summary field for the store page of its primary SKU.
|
||||
*
|
||||
* @deprecated Will be removed in v11
|
||||
*/
|
||||
std::string summary;
|
||||
|
||||
/**
|
||||
* @brief The hex encoded key for verification in interactions and the GameSDK's GetTicket.
|
||||
*/
|
||||
std::string verify_key;
|
||||
|
||||
/**
|
||||
* @brief If the application belongs to a team, this will be a list of the members of that team (may be empty).
|
||||
*/
|
||||
app_team team;
|
||||
|
||||
/**
|
||||
* @brief Optional: if this application is a game sold on Discord, this field will be the guild to which it has been linked.
|
||||
*/
|
||||
snowflake guild_id;
|
||||
|
||||
/**
|
||||
* @brief Partial object of the associated guild.
|
||||
*/
|
||||
guild guild_obj;
|
||||
|
||||
/**
|
||||
* @brief Optional: if this application is a game sold on Discord, this field will be the id of the "Game SKU" that is created, if exists.
|
||||
*/
|
||||
snowflake primary_sku_id;
|
||||
|
||||
/**
|
||||
* @brief Optional: if this application is a game sold on Discord, this field will be the URL slug that links to the store page.
|
||||
*/
|
||||
std::string slug;
|
||||
|
||||
/**
|
||||
* @brief Optional: the application's default rich presence invite cover image hash
|
||||
*/
|
||||
utility::iconhash cover_image;
|
||||
|
||||
/**
|
||||
* @brief Optional: the application's public flags.
|
||||
*/
|
||||
uint32_t flags;
|
||||
|
||||
/**
|
||||
* @brief Optional: Approximate count of guilds the app has been added to.
|
||||
*/
|
||||
uint64_t approximate_guild_count;
|
||||
|
||||
/**
|
||||
* @brief Optional: Approximate count of users that have installed the app
|
||||
*/
|
||||
uint64_t approximate_user_install_count;
|
||||
|
||||
/**
|
||||
* @brief Optional: Array of redirect URIs for the app.
|
||||
*/
|
||||
std::vector<std::string> redirect_uris;
|
||||
|
||||
/**
|
||||
* @brief Optional: Interactions endpoint URL for the app.
|
||||
*/
|
||||
std::string interactions_endpoint_url;
|
||||
|
||||
/**
|
||||
* @brief The application's role connection verification entry point
|
||||
* which, when configured, will render the app as a verification method
|
||||
* in the guild role verification configuration.
|
||||
*/
|
||||
std::string role_connections_verification_url;
|
||||
|
||||
/**
|
||||
* @brief Event webhooks URL for the app to receive webhook events
|
||||
*/
|
||||
std::string event_webhooks_url;
|
||||
|
||||
/**
|
||||
* @brief List of Webhook event types the app subscribes to.
|
||||
*/
|
||||
std::vector<std::string> event_webhooks_types;
|
||||
|
||||
/**
|
||||
* If webhook events are enabled for the app.
|
||||
*/
|
||||
application_event_webhook_status event_webhooks_status;
|
||||
|
||||
/**
|
||||
* @brief Up to 5 tags describing the content and functionality of the application.
|
||||
*/
|
||||
std::vector<std::string> tags;
|
||||
|
||||
/**
|
||||
* @brief Settings for the application's default in-app authorization link, if enabled.
|
||||
*/
|
||||
application_install_params install_params;
|
||||
|
||||
/**
|
||||
* @brief Default scopes and permissions for each supported installation context
|
||||
*/
|
||||
std::map<application_integration_types, integration_configuration> integration_types_config;
|
||||
|
||||
/**
|
||||
* @brief The application's default custom authorization link, if enabled.
|
||||
*/
|
||||
std::string custom_install_url;
|
||||
|
||||
/**
|
||||
* @warning This variable is not documented by discord, we have no idea what it means and how it works. Use at your own risk.
|
||||
*/
|
||||
uint8_t discoverability_state;
|
||||
|
||||
/**
|
||||
* @warning This variable is not documented by discord, we have no idea what it means and how it works. Use at your own risk.
|
||||
*/
|
||||
uint32_t discovery_eligibility_flags;
|
||||
/**
|
||||
* @warning This variable is not documented by discord, we have no idea what it means and how it works. Use at your own risk.
|
||||
*/
|
||||
uint8_t explicit_content_filter;
|
||||
|
||||
/**
|
||||
* @warning This variable is not documented by discord, we have no idea what it means and how it works. Use at your own risk.
|
||||
*/
|
||||
uint8_t creator_monetization_state;
|
||||
|
||||
/**
|
||||
* @warning This variable is not documented by discord, we have no idea what it means and how it works. Use at your own risk.
|
||||
*/
|
||||
bool integration_public;
|
||||
|
||||
/**
|
||||
* @warning This variable is not documented by discord, we have no idea what it means and how it works. Use at your own risk.
|
||||
*/
|
||||
bool integration_require_code_grant;
|
||||
|
||||
/**
|
||||
* @warning This variable is not documented by discord, we have no idea what it means and how it works. Use at your own risk.
|
||||
*/
|
||||
std::vector<std::string> interactions_event_types;
|
||||
|
||||
/**
|
||||
* @warning This variable is not documented by discord, we have no idea what it means and how it works. Use at your own risk.
|
||||
*/
|
||||
uint8_t interactions_version;
|
||||
|
||||
/**
|
||||
* @warning This variable is not documented by discord, we have no idea what it means and how it works. Use at your own risk.
|
||||
*/
|
||||
bool is_monetized;
|
||||
|
||||
/**
|
||||
* @warning This variable is not documented by discord, we have no idea what it means and how it works. Use at your own risk.
|
||||
*/
|
||||
uint32_t monetization_eligibility_flags;
|
||||
|
||||
/**
|
||||
* @warning This variable is not documented by discord, we have no idea what it means and how it works. Use at your own risk.
|
||||
*/
|
||||
uint8_t monetization_state;
|
||||
|
||||
/**
|
||||
* @warning This variable is not documented by discord, we have no idea what it means and how it works. Use at your own risk.
|
||||
*/
|
||||
bool hook;
|
||||
|
||||
/**
|
||||
* @warning This variable is not documented by discord, we have no idea what it means and how it works. Use at your own risk.
|
||||
*/
|
||||
uint8_t rpc_application_state;
|
||||
|
||||
/**
|
||||
* @warning This variable is not documented by discord, we have no idea what it means and how it works. Use at your own risk.
|
||||
*/
|
||||
uint8_t store_application_state;
|
||||
|
||||
/**
|
||||
* @warning This variable is not documented by discord, we have no idea what it means and how it works. Use at your own risk.
|
||||
*/
|
||||
uint8_t verification_state;
|
||||
|
||||
/** Constructor */
|
||||
application();
|
||||
|
||||
/** Destructor */
|
||||
~application();
|
||||
|
||||
/**
|
||||
* @brief Get the application's cover image url if they have one, otherwise returns an empty string
|
||||
*
|
||||
* @param size The size of the cover image in pixels. It can be any power of two between 16 and 4096,
|
||||
* otherwise the default sized cover image is returned.
|
||||
* @param format The format to use for the avatar. It can be one of `i_webp`, `i_jpg` or `i_png`.
|
||||
* @return std::string cover image url or an empty string, if required attributes are missing or an invalid format was passed
|
||||
*/
|
||||
std::string get_cover_image_url(uint16_t size = 0, const image_type format = i_png) const;
|
||||
|
||||
/**
|
||||
* @brief Get the application's icon url if they have one, otherwise returns an empty string
|
||||
*
|
||||
* @param size The size of the icon in pixels. It can be any power of two between 16 and 4096,
|
||||
* otherwise the default sized icon is returned.
|
||||
* @param format The format to use for the avatar. It can be one of `i_webp`, `i_jpg` or `i_png`.
|
||||
* @return std::string icon url or an empty string, if required attributes are missing or an invalid format was passed
|
||||
*/
|
||||
std::string get_icon_url(uint16_t size = 0, const image_type format = i_png) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A group of applications.
|
||||
*
|
||||
* This is not currently ever sent by Discord API but the DPP standard setup for
|
||||
* objects that can be received by REST has the possibility for this, so this exists.
|
||||
* Don't ever expect to see one at present.
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, application> application_map;
|
||||
|
||||
}
|
||||
481
dpp/auditlog.h
481
dpp/auditlog.h
@ -1,481 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <optional>
|
||||
#include <dpp/json_interface.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Defines types of audit log entry
|
||||
*/
|
||||
enum audit_type {
|
||||
/**
|
||||
* @brief Guild update
|
||||
*/
|
||||
aut_guild_update = 1,
|
||||
|
||||
/**
|
||||
* @brief Channel create
|
||||
*/
|
||||
aut_channel_create = 10,
|
||||
|
||||
/**
|
||||
* @brief Channel update
|
||||
*/
|
||||
aut_channel_update = 11,
|
||||
|
||||
/**
|
||||
* @brief Channel delete
|
||||
*/
|
||||
aut_channel_delete = 12,
|
||||
|
||||
/**
|
||||
* @brief Channel overwrite create
|
||||
*/
|
||||
aut_channel_overwrite_create = 13,
|
||||
|
||||
/**
|
||||
* @brief Channel overwrite update
|
||||
*/
|
||||
aut_channel_overwrite_update = 14,
|
||||
|
||||
/**
|
||||
* @brief Channel overwrite delete
|
||||
*/
|
||||
aut_channel_overwrite_delete = 15,
|
||||
|
||||
/**
|
||||
* @brief Channel member kick
|
||||
*/
|
||||
aut_member_kick = 20,
|
||||
|
||||
/**
|
||||
* @brief Channel member prune
|
||||
*/
|
||||
aut_member_prune = 21,
|
||||
|
||||
/**
|
||||
* @brief Channel member ban add
|
||||
*/
|
||||
aut_member_ban_add = 22,
|
||||
|
||||
/**
|
||||
* @brief Channel member ban remove
|
||||
*/
|
||||
aut_member_ban_remove = 23,
|
||||
|
||||
/**
|
||||
* @brief Guild member update
|
||||
*/
|
||||
aut_member_update = 24,
|
||||
|
||||
/**
|
||||
* @brief Guild member role update
|
||||
*/
|
||||
aut_member_role_update = 25,
|
||||
|
||||
/**
|
||||
* @brief Guild member move
|
||||
*/
|
||||
aut_member_move = 26,
|
||||
|
||||
/**
|
||||
* @brief Guild member voice disconnect
|
||||
*/
|
||||
aut_member_disconnect = 27,
|
||||
|
||||
/**
|
||||
* @brief Guild bot add
|
||||
*/
|
||||
aut_bot_add = 28,
|
||||
|
||||
/**
|
||||
* @brief Guild role create
|
||||
*/
|
||||
aut_role_create = 30,
|
||||
|
||||
/**
|
||||
* @brief Guild role update
|
||||
*/
|
||||
aut_role_update = 31,
|
||||
|
||||
/**
|
||||
* @brief Guild role delete
|
||||
*/
|
||||
aut_role_delete = 32,
|
||||
|
||||
/**
|
||||
* @brief Guild invite create
|
||||
*/
|
||||
aut_invite_create = 40,
|
||||
|
||||
/**
|
||||
* @brief Guild invite update
|
||||
*/
|
||||
aut_invite_update = 41,
|
||||
|
||||
/**
|
||||
* @brief Guild invite delete
|
||||
*/
|
||||
aut_invite_delete = 42,
|
||||
|
||||
/**
|
||||
* @brief Guild webhook create
|
||||
*/
|
||||
aut_webhook_create = 50,
|
||||
|
||||
/**
|
||||
* @brief Guild webhook update
|
||||
*/
|
||||
aut_webhook_update = 51,
|
||||
|
||||
/**
|
||||
* @brief Guild webhook delete
|
||||
*/
|
||||
aut_webhook_delete = 52,
|
||||
|
||||
/**
|
||||
* @brief Guild emoji create
|
||||
*/
|
||||
aut_emoji_create = 60,
|
||||
|
||||
/**
|
||||
* @brief Guild emoji update
|
||||
*/
|
||||
aut_emoji_update = 61,
|
||||
|
||||
/**
|
||||
* @brief Guild emoji delete
|
||||
*/
|
||||
aut_emoji_delete = 62,
|
||||
|
||||
/**
|
||||
* @brief Guild message delete
|
||||
*/
|
||||
aut_message_delete = 72,
|
||||
|
||||
/**
|
||||
* @brief Guild message bulk delete
|
||||
*/
|
||||
aut_message_bulk_delete = 73,
|
||||
|
||||
/**
|
||||
* @brief Guild message pin
|
||||
*/
|
||||
aut_message_pin = 74,
|
||||
|
||||
/**
|
||||
* @brief Guild message unpin
|
||||
*/
|
||||
aut_message_unpin = 75,
|
||||
|
||||
/**
|
||||
* @brief Guild integration create
|
||||
*/
|
||||
aut_integration_create = 80,
|
||||
|
||||
/**
|
||||
* @brief Guild integration update
|
||||
*/
|
||||
aut_integration_update = 81,
|
||||
|
||||
/**
|
||||
* @brief Guild integration delete
|
||||
*/
|
||||
aut_integration_delete = 82,
|
||||
|
||||
/**
|
||||
* @brief Stage instance create
|
||||
*/
|
||||
aut_stage_instance_create = 83,
|
||||
|
||||
/**
|
||||
* @brief Stage instance update
|
||||
*/
|
||||
aut_stage_instance_update = 84,
|
||||
|
||||
/**
|
||||
* @brief stage instance delete
|
||||
*/
|
||||
aut_stage_instance_delete = 85,
|
||||
|
||||
/**
|
||||
* @brief Sticker create
|
||||
*/
|
||||
aut_sticker_create = 90,
|
||||
|
||||
/**
|
||||
* @brief Sticker update
|
||||
*/
|
||||
aut_sticker_update = 91,
|
||||
|
||||
/**
|
||||
* @brief Sticker delete
|
||||
*/
|
||||
aut_sticker_delete = 92,
|
||||
|
||||
/**
|
||||
* @brief Scheduled event creation
|
||||
*/
|
||||
aut_guild_scheduled_event_create = 100,
|
||||
|
||||
/**
|
||||
* @brief Scheduled event update
|
||||
*/
|
||||
aut_guild_scheduled_event_update = 101,
|
||||
|
||||
/**
|
||||
* @brief Scheduled event deletion
|
||||
*/
|
||||
aut_guild_scheduled_event_delete = 102,
|
||||
|
||||
/**
|
||||
* @brief Thread create
|
||||
*/
|
||||
aut_thread_create = 110,
|
||||
|
||||
/**
|
||||
* @brief Thread update
|
||||
*/
|
||||
aut_thread_update = 111,
|
||||
|
||||
/**
|
||||
* @brief Thread delete
|
||||
*/
|
||||
aut_thread_delete = 112,
|
||||
|
||||
/**
|
||||
* @brief Application command permissions update
|
||||
*/
|
||||
aut_appcommand_permission_update = 121,
|
||||
|
||||
/**
|
||||
* @brief Auto moderation rule creation
|
||||
*/
|
||||
aut_automod_rule_create = 140,
|
||||
|
||||
/**
|
||||
* @brief Auto moderation rule update
|
||||
*/
|
||||
aut_automod_rule_update = 141,
|
||||
|
||||
/**
|
||||
* @brief Auto moderation rule deletion
|
||||
*/
|
||||
aut_automod_rule_delete = 142,
|
||||
|
||||
/**
|
||||
* @brief Message was blocked by Auto Moderation
|
||||
*/
|
||||
aut_automod_block_message = 143,
|
||||
|
||||
/**
|
||||
* @brief Message was flagged by Auto Moderation
|
||||
*/
|
||||
aut_automod_flag_to_channel = 144,
|
||||
|
||||
/**
|
||||
* @brief Member was timed out by Auto Moderation
|
||||
*/
|
||||
aut_automod_user_communication_disabled = 145,
|
||||
|
||||
/**
|
||||
* @brief Creator monetization request was created
|
||||
*/
|
||||
aut_creator_monetization_request_created = 150,
|
||||
|
||||
/**
|
||||
* @brief Creator monetization terms were accepted
|
||||
*/
|
||||
aut_creator_monetization_terms_accepted = 151,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Defines audit log changes
|
||||
*/
|
||||
struct DPP_EXPORT audit_change {
|
||||
/**
|
||||
* @brief Optional: Serialised new value of the change, e.g. for nicknames, the new nickname.
|
||||
*/
|
||||
std::string new_value;
|
||||
|
||||
/**
|
||||
* @brief Optional: Serialised old value of the change, e.g. for nicknames, the old nickname.
|
||||
*/
|
||||
std::string old_value;
|
||||
|
||||
/**
|
||||
* @brief The property name that was changed (e.g. `nick` for nickname changes).
|
||||
* @note For dpp::aut_appcommand_permission_update updates the key is the id of the user, channel, role, or a permission constant that was updated instead of an actual property name.
|
||||
*/
|
||||
std::string key;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Extra information for an audit log entry
|
||||
*/
|
||||
struct DPP_EXPORT audit_extra {
|
||||
/**
|
||||
* @brief Name of the Auto Moderation rule that was triggered.
|
||||
*/
|
||||
std::string automod_rule_name;
|
||||
|
||||
/**
|
||||
* @brief Trigger type of the Auto Moderation rule that was triggered.
|
||||
*/
|
||||
std::string automod_rule_trigger_type;
|
||||
|
||||
/**
|
||||
* @brief Number of days after which inactive members were kicked.
|
||||
*/
|
||||
std::string delete_member_days;
|
||||
|
||||
/**
|
||||
* @brief Number of members removed by the prune.
|
||||
*/
|
||||
std::string members_removed;
|
||||
|
||||
/**
|
||||
* @brief Channel in which the entities were targeted.
|
||||
*/
|
||||
snowflake channel_id;
|
||||
|
||||
/**
|
||||
* @brief ID of the message that was targeted.
|
||||
*/
|
||||
snowflake message_id;
|
||||
|
||||
/**
|
||||
* @brief Number of entities that were targeted.
|
||||
*/
|
||||
std::string count;
|
||||
|
||||
/**
|
||||
* @brief ID of the overwritten entity.
|
||||
*/
|
||||
snowflake id;
|
||||
|
||||
/**
|
||||
* @brief Type of overwritten entity - "0" for "role" or "1" for "member"
|
||||
*/
|
||||
std::string type;
|
||||
|
||||
/**
|
||||
* @brief Name of the role if type is "0" (not present if type is "1").
|
||||
*/
|
||||
std::string role_name;
|
||||
|
||||
/**
|
||||
* @brief ID of the app whose permissions were targeted
|
||||
*/
|
||||
snowflake application_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An individual audit log entry
|
||||
*/
|
||||
struct DPP_EXPORT audit_entry : public json_interface<audit_entry> {
|
||||
protected:
|
||||
friend struct json_interface<audit_entry>;
|
||||
|
||||
/** Read class values from json object
|
||||
* @param j A json object to read from
|
||||
* @return A reference to self
|
||||
*/
|
||||
audit_entry& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief ID of the entry.
|
||||
*/
|
||||
snowflake id;
|
||||
|
||||
/**
|
||||
* ID of the affected entity (webhook, user, role, etc.) (may be empty)
|
||||
* @note For dpp::audit_type::aut_appcommand_permission_update updates, it's the command ID or the app ID
|
||||
*/
|
||||
snowflake target_id;
|
||||
|
||||
/**
|
||||
* @brief Optional: changes made to the target_id.
|
||||
*/
|
||||
std::vector<audit_change> changes;
|
||||
|
||||
/**
|
||||
* @brief The user or app that made the changes (may be empty).
|
||||
*/
|
||||
snowflake user_id;
|
||||
|
||||
/**
|
||||
* @brief Type of action that occurred.
|
||||
*/
|
||||
audit_type type;
|
||||
|
||||
/**
|
||||
* @brief Optional: additional info for certain action types.
|
||||
*/
|
||||
std::optional<audit_extra> extra;
|
||||
|
||||
/**
|
||||
* @brief Optional: the reason for the change (1-512 characters).
|
||||
*/
|
||||
std::string reason;
|
||||
|
||||
/** Constructor */
|
||||
audit_entry();
|
||||
|
||||
/** Destructor */
|
||||
virtual ~audit_entry() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The auditlog class represents the audit log entries of a guild.
|
||||
*/
|
||||
class DPP_EXPORT auditlog : public json_interface<auditlog> {
|
||||
protected:
|
||||
friend struct json_interface<auditlog>;
|
||||
|
||||
/** Read class values from json object
|
||||
* @param j A json object to read from
|
||||
* @return A reference to self
|
||||
*/
|
||||
auditlog& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Audit log entries.
|
||||
*/
|
||||
std::vector<audit_entry> entries;
|
||||
|
||||
/** Constructor */
|
||||
auditlog() = default;
|
||||
|
||||
/** Destructor */
|
||||
virtual ~auditlog() = default;
|
||||
};
|
||||
|
||||
}
|
||||
403
dpp/automod.h
403
dpp/automod.h
@ -1,403 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/managed.h>
|
||||
#include <dpp/utility.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/json_interface.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Possible types of preset filter lists
|
||||
*/
|
||||
enum automod_preset_type : uint8_t {
|
||||
/**
|
||||
* @brief Strong swearing
|
||||
*/
|
||||
amod_preset_profanity = 1,
|
||||
|
||||
/**
|
||||
* @brief Sexual phrases and words
|
||||
*/
|
||||
amod_preset_sexual_content = 2,
|
||||
|
||||
/**
|
||||
* @brief Racial and other slurs, hate speech
|
||||
*/
|
||||
amod_preset_slurs = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Action types to perform on filtering
|
||||
*/
|
||||
enum automod_action_type : uint8_t {
|
||||
/**
|
||||
* @brief Blocks the message and prevents it from being posted.
|
||||
* A custom explanation can be specified and shown to members whenever their message is blocked
|
||||
*/
|
||||
amod_action_block_message = 1,
|
||||
|
||||
/**
|
||||
* @brief Send an alert to a given channel
|
||||
*/
|
||||
amod_action_send_alert = 2,
|
||||
|
||||
/**
|
||||
* @brief timeout the user
|
||||
* @note Can only be set up for rules with trigger types of dpp::amod_type_keyword and dpp::amod_type_mention_spam
|
||||
*/
|
||||
amod_action_timeout = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Event types, only message send is currently supported
|
||||
*/
|
||||
enum automod_event_type : uint8_t {
|
||||
/**
|
||||
* @brief Trigger on message send or edit
|
||||
*/
|
||||
amod_message_send = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Types of moderation to trigger
|
||||
*/
|
||||
enum automod_trigger_type : uint8_t {
|
||||
/**
|
||||
* @brief Check if content contains words from a user defined list of keywords (max 6 of this type per guild)
|
||||
*/
|
||||
amod_type_keyword = 1,
|
||||
|
||||
/**
|
||||
* @brief Harmful/malware links
|
||||
* @deprecated Removed by Discord
|
||||
*/
|
||||
amod_type_harmful_link = 2,
|
||||
|
||||
/**
|
||||
* @brief Check if content represents generic spam (max 1 of this type per guild)
|
||||
*/
|
||||
amod_type_spam = 3,
|
||||
|
||||
/**
|
||||
* @brief Check if content contains words from discord pre-defined wordsets (max 1 of this type per guild)
|
||||
*/
|
||||
amod_type_keyword_preset = 4,
|
||||
|
||||
/**
|
||||
* @brief Check if content contains more mentions than allowed (max 1 of this type per guild)
|
||||
*/
|
||||
amod_type_mention_spam = 5,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Metadata associated with an automod action. Different fields are relevant based on the value of dpp::automod_rule::trigger_type.
|
||||
*/
|
||||
struct DPP_EXPORT automod_metadata : public json_interface<automod_metadata> {
|
||||
protected:
|
||||
friend struct json_interface<automod_metadata>;
|
||||
|
||||
/**
|
||||
* @brief Fill object properties from JSON
|
||||
*
|
||||
* @param j JSON to fill from
|
||||
* @return automod_metadata& Reference to self
|
||||
*/
|
||||
automod_metadata& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Build a json for this object
|
||||
*
|
||||
* @return json JSON object
|
||||
*/
|
||||
virtual json to_json_impl(bool with_id = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief @brief Substrings which will be searched for in content (Maximum of 1000).
|
||||
*
|
||||
* Each keyword can be a phrase which contains multiple words.
|
||||
* All keywords are case insensitive and can be up to 60 characters.
|
||||
*
|
||||
* Wildcard symbols (`*`) can be used to customize how each keyword will be matched.
|
||||
*
|
||||
* **Examples for the `*` wildcard symbol:**
|
||||
*
|
||||
* Prefix - word must start with the keyword
|
||||
*
|
||||
* | keyword | matches |
|
||||
* |----------|-------------------------------------|
|
||||
* | cat* | <u><b>cat</b></u>ch, <u><b>Cat</b></u>apult, <u><b>CAt</b></u>tLE |
|
||||
* | the mat* | <u><b>the mat</b></u>rix |
|
||||
*
|
||||
* Suffix - word must end with the keyword
|
||||
*
|
||||
* | keyword | matches |
|
||||
* |----------|--------------------------|
|
||||
* | *cat | wild<u><b>cat</b></u>, copy<u><b>Cat</b></u> |
|
||||
* | *the mat | brea<u><b>the mat</b></u> |
|
||||
*
|
||||
* Anywhere - keyword can appear anywhere in the content
|
||||
*
|
||||
* | keyword | matches |
|
||||
* |-----------|-----------------------------|
|
||||
* | \*cat* | lo<u><b>cat</b></u>ion, edu<u><b>Cat</b></u>ion |
|
||||
* | \*the mat* | brea<u><b>the mat</b></u>ter |
|
||||
*
|
||||
* Whole Word - keyword is a full word or phrase and must be surrounded by whitespace at the beginning and end
|
||||
*
|
||||
* | keyword | matches |
|
||||
* |---------|-------------|
|
||||
* | cat | <u><b>Cat</b></u> |
|
||||
* | the mat | <u><b>the mat</b></u> |
|
||||
*
|
||||
*/
|
||||
std::vector<std::string> keywords;
|
||||
|
||||
/**
|
||||
* @brief Regular expression patterns which will be matched against content (Maximum of 10).
|
||||
*
|
||||
* Only Rust flavored regex is currently supported, which can be tested in online editors such as [Rustexp](https://rustexp.lpil.uk/).
|
||||
* Each regex pattern can be up to 260 characters.
|
||||
*/
|
||||
std::vector<std::string> regex_patterns;
|
||||
|
||||
/**
|
||||
* @brief Preset keyword list types to moderate
|
||||
* @see automod_preset_type
|
||||
*/
|
||||
std::vector<automod_preset_type> presets;
|
||||
|
||||
/**
|
||||
* @brief Substrings which should not trigger the rule (Maximum of 100 for the trigger type dpp::amod_type_keyword, Maximum of 1000 for the trigger type dpp::amod_type_keyword_preset).
|
||||
*
|
||||
* Each keyword can be a phrase which contains multiple words.
|
||||
* All keywords are case insensitive and can be up to 60 characters.
|
||||
*
|
||||
* Wildcard symbols (`*`) can be used to customize how each keyword will be matched.
|
||||
*
|
||||
* **Examples for the `*` wildcard symbol:**
|
||||
*
|
||||
* Prefix - word must start with the keyword
|
||||
*
|
||||
* | keyword | matches |
|
||||
* |----------|-------------------------------------|
|
||||
* | cat* | <u><b>cat</b></u>ch, <u><b>Cat</b></u>apult, <u><b>CAt</b></u>tLE |
|
||||
* | the mat* | <u><b>the mat</b></u>rix |
|
||||
*
|
||||
* Suffix - word must end with the keyword
|
||||
*
|
||||
* | keyword | matches |
|
||||
* |----------|--------------------------|
|
||||
* | *cat | wild<u><b>cat</b></u>, copy<u><b>Cat</b></u> |
|
||||
* | *the mat | brea<u><b>the mat</b></u> |
|
||||
*
|
||||
* Anywhere - keyword can appear anywhere in the content
|
||||
*
|
||||
* | keyword | matches |
|
||||
* |-----------|-----------------------------|
|
||||
* | \*cat* | lo<u><b>cat</b></u>ion, edu<u><b>Cat</b></u>ion |
|
||||
* | \*the mat* | brea<u><b>the mat</b></u>ter |
|
||||
*
|
||||
* Whole Word - keyword is a full word or phrase and must be surrounded by whitespace at the beginning and end
|
||||
*
|
||||
* | keyword | matches |
|
||||
* |---------|-------------|
|
||||
* | cat | <u><b>Cat</b></u> |
|
||||
* | the mat | <u><b>the mat</b></u> |
|
||||
*
|
||||
*/
|
||||
std::vector<std::string> allow_list;
|
||||
|
||||
/**
|
||||
* @brief Total number of unique role and user mentions allowed per message (Maximum of 50)
|
||||
*/
|
||||
uint8_t mention_total_limit;
|
||||
|
||||
/**
|
||||
* @brief Whether to automatically detect mention raids
|
||||
*/
|
||||
bool mention_raid_protection_enabled;
|
||||
|
||||
/**
|
||||
* @brief Construct a new automod metadata object
|
||||
*/
|
||||
automod_metadata();
|
||||
|
||||
/**
|
||||
* @brief Destroy the automod metadata object
|
||||
*/
|
||||
virtual ~automod_metadata();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents an automod action
|
||||
*/
|
||||
struct DPP_EXPORT automod_action : public json_interface<automod_action> {
|
||||
protected:
|
||||
friend struct json_interface<automod_action>;
|
||||
|
||||
/**
|
||||
* @brief Fill object properties from JSON
|
||||
*
|
||||
* @param j JSON to fill from
|
||||
* @return automod_action& Reference to self
|
||||
*/
|
||||
automod_action& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Build a json for this object
|
||||
*
|
||||
* @return json JSON object
|
||||
*/
|
||||
virtual json to_json_impl(bool with_id = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Type of action to take
|
||||
*/
|
||||
automod_action_type type;
|
||||
|
||||
/**
|
||||
* @brief Channel ID to which user content should be logged, for type dpp::amod_action_send_alert
|
||||
*/
|
||||
snowflake channel_id;
|
||||
|
||||
/**
|
||||
* @brief Additional explanation that will be shown to members whenever their message is blocked. For type dpp::amod_action_block_message
|
||||
*/
|
||||
std::string custom_message;
|
||||
|
||||
/**
|
||||
* @brief Timeout duration in seconds (Maximum of 2419200), for dpp::amod_action_timeout
|
||||
*/
|
||||
uint32_t duration_seconds;
|
||||
|
||||
/**
|
||||
* @brief Construct a new automod action object
|
||||
*/
|
||||
automod_action();
|
||||
|
||||
/**
|
||||
* @brief Destroy the automod action object
|
||||
*/
|
||||
virtual ~automod_action();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents an automod rule
|
||||
*/
|
||||
class DPP_EXPORT automod_rule : public managed, public json_interface<automod_rule> {
|
||||
protected:
|
||||
friend struct json_interface<automod_rule>;
|
||||
|
||||
/**
|
||||
* @brief Fill object properties from JSON
|
||||
*
|
||||
* @param j JSON to fill from
|
||||
* @return automod_rule& Reference to self
|
||||
*/
|
||||
automod_rule& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Build a json string for this object
|
||||
*
|
||||
* @return json JSON object
|
||||
*/
|
||||
virtual json to_json_impl(bool with_id = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief the id of this rule
|
||||
*/
|
||||
snowflake id;
|
||||
|
||||
/**
|
||||
* @brief the guild which this rule belongs to
|
||||
*/
|
||||
snowflake guild_id;
|
||||
|
||||
/**
|
||||
* @brief the rule name
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* @brief The user which first created this rule
|
||||
*/
|
||||
snowflake creator_id;
|
||||
|
||||
/**
|
||||
* @brief The rule event type
|
||||
*/
|
||||
automod_event_type event_type;
|
||||
|
||||
/**
|
||||
* @brief The rule trigger type
|
||||
*/
|
||||
automod_trigger_type trigger_type;
|
||||
|
||||
/**
|
||||
* @brief The rule trigger metadata
|
||||
*/
|
||||
automod_metadata trigger_metadata;
|
||||
|
||||
/**
|
||||
* @brief the actions which will execute when the rule is triggered
|
||||
*/
|
||||
std::vector<automod_action> actions;
|
||||
|
||||
/**
|
||||
* @brief Whether the rule is enabled
|
||||
*/
|
||||
bool enabled;
|
||||
|
||||
/**
|
||||
* @brief the role ids that should not be affected by the rule (Maximum of 20)
|
||||
*/
|
||||
std::vector<snowflake> exempt_roles;
|
||||
|
||||
/**
|
||||
* @brief the channel ids that should not be affected by the rule (Maximum of 50)
|
||||
*/
|
||||
std::vector<snowflake> exempt_channels;
|
||||
|
||||
/**
|
||||
* @brief Construct a new automod rule object
|
||||
*/
|
||||
automod_rule();
|
||||
|
||||
/**
|
||||
* @brief Destroy the automod rule object
|
||||
*/
|
||||
virtual ~automod_rule();
|
||||
};
|
||||
|
||||
/** A group of automod rules.
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, automod_rule> automod_rule_map;
|
||||
|
||||
}
|
||||
69
dpp/ban.h
69
dpp/ban.h
@ -1,69 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/json_interface.h>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief The ban class represents a ban on a guild.
|
||||
*
|
||||
*/
|
||||
class DPP_EXPORT ban : public json_interface<ban> {
|
||||
protected:
|
||||
friend struct json_interface<ban>;
|
||||
|
||||
/** Read class values from json object
|
||||
* @param j A json object to read from
|
||||
* @return A reference to self
|
||||
*/
|
||||
ban& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The ban reason.
|
||||
*/
|
||||
std::string reason;
|
||||
|
||||
/**
|
||||
* @brief User ID the ban applies to.
|
||||
*/
|
||||
snowflake user_id;
|
||||
|
||||
/** Constructor */
|
||||
ban();
|
||||
|
||||
/** Destructor */
|
||||
virtual ~ban() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A group of bans. The key is the user ID.
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, ban> ban_map;
|
||||
|
||||
}
|
||||
101
dpp/bignum.h
101
dpp/bignum.h
@ -1,101 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <memory>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief This contains the OpenSSL structs. It is not public,
|
||||
* so that the public interface doesn't depend on OpenSSL directly.
|
||||
*/
|
||||
struct openssl_bignum;
|
||||
|
||||
/**
|
||||
* @brief An arbitrary length integer number.
|
||||
* Officially, the Discord documentation says that permission values can be any arbitrary
|
||||
* number of digits. At time of writing there are only 50 bits of permissions, but this is
|
||||
* set to grow larger and potentially past 64 bits. They will continue to send this data
|
||||
* as a huge single integer at that point, because this is obviously sensible. /s
|
||||
*
|
||||
* @note dpp::bignumber uses OpenSSL BN_* under the hood, as we include openssl anyway
|
||||
* for HTTPS.
|
||||
*/
|
||||
class DPP_EXPORT bignumber {
|
||||
/**
|
||||
* @brief Internal opaque struct to contain OpenSSL things
|
||||
*/
|
||||
std::shared_ptr<openssl_bignum> ssl_bn{nullptr};
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new bignumber object
|
||||
*/
|
||||
bignumber() = default;
|
||||
|
||||
/**
|
||||
* @brief Parse a std::string of an arbitrary length number into
|
||||
* a bignumber.
|
||||
* @param number_string string representation of a number. The
|
||||
* number must be an integer, and can be positive or negative.
|
||||
* @note Prefixing number_string with 0x will parse it as hexadecimal.
|
||||
* This is not case sensitive.
|
||||
*/
|
||||
bignumber(const std::string& number_string);
|
||||
|
||||
/**
|
||||
* @brief Build a bignumber from a vector of 64 bit values.
|
||||
* The values are accepted in "reverse order", so the first vector
|
||||
* entry at index 0 is the leftmost 64 bits of the bignum.
|
||||
* The vector can be any arbitrary length.
|
||||
* @param bits Vector of 64 bit values which represent the number
|
||||
*/
|
||||
bignumber(std::vector<uint64_t> bits);
|
||||
|
||||
/**
|
||||
* @brief Default destructor
|
||||
*/
|
||||
~bignumber() = default;
|
||||
|
||||
/**
|
||||
* @brief Get the string representation of the bignumber.
|
||||
* @param hex If false (the default) the number is returned in
|
||||
* decimal, else if this parameter is true, it will be returned
|
||||
* as hex (without leading '0x')
|
||||
* @return String representation of bignumber
|
||||
*/
|
||||
[[nodiscard]] std::string get_number(bool hex = false) const;
|
||||
|
||||
/**
|
||||
* @brief Get the array of 64 bit values that represents the
|
||||
* bignumber. This is what we should use to store bignumbers
|
||||
* in memory, not this bignumber class itself, as the bignumber
|
||||
* class instantiates OpenSSL structs and takes significantly
|
||||
* more ram than just a vector.
|
||||
* @return Vector of 64 bit values representing the bignumber
|
||||
*/
|
||||
[[nodiscard]] std::vector<uint64_t> get_binary() const;
|
||||
};
|
||||
|
||||
}
|
||||
274
dpp/cache.h
274
dpp/cache.h
@ -1,274 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/managed.h>
|
||||
#include <unordered_map>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
extern DPP_EXPORT std::unordered_map<managed*, time_t> deletion_queue;
|
||||
extern DPP_EXPORT std::mutex deletion_mutex;
|
||||
|
||||
/** forward declaration */
|
||||
class guild_member;
|
||||
|
||||
/**
|
||||
* @brief A cache object maintains a cache of dpp::managed objects.
|
||||
*
|
||||
* This is for example users, channels or guilds. You may instantiate
|
||||
* your own caches, to contain any type derived from dpp::managed including
|
||||
* your own types.
|
||||
*
|
||||
* @note This class is critical to the operation of the library and therefore
|
||||
* designed with thread safety in mind.
|
||||
* @tparam T class type to store, which should be derived from dpp::managed.
|
||||
*/
|
||||
template<class T> class cache {
|
||||
private:
|
||||
/**
|
||||
* @brief Mutex to protect the cache
|
||||
*
|
||||
* This is a shared mutex so reading is cheap.
|
||||
*/
|
||||
std::shared_mutex cache_mutex;
|
||||
|
||||
/**
|
||||
* @brief Container of pointers to cached items
|
||||
*/
|
||||
std::unordered_map<snowflake, T*>* cache_map;
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Construct a new cache object.
|
||||
*
|
||||
* @note Caches must contain classes derived from dpp::managed.
|
||||
*/
|
||||
cache() {
|
||||
cache_map = new std::unordered_map<snowflake, T*>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroy the cache object
|
||||
*
|
||||
* @note This does not delete objects stored in the cache.
|
||||
*/
|
||||
~cache() {
|
||||
std::unique_lock l(cache_mutex);
|
||||
delete cache_map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Store an object in the cache. Passing a nullptr will have no effect.
|
||||
*
|
||||
* The object must be derived from dpp::managed and should be allocated on the heap.
|
||||
* Generally this is done via `new`. Once stored in the cache the lifetime of the stored
|
||||
* object is managed by the cache class unless the cache is deleted (at which point responsibility
|
||||
* for deleting the object returns to its allocator). Objects stored are removed when the
|
||||
* cache::remove() method is called by placing them into a garbage collection queue for deletion
|
||||
* within the next 60 seconds, which are then deleted in bulk for efficiency and to aid thread
|
||||
* safety.
|
||||
*
|
||||
* @note Adding an object to the cache with an ID which already exists replaces that entry.
|
||||
* The previously entered cache item is inserted into the garbage collection queue for deletion
|
||||
* similarly to if cache::remove() was called first.
|
||||
*
|
||||
* @param object object to store. Storing a pointer to the cache relinquishes ownership to the cache object.
|
||||
*/
|
||||
void store(T* object) {
|
||||
if (!object) {
|
||||
return;
|
||||
}
|
||||
std::unique_lock l(cache_mutex);
|
||||
auto existing = cache_map->find(object->id);
|
||||
if (existing == cache_map->end()) {
|
||||
(*cache_map)[object->id] = object;
|
||||
} else if (object != existing->second) {
|
||||
/* Flag old pointer for deletion and replace */
|
||||
std::lock_guard<std::mutex> delete_lock(deletion_mutex);
|
||||
deletion_queue[existing->second] = time(nullptr);
|
||||
(*cache_map)[object->id] = object;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove an object from the cache.
|
||||
*
|
||||
* @note The cache class takes ownership of the pointer, and calling this method will
|
||||
* cause deletion of the object within the next 60 seconds by means of a garbage
|
||||
* collection queue. This queue aids in efficiency by freeing memory in bulk, and
|
||||
* assists in thread safety by ensuring that all deletions can be locked and freed
|
||||
* at the same time.
|
||||
*
|
||||
* @param object object to remove. Passing a nullptr will have no effect.
|
||||
*/
|
||||
void remove(T* object) {
|
||||
if (!object) {
|
||||
return;
|
||||
}
|
||||
std::unique_lock l(cache_mutex);
|
||||
std::lock_guard<std::mutex> delete_lock(deletion_mutex);
|
||||
auto existing = cache_map->find(object->id);
|
||||
if (existing != cache_map->end()) {
|
||||
cache_map->erase(existing);
|
||||
deletion_queue[object] = time(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find an object in the cache by id.
|
||||
*
|
||||
* The cache is searched for the object. All dpp::managed objects have a snowflake id
|
||||
* (this is the only field dpp::managed actually has).
|
||||
*
|
||||
* @warning Do not hang onto objects returned by cache::find() indefinitely. They may be
|
||||
* deleted at a later date if cache::remove() is called. If persistence is required,
|
||||
* take a copy of the object after checking its pointer is non-null.
|
||||
*
|
||||
* @param id Object snowflake id to find
|
||||
* @return Found object or nullptr if the object with this id does not exist.
|
||||
*/
|
||||
T* find(snowflake id) {
|
||||
std::shared_lock l(cache_mutex);
|
||||
auto r = cache_map->find(id);
|
||||
if (r != cache_map->end()) {
|
||||
return r->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return a count of the number of items in the cache.
|
||||
*
|
||||
* This is used by the library e.g. to count guilds, users, and roles
|
||||
* stored within caches.
|
||||
* get
|
||||
* @return uint64_t count of items in the cache
|
||||
*/
|
||||
uint64_t count() {
|
||||
std::shared_lock l(cache_mutex);
|
||||
return cache_map->size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the cache's locking mutex.
|
||||
*
|
||||
* Use this whenever you manipulate or iterate raw elements in the cache!
|
||||
*
|
||||
* @note If you are only reading from the cache's container, wrap this
|
||||
* mutex in `std::shared_lock`, else wrap it in a `std::unique_lock`.
|
||||
* Shared locks will allow for multiple readers whilst blocking writers,
|
||||
* and unique locks will allow only one writer whilst blocking readers
|
||||
* and writers.
|
||||
*
|
||||
* **Example:**
|
||||
*
|
||||
* ```cpp
|
||||
* dpp::cache<guild>* c = dpp::get_guild_cache();
|
||||
* std::unordered_map<snowflake, guild*>& gc = c->get_container();
|
||||
* std::shared_lock l(c->get_mutex()); // MUST LOCK HERE
|
||||
* for (auto g = gc.begin(); g != gc.end(); ++g) {
|
||||
* dpp::guild* gp = (dpp::guild*)g->second;
|
||||
* // Do something here with the guild* in 'gp'
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @return The mutex used to protect the container
|
||||
*/
|
||||
std::shared_mutex& get_mutex() {
|
||||
return this->cache_mutex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the container unordered map
|
||||
*
|
||||
* @warning Be sure to use cache::get_mutex() correctly if you
|
||||
* manipulate or iterate the map returned by this method! If you do
|
||||
* not, this is not thread safe and will cause crashes!
|
||||
*
|
||||
* @see cache::get_mutex
|
||||
*
|
||||
* @return A reference to the cache's container map
|
||||
*/
|
||||
auto & get_container() {
|
||||
return *(this->cache_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief "Rehash" a cache by reallocating the map and copying
|
||||
* all elements into the new one.
|
||||
*
|
||||
* Over a long running timeframe, unordered maps can grow in size
|
||||
* due to bucket allocation, this function frees that unused memory
|
||||
* to keep the maps in control over time. If this is an issue which
|
||||
* is apparent with your use of dpp::cache objects, you should periodically
|
||||
* call this method.
|
||||
*
|
||||
* @warning May be time consuming! This function is O(n) in relation to the
|
||||
* number of cached entries.
|
||||
*/
|
||||
void rehash() {
|
||||
std::unique_lock l(cache_mutex);
|
||||
std::unordered_map<snowflake, T*>* n = new std::unordered_map<snowflake, T*>;
|
||||
n->reserve(cache_map->size());
|
||||
for (auto t = cache_map->begin(); t != cache_map->end(); ++t) {
|
||||
n->insert(*t);
|
||||
}
|
||||
delete cache_map;
|
||||
cache_map = n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get "real" size in RAM of the cached objects
|
||||
*
|
||||
* This does not include metadata used to maintain the unordered map itself.
|
||||
*
|
||||
* @return size_t size of cache in bytes
|
||||
*/
|
||||
size_t bytes() {
|
||||
std::shared_lock l(cache_mutex);
|
||||
return sizeof(*this) + (cache_map->bucket_count() * sizeof(size_t));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Run garbage collection across all caches removing deleted items
|
||||
* that have been deleted over 60 seconds ago.
|
||||
*/
|
||||
void DPP_EXPORT garbage_collection();
|
||||
|
||||
#define cache_decl(type, setter, getter, counter) /** Find an object in the cache by id. @return type* Pointer to the object or nullptr when it's not found */ DPP_EXPORT class type * setter (snowflake id); DPP_EXPORT cache<class type> * getter (); /** Get the amount of cached type objects. */ DPP_EXPORT uint64_t counter ();
|
||||
|
||||
/* Declare major caches */
|
||||
cache_decl(user, find_user, get_user_cache, get_user_count);
|
||||
cache_decl(guild, find_guild, get_guild_cache, get_guild_count);
|
||||
cache_decl(role, find_role, get_role_cache, get_role_count);
|
||||
cache_decl(channel, find_channel, get_channel_cache, get_channel_count);
|
||||
cache_decl(emoji, find_emoji, get_emoji_cache, get_emoji_count);
|
||||
|
||||
}
|
||||
|
||||
896
dpp/channel.h
896
dpp/channel.h
@ -1,896 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/managed.h>
|
||||
#include <dpp/utility.h>
|
||||
#include <dpp/voicestate.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/permissions.h>
|
||||
#include <dpp/json_interface.h>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/** @brief Flag integers as received from and sent to discord */
|
||||
enum channel_type : uint8_t {
|
||||
/**
|
||||
* @brief A text channel within a server.
|
||||
*/
|
||||
CHANNEL_TEXT = 0,
|
||||
|
||||
/**
|
||||
* @brief A direct message between users.
|
||||
*/
|
||||
DM = 1,
|
||||
|
||||
/**
|
||||
* @brief A voice channel within a server.
|
||||
*/
|
||||
CHANNEL_VOICE = 2,
|
||||
|
||||
/**
|
||||
* @brief a direct message between multiple users
|
||||
* @deprecated this channel type was intended to be used with the now deprecated GameBridge SDK.
|
||||
* Existing group dms with bots will continue to function, but newly created channels will be unusable.
|
||||
*/
|
||||
GROUP_DM = 3,
|
||||
|
||||
/**
|
||||
* @brief An organizational category that contains up to 50 channels.
|
||||
*/
|
||||
CHANNEL_CATEGORY = 4,
|
||||
|
||||
/**
|
||||
* @brief A channel that users can follow and cross-post into their own server.
|
||||
*/
|
||||
CHANNEL_ANNOUNCEMENT = 5,
|
||||
|
||||
/**
|
||||
* @brief A channel in which game developers can sell their game on Discord.
|
||||
* @deprecated Store channels are deprecated by Discord.
|
||||
*/
|
||||
CHANNEL_STORE = 6,
|
||||
|
||||
/**
|
||||
* @brief A temporary sub-channel within a `GUILD_ANNOUNCEMENT` channel.
|
||||
*/
|
||||
CHANNEL_ANNOUNCEMENT_THREAD = 10,
|
||||
|
||||
/**
|
||||
* @brief A temporary sub-channel within a `GUILD_TEXT` or `GUILD_FORUM` channel.
|
||||
*/
|
||||
CHANNEL_PUBLIC_THREAD = 11,
|
||||
|
||||
/**
|
||||
* @brief A temporary sub-channel within a `GUILD_TEXT` channel
|
||||
* that is only viewable by those invited and those with the `MANAGE_THREADS` permission.
|
||||
*/
|
||||
CHANNEL_PRIVATE_THREAD = 12,
|
||||
|
||||
/**
|
||||
* @brief A "stage" channel, like a voice channel with one authorised speaker.
|
||||
*/
|
||||
CHANNEL_STAGE = 13,
|
||||
|
||||
/**
|
||||
* @brief The channel in a hub containing the listed servers.
|
||||
*
|
||||
* @see https://support.discord.com/hc/en-us/articles/4406046651927-Discord-Student-Hubs-FAQ
|
||||
*/
|
||||
CHANNEL_DIRECTORY = 14,
|
||||
|
||||
/**
|
||||
* @brief Forum channel that can only contain threads.
|
||||
*/
|
||||
CHANNEL_FORUM = 15,
|
||||
|
||||
/**
|
||||
* @brief Media channel that can only contain threads, similar to forum channels.
|
||||
*/
|
||||
CHANNEL_MEDIA = 16,
|
||||
};
|
||||
|
||||
/** @brief Our flags as stored in the object
|
||||
* @note The bottom four bits of this flag are reserved to contain the channel_type values
|
||||
* listed above as provided by Discord. If discord add another value > 15, we will have to
|
||||
* shuffle these values upwards by one bit.
|
||||
*/
|
||||
enum channel_flags : uint16_t {
|
||||
/* Note that bits 1 to 4 are used for the channel type mask */
|
||||
/**
|
||||
* @brief NSFW Gated Channel
|
||||
*/
|
||||
c_nsfw = 0b0000000000010000,
|
||||
|
||||
/**
|
||||
* @brief Video quality forced to 720p
|
||||
*/
|
||||
c_video_quality_720p = 0b0000000000100000,
|
||||
|
||||
/**
|
||||
* @brief Lock permissions (only used when updating channel positions)
|
||||
*/
|
||||
c_lock_permissions = 0b0000000001000000,
|
||||
|
||||
/**
|
||||
* @brief Thread is pinned to the top of its parent forum or media channel
|
||||
*/
|
||||
c_pinned_thread = 0b0000000010000000,
|
||||
|
||||
/**
|
||||
* @brief Whether a tag is required to be specified when creating a thread in a forum or media channel.
|
||||
* Tags are specified in the thread::applied_tags field.
|
||||
*/
|
||||
c_require_tag = 0b0000000100000000,
|
||||
|
||||
/* Note that the 9th and 10th bit are used for the forum layout type. */
|
||||
/**
|
||||
* @brief When set hides the embedded media download options. Available only for media channels
|
||||
*/
|
||||
c_hide_media_download_options = 0b0001000000000000,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Types for sort posts in a forum channel
|
||||
*/
|
||||
enum default_forum_sort_order_t : uint8_t {
|
||||
/**
|
||||
* @brief Sort forum posts by activity (default)
|
||||
*/
|
||||
so_latest_activity = 0,
|
||||
|
||||
/**
|
||||
* @brief Sort forum posts by creation time (from most recent to oldest)
|
||||
*/
|
||||
so_creation_date = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Types of forum layout views that indicates how the threads in a forum channel will be displayed for users by default
|
||||
*/
|
||||
enum forum_layout_type : uint8_t {
|
||||
/**
|
||||
* @brief No default has been set for the forum channel
|
||||
*/
|
||||
fl_not_set = 0,
|
||||
|
||||
/**
|
||||
* @brief Display posts as a list
|
||||
*/
|
||||
fl_list_view = 1,
|
||||
|
||||
/**
|
||||
* @brief Display posts as a collection of tiles
|
||||
*/
|
||||
fl_gallery_view = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief channel permission overwrite types
|
||||
*/
|
||||
enum overwrite_type : uint8_t {
|
||||
/**
|
||||
* @brief Role
|
||||
*/
|
||||
ot_role = 0,
|
||||
|
||||
/**
|
||||
* @brief Member
|
||||
*/
|
||||
ot_member = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Channel permission overwrites
|
||||
*/
|
||||
struct DPP_EXPORT permission_overwrite {
|
||||
/**
|
||||
* @brief ID of the role or the member
|
||||
*/
|
||||
snowflake id;
|
||||
|
||||
/**
|
||||
* @brief Bitmask of allowed permissions
|
||||
*/
|
||||
permission allow;
|
||||
|
||||
/**
|
||||
* @brief Bitmask of denied permissions
|
||||
*/
|
||||
permission deny;
|
||||
|
||||
/**
|
||||
* @brief Type of overwrite. See dpp::overwrite_type
|
||||
*/
|
||||
uint8_t type;
|
||||
|
||||
/**
|
||||
* @brief Construct a new permission_overwrite object
|
||||
*/
|
||||
permission_overwrite();
|
||||
|
||||
/**
|
||||
* @brief Construct a new permission_overwrite object
|
||||
* @param id ID of the role or the member to create the overwrite for
|
||||
* @param allow Bitmask of allowed permissions (refer to enum dpp::permissions) for this user/role in this channel
|
||||
* @param deny Bitmask of denied permissions (refer to enum dpp::permissions) for this user/role in this channel
|
||||
* @param type Type of overwrite
|
||||
*/
|
||||
permission_overwrite(snowflake id, uint64_t allow, uint64_t deny, overwrite_type type);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Auto archive duration of threads which will stop showing in the channel list after the specified period of inactivity.
|
||||
* Defined as an enum to fit into 1 byte. Internally it'll be translated to minutes to match the API
|
||||
*/
|
||||
enum auto_archive_duration_t : uint8_t {
|
||||
/**
|
||||
* @brief Auto archive duration of 1 hour (60 minutes).
|
||||
*/
|
||||
arc_1_hour = 1,
|
||||
|
||||
/**
|
||||
* @brief Auto archive duration of 1 day (1440 minutes).
|
||||
*/
|
||||
arc_1_day = 2,
|
||||
|
||||
/**
|
||||
* @brief Auto archive duration of 3 days (4320 minutes).
|
||||
*/
|
||||
arc_3_days = 3,
|
||||
|
||||
/**
|
||||
* @brief Auto archive duration of 1 week (10080 minutes).
|
||||
*/
|
||||
arc_1_week = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a tag that is able to be applied to a thread in a forum or media channel
|
||||
*/
|
||||
struct DPP_EXPORT forum_tag : public managed, public json_interface<forum_tag> {
|
||||
protected:
|
||||
friend struct json_interface<forum_tag>;
|
||||
|
||||
/**
|
||||
* @brief Read struct values from a json object
|
||||
* @param j json to read values from
|
||||
* @return A reference to self
|
||||
*/
|
||||
forum_tag& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Build json for this forum_tag object
|
||||
*
|
||||
* @param with_id include the ID in the json
|
||||
* @return json JSON object
|
||||
*/
|
||||
json to_json_impl(bool with_id = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The name of the tag (0-20 characters).
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* @brief The emoji of the tag.
|
||||
* Contains either nothing, the id of a guild's custom emoji or the unicode character of the emoji.
|
||||
*/
|
||||
std::variant<std::monostate, snowflake, std::string> emoji;
|
||||
|
||||
/**
|
||||
* @brief Whether this tag can only be added to or removed from threads
|
||||
* by a member with the `MANAGE_THREADS` permission.
|
||||
*/
|
||||
bool moderated;
|
||||
|
||||
/** Constructor */
|
||||
forum_tag();
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param name The name of the tag. It will be truncated to the maximum length of 20 UTF-8 characters.
|
||||
*/
|
||||
forum_tag(const std::string& name);
|
||||
|
||||
/** Destructor */
|
||||
virtual ~forum_tag() = default;
|
||||
|
||||
/**
|
||||
* @brief Set name of this forum_tag object
|
||||
*
|
||||
* @param name Name to set
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*
|
||||
* @note name will be truncated to 20 chars, if longer
|
||||
*/
|
||||
forum_tag& set_name(const std::string& name);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A definition of a discord channel.
|
||||
* There are one of these for every channel type except threads. Threads are
|
||||
* special snowflakes. Get it? A Discord pun. Hahaha. .... I'll get my coat.
|
||||
*/
|
||||
class DPP_EXPORT channel : public managed, public json_interface<channel> {
|
||||
protected:
|
||||
friend struct json_interface<channel>;
|
||||
|
||||
/** Read class values from json object
|
||||
* @param j A json object to read from
|
||||
* @return A reference to self
|
||||
*/
|
||||
channel& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Build json for this channel object
|
||||
*
|
||||
* @param with_id include the ID in the json
|
||||
* @return json JSON object
|
||||
*/
|
||||
virtual json to_json_impl(bool with_id = false) const;
|
||||
|
||||
static constexpr uint16_t CHANNEL_TYPE_MASK = 0b0000000000001111;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Channel name (1-100 characters).
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* @brief Channel topic (0-4096 characters for forum and media channels, 0-1024 characters for all others).
|
||||
*/
|
||||
std::string topic;
|
||||
|
||||
/**
|
||||
* @brief Voice region if set for voice channel, otherwise empty string.
|
||||
*/
|
||||
std::string rtc_region;
|
||||
|
||||
/**
|
||||
* @brief DM recipients.
|
||||
*/
|
||||
std::vector<snowflake> recipients;
|
||||
|
||||
/**
|
||||
* @brief Permission overwrites to apply to base permissions.
|
||||
*/
|
||||
std::vector<permission_overwrite> permission_overwrites;
|
||||
|
||||
/**
|
||||
* @brief A set of tags that can be used in a forum or media channel.
|
||||
*/
|
||||
std::vector<forum_tag> available_tags;
|
||||
|
||||
/**
|
||||
* @brief The emoji to show as the default reaction button on a thread in a forum or media channel.
|
||||
* Contains either nothing, the id of a guild's custom emoji or the unicode character of the emoji.
|
||||
*/
|
||||
std::variant<std::monostate, snowflake, std::string> default_reaction;
|
||||
|
||||
/**
|
||||
* @brief Channel icon (for group DMs).
|
||||
*/
|
||||
utility::iconhash icon;
|
||||
|
||||
/**
|
||||
* @brief User ID of the creator for group DMs or threads.
|
||||
*/
|
||||
snowflake owner_id;
|
||||
|
||||
/**
|
||||
* @brief Parent ID (for guild channels: id of the parent category, for threads: id of the text channel this thread was created).
|
||||
*/
|
||||
snowflake parent_id;
|
||||
|
||||
/**
|
||||
* @brief Guild id of the guild that owns the channel.
|
||||
*/
|
||||
snowflake guild_id;
|
||||
|
||||
/**
|
||||
* @brief ID of last message to be sent to the channel.
|
||||
*
|
||||
* @warning may not point to an existing or valid message/thread.
|
||||
*/
|
||||
snowflake last_message_id;
|
||||
|
||||
/**
|
||||
* @brief Timestamp of last pinned message.
|
||||
*/
|
||||
time_t last_pin_timestamp;
|
||||
|
||||
/**
|
||||
* @brief This is only filled when the channel is part of the `resolved` set
|
||||
* sent within an interaction. Any other time it contains zero. When filled,
|
||||
* it contains the calculated permission bitmask of the user issuing the command
|
||||
* within this channel.
|
||||
*/
|
||||
permission permissions;
|
||||
|
||||
/**
|
||||
* @brief Sorting position, lower number means higher up the list
|
||||
*/
|
||||
uint16_t position;
|
||||
|
||||
/**
|
||||
* @brief The bitrate (in kilobits) of the voice channel.
|
||||
*/
|
||||
uint16_t bitrate;
|
||||
|
||||
/**
|
||||
* @brief Amount of seconds a user has to wait before sending another message (0-21600).
|
||||
* Bots, as well as users with the permission manage_messages or manage_channel, are unaffected
|
||||
*/
|
||||
uint16_t rate_limit_per_user;
|
||||
|
||||
/**
|
||||
* @brief The initial `rate_limit_per_user` to set on newly created threads in a channel.
|
||||
* This field is copied to the thread at creation time and does not live update.
|
||||
*/
|
||||
uint16_t default_thread_rate_limit_per_user;
|
||||
|
||||
/**
|
||||
* @brief Default duration, copied onto newly created threads. Used by the clients, not the API.
|
||||
* Threads will stop showing in the channel list after the specified period of inactivity. Defaults to dpp::arc_1_day.
|
||||
*/
|
||||
auto_archive_duration_t default_auto_archive_duration;
|
||||
|
||||
/**
|
||||
* @brief The default sort order type used to order posts in forum and media channels.
|
||||
*/
|
||||
default_forum_sort_order_t default_sort_order;
|
||||
|
||||
/**
|
||||
* @brief Flags bitmap (dpp::channel_flags)
|
||||
*/
|
||||
uint16_t flags;
|
||||
|
||||
/**
|
||||
* @brief Maximum user limit for voice channels (0-99)
|
||||
*/
|
||||
uint8_t user_limit;
|
||||
|
||||
/** Constructor */
|
||||
channel();
|
||||
|
||||
/** Destructor */
|
||||
virtual ~channel();
|
||||
|
||||
/**
|
||||
* @brief Create a mentionable channel.
|
||||
* @param id The ID of the channel.
|
||||
* @return std::string The formatted mention of the channel.
|
||||
*/
|
||||
static std::string get_mention(const snowflake& id);
|
||||
|
||||
/**
|
||||
* @brief Set name of this channel object
|
||||
*
|
||||
* @param name Name to set
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*
|
||||
* @note name will be truncated to 100 chars, if longer
|
||||
* @throw dpp::length_exception if length < 1
|
||||
*/
|
||||
channel& set_name(const std::string& name);
|
||||
|
||||
/**
|
||||
* @brief Set topic of this channel object
|
||||
*
|
||||
* @param topic Topic to set
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*
|
||||
* @note topic will be truncated to 1024 chars, if longer
|
||||
*/
|
||||
channel& set_topic(const std::string& topic);
|
||||
|
||||
/**
|
||||
* @brief Set type of this channel object
|
||||
*
|
||||
* @param type Channel type to set
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& set_type(channel_type type);
|
||||
|
||||
/**
|
||||
* @brief Set the default forum layout type for the forum channel
|
||||
*
|
||||
* @param layout_type The layout type
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& set_default_forum_layout(forum_layout_type layout_type);
|
||||
|
||||
/**
|
||||
* @brief Set the default forum sort order for the forum channel
|
||||
*
|
||||
* @param sort_order The sort order
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& set_default_sort_order(default_forum_sort_order_t sort_order);
|
||||
|
||||
/**
|
||||
* @brief Set flags for this channel object
|
||||
*
|
||||
* @param flags Flag bitmask to set from dpp::channel_flags
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& set_flags(const uint16_t flags);
|
||||
|
||||
/**
|
||||
* @brief Add (bitwise OR) a flag to this channel object
|
||||
*
|
||||
* @param flag Flag bit to add from dpp::channel_flags
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& add_flag(const channel_flags flag);
|
||||
|
||||
/**
|
||||
* @brief Remove (bitwise NOT AND) a flag from this channel object
|
||||
*
|
||||
* @param flag Flag bit to remove from dpp::channel_flags
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& remove_flag(const channel_flags flag);
|
||||
|
||||
/**
|
||||
* @brief Set position of this channel object
|
||||
*
|
||||
* @param position Position to set
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& set_position(const uint16_t position);
|
||||
|
||||
/**
|
||||
* @brief Set guild_id of this channel object
|
||||
*
|
||||
* @param guild_id Guild ID to set
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& set_guild_id(const snowflake guild_id);
|
||||
|
||||
/**
|
||||
* @brief Set parent_id of this channel object
|
||||
*
|
||||
* @param parent_id Parent ID to set
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& set_parent_id(const snowflake parent_id);
|
||||
|
||||
/**
|
||||
* @brief Set user_limit of this channel object
|
||||
*
|
||||
* @param user_limit Limit to set
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& set_user_limit(const uint8_t user_limit);
|
||||
|
||||
/**
|
||||
* @brief Set bitrate of this channel object
|
||||
*
|
||||
* @param bitrate Bitrate to set (in kilobits)
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& set_bitrate(const uint16_t bitrate);
|
||||
|
||||
/**
|
||||
* @brief Set nsfw property of this channel object
|
||||
*
|
||||
* @param is_nsfw true, if channel is nsfw
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& set_nsfw(const bool is_nsfw);
|
||||
|
||||
/**
|
||||
* @brief Set lock permissions property of this channel object
|
||||
* Used only with the reorder channels method
|
||||
*
|
||||
* @param is_lock_permissions true, if we are to inherit permissions from the category
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& set_lock_permissions(const bool is_lock_permissions);
|
||||
|
||||
/**
|
||||
* @brief Set rate_limit_per_user of this channel object
|
||||
*
|
||||
* @param rate_limit_per_user rate_limit_per_user (slowmode in sec) to set
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& set_rate_limit_per_user(const uint16_t rate_limit_per_user);
|
||||
|
||||
/**
|
||||
* @brief Add permission overwrites for a user or role.
|
||||
* If the channel already has permission overwrites for the passed target, the existing ones will be adjusted by the passed permissions
|
||||
*
|
||||
* @param target ID of the role or the member you want to adjust overwrites for
|
||||
* @param type type of overwrite
|
||||
* @param allowed_permissions bitmask of dpp::permissions you want to allow for this user/role in this channel. Note: You can use the dpp::permission class
|
||||
* @param denied_permissions bitmask of dpp::permissions you want to deny for this user/role in this channel. Note: You can use the dpp::permission class
|
||||
*
|
||||
* **Example:**
|
||||
*
|
||||
* ```cpp
|
||||
* channel.add_permission_overwrite(388499352297406481, dpp::ot_role, dpp::p_manage_channels | dpp::p_manage_messages, 0);
|
||||
* // Allows p_manage_channels and p_manage_messages permissions for the provided role.
|
||||
* ```
|
||||
*
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& add_permission_overwrite(const snowflake target, const overwrite_type type, const uint64_t allowed_permissions, const uint64_t denied_permissions);
|
||||
/**
|
||||
* @brief Set permission overwrites for a user or role on this channel object. Old permission overwrites for the target will be overwritten
|
||||
*
|
||||
* @param target ID of the role or the member you want to set overwrites for
|
||||
* @param type type of overwrite
|
||||
* @param allowed_permissions bitmask of allowed dpp::permissions for this user/role in this channel. Note: You can use the dpp::permission class
|
||||
* @param denied_permissions bitmask of denied dpp::permissions for this user/role in this channel. Note: You can use the dpp::permission class
|
||||
*
|
||||
* **Example:**
|
||||
*
|
||||
* ```cpp
|
||||
* channel.set_permission_overwrite(388499352297406481, dpp::ot_role, dpp::p_manage_channels | dpp::p_manage_messages, 0);
|
||||
* // Sets the allowed permissions to p_manage_channels and p_manage_messages and removes all denied permission flags for the provided role.
|
||||
* ```
|
||||
*
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*
|
||||
* @note If both `allowed_permissions` and `denied_permissions` parameters are 0, the permission overwrite for the target will be removed
|
||||
*/
|
||||
channel& set_permission_overwrite(const snowflake target, const overwrite_type type, const uint64_t allowed_permissions, const uint64_t denied_permissions);
|
||||
/**
|
||||
* @brief Remove channel specific permission overwrites of a user or role
|
||||
*
|
||||
* @param target ID of the role or the member you want to remove permission overwrites of
|
||||
* @param type type of overwrite
|
||||
*
|
||||
* @return Reference to self, so these method calls may be chained
|
||||
*/
|
||||
channel& remove_permission_overwrite(const snowflake target, const overwrite_type type);
|
||||
|
||||
/**
|
||||
* @brief Get the channel type
|
||||
*
|
||||
* @return channel_type Channel type
|
||||
*/
|
||||
channel_type get_type() const;
|
||||
|
||||
/**
|
||||
* @brief Get the default forum layout type used to display posts in forum channels
|
||||
*
|
||||
* @return forum_layout_types Forum layout type
|
||||
*/
|
||||
forum_layout_type get_default_forum_layout() const;
|
||||
|
||||
/**
|
||||
* @brief Get the mention ping for the channel
|
||||
*
|
||||
* @return std::string mention
|
||||
*/
|
||||
std::string get_mention() const;
|
||||
|
||||
/**
|
||||
* @brief Get the overall permissions for a member in this channel, including channel overwrites, role permissions and admin privileges.
|
||||
*
|
||||
* @param user The user to resolve the permissions for
|
||||
* @return permission Permission overwrites for the member. Made of bits in dpp::permissions.
|
||||
* @note Requires role cache to be enabled (it's enabled by default).
|
||||
*
|
||||
* @note This is an alias for guild::permission_overwrites and searches for the guild in the cache,
|
||||
* so consider using guild::permission_overwrites if you already have the guild object.
|
||||
*
|
||||
* @warning The method will search for the guild member in the cache by the users id.
|
||||
* If the guild member is not in cache, the method will always return 0.
|
||||
*/
|
||||
permission get_user_permissions(const class user* user) const;
|
||||
|
||||
/**
|
||||
* @brief Get the overall permissions for a member in this channel, including channel overwrites, role permissions and admin privileges.
|
||||
*
|
||||
* @param member The member to resolve the permissions for
|
||||
* @return permission Permission overwrites for the member. Made of bits in dpp::permissions.
|
||||
* @note Requires role cache to be enabled (it's enabled by default).
|
||||
*
|
||||
* @note This is an alias for guild::permission_overwrites and searches for the guild in the cache,
|
||||
* so consider using guild::permission_overwrites if you already have the guild object.
|
||||
*/
|
||||
permission get_user_permissions(const class guild_member &member) const;
|
||||
|
||||
/**
|
||||
* @brief Return a map of members on the channel, built from the guild's
|
||||
* member list based on which members have the VIEW_CHANNEL permission.
|
||||
* Does not return reliable information for voice channels, use
|
||||
* dpp::channel::get_voice_members() instead for this.
|
||||
* @return A map of guild members keyed by user id.
|
||||
* @note If the guild this channel belongs to is not in the cache, the function will always return 0.
|
||||
*/
|
||||
std::map<snowflake, class guild_member*> get_members();
|
||||
|
||||
/**
|
||||
* @brief Get a map of members in this channel, if it is a voice channel.
|
||||
* The map is keyed by snowflake id of the user.
|
||||
*
|
||||
* @return std::map<snowflake, voicestate> The voice members of the channel
|
||||
*/
|
||||
std::map<snowflake, voicestate> get_voice_members();
|
||||
|
||||
/**
|
||||
* @brief Get the channel's icon url (if its a group DM), otherwise returns an empty string
|
||||
*
|
||||
* @param size The size of the icon in pixels. It can be any power of two between 16 and 4096,
|
||||
* otherwise the default sized icon is returned.
|
||||
* @param format The format to use for the avatar. It can be one of `i_webp`, `i_jpg` or `i_png`.
|
||||
* @return std::string icon url or an empty string, if required attributes are missing or an invalid format was passed
|
||||
*/
|
||||
std::string get_icon_url(uint16_t size = 0, const image_type format = i_png) const;
|
||||
|
||||
/**
|
||||
* @brief Returns string of URL to channel
|
||||
*
|
||||
* @return string of URL to channel
|
||||
*/
|
||||
std::string get_url() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the channel is NSFW gated
|
||||
*
|
||||
* @return true if NSFW
|
||||
*/
|
||||
bool is_nsfw() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the permissions are to be synced with the category it is in.
|
||||
* Used only and set manually when using the reorder channels method.
|
||||
*
|
||||
* @return true if keeping permissions
|
||||
*/
|
||||
bool is_locked_permissions() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the channel is a text channel
|
||||
*
|
||||
* @return true if text channel
|
||||
*/
|
||||
bool is_text_channel() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the channel is a DM
|
||||
*
|
||||
* @return true if is a DM
|
||||
*/
|
||||
bool is_dm() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the channel is a voice channel
|
||||
*
|
||||
* @return true if voice channel
|
||||
*/
|
||||
bool is_voice_channel() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the channel is a group DM channel
|
||||
*
|
||||
* @return true if group DM
|
||||
*/
|
||||
bool is_group_dm() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the channel is a category
|
||||
*
|
||||
* @return true if a category
|
||||
*/
|
||||
bool is_category() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the channel is a forum
|
||||
*
|
||||
* @return true if a forum
|
||||
*/
|
||||
bool is_forum() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the channel is a media channel
|
||||
*
|
||||
* @return true if media channel
|
||||
*/
|
||||
bool is_media_channel() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the channel is an announcement channel
|
||||
*
|
||||
* @return true if announcement channel
|
||||
*/
|
||||
bool is_news_channel() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the channel is a store channel
|
||||
* @deprecated store channels are deprecated by Discord
|
||||
*
|
||||
* @return true if store channel
|
||||
*/
|
||||
bool is_store_channel() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the channel is a stage channel
|
||||
*
|
||||
* @return true if stage channel
|
||||
*/
|
||||
bool is_stage_channel() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if video quality is auto
|
||||
*
|
||||
* @return true if video quality is auto
|
||||
*/
|
||||
bool is_video_auto() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if video quality is 720p
|
||||
*
|
||||
* @return true if video quality is 720p
|
||||
*/
|
||||
bool is_video_720p() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if channel is a pinned thread in forum
|
||||
*
|
||||
* @return true, if channel is a pinned thread in forum
|
||||
*/
|
||||
bool is_pinned_thread() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if a tag is required to be specified when creating a thread in a forum channel
|
||||
*
|
||||
* @return true, if a tag is required to be specified when creating a thread in a forum channel
|
||||
*/
|
||||
bool is_tag_required() const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if embedded media download options are hidden in a media channel
|
||||
*
|
||||
* @return true, if embedded media download options are hidden in a media channel
|
||||
*/
|
||||
bool is_download_options_hidden() const;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Serialize a permission_overwrite object to json
|
||||
*
|
||||
* @param j JSON object to serialize to
|
||||
* @param po object to serialize
|
||||
*/
|
||||
void to_json(nlohmann::json& j, const permission_overwrite& po);
|
||||
|
||||
/**
|
||||
* @brief A group of channels
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, channel> channel_map;
|
||||
|
||||
}
|
||||
|
||||
4109
dpp/cluster.h
4109
dpp/cluster.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
473
dpp/collector.h
473
dpp/collector.h
@ -1,473 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/cluster.h>
|
||||
#include <dpp/timed_listener.h>
|
||||
#include <time.h>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Collects objects from events during a specified time period.
|
||||
*
|
||||
* This template must be specialised. There are premade specialisations which you can use
|
||||
* such as dpp::reaction_collector and dpp::message_collector. For these specialised instances
|
||||
* all you need to do is derive a simple class from them which implements collector::completed().
|
||||
*
|
||||
* A collector will run for the specified number of seconds, attaching itself to the
|
||||
* given event. During this time any events pass through the collector and collector::filter().
|
||||
* This function can return a pointer to an object to allow a copy of that object to be stored
|
||||
* to a vector, or it can return nullptr to do nothing with that object. For example a collector
|
||||
* attached to on_message_create would receive an event with the type message_create_t, and from
|
||||
* this may decide to extract the message_create_t::msg structure, returning a pointer to it, or
|
||||
* instead may choose to return a nullptr.
|
||||
*
|
||||
* When either the predetermined timeout is reached, or the collector::cancel() method is called,
|
||||
* or the collector is destroyed, the collector::completed() method is called, which will be
|
||||
* passed a list of collected objects in the order they were collected.
|
||||
*
|
||||
* @tparam T parameter type of the event this collector will monitor
|
||||
* @tparam C object type this collector will store
|
||||
*/
|
||||
template<class T, class C> class collector
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* @brief Owning cluster.
|
||||
*/
|
||||
class cluster* owner;
|
||||
private:
|
||||
/**
|
||||
* @brief Timed listener.
|
||||
*/
|
||||
timed_listener<event_router_t<T>, std::function<void(const T&)>>* tl;
|
||||
|
||||
/**
|
||||
* @brief Stored list.
|
||||
*/
|
||||
std::vector<C> stored;
|
||||
|
||||
/**
|
||||
* @brief Trigger flag.
|
||||
*/
|
||||
bool triggered;
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new collector object.
|
||||
*
|
||||
* The timer for the collector begins immediately on construction of the object.
|
||||
*
|
||||
* @param cl Pointer to cluster which manages this collector
|
||||
* @param duration Duration in seconds to run the collector for
|
||||
* @param event Event to attach to, e.g. cluster::on_message_create
|
||||
*/
|
||||
collector(class cluster* cl, uint64_t duration, event_router_t<T> & event) : owner(cl), triggered(false) {
|
||||
std::function<void(const T&)> f = [this](const T& event) {
|
||||
const C* v = filter(event);
|
||||
if (v) {
|
||||
stored.push_back(*v);
|
||||
}
|
||||
};
|
||||
tl = new dpp::timed_listener<event_router_t<T>, std::function<void(const T&)>>(cl, duration, event, f, [this]([[maybe_unused]] dpp::timer timer_handle) {
|
||||
if (!triggered) {
|
||||
triggered = true;
|
||||
completed(stored);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief You must implement this function to receive the completed list of
|
||||
* captured objects.
|
||||
* @param list The list of captured objects in captured order
|
||||
*/
|
||||
virtual void completed(const std::vector<C>& list) = 0;
|
||||
|
||||
/**
|
||||
* @brief Filter the list of elements.
|
||||
*
|
||||
* Every time an event is fired on the collector, this method wil be called
|
||||
* to determine if we should add an object to the list or not. This function
|
||||
* can then process the `element` value, extract the parts which are to be
|
||||
* saved to a list (e.g. a dpp::message out of a dpp::message_create_t) and
|
||||
* return it as the return value. Returning a value of nullptr causes no
|
||||
* object to be stored.
|
||||
*
|
||||
* Here is an example of how to filter messages which have specific text in them.
|
||||
* This should be used with the specialised type dpp::message_collector
|
||||
*
|
||||
* ```cpp
|
||||
* virtual const dpp::message* filter(const dpp::message_create_t& m) {
|
||||
* if (m.msg.content.find("something i want") != std::string::npos) {
|
||||
* return &m.msg;
|
||||
* } else {
|
||||
* return nullptr;
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param element The event data to filter
|
||||
* @return const C* Returned object or nullptr
|
||||
*/
|
||||
virtual const C* filter(const T& element) = 0;
|
||||
|
||||
/**
|
||||
* @brief Immediately cancels the collector.
|
||||
*
|
||||
* Use this if you have met the conditions for which you are collecting objects
|
||||
* early, e.g. you were watching for a message containing 'yes' or 'no' and have
|
||||
* received it before the time is up.
|
||||
*
|
||||
* @note Causes calling of the completed() method if it has not yet been called.
|
||||
*/
|
||||
virtual void cancel() {
|
||||
delete tl;
|
||||
tl = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroy the collector object.
|
||||
* @note Causes calling of the completed() method if it has not yet been called.
|
||||
*/
|
||||
virtual ~collector() {
|
||||
delete tl;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a reaction.
|
||||
* Can be filled for use in a collector
|
||||
*/
|
||||
class collected_reaction : public managed {
|
||||
public:
|
||||
/**
|
||||
* @brief Reacting user.
|
||||
*/
|
||||
user react_user{};
|
||||
|
||||
/**
|
||||
* @brief Reacting guild.
|
||||
*/
|
||||
guild react_guild{};
|
||||
|
||||
/**
|
||||
* @brief Reacting guild member.
|
||||
*/
|
||||
guild_member react_member{};
|
||||
|
||||
/**
|
||||
* @brief Reacting channel.
|
||||
*/
|
||||
channel react_channel{};
|
||||
|
||||
/**
|
||||
* @brief Reacted emoji.
|
||||
*/
|
||||
emoji react_emoji{};
|
||||
|
||||
/**
|
||||
* @brief Optional: ID of the user who authored the message which was reacted to.
|
||||
*/
|
||||
snowflake message_author_id{};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Template type for base class of channel collector
|
||||
*/
|
||||
typedef dpp::collector<dpp::channel_create_t, dpp::channel> channel_collector_t;
|
||||
|
||||
/**
|
||||
* @brief Template type for base class of thread collector
|
||||
*/
|
||||
typedef dpp::collector<dpp::thread_create_t, dpp::thread> thread_collector_t;
|
||||
|
||||
/**
|
||||
* @brief Template type for base class of role collector
|
||||
*/
|
||||
typedef dpp::collector<dpp::guild_role_create_t, dpp::role> role_collector_t;
|
||||
|
||||
/**
|
||||
* @brief Template type for base class of scheduled event collector
|
||||
*/
|
||||
typedef dpp::collector<dpp::guild_scheduled_event_create_t, dpp::scheduled_event> scheduled_event_collector_t;
|
||||
|
||||
/**
|
||||
* @brief Template type for base class of message collector
|
||||
*/
|
||||
typedef dpp::collector<dpp::message_create_t, dpp::message> message_collector_t;
|
||||
|
||||
/**
|
||||
* @brief Template type for base class of message reaction collector
|
||||
*/
|
||||
typedef dpp::collector<dpp::message_reaction_add_t, dpp::collected_reaction> reaction_collector_t;
|
||||
|
||||
/**
|
||||
* @brief Message collector.
|
||||
* Collects messages during a set timeframe and returns them in a list via the completed() method.
|
||||
*/
|
||||
class message_collector : public message_collector_t {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new message collector object
|
||||
*
|
||||
* @param cl cluster to associate the collector with
|
||||
* @param duration Duration of time to run the collector for in seconds
|
||||
*/
|
||||
message_collector(cluster* cl, uint64_t duration) : message_collector_t::collector(cl, duration, cl->on_message_create) { }
|
||||
|
||||
/**
|
||||
* @brief Return the completed collection
|
||||
*
|
||||
* @param list items collected during the timeframe specified
|
||||
*/
|
||||
virtual void completed(const std::vector<dpp::message>& list) = 0;
|
||||
|
||||
/**
|
||||
* @brief Select and filter the items which are to appear in the list
|
||||
* This is called every time a new event is fired, to filter the event and determine which
|
||||
* of the items is sent to the list. Returning nullptr excludes the item from the list.
|
||||
*
|
||||
* @param element element to filter
|
||||
* @return Returned item to add to the list, or nullptr to skip adding this element
|
||||
*/
|
||||
virtual const dpp::message* filter(const dpp::message_create_t& element) { return &element.msg; }
|
||||
|
||||
/**
|
||||
* @brief Destroy the message collector object
|
||||
*/
|
||||
virtual ~message_collector() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Reaction collector.
|
||||
* Collects message reactions during a set timeframe and returns them in a list via the completed() method.
|
||||
*/
|
||||
class reaction_collector : public reaction_collector_t {
|
||||
/**
|
||||
* @brief The ID of the message.
|
||||
*/
|
||||
snowflake message_id;
|
||||
|
||||
/**
|
||||
* @brief The reaction.
|
||||
*/
|
||||
collected_reaction react;
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new reaction collector object
|
||||
*
|
||||
* @param cl cluster to associate the collector with
|
||||
* @param duration Duration of time to run the collector for in seconds
|
||||
* @param msg_id Optional message ID. If specified, only collects reactions for the given message
|
||||
*/
|
||||
reaction_collector(cluster* cl, uint64_t duration, snowflake msg_id = 0) : reaction_collector_t::collector(cl, duration, cl->on_message_reaction_add), message_id(msg_id) { }
|
||||
|
||||
/**
|
||||
* @brief Return the completed collection
|
||||
*
|
||||
* @param list items collected during the timeframe specified
|
||||
*/
|
||||
virtual void completed(const std::vector<dpp::collected_reaction>& list) = 0;
|
||||
|
||||
/**
|
||||
* @brief Select and filter the items which are to appear in the list
|
||||
* This is called every time a new event is fired, to filter the event and determine which
|
||||
* of the items is sent to the list. Returning nullptr excludes the item from the list.
|
||||
*
|
||||
* @param element element to filter
|
||||
* @return Returned item to add to the list, or nullptr to skip adding this element
|
||||
*/
|
||||
virtual const dpp::collected_reaction* filter(const dpp::message_reaction_add_t& element) {
|
||||
/* Capture reactions for given message ID only */
|
||||
if (message_id.empty() || element.message_id == message_id) {
|
||||
react.id = element.message_id;
|
||||
react.react_user = element.reacting_user;
|
||||
react.react_guild = element.reacting_guild;
|
||||
react.react_member = element.reacting_member;
|
||||
react.react_channel = element.reacting_channel;
|
||||
react.react_emoji = element.reacting_emoji;
|
||||
react.message_author_id = element.message_author_id;
|
||||
return &react;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroy the reaction collector object
|
||||
*/
|
||||
virtual ~reaction_collector() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Channel collector.
|
||||
* Collects channels during a set timeframe and returns them in a list via the completed() method.
|
||||
*/
|
||||
class channel_collector : public channel_collector_t {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new channel collector object
|
||||
*
|
||||
* @param cl cluster to associate the collector with
|
||||
* @param duration Duration of time to run the collector for in seconds
|
||||
*/
|
||||
channel_collector(cluster* cl, uint64_t duration) : channel_collector_t::collector(cl, duration, cl->on_channel_create) { }
|
||||
|
||||
/**
|
||||
* @brief Return the completed collection
|
||||
*
|
||||
* @param list items collected during the timeframe specified
|
||||
*/
|
||||
virtual void completed(const std::vector<dpp::channel>& list) = 0;
|
||||
|
||||
/**
|
||||
* @brief Select and filter the items which are to appear in the list
|
||||
* This is called every time a new event is fired, to filter the event and determine which
|
||||
* of the items is sent to the list. Returning nullptr excludes the item from the list.
|
||||
*
|
||||
* @param element element to filter
|
||||
* @return Returned item to add to the list, or nullptr to skip adding this element
|
||||
*/
|
||||
virtual const dpp::channel* filter(const dpp::channel_create_t& element) { return &element.created; }
|
||||
|
||||
/**
|
||||
* @brief Destroy the channel collector object
|
||||
*/
|
||||
virtual ~channel_collector() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Thread collector.
|
||||
* Collects threads during a set timeframe and returns them in a list via the completed() method.
|
||||
*/
|
||||
class thread_collector : public thread_collector_t {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new thread collector object
|
||||
*
|
||||
* @param cl cluster to associate the collector with
|
||||
* @param duration Duration of time to run the collector for in seconds
|
||||
*/
|
||||
thread_collector(cluster* cl, uint64_t duration) : thread_collector_t::collector(cl, duration, cl->on_thread_create) { }
|
||||
|
||||
/**
|
||||
* @brief Return the completed collection
|
||||
*
|
||||
* @param list items collected during the timeframe specified
|
||||
*/
|
||||
virtual void completed(const std::vector<dpp::thread>& list) = 0;
|
||||
|
||||
/**
|
||||
* @brief Select and filter the items which are to appear in the list
|
||||
* This is called every time a new event is fired, to filter the event and determine which
|
||||
* of the items is sent to the list. Returning nullptr excludes the item from the list.
|
||||
*
|
||||
* @param element element to filter
|
||||
* @return Returned item to add to the list, or nullptr to skip adding this element
|
||||
*/
|
||||
virtual const dpp::thread* filter(const dpp::thread_create_t& element) { return &element.created; }
|
||||
|
||||
/**
|
||||
* @brief Destroy the thread collector object
|
||||
*/
|
||||
virtual ~thread_collector() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Role collector.
|
||||
* Collects guild roles during a set timeframe and returns them in a list via the completed() method.
|
||||
*/
|
||||
class role_collector : public role_collector_t {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new role collector object
|
||||
*
|
||||
* @param cl cluster to associate the collector with
|
||||
* @param duration Duration of time to run the collector for in seconds
|
||||
*/
|
||||
role_collector(cluster* cl, uint64_t duration) : role_collector_t::collector(cl, duration, cl->on_guild_role_create) { }
|
||||
|
||||
/**
|
||||
* @brief Return the completed collection
|
||||
*
|
||||
* @param list items collected during the timeframe specified
|
||||
*/
|
||||
virtual void completed(const std::vector<dpp::role>& list) = 0;
|
||||
|
||||
/**
|
||||
* @brief Select and filter the items which are to appear in the list
|
||||
* This is called every time a new event is fired, to filter the event and determine which
|
||||
* of the items is sent to the list. Returning nullptr excludes the item from the list.
|
||||
*
|
||||
* @param element element to filter
|
||||
* @return Returned item to add to the list, or nullptr to skip adding this element
|
||||
*/
|
||||
virtual const dpp::role* filter(const dpp::guild_role_create_t& element) { return &element.created; }
|
||||
|
||||
/**
|
||||
* @brief Destroy the role collector object
|
||||
*/
|
||||
virtual ~role_collector() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Scheduled event collector.
|
||||
* Collects messages during a set timeframe and returns them in a list via the completed() method.
|
||||
*/
|
||||
class scheduled_event_collector : public scheduled_event_collector_t {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new scheduled event collector object
|
||||
*
|
||||
* @param cl cluster to associate the collector with
|
||||
* @param duration Duration of time to run the collector for in seconds
|
||||
*/
|
||||
scheduled_event_collector(cluster* cl, uint64_t duration) : scheduled_event_collector_t::collector(cl, duration, cl->on_guild_scheduled_event_create) { }
|
||||
|
||||
/**
|
||||
* @brief Return the completed collection
|
||||
*
|
||||
* @param list items collected during the timeframe specified
|
||||
*/
|
||||
virtual void completed(const std::vector<dpp::scheduled_event>& list) = 0;
|
||||
|
||||
/**
|
||||
* @brief Select and filter the items which are to appear in the list
|
||||
* This is called every time a new event is fired, to filter the event and determine which
|
||||
* of the items is sent to the list. Returning nullptr excludes the item from the list.
|
||||
*
|
||||
* @param element element to filter
|
||||
* @return Returned item to add to the list, or nullptr to skip adding this element
|
||||
*/
|
||||
virtual const dpp::scheduled_event* filter(const dpp::guild_scheduled_event_create_t& element) { return &element.created; }
|
||||
|
||||
/**
|
||||
* @brief Destroy the scheduled event collector object
|
||||
*/
|
||||
virtual ~scheduled_event_collector() = default;
|
||||
};
|
||||
|
||||
}
|
||||
745
dpp/colors.h
745
dpp/colors.h
@ -1,745 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* @brief The main namespace for D++ functions. classes and types
|
||||
*/
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief predefined color constants.
|
||||
*/
|
||||
namespace colors {
|
||||
const uint32_t
|
||||
white = 0xFFFFFF,
|
||||
discord_white = 0xFFFFFE,
|
||||
light_gray = 0xC0C0C0,
|
||||
gray = 0x808080,
|
||||
dark_gray = 0x404040,
|
||||
black = 0x000000,
|
||||
discord_black = 0x000001,
|
||||
red = 0xFF0000,
|
||||
pink = 0xFFAFAF,
|
||||
orange = 0xFFC800,
|
||||
yellow = 0xFFFF00,
|
||||
green = 0x00FF00,
|
||||
magenta = 0xFF00FF,
|
||||
cyan = 0x00FFFF,
|
||||
blue = 0x0000FF,
|
||||
light_sea_green = 0x1ABC9C,
|
||||
medium_sea_green = 0x2ECC71,
|
||||
summer_sky = 0x3498DB,
|
||||
deep_lilac = 0x9B59B6,
|
||||
ruby = 0xE91E63,
|
||||
moon_yellow = 0xF1C40F,
|
||||
tahiti_gold = 0xE67E22,
|
||||
cinnabar = 0xE74C3C,
|
||||
submarine = 0x95A5A6,
|
||||
blue_aquamarine = 0x607D8B,
|
||||
deep_sea = 0x11806A,
|
||||
sea_green = 0x1F8B4C,
|
||||
endeavour = 0x206694,
|
||||
vivid_violet = 0x71368A,
|
||||
jazzberry_jam = 0xAD1457,
|
||||
dark_goldenrod = 0xC27C0E,
|
||||
rust = 0xA84300,
|
||||
brown = 0x992D22,
|
||||
gray_chateau = 0x979C9F,
|
||||
bismark = 0x546E7A,
|
||||
sti_blue = 0x0E4BEF,
|
||||
wrx_blue = 0x00247D,
|
||||
rallyart_crimson = 0xE60012,
|
||||
lime = 0x00FF00,
|
||||
forest_green = 0x228B22,
|
||||
cadmium_green = 0x097969,
|
||||
aquamarine = 0x7FFFD4,
|
||||
blue_green = 0x088F8F,
|
||||
raspberry = 0xE30B5C,
|
||||
scarlet_red = 0xFF2400,
|
||||
night = 0x0C090A,
|
||||
charcoal = 0x34282C,
|
||||
oil = 0x3B3131,
|
||||
light_black = 0x454545,
|
||||
black_cat = 0x413839,
|
||||
iridium = 0x3D3C3A,
|
||||
black_eel = 0x463E3F,
|
||||
black_cow = 0x4C4646,
|
||||
gray_wolf = 0x504A4B,
|
||||
grey_wolf = 0x504A4B,
|
||||
vampire_gray = 0x565051,
|
||||
vampire_grey = 0x565051,
|
||||
iron_gray = 0x52595D,
|
||||
iron_grey = 0x52595D,
|
||||
gray_dolphin = 0x5C5858,
|
||||
grey_dolphin = 0x5C5858,
|
||||
carbon_gray = 0x625D5D,
|
||||
carbon_grey = 0x625D5D,
|
||||
ash_gray = 0x666362,
|
||||
ash_grey = 0x666362,
|
||||
dim_gray = 0x696969,
|
||||
dim_grey = 0x696969,
|
||||
nardo_gray = 0x686A6C,
|
||||
nardo_grey = 0x686A6C,
|
||||
cloudy_gray = 0x6D6968,
|
||||
cloudy_grey = 0x6D6968,
|
||||
smokey_gray = 0x726E6D,
|
||||
smokey_grey = 0x726E6D,
|
||||
alien_gray = 0x736F6E,
|
||||
alien_grey = 0x736F6E,
|
||||
sonic_silver = 0x757575,
|
||||
platinum_gray = 0x797979,
|
||||
platinum_grey = 0x797979,
|
||||
granite = 0x837E7C,
|
||||
battleship_gray = 0x848482,
|
||||
battleship_grey = 0x848482,
|
||||
gunmetal_gray = 0x8D918D,
|
||||
gunmetal_grey = 0x8D918D,
|
||||
gray_cloud = 0xB6B6B4,
|
||||
grey_cloud = 0xB6B6B4,
|
||||
silver = 0xC0C0C0,
|
||||
pale_silver = 0xC9C0BB,
|
||||
gray_goose = 0xD1D0CE,
|
||||
grey_goose = 0xD1D0CE,
|
||||
platinum_silver = 0xCECECE,
|
||||
silver_white = 0xDADBDD,
|
||||
gainsboro = 0xDCDCDC,
|
||||
platinum = 0xE5E4E2,
|
||||
metallic_silver = 0xBCC6CC,
|
||||
blue_gray = 0x98AFC7,
|
||||
blue_grey = 0x98AFC7,
|
||||
roman_silver = 0x838996,
|
||||
light_slate_gray = 0x778899,
|
||||
light_slate_grey = 0x778899,
|
||||
slate_gray = 0x708090,
|
||||
slate_grey = 0x708090,
|
||||
rat_gray = 0x6D7B8D,
|
||||
slate_granite_gray = 0x657383,
|
||||
slate_granite_grey = 0x657383,
|
||||
jet_gray = 0x616D7E,
|
||||
jet_grey = 0x616D7E,
|
||||
mist_blue = 0x646D7E,
|
||||
marble_blue = 0x566D7E,
|
||||
slate_blue_grey = 0x737CA1,
|
||||
slate_blue_gray = 0x737CA1,
|
||||
light_purple_blue = 0x728FCE,
|
||||
azure_blue = 0x4863A0,
|
||||
blue_jay = 0x2B547E,
|
||||
charcoal_blue = 0x36454F,
|
||||
dark_blue_grey = 0x29465B,
|
||||
dark_slate = 0x2B3856,
|
||||
deep_sea_blue = 0x123456,
|
||||
night_blue = 0x151B54,
|
||||
midnight_blue = 0x191970,
|
||||
navy = 0x000080,
|
||||
denim_dark_blue = 0x151B8D,
|
||||
dark_blue = 0x00008B,
|
||||
lapis_blue = 0x15317E,
|
||||
new_midnight_blue = 0x0000A0,
|
||||
earth_blue = 0x0000A5,
|
||||
cobalt_blue = 0x0020C2,
|
||||
medium_blue = 0x0000CD,
|
||||
blueberry_blue = 0x0041C2,
|
||||
canary_blue = 0x2916F5,
|
||||
samco_blue = 0x0002FF,
|
||||
bright_blue = 0x0909FF,
|
||||
blue_orchid = 0x1F45FC,
|
||||
sapphire_blue = 0x2554C7,
|
||||
blue_eyes = 0x1569C7,
|
||||
bright_navy_blue = 0x1974D2,
|
||||
balloon_blue = 0x2B60DE,
|
||||
royal_blue = 0x4169E1,
|
||||
ocean_blue = 0x2B65EC,
|
||||
blue_ribbon = 0x306EFF,
|
||||
blue_dress = 0x157DEC,
|
||||
neon_blue = 0x1589FF,
|
||||
dodger_blue = 0x1E90FF,
|
||||
glacial_blue_ice = 0x368BC1,
|
||||
steel_blue = 0x4682B4,
|
||||
silk_blue = 0x488AC7,
|
||||
windows_blue = 0x357EC7,
|
||||
blue_ivy = 0x3090C7,
|
||||
blue_koi = 0x659EC7,
|
||||
columbia_blue = 0x87AFC7,
|
||||
baby_blue = 0x95B9C7,
|
||||
cornflower_blue = 0x6495ED,
|
||||
sky_blue_dress = 0x6698FF,
|
||||
iceberg = 0x56A5EC,
|
||||
butterfly_blue = 0x38ACEC,
|
||||
deep_sky_blue = 0x00BFFF,
|
||||
midday_blue = 0x3BB9FF,
|
||||
crystal_blue = 0x5CB3FF,
|
||||
denim_blue = 0x79BAEC,
|
||||
day_sky_blue = 0x82CAFF,
|
||||
light_sky_blue = 0x87CEFA,
|
||||
sky_blue = 0x87CEEB,
|
||||
jeans_blue = 0xA0CFEC,
|
||||
blue_angel = 0xB7CEEC,
|
||||
pastel_blue = 0xB4CFEC,
|
||||
light_day_blue = 0xADDFFF,
|
||||
sea_blue = 0xC2DFFF,
|
||||
heavenly_blue = 0xC6DEFF,
|
||||
robin_egg_blue = 0xBDEDFF,
|
||||
powder_blue = 0xB0E0E6,
|
||||
coral_blue = 0xAFDCEC,
|
||||
light_blue = 0xADD8E6,
|
||||
light_steel_blue = 0xB0CFDE,
|
||||
gulf_blue = 0xC9DFEC,
|
||||
pastel_light_blue = 0xD5D6EA,
|
||||
lavender_blue = 0xE3E4FA,
|
||||
white_blue = 0xDBE9FA,
|
||||
lavender = 0xE6E6FA,
|
||||
water = 0xEBF4FA,
|
||||
alice_blue = 0xF0F8FF,
|
||||
ghost_white = 0xF8F8FF,
|
||||
azure = 0xF0FFFF,
|
||||
light_cyan = 0xE0FFFF,
|
||||
light_slate = 0xCCFFFF,
|
||||
electric_blue = 0x9AFEFF,
|
||||
tron_blue = 0x7DFDFE,
|
||||
blue_zircon = 0x57FEFF,
|
||||
aqua = 0x00FFFF,
|
||||
bright_cyan = 0x0AFFFF,
|
||||
celeste = 0x50EBEC,
|
||||
blue_diamond = 0x4EE2EC,
|
||||
bright_turquoise = 0x16E2F5,
|
||||
blue_lagoon = 0x8EEBEC,
|
||||
pale_turquoise = 0xAFEEEE,
|
||||
pale_blue_lily = 0xCFECEC,
|
||||
light_teal = 0xB3D9D9,
|
||||
tiffany_blue = 0x81D8D0,
|
||||
blue_hosta = 0x77BFC7,
|
||||
cyan_opaque = 0x92C7C7,
|
||||
northern_lights_blue = 0x78C7C7,
|
||||
medium_aquamarine = 0x66CDAA,
|
||||
magic_mint = 0xAAF0D1,
|
||||
light_aquamarine = 0x93FFE8,
|
||||
bright_teal = 0x01F9C6,
|
||||
turquoise = 0x40E0D0,
|
||||
medium_turquoise = 0x48D1CC,
|
||||
deep_turquoise = 0x48CCCD,
|
||||
jellyfish = 0x46C7C7,
|
||||
blue_turquoise = 0x43C6DB,
|
||||
dark_turquoise = 0x00CED1,
|
||||
macaw_blue_green = 0x43BFC7,
|
||||
seafoam_green = 0x3EA99F,
|
||||
cadet_blue = 0x5F9EA0,
|
||||
blue_chill = 0x3B9C9C,
|
||||
dark_cyan = 0x008B8B,
|
||||
teal_green = 0x00827F,
|
||||
teal = 0x008080,
|
||||
teal_blue = 0x007C80,
|
||||
medium_teal = 0x045F5F,
|
||||
dark_teal = 0x045D5D,
|
||||
deep_teal = 0x033E3E,
|
||||
dark_slate_gray = 0x25383C,
|
||||
dark_slate_grey = 0x25383C,
|
||||
gunmetal = 0x2C3539,
|
||||
blue_moss_green = 0x3C565B,
|
||||
beetle_green = 0x4C787E,
|
||||
grayish_turquoise = 0x5E7D7E,
|
||||
greenish_blue = 0x307D7E,
|
||||
aquamarine_stone = 0x348781,
|
||||
sea_turtle_green = 0x438D80,
|
||||
dull_sea_green = 0x4E8975,
|
||||
dark_green_blue = 0x1F6357,
|
||||
deep_sea_green = 0x306754,
|
||||
bottle_green = 0x006A4E,
|
||||
elf_green = 0x1B8A6B,
|
||||
dark_mint = 0x31906E,
|
||||
jade = 0x00A36C,
|
||||
earth_green = 0x34A56F,
|
||||
chrome_green = 0x1AA260,
|
||||
emerald = 0x50C878,
|
||||
mint = 0x3EB489,
|
||||
metallic_green = 0x7C9D8E,
|
||||
camouflage_green = 0x78866B,
|
||||
sage_green = 0x848B79,
|
||||
hazel_green = 0x617C58,
|
||||
venom_green = 0x728C00,
|
||||
olive_drab = 0x6B8E23,
|
||||
olive = 0x808000,
|
||||
dark_olive_green = 0x556B2F,
|
||||
military_green = 0x4E5B31,
|
||||
green_leaves = 0x3A5F0B,
|
||||
army_green = 0x4B5320,
|
||||
fern_green = 0x667C26,
|
||||
fall_forest_green = 0x4E9258,
|
||||
irish_green = 0x08A04B,
|
||||
pine_green = 0x387C44,
|
||||
medium_forest_green = 0x347235,
|
||||
jungle_green = 0x347C2C,
|
||||
cactus_green = 0x227442,
|
||||
dark_green = 0x006400,
|
||||
deep_green = 0x056608,
|
||||
deep_emerald_green = 0x046307,
|
||||
hunter_green = 0x355E3B,
|
||||
dark_forest_green = 0x254117,
|
||||
lotus_green = 0x004225,
|
||||
seaweed_green = 0x437C17,
|
||||
shamrock_green = 0x347C17,
|
||||
green_onion = 0x6AA121,
|
||||
moss_green = 0x8A9A5B,
|
||||
grass_green = 0x3F9B0B,
|
||||
green_pepper = 0x4AA02C,
|
||||
dark_lime_green = 0x41A317,
|
||||
parrot_green = 0x12AD2B,
|
||||
clover_green = 0x3EA055,
|
||||
dinosaur_green = 0x73A16C,
|
||||
green_snake = 0x6CBB3C,
|
||||
alien_green = 0x6CC417,
|
||||
green_apple = 0x4CC417,
|
||||
lime_green = 0x32CD32,
|
||||
pea_green = 0x52D017,
|
||||
kelly_green = 0x4CC552,
|
||||
zombie_green = 0x54C571,
|
||||
green_peas = 0x89C35C,
|
||||
dollar_bill_green = 0x85BB65,
|
||||
frog_green = 0x99C68E,
|
||||
turquoise_green = 0xA0D6B4,
|
||||
dark_sea_green = 0x8FBC8F,
|
||||
basil_green = 0x829F82,
|
||||
gray_green = 0xA2AD9C,
|
||||
iguana_green = 0x9CB071,
|
||||
citron_green = 0x8FB31D,
|
||||
acid_green = 0xB0BF1A,
|
||||
avocado_green = 0xB2C248,
|
||||
pistachio_green = 0x9DC209,
|
||||
salad_green = 0xA1C935,
|
||||
yellow_green = 0x9ACD32,
|
||||
pastel_green = 0x77DD77,
|
||||
hummingbird_green = 0x7FE817,
|
||||
nebula_green = 0x59E817,
|
||||
stoplight_go_green = 0x57E964,
|
||||
neon_green = 0x16F529,
|
||||
jade_green = 0x5EFB6E,
|
||||
lime_mint_green = 0x36F57F,
|
||||
spring_green = 0x00FF7F,
|
||||
medium_spring_green = 0x00FA9A,
|
||||
emerald_green = 0x5FFB17,
|
||||
lawn_green = 0x7CFC00,
|
||||
bright_green = 0x66FF00,
|
||||
chartreuse = 0x7FFF00,
|
||||
yellow_lawn_green = 0x87F717,
|
||||
aloe_vera_green = 0x98F516,
|
||||
dull_green_yellow = 0xB1FB17,
|
||||
lemon_green = 0xADF802,
|
||||
green_yellow = 0xADFF2F,
|
||||
chameleon_green = 0xBDF516,
|
||||
neon_yellow_green = 0xDAEE01,
|
||||
yellow_green_grosbeak = 0xE2F516,
|
||||
tea_green = 0xCCFB5D,
|
||||
slime_green = 0xBCE954,
|
||||
algae_green = 0x64E986,
|
||||
light_green = 0x90EE90,
|
||||
dragon_green = 0x6AFB92,
|
||||
pale_green = 0x98FB98,
|
||||
mint_green = 0x98FF98,
|
||||
green_thumb = 0xB5EAAA,
|
||||
organic_brown = 0xE3F9A6,
|
||||
light_jade = 0xC3FDB8,
|
||||
light_mint_green = 0xC2E5D3,
|
||||
light_rose_green = 0xDBF9DB,
|
||||
chrome_white = 0xE8F1D4,
|
||||
honeydew = 0xF0FFF0,
|
||||
mint_cream = 0xF5FFFA,
|
||||
lemon_chiffon = 0xFFFACD,
|
||||
parchment = 0xFFFFC2,
|
||||
cream = 0xFFFFCC,
|
||||
cream_white = 0xFFFDD0,
|
||||
light_goldenrod_yellow = 0xFAFAD2,
|
||||
light_yellow = 0xFFFFE0,
|
||||
beige = 0xF5F5DC,
|
||||
cornsilk = 0xFFF8DC,
|
||||
blonde = 0xFBF6D9,
|
||||
champagne = 0xF7E7CE,
|
||||
antique_white = 0xFAEBD7,
|
||||
papaya_whip = 0xFFEFD5,
|
||||
blanched_almond = 0xFFEBCD,
|
||||
bisque = 0xFFE4C4,
|
||||
wheat = 0xF5DEB3,
|
||||
moccasin = 0xFFE4B5,
|
||||
peach = 0xFFE5B4,
|
||||
light_orange = 0xFED8B1,
|
||||
peach_puff = 0xFFDAB9,
|
||||
coral_peach = 0xFBD5AB,
|
||||
navajo_white = 0xFFDEAD,
|
||||
golden_blonde = 0xFBE7A1,
|
||||
golden_silk = 0xF3E3C3,
|
||||
dark_blonde = 0xF0E2B6,
|
||||
light_gold = 0xF1E5AC,
|
||||
vanilla = 0xF3E5AB,
|
||||
tan_brown = 0xECE5B6,
|
||||
dirty_white = 0xE8E4C9,
|
||||
pale_goldenrod = 0xEEE8AA,
|
||||
khaki = 0xF0E68C,
|
||||
cardboard_brown = 0xEDDA74,
|
||||
harvest_gold = 0xEDE275,
|
||||
sun_yellow = 0xFFE87C,
|
||||
corn_yellow = 0xFFF380,
|
||||
pastel_yellow = 0xFAF884,
|
||||
neon_yellow = 0xFFFF33,
|
||||
canary_yellow = 0xFFEF00,
|
||||
banana_yellow = 0xF5E216,
|
||||
mustard_yellow = 0xFFDB58,
|
||||
golden_yellow = 0xFFDF00,
|
||||
bold_yellow = 0xF9DB24,
|
||||
rubber_ducky_yellow = 0xFFD801,
|
||||
gold = 0xFFD700,
|
||||
bright_gold = 0xFDD017,
|
||||
chrome_gold = 0xFFCE44,
|
||||
golden_brown = 0xEAC117,
|
||||
deep_yellow = 0xF6BE00,
|
||||
macaroni_and_cheese = 0xF2BB66,
|
||||
saffron = 0xFBB917,
|
||||
neon_gold = 0xFDBD01,
|
||||
beer = 0xFBB117,
|
||||
yellow_orange = 0xFFAE42,
|
||||
orange_yellow = 0xFFAE42,
|
||||
cantaloupe = 0xFFA62F,
|
||||
cheese_orange = 0xFFA600,
|
||||
brown_sand = 0xEE9A4D,
|
||||
sandy_brown = 0xF4A460,
|
||||
brown_sugar = 0xE2A76F,
|
||||
camel_brown = 0xC19A6B,
|
||||
deer_brown = 0xE6BF83,
|
||||
burly_wood = 0xDEB887,
|
||||
tan = 0xD2B48C,
|
||||
light_french_beige = 0xC8AD7F,
|
||||
sand = 0xC2B280,
|
||||
sage = 0xBCB88A,
|
||||
fall_leaf_brown = 0xC8B560,
|
||||
ginger_brown = 0xC9BE62,
|
||||
bronze_gold = 0xC9AE5D,
|
||||
dark_khaki = 0xBDB76B,
|
||||
olive_green = 0xBAB86C,
|
||||
brass = 0xB5A642,
|
||||
cookie_brown = 0xC7A317,
|
||||
metallic_gold = 0xD4AF37,
|
||||
bee_yellow = 0xE9AB17,
|
||||
school_bus_yellow = 0xE8A317,
|
||||
goldenrod = 0xDAA520,
|
||||
orange_gold = 0xD4A017,
|
||||
caramel = 0xC68E17,
|
||||
cinnamon = 0xC58917,
|
||||
peru = 0xCD853F,
|
||||
bronze = 0xCD7F32,
|
||||
tiger_orange = 0xC88141,
|
||||
copper = 0xB87333,
|
||||
dark_gold = 0xAA6C39,
|
||||
metallic_bronze = 0xA97142,
|
||||
dark_almond = 0xAB784E,
|
||||
wood = 0x966F33,
|
||||
oak_brown = 0x806517,
|
||||
antique_bronze = 0x665D1E,
|
||||
hazel = 0x8E7618,
|
||||
dark_yellow = 0x8B8000,
|
||||
dark_moccasin = 0x827839,
|
||||
khaki_green = 0x8A865D,
|
||||
millennium_jade = 0x93917C,
|
||||
dark_beige = 0x9F8C76,
|
||||
bullet_shell = 0xAF9B60,
|
||||
army_brown = 0x827B60,
|
||||
sandstone = 0x786D5F,
|
||||
taupe = 0x483C32,
|
||||
mocha = 0x493D26,
|
||||
milk_chocolate = 0x513B1C,
|
||||
gray_brown = 0x3D3635,
|
||||
dark_coffee = 0x3B2F2F,
|
||||
old_burgundy = 0x43302E,
|
||||
western_charcoal = 0x49413F,
|
||||
bakers_brown = 0x5C3317,
|
||||
dark_brown = 0x654321,
|
||||
sepia_brown = 0x704214,
|
||||
dark_bronze = 0x804A00,
|
||||
coffee = 0x6F4E37,
|
||||
brown_bear = 0x835C3B,
|
||||
red_dirt = 0x7F5217,
|
||||
sepia = 0x7F462C,
|
||||
sienna = 0xA0522D,
|
||||
saddle_brown = 0x8B4513,
|
||||
dark_sienna = 0x8A4117,
|
||||
sangria = 0x7E3817,
|
||||
blood_red = 0x7E3517,
|
||||
chestnut = 0x954535,
|
||||
coral_brown = 0x9E4638,
|
||||
chestnut_red = 0xC34A2C,
|
||||
mahogany = 0xC04000,
|
||||
red_gold = 0xEB5406,
|
||||
red_fox = 0xC35817,
|
||||
dark_bisque = 0xB86500,
|
||||
light_brown = 0xB5651D,
|
||||
petra_gold = 0xB76734,
|
||||
copper_red = 0xCB6D51,
|
||||
orange_salmon = 0xC47451,
|
||||
chocolate = 0xD2691E,
|
||||
sedona = 0xCC6600,
|
||||
papaya_orange = 0xE56717,
|
||||
halloween_orange = 0xE66C2C,
|
||||
neon_orange = 0xFF6700,
|
||||
bright_orange = 0xFF5F1F,
|
||||
pumpkin_orange = 0xF87217,
|
||||
carrot_orange = 0xF88017,
|
||||
dark_orange = 0xFF8C00,
|
||||
construction_cone_orange = 0xF87431,
|
||||
indian_saffron = 0xFF7722,
|
||||
sunrise_orange = 0xE67451,
|
||||
mango_orange = 0xFF8040,
|
||||
coral = 0xFF7F50,
|
||||
basket_ball_orange = 0xF88158,
|
||||
light_salmon_rose = 0xF9966B,
|
||||
light_salmon = 0xFFA07A,
|
||||
dark_salmon = 0xE9967A,
|
||||
tangerine = 0xE78A61,
|
||||
light_copper = 0xDA8A67,
|
||||
salmon_pink = 0xFF8674,
|
||||
salmon = 0xFA8072,
|
||||
peach_pink = 0xF98B88,
|
||||
light_coral = 0xF08080,
|
||||
pastel_red = 0xF67280,
|
||||
pink_coral = 0xE77471,
|
||||
bean_red = 0xF75D59,
|
||||
valentine_red = 0xE55451,
|
||||
indian_red = 0xCD5C5C,
|
||||
tomato = 0xFF6347,
|
||||
shocking_orange = 0xE55B3C,
|
||||
orange_red = 0xFF4500,
|
||||
neon_red = 0xFD1C03,
|
||||
ruby_red = 0xF62217,
|
||||
ferrari_red = 0xF70D1A,
|
||||
fire_engine_red = 0xF62817,
|
||||
lava_red = 0xE42217,
|
||||
love_red = 0xE41B17,
|
||||
grapefruit = 0xDC381F,
|
||||
cherry_red = 0xC24641,
|
||||
chilli_pepper = 0xC11B17,
|
||||
fire_brick = 0xB22222,
|
||||
tomato_sauce_red = 0xB21807,
|
||||
carbon_red = 0xA70D2A,
|
||||
cranberry = 0x9F000F,
|
||||
saffron_red = 0x931314,
|
||||
crimson_red = 0x990000,
|
||||
red_wine = 0x990012,
|
||||
wine_red = 0x990012,
|
||||
dark_red = 0x8B0000,
|
||||
maroon = 0x800000,
|
||||
burgundy = 0x8C001A,
|
||||
vermilion = 0x7E191B,
|
||||
deep_red = 0x800517,
|
||||
red_blood = 0x660000,
|
||||
blood_night = 0x551606,
|
||||
dark_scarlet = 0x560319,
|
||||
black_bean = 0x3D0C02,
|
||||
chocolate_brown = 0x3F000F,
|
||||
midnight = 0x2B1B17,
|
||||
purple_lily = 0x550A35,
|
||||
purple_maroon = 0x810541,
|
||||
plum_pie = 0x7D0541,
|
||||
plum_velvet = 0x7D0552,
|
||||
dark_raspberry = 0x872657,
|
||||
velvet_maroon = 0x7E354D,
|
||||
rosy_finch = 0x7F4E52,
|
||||
dull_purple = 0x7F525D,
|
||||
puce = 0x7F5A58,
|
||||
rose_dust = 0x997070,
|
||||
pastel_brown = 0xB1907F,
|
||||
rosy_pink = 0xB38481,
|
||||
rosy_brown = 0xBC8F8F,
|
||||
khaki_rose = 0xC5908E,
|
||||
lipstick_pink = 0xC48793,
|
||||
pink_brown = 0xC48189,
|
||||
old_rose = 0xC08081,
|
||||
dusty_pink = 0xD58A94,
|
||||
pink_daisy = 0xE799A3,
|
||||
rose = 0xE8ADAA,
|
||||
dusty_rose = 0xC9A9A6,
|
||||
silver_pink = 0xC4AEAD,
|
||||
gold_pink = 0xE6C7C2,
|
||||
rose_gold = 0xECC5C0,
|
||||
deep_peach = 0xFFCBA4,
|
||||
pastel_orange = 0xF8B88B,
|
||||
desert_sand = 0xEDC9AF,
|
||||
unbleached_silk = 0xFFDDCA,
|
||||
pig_pink = 0xFDD7E4,
|
||||
pale_pink = 0xF2D4D7,
|
||||
blush = 0xFFE6E8,
|
||||
misty_rose = 0xFFE4E1,
|
||||
pink_bubble_gum = 0xFFDFDD,
|
||||
light_rose = 0xFBCFCD,
|
||||
light_red = 0xFFCCCB,
|
||||
warm_pink = 0xF6C6BD,
|
||||
deep_rose = 0xFBBBB9,
|
||||
light_pink = 0xFFB6C1,
|
||||
soft_pink = 0xFFB8BF,
|
||||
donut_pink = 0xFAAFBE,
|
||||
baby_pink = 0xFAAFBA,
|
||||
flamingo_pink = 0xF9A7B0,
|
||||
pastel_pink = 0xFEA3AA,
|
||||
rose_pink = 0xE7A1B0,
|
||||
pink_rose = 0xE7A1B0,
|
||||
cadillac_pink = 0xE38AAE,
|
||||
carnation_pink = 0xF778A1,
|
||||
pastel_rose = 0xE5788F,
|
||||
blush_red = 0xE56E94,
|
||||
pale_violet_red = 0xDB7093,
|
||||
purple_pink = 0xD16587,
|
||||
tulip_pink = 0xC25A7C,
|
||||
bashful_pink = 0xC25283,
|
||||
dark_pink = 0xE75480,
|
||||
dark_hot_pink = 0xF660AB,
|
||||
hot_pink = 0xFF69B4,
|
||||
watermelon_pink = 0xFC6C85,
|
||||
violet_red = 0xF6358A,
|
||||
hot_deep_pink = 0xF52887,
|
||||
bright_pink = 0xFF007F,
|
||||
deep_pink = 0xFF1493,
|
||||
neon_pink = 0xF535AA,
|
||||
chrome_pink = 0xFF33AA,
|
||||
neon_hot_pink = 0xFD349C,
|
||||
pink_cupcake = 0xE45E9D,
|
||||
royal_pink = 0xE759AC,
|
||||
dimorphotheca_magenta = 0xE3319D,
|
||||
pink_lemonade = 0xE4287C,
|
||||
red_pink = 0xFA2A55,
|
||||
crimson = 0xDC143C,
|
||||
bright_maroon = 0xC32148,
|
||||
rose_red = 0xC21E56,
|
||||
rogue_pink = 0xC12869,
|
||||
burnt_pink = 0xC12267,
|
||||
pink_violet = 0xCA226B,
|
||||
magenta_pink = 0xCC338B,
|
||||
medium_violet_red = 0xC71585,
|
||||
dark_carnation_pink = 0xC12283,
|
||||
raspberry_purple = 0xB3446C,
|
||||
pink_plum = 0xB93B8F,
|
||||
orchid = 0xDA70D6,
|
||||
deep_mauve = 0xDF73D4,
|
||||
violet = 0xEE82EE,
|
||||
fuchsia_pink = 0xFF77FF,
|
||||
bright_neon_pink = 0xF433FF,
|
||||
fuchsia = 0xFF00FF,
|
||||
crimson_purple = 0xE238EC,
|
||||
heliotrope_purple = 0xD462FF,
|
||||
tyrian_purple = 0xC45AEC,
|
||||
medium_orchid = 0xBA55D3,
|
||||
purple_flower = 0xA74AC7,
|
||||
orchid_purple = 0xB048B5,
|
||||
rich_lilac = 0xB666D2,
|
||||
pastel_violet = 0xD291BC,
|
||||
mauve_taupe = 0x915F6D,
|
||||
viola_purple = 0x7E587E,
|
||||
eggplant = 0x614051,
|
||||
plum_purple = 0x583759,
|
||||
grape = 0x5E5A80,
|
||||
purple_navy = 0x4E5180,
|
||||
slate_blue = 0x6A5ACD,
|
||||
blue_lotus = 0x6960EC,
|
||||
blurple = 0x5865F2,
|
||||
light_slate_blue = 0x736AFF,
|
||||
medium_slate_blue = 0x7B68EE,
|
||||
periwinkle_purple = 0x7575CF,
|
||||
very_peri = 0x6667AB,
|
||||
bright_grape = 0x6F2DA8,
|
||||
purple_amethyst = 0x6C2DC7,
|
||||
bright_purple = 0x6A0DAD,
|
||||
deep_periwinkle = 0x5453A6,
|
||||
dark_slate_blue = 0x483D8B,
|
||||
purple_haze = 0x4E387E,
|
||||
purple_iris = 0x571B7E,
|
||||
dark_purple = 0x4B0150,
|
||||
deep_purple = 0x36013F,
|
||||
midnight_purple = 0x2E1A47,
|
||||
purple_monster = 0x461B7E,
|
||||
indigo = 0x4B0082,
|
||||
blue_whale = 0x342D7E,
|
||||
rebecca_purple = 0x663399,
|
||||
purple_jam = 0x6A287E,
|
||||
dark_magenta = 0x8B008B,
|
||||
purple = 0x800080,
|
||||
french_lilac = 0x86608E,
|
||||
dark_orchid = 0x9932CC,
|
||||
dark_violet = 0x9400D3,
|
||||
purple_violet = 0x8D38C9,
|
||||
jasmine_purple = 0xA23BEC,
|
||||
purple_daffodil = 0xB041FF,
|
||||
clematis_violet = 0x842DCE,
|
||||
blue_violet = 0x8A2BE2,
|
||||
purple_sage_bush = 0x7A5DC7,
|
||||
lovely_purple = 0x7F38EC,
|
||||
neon_purple = 0x9D00FF,
|
||||
purple_plum = 0x8E35EF,
|
||||
aztech_purple = 0x893BFF,
|
||||
medium_purple = 0x9370DB,
|
||||
light_purple = 0x8467D7,
|
||||
crocus_purple = 0x9172EC,
|
||||
purple_mimosa = 0x9E7BFF,
|
||||
periwinkle = 0xCCCCFF,
|
||||
pale_lilac = 0xDCD0FF,
|
||||
lavender_purple = 0x967BB6,
|
||||
rose_purple = 0xB09FCA,
|
||||
lilac = 0xC8A2C8,
|
||||
mauve = 0xE0B0FF,
|
||||
bright_lilac = 0xD891EF,
|
||||
purple_dragon = 0xC38EC7,
|
||||
plum = 0xDDA0DD,
|
||||
blush_pink = 0xE6A9EC,
|
||||
pastel_purple = 0xF2A2E8,
|
||||
blossom_pink = 0xF9B7FF,
|
||||
wisteria_purple = 0xC6AEC7,
|
||||
purple_thistle = 0xD2B9D3,
|
||||
thistle = 0xD8BFD8,
|
||||
purple_white = 0xDFD3E3,
|
||||
periwinkle_pink = 0xE9CFEC,
|
||||
cotton_candy = 0xFCDFFF,
|
||||
lavender_pinocchio = 0xEBDDE2,
|
||||
dark_white = 0xE1D9D1,
|
||||
ash_white = 0xE9E4D4,
|
||||
white_chocolate = 0xEDE6D6,
|
||||
soft_ivory = 0xFAF0DD,
|
||||
off_white = 0xF8F0E3,
|
||||
pearl_white = 0xF8F6F0,
|
||||
red_white = 0xF3E8EA,
|
||||
lavender_blush = 0xFFF0F5,
|
||||
pearl = 0xFDEEF4,
|
||||
egg_shell = 0xFFF9E3,
|
||||
old_lace = 0xFEF0E3,
|
||||
linen = 0xFAF0E6,
|
||||
sea_shell = 0xFFF5EE,
|
||||
bone_white = 0xF9F6EE,
|
||||
rice = 0xFAF5EF,
|
||||
floral_white = 0xFFFAF0,
|
||||
ivory = 0xFFFFF0,
|
||||
white_gold = 0xFFFFF4,
|
||||
light_white = 0xFFFFF7,
|
||||
white_smoke = 0xF5F5F5,
|
||||
cotton = 0xFBFBF9,
|
||||
snow = 0xFFFAFA,
|
||||
milk_white = 0xFEFCFF,
|
||||
half_white = 0xFFFEFA;
|
||||
} // namespace colors
|
||||
|
||||
/**
|
||||
* @brief Predefined colour constants, same as colors but for the british.
|
||||
*/
|
||||
namespace colours = colors;
|
||||
} // namespace dpp
|
||||
@ -1,428 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/misc-enum.h>
|
||||
#include <dpp/user.h>
|
||||
#include <dpp/guild.h>
|
||||
#include <dpp/role.h>
|
||||
#include <dpp/appcommand.h>
|
||||
#include <dpp/dispatcher.h>
|
||||
#include <dpp/utility.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/event_router.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <variant>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief dpp::resolved_user contains both a dpp::guild_member and a dpp::user.
|
||||
* The user can be used to obtain in-depth user details such as if they are nitro,
|
||||
* and the guild member information to check their roles on a guild etc.
|
||||
* The Discord API provides both if a parameter is a user ping,
|
||||
* so we offer both in a combined structure.
|
||||
*/
|
||||
struct DPP_EXPORT resolved_user {
|
||||
/**
|
||||
* @brief Holds user information
|
||||
*/
|
||||
dpp::user user;
|
||||
|
||||
/**
|
||||
* @brief Holds member information
|
||||
*/
|
||||
dpp::guild_member member;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a received parameter.
|
||||
* We use variant so that multiple non-related types can be contained within.
|
||||
*/
|
||||
typedef std::variant<std::monostate, std::string, dpp::role, dpp::channel, dpp::resolved_user, int64_t, bool, double> command_parameter;
|
||||
|
||||
/**
|
||||
* @brief Parameter types when registering a command.
|
||||
* We don't pass these in when triggering the command in the handler, because it is
|
||||
* expected the developer added the command so they know what types to expect for each named
|
||||
* parameter.
|
||||
*/
|
||||
enum parameter_type {
|
||||
/**
|
||||
* @brief String parameter.
|
||||
*/
|
||||
pt_string,
|
||||
|
||||
/**
|
||||
* @brief Role object parameter.
|
||||
*/
|
||||
pt_role,
|
||||
|
||||
/**
|
||||
* @brief Channel object parameter.
|
||||
*/
|
||||
pt_channel,
|
||||
|
||||
/**
|
||||
* @brief User object parameter.
|
||||
*/
|
||||
pt_user,
|
||||
|
||||
/**
|
||||
* @brief 64 bit signed integer parameter.
|
||||
*/
|
||||
pt_integer,
|
||||
|
||||
/**
|
||||
* @brief double floating point parameter.
|
||||
*/
|
||||
pt_double,
|
||||
|
||||
/**
|
||||
* @brief Boolean parameter.
|
||||
*/
|
||||
pt_boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Details of a command parameter used in registration.
|
||||
* Note that for non-slash commands optional parameters can only be at the end of
|
||||
* the list of parameters.
|
||||
*/
|
||||
struct DPP_EXPORT param_info {
|
||||
/**
|
||||
* @brief Type of parameter
|
||||
*/
|
||||
parameter_type type;
|
||||
|
||||
/**
|
||||
* @brief True if the parameter is optional.
|
||||
* For non-slash commands optional parameters may only be on the end of the list.
|
||||
*/
|
||||
bool optional;
|
||||
|
||||
/**
|
||||
* @brief Description of command. Displayed only for slash commands
|
||||
*/
|
||||
std::string description;
|
||||
|
||||
/**
|
||||
* @brief Allowed multiple choice options.
|
||||
* The key name is the string passed to the command handler
|
||||
* and the key value is its description displayed to the user.
|
||||
*/
|
||||
std::map<command_value, std::string> choices;
|
||||
|
||||
/**
|
||||
* @brief Construct a new param_info object
|
||||
*
|
||||
* @param t Type of parameter
|
||||
* @param o True if parameter is optional
|
||||
* @param description The parameter description
|
||||
* @param opts The options for a multiple choice parameter
|
||||
*/
|
||||
param_info(parameter_type t, bool o, const std::string &description, const std::map<command_value, std::string> &opts = {});
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Parameter list used during registration.
|
||||
* Note that use of vector/pair is important here to preserve parameter order,
|
||||
* as opposed to unordered_map (which doesn't guarantee any order at all) and
|
||||
* std::map, which reorders keys alphabetically.
|
||||
*/
|
||||
typedef std::vector<std::pair<std::string, param_info>> parameter_registration_t;
|
||||
|
||||
/**
|
||||
* @brief Parameter list for a called command.
|
||||
* See dpp::parameter_registration_t for an explanation as to why vector is used.
|
||||
*/
|
||||
typedef std::vector<std::pair<std::string, command_parameter>> parameter_list_t;
|
||||
|
||||
/**
|
||||
* @brief Represents the sending source of a command.
|
||||
* This is passed to any command handler and should be passed back to
|
||||
* commandhandler::reply(), allowing the reply method to route any replies back
|
||||
* to the origin, which may be a slash command or a message. Both require different
|
||||
* response facilities but we want this to be transparent if you use the command
|
||||
* handler class.
|
||||
* @deprecated commandhandler and message commands are deprecated and dpp::slashcommand is encouraged as a replacement.
|
||||
*/
|
||||
struct DPP_EXPORT command_source {
|
||||
/**
|
||||
* @brief Sending guild id
|
||||
*/
|
||||
snowflake guild_id;
|
||||
|
||||
/**
|
||||
* @brief Source channel id
|
||||
*/
|
||||
snowflake channel_id;
|
||||
|
||||
/**
|
||||
* @brief Command ID of a slash command
|
||||
*/
|
||||
snowflake command_id;
|
||||
|
||||
/**
|
||||
* @brief Token for sending a slash command reply
|
||||
*/
|
||||
std::string command_token;
|
||||
|
||||
/**
|
||||
* @brief The user who issued the command
|
||||
*/
|
||||
user issuer;
|
||||
|
||||
/**
|
||||
* @brief Copy of the underlying message_create_t event, if it was a message create event
|
||||
*/
|
||||
std::optional<message_create_t> message_event;
|
||||
|
||||
/**
|
||||
* @brief Copy of the underlying interaction_create_t event, if it was an interaction create event
|
||||
*/
|
||||
std::optional<interaction_create_t> interaction_event;
|
||||
|
||||
/**
|
||||
* @brief Construct a command_source object from a message_create_t event
|
||||
*/
|
||||
command_source(const struct message_create_t& event);
|
||||
|
||||
/**
|
||||
* @brief Construct a command_source object from an interaction_create_t event
|
||||
*/
|
||||
command_source(const struct interaction_create_t& event);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The function definition for a command handler. Expects a command name string,
|
||||
* and a list of command parameters.
|
||||
* @deprecated commandhandler and message commands are deprecated and dpp::slashcommand is encouraged as a replacement.
|
||||
*/
|
||||
typedef std::function<void(const std::string&, const parameter_list_t&, command_source)> command_handler;
|
||||
|
||||
/**
|
||||
* @brief Represents the details of a command added to the command handler class.
|
||||
* @deprecated commandhandler and message commands are deprecated and dpp::slashcommand is encouraged as a replacement.
|
||||
*/
|
||||
struct DPP_EXPORT command_info_t {
|
||||
/**
|
||||
* @brief Function reference for the handler. This is std::function so it can represent
|
||||
* a class member, a lambda or a raw C function pointer.
|
||||
*/
|
||||
command_handler func;
|
||||
|
||||
/**
|
||||
* @brief Parameters requested for the command, with their types
|
||||
*/
|
||||
parameter_registration_t parameters;
|
||||
|
||||
/**
|
||||
* @brief Guild ID the command exists on, or 0 to be present on all guilds
|
||||
*/
|
||||
snowflake guild_id;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief The commandhandler class represents a group of commands, prefixed or slash commands with handling functions.
|
||||
*
|
||||
* It can automatically register slash commands, and handle routing of messages and interactions to separated command handler
|
||||
* functions.
|
||||
* @deprecated commandhandler and message commands are deprecated and dpp::slashcommand is encouraged as a replacement.
|
||||
*/
|
||||
class DPP_EXPORT DPP_DEPRECATED("commandhandler should not be used. Please consider using dpp::cluster::register_command instead.") commandhandler {
|
||||
private:
|
||||
/**
|
||||
* @brief List of guild commands to bulk register
|
||||
*/
|
||||
std::map<dpp::snowflake, std::vector<dpp::slashcommand>> bulk_registration_list_guild;
|
||||
|
||||
/**
|
||||
* @brief List of global commands to bulk register
|
||||
*/
|
||||
std::vector<dpp::slashcommand> bulk_registration_list_global;
|
||||
public:
|
||||
/**
|
||||
* @brief Commands in the handler
|
||||
*/
|
||||
std::unordered_map<std::string, command_info_t> commands;
|
||||
|
||||
/**
|
||||
* @brief Valid prefixes
|
||||
*/
|
||||
std::vector<std::string> prefixes;
|
||||
|
||||
/**
|
||||
* @brief Set to true automatically if one of the prefixes added is "/"
|
||||
*/
|
||||
bool slash_commands_enabled;
|
||||
|
||||
/**
|
||||
* @brief Cluster we are attached to for issuing REST calls
|
||||
*/
|
||||
class cluster* owner;
|
||||
|
||||
/**
|
||||
* @brief Application ID
|
||||
*/
|
||||
snowflake app_id;
|
||||
|
||||
/**
|
||||
* @brief Interaction event handle
|
||||
*/
|
||||
event_handle interactions;
|
||||
|
||||
/**
|
||||
* @brief Message event handle
|
||||
*/
|
||||
event_handle messages;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the string has a known prefix on the start.
|
||||
* Modifies string to remove prefix if it returns true.
|
||||
*
|
||||
* @param str String to check and modify
|
||||
* @return true string contained a prefix, prefix removed from string
|
||||
* @return false string did not contain a prefix
|
||||
*/
|
||||
bool string_has_prefix(std::string &str);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Construct a new commandhandler object
|
||||
*
|
||||
* @param o Owning cluster to attach to
|
||||
* @param auto_hook_events Set to true to automatically hook the on_slashcommand
|
||||
* and on_message events. You should not need to set this to false unless you have a specific
|
||||
* use case, as D++ supports multiple listeners to an event, so will allow the commandhandler
|
||||
* to hook to your command events without disrupting other uses for the events you may have.
|
||||
* @param application_id The application id of the bot. If not specified, the class will
|
||||
* look within the cluster object and use cluster::me::id instead.
|
||||
*/
|
||||
commandhandler(class cluster* o, bool auto_hook_events = true, snowflake application_id = 0);
|
||||
|
||||
/**
|
||||
* @brief Destroy the commandhandler object
|
||||
*/
|
||||
~commandhandler();
|
||||
|
||||
/**
|
||||
* @brief Set the application id after construction
|
||||
*
|
||||
* @param o Owning cluster to attach to
|
||||
*/
|
||||
commandhandler& set_owner(class cluster* o);
|
||||
|
||||
/**
|
||||
* @brief Add a prefix to the command handler
|
||||
*
|
||||
* @param prefix Prefix to be handled by the command handler
|
||||
* @return commandhandler& reference to self
|
||||
*/
|
||||
commandhandler& add_prefix(const std::string &prefix);
|
||||
|
||||
/**
|
||||
* @brief Add a command to the command handler
|
||||
*
|
||||
* @param command Command to be handled.
|
||||
* Note that if any one of your prefixes is "/" this will attempt to register
|
||||
* a global command using the API and you will receive notification of this command
|
||||
* via an interaction event.
|
||||
* @param handler Handler function
|
||||
* @param parameters Parameters to use for the command
|
||||
* @param description The description of the command, shown for slash commands
|
||||
* @param guild_id The guild ID to restrict the command to. For slash commands causes registration of a guild command as opposed to a global command.
|
||||
* @return commandhandler& reference to self
|
||||
* @throw dpp::logic_exception if application ID cannot be determined
|
||||
*/
|
||||
commandhandler& add_command(const std::string &command, const parameter_registration_t ¶meters, command_handler handler, const std::string &description = "", snowflake guild_id = 0);
|
||||
|
||||
/**
|
||||
* @brief Register all slash commands with Discord
|
||||
* This method must be called at least once if you are using the "/" prefix to mark the
|
||||
* end of commands being added to the handler. Note that this uses bulk registration and will replace any
|
||||
* existing slash commands.
|
||||
*
|
||||
* Note that if you have previously registered your commands and they have not changed, you do
|
||||
* not need to call this again. Discord retains a cache of previously added commands.
|
||||
*
|
||||
* @return commandhandler& Reference to self for chaining method calls
|
||||
*/
|
||||
commandhandler& register_commands();
|
||||
|
||||
/**
|
||||
* @brief Route a command from the on_message_create function.
|
||||
* Call this method from within your on_message_create with the received
|
||||
* dpp::message object if you have disabled automatic registration of events.
|
||||
*
|
||||
* @param event message create event to parse
|
||||
*/
|
||||
void route(const struct dpp::message_create_t& event);
|
||||
|
||||
/**
|
||||
* @brief Route a command from the on_slashcommand function.
|
||||
* Call this method from your on_slashcommand with the received
|
||||
* dpp::interaction_create_t object if you have disabled automatic registration of events.
|
||||
*
|
||||
* @param event command interaction event to parse
|
||||
*/
|
||||
void route(const struct slashcommand_t & event);
|
||||
|
||||
/**
|
||||
* @brief Reply to a command.
|
||||
* You should use this method rather than cluster::message_create as
|
||||
* the way you reply varies between slash commands and message commands.
|
||||
* Note you should ALWAYS reply. Slash commands will emit an ugly error
|
||||
* to the user if you do not emit some form of reply within 3 seconds.
|
||||
*
|
||||
* @param m message to reply with.
|
||||
* @param source source of the command
|
||||
* @param callback User function to execute when the api call completes.
|
||||
*/
|
||||
void reply(const dpp::message &m, command_source source, command_completion_event_t callback = utility::log_error());
|
||||
|
||||
/**
|
||||
* @brief Reply to a command without a message, causing the discord client
|
||||
* to display "Bot name is thinking...".
|
||||
* The "thinking" message will persist for a maximum of 15 minutes.
|
||||
* This counts as a reply for a slash command. Slash commands will emit an
|
||||
* ugly error to the user if you do not emit some form of reply within 3
|
||||
* seconds.
|
||||
*
|
||||
* @param source source of the command
|
||||
* @param callback User function to execute when the api call completes.
|
||||
*/
|
||||
void thinking(command_source source, command_completion_event_t callback = utility::log_error());
|
||||
|
||||
/**
|
||||
* @brief Easter egg (redefinition of dpp::commandhandler::thinking).
|
||||
*/
|
||||
void thonk(command_source source, command_completion_event_t callback = utility::log_error());
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
29
dpp/coro.h
29
dpp/coro.h
@ -1,29 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2022 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "coro/awaitable.h"
|
||||
#include "coro/async.h"
|
||||
#include "coro/coroutine.h"
|
||||
#include "coro/job.h"
|
||||
#include "coro/task.h"
|
||||
#include "coro/when_any.h"
|
||||
189
dpp/coro/async.h
189
dpp/coro/async.h
@ -1,189 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2022 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <dpp/utility.h>
|
||||
|
||||
#include <dpp/coro/awaitable.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
struct async_dummy : awaitable_dummy {
|
||||
std::shared_ptr<int> dummy_shared_state = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef DPP_NO_CORO
|
||||
|
||||
#include "coro.h"
|
||||
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <functional>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
namespace async {
|
||||
|
||||
/**
|
||||
* @brief Shared state of the async and its callback, to be used across threads.
|
||||
*/
|
||||
template <typename R>
|
||||
struct callback {
|
||||
/**
|
||||
* @brief Promise object to set the result into
|
||||
*/
|
||||
std::shared_ptr<basic_promise<R>> promise{nullptr};
|
||||
|
||||
/**
|
||||
* @brief Call operator, sets the value in the promise and notifies any awaiter
|
||||
*
|
||||
* @param v Callback value
|
||||
*/
|
||||
template <typename U = R>
|
||||
void operator()(const U& v) const requires (std::convertible_to<const U&, R>) {
|
||||
promise->set_value(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call operator, sets the value in the promise and notifies any awaiter
|
||||
*
|
||||
* @param v Callback value
|
||||
*/
|
||||
template <typename U = R>
|
||||
void operator()(U&& v) const requires (std::convertible_to<U&&, R>) {
|
||||
promise->set_value(std::move(v));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call operator, sets the value in the promise and notifies any awaiter
|
||||
*/
|
||||
void operator()() const requires (std::is_void_v<R>)
|
||||
{
|
||||
promise->set_value();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace async
|
||||
|
||||
} // namespace detail
|
||||
|
||||
struct confirmation_callback_t;
|
||||
|
||||
/**
|
||||
* @class async async.h coro/async.h
|
||||
* @brief A co_await-able object handling an API call in parallel with the caller.
|
||||
*
|
||||
* This class is the return type of the dpp::cluster::co_* methods, but it can also be created manually to wrap any async call.
|
||||
*
|
||||
* @remark - The coroutine may be resumed in another thread, do not rely on thread_local variables.
|
||||
* @warning - This feature is EXPERIMENTAL. The API may change at any time and there may be bugs. Please report any to <a href="https://github.com/brainboxdotcc/DPP/issues">GitHub issues</a> or to the <a href="https://discord.gg/dpp">D++ Discord server</a>.
|
||||
* @tparam R The return type of the API call. Defaults to confirmation_callback_t
|
||||
*/
|
||||
template <typename R>
|
||||
class async : public awaitable<R> {
|
||||
/**
|
||||
* @brief Callable object to pass to API calls
|
||||
*/
|
||||
detail::async::callback<R> api_callback{};
|
||||
|
||||
/**
|
||||
* @brief Internal promise constructor, grabs a promise object for the callback to use
|
||||
*/
|
||||
explicit async(std::shared_ptr<basic_promise<R>> &&promise) : awaitable<R>{promise.get()}, api_callback{std::move(promise)} {}
|
||||
|
||||
public:
|
||||
using awaitable<R>::awaitable; // use awaitable's constructors
|
||||
using awaitable<R>::operator=; // use async_base's assignment operator
|
||||
using awaitable<R>::await_ready; // expose await_ready as public
|
||||
|
||||
/**
|
||||
* @brief The return type of the API call. Defaults to confirmation_callback_t
|
||||
*/
|
||||
using result_type = R;
|
||||
|
||||
/**
|
||||
* @brief Construct an async object wrapping an object method, the call is made immediately by forwarding to <a href="https://en.cppreference.com/w/cpp/utility/functional/invoke">std::invoke</a> and can be awaited later to retrieve the result.
|
||||
*
|
||||
* @param obj The object to call the method on
|
||||
* @param fun The method of the object to call. Its last parameter must be a callback taking a parameter of type R
|
||||
* @param args Parameters to pass to the method, excluding the callback
|
||||
*/
|
||||
template <typename Obj, typename Fun, typename... Args>
|
||||
#ifndef _DOXYGEN_
|
||||
requires std::invocable<Fun, Obj, Args..., std::function<void(R)>>
|
||||
#endif
|
||||
explicit async(Obj &&obj, Fun &&fun, Args&&... args) : async{std::make_shared<basic_promise<R>>()} {
|
||||
std::invoke(std::forward<Fun>(fun), std::forward<Obj>(obj), std::forward<Args>(args)..., api_callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct an async object wrapping an invokeable object, the call is made immediately by forwarding to <a href="https://en.cppreference.com/w/cpp/utility/functional/invoke">std::invoke</a> and can be awaited later to retrieve the result.
|
||||
*
|
||||
* @param fun The object to call using <a href="https://en.cppreference.com/w/cpp/utility/functional/invoke">std::invoke</a>. Its last parameter must be a callable taking a parameter of type R
|
||||
* @param args Parameters to pass to the object, excluding the callback
|
||||
*/
|
||||
template <typename Fun, typename... Args>
|
||||
#ifndef _DOXYGEN_
|
||||
requires std::invocable<Fun, Args..., std::function<void(R)>>
|
||||
#endif
|
||||
explicit async(Fun &&fun, Args&&... args) : async{std::make_shared<basic_promise<R>>()} {
|
||||
std::invoke(std::forward<Fun>(fun), std::forward<Args>(args)..., api_callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy constructor is disabled.
|
||||
*/
|
||||
async(const async&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor, moves the awaitable async object
|
||||
*/
|
||||
async(async&&) = default;
|
||||
|
||||
/**
|
||||
* @brief Copy assignment operator is disabled.
|
||||
*/
|
||||
async& operator=(const async&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator, moves the awaitable async object
|
||||
*/
|
||||
async& operator=(async&&) = default;
|
||||
|
||||
/**
|
||||
* @brief Destructor, signals to the callback that the async object is gone and shouldn't be notified of the result
|
||||
*/
|
||||
~async() {
|
||||
this->abandon();
|
||||
}
|
||||
};
|
||||
|
||||
DPP_CHECK_ABI_COMPAT(async<>, async_dummy);
|
||||
|
||||
}
|
||||
|
||||
#endif /* DPP_NO_CORO */
|
||||
@ -1,735 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2022 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <dpp/utility.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
struct awaitable_dummy {
|
||||
int *promise_dummy = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef DPP_NO_CORO
|
||||
|
||||
#include <dpp/coro/coro.h>
|
||||
|
||||
// Do not include <coroutine> as coro.h includes <experimental/coroutine> or <coroutine> depending on clang version
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <exception>
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <cstdint>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
namespace detail::promise {
|
||||
|
||||
/**
|
||||
* @brief State of a promise
|
||||
*/
|
||||
enum state_flags {
|
||||
/**
|
||||
* @brief Promise is empty
|
||||
*/
|
||||
sf_none = 0b0000000,
|
||||
|
||||
/**
|
||||
* @brief Promise has spawned an awaitable
|
||||
*/
|
||||
sf_has_awaitable = 0b00000001,
|
||||
|
||||
/**
|
||||
* @brief Promise is being awaited
|
||||
*/
|
||||
sf_awaited = 0b00000010,
|
||||
|
||||
/**
|
||||
* @brief Promise has a result
|
||||
*/
|
||||
sf_ready = 0b00000100,
|
||||
|
||||
/**
|
||||
* @brief Promise has completed, no more results are expected
|
||||
*/
|
||||
sf_done = 0b00001000,
|
||||
|
||||
/**
|
||||
* @brief Promise was broken - future or promise is gone
|
||||
*/
|
||||
sf_broken = 0b0010000
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class promise_base;
|
||||
|
||||
/**
|
||||
* @brief Empty result from void-returning awaitable
|
||||
*/
|
||||
struct empty{};
|
||||
|
||||
/**
|
||||
* @brief Variant for the 3 conceptual values of a coroutine:
|
||||
*/
|
||||
template <typename T>
|
||||
using result_t = std::variant<std::monostate, std::conditional_t<std::is_void_v<T>, empty, T>, std::exception_ptr>;
|
||||
|
||||
template <typename T>
|
||||
void spawn_sync_wait_job(auto* awaitable, std::condition_variable &cv, auto&& result);
|
||||
|
||||
} /* namespace detail::promise */
|
||||
|
||||
template <typename Derived>
|
||||
class basic_awaitable {
|
||||
protected:
|
||||
/**
|
||||
* @brief Implementation for sync_wait. This is code used by sync_wait, sync_wait_for, sync_wait_until.
|
||||
*
|
||||
* @tparam Timed Whether the wait function times out or not
|
||||
* @param do_wait Function to do the actual wait on the cv
|
||||
* @return If T is void, returns a boolean for which true means the awaitable completed, false means it timed out.
|
||||
* @return If T is non-void, returns a std::optional<T> for which an absence of value means timed out.
|
||||
*/
|
||||
template <bool Timed>
|
||||
auto sync_wait_impl(auto&& do_wait) {
|
||||
using result_type = decltype(detail::co_await_resolve(std::declval<Derived>()).await_resume());
|
||||
using variant_type = detail::promise::result_t<result_type>;
|
||||
variant_type result;
|
||||
std::condition_variable cv;
|
||||
|
||||
detail::promise::spawn_sync_wait_job<result_type>(static_cast<Derived*>(this), cv, result);
|
||||
do_wait(cv, result);
|
||||
/*
|
||||
* Note: we use .index() here to support dpp::promise<std::exception_ptr> & dpp::promise<std::monostate> :D
|
||||
*/
|
||||
if (result.index() == 2) {
|
||||
std::rethrow_exception(std::get<2>(result));
|
||||
}
|
||||
if constexpr (!Timed) { // no timeout
|
||||
if constexpr (!std::is_void_v<result_type>) {
|
||||
return std::get<1>(result);
|
||||
}
|
||||
} else { // timeout
|
||||
if constexpr (std::is_void_v<result_type>) {
|
||||
return result.index() == 1 ? true : false;
|
||||
} else {
|
||||
return result.index() == 1 ? std::optional<result_type>{std::get<1>(result)} : std::nullopt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Blocks this thread and waits for the awaitable to finish.
|
||||
*
|
||||
* @attention This will BLOCK THE THREAD. It is likely you want to use co_await instead.
|
||||
* @return If T is void, returns a boolean for which true means the awaitable completed, false means it timed out.
|
||||
* @return If T is non-void, returns a std::optional<T> for which an absence of value means timed out.
|
||||
*/
|
||||
auto sync_wait() {
|
||||
return sync_wait_impl<false>([](std::condition_variable &cv, auto&& result) {
|
||||
std::mutex m{};
|
||||
std::unique_lock lock{m};
|
||||
cv.wait(lock, [&result] { return result.index() != 0; });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Blocks this thread and waits for the awaitable to finish.
|
||||
*
|
||||
* @attention This will BLOCK THE THREAD. It is likely you want to use co_await instead.
|
||||
* @param duration Maximum duration to wait for
|
||||
* @return If T is void, returns a boolean for which true means the awaitable completed, false means it timed out.
|
||||
* @return If T is non-void, returns a std::optional<T> for which an absence of value means timed out.
|
||||
*/
|
||||
template <class Rep, class Period>
|
||||
auto sync_wait_for(const std::chrono::duration<Rep, Period>& duration) {
|
||||
return sync_wait_impl<true>([duration](std::condition_variable &cv, auto&& result) {
|
||||
std::mutex m{};
|
||||
std::unique_lock lock{m};
|
||||
cv.wait_for(lock, duration, [&result] { return result.index() != 0; });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Blocks this thread and waits for the awaitable to finish.
|
||||
*
|
||||
* @attention This will BLOCK THE THREAD. It is likely you want to use co_await instead.
|
||||
* @param time Maximum time point to wait for
|
||||
* @return If T is void, returns a boolean for which true means the awaitable completed, false means it timed out.
|
||||
* @return If T is non-void, returns a std::optional<T> for which an absence of value means timed out.
|
||||
*/
|
||||
template <class Clock, class Duration>
|
||||
auto sync_wait_until(const std::chrono::time_point<Clock, Duration> &time) {
|
||||
return sync_wait_impl<true>([time](std::condition_variable &cv, auto&& result) {
|
||||
std::mutex m{};
|
||||
std::unique_lock lock{m};
|
||||
cv.wait_until(lock, time, [&result] { return result.index() != 0; });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Generic awaitable class, represents a future value that can be co_await-ed on.
|
||||
*
|
||||
* Roughly equivalent of std::future for coroutines, with the crucial distinction that the future does not own a reference to a "shared state".
|
||||
* It holds a non-owning reference to the promise, which must be kept alive for the entire lifetime of the awaitable.
|
||||
*
|
||||
* @tparam T Type of the asynchronous value
|
||||
* @see promise
|
||||
*/
|
||||
template <typename T>
|
||||
class awaitable : public basic_awaitable<awaitable<T>> {
|
||||
protected:
|
||||
friend class detail::promise::promise_base<T>;
|
||||
|
||||
using shared_state = detail::promise::promise_base<T>;
|
||||
using state_flags = detail::promise::state_flags;
|
||||
|
||||
/**
|
||||
* @brief The type of the result produced by this task.
|
||||
*/
|
||||
using result_type = T;
|
||||
|
||||
/**
|
||||
* @brief Non-owning pointer to the promise, which must be kept alive for the entire lifetime of the awaitable.
|
||||
*/
|
||||
shared_state *state_ptr = nullptr;
|
||||
|
||||
/**
|
||||
* @brief Construct from a promise.
|
||||
*
|
||||
* @param promise The promise to refer to.
|
||||
*/
|
||||
awaitable(shared_state *promise) noexcept : state_ptr{promise} {}
|
||||
|
||||
/**
|
||||
* @brief Abandons the promise.
|
||||
*
|
||||
* Set the promise's state to broken and unlinks this awaitable.
|
||||
*
|
||||
* @return uint8_t Flags previously held before setting them to broken
|
||||
*/
|
||||
uint8_t abandon();
|
||||
/**
|
||||
* @brief Awaiter returned by co_await.
|
||||
*
|
||||
* Contains the await_ready, await_suspend and await_resume functions required by the C++ standard.
|
||||
* This class is CRTP-like, in that it will refer to an object derived from awaitable.
|
||||
*
|
||||
* @tparam Derived Type of reference to refer to the awaitable.
|
||||
*/
|
||||
template <typename Derived>
|
||||
struct awaiter {
|
||||
Derived awaitable_obj;
|
||||
|
||||
/**
|
||||
* @brief First function called by the standard library when co_await-ing this object.
|
||||
*
|
||||
* @throws dpp::logic_exception If the awaitable's valid() would return false.
|
||||
* @return bool Whether the result is ready, in which case we don't need to suspend
|
||||
*/
|
||||
bool await_ready() const;
|
||||
|
||||
/**
|
||||
* @brief Second function called by the standard library when co_await-ing this object.
|
||||
*
|
||||
* @throws dpp::logic_exception If the awaitable's valid() would return false.
|
||||
* At this point the coroutine frame was allocated and suspended.
|
||||
*
|
||||
* @return bool Whether we do need to suspend or not
|
||||
*/
|
||||
bool await_suspend(detail::std_coroutine::coroutine_handle<> handle);
|
||||
|
||||
/**
|
||||
* @brief Third and final function called by the standard library when co_await-ing this object, after resuming.
|
||||
*
|
||||
* @throw ? Any exception that occured during the retrieval of the value will be thrown
|
||||
* @return T The result.
|
||||
*/
|
||||
T await_resume();
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct an empty awaitable.
|
||||
*
|
||||
* Such an awaitable must be assigned a promise before it can be awaited.
|
||||
*/
|
||||
awaitable() = default;
|
||||
|
||||
/**
|
||||
* @brief Copy construction is disabled.
|
||||
*/
|
||||
awaitable(const awaitable&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move from another awaitable.
|
||||
*
|
||||
* @param rhs The awaitable to move from, left in an unspecified state after this.
|
||||
*/
|
||||
awaitable(awaitable&& rhs) noexcept : state_ptr(std::exchange(rhs.state_ptr, nullptr)) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Title :)
|
||||
*
|
||||
* We use this in the destructor
|
||||
*/
|
||||
void if_this_causes_an_invalid_read_your_promise_was_destroyed_before_your_awaitable____check_your_promise_lifetime() {
|
||||
abandon();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor.
|
||||
*
|
||||
* May signal to the promise that it was destroyed.
|
||||
*/
|
||||
~awaitable();
|
||||
|
||||
/**
|
||||
* @brief Copy assignment is disabled.
|
||||
*/
|
||||
awaitable& operator=(const awaitable&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move from another awaitable.
|
||||
*
|
||||
* @param rhs The awaitable to move from, left in an unspecified state after this.
|
||||
* @return *this
|
||||
*/
|
||||
awaitable& operator=(awaitable&& rhs) noexcept {
|
||||
abandon();
|
||||
state_ptr = std::exchange(rhs.state_ptr, nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether this awaitable refers to a valid promise.
|
||||
*
|
||||
* @return bool Whether this awaitable refers to a valid promise or not
|
||||
*/
|
||||
bool valid() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Check whether or not co_await-ing this would suspend the caller, i.e. if we have the result or not
|
||||
*
|
||||
* @return bool Whether we already have the result or not
|
||||
*/
|
||||
bool await_ready() const;
|
||||
|
||||
/**
|
||||
* @brief Overload of the co_await operator.
|
||||
*
|
||||
* @return Returns an @ref awaiter referencing this awaitable.
|
||||
*/
|
||||
template <typename Derived>
|
||||
requires (std::is_base_of_v<awaitable, std::remove_cv_t<Derived>>)
|
||||
friend awaiter<Derived&> operator co_await(Derived& obj) noexcept {
|
||||
return {obj};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Overload of the co_await operator. Returns an @ref awaiter referencing this awaitable.
|
||||
*
|
||||
* @return Returns an @ref awaiter referencing this awaitable.
|
||||
*/
|
||||
template <typename Derived>
|
||||
requires (std::is_base_of_v<awaitable, std::remove_cv_t<Derived>>)
|
||||
friend awaiter<Derived&&> operator co_await(Derived&& obj) noexcept {
|
||||
return {std::move(obj)};
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail::promise {
|
||||
|
||||
/**
|
||||
* @brief Base class defining logic common to all promise types, aka the "write" end of an awaitable.
|
||||
*/
|
||||
template <typename T>
|
||||
class promise_base {
|
||||
protected:
|
||||
friend class awaitable<T>;
|
||||
|
||||
/**
|
||||
* @brief Variant representing one of either 3 states of the result value : empty, result, exception.
|
||||
*/
|
||||
using storage_type = result_t<T>;
|
||||
|
||||
/**
|
||||
* @brief State of the result value.
|
||||
*
|
||||
* @see storage_type
|
||||
*
|
||||
* @note use .index() instead of std::holds_alternative to support promise_base<std::exception_ptr> and promise_base<std::monostate> :)
|
||||
*/
|
||||
storage_type value = std::monostate{};
|
||||
|
||||
/**
|
||||
* @brief State of the awaitable tied to this promise.
|
||||
*/
|
||||
std::atomic<uint8_t> state = sf_none;
|
||||
|
||||
/**
|
||||
* @brief Coroutine handle currently awaiting the completion of this promise.
|
||||
*/
|
||||
std_coroutine::coroutine_handle<> awaiter = nullptr;
|
||||
|
||||
/**
|
||||
* @brief Check if the result is empty, throws otherwise.
|
||||
*
|
||||
* @throw dpp::logic_exception if the result isn't empty.
|
||||
*/
|
||||
void throw_if_not_empty() {
|
||||
if (value.index() != 0) [[unlikely]] {
|
||||
throw dpp::logic_exception("cannot set a value on a promise that already has one");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unlinks this promise from its currently linked awaiter and returns it.
|
||||
*
|
||||
* At the time of writing this is only used in the case of a serious internal error in dpp::task.
|
||||
* Avoid using this as this will crash if the promise is used after this.
|
||||
*/
|
||||
std_coroutine::coroutine_handle<> release_awaiter() {
|
||||
return std::exchange(awaiter, nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct a new promise, with empty result.
|
||||
*/
|
||||
promise_base() = default;
|
||||
|
||||
/**
|
||||
* @brief Copy construction is disabled.
|
||||
*/
|
||||
promise_base(const promise_base&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move construction is disabled.
|
||||
*
|
||||
* awaitable hold a pointer to this object so moving is not possible.
|
||||
*/
|
||||
promise_base(promise_base&& rhs) = delete;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Copy assignment is disabled.
|
||||
*/
|
||||
promise_base &operator=(const promise_base&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move assignment is disabled.
|
||||
*/
|
||||
promise_base &operator=(promise_base&& rhs) = delete;
|
||||
|
||||
/**
|
||||
* @brief Set this promise to an exception and resume any awaiter.
|
||||
*
|
||||
* @tparam Notify Whether to resume any awaiter or not.
|
||||
* @throws dpp::logic_exception if the promise is not empty.
|
||||
* @throws ? Any exception thrown by the coroutine if resumed will propagate
|
||||
*/
|
||||
template <bool Notify = true>
|
||||
void set_exception(std::exception_ptr ptr) {
|
||||
throw_if_not_empty();
|
||||
value.template emplace<2>(std::move(ptr));
|
||||
[[maybe_unused]] auto previous_value = this->state.fetch_or(sf_ready, std::memory_order_acq_rel);
|
||||
if constexpr (Notify) {
|
||||
if ((previous_value & sf_awaited) != 0) {
|
||||
this->awaiter.resume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notify a currently awaiting coroutine that the result is ready.
|
||||
*
|
||||
* @note This may resume the coroutine on the current thread.
|
||||
* @throws ? Any exception thrown by the coroutine if resumed will propagate
|
||||
*/
|
||||
void notify_awaiter() {
|
||||
if ((state.load(std::memory_order_acquire) & sf_awaited) != 0) {
|
||||
awaiter.resume();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get an awaitable object for this promise.
|
||||
*
|
||||
* @throws dpp::logic_exception if get_awaitable has already been called on this object.
|
||||
* @return awaitable<T> An object that can be co_await-ed to retrieve the value of this promise.
|
||||
*/
|
||||
awaitable<T> get_awaitable() {
|
||||
uint8_t previous_flags = state.fetch_or(sf_has_awaitable, std::memory_order_relaxed);
|
||||
if (previous_flags & sf_has_awaitable) [[unlikely]] {
|
||||
throw dpp::logic_exception{"an awaitable was already created from this promise"};
|
||||
}
|
||||
return { this };
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generic promise class, represents the owning potion of an asynchronous value.
|
||||
*
|
||||
* This class is roughly equivalent to std::promise, with the crucial distinction that the promise *IS* the shared state.
|
||||
* As such, the promise needs to be kept alive for the entire time a value can be retrieved.
|
||||
*
|
||||
* @tparam T Type of the asynchronous value
|
||||
* @see awaitable
|
||||
*/
|
||||
template <typename T>
|
||||
class basic_promise : public detail::promise::promise_base<T> {
|
||||
public:
|
||||
using detail::promise::promise_base<T>::promise_base;
|
||||
using detail::promise::promise_base<T>::operator=;
|
||||
|
||||
/**
|
||||
* @brief Construct the result in place by forwarding the arguments, and by default resume any awaiter.
|
||||
*
|
||||
* @tparam Notify Whether to resume any awaiter or not.
|
||||
* @throws dpp::logic_exception if the promise is not empty.
|
||||
*/
|
||||
template <bool Notify = true, typename... Args>
|
||||
requires (std::constructible_from<T, Args...>)
|
||||
void emplace_value(Args&&... args) {
|
||||
this->throw_if_not_empty();
|
||||
try {
|
||||
this->value.template emplace<1>(std::forward<Args>(args)...);
|
||||
} catch (...) {
|
||||
this->value.template emplace<2>(std::current_exception());
|
||||
}
|
||||
[[maybe_unused]] auto previous_value = this->state.fetch_or(detail::promise::sf_ready, std::memory_order_acq_rel);
|
||||
if constexpr (Notify) {
|
||||
if (previous_value & detail::promise::sf_awaited) {
|
||||
this->awaiter.resume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct the result by forwarding reference, and resume any awaiter.
|
||||
*
|
||||
* @tparam Notify Whether to resume any awaiter or not.
|
||||
* @throws dpp::logic_exception if the promise is not empty.
|
||||
*/
|
||||
template <bool Notify = true, typename U = T>
|
||||
requires (std::convertible_to<U&&, T>)
|
||||
void set_value(U&& v) {
|
||||
emplace_value<Notify>(std::forward<U>(v));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct a void result, and resume any awaiter.
|
||||
*
|
||||
* @tparam Notify Whether to resume any awaiter or not.
|
||||
* @throws dpp::logic_exception if the promise is not empty.
|
||||
*/
|
||||
template <bool Notify = true>
|
||||
requires (std::is_void_v<T>)
|
||||
void set_value() {
|
||||
this->throw_if_not_empty();
|
||||
this->value.template emplace<1>();
|
||||
[[maybe_unused]] auto previous_value = this->state.fetch_or(detail::promise::sf_ready, std::memory_order_acq_rel);
|
||||
if constexpr (Notify) {
|
||||
if (previous_value & detail::promise::sf_awaited) {
|
||||
this->awaiter.resume();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Generic promise class, represents the owning potion of an asynchronous value.
|
||||
*
|
||||
* This class is roughly equivalent to std::promise, with the crucial distinction that the promise *IS* the shared state.
|
||||
* As such, the promise needs to be kept alive for the entire time a value can be retrieved.
|
||||
*
|
||||
* The difference between basic_promise and this object is that this one is moveable as it wraps an underlying basic_promise in a std::unique_ptr.
|
||||
*
|
||||
* @see awaitable
|
||||
*/
|
||||
template <typename T>
|
||||
class moveable_promise {
|
||||
/**
|
||||
* @brief Shared state, wrapped in a unique_ptr to allow move without disturbing an awaitable's promise pointer.
|
||||
*/
|
||||
std::unique_ptr<basic_promise<T>> shared_state = std::make_unique<basic_promise<T>>();
|
||||
|
||||
public:
|
||||
/**
|
||||
* @copydoc basic_promise<T>::emplace_value
|
||||
*/
|
||||
template <bool Notify = true, typename... Args>
|
||||
requires (std::constructible_from<T, Args...>)
|
||||
void emplace_value(Args&&... args) {
|
||||
shared_state->template emplace_value<Notify>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc basic_promise<T>::set_value(U&&)
|
||||
*/
|
||||
template <bool Notify = true, typename U = T>
|
||||
void set_value(U&& v) requires (std::convertible_to<U&&, T>) {
|
||||
shared_state->template set_value<Notify>(std::forward<U>(v));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc basic_promise<T>::set_value()
|
||||
*/
|
||||
template <bool Notify = true>
|
||||
void set_value() requires (std::is_void_v<T>) {
|
||||
shared_state->template set_value<Notify>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc basic_promise<T>::set_value(T&&)
|
||||
*/
|
||||
template <bool Notify = true>
|
||||
void set_exception(std::exception_ptr ptr) {
|
||||
shared_state->template set_exception<Notify>(std::move(ptr));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc basic_promise<T>::notify_awaiter
|
||||
*/
|
||||
void notify_awaiter() {
|
||||
shared_state->notify_awaiter();
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc basic_promise<T>::get_awaitable
|
||||
*/
|
||||
awaitable<T> get_awaitable() {
|
||||
return shared_state->get_awaitable();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using promise = moveable_promise<T>;
|
||||
|
||||
template <typename T>
|
||||
auto awaitable<T>::abandon() -> uint8_t {
|
||||
uint8_t previous_state = state_flags::sf_broken;
|
||||
if (state_ptr) {
|
||||
previous_state = state_ptr->state.fetch_or(state_flags::sf_broken, std::memory_order_acq_rel);
|
||||
state_ptr = nullptr;
|
||||
}
|
||||
return previous_state;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
awaitable<T>::~awaitable() {
|
||||
if_this_causes_an_invalid_read_your_promise_was_destroyed_before_your_awaitable____check_your_promise_lifetime();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool awaitable<T>::valid() const noexcept {
|
||||
return state_ptr != nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool awaitable<T>::await_ready() const {
|
||||
if (!this->valid()) {
|
||||
throw dpp::logic_exception("cannot co_await an empty awaitable");
|
||||
}
|
||||
uint8_t state = this->state_ptr->state.load(std::memory_order_relaxed);
|
||||
return state & detail::promise::sf_ready;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename Derived>
|
||||
bool awaitable<T>::awaiter<Derived>::await_suspend(detail::std_coroutine::coroutine_handle<> handle) {
|
||||
auto &promise = *awaitable_obj.state_ptr;
|
||||
|
||||
promise.awaiter = handle;
|
||||
auto previous_flags = promise.state.fetch_or(detail::promise::sf_awaited, std::memory_order_relaxed);
|
||||
if (previous_flags & detail::promise::sf_awaited) {
|
||||
throw dpp::logic_exception("awaitable is already being awaited");
|
||||
}
|
||||
return !(previous_flags & detail::promise::sf_ready);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename Derived>
|
||||
T awaitable<T>::awaiter<Derived>::await_resume() {
|
||||
auto &promise = *awaitable_obj.state_ptr;
|
||||
|
||||
promise.state.fetch_and(static_cast<uint8_t>(~detail::promise::sf_awaited), std::memory_order_acq_rel);
|
||||
if (std::holds_alternative<std::exception_ptr>(promise.value)) {
|
||||
std::rethrow_exception(std::get<2>(promise.value));
|
||||
}
|
||||
if constexpr (!std::is_void_v<T>) {
|
||||
return std::get<1>(std::move(promise.value));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
template <typename Derived>
|
||||
bool awaitable<T>::awaiter<Derived>::await_ready() const {
|
||||
return static_cast<Derived>(awaitable_obj).await_ready();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include <dpp/coro/job.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
namespace detail::promise {
|
||||
|
||||
template <typename T>
|
||||
void spawn_sync_wait_job(auto* awaitable, std::condition_variable &cv, auto&& result) {
|
||||
[](auto* awaitable_, std::condition_variable &cv_, auto&& result_) -> dpp::job {
|
||||
try {
|
||||
if constexpr (std::is_void_v<T>) {
|
||||
co_await *awaitable_;
|
||||
result_.template emplace<1>();
|
||||
} else {
|
||||
result_.template emplace<1>(co_await *awaitable_);
|
||||
}
|
||||
} catch (...) {
|
||||
result_.template emplace<2>(std::current_exception());
|
||||
}
|
||||
cv_.notify_all();
|
||||
}(awaitable, cv, std::forward<decltype(result)>(result));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* DPP_NO_CORO */
|
||||
205
dpp/coro/coro.h
205
dpp/coro/coro.h
@ -1,205 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2022 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <dpp/export.h>
|
||||
|
||||
#ifndef DPP_NO_CORO
|
||||
|
||||
#if (defined(_LIBCPP_VERSION) and !defined(__cpp_impl_coroutine)) // if libc++ experimental implementation (LLVM < 14)
|
||||
# define STDCORO_EXPERIMENTAL_HEADER
|
||||
# define STDCORO_EXPERIMENTAL_NAMESPACE
|
||||
#endif
|
||||
|
||||
#ifdef STDCORO_GLIBCXX_COMPAT
|
||||
# define __cpp_impl_coroutine 1
|
||||
namespace std {
|
||||
namespace experimental {
|
||||
using namespace std;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STDCORO_EXPERIMENTAL_HEADER
|
||||
# include <experimental/coroutine>
|
||||
#else
|
||||
# include <coroutine>
|
||||
#endif
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Implementation details for internal use only.
|
||||
*
|
||||
* @attention This is only meant to be used by D++ internally. Support will not be given regarding the facilities in this namespace.
|
||||
*/
|
||||
namespace detail {
|
||||
#ifdef _DOXYGEN_
|
||||
/**
|
||||
* @brief Alias for either std or std::experimental depending on compiler and library. Used by coroutine implementation.
|
||||
*
|
||||
* @todo Remove and use std when all supported libraries have coroutines in it
|
||||
*/
|
||||
namespace std_coroutine {}
|
||||
#else
|
||||
# ifdef STDCORO_EXPERIMENTAL_NAMESPACE
|
||||
namespace std_coroutine = std::experimental;
|
||||
# else
|
||||
namespace std_coroutine = std;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef _DOXYGEN_
|
||||
/**
|
||||
* @brief Concept to check if a type has a useable `operator co_await()` member
|
||||
*/
|
||||
template <typename T>
|
||||
concept has_co_await_member = requires (T expr) { expr.operator co_await(); };
|
||||
|
||||
/**
|
||||
* @brief Concept to check if a type has a useable overload of the free function `operator co_await(expr)`
|
||||
*/
|
||||
template <typename T>
|
||||
concept has_free_co_await = requires (T expr) { operator co_await(expr); };
|
||||
|
||||
/**
|
||||
* @brief Concept to check if a type has useable `await_ready()`, `await_suspend()` and `await_resume()` member functions.
|
||||
*/
|
||||
template <typename T>
|
||||
concept has_await_members = requires (T expr) { expr.await_ready(); expr.await_suspend(); expr.await_resume(); };
|
||||
|
||||
/**
|
||||
* @brief Mimics the compiler's behavior of using co_await. That is, it returns whichever works first, in order : `expr.operator co_await();` > `operator co_await(expr)` > `expr`
|
||||
*/
|
||||
template <typename T>
|
||||
requires (has_co_await_member<T>)
|
||||
decltype(auto) co_await_resolve(T&& expr) noexcept(noexcept(expr.operator co_await())) {
|
||||
decltype(auto) awaiter = expr.operator co_await();
|
||||
return awaiter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Mimics the compiler's behavior of using co_await. That is, it returns whichever works first, in order : `expr.operator co_await();` > `operator co_await(expr)` > `expr`
|
||||
*/
|
||||
template <typename T>
|
||||
requires (!has_co_await_member<T> && has_free_co_await<T>)
|
||||
decltype(auto) co_await_resolve(T&& expr) noexcept(noexcept(operator co_await(expr))) {
|
||||
decltype(auto) awaiter = operator co_await(static_cast<T&&>(expr));
|
||||
return awaiter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Mimics the compiler's behavior of using co_await. That is, it returns whichever works first, in order : `expr.operator co_await();` > `operator co_await(expr)` > `expr`
|
||||
*/
|
||||
template <typename T>
|
||||
requires (!has_co_await_member<T> && !has_free_co_await<T>)
|
||||
decltype(auto) co_await_resolve(T&& expr) noexcept {
|
||||
return static_cast<T&&>(expr);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* @brief Concept to check if a type has a useable `operator co_await()` member
|
||||
*
|
||||
* @note This is actually a C++20 concept but Doxygen doesn't do well with them
|
||||
*/
|
||||
template <typename T>
|
||||
inline constexpr bool has_co_await_member;
|
||||
|
||||
/**
|
||||
* @brief Concept to check if a type has a useable overload of the free function `operator co_await(expr)`
|
||||
*
|
||||
* @note This is actually a C++20 concept but Doxygen doesn't do well with them
|
||||
*/
|
||||
template <typename T>
|
||||
inline constexpr bool has_free_co_await;
|
||||
|
||||
/**
|
||||
* @brief Concept to check if a type has useable `await_ready()`, `await_suspend()` and `await_resume()` member functions.
|
||||
*
|
||||
* @note This is actually a C++20 concept but Doxygen doesn't do well with them
|
||||
*/
|
||||
template <typename T>
|
||||
inline constexpr bool has_await_members;
|
||||
|
||||
/**
|
||||
* @brief Concept to check if a type can be used with co_await
|
||||
*
|
||||
* @note This is actually a C++20 concept but Doxygen doesn't do well with them
|
||||
*/
|
||||
template <typename T>
|
||||
inline constexpr bool awaitable_type;
|
||||
|
||||
/**
|
||||
* @brief Mimics the compiler's behavior of using co_await. That is, it returns whichever works first, in order : `expr.operator co_await();` > `operator co_await(expr)` > `expr`
|
||||
*
|
||||
* This function is conditionally noexcept, if the returned expression also is.
|
||||
*/
|
||||
decltype(auto) co_await_resolve(auto&& expr) {}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Convenience alias for the result of a certain awaitable's await_resume.
|
||||
*/
|
||||
template <typename T>
|
||||
using awaitable_result = decltype(co_await_resolve(std::declval<T>()).await_resume());
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* @brief Concept to check if a type can be used with co_await
|
||||
*/
|
||||
template <typename T>
|
||||
concept awaitable_type = requires (T expr) { detail::co_await_resolve(expr).await_ready(); };
|
||||
|
||||
struct confirmation_callback_t;
|
||||
|
||||
template <typename R = confirmation_callback_t>
|
||||
class async;
|
||||
|
||||
template <typename R = void>
|
||||
#ifndef _DOXYGEN_
|
||||
requires (!std::is_reference_v<R>)
|
||||
#endif
|
||||
class task;
|
||||
|
||||
template <typename R = void>
|
||||
class coroutine;
|
||||
|
||||
struct job;
|
||||
|
||||
#ifdef DPP_CORO_TEST
|
||||
/**
|
||||
* @brief Allocation count of a certain type, for testing purposes.
|
||||
*
|
||||
* @todo Remove when coro is stable
|
||||
*/
|
||||
template <typename T>
|
||||
inline int coro_alloc_count = 0;
|
||||
#endif
|
||||
|
||||
} // namespace dpp
|
||||
|
||||
#endif /* DPP_NO_CORO */
|
||||
|
||||
@ -1,406 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2022 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <dpp/utility.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
struct coroutine_dummy {
|
||||
int *handle_dummy = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef DPP_NO_CORO
|
||||
|
||||
#include <dpp/coro/coro.h>
|
||||
#include <dpp/coro/awaitable.h>
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <exception>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
namespace coroutine {
|
||||
|
||||
template <typename R>
|
||||
struct promise_t;
|
||||
|
||||
template <typename R>
|
||||
/**
|
||||
* @brief Alias for the handle_t of a coroutine.
|
||||
*/
|
||||
using handle_t = std_coroutine::coroutine_handle<promise_t<R>>;
|
||||
|
||||
} // namespace coroutine
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* @class coroutine coroutine.h coro/coroutine.h
|
||||
* @brief Base type for a coroutine, starts on co_await.
|
||||
*
|
||||
* @warning - This feature is EXPERIMENTAL. The API may change at any time and there may be bugs.
|
||||
* Please report any to <a href="https://github.com/brainboxdotcc/DPP/issues">GitHub Issues</a> or to our <a href="https://discord.gg/dpp">Discord Server</a>.
|
||||
* @warning - Using co_await on this object more than once is undefined behavior.
|
||||
* @tparam R Return type of the coroutine. Can be void, or a complete object that supports move construction and move assignment.
|
||||
*/
|
||||
template <typename R>
|
||||
class [[nodiscard("dpp::coroutine only starts when it is awaited, it will do nothing if discarded")]] coroutine : public basic_awaitable<coroutine<R>> {
|
||||
/**
|
||||
* @brief Promise has friend access for the constructor
|
||||
*/
|
||||
friend struct detail::coroutine::promise_t<R>;
|
||||
|
||||
/**
|
||||
* @brief Coroutine handle.
|
||||
*/
|
||||
detail::coroutine::handle_t<R> handle{nullptr};
|
||||
|
||||
/**
|
||||
* @brief Construct from a handle. Internal use only.
|
||||
*/
|
||||
coroutine(detail::coroutine::handle_t<R> h) : handle{h} {}
|
||||
|
||||
struct awaiter {
|
||||
/**
|
||||
* @brief Reference to the coroutine object being awaited.
|
||||
*/
|
||||
coroutine &coro;
|
||||
|
||||
/**
|
||||
* @brief First function called by the standard library when the coroutine is co_await-ed.
|
||||
*
|
||||
* @remark Do not call this manually, use the co_await keyword instead.
|
||||
* @throws invalid_operation_exception if the coroutine is empty or finished.
|
||||
* @return bool Whether the coroutine is done
|
||||
*/
|
||||
[[nodiscard]] bool await_ready() const {
|
||||
if (!coro.handle) {
|
||||
throw dpp::logic_exception("cannot co_await an empty coroutine");
|
||||
}
|
||||
return coro.handle.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Second function called by the standard library when the coroutine is co_await-ed.
|
||||
*
|
||||
* Stores the calling coroutine in the promise to resume when this coroutine suspends.
|
||||
*
|
||||
* @remark Do not call this manually, use the co_await keyword instead.
|
||||
* @param caller The calling coroutine, now suspended
|
||||
*/
|
||||
template <typename T>
|
||||
[[nodiscard]] detail::coroutine::handle_t<R> await_suspend(detail::std_coroutine::coroutine_handle<T> caller) noexcept {
|
||||
coro.handle.promise().parent = caller;
|
||||
return coro.handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Final function called by the standard library when the coroutine is co_await-ed.
|
||||
*
|
||||
* Pops the coroutine's result and returns it.
|
||||
* @remark Do not call this manually, use the co_await keyword instead.
|
||||
*/
|
||||
R await_resume() {
|
||||
detail::coroutine::promise_t<R> &promise = coro.handle.promise();
|
||||
if (promise.exception) {
|
||||
std::rethrow_exception(promise.exception);
|
||||
}
|
||||
if constexpr (!std::is_void_v<R>) {
|
||||
return *std::exchange(promise.result, std::nullopt);
|
||||
} else {
|
||||
return; // unnecessary but makes lsp happy
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The type of the result produced by this coroutine.
|
||||
*/
|
||||
using result_type = R;
|
||||
|
||||
/**
|
||||
* @brief Default constructor, creates an empty coroutine.
|
||||
*/
|
||||
coroutine() = default;
|
||||
|
||||
/**
|
||||
* @brief Copy constructor is disabled
|
||||
*/
|
||||
coroutine(const coroutine &) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor, grabs another coroutine's handle
|
||||
*
|
||||
* @param other Coroutine to move the handle from
|
||||
*/
|
||||
coroutine(coroutine &&other) noexcept : handle(std::exchange(other.handle, nullptr)) {}
|
||||
|
||||
/**
|
||||
* @brief Destructor, destroys the handle.
|
||||
*/
|
||||
~coroutine() {
|
||||
if (handle) {
|
||||
handle.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy assignment is disabled
|
||||
*/
|
||||
coroutine &operator=(const coroutine &) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move assignment, grabs another coroutine's handle
|
||||
*
|
||||
* @param other Coroutine to move the handle from
|
||||
*/
|
||||
coroutine &operator=(coroutine &&other) noexcept {
|
||||
handle = std::exchange(other.handle, nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto operator co_await() {
|
||||
return awaiter{*this};
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail::coroutine {
|
||||
template <typename R>
|
||||
struct final_awaiter;
|
||||
|
||||
#ifdef DPP_CORO_TEST
|
||||
struct promise_t_base{};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Promise type for coroutine.
|
||||
*/
|
||||
template <typename R>
|
||||
struct promise_t {
|
||||
/**
|
||||
* @brief Handle of the coroutine co_await-ing this coroutine.
|
||||
*/
|
||||
std_coroutine::coroutine_handle<> parent{nullptr};
|
||||
|
||||
/**
|
||||
* @brief Return value of the coroutine
|
||||
*/
|
||||
std::optional<R> result{};
|
||||
|
||||
/**
|
||||
* @brief Pointer to an uncaught exception thrown by the coroutine
|
||||
*/
|
||||
std::exception_ptr exception{nullptr};
|
||||
|
||||
#ifdef DPP_CORO_TEST
|
||||
promise_t() {
|
||||
++coro_alloc_count<promise_t_base>;
|
||||
}
|
||||
|
||||
~promise_t() {
|
||||
--coro_alloc_count<promise_t_base>;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when reaching the end of a coroutine
|
||||
*
|
||||
* @return final_awaiter<R> Resumes any coroutine co_await-ing on this
|
||||
*/
|
||||
[[nodiscard]] final_awaiter<R> final_suspend() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when the coroutine start
|
||||
*
|
||||
* @return @return <a href="https://en.cppreference.com/w/cpp/coroutine/suspend_always">std::suspend_always</a> Always suspend at the start, for a lazy start
|
||||
*/
|
||||
[[nodiscard]] std_coroutine::suspend_always initial_suspend() const noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called when an exception escapes the coroutine
|
||||
*
|
||||
* Stores the exception to throw to the co_await-er
|
||||
*/
|
||||
void unhandled_exception() noexcept {
|
||||
exception = std::current_exception();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when the coroutine co_returns a value.
|
||||
*
|
||||
* Stores the value internally to hand to the caller when it resumes.
|
||||
*
|
||||
* @param expr The value given to co_return
|
||||
*/
|
||||
void return_value(R&& expr) noexcept(std::is_nothrow_move_constructible_v<R>) requires std::move_constructible<R> {
|
||||
result = static_cast<R&&>(expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when the coroutine co_returns a value.
|
||||
*
|
||||
* Stores the value internally to hand to the caller when it resumes.
|
||||
*
|
||||
* @param expr The value given to co_return
|
||||
*/
|
||||
void return_value(const R &expr) noexcept(std::is_nothrow_copy_constructible_v<R>) requires std::copy_constructible<R> {
|
||||
result = expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when the coroutine co_returns a value.
|
||||
*
|
||||
* Stores the value internally to hand to the caller when it resumes.
|
||||
*
|
||||
* @param expr The value given to co_return
|
||||
*/
|
||||
template <typename T>
|
||||
requires (!std::is_same_v<R, std::remove_cvref_t<T>> && std::convertible_to<T, R>)
|
||||
void return_value(T&& expr) noexcept (std::is_nothrow_convertible_v<T, R>) {
|
||||
result = std::forward<T>(expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called to get the coroutine object
|
||||
*/
|
||||
dpp::coroutine<R> get_return_object() {
|
||||
return dpp::coroutine<R>{handle_t<R>::from_promise(*this)};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Struct returned by a coroutine's final_suspend, resumes the continuation
|
||||
*/
|
||||
template <typename R>
|
||||
struct final_awaiter {
|
||||
/**
|
||||
* @brief First function called by the standard library when reaching the end of a coroutine
|
||||
*
|
||||
* @return false Always return false, we need to suspend to resume the parent
|
||||
*/
|
||||
[[nodiscard]] bool await_ready() const noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Second function called by the standard library when reaching the end of a coroutine.
|
||||
*
|
||||
* @return std::handle_t<> Coroutine handle to resume, this is either the parent if present or std::noop_coroutine()
|
||||
*/
|
||||
[[nodiscard]] std_coroutine::coroutine_handle<> await_suspend(std_coroutine::coroutine_handle<promise_t<R>> handle) const noexcept {
|
||||
auto parent = handle.promise().parent;
|
||||
|
||||
return parent ? parent : std_coroutine::noop_coroutine();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when this object is resumed
|
||||
*/
|
||||
void await_resume() const noexcept {}
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
final_awaiter<R> promise_t<R>::final_suspend() const noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Struct returned by a coroutine's final_suspend, resumes the continuation
|
||||
*/
|
||||
template <>
|
||||
struct promise_t<void> {
|
||||
/**
|
||||
* @brief Handle of the coroutine co_await-ing this coroutine.
|
||||
*/
|
||||
std_coroutine::coroutine_handle<> parent{nullptr};
|
||||
|
||||
/**
|
||||
* @brief Pointer to an uncaught exception thrown by the coroutine
|
||||
*/
|
||||
std::exception_ptr exception{nullptr};
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when reaching the end of a coroutine
|
||||
*
|
||||
* @return final_awaiter<R> Resumes any coroutine co_await-ing on this
|
||||
*/
|
||||
[[nodiscard]] final_awaiter<void> final_suspend() const noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when the coroutine start
|
||||
*
|
||||
* @return @return <a href="https://en.cppreference.com/w/cpp/coroutine/suspend_always">std::suspend_always</a> Always suspend at the start, for a lazy start
|
||||
*/
|
||||
[[nodiscard]] std_coroutine::suspend_always initial_suspend() const noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called when an exception escapes the coroutine
|
||||
*
|
||||
* Stores the exception to throw to the co_await-er
|
||||
*/
|
||||
void unhandled_exception() noexcept {
|
||||
exception = std::current_exception();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called when co_return is used
|
||||
*/
|
||||
void return_void() const noexcept {}
|
||||
|
||||
/**
|
||||
* @brief Function called to get the coroutine object
|
||||
*/
|
||||
[[nodiscard]] dpp::coroutine<void> get_return_object() {
|
||||
return dpp::coroutine<void>{handle_t<void>::from_promise(*this)};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
DPP_CHECK_ABI_COMPAT(coroutine<void>, coroutine_dummy)
|
||||
DPP_CHECK_ABI_COMPAT(coroutine<uint64_t>, coroutine_dummy)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specialization of std::coroutine_traits, helps the standard library figure out a promise type from a coroutine function.
|
||||
*/
|
||||
template<typename R, typename... Args>
|
||||
struct dpp::detail::std_coroutine::coroutine_traits<dpp::coroutine<R>, Args...> {
|
||||
using promise_type = dpp::detail::coroutine::promise_t<R>;
|
||||
};
|
||||
|
||||
#endif /* DPP_NO_CORO */
|
||||
145
dpp/coro/job.h
145
dpp/coro/job.h
@ -1,145 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2022 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <dpp/utility.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
struct job_dummy {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef DPP_NO_CORO
|
||||
|
||||
#include "coro.h"
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @class job job.h coro/job.h
|
||||
* @brief Extremely light coroutine object designed to send off a coroutine to execute on its own.
|
||||
* Can be used in conjunction with coroutine events via @ref dpp::event_router_t::operator()(F&&) "event routers", or on its own.
|
||||
*
|
||||
* This object stores no state and is the recommended way to use coroutines if you do not need to co_await the result.
|
||||
*
|
||||
* @warning - This feature is EXPERIMENTAL. The API may change at any time and there may be bugs.
|
||||
* Please report any to <a href="https://github.com/brainboxdotcc/DPP/issues">GitHub Issues</a> or to our <a href="https://discord.gg/dpp">Discord Server</a>.
|
||||
* @warning - It cannot be co_awaited, which means the second it co_awaits something, the program jumps back to the calling function, which continues executing.
|
||||
* At this point, if the function returns, every object declared in the function including its parameters are destroyed, which causes @ref lambdas-and-locals "dangling references".
|
||||
* For this reason, `co_await` will error if any parameters are passed by reference.
|
||||
* If you must pass a reference, pass it as a pointer or with std::ref, but you must fully understand the reason behind this warning, and what to avoid.
|
||||
* If you prefer a safer type, use `coroutine` for synchronous execution, or `task` for parallel tasks, and co_await them.
|
||||
*/
|
||||
struct job {};
|
||||
|
||||
namespace detail {
|
||||
|
||||
namespace job {
|
||||
|
||||
#ifdef DPP_CORO_TEST
|
||||
struct promise{};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Coroutine promise type for a job
|
||||
*/
|
||||
template <typename... Args>
|
||||
struct promise {
|
||||
|
||||
#ifdef DPP_CORO_TEST
|
||||
promise() {
|
||||
++coro_alloc_count<job_promise_base>;
|
||||
}
|
||||
|
||||
~promise() {
|
||||
--coro_alloc_count<job_promise_base>;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Function called when the job is done.
|
||||
*
|
||||
* @return <a href="https://en.cppreference.com/w/cpp/coroutine/suspend_never">std::suspend_never</a> Do not suspend at the end, destroying the handle immediately
|
||||
*/
|
||||
std_coroutine::suspend_never final_suspend() const noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called when the job is started.
|
||||
*
|
||||
* @return <a href="https://en.cppreference.com/w/cpp/coroutine/suspend_never">std::suspend_never</a> Do not suspend at the start, starting the job immediately
|
||||
*/
|
||||
std_coroutine::suspend_never initial_suspend() const noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called to get the job object
|
||||
*
|
||||
* @return job
|
||||
*/
|
||||
dpp::job get_return_object() const noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called when an exception is thrown and not caught.
|
||||
*
|
||||
* @throw Immediately rethrows the exception to the caller / resumer
|
||||
*/
|
||||
void unhandled_exception() const {
|
||||
throw;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called when the job returns. Does nothing.
|
||||
*/
|
||||
void return_void() const noexcept {}
|
||||
};
|
||||
|
||||
} // namespace job
|
||||
|
||||
} // namespace detail
|
||||
|
||||
DPP_CHECK_ABI_COMPAT(job, job_dummy)
|
||||
} // namespace dpp
|
||||
|
||||
/**
|
||||
* @brief Specialization of std::coroutine_traits, helps the standard library figure out a promise type from a coroutine function.
|
||||
*/
|
||||
template<typename... Args>
|
||||
struct dpp::detail::std_coroutine::coroutine_traits<dpp::job, Args...> {
|
||||
/**
|
||||
* @brief Promise type for this coroutine signature.
|
||||
*
|
||||
* When the coroutine is created from a lambda, that lambda is passed as a first parameter.
|
||||
* Not ideal but we'll allow any callable that takes the rest of the arguments passed
|
||||
*/
|
||||
using promise_type = dpp::detail::job::promise<Args...>;
|
||||
};
|
||||
|
||||
#endif /* DPP_NO_CORO */
|
||||
446
dpp/coro/task.h
446
dpp/coro/task.h
@ -1,446 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2022 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <dpp/utility.h>
|
||||
#include <dpp/coro/awaitable.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
struct task_dummy : awaitable_dummy {
|
||||
int* handle_dummy = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef DPP_NO_CORO
|
||||
|
||||
#include <dpp/coro/coro.h>
|
||||
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <exception>
|
||||
#include <atomic>
|
||||
|
||||
#include <iostream> // std::cerr in final_suspend
|
||||
|
||||
namespace dpp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/* Internal cogwheels for dpp::task */
|
||||
namespace task {
|
||||
|
||||
/**
|
||||
* @brief A @ref dpp::task "task"'s promise_t type, with special logic for handling nested tasks.
|
||||
*
|
||||
* @tparam R Return type of the task
|
||||
*/
|
||||
template <typename R>
|
||||
struct promise_t;
|
||||
|
||||
/**
|
||||
* @brief The object automatically co_await-ed at the end of a @ref dpp::task "task". Ensures nested coroutine chains are resolved, and the promise_t cleans up if it needs to.
|
||||
*
|
||||
* @tparam R Return type of the task
|
||||
*/
|
||||
template <typename R>
|
||||
struct final_awaiter;
|
||||
|
||||
/**
|
||||
* @brief Alias for <a href="https://en.cppreference.com/w/cpp/coroutine/coroutine_handle"std::coroutine_handle</a> for a @ref dpp::task "task"'s @ref promise_t.
|
||||
*
|
||||
* @tparam R Return type of the task
|
||||
*/
|
||||
template <typename R>
|
||||
using handle_t = std_coroutine::coroutine_handle<promise_t<R>>;
|
||||
|
||||
} // namespace task
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* @class task task.h coro/task.h
|
||||
* @brief A coroutine task. It starts immediately on construction and can be co_await-ed, making it perfect for parallel coroutines returning a value.
|
||||
*
|
||||
* @warning - This feature is EXPERIMENTAL. The API may change at any time and there may be bugs.
|
||||
* Please report any to <a href="https://github.com/brainboxdotcc/DPP/issues">GitHub Issues</a> or to our <a href="https://discord.gg/dpp">Discord Server</a>.
|
||||
* @tparam R Return type of the task. Cannot be a reference but can be void.
|
||||
*/
|
||||
template <typename R>
|
||||
#ifndef _DOXYGEN_
|
||||
requires (!std::is_reference_v<R>)
|
||||
#endif
|
||||
class [[nodiscard("dpp::task cancels itself on destruction. use co_await on it, or its sync_wait method")]] task : public awaitable<R> {
|
||||
friend struct detail::task::promise_t<R>;
|
||||
|
||||
using handle_t = detail::task::handle_t<R>;
|
||||
using state_flags = detail::promise::state_flags;
|
||||
|
||||
handle_t handle{};
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Construct from a coroutine handle. Internal use only
|
||||
*/
|
||||
explicit task(handle_t handle_) : awaitable<R>(&handle_.promise()), handle(handle_) {}
|
||||
|
||||
/**
|
||||
* @brief Clean up our handle, cancelling any running task
|
||||
*/
|
||||
void cleanup() {
|
||||
if (handle && this->valid()) {
|
||||
if (this->abandon() & state_flags::sf_done) {
|
||||
handle.destroy();
|
||||
} else {
|
||||
cancel();
|
||||
}
|
||||
handle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor, creates a task not bound to a coroutine.
|
||||
*/
|
||||
task() = default;
|
||||
|
||||
/**
|
||||
* @brief Copy constructor is disabled
|
||||
*/
|
||||
task(const task &) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor, grabs another task's coroutine handle
|
||||
*
|
||||
* @param other Task to move the handle from
|
||||
*/
|
||||
task(task &&other) noexcept : awaitable<R>(std::move(other)), handle(std::exchange(other.handle, nullptr)) {}
|
||||
|
||||
/**
|
||||
* @brief Copy assignment is disabled
|
||||
*/
|
||||
task &operator=(const task &) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move assignment, grabs another task's coroutine handle
|
||||
*
|
||||
* @param other Task to move the handle from
|
||||
*/
|
||||
task &operator=(task &&other) noexcept {
|
||||
cleanup();
|
||||
handle = std::exchange(other.handle, nullptr);
|
||||
awaitable<R>::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor.
|
||||
*
|
||||
* Destroys the handle. If the task is still running, it will be cancelled.
|
||||
*/
|
||||
~task() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to check if the task has finished its execution entirely
|
||||
*
|
||||
* @return bool Whether the task is finished.
|
||||
*/
|
||||
[[nodiscard]] bool done() const noexcept {
|
||||
return handle && (!this->valid() || handle.promise().state.load(std::memory_order_acq_rel) == state_flags::sf_done);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cancel the task, it will stop the next time it uses co_await. On co_await-ing this task, throws dpp::task_cancelled_exception.
|
||||
*
|
||||
* @return *this
|
||||
*/
|
||||
task& cancel() & noexcept {
|
||||
handle.promise().cancelled.exchange(true, std::memory_order_relaxed);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cancel the task, it will stop the next time it uses co_await. On co_await-ing this task, throws dpp::task_cancelled_exception.
|
||||
*
|
||||
* @return *this
|
||||
*/
|
||||
task&& cancel() && noexcept {
|
||||
handle.promise().cancelled.exchange(true, std::memory_order_relaxed);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail::task {
|
||||
/**
|
||||
* @brief Awaitable returned from task::promise_t's final_suspend. Resumes the parent and cleans up its handle if needed
|
||||
*/
|
||||
template <typename R>
|
||||
struct final_awaiter {
|
||||
/**
|
||||
* @brief Always suspend at the end of the task. This allows us to clean up and resume the parent
|
||||
*/
|
||||
[[nodiscard]] bool await_ready() const noexcept {
|
||||
return (false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The suspension logic of the coroutine when it finishes. Always suspend the caller, meaning cleaning up the handle is on us
|
||||
*
|
||||
* @param handle The handle of this coroutine
|
||||
* @return std::coroutine_handle<> Handle to resume, which is either the parent if present or std::noop_coroutine() otherwise
|
||||
*/
|
||||
[[nodiscard]] std_coroutine::coroutine_handle<> await_suspend(handle_t<R> handle) const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Function called when this object is co_awaited by the standard library at the end of final_suspend. Do nothing, return nothing
|
||||
*/
|
||||
void await_resume() const noexcept {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Base implementation of task::promise_t, without the logic that would depend on the return type. Meant to be inherited from
|
||||
*/
|
||||
template <typename R>
|
||||
struct promise_base : basic_promise<R> {
|
||||
/**
|
||||
* @brief Whether the task is cancelled or not.
|
||||
*/
|
||||
std::atomic<bool> cancelled = false;
|
||||
|
||||
#ifdef DPP_CORO_TEST
|
||||
promise_base() {
|
||||
++coro_alloc_count<promise_base>;
|
||||
}
|
||||
|
||||
~promise_base() {
|
||||
--coro_alloc_count<promise_base>;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when the coroutine is created.
|
||||
*
|
||||
* @return <a href="https://en.cppreference.com/w/cpp/coroutine/suspend_never">std::suspend_never</a> Don't suspend, the coroutine starts immediately.
|
||||
*/
|
||||
std_coroutine::suspend_never initial_suspend() const noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when an exception is thrown and not caught in the coroutine.
|
||||
*
|
||||
* Stores the exception pointer to rethrow on co_await. If the task object is destroyed and was not cancelled, throw instead
|
||||
*/
|
||||
void unhandled_exception() {
|
||||
if ((this->state.load() & promise::state_flags::sf_broken) && !cancelled) {
|
||||
throw;
|
||||
}
|
||||
this->template set_exception<false>(std::current_exception());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Proxy awaitable that wraps any co_await inside the task and checks for cancellation on resumption
|
||||
*
|
||||
* @see await_transform
|
||||
*/
|
||||
template <typename A>
|
||||
struct proxy_awaiter {
|
||||
/** @brief The promise_t object bound to this proxy */
|
||||
const promise_base &promise;
|
||||
|
||||
/** @brief The inner awaitable being awaited */
|
||||
A awaitable;
|
||||
|
||||
/** @brief Wrapper for the awaitable's await_ready */
|
||||
[[nodiscard]] bool await_ready() noexcept(noexcept(awaitable.await_ready())) {
|
||||
return awaitable.await_ready();
|
||||
}
|
||||
|
||||
/** @brief Wrapper for the awaitable's await_suspend */
|
||||
template <typename T>
|
||||
[[nodiscard]] decltype(auto) await_suspend(T&& handle) noexcept(noexcept(awaitable.await_suspend(std::forward<T>(handle)))) {
|
||||
return awaitable.await_suspend(std::forward<T>(handle));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wrapper for the awaitable's await_resume, throws if the task is cancelled
|
||||
*
|
||||
* @throw dpp::task_cancelled_exception If the task was cancelled
|
||||
*/
|
||||
decltype(auto) await_resume() {
|
||||
if (promise.cancelled.load()) {
|
||||
throw dpp::task_cancelled_exception{"task was cancelled"};
|
||||
}
|
||||
return awaitable.await_resume();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Function called whenever co_await is used inside of the task
|
||||
*
|
||||
* @throw dpp::task_cancelled_exception On resumption if the task was cancelled
|
||||
*
|
||||
* @return @ref proxy_awaiter Returns a proxy awaiter that will check for cancellation on resumption
|
||||
*/
|
||||
template <awaitable_type T>
|
||||
[[nodiscard]] auto await_transform(T&& expr) const noexcept(noexcept(co_await_resolve(std::forward<T>(expr)))) {
|
||||
using awaitable_t = decltype(co_await_resolve(std::forward<T>(expr)));
|
||||
return proxy_awaiter<awaitable_t>{*this, co_await_resolve(std::forward<T>(expr))};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implementation of task::promise_t for non-void return type
|
||||
*/
|
||||
template <typename R>
|
||||
struct promise_t : promise_base<R> {
|
||||
friend struct final_awaiter<R>;
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when the coroutine co_returns a value.
|
||||
*
|
||||
* Stores the value internally to hand to the caller when it resumes.
|
||||
*
|
||||
* @param expr The value given to co_return
|
||||
*/
|
||||
void return_value(R&& expr) noexcept(std::is_nothrow_move_constructible_v<R>) requires std::move_constructible<R> {
|
||||
this->template set_value<false>(std::move(expr));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when the coroutine co_returns a value.
|
||||
*
|
||||
* Stores the value internally to hand to the caller when it resumes.
|
||||
*
|
||||
* @param expr The value given to co_return
|
||||
*/
|
||||
void return_value(const R &expr) noexcept(std::is_nothrow_copy_constructible_v<R>) requires std::copy_constructible<R> {
|
||||
this->template set_value<false>(expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when the coroutine co_returns a value.
|
||||
*
|
||||
* Stores the value internally to hand to the caller when it resumes.
|
||||
*
|
||||
* @param expr The value given to co_return
|
||||
*/
|
||||
template <typename T>
|
||||
requires (!std::is_same_v<R, std::remove_cvref_t<T>> && std::convertible_to<T, R>)
|
||||
void return_value(T&& expr) noexcept (std::is_nothrow_convertible_v<T, R>) {
|
||||
this->template emplace_value<false>(std::forward<T>(expr));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when the coroutine is created.
|
||||
*
|
||||
* @return dpp::task The coroutine object
|
||||
*/
|
||||
[[nodiscard]] dpp::task<R> get_return_object() noexcept {
|
||||
return dpp::task<R>{handle_t<R>::from_promise(*this)};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when the coroutine reaches its last suspension point
|
||||
*
|
||||
* @return final_awaiter Special object containing the chain resolution and clean-up logic.
|
||||
*/
|
||||
[[nodiscard]] final_awaiter<R> final_suspend() const noexcept {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implementation of task::promise_t for void return type
|
||||
*/
|
||||
template <>
|
||||
struct promise_t<void> : promise_base<void> {
|
||||
friend struct final_awaiter<void>;
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when the coroutine co_returns
|
||||
*
|
||||
* Sets the promise state to finished.
|
||||
*/
|
||||
void return_void() noexcept {
|
||||
set_value<false>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when the coroutine is created.
|
||||
*
|
||||
* @return task The coroutine object
|
||||
*/
|
||||
[[nodiscard]] dpp::task<void> get_return_object() noexcept {
|
||||
return dpp::task<void>{handle_t<void>::from_promise(*this)};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called by the standard library when the coroutine reaches its last suspension point
|
||||
*
|
||||
* @return final_awaiter Special object containing the chain resolution and clean-up logic.
|
||||
*/
|
||||
[[nodiscard]] final_awaiter<void> final_suspend() const noexcept {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
std_coroutine::coroutine_handle<> final_awaiter<R>::await_suspend(handle_t<R> handle) const noexcept {
|
||||
using state_flags = promise::state_flags;
|
||||
promise_t<R> &promise = handle.promise();
|
||||
uint8_t previous_state = promise.state.fetch_or(state_flags::sf_done);
|
||||
|
||||
if ((previous_state & state_flags::sf_awaited) != 0) { // co_await-ed, resume parent
|
||||
if ((previous_state & state_flags::sf_broken) != 0) { // major bug, these should never be set together
|
||||
// we don't have a cluster so just log it on cerr
|
||||
std::cerr << "dpp: task promise ended in both an awaited and dangling state. this is a bug and a memory leak, please report it to us!" << std::endl;
|
||||
}
|
||||
return promise.release_awaiter();
|
||||
}
|
||||
if ((previous_state & state_flags::sf_broken) != 0) { // task object is gone, free the handle
|
||||
handle.destroy();
|
||||
}
|
||||
return std_coroutine::noop_coroutine();
|
||||
}
|
||||
|
||||
} // namespace detail::task
|
||||
|
||||
DPP_CHECK_ABI_COMPAT(task<void>, task_dummy)
|
||||
DPP_CHECK_ABI_COMPAT(task<uint64_t>, task_dummy)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specialization of std::coroutine_traits, helps the standard library figure out a promise_t type from a coroutine function.
|
||||
*/
|
||||
template<typename T, typename... Args>
|
||||
struct dpp::detail::std_coroutine::coroutine_traits<dpp::task<T>, Args...> {
|
||||
using promise_type = dpp::detail::task::promise_t<T>;
|
||||
};
|
||||
|
||||
#endif /* DPP_NO_CORO */
|
||||
@ -1,536 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2022 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#ifndef DPP_NO_CORO
|
||||
#pragma once
|
||||
|
||||
#include "coro.h"
|
||||
#include "job.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
template <typename T>
|
||||
class event_router_t;
|
||||
|
||||
namespace detail {
|
||||
|
||||
namespace event_router {
|
||||
|
||||
template <typename T>
|
||||
class awaitable;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Internal cogwheels for dpp::when_any
|
||||
*/
|
||||
namespace when_any {
|
||||
|
||||
/**
|
||||
* @brief Current state of a when_any object
|
||||
*/
|
||||
enum await_state : uint8_t {
|
||||
/**
|
||||
* @brief Object is being awaited
|
||||
*/
|
||||
waiting = 1 << 0,
|
||||
/**
|
||||
* @brief Object was resumed
|
||||
*/
|
||||
done = 1 << 1,
|
||||
/**
|
||||
* @brief Result is ready to retrieve
|
||||
*/
|
||||
ready = 1 << 2,
|
||||
/**
|
||||
* @brief Object was destroyed
|
||||
*/
|
||||
dangling = 1 << 3
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Type trait helper to obtain the actual type that will be used by a when_any when a type is passed as a parameter.
|
||||
* May specialize for certain types for specific behavior, e.g. for an event_router, store the awaitable directly
|
||||
*/
|
||||
template <typename T>
|
||||
struct arg_helper_s {
|
||||
/** Raw type of the awaitable */
|
||||
using type = T;
|
||||
|
||||
/** Helper static method to get the awaitable from a variable */
|
||||
static decltype(auto) get(auto&& v) {
|
||||
return static_cast<decltype(v)>(v);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct arg_helper_s<dpp::event_router_t<T>> {
|
||||
using type = event_router::awaitable<T>;
|
||||
|
||||
template <typename U>
|
||||
#ifndef _DOXYGEN
|
||||
requires (std::same_as<std::remove_cvref_t<U>, dpp::event_router_t<T>>)
|
||||
#endif
|
||||
static event_router::awaitable<T> get(U&& v) {
|
||||
return static_cast<U>(v).operator co_await();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Alias for the actual type that an awaitable will be stored as in a when_any.
|
||||
* For example if given an event_router, store the awaitable, not the event_router.
|
||||
*/
|
||||
template <typename T>
|
||||
using awaitable_type = typename arg_helper_s<T>::type;
|
||||
|
||||
/**
|
||||
* @brief Helper struct with a method to convert an awaitable parameter to the actual value it will be stored as.
|
||||
* For example if given an event_router, store the awaitable, not the event_router.
|
||||
*/
|
||||
template <typename T>
|
||||
using arg_helper = arg_helper_s<std::remove_cvref_t<T>>;
|
||||
|
||||
/**
|
||||
* @brief Empty result from void-returning awaitable
|
||||
*/
|
||||
struct empty{};
|
||||
|
||||
/**
|
||||
* @brief Actual type a result will be stores as in when_any
|
||||
*/
|
||||
template <typename T>
|
||||
using storage_type = std::conditional_t<std::is_void_v<T>, empty, T>;
|
||||
|
||||
/**
|
||||
* @brief Concept satisfied if a stored result is void
|
||||
*/
|
||||
template <typename T>
|
||||
concept void_result = std::same_as<T, empty>;
|
||||
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* @class when_any when_any.h coro/when_any.h
|
||||
* @brief Experimental class to co_await on a bunch of awaitable objects, resuming when the first one completes.
|
||||
* On completion, returns a @ref result object that contains the index of the awaitable that finished first.
|
||||
* A user can call @ref result::index() and @ref result::get<N>() on the result object to get the result, similar to std::variant.
|
||||
*
|
||||
* @see when_any::result
|
||||
* @tparam Args... Type of each awaitable to await on
|
||||
*/
|
||||
template <typename... Args>
|
||||
#ifndef _DOXYGEN_
|
||||
requires (sizeof...(Args) >= 1)
|
||||
#endif
|
||||
class when_any {
|
||||
/**
|
||||
* @brief Alias for the type of the result variant
|
||||
*/
|
||||
using variant_type = std::variant<std::exception_ptr, std::remove_cvref_t<detail::when_any::storage_type<detail::awaitable_result<Args>>>...>;
|
||||
|
||||
/**
|
||||
* @brief Alias for the result type of the Nth arg.
|
||||
*
|
||||
* @tparam N index of the argument to fetch
|
||||
*/
|
||||
template <size_t N>
|
||||
using result_t = std::variant_alternative_t<N + 1, variant_type>;
|
||||
|
||||
/**
|
||||
* @brief State shared between all the jobs to spawn
|
||||
*/
|
||||
struct state_t {
|
||||
/**
|
||||
* @brief Constructor for the internal state. Its arguments are used to construct each awaitable
|
||||
*/
|
||||
template <typename... Args_>
|
||||
state_t(Args_&&... args) : awaitables{std::forward<Args_>(args)...} {}
|
||||
|
||||
/**
|
||||
* @brief Awaitable objects to handle.
|
||||
*/
|
||||
std::tuple<Args...> awaitables;
|
||||
|
||||
/**
|
||||
* @brief Result or exception, as a variant. This will contain the result of the first awaitable to finish
|
||||
*/
|
||||
variant_type result{};
|
||||
|
||||
/**
|
||||
* @brief Coroutine handle to resume after finishing an awaitable
|
||||
*/
|
||||
detail::std_coroutine::coroutine_handle<> handle{};
|
||||
|
||||
/**
|
||||
* @brief Index of the awaitable that finished. Initialized to the maximum value of std::size_t.
|
||||
*/
|
||||
size_t index_finished = std::numeric_limits<std::size_t>::max();
|
||||
|
||||
/**
|
||||
* @brief State of the when_any object.
|
||||
*
|
||||
* @see detail::when_any::await_state
|
||||
*/
|
||||
std::atomic<uint8_t> owner_state{};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Shared pointer to the state shared between the jobs spawned. Contains the awaitable objects and the result.
|
||||
*/
|
||||
std::shared_ptr<state_t> my_state{nullptr};
|
||||
|
||||
/**
|
||||
* @brief Spawn a dpp::job handling the Nth argument.
|
||||
*
|
||||
* @tparam N Index of the argument to handle
|
||||
* @return dpp::job Job handling the Nth argument
|
||||
*/
|
||||
template <size_t N>
|
||||
static job make_job(std::shared_ptr<state_t> shared_state) {
|
||||
using namespace detail::when_any;
|
||||
|
||||
/**
|
||||
* Any exceptions from the awaitable's await_suspend should be thrown to the caller (the coroutine creating the when_any object)
|
||||
* If the co_await passes, and it is the first one to complete, try construct the result, catch any exceptions to rethrow at resumption, and resume.
|
||||
*/
|
||||
if constexpr (!std::same_as<result_t<N>, empty>) {
|
||||
decltype(auto) result = co_await std::get<N>(shared_state->awaitables);
|
||||
|
||||
if (auto s = shared_state->owner_state.fetch_or(await_state::done, std::memory_order_relaxed); (s & (await_state::done | await_state::dangling)) != 0) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
using result_t = decltype(result);
|
||||
|
||||
/* Try construct, prefer move if possible, store any exception to rethrow */
|
||||
try {
|
||||
if constexpr (std::is_lvalue_reference_v<result_t> && !std::is_const_v<result_t> && std::is_move_constructible_v<std::remove_cvref_t<result_t>>) {
|
||||
shared_state->result.template emplace<N + 1>(std::move(result));
|
||||
} else {
|
||||
shared_state->result.template emplace<N + 1>(result);
|
||||
}
|
||||
} catch (...) {
|
||||
shared_state->result.template emplace<0>(std::current_exception());
|
||||
}
|
||||
} else {
|
||||
co_await std::get<N>(shared_state->awaitables);
|
||||
|
||||
if (auto s = shared_state->owner_state.fetch_or(await_state::done, std::memory_order_relaxed); (s & (await_state::done | await_state::dangling)) != 0) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
shared_state->result.template emplace<N + 1>();
|
||||
}
|
||||
|
||||
shared_state->index_finished = N;
|
||||
if (auto s = shared_state->owner_state.fetch_or(await_state::ready, std::memory_order_acq_rel); (s & (await_state::waiting)) != 0) {
|
||||
assert(shared_state->handle);
|
||||
shared_state->handle.resume();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Spawn a dpp::job to handle each awaitable.
|
||||
* Each of them will co_await the awaitable and set the result if they are the first to finish
|
||||
*/
|
||||
void make_jobs() {
|
||||
constexpr auto impl = []<size_t... Ns>(when_any *self, std::index_sequence<Ns...>) {
|
||||
// We create an array to guarantee evaluation order here
|
||||
// https://eel.is/c++draft/dcl.init.aggr#7
|
||||
[[maybe_unused]] dpp::job jobs[] = { make_job<Ns>(self->my_state)... };
|
||||
};
|
||||
impl(this, std::index_sequence_for<Args...>{});
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Object returned by \ref operator co_await() on resumption. Can be moved but not copied.
|
||||
*/
|
||||
class result {
|
||||
friend class when_any<Args...>;
|
||||
|
||||
/**
|
||||
* @brief Reference to the shared state to pull the data from
|
||||
*/
|
||||
std::shared_ptr<state_t> shared_state;
|
||||
|
||||
/**
|
||||
* @brief Default construction is deleted
|
||||
*/
|
||||
result() = delete;
|
||||
|
||||
/**
|
||||
* @brief Internal constructor taking the shared state
|
||||
*/
|
||||
result(std::shared_ptr<state_t> state) : shared_state{state} {}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Move constructor
|
||||
*/
|
||||
result(result&&) = default;
|
||||
|
||||
/**
|
||||
* @brief This object is not copyable.
|
||||
*/
|
||||
result(const result &) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator
|
||||
*/
|
||||
result &operator=(result&&) = default;
|
||||
|
||||
/**
|
||||
* @brief This object is not copyable.
|
||||
*/
|
||||
result &operator=(const result&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Retrieve the index of the awaitable that finished first.
|
||||
*
|
||||
* @return size_t Index of the awaitable that finished first, relative to the template arguments of when_any
|
||||
*/
|
||||
size_t index() const noexcept {
|
||||
return shared_state->index_finished;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the non-void result of an awaitable.
|
||||
*
|
||||
* @tparam N Index of the result to retrieve. Must correspond to index().
|
||||
* @throw ??? Throws any exception triggered at construction, or std::bad_variant_access if N does not correspond to index()
|
||||
* @return Result of the awaitable as a reference.
|
||||
*/
|
||||
template <size_t N>
|
||||
#ifndef _DOXYGEN_
|
||||
requires (!detail::when_any::void_result<result_t<N>>)
|
||||
#endif
|
||||
result_t<N>& get() & {
|
||||
if (is_exception()) {
|
||||
std::rethrow_exception(std::get<0>(shared_state->result));
|
||||
}
|
||||
return std::get<N + 1>(shared_state->result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the non-void result of an awaitable.
|
||||
*
|
||||
* @tparam N Index of the result to retrieve. Must correspond to index().
|
||||
* @throw ??? Throws any exception triggered at construction, or std::bad_variant_access if N does not correspond to index()
|
||||
* @return Result of the awaitable as a cpnst reference.
|
||||
*/
|
||||
template <size_t N>
|
||||
#ifndef _DOXYGEN_
|
||||
requires (!detail::when_any::void_result<result_t<N>>)
|
||||
#endif
|
||||
const result_t<N>& get() const& {
|
||||
if (is_exception()) {
|
||||
std::rethrow_exception(std::get<0>(shared_state->result));
|
||||
}
|
||||
return std::get<N + 1>(shared_state->result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the non-void result of an awaitable.
|
||||
*
|
||||
* @tparam N Index of the result to retrieve. Must correspond to index().
|
||||
* @throw ??? Throws any exception triggered at construction, or std::bad_variant_access if N does not correspond to index()
|
||||
* @return Result of the awaitable as an rvalue reference.
|
||||
*/
|
||||
template <size_t N>
|
||||
#ifndef _DOXYGEN_
|
||||
requires (!detail::when_any::void_result<result_t<N>>)
|
||||
#endif
|
||||
result_t<N>&& get() && {
|
||||
if (is_exception()) {
|
||||
std::rethrow_exception(std::get<0>(shared_state->result));
|
||||
}
|
||||
return std::get<N + 1>(shared_state->result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cannot retrieve a void result.
|
||||
*/
|
||||
template <size_t N>
|
||||
#ifndef _DOXYGEN
|
||||
requires (detail::when_any::void_result<result_t<N>>)
|
||||
#endif
|
||||
[[deprecated("cannot retrieve a void result")]] void get() = delete;
|
||||
|
||||
/**
|
||||
* @brief Checks whether the return of the first awaitable triggered an exception, that is, a call to get() will rethrow.
|
||||
*
|
||||
* @return Whether or not the result is an exception
|
||||
*/
|
||||
[[nodiscard]] bool is_exception() const noexcept {
|
||||
return shared_state->result.index() == 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Object returned by \ref operator co_await(). Meant to be used by the standard library, not by a user.
|
||||
*
|
||||
* @see result
|
||||
*/
|
||||
struct awaiter {
|
||||
/**
|
||||
* @brief Pointer to the when_any object
|
||||
*/
|
||||
when_any *self;
|
||||
|
||||
/**
|
||||
* @brief First function called by the standard library when using co_await.
|
||||
*
|
||||
* @return bool Whether the result is ready
|
||||
*/
|
||||
[[nodiscard]] bool await_ready() const noexcept {
|
||||
return self->await_ready();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Second function called by the standard library when using co_await.
|
||||
*
|
||||
* @return bool Returns false if we want to resume immediately.
|
||||
*/
|
||||
bool await_suspend(detail::std_coroutine::coroutine_handle<> caller) noexcept {
|
||||
using namespace detail::when_any;
|
||||
|
||||
self->my_state->handle = caller;
|
||||
auto prev = self->my_state->owner_state.fetch_or(await_state::waiting, std::memory_order_acq_rel);
|
||||
return (prev & await_state::ready) == 0; // true (suspend) if the state was not `ready` -- false (resume) if it was
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Third and final function called by the standard library when using co_await. Returns the result object.
|
||||
*
|
||||
* @see result
|
||||
*/
|
||||
result await_resume() const noexcept {
|
||||
return { self->my_state };
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
* A when_any object created this way holds no state
|
||||
*/
|
||||
when_any() = default;
|
||||
|
||||
/**
|
||||
* @brief Constructor from awaitable objects. Each awaitable is executed immediately and the when_any object can then be co_await-ed later.
|
||||
*
|
||||
* @throw ??? Any exception thrown by the start of each awaitable will propagate to the caller.
|
||||
* @param args Arguments to construct each awaitable from. The when_any object will construct an awaitable for each, it is recommended to pass rvalues or std::move.
|
||||
*/
|
||||
template <typename... Args_>
|
||||
#ifndef _DOXYGEN_
|
||||
requires (sizeof...(Args_) == sizeof...(Args))
|
||||
#endif /* _DOXYGEN_ */
|
||||
when_any(Args_&&... args) : my_state{ std::make_shared<state_t>(detail::when_any::arg_helper<Args_>::get(std::forward<Args_>(args))...) } {
|
||||
make_jobs();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This object is not copyable.
|
||||
*/
|
||||
when_any(const when_any &) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
*/
|
||||
when_any(when_any &&) noexcept = default;
|
||||
|
||||
/**
|
||||
* @brief On destruction the when_any will try to call @ref dpp::task::cancel() cancel() on each of its awaitable if they have such a method.
|
||||
*
|
||||
* @note If you are looking to use a custom type with when_any and want it to cancel on its destruction,
|
||||
* make sure it has a cancel() method, which will trigger an await_resume() throwing a dpp::task_cancelled_exception.
|
||||
* This object will swallow the exception and return cleanly. Any other exception will be thrown back to the resumer.
|
||||
*/
|
||||
~when_any() {
|
||||
if (!my_state)
|
||||
return;
|
||||
|
||||
my_state->owner_state = detail::when_any::await_state::dangling;
|
||||
|
||||
[]<size_t... Ns>(when_any *self, std::index_sequence<Ns...>) constexpr {
|
||||
constexpr auto cancel = []<size_t N>(when_any *self) constexpr {
|
||||
if constexpr (requires { std::get<N>(self->my_state->awaitables).cancel(); }) {
|
||||
try {
|
||||
std::get<N>(self->my_state->awaitables).cancel();
|
||||
} catch (...) {
|
||||
// swallow any exception. no choice here, we're in a destructor
|
||||
}
|
||||
}
|
||||
};
|
||||
(cancel.template operator()<Ns>(self), ...);
|
||||
}(this, std::index_sequence_for<Args...>());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This object is not copyable.
|
||||
*/
|
||||
when_any &operator=(const when_any &) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator.
|
||||
*/
|
||||
when_any &operator=(when_any &&) noexcept = default;
|
||||
|
||||
/**
|
||||
* @brief Check whether a call to co_await would suspend.
|
||||
*
|
||||
* @note This can change from false to true at any point, but not the other way around.
|
||||
* @return bool Whether co_await would suspend
|
||||
*/
|
||||
[[nodiscard]] bool await_ready() const noexcept {
|
||||
return (my_state->owner_state.load(std::memory_order_acquire) & detail::when_any::await_state::ready) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suspend the caller until any of the awaitables completes.
|
||||
*
|
||||
* @see result
|
||||
* @throw ??? On resumption, throws any exception caused by the construction of the result.
|
||||
* @return result On resumption, this object returns an object that allows to retrieve the index and result of the awaitable.
|
||||
*/
|
||||
[[nodiscard]] awaiter operator co_await() noexcept {
|
||||
return { this };
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
#ifndef _DOXYGEN_
|
||||
requires (sizeof...(Args) >= 1)
|
||||
#endif /* _DOXYGEN_ */
|
||||
when_any(Args...) -> when_any<detail::when_any::awaitable_type<Args>...>;
|
||||
|
||||
} /* namespace dpp */
|
||||
|
||||
#endif
|
||||
@ -1,74 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/http_server.h>
|
||||
#include <dpp/signature_verifier.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Creates a HTTP server which listens for incoming
|
||||
* Discord interactions, and if verified as valid, raises them
|
||||
* as cluster events, returning the response back.
|
||||
* Note that Discord requires all interaction endpoints to
|
||||
* have a valid SSL certificate (not self signed) so in most
|
||||
* cases you should put this port behind a reverse proxy, e.g.
|
||||
* nginx, apache, etc.
|
||||
*/
|
||||
struct discord_webhook_server : public http_server {
|
||||
|
||||
/**
|
||||
* @brief Verifier for signed requests
|
||||
*/
|
||||
signature_verifier verifier;
|
||||
|
||||
/**
|
||||
* @brief Public key from application dashboard
|
||||
*/
|
||||
std::string public_key_hex;
|
||||
|
||||
/**
|
||||
* @brief Constructor for creation of a HTTP(S) server
|
||||
* @param creator Cluster creator
|
||||
* @param discord_public_key Public key for the application from the application dashboard page
|
||||
* @param address address to bind to, use "0.0.0.0" to bind to all local addresses
|
||||
* @param port port to bind to. You should generally use a port > 1024.
|
||||
* @param ssl_private_key Private key PEM file for HTTPS/SSL. If empty, a plaintext server is created
|
||||
* @param ssl_public_key Public key PEM file for HTTPS/SSL. If empty, a plaintext server is created
|
||||
*/
|
||||
discord_webhook_server(cluster* creator, const std::string& discord_public_key, const std::string_view address, uint16_t port, const std::string& ssl_private_key = "", const std::string& ssl_public_key = "");
|
||||
|
||||
/**
|
||||
* @brief Handle Discord outbound webhook
|
||||
* @param request Request from discord
|
||||
*/
|
||||
void handle_request(http_server_request* request);
|
||||
|
||||
/**
|
||||
* @brief Virtual dtor
|
||||
*/
|
||||
virtual ~discord_webhook_server() = default;
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,624 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/wsclient.h>
|
||||
#include <dpp/dispatcher.h>
|
||||
#include <dpp/event.h>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <memory>
|
||||
#include <deque>
|
||||
#include <dpp/etf.h>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <dpp/zlibcontext.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Discord API version for shard websockets and HTTPS API requests
|
||||
*/
|
||||
#define DISCORD_API_VERSION "10"
|
||||
|
||||
/**
|
||||
* @brief HTTPS Request base path for API calls
|
||||
*/
|
||||
#define API_PATH "/api/v" DISCORD_API_VERSION
|
||||
|
||||
/* Forward declarations */
|
||||
class cluster;
|
||||
|
||||
/**
|
||||
* @brief How many seconds to wait between (re)connections. DO NOT change this.
|
||||
* It is mandated by the Discord API spec!
|
||||
*/
|
||||
constexpr time_t RECONNECT_INTERVAL = 5;
|
||||
|
||||
/**
|
||||
* @brief Represents different event opcodes sent and received on a shard websocket
|
||||
*
|
||||
* These are used internally to route frames.
|
||||
*/
|
||||
enum shard_frame_type : int {
|
||||
|
||||
/**
|
||||
* @brief An event was dispatched.
|
||||
* @note Receive only
|
||||
*/
|
||||
ft_dispatch = 0,
|
||||
|
||||
/**
|
||||
* @brief Fired periodically by the client to keep the connection alive.
|
||||
* @note Send/Receive
|
||||
*/
|
||||
ft_heartbeat = 1,
|
||||
|
||||
/**
|
||||
* @brief Starts a new session during the initial handshake.
|
||||
* @note Send only
|
||||
*/
|
||||
ft_identify = 2,
|
||||
|
||||
/**
|
||||
* @brief Update the client's presence.
|
||||
* @note Send only
|
||||
*/
|
||||
ft_presence = 3,
|
||||
|
||||
/**
|
||||
* @brief Used to join/leave or move between voice channels.
|
||||
* @note Send only
|
||||
*/
|
||||
ft_voice_state_update = 4,
|
||||
|
||||
/**
|
||||
* @brief Resume a previous session that was disconnected.
|
||||
* @note Send only
|
||||
*/
|
||||
ft_resume = 6,
|
||||
|
||||
/**
|
||||
* @brief You should attempt to reconnect and resume immediately.
|
||||
* @note Receive only
|
||||
*/
|
||||
ft_reconnect = 7,
|
||||
|
||||
/**
|
||||
* @brief Request information about offline guild members in a large guild.
|
||||
* @note Send only
|
||||
*/
|
||||
ft_request_guild_members = 8,
|
||||
|
||||
/**
|
||||
* @brief The session has been invalidated. You should reconnect and identify/resume accordingly.
|
||||
* @note Receive only
|
||||
*/
|
||||
ft_invalid_session = 9,
|
||||
|
||||
/**
|
||||
* @brief Sent immediately after connecting, contains the heartbeat interval to use.
|
||||
* @note Receive only
|
||||
*/
|
||||
ft_hello = 10,
|
||||
|
||||
/**
|
||||
* @brief Sent in response to receiving a heartbeat to acknowledge that it has been received.
|
||||
* @note Receive only
|
||||
*/
|
||||
ft_heartbeat_ack = 11,
|
||||
|
||||
/**
|
||||
* @brief Request information about soundboard sounds in a set of guilds.
|
||||
* @note Send only
|
||||
*/
|
||||
ft_request_soundboard_sounds = 31,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a connection to a voice channel.
|
||||
* A client can only connect to one voice channel per guild at a time, so these are stored in a map
|
||||
* in the dpp::discord_client keyed by guild_id.
|
||||
*/
|
||||
class DPP_EXPORT voiceconn {
|
||||
/**
|
||||
* @brief Owning dpp::discord_client instance
|
||||
*/
|
||||
class discord_client* creator;
|
||||
public:
|
||||
/**
|
||||
* @brief Voice Channel ID
|
||||
*/
|
||||
snowflake channel_id;
|
||||
|
||||
/**
|
||||
* @brief Websocket hostname for status
|
||||
*/
|
||||
std::string websocket_hostname;
|
||||
|
||||
/**
|
||||
* @brief Voice Voice session ID
|
||||
*/
|
||||
std::string session_id;
|
||||
|
||||
/**
|
||||
* @brief Voice websocket token
|
||||
*/
|
||||
std::string token;
|
||||
|
||||
/**
|
||||
* @brief voice websocket client
|
||||
*/
|
||||
class discord_voice_client* voiceclient;
|
||||
|
||||
/**
|
||||
* @brief True to enable DAVE E2EE
|
||||
* @warning This is an EXPERIMENTAL feature!
|
||||
*/
|
||||
bool dave;
|
||||
|
||||
/**
|
||||
* @brief Construct a new voiceconn object
|
||||
*/
|
||||
voiceconn() = default;
|
||||
|
||||
/**
|
||||
* @brief Construct a new voiceconn object
|
||||
*
|
||||
* @param o owner
|
||||
* @param _channel_id voice channel id
|
||||
* @param enable_dave True to enable DAVE E2EE
|
||||
* @warn DAVE is an EXPERIMENTAL feature!
|
||||
*/
|
||||
voiceconn(class discord_client* o, snowflake _channel_id, bool enable_dave);
|
||||
|
||||
/**
|
||||
* @brief Destroy the voiceconn object
|
||||
*/
|
||||
~voiceconn();
|
||||
|
||||
/**
|
||||
* @brief return true if the connection is ready to connect
|
||||
* (has hostname, token and session id)
|
||||
*
|
||||
* @return true if ready to connect
|
||||
*/
|
||||
bool is_ready() const;
|
||||
|
||||
/**
|
||||
* @brief return true if the connection is active (websocket exists)
|
||||
*
|
||||
* @return true if has an active websocket
|
||||
*/
|
||||
bool is_active() const;
|
||||
|
||||
/**
|
||||
* @brief Create websocket object and connect it.
|
||||
* Needs hostname, token and session_id to be set or does nothing.
|
||||
*
|
||||
* @param guild_id Guild to connect to the voice channel on
|
||||
* @return reference to self
|
||||
* @note It can spawn a thread to establish the connection, so this is NOT a synchronous blocking call!
|
||||
* You shouldn't call this directly. Use a wrapper function instead. e.g. dpp::guild::connect_member_voice
|
||||
*/
|
||||
voiceconn& connect(snowflake guild_id);
|
||||
|
||||
/**
|
||||
* @brief Disconnect from the currently connected voice channel
|
||||
* @return reference to self
|
||||
*/
|
||||
voiceconn& disconnect();
|
||||
|
||||
/**
|
||||
* @brief Reassigns the owner to the given discord_client.
|
||||
*/
|
||||
void reassign_owner(class discord_client* o);
|
||||
};
|
||||
|
||||
/** @brief Implements a discord client. Each discord_client connects to one shard and derives from a websocket client. */
|
||||
class DPP_EXPORT discord_client : public websocket_client
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* @brief Needed so that voice_state_update can call dpp::discord_client::disconnect_voice_internal
|
||||
*/
|
||||
friend class dpp::events::voice_state_update;
|
||||
|
||||
/**
|
||||
* @brief Needed so that guild_create can request member chunks if you have the correct intents
|
||||
*/
|
||||
friend class dpp::events::guild_create;
|
||||
|
||||
/**
|
||||
* @brief Needed to allow cluster::set_presence to use the ETF functions
|
||||
*/
|
||||
friend class dpp::cluster;
|
||||
|
||||
/**
|
||||
* @brief Disconnect from the connected voice channel on a guild
|
||||
*
|
||||
* @param guild_id The guild who's voice channel you wish to disconnect from
|
||||
* @param send_json True if we should send a json message confirming we are leaving the VC
|
||||
* Should be set to false if we already receive this message in an event.
|
||||
*/
|
||||
void disconnect_voice_internal(snowflake guild_id, bool send_json = true);
|
||||
|
||||
/**
|
||||
* @brief Start connecting the websocket
|
||||
*
|
||||
* Called from the constructor, or during reconnection
|
||||
*/
|
||||
void start_connecting();
|
||||
|
||||
/**
|
||||
* @brief Stores the most recent ping message on this shard, which we check
|
||||
* for to monitor latency
|
||||
*/
|
||||
std::string last_ping_message;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Mutex for message queue
|
||||
*/
|
||||
std::shared_mutex queue_mutex;
|
||||
|
||||
/**
|
||||
* @brief Mutex for zlib pointer
|
||||
*/
|
||||
std::mutex zlib_mutex;
|
||||
|
||||
/**
|
||||
* @brief Queue of outbound messages
|
||||
*/
|
||||
std::deque<std::string> message_queue;
|
||||
|
||||
/**
|
||||
* @brief If true, stream compression is enabled
|
||||
*/
|
||||
bool compressed;
|
||||
|
||||
/**
|
||||
* @brief Decompressed string
|
||||
*/
|
||||
std::string decompressed;
|
||||
|
||||
/**
|
||||
* @brief This object contains the various zlib structs which
|
||||
* are not usable by the user of the library directly. They
|
||||
* are wrapped within this opaque object so that this header
|
||||
* file does not bring in a dependency on zlib.h.
|
||||
*/
|
||||
std::unique_ptr<zlibcontext> zlib{};
|
||||
|
||||
/**
|
||||
* @brief Last connect time of cluster
|
||||
*/
|
||||
time_t connect_time;
|
||||
|
||||
/**
|
||||
* @brief Time last ping sent to websocket, in fractional seconds
|
||||
*/
|
||||
double ping_start;
|
||||
|
||||
/**
|
||||
* @brief ETF parser for when in ws_etf mode
|
||||
*/
|
||||
std::unique_ptr<etf_parser> etf;
|
||||
|
||||
/**
|
||||
* @brief Convert a JSON object to string.
|
||||
* In JSON protocol mode, call json.dump(), and in ETF mode,
|
||||
* call etf::build().
|
||||
*
|
||||
* @param json nlohmann::json object to convert
|
||||
* @return std::string string output in the correct format
|
||||
*/
|
||||
std::string jsonobj_to_string(const nlohmann::json& json);
|
||||
|
||||
/**
|
||||
* @brief Update the websocket hostname with the resume url
|
||||
* from the last READY event
|
||||
*/
|
||||
void set_resume_hostname();
|
||||
|
||||
/**
|
||||
* @brief Clean up resources
|
||||
*/
|
||||
void cleanup();
|
||||
public:
|
||||
/**
|
||||
* @brief Owning cluster
|
||||
*/
|
||||
class dpp::cluster* creator;
|
||||
|
||||
/**
|
||||
* @brief Heartbeat interval for sending heartbeat keepalive
|
||||
* @note value in milliseconds
|
||||
*/
|
||||
uint32_t heartbeat_interval;
|
||||
|
||||
/**
|
||||
* @brief Last heartbeat
|
||||
*/
|
||||
time_t last_heartbeat;
|
||||
|
||||
/**
|
||||
* @brief Shard ID of this client
|
||||
*/
|
||||
uint32_t shard_id;
|
||||
|
||||
/**
|
||||
* @brief Total number of shards
|
||||
*/
|
||||
uint32_t max_shards;
|
||||
|
||||
/**
|
||||
* @brief Last sequence number received, for resumes and pings
|
||||
*/
|
||||
uint64_t last_seq;
|
||||
|
||||
/**
|
||||
* @brief Discord bot token
|
||||
*/
|
||||
std::string token;
|
||||
|
||||
/**
|
||||
* @brief Privileged gateway intents
|
||||
* @see dpp::intents
|
||||
*/
|
||||
uint32_t intents;
|
||||
|
||||
/**
|
||||
* @brief Discord session id
|
||||
*/
|
||||
std::string sessionid;
|
||||
|
||||
/**
|
||||
* @brief Mutex for voice connections map
|
||||
*/
|
||||
std::shared_mutex voice_mutex;
|
||||
|
||||
/**
|
||||
* @brief Resume count
|
||||
*/
|
||||
uint32_t resumes;
|
||||
|
||||
/**
|
||||
* @brief Reconnection count
|
||||
*/
|
||||
uint32_t reconnects;
|
||||
|
||||
/**
|
||||
* @brief Websocket latency in fractional seconds
|
||||
*/
|
||||
double websocket_ping;
|
||||
|
||||
/**
|
||||
* @brief True if READY or RESUMED has been received
|
||||
*/
|
||||
bool ready;
|
||||
|
||||
/**
|
||||
* @brief Last heartbeat ACK (opcode 11)
|
||||
*/
|
||||
time_t last_heartbeat_ack;
|
||||
|
||||
/**
|
||||
* @brief Current websocket protocol, currently either ETF or JSON
|
||||
*/
|
||||
websocket_protocol_t protocol;
|
||||
|
||||
/**
|
||||
* @brief List of voice channels we are connecting to keyed by guild id
|
||||
*/
|
||||
std::unordered_map<snowflake, std::unique_ptr<voiceconn>> connecting_voice_channels;
|
||||
|
||||
/**
|
||||
* @brief The gateway address we reconnect to when we resume a session
|
||||
*/
|
||||
std::string resume_gateway_url;
|
||||
|
||||
/**
|
||||
* @brief Log a message to whatever log the user is using.
|
||||
* The logged message is passed up the chain to the on_log event in user code which can then do whatever
|
||||
* it wants to do with it.
|
||||
* @param severity The log level from dpp::loglevel
|
||||
* @param msg The log message to output
|
||||
*/
|
||||
virtual void log(dpp::loglevel severity, const std::string &msg) const override;
|
||||
|
||||
/**
|
||||
* @brief Handle an event (opcode 0)
|
||||
* @param event Event name, e.g. MESSAGE_CREATE
|
||||
* @param j JSON object for the event content
|
||||
* @param raw Raw JSON event string
|
||||
*/
|
||||
virtual void handle_event(const std::string &event, json &j, const std::string &raw);
|
||||
|
||||
/**
|
||||
* @brief Get the Guild Count for this shard
|
||||
*
|
||||
* @return uint64_t guild count
|
||||
*/
|
||||
uint64_t get_guild_count();
|
||||
|
||||
/**
|
||||
* @brief Get the Member Count for this shard
|
||||
*
|
||||
* @return uint64_t member count
|
||||
*/
|
||||
uint64_t get_member_count();
|
||||
|
||||
/**
|
||||
* @brief Get the Channel Count for this shard
|
||||
*
|
||||
* @return uint64_t channel count
|
||||
*/
|
||||
uint64_t get_channel_count();
|
||||
|
||||
/**
|
||||
* @brief Fires every second from the underlying socket I/O loop, used for sending heartbeats
|
||||
* and any queued outbound websocket frames.
|
||||
*/
|
||||
virtual void one_second_timer() override;
|
||||
|
||||
/**
|
||||
* @brief Queue a message to be sent via the websocket
|
||||
*
|
||||
* @param j The JSON data of the message to be sent
|
||||
* @param to_front If set to true, will place the message at the front of the queue not the back
|
||||
* (this is for urgent messages such as heartbeat, presence, so they can take precedence over
|
||||
* chunk requests etc)
|
||||
*/
|
||||
void queue_message(const std::string &j, bool to_front = false);
|
||||
|
||||
/**
|
||||
* @brief Clear the outbound message queue
|
||||
* @return reference to self
|
||||
*/
|
||||
discord_client& clear_queue();
|
||||
|
||||
/**
|
||||
* @brief Get the size of the outbound message queue
|
||||
*
|
||||
* @return The size of the queue
|
||||
*/
|
||||
size_t get_queue_size();
|
||||
|
||||
/**
|
||||
* @brief Returns true if the shard is connected
|
||||
*
|
||||
* @return True if connected
|
||||
*/
|
||||
bool is_connected();
|
||||
|
||||
/**
|
||||
* @brief Returns the connection time of the shard
|
||||
*
|
||||
* @return dpp::utility::uptime Detail of how long the shard has been connected for
|
||||
*/
|
||||
dpp::utility::uptime get_uptime();
|
||||
|
||||
/**
|
||||
* @brief Construct a new discord_client object
|
||||
*
|
||||
* @param _cluster The owning cluster for this shard
|
||||
* @param _shard_id The ID of the shard to start
|
||||
* @param _max_shards The total number of shards across all clusters
|
||||
* @param _token The bot token to use for identifying to the websocket
|
||||
* @param intents Privileged intents to use, a bitmask of values from dpp::intents
|
||||
* @param compressed True if the received data will be gzip compressed
|
||||
* @param ws_protocol Websocket protocol to use for the connection, JSON or ETF
|
||||
*
|
||||
* @throws std::bad_alloc Passed up to the caller if any internal objects fail to allocate, after cleanup has completed
|
||||
*/
|
||||
discord_client(dpp::cluster* _cluster, uint32_t _shard_id, uint32_t _max_shards, const std::string &_token, uint32_t intents = 0, bool compressed = true, websocket_protocol_t ws_protocol = ws_json);
|
||||
|
||||
/**
|
||||
* @brief Construct a discord_client object from another discord_client object
|
||||
* Used when resuming, the url to connect to will be taken from the resume url of the
|
||||
* other object, along with the seq number.
|
||||
*
|
||||
* @param old Previous connection to resume from
|
||||
* @param sequence Sequence number of previous session
|
||||
* @param session_id Session ID of previous session
|
||||
*/
|
||||
explicit discord_client(discord_client& old, uint64_t sequence, const std::string& session_id);
|
||||
|
||||
/**
|
||||
* @brief Destroy the discord client object
|
||||
*/
|
||||
virtual ~discord_client() = default;
|
||||
|
||||
/**
|
||||
* @brief Get decompressed total bytes received
|
||||
*
|
||||
* This will always return 0 if the connection is not compressed
|
||||
* @return uint64_t compressed bytes received
|
||||
*/
|
||||
uint64_t get_decompressed_bytes_in();
|
||||
|
||||
/**
|
||||
* @brief Handle JSON from the websocket.
|
||||
* @param buffer The entire buffer content from the websocket client
|
||||
* @param opcode The type of frame, e.g. text or binary
|
||||
* @returns True if a frame has been handled
|
||||
*/
|
||||
virtual bool handle_frame(const std::string &buffer, ws_opcode opcode) override;
|
||||
|
||||
/**
|
||||
* @brief Handle a websocket error.
|
||||
* @param errorcode The error returned from the websocket
|
||||
*/
|
||||
virtual void error(uint32_t errorcode) override;
|
||||
|
||||
/**
|
||||
* @brief Start and monitor I/O loop.
|
||||
*/
|
||||
void run();
|
||||
|
||||
/**
|
||||
* @brief Called when the HTTP socket is closed
|
||||
*/
|
||||
virtual void on_disconnect() override;
|
||||
|
||||
/**
|
||||
* @brief Connect to a voice channel
|
||||
*
|
||||
* @param guild_id Guild where the voice channel is
|
||||
* @param channel_id Channel ID of the voice channel
|
||||
* @param self_mute True if the bot should mute itself
|
||||
* @param self_deaf True if the bot should deafen itself
|
||||
* @param enable_dave True to enable DAVE E2EE - EXPERIMENTAL
|
||||
* @return reference to self
|
||||
* @note This is NOT a synchronous blocking call! The bot isn't instantly ready to send or listen for audio,
|
||||
* as we have to wait for the connection to the voice server to be established!
|
||||
* e.g. wait for dpp::cluster::on_voice_ready event, and then send the audio within that event.
|
||||
*/
|
||||
discord_client& connect_voice(snowflake guild_id, snowflake channel_id, bool self_mute = false, bool self_deaf = false, bool enable_dave = false);
|
||||
|
||||
/**
|
||||
* @brief Disconnect from the connected voice channel on a guild
|
||||
*
|
||||
* @param guild_id The guild who's voice channel you wish to disconnect from
|
||||
* @return reference to self
|
||||
* @note This is NOT a synchronous blocking call! The bot isn't instantly disconnected.
|
||||
*/
|
||||
discord_client& disconnect_voice(snowflake guild_id);
|
||||
|
||||
/**
|
||||
* @brief Get the dpp::voiceconn object for a specific guild on this shard.
|
||||
*
|
||||
* @param guild_id The guild ID to retrieve the voice connection for
|
||||
* @return voiceconn* The voice connection for the guild, or nullptr if there is no
|
||||
* voice connection to this guild.
|
||||
*/
|
||||
voiceconn* get_voice(snowflake guild_id);
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,232 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/json_interface.h>
|
||||
#include <dpp/utility.h>
|
||||
#include <string_view>
|
||||
#include <functional>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Returns a snowflake id from a json field value, if defined, else returns 0
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @return found value
|
||||
*/
|
||||
uint64_t DPP_EXPORT snowflake_not_null(const nlohmann::json* j, const char *keyname);
|
||||
|
||||
/**
|
||||
* @brief Sets a snowflake id from a json field value, if defined, else does nothing
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @param v Value to change
|
||||
*/
|
||||
void DPP_EXPORT set_snowflake_not_null(const nlohmann::json* j, const char *keyname, uint64_t &v);
|
||||
|
||||
/**
|
||||
* @brief Sets an array of snowflakes from a json field value, if defined, else does nothing
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for the values
|
||||
* @param v Value to change
|
||||
*/
|
||||
void DPP_EXPORT set_snowflake_array_not_null(const nlohmann::json* j, const char *keyname, std::vector<class snowflake> &v);
|
||||
|
||||
/**
|
||||
* @brief Applies a function to each element of a json array.
|
||||
* @param parent nlohmann::json instance to retrieve value from
|
||||
* @param key key name to check for the values
|
||||
* @param fn function to apply to each element
|
||||
*/
|
||||
void DPP_EXPORT for_each_json(nlohmann::json* parent, std::string_view key, const std::function<void(nlohmann::json*)> &fn);
|
||||
|
||||
/**
|
||||
* @brief Sets an array of objects from a json field value, if defined, else does nothing
|
||||
* @tparam T The class of which the array consists of. Must be derived from dpp::json_interface
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param key key name to check for the values
|
||||
* @param v Value to change
|
||||
*/
|
||||
template<class T> void set_object_array_not_null(nlohmann::json* j, std::string_view key, std::vector<T>& v) {
|
||||
v.clear();
|
||||
for_each_json(j, key, [&v](nlohmann::json* elem) {
|
||||
v.push_back(T{}.fill_from_json(elem));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a string from a json field value, if defined, else returns an empty string.
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @return found value
|
||||
*/
|
||||
std::string DPP_EXPORT string_not_null(const nlohmann::json* j, const char *keyname);
|
||||
|
||||
/**
|
||||
* @brief Sets a string from a json field value, if defined, else does nothing
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @param v Value to change
|
||||
*/
|
||||
void DPP_EXPORT set_string_not_null(const nlohmann::json* j, const char *keyname, std::string &v);
|
||||
|
||||
/**
|
||||
* @brief This is a repeat of set_string_not_null, but takes in a iconhash.
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @param v Value to change
|
||||
*/
|
||||
void DPP_EXPORT set_iconhash_not_null(const nlohmann::json* j, const char *keyname, utility::iconhash &v);
|
||||
|
||||
/**
|
||||
* @brief Returns a double from a json field value, if defined, else returns 0.
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @return found value
|
||||
*/
|
||||
double DPP_EXPORT double_not_null(const nlohmann::json* j, const char *keyname);
|
||||
|
||||
/**
|
||||
* @brief Sets a double from a json field value, if defined, else does nothing
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @param v Value to change
|
||||
*/
|
||||
void DPP_EXPORT set_double_not_null(const nlohmann::json* j, const char *keyname, double &v);
|
||||
|
||||
/**
|
||||
* @brief Returns a 64 bit unsigned integer from a json field value, if defined, else returns 0.
|
||||
* DO NOT use this for snowflakes, as usually snowflakes are wrapped in a string!
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @return found value
|
||||
*/
|
||||
uint64_t DPP_EXPORT int64_not_null(const nlohmann::json* j, const char *keyname);
|
||||
|
||||
/**
|
||||
* @brief Sets an unsigned 64 bit integer from a json field value, if defined, else does nothing
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @param v Value to change
|
||||
*/
|
||||
void DPP_EXPORT set_int64_not_null(const nlohmann::json* j, const char *keyname, uint64_t &v);
|
||||
|
||||
/**
|
||||
* @brief Returns a 32 bit unsigned integer from a json field value, if defined, else returns 0
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @return found value
|
||||
*/
|
||||
uint32_t DPP_EXPORT int32_not_null(const nlohmann::json* j, const char *keyname);
|
||||
|
||||
/**
|
||||
* @brief Sets an unsigned 32 bit integer from a json field value, if defined, else does nothing
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @param v Value to change
|
||||
*/
|
||||
void DPP_EXPORT set_int32_not_null(const nlohmann::json* j, const char *keyname, uint32_t &v);
|
||||
|
||||
/**
|
||||
* @brief Returns a 16 bit unsigned integer from a json field value, if defined, else returns 0
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @return found value
|
||||
*/
|
||||
uint16_t DPP_EXPORT int16_not_null(const nlohmann::json* j, const char *keyname);
|
||||
|
||||
/**
|
||||
* @brief Sets an unsigned 16 bit integer from a json field value, if defined, else does nothing
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @param v Value to change
|
||||
*/
|
||||
void DPP_EXPORT set_int16_not_null(const nlohmann::json* j, const char *keyname, uint16_t &v);
|
||||
|
||||
/**
|
||||
* @brief Returns an 8 bit unsigned integer from a json field value, if defined, else returns 0
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @return found value
|
||||
*/
|
||||
uint8_t DPP_EXPORT int8_not_null(const nlohmann::json* j, const char *keyname);
|
||||
|
||||
/**
|
||||
* @brief Sets an unsigned 8 bit integer from a json field value, if defined, else does nothing
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @param v Value to change
|
||||
*/
|
||||
void DPP_EXPORT set_int8_not_null(const nlohmann::json* j, const char *keyname, uint8_t &v);
|
||||
|
||||
/**
|
||||
* @brief Returns a boolean value from a json field value, if defined, else returns false
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @return found value
|
||||
*/
|
||||
bool DPP_EXPORT bool_not_null(const nlohmann::json* j, const char *keyname);
|
||||
|
||||
/**
|
||||
* @brief Sets a boolean from a json field value, if defined, else does nothing
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @param v Value to change
|
||||
*/
|
||||
void DPP_EXPORT set_bool_not_null(const nlohmann::json* j, const char *keyname, bool &v);
|
||||
|
||||
/**
|
||||
* @brief Returns a time_t from an ISO8601 timestamp field in a json value, if defined, else returns
|
||||
* epoch value of 0.
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @return found value
|
||||
*/
|
||||
time_t DPP_EXPORT ts_not_null(const nlohmann::json* j, const char *keyname);
|
||||
|
||||
/**
|
||||
* @brief Sets an timestamp from a json field value containing an ISO8601 string, if defined, else does nothing
|
||||
* @param j nlohmann::json instance to retrieve value from
|
||||
* @param keyname key name to check for a value
|
||||
* @param v Value to change
|
||||
*/
|
||||
void DPP_EXPORT set_ts_not_null(const nlohmann::json* j, const char *keyname, time_t &v);
|
||||
|
||||
/**
|
||||
* @brief Base64 encode data into a string.
|
||||
* @param buf Raw binary buffer
|
||||
* @param buffer_length Buffer length to encode
|
||||
* @return The base64 encoded string
|
||||
*/
|
||||
std::string DPP_EXPORT base64_encode(unsigned char const* buf, unsigned int buffer_length);
|
||||
|
||||
/**
|
||||
* @brief Convert time_t unix epoch to std::string ISO date/time
|
||||
*
|
||||
* @param ts Timestamp to convert
|
||||
* @return std::string Converted time/date string
|
||||
*/
|
||||
std::string DPP_EXPORT ts_to_string(time_t ts);
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
2319
dpp/dispatcher.h
2319
dpp/dispatcher.h
File diff suppressed because it is too large
Load Diff
98
dpp/dns.h
98
dpp/dns.h
@ -1,98 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#ifdef _WIN32
|
||||
#include <WinSock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
#else
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <dpp/socket.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Represents a cached DNS result.
|
||||
* Used by the ssl_connection class to store cached copies of dns lookups.
|
||||
*/
|
||||
struct DPP_EXPORT dns_cache_entry {
|
||||
/**
|
||||
* @brief Resolved address metadata
|
||||
*/
|
||||
addrinfo addr;
|
||||
|
||||
/**
|
||||
* @brief Resolved address as string.
|
||||
* The metadata is needed to know what type of address it is.
|
||||
* Do not do silly stuff like just looking to see if '.' is in it!
|
||||
*/
|
||||
std::string resolved_addr;
|
||||
|
||||
/**
|
||||
* @brief Time at which this cache entry is invalidated
|
||||
*/
|
||||
time_t expire_timestamp;
|
||||
|
||||
/**
|
||||
* @brief Get address length
|
||||
* @return address length
|
||||
*/
|
||||
[[nodiscard]] int size() const;
|
||||
|
||||
/**
|
||||
* @brief Get the address_t that corresponds to this cache entry
|
||||
* for use when connecting with ::connect()
|
||||
* @param port Port number to connect to
|
||||
* @return address_t prefilled with the IP and port number
|
||||
*/
|
||||
[[nodiscard]] const address_t get_connecting_address(uint16_t port) const;
|
||||
|
||||
/**
|
||||
* @brief Allocate a socket file descriptor for the given dns address
|
||||
* @return File descriptor ready for calling connect(), or INVALID_SOCKET
|
||||
* on failure.
|
||||
*/
|
||||
[[nodiscard]] socket make_connecting_socket() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Cache container type
|
||||
*/
|
||||
using dns_cache_t = std::unordered_map<std::string, std::unique_ptr<dns_cache_entry>>;
|
||||
|
||||
/**
|
||||
* @brief Resolve a hostname to an addrinfo
|
||||
*
|
||||
* @param hostname Hostname to resolve
|
||||
* @param port A port number or named service, e.g. "80"
|
||||
* @return dns_cache_entry* First IP address associated with the hostname DNS record
|
||||
* @throw dpp::connection_exception On failure to resolve hostname
|
||||
*/
|
||||
DPP_EXPORT const dns_cache_entry *resolve_hostname(const std::string &hostname, const std::string &port);
|
||||
}
|
||||
82
dpp/dpp.h
82
dpp/dpp.h
@ -1,82 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/version.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include <dpp/exception.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/misc-enum.h>
|
||||
#include <dpp/stringops.h>
|
||||
#include <dpp/managed.h>
|
||||
#include <dpp/socketengine.h>
|
||||
#include <dpp/utility.h>
|
||||
#include <dpp/voicestate.h>
|
||||
#include <dpp/permissions.h>
|
||||
#include <dpp/role.h>
|
||||
#include <dpp/user.h>
|
||||
#include <dpp/channel.h>
|
||||
#include <dpp/thread.h>
|
||||
#include <dpp/guild.h>
|
||||
#include <dpp/invite.h>
|
||||
#include <dpp/dtemplate.h>
|
||||
#include <dpp/emoji.h>
|
||||
#include <dpp/ban.h>
|
||||
#include <dpp/prune.h>
|
||||
#include <dpp/voiceregion.h>
|
||||
#include <dpp/integration.h>
|
||||
#include <dpp/webhook.h>
|
||||
#include <dpp/presence.h>
|
||||
#include <dpp/intents.h>
|
||||
#include <dpp/message.h>
|
||||
#include <dpp/appcommand.h>
|
||||
#include <dpp/stage_instance.h>
|
||||
#include <dpp/auditlog.h>
|
||||
#include <dpp/application.h>
|
||||
#include <dpp/scheduled_event.h>
|
||||
#include <dpp/discordclient.h>
|
||||
#include <dpp/dispatcher.h>
|
||||
#include <dpp/cluster.h>
|
||||
#include <dpp/cache.h>
|
||||
#include <dpp/httpsclient.h>
|
||||
#include <dpp/queues.h>
|
||||
#include <dpp/commandhandler.h>
|
||||
#include <dpp/once.h>
|
||||
#include <dpp/colors.h>
|
||||
#include <dpp/discordevents.h>
|
||||
#include <dpp/timed_listener.h>
|
||||
#include <dpp/collector.h>
|
||||
#include <dpp/bignum.h>
|
||||
#include <dpp/thread_pool.h>
|
||||
#include <dpp/signature_verifier.h>
|
||||
#include <dpp/socket_listener.h>
|
||||
#include <dpp/http_server.h>
|
||||
#include <dpp/discord_webhook_server.h>
|
||||
115
dpp/dtemplate.h
115
dpp/dtemplate.h
@ -1,115 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <unordered_map>
|
||||
#include <dpp/json_interface.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Represents a guild template
|
||||
*/
|
||||
class DPP_EXPORT dtemplate : public json_interface<dtemplate> {
|
||||
protected:
|
||||
friend struct json_interface<dtemplate>;
|
||||
|
||||
/** Read class values from json object
|
||||
* @param j A json object to read from
|
||||
* @return A reference to self
|
||||
*/
|
||||
dtemplate& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Build the JSON for this object
|
||||
*
|
||||
* @param with_id Add ID to output
|
||||
* @return json JSON content
|
||||
*/
|
||||
json to_json_impl(bool with_id = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Template code
|
||||
*/
|
||||
std::string code;
|
||||
|
||||
/**
|
||||
* @brief Template name
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* @brief Template description
|
||||
*/
|
||||
std::string description;
|
||||
|
||||
/**
|
||||
* @brief Usage counter
|
||||
*/
|
||||
uint32_t usage_count;
|
||||
|
||||
/**
|
||||
* @brief User ID of creator
|
||||
*/
|
||||
snowflake creator_id;
|
||||
|
||||
/**
|
||||
* @brief Creation date/time
|
||||
*
|
||||
*/
|
||||
time_t created_at;
|
||||
|
||||
/**
|
||||
* @brief Last update date/time
|
||||
*/
|
||||
time_t updated_at;
|
||||
|
||||
/**
|
||||
* @brief Guild id the template is created from
|
||||
*/
|
||||
snowflake source_guild_id;
|
||||
|
||||
/**
|
||||
* @brief True if needs synchronising
|
||||
*/
|
||||
bool is_dirty;
|
||||
|
||||
/**
|
||||
* @brief Construct a new dtemplate object
|
||||
*/
|
||||
dtemplate();
|
||||
|
||||
/**
|
||||
* @brief Destroy the dtemplate object
|
||||
*/
|
||||
virtual ~dtemplate() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A container of invites
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, dtemplate> dtemplate_map;
|
||||
|
||||
}
|
||||
252
dpp/emoji.h
252
dpp/emoji.h
@ -1,252 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/misc-enum.h>
|
||||
#include <dpp/managed.h>
|
||||
#include <dpp/utility.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <unordered_map>
|
||||
#include <dpp/json_interface.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
#define MAX_EMOJI_SIZE 256 * 1024
|
||||
|
||||
/**
|
||||
* @brief Flags for dpp::emoji
|
||||
*/
|
||||
enum emoji_flags : uint8_t {
|
||||
/**
|
||||
* @brief Emoji requires colons.
|
||||
*/
|
||||
e_require_colons = 0b00000001,
|
||||
|
||||
/**
|
||||
* @brief Managed (introduced by application)
|
||||
*/
|
||||
e_managed = 0b00000010,
|
||||
|
||||
/**
|
||||
* @brief Animated emoji.
|
||||
*/
|
||||
e_animated = 0b00000100,
|
||||
|
||||
/**
|
||||
* @brief Available (false if the guild doesn't meet boosting criteria, etc)
|
||||
*/
|
||||
e_available = 0b00001000,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents an emoji for a dpp::guild
|
||||
*/
|
||||
class DPP_EXPORT emoji : public managed, public json_interface<emoji> {
|
||||
protected:
|
||||
friend struct json_interface<emoji>;
|
||||
|
||||
/**
|
||||
* @brief Read class values from json object
|
||||
*
|
||||
* @param j A json object to read from
|
||||
* @return A reference to self
|
||||
*/
|
||||
emoji& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Build the json for this object
|
||||
*
|
||||
* @param with_id include the id in the JSON
|
||||
* @return std::string json data
|
||||
*/
|
||||
json to_json_impl(bool with_id = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Emoji name.
|
||||
*/
|
||||
std::string name{};
|
||||
|
||||
/**
|
||||
* @brief Roles allowed to use this emoji.
|
||||
*/
|
||||
std::vector<snowflake> roles;
|
||||
|
||||
/**
|
||||
* @brief The id of the user that created this emoji.
|
||||
*/
|
||||
snowflake user_id;
|
||||
|
||||
/**
|
||||
* @brief Image data for the emoji, if uploading.
|
||||
*/
|
||||
utility::image_data image_data;
|
||||
|
||||
/**
|
||||
* @brief Flags for the emoji from dpp::emoji_flags.
|
||||
*/
|
||||
uint8_t flags{0};
|
||||
|
||||
/**
|
||||
* @brief Construct a new emoji object
|
||||
*/
|
||||
emoji() = default;
|
||||
|
||||
/**
|
||||
* @brief Construct a new emoji object with name, ID and flags
|
||||
*
|
||||
* @param name The emoji's name
|
||||
* @param id ID, if it has one (unicode does not)
|
||||
* @param flags Emoji flags (emoji_flags)
|
||||
*/
|
||||
emoji(const std::string_view name, const snowflake id = 0, const uint8_t flags = 0);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor, copies another emoji's data
|
||||
*
|
||||
* @param rhs Emoji to copy
|
||||
*/
|
||||
emoji(const emoji &rhs) = default;
|
||||
|
||||
/**
|
||||
* @brief Move constructor, moves another emoji's data to this
|
||||
*
|
||||
* @param rhs Emoji to move from
|
||||
*/
|
||||
emoji(emoji &&rhs) noexcept = default;
|
||||
|
||||
/**
|
||||
* @brief Destroy the emoji object
|
||||
*/
|
||||
~emoji() override = default;
|
||||
|
||||
/**
|
||||
* @brief Copy assignment operator, copies another emoji's data
|
||||
*
|
||||
* @param rhs Emoji to copy
|
||||
*/
|
||||
emoji &operator=(const emoji &rhs) = default;
|
||||
|
||||
/**
|
||||
* @brief Move constructor, moves another emoji's data to this
|
||||
*
|
||||
* @param rhs Emoji to move from
|
||||
*/
|
||||
emoji &operator=(emoji &&rhs) noexcept = default;
|
||||
|
||||
/**
|
||||
* @brief Create a mentionable emoji
|
||||
* @param name The name of the emoji.
|
||||
* @param id The ID of the emoji.
|
||||
* @param is_animated is emoji animated.
|
||||
* @return std::string The formatted mention of the emoji.
|
||||
*/
|
||||
static std::string get_mention(std::string_view name, snowflake id, bool is_animated = false);
|
||||
|
||||
/**
|
||||
* @brief Emoji requires colons
|
||||
*
|
||||
* @return true Requires colons
|
||||
* @return false Does not require colons
|
||||
*/
|
||||
bool requires_colons() const;
|
||||
|
||||
/**
|
||||
* @brief Emoji is managed
|
||||
*
|
||||
* @return true Is managed
|
||||
* @return false Is not managed
|
||||
*/
|
||||
bool is_managed() const;
|
||||
|
||||
/**
|
||||
* @brief Emoji is animated
|
||||
*
|
||||
* @return true Is animated
|
||||
* @return false Is noy animated
|
||||
*/
|
||||
bool is_animated() const;
|
||||
|
||||
/**
|
||||
* @brief Is available
|
||||
*
|
||||
* @return true Is available
|
||||
* @return false Is unavailable
|
||||
*/
|
||||
bool is_available() const;
|
||||
|
||||
/**
|
||||
* @brief Load an image into the object
|
||||
*
|
||||
* @param image_blob Image binary data
|
||||
* @param type Type of image. It can be one of `i_gif`, `i_jpg` or `i_png`.
|
||||
* @return emoji& Reference to self
|
||||
* @throw dpp::length_exception Image content exceeds discord maximum of 256 kilobytes
|
||||
*/
|
||||
emoji& load_image(std::string_view image_blob, const image_type type);
|
||||
|
||||
/**
|
||||
* @brief Load an image into the object
|
||||
*
|
||||
* @param data Image binary data
|
||||
* @param size Size of the image.
|
||||
* @param type Type of image. It can be one of `i_gif`, `i_jpg` or `i_png`.
|
||||
* @return emoji& Reference to self
|
||||
* @throw dpp::length_exception Image content exceeds discord maximum of 256 kilobytes
|
||||
*/
|
||||
emoji& load_image(const std::byte* data, uint32_t size, const image_type type);
|
||||
|
||||
/**
|
||||
* @brief Format to name if unicode, name:id if has id or a:name:id if animated
|
||||
*
|
||||
* @return Formatted name for reactions
|
||||
*/
|
||||
std::string format() const;
|
||||
|
||||
/**
|
||||
* @brief Get the mention/ping for the emoji
|
||||
*
|
||||
* @return std::string mention
|
||||
*/
|
||||
std::string get_mention() const;
|
||||
|
||||
/**
|
||||
* @brief Get the custom emoji url
|
||||
*
|
||||
* @param size The size of the emoji in pixels. It can be any power of two between 16 and 4096,
|
||||
* otherwise the default sized emoji is returned.
|
||||
* @param format The format to use for the emoji. It can be one of `i_webp`, `i_jpg`, `i_png` or `i_gif`.
|
||||
* When passing `i_gif`, it returns an empty string for non-animated emojis. Consider using the `prefer_animated` parameter instead.
|
||||
* @param prefer_animated Whether you prefer gif format.
|
||||
* If true, it'll return gif format whenever the emoji is available as animated.
|
||||
* @return std::string emoji url or an empty string, if the id is not set
|
||||
*/
|
||||
std::string get_url(uint16_t size = 0, const image_type format = i_png, bool prefer_animated = true) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Group of emojis
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, emoji> emoji_map;
|
||||
|
||||
}
|
||||
@ -1,246 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/managed.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/json_interface.h>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief The type of entitlement.
|
||||
* */
|
||||
enum entitlement_type : uint8_t {
|
||||
/**
|
||||
* @brief Entitlement was purchased by user
|
||||
*/
|
||||
PURCHASE = 1,
|
||||
|
||||
/**
|
||||
* @brief Entitlement for Discord Nitro subscription
|
||||
*/
|
||||
PREMIUM_SUBSCRIPTION = 2,
|
||||
|
||||
/**
|
||||
* @brief Entitlement was gifted by developer
|
||||
*/
|
||||
DEVELOPER_GIFT = 3,
|
||||
|
||||
/**
|
||||
* @brief Entitlement was purchased by a dev in application test mode
|
||||
*/
|
||||
TEST_MODE_PURCHASE = 4,
|
||||
|
||||
/**
|
||||
* @brief Entitlement was granted when the SKU was free
|
||||
*/
|
||||
FREE_PURCHASE = 5,
|
||||
|
||||
/**
|
||||
* @brief Entitlement was gifted by another user
|
||||
*/
|
||||
USER_GIFT = 6,
|
||||
|
||||
/**
|
||||
* @brief Entitlement was claimed by user for free as a Nitro Subscriber
|
||||
*/
|
||||
PREMIUM_PURCHASE = 7,
|
||||
|
||||
/**
|
||||
* @brief Entitlement was purchased as an app subscription
|
||||
*/
|
||||
APPLICATION_SUBSCRIPTION = 8,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Entitlement flags.
|
||||
*/
|
||||
enum entitlement_flags : uint8_t {
|
||||
/**
|
||||
* @brief Entitlement was deleted
|
||||
*
|
||||
* @note Only discord staff can delete an entitlement via
|
||||
* their internal tooling. It should rarely happen except in cases
|
||||
* of fraud or chargeback.
|
||||
*/
|
||||
ent_deleted = 0b0000001,
|
||||
|
||||
/**
|
||||
* @brief Entitlement was consumed.
|
||||
*
|
||||
* @note A consumed entitlement is a used-up one-off purchase.
|
||||
*/
|
||||
ent_consumed = 0b0000010,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A definition of a discord entitlement.
|
||||
*
|
||||
* An entitlement is a user's connection to an SKU, basically a subscription
|
||||
* or a one-off purchase.
|
||||
*/
|
||||
class DPP_EXPORT entitlement : public managed, public json_interface<entitlement> {
|
||||
protected:
|
||||
friend struct json_interface<entitlement>;
|
||||
|
||||
/** Read class values from json object
|
||||
* @param j A json object to read from
|
||||
* @return A reference to self
|
||||
*/
|
||||
entitlement& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Build json for this entitlement object
|
||||
*
|
||||
* @param with_id include the ID in the json
|
||||
* @return json JSON object
|
||||
*/
|
||||
json to_json_impl(bool with_id = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief ID of the entitlement event
|
||||
*
|
||||
* Not sure if this remains constant, it does not relate to the SKU,
|
||||
* user, guild or subscription. Do not use it for anything except state
|
||||
* tracking.
|
||||
*/
|
||||
snowflake sku_id{0};
|
||||
|
||||
/**
|
||||
* @brief ID of the parent application
|
||||
*/
|
||||
snowflake application_id{0};
|
||||
|
||||
/**
|
||||
* @brief Subscription ID
|
||||
*
|
||||
* This is a unique identifier of the user or guilds subscription to the SKU.
|
||||
* It won't ever change.
|
||||
*/
|
||||
snowflake subscription_id{0};
|
||||
|
||||
/**
|
||||
* @brief Promotion id
|
||||
*
|
||||
* These are undocumented but given in examples in the docs.
|
||||
*/
|
||||
snowflake promotion_id{0};
|
||||
|
||||
/**
|
||||
* @brief Gift Code Flags (undocumented)
|
||||
*
|
||||
* Undocumented, but given in examples in the docs.
|
||||
*/
|
||||
uint8_t gift_code_flags{0};
|
||||
|
||||
/**
|
||||
* @brief Optional: ID of the user that is granted access to the entitlement's SKU
|
||||
*/
|
||||
snowflake user_id{0};
|
||||
|
||||
/**
|
||||
* @brief Optional: ID of the user that is granted access to the entitlement's SKU
|
||||
*
|
||||
* If a guild is provided, according to the examples the user who triggered the
|
||||
* purchase will also be passed in the user ID. The presence of a non-zero guild
|
||||
* id snowflake is indication it is a guild subscription.
|
||||
*/
|
||||
snowflake guild_id{0};
|
||||
|
||||
/**
|
||||
* @brief The type of entitlement.
|
||||
*/
|
||||
entitlement_type type = entitlement_type::APPLICATION_SUBSCRIPTION;
|
||||
|
||||
/**
|
||||
* @brief Optional: Start date at which the entitlement is valid.
|
||||
*
|
||||
* @note Not present when using test entitlements.
|
||||
*/
|
||||
time_t starts_at{0};
|
||||
|
||||
/**
|
||||
* @brief Optional: Date at which the entitlement is no longer valid.
|
||||
*
|
||||
* @note Not present when using test entitlements.
|
||||
*/
|
||||
time_t ends_at{0};
|
||||
|
||||
/**
|
||||
* @brief Flags bitmap from dpp::entitlement_flags
|
||||
*/
|
||||
uint16_t flags{0};
|
||||
|
||||
/**
|
||||
* @brief Construct a new entitlement object
|
||||
*/
|
||||
entitlement() = default;
|
||||
|
||||
/**
|
||||
* @brief Construct a new entitlement object with sku_id, ID, application_id, type, and flags.
|
||||
*
|
||||
* @param sku_id The ID of the SKU.
|
||||
* @param id The ID of the entitlement.
|
||||
* @param application_id The ID of the parent application.
|
||||
* @param type The type of entitlement (Should only ever be APPLICATION_SUBSCRIPTION unless you going to use this object as a parameter for dpp::cluster::entitlement_test_create).
|
||||
* @param flags The flags for the SKU from dpp::entitlement_flags.
|
||||
*/
|
||||
entitlement(const snowflake sku_id, const snowflake id = 0, const snowflake application_id = 0, const entitlement_type type = dpp::entitlement_type::APPLICATION_SUBSCRIPTION, const uint8_t flags = 0);
|
||||
|
||||
/**
|
||||
* @brief Get the type of entitlement.
|
||||
*
|
||||
* @return entitlement_type Entitlement type
|
||||
*/
|
||||
[[nodiscard]] entitlement_type get_type() const;
|
||||
|
||||
/**
|
||||
* @brief Was the entitlement consumed?
|
||||
*
|
||||
* A consumed entitlement is a one off purchase which
|
||||
* has been claimed as used by the application. for example
|
||||
* in-app purchases.
|
||||
*
|
||||
* @return true if the entitlement was consumed.
|
||||
*/
|
||||
[[nodiscard]] bool is_consumed() const;
|
||||
|
||||
/**
|
||||
* @brief Was the entitlement deleted?
|
||||
*
|
||||
* @return true if the entitlement was deleted.
|
||||
*/
|
||||
[[nodiscard]] bool is_deleted() const;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Group of entitlements.
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, entitlement> entitlement_map;
|
||||
|
||||
}
|
||||
711
dpp/etf.h
711
dpp/etf.h
@ -1,711 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Parts of this file inspired by, or outright copied from erlpack:
|
||||
* https://github.com/discord/erlpack/
|
||||
*
|
||||
* Acknowledgements:
|
||||
*
|
||||
* sysdep.h:
|
||||
* Based on work by FURUHASHI Sadayuki in msgpack-python
|
||||
* (https://github.com/msgpack/msgpack-python)
|
||||
*
|
||||
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
|
||||
* Licensed under the Apache License, Version 2.0 (the "License").
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Current ETF format version in use
|
||||
*/
|
||||
const uint8_t FORMAT_VERSION = 131;
|
||||
|
||||
/**
|
||||
* @brief Represents a token which identifies the type of value which follows it
|
||||
* in the ETF binary structure.
|
||||
*/
|
||||
enum etf_token_type : uint8_t {
|
||||
/**
|
||||
* @brief 68 [Distribution header]
|
||||
*/
|
||||
ett_distribution = 'D',
|
||||
|
||||
/**
|
||||
* @brief 70 [Float64:IEEE float]
|
||||
*/
|
||||
ett_new_float = 'F',
|
||||
|
||||
/**
|
||||
* @brief 77 [UInt32:Len, UInt8:Bits, Len:Data]
|
||||
*/
|
||||
ett_bit_binary = 'M',
|
||||
|
||||
/**
|
||||
* @brief 80 [UInt4:UncompressedSize, N:ZlibCompressedData]
|
||||
*/
|
||||
ett_compressed = 'P',
|
||||
|
||||
/**
|
||||
* @brief 97 [UInt8:Int]
|
||||
*/
|
||||
ett_smallint = 'a',
|
||||
|
||||
/**
|
||||
* @brief 98 [Int32:Int]
|
||||
*/
|
||||
ett_integer = 'b',
|
||||
|
||||
/**
|
||||
* @brief 99 [31:Float String] Float in string format (formatted "%.20e", sscanf "%lf").
|
||||
*
|
||||
* @note Superseded by ett_new_float.
|
||||
*/
|
||||
ett_float = 'c',
|
||||
|
||||
/**
|
||||
* @brief 100 [UInt16:Len, Len:AtomName] max Len is 255
|
||||
*/
|
||||
ett_atom = 'd',
|
||||
|
||||
/**
|
||||
* @brief 101 [atom:Node, UInt32:ID, UInt8:Creation]
|
||||
*/
|
||||
ett_reference = 'e',
|
||||
|
||||
/**
|
||||
* @brief 102 [atom:Node, UInt32:ID, UInt8:Creation]
|
||||
*/
|
||||
ett_port = 'f',
|
||||
|
||||
/**
|
||||
* @brief 103 [atom:Node, UInt32:ID, UInt32:Serial, UInt8:Creation]
|
||||
*/
|
||||
ett_pid = 'g',
|
||||
|
||||
/**
|
||||
* @brief 104 [UInt8:Arity, N:Elements]
|
||||
*/
|
||||
ett_small_tuple = 'h',
|
||||
|
||||
/**
|
||||
* @brief 105 [UInt32:Arity, N:Elements]
|
||||
*/
|
||||
ett_large_tuple = 'i',
|
||||
|
||||
/**
|
||||
* @brief 106 empty list
|
||||
*/
|
||||
ett_nil = 'j',
|
||||
|
||||
/**
|
||||
* @brief 107 [UInt16:Len, Len:Characters]
|
||||
*/
|
||||
ett_string = 'k',
|
||||
|
||||
/**
|
||||
* @brief 108 [UInt32:Len, Elements, Tail]
|
||||
*/
|
||||
ett_list = 'l',
|
||||
|
||||
/**
|
||||
* @brief 109 [UInt32:Len, Len:Data]
|
||||
*/
|
||||
ett_binary = 'm',
|
||||
|
||||
/**
|
||||
* @brief 110 [UInt8:n, UInt8:Sign, n:nums]
|
||||
*/
|
||||
ett_bigint_small = 'n',
|
||||
|
||||
/**
|
||||
* @brief 111 [UInt32:n, UInt8:Sign, n:nums]
|
||||
*/
|
||||
ett_bigint_large = 'o',
|
||||
|
||||
/**
|
||||
* @brief 112 [UInt32:Size, UInt8:Arity, 16*Uint6-MD5:Uniq, UInt32:Index, UInt32:NumFree, atom:Module, int:OldIndex, int:OldUniq, pid:Pid, NunFree*ext:FreeVars]
|
||||
*/
|
||||
ett_new_function = 'p',
|
||||
|
||||
/**
|
||||
* @brief 113 [atom:Module, atom:Function, smallint:Arity]
|
||||
*/
|
||||
ett_export = 'q',
|
||||
|
||||
/**
|
||||
* @brief 114 [UInt16:Len, atom:Node, UInt8:Creation, Len*UInt32:ID]
|
||||
*/
|
||||
ett_new_reference = 'r',
|
||||
|
||||
/**
|
||||
* @brief 115 [UInt8:Len, Len:AtomName]
|
||||
*/
|
||||
ett_atom_small = 's',
|
||||
|
||||
/**
|
||||
* @brief 116 [UInt32:Airty, N:Pairs]
|
||||
*/
|
||||
ett_map = 't',
|
||||
|
||||
/**
|
||||
* @brief 117 [UInt4:NumFree, pid:Pid, atom:Module, int:Index, int:Uniq, NumFree*ext:FreeVars]
|
||||
*/
|
||||
ett_function = 'u',
|
||||
|
||||
/**
|
||||
* @brief 118 [UInt16:Len, Len:AtomName] max Len is 255 characters (up to 4 bytes per)
|
||||
*/
|
||||
ett_atom_utf8 = 'v',
|
||||
|
||||
/**
|
||||
* @brief 119 [UInt8:Len, Len:AtomName]
|
||||
*/
|
||||
ett_atom_utf8_small = 'w'
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a buffer of bytes being encoded into ETF
|
||||
*/
|
||||
struct DPP_EXPORT etf_buffer {
|
||||
/**
|
||||
* @brief Raw buffer
|
||||
*/
|
||||
std::vector<char> buf;
|
||||
|
||||
/**
|
||||
* @brief Current used length of buffer
|
||||
* (this is different from buf.size() as it is pre-allocated
|
||||
* using resize and may not all be in use)
|
||||
*/
|
||||
size_t length;
|
||||
|
||||
/**
|
||||
* @brief Construct a new etf buffer object
|
||||
*
|
||||
* @param initial initial buffer size to allocate
|
||||
*/
|
||||
etf_buffer(size_t initial);
|
||||
|
||||
/**
|
||||
* @brief Destroy the etf buffer object
|
||||
*/
|
||||
~etf_buffer();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The etf_parser class can serialise and deserialise ETF (Erlang Term Format)
|
||||
* into and out of an nlohmann::json object, so that layers above the websocket don't
|
||||
* have to be any different for handling ETF.
|
||||
*/
|
||||
class DPP_EXPORT etf_parser {
|
||||
/**
|
||||
* @brief Current size of binary data
|
||||
*/
|
||||
size_t size;
|
||||
|
||||
/**
|
||||
* @brief Current offset into binary data
|
||||
*/
|
||||
size_t offset;
|
||||
|
||||
/**
|
||||
* @brief Pointer to binary ETF data to be decoded
|
||||
*/
|
||||
uint8_t* data;
|
||||
|
||||
/**
|
||||
* @brief Parse a single value, and if that value contains other
|
||||
* values (e.g. an array or map) then call itself recursively.
|
||||
*
|
||||
* @return nlohmann::json JSON value from the ETF
|
||||
*/
|
||||
nlohmann::json inner_parse();
|
||||
|
||||
/**
|
||||
* @brief Read 8 bits of data from the buffer
|
||||
*
|
||||
* @return uint8_t data retrieved
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
uint8_t read_8_bits();
|
||||
|
||||
/**
|
||||
* @brief Read 16 bits of data from the buffer
|
||||
*
|
||||
* @return uint16_t data retrieved
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
uint16_t read_16_bits();
|
||||
|
||||
/**
|
||||
* @brief Read 32 bits of data from the buffer
|
||||
*
|
||||
* @return uint32_t data retrieved
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
uint32_t read_32_bits();
|
||||
|
||||
/**
|
||||
* @brief Read 64 bits of data from the buffer
|
||||
*
|
||||
* @return uint64_t data retrieved
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
uint64_t read_64_bits();
|
||||
|
||||
/**
|
||||
* @brief Read string data from the buffer
|
||||
*
|
||||
* @param length Length of string to retrieve
|
||||
* @return const char* data retrieved
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
const char* read_string(uint32_t length);
|
||||
|
||||
/**
|
||||
* @brief Process an 'atom' value.
|
||||
* An atom is a "label" or constant value within the data,
|
||||
* such as a key name, nullptr, or false.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json process_atom(const char* atom, uint16_t length);
|
||||
|
||||
/**
|
||||
* @brief Decode an 'atom' value.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_atom();
|
||||
|
||||
/**
|
||||
* @brief Decode a small 'atom' value.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_small_atom();
|
||||
|
||||
/**
|
||||
* @brief Decode a small integer value (0-255).
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_small_integer();
|
||||
|
||||
/**
|
||||
* @brief Decode an integer value (-MAXINT -> MAXINT-1).
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_integer();
|
||||
|
||||
/**
|
||||
* @brief Decode an array of values.
|
||||
*
|
||||
* @return nlohmann::json values converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_array(uint32_t length);
|
||||
|
||||
/**
|
||||
* @brief Decode a list of values.
|
||||
*
|
||||
* @return nlohmann::json values converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_list();
|
||||
|
||||
/**
|
||||
* @brief Decode a 'tuple' value.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_tuple(uint32_t length);
|
||||
|
||||
/**
|
||||
* @brief Decode a nil 'atom' value.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_nil();
|
||||
|
||||
/**
|
||||
* @brief Decode a map (object) value.
|
||||
* Will recurse to evaluate each member variable.
|
||||
*
|
||||
* @return nlohmann::json values converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_map();
|
||||
|
||||
/**
|
||||
* @brief Decode a floating point numeric value.
|
||||
* (depreciated in erlang but still expected to be supported)
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_float();
|
||||
|
||||
/**
|
||||
* @brief Decode a floating type numeric value.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_new_float();
|
||||
|
||||
/**
|
||||
* @brief Decode a 'bigint' value.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_bigint(uint32_t digits);
|
||||
|
||||
/**
|
||||
* @brief Decode a small 'bigint' value.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_bigint_small();
|
||||
|
||||
/**
|
||||
* @brief Decode a large 'bigint' value.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_bigint_large();
|
||||
|
||||
/**
|
||||
* @brief Decode a binary value.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_binary();
|
||||
|
||||
/**
|
||||
* @brief Decode a string value.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_string();
|
||||
|
||||
/**
|
||||
* @brief Decode a string list value.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_string_as_list();
|
||||
|
||||
/**
|
||||
* @brief Decode a 'small tuple' value.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_tuple_small();
|
||||
|
||||
/**
|
||||
* @brief Decode a 'large tuple' value.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_tuple_large();
|
||||
|
||||
/**
|
||||
* @brief Decode a compressed value.
|
||||
* This is a zlib-compressed binary blob which contains another
|
||||
* ETF object.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_compressed();
|
||||
|
||||
/**
|
||||
* @brief Decode a 'reference' value.
|
||||
* Erlang expects this to be supported, in practice Discord doesn't send these right now.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_reference();
|
||||
|
||||
/**
|
||||
* @brief Decode a 'new reference' value.
|
||||
* Erlang expects this to be supported, in practice Discord doesn't send these right now.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_new_reference();
|
||||
|
||||
/**
|
||||
* @brief Decode a 'port' value.
|
||||
* Erlang expects this to be supported, in practice Discord doesn't send these right now.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_port();
|
||||
|
||||
/**
|
||||
* @brief Decode a 'PID' value.
|
||||
* Erlang expects this to be supported, in practice Discord doesn't send these right now.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_pid();
|
||||
|
||||
/**
|
||||
* @brief Decode an 'export' value.
|
||||
* Erlang expects this to be supported, in practice Discord doesn't send these right now.
|
||||
*
|
||||
* @return nlohmann::json value converted to JSON
|
||||
* @throw dpp::exception Data stream isn't long enough to fetch requested bits
|
||||
*/
|
||||
nlohmann::json decode_export();
|
||||
|
||||
/**
|
||||
* @brief Write to output buffer for creation of ETF from JSON
|
||||
*
|
||||
* @param pk buffer struct
|
||||
* @param bytes byte buffer to write
|
||||
* @param l number of bytes to write
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void buffer_write(etf_buffer *pk, const char *bytes, size_t l);
|
||||
|
||||
/**
|
||||
* @brief Append version number to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_version(etf_buffer *b);
|
||||
|
||||
/**
|
||||
* @brief Append nil value to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_nil(etf_buffer *b);
|
||||
|
||||
/**
|
||||
* @brief Append false value to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_false(etf_buffer *b);
|
||||
|
||||
/**
|
||||
* @brief Append true value to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_true(etf_buffer *b);
|
||||
|
||||
/**
|
||||
* @brief Append small integer value to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @param d double to append
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_small_integer(etf_buffer *b, unsigned char d);
|
||||
|
||||
/**
|
||||
* @brief Append integer value to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @param d integer to append
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_integer(etf_buffer *b, int32_t d);
|
||||
|
||||
/**
|
||||
* @brief Append 64 bit integer value to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @param d integer to append
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_unsigned_long_long(etf_buffer *b, unsigned long long d);
|
||||
|
||||
/**
|
||||
* @brief Append 64 bit integer value to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @param d integer to append
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_long_long(etf_buffer *b, long long d);
|
||||
|
||||
/**
|
||||
* @brief Append double value to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @param f double to append
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_double(etf_buffer *b, double f);
|
||||
|
||||
/**
|
||||
* @brief Append atom value to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @param bytes pointer to string to append
|
||||
* @param size size of string to append
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_atom(etf_buffer *b, const char *bytes, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Append utf8 atom value to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @param bytes pointer to string to append
|
||||
* @param size size of string to append
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_atom_utf8(etf_buffer *b, const char *bytes, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Append binary value to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @param bytes pointer to string to append
|
||||
* @param size size of string to append
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_binary(etf_buffer *b, const char *bytes, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Append string value to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @param bytes pointer to string to append
|
||||
* @param size size of string to append
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_string(etf_buffer *b, const char *bytes, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Append tuple value to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @param size size of value to append
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_tuple_header(etf_buffer *b, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Append list terminator to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_nil_ext(etf_buffer *b);
|
||||
|
||||
/**
|
||||
* @brief Append a list header value to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @param size size of values to append
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_list_header(etf_buffer *b, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Append a map header value to ETF buffer
|
||||
*
|
||||
* @param b buffer to append to
|
||||
* @param size size of values to append
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void append_map_header(etf_buffer *b, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Build ETF buffer
|
||||
*
|
||||
* @param j JSON object to build from
|
||||
* @param b Buffer to append to
|
||||
* @throw std::exception Buffer cannot be extended
|
||||
*/
|
||||
void inner_build(const nlohmann::json* j, etf_buffer* b);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new etf parser object
|
||||
*/
|
||||
etf_parser();
|
||||
|
||||
/**
|
||||
* @brief Destroy the etf parser object
|
||||
*/
|
||||
~etf_parser();
|
||||
|
||||
/**
|
||||
* @brief Convert ETF binary content to nlohmann::json
|
||||
*
|
||||
* @param in Raw binary ETF data (generally from a websocket)
|
||||
* @return nlohmann::json JSON data for use in the library
|
||||
* @throw dpp::exception Malformed or otherwise invalid ETF content
|
||||
*/
|
||||
nlohmann::json parse(const std::string& in);
|
||||
|
||||
/**
|
||||
* @brief Create ETF binary data from nlohmann::json
|
||||
*
|
||||
* @param j JSON value to encode to ETF
|
||||
* @return std::string raw ETF data. Note that this can
|
||||
* and probably will contain null values, use std::string::data()
|
||||
* and std::string::size() to manipulate or send it.
|
||||
* @throw std::exception Not enough memory, or invalid data types/values
|
||||
*/
|
||||
std::string build(const nlohmann::json& j);
|
||||
};
|
||||
|
||||
}
|
||||
159
dpp/event.h
159
dpp/event.h
@ -1,159 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
|
||||
#define event_decl(x,wstype) /** @brief Internal event handler for wstype websocket events. Called for each websocket message of this type. @internal */ \
|
||||
class x : public event { public: virtual void handle(class dpp::discord_client* client, nlohmann::json &j, const std::string &raw); };
|
||||
|
||||
/**
|
||||
* @brief The events namespace holds the internal event handlers for each websocket event.
|
||||
* These are handled internally and also dispatched to the user code if the event is hooked.
|
||||
*/
|
||||
namespace dpp::events {
|
||||
|
||||
/**
|
||||
* @brief An event object represents an event handled internally, passed from the websocket e.g. MESSAGE_CREATE.
|
||||
*/
|
||||
class DPP_EXPORT event {
|
||||
public:
|
||||
/**
|
||||
* @brief Pure virtual method for event handler code
|
||||
* @param client The creating shard
|
||||
* @param j The json data of the event
|
||||
* @param raw The raw event json
|
||||
*/
|
||||
virtual void handle(class discord_client* client, nlohmann::json &j, const std::string &raw) = 0;
|
||||
};
|
||||
|
||||
/* Internal logger */
|
||||
event_decl(logger,LOG);
|
||||
|
||||
/* Guilds */
|
||||
event_decl(guild_create,GUILD_CREATE);
|
||||
event_decl(guild_update,GUILD_UPDATE);
|
||||
event_decl(guild_delete,GUILD_DELETE);
|
||||
event_decl(guild_ban_add,GUILD_BAN_ADD);
|
||||
event_decl(guild_ban_remove,GUILD_BAN_REMOVE);
|
||||
event_decl(guild_emojis_update,GUILD_EMOJIS_UPDATE);
|
||||
event_decl(guild_integrations_update,GUILD_INTEGRATIONS_UPDATE);
|
||||
event_decl(guild_join_request_delete,GUILD_JOIN_REQUEST_DELETE);
|
||||
event_decl(guild_stickers_update,GUILD_STICKERS_UPDATE);
|
||||
|
||||
/* Stage channels */
|
||||
event_decl(stage_instance_create,STAGE_INSTANCE_CREATE);
|
||||
event_decl(stage_instance_update,STAGE_INSTANCE_UPDATE);
|
||||
event_decl(stage_instance_delete,STAGE_INSTANCE_DELETE);
|
||||
|
||||
/* Guild members */
|
||||
event_decl(guild_member_add,GUILD_MEMBER_ADD);
|
||||
event_decl(guild_member_remove,GUILD_MEMBER_REMOVE);
|
||||
event_decl(guild_members_chunk,GUILD_MEMBERS_CHUNK);
|
||||
event_decl(guild_member_update,GUILD_MEMBERS_UPDATE);
|
||||
|
||||
/* Guild roles */
|
||||
event_decl(guild_role_create,GUILD_ROLE_CREATE);
|
||||
event_decl(guild_role_update,GUILD_ROLE_UPDATE);
|
||||
event_decl(guild_role_delete,GUILD_ROLE_DELETE);
|
||||
|
||||
/* Session state */
|
||||
event_decl(resumed,RESUMED);
|
||||
event_decl(ready,READY);
|
||||
|
||||
/* Channels */
|
||||
event_decl(channel_create,CHANNEL_CREATE);
|
||||
event_decl(channel_update,CHANNEL_UPDATE);
|
||||
event_decl(channel_delete,CHANNEL_DELETE);
|
||||
event_decl(channel_pins_update,CHANNEL_PINS_UPDATE);
|
||||
|
||||
/* Threads */
|
||||
event_decl(thread_create,THREAD_CREATE);
|
||||
event_decl(thread_update,THREAD_UPDATE);
|
||||
event_decl(thread_delete,THREAD_DELETE);
|
||||
event_decl(thread_list_sync,THREAD_LIST_SYNC);
|
||||
event_decl(thread_member_update,THREAD_MEMBER_UPDATE);
|
||||
event_decl(thread_members_update,THREAD_MEMBERS_UPDATE);
|
||||
|
||||
/* Messages */
|
||||
event_decl(message_create,MESSAGE_CREATE);
|
||||
event_decl(message_update,MESSAGE_UPDATE);
|
||||
event_decl(message_delete,MESSAGE_DELETE);
|
||||
event_decl(message_delete_bulk,MESSAGE_DELETE_BULK);
|
||||
event_decl(message_poll_vote_add,MESSAGE_POLL_VOTE_ADD);
|
||||
event_decl(message_poll_vote_remove,MESSAGE_POLL_VOTE_REMOVE);
|
||||
|
||||
/* Presence/typing */
|
||||
event_decl(presence_update,PRESENCE_UPDATE);
|
||||
event_decl(typing_start,TYPING_START);
|
||||
|
||||
/* Users (outside of guild) */
|
||||
event_decl(user_update,USER_UPDATE);
|
||||
|
||||
/* Message reactions */
|
||||
event_decl(message_reaction_add,MESSAGE_REACTION_ADD);
|
||||
event_decl(message_reaction_remove,MESSAGE_REACTION_REMOVE);
|
||||
event_decl(message_reaction_remove_all,MESSAGE_REACTION_REMOVE_ALL);
|
||||
event_decl(message_reaction_remove_emoji,MESSAGE_REACTION_REMOVE_EMOJI);
|
||||
|
||||
/* Invites */
|
||||
event_decl(invite_create,INVITE_CREATE);
|
||||
event_decl(invite_delete,INVITE_DELETE);
|
||||
|
||||
/* Voice */
|
||||
event_decl(voice_state_update,VOICE_STATE_UPDATE);
|
||||
event_decl(voice_server_update,VOICE_SERVER_UPDATE);
|
||||
|
||||
/* Webhooks */
|
||||
event_decl(webhooks_update,WEBHOOKS_UPDATE);
|
||||
|
||||
/* Application commands */
|
||||
event_decl(interaction_create,INTERACTION_CREATE);
|
||||
|
||||
/* Integrations */
|
||||
event_decl(integration_create,INTEGRATION_CREATE);
|
||||
event_decl(integration_update,INTEGRATION_UPDATE);
|
||||
event_decl(integration_delete,INTEGRATION_DELETE);
|
||||
|
||||
/* Scheduled events */
|
||||
event_decl(guild_scheduled_event_create,GUILD_SCHEDULED_EVENT_CREATE);
|
||||
event_decl(guild_scheduled_event_update,GUILD_SCHEDULED_EVENT_UPDATE);
|
||||
event_decl(guild_scheduled_event_delete,GUILD_SCHEDULED_EVENT_DELETE);
|
||||
event_decl(guild_scheduled_event_user_add,GUILD_SCHEDULED_EVENT_USER_ADD);
|
||||
event_decl(guild_scheduled_event_user_remove,GUILD_SCHEDULED_EVENT_USER_REMOVE);
|
||||
|
||||
/* Auto moderation */
|
||||
event_decl(automod_rule_create, AUTO_MODERATION_RULE_CREATE);
|
||||
event_decl(automod_rule_update, AUTO_MODERATION_RULE_UPDATE);
|
||||
event_decl(automod_rule_delete, AUTO_MODERATION_RULE_DELETE);
|
||||
event_decl(automod_rule_execute, AUTO_MODERATION_ACTION_EXECUTION);
|
||||
|
||||
/* Audit log */
|
||||
event_decl(guild_audit_log_entry_create, GUILD_AUDIT_LOG_ENTRY_CREATE);
|
||||
|
||||
/* Entitlements */
|
||||
event_decl(entitlement_create, ENTITLEMENT_CREATE);
|
||||
event_decl(entitlement_update, ENTITLEMENT_UPDATE);
|
||||
event_decl(entitlement_delete, ENTITLEMENT_DELETE);
|
||||
|
||||
}
|
||||
@ -1,744 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <dpp/export.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <variant>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/misc-enum.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <cstring>
|
||||
#include <atomic>
|
||||
#include <dpp/exception.h>
|
||||
#include <dpp/coro/job.h>
|
||||
#include <dpp/coro/task.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
#ifndef DPP_NO_CORO
|
||||
|
||||
template <typename T>
|
||||
class event_router_t;
|
||||
|
||||
namespace detail {
|
||||
|
||||
/** @brief Internal cogwheels for dpp::event_router_t */
|
||||
namespace event_router {
|
||||
|
||||
/** @brief State of an owner of an event_router::awaitable */
|
||||
enum class awaiter_state {
|
||||
/** @brief Awaitable is not being awaited */
|
||||
none,
|
||||
/** @brief Awaitable is being awaited */
|
||||
waiting,
|
||||
/** @brief Awaitable will be resumed imminently */
|
||||
resuming,
|
||||
/** @brief Awaitable will be cancelled imminently */
|
||||
cancelling
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Awaitable object representing an event.
|
||||
* A user can co_await on this object to resume the next time the event is fired,
|
||||
* optionally with a condition.
|
||||
*/
|
||||
template <typename T>
|
||||
class awaitable {
|
||||
friend class event_router_t<T>;
|
||||
|
||||
/** @brief Resume the coroutine waiting on this object */
|
||||
void resume() {
|
||||
std_coroutine::coroutine_handle<>::from_address(handle).resume();
|
||||
}
|
||||
|
||||
/** @brief Event router that will manage this object */
|
||||
event_router_t<T> *self;
|
||||
|
||||
/** @brief Predicate on the event, or nullptr for always match */
|
||||
std::function<bool (const T &)> predicate = nullptr;
|
||||
|
||||
/** @brief Event that triggered a resumption, to give to the resumer */
|
||||
const T *event = nullptr;
|
||||
|
||||
/** @brief Coroutine handle, type-erased */
|
||||
void* handle = nullptr;
|
||||
|
||||
/** @brief The state of the awaiting coroutine */
|
||||
std::atomic<awaiter_state> state = awaiter_state::none;
|
||||
|
||||
/** Default constructor is accessible only to event_router_t */
|
||||
awaitable() = default;
|
||||
|
||||
/** Normal constructor is accessible only to event_router_t */
|
||||
template <typename F>
|
||||
awaitable(event_router_t<T> *router, F&& fun) : self{router}, predicate{std::forward<F>(fun)} {}
|
||||
|
||||
public:
|
||||
/** This object is not copyable. */
|
||||
awaitable(const awaitable &) = delete;
|
||||
|
||||
/** Move constructor. */
|
||||
awaitable(awaitable &&rhs) noexcept : self{rhs.self}, predicate{std::move(rhs.predicate)}, event{rhs.event}, handle{std::exchange(rhs.handle, nullptr)}, state{rhs.state.load(std::memory_order_relaxed)} {}
|
||||
|
||||
/** This object is not copyable. */
|
||||
awaitable& operator=(const awaitable &) = delete;
|
||||
|
||||
/** Move assignment operator. */
|
||||
awaitable& operator=(awaitable&& rhs) noexcept {
|
||||
self = rhs.self;
|
||||
predicate = std::move(rhs.predicate);
|
||||
event = rhs.event;
|
||||
handle = std::exchange(rhs.handle, nullptr);
|
||||
state = rhs.state.load(std::memory_order_relaxed);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Request cancellation. This will detach this object from the event router and resume the awaiter, which will be thrown dpp::task_cancelled::exception.
|
||||
*
|
||||
* @throw ??? As this resumes the coroutine, it may throw any exceptions at the caller.
|
||||
*/
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* @brief First function called by the standard library when awaiting this object. Returns true if we need to suspend.
|
||||
*
|
||||
* @retval false always.
|
||||
*/
|
||||
[[nodiscard]] constexpr bool await_ready() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Second function called by the standard library when awaiting this object, after suspension.
|
||||
* This will attach the object to its event router, to be resumed on the next event that satisfies the predicate.
|
||||
*
|
||||
* @return void never resume on call.
|
||||
*/
|
||||
void await_suspend(detail::std_coroutine::coroutine_handle<> caller);
|
||||
|
||||
/**
|
||||
* @brief Third and final function called by the standard library, called when resuming the coroutine.
|
||||
*
|
||||
* @throw @ref task_cancelled_exception if cancel() has been called
|
||||
* @return const T& __Reference__ to the event that matched
|
||||
*/
|
||||
[[maybe_unused]] const T& await_resume();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief A returned event handle for an event which was attached
|
||||
*/
|
||||
typedef size_t event_handle;
|
||||
|
||||
/**
|
||||
* @brief Handles routing of an event to multiple listeners.
|
||||
* Multiple listeners may attach to the event_router_t by means of @ref operator()(F&&) "operator()". Passing a
|
||||
* lambda into @ref operator()(F&&) "operator()" attaches to the event.
|
||||
*
|
||||
* @details Dispatchers of the event may call the @ref call() method to cause all listeners
|
||||
* to receive the event.
|
||||
*
|
||||
* The @ref empty() method will return true if there are no listeners attached
|
||||
* to the event_router_t (this can be used to save time by not constructing objects that
|
||||
* nobody will ever see).
|
||||
*
|
||||
* The @ref detach() method removes an existing listener from the event,
|
||||
* using the event_handle ID returned by @ref operator()(F&&) "operator()".
|
||||
*
|
||||
* This class is used by the library to route all websocket events to listening code.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* @code{cpp}
|
||||
* // Declare an event that takes log_t as its parameter
|
||||
* event_router_t<log_t> my_event;
|
||||
*
|
||||
* // Attach a listener to the event
|
||||
* event_handle id = my_event([&](const log_t& cc) {
|
||||
* std::cout << cc.message << "\n";
|
||||
* });
|
||||
*
|
||||
* // Construct a log_t and call the event (listeners will receive the log_t object)
|
||||
* log_t lt;
|
||||
* lt.message = "foo";
|
||||
* my_event.call(lt);
|
||||
*
|
||||
* // Detach from an event using the handle returned by operator()
|
||||
* my_event.detach(id);
|
||||
* @endcode
|
||||
*
|
||||
* @tparam T type of single parameter passed to event lambda derived from event_dispatch_t
|
||||
*/
|
||||
template<class T> class event_router_t {
|
||||
private:
|
||||
friend class cluster;
|
||||
|
||||
/**
|
||||
* @brief Non-coro event handler type
|
||||
*/
|
||||
using regular_handler_t = std::function<void(const T&)>;
|
||||
|
||||
/**
|
||||
* @brief Type that event handlers will be stored as with DPP_CORO off.
|
||||
* This is the ABI DPP_CORO has to match.
|
||||
*/
|
||||
using event_handler_abi_t = std::variant<regular_handler_t, std::function<task_dummy(T)>>;
|
||||
|
||||
#ifndef DPP_NO_CORO
|
||||
friend class detail::event_router::awaitable<T>;
|
||||
|
||||
/** @brief dpp::task coro event handler */
|
||||
using task_handler_t = std::function<dpp::task<void>(const T&)>;
|
||||
|
||||
/** @brief Type that event handlers are stored as */
|
||||
using event_handler_t = std::variant<regular_handler_t, task_handler_t>;
|
||||
|
||||
DPP_CHECK_ABI_COMPAT(event_handler_t, event_handler_abi_t)
|
||||
#else
|
||||
/**
|
||||
* @brief Type that event handlers are stored as
|
||||
*/
|
||||
using event_handler_t = event_handler_abi_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Identifier for the next event handler, will be given to the user on attaching a handler
|
||||
*/
|
||||
event_handle next_handle = 1;
|
||||
|
||||
/**
|
||||
* @brief Thread safety mutex
|
||||
*/
|
||||
mutable std::shared_mutex mutex;
|
||||
|
||||
/**
|
||||
* @brief Container of event listeners keyed by handle,
|
||||
* as handles are handed out sequentially they will always
|
||||
* be called in they order they are bound to the event
|
||||
* as std::map is an ordered container.
|
||||
*/
|
||||
std::map<event_handle, event_handler_t> dispatch_container;
|
||||
|
||||
#ifndef DPP_NO_CORO
|
||||
/**
|
||||
* @brief Mutex for messing with coro_awaiters.
|
||||
*/
|
||||
mutable std::shared_mutex coro_mutex;
|
||||
|
||||
/**
|
||||
* @brief Vector containing the awaitables currently being awaited on for this event router.
|
||||
*/
|
||||
mutable std::vector<detail::event_router::awaitable<T> *> coro_awaiters;
|
||||
#else
|
||||
/**
|
||||
* @brief Dummy for ABI compatibility between DPP_CORO and not
|
||||
*/
|
||||
utility::dummy<std::shared_mutex> definitely_not_a_mutex;
|
||||
|
||||
/**
|
||||
* @brief Dummy for ABI compatibility between DPP_CORO and not
|
||||
*/
|
||||
utility::dummy<std::vector<void*>> definitely_not_a_vector;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief A function to be called whenever the method is called, to check
|
||||
* some condition that is required for this event to trigger correctly.
|
||||
*/
|
||||
std::function<void(const T&)> warning;
|
||||
|
||||
/**
|
||||
* @brief Next handle to be given out by the event router
|
||||
*/
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief Set the warning callback object used to check that this
|
||||
* event is capable of running properly
|
||||
*
|
||||
* @param warning_function A checking function to call
|
||||
*/
|
||||
void set_warning_callback(std::function<void(const T&)> warning_function) {
|
||||
warning = warning_function;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle an event. This function should only be used without coro enabled, otherwise use handle_coro.
|
||||
*/
|
||||
void handle(const T& event) const {
|
||||
if (warning) {
|
||||
warning(event);
|
||||
}
|
||||
|
||||
std::shared_lock l(mutex);
|
||||
for (const auto& [_, listener] : dispatch_container) {
|
||||
if (!event.is_cancelled()) {
|
||||
if (std::holds_alternative<regular_handler_t>(listener)) {
|
||||
std::get<regular_handler_t>(listener)(event);
|
||||
} else {
|
||||
throw dpp::logic_exception("cannot handle a coroutine event handler with a library built without DPP_CORO");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#ifndef DPP_NO_CORO
|
||||
/**
|
||||
* @brief Handle an event as a coroutine, ensuring the lifetime of the event object.
|
||||
*/
|
||||
dpp::job handle_coro(T event) const {
|
||||
if (warning) {
|
||||
warning(event);
|
||||
}
|
||||
|
||||
resume_awaiters(event);
|
||||
|
||||
std::vector<dpp::task<void>> tasks;
|
||||
{
|
||||
std::shared_lock l(mutex);
|
||||
|
||||
for (const auto& [_, listener] : dispatch_container) {
|
||||
if (!event.is_cancelled()) {
|
||||
if (std::holds_alternative<task_handler_t>(listener)) {
|
||||
tasks.push_back(std::get<task_handler_t>(listener)(event));
|
||||
} else if (std::holds_alternative<regular_handler_t>(listener)) {
|
||||
std::get<regular_handler_t>(listener)(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
for (dpp::task<void>& t : tasks) {
|
||||
co_await t; // keep the event object alive until all tasks finished
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attach a suspended coroutine to this event router via detail::event_router::awaitable.
|
||||
* It will be resumed and detached when an event satisfying its condition completes, or it is cancelled.
|
||||
*
|
||||
* This is for internal usage only, the user way to do this is to co_await it (which will call this when suspending)
|
||||
* This guarantees that the coroutine is indeed suspended and thus can be resumed at any time
|
||||
*
|
||||
* @param awaiter Awaiter to attach
|
||||
*/
|
||||
void attach_awaiter(detail::event_router::awaitable<T> *awaiter) {
|
||||
std::unique_lock lock{coro_mutex};
|
||||
|
||||
coro_awaiters.emplace_back(awaiter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Detach an awaiting coroutine handle from this event router.
|
||||
* This is mostly called when a detail::event_router::awaitable is cancelled.
|
||||
*
|
||||
* @param handle Coroutine handle to find in the attached coroutines
|
||||
*/
|
||||
void detach_coro(void *handle) {
|
||||
std::unique_lock lock{coro_mutex};
|
||||
|
||||
coro_awaiters.erase(std::remove_if(coro_awaiters.begin(), coro_awaiters.end(), [handle](detail::event_router::awaitable<T> const *awaiter) { return awaiter->handle == handle; }), coro_awaiters.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume any awaiter whose predicate matches this event, or is null.
|
||||
*
|
||||
* @param event Event to compare and pass to accepting awaiters
|
||||
*/
|
||||
void resume_awaiters(const T& event) const {
|
||||
std::vector<detail::event_router::awaitable<T>*> to_resume;
|
||||
std::unique_lock lock{coro_mutex};
|
||||
|
||||
for (auto it = coro_awaiters.begin(); it != coro_awaiters.end();) {
|
||||
detail::event_router::awaitable<T>* awaiter = *it;
|
||||
|
||||
if (awaiter->predicate && !awaiter->predicate(event)) {
|
||||
++it;
|
||||
} else {
|
||||
using state_t = detail::event_router::awaiter_state;
|
||||
|
||||
/**
|
||||
* If state == none (was never awaited), do nothing
|
||||
* If state == waiting, prevent resumption, resume on our end
|
||||
* If state == resuming || cancelling, ignore
|
||||
*
|
||||
* Technically only cancelling || waiting should be possible here
|
||||
* We do this by trying to exchange "waiting" with "resuming". If that returns false, this is presumed to be "cancelling"
|
||||
*/
|
||||
|
||||
state_t s = state_t::waiting;
|
||||
if (awaiter->state.compare_exchange_strong(s, state_t::resuming)) {
|
||||
to_resume.emplace_back(awaiter);
|
||||
awaiter->event = &event;
|
||||
|
||||
it = coro_awaiters.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
lock.unlock();
|
||||
for (detail::event_router::awaitable<T>* awaiter : to_resume)
|
||||
awaiter->resume();
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new event_router_t object.
|
||||
*/
|
||||
event_router_t() = default;
|
||||
|
||||
/**
|
||||
* @brief Destructor. Will cancel any coroutine awaiting on events.
|
||||
*
|
||||
* @throw ! Cancelling a coroutine will throw a dpp::task_cancelled_exception to it.
|
||||
* This will be caught in this destructor, however, make sure no other exceptions are thrown in the coroutine after that or it will terminate.
|
||||
*/
|
||||
~event_router_t() {
|
||||
#ifndef DPP_NO_CORO
|
||||
while (!coro_awaiters.empty()) {
|
||||
// cancel all awaiters. here we cannot do the usual loop as we'd need to lock coro_mutex, and cancel() locks and modifies coro_awaiters
|
||||
try {
|
||||
coro_awaiters.back()->cancel();
|
||||
/*
|
||||
* will resume coroutines and may throw ANY exception, including dpp::task_cancelled_exception cancel() throws at them.
|
||||
* we catch that one. for the rest, good luck :)
|
||||
* realistically the only way any other exception would pop up here is if someone catches dpp::task_cancelled_exception THEN throws another exception.
|
||||
*/
|
||||
} catch (const dpp::task_cancelled_exception &) {
|
||||
// ok. likely we threw this one
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call all attached listeners.
|
||||
* Listeners may cancel, by calling the event.cancel method.
|
||||
*
|
||||
* @param event Class to pass as parameter to all listeners.
|
||||
*/
|
||||
void call(const T& event) const {
|
||||
#ifndef DPP_NO_CORO
|
||||
handle_coro(event);
|
||||
#else
|
||||
handle(event);
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Call all attached listeners.
|
||||
* Listeners may cancel, by calling the event.cancel method.
|
||||
*
|
||||
* @param event Class to pass as parameter to all listeners.
|
||||
*/
|
||||
void call(T&& event) const {
|
||||
#ifndef DPP_NO_CORO
|
||||
handle_coro(std::move(event));
|
||||
#else
|
||||
handle(std::move(event));
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef DPP_NO_CORO
|
||||
/**
|
||||
* @brief Obtain an awaitable object that refers to an event with a certain condition.
|
||||
* It can be co_await-ed to wait for the next event that satisfies this condition.
|
||||
* On resumption the awaiter will be given __a reference__ to the event,
|
||||
* saving it in a variable is recommended to avoid variable lifetime issues.
|
||||
*
|
||||
* @details Example: @code{cpp}
|
||||
* dpp::task<> my_handler(const dpp::slashcommand_t& event) {
|
||||
* co_await event.co_reply(dpp::message().add_component(dpp::component().add_component().set_label("click me!").set_id("test")));
|
||||
*
|
||||
* dpp::button_click_t b = co_await c->on_button_click.with([](const dpp::button_click_t &event){ return event.custom_id == "test"; });
|
||||
*
|
||||
* // do something on button click
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* This can be combined with dpp::when_any and other awaitables, for example dpp::cluster::co_sleep to create @ref expiring-buttons "expiring buttons".
|
||||
*
|
||||
* @warning On resumption the awaiter will be given <b>a reference</b> to the event.
|
||||
* This means that variable may become dangling at the next co_await, be careful and save it in a variable
|
||||
* if you need to.
|
||||
* @param pred Predicate to check the event against. This should be a callable of the form `bool(const T&)`
|
||||
* where T is the event type, returning true if the event is to match.
|
||||
* @return awaitable An awaitable object that can be co_await-ed to await an event matching the condition.
|
||||
*/
|
||||
template <typename Predicate>
|
||||
#ifndef _DOXYGEN_
|
||||
requires utility::callable_returns<Predicate, bool, const T&>
|
||||
#endif
|
||||
auto when(Predicate&& pred)
|
||||
#ifndef _DOXYGEN_
|
||||
noexcept(noexcept(std::function<bool(const T&)>{std::declval<Predicate>()}))
|
||||
#endif
|
||||
{
|
||||
return detail::event_router::awaitable<T>{this, std::forward<Predicate>(pred)};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Obtain an awaitable object that refers to any event.
|
||||
* It can be co_await-ed to wait for the next event.
|
||||
*
|
||||
* @details Example: @code{cpp}
|
||||
* dpp::task<> my_handler(const dpp::slashcommand_t& event) {
|
||||
* co_await event.co_reply(dpp::message().add_component(dpp::component().add_component().set_label("click me!").set_id("test")));
|
||||
*
|
||||
* dpp::button_click_t b = co_await c->on_message_create;
|
||||
*
|
||||
* // do something on button click
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* This can be combined with dpp::when_any and other awaitables, for example dpp::cluster::co_sleep to create expiring buttons.
|
||||
*
|
||||
* @warning On resumption the awaiter will be given <b>a reference</b> to the event.
|
||||
* This means that variable may become dangling at the next co_await, be careful and save it in a variable
|
||||
* if you need to.
|
||||
* @return awaitable An awaitable object that can be co_await-ed to await an event matching the condition.
|
||||
*/
|
||||
[[nodiscard]] auto operator co_await() noexcept {
|
||||
return detail::event_router::awaitable<T>{this, nullptr};
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Returns true if the container of listeners is empty,
|
||||
* i.e. there is nothing listening for this event right now.
|
||||
*
|
||||
* @retval true if there are no listeners
|
||||
* @retval false if there are some listeners
|
||||
*/
|
||||
[[nodiscard]] bool empty() const {
|
||||
#ifndef DPP_NO_CORO
|
||||
std::shared_lock lock{mutex};
|
||||
std::shared_lock coro_lock{coro_mutex};
|
||||
|
||||
return dispatch_container.empty() && coro_awaiters.empty();
|
||||
#else
|
||||
std::shared_lock lock{mutex};
|
||||
|
||||
return dispatch_container.empty();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if any listeners are attached.
|
||||
*
|
||||
* This is the boolean opposite of event_router_t::empty().
|
||||
* @retval true if listeners are attached
|
||||
* @retval false if no listeners are attached
|
||||
*/
|
||||
operator bool() const {
|
||||
return !empty();
|
||||
}
|
||||
|
||||
#ifdef _DOXYGEN_
|
||||
/**
|
||||
* @brief Attach a callable to the event, adding a listener.
|
||||
* The callable should either be of the form `void(const T&)` or
|
||||
* `dpp::task<void>(const T&)`,
|
||||
* where T is the event type for this event router.
|
||||
*
|
||||
* This has the exact same behavior as using \ref attach(F&&) "attach".
|
||||
*
|
||||
* @see attach
|
||||
* @param fun Callable to attach to event
|
||||
* @return event_handle An event handle unique to this event, used to
|
||||
* detach the listener from the event later if necessary.
|
||||
*/
|
||||
template <typename F>
|
||||
[[maybe_unused]] event_handle operator()(F&& fun);
|
||||
|
||||
/**
|
||||
* @brief Attach a callable to the event, adding a listener.
|
||||
* The callable should either be of the form `void(const T&)` or
|
||||
* `dpp::task<void>(const T&)`,
|
||||
* where T is the event type for this event router.
|
||||
*
|
||||
* @param fun Callable to attach to event
|
||||
* @return event_handle An event handle unique to this event, used to
|
||||
* detach the listener from the event later if necessary.
|
||||
*/
|
||||
template <typename F>
|
||||
[[maybe_unused]] event_handle attach(F&& fun);
|
||||
#else /* not _DOXYGEN_ */
|
||||
# ifndef DPP_NO_CORO
|
||||
/**
|
||||
* @brief Attach a callable to the event, adding a listener.
|
||||
* The callable should either be of the form `void(const T&)` or
|
||||
* `dpp::task<void>(const T&)`, where T is the event type for this event router.
|
||||
*
|
||||
* @param fun Callable to attach to event
|
||||
* @return event_handle An event handle unique to this event, used to
|
||||
* detach the listener from the event later if necessary.
|
||||
*/
|
||||
template <typename F>
|
||||
requires (utility::callable_returns<F, dpp::task<void>, const T&> || utility::callable_returns<F, void, const T&>)
|
||||
[[maybe_unused]] event_handle operator()(F&& fun) {
|
||||
return this->attach(std::forward<F>(fun));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attach a callable to the event, adding a listener.
|
||||
* The callable should either be of the form `void(const T&)` or
|
||||
* `dpp::task<void>(const T&)`, where T is the event type for this event router.
|
||||
*
|
||||
* @param fun Callable to attach to event
|
||||
* @return event_handle An event handle unique to this event, used to
|
||||
* detach the listener from the event later if necessary.
|
||||
*/
|
||||
template <typename F>
|
||||
requires (utility::callable_returns<F, void, const T&>)
|
||||
[[maybe_unused]] event_handle attach(F&& fun) {
|
||||
std::unique_lock l(mutex);
|
||||
event_handle h = next_handle++;
|
||||
dispatch_container.emplace(std::piecewise_construct, std::forward_as_tuple(h), std::forward_as_tuple(std::in_place_type_t<regular_handler_t>{}, std::forward<F>(fun)));
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attach a callable to the event, adding a listener.
|
||||
* The callable should either be of the form `void(const T&)` or
|
||||
* `dpp::task<void>(const T&)`, where T is the event type for this event router.
|
||||
*
|
||||
* @param fun Callable to attach to event
|
||||
* @return event_handle An event handle unique to this event, used to
|
||||
* detach the listener from the event later if necessary.
|
||||
*/
|
||||
template <typename F>
|
||||
requires (utility::callable_returns<F, task<void>, const T&>)
|
||||
[[maybe_unused]] event_handle attach(F&& fun) {
|
||||
assert(dpp::utility::is_coro_enabled());
|
||||
|
||||
std::unique_lock l(mutex);
|
||||
event_handle h = next_handle++;
|
||||
dispatch_container.emplace(std::piecewise_construct, std::forward_as_tuple(h), std::forward_as_tuple(std::in_place_type_t<task_handler_t>{}, std::forward<F>(fun)));
|
||||
return h;
|
||||
}
|
||||
# else
|
||||
/**
|
||||
* @brief Attach a callable to the event, adding a listener.
|
||||
* The callable should be of the form `void(const T&)`
|
||||
* where T is the event type for this event router.
|
||||
*
|
||||
* @param fun Callable to attach to event
|
||||
* @return event_handle An event handle unique to this event, used to
|
||||
* detach the listener from the event later if necessary.
|
||||
*/
|
||||
template <typename F>
|
||||
[[maybe_unused]] std::enable_if_t<utility::callable_returns_v<F, void, const T&>, event_handle> operator()(F&& fun) {
|
||||
return this->attach(std::forward<F>(fun));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attach a callable to the event, adding a listener.
|
||||
* The callable should be of the form `void(const T&)`
|
||||
* where T is the event type for this event router.
|
||||
*f
|
||||
* @warning You cannot call this within an event handler.
|
||||
*
|
||||
* @param fun Callable to attach to event
|
||||
* @return event_handle An event handle unique to this event, used to
|
||||
* detach the listener from the event later if necessary.
|
||||
*/
|
||||
template <typename F>
|
||||
[[maybe_unused]] std::enable_if_t<utility::callable_returns_v<F, void, const T&>, event_handle> attach(F&& fun) {
|
||||
std::unique_lock l(mutex);
|
||||
event_handle h = next_handle++;
|
||||
dispatch_container.emplace(h, std::forward<F>(fun));
|
||||
return h;
|
||||
}
|
||||
# endif /* DPP_NO_CORO */
|
||||
#endif /* _DOXYGEN_ */
|
||||
/**
|
||||
* @brief Detach a listener from the event using a previously obtained ID.
|
||||
*
|
||||
* @warning You cannot call this within an event handler.
|
||||
*
|
||||
* @param handle An ID obtained from @ref operator(F&&) "operator()"
|
||||
* @retval true The event was successfully detached
|
||||
* @retval false The ID is invalid (possibly already detached, or does not exist)
|
||||
*/
|
||||
[[maybe_unused]] bool detach(const event_handle& handle) {
|
||||
std::unique_lock l(mutex);
|
||||
return this->dispatch_container.erase(handle);
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef DPP_NO_CORO
|
||||
|
||||
namespace detail::event_router {
|
||||
|
||||
template <typename T>
|
||||
void awaitable<T>::cancel() {
|
||||
awaiter_state s = awaiter_state::waiting;
|
||||
/**
|
||||
* If state == none (was never awaited), do nothing
|
||||
* If state == waiting, prevent resumption, resume on our end
|
||||
* If state == resuming || cancelling, ignore
|
||||
*/
|
||||
if (state.compare_exchange_strong(s, awaiter_state::cancelling)) {
|
||||
self->detach_coro(handle);
|
||||
resume();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool awaitable<T>::await_ready() const noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void awaitable<T>::await_suspend(detail::std_coroutine::coroutine_handle<> caller) {
|
||||
state.store(awaiter_state::waiting);
|
||||
handle = caller.address();
|
||||
self->attach_awaiter(this);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T &awaitable<T>::await_resume() {
|
||||
handle = nullptr;
|
||||
predicate = nullptr;
|
||||
if (state.exchange(awaiter_state::none, std::memory_order_relaxed) == awaiter_state::cancelling) {
|
||||
throw dpp::task_cancelled_exception{"event_router::awaitable was cancelled"};
|
||||
}
|
||||
return *std::exchange(event, nullptr);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
607
dpp/exception.h
607
dpp/exception.h
@ -1,607 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
#include <algorithm>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Exception error codes possible for dpp::exception::code()
|
||||
*
|
||||
* This list is a combined list of Discord's error codes, HTTP error codes,
|
||||
* zlib, opus and C library codes (e.g. DNS, socket etc). You may
|
||||
* use these to easily identify a type of exception without having to resort
|
||||
* to string comparison against dpp::exception::what()
|
||||
*
|
||||
* For detailed descriptions of each error code, see the text description
|
||||
* returned in `what()`.
|
||||
*
|
||||
* @note Some exceptions MAY have error codes which are NOT in this list
|
||||
* in the event a C library is updated and adds new codes we did not document
|
||||
* here. In this case, or where the code is not specific, refer to `what()`.
|
||||
*/
|
||||
enum exception_error_code {
|
||||
err_no_code_specified = 0,
|
||||
err_zlib_see_errno = -1,
|
||||
err_zlib_init_stream = -2,
|
||||
err_zlib_init_data = -3,
|
||||
err_zlib_init_mem = -4,
|
||||
err_zlib_init_buffer = -5,
|
||||
err_zlib_init_version = -6,
|
||||
err_opus_bad_arg = -11,
|
||||
err_opus_buffer_too_small = -12,
|
||||
err_opus_internal_error = -13,
|
||||
err_opus_invalid_packet = -14,
|
||||
err_opus_unimplemented = -15,
|
||||
err_opus_invalid_state = -16,
|
||||
err_opus_alloc_fail = -17,
|
||||
err_dns_bad_flags = -21,
|
||||
err_name_or_service_unknown = -22,
|
||||
err_dns_again = -23,
|
||||
err_dns_fail = -24,
|
||||
err_dns_family = -26,
|
||||
err_dns_socket_type = -27,
|
||||
err_dns_service = -28,
|
||||
err_dns_memory = -30,
|
||||
err_dns_system_error = -31,
|
||||
err_dns_overflow = -32,
|
||||
err_ssl_new = 1,
|
||||
err_ssl_connect = 2,
|
||||
err_write = 3,
|
||||
err_ssl_write = 4,
|
||||
err_no_sessions_left = 5,
|
||||
err_auto_shard = 6,
|
||||
err_reconnection = 7,
|
||||
err_bind_failure = 8,
|
||||
err_nonblocking_failure = 9,
|
||||
err_voice_terminating = 10,
|
||||
err_connect_failure = 11,
|
||||
err_ssl_context = 12,
|
||||
err_ssl_version = 13,
|
||||
err_invalid_socket = 14,
|
||||
err_socket_error = 15,
|
||||
err_websocket_proto_already_set = 16,
|
||||
err_command_handler_not_ready = 17,
|
||||
err_no_owning_message = 18,
|
||||
err_cancelled_event = 19,
|
||||
err_event_status = 20,
|
||||
err_event_start_time = 21,
|
||||
err_event_end_time = 22,
|
||||
err_command_has_caps = 23,
|
||||
err_choice_autocomplete = 24,
|
||||
err_interaction = 25,
|
||||
err_too_many_component_rows = 26,
|
||||
err_invalid_webhook = 27,
|
||||
err_voice_state_timestamp = 28,
|
||||
err_no_voice_support = 29,
|
||||
err_invalid_voice_packet_length = 30,
|
||||
err_opus = 31,
|
||||
err_cant_start_shard = 32,
|
||||
err_etf = 33,
|
||||
err_cache = 34,
|
||||
err_icon_size = 35,
|
||||
err_massive_audio = 36,
|
||||
err_unknown = 37,
|
||||
err_bad_request = 400,
|
||||
err_unauthorized = 401,
|
||||
err_payment_required = 402,
|
||||
err_forbidden = 403,
|
||||
err_not_found = 404,
|
||||
err_method_not_allowed = 405,
|
||||
err_not_acceptable = 406,
|
||||
err_proxy_auth_required = 407,
|
||||
err_request_timeout = 408,
|
||||
err_conflict = 409,
|
||||
err_gone = 410,
|
||||
err_length_required = 411,
|
||||
err_precondition_failed = 412,
|
||||
err_payload_too_large = 413,
|
||||
err_uri_too_long = 414,
|
||||
err_unsupported_media_type = 415,
|
||||
err_range_not_satisfiable = 416,
|
||||
err_expectation_failed = 417,
|
||||
err_im_a_teapot = 418,
|
||||
err_page_expired = 419,
|
||||
err_twitter_rate_limited = 420,
|
||||
err_misdirected_request = 421,
|
||||
err_unprocessable_content = 422,
|
||||
err_webdav_locked = 423,
|
||||
err_webdav_failed_dependency = 424,
|
||||
err_too_early = 425,
|
||||
err_upgrade_required = 426,
|
||||
err_precondition_required = 428,
|
||||
err_rate_limited = 429,
|
||||
err_request_headers_too_large = 431,
|
||||
err_page_blocked = 450,
|
||||
err_unavailable_for_legal_reasons = 451,
|
||||
err_http_request_on_https_port = 497,
|
||||
err_internal_server_error = 500,
|
||||
err_not_implemented = 501,
|
||||
err_bad_gateway = 502,
|
||||
err_service_unavailable = 503,
|
||||
err_gateway_timeout = 504,
|
||||
err_http_version_not_supported = 505,
|
||||
err_variant_also_negotiates = 506,
|
||||
err_webdav_insufficient_storage = 507,
|
||||
err_webdav_loop_detected = 508,
|
||||
err_bandwidth_limit_exceeded = 509,
|
||||
err_not_extended = 510,
|
||||
err_network_auth_required = 511,
|
||||
err_web_server_down = 521,
|
||||
err_connection_timed_out = 522,
|
||||
err_origin_unreachable = 523,
|
||||
err_timeout = 524,
|
||||
err_ssl_handshake_failed = 525,
|
||||
err_invalid_ssl_certificate = 526,
|
||||
err_railgun = 527,
|
||||
err_cloudflare = 530,
|
||||
err_websocket_unknown = 4000,
|
||||
err_websocket_bad_opcode= 4001,
|
||||
err_websocket_decode = 4002,
|
||||
err_websocket_not_authenticated = 4003,
|
||||
err_websocket_authentication_failed = 4004,
|
||||
err_websocket_already_authenticated = 4005,
|
||||
err_websocket_invalid_seq_number = 4007,
|
||||
err_websocket_rate_limited = 4008,
|
||||
err_websocket_session_timeout = 4009,
|
||||
err_websocket_invalid_shard = 4010,
|
||||
err_websocket_sharding_required = 4011,
|
||||
err_websocket_invalid_api_version = 4012,
|
||||
err_websocket_invalid_intents = 4013,
|
||||
err_websocket_disallowed_intents = 4014,
|
||||
err_websocket_voice_disconnected = 4014,
|
||||
err_websocket_voice_server_crashed = 4015,
|
||||
err_websocket_voice_unknown_encryption = 4016,
|
||||
err_compression_stream = 6000,
|
||||
err_compression_data = 6001,
|
||||
err_compression_memory = 6002,
|
||||
err_unknown_account = 10001,
|
||||
err_unknown_application = 10002,
|
||||
err_unknown_channel = 10003,
|
||||
err_unknown_guild = 10004,
|
||||
err_unknown_integration = 10005,
|
||||
err_unknown_invite = 10006,
|
||||
err_unknown_member = 10007,
|
||||
err_unknown_message = 10008,
|
||||
err_unknown_permission_overwrite = 10009,
|
||||
err_unknown_provider = 10010,
|
||||
err_unknown_role = 10011,
|
||||
err_unknown_token = 10012,
|
||||
err_unknown_user = 10013,
|
||||
err_unknown_emoji = 10014,
|
||||
err_unknown_webhook = 10015,
|
||||
err_unknown_webhook_service = 10016,
|
||||
err_unknown_session = 10020,
|
||||
err_unknown_ban = 10026,
|
||||
err_unknown_sku = 10027,
|
||||
err_unknown_store_listing = 10028,
|
||||
err_unknown_entitlement = 10029,
|
||||
err_unknown_build = 10030,
|
||||
err_unknown_lobby = 10031,
|
||||
err_unknown_branch = 10032,
|
||||
err_unknown_store_directory_layout = 10033,
|
||||
err_unknown_redistributable = 10036,
|
||||
err_unknown_gift_code = 10038,
|
||||
err_unknown_stream = 10049,
|
||||
err_unknown_premium_server_subscribe_cooldown = 10050,
|
||||
err_unknown_guild_template = 10057,
|
||||
err_unknown_discoverable_server_category = 10059,
|
||||
err_unknown_sticker = 10060,
|
||||
err_unknown_interaction = 10062,
|
||||
err_unknown_application_command = 10063,
|
||||
err_unknown_voice_state = 10065,
|
||||
err_unknown_application_command_permissions = 10066,
|
||||
err_unknown_stage_instance = 10067,
|
||||
err_unknown_guild_member_verification_form = 10068,
|
||||
err_unknown_guild_welcome_screen = 10069,
|
||||
err_unknown_guild_scheduled_event = 10070,
|
||||
err_unknown_guild_scheduled_event_user = 10071,
|
||||
err_unknown_tag = 10087,
|
||||
err_bots_cannot_use_this_endpoint = 20001,
|
||||
err_only_bots_can_use_this_endpoint = 20002,
|
||||
err_explicit_content = 20009,
|
||||
err_unauthorized_for_application = 20012,
|
||||
err_slowmode_rate_limit = 20016,
|
||||
err_owner_only = 20018,
|
||||
err_announcement_rate_limit = 20022,
|
||||
err_under_minimum_age = 20024,
|
||||
err_write_rate_limit = 20029,
|
||||
err_stage_banned_words = 20031,
|
||||
err_guild_premium_subscription_level_too_low = 20035,
|
||||
err_guilds = 30001,
|
||||
err_friends = 30002,
|
||||
err_pins_for_the_channel = 30003,
|
||||
err_recipients = 30004,
|
||||
err_guild_roles = 30005,
|
||||
err_webhooks = 30007,
|
||||
err_emojis = 30008,
|
||||
err_reactions = 30010,
|
||||
err_group_dms = 30011,
|
||||
err_guild_channels = 30013,
|
||||
err_attachments_in_a_message = 30015,
|
||||
err_invites = 30016,
|
||||
err_animated_emojis = 30018,
|
||||
err_server_members = 30019,
|
||||
err_server_categories = 30030,
|
||||
err_guild_already_has_a_template = 30031,
|
||||
err_application_commands = 30032,
|
||||
err_thread_participants = 30033,
|
||||
err_daily_application_command_creates = 30034,
|
||||
err_bans_for_non_guild_members_have_been_exceeded = 30035,
|
||||
err_bans_fetches = 30037,
|
||||
err_uncompleted_guild_scheduled_events = 30038,
|
||||
err_stickers = 30039,
|
||||
err_prune_requests = 30040,
|
||||
err_guild_widget_settings_updates = 30042,
|
||||
err_edits_to_messages_older_than_1_hour = 30046,
|
||||
err_pinned_threads_in_a_forum_channel = 30047,
|
||||
err_tags_in_a_forum_channel = 30048,
|
||||
err_bitrate_is_too_high_for_channel_of_this_type = 30052,
|
||||
err_premium_emojis = 30056,
|
||||
err_webhooks_per_guild = 30058,
|
||||
err_channel_permission_overwrites = 30060,
|
||||
err_the_channels_for_this_guild_are_too_large = 30061,
|
||||
err_unauthorized_invalid_token = 40001,
|
||||
err_verify_your_account = 40002,
|
||||
err_you_are_opening_direct_messages_too_fast = 40003,
|
||||
err_send_messages_has_been_temporarily_disabled = 40004,
|
||||
err_request_entity_too_large = 40005,
|
||||
err_this_feature_has_been_temporarily_disabled_server_side = 40006,
|
||||
err_the_user_is_banned_from_this_guild = 40007,
|
||||
err_connection_has_been_revoked = 40012,
|
||||
err_target_user_is_not_connected_to_voice = 40032,
|
||||
err_this_message_has_already_been_crossposted = 40033,
|
||||
err_an_application_command_with_that_name_already_exists = 40041,
|
||||
err_application_interaction_failed_to_send = 40043,
|
||||
err_cannot_send_a_message_in_a_forum_channel = 40058,
|
||||
err_interaction_has_already_been_acknowledged = 40060,
|
||||
err_tag_names_must_be_unique = 40061,
|
||||
err_service_resource_is_being_rate_limited = 40062,
|
||||
err_no_tags_available = 40066,
|
||||
err_tag_required = 40067,
|
||||
err_entitlement_already_granted = 40074,
|
||||
err_missing_access = 50001,
|
||||
err_invalid_account_type = 50002,
|
||||
err_cannot_execute_action_on_a_dm_channel = 50003,
|
||||
err_guild_widget_disabled = 50004,
|
||||
err_cannot_edit_a_message_by_other_user = 50005,
|
||||
err_cannot_send_empty_message = 50006,
|
||||
err_cannot_send_messages_to_this_user = 50007,
|
||||
err_cannot_send_messages_in_a_non_text_channel = 50008,
|
||||
err_channel_verification_level_too_high = 50009,
|
||||
err_oauth2_application_does_not_have_a_bot = 50010,
|
||||
err_oauth2_application_limit = 50011,
|
||||
err_invalid_oauth2_state = 50012,
|
||||
err_permissions = 50013,
|
||||
err_invalid_authentication_token = 50014,
|
||||
err_note_was_too_long = 50015,
|
||||
err_too_few_or_too_many_messages = 50016,
|
||||
err_invalid_mfa_level = 50017,
|
||||
err_invalid_pin = 50019,
|
||||
err_invite_code_invalid = 50020,
|
||||
err_system_message = 50021,
|
||||
err_channel_type = 50024,
|
||||
err_invalid_oauth2_access_token = 50025,
|
||||
err_missing_required_oauth2_scope = 50026,
|
||||
err_invalid_webhook_token = 50027,
|
||||
err_invalid_role = 50028,
|
||||
err_invalid_recipients = 50033,
|
||||
err_too_old_to_bulk_delete = 50034,
|
||||
err_invalid_form_body = 50035,
|
||||
err_invite_error = 50036,
|
||||
err_invalid_activity_action = 50039,
|
||||
err_invalid_api_version_provided = 50041,
|
||||
err_file_uploaded_exceeds_the_maximum_size = 50045,
|
||||
err_invalid_file_uploaded = 50046,
|
||||
err_cannot_self_redeem_this_gift = 50054,
|
||||
err_invalid_guild = 50055,
|
||||
err_invalid_sku = 50057,
|
||||
err_invalid_request_origin = 50067,
|
||||
err_invalid_message_type = 50068,
|
||||
err_payment_source_required = 50070,
|
||||
err_cannot_modify_a_system_webhook = 50073,
|
||||
err_cannot_delete_a_channel_required_for_community_guilds = 50074,
|
||||
err_cannot_edit_stickers_within_a_message = 50080,
|
||||
err_invalid_sticker_sent = 50081,
|
||||
err_tried_to_perform_an_operation_on_an_archived_thread = 50083,
|
||||
err_invalid_thread_notification_settings = 50084,
|
||||
err_before_value_is_earlier_than_the_thread_creation_date = 50085,
|
||||
err_community_server_channels_must_be_text_channels = 50086,
|
||||
err_bad_event_entity_type = 50091,
|
||||
err_this_server_is_not_available_in_your_location = 50095,
|
||||
err_monetization_enabled_in_order_to_perform_this_action = 50097,
|
||||
err_more_boosts_to_perform_this_action = 50101,
|
||||
err_the_request_body_contains_invalid_json = 50109,
|
||||
err_owner_cannot_be_pending_member = 50131,
|
||||
err_ownership_cannot_be_transferred_to_a_bot_user = 50132,
|
||||
err_failed_to_resize_asset_below_the_maximum_size = 50138,
|
||||
err_cannot_mix_subscription_and_non_subscription_roles_for_an_emoji = 50144,
|
||||
err_cannot_convert_between_premium_emoji_and_normal_emoji = 50145,
|
||||
err_uploaded_file_not_found = 50146,
|
||||
err_voice_messages_do_not_support_additional_content = 50159,
|
||||
err_voice_messages_must_have_a_single_audio_attachment = 50160,
|
||||
err_voice_messages_must_have_supporting_metadata = 50161,
|
||||
err_voice_messages_cannot_be_edited = 50162,
|
||||
err_cannot_delete_guild_subscription_integration = 50163,
|
||||
err_you_cannot_send_voice_messages_in_this_channel = 50173,
|
||||
err_the_user_account_must_first_be_verified = 50178,
|
||||
err_you_do_not_have_permission_to_send_this_sticker = 50600,
|
||||
err_two_factor_is_required_for_this_operation = 60003,
|
||||
err_no_users_with_discordtag_exist = 80004,
|
||||
err_reaction_was_blocked = 90001,
|
||||
err_user_cannot_use_burst_reactions = 90002,
|
||||
err_application_not_yet_available = 110001,
|
||||
err_api_resource_is_currently_overloaded = 130000,
|
||||
err_the_stage_is_already_open = 150006,
|
||||
err_cannot_reply_without_permission_to_read_message_history = 160002,
|
||||
err_a_thread_has_already_been_created_for_this_message = 160004,
|
||||
err_thread_is_locked = 160005,
|
||||
err_active_threads = 160006,
|
||||
err_active_announcement_threads = 160007,
|
||||
err_invalid_json_for_uploaded_lottie_file = 170001,
|
||||
err_uploaded_lotties_cannot_contain_rasterized_images = 170002,
|
||||
err_sticker_maximum_framerate = 170003,
|
||||
err_sticker_frame_count = 170004,
|
||||
err_lottie_animation_dimensions = 170005,
|
||||
err_sticker_frame_rate = 170006,
|
||||
err_sticker_animation_duration = 170007,
|
||||
err_cannot_update_a_finished_event = 180000,
|
||||
err_failed_to_create_stage_needed_for_stage_event = 180002,
|
||||
err_message_was_blocked_by_automatic_moderation = 200000,
|
||||
err_title_was_blocked_by_automatic_moderation = 200001,
|
||||
err_webhooks_posted_to_forum_channels_must_have_a_thread_name_or_thread_id = 220001,
|
||||
err_webhooks_posted_to_forum_channels_cannot_have_both_a_thread_name_and_thread_id = 220002,
|
||||
err_webhooks_can_only_create_threads_in_forum_channels = 220003,
|
||||
err_webhook_services_cannot_be_used_in_forum_channels = 220004,
|
||||
err_message_blocked_links = 240000,
|
||||
err_cannot_enable_onboarding_requirements_are_not_met = 350000,
|
||||
err_cannot_update_onboarding_below_requirements = 350001,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The dpp::exception class derives from std::exception and supports some other
|
||||
* ways of passing in error details such as via std::string.
|
||||
*/
|
||||
class exception : public std::exception
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* @brief Exception message
|
||||
*/
|
||||
std::string msg;
|
||||
|
||||
/**
|
||||
* @brief Exception error code
|
||||
*/
|
||||
exception_error_code error_code;
|
||||
|
||||
public:
|
||||
|
||||
using std::exception::exception;
|
||||
|
||||
/**
|
||||
* @brief Construct a new exception object
|
||||
*/
|
||||
exception() = default;
|
||||
|
||||
/**
|
||||
* @brief Construct a new exception object
|
||||
*
|
||||
* @param what reason message
|
||||
*/
|
||||
explicit exception(const char* what) : msg(what), error_code(err_no_code_specified) { }
|
||||
|
||||
/**
|
||||
* @brief Construct a new exception object
|
||||
*
|
||||
* @param what reason message
|
||||
* @param code Exception code
|
||||
*/
|
||||
explicit exception(exception_error_code code, const char* what) : msg(what), error_code(code) { }
|
||||
|
||||
/**
|
||||
* @brief Construct a new exception object
|
||||
*
|
||||
* @param what reason message
|
||||
* @param len length of reason message
|
||||
*/
|
||||
exception(const char* what, size_t len) : msg(what, len), error_code(err_no_code_specified) { }
|
||||
|
||||
/**
|
||||
* @brief Construct a new exception object
|
||||
*
|
||||
* @param what reason message
|
||||
*/
|
||||
explicit exception(const std::string& what) : msg(what), error_code(err_no_code_specified) { }
|
||||
|
||||
/**
|
||||
* @brief Construct a new exception object
|
||||
*
|
||||
* @param what reason message
|
||||
* @param code Exception code
|
||||
*/
|
||||
explicit exception(exception_error_code code, const std::string& what) : msg(what), error_code(code) { }
|
||||
|
||||
/**
|
||||
* @brief Construct a new exception object
|
||||
*
|
||||
* @param what reason message
|
||||
*/
|
||||
explicit exception(std::string&& what) : msg(std::move(what)) { }
|
||||
|
||||
/**
|
||||
* @brief Construct a new exception object
|
||||
*
|
||||
* @param what reason message
|
||||
* @param code Exception code
|
||||
*/
|
||||
explicit exception(exception_error_code code, std::string&& what) : msg(std::move(what)), error_code(code) { }
|
||||
|
||||
/**
|
||||
* @brief Construct a new exception object (copy constructor)
|
||||
*/
|
||||
exception(const exception&) = default;
|
||||
|
||||
/**
|
||||
* @brief Construct a new exception object (move constructor)
|
||||
*/
|
||||
exception(exception&&) = default;
|
||||
|
||||
/**
|
||||
* @brief Destroy the exception object
|
||||
*/
|
||||
~exception() override = default;
|
||||
|
||||
/**
|
||||
* @brief Copy assignment operator
|
||||
*
|
||||
* @return exception& reference to self
|
||||
*/
|
||||
exception & operator = (const exception &) = default;
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator
|
||||
*
|
||||
* @return exception& reference to self
|
||||
*/
|
||||
exception & operator = (exception&&) = default;
|
||||
|
||||
/**
|
||||
* @brief Get exception message
|
||||
*
|
||||
* @return const char* error message
|
||||
*/
|
||||
[[nodiscard]] const char* what() const noexcept override { return msg.c_str(); };
|
||||
|
||||
/**
|
||||
* @brief Get exception code
|
||||
*
|
||||
* @return exception_error_code error code
|
||||
*/
|
||||
[[nodiscard]] exception_error_code code() const noexcept { return error_code; };
|
||||
|
||||
};
|
||||
|
||||
#ifndef _DOXYGEN_
|
||||
#define derived_exception(name, ancestor) class name : public dpp::ancestor { \
|
||||
public: \
|
||||
using dpp::ancestor::ancestor; \
|
||||
name() = default; \
|
||||
explicit name(const char* what) : ancestor(what) { } \
|
||||
explicit name(exception_error_code code, const char* what) : ancestor(code, what) { } \
|
||||
name(const char* what, size_t len) : ancestor(what, len) { } \
|
||||
explicit name(const std::string& what) : ancestor(what) { } \
|
||||
explicit name(exception_error_code code, const std::string& what) : ancestor(code, what) { } \
|
||||
explicit name(std::string&& what) : ancestor(what) { } \
|
||||
explicit name(exception_error_code code, std::string&& what) : ancestor(code, what) { } \
|
||||
name(const name&) = default; \
|
||||
name(name&&) = default; \
|
||||
~name() override = default; \
|
||||
name & operator = (const name &) = default; \
|
||||
name & operator = (name&&) = default; \
|
||||
[[nodiscard]] const char* what() const noexcept override { return msg.c_str(); }; \
|
||||
[[nodiscard]] exception_error_code code() const noexcept { return error_code; }; \
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef _DOXYGEN_
|
||||
/*
|
||||
* THESE DEFINITIONS ARE NOT THE REAL DEFINITIONS USED BY PROGRAM CODE.
|
||||
*
|
||||
* They exist only to cause Doxygen to emit proper documentation for the derived exception types.
|
||||
* Proper definitions are emitted by the `derived_exception` macro in the "else" section.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Represents an error in logic, e.g. you asked the library to do something the Discord API does not support
|
||||
* @note This is a stub for documentation purposes. For full information on supported methods please see dpp::exception.
|
||||
*/
|
||||
class logic_exception : public dpp::exception { };
|
||||
/**
|
||||
* @brief Represents an error reading or writing to a file
|
||||
* @note This is a stub for documentation purposes. For full information on supported methods please see dpp::exception.
|
||||
*/
|
||||
class file_exception : public dpp::exception { };
|
||||
/**
|
||||
* @brief Represents an error establishing or maintaining a connection
|
||||
* @note This is a stub for documentation purposes. For full information on supported methods please see dpp::exception.
|
||||
*/
|
||||
class connection_exception : public dpp::exception { };
|
||||
/**
|
||||
* @brief Represents an error with voice processing
|
||||
* @note This is a stub for documentation purposes. For full information on supported methods please see dpp::exception.
|
||||
*/
|
||||
class voice_exception : public dpp::exception { };
|
||||
/**
|
||||
* @brief Represents an error on a REST API call, e.g. a HTTPS request
|
||||
* @note This is a stub for documentation purposes. For full information on supported methods please see dpp::exception.
|
||||
*/
|
||||
class rest_exception : public dpp::exception { };
|
||||
/**
|
||||
* @brief Represents invalid length of argument being passed to a function
|
||||
* @note This is a stub for documentation purposes. For full information on supported methods please see dpp::exception.
|
||||
*/
|
||||
class length_exception : public dpp::exception { };
|
||||
/**
|
||||
* @brief Represents inability to parse data, usually caused by malformed JSON or ETF
|
||||
* @note This is a stub for documentation purposes. For full information on supported methods please see dpp::exception.
|
||||
*/
|
||||
class parse_exception : public dpp::exception { };
|
||||
/**
|
||||
* @brief Represents invalid access to dpp's cache or its members, which may or may not exist.
|
||||
* @note This is a stub for documentation purposes. For full information on supported methods please see dpp::exception.
|
||||
*/
|
||||
class cache_exception : public dpp::exception { };
|
||||
/**
|
||||
* @brief Represents an attempt to construct a cluster with an invalid bot token.
|
||||
* @note This is a stub for documentation purposes. For full information on supported methods please see dpp::exception.
|
||||
*/
|
||||
class invalid_token_exception : public dpp::rest_exception { };
|
||||
#ifndef DPP_NO_CORO
|
||||
/**
|
||||
* @brief Represents the cancellation of a task. Will be thrown to the awaiter of a cancelled task.
|
||||
* @note This is a stub for documentation purposes. For full information on supported methods please see dpp::exception.
|
||||
*/
|
||||
class task_cancelled_exception : public dpp::exception { };
|
||||
#endif /* DPP_NO_CORO */
|
||||
#else
|
||||
derived_exception(logic_exception, exception);
|
||||
derived_exception(file_exception, exception);
|
||||
derived_exception(connection_exception, exception);
|
||||
derived_exception(voice_exception, exception);
|
||||
derived_exception(encryption_exception, voice_exception);
|
||||
derived_exception(decryption_exception, voice_exception);
|
||||
derived_exception(rest_exception, exception);
|
||||
derived_exception(invalid_token_exception, rest_exception);
|
||||
derived_exception(length_exception, exception);
|
||||
derived_exception(parse_exception, exception);
|
||||
derived_exception(cache_exception, exception);
|
||||
# ifndef DPP_NO_CORO
|
||||
derived_exception(task_cancelled_exception, exception);
|
||||
# endif /* DPP_NO_CORO */
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
148
dpp/export.h
148
dpp/export.h
@ -1,148 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
/* Compile-time check for C++17.
|
||||
* Either one of the following causes a compile time error:
|
||||
* __cplusplus not defined at all (this means we are being compiled on a C compiler)
|
||||
* MSVC defined and _MSVC_LANG < 201703L (Visual Studio, but not C++17 or newer)
|
||||
* MSVC not defined and __cplusplus < 201703L (Non-visual studio, but not C++17 or newer)
|
||||
* The additional checks are required because MSVC doesn't correctly set __cplusplus to 201703L,
|
||||
* which is hugely non-standard, but apparently "it broke stuff" so they dont ever change it
|
||||
* from C++98. Ugh.
|
||||
*/
|
||||
#if (!defined(__cplusplus) || (defined(_MSC_VER) && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)) || (!defined(_MSC_VER) && __cplusplus < 201703L))
|
||||
#error "D++ Requires a C++17 compatible C++ compiler. Please ensure that you have enabled C++17 in your compiler flags."
|
||||
#endif
|
||||
|
||||
/* If not using c++20, define DPP_CPP17_COMPAT and DPP_NO_CORO if DPP_NO_CORO is not already defined.
|
||||
*/
|
||||
#if !(defined(__cplusplus) && __cplusplus >= 202002L) && !(defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
||||
#define DPP_CPP17_COMPAT
|
||||
#if !defined(DPP_CORO) || !DPP_CORO // Allow overriding this because why not
|
||||
#ifndef DPP_NO_CORO
|
||||
#define DPP_NO_CORO
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef DPP_STATIC
|
||||
/* Dynamic linked build as shared object or dll */
|
||||
#ifdef DPP_BUILD
|
||||
/* Building the library */
|
||||
#ifdef _WIN32
|
||||
#include <dpp/win32_safe_warnings.h>
|
||||
#define DPP_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define DPP_EXPORT
|
||||
#endif
|
||||
#else
|
||||
/* Including the library */
|
||||
#ifdef _WIN32
|
||||
#define DPP_EXPORT __declspec(dllimport)
|
||||
#else
|
||||
#define DPP_EXPORT
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
/* Static linked build */
|
||||
#if defined(_WIN32) && defined(DPP_BUILD)
|
||||
#include <dpp/win32_safe_warnings.h>
|
||||
#endif
|
||||
#define DPP_EXPORT
|
||||
#endif
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Represents a build configuration. On some platforms (e.g. Windows) release isn't compatible with debug, so we use this enum to detect it.
|
||||
*/
|
||||
enum class build_type {
|
||||
/**
|
||||
* @brief Universal build, works with both debug and release
|
||||
*/
|
||||
universal,
|
||||
|
||||
/**
|
||||
* @brief Debug build
|
||||
*/
|
||||
debug,
|
||||
|
||||
/**
|
||||
* @brief Release build
|
||||
*/
|
||||
release
|
||||
};
|
||||
|
||||
template <build_type>
|
||||
extern bool DPP_EXPORT validate_configuration();
|
||||
|
||||
#if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_GAME) || defined(UE_EDITOR) || defined(UE_BUILD_SHIPPING_WITH_EDITOR) || defined(UE_BUILD_DOCS)
|
||||
/*
|
||||
* We need to tell DPP to NOT do the version checker if something from Unreal Engine is defined.
|
||||
* We have to do this because UE is causing some weirdness where the version checker is broken and always errors.
|
||||
* This is really only for DPP-UE. There is no reason to not do the version checker unless you are in Unreal Engine.
|
||||
*/
|
||||
#define DPP_BYPASS_VERSION_CHECKING
|
||||
#endif /* UE */
|
||||
|
||||
#ifndef DPP_BUILD /* when including dpp */
|
||||
/**
|
||||
* Version checking, making sure the program is in a configuration compatible with DPP's.
|
||||
*
|
||||
* Do NOT make these variables constexpr.
|
||||
* We want them to initialize at runtime so the function can be pulled from the shared library object.
|
||||
*/
|
||||
#ifndef DPP_BYPASS_VERSION_CHECKING
|
||||
#if defined(_WIN32)
|
||||
#ifdef _DEBUG
|
||||
inline const bool is_valid_config = validate_configuration<build_type::debug>();
|
||||
#else
|
||||
inline const bool is_valid_config = validate_configuration<build_type::release>();
|
||||
#endif /* _DEBUG */
|
||||
#else
|
||||
inline const bool is_valid_config = validate_configuration<build_type::universal>();
|
||||
#endif /* _WIN32 */
|
||||
#endif /* !DPP_BYPASS_VERSION_CHECKING */
|
||||
#endif /* !DPP_BUILD */
|
||||
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <WinSock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef _DOXYGEN_
|
||||
/** @brief Macro that expands to [[deprecated(reason)]] when including the library, nothing when building the library */
|
||||
#define DPP_DEPRECATED(reason)
|
||||
#else /* !_DOXYGEN_ */
|
||||
#if defined(DPP_BUILD) || defined(DPP_NO_DEPRECATED)
|
||||
/** @brief Macro that expands to [[deprecated(reason)]] when including the library, nothing when building the library */
|
||||
#define DPP_DEPRECATED(reason)
|
||||
#else
|
||||
/** @brief Macro that expands to [[deprecated(reason)]] when including the library, nothing when building the library */
|
||||
#define DPP_DEPRECATED(reason) [[deprecated(reason)]]
|
||||
#endif
|
||||
#endif /* _DOXYGEN_ */
|
||||
2053
dpp/guild.h
2053
dpp/guild.h
File diff suppressed because it is too large
Load Diff
@ -1,74 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/cluster.h>
|
||||
#include <dpp/socket_listener.h>
|
||||
#include <dpp/http_server_request.h>
|
||||
#include <dpp/ssl_context.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Creates a simple HTTP server which listens on a TCP port for a
|
||||
* plaintext or SSL incoming request, and passes that request to a callback
|
||||
* to generate the response.
|
||||
*/
|
||||
struct DPP_EXPORT http_server : public socket_listener<http_server_request> {
|
||||
|
||||
/**
|
||||
* @brief Request handler callback to use for all incoming HTTP(S) requests
|
||||
*/
|
||||
http_server_request_event request_handler;
|
||||
|
||||
/**
|
||||
* @brief Port we are listening on
|
||||
*/
|
||||
uint16_t bound_port;
|
||||
|
||||
/**
|
||||
* @brief Constructor for creation of a HTTP(S) server
|
||||
* @param creator Cluster creator
|
||||
* @param address address to bind to, use "0.0.0.0" to bind to all local addresses
|
||||
* @param port port to bind to. You should generally use a port > 1024.
|
||||
* @param handle_request Callback to call for each pending request
|
||||
* @param private_key Private key PEM file for HTTPS/SSL. If empty, a plaintext server is created
|
||||
* @param public_key Public key PEM file for HTTPS/SSL. If empty, a plaintext server is created
|
||||
*/
|
||||
http_server(cluster* creator, const std::string_view address, uint16_t port, http_server_request_event handle_request, const std::string& private_key = "", const std::string& public_key = "");
|
||||
|
||||
/**
|
||||
* @brief Emplace a new request into the connection pool
|
||||
* @param newfd file descriptor of new request
|
||||
*/
|
||||
void emplace(socket newfd) override;
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~http_server() {
|
||||
detail::release_ssl_context(bound_port);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,260 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
#include <dpp/sslconnection.h>
|
||||
#include <dpp/version.h>
|
||||
#include <dpp/stringops.h>
|
||||
#include <dpp/httpsclient.h>
|
||||
#include <climits>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Callback type for HTTP server request callbacks
|
||||
*/
|
||||
using http_server_request_event = std::function<void(class http_server_request*)>;
|
||||
|
||||
/*
|
||||
* @brief Implements a HTTPS socket client based on the SSL client.
|
||||
* @note plaintext HTTP without SSL is also supported via a "downgrade" setting
|
||||
*/
|
||||
class DPP_EXPORT http_server_request : public ssl_connection {
|
||||
/**
|
||||
* @brief The request body, e.g. form data
|
||||
*/
|
||||
std::string request_body;
|
||||
|
||||
/**
|
||||
* @brief Headers from the client
|
||||
*/
|
||||
http_headers request_headers;
|
||||
|
||||
/**
|
||||
* @brief Time at which the request should be abandoned
|
||||
*/
|
||||
time_t timeout;
|
||||
|
||||
/**
|
||||
* @brief Headers for our response
|
||||
*/
|
||||
http_headers response_headers;
|
||||
|
||||
/**
|
||||
* @brief Handler to handle the inbound request
|
||||
*/
|
||||
http_server_request_event handler{};
|
||||
|
||||
/**
|
||||
* @brief Response body
|
||||
*/
|
||||
std::string response_body;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief The type of the request, e.g. GET, POST
|
||||
*/
|
||||
std::string request_type;
|
||||
|
||||
/**
|
||||
* @brief Path part of URL for HTTPS connection
|
||||
*/
|
||||
std::string path;
|
||||
|
||||
/**
|
||||
* @brief Current connection state
|
||||
*/
|
||||
http_state state;
|
||||
|
||||
/**
|
||||
* @brief HTTP status code for response
|
||||
*/
|
||||
uint16_t status{0};
|
||||
|
||||
/**
|
||||
* @brief Start the connection
|
||||
*/
|
||||
virtual void connect() override;
|
||||
|
||||
/**
|
||||
* @brief Called when the output buffer is drained to empty
|
||||
*/
|
||||
void on_buffer_drained() override;
|
||||
|
||||
/**
|
||||
* @brief Maximum size of POST body
|
||||
*/
|
||||
[[nodiscard]] uint64_t get_max_post_size() const;
|
||||
|
||||
/**
|
||||
* @brief Maximum size of headers
|
||||
*/
|
||||
[[nodiscard]] uint64_t get_max_header_size() const;
|
||||
|
||||
/**
|
||||
* @brief Reply with an error message
|
||||
* @param error_code error code
|
||||
* @param message message
|
||||
*/
|
||||
void generate_error(uint16_t error_code, const std::string& message);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief If true the response timed out while waiting
|
||||
*/
|
||||
bool timed_out;
|
||||
|
||||
/**
|
||||
* @brief Get request state
|
||||
* @return request state
|
||||
*/
|
||||
http_state get_state() const;
|
||||
|
||||
/**
|
||||
* @brief Get current response body
|
||||
* @return response body
|
||||
*/
|
||||
std::string get_response_body() const;
|
||||
|
||||
/**
|
||||
* @brief Get current request body
|
||||
* @return request body
|
||||
*/
|
||||
std::string get_request_body() const;
|
||||
|
||||
/**
|
||||
* @brief Get current status code
|
||||
* @return status code
|
||||
*/
|
||||
uint16_t get_status() const;
|
||||
|
||||
/**
|
||||
* @brief Content length sent by client
|
||||
*/
|
||||
uint64_t content_length{ULLONG_MAX};
|
||||
|
||||
/**
|
||||
* @brief Construct a new server request object.
|
||||
* Server request objects are instantiated for an incoming server connection, as such they already
|
||||
* have a file descriptor.
|
||||
* @param creator creating owner
|
||||
* @param fd file descriptor
|
||||
* @param port Port the connection came in on
|
||||
* @param plaintext_downgrade true if plaintext, false if SSL
|
||||
* @param private_key if SSL, the path to the private key PEM
|
||||
* @param public_key if SSL, the path to the public key PEM
|
||||
* @param handle_request request handler callback
|
||||
*/
|
||||
http_server_request(cluster* creator, socket fd, uint16_t port, bool plaintext_downgrade, const std::string& private_key, const std::string& public_key, http_server_request_event handle_request);
|
||||
|
||||
/**
|
||||
* @brief Destroy the https client object
|
||||
*/
|
||||
virtual ~http_server_request() override;
|
||||
|
||||
/**
|
||||
* @brief Processes incoming data from the SSL socket input buffer.
|
||||
*
|
||||
* @param buffer The buffer contents. Can modify this value removing the head elements when processed.
|
||||
*/
|
||||
virtual bool handle_buffer(std::string &buffer) override;
|
||||
|
||||
/**
|
||||
* @brief Close HTTPS socket
|
||||
*/
|
||||
virtual void close() override;
|
||||
|
||||
/**
|
||||
* @brief Fires every second from the underlying socket I/O loop, used for timeouts
|
||||
*/
|
||||
virtual void one_second_timer() override;
|
||||
|
||||
/**
|
||||
* @brief Get a HTTP request header
|
||||
*
|
||||
* @param header_name Header name to find, case insensitive
|
||||
* @return Header content or empty string if not found.
|
||||
* If multiple values have the same header_name, this will return one of them.
|
||||
* @see get_header_count to determine if multiple are present
|
||||
* @see get_header_list to retrieve all entries of the same header_name
|
||||
*/
|
||||
[[nodiscard]] const std::string get_header(const std::string& header_name) const;
|
||||
|
||||
/**
|
||||
* @brief Get the number of headers with the same header name
|
||||
*
|
||||
* @param header_name
|
||||
* @return the number of headers with this count
|
||||
*/
|
||||
[[nodiscard]] size_t get_header_count(const std::string& header_name) const;
|
||||
|
||||
/**
|
||||
* @brief Get a set of HTTP request headers with a common name
|
||||
*
|
||||
* @param header_name
|
||||
* @return A list of headers with the same name, or an empty list if not found
|
||||
*/
|
||||
[[nodiscard]] std::list<std::string> get_header_list(const std::string& header_name) const;
|
||||
|
||||
/**
|
||||
* @brief Get all HTTP request headers
|
||||
*
|
||||
* @return headers as a map
|
||||
*/
|
||||
[[nodiscard]] std::multimap<std::string, std::string> get_headers() const;
|
||||
|
||||
/**
|
||||
* @brief Set a response header
|
||||
* @param header header name
|
||||
* @param value header value
|
||||
* @return ref to self
|
||||
*/
|
||||
http_server_request& set_response_header(const std::string& header, const std::string& value);
|
||||
|
||||
/**
|
||||
* @brief Set the response content
|
||||
*
|
||||
* @param new_content response content
|
||||
*/
|
||||
http_server_request& set_response_body(const std::string& new_content);
|
||||
|
||||
/**
|
||||
* @brief Set the response HTTP status, e.g.
|
||||
* 200 for OK, 404 for not found, 429 for rate limited etc.
|
||||
*
|
||||
* @param new_status HTTP status
|
||||
*/
|
||||
http_server_request& set_status(uint16_t new_status);
|
||||
|
||||
/**
|
||||
* @brief Get whole response as a string
|
||||
*/
|
||||
[[nodiscard]] std::string get_response();
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,357 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
#include <dpp/sslconnection.h>
|
||||
#include <dpp/version.h>
|
||||
#include <dpp/stringops.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
static inline const std::string http_version = "DiscordBot (https://github.com/brainboxdotcc/DPP, "
|
||||
+ to_hex(DPP_VERSION_MAJOR, false) + "." + to_hex(DPP_VERSION_MINOR, false) + "." + to_hex(DPP_VERSION_PATCH, false) + ")";
|
||||
|
||||
static inline constexpr const char* DISCORD_HOST = "https://discord.com";
|
||||
|
||||
/**
|
||||
* @brief HTTP connection status
|
||||
*/
|
||||
enum http_state : uint8_t {
|
||||
/**
|
||||
* @brief Sending/receiving HTTP headers and request body
|
||||
*/
|
||||
HTTPS_HEADERS,
|
||||
|
||||
/**
|
||||
* @brief Receiving body content.
|
||||
*/
|
||||
HTTPS_CONTENT,
|
||||
|
||||
/**
|
||||
* @brief Completed connection, as it was closed or the body is >= Content-Length
|
||||
*
|
||||
*/
|
||||
HTTPS_DONE,
|
||||
|
||||
/**
|
||||
* @brief Received chunk length
|
||||
*
|
||||
*/
|
||||
HTTPS_CHUNK_LEN,
|
||||
|
||||
/**
|
||||
* @brief Received chunk trailing CRLF
|
||||
*/
|
||||
HTTPS_CHUNK_TRAILER,
|
||||
|
||||
/**
|
||||
* @brief The last received chunk is the final chunk
|
||||
*/
|
||||
HTTPS_CHUNK_LAST,
|
||||
|
||||
/**
|
||||
* @brief Receiving contents of a chunk
|
||||
*/
|
||||
HTTPS_CHUNK_CONTENT
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Request headers
|
||||
*/
|
||||
typedef std::multimap<std::string, std::string> http_headers;
|
||||
|
||||
/**
|
||||
* @brief Represents a multipart mime body and the correct top-level mime type
|
||||
* If a non-multipart request is passed in, this is represented as a plain body
|
||||
* and the application/json mime type.
|
||||
*/
|
||||
struct multipart_content {
|
||||
/**
|
||||
* @brief Multipart body
|
||||
*/
|
||||
std::string body;
|
||||
|
||||
/**
|
||||
* @brief MIME type
|
||||
*/
|
||||
std::string mimetype;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a HTTP scheme, hostname and port
|
||||
* split into parts for easy use in https_client.
|
||||
*/
|
||||
struct http_connect_info {
|
||||
/**
|
||||
* @brief True if the connection should be SSL
|
||||
*/
|
||||
bool is_ssl{};
|
||||
|
||||
/**
|
||||
* @brief The request scheme, e.g. 'https' or 'http'
|
||||
*/
|
||||
std::string scheme;
|
||||
|
||||
/**
|
||||
* @brief The request hostname part, e.g. 'discord.com'
|
||||
*/
|
||||
std::string hostname;
|
||||
|
||||
/**
|
||||
* @brief The port number, either determined from the scheme,
|
||||
* or from the part of the hostname after a colon ":" character
|
||||
*/
|
||||
uint16_t port{};
|
||||
};
|
||||
|
||||
using https_client_completion_event = std::function<void(class https_client*)>;
|
||||
|
||||
/**
|
||||
* @brief Implements a HTTPS socket client based on the SSL client.
|
||||
* @note plaintext HTTP without SSL is also supported via a "downgrade" setting
|
||||
*/
|
||||
class DPP_EXPORT https_client : public ssl_connection {
|
||||
|
||||
/**
|
||||
* @brief The type of the request, e.g. GET, POST
|
||||
*/
|
||||
std::string request_type;
|
||||
|
||||
/**
|
||||
* @brief Path part of URL for HTTPS connection
|
||||
*/
|
||||
std::string path;
|
||||
|
||||
/**
|
||||
* @brief The request body, e.g. form data
|
||||
*/
|
||||
std::string request_body;
|
||||
|
||||
/**
|
||||
* @brief The response body, e.g. file content or JSON
|
||||
*/
|
||||
std::string body;
|
||||
|
||||
/**
|
||||
* @brief The reported length of the content. If this is
|
||||
* UULONG_MAX, then no length was reported by the server.
|
||||
*/
|
||||
uint64_t content_length;
|
||||
|
||||
/**
|
||||
* @brief Headers for the request, e.g. Authorization, etc.
|
||||
*/
|
||||
http_headers request_headers;
|
||||
|
||||
/**
|
||||
* @brief The status of the HTTP request from the server,
|
||||
* e.g. 200 for OK, 404 for not found. A value of 0 means
|
||||
* no request has been completed.
|
||||
*/
|
||||
uint16_t status;
|
||||
|
||||
/**
|
||||
* @brief The HTTP protocol to use
|
||||
*/
|
||||
std::string http_protocol;
|
||||
|
||||
/**
|
||||
* @brief Time at which the request should be abandoned
|
||||
*/
|
||||
time_t timeout;
|
||||
|
||||
/**
|
||||
* @brief If true the content is chunked encoding
|
||||
*/
|
||||
bool chunked;
|
||||
|
||||
/**
|
||||
* @brief Size of current chunk
|
||||
*/
|
||||
size_t chunk_size;
|
||||
|
||||
/**
|
||||
* @brief Number of bytes received in current chunk
|
||||
*/
|
||||
size_t chunk_receive;
|
||||
|
||||
/**
|
||||
* @brief Headers from the server's response, e.g. RateLimit
|
||||
* headers, cookies, etc.
|
||||
*/
|
||||
std::multimap<std::string, std::string> response_headers;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Start the connection
|
||||
*/
|
||||
virtual void connect() override;
|
||||
|
||||
/**
|
||||
* @brief Get request state
|
||||
* @return request state
|
||||
*/
|
||||
http_state get_state();
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief If true the response timed out while waiting
|
||||
*/
|
||||
bool timed_out;
|
||||
|
||||
/**
|
||||
* @brief Function to call when HTTP request is completed
|
||||
*/
|
||||
https_client_completion_event completed;
|
||||
|
||||
/**
|
||||
* @brief Current connection state
|
||||
*/
|
||||
http_state state;
|
||||
|
||||
/**
|
||||
* @brief Connect to a specific HTTP(S) server and complete a request.
|
||||
*
|
||||
* The constructor will attempt the connection, and return the content.
|
||||
* By the time the constructor completes, the HTTP request will be stored
|
||||
* in the object.
|
||||
*
|
||||
* @note This is a blocking call. It starts a loop which runs non-blocking
|
||||
* functions within it, but does not return until the request completes.
|
||||
* See queues.cpp for how to make this asynchronous.
|
||||
*
|
||||
* @param hostname Hostname to connect to
|
||||
* @param port Port number to connect to, usually 443 for SSL and 80 for plaintext
|
||||
* @param urlpath path part of URL, e.g. "/api"
|
||||
* @param verb Request verb, e.g. GET or POST
|
||||
* @param req_body Request body, use dpp::https_client::build_multipart() to build a multipart MIME body (e.g. for multiple file upload)
|
||||
* @param extra_headers Additional request headers, e.g. user-agent, authorization, etc
|
||||
* @param plaintext_connection Set to true to make the connection plaintext (turns off SSL)
|
||||
* @param request_timeout How many seconds before the connection is considered failed if not finished
|
||||
* @param protocol Request HTTP protocol (default: 1.1)
|
||||
* @param done Function to call when https_client request is completed
|
||||
*/
|
||||
https_client(cluster* creator, const std::string &hostname, uint16_t port = 443, const std::string &urlpath = "/", const std::string &verb = "GET", const std::string &req_body = "", const http_headers& extra_headers = {}, bool plaintext_connection = false, uint16_t request_timeout = 5, const std::string &protocol = "1.1", https_client_completion_event done = {});
|
||||
|
||||
/**
|
||||
* @brief Destroy the https client object
|
||||
*/
|
||||
virtual ~https_client() override;
|
||||
|
||||
/**
|
||||
* @brief Build a multipart content from a set of files and some json
|
||||
*
|
||||
* @param json The json content
|
||||
* @param filenames File names of files to send
|
||||
* @param contents Contents of each of the files to send
|
||||
* @param mimetypes MIME types of each of the files to send
|
||||
* @return multipart mime content and headers
|
||||
*/
|
||||
static multipart_content build_multipart(const std::string &json, const std::vector<std::string>& filenames = {}, const std::vector<std::string>& contents = {}, const std::vector<std::string>& mimetypes = {});
|
||||
|
||||
/**
|
||||
* @brief Processes incoming data from the SSL socket input buffer.
|
||||
*
|
||||
* @param buffer The buffer contents. Can modify this value removing the head elements when processed.
|
||||
*/
|
||||
virtual bool handle_buffer(std::string &buffer) override;
|
||||
|
||||
/**
|
||||
* @brief Close HTTPS socket
|
||||
*/
|
||||
virtual void close() override;
|
||||
|
||||
/**
|
||||
* @brief Fires every second from the underlying socket I/O loop, used for timeouts
|
||||
*/
|
||||
virtual void one_second_timer() override;
|
||||
|
||||
/**
|
||||
* @brief Get a HTTP response header
|
||||
*
|
||||
* @param header_name Header name to find, case insensitive
|
||||
* @return Header content or empty string if not found.
|
||||
* If multiple values have the same header_name, this will return one of them.
|
||||
* @see get_header_count to determine if multiple are present
|
||||
* @see get_header_list to retrieve all entries of the same header_name
|
||||
*/
|
||||
const std::string get_header(std::string header_name) const;
|
||||
|
||||
/**
|
||||
* @brief Get the number of headers with the same header name
|
||||
*
|
||||
* @param header_name
|
||||
* @return the number of headers with this count
|
||||
*/
|
||||
size_t get_header_count(std::string header_name) const;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a set of HTTP response headers with a common name
|
||||
*
|
||||
* @param header_name
|
||||
* @return A list of headers with the same name, or an empty list if not found
|
||||
*/
|
||||
const std::list<std::string> get_header_list(std::string header_name) const;
|
||||
|
||||
/**
|
||||
* @brief Get all HTTP response headers
|
||||
*
|
||||
* @return headers as a map
|
||||
*/
|
||||
const std::multimap<std::string, std::string> get_headers() const;
|
||||
|
||||
/**
|
||||
* @brief Get the response content
|
||||
*
|
||||
* @return response content
|
||||
*/
|
||||
const std::string get_content() const;
|
||||
|
||||
/**
|
||||
* @brief Get the response HTTP status, e.g.
|
||||
* 200 for OK, 404 for not found, 429 for rate limited.
|
||||
* A value of 0 indicates the request was not completed.
|
||||
*
|
||||
* @return uint16_t HTTP status
|
||||
*/
|
||||
uint16_t get_status() const;
|
||||
|
||||
/**
|
||||
* @brief Break down a scheme, hostname and port into
|
||||
* a http_connect_info.
|
||||
*
|
||||
* All but the hostname portion are optional. The path component
|
||||
* should not be passed to this function.
|
||||
*
|
||||
* @param url URL to break down
|
||||
* @return Split URL
|
||||
*/
|
||||
static http_connect_info get_host_info(std::string url);
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,353 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/managed.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <unordered_map>
|
||||
#include <dpp/json_interface.h>
|
||||
#include <dpp/user.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Where an app can be installed, also called its supported installation contexts.
|
||||
*/
|
||||
enum application_integration_types : uint8_t {
|
||||
/**
|
||||
* @brief Installable to servers
|
||||
*/
|
||||
ait_guild_install = 0,
|
||||
/**
|
||||
* @brief Installable to users
|
||||
*/
|
||||
ait_user_install = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Integration types
|
||||
*/
|
||||
enum integration_type : uint8_t {
|
||||
/**
|
||||
* @brief Twitch integration
|
||||
*/
|
||||
i_twitch,
|
||||
|
||||
/**
|
||||
* @brief YouTube integration
|
||||
*/
|
||||
i_youtube,
|
||||
|
||||
/**
|
||||
* @brief Discord integration
|
||||
*/
|
||||
i_discord,
|
||||
|
||||
/**
|
||||
* @brief Subscription
|
||||
*/
|
||||
i_guild_subscription,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Integration flags
|
||||
*/
|
||||
enum integration_flags : uint8_t {
|
||||
/**
|
||||
* @brief Is this integration enabled?
|
||||
*/
|
||||
if_enabled = 0b00000001,
|
||||
|
||||
/**
|
||||
* @brief Is this integration syncing?
|
||||
* @warning This is not provided for discord bot integrations.
|
||||
*/
|
||||
if_syncing = 0b00000010,
|
||||
|
||||
/**
|
||||
* @brief Whether emoticons should be synced for this integration (twitch only currently).
|
||||
* @warning This is not provided for discord bot integrations.
|
||||
*/
|
||||
if_emoticons = 0b00000100,
|
||||
|
||||
/**
|
||||
* @brief Has this integration been revoked?
|
||||
* @warning This is not provided for discord bot integrations.
|
||||
*/
|
||||
if_revoked = 0b00001000,
|
||||
|
||||
/**
|
||||
* @brief Kick user when their subscription expires, otherwise only remove the role that is specified by `role_id`.
|
||||
* @warning This is not provided for discord bot integrations.
|
||||
*/
|
||||
if_expire_kick = 0b00010000,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An application that has been integrated
|
||||
*/
|
||||
struct DPP_EXPORT integration_app {
|
||||
/**
|
||||
* @brief The id of the app.
|
||||
*/
|
||||
snowflake id;
|
||||
|
||||
/**
|
||||
* @brief The name of the app.
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* @brief The icon hash of the app.
|
||||
*/
|
||||
utility::iconhash icon;
|
||||
|
||||
/**
|
||||
* @brief The description of the app
|
||||
*/
|
||||
std::string description;
|
||||
|
||||
/**
|
||||
* @brief The bot associated with this application.
|
||||
*/
|
||||
class user* bot;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The account information for an integration.
|
||||
*/
|
||||
struct DPP_EXPORT integration_account {
|
||||
/**
|
||||
* @brief ID of the account
|
||||
*/
|
||||
snowflake id;
|
||||
|
||||
/**
|
||||
* @brief Name of the account.
|
||||
*/
|
||||
std::string name;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents an integration on a guild, e.g. a connection to twitch.
|
||||
*/
|
||||
class DPP_EXPORT integration : public managed, public json_interface<integration> {
|
||||
protected:
|
||||
friend struct json_interface<integration>;
|
||||
|
||||
/** Read class values from json object
|
||||
* @param j A json object to read from
|
||||
* @return A reference to self
|
||||
*/
|
||||
integration& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/** Build a json from this object.
|
||||
* @param with_id Add ID to output
|
||||
* @return JSON of the object
|
||||
*/
|
||||
virtual json to_json_impl(bool with_id = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Integration name.
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* @brief Integration type (twitch, youtube, discord, or guild_subscription).
|
||||
*/
|
||||
integration_type type;
|
||||
|
||||
/**
|
||||
* @brief Integration flags from dpp::integration_flags
|
||||
*/
|
||||
uint8_t flags;
|
||||
|
||||
/**
|
||||
* @brief ID that this integration uses for "subscribers".
|
||||
*
|
||||
* @warning This is not provided for discord bot integrations.
|
||||
*/
|
||||
snowflake role_id;
|
||||
|
||||
/**
|
||||
* @brief The grace period (in days) before expiring subscribers.
|
||||
*
|
||||
* @warning This is not provided for discord bot integrations.
|
||||
*/
|
||||
uint32_t expire_grace_period;
|
||||
|
||||
/**
|
||||
* @brief User for this integration
|
||||
*/
|
||||
user user_obj;
|
||||
|
||||
/**
|
||||
* @brief Integration account information
|
||||
*/
|
||||
integration_account account;
|
||||
|
||||
/**
|
||||
* @brief When this integration was last synced.
|
||||
*
|
||||
* @warning This is not provided for discord bot integrations.
|
||||
*/
|
||||
time_t synced_at;
|
||||
|
||||
/**
|
||||
* @brief How many subscribers this integration has.
|
||||
*
|
||||
* @warning This is not provided for discord bot integrations.
|
||||
*/
|
||||
uint32_t subscriber_count;
|
||||
|
||||
/**
|
||||
* @brief The bot/OAuth2 application for discord integrations.
|
||||
*/
|
||||
integration_app app;
|
||||
|
||||
/**
|
||||
* @brief The scopes the application has been authorized for.
|
||||
*/
|
||||
std::vector<std::string> scopes;
|
||||
|
||||
/** Default constructor */
|
||||
integration();
|
||||
|
||||
/** Default destructor */
|
||||
~integration() = default;
|
||||
|
||||
/**
|
||||
* Are emoticons enabled for this integration?
|
||||
* @warning This is not provided for discord bot integrations.
|
||||
*/
|
||||
bool emoticons_enabled() const;
|
||||
|
||||
/**
|
||||
* Is the integration enabled?
|
||||
* @warning This is not provided for discord bot integrations.
|
||||
*/
|
||||
bool is_enabled() const;
|
||||
|
||||
/**
|
||||
* Is the integration syncing?
|
||||
* @warning This is not provided for discord bot integrations.
|
||||
*/
|
||||
bool is_syncing() const;
|
||||
|
||||
/**
|
||||
* Has this integration been revoked?
|
||||
* @warning This is not provided for discord bot integrations.
|
||||
*/
|
||||
bool is_revoked() const;
|
||||
|
||||
/**
|
||||
* Will the user be kicked if their subscription runs out to the integration?
|
||||
* If false, the integration will simply remove the role that is specified by `role_id`.
|
||||
* @warning This is not provided for discord bot integrations.
|
||||
*/
|
||||
bool expiry_kicks_user() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The connection object that the user has attached.
|
||||
*/
|
||||
class DPP_EXPORT connection : public json_interface<connection> {
|
||||
protected:
|
||||
friend struct json_interface<connection>;
|
||||
|
||||
/** Read class values from json object
|
||||
* @param j A json object to read from
|
||||
* @return A reference to self
|
||||
*/
|
||||
connection& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief ID of the connection account.
|
||||
*/
|
||||
std::string id;
|
||||
|
||||
/**
|
||||
* @brief the username of the connection account.
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* @brief the service of the connection (twitch, youtube, discord, or guild_subscription).
|
||||
*/
|
||||
std::string type;
|
||||
|
||||
/**
|
||||
* @brief Optional: whether the connection is revoked.
|
||||
*/
|
||||
bool revoked;
|
||||
|
||||
/**
|
||||
* @brief Optional: an array of partial server integrations.
|
||||
*/
|
||||
std::vector<integration> integrations;
|
||||
|
||||
/**
|
||||
* @brief Whether the connection is verified.
|
||||
*/
|
||||
bool verified;
|
||||
|
||||
/**
|
||||
* @brief Whether friend sync is enabled for this connection.
|
||||
*/
|
||||
bool friend_sync;
|
||||
|
||||
/**
|
||||
* @brief Whether activities related to this connection will be shown in presence updates.
|
||||
*/
|
||||
bool show_activity;
|
||||
|
||||
/**
|
||||
* @brief Whether this connection has a corresponding third party OAuth2 token.
|
||||
*/
|
||||
bool two_way_link;
|
||||
|
||||
/**
|
||||
* @brief Visibility of this connection.
|
||||
*/
|
||||
bool visible;
|
||||
|
||||
/**
|
||||
* @brief Construct a new connection object
|
||||
*/
|
||||
connection();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A group of integrations
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, integration> integration_map;
|
||||
|
||||
/**
|
||||
* @brief A group of connections
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, connection> connection_map;
|
||||
|
||||
}
|
||||
|
||||
155
dpp/intents.h
155
dpp/intents.h
@ -1,155 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief intents are a bitmask of allowed events on your websocket.
|
||||
*
|
||||
* Some of these are known as Privileged intents (GUILD_MEMBERS and GUILD_PRESENCES)
|
||||
* and require verification of a bot over 100 servers by discord via submission of
|
||||
* your real life ID.
|
||||
*/
|
||||
enum intents {
|
||||
/**
|
||||
* @brief Intent for receipt of guild information.
|
||||
*/
|
||||
i_guilds = (1 << 0),
|
||||
|
||||
/**
|
||||
* @brief Intent for receipt of guild members.
|
||||
*/
|
||||
i_guild_members = (1 << 1),
|
||||
|
||||
/**
|
||||
* @brief Intent for receipt of guild bans.
|
||||
*/
|
||||
i_guild_bans = (1 << 2),
|
||||
|
||||
/**
|
||||
* @brief Intent for receipt of guild emojis.
|
||||
*/
|
||||
i_guild_emojis = (1 << 3),
|
||||
|
||||
/**
|
||||
* @brief Intent for receipt of guild integrations.
|
||||
*/
|
||||
i_guild_integrations = (1 << 4),
|
||||
|
||||
/**
|
||||
* @brief Intent for receipt of guild webhooks.
|
||||
*/
|
||||
i_guild_webhooks = (1 << 5),
|
||||
|
||||
/**
|
||||
* @brief Intent for receipt of guild invites.
|
||||
*/
|
||||
i_guild_invites = (1 << 6),
|
||||
|
||||
/**
|
||||
* @brief Intent for receipt of guild voice states.
|
||||
*/
|
||||
i_guild_voice_states = (1 << 7),
|
||||
|
||||
/**
|
||||
* @brief Intent for receipt of guild presences.
|
||||
*/
|
||||
i_guild_presences = (1 << 8),
|
||||
|
||||
/**
|
||||
* @brief Intent for receipt of guild messages.
|
||||
*/
|
||||
i_guild_messages = (1 << 9),
|
||||
|
||||
/**
|
||||
* @brief Intent for receipt of guild message reactions.
|
||||
*/
|
||||
i_guild_message_reactions = (1 << 10),
|
||||
|
||||
/**
|
||||
* @brief Intent for receipt of guild message typing notifications.
|
||||
*/
|
||||
i_guild_message_typing = (1 << 11),
|
||||
|
||||
/**
|
||||
* @brief Intent for receipt of direct messages (DMs).
|
||||
*/
|
||||
i_direct_messages = (1 << 12),
|
||||
|
||||
/**
|
||||
* @brief Intent for receipt of direct message reactions.
|
||||
*/
|
||||
i_direct_message_reactions = (1 << 13),
|
||||
|
||||
/**
|
||||
* @brief Intent for receipt of direct message typing notifications.
|
||||
*/
|
||||
i_direct_message_typing = (1 << 14),
|
||||
|
||||
/**
|
||||
* @brief Intent for receipt of message content.
|
||||
*/
|
||||
i_message_content = (1 << 15),
|
||||
|
||||
/**
|
||||
* @brief Scheduled events.
|
||||
*/
|
||||
i_guild_scheduled_events = (1 << 16),
|
||||
|
||||
/**
|
||||
* @brief Auto moderation configuration.
|
||||
*/
|
||||
i_auto_moderation_configuration = (1 << 20),
|
||||
|
||||
/**
|
||||
* @brief Auto moderation configuration.
|
||||
*/
|
||||
i_auto_moderation_execution = (1 << 21),
|
||||
|
||||
/**
|
||||
* @brief Default D++ intents (all non-privileged intents).
|
||||
*/
|
||||
i_default_intents = dpp::i_guilds | dpp::i_guild_bans | dpp::i_guild_emojis | dpp::i_guild_integrations |
|
||||
dpp::i_guild_webhooks | dpp::i_guild_invites | dpp::i_guild_voice_states |
|
||||
dpp::i_guild_messages | dpp::i_guild_message_reactions | dpp::i_guild_message_typing |
|
||||
dpp::i_direct_messages | dpp::i_direct_message_typing | dpp::i_direct_message_reactions |
|
||||
dpp::i_guild_scheduled_events | dpp::i_auto_moderation_configuration |
|
||||
dpp::i_auto_moderation_execution,
|
||||
|
||||
/**
|
||||
* @brief Privileged intents requiring ID.
|
||||
*/
|
||||
i_privileged_intents = dpp::i_guild_members | dpp::i_guild_presences | dpp::i_message_content,
|
||||
|
||||
/**
|
||||
* @brief Every single intent (dpp::i_default_intents and dpp::i_privileged_intents).
|
||||
*/
|
||||
i_all_intents = dpp::i_default_intents | dpp::i_privileged_intents,
|
||||
|
||||
/**
|
||||
* @brief Unverified bots default intents.
|
||||
*/
|
||||
i_unverified_default_intents = dpp::i_default_intents | dpp::i_message_content
|
||||
};
|
||||
|
||||
}
|
||||
245
dpp/invite.h
245
dpp/invite.h
@ -1,245 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/stage_instance.h>
|
||||
#include <unordered_map>
|
||||
#include <dpp/json_interface.h>
|
||||
#include <dpp/channel.h>
|
||||
#include <dpp/user.h>
|
||||
#include <dpp/guild.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Invite target types for dpp::invite
|
||||
*/
|
||||
enum invite_target_t : uint8_t {
|
||||
/**
|
||||
* @brief Undefined invite target type.
|
||||
*/
|
||||
itt_none = 0,
|
||||
|
||||
/**
|
||||
* @brief Stream target type.
|
||||
*/
|
||||
itt_stream = 1,
|
||||
|
||||
/**
|
||||
* @brief Embedded Application target type.
|
||||
*/
|
||||
itt_embedded_application = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents an invite to a discord guild or channel
|
||||
*/
|
||||
class DPP_EXPORT invite : public json_interface<invite> {
|
||||
protected:
|
||||
friend struct json_interface<invite>;
|
||||
|
||||
/** Read class values from json object
|
||||
* @param j A json object to read from
|
||||
* @return A reference to self
|
||||
*/
|
||||
invite& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/** Build JSON from this object.
|
||||
* @param with_id Include ID in JSON
|
||||
* @return The JSON of the invite
|
||||
*/
|
||||
virtual json to_json_impl(bool with_id = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Invite code.
|
||||
*/
|
||||
std::string code;
|
||||
|
||||
/**
|
||||
* @brief Readonly expiration timestamp of this invite or 0 if the invite doesn't expire.
|
||||
* @note Only returned from cluster::invite_get
|
||||
*/
|
||||
time_t expires_at;
|
||||
|
||||
/**
|
||||
* @brief Guild ID this invite is for.
|
||||
*/
|
||||
snowflake guild_id;
|
||||
|
||||
/**
|
||||
* @brief The partial guild this invite is for.
|
||||
* @note Only filled in retrieved invites.
|
||||
*/
|
||||
guild destination_guild;
|
||||
|
||||
/**
|
||||
* @brief Channel ID this invite is for.
|
||||
*/
|
||||
snowflake channel_id;
|
||||
|
||||
/**
|
||||
* @brief The partial channel this invite is for.
|
||||
* @note Only filled in retrieved invites.
|
||||
*/
|
||||
channel destination_channel;
|
||||
|
||||
/**
|
||||
* @brief User ID who created this invite.
|
||||
* @deprecated Use the `inviter` field instead
|
||||
*/
|
||||
snowflake inviter_id;
|
||||
|
||||
/**
|
||||
* @brief User who created this invite.
|
||||
*/
|
||||
user inviter;
|
||||
|
||||
/**
|
||||
* @brief The user ID whose stream to display for this voice channel stream invite.
|
||||
*/
|
||||
snowflake target_user_id;
|
||||
|
||||
/**
|
||||
* @brief Target type for this voice channel invite.
|
||||
*/
|
||||
invite_target_t target_type;
|
||||
|
||||
/**
|
||||
* @brief Approximate number of online users.
|
||||
* @note Only returned from cluster::invite_get
|
||||
*/
|
||||
uint32_t approximate_presence_count;
|
||||
|
||||
/**
|
||||
* @brief Approximate number of total users online and offline.
|
||||
* @note Only returned from cluster::invite_get.
|
||||
*/
|
||||
uint32_t approximate_member_count;
|
||||
|
||||
/**
|
||||
* @brief Duration (in seconds) after which the invite expires, or 0 for no expiration. Defaults to 86400 (1 day).
|
||||
*
|
||||
* @note Must be between 0 and 604800 (7 days).
|
||||
*/
|
||||
uint32_t max_age;
|
||||
|
||||
/**
|
||||
* @brief Maximum number of uses, or 0 for unlimited. Defaults to 0.
|
||||
*
|
||||
* @note Must be between 0 and 100.
|
||||
*/
|
||||
uint8_t max_uses;
|
||||
|
||||
/**
|
||||
* @brief Whether this invite only grants temporary membership.
|
||||
*/
|
||||
bool temporary;
|
||||
|
||||
/**
|
||||
* @brief True if this invite should not replace or "attach to" similar invites.
|
||||
*/
|
||||
bool unique;
|
||||
|
||||
/**
|
||||
* @brief How many times this invite has been used.
|
||||
*/
|
||||
uint32_t uses;
|
||||
|
||||
/**
|
||||
* @note The stage instance data if there is a public stage instance in the stage channel this invite is for.
|
||||
* @deprecated Deprecated
|
||||
*/
|
||||
stage_instance stage;
|
||||
|
||||
/**
|
||||
* @brief Timestamp at which the invite was created.
|
||||
*/
|
||||
time_t created_at;
|
||||
|
||||
/**
|
||||
* @brief Constructor.
|
||||
*/
|
||||
invite();
|
||||
|
||||
/**
|
||||
* @brief Destructor.
|
||||
*/
|
||||
virtual ~invite() = default;
|
||||
|
||||
/**
|
||||
* @brief Set the max age after which the invite expires
|
||||
*
|
||||
* @param max_age_ The duration in seconds, or 0 for no expiration. Must be between 0 and 604800 (7 days)
|
||||
* @return invite& reference to self for chaining of calls
|
||||
*/
|
||||
invite& set_max_age(const uint32_t max_age_);
|
||||
|
||||
/**
|
||||
* @brief Set the maximum number of uses for this invite
|
||||
*
|
||||
* @param max_uses_ Maximum number of uses, or 0 for unlimited. Must be between 0 and 100
|
||||
* @return invite& reference to self for chaining of calls
|
||||
*/
|
||||
invite& set_max_uses(const uint8_t max_uses_);
|
||||
|
||||
/**
|
||||
* @brief Set the target user id
|
||||
*
|
||||
* @param user_id The user ID whose stream to display for this voice channel stream invite
|
||||
* @return invite& reference to self for chaining of calls
|
||||
*/
|
||||
invite& set_target_user_id(const snowflake user_id);
|
||||
|
||||
/**
|
||||
* @brief Set the target type for this voice channel invite
|
||||
*
|
||||
* @param type invite_target_t Target type
|
||||
* @return invite& reference to self for chaining of calls
|
||||
*/
|
||||
invite& set_target_type(const invite_target_t type);
|
||||
|
||||
/**
|
||||
* @brief Set temporary property of this invite object
|
||||
*
|
||||
* @param is_temporary Whether this invite only grants temporary membership
|
||||
* @return invite& reference to self for chaining of calls
|
||||
*/
|
||||
invite& set_temporary(const bool is_temporary);
|
||||
|
||||
/**
|
||||
* @brief Set unique property of this invite object
|
||||
*
|
||||
* @param is_unique True if this invite should not replace or "attach to" similar invites
|
||||
* @return invite& reference to self for chaining of calls
|
||||
*/
|
||||
invite& set_unique(const bool is_unique);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A container of invites
|
||||
*/
|
||||
typedef std::unordered_map<std::string, invite> invite_map;
|
||||
|
||||
}
|
||||
112
dpp/isa/avx.h
112
dpp/isa/avx.h
@ -1,112 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#if defined _MSC_VER || defined __GNUC__ || defined __clang__
|
||||
|
||||
#include <immintrin.h>
|
||||
#include <numeric>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
using avx_float = __m128;
|
||||
|
||||
/**
|
||||
* @brief A class for audio mixing operations using AVX instructions.
|
||||
*/
|
||||
class audio_mixer {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief The number of 32-bit values per CPU register.
|
||||
*/
|
||||
inline static constexpr int32_t byte_blocks_per_register{ 4 };
|
||||
|
||||
/**
|
||||
* @brief Collect a single register worth of data from data_in, apply gain and increment, and store the result in data_out.
|
||||
* This version uses AVX instructions.
|
||||
*
|
||||
* @param data_in Pointer to the input array of int32_t values.
|
||||
* @param data_out Pointer to the output array of int16_t values.
|
||||
* @param current_gain The gain to be applied to the elements.
|
||||
* @param increment The increment value to be added to each element.
|
||||
*/
|
||||
inline void collect_single_register(int32_t* data_in, int16_t* data_out, float current_gain, float increment) {
|
||||
avx_float current_samples_new{ _mm_mul_ps(gather_values(data_in),
|
||||
_mm_add_ps(_mm_set1_ps(current_gain), _mm_mul_ps(_mm_set1_ps(increment), _mm_set_ps(0.0f, 1.0f, 2.0f, 3.0f)))) };
|
||||
|
||||
current_samples_new = _mm_blendv_ps(_mm_max_ps(current_samples_new, _mm_set1_ps(static_cast<float>(std::numeric_limits<int16_t>::min()))),
|
||||
_mm_min_ps(current_samples_new, _mm_set1_ps(static_cast<float>(std::numeric_limits<int16_t>::max()))),
|
||||
_mm_cmp_ps(current_samples_new, _mm_set1_ps(0.0f), _CMP_GE_OQ));
|
||||
|
||||
store_values(current_samples_new, data_out);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Combine a register worth of elements from decoded_data and store the result in up_sampled_vector.
|
||||
* This version uses AVX instructions.
|
||||
*
|
||||
* @param up_sampled_vector Pointer to the array of int32_t values.
|
||||
* @param decoded_data Pointer to the array of int16_t values.
|
||||
*/
|
||||
inline void combine_samples(int32_t* up_sampled_vector, const int16_t* decoded_data) {
|
||||
auto newValues{ _mm_add_ps(gather_values(up_sampled_vector), gather_values(decoded_data)) };
|
||||
store_values(newValues, up_sampled_vector);
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Array for storing the values to be loaded/stored.
|
||||
*/
|
||||
alignas(16) float values[byte_blocks_per_register]{};
|
||||
|
||||
/**
|
||||
* @brief Stores values from a 128-bit AVX vector to a storage location.
|
||||
* @tparam value_type The target value type for storage.
|
||||
* @param values_to_store The 128-bit AVX vector containing values to store.
|
||||
* @param storage_location Pointer to the storage location.
|
||||
*/
|
||||
template<typename value_type> inline void store_values(const avx_float& values_to_store, value_type* storage_location) {
|
||||
_mm_store_ps(values, values_to_store);
|
||||
for (int64_t x = 0; x < byte_blocks_per_register; ++x) {
|
||||
storage_location[x] = static_cast<value_type>(values[x]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specialization for gathering non-float values into an AVX register.
|
||||
* @tparam value_type The type of values being gathered.
|
||||
* @tparam Indices Parameter pack of indices for gathering values.
|
||||
* @return An AVX register containing gathered values.
|
||||
*/
|
||||
template<typename value_type> inline avx_float gather_values(value_type* values_new) {
|
||||
for (uint64_t x = 0; x < byte_blocks_per_register; ++x) {
|
||||
values[x] = static_cast<float>(values_new[x]);
|
||||
}
|
||||
return _mm_load_ps(values);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
115
dpp/isa/avx2.h
115
dpp/isa/avx2.h
@ -1,115 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#if defined _MSC_VER || defined __GNUC__ || defined __clang__
|
||||
|
||||
#include <immintrin.h>
|
||||
#include <numeric>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
using avx_2_float = __m256;
|
||||
|
||||
/**
|
||||
* @brief A class for audio mixing operations using AVX2 instructions.
|
||||
*/
|
||||
class audio_mixer {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief The number of 32-bit values per CPU register.
|
||||
*/
|
||||
inline static constexpr int32_t byte_blocks_per_register{ 8 };
|
||||
|
||||
/**
|
||||
* @brief Collect a single register worth of data from data_in, apply gain and increment, and store the result in data_out.
|
||||
* This version uses AVX2 instructions.
|
||||
*
|
||||
* @param data_in Pointer to the input array of int32_t values.
|
||||
* @param data_out Pointer to the output array of int16_t values.
|
||||
* @param current_gain The gain to be applied to the elements.
|
||||
* @param increment The increment value to be added to each element.
|
||||
*/
|
||||
inline void collect_single_register(int32_t* data_in, int16_t* data_out, float current_gain, float increment) {
|
||||
avx_2_float current_samples_new{ _mm256_mul_ps(gather_values(data_in),
|
||||
_mm256_add_ps(_mm256_set1_ps(current_gain),
|
||||
_mm256_mul_ps(_mm256_set1_ps(increment), _mm256_set_ps(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f)))) };
|
||||
|
||||
current_samples_new =
|
||||
_mm256_blendv_ps(_mm256_max_ps(current_samples_new, _mm256_set1_ps(static_cast<float>(std::numeric_limits<int16_t>::min()))),
|
||||
_mm256_min_ps(current_samples_new, _mm256_set1_ps(static_cast<float>(std::numeric_limits<int16_t>::max()))),
|
||||
_mm256_cmp_ps(current_samples_new, _mm256_set1_ps(0.0f), _CMP_GE_OQ));
|
||||
|
||||
store_values(current_samples_new, data_out);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Combine a register worth of elements from decoded_data and store the result in up_sampled_vector.
|
||||
* This version uses AVX2 instructions.
|
||||
*
|
||||
* @param up_sampled_vector Pointer to the array of int32_t values.
|
||||
* @param decoded_data Pointer to the array of int16_t values.
|
||||
* @param x Index to select a specific set of elements to combine.
|
||||
*/
|
||||
inline void combine_samples(int32_t* up_sampled_vector, const int16_t* decoded_data) {
|
||||
auto newValues{ _mm256_add_ps(gather_values(up_sampled_vector), gather_values(decoded_data)) };
|
||||
store_values(newValues, up_sampled_vector);
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Array for storing the values to be loaded/stored.
|
||||
*/
|
||||
alignas(32) float values[byte_blocks_per_register]{};
|
||||
|
||||
/**
|
||||
* @brief Stores values from a 256-bit AVX2 vector to a storage location.
|
||||
* @tparam value_type The target value type for storage.
|
||||
* @param values_to_store The 256-bit AVX2 vector containing values to store.
|
||||
* @param storage_location Pointer to the storage location.
|
||||
*/
|
||||
template<typename value_type> inline void store_values(const avx_2_float& values_to_store, value_type* storage_location) {
|
||||
_mm256_store_ps(values, values_to_store);
|
||||
for (int64_t x = 0; x < byte_blocks_per_register; ++x) {
|
||||
storage_location[x] = static_cast<value_type>(values[x]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specialization for gathering non-float values into an AVX2 register.
|
||||
* @tparam value_type The type of values being gathered.
|
||||
* @tparam Indices Parameter pack of indices for gathering values.
|
||||
* @return An AVX2 register containing gathered values.
|
||||
*/
|
||||
template<typename value_type> inline avx_2_float gather_values(value_type* values_new) {
|
||||
for (uint64_t x = 0; x < byte_blocks_per_register; ++x) {
|
||||
values[x] = static_cast<float>(values_new[x]);
|
||||
}
|
||||
return _mm256_load_ps(values);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
118
dpp/isa/avx512.h
118
dpp/isa/avx512.h
@ -1,118 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#if defined _MSC_VER || defined __GNUC__ || defined __clang__
|
||||
|
||||
#include <immintrin.h>
|
||||
#include <numeric>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
using avx_512_float = __m512;
|
||||
|
||||
/**
|
||||
* @brief A class for audio mixing operations using AVX512 instructions.
|
||||
*/
|
||||
class audio_mixer {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief The number of 32-bit values per CPU register.
|
||||
*/
|
||||
inline static constexpr int32_t byte_blocks_per_register{ 16 };
|
||||
|
||||
/**
|
||||
* @brief Collect a single register worth of data from data_in, apply gain and increment, and store the result in data_out.
|
||||
* This version uses AVX512 instructions.
|
||||
*
|
||||
* @param data_in Pointer to the input array of int32_t values.
|
||||
* @param data_out Pointer to the output array of int16_t values.
|
||||
* @param current_gain The gain to be applied to the elements.
|
||||
* @param increment The increment value to be added to each element.
|
||||
*/
|
||||
inline void collect_single_register(int32_t* data_in, int16_t* data_out, float current_gain, float increment) {
|
||||
avx_512_float current_samples_new{ _mm512_mul_ps(gather_values(data_in),
|
||||
_mm512_add_ps(_mm512_set1_ps(current_gain),
|
||||
_mm512_mul_ps(_mm512_set1_ps(increment),
|
||||
_mm512_set_ps(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f)))) };
|
||||
|
||||
__m512 lower_limit = _mm512_set1_ps(static_cast<float>(std::numeric_limits<int16_t>::min()));
|
||||
__m512 upper_limit = _mm512_set1_ps(static_cast<float>(std::numeric_limits<int16_t>::max()));
|
||||
|
||||
__mmask16 mask_ge = _mm512_cmp_ps_mask(current_samples_new, _mm512_set1_ps(0.0f), _CMP_GE_OQ);
|
||||
|
||||
current_samples_new = _mm512_mask_max_ps(current_samples_new, mask_ge, current_samples_new, lower_limit);
|
||||
current_samples_new = _mm512_mask_min_ps(current_samples_new, ~mask_ge, current_samples_new, upper_limit);
|
||||
|
||||
store_values(current_samples_new, data_out);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Combine a register worth of elements from decoded_data and store the result in up_sampled_vector.
|
||||
* This version uses AVX512 instructions.
|
||||
*
|
||||
* @param up_sampled_vector Pointer to the array of int32_t values.
|
||||
* @param decoded_data Pointer to the array of int16_t values.
|
||||
*/
|
||||
inline void combine_samples(int32_t* up_sampled_vector, const int16_t* decoded_data) {
|
||||
auto newValues{ _mm512_add_ps(gather_values(up_sampled_vector), gather_values(decoded_data)) };
|
||||
store_values(newValues, up_sampled_vector);
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Array for storing the values to be loaded/stored.
|
||||
*/
|
||||
alignas(64) float values[byte_blocks_per_register]{};
|
||||
|
||||
/**
|
||||
* @brief Stores values from a 512-bit AVX512 vector to a storage location.
|
||||
* @tparam value_type The target value type for storage.
|
||||
* @param values_to_store The 512-bit AVX512 vector containing values to store.
|
||||
* @param storage_location Pointer to the storage location.
|
||||
*/
|
||||
template<typename value_type> inline static void store_values(const avx_512_float& values_to_store, value_type* storage_location) {
|
||||
_mm256_store_ps(values, values_to_store);
|
||||
for (int64_t x = 0; x < byte_blocks_per_register; ++x) {
|
||||
storage_location[x] = static_cast<value_type>(values[x]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specialization for gathering non-float values into an AVX512 register.
|
||||
* @tparam value_type The type of values being gathered.
|
||||
* @tparam Indices Parameter pack of indices for gathering values.
|
||||
* @return An AVX512 register containing gathered values.
|
||||
*/
|
||||
template<typename value_type> inline avx_512_float gather_values(value_type* values_new) {
|
||||
for (uint64_t x = 0; x < byte_blocks_per_register; ++x) {
|
||||
values[x] = static_cast<float>(values_new[x]);
|
||||
}
|
||||
return _mm512_load_ps(values);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,79 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <dpp/export.h>
|
||||
#include <numeric>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief A class for audio mixing operations using x64 instructions.
|
||||
*/
|
||||
class audio_mixer {
|
||||
public:
|
||||
/*
|
||||
* @brief The number of 32-bit values per CPU register.
|
||||
*/
|
||||
inline static constexpr int32_t byte_blocks_per_register{ 2 };
|
||||
|
||||
/**
|
||||
* @brief Collect a single register worth of data from data_in, apply gain and increment, and store the result in data_out.
|
||||
* This version uses x64 instructions.
|
||||
*
|
||||
* @param data_in Pointer to the input array of int32_t values.
|
||||
* @param data_out Pointer to the output array of int16_t values.
|
||||
* @param current_gain The gain to be applied to the elements.
|
||||
* @param increment The increment value to be added to each element.
|
||||
*/
|
||||
inline static void collect_single_register(int32_t* data_in, int16_t* data_out, float current_gain, float increment) {
|
||||
for (uint64_t x = 0; x < byte_blocks_per_register; ++x) {
|
||||
auto increment_new = increment * x;
|
||||
auto current_gain_new = current_gain + increment_new;
|
||||
auto current_sample_new = data_in[x] * current_gain_new;
|
||||
if (current_sample_new >= std::numeric_limits<int16_t>::max()) {
|
||||
current_sample_new = std::numeric_limits<int16_t>::max();
|
||||
}
|
||||
else if (current_sample_new <= std::numeric_limits<int16_t>::min()) {
|
||||
current_sample_new = std::numeric_limits<int16_t>::min();
|
||||
}
|
||||
data_out[x] = static_cast<int16_t>(current_sample_new);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Combine a register worth of elements from decoded_data and store the result in up_sampled_vector.
|
||||
* This version uses x64 instructions.
|
||||
*
|
||||
* @param up_sampled_vector Pointer to the array of int32_t values.
|
||||
* @param decoded_data Pointer to the array of int16_t values.
|
||||
*/
|
||||
inline static void combine_samples(int32_t* up_sampled_vector, const int16_t* decoded_data) {
|
||||
for (uint64_t x = 0; x < byte_blocks_per_register; ++x) {
|
||||
up_sampled_vector[x] += static_cast<int32_t>(decoded_data[x]);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
120
dpp/isa/neon.h
120
dpp/isa/neon.h
@ -1,120 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#if defined _MSC_VER || defined __GNUC__ || defined __clang__
|
||||
|
||||
#include <arm_neon.h>
|
||||
#include <numeric>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
using neon_float = float32x4_t;
|
||||
|
||||
/**
|
||||
* @brief A class for audio mixing operations using ARM NEON instructions.
|
||||
*/
|
||||
class audio_mixer {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief The number of 32-bit values per CPU register.
|
||||
*/
|
||||
inline static constexpr int32_t byte_blocks_per_register{ 4 };
|
||||
|
||||
/**
|
||||
* @brief Collect a single register worth of data from data_in, apply gain and increment, and store the result in data_out.
|
||||
* This version uses ARM NEON instructions.
|
||||
*
|
||||
* @param data_in Pointer to the input array of int32_t values.
|
||||
* @param data_out Pointer to the output array of int16_t values.
|
||||
* @param current_gain The gain to be applied to the elements.
|
||||
* @param increment The increment value to be added to each element.
|
||||
*/
|
||||
inline void collect_single_register(int32_t* data_in, int16_t* data_out, float current_gain, float increment) {
|
||||
neon_float gathered_values = gather_values(data_in);
|
||||
neon_float gain_vector = vdupq_n_f32(current_gain);
|
||||
static constexpr float data[4] = { 0.0f, 1.0f, 2.0f, 3.0f };
|
||||
neon_float floats = vld1q_f32(data);
|
||||
neon_float increment_vector = vmulq_f32(vdupq_n_f32(increment), floats);
|
||||
neon_float current_samples_new = vmulq_f32(gathered_values, vaddq_f32(gain_vector, increment_vector));
|
||||
|
||||
// Clamping the values between int16_t min and max
|
||||
neon_float min_val = vdupq_n_f32(static_cast<float>(std::numeric_limits<int16_t>::min()));
|
||||
neon_float max_val = vdupq_n_f32(static_cast<float>(std::numeric_limits<int16_t>::max()));
|
||||
|
||||
current_samples_new = vmaxq_f32(current_samples_new, min_val);
|
||||
current_samples_new = vminq_f32(current_samples_new, max_val);
|
||||
|
||||
store_values(current_samples_new, data_out);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Combine a register worth of elements from decoded_data and store the result in up_sampled_vector.
|
||||
* This version uses ARM NEON instructions.
|
||||
*
|
||||
* @param up_sampled_vector Pointer to the array of int32_t values.
|
||||
* @param decoded_data Pointer to the array of int16_t values.
|
||||
*/
|
||||
inline void combine_samples(int32_t* up_sampled_vector, const int16_t* decoded_data) {
|
||||
neon_float up_sampled = gather_values(up_sampled_vector);
|
||||
neon_float decoded = gather_values(decoded_data);
|
||||
neon_float newValues = vaddq_f32(up_sampled, decoded);
|
||||
store_values(newValues, up_sampled_vector);
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Array for storing the values to be loaded/stored.
|
||||
*/
|
||||
alignas(16) float values[byte_blocks_per_register]{};
|
||||
|
||||
/**
|
||||
* @brief Stores values from a 128-bit NEON vector to a storage location.
|
||||
* @tparam value_type The target value type for storage.
|
||||
* @param values_to_store The 128-bit NEON vector containing values to store.
|
||||
* @param storage_location Pointer to the storage location.
|
||||
*/
|
||||
template<typename value_type> inline void store_values(const neon_float& values_to_store, value_type* storage_location) {
|
||||
vst1q_f32(values, values_to_store);
|
||||
for (int64_t x = 0; x < byte_blocks_per_register; ++x) {
|
||||
storage_location[x] = static_cast<value_type>(values[x]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specialization for gathering non-float values into a NEON register.
|
||||
* @tparam value_type The type of values being gathered.
|
||||
* @return A NEON register containing gathered values.
|
||||
*/
|
||||
template<typename value_type> inline neon_float gather_values(value_type* values_new) {
|
||||
for (uint64_t x = 0; x < byte_blocks_per_register; ++x) {
|
||||
values[x] = static_cast<float>(values_new[x]);
|
||||
}
|
||||
return vld1q_f32(values);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dpp
|
||||
|
||||
#endif
|
||||
@ -1,33 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#if AVX_TYPE == 1024
|
||||
#include "isa/neon.h"
|
||||
#elif AVX_TYPE == 512
|
||||
#include "isa/avx512.h"
|
||||
#elif AVX_TYPE == 2
|
||||
#include "isa/avx2.h"
|
||||
#elif AVX_TYPE == 1
|
||||
#include "isa/avx.h"
|
||||
#else
|
||||
#include "isa/fallback.h"
|
||||
#endif
|
||||
32
dpp/json.h
32
dpp/json.h
@ -1,32 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#ifdef DPP_USE_EXTERNAL_JSON
|
||||
#include <nlohmann/json.hpp>
|
||||
#else
|
||||
#include <dpp/nlohmann/json.hpp>
|
||||
#endif
|
||||
|
||||
namespace dpp {
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#ifdef DPP_USE_EXTERNAL_JSON
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
#else
|
||||
#include <dpp/nlohmann/json_fwd.hpp>
|
||||
#endif
|
||||
|
||||
namespace dpp {
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2022 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/json.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Represents an interface for an object that can optionally implement functions
|
||||
* for converting to and from nlohmann::json. The methods are only present if the actual object
|
||||
* also has those methods.
|
||||
*
|
||||
* @tparam T Type of class that implements the interface
|
||||
*/
|
||||
template<typename T>
|
||||
struct json_interface {
|
||||
/**
|
||||
* @brief Convert object from nlohmann::json
|
||||
*
|
||||
* @param j nlohmann::json object
|
||||
* @return T& Reference to self for fluent calling
|
||||
*/
|
||||
template <typename U = T, typename = decltype(std::declval<U&>().fill_from_json_impl(std::declval<nlohmann::json*>()))>
|
||||
T& fill_from_json(nlohmann::json* j) {
|
||||
return static_cast<T*>(this)->fill_from_json_impl(j);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert object to nlohmann::json
|
||||
*
|
||||
* @param with_id Whether to include the ID or not
|
||||
* @note Some fields are conditionally filled, do not rely on all fields being present
|
||||
* @return json Json built from the structure
|
||||
*/
|
||||
template <typename U = T, typename = decltype(std::declval<U&>().to_json_impl(bool{}))>
|
||||
auto to_json(bool with_id = false) const {
|
||||
return static_cast<const T*>(this)->to_json_impl(with_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert object to json string
|
||||
*
|
||||
* @param with_id Whether to include the ID or not
|
||||
* @note Some fields are conditionally filled, do not rely on all fields being present
|
||||
* @return std::string Json built from the structure
|
||||
*/
|
||||
template <typename U = T, typename = decltype(std::declval<U&>().to_json_impl(bool{}))>
|
||||
std::string build_json(bool with_id = false) const {
|
||||
return to_json(with_id).dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
116
dpp/managed.h
116
dpp/managed.h
@ -1,116 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <string>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/** @brief The managed class is the base class for various types that can
|
||||
* be stored in a cache that are identified by a dpp::snowflake id.
|
||||
*/
|
||||
class DPP_EXPORT managed {
|
||||
public:
|
||||
/**
|
||||
* @brief Unique ID of object set by Discord.
|
||||
* This value contains a timestamp, worker ID, internal server ID, and an incrementing value.
|
||||
* Only the timestamp is relevant to us as useful metadata.
|
||||
*/
|
||||
snowflake id = {};
|
||||
|
||||
/**
|
||||
* @brief Constructor, initialises id to 0.
|
||||
*/
|
||||
managed() = default;
|
||||
|
||||
/**
|
||||
* @brief Constructor, initialises ID
|
||||
* @param nid ID to set
|
||||
*/
|
||||
managed(const snowflake nid) : id{nid} {}
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @param rhs Object to copy
|
||||
*/
|
||||
managed(const managed &rhs) = default;
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
*
|
||||
* Effectively equivalent to copy constructor
|
||||
* @param rhs Object to move from
|
||||
*/
|
||||
managed(managed &&rhs) = default;
|
||||
|
||||
/**
|
||||
* @brief Destroy the managed object
|
||||
*/
|
||||
virtual ~managed() = default;
|
||||
|
||||
/**
|
||||
* @brief Copy assignment operator
|
||||
* @param rhs Object to copy
|
||||
*/
|
||||
managed &operator=(const managed& rhs) = default;
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator
|
||||
* @param rhs Object to move from
|
||||
*/
|
||||
managed &operator=(managed&& rhs) = default;
|
||||
|
||||
/**
|
||||
* @brief Get the creation time of this object according to Discord.
|
||||
*
|
||||
* @return double creation time inferred from the snowflake ID.
|
||||
* The minimum possible value is the first second of 2015.
|
||||
*/
|
||||
constexpr double get_creation_time() const noexcept {
|
||||
return id.get_creation_time();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Comparison operator for comparing two managed objects by id
|
||||
*
|
||||
* @param other Other object to compare against
|
||||
* @return true objects are the same id
|
||||
* @return false objects are not the same id
|
||||
*/
|
||||
constexpr bool operator==(const managed& other) const noexcept {
|
||||
return id == other.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Comparison operator for comparing two managed objects by id
|
||||
*
|
||||
* @param other Other object to compare against
|
||||
* @return true objects are not the same id
|
||||
* @return false objects are the same id
|
||||
*/
|
||||
constexpr bool operator!=(const managed& other) const noexcept {
|
||||
return id != other.id;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
3016
dpp/message.h
3016
dpp/message.h
File diff suppressed because it is too large
Load Diff
@ -1,89 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Supported image types for profile pictures and CDN endpoints
|
||||
*/
|
||||
enum image_type : uint8_t {
|
||||
/**
|
||||
* @brief image/png
|
||||
*/
|
||||
i_png,
|
||||
|
||||
/**
|
||||
* @brief image/jpeg.
|
||||
*/
|
||||
i_jpg,
|
||||
|
||||
/**
|
||||
* @brief image/gif.
|
||||
*/
|
||||
i_gif,
|
||||
|
||||
/**
|
||||
* @brief Webp.
|
||||
*/
|
||||
i_webp,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Log levels
|
||||
*/
|
||||
enum loglevel {
|
||||
/**
|
||||
* @brief Trace
|
||||
*/
|
||||
ll_trace = 0,
|
||||
|
||||
/**
|
||||
* @brief Debug
|
||||
*/
|
||||
ll_debug,
|
||||
|
||||
/**
|
||||
* @brief Information
|
||||
*/
|
||||
ll_info,
|
||||
|
||||
/**
|
||||
* @brief Warning
|
||||
*/
|
||||
ll_warning,
|
||||
|
||||
/**
|
||||
* @brief Error
|
||||
*/
|
||||
ll_error,
|
||||
|
||||
/**
|
||||
* @brief Critical
|
||||
*/
|
||||
ll_critical
|
||||
};
|
||||
|
||||
}
|
||||
24596
dpp/nlohmann/json.hpp
24596
dpp/nlohmann/json.hpp
File diff suppressed because it is too large
Load Diff
@ -1,175 +0,0 @@
|
||||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++
|
||||
// | | |__ | | | | | | version 3.11.2
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||
|
||||
#include <cstdint> // int64_t, uint64_t
|
||||
#include <map> // map
|
||||
#include <memory> // allocator
|
||||
#include <string> // string
|
||||
#include <vector> // vector
|
||||
|
||||
// #include <nlohmann/detail/abi_macros.hpp>
|
||||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++
|
||||
// | | |__ | | | | | | version 3.11.2
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
|
||||
|
||||
// This file contains all macro definitions affecting or depending on the ABI
|
||||
|
||||
#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
|
||||
#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
|
||||
#if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2
|
||||
#warning "Already included a different version of the library!"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
|
||||
#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
|
||||
#define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum)
|
||||
|
||||
#ifndef JSON_DIAGNOSTICS
|
||||
#define JSON_DIAGNOSTICS 0
|
||||
#endif
|
||||
|
||||
#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
|
||||
#endif
|
||||
|
||||
#if JSON_DIAGNOSTICS
|
||||
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
|
||||
#else
|
||||
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
|
||||
#endif
|
||||
|
||||
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
|
||||
#else
|
||||
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||
#endif
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
|
||||
#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
|
||||
#endif
|
||||
|
||||
// Construct the namespace ABI tags component
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
|
||||
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
|
||||
|
||||
#define NLOHMANN_JSON_ABI_TAGS \
|
||||
NLOHMANN_JSON_ABI_TAGS_CONCAT( \
|
||||
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
|
||||
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
|
||||
|
||||
// Construct the namespace version component
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
|
||||
_v ## major ## _ ## minor ## _ ## patch
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
|
||||
|
||||
#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION
|
||||
#else
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
|
||||
NLOHMANN_JSON_VERSION_MINOR, \
|
||||
NLOHMANN_JSON_VERSION_PATCH)
|
||||
#endif
|
||||
|
||||
// Combine namespace components
|
||||
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
|
||||
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
|
||||
NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE
|
||||
#define NLOHMANN_JSON_NAMESPACE \
|
||||
nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
|
||||
NLOHMANN_JSON_ABI_TAGS, \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION)
|
||||
#endif
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
|
||||
namespace nlohmann \
|
||||
{ \
|
||||
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
|
||||
NLOHMANN_JSON_ABI_TAGS, \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION) \
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE_END
|
||||
#define NLOHMANN_JSON_NAMESPACE_END \
|
||||
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
|
||||
} // namespace nlohmann
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
@brief namespace for Niels Lohmann
|
||||
@see https://github.com/nlohmann
|
||||
@since version 1.0.0
|
||||
*/
|
||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
|
||||
/*!
|
||||
@brief default JSONSerializer template argument
|
||||
|
||||
This serializer ignores the template arguments and uses ADL
|
||||
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
|
||||
for serialization.
|
||||
*/
|
||||
template<typename T = void, typename SFINAE = void>
|
||||
struct adl_serializer;
|
||||
|
||||
/// a class to store JSON values
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/
|
||||
template<template<typename U, typename V, typename... Args> class ObjectType =
|
||||
std::map,
|
||||
template<typename U, typename... Args> class ArrayType = std::vector,
|
||||
class StringType = std::string, class BooleanType = bool,
|
||||
class NumberIntegerType = std::int64_t,
|
||||
class NumberUnsignedType = std::uint64_t,
|
||||
class NumberFloatType = double,
|
||||
template<typename U> class AllocatorType = std::allocator,
|
||||
template<typename T, typename SFINAE = void> class JSONSerializer =
|
||||
adl_serializer,
|
||||
class BinaryType = std::vector<std::uint8_t>>
|
||||
class basic_json;
|
||||
|
||||
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
|
||||
/// @sa https://json.nlohmann.me/api/json_pointer/
|
||||
template<typename RefStringType>
|
||||
class json_pointer;
|
||||
|
||||
/*!
|
||||
@brief default specialization
|
||||
@sa https://json.nlohmann.me/api/json/
|
||||
*/
|
||||
using json = basic_json<>;
|
||||
|
||||
/// @brief a minimal map-like container that preserves insertion order
|
||||
/// @sa https://json.nlohmann.me/api/ordered_map/
|
||||
template<class Key, class T, class IgnoredLess, class Allocator>
|
||||
struct ordered_map;
|
||||
|
||||
/// @brief specialization that maintains the insertion order of object keys
|
||||
/// @sa https://json.nlohmann.me/api/ordered_json/
|
||||
using ordered_json = basic_json<nlohmann::ordered_map>;
|
||||
|
||||
NLOHMANN_JSON_NAMESPACE_END
|
||||
|
||||
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||
46
dpp/once.h
46
dpp/once.h
@ -1,46 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2022 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <utility>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Run some code within an if() statement only once.
|
||||
*
|
||||
* Use this template like this:
|
||||
*
|
||||
* ```
|
||||
* if (dpp::run_once<struct any_unique_name_you_like_here>()) {
|
||||
* // Your code here
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @tparam T any unique 'tag' identifier name
|
||||
* @return auto a true/false return to say if we should execute or not
|
||||
*/
|
||||
template <typename T> auto run_once() {
|
||||
static auto called = false;
|
||||
return !std::exchange(called, true);
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,459 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/json.h>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Represents the various discord permissions
|
||||
*/
|
||||
enum permissions : uint64_t {
|
||||
/**
|
||||
* @brief Allows creation of instant invites.
|
||||
*/
|
||||
p_create_instant_invite = 0x00000000001,
|
||||
|
||||
/**
|
||||
* @brief Allows kicking members.
|
||||
*/
|
||||
p_kick_members = 0x00000000002,
|
||||
|
||||
/**
|
||||
* @brief Allows banning members.
|
||||
*/
|
||||
p_ban_members = 0x00000000004,
|
||||
|
||||
/**
|
||||
* @brief Allows all permissions and bypasses channel permission overwrites.
|
||||
*/
|
||||
p_administrator = 0x00000000008,
|
||||
|
||||
/**
|
||||
* @brief Allows management and editing of channels.
|
||||
*/
|
||||
p_manage_channels = 0x00000000010,
|
||||
|
||||
/**
|
||||
* @brief Allows management and editing of the guild.
|
||||
*/
|
||||
p_manage_guild = 0x00000000020,
|
||||
|
||||
/**
|
||||
* @brief Allows for the addition of reactions to messages.
|
||||
*/
|
||||
p_add_reactions = 0x00000000040,
|
||||
|
||||
/**
|
||||
* @brief Allows for viewing of audit logs.
|
||||
*/
|
||||
p_view_audit_log = 0x00000000080,
|
||||
|
||||
/**
|
||||
* @brief Allows for using priority speaker in a voice channel.
|
||||
*/
|
||||
p_priority_speaker = 0x00000000100,
|
||||
|
||||
/**
|
||||
* @brief Allows the user to go live.
|
||||
*/
|
||||
p_stream = 0x00000000200,
|
||||
|
||||
/**
|
||||
* @brief Allows guild members to view a channel,
|
||||
* which includes reading messages in text channels and joining voice channels.
|
||||
*/
|
||||
p_view_channel = 0x00000000400,
|
||||
|
||||
/**
|
||||
* @brief Allows for sending messages in a channel.
|
||||
*/
|
||||
p_send_messages = 0x00000000800,
|
||||
|
||||
/**
|
||||
* @brief Allows for sending of /tts messages.
|
||||
*/
|
||||
p_send_tts_messages = 0x00000001000,
|
||||
|
||||
/**
|
||||
* @brief Allows for deletion of other users messages.
|
||||
*/
|
||||
p_manage_messages = 0x00000002000,
|
||||
|
||||
/**
|
||||
* @brief Links sent by users with this permission will be auto-embedded.
|
||||
*/
|
||||
p_embed_links = 0x00000004000,
|
||||
|
||||
/**
|
||||
* @brief Allows for uploading images and files.
|
||||
*/
|
||||
p_attach_files = 0x00000008000,
|
||||
|
||||
/**
|
||||
* @brief Allows for reading of message history.
|
||||
*/
|
||||
p_read_message_history = 0x00000010000,
|
||||
|
||||
/**
|
||||
* @brief Allows for using the everyone and the here tag to notify users in a channel.
|
||||
*/
|
||||
p_mention_everyone = 0x00000020000,
|
||||
|
||||
/**
|
||||
* @brief Allows the usage of custom emojis from other servers.
|
||||
*/
|
||||
p_use_external_emojis = 0x00000040000,
|
||||
|
||||
/**
|
||||
* @brief Allows for viewing guild insights.
|
||||
*/
|
||||
p_view_guild_insights = 0x00000080000,
|
||||
|
||||
/**
|
||||
* @brief Allows for joining of a voice channel.
|
||||
*/
|
||||
p_connect = 0x00000100000,
|
||||
|
||||
/**
|
||||
* @brief Allows for speaking in a voice channel.
|
||||
*/
|
||||
p_speak = 0x00000200000,
|
||||
|
||||
/**
|
||||
* @brief Allows for muting members in a voice channel.
|
||||
*/
|
||||
p_mute_members = 0x00000400000,
|
||||
|
||||
/**
|
||||
* @brief Allows for deafening of members in a voice channel.
|
||||
*/
|
||||
p_deafen_members = 0x00000800000,
|
||||
|
||||
/**
|
||||
* @brief Allows for moving of members between voice channels.
|
||||
*/
|
||||
p_move_members = 0x00001000000,
|
||||
|
||||
/**
|
||||
* @brief Allows for using voice-activity-detection in a voice channel.
|
||||
*/
|
||||
p_use_vad = 0x00002000000,
|
||||
|
||||
/**
|
||||
* @brief Allows for modification of own nickname.
|
||||
*/
|
||||
p_change_nickname = 0x00004000000,
|
||||
|
||||
/**
|
||||
* @brief Allows for modification of other users nicknames.
|
||||
*/
|
||||
p_manage_nicknames = 0x00008000000,
|
||||
|
||||
/**
|
||||
* @brief Allows management and editing of roles.
|
||||
*/
|
||||
p_manage_roles = 0x00010000000,
|
||||
|
||||
/**
|
||||
* @brief Allows management and editing of webhooks.
|
||||
*/
|
||||
p_manage_webhooks = 0x00020000000,
|
||||
|
||||
/**
|
||||
* @brief Allows management and editing of emojis and stickers.
|
||||
*/
|
||||
p_manage_emojis_and_stickers = 0x00040000000,
|
||||
|
||||
/**
|
||||
* @brief Allows members to use application commands,
|
||||
* including slash commands and context menus.
|
||||
*/
|
||||
p_use_application_commands = 0x00080000000,
|
||||
|
||||
/**
|
||||
* @brief Allows for requesting to speak in stage channels.
|
||||
*
|
||||
* @warning Discord: This permission is under active development and may be changed or removed.
|
||||
*/
|
||||
p_request_to_speak = 0x00100000000,
|
||||
|
||||
/**
|
||||
* @brief Allows for management (creation, updating, deleting, starting) of scheduled events.
|
||||
*/
|
||||
p_manage_events = 0x00200000000,
|
||||
|
||||
/**
|
||||
* @brief Allows for deleting and archiving threads, and viewing all private threads.
|
||||
*/
|
||||
p_manage_threads = 0x00400000000,
|
||||
|
||||
/**
|
||||
* @brief Allows for creating public and announcement threads.
|
||||
*/
|
||||
p_create_public_threads = 0x00800000000,
|
||||
|
||||
/**
|
||||
* @brief Allows for creating private threads.
|
||||
*/
|
||||
p_create_private_threads = 0x01000000000,
|
||||
|
||||
/**
|
||||
* @brief Allows the usage of custom stickers from other servers.
|
||||
*/
|
||||
p_use_external_stickers = 0x02000000000,
|
||||
|
||||
/**
|
||||
* @brief Allows for sending messages in threads.
|
||||
*/
|
||||
p_send_messages_in_threads = 0x04000000000,
|
||||
|
||||
/**
|
||||
* @brief Allows for using activities (applications with the EMBEDDED flag) in a voice channel.
|
||||
*/
|
||||
p_use_embedded_activities = 0x08000000000,
|
||||
|
||||
/**
|
||||
* @brief Allows for timing out users
|
||||
* to prevent them from sending or reacting to messages in chat and threads,
|
||||
* and from speaking in voice and stage channels.
|
||||
*/
|
||||
p_moderate_members = 0x10000000000,
|
||||
|
||||
/**
|
||||
* @brief Allows for viewing role subscription insights.
|
||||
*/
|
||||
p_view_creator_monetization_analytics = 0x20000000000,
|
||||
|
||||
/**
|
||||
* @brief Allows for using soundboard in a voice channel.
|
||||
*/
|
||||
p_use_soundboard = 0x40000000000,
|
||||
|
||||
/**
|
||||
* @brief Allows the usage of custom soundboard sounds from other servers.
|
||||
*/
|
||||
p_use_external_sounds = 0x0000200000000000,
|
||||
|
||||
/**
|
||||
* @brief Allows sending voice messages.
|
||||
*/
|
||||
p_send_voice_messages = 0x0000400000000000,
|
||||
|
||||
/**
|
||||
* @brief Allows use of Clyde AI.
|
||||
*/
|
||||
p_use_clyde_ai = 0x0000800000000000,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents the various discord permissions
|
||||
* @deprecated Use dpp::permissions instead.
|
||||
*/
|
||||
using role_permissions = permissions;
|
||||
|
||||
/**
|
||||
* @brief Represents a permission bitmask (refer to enum dpp::permissions) which are held in an uint64_t
|
||||
*/
|
||||
class DPP_EXPORT permission {
|
||||
protected:
|
||||
/**
|
||||
* @brief The permission bitmask value
|
||||
*/
|
||||
uint64_t value{0};
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor, initializes permission to 0
|
||||
*/
|
||||
constexpr permission() = default;
|
||||
|
||||
/**
|
||||
* @brief Bitmask constructor, initializes permission to the argument
|
||||
* @param value The bitmask to initialize the permission to
|
||||
*/
|
||||
constexpr permission(uint64_t value) noexcept : value{value} {}
|
||||
|
||||
/**
|
||||
* @brief For acting like an integer
|
||||
* @return The permission bitmask value
|
||||
*/
|
||||
constexpr operator uint64_t() const noexcept {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For acting like an integer
|
||||
* @return A reference to the permission bitmask value
|
||||
*/
|
||||
constexpr operator uint64_t &() noexcept {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For building json
|
||||
* @return The permission bitmask value as a string
|
||||
*/
|
||||
operator nlohmann::json() const;
|
||||
|
||||
/**
|
||||
* @brief Check for certain permissions, taking into account administrator privileges. It uses the Bitwise AND operator
|
||||
* @tparam T one or more uint64_t permission bits
|
||||
* @param values The permissions (from dpp::permissions) to check for
|
||||
*
|
||||
* **Example:**
|
||||
*
|
||||
* ```cpp
|
||||
* bool is_mod = permission.can(dpp::p_kick_members, dpp::p_ban_members);
|
||||
* // Returns true if it has permission to p_kick_members and p_ban_members
|
||||
* ```
|
||||
*
|
||||
* @return bool True if it has **all** the given permissions or dpp::p_administrator
|
||||
*/
|
||||
template <typename... T>
|
||||
constexpr bool can(T... values) const noexcept {
|
||||
return has(values...) || (value & p_administrator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check for certain permissions, taking into account administrator privileges. It uses the Bitwise AND operator
|
||||
* @tparam T one or more uint64_t permission bits
|
||||
* @param values The permissions (from dpp::permissions) to check for
|
||||
*
|
||||
* **Example:**
|
||||
*
|
||||
* ```cpp
|
||||
* bool is_mod = permission.can_any(dpp::p_kick_members, dpp::p_ban_members);
|
||||
* // Returns true if it has permission to p_kick_members or p_ban_members
|
||||
* ```
|
||||
*
|
||||
* @return bool True if it has **any** of the given permissions or dpp::p_administrator
|
||||
*/
|
||||
template <typename... T>
|
||||
constexpr bool can_any(T... values) const noexcept {
|
||||
return has_any(values...) || (value & p_administrator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check for permission flags set. It uses the Bitwise AND operator
|
||||
* @tparam T one or more uint64_t permission bits
|
||||
* @param values The permissions (from dpp::permissions) to check for
|
||||
*
|
||||
* **Example:**
|
||||
*
|
||||
* ```cpp
|
||||
* bool is_mod = permission.has(dpp::p_kick_members, dpp::p_ban_members);
|
||||
* // Returns true if the permission bitmask contains p_kick_members and p_ban_members
|
||||
* ```
|
||||
*
|
||||
* @return bool True if it has **all** the given permissions
|
||||
*/
|
||||
template <typename... T>
|
||||
constexpr bool has(T... values) const noexcept {
|
||||
return (value & (0 | ... | values)) == (0 | ... | values);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check for permission flags set. It uses the Bitwise AND operator
|
||||
* @tparam T one or more uint64_t permission bits
|
||||
* @param values The permissions (from dpp::permissions) to check for
|
||||
*
|
||||
* **Example:**
|
||||
*
|
||||
* ```cpp
|
||||
* bool is_mod = permission.has_any(dpp::p_administrator, dpp::p_ban_members);
|
||||
* // Returns true if the permission bitmask contains p_administrator or p_ban_members
|
||||
* ```
|
||||
*
|
||||
* @return bool True if it has **any** of the given permissions
|
||||
*/
|
||||
template <typename... T>
|
||||
constexpr bool has_any(T... values) const noexcept {
|
||||
return (value & (0 | ... | values)) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a permission with the Bitwise OR operation
|
||||
* @tparam T one or more uint64_t permission bits
|
||||
* @param values The permissions (from dpp::permissions) to add
|
||||
*
|
||||
* **Example:**
|
||||
*
|
||||
* ```cpp
|
||||
* permission.add(dpp::p_view_channel, dpp::p_send_messages);
|
||||
* // Adds p_view_channel and p_send_messages to the permission bitmask
|
||||
* ```
|
||||
*
|
||||
* @return permission& reference to self for chaining
|
||||
*/
|
||||
template <typename... T>
|
||||
std::enable_if_t<(std::is_convertible_v<T, uint64_t> && ...), permission&>
|
||||
constexpr add(T... values) noexcept {
|
||||
value |= (0 | ... | values);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assign permissions. This will reset the bitmask to the new value.
|
||||
* @tparam T one or more uint64_t permission bits
|
||||
* @param values The permissions (from dpp::permissions) to set
|
||||
*
|
||||
* **Example:**
|
||||
*
|
||||
* ```cpp
|
||||
* permission.set(dpp::p_view_channel, dpp::p_send_messages);
|
||||
* ```
|
||||
*
|
||||
* @return permission& reference to self for chaining
|
||||
*/
|
||||
template <typename... T>
|
||||
std::enable_if_t<(std::is_convertible_v<T, uint64_t> && ...), permission&>
|
||||
constexpr set(T... values) noexcept {
|
||||
value = (0 | ... | values);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove a permission with the Bitwise NOT operation
|
||||
* @tparam T one or more uint64_t permission bits
|
||||
* @param values The permissions (from dpp::permissions) to remove
|
||||
*
|
||||
* **Example:**
|
||||
*
|
||||
* ```cpp
|
||||
* permission.remove(dpp::p_view_channel, dpp::p_send_messages);
|
||||
* // Removes p_view_channel and p_send_messages permission
|
||||
* ```
|
||||
*
|
||||
* @return permission& reference to self for chaining
|
||||
*/
|
||||
template <typename... T>
|
||||
std::enable_if_t<(std::is_convertible_v<T, uint64_t> && ...), permission&>
|
||||
constexpr remove(T... values) noexcept {
|
||||
value &= ~(0 | ... | values);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
598
dpp/presence.h
598
dpp/presence.h
@ -1,598 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/emoji.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <unordered_map>
|
||||
#include <dpp/json_interface.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Presence flags bitmask
|
||||
*/
|
||||
enum presence_flags {
|
||||
/**
|
||||
* @brief Desktop: Online.
|
||||
*/
|
||||
p_desktop_online = 0b00000001,
|
||||
|
||||
/**
|
||||
* @brief Desktop: DND.
|
||||
*/
|
||||
p_desktop_dnd = 0b00000010,
|
||||
|
||||
/**
|
||||
* @brief Desktop: Idle.
|
||||
*/
|
||||
p_desktop_idle = 0b00000011,
|
||||
|
||||
/**
|
||||
* @brief Web: Online.
|
||||
*/
|
||||
p_web_online = 0b00000100,
|
||||
|
||||
/**
|
||||
* @brief Web: DND.
|
||||
*/
|
||||
p_web_dnd = 0b00001000,
|
||||
|
||||
/**
|
||||
* @brief Web: Idle.
|
||||
*/
|
||||
p_web_idle = 0b00001100,
|
||||
|
||||
/**
|
||||
* @brief Mobile: Online.
|
||||
*/
|
||||
p_mobile_online = 0b00010000,
|
||||
|
||||
/**
|
||||
* @brief Mobile: DND.
|
||||
*/
|
||||
p_mobile_dnd = 0b00100000,
|
||||
|
||||
/**
|
||||
* @brief Mobile: Idle.
|
||||
*/
|
||||
p_mobile_idle = 0b00110000,
|
||||
|
||||
/**
|
||||
* @brief General: Online.
|
||||
*/
|
||||
p_status_online = 0b01000000,
|
||||
|
||||
/**
|
||||
* @brief General: DND.
|
||||
*/
|
||||
p_status_dnd = 0b10000000,
|
||||
|
||||
/**
|
||||
* @brief General: Idle.
|
||||
*/
|
||||
p_status_idle = 0b11000000
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Online presence status values
|
||||
*/
|
||||
enum presence_status : uint8_t {
|
||||
/**
|
||||
* @brief Offline.
|
||||
*/
|
||||
ps_offline = 0,
|
||||
|
||||
/**
|
||||
* @brief Online.
|
||||
*/
|
||||
ps_online = 1,
|
||||
|
||||
/**
|
||||
* @brief DND.
|
||||
*/
|
||||
ps_dnd = 2,
|
||||
|
||||
/**
|
||||
* @brief Idle.
|
||||
*/
|
||||
ps_idle = 3,
|
||||
|
||||
/**
|
||||
* @brief Invisible (show as offline).
|
||||
*/
|
||||
ps_invisible = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Bit shift for desktop status.
|
||||
*/
|
||||
#define PF_SHIFT_DESKTOP 0
|
||||
|
||||
/**
|
||||
* @brief Bit shift for web status.
|
||||
*/
|
||||
#define PF_SHIFT_WEB 2
|
||||
|
||||
/**
|
||||
* @brief Bit shift for mobile status.
|
||||
*/
|
||||
#define PF_SHIFT_MOBILE 4
|
||||
|
||||
/**
|
||||
* @brief Bit shift for main status.
|
||||
*/
|
||||
#define PF_SHIFT_MAIN 6
|
||||
|
||||
/**
|
||||
* @brief Bit mask for status.
|
||||
*/
|
||||
#define PF_STATUS_MASK 0b00000011
|
||||
|
||||
/**
|
||||
* @brief Bit mask for clearing desktop status.
|
||||
*/
|
||||
#define PF_CLEAR_DESKTOP 0b11111100
|
||||
|
||||
/**
|
||||
* @brief Bit mask for clearing web status.
|
||||
*/
|
||||
#define PF_CLEAR_WEB 0b11110011
|
||||
|
||||
/**
|
||||
* @brief Bit mask for clearing mobile status.
|
||||
*/
|
||||
#define PF_CLEAR_MOBILE 0b11001111
|
||||
|
||||
/**
|
||||
* @brief Bit mask for clearing main status.
|
||||
*/
|
||||
#define PF_CLEAR_STATUS 0b00111111
|
||||
|
||||
/**
|
||||
* @brief Game types
|
||||
*/
|
||||
enum activity_type : uint8_t {
|
||||
/**
|
||||
* @brief "Playing ..."
|
||||
*/
|
||||
at_game = 0,
|
||||
|
||||
/**
|
||||
* @brief "Streaming ..."
|
||||
*/
|
||||
at_streaming = 1,
|
||||
|
||||
/**
|
||||
* @brief "Listening to..."
|
||||
*/
|
||||
at_listening = 2,
|
||||
|
||||
/**
|
||||
* @brief "Watching..."
|
||||
*/
|
||||
at_watching = 3,
|
||||
|
||||
/**
|
||||
* @brief "Emoji..."
|
||||
*/
|
||||
at_custom = 4,
|
||||
|
||||
/**
|
||||
* @brief "Competing in..."
|
||||
*/
|
||||
at_competing = 5
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Activity types for rich presence
|
||||
*/
|
||||
enum activity_flags {
|
||||
/**
|
||||
* @brief In an instance.
|
||||
*/
|
||||
af_instance = 0b000000001,
|
||||
|
||||
/**
|
||||
* @brief Joining.
|
||||
*/
|
||||
af_join = 0b000000010,
|
||||
|
||||
/**
|
||||
* @brief Spectating.
|
||||
*/
|
||||
af_spectate = 0b000000100,
|
||||
|
||||
/**
|
||||
* @brief Sending join request.
|
||||
*/
|
||||
af_join_request = 0b000001000,
|
||||
|
||||
/**
|
||||
* @brief Synchronising.
|
||||
*/
|
||||
af_sync = 0b000010000,
|
||||
|
||||
/**
|
||||
* @brief Playing.
|
||||
*/
|
||||
af_play = 0b000100000,
|
||||
|
||||
/**
|
||||
* @brief Party privacy friends.
|
||||
*/
|
||||
af_party_privacy_friends = 0b001000000,
|
||||
|
||||
/**
|
||||
* @brief Party privacy voice channel.
|
||||
*/
|
||||
af_party_privacy_voice_channel = 0b010000000,
|
||||
|
||||
/**
|
||||
* @brief Embedded.
|
||||
*/
|
||||
af_embedded = 0b100000000
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An activity button is a custom button shown in the rich presence. Can be to join a game or whatever
|
||||
*/
|
||||
struct DPP_EXPORT activity_button {
|
||||
public:
|
||||
/**
|
||||
* @brief The text shown on the button (1-32 characters).
|
||||
*/
|
||||
std::string label;
|
||||
|
||||
/**
|
||||
* @brief The url opened when clicking the button (1-512 characters, can be empty).
|
||||
*
|
||||
* @note Bots cannot access the activity button URLs.
|
||||
*/
|
||||
std::string url;
|
||||
|
||||
/** Constructor */
|
||||
activity_button() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An activity asset are the images and the hover text displayed in the rich presence
|
||||
*/
|
||||
struct DPP_EXPORT activity_assets {
|
||||
public:
|
||||
/**
|
||||
* @brief The large asset image which usually contain snowflake ID or prefixed image ID.
|
||||
*/
|
||||
std::string large_image;
|
||||
|
||||
/**
|
||||
* @brief Text displayed when hovering over the large image of the activity.
|
||||
*/
|
||||
std::string large_text;
|
||||
|
||||
/**
|
||||
* @brief The small asset image which usually contain snowflake ID or prefixed image ID.
|
||||
*/
|
||||
std::string small_image;
|
||||
|
||||
/**
|
||||
* @brief Text displayed when hovering over the small image of the activity.
|
||||
*/
|
||||
std::string small_text;
|
||||
|
||||
/** Constructor */
|
||||
activity_assets() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Secrets for Rich Presence joining and spectating.
|
||||
*/
|
||||
struct DPP_EXPORT activity_secrets {
|
||||
public:
|
||||
/**
|
||||
* @brief The secret for joining a party.
|
||||
*/
|
||||
std::string join;
|
||||
|
||||
/**
|
||||
* @brief The secret for spectating a game.
|
||||
*/
|
||||
std::string spectate;
|
||||
|
||||
/**
|
||||
* @brief The secret for a specific instanced match.
|
||||
*/
|
||||
std::string match;
|
||||
|
||||
/** Constructor */
|
||||
activity_secrets() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Information for the current party of the player
|
||||
*/
|
||||
struct DPP_EXPORT activity_party {
|
||||
public:
|
||||
/**
|
||||
* @brief The ID of the party.
|
||||
*/
|
||||
snowflake id;
|
||||
|
||||
/**
|
||||
* @brief The party's current size.
|
||||
* Used to show the party's current size.
|
||||
*/
|
||||
int32_t current_size;
|
||||
|
||||
/**
|
||||
* @brief The party's maximum size.
|
||||
* Used to show the party's maximum size.
|
||||
*/
|
||||
int32_t maximum_size;
|
||||
|
||||
/** Constructor */
|
||||
activity_party();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An activity is a representation of what a user is doing. It might be a game, or a website, or a movie. Whatever.
|
||||
*/
|
||||
class DPP_EXPORT activity {
|
||||
public:
|
||||
/**
|
||||
* @brief Name of activity.
|
||||
* e.g. "Fortnite", "Mr Boom's Firework Factory", etc.
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* @brief State of activity or the custom user status.
|
||||
* e.g. "Waiting in lobby".
|
||||
*/
|
||||
std::string state;
|
||||
|
||||
/**
|
||||
* @brief What the player is currently doing.
|
||||
*/
|
||||
std::string details;
|
||||
|
||||
/**
|
||||
* @brief Images for the presence and their hover texts.
|
||||
*/
|
||||
activity_assets assets;
|
||||
|
||||
/**
|
||||
* @brief URL of activity (this is also named details).
|
||||
*
|
||||
* @note Only applicable for certain sites such a YouTube
|
||||
*/
|
||||
std::string url;
|
||||
|
||||
/**
|
||||
* @brief The custom buttons shown in the Rich Presence (max 2).
|
||||
*/
|
||||
std::vector<activity_button> buttons;
|
||||
|
||||
/**
|
||||
* @brief The emoji used for the custom status.
|
||||
*/
|
||||
dpp::emoji emoji;
|
||||
|
||||
/**
|
||||
* @brief Information of the current party if there is one.
|
||||
*/
|
||||
activity_party party;
|
||||
|
||||
/**
|
||||
* @brief Secrets for rich presence joining and spectating.
|
||||
*/
|
||||
activity_secrets secrets;
|
||||
|
||||
/**
|
||||
* @brief Activity type.
|
||||
*/
|
||||
activity_type type;
|
||||
|
||||
/**
|
||||
* @brief Time activity was created.
|
||||
*/
|
||||
time_t created_at;
|
||||
|
||||
/**
|
||||
* @brief Start time.
|
||||
* e.g. when game was started.
|
||||
*/
|
||||
time_t start;
|
||||
|
||||
/**
|
||||
* @brief End time.
|
||||
* e.g. for songs on spotify.
|
||||
*/
|
||||
time_t end;
|
||||
|
||||
/**
|
||||
* @brief Creating application.
|
||||
* e.g. a linked account on the user's client.
|
||||
*/
|
||||
snowflake application_id;
|
||||
|
||||
/**
|
||||
* @brief Flags bitmask from dpp::activity_flags.
|
||||
*/
|
||||
uint8_t flags;
|
||||
|
||||
/**
|
||||
* @brief Whether or not the activity is an instanced game session.
|
||||
*/
|
||||
bool is_instance;
|
||||
|
||||
/**
|
||||
* @brief Get the assets large image url if they have one, otherwise returns an empty string. In case of prefixed image IDs (mp:{image_id}) it returns an empty string.
|
||||
*
|
||||
* @see https://discord.com/developers/docs/topics/gateway-events#activity-object-activity-asset-image
|
||||
*
|
||||
* @param size The size of the image in pixels. It can be any power of two between 16 and 4096,
|
||||
* otherwise the default sized image is returned.
|
||||
* @param format The format to use for the avatar. It can be one of `i_webp`, `i_jpg` or `i_png`.
|
||||
* @return std::string image url or an empty string, if required attributes are missing or an invalid format was passed
|
||||
*/
|
||||
std::string get_large_asset_url(uint16_t size = 0, const image_type format = i_png) const;
|
||||
|
||||
/**
|
||||
* @brief Get the assets small image url if they have one, otherwise returns an empty string. In case of prefixed image IDs (mp:{image_id}) it returns an empty string.
|
||||
*
|
||||
* @see https://discord.com/developers/docs/topics/gateway-events#activity-object-activity-asset-image
|
||||
*
|
||||
* @param size The size of the image in pixels. It can be any power of two between 16 and 4096,
|
||||
* otherwise the default sized image is returned.
|
||||
* @param format The format to use for the avatar. It can be one of `i_webp`, `i_jpg` or `i_png`.
|
||||
* @return std::string image url or an empty string, if required attributes are missing or an invalid format was passed
|
||||
*/
|
||||
std::string get_small_asset_url(uint16_t size = 0, const image_type format = i_png) const;
|
||||
|
||||
activity();
|
||||
|
||||
/**
|
||||
* @brief Construct a new activity
|
||||
*
|
||||
* @param typ activity type
|
||||
* @param nam Name of the activity
|
||||
* @param stat State of the activity
|
||||
* @param url_ url of the activity, only works for certain sites, such as YouTube
|
||||
*/
|
||||
activity(const activity_type typ, const std::string& nam, const std::string& stat, const std::string& url_);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents user presence, e.g. what game they are playing and if they are online
|
||||
*/
|
||||
class DPP_EXPORT presence : public json_interface<presence> {
|
||||
protected:
|
||||
friend struct json_interface<presence>;
|
||||
|
||||
/** Fill this object from json.
|
||||
* @param j JSON object to fill from
|
||||
* @return A reference to self
|
||||
*/
|
||||
presence& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/** Build JSON from this object.
|
||||
*
|
||||
* @note This excludes any part of the presence object that are not valid for websockets and bots,
|
||||
* and includes websocket opcode 3. You will not get what you expect if you call this on a user's
|
||||
* presence received from on_presence_update or on_guild_create!
|
||||
*
|
||||
* @param with_id Add ID to output
|
||||
* @return The JSON text of the presence
|
||||
*/
|
||||
virtual json to_json_impl(bool with_id = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The user the presence applies to.
|
||||
*/
|
||||
snowflake user_id;
|
||||
|
||||
/**
|
||||
* @brief Guild ID.
|
||||
*
|
||||
* @note Apparently, Discord supports this internally, but the client doesn't...
|
||||
*/
|
||||
snowflake guild_id;
|
||||
|
||||
/**
|
||||
* @brief Flags bitmask containing dpp::presence_flags
|
||||
*/
|
||||
uint8_t flags;
|
||||
|
||||
/**
|
||||
* @brief List of activities.
|
||||
*/
|
||||
std::vector<activity> activities;
|
||||
|
||||
/** Constructor */
|
||||
presence();
|
||||
|
||||
/**
|
||||
* @brief Construct a new presence object with some parameters for sending to a websocket
|
||||
*
|
||||
* @param status Status of the activity
|
||||
* @param type Type of activity
|
||||
* @param activity_description Description of the activity
|
||||
*/
|
||||
presence(presence_status status, activity_type type, const std::string& activity_description);
|
||||
|
||||
/**
|
||||
* @brief Construct a new presence object with some parameters for sending to a websocket.
|
||||
*
|
||||
* @param status Status of the activity
|
||||
* @param a Activity itself
|
||||
*/
|
||||
presence(presence_status status, const activity& a);
|
||||
|
||||
/** Destructor */
|
||||
~presence();
|
||||
|
||||
/**
|
||||
* @brief The users status on desktop
|
||||
* @return The user's status on desktop
|
||||
*/
|
||||
presence_status desktop_status() const;
|
||||
|
||||
/**
|
||||
* @brief The user's status on web
|
||||
* @return The user's status on web
|
||||
*/
|
||||
presence_status web_status() const;
|
||||
|
||||
/**
|
||||
* @brief The user's status on mobile
|
||||
* @return The user's status on mobile
|
||||
*/
|
||||
presence_status mobile_status() const;
|
||||
|
||||
/**
|
||||
* @brief The user's status as shown to other users
|
||||
* @return The user's status as shown to other users
|
||||
*/
|
||||
presence_status status() const;
|
||||
|
||||
/**
|
||||
* @brief Build JSON from this object.
|
||||
*
|
||||
* @note This excludes any part of the presence object that are not valid for websockets and bots,
|
||||
* and includes websocket opcode 3. You will not get what you expect if you call this on a user's
|
||||
* presence received from on_presence_update or on_guild_create!
|
||||
*
|
||||
* @param with_id Add ID to output
|
||||
* @return The JSON of the presence
|
||||
*/
|
||||
json to_json(bool with_id = false) const; // Intentional shadow of json_interface, mostly present for documentation
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A container of presences
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, presence> presence_map;
|
||||
|
||||
}
|
||||
80
dpp/prune.h
80
dpp/prune.h
@ -1,80 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/json_interface.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Defines a request to count prunable users, or start a prune operation
|
||||
*/
|
||||
struct DPP_EXPORT prune : public json_interface<prune> {
|
||||
protected:
|
||||
friend struct json_interface<prune>;
|
||||
|
||||
/** Fill this object from json.
|
||||
* @param j JSON object to fill from
|
||||
* @return A reference to self
|
||||
*/
|
||||
prune& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/** Build JSON from this object.
|
||||
* @param with_prune_count True if the prune count boolean is to be set in the built JSON
|
||||
* @return The JSON of the prune object
|
||||
*/
|
||||
virtual json to_json_impl(bool with_prune_count = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Destroy this prune object
|
||||
*/
|
||||
virtual ~prune() = default;
|
||||
|
||||
/**
|
||||
* @brief Number of days to include in the prune.
|
||||
*/
|
||||
uint32_t days = 0;
|
||||
|
||||
/**
|
||||
* @brief Roles to include in the prune (empty to include everyone).
|
||||
*/
|
||||
std::vector<snowflake> include_roles;
|
||||
|
||||
/**
|
||||
* @brief True if the count of pruneable users should be returned.
|
||||
* @warning Discord recommend not using this on big guilds.
|
||||
*/
|
||||
bool compute_prune_count;
|
||||
|
||||
/**
|
||||
* @brief Build JSON from this object.
|
||||
*
|
||||
* @param with_id True if the prune count boolean is to be set in the built JSON
|
||||
* @return The JSON of the prune object
|
||||
*/
|
||||
json to_json(bool with_id = false) const; // Intentional shadow of json_interface, mostly present for documentation
|
||||
};
|
||||
|
||||
}
|
||||
639
dpp/queues.h
639
dpp/queues.h
@ -1,639 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <queue>
|
||||
#include <map>
|
||||
#include <shared_mutex>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <atomic>
|
||||
#include <dpp/httpsclient.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Error values. Most of these are currently unused in https_client.
|
||||
*/
|
||||
enum http_error : uint8_t {
|
||||
/**
|
||||
* @brief Request successful.
|
||||
*/
|
||||
h_success = 0,
|
||||
|
||||
/**
|
||||
* @brief Status unknown.
|
||||
*/
|
||||
h_unknown,
|
||||
|
||||
/**
|
||||
* @brief Connect failed.
|
||||
*/
|
||||
h_connection,
|
||||
|
||||
/**
|
||||
* @brief Invalid local ip address.
|
||||
*/
|
||||
h_bind_ip_address,
|
||||
|
||||
/**
|
||||
* @brief Read error.
|
||||
*/
|
||||
h_read,
|
||||
|
||||
/**
|
||||
* @brief Write error.
|
||||
*/
|
||||
h_write,
|
||||
|
||||
/**
|
||||
* @brief Too many 30x redirects.
|
||||
*/
|
||||
h_exceed_redirect_count,
|
||||
|
||||
/**
|
||||
* @brief Request cancelled.
|
||||
*/
|
||||
h_canceled,
|
||||
|
||||
/**
|
||||
* @brief SSL connection error.
|
||||
*/
|
||||
h_ssl_connection,
|
||||
|
||||
/**
|
||||
* @brief SSL cert loading error.
|
||||
*/
|
||||
h_ssl_loading_certs,
|
||||
|
||||
/**
|
||||
* @brief SSL server verification error.
|
||||
*/
|
||||
h_ssl_server_verification,
|
||||
|
||||
/**
|
||||
* @brief Unsupported multipart boundary characters.
|
||||
*/
|
||||
h_unsupported_multipart_boundary_chars,
|
||||
|
||||
/**
|
||||
* @brief Compression error.
|
||||
*/
|
||||
h_compression,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The result of any HTTP request. Contains the headers, vital
|
||||
* rate limit figures, and returned request body.
|
||||
*/
|
||||
struct DPP_EXPORT http_request_completion_t {
|
||||
/**
|
||||
* @brief HTTP headers of response.
|
||||
*/
|
||||
std::multimap<std::string, std::string> headers;
|
||||
|
||||
/**
|
||||
* @brief HTTP status.
|
||||
* e.g. 200 = OK, 404 = Not found, 429 = Rate limited, etc.
|
||||
*/
|
||||
uint16_t status = 0;
|
||||
|
||||
/**
|
||||
* @brief Error status.
|
||||
* e.g. if the request could not connect at all.
|
||||
*/
|
||||
http_error error = h_success;
|
||||
|
||||
/**
|
||||
* @brief Ratelimit bucket.
|
||||
*/
|
||||
std::string ratelimit_bucket;
|
||||
|
||||
/**
|
||||
* @brief Ratelimit limit of requests.
|
||||
*/
|
||||
uint64_t ratelimit_limit = 0;
|
||||
|
||||
/**
|
||||
* @brief Ratelimit remaining requests.
|
||||
*/
|
||||
uint64_t ratelimit_remaining = 0;
|
||||
|
||||
/**
|
||||
* @brief Ratelimit reset after (seconds).
|
||||
*/
|
||||
uint64_t ratelimit_reset_after = 0;
|
||||
|
||||
/**
|
||||
* @brief Ratelimit retry after (seconds).
|
||||
*/
|
||||
uint64_t ratelimit_retry_after = 0;
|
||||
|
||||
/**
|
||||
* @brief True if this request has caused us to be globally rate limited.
|
||||
*/
|
||||
bool ratelimit_global = false;
|
||||
|
||||
/**
|
||||
* @brief Reply body.
|
||||
*/
|
||||
std::string body;
|
||||
|
||||
/**
|
||||
* @brief Ping latency.
|
||||
*/
|
||||
double latency;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Results of HTTP requests are called back to these std::function types.
|
||||
*
|
||||
* @note Returned http_completion_events are called ASYNCHRONOUSLY in your
|
||||
* code which means they execute in a separate thread, results for the requests going
|
||||
* into a dpp::thread_pool. Completion events may not arrive in order depending on if
|
||||
* one request takes longer than another. Using the callbacks or using coroutines
|
||||
* correctly ensures that the order they arrive in the queue does not negatively affect
|
||||
* your code.
|
||||
*/
|
||||
typedef std::function<void(const http_request_completion_t&)> http_completion_event;
|
||||
|
||||
/**
|
||||
* @brief Various types of http method supported by the Discord API
|
||||
*/
|
||||
enum http_method {
|
||||
/**
|
||||
* @brief GET.
|
||||
*/
|
||||
m_get,
|
||||
|
||||
/**
|
||||
* @brief POST.
|
||||
*/
|
||||
m_post,
|
||||
|
||||
/**
|
||||
* @brief PUT.
|
||||
*/
|
||||
m_put,
|
||||
|
||||
/**
|
||||
* @brief PATCH.
|
||||
*/
|
||||
m_patch,
|
||||
|
||||
/**
|
||||
* @brief DELETE.
|
||||
*/
|
||||
m_delete
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A HTTP request.
|
||||
*
|
||||
* You should instantiate one of these objects via its constructor,
|
||||
* and pass a pointer to it into an instance of request_queue. Although you can
|
||||
* directly call the run() method of the object and it will make a HTTP call, be
|
||||
* aware that if you do this, it will be a **BLOCKING call** (not asynchronous) and
|
||||
* will not respect rate limits, as both of these functions are managed by the
|
||||
* request_queue class.
|
||||
*/
|
||||
class DPP_EXPORT http_request {
|
||||
/**
|
||||
* @brief Completion callback.
|
||||
*/
|
||||
http_completion_event complete_handler;
|
||||
|
||||
/**
|
||||
* @brief True if request has been made.
|
||||
*/
|
||||
bool completed;
|
||||
|
||||
/**
|
||||
* @brief True for requests that are not going to discord (rate limits code skipped).
|
||||
*/
|
||||
bool non_discord;
|
||||
|
||||
/**
|
||||
* @brief HTTPS client
|
||||
*/
|
||||
std::unique_ptr<https_client> cli;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Endpoint name
|
||||
* e.g. /api/users.
|
||||
*/
|
||||
std::string endpoint;
|
||||
|
||||
/**
|
||||
* @brief Major and minor parameters.
|
||||
*/
|
||||
std::string parameters;
|
||||
|
||||
/**
|
||||
* @brief Postdata for POST and PUT.
|
||||
*/
|
||||
std::string postdata;
|
||||
|
||||
/**
|
||||
* @brief HTTP method for request.
|
||||
*/
|
||||
http_method method;
|
||||
|
||||
/**
|
||||
* @brief Audit log reason for Discord requests, if non-empty.
|
||||
*/
|
||||
std::string reason;
|
||||
|
||||
/**
|
||||
* @brief Upload file name (server side).
|
||||
*/
|
||||
std::vector<std::string> file_name;
|
||||
|
||||
/**
|
||||
* @brief Upload file contents (binary).
|
||||
*/
|
||||
std::vector<std::string> file_content;
|
||||
|
||||
/**
|
||||
* @brief Upload file mime types.
|
||||
* application/octet-stream if unspecified.
|
||||
*/
|
||||
std::vector<std::string> file_mimetypes;
|
||||
|
||||
/**
|
||||
* @brief Request mime type.
|
||||
*/
|
||||
std::string mimetype;
|
||||
|
||||
/**
|
||||
* @brief Request headers (non-discord requests only).
|
||||
*/
|
||||
std::multimap<std::string, std::string> req_headers;
|
||||
|
||||
/**
|
||||
* @brief Waiting for rate limit to expire.
|
||||
*/
|
||||
bool waiting;
|
||||
|
||||
/**
|
||||
* @brief HTTP protocol.
|
||||
*/
|
||||
std::string protocol;
|
||||
|
||||
/**
|
||||
* @brief Constructor. When constructing one of these objects it should be passed to request_queue::post_request().
|
||||
* @param _endpoint The API endpoint, e.g. /api/guilds
|
||||
* @param _parameters Major and minor parameters for the endpoint e.g. a user id or guild id
|
||||
* @param completion completion event to call when done
|
||||
* @param _postdata Data to send in POST and PUT requests
|
||||
* @param method The HTTP method to use from dpp::http_method
|
||||
* @param audit_reason Audit log reason to send, empty to send none
|
||||
* @param filename The filename (server side) of any uploaded file
|
||||
* @param filecontent The binary content of any uploaded file for the request
|
||||
* @param filemimetype The MIME type of any uploaded file for the request
|
||||
* @param http_protocol HTTP protocol
|
||||
*/
|
||||
http_request(const std::string &_endpoint, const std::string &_parameters, http_completion_event completion, const std::string &_postdata = "", http_method method = m_get, const std::string &audit_reason = "", const std::string &filename = "", const std::string &filecontent = "", const std::string &filemimetype = "", const std::string &http_protocol = "1.1");
|
||||
|
||||
/**
|
||||
* @brief Constructor. When constructing one of these objects it should be passed to request_queue::post_request().
|
||||
* @param _endpoint The API endpoint, e.g. /api/guilds
|
||||
* @param _parameters Major and minor parameters for the endpoint e.g. a user id or guild id
|
||||
* @param completion completion event to call when done
|
||||
* @param _postdata Data to send in POST and PUT requests
|
||||
* @param method The HTTP method to use from dpp::http_method
|
||||
* @param audit_reason Audit log reason to send, empty to send none
|
||||
* @param filename The filename (server side) of any uploaded file
|
||||
* @param filecontent The binary content of any uploaded file for the request
|
||||
* @param filemimetypes The MIME type of any uploaded file for the request
|
||||
* @param http_protocol HTTP protocol
|
||||
*/
|
||||
http_request(const std::string &_endpoint, const std::string &_parameters, http_completion_event completion, const std::string &_postdata = "", http_method method = m_get, const std::string &audit_reason = "", const std::vector<std::string> &filename = {}, const std::vector<std::string> &filecontent = {}, const std::vector<std::string> &filemimetypes = {}, const std::string &http_protocol = "1.1");
|
||||
|
||||
/**
|
||||
* @brief Constructor. When constructing one of these objects it should be passed to request_queue::post_request().
|
||||
* @param _url Raw HTTP url
|
||||
* @param completion completion event to call when done
|
||||
* @param method The HTTP method to use from dpp::http_method
|
||||
* @param _postdata Data to send in POST and PUT requests
|
||||
* @param _mimetype POST data mime type
|
||||
* @param _headers HTTP headers to send
|
||||
* @param http_protocol HTTP protocol
|
||||
*/
|
||||
http_request(const std::string &_url, http_completion_event completion, http_method method = m_get, const std::string &_postdata = "", const std::string &_mimetype = "text/plain", const std::multimap<std::string, std::string> &_headers = {}, const std::string &http_protocol = "1.1");
|
||||
|
||||
/**
|
||||
* @brief Destroy the http request object
|
||||
*/
|
||||
~http_request();
|
||||
|
||||
/**
|
||||
* @brief Call the completion callback, if the request is complete.
|
||||
* @param c callback to call
|
||||
*/
|
||||
void complete(const http_request_completion_t &c);
|
||||
|
||||
/**
|
||||
* @brief Execute the HTTP request and mark the request complete.
|
||||
* @param processor Request concurrency queue this request was created by
|
||||
* @param owner creating cluster
|
||||
*/
|
||||
http_request_completion_t run(class request_concurrency_queue* processor, class cluster* owner);
|
||||
|
||||
/**
|
||||
* @brief Returns true if the request is complete
|
||||
* @return True if completed
|
||||
* */
|
||||
bool is_completed();
|
||||
|
||||
/**
|
||||
* @brief Get the HTTPS client used to perform this request, or nullptr if there is none
|
||||
* @return https_client object
|
||||
*/
|
||||
https_client* get_client() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A rate limit bucket. The library builds one of these for
|
||||
* each endpoint.
|
||||
*/
|
||||
struct DPP_EXPORT bucket_t {
|
||||
/**
|
||||
* @brief Request limit.
|
||||
*/
|
||||
uint64_t limit;
|
||||
|
||||
/**
|
||||
* @brief Requests remaining.
|
||||
*/
|
||||
uint64_t remaining;
|
||||
|
||||
/**
|
||||
* @brief Rate-limit of this bucket resets after this many seconds.
|
||||
*/
|
||||
uint64_t reset_after;
|
||||
|
||||
/**
|
||||
* @brief Rate-limit of this bucket can be retried after this many seconds.
|
||||
*/
|
||||
uint64_t retry_after;
|
||||
|
||||
/**
|
||||
* @brief Timestamp this buckets counters were updated.
|
||||
*/
|
||||
time_t timestamp;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Represents a timer instance in a pool handling requests to HTTP(S) servers.
|
||||
* There are several of these, the total defined by a constant in cluster.cpp, and each
|
||||
* one will always receive requests for the same rate limit bucket based on its endpoint
|
||||
* portion of the url. This makes rate limit handling reliable and easy to manage.
|
||||
* Each of these also has its own mutex, making it thread safe to call and use these
|
||||
* from anywhere in the code.
|
||||
*/
|
||||
class DPP_EXPORT request_concurrency_queue {
|
||||
public:
|
||||
/**
|
||||
* @brief Queue index
|
||||
*/
|
||||
int in_index{0};
|
||||
|
||||
/**
|
||||
* @brief True if ending.
|
||||
*/
|
||||
std::atomic<bool> terminating;
|
||||
|
||||
/**
|
||||
* @brief Request queue that owns this request_concurrency_queue.
|
||||
*/
|
||||
class request_queue* requests;
|
||||
|
||||
/**
|
||||
* @brief The cluster that owns this request_concurrency_queue.
|
||||
*/
|
||||
class cluster* creator;
|
||||
|
||||
/**
|
||||
* @brief Inbound queue mutex thread safety.
|
||||
*/
|
||||
std::shared_mutex in_mutex;
|
||||
|
||||
/**
|
||||
* @brief Inbound queue timer. The timer is called every second,
|
||||
* and when it wakes up it checks for requests pending to be sent in the queue.
|
||||
* If there are any requests and we are not waiting on rate limit, it will send them,
|
||||
* else it will wait for the rate limit to expire.
|
||||
*/
|
||||
dpp::timer in_timer;
|
||||
|
||||
/**
|
||||
* @brief Rate-limit bucket counters.
|
||||
*/
|
||||
std::map<std::string, bucket_t> buckets;
|
||||
|
||||
/**
|
||||
* @brief Queue of requests to be made. Sorted by http_request::endpoint.
|
||||
*/
|
||||
std::vector<std::unique_ptr<http_request>> requests_in;
|
||||
|
||||
/**
|
||||
* @brief Requests to remove after a set amount of time has passed
|
||||
*/
|
||||
std::vector<std::unique_ptr<http_request>> removals;
|
||||
|
||||
/**
|
||||
* @brief Timer callback
|
||||
* @param index Index ID for this timer
|
||||
*/
|
||||
void tick_and_deliver_requests(uint32_t index);
|
||||
|
||||
/**
|
||||
* @brief Construct a new concurrency queue object
|
||||
*
|
||||
* @param owner Owning cluster
|
||||
* @param req_q Owning request queue
|
||||
* @param index Queue index number, uniquely identifies this queue for hashing
|
||||
*/
|
||||
request_concurrency_queue(class cluster* owner, class request_queue* req_q, uint32_t index);
|
||||
|
||||
/**
|
||||
* @brief Destroy the concurrency queue object
|
||||
* This will stop the timer.
|
||||
*/
|
||||
~request_concurrency_queue();
|
||||
|
||||
/**
|
||||
* @brief Flags the queue as terminating
|
||||
* This will set the internal atomic bool that indicates this queue is to accept no more requests
|
||||
*/
|
||||
void terminate();
|
||||
|
||||
/**
|
||||
* @brief Post a http_request to this queue.
|
||||
*
|
||||
* @param req http_request to post. The pointer will be freed when it has
|
||||
* been executed.
|
||||
*/
|
||||
void post_request(std::unique_ptr<http_request> req);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The request_queue class manages rate limits and marshalls HTTP requests that have
|
||||
* been built as http_request objects.
|
||||
*
|
||||
* It ensures asynchronous delivery of events and queueing of requests.
|
||||
*
|
||||
* It will spawn multiple timers to make outbound HTTP requests and then call the callbacks
|
||||
* of those requests on completion within the dpp::thread_pool for the cluster.
|
||||
* If the user decides to take a long time processing a reply in their callback it won't affect
|
||||
* when other requests are sent, and if a HTTP request takes a long time due to latency, it won't
|
||||
* hold up user processing.
|
||||
*
|
||||
* There are usually two request_queue objects in each dpp::cluster, one of which is used
|
||||
* internally for the various REST methods to Discord such as sending messages, and the other
|
||||
* used to support user REST calls via dpp::cluster::request(). They are separated so that the
|
||||
* one for user requests can be specifically configured to never ever send the Discord token
|
||||
* unless it is explicitly placed into the request, for security reasons.
|
||||
*/
|
||||
class DPP_EXPORT request_queue {
|
||||
public:
|
||||
/**
|
||||
* @brief Required so request_concurrency_queue can access these member variables
|
||||
*/
|
||||
friend class request_concurrency_queue;
|
||||
|
||||
/**
|
||||
* @brief The cluster that owns this request_queue
|
||||
*/
|
||||
class cluster* creator;
|
||||
|
||||
/**
|
||||
* @brief A completed request. Contains both the request and the response
|
||||
*/
|
||||
struct completed_request {
|
||||
/**
|
||||
* @brief Request sent
|
||||
*/
|
||||
std::unique_ptr<http_request> request;
|
||||
|
||||
/**
|
||||
* @brief Response to the request
|
||||
*/
|
||||
std::unique_ptr<http_request_completion_t> response;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A vector of timers forming a pool.
|
||||
*
|
||||
* There are a set number of these defined by a constant in cluster.cpp. A request is always placed
|
||||
* on the same element in this vector, based upon its url, so that two conditions are satisfied:
|
||||
*
|
||||
* 1) Any requests for the same ratelimit bucket are handled by the same concurrency queue in the pool so that
|
||||
* they do not create unnecessary 429 errors,
|
||||
* 2) Requests for different endpoints go into different buckets, so that they may be requested in parallel
|
||||
* A global ratelimit event pauses all timers in the pool. These are few and far between.
|
||||
*/
|
||||
std::vector<std::unique_ptr<request_concurrency_queue>> requests_in;
|
||||
|
||||
/**
|
||||
* @brief Set to true if the timers should terminate.
|
||||
* When this is set to true no further requests are accepted to the queues.
|
||||
*/
|
||||
std::atomic<bool> terminating;
|
||||
|
||||
/**
|
||||
* @brief True if globally rate limited
|
||||
*
|
||||
* When globally rate limited the concurrency queues associated with this request queue
|
||||
* will not process any requests in their timers until the global rate limit expires.
|
||||
*/
|
||||
bool globally_ratelimited;
|
||||
|
||||
/**
|
||||
* @brief When we are globally rate limited until (unix epoch)
|
||||
*
|
||||
* @note Only valid if globally_rate limited is true. If we are globally rate limited,
|
||||
* queues in this class will not process requests until the current unix epoch time
|
||||
* is greater than this time.
|
||||
*/
|
||||
time_t globally_limited_until;
|
||||
|
||||
/**
|
||||
* @brief Number of request queues in the pool. This is the direct size of the requests_in
|
||||
* vector.
|
||||
*/
|
||||
uint32_t in_queue_pool_size;
|
||||
|
||||
/**
|
||||
* @brief constructor
|
||||
* @param owner The creating cluster.
|
||||
* @param request_concurrency The number of http request queues to allocate.
|
||||
* Each request queue is a dpp::timer which ticks every second looking for new
|
||||
* requests to run. The timer will hold back requests if we are waiting as to comply
|
||||
* with rate limits. Adding a request to this class will cause the queue it is placed in
|
||||
* to run immediately but this cannot override rate limits.
|
||||
* By default eight concurrency queues are allocated.
|
||||
* Side effects: Creates timers for the queue
|
||||
*/
|
||||
request_queue(class cluster* owner, uint32_t request_concurrency = 8);
|
||||
|
||||
/**
|
||||
* @brief Get the request queue concurrency count
|
||||
* @return uint32_t number of request queues that are active
|
||||
*/
|
||||
uint32_t get_request_queue_count() const;
|
||||
|
||||
/**
|
||||
* @brief Destroy the request queue object.
|
||||
* Side effects: Ends and deletes concurrency timers
|
||||
*/
|
||||
~request_queue();
|
||||
|
||||
/**
|
||||
* @brief Put a http_request into the request queue.
|
||||
* @note Will use a simple hash function to determine which of the 'in queues' to place
|
||||
* this request onto.
|
||||
* @param req request to add
|
||||
* @return reference to self
|
||||
*/
|
||||
request_queue& post_request(std::unique_ptr<http_request> req);
|
||||
|
||||
/**
|
||||
* @brief Returns true if the bot is currently globally rate limited
|
||||
* @return true if globally rate limited
|
||||
*/
|
||||
bool is_globally_ratelimited() const;
|
||||
|
||||
/**
|
||||
* @brief Returns the number of active requests on this queue
|
||||
* @return Total number of active requests
|
||||
*/
|
||||
size_t get_active_request_count() const;
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,296 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2022 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/cluster.h>
|
||||
#include <dpp/invite.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Templated REST request helper to save on typing
|
||||
*
|
||||
* @tparam T type to return in lambda callback
|
||||
* @param c calling cluster
|
||||
* @param basepath base path for API call
|
||||
* @param major major API function
|
||||
* @param minor minor API function
|
||||
* @param method HTTP method
|
||||
* @param postdata Post data or empty string
|
||||
* @param callback Callback lambda
|
||||
*/
|
||||
template<class T> inline void rest_request(dpp::cluster* c, const char* basepath, const std::string &major, const std::string &minor, http_method method, const std::string& postdata, command_completion_event_t callback) {
|
||||
c->post_rest(basepath, major, minor, method, postdata, [c, callback](json &j, const http_request_completion_t& http) {
|
||||
if (callback) {
|
||||
callback(confirmation_callback_t(c, T().fill_from_json(&j), http));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Templated REST request helper to save on typing (specialised for message)
|
||||
*
|
||||
* @tparam T type to return in lambda callback
|
||||
* @param c calling cluster
|
||||
* @param basepath base path for API call
|
||||
* @param major major API function
|
||||
* @param minor minor API function
|
||||
* @param method HTTP method
|
||||
* @param postdata Post data or empty string
|
||||
* @param callback Callback lambda
|
||||
*/
|
||||
template<> inline void rest_request<message>(dpp::cluster* c, const char* basepath, const std::string &major, const std::string &minor, http_method method, const std::string& postdata, command_completion_event_t callback) {
|
||||
c->post_rest(basepath, major, minor, method, postdata, [c, callback](json &j, const http_request_completion_t& http) {
|
||||
if (callback) {
|
||||
callback(confirmation_callback_t(c, message(c).fill_from_json(&j), http));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Templated REST request helper to save on typing (specialised for confirmation)
|
||||
*
|
||||
* @tparam T type to return in lambda callback
|
||||
* @param c calling cluster
|
||||
* @param basepath base path for API call
|
||||
* @param major major API function
|
||||
* @param minor minor API function
|
||||
* @param method HTTP method
|
||||
* @param postdata Post data or empty string
|
||||
* @param callback Callback lambda
|
||||
*/
|
||||
template<> inline void rest_request<confirmation>(dpp::cluster* c, const char* basepath, const std::string &major, const std::string &minor, http_method method, const std::string& postdata, command_completion_event_t callback) {
|
||||
c->post_rest(basepath, major, minor, method, postdata, [c, callback](json &j, const http_request_completion_t& http) {
|
||||
if (callback) {
|
||||
callback(confirmation_callback_t(c, confirmation(), http));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Templated REST request helper to save on typing (for returned lists)
|
||||
*
|
||||
* @tparam T singular type to return in lambda callback
|
||||
* @tparam T map type to return in lambda callback
|
||||
* @param c calling cluster
|
||||
* @param basepath base path for API call
|
||||
* @param major major API function
|
||||
* @param minor minor API function
|
||||
* @param method HTTP method
|
||||
* @param postdata Post data or empty string
|
||||
* @param key Key name of elements in the json list
|
||||
* @param callback Callback lambda
|
||||
*/
|
||||
template<class T> inline void rest_request_list(dpp::cluster* c, const char* basepath, const std::string &major, const std::string &minor, http_method method, const std::string& postdata, command_completion_event_t callback, const std::string& key = "id") {
|
||||
c->post_rest(basepath, major, minor, method, postdata, [c, key, callback](json &j, const http_request_completion_t& http) {
|
||||
std::unordered_map<snowflake, T> list;
|
||||
confirmation_callback_t e(c, confirmation(), http);
|
||||
if (!e.is_error()) {
|
||||
for (auto & curr_item : j) {
|
||||
list[snowflake_not_null(&curr_item, key.c_str())] = T().fill_from_json(&curr_item);
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(confirmation_callback_t(c, list, http));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Templated REST request helper to save on typing (for returned lists, specialised for invites)
|
||||
*
|
||||
* @tparam T singular type to return in lambda callback
|
||||
* @tparam T map type to return in lambda callback
|
||||
* @param c calling cluster
|
||||
* @param basepath base path for API call
|
||||
* @param major major API function
|
||||
* @param minor minor API function
|
||||
* @param method HTTP method
|
||||
* @param postdata Post data or empty string
|
||||
* @param key Key name of elements in the json list
|
||||
* @param callback Callback lambda
|
||||
*/
|
||||
template<> inline void rest_request_list<invite>(dpp::cluster* c, const char* basepath, const std::string &major, const std::string &minor, http_method method, const std::string& postdata, command_completion_event_t callback, const std::string& key) {
|
||||
c->post_rest(basepath, major, minor, method, postdata, [c, callback](json &j, const http_request_completion_t& http) {
|
||||
invite_map list;
|
||||
confirmation_callback_t e(c, confirmation(), http);
|
||||
if (!e.is_error()) {
|
||||
for (auto & curr_item : j) {
|
||||
list[string_not_null(&curr_item, "code")] = invite().fill_from_json(&curr_item);
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(confirmation_callback_t(c, list, http));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Templated REST request helper to save on typing (for returned lists, specialised for voiceregions)
|
||||
*
|
||||
* @tparam T singular type to return in lambda callback
|
||||
* @tparam T map type to return in lambda callback
|
||||
* @param c calling cluster
|
||||
* @param basepath base path for API call
|
||||
* @param major major API function
|
||||
* @param minor minor API function
|
||||
* @param method HTTP method
|
||||
* @param postdata Post data or empty string
|
||||
* @param key Key name of elements in the json list
|
||||
* @param callback Callback lambda
|
||||
*/
|
||||
template<> inline void rest_request_list<voiceregion>(dpp::cluster* c, const char* basepath, const std::string &major, const std::string &minor, http_method method, const std::string& postdata, command_completion_event_t callback, const std::string& key) {
|
||||
c->post_rest(basepath, major, minor, method, postdata, [c, callback](json &j, const http_request_completion_t& http) {
|
||||
voiceregion_map list;
|
||||
confirmation_callback_t e(c, confirmation(), http);
|
||||
if (!e.is_error()) {
|
||||
for (auto & curr_item : j) {
|
||||
list[string_not_null(&curr_item, "id")] = voiceregion().fill_from_json(&curr_item);
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(confirmation_callback_t(c, list, http));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Templated REST request helper to save on typing (for returned lists, specialised for bans)
|
||||
*
|
||||
* @tparam T singular type to return in lambda callback
|
||||
* @tparam T map type to return in lambda callback
|
||||
* @param c calling cluster
|
||||
* @param basepath base path for API call
|
||||
* @param major major API function
|
||||
* @param minor minor API function
|
||||
* @param method HTTP method
|
||||
* @param postdata Post data or empty string
|
||||
* @param key Key name of elements in the json list
|
||||
* @param callback Callback lambda
|
||||
*/
|
||||
template<> inline void rest_request_list<ban>(dpp::cluster* c, const char* basepath, const std::string &major, const std::string &minor, http_method method, const std::string& postdata, command_completion_event_t callback, const std::string& key) {
|
||||
c->post_rest(basepath, major, minor, method, postdata, [c, callback](json &j, const http_request_completion_t& http) {
|
||||
std::unordered_map<snowflake, ban> list;
|
||||
confirmation_callback_t e(c, confirmation(), http);
|
||||
if (!e.is_error()) {
|
||||
for (auto & curr_item : j) {
|
||||
ban curr_ban = ban().fill_from_json(&curr_item);
|
||||
list[curr_ban.user_id] = curr_ban;
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(confirmation_callback_t(c, list, http));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Templated REST request helper to save on typing (for returned lists, specialised for sticker packs)
|
||||
*
|
||||
* @tparam T singular type to return in lambda callback
|
||||
* @tparam T map type to return in lambda callback
|
||||
* @param c calling cluster
|
||||
* @param basepath base path for API call
|
||||
* @param major major API function
|
||||
* @param minor minor API function
|
||||
* @param method HTTP method
|
||||
* @param postdata Post data or empty string
|
||||
* @param key Key name of elements in the json list
|
||||
* @param callback Callback lambda
|
||||
*/
|
||||
template<> inline void rest_request_list<sticker_pack>(dpp::cluster* c, const char* basepath, const std::string &major, const std::string &minor, http_method method, const std::string& postdata, command_completion_event_t callback, const std::string& key) {
|
||||
c->post_rest(basepath, major, minor, method, postdata, [c, key, callback](json &j, const http_request_completion_t& http) {
|
||||
std::unordered_map<snowflake, sticker_pack> list;
|
||||
confirmation_callback_t e(c, confirmation(), http);
|
||||
if (!e.is_error()) {
|
||||
if (j.contains("sticker_packs")) {
|
||||
for (auto &curr_item: j["sticker_packs"]) {
|
||||
list[snowflake_not_null(&curr_item, key.c_str())] = sticker_pack().fill_from_json(&curr_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(confirmation_callback_t(c, list, http));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Templated REST request helper to save on typing (for returned lists)
|
||||
*
|
||||
* @tparam T singular type to return in lambda callback
|
||||
* @tparam T map type to return in lambda callback
|
||||
* @param c calling cluster
|
||||
* @param basepath base path for API call
|
||||
* @param major major API function
|
||||
* @param minor minor API function
|
||||
* @param method HTTP method
|
||||
* @param postdata Post data or empty string
|
||||
* @param key Key name of elements in the json list
|
||||
* @param root Root element to look for
|
||||
* @param callback Callback lambda
|
||||
*/
|
||||
template<class T> inline void rest_request_list(dpp::cluster* c, const char* basepath, const std::string &major, const std::string &minor, http_method method, const std::string& postdata, command_completion_event_t callback, const std::string& key, const std::string& root) {
|
||||
c->post_rest(basepath, major, minor, method, postdata, [c, root, key, callback](json &j, const http_request_completion_t& http) {
|
||||
std::unordered_map<snowflake, T> list;
|
||||
confirmation_callback_t e(c, confirmation(), http);
|
||||
if (!e.is_error()) {
|
||||
for (auto & curr_item : j[root]) {
|
||||
list[snowflake_not_null(&curr_item, key.c_str())] = T().fill_from_json(&curr_item);
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(confirmation_callback_t(c, list, http));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Templated REST request helper to save on typing (for returned lists, specialised for objects which doesn't have ids)
|
||||
*
|
||||
* @tparam T singular type to return in lambda callback
|
||||
* @tparam T vector type to return in lambda callback
|
||||
* @param c calling cluster
|
||||
* @param basepath base path for API call
|
||||
* @param major major API function
|
||||
* @param minor minor API function
|
||||
* @param method HTTP method
|
||||
* @param postdata Post data or empty string
|
||||
* @param callback Callback lambda
|
||||
*/
|
||||
template<class T> inline void rest_request_vector(dpp::cluster* c, const char* basepath, const std::string &major, const std::string &minor, http_method method, const std::string& postdata, command_completion_event_t callback) {
|
||||
c->post_rest(basepath, major, minor, method, postdata, [c, callback](json &j, const http_request_completion_t& http) {
|
||||
std::vector<T> list;
|
||||
confirmation_callback_t e(c, confirmation(), http);
|
||||
if (!e.is_error()) {
|
||||
for (auto & curr_item : j) {
|
||||
list.push_back(T().fill_from_json(&curr_item));
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(confirmation_callback_t(c, list, http));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,342 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <dpp/export.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <variant>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/dispatcher.h>
|
||||
#include <dpp/misc-enum.h>
|
||||
#include <dpp/timer.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/discordclient.h>
|
||||
#include <dpp/voiceregion.h>
|
||||
#include <dpp/dtemplate.h>
|
||||
#include <dpp/prune.h>
|
||||
#include <dpp/auditlog.h>
|
||||
#include <dpp/queues.h>
|
||||
#include <dpp/cache.h>
|
||||
#include <dpp/intents.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <shared_mutex>
|
||||
#include <cstring>
|
||||
#include <dpp/entitlement.h>
|
||||
#include <dpp/sku.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief A list of shards
|
||||
*/
|
||||
typedef std::map<uint32_t, class discord_client*> shard_list;
|
||||
|
||||
/**
|
||||
* @brief List of shards awaiting reconnection, by id with earliest possible reconnect time
|
||||
*/
|
||||
typedef std::map<uint32_t, time_t> reconnect_list;
|
||||
|
||||
/**
|
||||
* @brief Represents the various information from the 'get gateway bot' api call
|
||||
*/
|
||||
struct DPP_EXPORT gateway : public json_interface<gateway> {
|
||||
protected:
|
||||
friend struct json_interface<gateway>;
|
||||
|
||||
/**
|
||||
* @brief Fill this object from json
|
||||
*
|
||||
* @param j json to fill from
|
||||
* @return gateway& reference to self
|
||||
*/
|
||||
gateway& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Gateway websocket url.
|
||||
*/
|
||||
std::string url;
|
||||
|
||||
/**
|
||||
* @brief Number of suggested shards to start.
|
||||
*/
|
||||
uint32_t shards;
|
||||
|
||||
/**
|
||||
* @brief Total number of sessions that can be started.
|
||||
*/
|
||||
uint32_t session_start_total;
|
||||
|
||||
/**
|
||||
* @brief How many sessions are left.
|
||||
*/
|
||||
uint32_t session_start_remaining;
|
||||
|
||||
/**
|
||||
* @brief How many seconds until the session start quota resets.
|
||||
*/
|
||||
uint32_t session_start_reset_after;
|
||||
|
||||
/**
|
||||
* @brief How many sessions can be started at the same time.
|
||||
*/
|
||||
uint32_t session_start_max_concurrency;
|
||||
|
||||
/**
|
||||
* @brief Construct a new gateway object
|
||||
*
|
||||
* @param j JSON data to construct from
|
||||
*/
|
||||
gateway(nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Construct a new gateway object
|
||||
*/
|
||||
gateway();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Confirmation object represents any true or false simple REST request
|
||||
*
|
||||
*/
|
||||
struct DPP_EXPORT confirmation {
|
||||
bool success;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A container for types that can be returned for a REST API call
|
||||
*
|
||||
*/
|
||||
typedef std::variant<
|
||||
active_threads,
|
||||
application_role_connection,
|
||||
application_role_connection_metadata_list,
|
||||
confirmation,
|
||||
message,
|
||||
message_map,
|
||||
user,
|
||||
user_identified,
|
||||
user_map,
|
||||
guild_member,
|
||||
guild_member_map,
|
||||
channel,
|
||||
channel_map,
|
||||
thread_member,
|
||||
thread_member_map,
|
||||
guild,
|
||||
guild_map,
|
||||
guild_command_permissions,
|
||||
guild_command_permissions_map,
|
||||
role,
|
||||
role_map,
|
||||
invite,
|
||||
invite_map,
|
||||
dtemplate,
|
||||
dtemplate_map,
|
||||
emoji,
|
||||
emoji_map,
|
||||
ban,
|
||||
ban_map,
|
||||
voiceregion,
|
||||
voiceregion_map,
|
||||
voicestate,
|
||||
integration,
|
||||
integration_map,
|
||||
webhook,
|
||||
webhook_map,
|
||||
prune,
|
||||
guild_widget,
|
||||
gateway,
|
||||
interaction,
|
||||
interaction_response,
|
||||
auditlog,
|
||||
slashcommand,
|
||||
slashcommand_map,
|
||||
stage_instance,
|
||||
sticker,
|
||||
sticker_map,
|
||||
sticker_pack,
|
||||
sticker_pack_map,
|
||||
application,
|
||||
application_map,
|
||||
connection,
|
||||
connection_map,
|
||||
thread,
|
||||
thread_map,
|
||||
scheduled_event,
|
||||
scheduled_event_map,
|
||||
event_member,
|
||||
event_member_map,
|
||||
automod_rule,
|
||||
automod_rule_map,
|
||||
onboarding,
|
||||
welcome_screen,
|
||||
entitlement,
|
||||
entitlement_map,
|
||||
sku,
|
||||
sku_map
|
||||
> confirmable_t;
|
||||
|
||||
/**
|
||||
* @brief The details of a field in an error response
|
||||
*/
|
||||
struct DPP_EXPORT error_detail {
|
||||
/**
|
||||
* @brief Object name which is in error
|
||||
*/
|
||||
std::string object;
|
||||
|
||||
/**
|
||||
* @brief Field name which is in error
|
||||
*/
|
||||
std::string field;
|
||||
|
||||
/**
|
||||
* @brief Error code
|
||||
*/
|
||||
std::string code;
|
||||
|
||||
/**
|
||||
* @brief Error reason (full message)
|
||||
*/
|
||||
std::string reason;
|
||||
|
||||
/**
|
||||
* @brief Object field index
|
||||
*/
|
||||
DPP_DEPRECATED("index is unused and will be removed in a future version") int index = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The full details of an error from a REST response
|
||||
*/
|
||||
struct DPP_EXPORT error_info {
|
||||
/**
|
||||
* @brief Error code
|
||||
*/
|
||||
uint32_t code = 0;
|
||||
|
||||
/**
|
||||
* @brief Error message
|
||||
*
|
||||
*/
|
||||
std::string message;
|
||||
|
||||
/**
|
||||
* @brief Field specific error descriptions
|
||||
*/
|
||||
std::vector<error_detail> errors;
|
||||
|
||||
/**
|
||||
* @brief Human readable error message constructed from the above
|
||||
*/
|
||||
std::string human_readable;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The results of a REST call wrapped in a convenient struct
|
||||
*/
|
||||
struct DPP_EXPORT confirmation_callback_t {
|
||||
/**
|
||||
* @brief Information about the HTTP call used to make the request.
|
||||
*/
|
||||
http_request_completion_t http_info;
|
||||
|
||||
/**
|
||||
* @brief Value returned, wrapped in variant.
|
||||
*/
|
||||
confirmable_t value;
|
||||
|
||||
/**
|
||||
* @brief Owner/creator of the callback object.
|
||||
*/
|
||||
const class cluster* bot;
|
||||
|
||||
/**
|
||||
* @brief Construct a new confirmation callback t object.
|
||||
*/
|
||||
confirmation_callback_t() = default;
|
||||
|
||||
/**
|
||||
* @brief Construct a new confirmation callback t object
|
||||
*
|
||||
* @param creator owning cluster object
|
||||
*/
|
||||
confirmation_callback_t(cluster* creator);
|
||||
|
||||
/**
|
||||
* @brief Construct a new confirmation callback object
|
||||
*
|
||||
* @param _http The HTTP metadata from the REST call
|
||||
*/
|
||||
confirmation_callback_t(const http_request_completion_t& _http);
|
||||
|
||||
/**
|
||||
* @brief Construct a new confirmation callback object
|
||||
*
|
||||
* @param creator owning cluster object
|
||||
* @param _value The value to encapsulate in the confirmable_t
|
||||
* @param _http The HTTP metadata from the REST call
|
||||
*/
|
||||
confirmation_callback_t(cluster* creator, const confirmable_t& _value, const http_request_completion_t& _http);
|
||||
|
||||
/**
|
||||
* @brief Returns true if the call resulted in an error rather than a legitimate value in the
|
||||
* confirmation_callback_t::value member.
|
||||
*
|
||||
* @return true There was an error who's details can be obtained by get_error()
|
||||
* @return false There was no error
|
||||
*/
|
||||
bool is_error() const;
|
||||
|
||||
/**
|
||||
* @brief Get the error_info object.
|
||||
* The error_info object contains the details of any REST error, if there is an error
|
||||
* (to find out if there is an error check confirmation_callback_t::is_error())
|
||||
*
|
||||
* @return error_info The details of the error message
|
||||
*/
|
||||
error_info get_error() const;
|
||||
|
||||
/**
|
||||
* @brief Get the stored value via std::get
|
||||
* @tparam T type to get
|
||||
* @return stored value as type T
|
||||
*/
|
||||
template<typename T>
|
||||
T get() const {
|
||||
return std::get<T>(value);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A callback upon command completion
|
||||
*/
|
||||
typedef std::function<void(const confirmation_callback_t&)> command_completion_event_t;
|
||||
|
||||
/**
|
||||
* @brief Automatically JSON encoded HTTP result
|
||||
*/
|
||||
typedef std::function<void(json&, const http_request_completion_t&)> json_encode_t;
|
||||
}
|
||||
1007
dpp/role.h
1007
dpp/role.h
File diff suppressed because it is too large
Load Diff
@ -1,339 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/managed.h>
|
||||
#include <dpp/user.h>
|
||||
#include <dpp/guild.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/json_interface.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Represents the privacy of an event.
|
||||
*/
|
||||
enum event_privacy_level : uint8_t {
|
||||
/**
|
||||
* @brief The event is visible to only guild members.
|
||||
*/
|
||||
ep_guild_only = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Event entity types.
|
||||
*/
|
||||
enum event_entity_type : uint8_t {
|
||||
/**
|
||||
* @brief A stage instance.
|
||||
*/
|
||||
eet_stage_instance = 1,
|
||||
|
||||
/**
|
||||
* @brief A voice channel.
|
||||
*/
|
||||
eet_voice = 2,
|
||||
|
||||
/**
|
||||
* @brief External to discord, or a text channel etc.
|
||||
*/
|
||||
eet_external = 3
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Event status types.
|
||||
*/
|
||||
enum event_status : uint8_t {
|
||||
/**
|
||||
* @brief Scheduled.
|
||||
*/
|
||||
es_scheduled = 1,
|
||||
|
||||
/**
|
||||
* @brief Active now.
|
||||
*/
|
||||
es_active = 2,
|
||||
|
||||
/**
|
||||
* @brief Completed.
|
||||
*/
|
||||
es_completed = 3,
|
||||
|
||||
/**
|
||||
* @brief Cancelled.
|
||||
*/
|
||||
es_cancelled = 4
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Entities for the event.
|
||||
*/
|
||||
struct DPP_EXPORT event_entities {
|
||||
/**
|
||||
* @brief Location of the event.
|
||||
*/
|
||||
std::string location;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a guild member/user who has registered interest in an event.
|
||||
*
|
||||
*/
|
||||
struct DPP_EXPORT event_member {
|
||||
/**
|
||||
* @brief Event ID associated with.
|
||||
*/
|
||||
snowflake guild_scheduled_event_id;
|
||||
|
||||
/**
|
||||
* @brief User details of associated user.
|
||||
*
|
||||
*/
|
||||
dpp::user user;
|
||||
|
||||
/**
|
||||
* @brief Member details of user on the associated guild.
|
||||
*/
|
||||
dpp::guild_member member;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A scheduled event.
|
||||
*/
|
||||
struct DPP_EXPORT scheduled_event : public managed, public json_interface<scheduled_event> {
|
||||
protected:
|
||||
friend struct json_interface<scheduled_event>;
|
||||
|
||||
/**
|
||||
* @brief Serialise a scheduled_event object from json
|
||||
*
|
||||
* @return scheduled_event& a reference to self
|
||||
*/
|
||||
scheduled_event& fill_from_json_impl(const nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Build json for this object
|
||||
* @param with_id Include id field in json
|
||||
*
|
||||
* @return std::string Json of this object
|
||||
*/
|
||||
json to_json_impl(bool with_id = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The guild ID which the scheduled event belongs to.
|
||||
*/
|
||||
snowflake guild_id;
|
||||
|
||||
/**
|
||||
* @brief The channel ID in which the scheduled event will be hosted, or null if scheduled entity type is EXTERNAL.
|
||||
*
|
||||
* @note This may be empty.
|
||||
*/
|
||||
snowflake channel_id;
|
||||
|
||||
/**
|
||||
* @brief Optional: The ID of the user that created the scheduled event.
|
||||
*/
|
||||
snowflake creator_id;
|
||||
|
||||
/**
|
||||
* @brief The name of the scheduled event.
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* @brief Optional: The description of the scheduled event (1-1000 characters).
|
||||
*/
|
||||
std::string description;
|
||||
|
||||
/**
|
||||
* @brief The image of the scheduled event.
|
||||
*
|
||||
* @note This may be empty.
|
||||
*/
|
||||
utility::icon image;
|
||||
|
||||
/**
|
||||
* @brief The time the scheduled event will start.
|
||||
*/
|
||||
time_t scheduled_start_time;
|
||||
|
||||
/**
|
||||
* @brief The time the scheduled event will end, or null if the event does not have a scheduled time to end.
|
||||
*
|
||||
* @note This may be empty.
|
||||
*/
|
||||
time_t scheduled_end_time;
|
||||
|
||||
/**
|
||||
* @brief The privacy level of the scheduled event.
|
||||
*/
|
||||
event_privacy_level privacy_level;
|
||||
|
||||
/**
|
||||
* @brief The status of the scheduled event.
|
||||
*/
|
||||
event_status status;
|
||||
|
||||
/**
|
||||
* @brief The type of hosting entity associated with a scheduled event.
|
||||
* e.g. voice channel or stage channel.
|
||||
*/
|
||||
event_entity_type entity_type;
|
||||
|
||||
/**
|
||||
* @brief Any additional ID of the hosting entity associated with event.
|
||||
* e.g. stage instance ID.
|
||||
*
|
||||
* @note This may be empty.
|
||||
*/
|
||||
snowflake entity_id;
|
||||
|
||||
/**
|
||||
* @brief The entity metadata for the scheduled event.
|
||||
*
|
||||
* @note This may be empty.
|
||||
*/
|
||||
event_entities entity_metadata;
|
||||
|
||||
/**
|
||||
* @brief Optional: The creator of the scheduled event.
|
||||
*/
|
||||
user creator;
|
||||
|
||||
/**
|
||||
* @brief Optional: The number of users subscribed to the scheduled event.
|
||||
*/
|
||||
uint32_t user_count;
|
||||
|
||||
/**
|
||||
* @brief Create a scheduled_event object.
|
||||
*/
|
||||
scheduled_event();
|
||||
|
||||
/**
|
||||
* @brief Set the name of the event.
|
||||
* Minimum length: 1, Maximum length: 100
|
||||
* @param n event name
|
||||
* @return scheduled_event& reference to self
|
||||
* @throw dpp::length_error if length < 1
|
||||
*/
|
||||
scheduled_event& set_name(const std::string& n);
|
||||
|
||||
/**
|
||||
* @brief Set the description of the event.
|
||||
* Minimum length: 1 (if set), Maximum length: 100
|
||||
* @param d event description
|
||||
* @return scheduled_event& reference to self
|
||||
* @throw dpp::length_error if length < 1
|
||||
*/
|
||||
scheduled_event& set_description(const std::string& d);
|
||||
|
||||
/**
|
||||
* @brief Clear the description of the event.
|
||||
* @return scheduled_event& reference to self
|
||||
*/
|
||||
scheduled_event& clear_description();
|
||||
|
||||
/**
|
||||
* @brief Set the location of the event.
|
||||
* Minimum length: 1, Maximum length: 1000
|
||||
* @note Clears channel_id
|
||||
* @param l event location
|
||||
* @return scheduled_event& reference to self
|
||||
* @throw dpp::length_error if length < 1
|
||||
*/
|
||||
scheduled_event& set_location(const std::string& l);
|
||||
|
||||
/**
|
||||
* @brief Set the voice channel id of the event.
|
||||
* @note clears location
|
||||
* @param c channel ID
|
||||
* @return scheduled_event& reference to self
|
||||
*/
|
||||
scheduled_event& set_channel_id(snowflake c);
|
||||
|
||||
/**
|
||||
* @brief Set the creator id of the event.
|
||||
* @param c creator user ID
|
||||
* @return scheduled_event& reference to self
|
||||
*/
|
||||
scheduled_event& set_creator_id(snowflake c);
|
||||
|
||||
/**
|
||||
* @brief Set the status of the event.
|
||||
* @param s status to set
|
||||
* @return scheduled_event& reference to self
|
||||
* @throw dpp::logic_exception if status change is not valid
|
||||
*/
|
||||
scheduled_event& set_status(event_status s);
|
||||
|
||||
/**
|
||||
* @brief Set the start time of the event.
|
||||
* @param t starting time
|
||||
* @return scheduled_event& reference to self
|
||||
* @throw dpp::length_error if time is before now
|
||||
*/
|
||||
scheduled_event& set_start_time(time_t t);
|
||||
|
||||
/**
|
||||
* @brief Set the end time of the event.
|
||||
* @param t ending time
|
||||
* @return scheduled_event& reference to self
|
||||
* @throw dpp::length_error if time is before now
|
||||
*/
|
||||
scheduled_event& set_end_time(time_t t);
|
||||
|
||||
/**
|
||||
* @brief Load an image for the event cover.
|
||||
*
|
||||
* @param image_blob Image binary data
|
||||
* @param type Type of image. It can be one of `i_gif`, `i_jpg` or `i_png`.
|
||||
* @return emoji& Reference to self
|
||||
*/
|
||||
scheduled_event& load_image(std::string_view image_blob, const image_type type);
|
||||
|
||||
/**
|
||||
* @brief Load an image for the event cover.
|
||||
*
|
||||
* @param data Image binary data
|
||||
* @param size Size of the image.
|
||||
* @param type Type of image. It can be one of `i_gif`, `i_jpg` or `i_png`.
|
||||
* @return emoji& Reference to self
|
||||
*/
|
||||
scheduled_event& load_image(const std::byte* data, uint32_t size, const image_type type);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A group of scheduled events.
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, scheduled_event> scheduled_event_map;
|
||||
|
||||
/**
|
||||
* @brief A group of scheduled event members.
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, event_member> event_member_map;
|
||||
|
||||
|
||||
} // namespace dpp
|
||||
@ -1,53 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <dpp/export.h>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Verifies signatures on incoming webhooks using OpenSSL
|
||||
*/
|
||||
class signature_verifier {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor initializes the OpenSSL context and public key buffer
|
||||
*/
|
||||
signature_verifier();
|
||||
|
||||
/**
|
||||
* @brief Verifies the signature with the provided public key, timestamp, body, and signature
|
||||
* @param timestamp The timestamp of the request
|
||||
* @param body The body of the request
|
||||
* @param signature The hex-encoded signature to verify
|
||||
* @param public_key_hex The hex-encoded public key
|
||||
* @return true if the signature is valid, false otherwise
|
||||
*/
|
||||
bool verify_signature(const std::string& timestamp, const std::string& body, const std::string& signature, const std::string& public_key_hex);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
176
dpp/sku.h
176
dpp/sku.h
@ -1,176 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/managed.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/json_interface.h>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief The type of SKU.
|
||||
* */
|
||||
enum sku_type : uint8_t {
|
||||
/**
|
||||
* @brief Represents a durable one-time purchase
|
||||
*/
|
||||
DURABLE = 2,
|
||||
/**
|
||||
* @brief Consumable one-time purchase
|
||||
*/
|
||||
CONSUMABLE = 3,
|
||||
/**
|
||||
* @brief Represents a recurring subscription
|
||||
*/
|
||||
SUBSCRIPTION = 5,
|
||||
|
||||
/**
|
||||
* @brief System-generated group for each SUBSCRIPTION SKU created
|
||||
* @warning These are automatically created for each subscription SKU and are not used at this time. Please refrain from using these.
|
||||
*/
|
||||
SUBSCRIPTION_GROUP = 6,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief SKU flags.
|
||||
*/
|
||||
enum sku_flags : uint16_t {
|
||||
/**
|
||||
* @brief SKU is available for purchase
|
||||
*/
|
||||
sku_available = 0b000000000000100,
|
||||
|
||||
/**
|
||||
* @brief Recurring SKU that can be purchased by a user and applied to a single server. Grants access to every user in that server.
|
||||
*/
|
||||
sku_guild_subscription = 0b000000010000000,
|
||||
|
||||
/**
|
||||
* @brief Recurring SKU purchased by a user for themselves. Grants access to the purchasing user in every server.
|
||||
*/
|
||||
sku_user_subscription = 0b000000100000000,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A definition of a discord SKU.
|
||||
*/
|
||||
class DPP_EXPORT sku : public managed, public json_interface<sku> {
|
||||
protected:
|
||||
friend struct json_interface<sku>;
|
||||
|
||||
/** Read class values from json object
|
||||
* @param j A json object to read from
|
||||
* @return A reference to self
|
||||
*/
|
||||
sku& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Build json for this SKU object
|
||||
*
|
||||
* @param with_id include the ID in the json
|
||||
* @return json JSON object
|
||||
*/
|
||||
json to_json_impl(bool with_id = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The type of SKU.
|
||||
*/
|
||||
sku_type type{sku_type::SUBSCRIPTION};
|
||||
|
||||
/**
|
||||
* @brief ID of the parent application
|
||||
*/
|
||||
snowflake application_id{0};
|
||||
|
||||
/**
|
||||
* @brief Customer-facing name of your premium offering
|
||||
*/
|
||||
std::string name{};
|
||||
|
||||
/**
|
||||
* @brief System-generated URL slug based on the SKU's name
|
||||
*/
|
||||
std::string slug{};
|
||||
|
||||
/**
|
||||
* @brief Flags bitmap from dpp::sku_flags
|
||||
*/
|
||||
uint16_t flags{0};
|
||||
|
||||
/**
|
||||
* @brief Construct a new SKU object
|
||||
*/
|
||||
sku() = default;
|
||||
|
||||
/**
|
||||
* @brief Construct a new SKU object with all data required.
|
||||
*
|
||||
* @param id ID of the SKU.
|
||||
* @param type Type of SKU (sku_type).
|
||||
* @param application_id ID of the parent application.
|
||||
* @param name Customer-facing name of your premium offering.
|
||||
* @param slug System-generated URL slug based on the SKU's name.
|
||||
* @param flags Flags bitmap from dpp::sku_flags.
|
||||
*
|
||||
*/
|
||||
sku(const snowflake id, const sku_type type, const snowflake application_id, const std::string name, const std::string slug, const uint16_t flags);
|
||||
|
||||
/**
|
||||
* @brief Get the type of SKU.
|
||||
*
|
||||
* @return sku_type SKU type
|
||||
*/
|
||||
sku_type get_type() const;
|
||||
|
||||
/**
|
||||
* @brief Is the SKU available for purchase?
|
||||
*
|
||||
* @return true if the SKU can be purchased.
|
||||
*/
|
||||
bool is_available() const;
|
||||
|
||||
/**
|
||||
* @brief Is the SKU a guild subscription?
|
||||
*
|
||||
* @return true if the SKU is a guild subscription.
|
||||
*/
|
||||
bool is_guild_subscription() const;
|
||||
|
||||
/**
|
||||
* @brief Is the SKU a user subscription?
|
||||
*
|
||||
* @return true if the SKU is a user subscription
|
||||
*/
|
||||
bool is_user_subscription() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Group of SKUs.
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, sku> sku_map;
|
||||
|
||||
}
|
||||
307
dpp/snowflake.h
307
dpp/snowflake.h
@ -1,307 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/exception.h>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef DPP_FORMATTERS
|
||||
#include <format>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief The main namespace for D++ functions. classes and types
|
||||
*/
|
||||
namespace dpp {
|
||||
|
||||
/** @brief A container for a 64 bit unsigned value representing many things on discord.
|
||||
* This value is known in distributed computing as a snowflake value.
|
||||
*
|
||||
* Snowflakes are:
|
||||
*
|
||||
* - Performant (very fast to generate at source and to compare in code)
|
||||
* - Uncoordinated (allowing high availability across clusters, data centres etc)
|
||||
* - Time ordered (newer snowflakes have higher IDs)
|
||||
* - Directly Sortable (due to time ordering)
|
||||
* - Compact (64 bit numbers, not 128 bit, or string)
|
||||
*
|
||||
* An identical format of snowflake is used by Twitter, Instagram and several other platforms.
|
||||
*
|
||||
* @see https://en.wikipedia.org/wiki/Snowflake_ID
|
||||
* @see https://github.com/twitter-archive/snowflake/tree/b3f6a3c6ca8e1b6847baa6ff42bf72201e2c2231
|
||||
*/
|
||||
class DPP_EXPORT snowflake final {
|
||||
friend struct std::hash<dpp::snowflake>;
|
||||
protected:
|
||||
/**
|
||||
* @brief The snowflake value
|
||||
*/
|
||||
uint64_t value = 0;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a snowflake object
|
||||
*/
|
||||
constexpr snowflake() noexcept = default;
|
||||
|
||||
/**
|
||||
* @brief Copy a snowflake object
|
||||
*/
|
||||
constexpr snowflake(const snowflake &rhs) noexcept = default;
|
||||
|
||||
/**
|
||||
* @brief Move a snowflake object
|
||||
*/
|
||||
constexpr snowflake(snowflake &&rhs) noexcept = default;
|
||||
|
||||
/**
|
||||
* @brief Construct a snowflake from an integer value
|
||||
*
|
||||
* @throw dpp::logic_exception on assigning a negative value. The function is noexcept if the type given is unsigned
|
||||
* @param snowflake_val snowflake value as an integer type
|
||||
*/
|
||||
template <typename T, typename = std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<T, bool>>>
|
||||
constexpr snowflake(T snowflake_val) noexcept(std::is_unsigned_v<T>) : value(static_cast<std::make_unsigned_t<T>>(snowflake_val)) {
|
||||
/**
|
||||
* we cast to the unsigned version of the type given - this maintains "possible loss of data" warnings for sizeof(T) > sizeof(value)
|
||||
* while suppressing them for signed to unsigned conversion (for example snowflake(42) will call snowflake(int) which is a signed type)
|
||||
*/
|
||||
if constexpr (!std::is_unsigned_v<T>) {
|
||||
/* if the type is signed, at compile-time, add a check at runtime that the value is unsigned */
|
||||
if (snowflake_val < 0) {
|
||||
value = 0;
|
||||
throw dpp::logic_exception{"cannot assign a negative value to dpp::snowflake"};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct a snowflake object from an unsigned integer in a string
|
||||
*
|
||||
* On invalid string the value will be 0
|
||||
* @param string_value A snowflake value
|
||||
*/
|
||||
snowflake(std::string_view string_value) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Construct a snowflake object from an unsigned integer in a string
|
||||
*
|
||||
* On invalid string the value will be 0
|
||||
* @param string_value A snowflake value
|
||||
*/
|
||||
template <typename T, typename = std::enable_if_t<std::is_same_v<T, std::string>>>
|
||||
snowflake(const T &string_value) noexcept : snowflake(std::string_view{string_value}) {}
|
||||
/* ^ this exists to preserve `message_cache.find(std::get<std::string>(event.get_parameter("message_id")));` */
|
||||
|
||||
/**
|
||||
* @brief Copy value from another snowflake
|
||||
*
|
||||
* @param rhs The snowflake to copy from
|
||||
*/
|
||||
constexpr dpp::snowflake &operator=(const dpp::snowflake& rhs) noexcept = default;
|
||||
|
||||
/**
|
||||
* @brief Move value from another snowflake
|
||||
*
|
||||
* @param rhs The snowflake to move from
|
||||
*/
|
||||
constexpr dpp::snowflake &operator=(dpp::snowflake&& rhs) noexcept = default;
|
||||
|
||||
/**
|
||||
* @brief Assign integer value to the snowflake
|
||||
*
|
||||
* @throw dpp::logic_exception on assigning a negative value. The function is noexcept if the type given is unsigned
|
||||
* @param snowflake_val snowflake value as an integer type
|
||||
*/
|
||||
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
|
||||
constexpr dpp::snowflake &operator=(T snowflake_val) noexcept(std::is_unsigned_v<T>) {
|
||||
return *this = dpp::snowflake{snowflake_val};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assign value converted from a string to the snowflake
|
||||
*
|
||||
* On invalid string the value will be 0
|
||||
* @param snowflake_val snowflake value as a string
|
||||
*/
|
||||
template <typename T, typename = std::enable_if_t<std::is_convertible_v<T, std::string_view>>>
|
||||
constexpr dpp::snowflake &operator=(T&& snowflake_val) noexcept {
|
||||
return *this = dpp::snowflake{std::forward<T>(snowflake_val)};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the snowflake holds an empty value (is 0)
|
||||
*
|
||||
* @return true if empty (zero)
|
||||
*/
|
||||
constexpr bool empty() const noexcept {
|
||||
return value == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the stringified version of the snowflake value
|
||||
*
|
||||
* @return std::string string form of snowflake value
|
||||
*/
|
||||
inline std::string str() const {
|
||||
return std::to_string(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Comparison operator with another snowflake
|
||||
*
|
||||
* @param snowflake_val snowflake
|
||||
*/
|
||||
constexpr bool operator==(dpp::snowflake snowflake_val) const noexcept {
|
||||
return value == snowflake_val.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Comparison operator with a string
|
||||
*
|
||||
* @param snowflake_val snowflake value as a string
|
||||
*/
|
||||
bool operator==(std::string_view snowflake_val) const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Comparison operator with an integer
|
||||
*
|
||||
* @param snowflake_val snowflake value as an integer type
|
||||
*/
|
||||
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
|
||||
constexpr bool operator==(T snowflake_val) const noexcept {
|
||||
/* We use the std::enable_if_t trick to disable implicit conversions so there is a perfect candidate for overload resolution for integers, and it isn't ambiguous */
|
||||
return *this == dpp::snowflake{snowflake_val};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For acting like an integer
|
||||
* @return The snowflake value
|
||||
*/
|
||||
constexpr operator uint64_t() const noexcept {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For acting like an integer
|
||||
* @return A reference to the snowflake value
|
||||
*/
|
||||
constexpr operator uint64_t &() noexcept {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For building json
|
||||
* @return The snowflake value as a string
|
||||
*/
|
||||
operator json() const;
|
||||
|
||||
/**
|
||||
* @brief Get the creation time of this snowflake according to Discord.
|
||||
*
|
||||
* @return double creation time inferred from the snowflake ID.
|
||||
* The minimum possible value is the first second of 2015.
|
||||
*/
|
||||
constexpr double get_creation_time() const noexcept {
|
||||
constexpr uint64_t first_january_2016 = 1420070400000ull;
|
||||
return static_cast<double>((value >> 22) + first_january_2016) / 1000.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the worker id that produced this snowflake value
|
||||
*
|
||||
* @return uint8_t worker id
|
||||
*/
|
||||
constexpr uint8_t get_worker_id() const noexcept {
|
||||
return static_cast<uint8_t>((value & 0x3E0000) >> 17);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the process id that produced this snowflake value
|
||||
*
|
||||
* @return uint8_t process id
|
||||
*/
|
||||
constexpr uint8_t get_process_id() const noexcept {
|
||||
return static_cast<uint8_t>((value & 0x1F000) >> 12);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the increment, which is incremented for every snowflake
|
||||
* created over the one millisecond resolution in the timestamp.
|
||||
*
|
||||
* @return uint64_t millisecond increment
|
||||
*/
|
||||
constexpr uint16_t get_increment() const noexcept {
|
||||
return static_cast<uint16_t>(value & 0xFFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function for libfmt so that a snowflake can be directly formatted as a uint64_t.
|
||||
*
|
||||
* @see https://fmt.dev/latest/api.html#formatting-user-defined-types
|
||||
* @return uint64_t snowflake ID
|
||||
*/
|
||||
friend constexpr uint64_t format_as(snowflake s) noexcept {
|
||||
/* note: this function must stay as "friend" - this declares it as a free function but makes it invisible unless the argument is snowflake
|
||||
* this effectively means no implicit conversions are performed to snowflake, for example format_as(0) doesn't call this function */
|
||||
return s.value;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
struct std::hash<dpp::snowflake>
|
||||
{
|
||||
/**
|
||||
* @brief Hashing function for dpp::snowflake
|
||||
* Used by std::unordered_map. This just calls std::hash<uint64_t>.
|
||||
*
|
||||
* @param s Snowflake value to hash
|
||||
* @return std::size_t hash value
|
||||
*/
|
||||
std::size_t operator()(dpp::snowflake s) const noexcept {
|
||||
return std::hash<uint64_t>{}(s.value);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef DPP_FORMATTERS
|
||||
/*
|
||||
* @brief implementation of formater for dpp::snowflake for std::format support
|
||||
* https://en.cppreference.com/w/cpp/utility/format/formatter
|
||||
*/
|
||||
template <>
|
||||
struct std::formatter<dpp::snowflake>
|
||||
{
|
||||
template<class TP>
|
||||
constexpr typename TP::iterator parse(TP& ctx) {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template<class TF>
|
||||
typename TF::iterator format(const dpp::snowflake& snowflake, TF& ctx) const {
|
||||
return std::format_to(ctx.out(), "{}", snowflake.str());
|
||||
}
|
||||
};
|
||||
#endif //DPP_FORMATTERS
|
||||
196
dpp/socket.h
196
dpp/socket.h
@ -1,196 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <dpp/export.h>
|
||||
#ifdef _WIN32
|
||||
#include <WinSock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
#include <io.h>
|
||||
#define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout)
|
||||
#define pollfd WSAPOLLFD
|
||||
#else
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include <string_view>
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
namespace dpp
|
||||
{
|
||||
/**
|
||||
* @brief Represents a socket file descriptor.
|
||||
* This is used to ensure parity between windows and unix-like systems.
|
||||
*/
|
||||
#ifndef _WIN32
|
||||
using socket = int;
|
||||
#else
|
||||
using socket = SOCKET;
|
||||
#endif
|
||||
|
||||
#ifndef SOCKET_ERROR
|
||||
/**
|
||||
* @brief Represents a socket in error state
|
||||
*/
|
||||
#define SOCKET_ERROR -1
|
||||
#endif
|
||||
|
||||
#ifndef INVALID_SOCKET
|
||||
/**
|
||||
* @brief Represents a socket which is not yet assigned
|
||||
*/
|
||||
#define INVALID_SOCKET ~0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Represents an IPv4 address for use with socket functions such as
|
||||
* bind().
|
||||
*
|
||||
* Avoids type punning with C style casts from sockaddr_in to sockaddr pointers.
|
||||
*/
|
||||
class DPP_EXPORT address_t {
|
||||
/**
|
||||
* @brief Internal sockaddr struct
|
||||
*/
|
||||
sockaddr socket_addr{};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Create a new address_t
|
||||
* @param ip IPv4 address
|
||||
* @param port Port number
|
||||
* @note Leave both as defaults to create a default bind-to-any setting
|
||||
*/
|
||||
address_t(const std::string_view ip = "0.0.0.0", uint16_t port = 0);
|
||||
|
||||
/**
|
||||
* @brief Get sockaddr
|
||||
* @return sockaddr pointer
|
||||
*/
|
||||
[[nodiscard]] sockaddr *get_socket_address();
|
||||
|
||||
/**
|
||||
* @brief Returns size of sockaddr_in
|
||||
* @return sockaddr_in size
|
||||
* @note It is important the size this returns is sizeof(sockaddr_in) not
|
||||
* sizeof(sockaddr), this is NOT a bug but requirement of C socket functions.
|
||||
*/
|
||||
[[nodiscard]] size_t size();
|
||||
|
||||
/**
|
||||
* @brief Get the port bound to a file descriptor
|
||||
* @param fd File descriptor
|
||||
* @return Port number, or 0 if no port bound
|
||||
*/
|
||||
[[nodiscard]] uint16_t get_port(socket fd);
|
||||
};
|
||||
|
||||
enum raii_socket_type {
|
||||
rst_udp,
|
||||
rst_tcp,
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Allocates a dpp::socket, closing it on destruction
|
||||
*/
|
||||
struct DPP_EXPORT raii_socket {
|
||||
/**
|
||||
* @brief File descriptor
|
||||
*/
|
||||
socket fd;
|
||||
|
||||
/**
|
||||
* @brief Construct a socket.
|
||||
* Calls socket() and returns a new file descriptor
|
||||
*/
|
||||
raii_socket(raii_socket_type type = rst_udp);
|
||||
|
||||
/**
|
||||
* @brief Convert an established fd to an raii_socket
|
||||
* @param plain_fd
|
||||
*/
|
||||
raii_socket(socket plain_fd);
|
||||
|
||||
/**
|
||||
* @brief Non-copyable
|
||||
*/
|
||||
raii_socket(raii_socket&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Non-movable
|
||||
*/
|
||||
raii_socket(raii_socket&&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Sets the value of a socket option.
|
||||
* @tparam T type to set option for
|
||||
* @param level The level at which to change the socket options
|
||||
* @param name The option to change the value of
|
||||
* @param value The value to set
|
||||
* @return True if set successfully
|
||||
*/
|
||||
template <typename T> bool set_option(int level, int name, T value);
|
||||
|
||||
/**
|
||||
* @brief Bind socket to IP/port
|
||||
* @param address address to bind to
|
||||
* @return true on success
|
||||
*/
|
||||
bool bind(address_t address);
|
||||
|
||||
/**
|
||||
* @brief Listen on previously bound port
|
||||
* @return true on success
|
||||
*/
|
||||
bool listen();
|
||||
|
||||
/**
|
||||
* @brief Accept a pending connection on listening socket
|
||||
* @return new connection file descriptor
|
||||
*/
|
||||
socket accept();
|
||||
|
||||
/**
|
||||
* @brief Non-copyable
|
||||
*/
|
||||
raii_socket operator=(raii_socket&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Non-movable
|
||||
*/
|
||||
raii_socket operator=(raii_socket&&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
* Frees the socket by closing it
|
||||
*/
|
||||
~raii_socket();
|
||||
};
|
||||
|
||||
extern template DPP_EXPORT bool raii_socket::set_option<int>(int level, int name, int value);
|
||||
|
||||
|
||||
}
|
||||
@ -1,154 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/cluster.h>
|
||||
#include <dpp/socket.h>
|
||||
#include <dpp/sslconnection.h>
|
||||
#include <type_traits>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
enum socket_listener_type : uint8_t {
|
||||
li_plaintext,
|
||||
li_ssl,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Listens on a TCP socket for new connections, and whenever a new connection is
|
||||
* received, accept it and spawn a new connection of type T.
|
||||
* @tparam T type for socket connection, must be derived from ssl_connection
|
||||
*/
|
||||
template<typename T, typename = std::enable_if_t<std::is_base_of_v<ssl_connection, T>>>
|
||||
struct socket_listener {
|
||||
/**
|
||||
* @brief The listening socket for incoming connections
|
||||
*/
|
||||
raii_socket fd;
|
||||
|
||||
/**
|
||||
* @brief Active connections for the server of type T
|
||||
*/
|
||||
std::unordered_map<socket, std::unique_ptr<T>> connections;
|
||||
|
||||
/**
|
||||
* @brief Cluster creator
|
||||
*/
|
||||
cluster* creator{nullptr};
|
||||
|
||||
/**
|
||||
* @brief True if plain text connections to the server are allowed
|
||||
*/
|
||||
bool plaintext{true};
|
||||
|
||||
/**
|
||||
* @brief Private key PEM file path, if running an SSL server
|
||||
*/
|
||||
std::string private_key_file;
|
||||
|
||||
/**
|
||||
* @brief Public key PEM file path, if running an SSL server
|
||||
*/
|
||||
std::string public_key_file;
|
||||
|
||||
/**
|
||||
* @brief Event to handle socket removal from the connection map
|
||||
*/
|
||||
event_handle close_event;
|
||||
|
||||
/**
|
||||
* @brief Socket events for listen socket in the socket engine
|
||||
*/
|
||||
socket_events events;
|
||||
|
||||
/**
|
||||
* @brief Create a new socket listener (TCP server)
|
||||
* @param owner Owning cluster
|
||||
* @param address IP address to bind the listening socket to, use 0.0.0.0 to bind all interfaces
|
||||
* @param port Port number to bind the listening socket to
|
||||
* @param type Type of server, plaintext or SSL
|
||||
* @param private_key For SSL servers, a path to the PEM private key file
|
||||
* @param public_key For SSL servers, a path to the PEM public key file
|
||||
* @throws connection_exception on failure to bind or listen to the port/interface
|
||||
*/
|
||||
socket_listener(cluster* owner, const std::string_view address, uint16_t port, socket_listener_type type = li_plaintext, const std::string& private_key = "", const std::string& public_key = "")
|
||||
: fd(rst_tcp), creator(owner), plaintext(type == li_plaintext), private_key_file(private_key), public_key_file(public_key)
|
||||
{
|
||||
fd.set_option<int>(SOL_SOCKET, SO_REUSEADDR, 1);
|
||||
if (!fd.bind(address_t(address, port))) {
|
||||
// error
|
||||
throw dpp::connection_exception("Could not bind to " + std::string(address) + ":" + std::to_string(port));
|
||||
}
|
||||
if (!fd.listen()) {
|
||||
// error
|
||||
throw dpp::connection_exception("Could not listen for connections on " + std::string(address) + ":" + std::to_string(port));
|
||||
}
|
||||
events = dpp::socket_events(
|
||||
fd.fd,
|
||||
WANT_READ | WANT_ERROR,
|
||||
[this](socket sfd, const struct socket_events &e) {
|
||||
handle_accept(sfd, e);
|
||||
},
|
||||
[](socket, const struct socket_events&) { },
|
||||
[](socket, const struct socket_events&, int) { }
|
||||
);
|
||||
owner->socketengine->register_socket(events);
|
||||
|
||||
close_event = creator->on_socket_close([this](const socket_close_t& event) {
|
||||
connections.erase(event.fd);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor, detaches on_socket_close event
|
||||
*/
|
||||
~socket_listener() {
|
||||
creator->on_socket_close.detach(close_event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle a new incoming socket with accept()
|
||||
* Accepts a new connection, and calls emplace() if valid
|
||||
* @param sfd File descriptor for listening socket
|
||||
* @param e socket events for the listening socket
|
||||
*/
|
||||
virtual void handle_accept(socket sfd, const struct socket_events &e) {
|
||||
socket new_fd{fd.accept()};
|
||||
if (new_fd >= 0) {
|
||||
emplace(new_fd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Emplace a new connection into the connection map for the server.
|
||||
* This is a factory function which must be implemented by the deriving class
|
||||
* @param newfd File descriptor for new connection
|
||||
*/
|
||||
virtual void emplace(socket newfd) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,332 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/socket.h>
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <functional>
|
||||
#include <shared_mutex>
|
||||
#include <dpp/thread_pool.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Types of IO events a socket may subscribe to.
|
||||
*/
|
||||
enum socket_event_flags : uint8_t {
|
||||
/**
|
||||
* @brief Socket wants to receive events when it can be read from.
|
||||
* This is provided by the underlying implementation.
|
||||
*/
|
||||
WANT_READ = 1,
|
||||
/**
|
||||
* @brief Socket wants to receive events when it can be written to.
|
||||
* This is provided by the underlying implementation, and will be
|
||||
* a one-off event. If you want to receive ongoing write events you
|
||||
* must re-request this event type each time.
|
||||
*/
|
||||
WANT_WRITE = 2,
|
||||
/**
|
||||
* @brief Socket wants to receive events that indicate an error condition.
|
||||
* Note that EOF (graceful close) is not an error condition and is indicated
|
||||
* by errno being 0 and ::read() returning 0.
|
||||
*/
|
||||
WANT_ERROR = 4,
|
||||
/**
|
||||
* @brief Socket should be removed as soon as is safe to do so. Generally, this is
|
||||
* after the current iteration through the active event list.
|
||||
*/
|
||||
WANT_DELETION = 8,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Read ready event
|
||||
*/
|
||||
using socket_read_event = std::function<void(dpp::socket fd, const struct socket_events&)>;
|
||||
|
||||
/**
|
||||
* @brief Write ready event
|
||||
*/
|
||||
using socket_write_event = std::function<void(dpp::socket fd, const struct socket_events&)>;
|
||||
|
||||
/**
|
||||
* @brief Error event
|
||||
*/
|
||||
using socket_error_event = std::function<void(dpp::socket fd, const struct socket_events&, int error_code)>;
|
||||
|
||||
/**
|
||||
* @brief Contains statistics about the IO loop
|
||||
*/
|
||||
struct DPP_EXPORT socket_stats {
|
||||
/**
|
||||
* @brief Number of reads since startup
|
||||
*/
|
||||
uint64_t reads{0};
|
||||
|
||||
/**
|
||||
* @brief Number of writes since startup
|
||||
*/
|
||||
uint64_t writes{0};
|
||||
|
||||
/**
|
||||
* @brief Number of errors since startup
|
||||
*/
|
||||
uint64_t errors{0};
|
||||
|
||||
/**
|
||||
* @brief Number of updates to file descriptors
|
||||
*/
|
||||
uint64_t updates{0};
|
||||
|
||||
/**
|
||||
* @brief Number of deletions of file descriptors
|
||||
*/
|
||||
uint64_t deletions{0};
|
||||
|
||||
/**
|
||||
* @brief Number of loop iterations since startup
|
||||
*/
|
||||
uint64_t iterations{0};
|
||||
|
||||
/**
|
||||
* @brief Number of currently active file descriptors
|
||||
*/
|
||||
uint64_t active_fds{0};
|
||||
|
||||
/**
|
||||
* @brief Socket engine type
|
||||
*/
|
||||
std::string_view engine_type;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents an active socket event set in the socket engine.
|
||||
*
|
||||
* An event set contains a file descriptor, a set of event handler callbacks, and
|
||||
* a set of bitmask flags which indicate which events it wants to receive.
|
||||
* It is possible to quickly toggle event types on or off, as it is not always necessary
|
||||
* or desired to receive all events all the time, in fact doing so can cause an event
|
||||
* storm which will consume 100% CPU (e.g. if you request to receive write events all
|
||||
* the time).
|
||||
*/
|
||||
struct DPP_EXPORT socket_events {
|
||||
/**
|
||||
* @brief File descriptor
|
||||
*
|
||||
* This should be a valid file descriptor created via ::socket().
|
||||
*/
|
||||
dpp::socket fd{INVALID_SOCKET};
|
||||
|
||||
/**
|
||||
* @brief Flag bit mask of values from dpp::socket_event_flags
|
||||
*/
|
||||
uint8_t flags{0};
|
||||
|
||||
/**
|
||||
* @brief Read ready event
|
||||
* @note This function will be called from a different thread to that
|
||||
* which adds the event set to the socket engine.
|
||||
*/
|
||||
socket_read_event on_read{};
|
||||
|
||||
/**
|
||||
* @brief Write ready event
|
||||
* @note This function will be called from a different thread to that
|
||||
* which adds the event set to the socket engine.
|
||||
*/
|
||||
socket_write_event on_write{};
|
||||
|
||||
/**
|
||||
* @brief Error event
|
||||
* @note This function will be called from a different thread to that
|
||||
* which adds the event set to the socket engine.
|
||||
*/
|
||||
socket_error_event on_error{};
|
||||
|
||||
/**
|
||||
* @brief Construct a new socket_events
|
||||
* @param socket_fd file descriptor
|
||||
* @param _flags initial flags bitmask
|
||||
* @param read_event read ready event
|
||||
* @param write_event write ready event
|
||||
* @param error_event error event
|
||||
*/
|
||||
socket_events(dpp::socket socket_fd, uint8_t _flags, const socket_read_event& read_event, const socket_write_event& write_event = {}, const socket_error_event& error_event = {})
|
||||
: fd(socket_fd), flags(_flags), on_read(read_event), on_write(write_event), on_error(error_event) { }
|
||||
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
socket_events() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Container of event sets keyed by socket file descriptor
|
||||
*/
|
||||
using socket_container = std::unordered_map<dpp::socket, std::unique_ptr<socket_events>>;
|
||||
|
||||
/**
|
||||
* @brief This is the base class for socket engines.
|
||||
* The actual implementation is OS specific and the correct implementation is detected by
|
||||
* CMake. It is then compiled specifically into DPP so only one implementation can exist
|
||||
* in the implementation. All implementations should behave identically to the user, abstracting
|
||||
* out implementation-specific behaviours (e.g. difference between edge and level triggered
|
||||
* event mechanisms etc).
|
||||
*/
|
||||
struct DPP_EXPORT socket_engine_base {
|
||||
|
||||
/**
|
||||
* @brief Owning cluster
|
||||
*/
|
||||
class cluster* owner{nullptr};
|
||||
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param creator Owning cluster
|
||||
*/
|
||||
socket_engine_base(class cluster* creator);
|
||||
|
||||
/**
|
||||
* @brief Non-copyable
|
||||
*/
|
||||
socket_engine_base(const socket_engine_base&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Non-copyable
|
||||
*/
|
||||
socket_engine_base(socket_engine_base&&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Non-movable
|
||||
*/
|
||||
socket_engine_base& operator=(const socket_engine_base&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Non-movable
|
||||
*/
|
||||
socket_engine_base& operator=(socket_engine_base&&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Default destructor
|
||||
*/
|
||||
virtual ~socket_engine_base() = default;
|
||||
|
||||
/**
|
||||
* @brief Should be called repeatedly in a loop.
|
||||
* Will run for a maximum of 1 second.
|
||||
*/
|
||||
virtual void process_events() = 0;
|
||||
|
||||
/**
|
||||
* @brief Register a new socket with the socket engine
|
||||
* @param e Socket events
|
||||
* @return true if socket was added
|
||||
*/
|
||||
virtual bool register_socket(const socket_events& e);
|
||||
|
||||
/**
|
||||
* @brief Update an existing socket in the socket engine
|
||||
* @param e Socket events
|
||||
* @return true if socket was updated
|
||||
*/
|
||||
virtual bool update_socket(const socket_events& e);
|
||||
|
||||
/**
|
||||
* @brief Delete a socket from the socket engine
|
||||
* @note This will not remove the socket immediately. It will set the
|
||||
* WANT_DELETION flag causing it to be removed as soon as is safe to do so
|
||||
* (once all events associated with it are completed).
|
||||
* @param e File descriptor
|
||||
* @return true if socket was queued for deletion
|
||||
*/
|
||||
bool delete_socket(dpp::socket fd);
|
||||
|
||||
/**
|
||||
* @brief Iterate through the list of sockets and remove any
|
||||
* with WANT_DELETION set. This will also call implementation-specific
|
||||
* remove_socket() on each entry to be removed.
|
||||
*/
|
||||
void prune();
|
||||
|
||||
/**
|
||||
* @brief Merge new flags in with the given file descriptor
|
||||
* @param fd file descriptor
|
||||
* @param extra_flags extra flags to add
|
||||
*/
|
||||
void inplace_modify_fd(dpp::socket fd, uint8_t extra_flags);
|
||||
|
||||
/**
|
||||
* @brief Get statistics for socket engine
|
||||
* @return socket stats
|
||||
*/
|
||||
const socket_stats& get_stats() const;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief Mutex for fds
|
||||
*/
|
||||
std::shared_mutex fds_mutex;
|
||||
|
||||
/**
|
||||
* @brief File descriptors, and their states
|
||||
*/
|
||||
socket_container fds;
|
||||
|
||||
/**
|
||||
* @brief Socket engine statistics
|
||||
*/
|
||||
socket_stats stats{};
|
||||
|
||||
/**
|
||||
* @brief Find a file descriptors socket events
|
||||
* @param fd file descriptor
|
||||
* @return file descriptor or nullptr if doesn't exist
|
||||
*/
|
||||
socket_events* get_fd(dpp::socket fd);
|
||||
|
||||
/**
|
||||
* @brief Called by the prune() function to remove sockets when safe to do so.
|
||||
* This is normally at the end or before an iteration of the event loop.
|
||||
* @param fd File descriptor to remove
|
||||
*/
|
||||
virtual bool remove_socket(dpp::socket fd);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This is implemented by whatever derived form socket_engine takes
|
||||
* @param creator Creating cluster
|
||||
*/
|
||||
DPP_EXPORT std::unique_ptr<socket_engine_base> create_socket_engine(class cluster *creator);
|
||||
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
* @brief Set up a signal handler to be ignored
|
||||
* @param signal Signal to set. If the signal is already set up with a handler,
|
||||
* this will do nothing.
|
||||
*/
|
||||
void set_signal_handler(int signal);
|
||||
#endif
|
||||
|
||||
};
|
||||
@ -1,53 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
namespace dpp::detail {
|
||||
|
||||
struct wrapped_ssl_ctx;
|
||||
|
||||
/**
|
||||
* @brief Generate a new wrapped SSL context.
|
||||
* If an SSL context already exists for the given port number, it will be returned, else a new one will be
|
||||
* generated and cached. Contexts with port = 0 will be considered client contexts. There can only be one
|
||||
* client context at a time and it covers all SSL client connections. There can be many SSL server contexts,
|
||||
* individual ones can be cached per-port, each with their own loaded SSL private and public key PEM certificate.
|
||||
*
|
||||
* @param port Port number. Pass zero to create or get the client context.
|
||||
* @param private_key Private key PEM pathname for server contexts
|
||||
* @param public_key Public key PEM pathname for server contexts
|
||||
* @return wrapped SSL context
|
||||
*/
|
||||
DPP_EXPORT wrapped_ssl_ctx* generate_ssl_context(uint16_t port = 0, const std::string &private_key = "", const std::string &public_key = "");
|
||||
|
||||
/**
|
||||
* @brief Release an SSL context
|
||||
* @warning Only do this if you are certain no SSL connections remain that use this context.
|
||||
* As OpenSSL is a C library it is impossible for us to track this on its behalf. Be careful!
|
||||
* @param port port number to release
|
||||
*/
|
||||
DPP_EXPORT void release_ssl_context(uint16_t port = 0);
|
||||
|
||||
};
|
||||
@ -1,403 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/misc-enum.h>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <ctime>
|
||||
#include <mutex>
|
||||
#include <dpp/socket.h>
|
||||
#include <cstdint>
|
||||
#include <dpp/timer.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief This is an opaque class containing openssl library specific structures.
|
||||
* We define it this way so that the public facing D++ library doesn't require
|
||||
* the openssl headers be available to build against it.
|
||||
*/
|
||||
class openssl_connection;
|
||||
|
||||
/**
|
||||
* @brief Close a socket
|
||||
*
|
||||
* @param sfd Socket to close
|
||||
* @return false on error, true on success
|
||||
*/
|
||||
DPP_EXPORT bool close_socket(dpp::socket sfd);
|
||||
|
||||
/**
|
||||
* @brief Set a socket to blocking or non-blocking IO
|
||||
*
|
||||
* @param sockfd socket to act upon
|
||||
* @param non_blocking should socket be non-blocking?
|
||||
* @return false on error, true on success
|
||||
*/
|
||||
DPP_EXPORT bool set_nonblocking(dpp::socket sockfd, bool non_blocking);
|
||||
|
||||
/**
|
||||
* @brief SSL_read buffer size
|
||||
*
|
||||
* You'd think that we would get better performance with a bigger buffer, but SSL frames are 16k each.
|
||||
* SSL_read in non-blocking mode will only read 16k at a time. There's no point in a bigger buffer as
|
||||
* it'd go unused.
|
||||
*/
|
||||
constexpr uint16_t DPP_BUFSIZE{16 * 1024};
|
||||
|
||||
/**
|
||||
* @brief Represents a failed socket system call, e.g. connect() failure
|
||||
*/
|
||||
constexpr int ERROR_STATUS{-1};
|
||||
|
||||
/**
|
||||
* @brief Maximum number of internal connect() retries on TCP connections
|
||||
*/
|
||||
constexpr int MAX_RETRIES{4};
|
||||
|
||||
/**
|
||||
* @brief Implements a simple non-blocking SSL stream connection.
|
||||
*/
|
||||
class DPP_EXPORT ssl_connection
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* @brief Clean up resources
|
||||
*/
|
||||
void cleanup();
|
||||
|
||||
/**
|
||||
* @brief Mutex for creation of internal SSL pointers by openssl
|
||||
*/
|
||||
std::mutex ssl_mutex;
|
||||
|
||||
/**
|
||||
* @brief Mutex for output buffer
|
||||
*/
|
||||
std::mutex out_mutex;
|
||||
|
||||
/**
|
||||
* @brief Start offset into internal ring buffer for client to server IO
|
||||
*/
|
||||
size_t client_to_server_length = 0;
|
||||
|
||||
/**
|
||||
* @brief Start offset into internal ring buffer for server to client IO
|
||||
*/
|
||||
size_t client_to_server_offset = 0;
|
||||
|
||||
/**
|
||||
* @brief Internal ring buffer for client to server IO
|
||||
*/
|
||||
char client_to_server_buffer[DPP_BUFSIZE];
|
||||
|
||||
/**
|
||||
* @brief Internal ring buffer for server to client IO
|
||||
*/
|
||||
char server_to_client_buffer[DPP_BUFSIZE];
|
||||
|
||||
/**
|
||||
* @brief True if this connection is a server inbound connection from accept()
|
||||
*/
|
||||
bool is_server = false;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Input buffer received from socket
|
||||
*/
|
||||
std::string buffer;
|
||||
|
||||
/**
|
||||
* @brief Output buffer for sending to socket
|
||||
*/
|
||||
std::string obuffer;
|
||||
|
||||
/**
|
||||
* @brief Raw file descriptor of connection
|
||||
*/
|
||||
dpp::socket sfd;
|
||||
|
||||
/**
|
||||
* @brief Openssl opaque contexts
|
||||
*/
|
||||
openssl_connection* ssl;
|
||||
|
||||
/**
|
||||
* @brief SSL cipher in use
|
||||
*/
|
||||
std::string cipher;
|
||||
|
||||
/**
|
||||
* @brief For timers
|
||||
*/
|
||||
time_t last_tick;
|
||||
|
||||
/**
|
||||
* @brief Start time of connection
|
||||
*/
|
||||
time_t start;
|
||||
|
||||
/**
|
||||
* @brief How many times we retried connect()
|
||||
*/
|
||||
uint8_t connect_retries{0};
|
||||
|
||||
/**
|
||||
* @brief Hostname connected to
|
||||
*/
|
||||
std::string hostname;
|
||||
|
||||
/**
|
||||
* @brief Port connected to
|
||||
*/
|
||||
std::string port;
|
||||
|
||||
/**
|
||||
* @brief Bytes out
|
||||
*/
|
||||
uint64_t bytes_out;
|
||||
|
||||
/**
|
||||
* @brief Bytes in
|
||||
*/
|
||||
uint64_t bytes_in;
|
||||
|
||||
/**
|
||||
* @brief True for a plain text connection
|
||||
*/
|
||||
bool plaintext;
|
||||
|
||||
/**
|
||||
* @brief True if connection is completed
|
||||
*/
|
||||
bool connected{false};
|
||||
|
||||
/**
|
||||
* @brief True if tcp connect() succeeded
|
||||
*/
|
||||
bool tcp_connect_done{false};
|
||||
|
||||
/**
|
||||
* @brief Timer handle for one second timer
|
||||
*/
|
||||
timer timer_handle;
|
||||
|
||||
/**
|
||||
* @brief Unique ID of socket used as a nonce
|
||||
* You can use this to identify requests vs reply
|
||||
* if you want. D++ itself only sets this, and does
|
||||
* not use it in any logic. It starts at 1 and increments
|
||||
* for each request made.
|
||||
*/
|
||||
uint64_t unique_id;
|
||||
|
||||
/**
|
||||
* @brief Called every second
|
||||
*/
|
||||
virtual void one_second_timer();
|
||||
|
||||
/**
|
||||
* @brief Start SSL connection and connect to TCP endpoint
|
||||
* @throw dpp::exception Failed to initialise connection
|
||||
*/
|
||||
virtual void connect();
|
||||
|
||||
/**
|
||||
* @brief Set this to true to log all IO to debug for this connection.
|
||||
* This is an internal developer facility. Do not enable it unless you
|
||||
* need to, as it will be very noisy.
|
||||
*/
|
||||
bool raw_trace{false};
|
||||
|
||||
/**
|
||||
* @brief If raw_trace is set to true, log a debug message for this connection
|
||||
* @param message debug message
|
||||
*/
|
||||
void do_raw_trace(const std::string& message) const;
|
||||
|
||||
virtual void on_buffer_drained();
|
||||
|
||||
/**
|
||||
* @brief Start connecting to a TCP socket.
|
||||
* This simply calls connect() and checks for error return, as the timeout is now handled in the main
|
||||
* IO events for the ssl_connection class.
|
||||
*
|
||||
* @param sockfd socket descriptor
|
||||
* @param addr address to connect to
|
||||
* @param addrlen address length
|
||||
* @param timeout_ms timeout in milliseconds
|
||||
* @return int -1 on error, 0 on success just like POSIX connect()
|
||||
* @throw dpp::connection_exception on failure
|
||||
*/
|
||||
int start_connecting(dpp::socket sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief For low-level debugging, calling this function will
|
||||
* enable low level I/O logging for this connection to the logger.
|
||||
* This can be very loud, and output a lot of data, so only enable it
|
||||
* selectively where you need it.
|
||||
*
|
||||
* Generally, you won't need this, it is a library development utility.
|
||||
*/
|
||||
void enable_raw_tracing();
|
||||
|
||||
/**
|
||||
* @brief Get the bytes out objectGet total bytes sent
|
||||
* @return uint64_t bytes sent
|
||||
*/
|
||||
uint64_t get_bytes_out();
|
||||
|
||||
/**
|
||||
* @brief Get total bytes received
|
||||
* @return uint64_t bytes received
|
||||
*/
|
||||
uint64_t get_bytes_in();
|
||||
|
||||
/**
|
||||
* @brief Every request made has a unique ID. This increments
|
||||
* for every request, starting at 1. You can use this for statistics,
|
||||
* or to associate requests and replies in external event loops.
|
||||
* @return Unique ID
|
||||
*/
|
||||
uint64_t get_unique_id() const;
|
||||
|
||||
/**
|
||||
* @brief Get SSL cipher name
|
||||
* @return std::string ssl cipher name
|
||||
*/
|
||||
std::string get_cipher();
|
||||
|
||||
/**
|
||||
* @brief True if we are keeping the connection alive after it has finished
|
||||
*/
|
||||
bool keepalive;
|
||||
|
||||
/**
|
||||
* @brief Owning cluster
|
||||
*/
|
||||
class cluster* owner;
|
||||
|
||||
/**
|
||||
* @brief Private key PEM file path for inbound SSL connections
|
||||
*/
|
||||
std::string private_key_file;
|
||||
|
||||
/**
|
||||
* @brief Public key PEM file path for inbound SSL connections
|
||||
*/
|
||||
std::string public_key_file;
|
||||
|
||||
/**
|
||||
* @brief Connect to a specified host and port. Throws std::runtime_error on fatal error.
|
||||
* @param creator Creating cluster
|
||||
* @param _hostname The hostname to connect to
|
||||
* @param _port the Port number to connect to
|
||||
* @param plaintext_downgrade Set to true to connect using plaintext only, without initialising SSL.
|
||||
* @param reuse Attempt to reuse previous connections for this hostname and port, if available
|
||||
* Note that no Discord endpoints will function when downgraded. This option is provided only for
|
||||
* connection to non-Discord addresses such as within dpp::cluster::request().
|
||||
* @throw dpp::exception Failed to initialise connection
|
||||
*/
|
||||
ssl_connection(cluster* creator, const std::string &_hostname, const std::string &_port = "443", bool plaintext_downgrade = false, bool reuse = false);
|
||||
|
||||
/**
|
||||
* @brief Accept a new connection from listen()/accept() socket
|
||||
* @param creator Creating cluster
|
||||
* @param fd Socket file descriptor assigned by accept()
|
||||
* @param port Port the new fd came from
|
||||
* @param plaintext_downgrade Set to true to connect using plaintext only, without initialising SSL.
|
||||
* @param private_key if plaintext_downgrade is set to false, a private key PEM file for SSL connections
|
||||
* @param public_key if plaintext_downgrade is set to false, a public key PEM file for SSL connections
|
||||
*/
|
||||
ssl_connection(cluster* creator, socket fd, uint16_t port, bool plaintext_downgrade = false, const std::string& private_key = "", const std::string& public_key = "");
|
||||
|
||||
/**
|
||||
* @brief Set up non blocking I/O and configure on_read, on_write and on_error.
|
||||
* @throw std::exception Any std::exception (or derivative) thrown from read_loop() indicates setup failed
|
||||
*/
|
||||
void read_loop();
|
||||
|
||||
/**
|
||||
* @brief Destroy the ssl_connection object
|
||||
*/
|
||||
virtual ~ssl_connection();
|
||||
|
||||
/**
|
||||
* @brief Handle input from the input buffer. This function will be called until
|
||||
* all data in the buffer has been processed and the buffer is empty.
|
||||
* @param buffer the buffer content. Will be modified removing any processed front elements
|
||||
* @return bool True if the socket should remain connected
|
||||
*/
|
||||
virtual bool handle_buffer(std::string &buffer);
|
||||
|
||||
/**
|
||||
* @brief Write to the output buffer.
|
||||
* @param data Data to be written to the buffer.
|
||||
* @note The data may not be written immediately and may be written at a later time to the socket.
|
||||
*/
|
||||
void socket_write(const std::string_view data);
|
||||
|
||||
/**
|
||||
* @brief Close socket connection
|
||||
*/
|
||||
virtual void close();
|
||||
|
||||
/**
|
||||
* @brief Log a message
|
||||
* @param severity severity of log message
|
||||
* @param msg Log message to send
|
||||
*/
|
||||
virtual void log(dpp::loglevel severity, const std::string &msg) const;
|
||||
|
||||
/**
|
||||
* @brief Called while SSL handshake is in progress.
|
||||
* If the handshake completes, the state of the socket is progressed to
|
||||
* an established state.
|
||||
* @param ev Socket events for the socket
|
||||
*/
|
||||
void complete_handshake(const struct socket_events* ev);
|
||||
|
||||
/**
|
||||
* @brief Called when the TCP socket has data to read
|
||||
* @param fd File descriptor
|
||||
* @param ev Socket events
|
||||
*/
|
||||
void on_read(dpp::socket fd, const struct dpp::socket_events& ev);
|
||||
|
||||
/**
|
||||
* @brief Called when the TCP socket can be written to without blocking
|
||||
* @param fd File descriptor
|
||||
* @param e Socket events
|
||||
*/
|
||||
void on_write(dpp::socket fd, const struct dpp::socket_events& e);
|
||||
|
||||
/**
|
||||
* @brief Called when there is an error on the TCP socket
|
||||
* @param fd File descriptor
|
||||
* @param error_code Error code
|
||||
*/
|
||||
void on_error(dpp::socket fd, const struct dpp::socket_events&, int error_code);
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,112 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/managed.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <unordered_map>
|
||||
#include <dpp/json_interface.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Represents the privacy of a stage instance
|
||||
*/
|
||||
enum stage_privacy_level : uint8_t {
|
||||
/**
|
||||
* @brief The Stage instance is visible publicly, such as on Stage Discovery.
|
||||
*/
|
||||
sp_public = 1,
|
||||
|
||||
/**
|
||||
* @brief The Stage instance is visible to only guild members.
|
||||
*/
|
||||
sp_guild_only = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A stage instance.
|
||||
* Stage instances are like a conference facility, with moderators/speakers and listeners.
|
||||
*/
|
||||
struct DPP_EXPORT stage_instance : public managed, public json_interface<stage_instance> {
|
||||
protected:
|
||||
friend struct json_interface<stage_instance>;
|
||||
|
||||
/**
|
||||
* @brief Serialise a stage_instance object rom json
|
||||
*
|
||||
* @return stage_instance& a reference to self
|
||||
*/
|
||||
stage_instance& fill_from_json_impl(const nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Build json for this object
|
||||
*
|
||||
* @param with_id include ID
|
||||
* @return json Json of this object
|
||||
*/
|
||||
virtual json to_json_impl(bool with_id = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The guild ID of the associated Stage channel.
|
||||
*/
|
||||
snowflake guild_id;
|
||||
|
||||
/**
|
||||
* @brief The ID of the associated Stage channel.
|
||||
*/
|
||||
snowflake channel_id;
|
||||
|
||||
/**
|
||||
* @brief The topic of the Stage instance (1-120 characters).
|
||||
*/
|
||||
std::string topic;
|
||||
|
||||
/**
|
||||
* @brief The privacy level of the Stage instance.
|
||||
*/
|
||||
stage_privacy_level privacy_level;
|
||||
|
||||
/**
|
||||
* @brief Whether or not Stage Discovery is disabled.
|
||||
*/
|
||||
bool discoverable_disabled;
|
||||
|
||||
/**
|
||||
* @brief Create a stage_instance object
|
||||
*/
|
||||
stage_instance();
|
||||
|
||||
/**
|
||||
* @brief Destroy the stage_instance object
|
||||
*/
|
||||
~stage_instance() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A group of stage instances
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, stage_instance> stage_instance_map;
|
||||
|
||||
}
|
||||
223
dpp/stringops.h
223
dpp/stringops.h
@ -1,223 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++ - A Lightweight C++ Library for Discord
|
||||
*
|
||||
* stringops.h taken from TriviaBot
|
||||
*
|
||||
* Copyright 2004 Craig Edwards <support@sporks.gg>
|
||||
*
|
||||
* Core based on Sporks, the Learning Discord Bot, Craig Edwards (c) 2019.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
#include <locale>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <charconv>
|
||||
|
||||
namespace dpp {
|
||||
/**
|
||||
* @brief Convert a string to lowercase using tolower()
|
||||
*
|
||||
* @tparam T type of string
|
||||
* @param s String to lowercase
|
||||
* @return std::basic_string<T> lowercased string
|
||||
*/
|
||||
template <typename T> std::basic_string<T> lowercase(const std::basic_string<T>& s)
|
||||
{
|
||||
std::basic_string<T> s2 = s;
|
||||
std::transform(s2.begin(), s2.end(), s2.begin(), tolower);
|
||||
return s2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a string to uppercase using toupper()
|
||||
*
|
||||
* @tparam T type of string
|
||||
* @param s String to uppercase
|
||||
* @return std::basic_string<T> uppercased string
|
||||
*/
|
||||
template <typename T> std::basic_string<T> uppercase(const std::basic_string<T>& s)
|
||||
{
|
||||
std::basic_string<T> s2 = s;
|
||||
std::transform(s2.begin(), s2.end(), s2.begin(), toupper);
|
||||
return s2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief trim from end of string (right)
|
||||
*
|
||||
* @param s String to trim
|
||||
* @return std::string trimmed string
|
||||
*/
|
||||
inline std::string rtrim(std::string s)
|
||||
{
|
||||
s.erase(s.find_last_not_of(" \t\n\r\f\v") + 1);
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief trim from beginning of string (left)
|
||||
*
|
||||
* @param s string to trim
|
||||
* @return std::string trimmed string
|
||||
*/
|
||||
inline std::string ltrim(std::string s)
|
||||
{
|
||||
s.erase(0, s.find_first_not_of(" \t\n\r\f\v"));
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Trim from both ends of string (right then left)
|
||||
*
|
||||
* @param s string to trim
|
||||
* @return std::string trimmed string
|
||||
*/
|
||||
inline std::string trim(std::string s)
|
||||
{
|
||||
return ltrim(rtrim(s));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add commas to a string (or dots) based on current locale server-side
|
||||
*
|
||||
* @tparam T type of numeric value
|
||||
* @param value Value
|
||||
* @return std::string number with commas added
|
||||
*/
|
||||
template<class T> std::string comma(T value)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale(""));
|
||||
ss << std::fixed << value;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert any value from a string to another type using stringstream.
|
||||
* The optional second parameter indicates the format of the input string,
|
||||
* e.g. std::dec for decimal, std::hex for hex, std::oct for octal.
|
||||
*
|
||||
* @tparam T Type to convert to
|
||||
* @param s String to convert from
|
||||
* @param f Numeric base, e.g. `std::dec` or `std::hex`
|
||||
* @return T Returned numeric value
|
||||
*/
|
||||
template <typename T> T from_string(const std::string &s, std::ios_base & (*f)(std::ios_base&))
|
||||
{
|
||||
T t;
|
||||
std::istringstream iss(s);
|
||||
iss >> f, iss >> t;
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert any value from a string to another type using stringstream.
|
||||
*
|
||||
* @tparam T Type to convert to
|
||||
* @param s String to convert from
|
||||
* @return T Returned numeric value
|
||||
*
|
||||
* @note Base 10 for numeric conversions.
|
||||
*/
|
||||
template <typename T> T from_string(const std::string &s)
|
||||
{
|
||||
if (s.empty()) {
|
||||
return static_cast<T>(0);
|
||||
}
|
||||
T t;
|
||||
std::istringstream iss(s);
|
||||
iss >> t;
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specialised conversion of uint64_t from string
|
||||
*
|
||||
* @tparam int64_t
|
||||
* @param s string to convert
|
||||
* @return uint64_t return value
|
||||
*/
|
||||
template <uint64_t> uint64_t from_string(const std::string &s)
|
||||
{
|
||||
return std::stoull(s, 0, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specialised conversion of uint32_t from string
|
||||
*
|
||||
* @tparam uint32_t
|
||||
* @param s string to convert
|
||||
* @return uint32_t return value
|
||||
*/
|
||||
template <uint32_t> uint32_t from_string(const std::string &s)
|
||||
{
|
||||
return (uint32_t) std::stoul(s, 0, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specialised conversion of int from string
|
||||
*
|
||||
* @tparam int
|
||||
* @param s string to convert
|
||||
* @return int return value
|
||||
*/
|
||||
template <int> int from_string(const std::string &s)
|
||||
{
|
||||
return std::stoi(s, 0, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a numeric value to hex
|
||||
*
|
||||
* @tparam T numeric type
|
||||
* @param i numeric value
|
||||
* @param leading_zeroes set to false if you don't want the leading zeroes in the output
|
||||
* @return std::string value in hex, the length will be 2* the raw size of the type
|
||||
*/
|
||||
template <typename T> std::string to_hex(T i, bool leading_zeroes = true)
|
||||
{
|
||||
char str[26] = { 0 };
|
||||
size_t size = sizeof(T) * 2;
|
||||
std::to_chars(std::begin(str), std::end(str), i, 16);
|
||||
std::string out{str};
|
||||
if (leading_zeroes && out.length() < size) {
|
||||
out.insert(out.begin(), size - out.length(), '0');
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Format a numeric type as a string with leading zeroes
|
||||
*
|
||||
* @tparam T numeric type
|
||||
* @param i numeric value
|
||||
* @param width width of type including the leading zeroes
|
||||
* @return std::string resultant string with leading zeroes
|
||||
*/
|
||||
template <typename T> std::string leading_zeroes(T i, size_t width)
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream.imbue(std::locale::classic());
|
||||
stream << std::setfill('0') << std::setw((int)width) << std::dec << i;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
}
|
||||
120
dpp/sysdep.h
120
dpp/sysdep.h
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Discord erlpack - tidied up for D++, Craig Edwards 2021.
|
||||
*
|
||||
* MessagePack system dependencies modified for erlpack.
|
||||
*
|
||||
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#if defined(__linux__)
|
||||
#include <endian.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* numeric_limits<T>::min,max */
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
#include <arpa/inet.h> /* __BYTE_ORDER */
|
||||
#endif
|
||||
|
||||
#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define __LITTLE_ENDIAN__
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define __BIG_ENDIAN__
|
||||
#elif _WIN32
|
||||
#define __LITTLE_ENDIAN__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
|
||||
#ifdef _WIN32
|
||||
# if defined(ntohs)
|
||||
# define etf_byte_order_16(x) ntohs(x)
|
||||
# elif defined(_byteswap_ushort) || (defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||
# define etf_byte_order_16(x) ((uint16_t)_byteswap_ushort((unsigned short)x))
|
||||
# else
|
||||
# define etf_byte_order_16(x) ( \
|
||||
((((uint16_t)x) << 8) ) | \
|
||||
((((uint16_t)x) >> 8) ) )
|
||||
# endif
|
||||
#else
|
||||
# define etf_byte_order_16(x) ntohs(x)
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# if defined(ntohl)
|
||||
# define etf_byte_order_32(x) ntohl(x)
|
||||
# elif defined(_byteswap_ulong) || (defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||
# define etf_byte_order_32(x) ((uint32_t)_byteswap_ulong((unsigned long)x))
|
||||
# else
|
||||
# define etf_byte_order_32(x) \
|
||||
( ((((uint32_t)x) << 24) ) | \
|
||||
((((uint32_t)x) << 8) & 0x00ff0000U ) | \
|
||||
((((uint32_t)x) >> 8) & 0x0000ff00U ) | \
|
||||
((((uint32_t)x) >> 24) ) )
|
||||
# endif
|
||||
#else
|
||||
# define etf_byte_order_32(x) ntohl(x)
|
||||
#endif
|
||||
|
||||
#if defined(_byteswap_uint64) || (defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||
# define etf_byte_order_64(x) (_byteswap_uint64(x))
|
||||
#elif defined(bswap_64)
|
||||
# define etf_byte_order_64(x) bswap_64(x)
|
||||
#elif defined(__DARWIN_OSSwapInt64)
|
||||
# define etf_byte_order_64(x) __DARWIN_OSSwapInt64(x)
|
||||
#elif defined(__linux__)
|
||||
# define etf_byte_order_64(x) be64toh(x)
|
||||
#else
|
||||
# define etf_byte_order_64(x) \
|
||||
( ((((uint64_t)x) << 56) ) | \
|
||||
((((uint64_t)x) << 40) & 0x00ff000000000000ULL ) | \
|
||||
((((uint64_t)x) << 24) & 0x0000ff0000000000ULL ) | \
|
||||
((((uint64_t)x) << 8) & 0x000000ff00000000ULL ) | \
|
||||
((((uint64_t)x) >> 8) & 0x00000000ff000000ULL ) | \
|
||||
((((uint64_t)x) >> 24) & 0x0000000000ff0000ULL ) | \
|
||||
((((uint64_t)x) >> 40) & 0x000000000000ff00ULL ) | \
|
||||
((((uint64_t)x) >> 56) ) )
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define etf_byte_order_16(x) (x)
|
||||
#define etf_byte_order_32(x) (x)
|
||||
#define etf_byte_order_64(x) (x)
|
||||
#endif
|
||||
|
||||
#define store_16_bits(to, num) \
|
||||
do { uint16_t val = etf_byte_order_16(num); memcpy(to, &val, 2); } while(0)
|
||||
#define store_32_bits(to, num) \
|
||||
do { uint32_t val = etf_byte_order_32(num); memcpy(to, &val, 4); } while(0)
|
||||
#define store_64_bits(to, num) \
|
||||
do { uint64_t val = etf_byte_order_64(num); memcpy(to, &val, 8); } while(0)
|
||||
236
dpp/thread.h
236
dpp/thread.h
@ -1,236 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/managed.h>
|
||||
#include <dpp/channel.h>
|
||||
#include <dpp/message.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief represents membership of a user with a thread
|
||||
*/
|
||||
struct DPP_EXPORT thread_member : public json_interface<thread_member> {
|
||||
protected:
|
||||
friend struct json_interface<thread_member>;
|
||||
|
||||
/**
|
||||
* @brief Read struct values from a json object
|
||||
* @param j json to read values from
|
||||
* @return A reference to self
|
||||
*/
|
||||
thread_member& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief ID of the thread member is part of.
|
||||
*/
|
||||
snowflake thread_id = {};
|
||||
|
||||
/**
|
||||
* @brief ID of the member.
|
||||
*/
|
||||
snowflake user_id = {};
|
||||
|
||||
/**
|
||||
* @brief The time when user last joined the thread.
|
||||
*/
|
||||
time_t joined = 0;
|
||||
|
||||
/**
|
||||
* @brief Any user-thread settings, currently only used for notifications.
|
||||
*/
|
||||
uint32_t flags = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A group of thread member objects. the key is the user_id of the dpp::thread_member
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, thread_member> thread_member_map;
|
||||
|
||||
/**
|
||||
* @brief metadata for threads
|
||||
*/
|
||||
struct DPP_EXPORT thread_metadata {
|
||||
/**
|
||||
* @brief Timestamp when the thread's archive status was last changed, used for calculating recent activity.
|
||||
*/
|
||||
time_t archive_timestamp;
|
||||
|
||||
/**
|
||||
* @brief The duration in minutes to automatically archive the thread after recent activity (60, 1440, 4320, 10080).
|
||||
*/
|
||||
uint16_t auto_archive_duration;
|
||||
|
||||
/**
|
||||
* @brief Whether a thread is archived
|
||||
*/
|
||||
bool archived;
|
||||
|
||||
/**
|
||||
* @brief Whether a thread is locked. When a thread is locked,
|
||||
* only users with `MANAGE_THREADS` can un-archive it.
|
||||
*/
|
||||
bool locked;
|
||||
|
||||
/**
|
||||
* @brief Whether non-moderators can add other non-moderators. Only for private threads.
|
||||
*/
|
||||
bool invitable;
|
||||
};
|
||||
|
||||
/** @brief A definition of a discord thread.
|
||||
* A thread is a superset of a channel. Not to be confused with `std::thread`!
|
||||
*/
|
||||
class DPP_EXPORT thread : public channel, public json_interface<thread> {
|
||||
protected:
|
||||
friend struct json_interface<thread>;
|
||||
|
||||
/** Read class values from json object
|
||||
* @param j A json object to read from
|
||||
* @return A reference to self
|
||||
*/
|
||||
thread& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Build json for this thread object
|
||||
*
|
||||
* @param with_id include the ID in the json
|
||||
* @return std::string JSON string
|
||||
*/
|
||||
json to_json_impl(bool with_id = false) const override;
|
||||
|
||||
public:
|
||||
using json_interface<thread>::fill_from_json;
|
||||
using json_interface<thread>::build_json;
|
||||
using json_interface<thread>::to_json;
|
||||
|
||||
/**
|
||||
* @brief Thread member of current user if joined to the thread.
|
||||
* Note this is only set by certain api calls otherwise contains default data
|
||||
*/
|
||||
thread_member member = {};
|
||||
|
||||
/**
|
||||
* @brief Thread metadata (threads)
|
||||
*/
|
||||
thread_metadata metadata = {};
|
||||
|
||||
/**
|
||||
* @brief Created message. Only filled within the cluster::thread_create_in_forum() method
|
||||
*/
|
||||
message msg = {};
|
||||
|
||||
/**
|
||||
* @brief A list of dpp::forum_tag IDs that have been applied to a thread in a forum or media channel.
|
||||
*/
|
||||
std::vector<snowflake> applied_tags = {};
|
||||
|
||||
/**
|
||||
* @brief Number of messages ever sent in the thread.
|
||||
* It's similar to thread::message_count on message creation, but will not decrement the number when a message is deleted
|
||||
*/
|
||||
uint32_t total_messages_sent = 0;
|
||||
|
||||
/**
|
||||
* @brief Number of messages (not including the initial message or deleted messages) of the thread.
|
||||
* For threads created before July 1, 2022, the message count is inaccurate when it's greater than 50.
|
||||
*/
|
||||
uint8_t message_count = 0;
|
||||
|
||||
/**
|
||||
* @brief Approximate count of members in a thread (stops counting at 50)
|
||||
*/
|
||||
uint8_t member_count = 0;
|
||||
|
||||
/**
|
||||
* @brief Was this thread newly created?
|
||||
* @note This will only show in dpp::cluster::on_thread_create if the thread was just made.
|
||||
*/
|
||||
bool newly_created{false};
|
||||
|
||||
/**
|
||||
* @brief Returns true if the thread is within an announcement channel
|
||||
*
|
||||
* @return true if announcement thread
|
||||
*/
|
||||
constexpr bool is_news_thread() const noexcept {
|
||||
return (flags & channel::CHANNEL_TYPE_MASK) == CHANNEL_ANNOUNCEMENT_THREAD;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the channel is a public thread
|
||||
*
|
||||
* @return true if public thread
|
||||
*/
|
||||
constexpr bool is_public_thread() const noexcept {
|
||||
return (flags & channel::CHANNEL_TYPE_MASK) == CHANNEL_PUBLIC_THREAD;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the channel is a private thread
|
||||
*
|
||||
* @return true if private thread
|
||||
*/
|
||||
constexpr bool is_private_thread() const noexcept {
|
||||
return (flags & channel::CHANNEL_TYPE_MASK) == CHANNEL_PRIVATE_THREAD;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Serialize a thread_metadata object to json
|
||||
*
|
||||
* @param j JSON object to serialize to
|
||||
* @param tmdata object to serialize
|
||||
*/
|
||||
void to_json(nlohmann::json& j, const thread_metadata& tmdata);
|
||||
|
||||
/**
|
||||
* @brief A group of threads
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, thread> thread_map;
|
||||
|
||||
/**
|
||||
* @brief A thread alongside the bot's optional thread_member object tied to it
|
||||
*/
|
||||
struct active_thread_info {
|
||||
/**
|
||||
* @brief The thread object
|
||||
*/
|
||||
thread active_thread;
|
||||
|
||||
/**
|
||||
* @brief The bot as a thread member, only present if the bot is in the thread
|
||||
*/
|
||||
std::optional<thread_member> bot_member;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A map of threads alongside optionally the thread_member tied to the bot if it is in the thread. The map's key is the thread id. Returned from the cluster::threads_get_active method
|
||||
*/
|
||||
using active_threads = std::map<snowflake, active_thread_info>;
|
||||
|
||||
}
|
||||
@ -1,117 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <thread>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <functional>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief A work unit is a lambda executed in the thread pool
|
||||
*/
|
||||
using work_unit = std::function<void()>;
|
||||
|
||||
/**
|
||||
* @brief A task within a thread pool. A simple lambda that accepts no parameters and returns void.
|
||||
*/
|
||||
struct DPP_EXPORT thread_pool_task {
|
||||
/**
|
||||
* @brief Task priority, lower value is higher priority
|
||||
*/
|
||||
int priority;
|
||||
/**
|
||||
* @brief Work unit to execute as the task
|
||||
*/
|
||||
work_unit function;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Compares two thread pool tasks by priority
|
||||
*/
|
||||
struct DPP_EXPORT thread_pool_task_comparator {
|
||||
/**
|
||||
* @brief Compare two tasks
|
||||
* @param a first task
|
||||
* @param b second task
|
||||
* @return true if a > b
|
||||
*/
|
||||
bool operator()(const thread_pool_task &a, const thread_pool_task &b) const {
|
||||
return a.priority > b.priority;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A thread pool contains 1 or more worker threads which accept thread_pool_task lambadas
|
||||
* into a queue, which is processed in-order by whichever thread is free.
|
||||
*/
|
||||
struct DPP_EXPORT thread_pool {
|
||||
|
||||
/**
|
||||
* @brief Threads that comprise the thread pool
|
||||
*/
|
||||
std::vector<std::thread> threads;
|
||||
|
||||
/**
|
||||
* @brief Priority queue of tasks to be executed
|
||||
*/
|
||||
std::priority_queue<thread_pool_task, std::vector<thread_pool_task>, thread_pool_task_comparator> tasks;
|
||||
|
||||
/**
|
||||
* @brief Mutex for accessing the priority queue
|
||||
*/
|
||||
std::mutex queue_mutex;
|
||||
|
||||
/**
|
||||
* @brief Condition variable to notify for new tasks to run
|
||||
*/
|
||||
std::condition_variable cv;
|
||||
|
||||
/**
|
||||
* @brief True if the thread pool is due to stop
|
||||
*/
|
||||
bool stop{false};
|
||||
|
||||
/**
|
||||
* @brief Create a new priority thread pool
|
||||
* @param creator creating cluster (for logging)
|
||||
* @param num_threads number of threads in the pool
|
||||
*/
|
||||
explicit thread_pool(class cluster* creator, size_t num_threads = std::thread::hardware_concurrency());
|
||||
|
||||
/**
|
||||
* @brief Destroy the thread pool
|
||||
*/
|
||||
~thread_pool();
|
||||
|
||||
/**
|
||||
* @brief Enqueue a new task to the thread pool
|
||||
* @param task task to enqueue
|
||||
*/
|
||||
void enqueue(thread_pool_task task);
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,105 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/cluster.h>
|
||||
#include <time.h>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief A timed_listener is a way to temporarily attach to an event for a specific timeframe, then detach when complete.
|
||||
* A lambda may also be optionally called when the timeout is reached. Destructing the timed_listener detaches any attached
|
||||
* event listeners, and cancels any created timers, but does not call any timeout lambda.
|
||||
*
|
||||
* @tparam attached_event Event within cluster to attach to within the cluster::dispatch member (dpp::dispatcher object)
|
||||
* @tparam listening_function Definition of lambda function that matches up with the attached_event.
|
||||
*/
|
||||
template <typename attached_event, class listening_function> class timed_listener
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* @brief Owning cluster.
|
||||
*/
|
||||
cluster* owner;
|
||||
|
||||
/**
|
||||
* @brief Duration of listen.
|
||||
*/
|
||||
time_t duration;
|
||||
|
||||
/**
|
||||
* @brief Reference to attached event in cluster.
|
||||
*/
|
||||
//event_router_t<thread_member_update_t> on_thread_member_update;
|
||||
attached_event& ev;
|
||||
|
||||
/**
|
||||
* @brief Timer handle.
|
||||
*/
|
||||
timer th;
|
||||
|
||||
/**
|
||||
* @brief Event handle.
|
||||
*/
|
||||
event_handle listener_handle;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new timed listener object
|
||||
*
|
||||
* @param cl Owning cluster
|
||||
* @param _duration Duration of timed event in seconds
|
||||
* @param event Event to hook, e.g. cluster.on_message_create
|
||||
* @param on_end An optional void() lambda to trigger when the timed_listener times out.
|
||||
* Calling the destructor before the timeout is reached does not call this lambda.
|
||||
* @param listener Lambda to receive events. Type must match up properly with that passed into the 'event' parameter.
|
||||
*/
|
||||
timed_listener(cluster* cl, uint64_t _duration, attached_event& event, listening_function listener, timer_callback_t on_end = {})
|
||||
: owner(cl), duration(_duration), ev(event)
|
||||
{
|
||||
/* Attach event */
|
||||
listener_handle = ev(listener);
|
||||
/* Create timer */
|
||||
th = cl->start_timer([this]([[maybe_unused]] dpp::timer timer_handle) {
|
||||
/* Timer has finished, detach it from event.
|
||||
* Only allowed to tick once.
|
||||
*/
|
||||
ev.detach(listener_handle);
|
||||
owner->stop_timer(th);
|
||||
}, duration, on_end);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroy the timed listener object
|
||||
*/
|
||||
~timed_listener() {
|
||||
/* Stop timer and detach event, but do not call on_end */
|
||||
ev.detach(listener_handle);
|
||||
owner->stop_timer(th);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
150
dpp/timer.h
150
dpp/timer.h
@ -1,150 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <cstddef>
|
||||
#include <ctime>
|
||||
#include <set>
|
||||
#include <queue>
|
||||
#include <functional>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Represents a timer handle.
|
||||
* Returned from cluster::start_timer and used by cluster::stop_timer.
|
||||
* This is obtained from a simple incrementing value, internally.
|
||||
*/
|
||||
typedef size_t timer;
|
||||
|
||||
/**
|
||||
* @brief The type for a timer callback
|
||||
*/
|
||||
typedef std::function<void(timer)> timer_callback_t;
|
||||
|
||||
/**
|
||||
* @brief Used internally to store state of active timers
|
||||
*/
|
||||
struct DPP_EXPORT timer_t {
|
||||
/**
|
||||
* @brief Timer handle
|
||||
*/
|
||||
timer handle{0};
|
||||
|
||||
/**
|
||||
* @brief Next timer tick as unix epoch
|
||||
*/
|
||||
time_t next_tick{0};
|
||||
|
||||
/**
|
||||
* @brief Frequency between ticks
|
||||
*/
|
||||
uint64_t frequency{0};
|
||||
|
||||
/**
|
||||
* @brief Lambda to call on tick
|
||||
*/
|
||||
timer_callback_t on_tick{};
|
||||
|
||||
/**
|
||||
* @brief Lambda to call on stop (optional)
|
||||
*/
|
||||
timer_callback_t on_stop{};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Used to compare two timers next tick times in a priority queue
|
||||
*/
|
||||
struct DPP_EXPORT timer_comparator {
|
||||
/**
|
||||
* @brief Compare two timers
|
||||
* @param a first timer
|
||||
* @param b second timer
|
||||
* @return returns true if a > b
|
||||
*/
|
||||
bool operator()(const timer_t &a, const timer_t &b) const {
|
||||
return a.next_tick > b.next_tick;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief A priority timers, ordered by earliest first so that the head is always the
|
||||
* soonest to be due.
|
||||
*/
|
||||
typedef std::priority_queue<timer_t, std::vector<timer_t>, timer_comparator> timer_next_t;
|
||||
|
||||
/**
|
||||
* @brief A set of deleted timer handles
|
||||
*/
|
||||
typedef std::set<timer> timers_deleted_t;
|
||||
|
||||
/**
|
||||
* @brief Trigger a timed event once.
|
||||
* The provided callback is called only once.
|
||||
*/
|
||||
class DPP_EXPORT oneshot_timer
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* @brief Owning cluster.
|
||||
*/
|
||||
class cluster* owner;
|
||||
|
||||
/**
|
||||
* @brief Timer handle.
|
||||
*/
|
||||
timer th;
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new oneshot timer object
|
||||
*
|
||||
* @param cl cluster owner
|
||||
* @param duration duration before firing
|
||||
* @param callback callback to call on firing
|
||||
*/
|
||||
oneshot_timer(class cluster* cl, uint64_t duration, timer_callback_t callback);
|
||||
|
||||
/**
|
||||
* @brief Get the handle for the created one-shot timer
|
||||
*
|
||||
* @return timer handle for use with stop_timer
|
||||
*/
|
||||
timer get_handle();
|
||||
|
||||
/**
|
||||
* @brief Cancel the one shot timer immediately.
|
||||
* Callback function is not called.
|
||||
*/
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* @brief Destroy the oneshot timer object
|
||||
*/
|
||||
~oneshot_timer();
|
||||
};
|
||||
|
||||
}
|
||||
5739
dpp/unicode_emoji.h
5739
dpp/unicode_emoji.h
File diff suppressed because it is too large
Load Diff
584
dpp/user.h
584
dpp/user.h
@ -1,584 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/managed.h>
|
||||
#include <dpp/utility.h>
|
||||
#include <dpp/json_interface.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
constexpr uint32_t MAX_AVATAR_SIZE = 10240 * 1000; // 10240KB.
|
||||
|
||||
/**
|
||||
* @brief Various bitmask flags used to represent information about a dpp::user
|
||||
*/
|
||||
enum user_flags : uint32_t {
|
||||
/**
|
||||
* @brief User is a bot.
|
||||
*/
|
||||
u_bot = 0b00000000000000000000000000000001,
|
||||
|
||||
/**
|
||||
* @brief User is a system user (Clyde!).
|
||||
*/
|
||||
u_system = 0b00000000000000000000000000000010,
|
||||
|
||||
/**
|
||||
* @brief User has multi-factor authentication enabled.
|
||||
*/
|
||||
u_mfa_enabled = 0b00000000000000000000000000000100,
|
||||
|
||||
/**
|
||||
* @brief User is verified (verified email address).
|
||||
*/
|
||||
u_verified = 0b00000000000000000000000000001000,
|
||||
|
||||
/**
|
||||
* @brief User has full nitro.
|
||||
*/
|
||||
u_nitro_full = 0b00000000000000000000000000010000,
|
||||
|
||||
/**
|
||||
* @brief User has nitro classic.
|
||||
*/
|
||||
u_nitro_classic = 0b00000000000000000000000000100000,
|
||||
|
||||
/**
|
||||
* @brief User is discord staff.
|
||||
*/
|
||||
u_discord_employee = 0b00000000000000000000000001000000,
|
||||
|
||||
/**
|
||||
* @brief User owns a partnered server.
|
||||
*/
|
||||
u_partnered_owner = 0b00000000000000000000000010000000,
|
||||
|
||||
/**
|
||||
* @brief User is a member of hypesquad events.
|
||||
*/
|
||||
u_hypesquad_events = 0b00000000000000000000000100000000,
|
||||
|
||||
/**
|
||||
* @brief User has BugHunter level 1.
|
||||
*/
|
||||
u_bughunter_1 = 0b00000000000000000000001000000000,
|
||||
|
||||
/**
|
||||
* @brief User is a member of House Bravery.
|
||||
*/
|
||||
u_house_bravery = 0b00000000000000000000010000000000,
|
||||
|
||||
/**
|
||||
* @brief User is a member of House Brilliance.
|
||||
*/
|
||||
u_house_brilliance = 0b00000000000000000000100000000000,
|
||||
|
||||
/**
|
||||
* @brief User is a member of House Balance.
|
||||
*/
|
||||
u_house_balance = 0b00000000000000000001000000000000,
|
||||
|
||||
/**
|
||||
* @brief User is an early supporter.
|
||||
*/
|
||||
u_early_supporter = 0b00000000000000000010000000000000,
|
||||
|
||||
/**
|
||||
* @brief User is a team user.
|
||||
*/
|
||||
u_team_user = 0b00000000000000000100000000000000,
|
||||
|
||||
/**
|
||||
* @brief User is has Bug Hunter level 2.
|
||||
*/
|
||||
u_bughunter_2 = 0b00000000000000001000000000000000,
|
||||
|
||||
/**
|
||||
* @brief User is a verified bot.
|
||||
*/
|
||||
u_verified_bot = 0b00000000000000010000000000000000,
|
||||
|
||||
/**
|
||||
* @brief User has the Early Verified Bot Developer badge.
|
||||
*/
|
||||
u_verified_bot_dev = 0b00000000000000100000000000000000,
|
||||
|
||||
/**
|
||||
* @brief User's icon is animated.
|
||||
*/
|
||||
u_animated_icon = 0b00000000000001000000000000000000,
|
||||
|
||||
/**
|
||||
* @brief User is a certified moderator.
|
||||
*/
|
||||
u_certified_moderator = 0b00000000000010000000000000000000,
|
||||
|
||||
/**
|
||||
* @brief User is a bot using HTTP interactions.
|
||||
*
|
||||
* @note shows online even when not connected to a websocket.
|
||||
*/
|
||||
u_bot_http_interactions = 0b00000000000100000000000000000000,
|
||||
|
||||
/**
|
||||
* @brief User has nitro basic.
|
||||
*/
|
||||
u_nitro_basic = 0b00000000001000000000000000000000,
|
||||
|
||||
/**
|
||||
* @brief User has the active developer badge.
|
||||
*/
|
||||
u_active_developer = 0b00000000010000000000000000000000,
|
||||
|
||||
/**
|
||||
* @brief User's banner is animated.
|
||||
*/
|
||||
u_animated_banner = 0b00000000100000000000000000000000,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a user on discord. May or may not be a member of a dpp::guild.
|
||||
*/
|
||||
class DPP_EXPORT user : public managed, public json_interface<user> {
|
||||
protected:
|
||||
friend struct json_interface<user>;
|
||||
|
||||
/** Fill this record from json.
|
||||
* @param j The json to fill this record from
|
||||
* @return Reference to self
|
||||
*/
|
||||
user& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Convert to JSON
|
||||
*
|
||||
* @param with_id include ID in output
|
||||
* @return json JSON output
|
||||
*/
|
||||
virtual json to_json_impl(bool with_id = true) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Discord username.
|
||||
*/
|
||||
std::string username;
|
||||
|
||||
/**
|
||||
* @brief Global display name.
|
||||
*/
|
||||
std::string global_name;
|
||||
|
||||
/**
|
||||
* @brief Avatar hash.
|
||||
*/
|
||||
utility::iconhash avatar;
|
||||
|
||||
/**
|
||||
* @brief Avatar decoration hash.
|
||||
*/
|
||||
utility::iconhash avatar_decoration;
|
||||
|
||||
/**
|
||||
* @brief Flags built from a bitmask of values in dpp::user_flags.
|
||||
*/
|
||||
uint32_t flags;
|
||||
|
||||
/**
|
||||
* @brief Discriminator (aka tag), 4 digits usually displayed with leading zeroes.
|
||||
*
|
||||
* @note To print the discriminator with leading zeroes, use format_username().
|
||||
* 0 for users that have migrated to the new username format.
|
||||
*/
|
||||
uint16_t discriminator;
|
||||
|
||||
/**
|
||||
* @brief Reference count of how many guilds this user is in.
|
||||
*/
|
||||
uint8_t refcount;
|
||||
|
||||
/**
|
||||
* @brief Construct a new user object
|
||||
*/
|
||||
user();
|
||||
|
||||
/**
|
||||
* @brief Destroy the user object
|
||||
*/
|
||||
virtual ~user() = default;
|
||||
|
||||
/**
|
||||
* @brief Create a mentionable user.
|
||||
* @param id The ID of the user.
|
||||
* @return std::string The formatted mention of the user.
|
||||
*/
|
||||
static std::string get_mention(const snowflake& id);
|
||||
|
||||
/**
|
||||
* @brief Get the avatar url of the user
|
||||
*
|
||||
* @note If the user doesn't have an avatar, the default user avatar url is returned which is always in `png` format!
|
||||
*
|
||||
* @param size The size of the avatar in pixels. It can be any power of two between 16 and 4096,
|
||||
* otherwise the default sized avatar is returned.
|
||||
* @param format The format to use for the avatar. It can be one of `i_webp`, `i_jpg`, `i_png` or `i_gif`.
|
||||
* When passing `i_gif`, it returns an empty string for non-animated images. Consider using the `prefer_animated` parameter instead.
|
||||
* @param prefer_animated Whether you prefer gif format.
|
||||
* If true, it'll return gif format whenever the image is available as animated.
|
||||
* @return std::string avatar url or an empty string, if required attributes are missing or an invalid format was passed
|
||||
*/
|
||||
std::string get_avatar_url(uint16_t size = 0, const image_type format = i_png, bool prefer_animated = true) const;
|
||||
|
||||
/**
|
||||
* @brief Get the default avatar url of the user. This is calculated by the discriminator.
|
||||
*
|
||||
* @return std::string avatar url or an empty string, if the discriminator is empty
|
||||
*/
|
||||
std::string get_default_avatar_url() const;
|
||||
|
||||
/**
|
||||
* @brief Get the avatar decoration url of the user if they have one, otherwise returns an empty string.
|
||||
*
|
||||
* @param size The size of the avatar decoration in pixels. It can be any power of two between 16 and 4096,
|
||||
* otherwise the default sized avatar decoration is returned.
|
||||
* @return std::string avatar url or an empty string
|
||||
*/
|
||||
std::string get_avatar_decoration_url(uint16_t size = 0) const;
|
||||
|
||||
/**
|
||||
* @brief Return a ping/mention for the user
|
||||
*
|
||||
* @return std::string mention
|
||||
*/
|
||||
std::string get_mention() const;
|
||||
|
||||
/**
|
||||
* @brief Returns URL to user
|
||||
*
|
||||
* @return string of URL to user
|
||||
*/
|
||||
std::string get_url() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user has the active Developer badge
|
||||
*
|
||||
* @return true if has active developer
|
||||
*/
|
||||
bool is_active_developer() const;
|
||||
|
||||
/**
|
||||
* @brief User is a bot
|
||||
*
|
||||
* @return True if the user is a bot
|
||||
*/
|
||||
bool is_bot() const;
|
||||
|
||||
/**
|
||||
* @brief User is a system user (Clyde)
|
||||
*
|
||||
* @return true if user is a system user
|
||||
*/
|
||||
bool is_system() const;
|
||||
|
||||
/**
|
||||
* @brief User has multi-factor authentication enabled
|
||||
*
|
||||
* @return true if multi-factor is enabled
|
||||
*/
|
||||
bool is_mfa_enabled() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user has verified account
|
||||
*
|
||||
* @return true if verified
|
||||
*/
|
||||
bool is_verified() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user has full nitro.
|
||||
* This is mutually exclusive with full nitro.
|
||||
*
|
||||
* @return true if user has full nitro
|
||||
*/
|
||||
bool has_nitro_full() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user has nitro classic.
|
||||
* This is mutually exclusive with nitro classic.
|
||||
*
|
||||
* @return true if user has nitro classic
|
||||
*/
|
||||
bool has_nitro_classic() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user has nitro basic.
|
||||
* This is mutually exclusive with nitro basic.
|
||||
*
|
||||
* @return true if user has nitro basic
|
||||
*/
|
||||
bool has_nitro_basic() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user is a discord employee
|
||||
*
|
||||
* @return true if user is discord staff
|
||||
*/
|
||||
bool is_discord_employee() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user owns a partnered server
|
||||
*
|
||||
* @return true if user has partnered server
|
||||
*/
|
||||
bool is_partnered_owner() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user has hypesquad events
|
||||
*
|
||||
* @return true if has hypesquad events
|
||||
*/
|
||||
bool has_hypesquad_events() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user has the bughunter level 1 badge
|
||||
*
|
||||
* @return true if has bughunter level 1
|
||||
*/
|
||||
bool is_bughunter_1() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user is in house bravery
|
||||
*
|
||||
* @return true if in house bravery
|
||||
*/
|
||||
bool is_house_bravery() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user is in house brilliance
|
||||
*
|
||||
* @return true if in house brilliance
|
||||
*/
|
||||
bool is_house_brilliance() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user is in house balance
|
||||
*
|
||||
* @return true if in house brilliance
|
||||
*/
|
||||
bool is_house_balance() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user is an early supporter
|
||||
*
|
||||
* @return true if early supporter
|
||||
*/
|
||||
bool is_early_supporter() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user is a team user
|
||||
*
|
||||
* @return true if a team user
|
||||
*/
|
||||
bool is_team_user() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user has the bughunter level 2 badge
|
||||
*
|
||||
* @return true if has bughunter level 2
|
||||
*/
|
||||
bool is_bughunter_2() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user has the verified bot badge
|
||||
*
|
||||
* @return true if verified bot
|
||||
*/
|
||||
bool is_verified_bot() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user is an early verified bot developer
|
||||
*
|
||||
* @return true if verified bot developer
|
||||
*/
|
||||
bool is_verified_bot_dev() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user is a certified moderator
|
||||
*
|
||||
* @return true if certified moderator
|
||||
*/
|
||||
bool is_certified_moderator() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user is a bot which exclusively uses HTTP interactions.
|
||||
* Bots using HTTP interactions are always considered online even when not connected to a websocket.
|
||||
*
|
||||
* @return true if is a http interactions only bot
|
||||
*/
|
||||
bool is_bot_http_interactions() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user has an animated icon
|
||||
*
|
||||
* @return true if icon is animated (gif)
|
||||
*/
|
||||
bool has_animated_icon() const;
|
||||
|
||||
/**
|
||||
* @brief Format a username into user\#discriminator
|
||||
*
|
||||
* For example Brain#0001
|
||||
*
|
||||
* @note This will, most often, return something like Brain#0000 due to discriminators slowly being removed.
|
||||
* Some accounts, along with most bots, still have discriminators, so they will still show as Bot#1234.
|
||||
*
|
||||
* @return Formatted username and discriminator
|
||||
*/
|
||||
std::string format_username() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A user with additional fields only available via the oauth2 identify scope.
|
||||
* These are not included in dpp::user as additional scopes are needed to fetch them
|
||||
* which bots do not normally have.
|
||||
*/
|
||||
class DPP_EXPORT user_identified : public user, public json_interface<user_identified> {
|
||||
protected:
|
||||
friend struct json_interface<user_identified>;
|
||||
|
||||
/** Fill this record from json.
|
||||
* @param j The json to fill this record from
|
||||
* @return Reference to self
|
||||
*/
|
||||
user_identified& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Convert to JSON
|
||||
*
|
||||
* @param with_id include ID in output
|
||||
* @return json JSON output
|
||||
*/
|
||||
virtual json to_json_impl(bool with_id = true) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Optional: The user's chosen language option identify.
|
||||
*/
|
||||
std::string locale;
|
||||
|
||||
/**
|
||||
* @brief Optional: The user's email.
|
||||
*
|
||||
* @note This may be empty.
|
||||
*/
|
||||
std::string email;
|
||||
|
||||
/**
|
||||
* @brief Optional: The user's banner hash identify.
|
||||
*
|
||||
* @note This may be empty.
|
||||
*/
|
||||
utility::iconhash banner;
|
||||
|
||||
/**
|
||||
* @brief Optional: The user's banner color encoded as an integer representation of hexadecimal color code identify.
|
||||
*
|
||||
* @note This may be empty.
|
||||
*/
|
||||
uint32_t accent_color;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Optional: Whether the email on this account has been verified email.
|
||||
*/
|
||||
bool verified;
|
||||
|
||||
/**
|
||||
* @brief Construct a new user identified object
|
||||
*/
|
||||
user_identified();
|
||||
|
||||
/**
|
||||
* @brief Construct a new user identified object from a user object
|
||||
*
|
||||
* @param u user object
|
||||
*/
|
||||
user_identified(const user& u);
|
||||
|
||||
/**
|
||||
* @brief Destroy the user identified object
|
||||
*/
|
||||
virtual ~user_identified() = default;
|
||||
|
||||
using json_interface<user_identified>::fill_from_json;
|
||||
using json_interface<user_identified>::build_json;
|
||||
using json_interface<user_identified>::to_json;
|
||||
|
||||
/**
|
||||
* @brief Return true if user has an animated banner
|
||||
*
|
||||
* @return true if banner is animated (gif)
|
||||
*/
|
||||
bool has_animated_banner() const;
|
||||
|
||||
/**
|
||||
* @brief Get the user identified's banner url if they have one, otherwise returns an empty string
|
||||
*
|
||||
* @param size The size of the banner in pixels. It can be any power of two between 16 and 4096,
|
||||
* otherwise the default sized banner is returned.
|
||||
* @param format The format to use for the avatar. It can be one of `i_webp`, `i_jpg`, `i_png` or `i_gif`.
|
||||
* When passing `i_gif`, it returns an empty string for non-animated images. Consider using the `prefer_animated` parameter instead.
|
||||
* @param prefer_animated Whether you prefer gif format.
|
||||
* If true, it'll return gif format whenever the image is available as animated.
|
||||
* @return std::string banner url or an empty string, if required attributes are missing or an invalid format was passed
|
||||
*/
|
||||
std::string get_banner_url(uint16_t size = 0, const image_type format = i_png, bool prefer_animated = true) const;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief helper function to deserialize a user from json
|
||||
*
|
||||
* @see https://github.com/nlohmann/json#arbitrary-types-conversions
|
||||
*
|
||||
* @param j output json object
|
||||
* @param u user to be deserialized
|
||||
*/
|
||||
void from_json(const nlohmann::json& j, user& u);
|
||||
|
||||
/**
|
||||
* @brief helper function to deserialize a user_identified from json
|
||||
*
|
||||
* @see https://github.com/nlohmann/json#arbitrary-types-conversions
|
||||
*
|
||||
* @param j output json object
|
||||
* @param u user to be deserialized
|
||||
*/
|
||||
void from_json(const nlohmann::json& j, user_identified& u);
|
||||
|
||||
/**
|
||||
* @brief A group of users.
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, user> user_map;
|
||||
|
||||
}
|
||||
1069
dpp/utility.h
1069
dpp/utility.h
File diff suppressed because it is too large
Load Diff
@ -1,32 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#ifndef DPP_VERSION_LONG
|
||||
#define DPP_VERSION_LONG 0x00100104
|
||||
#define DPP_VERSION_SHORT 100104
|
||||
#define DPP_VERSION_TEXT "D++ 10.1.4 (07-Jul-2025)"
|
||||
|
||||
#define DPP_VERSION_MAJOR ((DPP_VERSION_LONG & 0x00ff0000) >> 16)
|
||||
#define DPP_VERSION_MINOR ((DPP_VERSION_LONG & 0x0000ff00) >> 8)
|
||||
#define DPP_VERSION_PATCH (DPP_VERSION_LONG & 0x000000ff)
|
||||
#endif
|
||||
@ -1,126 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <unordered_map>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/json_interface.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Flags related to a voice region
|
||||
*/
|
||||
enum voiceregion_flags {
|
||||
/**
|
||||
* @brief The closest (optimal) voice region.
|
||||
*/
|
||||
v_optimal = 0x00000001,
|
||||
|
||||
/**
|
||||
* @brief A Deprecated voice region (avoid switching to these).
|
||||
*/
|
||||
v_deprecated = 0x00000010,
|
||||
|
||||
/**
|
||||
* @brief A custom voice region (used for events/etc).
|
||||
*/
|
||||
v_custom = 0x00000100
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a voice region on discord
|
||||
*/
|
||||
class DPP_EXPORT voiceregion : public json_interface<voiceregion> {
|
||||
protected:
|
||||
friend struct json_interface<voiceregion>;
|
||||
|
||||
/**
|
||||
* @brief Fill object properties from JSON
|
||||
*
|
||||
* @param j JSON to fill from
|
||||
* @return voiceregion& Reference to self
|
||||
*/
|
||||
voiceregion& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Build a json for this object
|
||||
*
|
||||
* @param with_id Add ID to output
|
||||
* @return json JSON string
|
||||
*/
|
||||
virtual json to_json_impl(bool with_id = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Voice server ID
|
||||
*/
|
||||
std::string id;
|
||||
|
||||
/**
|
||||
* @brief Voice server name
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* @brief Flags bitmap
|
||||
*/
|
||||
uint8_t flags;
|
||||
|
||||
/**
|
||||
* @brief Construct a new voiceregion object
|
||||
*/
|
||||
voiceregion();
|
||||
|
||||
/**
|
||||
* @brief Destroy the voiceregion object
|
||||
*/
|
||||
virtual ~voiceregion() = default;
|
||||
|
||||
/**
|
||||
* @brief True if is the optimal voice server
|
||||
*
|
||||
* @return true if optimal
|
||||
*/
|
||||
bool is_optimal() const;
|
||||
|
||||
/**
|
||||
* @brief True if is a deprecated voice server
|
||||
*
|
||||
* @return true if deprecated
|
||||
*/
|
||||
bool is_deprecated() const;
|
||||
|
||||
/**
|
||||
* @brief True if is a custom voice server
|
||||
*
|
||||
* @return true if custom
|
||||
*/
|
||||
bool is_custom() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A group of voice regions
|
||||
*/
|
||||
typedef std::unordered_map<std::string, voiceregion> voiceregion_map;
|
||||
|
||||
}
|
||||
179
dpp/voicestate.h
179
dpp/voicestate.h
@ -1,179 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <unordered_map>
|
||||
#include <dpp/json_interface.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Bit mask flags relating to voice states
|
||||
*/
|
||||
enum voicestate_flags {
|
||||
/**
|
||||
* @brief Deafened by the server.
|
||||
*/
|
||||
vs_deaf = 0b00000001,
|
||||
|
||||
/**
|
||||
* @brief Muted by the server.
|
||||
*/
|
||||
vs_mute = 0b00000010,
|
||||
|
||||
/**
|
||||
* @brief Locally Muted.
|
||||
*/
|
||||
vs_self_mute = 0b00000100,
|
||||
|
||||
/**
|
||||
* @brief Locally deafened.
|
||||
*/
|
||||
vs_self_deaf = 0b00001000,
|
||||
|
||||
/**
|
||||
* @brief Whether this user is streaming using "Go Live".
|
||||
*/
|
||||
vs_self_stream = 0b00010000,
|
||||
|
||||
/**
|
||||
* @brief Whether this user's camera is enabled.
|
||||
*/
|
||||
vs_self_video = 0b00100000,
|
||||
|
||||
/**
|
||||
* @brief Whether this user's permission to speak is denied.
|
||||
*/
|
||||
vs_suppress = 0b01000000
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents the voice state of a user on a guild
|
||||
* These are stored in the dpp::guild object, and accessible there,
|
||||
* or via dpp::channel::get_voice_members
|
||||
*/
|
||||
class DPP_EXPORT voicestate : public json_interface<voicestate> {
|
||||
protected:
|
||||
friend struct json_interface<voicestate>;
|
||||
|
||||
/**
|
||||
* @brief Fill voicestate object from json data
|
||||
*
|
||||
* @param j JSON data to fill from
|
||||
* @return voicestate& Reference to self
|
||||
*/
|
||||
voicestate& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Owning shard.
|
||||
*/
|
||||
int32_t shard_id{0};
|
||||
|
||||
/**
|
||||
* @brief Optional: The guild id this voice state is for.
|
||||
*/
|
||||
snowflake guild_id{0};
|
||||
|
||||
/**
|
||||
* @brief The channel id this user is connected to.
|
||||
*
|
||||
* @note This may be empty.
|
||||
*/
|
||||
snowflake channel_id{0};
|
||||
|
||||
/**
|
||||
* @brief The user id this voice state is for.
|
||||
*/
|
||||
snowflake user_id{0};
|
||||
|
||||
/**
|
||||
* @brief The session id for this voice state.
|
||||
*/
|
||||
std::string session_id;
|
||||
|
||||
/**
|
||||
* @brief Voice state flags from dpp::voicestate_flags.
|
||||
*/
|
||||
uint8_t flags{0};
|
||||
|
||||
/**
|
||||
* @brief The time at which the user requested to speak.
|
||||
*
|
||||
* @note If the user never requested to speak, this is 0.
|
||||
*/
|
||||
time_t request_to_speak{0};
|
||||
|
||||
/**
|
||||
* @brief Construct a new voicestate object
|
||||
*/
|
||||
voicestate();
|
||||
|
||||
/**
|
||||
* @brief Destroy the voicestate object
|
||||
*/
|
||||
virtual ~voicestate() = default;
|
||||
|
||||
/**
|
||||
* @brief Return true if the user is deafened by the server.
|
||||
*/
|
||||
bool is_deaf() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if the user is muted by the server.
|
||||
*/
|
||||
bool is_mute() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user muted themselves.
|
||||
*/
|
||||
bool is_self_mute() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user deafened themselves.
|
||||
*/
|
||||
bool is_self_deaf() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if the user is streaming using "Go Live".
|
||||
*/
|
||||
bool self_stream() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if the user's camera is enabled.
|
||||
*/
|
||||
bool self_video() const;
|
||||
|
||||
/**
|
||||
* @brief Return true if user is suppressed.
|
||||
*
|
||||
* "HELP HELP I'M BEING SUPPRESSED!"
|
||||
*/
|
||||
bool is_suppressed() const;
|
||||
};
|
||||
|
||||
/** A container of voicestates */
|
||||
typedef std::unordered_map<std::string, voicestate> voicestate_map;
|
||||
|
||||
}
|
||||
208
dpp/webhook.h
208
dpp/webhook.h
@ -1,208 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/snowflake.h>
|
||||
#include <dpp/misc-enum.h>
|
||||
#include <dpp/managed.h>
|
||||
#include <dpp/json_fwd.h>
|
||||
#include <dpp/user.h>
|
||||
#include <dpp/guild.h>
|
||||
#include <dpp/channel.h>
|
||||
#include <unordered_map>
|
||||
#include <dpp/json_interface.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Defines types of webhook
|
||||
*/
|
||||
enum webhook_type {
|
||||
/**
|
||||
* @brief Incoming webhook.
|
||||
*/
|
||||
w_incoming = 1,
|
||||
|
||||
/**
|
||||
* @brief Channel following webhook.
|
||||
*/
|
||||
w_channel_follower = 2,
|
||||
|
||||
/**
|
||||
* @brief Application webhooks for interactions.
|
||||
*/
|
||||
w_application = 3
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a discord webhook
|
||||
*/
|
||||
class DPP_EXPORT webhook : public managed, public json_interface<webhook> {
|
||||
protected:
|
||||
friend struct json_interface<webhook>;
|
||||
|
||||
/**
|
||||
* @brief Fill in object from json data
|
||||
*
|
||||
* @param j JSON data
|
||||
* @return webhook& Reference to self
|
||||
*/
|
||||
webhook& fill_from_json_impl(nlohmann::json* j);
|
||||
|
||||
/**
|
||||
* @brief Build JSON string from object
|
||||
*
|
||||
* @param with_id Include the ID of the webhook in the json
|
||||
* @return std::string JSON encoded object
|
||||
*/
|
||||
virtual json to_json_impl(bool with_id = false) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Type of the webhook from dpp::webhook_type.
|
||||
*/
|
||||
uint8_t type;
|
||||
|
||||
/**
|
||||
* @brief The guild id this webhook is for.
|
||||
*
|
||||
* @note This field is optional, and may also be empty.
|
||||
*/
|
||||
snowflake guild_id;
|
||||
|
||||
/**
|
||||
* @brief The channel id this webhook is for.
|
||||
*
|
||||
* @note This may be empty.
|
||||
*/
|
||||
snowflake channel_id;
|
||||
|
||||
/**
|
||||
* @brief The user this webhook was created by.
|
||||
*
|
||||
* @note This field is optional.
|
||||
* @warning This is not returned when getting a webhook with its token!
|
||||
*/
|
||||
user user_obj;
|
||||
|
||||
/**
|
||||
* @brief The default name of the webhook.
|
||||
*
|
||||
* @note This may be empty.
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* @brief The default avatar of the webhook.
|
||||
*
|
||||
* @note This value will not have any effect when `avatar_url` is set, they are mutually exclusive.
|
||||
* @note This may be empty.
|
||||
*/
|
||||
utility::iconhash avatar;
|
||||
|
||||
/**
|
||||
* @brief Avatar URL to use instead of the default if it is set.
|
||||
*
|
||||
* @note This will override `avatar` if it is set, they are mutually exclusive.
|
||||
* @note This may be empty.
|
||||
*/
|
||||
std::string avatar_url;
|
||||
|
||||
/**
|
||||
* @brief The secure token of the webhook (returned for Incoming Webhooks).
|
||||
*
|
||||
* @note This field is optional.
|
||||
*/
|
||||
std::string token;
|
||||
|
||||
/**
|
||||
* @brief The bot/OAuth2 application that created this webhook.
|
||||
*
|
||||
* @note This may be empty.
|
||||
*/
|
||||
snowflake application_id;
|
||||
|
||||
/**
|
||||
* @brief The guild of the channel that this webhook is following (only for Channel Follower Webhooks).
|
||||
*
|
||||
* @warning This will be absent if the webhook creator has since lost access to the guild where the followed channel resides!
|
||||
*/
|
||||
guild source_guild;
|
||||
|
||||
/**
|
||||
* @brief The channel that this webhook is following (only for Channel Follower Webhooks).
|
||||
*
|
||||
* @warning This will be absent if the webhook creator has since lost access to the guild where the followed channel resides!
|
||||
*/
|
||||
channel source_channel;
|
||||
|
||||
/**
|
||||
* @brief The url used for executing the webhook (returned by the webhooks OAuth2 flow).
|
||||
*/
|
||||
std::string url;
|
||||
|
||||
/**
|
||||
* @brief base64 encoded image data if uploading a new image.
|
||||
*
|
||||
* @warning You should only ever read data from here. If you want to set the data, use dpp::webhook::load_image.
|
||||
*/
|
||||
std::string image_data;
|
||||
|
||||
/**
|
||||
* @brief Construct a new webhook object
|
||||
*/
|
||||
webhook();
|
||||
|
||||
/**
|
||||
* @brief Construct a new webhook object using the Webhook URL provided by Discord
|
||||
*
|
||||
* @param webhook_url a fully qualified web address of an existing webhook
|
||||
* @throw logic_exception if the webhook url could not be parsed
|
||||
*/
|
||||
webhook(const std::string& webhook_url);
|
||||
|
||||
/**
|
||||
* @brief Construct a new webhook object using the webhook ID and the webhook token
|
||||
*
|
||||
* @param webhook_id id taken from a link of an existing webhook
|
||||
* @param webhook_token token taken from a link of an existing webhook
|
||||
*/
|
||||
webhook(const snowflake webhook_id, const std::string& webhook_token);
|
||||
|
||||
/**
|
||||
* @brief Base64 encode image data and allocate it to image_data
|
||||
*
|
||||
* @param image_blob Binary image data
|
||||
* @param type Image type. It can be one of `i_gif`, `i_jpg` or `i_png`.
|
||||
* @param is_base64_encoded True if the image data is already base64 encoded
|
||||
* @return webhook& Reference to self
|
||||
* @throw dpp::length_exception Image data is larger than the maximum size of 256 kilobytes
|
||||
*/
|
||||
webhook& load_image(const std::string &image_blob, const image_type type, bool is_base64_encoded = false);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A group of webhooks
|
||||
*/
|
||||
typedef std::unordered_map<snowflake, webhook> webhook_map;
|
||||
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
/* This file contains pragmas to disable warnings on win32 builds with msvc only.
|
||||
* It is only included during build of D++ itself, and not when including the headers
|
||||
* into a user's project.
|
||||
*
|
||||
* Before adding a warning here please be ABSOLUTELY SURE it is one we cannot easily fix
|
||||
* and is to be silenced, thrown into the sarlacc pit to be eaten for 1000 years...
|
||||
*/
|
||||
|
||||
_Pragma("warning( disable : 4251 )"); // 4251 warns when we export classes or structures with stl member variables
|
||||
_Pragma("warning( disable : 5105 )"); // 5105 is to do with macro warnings
|
||||
@ -1,106 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#include <dpp/exception.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#include <string>
|
||||
#pragma once
|
||||
|
||||
namespace dpp::detail {
|
||||
|
||||
/**
|
||||
* @brief This class wraps a raw SSL_CTX pointer, managing moving,
|
||||
* creation, and RAII destruction.
|
||||
*/
|
||||
struct wrapped_ssl_ctx {
|
||||
|
||||
/**
|
||||
* @brief SSL_CTX pointer, raw C pointer nastiness
|
||||
*/
|
||||
SSL_CTX *context{nullptr};
|
||||
|
||||
/**
|
||||
* @brief Get last SSL error message
|
||||
* @return SSL error message
|
||||
*/
|
||||
std::string get_ssl_error() {
|
||||
unsigned long error_code = ERR_get_error();
|
||||
if (error_code == 0) {
|
||||
return "No error";
|
||||
}
|
||||
char error_buffer[1024]{0};
|
||||
ERR_error_string_n(error_code, error_buffer, sizeof(error_buffer));
|
||||
return std::string(error_buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a wrapped SSL context
|
||||
* @param is_server true to create a server context, false to create a client context
|
||||
* @throws dpp::connection_exception if context could not be created
|
||||
*/
|
||||
explicit wrapped_ssl_ctx(bool is_server = false) : context(SSL_CTX_new(is_server ? TLS_server_method() : TLS_client_method())) {
|
||||
if (context == nullptr) {
|
||||
throw dpp::connection_exception(err_ssl_context, "Failed to create SSL client context: " + get_ssl_error());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @note Intentionally deleted
|
||||
*/
|
||||
wrapped_ssl_ctx(const wrapped_ssl_ctx&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Copy assignment operator
|
||||
* @note Intentionally deleted
|
||||
*/
|
||||
wrapped_ssl_ctx& operator=(const wrapped_ssl_ctx&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
* @param other source context
|
||||
*/
|
||||
wrapped_ssl_ctx(wrapped_ssl_ctx&& other) noexcept : context(other.context) {
|
||||
other.context = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator
|
||||
* @param other source context
|
||||
* @return self
|
||||
*/
|
||||
wrapped_ssl_ctx& operator=(wrapped_ssl_ctx&& other) noexcept {
|
||||
if (this != &other) {
|
||||
/* Free current context if any and transfer ownership */
|
||||
SSL_CTX_free(context);
|
||||
context = other.context;
|
||||
other.context = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~wrapped_ssl_ctx() {
|
||||
SSL_CTX_free(context);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
252
dpp/wsclient.h
252
dpp/wsclient.h
@ -1,252 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <dpp/sslconnection.h>
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Websocket protocol types available on Discord
|
||||
*/
|
||||
enum websocket_protocol_t : uint8_t {
|
||||
/**
|
||||
* @brief JSON data, text, UTF-8 character set
|
||||
*/
|
||||
ws_json = 0,
|
||||
|
||||
/**
|
||||
* @brief Erlang Term Format (ETF) binary protocol
|
||||
*/
|
||||
ws_etf = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Websocket connection status
|
||||
*/
|
||||
enum ws_state : uint8_t {
|
||||
/**
|
||||
* @brief Sending/receiving HTTP headers, acting as a standard HTTP connection.
|
||||
* This is the state prior to receiving "HTTP/1.1 101 Switching Protocols" from the
|
||||
* server side.
|
||||
*/
|
||||
HTTP_HEADERS,
|
||||
|
||||
/**
|
||||
* @brief Connected as a websocket, and "upgraded". Now talking using binary frames.
|
||||
*/
|
||||
CONNECTED
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Low-level websocket opcodes for frames
|
||||
*/
|
||||
enum ws_opcode : uint8_t {
|
||||
/**
|
||||
* @brief Continuation.
|
||||
*/
|
||||
OP_CONTINUATION = 0x00,
|
||||
|
||||
/**
|
||||
* @brief Text frame.
|
||||
*/
|
||||
OP_TEXT = 0x01,
|
||||
|
||||
/**
|
||||
* @brief Binary frame.
|
||||
*/
|
||||
OP_BINARY = 0x02,
|
||||
|
||||
/**
|
||||
* @brief Close notification with close code.
|
||||
*/
|
||||
OP_CLOSE = 0x08,
|
||||
|
||||
/**
|
||||
* @brief Low level ping.
|
||||
*/
|
||||
OP_PING = 0x09,
|
||||
|
||||
/**
|
||||
* @brief Low level pong.
|
||||
*/
|
||||
OP_PONG = 0x0a,
|
||||
|
||||
/**
|
||||
* @brief Automatic selection of type
|
||||
*/
|
||||
OP_AUTO = 0xff,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements a websocket client based on the SSL client
|
||||
*/
|
||||
class DPP_EXPORT websocket_client : public ssl_connection {
|
||||
/**
|
||||
* @brief Connection key used in the HTTP headers
|
||||
*/
|
||||
std::string key;
|
||||
|
||||
/**
|
||||
* @brief Current websocket state
|
||||
*/
|
||||
ws_state state;
|
||||
|
||||
/**
|
||||
* @brief Path part of URL for websocket
|
||||
*/
|
||||
std::string path;
|
||||
|
||||
/**
|
||||
* @brief Data opcode, represents the type of frames we send
|
||||
*/
|
||||
ws_opcode data_opcode;
|
||||
|
||||
/**
|
||||
* @brief HTTP headers received on connecting/upgrading
|
||||
*/
|
||||
std::map<std::string, std::string> http_headers;
|
||||
|
||||
/**
|
||||
* @brief Parse headers for a websocket frame from the buffer.
|
||||
* @param buffer The buffer to operate on. Will modify the string removing completed items from the head of the queue
|
||||
* @return true if a complete header has been received
|
||||
*/
|
||||
bool parseheader(std::string& buffer);
|
||||
|
||||
/**
|
||||
* @brief Fill a header for outbound messages
|
||||
* @param outbuf The raw frame to fill
|
||||
* @param sendlength The size of the data to encapsulate
|
||||
* @param opcode the ws_opcode to send in the header
|
||||
* @return size of filled header
|
||||
*/
|
||||
size_t fill_header(unsigned char* outbuf, size_t sendlength, ws_opcode opcode);
|
||||
|
||||
/**
|
||||
* @brief Handle ping requests.
|
||||
* @param payload The ping payload, to be returned as-is for a pong
|
||||
*/
|
||||
void handle_ping(const std::string& payload);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief Connect to websocket server
|
||||
*/
|
||||
virtual void connect() override;
|
||||
|
||||
/**
|
||||
* @brief Get websocket state
|
||||
* @return websocket state
|
||||
*/
|
||||
[[nodiscard]] ws_state get_state() const;
|
||||
|
||||
/**
|
||||
* @brief If true the connection timed out while waiting,
|
||||
* when waiting for SSL negotiation, TCP connect(), or HTTP.
|
||||
*/
|
||||
bool timed_out;
|
||||
|
||||
/**
|
||||
* @brief Time at which the connection should be abandoned,
|
||||
* if we are still connecting or negotiating with a HTTP server
|
||||
*/
|
||||
time_t timeout;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Connect to a specific websocket server.
|
||||
* @param creator Creating cluster
|
||||
* @param hostname Hostname to connect to
|
||||
* @param port Port to connect to
|
||||
* @param urlpath The URL path components of the HTTP request to send
|
||||
* @param opcode The encoding type to use, either OP_BINARY or OP_TEXT
|
||||
* @note This just indicates the default for frames sent. Certain sockets,
|
||||
* such as voice websockets, may send a combination of OP_TEXT and OP_BINARY
|
||||
* frames, whereas shard websockets will only ever send OP_BINARY for ETF and
|
||||
* OP_TEXT for JSON.
|
||||
*/
|
||||
websocket_client(cluster* creator, const std::string& hostname, const std::string& port = "443", const std::string& urlpath = "", ws_opcode opcode = OP_BINARY);
|
||||
|
||||
/**
|
||||
* @brief Destroy the websocket client object
|
||||
*/
|
||||
virtual ~websocket_client() = default;
|
||||
|
||||
/**
|
||||
* @brief Write to websocket. Encapsulates data in frames if the status is CONNECTED.
|
||||
* @param data The data to send.
|
||||
* @param _opcode The opcode of the data to send, either binary or text. The default
|
||||
* is to use the socket's opcode as set in the constructor.
|
||||
*/
|
||||
virtual void write(const std::string_view data, ws_opcode _opcode = OP_AUTO);
|
||||
|
||||
/**
|
||||
* @brief Processes incoming frames from the SSL socket input buffer.
|
||||
* @param buffer The buffer contents. Can modify this value removing the head elements when processed.
|
||||
*/
|
||||
virtual bool handle_buffer(std::string& buffer) override;
|
||||
|
||||
/**
|
||||
* @brief Close websocket
|
||||
*/
|
||||
virtual void close() override;
|
||||
|
||||
/**
|
||||
* @brief Receives raw frame content only without headers
|
||||
*
|
||||
* @param buffer The buffer contents
|
||||
* @param opcode Frame type, e.g. OP_TEXT, OP_BINARY
|
||||
* @return True if the frame was successfully handled. False if no valid frame is in the buffer.
|
||||
*/
|
||||
virtual bool handle_frame(const std::string& buffer, ws_opcode opcode);
|
||||
|
||||
/**
|
||||
* @brief Called upon error frame.
|
||||
*
|
||||
* @param errorcode The error code from the websocket server
|
||||
*/
|
||||
virtual void error(uint32_t errorcode);
|
||||
|
||||
/**
|
||||
* @brief Fires every second from the underlying socket I/O loop, used for sending websocket pings
|
||||
*/
|
||||
virtual void one_second_timer() override;
|
||||
|
||||
/**
|
||||
* @brief Send OP_CLOSE error code 1000 to the other side of the connection.
|
||||
* This indicates graceful close.
|
||||
* @note This informs Discord to invalidate the session, you cannot resume if you send this
|
||||
*/
|
||||
void send_close_packet();
|
||||
|
||||
/**
|
||||
* @brief Called on HTTP socket closure
|
||||
*/
|
||||
virtual void on_disconnect();
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,85 +0,0 @@
|
||||
/************************************************************************************
|
||||
*
|
||||
* D++, A Lightweight C++ library for Discord
|
||||
*
|
||||
* Copyright 2021 Craig Edwards and D++ contributors
|
||||
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
************************************************************************************/
|
||||
#pragma once
|
||||
#include <dpp/export.h>
|
||||
#include <dpp/exception.h>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
/**
|
||||
* @brief Forward declaration for zlib stream type
|
||||
*/
|
||||
typedef struct z_stream_s z_stream;
|
||||
|
||||
namespace dpp {
|
||||
|
||||
/**
|
||||
* @brief Size of decompression buffer for zlib compressed traffic
|
||||
*/
|
||||
constexpr size_t DECOMP_BUFFER_SIZE = 512 * 1024;
|
||||
|
||||
/**
|
||||
* @brief This is an opaque class containing zlib library specific structures.
|
||||
* This wraps the C pointers needed for zlib with unique_ptr and gives us a nice
|
||||
* buffer abstraction so we don't need to wrestle with raw pointers.
|
||||
*/
|
||||
class DPP_EXPORT zlibcontext {
|
||||
public:
|
||||
/**
|
||||
* @brief Zlib stream struct. The actual type is defined in zlib.h
|
||||
* so is only defined in the implementation file.
|
||||
*/
|
||||
z_stream* d_stream{};
|
||||
|
||||
/**
|
||||
* @brief ZLib decompression buffer.
|
||||
* This is automatically set to DECOMP_BUFFER_SIZE bytes when
|
||||
* the class is constructed.
|
||||
*/
|
||||
std::vector<unsigned char> decomp_buffer{};
|
||||
|
||||
/**
|
||||
* @brief Total decompressed received bytes counter
|
||||
*/
|
||||
uint64_t decompressed_total{};
|
||||
|
||||
/**
|
||||
* @brief Initialise zlib struct via inflateInit()
|
||||
* and size the buffer
|
||||
*/
|
||||
zlibcontext();
|
||||
|
||||
/**
|
||||
* @brief Destroy zlib struct via inflateEnd()
|
||||
*/
|
||||
~zlibcontext();
|
||||
|
||||
/**
|
||||
* @brief Decompress zlib deflated buffer
|
||||
* @param buffer input compressed stream
|
||||
* @param decompressed output decompressed content
|
||||
* @return an error code on error, or err_no_code_specified (0) on success
|
||||
*/
|
||||
exception_error_code decompress(const std::string& buffer, std::string& decompressed);
|
||||
};
|
||||
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
libdpp.so.10.1.4
|
||||
Binary file not shown.
33
makefile
33
makefile
@ -4,30 +4,20 @@ EXECUTABLE_NAME = discord-bot
|
||||
PLATFORM = $(shell uname)
|
||||
BUILD_TYPE ?= release# Default to release build if not specified
|
||||
|
||||
STB_PATH = $(HOME)/workdir/stb
|
||||
LINUX_LIB_EXT = so
|
||||
|
||||
# Version configuration (can be overridden)
|
||||
DPP_VERSION ?= $(shell find ../DPP/build/library -name "libdpp.so.*.*.*" -type f | head -1 | sed 's/.*libdpp\.so\.//')
|
||||
# Conditional assignment for DPP_PATH based on whether DPP_VERSION was found or is empty
|
||||
# This logic assumes that if DPP_VERSION is found (not empty), it's a custom build (../DPP).
|
||||
# If DPP_VERSION is empty (meaning libdpp.so.*.*.* was not found in the custom build path),
|
||||
# we default to 'lib', assuming a system-wide or standard install location.
|
||||
ifeq ($(strip $(DPP_VERSION)),) # Check if DPP_VERSION is empty (no version found)
|
||||
DPP_PATH = ./lib # use .so file provided instead of the dpp source files
|
||||
# Define include directories for headers
|
||||
# -I<path> tells the compiler where to look for #include <file.h> or #include <dir/file.h>
|
||||
# We assume:
|
||||
# - STB headers are in the root project folder
|
||||
# - D++ headers are in 'dpp/' (so dpp.h is found via include/dpp/dpp.h)
|
||||
INC_DIRS = -Iinclude -Idpp/
|
||||
LIB_PATHS = $(DPP_PATH)
|
||||
else
|
||||
# If DPP_VERSION has a value (a version was found), assume custom build path
|
||||
DPP_PATH = $(HOME)/workdir/DPP
|
||||
DPP_BUILD_DIR = $(DPP_PATH)/build/library
|
||||
LIB_PATHS = $(DPP_BUILD_DIR)
|
||||
INC_DIRS = -Iinclude -I$(DPP_PATH)/include/
|
||||
endif
|
||||
INC_DIRS = -Iinclude -I$(DPP_PATH)/include/ -I$(STB_PATH)
|
||||
#endif
|
||||
|
||||
DPP_VERSION := $(or $(DPP_VERSION),10.1.4)# Fallback version if auto-detection fails
|
||||
DPP_LINUX_LIB_VERSION_FILE = libdpp.$(LINUX_LIB_EXT).$(DPP_VERSION)
|
||||
DPP_LIB_NAME = libdpp.$(LINUX_LIB_EXT)
|
||||
|
||||
# Common paths
|
||||
OBJ_DIR = obj/$(PLATFORM)/$(BUILD_TYPE)
|
||||
@ -51,7 +41,7 @@ CXX_FLAGS = $(COMMON_FLAGS) -std=c++17 -Wall -g $(INC_DIRS)
|
||||
|
||||
# Linker directive flags (L for library search path, l for library)
|
||||
# Need to link against the D++ library and pthread (common for C++ applications with threading)
|
||||
LDFLAGS = -L$(LIB_PATHS) -ldpp -lpthread -Wl,-rpath=../../../$(LIB_PATHS)
|
||||
LDFLAGS = -L$(LIB_PATHS) -ldpp -lpthread -Wl,-rpath='$$ORIGIN' # search for lib in the same place as the executable file
|
||||
|
||||
# List of object files for your executable
|
||||
# We've changed this back to use discord-bot.o as the source of the executable
|
||||
@ -73,12 +63,19 @@ $(OUTPUT_FILE): $(OBJECTS)
|
||||
@if test -f token.txt; then \
|
||||
echo "Copying token.txt to $(@D)"; \
|
||||
cp token.txt $(@D); \
|
||||
if test -f $(DPP_BUILD_DIR)/$(DPP_LINUX_LIB_VERSION_FILE); then \
|
||||
cp $(DPP_BUILD_DIR)/$(DPP_LINUX_LIB_VERSION_FILE) $(BIN_DIR)/$(DPP_LINUX_LIB_VERSION_FILE); \
|
||||
ln -sf $(DPP_LINUX_LDPP_LINUX_LIB_VERSION_FILEIB_FILE) $(BIN_DIR)/$(DPP_LIB_NAME); \
|
||||
else \
|
||||
cp $(DPP_BUILD_DIR)/$(DPP_LIB_NAME) $(BIN_DIR)/$(DPP_LIB_NAME); \
|
||||
fi \
|
||||
else \
|
||||
echo "Error: token.txt not found! Please create it in the project root. Copy the token when you create your discord bot and paste it in token.txt"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Rule to compile the object file:
|
||||
# This takes your .cpp source file and compiles it into an object file (.o).
|
||||
$(OBJ_DIR)/$(EXECUTABLE_NAME).o: $(EXECUTABLE_NAME).cpp
|
||||
|
||||
7988
stb_image.h
7988
stb_image.h
File diff suppressed because it is too large
Load Diff
1724
stb_image_write.h
1724
stb_image_write.h
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user