From 78678b24bdb006c1b997b475b36a312690705dfa Mon Sep 17 00:00:00 2001 From: polymath Date: Sun, 6 Oct 2024 19:06:09 +0200 Subject: [PATCH] Added more functionalities --- xmpp_bot.c | 102 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 75 insertions(+), 27 deletions(-) diff --git a/xmpp_bot.c b/xmpp_bot.c index 05c8e2a..dcc192b 100644 --- a/xmpp_bot.c +++ b/xmpp_bot.c @@ -8,6 +8,8 @@ #define BOT_NICKNAME "erdhe" #define BOT_JID "bot@hax.al" #define BOT_PASSWORD "passwordfield" +#define DEFAULT_WELCOME_MSG "Welcome to the room, %s!" +#define CMD_PREFIX ".erdha wm" /* Add UNUSED macro to suppress warnings */ #define UNUSED(x) (void)(x) @@ -19,13 +21,16 @@ typedef struct UserList { int size; } UserList; -/* Global user list */ +/* Global variables */ UserList userlist; - -/* Flag to determine whether the bot has finished joining the room */ int bot_joined = 0; +char welcome_message[512]; -/* Add user to list */ +/* Function prototypes */ +void send_whisper(xmpp_conn_t * const conn, xmpp_ctx_t *ctx, const char *to_jid, const char *message); +int message_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); + +/* User list functions */ void userlist_add(UserList *list, const char *jid) { if (list->count >= list->size) { list->size *= 2; @@ -35,7 +40,6 @@ void userlist_add(UserList *list, const char *jid) { list->count++; } -/* Check if user is in the list */ int userlist_contains(UserList *list, const char *jid) { for (int i = 0; i < list->count; i++) { if (strcmp(list->users[i], jid) == 0) { @@ -45,6 +49,20 @@ int userlist_contains(UserList *list, const char *jid) { return 0; } +/* Extract nickname from full JID */ +const char *get_nickname(const char *full_jid) { + const char *slash = strrchr(full_jid, '/'); + return slash ? slash + 1 : full_jid; +} + +/* Send a formatted welcome message */ +void send_welcome_message(xmpp_conn_t * const conn, xmpp_ctx_t *ctx, const char *to_jid) { + const char *nickname = get_nickname(to_jid); + char formatted_msg[1024]; + snprintf(formatted_msg, sizeof(formatted_msg), welcome_message, nickname); + send_whisper(conn, ctx, to_jid, formatted_msg); +} + /* Send a whisper message */ void send_whisper(xmpp_conn_t * const conn, xmpp_ctx_t *ctx, const char *to_jid, const char *message) { xmpp_stanza_t *msg = xmpp_stanza_new(ctx); @@ -67,21 +85,23 @@ void send_whisper(xmpp_conn_t * const conn, xmpp_ctx_t *ctx, const char *to_jid, fprintf(stderr, "Sent whisper to %s: %s\n", to_jid, message); } +/* Check if user is admin or owner */ +int is_admin_or_owner(const char *affiliation) { + return (strcmp(affiliation, "owner") == 0 || strcmp(affiliation, "admin") == 0); +} + /* Handle presence stanzas */ int presence_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { - const char *from = xmpp_stanza_get_attribute(stanza, "from"); // Fix const issue + const char *from = xmpp_stanza_get_attribute(stanza, "from"); xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; - /* Ensure the presence is related to the room */ if (from && strstr(from, ROOM_JID)) { const char *resource = strchr(from, '/'); - if (resource && strcmp(resource + 1, BOT_NICKNAME) != 0) { // Ignore presence from the bot itself - /* Send whisper only if the bot has fully joined and user hasn't received it before */ + if (resource && strcmp(resource + 1, BOT_NICKNAME) != 0) { if (bot_joined && !userlist_contains(&userlist, from)) { - send_whisper(conn, ctx, from, "Welcome to the room!"); + send_welcome_message(conn, ctx, from); userlist_add(&userlist, from); - } else { - /* Add user to the list if the bot is still joining */ + } else if (!bot_joined) { userlist_add(&userlist, from); } } @@ -90,7 +110,42 @@ int presence_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, voi return 1; } -/* Handle connection events */ +/* Handle message stanzas */ +int message_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { + xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; + const char *type = xmpp_stanza_get_type(stanza); + const char *from = xmpp_stanza_get_attribute(stanza, "from"); + + if (type && strcmp(type, "groupchat") == 0) { + xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, "body"); + if (body) { + char *message = xmpp_stanza_get_text(body); + if (message && strncmp(message, CMD_PREFIX, strlen(CMD_PREFIX)) == 0) { + /* Check if sender is admin/owner */ + xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, "http://jabber.org/protocol/muc#user"); + if (x) { + xmpp_stanza_t *item = xmpp_stanza_get_child_by_name(x, "item"); + if (item) { + const char *affiliation = xmpp_stanza_get_attribute(item, "affiliation"); + if (is_admin_or_owner(affiliation)) { + char *new_msg = message + strlen(CMD_PREFIX) + 1; + strncpy(welcome_message, new_msg, sizeof(welcome_message) - 1); + welcome_message[sizeof(welcome_message) - 1] = '\0'; + + char response[1024]; + snprintf(response, sizeof(response), "Welcome message updated to: %s", welcome_message); + send_whisper(conn, ctx, from, response); + } + } + } + } + if (message) xmpp_free(ctx, message); + } + } + return 1; +} + +/* Connection handler */ void conn_handler(xmpp_conn_t * const conn, const xmpp_conn_event_t status, const int error, xmpp_stream_error_t * const stream_error, void * const userdata) { @@ -99,32 +154,26 @@ void conn_handler(xmpp_conn_t * const conn, const xmpp_conn_event_t status, if (status == XMPP_CONN_CONNECT) { fprintf(stderr, "Connected to server %s\n", SERVER); - /* Add handler for presence stanzas */ xmpp_handler_add(conn, presence_handler, NULL, "presence", NULL, ctx); + xmpp_handler_add(conn, message_handler, NULL, "message", NULL, ctx); - /* Create presence stanza to join room */ xmpp_stanza_t *presence = xmpp_stanza_new(ctx); xmpp_stanza_set_name(presence, "presence"); - /* Set the "to" attribute as room_jid/nickname */ char to_buffer[512]; snprintf(to_buffer, sizeof(to_buffer), "%s/%s", ROOM_JID, BOT_NICKNAME); xmpp_stanza_set_attribute(presence, "to", to_buffer); - /* Add MUC namespace */ xmpp_stanza_t *x = xmpp_stanza_new(ctx); xmpp_stanza_set_name(x, "x"); xmpp_stanza_set_ns(x, "http://jabber.org/protocol/muc"); xmpp_stanza_add_child(presence, x); xmpp_stanza_release(x); - /* Send presence stanza */ xmpp_send(conn, presence); xmpp_stanza_release(presence); fprintf(stderr, "Sent presence to join room: %s\n", to_buffer); - - /* Mark the bot as fully joined after the initial presence handling */ bot_joined = 1; } else { @@ -145,22 +194,21 @@ int main(void) { xmpp_conn_t *conn; xmpp_log_t *log; - /* Initialize userlist */ - userlist.size = 10; // Initial size + /* Initialize userlist and welcome message */ + userlist.size = 10; userlist.count = 0; userlist.users = malloc(userlist.size * sizeof(char *)); + strncpy(welcome_message, DEFAULT_WELCOME_MSG, sizeof(welcome_message) - 1); + welcome_message[sizeof(welcome_message) - 1] = '\0'; xmpp_initialize(); - log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG); /* Use default logger instead of creating new one */ + log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG); ctx = xmpp_ctx_new(NULL, log); - conn = xmpp_conn_new(ctx); xmpp_conn_set_jid(conn, BOT_JID); xmpp_conn_set_pass(conn, BOT_PASSWORD); - - /* Explicitly set the server */ xmpp_conn_set_flags(conn, XMPP_CONN_FLAG_MANDATORY_TLS); fprintf(stderr, "Connecting to %s...\n", SERVER); @@ -183,4 +231,4 @@ int main(void) { free(userlist.users); return 0; -} +} \ No newline at end of file