819 lines
26 KiB
C
819 lines
26 KiB
C
/**
|
|
* @file discord.h
|
|
* @author Cogmasters
|
|
* @brief Public functions and datatypes
|
|
*
|
|
* These symbols are organized in a intuitive fashion to be easily
|
|
* matched to the official Discord API docs
|
|
* @see https://discord.com/developers/docs/intro
|
|
*/
|
|
|
|
#ifndef DISCORD_H
|
|
#define DISCORD_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
|
|
#include <inttypes.h>
|
|
#include <stdbool.h>
|
|
|
|
#include "concord-error.h"
|
|
#include "types.h"
|
|
#include "io_poller.h"
|
|
#define LOGMOD_HEADER
|
|
#include "logmod.h"
|
|
|
|
#ifndef DISCORD_VERSION
|
|
/**
|
|
* @brief The Discord API version to use
|
|
* @warning only change this if you know what you are doing!
|
|
*/
|
|
#define DISCORD_VERSION "10"
|
|
#endif
|
|
|
|
#define DISCORD_API_BASE_URL "https://discord.com/api/v" DISCORD_VERSION
|
|
#define DISCORD_GATEWAY_URL_SUFFIX "?v=" DISCORD_VERSION "&encoding=json"
|
|
|
|
/* forward declaration */
|
|
struct discord;
|
|
struct reflectc;
|
|
/**/
|
|
|
|
/**
|
|
* @brief Get the reflectc registry from a Discord client
|
|
*
|
|
* @param client the client created with discord_from_json() or discord_from_token()
|
|
* @return the reflectc registry used by the client
|
|
*/
|
|
struct reflectc *discord_get_registry(struct discord *client);
|
|
|
|
#include "discord_codecs.h"
|
|
#include "discord-response.h"
|
|
|
|
/** @defgroup DiscordClient Client */
|
|
|
|
/** @defgroup DiscordConstants Constants
|
|
* @brief Macros for constants defined by Discord
|
|
* @note macros assume the worst-case scenario for strings, where each
|
|
* character is 4 bytes long (UTF8)
|
|
* @{ */
|
|
|
|
/** @defgroup DiscordConstantsGeneral General lengths
|
|
* @brief Max length for general fields
|
|
* @{ */
|
|
#define DISCORD_MAX_NAME_LEN 4 * 100 + 1
|
|
#define DISCORD_MAX_TOPIC_LEN 4 * 1024 + 1
|
|
#define DISCORD_MAX_DESCRIPTION_LEN 4 * 2048 + 1
|
|
#define DISCORD_MAX_USERNAME_LEN 4 * 32 + 1
|
|
#define DISCORD_MAX_DISCRIMINATOR_LEN 4 + 1
|
|
#define DISCORD_MAX_REASON_LEN 4 * 512 + 1
|
|
#define DISCORD_MAX_MESSAGE_LEN 4 * 2000 + 1
|
|
#define DISCORD_MAX_PAYLOAD_LEN 4 * 4096 + 1
|
|
/** @} DiscordConstantsGeneral */
|
|
|
|
/** @defgroup DiscordConstantsEmbed Embed lengths
|
|
* @brief Max length for embed fields
|
|
* @{ */
|
|
#define DISCORD_EMBED_TITLE_LEN 4 * 256 + 1
|
|
#define DISCORD_EMBED_DESCRIPTION_LEN 4 * 4096 + 1
|
|
#define DISCORD_EMBED_MAX_FIELDS 25
|
|
#define DISCORD_EMBED_FIELD_NAME_LEN 4 * 256 + 1
|
|
#define DISCORD_EMBED_FIELD_VALUE_LEN 4 * 1024 + 1
|
|
#define DISCORD_EMBED_FOOTER_TEXT_LEN 4 * 2048 + 1
|
|
#define DISCORD_EMBED_AUTHOR_NAME_LEN 4 * 256 + 1
|
|
/** @} DiscordConstantsEmbed */
|
|
|
|
/** @defgroup DiscordConstantsWebhook Webhook lengths
|
|
* @brief Max length for embed fields
|
|
* @{ */
|
|
#define DISCORD_WEBHOOK_NAME_LEN 4 * 80 + 1
|
|
/** @} DiscordConstantsWebhook */
|
|
|
|
/** @} DiscordConstants */
|
|
|
|
/** @addtogroup ConcordError
|
|
* @{ */
|
|
|
|
/* XXX: As new values are added, discord_strerror() and
|
|
* discord_code_as_string() should be updated accordingly! */
|
|
/** @defgroup DiscordError Discord error codes
|
|
* @brief Error codes triggered from Discord
|
|
* @{ */
|
|
|
|
/** Alias for @ref CCORD_OK */
|
|
#define CCORD_DISCORD_OK CCORD_OK
|
|
/** action is pending (ex: request has been enqueued and will be performed
|
|
* later) */
|
|
#define CCORD_PENDING 1
|
|
/** received a JSON error message */
|
|
#define CCORD_DISCORD_JSON_CODE 100
|
|
/** bad authentication token */
|
|
#define CCORD_DISCORD_BAD_AUTH 101
|
|
/** being ratelimited */
|
|
#define CCORD_DISCORD_RATELIMIT 102
|
|
/** couldn't establish connection to Discord */
|
|
#define CCORD_DISCORD_CONNECTION 103
|
|
|
|
/**
|
|
* @brief Return the value of CCORDcode as a string
|
|
*
|
|
* @param code the CCORDcode value
|
|
* @return the enum value as a string
|
|
*/
|
|
const char *discord_code_as_string(CCORDcode code);
|
|
|
|
/**
|
|
* @brief Return the meaning of CCORDcode
|
|
*
|
|
* @param code the CCORDcode value
|
|
* @param client @note unused parameter
|
|
* @return a string containing the code meaning
|
|
*/
|
|
const char *discord_strerror(CCORDcode code, struct discord *client);
|
|
|
|
/** @} DiscordError */
|
|
|
|
/** @} ConcordError */
|
|
|
|
/** @defgroup DiscordAPI API
|
|
* @brief The Discord public API supported by Concord
|
|
* @{ */
|
|
|
|
#include "audit_log.h"
|
|
#include "auto_moderation.h"
|
|
#include "invite.h"
|
|
#include "channel.h"
|
|
#include "emoji.h"
|
|
#include "guild.h"
|
|
#include "guild_scheduled_event.h"
|
|
#include "guild_template.h"
|
|
#include "stage_instance.h"
|
|
#include "sticker.h"
|
|
#include "user.h"
|
|
#include "voice.h"
|
|
#include "webhook.h"
|
|
#include "gateway.h"
|
|
#include "oauth2.h"
|
|
/** @defgroup DiscordAPIInteractions Interactions
|
|
* @brief Interactions public API supported by Concord
|
|
* @{ */
|
|
#include "application_command.h"
|
|
#include "interaction.h"
|
|
/** @} DiscordAPIInteractions */
|
|
|
|
/** @} DiscordAPI */
|
|
|
|
/** @addtogroup DiscordClient
|
|
* @brief Client functions and datatypes
|
|
* @{ */
|
|
|
|
/** @struct discord */
|
|
|
|
#include "discord-cache.h"
|
|
#include "discord-events.h"
|
|
|
|
/**
|
|
* @brief Claim ownership of a resource provided by Concord
|
|
* @see discord_unclaim()
|
|
*
|
|
* @param client the client initialized with discord_from_token()
|
|
* @param data a resource provided by Concord
|
|
* @return pointer to `data` (for one-liners)
|
|
*/
|
|
#define discord_claim(client, data) (__discord_claim(client, data), data)
|
|
void __discord_claim(struct discord *client, const void *data);
|
|
|
|
/**
|
|
* @brief Unclaim ownership of a resource provided by Concord
|
|
* @note this will make the resource eligible for cleanup, so this should
|
|
* only be called when you no longer plan to use it
|
|
* @see discord_claim()
|
|
*
|
|
* @param client the client initialized with discord_from_token()
|
|
* @param data a resource provided by Concord, that has been
|
|
* previously claimed with discord_claim()
|
|
*/
|
|
void discord_unclaim(struct discord *client, const void *data);
|
|
|
|
/** @deprecated since v3.0.0, keep backwards compatibility */
|
|
#define ccord_global_init()
|
|
|
|
/** @deprecated since v3.0.0, keep backwards compatibility */
|
|
#define ccord_global_cleanup()
|
|
|
|
/**
|
|
* @brief Gracefully notify all Discord connections for shutting down
|
|
*
|
|
* @note this function will not wait before returning, and will
|
|
* return immediately. The shutdown process will be handled
|
|
* in the background.
|
|
*/
|
|
void discord_shutdown_all(void);
|
|
|
|
/**
|
|
* @brief Check if all Discord connections shutting down is in progress
|
|
*
|
|
* @return true if all shutdown is in progress, false otherwise
|
|
*/
|
|
bool discord_shutdown_all_ongoing(void);
|
|
|
|
/**
|
|
* @brief Backwards compatible alias for discord_shutdown_all()
|
|
* @deprecated since v3.0.0
|
|
*/
|
|
#define ccord_shutdown_async() discord_shutdown_all()
|
|
|
|
/**
|
|
* @brief Creates a Discord Client handle from a token
|
|
* @see discord_get_logmod() to configure logging behavior
|
|
*
|
|
* @param token the bot token
|
|
* @return the newly created Discord Client handle
|
|
*/
|
|
struct discord *discord_from_token(const char token[]);
|
|
|
|
/**
|
|
* @brief Creates a Discord Client handle from a `config.json` file
|
|
* @see discord_get_logmod() to configure logging behavior
|
|
*
|
|
* @param config_file the `config.json` file name
|
|
* @return the newly created Discord Client handle
|
|
*/
|
|
struct discord *discord_from_json(const char config_file[]);
|
|
|
|
/**
|
|
* @brief The Discord configuration handler
|
|
*
|
|
* This struct is used to store the Discord client configuration
|
|
*/
|
|
struct discord_config {
|
|
/** the bot token */
|
|
char *token;
|
|
/**
|
|
* optional override for the REST API base URL
|
|
* (e.g. `"http://127.0.0.1:8080"` for a local test server)
|
|
* @note when `NULL` (the default) @ref DISCORD_API_BASE_URL is used
|
|
* @note only read during client initialization and copied by the
|
|
* User-Agent layer; the client does not take ownership and will
|
|
* never free this pointer
|
|
*/
|
|
char *base_url;
|
|
struct {
|
|
/** minimum logging level */
|
|
enum logmod_levels level;
|
|
/** silence terminal logging */
|
|
bool quiet;
|
|
/** enable color to terminal logging */
|
|
bool color;
|
|
/** overwrite existing files */
|
|
bool overwrite;
|
|
/* the trace log file */
|
|
FILE *trace;
|
|
/* the http log file */
|
|
FILE *http;
|
|
/* the ws log file */
|
|
FILE *ws;
|
|
struct {
|
|
size_t size;
|
|
char **ids;
|
|
} disable; /**< list of 'id' that should be ignored */
|
|
} log; /**< logging directives */
|
|
};
|
|
|
|
/**
|
|
* @brief Creates a Discord Client handle from a
|
|
* @ref discord_config structure
|
|
* @see discord_get_logmod() to configure logging behavior
|
|
*
|
|
* @param config the @ref discord_config structure
|
|
* @return the newly created Discord Client handle
|
|
*/
|
|
struct discord *discord_from_config(const struct discord_config *config);
|
|
|
|
/**
|
|
* @brief Backwards compatible alias for discord_from_token()
|
|
* @deprecated since v3.0.0
|
|
*/
|
|
#define discord_init discord_from_token
|
|
|
|
/**
|
|
* @brief Backwards compatible alias for discord_from_json()
|
|
* @deprecated since v3.0.0
|
|
*/
|
|
#define discord_config_init discord_from_json
|
|
|
|
/**
|
|
* @brief Get the contents from the config file field
|
|
* @note your bot **MUST** have been initialized with discord_from_json()
|
|
*
|
|
* @code{.c}
|
|
* // Assume the following custom config.json field to be extracted
|
|
* // "field": { "foo": "a string", "bar": 1234 }
|
|
*
|
|
* ...
|
|
* struct ccord_szbuf_readonly value;
|
|
* char foo[128];
|
|
* long bar;
|
|
*
|
|
* // field.foo
|
|
* value = discord_config_get_field(client, (char *[2]){ "field", "foo" }, 2);
|
|
* snprintf(foo, sizeof(foo), "%.*s", (int)value.size, value.start);
|
|
* // field.bar
|
|
* value = discord_config_get_field(client, (char *[2]){ "field", "bar" }, 2);
|
|
* bar = strtol(value.start, NULL, 10);
|
|
*
|
|
* printf("%s %ld", foo, bar); // "a string" 1234
|
|
* @endcode
|
|
*
|
|
* @param client the client created with discord_from_json()
|
|
* @param path the JSON key path
|
|
* @param depth the path depth
|
|
* @return a read-only sized buffer containing the field's contents
|
|
*/
|
|
struct ccord_szbuf_readonly discord_config_get_field(struct discord *client,
|
|
char *const path[],
|
|
unsigned depth);
|
|
|
|
/**
|
|
* @brief Clone a discord client
|
|
*
|
|
* Should be called before entering a thread, to ensure each thread
|
|
* has its own client instance with unique buffers, url and headers
|
|
* @param orig the original client created with discord_from_token()
|
|
* @return the client clone
|
|
*/
|
|
|
|
struct discord *discord_clone(const struct discord *orig);
|
|
|
|
/**
|
|
* @brief Free a Discord Client handle
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
*/
|
|
|
|
void discord_cleanup(struct discord *client);
|
|
|
|
/**
|
|
* @brief Get the client's cached user
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @warning the returned structure should NOT be modified
|
|
*/
|
|
|
|
const struct discord_user *discord_get_self(struct discord *client);
|
|
|
|
/**
|
|
* @brief Start a connection to the Discord Gateway
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @CCORD_return
|
|
*/
|
|
CCORDcode discord_run(struct discord *client);
|
|
|
|
/**
|
|
* @brief Gracefully shutdown an ongoing Discord connection
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
*/
|
|
void discord_shutdown(struct discord *client);
|
|
|
|
/**
|
|
* @brief Gracefully reconnects an ongoing Discord connection
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @param resume true to attempt to resume to previous session,
|
|
* false restart a fresh session
|
|
*/
|
|
void discord_reconnect(struct discord *client, bool resume);
|
|
|
|
/**
|
|
* @brief Store user arbitrary data that can be retrieved by discord_get_data()
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @param data user arbitrary data
|
|
* @return pointer to user data
|
|
* @warning the user should provide their own locking mechanism to protect
|
|
* its data from race conditions
|
|
*/
|
|
void *discord_set_data(struct discord *client, void *data);
|
|
|
|
/**
|
|
* @brief Receive user arbitrary data stored with discord_set_data()
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @return pointer to user data
|
|
* @warning the user should provide their own locking mechanism to protect
|
|
* its data from race conditions
|
|
*/
|
|
void *discord_get_data(struct discord *client);
|
|
|
|
/**
|
|
* @brief Get the client WebSockets ping
|
|
* @note Only works after a connection has been established via
|
|
* discord_run()
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @return the ping in milliseconds
|
|
*/
|
|
int discord_get_ping(struct discord *client);
|
|
|
|
/**
|
|
* @brief Get the current timestamp (in milliseconds)
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @return the timestamp in milliseconds
|
|
*/
|
|
uint64_t discord_timestamp(struct discord *client);
|
|
|
|
/**
|
|
* @brief Get the current timestamp (in microseconds)
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @return the timestamp in microseconds
|
|
*/
|
|
uint64_t discord_timestamp_us(struct discord *client);
|
|
|
|
/**
|
|
* @brief Retrieve client's logging module for configuration purposes
|
|
* @see logmod.h
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @return the client's logging manager
|
|
*/
|
|
struct logmod *discord_get_logmod(struct discord *client);
|
|
|
|
/**
|
|
* @brief get the io_poller used by the discord client
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @return struct io_poller*
|
|
*/
|
|
struct io_poller *discord_get_io_poller(struct discord *client);
|
|
|
|
/** @addtogroup DiscordDataWrap Data Wrap
|
|
* @brief Helpers for wrapping Discord data types for easier management
|
|
* @{ */
|
|
|
|
#define __CAT(_a, _b) _a##_b
|
|
#define _CAT(_a, _b) __CAT(_a, _b)
|
|
#define _EXPECT_CONTAINER__struct
|
|
#define _EXPECT_CONTAINER__union
|
|
#define _DISCORD_SYMBOL_WITHOUT_CONTAINER(_symbol) \
|
|
_CAT(_EXPECT_CONTAINER__, _symbol)
|
|
|
|
/**
|
|
* @brief The Discord data wrap structure
|
|
*
|
|
* This struct is used to wrap Discord data types for easier management
|
|
*/
|
|
#define discord_data_wrap reflectc_wrap
|
|
|
|
/**
|
|
* @brief Wrap a Discord data type into a reflectc_wrap structure
|
|
*
|
|
* @param _symbol the Discord data type symbol (with struct or union)
|
|
* @param _client the client created with discord_from_token()
|
|
* @param _data the Discord data type to be wrapped
|
|
* @return the @ref discord_data_wrap Discord data type
|
|
*/
|
|
#define discord_data_wrap_from(_symbol, _client, _data) \
|
|
_CAT(reflectc_from_, _DISCORD_SYMBOL_WITHOUT_CONTAINER(_symbol))( \
|
|
discord_get_registry((_client)), _data, NULL)
|
|
|
|
/**
|
|
* @brief Cleanup a Discord data type wrapped into a reflectc_wrap structure
|
|
*
|
|
* Releases everything discord_data_from_json() allocated for `_data` —
|
|
* strings, nested objects, list arrays — plus the reflect-c wrap and its
|
|
* registry entry. Every non-NULL pointer member is treated as owned: do
|
|
* not call this on hand-built structs pointing at literals or stack
|
|
* objects.
|
|
*
|
|
* @param _client the client created with discord_from_token()
|
|
* @param _data the Discord data type to be cleaned up
|
|
*/
|
|
#define discord_data_cleanup(_client, _data) \
|
|
discord_data_free(discord_get_registry((_client)), (_data))
|
|
|
|
/** Function backing @ref discord_data_cleanup; see its contract */
|
|
void discord_data_free(struct reflectc *registry, void *data);
|
|
|
|
/**
|
|
* @brief Drop the wrap cached for `_data` without touching its contents
|
|
*
|
|
* discord_data_to_json() caches a reflect-c wrap keyed by `_data`'s
|
|
* address; release it with this once done encoding a caller-owned
|
|
* struct (e.g. stack-built params). Without it the stale registry entry
|
|
* would be wrongly reused by a future object at the same address.
|
|
* Decoded structs don't need this — discord_data_cleanup() releases
|
|
* both the data and the wrap.
|
|
*
|
|
* @param _client the client created with discord_from_token()
|
|
* @param _data the encoded Discord data type to drop the wrap for
|
|
*/
|
|
#define discord_data_unwrap(_client, _data) \
|
|
discord_data_release(discord_get_registry((_client)), (_data))
|
|
|
|
/** Function backing @ref discord_data_unwrap */
|
|
void discord_data_release(struct reflectc *registry, void *data);
|
|
|
|
/** @addtogroup DiscordDataWrapJSON JSON Conversion
|
|
* @brief Helpers for converting Discord data types to/from JSON
|
|
* @{ */
|
|
|
|
/* forward declaration */
|
|
struct jsmnf_pair;
|
|
struct jsonb;
|
|
|
|
/**
|
|
* @brief Transform a wrapped Discord data type into a JSON string
|
|
*
|
|
* @param member the wrapped Discord data type
|
|
* @param p_buf pointer to the JSON buffer
|
|
* @param p_bufsize pointer to the JSON buffer size
|
|
* @CCORD_return
|
|
*/
|
|
CCORDcode discord_data_wrap_to_json(const struct discord_data_wrap *member,
|
|
char *p_buf[],
|
|
size_t *p_bufsize);
|
|
|
|
/**
|
|
* @brief Transform a Discord data type into a JSON string
|
|
*
|
|
* @param _symbol the Discord data type symbol (with struct or union)
|
|
* @param _client the client created with discord_from_token()
|
|
* @param _data the Discord data type to be transformed
|
|
* @param _p_buf pointer to the JSON buffer
|
|
* @param _p_bufsize pointer to the JSON buffer size
|
|
* @CCORD_return
|
|
*/
|
|
#define discord_data_to_json(_symbol, _client, _data, _p_buf, _p_bufsize) \
|
|
discord_data_wrap_to_json( \
|
|
discord_data_wrap_from(_symbol, _client, _data), _p_buf, _p_bufsize)
|
|
|
|
/**
|
|
* @brief Transform a wrapped Discord data type into a jsonb handle
|
|
*
|
|
* @param jb the jsonb handle
|
|
* @param member the wrapped Discord data type
|
|
* @param p_buf pointer to the JSON buffer
|
|
* @param p_bufsize pointer to the JSON buffer size
|
|
* @CCORD_return
|
|
*/
|
|
CCORDcode discord_data_wrap_to_jsonb(struct jsonb *jb,
|
|
const struct discord_data_wrap *member,
|
|
char *p_buf[],
|
|
size_t *p_bufsize);
|
|
|
|
/**
|
|
* @brief Transform a Discord data type into a jsonb handle
|
|
*
|
|
* @param _symbol the Discord data type symbol (with struct or union)
|
|
* @param _client the client created with discord_from_token()
|
|
* @param _jb the jsonb handle
|
|
* @param _data the Discord data type to be transformed
|
|
* @param _p_buf pointer to the JSON buffer
|
|
* @param _p_bufsize pointer to the JSON buffer size
|
|
* @CCORD_return
|
|
*/
|
|
#define discord_data_to_jsonb(_symbol, _client, _jb, _data, _p_buf, \
|
|
_p_bufsize) \
|
|
discord_data_wrap_to_jsonb( \
|
|
_jb, discord_data_wrap_from(_symbol, _client, _data), _p_buf, \
|
|
_p_bufsize)
|
|
|
|
/**
|
|
* @brief Parse a JSON string and fill a wrapped Discord data type
|
|
*
|
|
* @param json the JSON string
|
|
* @param len length of @ref json
|
|
* @param root the root wrapped Discord data type
|
|
* @CCORD_return
|
|
*/
|
|
CCORDcode discord_data_wrap_from_json(const char *json,
|
|
size_t len,
|
|
struct discord_data_wrap *root);
|
|
|
|
/**
|
|
* @brief Parse a JSON string and fill a Discord data type
|
|
*
|
|
* @param _symbol the Discord data type symbol (with struct or union)
|
|
* @param _client the client created with discord_from_token()
|
|
* @param _json the JSON string
|
|
* @param _len length of @ref json
|
|
* @param _data the Discord data type to be filled
|
|
* @CCORD_return
|
|
*/
|
|
#define discord_data_from_json(_symbol, _client, _json, _len, _data) \
|
|
discord_data_wrap_from_json( \
|
|
_json, _len, discord_data_wrap_from(_symbol, _client, _data))
|
|
|
|
/**
|
|
* @brief Parse a jsmnf_pair and fill a wrapped Discord data type
|
|
*
|
|
* @param p the jsmnf_pair
|
|
* @param json the JSON string
|
|
* @param length length of @ref json
|
|
* @param member the wrapped Discord data type
|
|
* @CCORD_return
|
|
*/
|
|
CCORDcode discord_data_wrap_from_jsmnf(const struct jsmnf_pair *p,
|
|
const char *json,
|
|
size_t length,
|
|
const struct discord_data_wrap *member);
|
|
|
|
/**
|
|
* @brief Parse a jsmnf_pair and fill a Discord data type
|
|
*
|
|
* @param _client the client created with discord_from_token()
|
|
* @param _p the jsmnf_pair
|
|
* @param _json the JSON string
|
|
* @param _length length of @ref json
|
|
* @param _type the Discord data type symbol (without struct/union)
|
|
* @param _data the Discord data type to be filled
|
|
* @CCORD_return
|
|
*/
|
|
#define discord_data_from_jsmnf(_client, _p, _json, _length, _type, _data) \
|
|
discord_data_wrap_from_jsmnf( \
|
|
_p, _json, _length, discord_data_wrap_from(_type, _client, _data))
|
|
|
|
/** @} DiscordDataWrapJSON */
|
|
|
|
/** @} DiscordDataWrap */
|
|
|
|
/** @addtogroup DiscordTimer Timer
|
|
* @brief Schedule callbacks to be called in the future
|
|
* @{ */
|
|
|
|
/* forward declaration */
|
|
struct discord_timer;
|
|
/**/
|
|
|
|
/** @brief callback to be used with struct discord_timer */
|
|
typedef void (*discord_ev_timer)(struct discord *client,
|
|
struct discord_timer *ev);
|
|
|
|
/** @brief flags used to change behaviour of timer */
|
|
enum discord_timer_flags {
|
|
/** use milliseconds for interval and start_time */
|
|
DISCORD_TIMER_MILLISECONDS = 0,
|
|
/** use microseconds for interval and start_time */
|
|
DISCORD_TIMER_MICROSECONDS = 1 << 0,
|
|
/** whether or not timer is marked for deletion */
|
|
DISCORD_TIMER_DELETE = 1 << 1,
|
|
/** automatically delete a timer once its repeat counter runs out */
|
|
DISCORD_TIMER_DELETE_AUTO = 1 << 2,
|
|
/** timer has been canceled. user should cleanup only */
|
|
DISCORD_TIMER_CANCELED = 1 << 3,
|
|
/** flag is set when on_tick callback has been called */
|
|
DISCORD_TIMER_TICK = 1 << 4,
|
|
/** used in discord_timer_ctl to get the timer's data */
|
|
DISCORD_TIMER_GET = 1 << 5,
|
|
/** timer should run using a fixed interval based on start time */
|
|
DISCORD_TIMER_INTERVAL_FIXED = 1 << 6,
|
|
};
|
|
|
|
/** @brief struct used for modifying, and getting info about a timer */
|
|
struct discord_timer {
|
|
/** the identifier used for the timer. 0 creates a new timer */
|
|
unsigned id;
|
|
/** the flags used to manipulate the timer */
|
|
enum discord_timer_flags flags;
|
|
/** (nullable) the callback that should be called when timer triggers */
|
|
discord_ev_timer on_tick;
|
|
/** (nullable) the callback for status updates timer->flags
|
|
* will have: DISCORD_TIMER_CANCELED, and DISCORD_TIMER_DELETE */
|
|
discord_ev_timer on_status_changed;
|
|
/** user data */
|
|
void *data;
|
|
/** delay before timer should start */
|
|
int64_t delay;
|
|
/** interval that the timer should repeat at. must be >= 0 */
|
|
int64_t interval;
|
|
/** how many times a timer should repeat (-1 == infinity) */
|
|
int64_t repeat;
|
|
};
|
|
|
|
/**
|
|
* @brief modifies or creates a timer
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @param timer the timer that should be modified
|
|
* @return the id of the timer
|
|
*/
|
|
unsigned discord_timer_ctl(struct discord *client,
|
|
struct discord_timer *timer);
|
|
|
|
/**
|
|
* @brief creates a one shot timer that automatically
|
|
* deletes itself upon completion
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @param on_tick_cb (nullable) the callback that should be called when timer
|
|
* triggers
|
|
* @param on_status_changed_cb (nullable) the callback for status updates
|
|
* timer->flags will have: DISCORD_TIMER_CANCELED, and DISCORD_TIMER_DELETE
|
|
* @param data user data
|
|
* @param delay delay before timer should start in milliseconds
|
|
* @return the id of the timer
|
|
*/
|
|
unsigned discord_timer(struct discord *client,
|
|
discord_ev_timer on_tick_cb,
|
|
discord_ev_timer on_status_changed_cb,
|
|
void *data,
|
|
int64_t delay);
|
|
|
|
/**
|
|
* @brief creates a repeating timer that automatically
|
|
* deletes itself upon completion
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @param on_tick_cb (nullable) the callback that should be called when timer
|
|
* triggers
|
|
* @param on_status_changed_cb (nullable) the callback for status updates
|
|
* timer->flags will have: DISCORD_TIMER_CANCELED, and DISCORD_TIMER_DELETE
|
|
* @param data user data
|
|
* @param delay delay before timer should start in milliseconds
|
|
* @param interval interval between runs. (-1 == disable repeat)
|
|
* @param repeat repetitions (-1 == infinity)
|
|
* @return the id of the timer
|
|
*/
|
|
unsigned discord_timer_interval(struct discord *client,
|
|
discord_ev_timer on_tick_cb,
|
|
discord_ev_timer on_status_changed_cb,
|
|
void *data,
|
|
int64_t delay,
|
|
int64_t interval,
|
|
int64_t repeat);
|
|
|
|
/**
|
|
* @brief get the data associated with the timer
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @param id id of the timer
|
|
* @param timer where to copy the timer data to
|
|
* @return true on success
|
|
*/
|
|
bool discord_timer_get(struct discord *client,
|
|
unsigned id,
|
|
struct discord_timer *timer);
|
|
|
|
/**
|
|
* @brief starts a timer
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @param id id of the timer
|
|
* @return true on success
|
|
*/
|
|
bool discord_timer_start(struct discord *client, unsigned id);
|
|
|
|
/**
|
|
* @brief stops a timer
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @param id id of the timer
|
|
* @return true on success
|
|
*/
|
|
bool discord_timer_stop(struct discord *client, unsigned id);
|
|
|
|
/**
|
|
* @brief cancels a timer,
|
|
* this will delete the timer if DISCORD_TIMER_DELETE_AUTO is enabled
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @param id id of the timer
|
|
* @return true on success
|
|
*/
|
|
bool discord_timer_cancel(struct discord *client, unsigned id);
|
|
|
|
/**
|
|
* @brief deletes a timer
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @param id id of the timer
|
|
* @return true on success
|
|
*/
|
|
bool discord_timer_delete(struct discord *client, unsigned id);
|
|
|
|
/**
|
|
* @brief cancels, and deletes a timer
|
|
*
|
|
* @param client the client created with discord_from_token()
|
|
* @param id id of the timer
|
|
* @return true on success
|
|
*/
|
|
bool discord_timer_cancel_and_delete(struct discord *client, unsigned id);
|
|
|
|
/** @example timers.c
|
|
* Demonstrates the Timer API for callback scheduling */
|
|
|
|
/** @} DiscordTimer */
|
|
/** @} DiscordClient */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
|
|
#endif /* DISCORD_H */
|