/*
 * =================================================================
 * Filename:       m_tempshun.c
 * =================================================================
 * Description:    Command /tempshun: makes someone temporarily
 *                 shunned (only adds a shun on the client's current
 *                 session). The module is required to be loaded on
 *                 all servers. Only those people can use this
 *                 command who already has privileges to do a /shun.
 *                 Notifications are sent to snomask +G.
 * =================================================================
 * Author:         AngryWolf
 * Email:          angrywolf@flashmail.com
 * =================================================================
 * Feedback:
 *
 * I accept bugreports, ideas and opinions, and if you have
 * questions, just send an email for me!
 *
 * Thank you for using my module!
 *
 * =================================================================
 * Requirements:
 * =================================================================
 *
 * o Unreal >=3.2-RC1
 * o One of the supported operating systems (see unreal32docs.html)
 *
 * =================================================================
 * Installation:
 * =================================================================
 *
 * See http://angrywolf.linktipp.org/compiling.php?lang=en
 *
 * =================================================================
 * Usage:
 * =================================================================
 *
 * Command TEMPSHUN:
 * ----------------
 *
 * Syntax:
 *
 *     /tempshun [+|-]<nickname> [<reason>]
 *
 * Examples:
 *
 * - To set a tempshun on Guset12345:
 *       /tempshun Guest12345 Because of flooding
 * - To remove a tempshun from SomeOne:
 *       /tempshun -SomeOne
 *
 * =================================================================
 * Mirror files:
 * =================================================================
 *
 * http://www.angrywolf.org/m_tempshun.c [Germany]
 * http://angrywolf.uw.hu/m_tempshun.c [Hungary]
 * http://angrywolf.fw.hu/m_tempshun.c [Hungary]
 * http://www.angrywolf.za.net/m_tempshun.c [South Africa]
 *
 * =================================================================
 * Changes:
 * =================================================================
 *
 * $Log: m_tempshun.c,v $
 * Revision 1.3  2004/03/08 21:26:18  angrywolf
 * - Fixed some bugs that could cause crash if you compile the module
 *   statically (for example, under Windows).
 *
 * Revision 1.2  2004/02/15 13:38:52  angrywolf
 * - Corrected some doc typos.
 *
 * Revision 1.1  2004/02/15 13:32:00  angrywolf
 * Initial revision
 *
 * =================================================================
 */

#include "config.h"
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.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

extern void		sendto_one(aClient *to, char *pattern, ...);
extern void		sendto_serv_butone_token(aClient *one, char *prefix, char *command, char *token, char *pattern, ...);

#define MSG_TEMPSHUN	"TEMPSHUN"
#define TOK_TEMPSHUN	"TE"
#define IsParam(x)      (parc > (x) && !BadPtr(parv[(x)]))
#define IsNotParam(x)   (parc <= (x) || BadPtr(parv[(x)]))
#define DelHook(x)	if (x) HookDel(x); x = NULL
#define DelCommand(x)	if (x) CommandDel(x); x = NULL
#define DelSnomask(x)	if (x) SnomaskDel(x); x = NULL

static Command		*AddCommand(Module *module, char *msg, char *token, iFP func, unsigned char params);
static int		m_tempshun(aClient *, aClient *, int, char *[]);

static Command		*CmdTempshun;

ModuleHeader MOD_HEADER(m_tempshun)
  = {
	"m_tempshun",
	"$Id: m_tempshun.c,v 1.3 2004/03/08 21:26:18 angrywolf Exp $",
	"Command /tempshun",
	"3.2-b8-1",
	NULL 
    };

DLLFUNC int MOD_INIT(m_tempshun)(ModuleInfo *modinfo)
{
	if (!(CmdTempshun = AddCommand(modinfo->handle, MSG_TEMPSHUN,
	    TOK_TEMPSHUN, m_tempshun, 2)))
		return MOD_FAILED;

	return MOD_SUCCESS;
}

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

DLLFUNC int MOD_UNLOAD(m_tempshun)(int module_unload)
{
	DelCommand(CmdTempshun);
	return MOD_SUCCESS;
}

