]> jfr.im git - irc/quakenet/newserv.git/commitdiff
Added new USERS command - shows channel users with account names and Q flags.
authorsplidge <redacted>
Thu, 13 Mar 2008 01:26:04 +0000 (01:26 +0000)
committersplidge <redacted>
Thu, 13 Mar 2008 01:26:04 +0000 (01:26 +0000)
Usable by users if they have +o on Q on the channel and are currently on it.
Usable by staff at any time.

chanserv/chancmds/Makefile
chanserv/chancmds/commandlist.c
chanserv/chancmds/users.c [new file with mode: 0644]
chanserv/chanserv.h
chanserv/database/chanservdb_messages.c

index 9fcfa60f83615ca0826690553234e05bb9181c4a..6c3dd2cf2043472fb8ad0fa2ae8cec2911128065 100644 (file)
@@ -6,5 +6,5 @@ all: Makefile chanserv_chancmds.so
 Makefile:
        ../mkcommandlist.pl chanserv_chancmds.so
 
-chanserv_chancmds.so: addchan.o adduser.o autolimit.o ban.o banclear.o bandel.o banlist.o bantimer.o chanflags.o chanlev.o chanlevhistory.o chanmode.o channelcomment.o chanophistory.o chanstat.o chantype.o clearchan.o delchan.o deopall.o devoiceall.o giveowner.o invite.o op.o permban.o recover.o rejoin.o removeuser.o renchan.o requestowner.o rollbackchan.o settopic.o suspendchan.o suspendchanlist.o tempban.o unban.o unbanall.o unbanmask.o unbanme.o unsuspendchan.o voice.o welcome.o commandlist.o init.o 
+chanserv_chancmds.so: addchan.o adduser.o autolimit.o ban.o banclear.o bandel.o banlist.o bantimer.o chanflags.o chanlev.o chanlevhistory.o chanmode.o channelcomment.o chanophistory.o chanstat.o chantype.o clearchan.o delchan.o deopall.o devoiceall.o giveowner.o invite.o op.o permban.o recover.o rejoin.o removeuser.o renchan.o requestowner.o rollbackchan.o settopic.o suspendchan.o suspendchanlist.o tempban.o unban.o unbanall.o unbanmask.o unbanme.o unsuspendchan.o users.o voice.o welcome.o commandlist.o init.o 
         ld -shared -Bdynamic -o $@ $^ 
index 3964a2dc77d0bef07f419432e62feca25f9a7cfc..5d393b440f59b5d732823e012b3470cfcbbfe80e 100644 (file)
@@ -42,6 +42,7 @@ int csc_dounbanall(void *source, int cargc, char **cargv);
 int csc_dounbanmask(void *source, int cargc, char **cargv);
 int csc_dounbanme(void *source, int cargc, char **cargv);
 int csc_dounsuspendchan(void *source, int cargc, char **cargv);
+int csc_dousers(void *source, int cargc, char **cargv);
 int csc_dovoice(void *source, int cargc, char **cargv);
 int csc_dowelcome(void *source, int cargc, char **cargv);
 void chancmds_init(void);
@@ -89,6 +90,7 @@ void _init() {
   chanservaddcommand("unbanmask", QCMD_AUTHED, 2, csc_dounbanmask, "Removes bans matching a particular mask from a channel.", "Usage: UNBANMASK <channel> <mask>\nRemoves any bans on the channel which are overlapped by the named mask.  Can\nremove both channel bans and registered bans.  Where:\nchannel - channel to use\nmask    - mask to remove.  Any ban subsumed by this mask will be removed.  For\n          example, UNBANMASK *!*@*.isp.net would remove *!*@host1.isp.net and \n          *!*@host2.isp.net and *!user@*.isp.net.\nUNBANMASK requires operator (+o) access on the named channel.\nRemoving registered bans requires master (+m) access on the named channel.\n");
   chanservaddcommand("unbanme", QCMD_AUTHED, 1, csc_dounbanme, "Removes any bans affecting you from a channel.", "Usage: UNBANME <channel>\nThis command removes any channel bans which affect you from a channel.  It does\nnot affect persistent bans set by PERMBAN and TEMPBAN.  Where:\nchannel - channel to use\nUNBANME requires operator (+o) access on the named channel.\n");
   chanservaddcommand("unsuspendchan", QCMD_OPER, 1, csc_dounsuspendchan, "Unsuspends a channel from the bot.", "Usage: unsuspendchan <channel>\nUnsuspends specified channel.\n");
+  chanservaddcommand("users", QCMD_AUTHED, 1, csc_dousers, "Displays a list of users on the channel.", "Usage: USERS <channel>\nDisplays a list of users on the named channel along with their usernames and flags\non the channel, where:\nchannel - channel to use\nUSERS requires operator (+o) access on the named channel.\n");
   chanservaddcommand("voice", QCMD_AUTHED, 20, csc_dovoice, "Voices you or other users on channel(s).", "Usage: VOICE [<channel> [<user1> [<user2> [...]]]\nGrants voice to you on one or more channels, or grants voice to one or more\nother users on a particular channel.  This command cannot be used to grant\nvoice to users who would otherwise be prevented from obtaining voice, e.g.\nthe quiet (+q) chanlev flag.  Where:\nchannel - channel to use.  If no channel is specified, you will be granted voice\n          on every channel where you have appropriate access and are not already \n          voiced.\nuser<n> - other users to grant voice to.  Must be specified as the nickname\n          of users who are on the named channel.\nVoicing yourself requires voice (+v) access on the relevant channels.\nVoicing other users requires operator (+o) access on the named channel.  If this \ncommand is used to voice other users, a notice will be sent to channel operators\non the channel identifying you, unless you have master (+m) access.\n");
   chanservaddcommand("welcome", QCMD_AUTHED, 2, csc_dowelcome, "Shows or changes the welcome message on a channel.", "Usage: WELCOME <channel> [<message>]\nThis shows the current welcome message set on a channel and allows it to be\nchanged.  In order to be displayed to users, the feature must be enabled\nby the +w chanflag (see CHANFLAGS).  Where:\nchannel - channel to use\nmessage - welcome message to set.  If this is not provided the existing welcome\n          message is displayed.\nDisplaying the message requires operator (+o) access on the named channel.\nChanging the message requires master (+m) access on the named channel.\n");
 }
