added cmd_register & cmd_unregister to mod-watchdog.c, fixed trigger & missing ;...
[srvx.git] / src / mod-watchdog.c
index 11d59c5f535472c8d98f83da1e7081052c012621..36b3ac57e5fe892cb952c5f4b04a3d8bfa60b352 100644 (file)
@@ -22,7 +22,7 @@
  * "modules" {
  *     "watchdog" {
  *         "nick" "Watchdog";
- *         "modes" "+iok"
+ *         "modes" "+iok";
  *     };
  *  };
  *
 #include "saxdb.h"
 #include "timeq.h"
 
-#define KEY_SENT "sent"
+#define KEY_BADWORDS "badwords"
+#define KEY_BADWORD_MASK "mask"
+#define KEY_BADWORD_TRIGGERED "count"
+#define KEY_BADWORD_ACTION "action"
+#define KEY_CHANNELS "channel"
 
 static const struct message_entry msgtab[] = {
-    { "WDMSG_NULL", "null." },
+    { "WD_REGISTER_SUCCESS", "$b%s$b is now registered with %s." },
+    { "WD_NOT_REGISTERED", "$b%s$b is not registered with %s." },
     { NULL, NULL }
 };
 
+DECLARE_LIST(shitList, struct badword*);
+DEFINE_LIST(shitList, struct badword*)
+
 struct badword {
     char *badword_mask;
     unsigned int triggered : 29;
     unsigned int action : 3;
 };
 
-DECLARE_LIST(shitList, struct badword*);
-DEFINE_LIST(shitList, struct badword*)
+struct watchdog_channel {
+    struct chanNode *channel;
+    //struct shitList *shitlist;
+};
 
 /* badword.action fields */
 #define BADACTION_KICK   1
@@ -56,14 +66,17 @@ DEFINE_LIST(shitList, struct badword*)
 #define BADACTION_GLINE  3
 
 static struct {
-    char *nick;
-    char *modes;
+    const char *nick;
+    const char *modes;
 } watchdog_conf;
 
+const char *watchdog_module_deps[] = { NULL };
 struct userNode *watchdog;
 static struct module *watchdog_module;
 static struct service *watchdog_service;
-static struct shitList *shitlist;
+static struct shitList shitlist;
+static dict_t chanlist;
+static struct log_type *MS_LOG;
 
 
 static MODCMD_FUNC(cmd_addbad)
@@ -90,6 +103,63 @@ static MODCMD_FUNC(cmd_listbad)
     return 1;
 }
 
