changed spamserv,chanserv and watchdog messages to privmsgs
[srvx.git] / src / chanserv.c
index d50c9147fbe56909b65f776179f763e99bb2ca8d..44f6d9d5f1488f88c0b24d06260e0fce960e1eb9 100644 (file)
@@ -43,6 +43,7 @@
 #define KEY_DNR_EXPIRE_FREQ         "dnr_expire_freq"
 #define KEY_MAX_CHAN_USERS          "max_chan_users"
 #define KEY_MAX_CHAN_BANS           "max_chan_bans"
+#define KEY_MIN_TIME_BANS                      "min_time_bans"
 #define KEY_NICK                    "nick"
 #define KEY_OLD_CHANSERV_NAME       "old_chanserv_name"
 #define KEY_8BALL_RESPONSES         "8ball"
@@ -155,6 +156,7 @@ static const struct message_entry msgtab[] = {
     { "CSMSG_MUST_BE_OPPED", "You must be a channel operator in $b%s$b to register it." },
     { "CSMSG_PROXY_FORBIDDEN", "You may not register a channel for someone else." },
     { "CSMSG_OWN_TOO_MANY", "%s already owns enough channels (at least %d); use FORCE to override." },
+    { "CMSG_ALERT_REGISTERED" "%s registered to %s by %s." },
 
 /* Do-not-register channels */
     { "CSMSG_NOT_DNR", "$b%s$b is not a valid channel name or *account." },
@@ -177,6 +179,7 @@ static const struct message_entry msgtab[] = {
     { "CSMSG_UNREG_NODELETE", "$b%s$b is protected from unregistration." },
     { "CSMSG_CHAN_SUSPENDED", "$b$C$b access to $b%s$b has been temporarily suspended (%s)." },
     { "CSMSG_CONFIRM_UNREG", "To confirm this unregistration, you must use 'unregister %s'." },
+    { "CMSG_ALERT_UNREGISTERED" "%s %s" },
 
 /* Channel moving */
     { "CSMSG_MOVE_SUCCESS", "Channel registration has been moved to $b%s$b." },
@@ -547,6 +550,9 @@ static const struct message_entry msgtab[] = {
 DECLARE_LIST(dnrList, struct do_not_register *);
 DEFINE_LIST(dnrList, struct do_not_register *)
 
+#define chanserv_notice(target, format...) send_message(target , chanserv , ## format)
+#define chanserv_oper_message(format...) do { if(chanserv_conf.oper_channel) send_channel_message(chanserv_conf.oper_channel , chanserv , ## format); } while(0)
+
 static int eject_user(struct userNode *user, struct chanNode *channel, unsigned int argc, char *argv[], struct svccmd *cmd, int action);
 
 struct userNode *chanserv;
@@ -581,6 +587,7 @@ static struct
     unsigned int    max_owned;
     unsigned int    max_chan_users;
     unsigned int    max_chan_bans;
+    unsigned int    min_time_bans;
     unsigned int    max_userinfo_length;
     
     unsigned int    revoke_mode_a;
@@ -599,6 +606,8 @@ static struct
     const char          *new_channel_authed;
     const char          *new_channel_unauthed;
     const char          *new_channel_msg;
+
+    struct chanNode    *oper_channel;
 } chanserv_conf;
 
 struct listData
@@ -1515,10 +1524,9 @@ unregister_channel(struct chanData *channel, const char *reason)
     channel->channel->channel_info = NULL;
 
     dict_delete(channel->notes);
-    sprintf(msgbuf, "%s %s", channel->channel->name, reason);
     if(!IsSuspended(channel))
         DelChannelUser(chanserv, channel->channel, msgbuf, 0);
-    global_message(MESSAGE_RECIPIENT_OPERS | MESSAGE_RECIPIENT_HELPERS, msgbuf);
+    chanserv_oper_message(CSMSGL_CHANNEL_UNREGISTERED, channel->channel->name, reason);
     UnlockChannel(channel->channel);
     free(channel);
     registered_channels--;
@@ -2269,8 +2277,7 @@ static CHANSERV_FUNC(cmd_register)
     else
         reply("CSMSG_REG_SUCCESS", channel->name);
 
-    sprintf(reason, "%s registered to %s by %s.", channel->name, handle->handle, user->handle_info->handle);
-    global_message(MESSAGE_RECIPIENT_OPERS | MESSAGE_RECIPIENT_HELPERS, reason);
+    chanserv_oper_message(CSMSG_ALERT_REGISTERED, channel->name, handle->handle, user->handle_info->handle);
     return 1;
 }
 
@@ -3476,7 +3483,7 @@ eject_user(struct userNode *user, struct chanNode *channel, unsigned int argc, c
         {
             duration = ParseInterval(argv[2]);
 
-            if(duration < 15)
+            if(duration < chanserv_conf.min_time_bans)
             {
                 reply("CSMSG_DURATION_TOO_LOW");
                 free(ban);
@@ -4167,6 +4174,8 @@ cmd_list_users(struct userNode *user, struct chanNode *channel, unsigned int arg
         ary[1] = uData->handle->handle;
         if(uData->present)
             ary[2] = "Here";
+        else if(HANDLE_FLAGGED(uData->handle, NETWORK))
+             ary[2] = "Here";
         else if(!uData->seen)
             ary[2] = "Never";
         else
@@ -4174,6 +4183,12 @@ cmd_list_users(struct userNode *user, struct chanNode *channel, unsigned int arg
         ary[2] = strdup(ary[2]);
         if(IsUserSuspended(uData))
             ary[3] = "Suspended";
+        else if(HANDLE_FLAGGED(uData->handle, OPER))
+            ary[3] = "Operator";
+        else if(HANDLE_FLAGGED(uData->handle, HELPING))
+            ary[3] = "Staff";
+        else if(HANDLE_FLAGGED(uData->handle, NETWORK))
+            ary[3] = "Network";
         else if(HANDLE_FLAGGED(uData->handle, FROZEN))
             ary[3] = "Vacation";
         else if(HANDLE_FLAGGED(uData->handle, BOT))
@@ -4421,10 +4436,10 @@ static CHANSERV_FUNC(cmd_topic)
                     if(!isdigit(topic[pos]))
                         break;
                 }
-                if(advtopic_index < 0 || advtopic_index > MAXADVTOPICENTRIES)
+                if(advtopic_index < 0 || advtopic_index >= MAXADVTOPICENTRIES)
                 {
                     //invalid id!
-                    reply("CSMSG_ADVTOPIC_INVALID_ID", advtopic_index);
+                    reply("CSMSG_ADVTOPIC_INVALID_ID", advtopic_index+1);
                     return 0;
                 }
                 if(cData->advtopic[advtopic_index])
@@ -4446,7 +4461,6 @@ static CHANSERV_FUNC(cmd_topic)
                             new_topic[dpos++] = *ptr; //is % again
                             break;
                         }
-                        ptr--;
                         advtopic_index--; //no zero base
                         if(!cData->advtopic[advtopic_index])
                             break; //just leave it empty
@@ -4458,11 +4472,12 @@ static CHANSERV_FUNC(cmd_topic)
                         break;
                     case '\\': 
                         ptr++; /* and fall through */
+                        if(!*ptr) break;
                     default:
                         new_topic[dpos++] = *ptr;
+                        ptr++;
                         break;
                     }
-                    ptr++;
                 }
             } else {
                 while((tchar = topic_mask[pos++]) && (dpos <= TOPICLEN))
@@ -6573,13 +6588,23 @@ static CHANSERV_FUNC(cmd_giveownership)
     return 1;
 }
 
+static void
+chanserv_expire_user_suspension(void *data)
+{
+    struct userData *target = data;
+
+       target->expires = 0;
+       target->flags &= ~USER_SUSPENDED;       
+}
+
 static CHANSERV_FUNC(cmd_suspend)
 {
     struct handle_info *hi;
     struct userData *actor, *real_actor, *target;
     unsigned int override = 0;
+    time_t expiry;
 
-    REQUIRE_PARAMS(2);
+    REQUIRE_PARAMS(3);
     if(!(hi = modcmd_get_handle_info(user, argv[1]))) return 0;
     actor = GetChannelUser(channel->channel_info, user->handle_info);
     real_actor = GetChannelAccess(channel->channel_info, user->handle_info);
@@ -6605,6 +6630,24 @@ static CHANSERV_FUNC(cmd_suspend)
     }
     if(!real_actor || target->access >= real_actor->access)
         override = CMD_LOG_OVERRIDE;
+       if(!strcmp(argv[2], "0"))
+        expiry = 0;
+    else
+    {
+        unsigned int duration;
+        if(!(duration = ParseInterval(argv[2])))
+        {
+            reply("MSG_INVALID_DURATION", argv[2]);
+            return 0;
+        }
+        expiry = now + duration;
+    }
+
+       target->expires = expiry;
+
+       if(target->expires)
+               timeq_add(target->expires, chanserv_expire_user_suspension, target);
+
     target->flags |= USER_SUSPENDED;
     reply("CSMSG_USER_SUSPENDED", hi->handle, channel->name);
     return 1 | override;
@@ -6637,6 +6680,7 @@ static CHANSERV_FUNC(cmd_unsuspend)
     }
     if(!real_actor || target->access >= real_actor->access)
         override = CMD_LOG_OVERRIDE;
