/*
* =================================================================
* Filename: m_elmer.c
* =================================================================
* Description: Command /elmer: makes someone talk like Elmer J.
* Fudd, that is, letters 'l' and 'r' become 'w', for
* example, "Shhhhhh! Be vewy, vewy quiet... I'm
* hunting wabbits, heh-heh-heh." (More info at
* http://www.geocities.com/Hollywood/Park/2326/
* character1.html#elmer.) Install this module
* on all servers in order to make it work properly.
* =================================================================
* Author: AngryWolf
* Email: angrywolf@flashmail.com
* =================================================================
* Feedback:
*
* I accept bugreports, ideas and opinions, and if you have any
* questions, just send an email to me!
*
* Thank you for using my module!
*
* =================================================================
* Requirements:
* =================================================================
*
* o Unreal >=3.2-beta18
* o One of the supported operating systems (see unreal32docs.html)
*
* =================================================================
* Installation:
* =================================================================
*
* See http://angrywolf.linktipp.org/compiling.php?lang=en
*
* =================================================================
* Usage:
* =================================================================
*
* Command ELMER:
* --------------
*
* Syntax: /elmer [+|-]<nickname>
*
* Examples:
*
* - To make someone talk like Elmer:
* /elmer SomeNick
* - To remove the previous setting from someone:
* /elmer -SomeNick
*
* =================================================================
* Mirror files:
* =================================================================
*
* http://angrywolf.linktipp.org/m_elmer.c [Germany]
* http://angrywolf.uw.hu/m_elmer.c [Hungary]
* http://angrywolf.fw.hu/m_elmer.c [Hungary]
*
* =================================================================
* Changes:
* =================================================================
*
* $Log: m_elmer.c,v $
* Revision 1.6 2004/03/12 11:59:30 angrywolf
* - Made some minor fixes.
*
* Revision 1.5 2004/03/08 21:25:12 angrywolf
* - Fixed some bugs that could cause crash if you compile the module
* statically (for example, under Windows).
*
* Revision 1.4 2004/02/23 17:37:34 angrywolf
* - Unoccupied flags are not trustable, CVS .2138 took use
* of the one I used before to mark users as Elmers.
* Therefore I use a separate list now, even if it's
* more memory intensive.
*
* Revision 1.3 2004/02/17 10:42:24 angrywolf
* *** empty log message ***
*
* Revision 1.2 2004/02/17 10:35:50 angrywolf
* - Fixed a letter case problem, reported by MichaelJE2.
*
* Revision 1.1 2004/01/29 13:59:28 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_realops(char *pattern, ...);
#define MSG_ELMER "ELMER"
#define TOK_ELMER "EL"
#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
static Command *AddCommand(Module *module, char *msg, char *token, iFP func);
static int m_elmer(aClient *, aClient *, int, char *[]);
static char *cb_privmsg(aClient *, aClient *, aClient *, char *, int);
static char *cb_chanmsg(aClient *, aClient *, aChannel *, char *, int);
static int cb_quit(aClient *, char *);
static void free_elmerflags();
static Command *CmdElmer;
static Hook *HookPrivMsg = NULL, *HookChanMsg = NULL, *HookQuit = NULL;
/*
* Unoccupied flags are not trustable, they may become used anytime.
* Therefore I use a separate list.
*/
typedef struct _elmerflag ElmerFlag;
struct _elmerflag
{
ElmerFlag *prev, *next;
aClient *cptr;
};
static ElmerFlag *ElmerFlags;
ModuleHeader MOD_HEADER(m_elmer)
= {
"m_elmer",
"$Id: m_elmer.c,v 1.6 2004/03/12 11:59:30 angrywolf Exp $",
"Command /elmer",
"3.2-b8-1",
NULL
};
DLLFUNC int MOD_INIT(m_elmer)(ModuleInfo *modinfo)
{
ElmerFlags = NULL;
if (!(CmdElmer = AddCommand(modinfo->handle, MSG_ELMER, TOK_ELMER, m_elmer)))
return MOD_FAILED;
HookPrivMsg = HookAddPCharEx(modinfo->handle, HOOKTYPE_USERMSG, cb_privmsg);
HookChanMsg = HookAddPCharEx(modinfo->handle, HOOKTYPE_CHANMSG, cb_chanmsg);
HookQuit = HookAddEx(modinfo->handle, HOOKTYPE_LOCAL_QUIT, cb_quit);
return MOD_SUCCESS;
}
DLLFUNC int MOD_LOAD(m_elmer)(int module_load)
{
return MOD_SUCCESS;
}
DLLFUNC int MOD_UNLOAD(m_elmer)(int module_unload)
{
free_elmerflags();
DelHook(HookQuit);
DelHook(HookChanMsg);
DelHook(HookPrivMsg);
DelCommand(CmdElmer);
return MOD_SUCCESS;
}
static Command *AddCommand(Module *module, char *msg, char *token, iFP func)
{
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, MAXPARA, 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;
}
static ElmerFlag *find_elmer(aClient *cptr)
{
ElmerFlag *e;
for (e = ElmerFlags; e; e = e->next)
if (e->cptr == cptr)
break;
return e;
}
static void set_elmer(aClient *cptr)
{
ElmerFlag *e;
e = (ElmerFlag *) MyMalloc(sizeof(cptr));
e->cptr = cptr;
AddListItem(e, ElmerFlags);
}
static void clear_elmer(ElmerFlag *e)
{
DelListItem(e, ElmerFlags);
MyFree(e);
}
static void free_elmerflags()
{
ElmerFlag *e;
ListStruct *next;
for (e = ElmerFlags; e; e = (ElmerFlag *) next)
{
next = (ListStruct *) e->next;
DelListItem(e, ElmerFlags);
MyFree(e);
}
}
static char *convert_to_elmer(char *str)
{
char *p;
for (p = str; *p; p++)
switch(*p)
{
case 'l':
case 'r':
*p = 'w';
break;
case 'L':
case 'R':
*p = 'W';
}
return str;
}
static int cb_quit(aClient *sptr, char *comment)
{
ElmerFlag *e;
if ((e = find_elmer(sptr)))
clear_elmer(e);
return 0;
}
static char *cb_privmsg(aClient *cptr, aClient *from, aClient *to, char *str, int notice)
{
return find_elmer(cptr) ? convert_to_elmer(str) : str;
}
static char *cb_chanmsg(aClient *cptr, aClient *from, aChannel *to, char *str, int notice)
{
return find_elmer(cptr) ? convert_to_elmer(str) : str;
}
static int m_elmer(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
aClient *acptr = NULL;
ElmerFlag *is_elmer = NULL;
char *nick = NULL;
int add = 1;
if (IsPerson(sptr) && !IsAnOper(sptr))
{
sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,
parv[0]);
return -1;
}
nick = IsParam(1) ? parv[1] : NULL;
if (nick)
{
if (*nick == '+')
nick++;
else if (*nick == '-')
{
nick++;
add = 0;
}
if (!*nick)
nick = NULL;
}
if (!nick)
{
if (!IsServer(sptr))
sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
me.name, sptr->name, MSG_ELMER);
return -1;
}
acptr = find_person(nick, NULL);
if (!acptr)
{
if (!IsServer(sptr))
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",
sptr->name, IsToken(cptr) ? TOK_ELMER : MSG_ELMER,
add ? '+' : '-', acptr->name);
return 0;
}
is_elmer = find_elmer(acptr);
if (add)
{
if (is_elmer)
{
if (!IsServer(sptr))
sendto_one(sptr,
":%s %s %s :*** %s is already set to talk like Elmer",
me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE",
sptr->name, acptr->name);
return 0;
}
set_elmer(acptr);
sendto_realops("*** %s made %s!%s@%s talk like Elmer",
sptr->name, acptr->name, acptr->user->username,
GetHost(acptr));
sendto_serv_butone(&me,
":%s SMO o :*** %s made %s!%s@%s talk like Elmer",
me.name, sptr->name, acptr->name, acptr->user->username,
GetHost(acptr));
if (MyConnect(sptr) && acptr != sptr)
sendto_one(sptr,
":%s %s %s :*** %s is now talking like Elmer",
me.name, IsWebTV(acptr) ? "PRIVMSG" : "NOTICE",
sptr->name, acptr->name);
}
else
{
if (!is_elmer)
{
if (!IsServer(sptr))
sendto_one(sptr,
":%s %s %s :*** %s is not talking like Elmer",
me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE",
sptr->name, acptr->name);
return 0;
}
clear_elmer(is_elmer);
sendto_realops("*** %s made %s!%s@%s no longer talk like Elmer",
sptr->name, acptr->name,
acptr->user->username, GetHost(acptr));
sendto_serv_butone(&me,
":%s SMO o :*** %s made %s!%s@%s no longer talk like Elmer",
me.name, sptr->name, acptr->name,
acptr->user->username, GetHost(acptr));
if (MyConnect(sptr) && acptr != sptr)
sendto_one(sptr,
":%s %s %s :*** %s is no longer talking like Elmer",
me.name, IsWebTV(acptr) ? "PRIVMSG" : "NOTICE",
sptr->name, acptr->name);
}
return 0;
}