Concord - C Discord API library
A Discord API wrapper library written in C
slash-commands2.c

Demonstrates registering and reacting to slash commands from the console

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <pthread.h>
#include <assert.h>
#include <errno.h>
#include <inttypes.h> /* SCNu64 */
#include "discord.h"
#include "log.h"
u64snowflake g_app_id;
void
print_usage(void)
{
printf("\n\nThis bot demonstrates how easy it is to create/update/delete "
"application commands\n"
"1. Input a valid application id from "
"https://discord.com/developers/applications\n"
"2. Type HELP to see commands\n"
"\nTYPE ANY KEY TO START BOT\n");
}
void
print_help(void)
{
log_info("\nHelp :\n"
"\tPrint help : HELP\n"
"\tList Commands : LIST <?guild_id>\n"
"\tCreate Command : CREATE <cmd_name>[<cmd_desc>] <?guild_id>\n"
"\tUpdate Command : UPDATE <cmd_id> <cmd_name>[<cmd_desc>] "
"<?guild_id>\n"
"\tDelete Command : DELETE <cmd_id> <?guild_id>\n");
}
void
on_ready(struct discord *client, const struct discord_ready *event)
{
log_info("Slash-Commands-Bot succesfully connected to Discord as %s#%s!",
event->user->username, event->user->discriminator);
}
void
fail_interaction_create(struct discord *client, struct discord_response *resp)
{
log_error("%s", discord_strerror(resp->code, client));
}
void
on_interaction_create(struct discord *client,
const struct discord_interaction *event)
{
log_info("Interaction %" PRIu64 " received", event->id);
.content = "Hello World!",
};
struct discord_interaction_response params = {
.data = &data,
};
.fail = &fail_interaction_create
};
&params, &ret);
}
void *
read_input(void *p_client)
{
struct discord *client = p_client;
ptrdiff_t bufoffset;
char cmd_action[9 + 1];
CCORDcode code;
pthread_detach(pthread_self());
while (1) {
memset(buf, 0, sizeof(buf));
fgets(buf, sizeof(buf), stdin);
if (!*buf) continue; // is empty
memset(cmd_action, 0, sizeof(cmd_action));
sscanf(buf, "%s", cmd_action);
bufoffset = strlen(cmd_action) + 1;
if (!*cmd_action || 0 == strcasecmp(cmd_action, "HELP")) goto _help;
if (0 == strcasecmp(cmd_action, "LIST")) {
struct discord_application_commands app_cmds = { 0 };
u64snowflake guild_id = 0;
sscanf(buf + bufoffset, "%" SCNu64, &guild_id);
.sync = &app_cmds,
};
if (guild_id)
code = discord_get_guild_application_commands(client, g_app_id,
guild_id, &ret);
else
g_app_id, &ret);
if (CCORD_OK == code && app_cmds.size) {
char list[4096] = ""; // should be large enough ?
size_t len = 0;
for (int i = 0; i < app_cmds.size; ++i) {
len +=
snprintf(list + len, sizeof(list) - len,
"\t%d:\t%s (%" PRIu64 ")\n", i,
app_cmds.array[i].name, app_cmds.array[i].id);
}
log_info("\nCommands: \n%.*s", (int)len, list);
}
else {
log_error("Couldn't list commands");
}
}
else if (0 == strcasecmp(cmd_action, "CREATE")) {
char cmd_name[32 + 1] = "", cmd_desc[100 + 1] = "";
struct discord_application_command app_cmd = { 0 };
sscanf(buf + bufoffset, "%32[^[][%100[^]]] %" SCNu64, cmd_name,
cmd_desc, &guild_id);
if (!*cmd_name || !*cmd_desc) goto _help;
.sync = &app_cmd,
};
if (guild_id) {
.name = cmd_name,
.description = cmd_desc,
.default_permission = true,
.type = 1,
};
client, g_app_id, guild_id, &params, &ret);
}
else {
.name = cmd_name,
.description = cmd_desc,
.default_permission = true,
.type = 1,
};
client, g_app_id, &params, &ret);
}
if (CCORD_OK == code && app_cmd.id) {
log_info("Created command:\t%s (" PRIu64 ")", app_cmd.name,
app_cmd.id);
}
else {
log_error("Couldn't create command '%s'", cmd_name);
}
}
else if (0 == strcasecmp(cmd_action, "UPDATE")) {
char cmd_name[32 + 1] = "", cmd_desc[100 + 1] = "";
u64snowflake command_id = 0, guild_id = 0;
sscanf(buf + bufoffset, "%" SCNu64 " %32[^[][%100[^]]] %" SCNu64,
&command_id, cmd_name, cmd_desc, &guild_id);
if (!command_id) goto _help;
struct discord_application_command app_cmd = { 0 };
.sync = &app_cmd,
};
if (guild_id) {
.name = *cmd_name ? cmd_name : NULL,
.description = *cmd_desc ? cmd_desc : NULL,
.default_permission = true,
};
client, g_app_id, guild_id, command_id, &params, &ret);
}
else {
.name = *cmd_name ? cmd_name : NULL,
.description = *cmd_desc ? cmd_desc : NULL,
.default_permission = true,
};
client, g_app_id, command_id, &params, &ret);
}
if (CCORD_OK == code && app_cmd.id) {
log_info("Edited command:\t%s (%" PRIu64 ")", app_cmd.name,
app_cmd.id);
}
else {
log_error("Couldn't create command '%s'", cmd_name);
}
}
else if (0 == strcasecmp(cmd_action, "DELETE")) {
u64snowflake command_id = 0, guild_id = 0;
sscanf(buf + bufoffset, "%" SCNu64 "%" SCNu64, &command_id,
&guild_id);
if (!command_id) goto _help;
struct discord_ret ret = { .sync = true };
if (guild_id) {
client, g_app_id, guild_id, command_id, &ret);
}
else {
client, g_app_id, command_id, &ret);
}
if (CCORD_OK == code)
log_info("Deleted command");
else
log_error("Couldn't delete command");
}
else {
goto _help;
}
continue;
_help:
print_help();
}
pthread_exit(NULL);
}
int
main(int argc, char *argv[])
{
const char *config_file;
if (argc > 1)
config_file = argv[1];
else
config_file = "../config.json";
struct discord *client = discord_config_init(config_file);
assert(NULL != client && "Could not initialize client");
discord_set_on_ready(client, &on_ready);
discord_set_on_interaction_create(client, &on_interaction_create);
print_usage();
fgetc(stdin); // wait for input
printf("Please provide a valid application id in order to test the Slash "
"Commands functionality, it can be obtained from: "
"https://discord.com/developers/applications\n");
do {
printf("Application ID:\n");
fscanf(stdin, "%" SCNu64, &g_app_id);
} while (!g_app_id || errno == ERANGE);
pthread_t tid;
pthread_create(&tid, NULL, &read_input, client);
discord_run(client);
discord_cleanup(client);
}
void discord_application_commands_cleanup(struct discord_application_commands *self)
void discord_application_command_cleanup(struct discord_application_command *self)
CCORDcode ccord_global_init()
Initialize global shared-resources not API-specific.
void ccord_global_cleanup()
Cleanup global shared-resources.
Public functions and datatypes.
CCORDcode
Definition: error.h:12
const char * discord_strerror(CCORDcode code, struct discord *client)
Return the meaning of CCORDcode.
@ CCORD_OK
Definition: error.h:42
uint64_t u64snowflake
Snowflake datatype.
Definition: types.h:28
#define DISCORD_MESSAGE_EPHEMERAL
Definition: channel.h:41
CCORDcode discord_create_global_application_command(struct discord *client, u64snowflake application_id, struct discord_create_global_application_command *params, struct discord_ret_application_command *ret)
Create a new global command.
CCORDcode discord_edit_guild_application_command(struct discord *client, u64snowflake application_id, u64snowflake guild_id, u64snowflake command_id, struct discord_edit_guild_application_command *params, struct discord_ret_application_command *ret)
Edit a guild command.
CCORDcode discord_delete_guild_application_command(struct discord *client, u64snowflake application_id, u64snowflake guild_id, u64snowflake command_id, struct discord_ret *ret)
Deletes a guild command.
CCORDcode discord_edit_global_application_command(struct discord *client, u64snowflake application_id, u64snowflake command_id, struct discord_edit_global_application_command *params, struct discord_ret_application_command *ret)
Edit a global command.
CCORDcode discord_create_guild_application_command(struct discord *client, u64snowflake application_id, u64snowflake guild_id, struct discord_create_guild_application_command *params, struct discord_ret_application_command *ret)
Create a new guild command.
CCORDcode discord_get_global_application_commands(struct discord *client, u64snowflake application_id, struct discord_ret_application_commands *ret)
Fetch all of the global commands for your application.
CCORDcode discord_delete_global_application_command(struct discord *client, u64snowflake application_id, u64snowflake command_id, struct discord_ret *ret)
Deletes a global command.
CCORDcode discord_get_guild_application_commands(struct discord *client, u64snowflake application_id, u64snowflake guild_id, struct discord_ret_application_commands *ret)
Fetch all of the guild commands of a given guild.
CCORDcode discord_create_interaction_response(struct discord *client, u64snowflake interaction_id, const char interaction_token[], struct discord_interaction_response *params, struct discord_ret_interaction_response *ret)
Create a response to an Interaction from the gateway.
void discord_cleanup(struct discord *client)
Free a Discord Client handle.
CCORDcode discord_run(struct discord *client)
Start a connection to the Discord Gateway.
struct discord * discord_config_init(const char config_file[])
Create a Discord Client handle by a config.json file.
#define DISCORD_MAX_MESSAGE_LEN
Definition: discord.h:64
void discord_set_on_interaction_create(struct discord *client, void(*callback)(struct discord *client, const struct discord_interaction *event))
Triggers when user has used an interaction, such as an application command.
void discord_set_on_ready(struct discord *client, void(*callback)(struct discord *client, const struct discord_ready *event))
Triggers when the client session is ready.
@ DISCORD_INTERACTION_CHANNEL_MESSAGE_WITH_SOURCE
Definition: interactions.h:33
#define log_error(...)
Definition: log.h:54
#define log_info(...)
Definition: log.h:52
Definition: application_commands.h:56
u64snowflake id
Definition: application_commands.h:59
char * name
Definition: application_commands.h:75
u64snowflake guild_id
Definition: application_commands.h:71
Definition: application_commands.h:107
struct discord_application_command * array
Definition: application_commands.h:108
int size
Definition: application_commands.h:107
Definition: application_commands.h:208
char * name
Definition: application_commands.h:210
Definition: application_commands.h:254
char * name
Definition: application_commands.h:256
Definition: application_commands.h:233
char * name
Definition: application_commands.h:235
Definition: application_commands.h:279
char * name
Definition: application_commands.h:281
Definition: interactions.h:133
char * content
Definition: interactions.h:145
Definition: interactions.h:125
enum discord_interaction_callback_types type
Definition: interactions.h:127
struct discord_interaction_callback_data * data
Definition: interactions.h:130
Definition: interactions.h:48
u64snowflake id
Definition: interactions.h:50
char * token
Definition: interactions.h:66
Definition: gateway.h:332
struct discord_user * user
Definition: gateway.h:336
The response for the completed request.
Definition: discord-response.h:12
CCORDcode code
Definition: discord-response.h:18
Request's return context.
Definition: discord-response.h:169
struct discord_application_command * sync
Definition: discord-response.h:169
Request's return context.
Definition: discord-response.h:170
struct discord_application_commands * sync
Definition: discord-response.h:170
Request's return context.
Definition: discord-response.h:179
void(* fail)(struct discord *client, struct discord_response *resp)
Definition: discord-response.h:179
Request's return context.
Definition: discord-response.h:54
char * username
Definition: user.h:73
char * discriminator
Definition: user.h:75
The Discord client handler.
Definition: discord-internal.h:1182