+    timeq_del(target->expires, chanserv_expire_user_suspension, target, 0);
     target->flags &= ~USER_SUSPENDED;
     scan_user_presence(target, NULL);
     reply("CSMSG_USER_UNSUSPENDED", hi->handle, channel->name);
@@ -7849,6 +7893,8 @@ chanserv_conf_read(void)
     chanserv_conf.max_chan_users = str ? atoi(str) : 512;
     str = database_get_data(conf_node, KEY_MAX_CHAN_BANS, RECDB_QSTRING);
     chanserv_conf.max_chan_bans = str ? atoi(str) : 512;
+    str = database_get_data(conf_node, KEY_MIN_TIME_BANS, RECDB_QSTRING);
+    chanserv_conf.min_time_bans = str ? atoi(str) : 5;
     str = database_get_data(conf_node, KEY_MAX_USERINFO_LENGTH, RECDB_QSTRING);
     chanserv_conf.max_userinfo_length = str ? atoi(str) : 400;
     str = database_get_data(conf_node, KEY_NICK, RECDB_QSTRING);
@@ -7939,6 +7985,16 @@ chanserv_conf_read(void)
     chanserv_conf.old_ban_names = strlist;
     str = database_get_data(conf_node, "off_channel", RECDB_QSTRING);
     off_channel = str ? atoi(str) : 0;
