opinions about updated m_nochan.c

These are old archives. They are kept for historic purposes only.
Post Reply
nexus
Posts: 14
Joined: Fri Mar 12, 2004 5:45 pm
Contact:

opinions about updated m_nochan.c

Post by nexus »

Hiya guys ;)

I saw that Special had coded the original m_nochan.c, which has always been a great module, but there were some features that I really thought would enhance the module, so I've made a few of my own additions to it (my changes are all outlined in the code comments at the top). I have also tried to contact Special about this but he hasn't responded yet.

My additions seems to work fine so far, but note that this is my first attempt at any module coding, so if any of you veteran module coders see any potential bugs, please let me know ;)

thanks,

nexus (HiT)

Code: Select all

/*
 *   m_nochan - /NOCHAN command to list 0-chan users
 *   Original module was made by Special ([email protected])
 *   Recent additions done by HiT ([email protected])
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 1, or (at your option)
 *   any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "config.h"
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.h"
#include "proto.h"
#include "channel.h"
#include <time.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <io.h>
#endif
#include <fcntl.h>
#include "h.h"
#ifdef STRIPBADWORDS
#include "badwords.h"
#endif
#ifdef _WIN32
#include "version.h"
#endif

/* Changes of 1.1.1h (done by HiT):
 *   (many thanks to Special for his original
 *      module on which this is heavily based,
 *      and to AngryWolf for some join code
 *      I borrowed from his courtroom module)
 *   Added hiding of services pseudonicks (always on)
 *   Added -b switch to filter out +B bots
 *   Added HelpOp filtering to -o switch
 *     (so now -o filters both IRCops and HelpOps)
 *   Added -s/z switch to filter out SSL clients
 *   Added -p switch to use some preset switches
 *     (preset switches: -aorsi)
 *   Added -i switch to filter out working identds
 *   Now uses numerics 343 and 344 instead of WHO
 *     numerics. This way, mIRC won't filter out server
 *     names in the output (it does this by default for
 *     WHO replies), but the output still closely
 *     resembles WHO output.
 *   Added z and h flags to output (z for SSL clients,
 *     h for HelpOps)
 *   Added -J and -j switches to force matching users
 *     into a channel (defined below). -J forces them without
 *     giving a reason why, and -j gives a reason via notice
 *     (notice text is defined below)
 *     NOTE: You (the module user) are exempt from these joins
 *   Only services admins and higher can use this module now
 *   Added counters to show the number of results returned
 */

/* Changes of 1.1.0 (done by Special):
 *   Added -r switch to filter out registered users.
 *   Added -o switch to filter out opers
 */

void make_status(aClient *sptr, aClient *acptr, char *status);
void nochan_force_join(aClient *acptr, char *channel, char *reason);
DLLFUNC int m_nochan(aClient *cptr, aClient *sptr, int parc, char *parv[]);
void showncHelp(aClient *sptr);

#define MSG_NOCHAN 			"NOCHAN"
#define TOK_NOCHAN			NULL
#define NC_IDLECHAN 		"#idlers"
#define NC_JOINREASON 		"all users who were in 0 channels have been joined here automatically"
#define RPL_NOCHAN			343
#define RPL_ENDOFNOCHAN		344
#define RPL_NOCHANHELP		334
#define IsABot(x) 			((x)->umodes & UMODE_BOT)
#define IsServExempt(x) 	(IsServer(x) || IsServices(x) || IsMe(x))

static Command		*CmdNochan;

ModuleHeader MOD_HEADER(m_nochan)
  = {
	"nochan",
	"v1.1.1h",
	"/NOCHAN command to list 0-chan users",
	"3.2.3",
	NULL
    };

