aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorturret <turret@duck.com>2024-03-30 20:35:30 -0500
committerturret <turret@duck.com>2024-03-30 20:35:30 -0500
commit2fb619ed6eac19afd7ed3b2c7baa4adc253f418e (patch)
tree521d3ec070fa39c398ec2d5835cac22bcd95190a
parent80a67b7d20393a29aa5d2cb92197f3381be7fd96 (diff)
downloaddiscord-bot-skeleton-2fb619ed6eac19afd7ed3b2c7baa4adc253f418e.tar.gz
discord-bot-skeleton-2fb619ed6eac19afd7ed3b2c7baa4adc253f418e.tar.bz2
discord-bot-skeleton-2fb619ed6eac19afd7ed3b2c7baa4adc253f418e.zip
net: event handler
in subsys.h: include init.h to ensure l5_initcall availability also: add example/ directory to provide some user-code in the skeleton (will likely be made defunct as i make the remainder of the skeleton, such as a /ping command and user action and maybe some buttons, which will require more organisation)
-rw-r--r--example/hello.c17
-rw-r--r--include/dbs/bits/events.h68
-rw-r--r--include/dbs/event.h20
-rw-r--r--include/dbs/subsys.h2
-rw-r--r--util/net.c61
5 files changed, 166 insertions, 2 deletions
diff --git a/example/hello.c b/example/hello.c
new file mode 100644
index 0000000..f192a52
--- /dev/null
+++ b/example/hello.c
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+#include <cJSON.h>
+
+#include <dbs/event.h>
+#include <dbs/log.h>
+
+int hello(cJSON *data)
+{
+ char *string = cJSON_Print(data);
+ print("hello, world!");
+ print("hello data: %s", string);
+ free(string);
+
+ return 0;
+}
+declare_event(HELLO, hello);
diff --git a/include/dbs/bits/events.h b/include/dbs/bits/events.h
new file mode 100644
index 0000000..de8b35d
--- /dev/null
+++ b/include/dbs/bits/events.h
@@ -0,0 +1,68 @@
+E(HELLO, hello)
+E(READY, ready)
+E(RESUMED, resumed)
+E(RECONNECT, reconnect)
+E(INVALID_SESSION, invalid_session)
+E(APPLICATION_COMMAND_PERMISSIONS_UPDATE, application_command_permissions_update)
+E(AUTO_MODERATION_RULE_CREATE, auto_moderation_rule_create)
+E(AUTO_MODERATION_RULE_UPDATE, auto_moderation_rule_update)
+E(AUTO_MODERATION_RULE_DELETE, auto_moderation_rule_delete)
+E(AUTO_MODERATION_ACTION_EXECUTION, auto_moderation_action_execution)
+E(CHANNEL_CREATE, channel_create)
+E(CHANNEL_UPDATE, channel_update)
+E(CHANNEL_DELETE, channel_delete)
+E(CHANNEL_PINS_UPDATE, channel_pins_update)
+E(THREAD_CREATE, thread_create)
+E(THREAD_UPDATE, thread_update)
+E(THREAD_DELETE, thread_delete)
+E(THREAD_LIST_SYNC, thread_list_sync)
+E(THREAD_MEMBER_UPDATE, thread_member_update)
+E(THREAD_MEMBERS_UPDATE, thread_members_update)
+E(ENTITLEMENT_CREATE, entitlement_create)
+E(ENTITLEMENT_UPDATE, entitlement_update)
+E(ENTITLEMENT_DELETE, entitlement_delete)
+E(GUILD_CREATE, guild_create)
+E(GUILD_UPDATE, guild_update)
+E(GUILD_DELETE, guild_delete)
+E(GUILD_AUDIT_LOG_ENTRY_CREATE, guild_audit_log_entry_create)
+E(GUILD_BAN_ADD, guild_ban_add)
+E(GUILD_BAN_REMOVE, guild_ban_remove)
+E(GUILD_EMOJIS_UPDATE, guild_emojis_update)
+E(GUILD_STICKERS_UPDATE, guild_stickers_update)
+E(GUILD_INTEGRATIONS_UPDATE, guild_integrations_update)
+E(GUILD_MEMBER_ADD, guild_member_add)
+E(GUILD_MEMBER_REMOVE, guild_member_remove)
+E(GUILD_MEMBER_UPDATE, guild_member_update)
+E(GUILD_MEMBERS_CHUNK, guild_members_chunk)
+E(GUILD_ROLE_CREATE, guild_role_create)
+E(GUILD_ROLE_UPDATE, guild_role_update)
+E(GUILD_ROLE_DELETE, guild_role_delete)
+E(GUILD_SCHEDULED_EVENT_CREATE, guild_scheduled_event_create)
+E(GUILD_SCHEDULED_EVENT_UPDATE, guild_scheduled_event_update)
+E(GUILD_SCHEDULED_EVENT_DELETE, guild_scheduled_event_delete)
+E(GUILD_SCHEDULED_EVENT_USER_ADD, guild_scheduled_event_user_add)
+E(GUILD_SCHEDULED_EVENT_USER_REMOVE, guild_scheduled_event_user_remove)
+E(INTEGRATION_CREATE, integration_create)
+E(INTEGRATION_UPDATE, integration_update)
+E(INTEGRATION_DELETE, integration_delete)
+E(INTERACTION_CREATE, interaction_create)
+E(INVITE_CREATE, invite_create)
+E(INVITE_DELETE, invite_delete)
+E(MESSAGE_CREATE, message_create)
+E(MESSAGE_UPDATE, message_update)
+E(MESSAGE_DELETE, message_delete)
+E(MESSAGE_DELETE_BULK, message_delete_bulk)
+E(MESSAGE_REACTION_ADD, message_reaction_add)
+E(MESSAGE_REACTION_REMOVE, message_reaction_remove)
+E(MESSAGE_REACTION_REMOVE_ALL, message_reaction_remove_all)
+E(MESSAGE_REACTION_REMOVE_EMOJI, message_reaction_remove_emoji)
+E(PRESENCE_UPDATE, presence_update)
+E(STAGE_INSTANCE_CREATE, stage_instance_create)
+E(STAGE_INSTANCE_UPDATE, stage_instance_update)
+E(STAGE_INSTANCE_DELETE, stage_instance_delete)
+E(TYPING_START, typing_start)
+E(USER_UPDATE, user_update)
+E(VOICE_STATE_UPDATE, voice_state_update)
+E(VOICE_SERVER_UPDATE, voice_server_update)
+E(WEBHOOKS_UPDATE, webhooks_update)
+E(EVENT_INVALID, event_invalid)
diff --git a/include/dbs/event.h b/include/dbs/event.h
new file mode 100644
index 0000000..6be3378
--- /dev/null
+++ b/include/dbs/event.h
@@ -0,0 +1,20 @@
+#ifndef __EVENT_H
+#define __EVENT_H
+
+#include <dbs/init.h>
+
+enum Event {
+#define E(ev_name, _) ev_name,
+#include <dbs/bits/events.h>
+#undef E
+};
+
+int ev_set_handler(enum Event event, int (*ev_handler)(cJSON*));
+
+#define declare_event(event, handler) \
+ void __decl_##event_##handler() { \
+ ev_set_handler(event, handler); \
+ } \
+ l3_initcall(__decl_##event_##handler)
+
+#endif
diff --git a/include/dbs/subsys.h b/include/dbs/subsys.h
index 1885a80..fa3b423 100644
--- a/include/dbs/subsys.h
+++ b/include/dbs/subsys.h
@@ -1,6 +1,8 @@
#ifndef __SUBSYS_H
#define __SUBSYS_H
+#include <dbs/init.h>
+
int __impl_start_subsystem(char *name, int (*fn)(void));
#define start_subsystem(fn) __impl_start_subsystem(#fn, fn)
#define declare_subsystem(fn) \
diff --git a/util/net.c b/util/net.c
index 98f371a..42fb004 100644
--- a/util/net.c
+++ b/util/net.c
@@ -12,6 +12,7 @@
#include <curl/curl.h>
#include <dbs/api.h>
+#include <dbs/event.h>
#include <dbs/init.h>
#include <dbs/log.h>
#include <dbs/subsys.h>
@@ -23,6 +24,9 @@ int api_request(HTTPMethod method, char *url,
struct curl_slist *headers, char *writebuf, size_t bufsiz);
static void setup_token_header();
+static int (**ev_get_handler(enum Event event)) (cJSON *);
+int ev_set_handler(enum Event event, int (*ev_handler)(cJSON*));
+
static void ws_send_heartbeat();
static void ws_handle_event(cJSON *event);
@@ -30,6 +34,12 @@ int net_subsystem();
void net_get_gateway_url();
/* variables */
+static struct {
+#define E(_, ev_name) int (*ev_name)(cJSON *);
+#include <dbs/bits/events.h>
+#undef E
+} ev_handlers;
+
static CURL *ws_handle;
static char *gateway_url;
static char *token_header;
@@ -127,6 +137,27 @@ int api_request(HTTPMethod method, char *url,
return ret;
}
+/* returns the pointer of the function pointer in the ev_handlers struct */
+static int (**ev_get_handler(enum Event event)) (cJSON *)
+{
+ switch(event) {
+#define E(ev_enum, ev_func) \
+ case ev_enum: \
+ return &(ev_handlers.ev_func);
+#include <dbs/bits/events.h>
+#undef E
+ default:
+ return &(ev_handlers.event_invalid);
+ }
+}
+
+int ev_set_handler(enum Event event, int (*ev_handler)(cJSON*))
+{
+ int (**ev_pointer)(cJSON*) = ev_get_handler(event);
+ *ev_pointer = ev_handler;
+ return 0;
+}
+
static void ws_send_heartbeat()
{
char buf[128] = "{\"op\":1,\"d\":null}";
@@ -152,7 +183,27 @@ static void ws_handle_event(cJSON *event)
int op = cJSON_GetObjectItem(event, "op")->valueint;
cJSON *data = cJSON_GetObjectItem(event, "d");
switch(op) {
- case 0: /* Event dispatch */
+ case 0: ; /* Event dispatch */
+ cJSON *ev_name = cJSON_GetObjectItem(event, "t");
+ if(!cJSON_IsString(ev_name)) {
+ print(LOG_ERR "ws: malformed event dispatch (t not a string)");
+ break;
+ }
+
+ char *event = ev_name->valuestring;
+ enum Event ev;
+#define E(ev_name, _) \
+ if (strcmp(event, #ev_name ) == 0) { \
+ ev = ev_name; \
+ } else
+#include <dbs/bits/events.h>
+#undef E
+ { ev = EVENT_INVALID; }
+
+ int (*ev_handler)(cJSON *) = *ev_get_handler(ev);
+ if(ev_handler != NULL) {
+ ev_handler(data);
+ }
break;
case 1: /* Heartbeat request */
ws_send_heartbeat();
@@ -168,7 +219,7 @@ static void ws_handle_event(cJSON *event)
/* FALLTHROUGH */
case 7: /* Reconnect */
/* TODO */
- panic("ws: cannot reconnect to ws after failure");
+ panic("ws: cannot reconnect to ws after failure (Not supported)");
break;
case 10: ; /* Hello */
int heartbeat_wait = cJSON_GetObjectItem(data,
@@ -186,6 +237,12 @@ static void ws_handle_event(cJSON *event)
.it_value = jitter_time
};
setitimer(ITIMER_REAL, &new_itimer, NULL);
+
+ int (*hello_handler)(cJSON *) = *ev_get_handler(HELLO);
+ if(hello_handler) {
+ (hello_handler)(data);
+ }
+
break;
case 11: /* Heartbeat ACK */
print(LOG_DEBUG "ws: heartbeat ACK");