+
+    str = database_get_data(conf_node, "oper_chan", RECDB_QSTRING);
+       if(str)
+       {
+               chanserv_conf.oper_channel = AddChannel(str, now, "+tinms", NULL);
+       }
+       else
+       {
+               chanserv_conf.oper_channel = NULL;
+       }
 }
 
 static void
@@ -8023,7 +8079,7 @@ user_read_helper(const char *key, struct record_data *rd, struct chanData *chan)
 {
     struct handle_info *handle;
     struct userData *uData;
-    char *seen, *inf, *flags, *voted, *votefor;
+    char *seen, *inf, *flags, *voted, *votefor, *expires;
     unsigned long last_seen;
     unsigned short access_level;
 
@@ -8044,6 +8100,7 @@ user_read_helper(const char *key, struct record_data *rd, struct chanData *chan)
     seen = database_get_data(rd->d.object, KEY_SEEN, RECDB_QSTRING);
     last_seen = seen ? strtoul(seen, NULL, 0) : now;
     flags = database_get_data(rd->d.object, KEY_FLAGS, RECDB_QSTRING);
+    expires = database_get_data(rd->d.object, KEY_EXPIRES, RECDB_QSTRING);
     voted = database_get_data(rd->d.object, KEY_VOTE_VOTED, RECDB_QSTRING);
     votefor = database_get_data(rd->d.object, KEY_VOTE_VOTEDFOR, RECDB_QSTRING);
     handle = get_handle_info(key);
@@ -8055,6 +8112,15 @@ user_read_helper(const char *key, struct record_data *rd, struct chanData *chan)
 
     uData = add_channel_user(chan, handle, access_level, last_seen, inf);
     uData->flags = flags ? strtoul(flags, NULL, 0) : 0;
+       uData->expires = expires ? (signed)strtoul(expires, NULL, 0) : 0;
+
+       if((uData->flags & USER_SUSPENDED) && uData->expires)
+       {
+         if(uData->expires > now)
+                 timeq_add(uData->expires, chanserv_expire_user_suspension, uData);
+         else
+                 uData->flags &= ~USER_SUSPENDED;
+       }
     if(chan->vote) {
         uData->voted = voted ? strtoul(voted, NULL, 0) : 0;
         uData->votefor = votefor ? strtoul(votefor, NULL, 0) : 0;
@@ -8472,6 +8538,8 @@ chanserv_write_users(struct saxdb_context *ctx, struct userData *uData)
         saxdb_write_int(ctx, KEY_SEEN, uData->seen);
         if(uData->flags)
             saxdb_write_int(ctx, KEY_FLAGS, uData->flags);
+        if(uData->expires)
+            saxdb_write_int(ctx, KEY_EXPIRES, uData->expires);
         if(uData->channel->vote && uData->voted)
             saxdb_write_int(ctx, KEY_VOTE_VOTED, uData->voted);
         if(uData->channel->vote && uData->votefor)