Added more functionalities

This commit is contained in:
polymath 2024-10-06 19:06:09 +02:00
parent b4077f8878
commit 78678b24bd

View file

@ -8,6 +8,8 @@
#define BOT_NICKNAME "erdhe" #define BOT_NICKNAME "erdhe"
#define BOT_JID "bot@hax.al" #define BOT_JID "bot@hax.al"
#define BOT_PASSWORD "passwordfield" #define BOT_PASSWORD "passwordfield"
#define DEFAULT_WELCOME_MSG "Welcome to the room, %s!"
#define CMD_PREFIX ".erdha wm"
/* Add UNUSED macro to suppress warnings */ /* Add UNUSED macro to suppress warnings */
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
@ -19,13 +21,16 @@ typedef struct UserList {
int size; int size;
} UserList; } UserList;
/* Global user list */ /* Global variables */
UserList userlist; UserList userlist;
/* Flag to determine whether the bot has finished joining the room */
int bot_joined = 0; 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) { void userlist_add(UserList *list, const char *jid) {
if (list->count >= list->size) { if (list->count >= list->size) {
list->size *= 2; list->size *= 2;
@ -35,7 +40,6 @@ void userlist_add(UserList *list, const char *jid) {
list->count++; list->count++;
} }
/* Check if user is in the list */
int userlist_contains(UserList *list, const char *jid) { int userlist_contains(UserList *list, const char *jid) {
for (int i = 0; i < list->count; i++) { for (int i = 0; i < list->count; i++) {
if (strcmp(list->users[i], jid) == 0) { if (strcmp(list->users[i], jid) == 0) {
@ -45,6 +49,20 @@ int userlist_contains(UserList *list, const char *jid) {
return 0; 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 */ /* Send a whisper message */
void send_whisper(xmpp_conn_t * const conn, xmpp_ctx_t *ctx, const char *to_jid, const char *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); 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); 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 */ /* Handle presence stanzas */
int presence_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { 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; xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
/* Ensure the presence is related to the room */
if (from && strstr(from, ROOM_JID)) { if (from && strstr(from, ROOM_JID)) {
const char *resource = strchr(from, '/'); const char *resource = strchr(from, '/');
if (resource && strcmp(resource + 1, BOT_NICKNAME) != 0) { // Ignore presence from the bot itself if (resource && strcmp(resource + 1, BOT_NICKNAME) != 0) {
/* Send whisper only if the bot has fully joined and user hasn't received it before */
if (bot_joined && !userlist_contains(&userlist, from)) { 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); userlist_add(&userlist, from);
} else { } else if (!bot_joined) {
/* Add user to the list if the bot is still joining */
userlist_add(&userlist, from); userlist_add(&userlist, from);
} }
} }
@ -90,7 +110,42 @@ int presence_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, voi
return 1; 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, void conn_handler(xmpp_conn_t * const conn, const xmpp_conn_event_t status,
const int error, xmpp_stream_error_t * const stream_error, const int error, xmpp_stream_error_t * const stream_error,
void * const userdata) { 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) { if (status == XMPP_CONN_CONNECT) {
fprintf(stderr, "Connected to server %s\n", SERVER); 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, 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_t *presence = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(presence, "presence"); xmpp_stanza_set_name(presence, "presence");
/* Set the "to" attribute as room_jid/nickname */
char to_buffer[512]; char to_buffer[512];
snprintf(to_buffer, sizeof(to_buffer), "%s/%s", ROOM_JID, BOT_NICKNAME); snprintf(to_buffer, sizeof(to_buffer), "%s/%s", ROOM_JID, BOT_NICKNAME);
xmpp_stanza_set_attribute(presence, "to", to_buffer); xmpp_stanza_set_attribute(presence, "to", to_buffer);
/* Add MUC namespace */
xmpp_stanza_t *x = xmpp_stanza_new(ctx); xmpp_stanza_t *x = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(x, "x"); xmpp_stanza_set_name(x, "x");
xmpp_stanza_set_ns(x, "http://jabber.org/protocol/muc"); xmpp_stanza_set_ns(x, "http://jabber.org/protocol/muc");
xmpp_stanza_add_child(presence, x); xmpp_stanza_add_child(presence, x);
xmpp_stanza_release(x); xmpp_stanza_release(x);
/* Send presence stanza */
xmpp_send(conn, presence); xmpp_send(conn, presence);
xmpp_stanza_release(presence); xmpp_stanza_release(presence);
fprintf(stderr, "Sent presence to join room: %s\n", to_buffer); 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; bot_joined = 1;
} else { } else {
@ -145,22 +194,21 @@ int main(void) {
xmpp_conn_t *conn; xmpp_conn_t *conn;
xmpp_log_t *log; xmpp_log_t *log;
/* Initialize userlist */ /* Initialize userlist and welcome message */
userlist.size = 10; // Initial size userlist.size = 10;
userlist.count = 0; userlist.count = 0;
userlist.users = malloc(userlist.size * sizeof(char *)); 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(); 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); ctx = xmpp_ctx_new(NULL, log);
conn = xmpp_conn_new(ctx); conn = xmpp_conn_new(ctx);
xmpp_conn_set_jid(conn, BOT_JID); xmpp_conn_set_jid(conn, BOT_JID);
xmpp_conn_set_pass(conn, BOT_PASSWORD); xmpp_conn_set_pass(conn, BOT_PASSWORD);
/* Explicitly set the server */
xmpp_conn_set_flags(conn, XMPP_CONN_FLAG_MANDATORY_TLS); xmpp_conn_set_flags(conn, XMPP_CONN_FLAG_MANDATORY_TLS);
fprintf(stderr, "Connecting to %s...\n", SERVER); fprintf(stderr, "Connecting to %s...\n", SERVER);
@ -183,4 +231,4 @@ int main(void) {
free(userlist.users); free(userlist.users);
return 0; return 0;
} }