connect Watchdog before loading saved data (channels)
[srvx.git] / src / mod-watchdog.c
index 1d70cf6f1746d774f173a22af0ee0a63eb51eb03..4cfcd34e41be27687d52c552ab80941a74bbad90 100644 (file)
@@ -22,7 +22,7 @@
  * "modules" {
  *     "watchdog" {
  *         "nick" "Watchdog";
- *         "modes" "+iok"
+ *         "modes" "+iok";
  *     };
  *  };
  *
 #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
@@ -68,6 +75,7 @@ struct userNode *watchdog;
 static struct module *watchdog_module;
 static struct service *watchdog_service;
 static struct shitList shitlist;
+static dict_t chanlist;
 static struct log_type *MS_LOG;
 
 
@@ -95,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)
 {
@@ -125,6 +190,38 @@ delete_badword(struct badword *badword)
     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)
 {
@@ -167,12 +264,29 @@ 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(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;
 }
 
@@ -182,6 +296,7 @@ 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 < shitlist.used; ++ii) {
@@ -195,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;
 }
 
@@ -204,30 +330,40 @@ watchdog_cleanup(void)
     while (shitlist.used)
         delete_badword(shitlist.list[0]);
     shitList_clean(&shitlist);
+    dict_delete(chanlist);
 }
 
 int
 watchdog_init(void)
 {
     MS_LOG = log_register_type("Watchdog", "file:watchdog.log");
+    
     shitList_init(&shitlist);
-    conf_register_reload(watchdog_conf_read);
-    reg_exit_func(watchdog_cleanup);
-    saxdb_register("Watchdog", watchdog_saxdb_read, watchdog_saxdb_write);
+    /* set up chanlist dict */
+    dict_delete(chanlist);
+    chanlist = dict_new();
+    dict_set_free_data(chanlist, free_chanlist_entry);
 
     const char *nick, *modes;
-    if((nick = conf_get_data("services/watchdog/nick", RECDB_QSTRING))) {
-        modes = conf_get_data("services/watchdog/modes", RECDB_QSTRING);
+    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);
     }
 
+    conf_register_reload(watchdog_conf_read);
+    reg_exit_func(watchdog_cleanup);
+    saxdb_register("Watchdog", watchdog_saxdb_read, watchdog_saxdb_write);
+
     watchdog_module = module_register("Watchdog", MS_LOG, "mod-watchdog.help", NULL);
     modcmd_register(watchdog_module, "addbad", cmd_addbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
     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;