@@ -134,6 +136,7 @@ void _fini() {
   chanservremovecommand("unbanmask", csc_dounbanmask);
   chanservremovecommand("unbanme", csc_dounbanme);
   chanservremovecommand("unsuspendchan", csc_dounsuspendchan);
+  chanservremovecommand("users", csc_dousers);
   chanservremovecommand("voice", csc_dovoice);
   chanservremovecommand("welcome", csc_dowelcome);
 }
diff --git a/chanserv/chancmds/users.c b/chanserv/chancmds/users.c
new file mode 100644 (file)
index 0000000..94398d1
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * CMDNAME: users
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 1
+ * CMDDESC: Displays a list of users on the channel.
+ * CMDFUNC: csc_dousers
+ * CMDPROTO: int csc_dousers(void *source, int cargc, char **cargv);
+ * CMDHELP: Usage: USERS <channel>
+ * CMDHELP: Displays a list of users on the named channel along with their usernames and flags
+ * CMDHELP: on the channel, where:
+ * CMDHELP: channel - channel to use
+ * CMDHELP: USERS requires operator (+o) access on the named channel.
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+#define ISQ   0x40000000
+#define ISOP  0x20000000
+#define ISV   0x10000000
+
+struct chanuserrec {
+  unsigned int flags; /* Something that sorts nicely */
+  regchanuser *rcup;
+  reguser *rup;
+  nick *np;
+};
+
+static int comparetheflags(const void *a, const void *b) {
+  const struct chanuserrec *ra=a, *rb=b;
+  
+  return rb->flags-ra->flags;
+}
+
+int csc_dousers(void *source, int cargc, char **cargv) {
+  nick *sender=source, *np;
+  chanindex *cip;
+  regchan *rcp;
+  struct chanuserrec *theusers;
+  regchanuser *rcup;
+  channel *cp;
+  unsigned int i,j;
+  char *flagbuf, *unbuf, modechar;
+  char uhbuf[USERLEN+HOSTLEN+2];
+  flag_t flagmask;
+  unsigned int ops,voices,users,flags,qops,masters;
+  
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "users");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV,
+                          NULL, "users", QPRIV_VIEWFULLCHANLEV, 0)))
+    return CMD_ERROR;
+  
+  rcp=cip->exts[chanservext];
+
+  if (!(cp=cip->channel)) {
+    chanservstdmessage(sender,QM_EMPTYCHAN,cip->name->content);
+    return CMD_ERROR;
+  }
+  
+  if (!cs_privcheck(QPRIV_VIEWFULLCHANLEV, sender) && !getnumerichandlefromchanhash(cip->channel->users,sender->numeric)) {
+    chanservstdmessage(sender,QM_NOTONCHAN,cip->name->content);
+    return CMD_ERROR;
+  }
+  
+  theusers=malloc(cp->users->totalusers * sizeof(struct chanuserrec));
+  memset(theusers,0,cp->users->totalusers * sizeof(struct chanuserrec));
+  
+  for (i=0,j=0;i<cp->users->hashsize;i++) {
+    if (cp->users->content[i]==nouser)
+      continue;
+    
+    if (!(np=getnickbynumeric(cp->users->content[i])))
+      goto out;
+
+    theusers[j].np=np;
+
+    theusers[j].flags=(cp->users->content[i]>>2) & 0x30000000;
+
+    if (np==chanservnick) {
+      theusers[j].flags|=0x40000000;
+    }
+    
+    theusers[j].rup=getreguserfromnick(np);
+    if (theusers[j].rup) {
+      theusers[j].rcup=findreguseronchannel(rcp, theusers[j].rup);
+      if (theusers[j].rcup)
+        theusers[j].flags |= theusers[j].rcup->flags;
+    }
+    j++;
+  }
+  
+  qsort(theusers, j, sizeof(struct chanuserrec), comparetheflags);
+  
+  chanservstdmessage(sender,QM_USERSHEADER, cip->name->content);
+  
+  flagmask=QCUFLAGS_PUBLIC;
+  ops=voices=users=flags=qops=masters=0;
+  if (cs_checkaccess(sender, NULL, CA_MASTERPRIV, cip, "users", 0, 1))
+    flagmask |= QCUFLAGS_PUNISH;
+  
+  if (cs_privcheck(QPRIV_VIEWFULLCHANLEV, sender))
+    flagmask = QCUFLAG_ALL;
+  
+  for (i=0;i<j;i++) {
+    if (theusers[i].flags & ISOP) {
+      ops++;
+      modechar='@';
+    } else if (theusers[i].flags & ISV) {
+      voices++;
+      modechar='+';
+    } else {
+      users++;
+      modechar=' ';
+    } 
+
+    if (theusers[i].flags & ISQ) {
+      modechar='@';
+      unbuf="It's me!";
+      flagbuf="";
+    } else {
+      if (theusers[i].rup) {
+        unbuf=theusers[i].rup->username;
+      } else {
+        unbuf="";
+      }
+      
+      rcup=theusers[i].rcup;
+      
+      if (rcup) {
+        flags++;
+        if (CUHasOpPriv(rcup))
+          qops++;
+        
+        if (CUIsMaster(rcup) || CUIsOwner(rcup))
+          masters++;
+      }        
+      
+      if (theusers[i].rcup && (theusers[i].rcup->flags & flagmask)) {
+        flagbuf=printflags((flagmask | (theusers[i].np==sender?QCUFLAGS_PERSONAL:0)) & theusers[i].rcup->flags, rcuflags);
+      } else {
+        flagbuf="";
+      }
+    }
+    np=theusers[i].np;
+    chanservsendmessage(sender, "%c%-15s %-15s %-12s (%s)",modechar,np->nick,unbuf,flagbuf,visibleuserhost(np, uhbuf));
+  }
+  free(theusers);
+  
+  chanservstdmessage(sender, QM_ENDOFLIST);
+  chanservstdmessage(sender, QM_USERSSUMMARY, j, ops, voices, users, flags, qops, masters);
+  return CMD_OK;
+  
+  out:
+  free(theusers);
+  return CMD_ERROR;
+}
index 35c5389c4b8b29b13254db813805e3105c62da0d..97940cdf4eb55e761ec9bc05a98ea8c9d27024a1 100644 (file)
 #define QM_CHANLEVCHANGED          182
 #define QM_CHANLEVREMOVED          183
 #define QM_CHANLEVNOCHANGE         184
