Fix command registration and add command infra

This commit is contained in:
2026-08-29 18:46:38 +02:00
parent ee3aa1e488
commit 57ff0d0378
12 changed files with 463 additions and 89 deletions
+28 -10
View File
@@ -10,25 +10,43 @@
struct hammy_bot_t {
struct discord* client; // Owning reference to the client - handoff from main.c
bool commands_registered; // A flag if commands have been registered. Avoid re-registering every reconnect.
vector_t* commands; // vector_t of commands. Owning.
bool commandsRegistered; // A flag if commands have been registered. Avoid re-registering every reconnect.
vector_t* commands; // vector_t of commands. Owning the vector, NOT the elements.
hammy_pool_t* pool; // Owning reference to the thread pool.
u64snowflake appId; // Learned from the ready event.
};
// Alloc on heap and create
hammy_bot_t* hammy_bot_create();
// Sets the on_ready() call function pointer
bool hammy_bot_set_on_ready(hammy_bot_t* bot, void (*func)(struct discord* client, const struct discord_ready* event));
// Copies every entry from hammy_command_builtins() into the vector.
bool hammy_bot_load_builtins(hammy_bot_t* bot);
// Starts the worker pool. Pass 0 for the defaults. Call this from the ready
// callback, NOT before hammy_bot_run(): the workers are built on
// discord_clone(), which only succeeds inside a gateway dispatch.
// Returns true if the pool is already running.
bool hammy_bot_start_pool(hammy_bot_t* bot, size_t nWorkers, size_t queueCap);
// Runs the bot. Return true on succeed, false on failure.
bool hammy_bot_run(hammy_bot_t* bot);
// Adds a command to the vector as a COPY, get rid of the old struct.
bool hammy_bot_add_command(hammy_bot_t* bot, hammy_command_t* command);
// Registers all commands. Return true if succeeded or already registered; false if failure.
// Adds a command to the vector as a COPY. Commands own nothing, so the source
// struct needs no cleanup and may be a compound literal.
bool hammy_bot_add_command(hammy_bot_t* bot, const hammy_command_t* command);
// Looks a command up by name. Returns a pointer into the vector's storage, or
// NULL. Valid until the vector is next modified, which after startup is never.
const hammy_command_t* hammy_bot_find_command(const hammy_bot_t* bot, const char* name);
// Registers all commands with Discord. Return true if succeeded or already
// registered; false if failure. Requires bot->application_id to be set, so call
// this from on_ready, not before.
bool hammy_bot_register_commands(hammy_bot_t* bot);
// Destroy bot, NULLs the passing reference
bool hammy_bot_destroy(hammy_bot_t** bot);
+7 -1
View File
@@ -30,12 +30,14 @@ struct hammy_job_t {
hammy_arg_t* args; // Array of size nArgs. Owning, array and contents.
size_t nArgs;
int64_t queuedAt; // Staleness checks, in ms. From discord_timestamp().
hammy_bot_t* bot; // NOT owning, used to access the command table
};
// Deep-copies everything the job needs out of the interaction event, so the
// event may be freed by Concord the moment the handler returns.
// Returns NULL on allocation failure.
hammy_job_t* hammy_job_create(struct discord* client, const struct discord_interaction* event);
hammy_job_t* hammy_job_create(hammy_bot_t* bot, const struct discord_interaction* event);
// Frees the job and everything it owns. NULLs the passing reference.
// Safe to call with NULL or with a pointer to NULL.
@@ -56,4 +58,8 @@ void hammy_job_run(hammy_job_t* job, struct discord* client);
// Used by hammy_job_run() and by the pool's error paths.
void hammy_job_reply(const hammy_job_t* job, struct discord* client, const char* content);
// Sends a fresh interaction response with a plain text body.
// Only valid on the instant path, where nothing has been sent yet.
void hammy_job_respond(const hammy_job_t* job, struct discord* client, const char* content);
#endif
+5 -1
View File
@@ -43,6 +43,9 @@ struct hammy_pool_t {
// Creates the pool and starts n_workers threads, each with its own
// discord_clone() of client. Pass 0 for either size to take the defaults.
// Returns NULL on failure; no threads are left running in that case.
// MUST be called from inside a gateway dispatch callback (on_ready is the
// earliest one): discord_clone() copies the gateway's current payload and
// fails with CCORD_ERRNO when there isn't one.
hammy_pool_t* hammy_pool_create(struct discord* client, size_t nWorkers, size_t queueCap);
// Enqueues a job. See hammy_push_result_t for who owns the job afterwards.
@@ -56,7 +59,8 @@ hammy_push_result_t hammy_pool_push(hammy_pool_t* pool, hammy_job_t* job);
void hammy_pool_shutdown(hammy_pool_t* pool);
// As above but discards anything still queued (each dropped job gets an
// apology reply if it can be sent quickly).
// apology reply). Call from the gateway thread only - the apologies are
// serialised through the original client, which that thread owns.
void hammy_pool_shutdown_now(hammy_pool_t* pool);
// Frees the pool. Runs hammy_pool_shutdown() first if it has not happened yet.
+2
View File
@@ -15,6 +15,8 @@ struct hammy_worker_t {
// Clones client, spawns the thread. Returns false on clone or spawn failure,
// leaving the worker safe to pass to hammy_worker_join().
// Inherits hammy_pool_create()'s precondition: the clone only succeeds from
// inside a gateway dispatch callback.
bool hammy_worker_start(hammy_worker_t* worker, hammy_pool_t* pool, struct discord* client, int id);
// Joins the thread if it was started and cleans up the clone.