allow IRC Ops unregister protected channels (nodelete override)
[srvx.git] / src / chanserv.c
index f90f0f6f6bde2c241aab487a4a2216428d3b15ed..75fbdaf31ac76354dc01eab828a43059e4bdf01f 100644 (file)
@@ -22,7 +22,7 @@
 #include "conf.h"
 #include "global.h"
 #include "modcmd.h"
-#include "opserv.h" /* for opserv_bad_channel() */
+#include "opserv.h" /* for opserv_bad_channel() and devnull management */
 #include "nickserv.h" /* for oper_outranks() */
 #include "saxdb.h"
 #include "spamserv.h"
@@ -209,7 +209,7 @@ static const struct message_entry msgtab[] = {
 /* User management */
     { "CSMSG_ADDED_USER", "Added %s to the %s user list with access %d." },
     { "CSMSG_DELETED_USER", "Deleted %s (with access %d) from the %s user list." },
-    { "CSMSG_BAD_RANGE", "Invalid access range; minimum (%d) must be greater than maximum (%d)." },
+    { "CSMSG_BAD_RANGE", "Invalid access range; minimum (%d) must be lower than maximum (%d)." },
     { "CSMSG_DELETED_USERS", "Deleted accounts matching $b%s$b with access from $b%d$b to $b%d$b from the %s user list." },
     { "CSMSG_TRIMMED_USERS", "Trimmed $b%d users$b with access from %d to %d from the %s user list who were inactive for at least %s." },
     { "CSMSG_INCORRECT_ACCESS", "%s has access $b%d$b, not %s." },
@@ -345,6 +345,7 @@ static const struct message_entry msgtab[] = {
     { "CSMSG_ACCESS_SEARCH_HEADER", "%s users from level %d to %d matching %s:" },
     { "CSMSG_INVALID_ACCESS", "$b%s$b is an invalid access level." },
     { "CSMSG_CHANGED_ACCESS", "%s now has access $b%d$b in %s." },
+    { "CSMSG_TOTAL_USERS", "There are $b%d$b users in %s." },
 
 /* Channel note list */
     { "CSMSG_NOTELIST_HEADER", "Notes for $b%s$b:" },
@@ -2284,7 +2285,7 @@ static CHANSERV_FUNC(cmd_unregister)
         return 0;
     }
 
-    if(IsProtected(cData))
+    if(IsProtected(cData) && !IsOper(user))
     {
         reply("CSMSG_UNREG_NODELETE", channel->name);
         return 0;
@@ -3235,6 +3236,45 @@ static CHANSERV_FUNC(cmd_devoice)
     return modify_users(CSFUNC_ARGS, NULL, MODE_REMOVE|MODE_VOICE, "CSMSG_DEVOICED_USERS");
 }
 
+static CHANSERV_FUNC(cmd_opme)
+{
+    struct mod_chanmode change;
+    struct userData *uData;
+    const char *errmsg;
+
+    mod_chanmode_init(&change);
+    change.argc = 1;
+    change.args[0].u.member = GetUserMode(channel, user);
+    if(!change.args[0].u.member)
+    {
+        if(argc)
+            reply("MSG_CHANNEL_ABSENT", channel->name);
+        return 0;
+    }
+
+    struct devnull_class *devnull;
+    if(user->handle_info->devnull && (devnull = devnull_get(user->handle_info->devnull)) && (devnull->modes & DEVNULL_MODE_OPME))
+    {
+        change.args[0].mode = MODE_CHANOP;
+        errmsg = "CSMSG_ALREADY_OPPED";
+    }
+    else
+    {
+        if(argc)
+            reply("CSMSG_NO_ACCESS");
+        return 0;
+    }
+    change.args[0].mode &= ~change.args[0].u.member->modes;
+    if(!change.args[0].mode)
+    {
+        if(argc)
+            reply(errmsg, channel->name);
+        return 0;
+    }
+    modcmd_chanmode_announce(&change);
+    return 1;
+}
+
 static int
 bad_channel_ban(struct chanNode *channel, struct userNode *user, const char *ban, unsigned int *victimCount, struct modeNode **victims)
 {
@@ -3854,7 +3894,8 @@ static CHANSERV_FUNC(cmd_myaccess)
 
         if(IsProtected(cData)
            && (target_handle != user->handle_info)
-           && !GetTrueChannelAccess(cData, user->handle_info))
+           && !GetTrueChannelAccess(cData, user->handle_info)
+           && !IsNetworkHelper(user))
             continue;
         sbuf.used = 0;
         string_buffer_append_printf(&sbuf, "[%s (%d", cData->channel->name, uData->access);
@@ -4171,6 +4212,7 @@ cmd_list_users(struct userNode *user, struct chanNode *channel, unsigned int arg
     }
     free(lData.table.contents[0]);
     free(lData.table.contents);
+    reply("CSMSG_TOTAL_USERS",(lData.table.length - 1),channel->name);
     return 1;
 }
 
@@ -8660,6 +8702,8 @@ init_chanserv(const char *nick)
     DEFINE_COMMAND(endvote, 1, MODCMD_REQUIRE_AUTHED, NULL);
     DEFINE_COMMAND(voteresults, 1, MODCMD_REQUIRE_AUTHED, NULL);
 
+    DEFINE_COMMAND(opme, 1, MODCMD_REQUIRE_AUTHED|MODCMD_REQUIRE_CHANNEL, NULL);
+    
     /* Channel options */
     DEFINE_CHANNEL_OPTION(defaulttopic);
     DEFINE_CHANNEL_OPTION(topicmask);