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);
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");
}
chanservremovecommand("unbanmask", csc_dounbanmask);
chanservremovecommand("unbanme", csc_dounbanme);
chanservremovecommand("unsuspendchan", csc_dounsuspendchan);
+ chanservremovecommand("users", csc_dousers);
chanservremovecommand("voice", csc_dovoice);
chanservremovecommand("welcome", csc_dowelcome);
}
--- /dev/null
+/*
+ * 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;
+}