DLLFUNC int MOD_INIT(m_nochan)(ModuleInfo *modinfo)
{
	if (CommandExists(MSG_NOCHAN))
	{
		config_error("Command " MSG_NOCHAN " already exists");
		return MOD_FAILED;
	}
	CmdNochan = CommandAdd(modinfo->handle, MSG_NOCHAN, TOK_NOCHAN, m_nochan, MAXPARA, 0);
	if (ModuleGetError(modinfo->handle) != MODERR_NOERROR)
	{
		config_error("Error adding command " MSG_NOCHAN ": %s",
			ModuleGetErrorStr(modinfo->handle));
		return MOD_FAILED;
	}
	return MOD_SUCCESS;
}

DLLFUNC int MOD_LOAD(m_nochan)(int module_load)
{
	return MOD_SUCCESS;
}

DLLFUNC int MOD_UNLOAD(m_nochan)(int module_unload)
{
	CommandDel(CmdNochan);
	return MOD_SUCCESS;
}

void showncHelp(aClient *sptr)
{
	sendto_one(sptr, ":%s %d %s :---------------------------------", me.name, RPL_NOCHANHELP, sptr->name);
	sendto_one(sptr, ":%s %d %s :Syntax: /NOCHAN [-a/o/r/b/s/i/p/j/J]", me.name, RPL_NOCHANHELP, sptr->name);
	sendto_one(sptr, ":%s %d %s :Switches:", me.name, RPL_NOCHANHELP, sptr->name);
	sendto_one(sptr, ":%s %d %s :  -a   Hide users who are away", me.name, RPL_NOCHANHELP, sptr->name);
	sendto_one(sptr, ":%s %d %s :  -o   Hide IRCops and HelpOps", me.name, RPL_NOCHANHELP, sptr->name);
	sendto_one(sptr, ":%s %d %s :  -r   Hide registered users", me.name, RPL_NOCHANHELP, sptr->name);
	sendto_one(sptr, ":%s %d %s :  -b   Hide +B bots", me.name, RPL_NOCHANHELP, sptr->name);
	sendto_one(sptr, ":%s %d %s :  -s/z Hide SSL clients", me.name, RPL_NOCHANHELP, sptr->name);
	sendto_one(sptr, ":%s %d %s :  -i   Hide clients with working Identd", me.name, RPL_NOCHANHELP, sptr->name);
	sendto_one(sptr, ":%s %d %s :  -p   Use preset switches (-aorsi)", me.name, RPL_NOCHANHELP, sptr->name);
	sendto_one(sptr, ":%s %d %s :  -j   Force matching users into %s (with a default reason)", me.name,
		RPL_NOCHANHELP, sptr->name, NC_IDLECHAN);
	sendto_one(sptr, ":%s %d %s :  -J   Force matching users into %s (without a reason)", me.name,
		RPL_NOCHANHELP, sptr->name, NC_IDLECHAN);
	sendto_one(sptr, ":%s %d %s :Examples: /nochan -aor, /nochan -p", me.name, RPL_NOCHANHELP, sptr->name);
	sendto_one(sptr, ":%s %d %s :---------------------------------", me.name, RPL_NOCHANHELP, sptr->name);
}