static Command *AddCommand(Module *module, char *msg, char *token, iFP func, unsigned char params)
{
	Command *cmd;

	if (CommandExists(msg))
    	{
		config_error("Command %s already exists", msg);
		return NULL;
    	}
    	if (CommandExists(token))
	{
		config_error("Token %s already exists", token);
		return NULL;
    	}

	cmd = CommandAdd(module, msg, token, func, params, 0);

#ifndef STATIC_LINKING
	if (ModuleGetError(module) != MODERR_NOERROR || !cmd)
#else
	if (!cmd)
#endif
	{
#ifndef STATIC_LINKING
		config_error("Error adding command %s: %s", msg,
			ModuleGetErrorStr(module));
#else
		config_error("Error adding command %s", msg);
#endif
		return NULL;
	}

	return cmd;
}

int m_tempshun(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	static char	buf[1024];
	aClient		*acptr;
	char		*nick, *reason;
	int		add = 1;

	if (IsServer(sptr))
		return 0;

	if (MyClient(sptr) && (!OPCanTKL(sptr) || !IsOper(sptr)))
	{
    		sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,
            		parv[0]);
                return -1;
	}

	nick	= IsParam(1) ? parv[1] : NULL;
	reason	= IsParam(2) ? parv[2] : NULL;

	if (nick)
	{
		if (*nick == '+')
			nick++;
		else if (*nick == '-')
		{
			nick++;
			add = 0;
		}
		if (!*nick)
			nick = NULL;
	}

        if (!nick)
	{
	    	sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
			me.name, parv[0], MSG_TEMPSHUN);
		return -1;
	}

	acptr = find_person(nick, NULL);

	if (!acptr)
	{
	    	sendto_one(sptr, err_str(ERR_NOSUCHNICK),
			me.name, sptr->name, nick);
	        return 0;
	}

	if (!MyConnect(acptr))
	{
		sendto_one(acptr->from, ":%s %s %c%s%s%s",
			sptr->name, IsToken(acptr->from) ? TOK_TEMPSHUN : MSG_TEMPSHUN,
			add ? '+' : '-', acptr->name,
			(reason && add) ? " " : "", (reason && add) ? reason : "");
		return 0;
	}

	if (add)
	{
		if (IsAnOper(acptr))
		{
			sendto_one(sptr,
				":%s %s %s :*** IRC operators should not be shunned",
				me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE",
				sptr->name);
			return 0;
		}
		if (IsShunned(acptr))
		{
			sendto_one(sptr,
				":%s %s %s :*** %s is already shunned",
				me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE",
				sptr->name, acptr->name);
			return 0;
		}

		SetShunned(acptr);
		ircsprintf(buf, "Temporary shun added for %s (%s@%s) by %s [%s]",
			acptr->name, acptr->user->username,
			acptr->user->realhost, sptr->name, reason ? reason : "no reason");
		sendto_snomask(SNO_TKL, "%s", buf);
		sendto_serv_butone_token(NULL, me.name, MSG_SENDSNO, TOK_SENDSNO, "G :%s", buf);

		sendto_one(acptr,
			":%s %s %s :*** %s has set a temporary shun on you (%s)",
			me.name, IsWebTV(acptr) ? "PRIVMSG" : "NOTICE",
			acptr->name, sptr->name, reason ? reason : "no reason");
		if (acptr != sptr)
			sendto_one(sptr,
				":%s %s %s :*** %s is now temporarily shunned",
				me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE",
				sptr->name, acptr->name);
	}
	else
	{
		if (!IsShunned(acptr))
		{
			sendto_one(sptr,
				":%s %s %s :*** %s is not shunned",
				me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE",
				sptr->name, acptr->name);
			return 0;
		}

		ClearShunned(acptr);
		ircsprintf(buf, "%s removed temporary shun from %s (%s@%s)",
			sptr->name, acptr->name, acptr->user->username,
			acptr->user->realhost);
		sendto_snomask(SNO_TKL, "%s", buf);
		sendto_serv_butone_token(NULL, me.name, MSG_SENDSNO, TOK_SENDSNO, "G :%s", buf);

		sendto_one(acptr,
			":%s %s %s :*** You are no longer shunned",
			me.name, IsWebTV(acptr) ? "PRIVMSG" : "NOTICE",
			acptr->name);
		if (acptr != sptr)
			sendto_one(sptr,
				":%s %s %s :*** %s is no longer shunned",
				me.name, IsWebTV(acptr) ? "PRIVMSG" : "NOTICE",
				sptr->name, acptr->name);
	}

	return 0;
}

