Newer
Older
xmpp-bot / src / core / handlers.c
/* bot/handlers.c
 */
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <glib.h>
#include "handlers.h"
#include "../expenses/task.h"

int version_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
	xmpp_stanza_t *reply, *query, *name, *version, *text;
	const char *ns;
	xmpp_ctx_t *ctx = (xmpp_ctx_t*)userdata;
	printf("Received version request from %s\n", xmpp_stanza_get_attribute(stanza, "from"));
	
	reply = xmpp_stanza_new(ctx);
	xmpp_stanza_set_name(reply, "iq");
	xmpp_stanza_set_type(reply, "result");
	xmpp_stanza_set_id(reply, xmpp_stanza_get_id(stanza));
	xmpp_stanza_set_attribute(reply, "to", xmpp_stanza_get_attribute(stanza, "from"));
	
	query = xmpp_stanza_new(ctx);
	xmpp_stanza_set_name(query, "query");
    ns = xmpp_stanza_get_ns(xmpp_stanza_get_children(stanza));
    if (ns) {
        xmpp_stanza_set_ns(query, ns);
    }

	name = xmpp_stanza_new(ctx);
	xmpp_stanza_set_name(name, "name");
	xmpp_stanza_add_child(query, name);
	
	text = xmpp_stanza_new(ctx);
	xmpp_stanza_set_text(text, "libstrophe example bot");
	xmpp_stanza_add_child(name, text);
	
	version = xmpp_stanza_new(ctx);
	xmpp_stanza_set_name(version, "version");
	xmpp_stanza_add_child(query, version);
	
	text = xmpp_stanza_new(ctx);
	xmpp_stanza_set_text(text, "1.0");
	xmpp_stanza_add_child(version, text);
	
	xmpp_stanza_add_child(reply, query);

	xmpp_send(conn, reply);
	xmpp_stanza_release(reply);
	return 1;
}


int message_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
    unsigned int lastId;
	xmpp_stanza_t *reply, *body, *text;
	xmpp_ctx_t *ctx = (xmpp_ctx_t*)userdata;
	GString *intext;
    GString *replytext;
    BotReminder *reminder;
    const gchar * from = xmpp_stanza_get_attribute(stanza, "from");
	
	if(!xmpp_stanza_get_child_by_name(stanza, "body")) return 1;
	if(!strcmp(xmpp_stanza_get_attribute(stanza, "type"), "error")) return 1;
	
	intext = g_string_new(xmpp_stanza_get_text(xmpp_stanza_get_child_by_name(stanza, "body")));
	
	printf("Incoming message from %s: %s\n", from, intext->str);

	reply = xmpp_stanza_new(ctx);
	xmpp_stanza_set_name(reply, "message");
	xmpp_stanza_set_type(reply, xmpp_stanza_get_type(stanza)?xmpp_stanza_get_type(stanza):"chat");
	xmpp_stanza_set_attribute(reply, "to", from);
	
	body = xmpp_stanza_new(ctx);
	xmpp_stanza_set_name(body, "body");
	
	replytext = g_string_new(NULL);

    /* parse and store the message */
    if(grammar_parse_string(intext) == 0) {
        switch(bot_get_last_command()) {
        case BOT_CMD_IN:
        case BOT_CMD_OUT:
            lastId = (bot_get_last_expense())->id;
            g_string_printf(replytext, "OK! Ho salvato l'ultima spesa, id: %u\n", lastId);
            break;
        case BOT_CMD_REMINDER:
            reminder = bot_get_last_reminder();
            g_string_append(reminder->from, from);
            if(reminder->minutes > 0) {
                if(bot_start_task(reminder) != 0) {
                    g_string_printf(replytext, "Mi dispiace %s ma non posso mandarti un messaggio tra %d minuti, qualcosa non va.\n", strtok(strdup(reminder->from->str), "@"), reminder->minutes);
                } else {
                    g_string_printf(replytext, "Va bene %s, ti mando un messaggio tra %d minuti.\n", strtok(strdup(reminder->from->str), "@"), reminder->minutes);
                }
            } else {
                /* cancel reminder */
                bot_cancel_task(from);
                g_string_printf(replytext, "Ho cancellato il reminder, %s.\n", strtok(strdup(reminder->from->str), "@"));
            }
            break;
        default:
            g_string_printf(replytext, "Non ho riconosciuto il comando: %s", intext->str);
            break;
        }
    } else {
        g_string_printf(replytext, "Stavo rosicchiando una ghianda e non ho capito. Che vuol dire \"%s\"?\n%s\n", intext->str, HELPTEXT);
    }
	
	text = xmpp_stanza_new(ctx);
	xmpp_stanza_set_text(text, replytext->str);
	xmpp_stanza_add_child(body, text);
	xmpp_stanza_add_child(reply, body);
	
	xmpp_send(conn, reply);
	xmpp_stanza_release(reply);
	g_string_free(replytext, true);
	g_string_free(intext, true);

	return 1;
}

/* define a handler for 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) {
        xmpp_stanza_t* pres;
        fprintf(stderr, "DEBUG: connected\n");
        xmpp_handler_add(conn,version_handler, "jabber:iq:version", "iq", NULL, ctx);
        xmpp_handler_add(conn,message_handler, NULL, "message", NULL, ctx);
	
        /* Send initial <presence/> so that we appear online to contacts */
        pres = xmpp_stanza_new(ctx);
        xmpp_stanza_set_name(pres, "presence");
        xmpp_send(conn, pres);
        xmpp_stanza_release(pres);
    }
    else {
        fprintf(stderr, "DEBUG: disconnected\n");
        xmpp_stop(ctx);
    }
}

void send_message(xmpp_conn_t * const conn, GString * const from, xmpp_ctx_t * const ctx, const GString *msg)
{
	xmpp_stanza_t *reply, *body, *text;

	reply = xmpp_stanza_new(ctx);
	xmpp_stanza_set_name(reply, "message");
	xmpp_stanza_set_type(reply, "chat");
    xmpp_stanza_set_attribute(reply, "to", from->str);
	
	body = xmpp_stanza_new(ctx);
	xmpp_stanza_set_name(body, "body");
	
	text = xmpp_stanza_new(ctx);
	xmpp_stanza_set_text(text, msg->str);
	xmpp_stanza_add_child(body, text);
	xmpp_stanza_add_child(reply, body);

	xmpp_send(conn, reply);
	xmpp_stanza_release(reply);
}