DLLFUNC int m_nochan(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	/* Simple: Loop through each user, check the number of channels they
	 * are on (acptr->user->joined), send a who reply (with borrowed code from
	 * m_who), and go on). */
	aClient *acptr;
	int hideReg = 0, hideOper = 0, hideAway = 0, hideBot = 0, hideSecure = 0, hideIdentd = 0;
	int ncTotal = 0, ncAllTotal = 0, MakeJoin = 0, ncJoinTotal = 0, ncJoinReason = 0, hc = 0, i, j;
	if (!IsSAdmin(sptr))
	{
		sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, sptr->name);
		return 0;
	}
	if (parc > 1)
	{
		/* This could be coded a lot more cleanly, but I want it to
		 * allow /nochan -r -o -a AND /nochan -roa (and even /nochan -ro -a).
		 */
		for (i = 0; i < parc; i++)
		{
			if (parv[i][0] == '-')
			{
				for (j = 1; j < strlen(parv[i]); j++)
				{
					if (parv[i][j] == 'p')
					{
						hc++;
						hideAway = 1;
						hideOper = 1;
						hideReg = 1;
						hideSecure = 1;
						hideIdentd = 1;
					}
					else if (parv[i][j] == 'r')
					{
						hc++;
						hideReg = 1;
					}
					else if (parv[i][j] == 'o')
					{
						hc++;
						hideOper = 1;
					}
					else if (parv[i][j] == 'a')
					{
						hc++;
						hideAway = 1;
					}
					else if (parv[i][j] == 'b')
					{
						hc++;
						hideBot = 1;
					}
					else if (parv[i][j] == 's' || parv[i][j] == 'z')
					{
						hc++;
						hideSecure = 1;
					}
					else if (parv[i][j] == 'i')
					{
						hc++;
						hideIdentd = 1;
					}

					else if (parv[i][j] == 'J')
					{
						MakeJoin = 1;
						ncJoinReason = 0;
					}
					else if (parv[i][j] == 'j')
					{
						MakeJoin = 1;
						ncJoinReason = 1;
					}
					else
					{
						/* We show them the help if they specify invalid switch(es) */
						sendto_one(sptr, ":%s %d %s :[NOCHAN]: unknown switch(es) given, showing help",
							me.name, RPL_NOCHANHELP, sptr->name);
						showncHelp(sptr);
						return 0;
					}
				}
			}
		}
	}

	for (acptr = client; acptr; acptr = acptr->next)
	{
		char stat[20];

		if (IsServExempt(acptr) || acptr->user->joined > 0)
		{
			continue;
		}
		ncAllTotal++;
		if (hideReg && IsARegNick(acptr))
		{
			continue;
		}
		if (hideOper && (IsAnOper(acptr) || IsHelpOp(acptr)))
		{
			continue;
		}
		if (hideAway && acptr->user->away)
		{
			continue;
		}
		if (hideBot && IsABot(acptr))
		{
			continue;
		}
		if (hideSecure && IsSecureConnect(acptr))
		{
			continue;
		}
		if (hideIdentd && acptr->user->username[0] != '~')
		{
			continue;
		}


		/* Make the reply..
		 * 343 = NOCHAN reply
		 * 344 = End of NOCHAN, with counter(s)
		 * Reply format is very similar to WHO,
		   except for some extra flags (zh) - HiT
		 */
		make_status(sptr, acptr, stat);
		sendto_one(sptr, ":%s %d %s :%s %s %s %s@%s :%d %s %s",
			me.name, RPL_NOCHAN, sptr->name,
			"*", /* The channel.. */
			acptr->name, /* Nickname */
			stat, /* Status */
			acptr->user->username, /* The username (ident) */
			acptr->user->realhost, /* The hostname */
			acptr->hopcount, /* Hops to this server */
			acptr->info ? acptr->info : "", /* Real name (Gecos) */
			acptr->user->server /* Server name */
			);
		if (MakeJoin > 0 && (acptr->name != sptr->name))
		{
		    ncJoinTotal++;
		    if (ncJoinReason > 0)
				nochan_force_join(acptr, NC_IDLECHAN, NC_JOINREASON);
			else
				nochan_force_join(acptr, NC_IDLECHAN, NULL);
		}
		ncTotal++;
	}
	if (hc > 0)
	{
		sendto_one(sptr, ":%s %d %s :%s End of /NOCHAN list: %d matches, %d total",
			me.name, RPL_ENDOFNOCHAN, sptr->name, sptr->name, ncTotal, ncAllTotal);
	}
	else
	{
		sendto_one(sptr, ":%s %d %s :%s End of /NOCHAN list: %d total",
			me.name, RPL_ENDOFNOCHAN, sptr->name, sptr->name, ncAllTotal);
	}
	if (ncJoinTotal > 0)
	{
		if (ncJoinReason > 0)
			sendto_one(sptr, ":%s %d %s :[NOCHAN]: %d users were forced into %s (with a default reason)",
				me.name, RPL_NOCHANHELP, sptr->name, ncJoinTotal, NC_IDLECHAN);
		else
			sendto_one(sptr, ":%s %d %s :[NOCHAN]: %d users were forced into %s (without a reason)",
				me.name, RPL_NOCHANHELP, sptr->name, ncJoinTotal, NC_IDLECHAN);
	}
	else if (MakeJoin > 0)
	{
		sendto_one(sptr, ":%s %d %s :[NOCHAN]: There were no eligible users to force into %s",
			me.name, RPL_NOCHANHELP, sptr->name, NC_IDLECHAN);
	}
	return 0;
}

