orca
...
ORCAcode code = ORCA_OK;
printf("%s\n", orca_strerror(code));
orca_global_init();
orca_global_cleanup();
concord
...
CCORDcode code = CCORD_OK;
printf("%s\n", ccord_strerror(code));
ccord_global_init();
ccord_global_cleanup();
_t
suffixing is usually "reserved" for the C standard.
orca
u64_snowflake_t channel_id;
u64_unix_ms_t time_ms;
u64_bitmask_t bitmask;
concord
u64snowflake channel_id;
u64unix_ms time_ms;
u64bitmask bitmask;
All instances of _params
suffixing have been removed from the codebase:
orca
...
struct discord_create_message_params params = { .content = "Hi" };
discord_create_message(client, channel_id, ¶ms, NULL);
concord
...
struct discord_create_message params = { .content = "Hi" };
discord_create_message(client, channel_id, ¶ms, NULL);
Callback parameters have been wrapped in structs to reduce the user complexity of having to match a specific callback-signature with many parameters, and also allow them to take ownership of the struct so its not automatically cleaned-up.
orca
void on_ready(struct discord *client)
{
printf("Bot %s is ready!", discord_self(client)->username);
}
void done_create_message(struct discord *client, struct discord_async_ret *ret)
{
char *nick = ret->data;
printf("Reaction has been sent by %s\n", nick);
}
void fail_create_message(struct discord *client, struct discord_async_err *err)
{
printf("%s\n", discord_strerror(err->code, client));
}
void on_reaction_add(struct discord *client,
u64snowflake user_id,
u64snowflake channel_id,
u64snowflake message_id,
u64snowflake guild_id,
const struct discord_guild_member *member,
const struct discord_emoji *emoji)
{
printf("Received emoji %s", emoji->name);
struct discord_create_message_params params = { .content = "Received a reaction!" };
discord_async_next(client, &(struct discord_async_attr){
.done = &done_create_message,
.fail = &fail_create_message,
.data = strdup(member->nick),
.cleanup = free
});
discord_create_message(client, ¶ms, NULL);
}
int main(void)
{
struct discord *client = discord_init(BOT_TOKEN);
discord_set_on_ready(client, &on_ready);
discord_set_on_message_reaction_add(client, &on_reaction_add);
}
concord
void on_ready(struct discord *client, const struct discord_ready *event)
{
printf("Bot %s is ready!", event->user->username);
}
void done_create_message(struct discord *client,
struct discord_response *resp,
const struct discord_message *msg)
{
const struct discord_message_reaction_add *event = resp->keep;
printf("Reaction has been sent by %s\n", event->member->nick);
}
void fail_create_message(struct discord *client, struct discord_response *resp)
{
printf("%s\n", discord_strerror(resp->code, client));
}
void on_reaction_add(struct discord *client, const struct discord_message_reaction_add *event)
{
printf("Received emoji %s", event->emoji->name);
struct discord_create_message params = { .content = "Received a reaction!" };
discord_create_message(client, ¶ms, &(struct discord_ret_message){
.done = &done_create_message,
.fail = &fail_create_message,
.keep = event // ensures event is kept and sent to callbacks
});
}
int main(void)
{
struct discord *client = discord_init(BOT_TOKEN);
discord_set_on_ready(client, &on_ready);
discord_set_on_message_reaction_add(client, &on_reaction_add);
}
Null-terminated lists were neither begginner friendly or intuitive, there were two common scenarios that would lead to a segfault:
...
// assuming list is a NTL, if it is NULL, then 'list[i]' will lead to a segfault
for (int i = 0; list[i]; ++i)
printf("%d\n", i);
// if NULL is left out, it will lead to a segfault
int **integers = (int *[]){
&(int){ 0 },
&(int){ 2 },
// NULL
};
orca
...
struct discord_embed **embeds = {
&(struct discord_embed){
.title = "First embed"
},
&(struct discord_embed){
.title = "Second embed"
},
NULL
};
for (int i = 0; embeds[i]; ++i)
printf("%s\n", embeds[i]->title);
concord
...
struct discord_embeds embeds = {
.size = 2,
.array = (struct discord_embed []){
{
.title = "First embed"
},
{
.title = "Second embed"
}
}
};
for (int i = 0; i < embeds->size; ++i)
printf("%s\n", embeds->array[i].title);
This removes discord_async_next()
, and adds a parameter at the end of each request function where user
can assign their callbacks to.
A asynchronous request that doesn't care about capturing the request response
orca
...
discord_async_next(client, NULL);
struct discord_create_message_params params = { .content = "Hi" };
discord_create_message(client, channel_id, ¶ms, NULL);
concord
...
struct discord_create_message params = { .content = "Hi" };
discord_create_message(client, channel_id, ¶ms, NULL);
A asynchronous request that captures request response
orca
void done_create_message(struct discord *client, struct discord_async_ret *ret)
{
const struct discord_message *msg = ret->ret;
printf("Message has been sent (by %s)\n", msg->author->username);
}
void fail_create_message(struct discord *client, struct discord_async_err *err)
{
printf("%s\n", discord_strerror(err->code, client));
}
...
discord_async_next(client, &(struct discord_async_attr){
.done = &done_create_message,
.fail = &fail_create_message
});
struct discord_create_message_params params = { .content = "Hi" };
discord_create_message(client, channel_id, ¶ms, NULL);
concord
void done_create_message(struct discord *client, struct discord_response *resp, const struct discord_message *msg)
{
printf("Message has been sent (by %s)\n", msg->author->username);
}
void fail_create_message(struct discord *client, struct discord_response *resp)
{
printf("%s\n", discord_strerror(resp->code, client));
}
...
struct discord_create_message params = { .content = "Hi" };
discord_create_message(client, channel_id, ¶ms, &(struct discord_ret_message){
.done = &done_create_message,
.fail = &fail_create_message
});
A synchronous (blocking) request that doesn't care about capturing the request response
orca
...
struct discord_create_message_params params = { .content = "Hi" };
ORCAcode code = discord_create_message(client, channel_id, ¶ms, NULL);
if (code == ORCA_OK)
printf("Message has been sent\n");
else
printf("%s\n", discord_strerror(code, client));
concord
...
struct discord_create_message params = { .content = "Hi" };
CCORDcode code = discord_create_message(client, channel_id, ¶ms, &(struct discord_ret_message){
.sync = DISCORD_SYNC_FLAG // enable blocking request
});
if (code == CCORD_OK)
printf("Message has been sent\n");
else
printf("%s\n", discord_strerror(code, client));
A synchronous (blocking) request that captures request response
orca
...
struct discord_message msg = { 0 };
struct discord_create_message_params params = { .content = "Hi" };
ORCAcode code = discord_create_message(client, channel_id, ¶ms, &msg);
if (code == ORCA_OK) {
printf("Message has been sent (by %s)\n", msg.author->username);
discord_message_cleanup(&msg);
}
else {
printf("%s\n", discord_strerror(code, client));
}
concord
...
struct discord_message msg = { 0 };
struct discord_create_message params = { .content = "Hi" };
CCORDcode code = discord_create_message(client, channel_id, ¶ms, &(struct discord_ret_message){
.sync = &msg // enable blocking request
});
if (code == CCORD_OK) {
printf("Message has been sent (by %s)\n", msg.author->username);
discord_message_cleanup(&msg);
}
else {
printf("%s\n", discord_strerror(code, client));
}