/************************************************************************************ * * 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 #include #include #include #include #include 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 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 { protected: friend struct json_interface; /** 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 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 presence_map; } // namespace dpp