+static struct watchdog_channel *add_channel(const char *name);
+
+static MODCMD_FUNC(cmd_register)
+{
+    dict_iterator_t it;
+
+    if((argc < 2) || !IsChannelName(argv[1]))
+    {
+        reply("MSG_NOT_CHANNEL_NAME");
+        return 0;
+    }
+
+    if(opserv_bad_channel(argv[1]))
+    {
+        reply("CSMSG_ILLEGAL_CHANNEL", argv[1]);
+        return 0;
+    }
+
+    channel = AddChannel(argv[1], now, NULL, NULL);
+
+    for (it = dict_first(chanlist); it; it = iter_next(it)) {
+        struct watchdog_channel *chan = iter_data(it);
+        if(chan->channel == channel) {
+            reply("CSMSG_ALREADY_REGGED", channel->name);
+            return 0;
+        }
+    }
+
+    add_channel(channel->name);
+    reply("WD_REGISTER_SUCCESS", channel->name, watchdog->nick);
+    return 1;
+}
+
+static MODCMD_FUNC(cmd_unregister)
+{
+    struct watchdog_channel *chan = NULL;
+    dict_iterator_t it;
+    
+    for (it = dict_first(chanlist); it; it = iter_next(it)) {
+        chan = iter_data(it);
+        if(chan->channel == channel)
+            break;
+    }
+    
+    if(chan && chan->channel == channel) {
+        //found, unregister it!
+        DelChannelUser(watchdog, channel, "unregistered.", 0);
+        dict_remove(chanlist, channel->name);
+        reply("CSMSG_UNREG_SUCCESS", channel->name);
+        return 1;
+    } else {
+        reply("WD_NOT_REGISTERED", channel->name, watchdog->nick);
+        return 0;
+    }
+
+}
+
 static void
 watchdog_channel_message(struct userNode *user, struct chanNode *chan, const char *text, struct userNode *bot, unsigned int is_notice)
 {
@@ -97,7 +167,7 @@ watchdog_channel_message(struct userNode *user, struct chanNode *chan, const cha
 }
 
 static struct badword*
-add_badword(char *badword, unsigned int triggered, unsigned int action)
+add_badword(char *badword_mask, unsigned int triggered, unsigned int action)
 {
     struct badword *badword;
 
@@ -105,21 +175,53 @@ add_badword(char *badword, unsigned int triggered, unsigned int action)
     if (!badword)
         return NULL;
 
-    badword->badword_mask = strdup(badword);
+    badword->badword_mask = strdup(badword_mask);
     badword->triggered = triggered;
     badword->action = action;
-    shitlist_append(&shitlist, badword);
+    shitList_append(&shitlist, badword);
     return badword;
 }
 
 static void
 delete_badword(struct badword *badword)
 {
-    shitlist_remove(&shitlist, badword);
+    shitList_remove(&shitlist, badword);
     free(badword->badword_mask);
     free(badword);
 }
 
+static struct watchdog_channel*
+add_channel(const char *name)
+{
+    struct watchdog_channel *wc;
+    struct mod_chanmode *change;
+
+    if(!watchdog) //module disabled
+        return NULL;
+
+    wc = calloc(1, sizeof(*wc));
+    if (!wc)
+        return NULL;
+
+    wc->channel = AddChannel(name, now, NULL, NULL);
+    change = mod_chanmode_alloc(1);
+    change->argc = 1;
+    change->args[0].mode = MODE_CHANOP;
+    change->args[0].u.member = AddChannelUser(watchdog, wc->channel);
+    mod_chanmode_announce(watchdog, wc->channel, change);
+       mod_chanmode_free(change);
+    dict_insert(chanlist, wc->channel->name, wc);
+    return wc;
+}
+
+static void
+free_chanlist_entry(void *data)
+{
+    struct watchdog_channel *wc = data;
+    
+    free(wc);
+}
+
 static void
 watchdog_conf_read(void)
 {
@@ -139,7 +241,7 @@ watchdog_conf_read(void)
     watchdog_conf.nick = str;
     
     str = database_get_data(conf_node, "modes", RECDB_QSTRING);
-    watchdog_conf.modes = str;
+    watchdog_conf.modes = (str ? str : NULL);
 }
 
 static int
@@ -162,12 +264,30 @@ watchdog_saxdb_read_shitlist(const char *name, void *data, UNUSED_ARG(void *extr
         return 0;
 }
 
+static int
+watchdog_saxdb_read_chanlist(const char *name, void *data, UNUSED_ARG(void *extra))
+{
+    struct record_data *rd = data;
+
+     if (rd->type == RECDB_OBJECT) {
+        dict_t obj = GET_RECORD_OBJECT(rd);
+        /* nothing in here, yet */
+
+        add_channel(name);
+        return 1;
+    } else
+        return 0;
+}
+
 static int
 watchdog_saxdb_read(struct dict *db)
 {
     struct dict *object;
-    if ((object = database_get_data(conf_db, KEY_BADWORDS, RECDB_OBJECT)))
+    if ((object = database_get_data(db, KEY_BADWORDS, RECDB_OBJECT)))
         dict_foreach(object, watchdog_saxdb_read_shitlist, NULL);
+    if ((object = database_get_data(db, KEY_CHANNELS, RECDB_OBJECT)))
+        dict_foreach(object, watchdog_saxdb_read_chanlist, NULL);
+    return 1;
 }
 
 static int
@@ -176,10 +296,11 @@ watchdog_saxdb_write(struct saxdb_context *ctx)
     struct badword *badword;
     char str[17];
     unsigned int id = 0, ii;
+    dict_iterator_t it;
 
     saxdb_start_record(ctx, KEY_BADWORDS, 1);
-    for (ii = 0; ii < ma->recvd.used; ++ii) {
-        badword = ma->recvd.list[ii];
+    for (ii = 0; ii < shitlist.used; ++ii) {
+        badword = shitlist.list[ii];
         snprintf(str, sizeof(str), "%x", id++);
         saxdb_start_record(ctx, str, 0);
         saxdb_write_string(ctx, KEY_BADWORD_MASK, badword->badword_mask);
@@ -189,6 +310,17 @@ watchdog_saxdb_write(struct saxdb_context *ctx)
     }
     saxdb_end_record(ctx);
 
+    if (dict_size(chanlist)) {
+        saxdb_start_record(ctx, KEY_CHANNELS, 1);
+        for (it = dict_first(chanlist); it; it = iter_next(it)) {
+            struct watchdog_channel *wc = iter_data(it);
+            saxdb_start_record(ctx, wc->channel->name, 0);
+            //anything else?
+            saxdb_end_record(ctx);
+        }
+        saxdb_end_record(ctx);
+    }
+    
     return 0;
 }
 
@@ -197,23 +329,32 @@ watchdog_cleanup(void)
 {
     while (shitlist.used)
         delete_badword(shitlist.list[0]);
-    shitlist_clean(&shitlist);
+    shitList_clean(&shitlist);
+    dict_delete(chanlist);
 }
 
 int
 watchdog_init(void)
 {
     MS_LOG = log_register_type("Watchdog", "file:watchdog.log");
+    
+    shitList_init(&shitlist);
+    /* set up chanlist dict */
+    dict_delete(chanlist);
+    chanlist = dict_new();
+    dict_set_free_data(chanlist, free_chanlist_entry);
+    
     conf_register_reload(watchdog_conf_read);
     reg_exit_func(watchdog_cleanup);
     saxdb_register("Watchdog", watchdog_saxdb_read, watchdog_saxdb_write);
 
     const char *nick, *modes;
-    if(nick = conf_get_data("services/spamserv/nick", RECDB_QSTRING)) {
-        modes = conf_get_data("services/spamserv/modes", RECDB_QSTRING);
-        spamserv = AddLocalUser(nick, nick, NULL, "Watchdog Service", modes);
-        spamserv_service = service_register(spamserv);
-        reg_allchanmsg_func(spamserv, watchdog_channel_message);
+    if((nick = conf_get_data("modules/watchdog/nick", RECDB_QSTRING))) {
+        modes = conf_get_data("modules/watchdog/modes", RECDB_QSTRING);
+        watchdog = AddLocalUser(nick, nick, NULL, "Watchdog Service", modes);
+        watchdog_service = service_register(watchdog);
+        watchdog_service->trigger = ',';
+        reg_allchanmsg_func(watchdog, watchdog_channel_message);
     }
 
     watchdog_module = module_register("Watchdog", MS_LOG, "mod-watchdog.help", NULL);
@@ -221,6 +362,8 @@ watchdog_init(void)
     modcmd_register(watchdog_module, "delbad", cmd_delbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
     modcmd_register(watchdog_module, "editbad", cmd_editbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
     modcmd_register(watchdog_module, "listbad", cmd_listbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
+    modcmd_register(watchdog_module, "register", cmd_register, 1, MODCMD_REQUIRE_AUTHED, "flags", "+helping", NULL);
+    modcmd_register(watchdog_module, "unregister", cmd_unregister, 1, MODCMD_REQUIRE_AUTHED | MODCMD_REQUIRE_CHANNEL, "flags", "+helping", NULL);
     message_register_table(msgtab);
 
     return 1;