void make_status(aClient *sptr, aClient *acptr, char *status)
{
	int i = 0;
	if (acptr->user->away)
	{
		status[i++] = 'G';
	}
	else
	{
		status[i++] = 'H';
	}
	if (IsARegNick(acptr))
	{
		status[i++] = 'r';
	}
	if (IsABot(acptr))
	{
		status[i++] = 'B';
	}
	if (IsSecureConnect(acptr))
	{
		status[i++] = 'z';
	}
	if (IsHelpOp(acptr))
	{
		status[i++] = 'h';
	}
	if (IsAnOper(acptr))
	{
		status[i++] = '*';
	}
	status[i] = '\0';
}

/* this code is borrowed from AngryWolf's courtroom module - HiT */
void nochan_force_join(aClient *acptr, char *channel, char *reason)
{
	int		flags;
	aChannel	*chptr;

	flags = (ChannelExists(channel)) ? CHFL_DEOPPED : CHFL_CHANOP;
	chptr = get_channel(acptr, channel, CREATE);

	if (chptr && find_membership_link(acptr->user->channel, chptr))
		return;

	if (reason)
		sendnotice(acptr, "*** You were forced to join %s (%s)",
			chptr->chname, reason);

	join_channel(chptr, acptr, acptr, flags);
}
Psadi
Posts: 42
Joined: Sat Mar 20, 2004 7:50 pm

Post by Psadi »

I like the old one also. I like what you have added to this one so far I havent found any errors. The only thing I have is that the old version posted all the nochan users tightly together. You have a line with - between each user. It doesnt do that much if there are a few users but when there are as I had just 8 it fills upp most of the screen. So if you could do it like the old way when its posted I would be very happy.

this is old
this is old

this is new
-
this is new
-


I hope the simple example gives you an understanding to what I mean :)
Stealth
Head of Support
Posts: 2085
Joined: Tue Jun 15, 2004 8:50 pm
Location: Chino Hills, CA, US
Contact:

Post by Stealth »

The reason for the - between lines is not the modules fault. Your client (I'm guessing mIRC) adds the - between lines for unknown replies. The reason you did not get that with the old nochan module, is because Special used the standard WHO replies. nexus used 2 unknown numberics, 343 and 344, which your client does not know.

My opinions about the module: It looks good, I have not tested it myself. My only suggestion about it is instead of having RPL_NOCHAN and RPL_NOCHANHELP use the same numeric (344), have RPL_NOCHANHELP use the HELPOP reply numeric (I'm too lazy to look it up).
nexus
Posts: 14
Joined: Fri Mar 12, 2004 5:45 pm
Contact:

Post by nexus »

Yeah Stealth is right about those - line separators. They are done by the client not the module. For mIRC you can disable those by going to alt o --> other, and remove the dash shown there as the line separator.

And about the numerics, RPL_NOCHAN and RPL_NOCHANHELP are already different (RPL_NOCHAN is 343 and RPL_NOCHANHELP is 334); they only look the same at first glance ;)
Psadi
Posts: 42
Joined: Sat Mar 20, 2004 7:50 pm

Post by Psadi »

ahhh

didnt know that about line separator in mirc :) Thanks for the info and its removed now
Post Reply