+#define QM_USERSHEADER             185
+#define QM_EMPTYCHAN               186
+#define QM_USERSSUMMARY            187
 
 /* List of privileged operations */
 
 #define   QCUFLAG_SELFCON   (QCUFLAG_OP | QCUFLAG_VOICE | QCUFLAG_AUTOOP | QCUFLAG_AUTOVOICE | \
                              QCUFLAG_TOPIC | QCUFLAG_INFO)
 
+#define   QCUFLAGS_PUBLIC   (QCUFLAG_OWNER | QCUFLAG_MASTER | QCUFLAG_OP | QCUFLAG_VOICE | \
+                             QCUFLAG_KNOWN | QCUFLAG_AUTOOP | QCUFLAG_AUTOVOICE | QCUFLAG_TOPIC | \
+                             QCUFLAG_PROTECT)
+                                                         
 #define   QCUFLAGS_PUNISH   (QCUFLAG_BANNED | QCUFLAG_QUIET | QCUFLAG_DENY)
 #define   QCUFLAGS_PERSONAL (QCUFLAG_HIDEWELCOME | QCUFLAG_AUTOINVITE)
 
index 966f760d6a370631a7056ebb467cda0fccf5d159..a4a05056a729f9d3c9199e02592a9208694d212a 100644 (file)
@@ -192,7 +192,10 @@ char *defaultmessages[MAXMESSAGES] = {
   /* 181*/ "The channel has been deleted since the last known user was removed.",
   /* 182*/ "Done.  Flags for %s on %s are now: %s.",
   /* 183*/ "Done.  User %s is no longer known on %s.",
-  /* 184*/ "No change - check that you didn't specify an impossible flag combination."
+  /* 184*/ "No change - check that you didn't specify an impossible flag combination.",
+  /* 185*/ "Users currently on %s:\nNick            Username        Flags        Host",
+  /* 186*/ "Channel %s is currently empty.",
+  /* 187*/ "Total %d users: %d opped, %d voiced, %d others, %d with flags (%d ops, %d masters)"
 };
 
 void initmessages() {