src/parse.c
author Markus Bröker <mbroeker@4customers.de>
Fri, 29 Oct 2021 22:31:10 +0200
changeset 62 2d6419d6d4ed
parent 61 fb2cfcee38bd
permissions -rw-r--r--
Build System Fixes for debhelper 10

/**
 *  $Id: parse.c 153 2008-04-27 07:26:15Z mbroeker $
 * $URL: http://localhost/svn/c/mcbot/trunk/src/parse.c $
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include <mcbot.h>
#include <database.h>
#include "common.h"

#include <locale.h>
#include <libintl.h>

#ifndef DATABASE_FILE
#define DATABASE_FILE "/var/lib/mcbot/data/mcbot.dat"
#endif

#ifndef SOURCE_URL
#define SOURCE_URL "https://4customers.de/hg/mcbot"
#endif

enum command_map {
    HELP, JOIN, LEAVE, ADD, REPLACE, DELETE, LIST, SEARCH, INFO, PING, ON, OFF, DEBUG,
    VACCUUM, LOGOUT, WHO, WHOIS, TIME, TELL, OP, DEOP, KICK, BAN, UNBAN, KICKBAN, HELLO,
    TOPIC,
};

const
char *COMMAND_LIST[] = {
    "help      Known Commands: join(1), leave(2), add(3), replace(4), delete(5), list(6), search(7), info(8)\r\n",
    "join      Joins a new channel\r\n",
    "leave     Parts from the current channel\r\n",
    "add       adds an entry\r\n",
    "replace   replaces an entry\r\n",
    "delete    deletes an entry\r\n",
    "list      lists the number of stored values\r\n",
    "search    searches an entry up\r\n",
    "info      Prints the current Bot-Version\r\n",
    "ping      pings an host\r\n",
    "on        enables autolearning mode\r\n",
    "off       disables autolearning\r\n",
    "debug     prints some debug infos\r\n",
    "vaccuum   reorganizes the database\r\n",
    "logout    Protected logout function\r\n",
    "topic     Sets a new topic\r\n",
    NULL,
};

const
char VISIBLE_ITEMS = 14;

const
char *Bot_Commands[] = {
    "!help", "!join", "!leave",
    "!add", "!replace", "!delete",
    "!list", "!search", "!info",
    "!ping", "!on", "!off",
    "!debug", "!vaccuum", "!logout",
    "!who", "!whois", "!time",
    "!tell", "!op", "!deop",
    "!kick", "!ban", "!unban",
    "!kickban", "!hello", "!topic",
    NULL
};

char *parse (MSG * message)
{
    static char msg[DEFAULT_BUF_SIZE];
    int cmd = -1;
    enum command_map map;
    char *token;
    char *parameters;

    time_t t;
    struct tm *timeptr;

    /*
     * make sure that parseable data is available
     * this prevents a possible segmentation fault
     */
    if (message->user == NULL)
        message->user = "error";
    if (message->domain == NULL)
        message->domain = "server.err";

    /*
     * default message
     */
    snprintf (msg, sizeof (msg), "PRIVMSG %s :%s.\r\n", message->channel, gettext ("Request cannot be performed"));

    /*
     * PRIVATE MESSAGES
     */
    if (!strcmp (message->channel, message->nick))
        message->channel = message->user;

    /*
     * NO BOT Commands
     */
    if (*message->line != '!') {
        return NULL;
    }

    map = 0;
    token = strtok (message->line, " ");
    while (Bot_Commands[map]) {
        if (!strcmp (token, Bot_Commands[map])) {
            switch (map) {
            case HELP:
                if ((token = strtok (NULL, "\r\n")))
                    cmd = atoi (token);
                if ((cmd > 0) && (cmd < VISIBLE_ITEMS))
                    snprintf (msg, sizeof (msg), "PRIVMSG %s :%s\r\n", message->channel, COMMAND_LIST[cmd]);
                else
                    snprintf (msg, sizeof (msg), "PRIVMSG %s :%s\r\n", message->channel, COMMAND_LIST[0]);
                return msg;

            case JOIN:
                if ((token = strtok (NULL, "\r\n")))
                    if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                        if (strstr (message->domain, db_lookup (DATABASE_FILE, "mcbot.domain")))
                            snprintf (msg, sizeof (msg), "JOIN %s\r\n", token);
                    }
                return msg;

            case LEAVE:
                if (*message->channel != '#')
                    return NULL;
                if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                    if (strstr (message->domain, db_lookup (DATABASE_FILE, "mcbot.domain")))
                        snprintf (msg, sizeof (msg), "PART %s :Leaving.\r\n", message->channel);
                }
                return msg;

            case ADD:
                if ((token = strtok (NULL, " "))) {
                    if ((parameters = strtok (NULL, "\r\n"))) {
                        snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s\r\n",
                                  message->channel, message->user, db_insert (DATABASE_FILE, token, parameters, 0));
                    } else {
                        snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s!\r\n", message->channel,
                                  gettext ("I need more parameters to add"), message->user);
                    }
                }
                return msg;

            case REPLACE:
                if ((token = strtok (NULL, " "))) {
                    if ((parameters = strtok (NULL, "\r\n"))) {
                        snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s\r\n",
                                  message->channel, message->user, db_insert (DATABASE_FILE, token, parameters, 1));
                    } else {
                        snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s!\r\n", message->channel,
                                  gettext ("I need more parameters to replace"), message->user);
                    }
                }
                return msg;

            case DELETE:
                if ((token = strtok (NULL, "\r\n"))) {
                    snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s\r\n",
                              message->channel, message->user, db_remove (DATABASE_FILE, token));
                } else {
                    snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s!\r\n", message->channel,
                              gettext ("I need a key to delete"), message->user);
                }
                return msg;

            case LIST:
                snprintf (msg, sizeof (msg), "PRIVMSG %s :%s %s\r\n", message->channel, db_elements (DATABASE_FILE),
                          db_lookup (DATABASE_FILE, "mcbot.cgi"));
                return msg;

            case SEARCH:
                if ((token = strtok (NULL, "\r\n"))) {
                    snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s\r\n", message->channel, message->user,
                              db_lookup (DATABASE_FILE, token));
                } else {
                    snprintf (msg, sizeof (msg),
                              "PRIVMSG %s :%s, %s!\r\n", message->channel, gettext ("I need a key to lookup"),
                              message->user);
                }
                return msg;

            case INFO:
                snprintf (msg, sizeof (msg),
                          "PRIVMSG %s :I am MCBot-%1.2f Build %s and my source code can be found at %s\r\n",
                          message->channel, BOT_VERSION, BOT_BUILD, SOURCE_URL);
                return msg;

            case PING:
                if ((token = strtok (NULL, "\r\n")))
                    snprintf (msg, sizeof (msg), "PRIVMSG %s :PING 0815\r\n", token);
                return msg;

            case ON:
                snprintf (msg, sizeof (msg), "PRIVMSG %s :%s %s.\r\n", message->user,
                          gettext ("Autolearn enabled for channel"), message->channel);
                return msg;

            case OFF:
                snprintf (msg, sizeof (msg), "PRIVMSG %s :%s %s.\r\n", message->user,
                          gettext ("Autolearn disabled for channel"), message->channel);
                return msg;

            case DEBUG:
                snprintf (msg, sizeof (msg), "PRIVMSG %s :USER: %s domain: %s CHANNEL: %s LINE: %s\r\n",
                          message->channel, message->user, message->domain, message->channel, message->line);
                return msg;

            case VACCUUM:
                snprintf (msg, sizeof (msg), "PRIVMSG %s :%s\r\n", message->channel, db_vaccuum (DATABASE_FILE));
                return msg;

            case LOGOUT:
                if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                    if (strstr (message->domain, db_lookup (DATABASE_FILE, "mcbot.domain"))) {
                        snprintf (msg, sizeof (msg), "PRIVMSG %s :%s!\r\nQUIT\r\n", message->channel,
                                  gettext ("Bye, have a nice day!"));
                    }
                }
                /*
                 * the returned message is either the default one or the generated one
                 */
                return msg;

            case WHO:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    snprintf (msg, sizeof (msg), "WHO %s\r\n", token);
                }
                return msg;

            case WHOIS:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    snprintf (msg, sizeof (msg), "WHOIS %s\r\n", token);
                }
                return msg;

            case TIME:
                t = time (NULL);
                timeptr = localtime (&t);
                if ((token = malloc (81))) {
                    strftime (token, 80, "%I:%M:%S %p", timeptr);
                    snprintf (msg, sizeof (msg), "PRIVMSG %s :%s %s, %s!\r\n", message->channel, gettext ("It is"),
                              token, message->user);
                    free (token);
                }
                return msg;

            case TELL:
                if ((token = strtok (NULL, " "))) {
                    if ((parameters = strtok (NULL, "\r\n"))) {
                        if (*token == '*')
                            message->channel = ++token;
                        snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s\r\n", message->channel, token,
                                  db_lookup (DATABASE_FILE, parameters));
                    }
                }
                return msg;

            case OP:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                        if (strstr (message->domain, db_lookup (DATABASE_FILE, "mcbot.domain")))
                            snprintf (msg, sizeof (msg), "MODE %s +o %s\r\n", message->channel, token);
                    }
                }
                return msg;

            case DEOP:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                        if (strstr (message->domain, db_lookup (DATABASE_FILE, "mcbot.domain")))
                            snprintf (msg, sizeof (msg), "MODE %s -o %s\r\n", message->channel, token);
                    }
                }
                return msg;

            case KICK:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                        if (strstr (message->domain, db_lookup (DATABASE_FILE, "mcbot.domain")))
                            snprintf (msg, sizeof (msg), "KICK %s %s\r\n", message->channel, token);
                    }
                }
                return msg;

            case BAN:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                        if (strstr (message->domain, db_lookup (DATABASE_FILE, "mcbot.domain")))
                            snprintf (msg, sizeof (msg), "MODE %s +b %s\r\n", message->channel, token);
                    }
                }
                return msg;

            case UNBAN:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                        if (strstr (message->domain, db_lookup (DATABASE_FILE, "mcbot.domain")))
                            snprintf (msg, sizeof (msg), "MODE %s -b %s\r\n", message->channel, token);
                    }
                }
                return msg;

            case KICKBAN:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                        if (strstr (message->domain, db_lookup (DATABASE_FILE, "mcbot.domain")))
                            snprintf (msg, sizeof (msg), "MODE %s +b %s\r\nKICK %s %s\r\n", message->channel, token,
                                      message->channel, token);
                    }
                }
                return msg;

            case HELLO:
                snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s?\r\n", message->channel, gettext ("What's up"),
                          message->user);
                return msg;

            case TOPIC:
                if ((token = strtok (NULL, "\r\n")) == NULL)
                    return NULL;

                snprintf (msg, sizeof (msg), "TOPIC %s :%s\r\n", message->channel, token);
                return msg;
            }
        }
        map++;
    }

    return NULL;
}