Welcome Erdhe
This commit is contained in:
parent
a9bbe886f0
commit
7aa4331e1b
2 changed files with 195 additions and 0 deletions
9
Makefile
Normal file
9
Makefile
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
CC = gcc
|
||||||
|
CFLAGS = -Wall -Wextra $(shell pkg-config --cflags libstrophe)
|
||||||
|
LDFLAGS = $(shell pkg-config --libs libstrophe)
|
||||||
|
|
||||||
|
xmpp_bot: xmpp_bot.c
|
||||||
|
$(CC) $(CFLAGS) -o xmpp_bot xmpp_bot.c $(LDFLAGS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f xmpp_bot
|
186
xmpp_bot.c
Normal file
186
xmpp_bot.c
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
#include <strophe.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define SERVER "whatevermaybe.net"
|
||||||
|
#define ROOM_JID "archlinux@chat.hax.al"
|
||||||
|
#define BOT_NICKNAME "erdhe"
|
||||||
|
#define BOT_JID "bot@hax.al"
|
||||||
|
#define BOT_PASSWORD "passwordfield"
|
||||||
|
|
||||||
|
/* Add UNUSED macro to suppress warnings */
|
||||||
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
||||||
|
/* List to track users who have already received the whisper */
|
||||||
|
typedef struct UserList {
|
||||||
|
char **users;
|
||||||
|
int count;
|
||||||
|
int size;
|
||||||
|
} UserList;
|
||||||
|
|
||||||
|
/* Global user list */
|
||||||
|
UserList userlist;
|
||||||
|
|
||||||
|
/* Flag to determine whether the bot has finished joining the room */
|
||||||
|
int bot_joined = 0;
|
||||||
|
|
||||||
|
/* Add user to list */
|
||||||
|
void userlist_add(UserList *list, const char *jid) {
|
||||||
|
if (list->count >= list->size) {
|
||||||
|
list->size *= 2;
|
||||||
|
list->users = realloc(list->users, list->size * sizeof(char *));
|
||||||
|
}
|
||||||
|
list->users[list->count] = strdup(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) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
xmpp_stanza_set_name(msg, "message");
|
||||||
|
xmpp_stanza_set_type(msg, "chat");
|
||||||
|
xmpp_stanza_set_attribute(msg, "to", to_jid);
|
||||||
|
|
||||||
|
xmpp_stanza_t *body = xmpp_stanza_new(ctx);
|
||||||
|
xmpp_stanza_set_name(body, "body");
|
||||||
|
xmpp_stanza_t *text = xmpp_stanza_new(ctx);
|
||||||
|
xmpp_stanza_set_text(text, message);
|
||||||
|
xmpp_stanza_add_child(body, text);
|
||||||
|
xmpp_stanza_add_child(msg, body);
|
||||||
|
xmpp_stanza_release(text);
|
||||||
|
xmpp_stanza_release(body);
|
||||||
|
|
||||||
|
xmpp_send(conn, msg);
|
||||||
|
xmpp_stanza_release(msg);
|
||||||
|
|
||||||
|
fprintf(stderr, "Sent whisper to %s: %s\n", to_jid, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
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 (bot_joined && !userlist_contains(&userlist, from)) {
|
||||||
|
send_whisper(conn, ctx, from, "Welcome to the room!");
|
||||||
|
userlist_add(&userlist, from);
|
||||||
|
} else {
|
||||||
|
/* Add user to the list if the bot is still joining */
|
||||||
|
userlist_add(&userlist, from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle connection events */
|
||||||
|
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) {
|
||||||
|
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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 {
|
||||||
|
if (error) {
|
||||||
|
fprintf(stderr, "Connection error: %d\n", error);
|
||||||
|
if (stream_error) {
|
||||||
|
fprintf(stderr, "Stream error type: %d\n", stream_error->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Disconnected from server\n");
|
||||||
|
xmpp_stop(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main function */
|
||||||
|
int main(void) {
|
||||||
|
xmpp_ctx_t *ctx;
|
||||||
|
xmpp_conn_t *conn;
|
||||||
|
xmpp_log_t *log;
|
||||||
|
|
||||||
|
/* Initialize userlist */
|
||||||
|
userlist.size = 10; // Initial size
|
||||||
|
userlist.count = 0;
|
||||||
|
userlist.users = malloc(userlist.size * sizeof(char *));
|
||||||
|
|
||||||
|
xmpp_initialize();
|
||||||
|
|
||||||
|
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG); /* Use default logger instead of creating new one */
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (xmpp_connect_client(conn, SERVER, 0, conn_handler, ctx) == XMPP_EOK) {
|
||||||
|
fprintf(stderr, "Running connection...\n");
|
||||||
|
xmpp_run(ctx);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Failed to start connection\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
xmpp_conn_release(conn);
|
||||||
|
xmpp_ctx_free(ctx);
|
||||||
|
xmpp_shutdown();
|
||||||
|
|
||||||
|
/* Free the userlist */
|
||||||
|
for (int i = 0; i < userlist.count; i++) {
|
||||||
|
free(userlist.users[i]);
|
||||||
|
}
|
||||||
|
free(userlist.users);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue