Development has been happening in the dev branch. We are working on new features and improvements. To access the latest version of the library, please check out the dev branch.
Concord is an asynchronous C99 Discord API library with minimal external dependencies, and a low-level translation of the Discord official documentation to C code.
The following are minimalistic examples, refer to examples/
for a better overview.
Note: you need to replace GUILD_ID
with an actual guild ID, or this example won't compile!
You can use a macro to do this: #define GUILD_ID 1234567898765431
#include <string.h>
#include <concord/discord.h>
void on_ready(struct discord *client, const struct discord_ready *event) {
struct discord_create_guild_application_command params = {
.name = "ping",
.description = "Ping command!"
};
discord_create_guild_application_command(client, event->application->id,
GUILD_ID, ¶ms, NULL);
}
void on_interaction(struct discord *client, const struct discord_interaction *event) {
if (event->type != DISCORD_INTERACTION_APPLICATION_COMMAND)
return; /* return if interaction isn't a slash command */
if (strcmp(event->data->name, "ping") == 0) {
struct discord_interaction_response params = {
.type = DISCORD_INTERACTION_CHANNEL_MESSAGE_WITH_SOURCE,
.data = &(struct discord_interaction_callback_data){
.content = "pong"
}
};
discord_create_interaction_response(client, event->id,
event->token, ¶ms, NULL);
}
}
int main(void) {
struct discord *client = discord_init(BOT_TOKEN);
discord_set_on_ready(client, &on_ready);
discord_set_on_interaction_create(client, &on_interaction);
discord_run(client);
}
#include <string.h>
#include <concord/discord.h>
#include <concord/log.h>
void on_ready(struct discord *client, const struct discord_ready *event) {
log_info("Logged in as %s!", event->user->username);
}
void on_message(struct discord *client, const struct discord_message *event) {
if (strcmp(event->content, "ping") == 0) {
struct discord_create_message params = { .content = "pong" };
discord_create_message(client, event->channel_id, ¶ms, NULL);
}
}
int main(void) {
struct discord *client = discord_init(BOT_TOKEN);
discord_add_intents(client, DISCORD_GATEWAY_MESSAGE_CONTENT);
discord_set_on_ready(client, &on_ready);
discord_set_on_message_create(client, &on_message);
discord_run(client);
}
- GNU/Linux 4.x
- FreeBSD 12
- NetBSD 8.1
- Windows 7 (Cygwin)
- GNU/Hurd 0.9
- Mac OS X 10.9
Note: big-endian processors running certain OSes like SPARC Solaris, PowerPC AIX, System Z z/OS or Linux, or MIPS IRIX are NOT supported. There are currently a few issues that prevent some of the logic from correctly on big-endian systems. This will be fixed soon.
The only dependency is curl-8.7.1
or higher with websockets support. Since many system package managers don't provide this specific version with websockets enabled, we recommend compiling from source.
Important
Libcurl must be compiled with the --enable-websockets
flag to work with Concord.
- Install Cygwin
- During Cygwin installation, select packages:
gcc
,make
,git
,autoconf
,libtool
,pkg-config
,openssl-devel
,zlib-devel
- Follow the Windows tutorial here
- Then compile libcurl from source (instructions below)
# Install build dependencies
# Ubuntu/Debian:
$ sudo apt-get update && sudo apt-get install -y build-essential autoconf libtool pkg-config libssl-dev zlib1g-dev
# Fedora/RHEL/CentOS:
$ sudo dnf install -y gcc make autoconf libtool pkgconfig openssl-devel zlib-devel
# Arch/Manjaro:
$ sudo pacman -S --needed base-devel openssl zlib
# Alpine:
$ apk add build-base autoconf libtool pkgconfig openssl-dev zlib-dev
# FreeBSD:
$ pkg install autoconf libtool pkgconf openssl
# OS X:
$ xcode-select --install
$ brew install autoconf libtool pkg-config openssl@3
# or with MacPorts:
$ port install autoconf libtool pkgconfig openssl
# Download and compile libcurl
$ curl -LO https://curl.se/download/curl-8.7.1.tar.gz
$ tar -xzf curl-8.7.1.tar.gz
$ cd curl-8.7.1
$ ./configure --with-openssl --enable-websockets
$ make
$ sudo make install
# You might need to inform the system's dynamic linker about the new library location with:
$ echo "/usr/local/lib" > /etc/ld.so.conf.d/curl.conf
$ sudo ldconfig
$ git clone https://github.com/cogmasters/concord.git && cd concord
$ make
You might run into trouble with the compiler and linker not finding your Libcurl headers. You can do something like this:
$ CFLAGS=-I<some_path> LDFLAGS=-L<some_path> make
For instance, on a FreeBSD system:
$ CFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib make
On OS X using MacPorts:
$ CFLAGS=-I/opt/local/include LDFLAGS=-L/opt/local/lib make
On OS X using a self-compiled libcurl:
$ CFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/include make
On Windows with Cygwin, you might need to pass both arguments to use POSIX threading:
$ CFLAGS="-pthread -lpthread" make
In some cases, you might want to link Concord into a shared object, or link it as a shared object into another shared
object. In that case, you will need to compile Concord with CFLAGS="-fpic" make
.
discord_config_init() is the initialization method that allows configuring your bot without recompiling.
The following outlines config.json
fields:
{
"logging": { // logging directives
"level": "trace", // trace, debug, info, warn, error, fatal
"filename": "bot.log", // the log output file
"quiet": false, // change to true to disable logs in console
"overwrite": true, // overwrite file if already exists, append otherwise
"use_color": true, // display color for log entries
"http": {
"enable": true, // generate http specific logging
"filename": "http.log" // the HTTP log output file
},
"disable_modules": ["WEBSOCKETS", "USER_AGENT"] // disable logging for these modules
},
"discord": { // discord directives
"token": "YOUR-BOT-TOKEN", // replace with your bot token
"default_prefix": {
"enable": false, // enable default command prefix
"prefix": "YOUR-COMMANDS-PREFIX" // replace with your prefix
}
},
... // here you can add your custom fields *
}
* Your custom field contents can be fetched with discord_config_get_field()
- Get your bot token and add it to
config.json
, by assigning it to discord's "token" field. There are well written instructions from discord-irc explaining how to get your bot token and adding it to a server. - Build example executables:
$ make examples
- Run Copycat-Bot:
$ cd examples && ./copycat
Type a message in any channel the bot is part of and the bot should send an exact copy of it in return.
With Ctrl+c or with Ctrl+|
The following outlines special flags and targets to override the default Makefile build with additional functionalities.
-DCCORD_SIGINTCATCH
- By default Concord will not shutdown gracefully when a SIGINT is received (i.e. Ctrl+c), enable this flag if you wish it to be handled for you.
-DCCORD_DEBUG_WEBSOCKETS
- Enable verbose debugging for WebSockets communication.
-DCCORD_DEBUG_HTTP
- Enable verbose debugging for HTTP communication.
Example:
$ CFLAGS="-DCCORD_SIGINTCATCH -DCCORD_DEBUG_HTTP" make
make shared
- Produce a dynamically-linked version of Concord. This Makefile is intended for GNU-style compilers, such as
gcc
orclang
.
- Produce a dynamically-linked version of Concord. This Makefile is intended for GNU-style compilers, such as
make shared_osx
- Produce a dynamically-linked version of Concord, for OS X and Darwin systems.
make voice
- Enable experimental Voice Connection handling - not production ready.
make debug
- Enable some flags useful while developing, such as
-O0
and-g
- Enable some flags useful while developing, such as
(note -- #
means that you should be running as root)
# make install
This will install the headers and library files into $PREFIX. You can override this as such:
# PREFIX=/opt/concord make install
To cross-compile Concord, see the manual here.
The following are stable
and well documented dependencies that are packaged with Concord and can be included to your projects:
File | Description |
---|---|
cog-utils | General purpose functions aimed at portability |
log.c* | A simple C99 logging library |
carray* | Macro-based implementation of type-safe arrays |
anomap* | Sorted key/value storage for C99 |
chash* | Macro-based implementation of type-safe hashtables |
json-build | Tiny, zero-allocation JSON serializer |
jsmn-find | Tiny, zero-allocation JSON tokenizer |
* Concord uses its own modified version that may be not up to date with the original
Note that included headers must be concord/
prefixed:
#include <concord/discord.h>
#include <concord/log.h>
$ gcc myBot.c -o myBot -pthread -ldiscord -lcurl
$ clang myBot.c -o myBot -pthread -ldiscord -lcurl
- IBM XL C/C++ (AIX, z/OS, IBM i)
- Sun/Oracle Studio (Solaris)
- IRIX MIPSpro C++ (IRIX) -- NOTE: currently not supported
- HP aCC (HP-UX)
- Compaq C (Tru64 UNIX) -- NOTE: also currently not supported Note: if you want to actually compile this on one of the systems listed above, please see the "Compiling on old computers" guide.
$ cc myBot.c -o myBot -ldiscord -lcurl -lpthread
Note: some systems such as Cygwin require you to do this:
$ gcc myBot.c -o myBot -pthread -lpthread -ldiscord -lcurl
(this links against libpthread.a in /usr/lib
)
First, make sure your executable is compiled with the -g
flag to ensure human-readable debugger messages.
Using valgrind to check for memory leaks:
valgrind --leak-check=full ./myBot
For a more comprehensive guide check Valgrind's Quick Start.
Using GDB to check for runtime errors, such as segmentation faults:
$ gdb ./myBot
And then execute your bot from the gdb environment:
(gdb) run
If the program has crashed, get a backtrace of the function calls leading to it:
(gdb) bt
For a more comprehensive guide check Beej's Quick Guide to GDB
Problems? Check out our Discord Server
All kinds of contributions are welcome, all we ask is to abide to our guidelines! If you want to help but is unsure where to get started then our Discord API Roadmap is a good starting point. Check our links for more helpful information.