Implements a discord client. More...
#include "discordclient.h"
Public Member Functions | |
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) | |
Construct a new discord_client object. More... | |
virtual | ~discord_client () |
Destroy the discord client object. More... | |
discord_client & | clear_queue () |
Clear the outbound message queue. More... | |
virtual void | close () |
Close websocket. More... | |
discord_client & | connect_voice (snowflake guild_id, snowflake channel_id, bool self_mute=false, bool self_deaf=false) |
Connect to a voice channel. More... | |
discord_client & | disconnect_voice (snowflake guild_id) |
Disconnect from the connected voice channel on a guild. More... | |
virtual void | error (uint32_t errorcode) |
Handle a websocket error. More... | |
uint64_t | get_bytes_in () |
Get total bytes received. More... | |
uint64_t | get_bytes_out () |
Get the bytes out objectGet total bytes sent. More... | |
uint64_t | get_channel_count () |
Get the Channel Count for this shard. More... | |
std::string | get_cipher () |
Get SSL cipher name. More... | |
uint64_t | get_decompressed_bytes_in () |
Get the decompressed bytes in objectGet decompressed total bytes received. More... | |
uint64_t | get_guild_count () |
Get the Guild Count for this shard. More... | |
uint64_t | get_member_count () |
Get the Member Count for this shard. More... | |
size_t | get_queue_size () |
Get the size of the outbound message queue. More... | |
dpp::utility::uptime | get_uptime () |
Returns the connection time of the shard. More... | |
voiceconn * | get_voice (snowflake guild_id) |
Get the dpp::voiceconn object for a specific guild on this shard. More... | |
virtual bool | handle_buffer (std::string &buffer) |
Processes incoming frames from the SSL socket input buffer. More... | |
virtual void | handle_event (const std::string &event, json &j, const std::string &raw) |
Handle an event (opcode 0) More... | |
virtual bool | handle_frame (const std::string &buffer) |
Handle JSON from the websocket. More... | |
bool | is_connected () |
Returns true if the shard is connected. More... | |
virtual void | log (dpp::loglevel severity, const std::string &msg) const |
Log a message to whatever log the user is using. More... | |
virtual void | one_second_timer () |
Fires every second from the underlying socket I/O loop, used for sending heartbeats. More... | |
void | queue_message (const std::string &j, bool to_front=false) |
Queue a message to be sent via the websocket. More... | |
void | read_loop () |
Nonblocking I/O loop. More... | |
void | run () |
Start and monitor I/O loop. More... | |
void | send_close_packet () |
Send OP_CLOSE error code 1000 to the other side of the connection. More... | |
virtual void | write (const std::string &data) |
Write to websocket. More... | |
Public Attributes | |
std::unordered_map< snowflake, std::unique_ptr< voiceconn > > | connecting_voice_channels |
List of voice channels we are connecting to keyed by guild id. More... | |
class dpp::cluster * | creator |
Owning cluster. More... | |
socket_callback_t | custom_readable_fd |
Attaching an additional file descriptor to this function will send notifications when there is data to read. More... | |
socket_notification_t | custom_readable_ready |
This event will be called when you can read from the custom fd. More... | |
socket_callback_t | custom_writeable_fd |
Attaching an additional file descriptor to this function will send notifications when you are able to write to the socket. More... | |
socket_notification_t | custom_writeable_ready |
This event will be called when you can write to a custom fd. More... | |
uint32_t | heartbeat_interval |
Heartbeat interval for sending heartbeat keepalive. More... | |
uint32_t | intents |
Privileged gateway intents. More... | |
bool | keepalive |
True if we are keeping the connection alive after it has finished. More... | |
time_t | last_heartbeat |
Last heartbeat. More... | |
time_t | last_heartbeat_ack |
Last heartbeat ACK (opcode 11) More... | |
uint64_t | last_seq |
Last sequence number received, for resumes and pings. More... | |
uint32_t | max_shards |
Total number of shards. More... | |
websocket_protocol_t | protocol |
Current websocket protocol, currently either ETF or JSON. More... | |
bool | ready |
True if READY or RESUMED has been received. More... | |
uint32_t | reconnects |
Reconnection count. More... | |
std::string | resume_gateway_url |
The gateway address we reconnect to when we resume a session. More... | |
uint32_t | resumes |
Resume count. More... | |
std::string | sessionid |
Discord session id. More... | |
uint32_t | shard_id |
Shard ID of this client. More... | |
std::thread::native_handle_type | thread_id |
Thread ID. More... | |
std::string | token |
Discord bot token. More... | |
std::shared_mutex | voice_mutex |
Mutex for voice connections map. More... | |
double | websocket_ping |
Websocket latency in fractional seconds. More... | |
Protected Member Functions | |
virtual void | connect () |
(Re)connect More... | |
void | disconnect_voice_internal (snowflake guild_id, bool send_json=true) |
Disconnect from the connected voice channel on a guild. More... | |
ws_state | get_state () |
Get websocket state. More... | |
Protected Attributes | |
std::string | buffer |
Input buffer received from socket. More... | |
uint64_t | bytes_in |
Bytes in. More... | |
uint64_t | bytes_out |
Bytes out. More... | |
std::string | cipher |
SSL cipher in use. More... | |
std::string | hostname |
Hostname connected to. More... | |
time_t | last_tick |
For timers. More... | |
bool | make_new |
True if we are establishing a new connection, false if otherwise. More... | |
bool | nonblocking |
True if in nonblocking mode. More... | |
std::string | obuffer |
Output buffer for sending to socket. More... | |
bool | plaintext |
True for a plain text connection. More... | |
std::string | port |
Port connected to. More... | |
dpp::socket | sfd |
Raw file descriptor of connection. More... | |
openssl_connection * | ssl |
Openssl opaque contexts. More... | |
bool | terminating |
True if the shard is terminating. More... | |
Friends | |
class | dpp::cluster |
Needed to allow cluster::set_presence to use the ETF functions. More... | |
class | dpp::events::guild_create |
Needed so that guild_create can request member chunks if you have the correct intents. More... | |
class | dpp::events::voice_state_update |
Needed so that voice_state_update can call dpp::discord_client::disconnect_voice_internal. More... | |
Implements a discord client.
Each discord_client connects to one shard and derives from a websocket client.
dpp::discord_client::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 |
||
) |
Construct a new discord_client object.
_cluster | The owning cluster for this shard |
_shard_id | The ID of the shard to start |
_max_shards | The total number of shards across all clusters |
_token | The bot token to use for identifying to the websocket |
intents | Privileged intents to use, a bitmask of values from dpp::intents |
compressed | True if the received data will be gzip compressed |
ws_protocol | Websocket protocol to use for the connection, JSON or ETF |
std::bad_alloc | Passed up to the caller if any internal objects fail to allocate, after cleanup has completed |
References dpp::websocket_client::connect().
|
virtual |
Destroy the discord client object.
discord_client & dpp::discord_client::clear_queue | ( | ) |
Clear the outbound message queue.
|
virtualinherited |
Close websocket.
Reimplemented from dpp::ssl_client.
Referenced by handle_frame().
|
protectedvirtualinherited |
(Re)connect
Reimplemented from dpp::ssl_client.
Referenced by discord_client(), dpp::discord_voice_client::discord_voice_client(), and dpp::discord_voice_client::discover_ip().
discord_client & dpp::discord_client::connect_voice | ( | snowflake | guild_id, |
snowflake | channel_id, | ||
bool | self_mute = false , |
||
bool | self_deaf = false |
||
) |
Connect to a voice channel.
guild_id | Guild where the voice channel is |
channel_id | Channel ID of the voice channel |
self_mute | True if the bot should mute itself |
self_deaf | True if the bot should deafen itself |
References connecting_voice_channels, dpp::ll_debug, dpp::unicode_emoji::lock, log(), queue_message(), and voice_mutex.
discord_client & dpp::discord_client::disconnect_voice | ( | snowflake | guild_id | ) |
Disconnect from the connected voice channel on a guild.
guild_id | The guild who's voice channel you wish to disconnect from |
References disconnect_voice_internal().
|
protected |
Disconnect from the connected voice channel on a guild.
guild_id | The guild who's voice channel you wish to disconnect from |
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. |
References connecting_voice_channels, dpp::ll_debug, dpp::unicode_emoji::lock, log(), queue_message(), dpp::unicode_emoji::v, and voice_mutex.
Referenced by disconnect_voice().
|
virtual |
Handle a websocket error.
errorcode | The error returned from the websocket |
Reimplemented from dpp::websocket_client.
References dpp::ll_warning, and log().
Referenced by handle_frame().
|
inherited |
|
inherited |
Get the bytes out objectGet total bytes sent.
References dpp::ssl_client::bytes_out.
uint64_t dpp::discord_client::get_channel_count | ( | ) |
Get the Channel Count for this shard.
References dpp::guild::channels, dpp::cache< T >::get_container(), dpp::get_guild_cache(), dpp::cache< T >::get_mutex(), if, and dpp::guild::shard_id.
|
inherited |
uint64_t dpp::discord_client::get_decompressed_bytes_in | ( | ) |
Get the decompressed bytes in objectGet decompressed total bytes received.
uint64_t dpp::discord_client::get_guild_count | ( | ) |
Get the Guild Count for this shard.
References dpp::cache< T >::get_container(), dpp::get_guild_cache(), dpp::cache< T >::get_mutex(), if, and dpp::guild::shard_id.
uint64_t dpp::discord_client::get_member_count | ( | ) |
Get the Member Count for this shard.
References dpp::cluster::cache_policy, dpp::cp_aggressive, creator, dpp::cache< T >::get_container(), dpp::get_guild_cache(), dpp::cache< T >::get_mutex(), if, dpp::guild::member_count, dpp::guild::members, dpp::guild::shard_id, and dpp::cache_policy_t::user_policy.
size_t dpp::discord_client::get_queue_size | ( | ) |
Get the size of the outbound message queue.
|
protectedinherited |
Get websocket state.
References dpp::WS_MASKBIT.
Referenced by is_connected(), dpp::discord_voice_client::is_connected(), and dpp::discord_voice_client::one_second_timer().
dpp::utility::uptime dpp::discord_client::get_uptime | ( | ) |
Returns the connection time of the shard.
Get the dpp::voiceconn object for a specific guild on this shard.
guild_id | The guild ID to retrieve the voice connection for |
References connecting_voice_channels, dpp::unicode_emoji::lock, dpp::unicode_emoji::v, and voice_mutex.
|
virtualinherited |
Processes incoming frames from the SSL socket input buffer.
buffer | The buffer contents. Can modify this value removing the head elements when processed. |
Reimplemented from dpp::ssl_client.
References dpp::CONNECTED.
|
virtual |
Handle an event (opcode 0)
event | Event name, e.g. MESSAGE_CREATE |
j | JSON object for the event content |
raw | Raw JSON event string |
References dpp::event_map, dpp::ll_debug, and log().
Referenced by handle_frame().
|
virtual |
Handle JSON from the websocket.
buffer | The entire buffer content from the websocket client |
This section parses the input frames from the websocket after they're decompressed. Note that both ETF and JSON parsers return an nlohmann::json object, so that the rest of the library or any user code does not need to be concerned with protocol differences. Generally, ETF is faster and consumes much less memory, but provides less opportunities to diagnose if it goes wrong.
Reimplemented from dpp::websocket_client.
References dpp::ssl_client::buffer, dpp::websocket_client::close(), creator, dpp::zlibcontext::d_stream, dpp::utility::debug_dump(), DECOMP_BUFFER_SIZE, DPP_OS, dpp::err_compression_data, dpp::err_compression_memory, dpp::err_compression_stream, dpp::err_reconnection, error(), handle_event(), heartbeat_interval, last_heartbeat_ack, dpp::cluster::last_identify, last_seq, dpp::ll_debug, dpp::ll_error, log(), max_shards, dpp::unicode_emoji::o, dpp::etf_parser::parse(), protocol, reconnects, resumes, sessionid, shard_id, STRINGIFY, dpp::utility::time_f(), token, websocket_ping, dpp::websocket_client::write(), dpp::ws_etf, and dpp::ws_json.
bool dpp::discord_client::is_connected | ( | ) |
Returns true if the shard is connected.
References dpp::CONNECTED, dpp::websocket_client::get_state(), and ready.
Referenced by one_second_timer().
|
virtual |
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.
severity | The log level from dpp::loglevel |
msg | The log message to output |
Reimplemented from dpp::ssl_client.
References creator, dpp::log_t::message, dpp::cluster::on_log, and dpp::log_t::severity.
Referenced by dpp::voiceconn::connect(), connect_voice(), disconnect_voice_internal(), error(), handle_event(), handle_frame(), and one_second_timer().
|
virtual |
Fires every second from the underlying socket I/O loop, used for sending heartbeats.
Reimplemented from dpp::websocket_client.
References dpp::close_socket(), creator, dpp::garbage_collection(), dpp::cluster::get_shards(), heartbeat_interval, is_connected(), last_heartbeat, last_heartbeat_ack, dpp::last_ping_message, last_seq, dpp::ll_warning, log(), dpp::websocket_client::one_second_timer(), queue_message(), sessionid, dpp::ssl_client::sfd, terminating, dpp::utility::time_f(), dpp::websocket_client::write(), and dpp::unicode_emoji::x.
void dpp::discord_client::queue_message | ( | const std::string & | j, |
bool | to_front = false |
||
) |
Queue a message to be sent via the websocket.
j | The JSON data of the message to be sent |
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) |
Referenced by connect_voice(), disconnect_voice_internal(), and one_second_timer().
|
inherited |
Nonblocking I/O loop.
std::exception | Any std::exception (or derivative) thrown from read_loop() causes reconnection of the shard |
References dpp::ssl_client::buffer, dpp::ssl_client::bytes_in, dpp::ssl_client::bytes_out, dpp::ssl_client::custom_readable_fd, dpp::ssl_client::custom_readable_ready, dpp::ssl_client::custom_writeable_fd, dpp::ssl_client::custom_writeable_ready, DPP_BUFSIZE, dpp::err_invalid_socket, dpp::err_nonblocking_failure, dpp::err_socket_error, dpp::ssl_client::handle_buffer(), INVALID_SOCKET, dpp::ssl_client::last_tick, dpp::ll_warning, dpp::ssl_client::log(), dpp::ssl_client::nonblocking, dpp::ssl_client::obuffer, dpp::ssl_client::one_second_timer(), dpp::ssl_client::plaintext, dpp::set_nonblocking(), dpp::ssl_client::sfd, dpp::openssl_connection::ssl, and dpp::ssl_client::ssl.
void dpp::discord_client::run | ( | ) |
Start and monitor I/O loop.
References dpp::unicode_emoji::thread, and thread_id.
|
inherited |
Send OP_CLOSE error code 1000 to the other side of the connection.
This indicates graceful close.
References dpp::ssl_client::close(), and dpp::HTTP_HEADERS.
|
virtualinherited |
Write to websocket.
Encapsulates data in frames if the status is CONNECTED.
data | The data to send. |
Reimplemented from dpp::ssl_client.
Referenced by handle_frame(), dpp::discord_voice_client::handle_frame(), one_second_timer(), dpp::discord_voice_client::one_second_timer(), and dpp::websocket_client::websocket_client().
|
friend |
Needed to allow cluster::set_presence to use the ETF functions.
|
friend |
Needed so that guild_create can request member chunks if you have the correct intents.
|
friend |
Needed so that voice_state_update can call dpp::discord_client::disconnect_voice_internal.
|
protectedinherited |
Input buffer received from socket.
Referenced by dpp::ssl_client::close(), handle_frame(), and dpp::ssl_client::read_loop().
|
protectedinherited |
Bytes in.
Referenced by dpp::ssl_client::get_bytes_in(), and dpp::ssl_client::read_loop().
|
protectedinherited |
Bytes out.
Referenced by dpp::ssl_client::get_bytes_out(), and dpp::ssl_client::read_loop().
|
protectedinherited |
SSL cipher in use.
Referenced by dpp::ssl_client::connect(), and dpp::ssl_client::get_cipher().
std::unordered_map<snowflake, std::unique_ptr<voiceconn> > dpp::discord_client::connecting_voice_channels |
List of voice channels we are connecting to keyed by guild id.
Referenced by connect_voice(), disconnect_voice_internal(), and get_voice().
class dpp::cluster* dpp::discord_client::creator |
Owning cluster.
Referenced by dpp::voiceconn::connect(), dpp::interaction_create_t::dialog(), get_member_count(), handle_frame(), log(), and one_second_timer().
|
inherited |
Attaching an additional file descriptor to this function will send notifications when there is data to read.
NOTE: Only hook this if you NEED it as it can increase CPU usage of the thread! Returning -1 means that you don't want to be notified.
Referenced by dpp::discord_voice_client::handle_frame(), and dpp::ssl_client::read_loop().
|
inherited |
This event will be called when you can read from the custom fd.
Referenced by dpp::discord_voice_client::handle_frame(), and dpp::ssl_client::read_loop().
|
inherited |
Attaching an additional file descriptor to this function will send notifications when you are able to write to the socket.
NOTE: Only hook this if you NEED it as it can increase CPU usage of the thread! You should toggle this to -1 when you do not have anything to write otherwise it'll keep triggering repeatedly (it is level triggered).
Referenced by dpp::discord_voice_client::handle_frame(), and dpp::ssl_client::read_loop().
|
inherited |
This event will be called when you can write to a custom fd.
Referenced by dpp::discord_voice_client::handle_frame(), and dpp::ssl_client::read_loop().
uint32_t dpp::discord_client::heartbeat_interval |
Heartbeat interval for sending heartbeat keepalive.
Referenced by handle_frame(), and one_second_timer().
|
protectedinherited |
Hostname connected to.
Referenced by dpp::ssl_client::close(), dpp::ssl_client::connect(), and dpp::ssl_client::ssl_client().
uint32_t dpp::discord_client::intents |
Privileged gateway intents.
|
inherited |
True if we are keeping the connection alive after it has finished.
Referenced by dpp::ssl_client::close(), and dpp::ssl_client::ssl_client().
time_t dpp::discord_client::last_heartbeat |
Last heartbeat.
Referenced by one_second_timer().
time_t dpp::discord_client::last_heartbeat_ack |
Last heartbeat ACK (opcode 11)
Referenced by handle_frame(), and one_second_timer().
uint64_t dpp::discord_client::last_seq |
Last sequence number received, for resumes and pings.
Referenced by handle_frame(), and one_second_timer().
|
protectedinherited |
For timers.
Referenced by dpp::ssl_client::read_loop().
|
protectedinherited |
True if we are establishing a new connection, false if otherwise.
Referenced by dpp::ssl_client::connect(), and dpp::ssl_client::ssl_client().
uint32_t dpp::discord_client::max_shards |
Total number of shards.
Referenced by handle_frame().
|
protectedinherited |
True if in nonblocking mode.
The socket switches to nonblocking mode once ReadLoop is called.
Referenced by dpp::ssl_client::connect(), dpp::ssl_client::read_loop(), and dpp::ssl_client::write().
|
protectedinherited |
Output buffer for sending to socket.
Referenced by dpp::ssl_client::close(), dpp::ssl_client::read_loop(), and dpp::ssl_client::write().
|
protectedinherited |
True for a plain text connection.
Referenced by dpp::ssl_client::close(), dpp::ssl_client::connect(), dpp::ssl_client::read_loop(), dpp::ssl_client::ssl_client(), and dpp::ssl_client::write().
|
protectedinherited |
Port connected to.
Referenced by dpp::ssl_client::close(), dpp::ssl_client::connect(), and dpp::ssl_client::ssl_client().
websocket_protocol_t dpp::discord_client::protocol |
Current websocket protocol, currently either ETF or JSON.
Referenced by handle_frame().
bool dpp::discord_client::ready |
True if READY or RESUMED has been received.
Referenced by is_connected().
uint32_t dpp::discord_client::reconnects |
Reconnection count.
Referenced by handle_frame().
std::string dpp::discord_client::resume_gateway_url |
The gateway address we reconnect to when we resume a session.
uint32_t dpp::discord_client::resumes |
Resume count.
Referenced by handle_frame().
std::string dpp::discord_client::sessionid |
Discord session id.
Referenced by handle_frame(), and one_second_timer().
|
protectedinherited |
Raw file descriptor of connection.
Referenced by dpp::ssl_client::close(), dpp::ssl_client::connect(), one_second_timer(), dpp::ssl_client::read_loop(), dpp::ssl_client::ssl_client(), and dpp::ssl_client::write().
uint32_t dpp::discord_client::shard_id |
Shard ID of this client.
Referenced by handle_frame().
|
protectedinherited |
Openssl opaque contexts.
Referenced by dpp::ssl_client::close(), dpp::ssl_client::connect(), dpp::ssl_client::read_loop(), dpp::ssl_client::ssl_client(), and dpp::ssl_client::write().
|
protected |
True if the shard is terminating.
Referenced by one_second_timer().
std::thread::native_handle_type dpp::discord_client::thread_id |
Thread ID.
Referenced by run().
std::string dpp::discord_client::token |
Discord bot token.
Referenced by handle_frame().
std::shared_mutex dpp::discord_client::voice_mutex |
Mutex for voice connections map.
Referenced by connect_voice(), disconnect_voice_internal(), and get_voice().
double dpp::discord_client::websocket_ping |
Websocket latency in fractional seconds.
Referenced by handle_frame(), and main().