2014-03-08 19:56:21 -05:00
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
EnergyMech, IRC bot software
|
|
|
|
|
Parts Copyright (c) 1997-2009 proton
|
|
|
|
|
|
|
|
|
|
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 2 of the License, 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.
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
#define SHITLIST_C
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
|
|
#include "defines.h"
|
|
|
|
|
#include "structs.h"
|
|
|
|
|
#include "global.h"
|
|
|
|
|
#include "h.h"
|
|
|
|
|
#include "text.h"
|
|
|
|
|
#include "mcmd.h"
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* shitlist enforcing
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void shit_action(Chan *chan, ChanUser *cu)
|
|
|
|
|
{
|
|
|
|
|
Shit *shit;
|
2018-04-04 08:56:14 +02:00
|
|
|
const char *nick;
|
|
|
|
|
char *fromnick;
|
2014-03-08 19:56:21 -05:00
|
|
|
char *userhost;
|
|
|
|
|
|
|
|
|
|
if (!chan->setting[TOG_SHIT].int_var || !chan->bot_is_op || cu->user)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
userhost = get_nuh(cu);
|
|
|
|
|
if ((cu->shit = find_shit(userhost,chan->name)) == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
shit = cu->shit;
|
|
|
|
|
|
|
|
|
|
if (shit->action == SHIT_KB || shit->action == SHIT_PERMABAN)
|
|
|
|
|
{
|
|
|
|
|
nick = cu->nick;
|
|
|
|
|
|
|
|
|
|
send_mode(chan,85,QM_CHANUSER,'-','o',cu);
|
|
|
|
|
send_mode(chan,90,QM_RAWMODE,'+','b',shit->mask);
|
|
|
|
|
|
|
|
|
|
fromnick = nickcpy(NULL,shit->from);
|
2025-11-20 14:55:08 +01:00
|
|
|
send_kick(chan,nick,"%s %s: %s",maketimestr(shit->time,TFMT_DATE),fromnick,
|
2014-03-08 19:56:21 -05:00
|
|
|
(shit->reason) ? shit->reason : "GET THE HELL OUT!!!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
/*
|
|
|
|
|
* shitlevel 1: not allowed to be chanop
|
|
|
|
|
*/
|
|
|
|
|
if (shit->action == SHIT_CHANOP)
|
|
|
|
|
{
|
|
|
|
|
send_mode(chan,160,QM_CHANUSER,'-','o',(void*)cu);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void check_shit(void)
|
|
|
|
|
{
|
|
|
|
|
ChanUser *cu;
|
|
|
|
|
Chan *chan;
|
|
|
|
|
|
|
|
|
|
for(chan=current->chanlist;chan;chan=chan->next)
|
|
|
|
|
{
|
|
|
|
|
for(cu=chan->users;cu;cu=cu->next)
|
|
|
|
|
{
|
|
|
|
|
shit_action(chan,cu);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* shitlist management. adding, deleting, clearing, searching, ...
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void remove_shit(Shit *shit)
|
|
|
|
|
{
|
|
|
|
|
Chan *chan;
|
|
|
|
|
ChanUser *cu;
|
|
|
|
|
Shit **pp;
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2018-04-04 06:04:58 +02:00
|
|
|
debug("(remove_shit) removing shit %s on channel %s (Level %i)\n",shit->mask,shit->chan,shit->action);
|
2014-03-08 19:56:21 -05:00
|
|
|
#endif /* DEBUG */
|
|
|
|
|
pp = ¤t->shitlist;
|
|
|
|
|
while(*pp)
|
|
|
|
|
{
|
|
|
|
|
if (*pp == shit)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* remove links to this shit record from the chanuserlist
|
|
|
|
|
*/
|
|
|
|
|
for(chan=current->chanlist;chan;chan=chan->next)
|
|
|
|
|
{
|
|
|
|
|
for(cu=chan->users;cu;cu=cu->next)
|
|
|
|
|
{
|
|
|
|
|
if (cu->shit == shit)
|
|
|
|
|
cu->shit = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*pp = shit->next;
|
|
|
|
|
Free((char**)&shit);
|
|
|
|
|
current->ul_save++;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
pp = &(*pp)->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void purge_shitlist(void)
|
|
|
|
|
{
|
|
|
|
|
while(current->shitlist)
|
|
|
|
|
remove_shit(current->shitlist);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Shit *add_shit(char *from, char *chan, char *mask, char *reason, int axs, int expire)
|
|
|
|
|
{
|
|
|
|
|
Shit *shit;
|
|
|
|
|
|
|
|
|
|
set_mallocdoer(add_shit);
|
2018-03-26 00:43:24 +02:00
|
|
|
shit = (Shit*)Calloc(sizeof(Shit) + StrlenX(from,chan,mask,reason,NULL));
|
2014-03-08 19:56:21 -05:00
|
|
|
|
|
|
|
|
shit->action = axs;
|
|
|
|
|
shit->time = now;
|
|
|
|
|
shit->expire = expire;
|
|
|
|
|
|
|
|
|
|
shit->next = current->shitlist;
|
|
|
|
|
current->shitlist = shit;
|
|
|
|
|
|
2018-04-04 06:04:58 +02:00
|
|
|
shit->chan = stringcpy(shit->mask,mask) + 1;
|
|
|
|
|
shit->from = stringcpy(shit->chan,chan) + 1;
|
|
|
|
|
shit->reason = stringcpy(shit->from,from) + 1;
|
|
|
|
|
stringcpy(shit->reason,reason);
|
2014-03-08 19:56:21 -05:00
|
|
|
|
|
|
|
|
current->ul_save++;
|
|
|
|
|
return(shit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Shit *find_shit(const char *userhost, const char *channel)
|
|
|
|
|
{
|
|
|
|
|
Shit *shit,*save;
|
|
|
|
|
int num,best;
|
|
|
|
|
|
|
|
|
|
if (!userhost)
|
|
|
|
|
return(NULL);
|
|
|
|
|
save = NULL;
|
|
|
|
|
best = 0;
|
|
|
|
|
for(shit=current->shitlist;shit;shit=shit->next)
|
|
|
|
|
{
|
2018-04-04 06:04:58 +02:00
|
|
|
if (!channel || !stringcasecmp(channel,shit->chan) ||
|
2014-03-08 19:56:21 -05:00
|
|
|
(*shit->chan == '*') || (*channel == '*'))
|
|
|
|
|
{
|
|
|
|
|
num = num_matches(shit->mask,userhost);
|
|
|
|
|
if (num > best)
|
|
|
|
|
{
|
|
|
|
|
best = num;
|
|
|
|
|
save = shit;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (save && save->expire < now)
|
|
|
|
|
{
|
|
|
|
|
remove_shit(save);
|
|
|
|
|
save = NULL;
|
|
|
|
|
}
|
|
|
|
|
return(save);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Shit *get_shituser(char *userhost, char *channel)
|
|
|
|
|
{
|
|
|
|
|
ChanUser *cu;
|
|
|
|
|
Chan *chan;
|
|
|
|
|
Shit *shit;
|
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
debug("(get_shituser) userhost = '%s', channel = '%s'\n",
|
|
|
|
|
nullstr(userhost),nullstr(channel));
|
|
|
|
|
#endif /* DEBUG */
|
|
|
|
|
/*
|
|
|
|
|
* save us a few million function calls if the shitlist is empty
|
|
|
|
|
*/
|
|
|
|
|
if (!current->shitlist)
|
|
|
|
|
return(NULL);
|
2025-10-27 15:13:49 +01:00
|
|
|
if (!nickcmp(getbotnick(current),userhost))
|
2014-03-08 19:56:21 -05:00
|
|
|
return(NULL);
|
|
|
|
|
for(chan=current->chanlist;chan;chan=chan->next)
|
|
|
|
|
{
|
|
|
|
|
for(cu=chan->users;cu;cu=cu->next)
|
|
|
|
|
{
|
|
|
|
|
p = get_nuh(cu);
|
|
|
|
|
if (matches(userhost,p))
|
|
|
|
|
continue;
|
|
|
|
|
if ((shit = find_shit(p,channel)) != NULL)
|
|
|
|
|
return(shit);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int get_shitaction(const char *userhost, const char *chan)
|
|
|
|
|
{
|
|
|
|
|
Shit *shit;
|
|
|
|
|
|
|
|
|
|
if ((shit = find_shit(userhost,chan)))
|
|
|
|
|
return(shit->action);
|
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* commands related to shitlist
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* SHIT <channel|*> <nick|mask> <action> [expire] <reason>
|
|
|
|
|
*/
|
|
|
|
|
void do_shit(COMMAND_ARGS)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* on_msg checks CARGS
|
|
|
|
|
*/
|
|
|
|
|
char *channel,*nick,*nuh;
|
2018-04-04 06:04:58 +02:00
|
|
|
int shitlevel,days,uaccess,shitaccess;
|
2014-03-08 19:56:21 -05:00
|
|
|
|
|
|
|
|
if (CurrentCmd->name == C_QSHIT)
|
|
|
|
|
{
|
|
|
|
|
channel = MATCH_ALL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
channel = chop(&rest);
|
|
|
|
|
if (!ischannel(channel) && *channel != '*')
|
|
|
|
|
{
|
|
|
|
|
usage:
|
|
|
|
|
usage(from); /* usage for CurrentCmd->name */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((uaccess = get_useraccess(from,channel)) < cmdaccess)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if ((nick = chop(&rest)) == NULL)
|
|
|
|
|
goto usage;
|
|
|
|
|
|
|
|
|
|
if (CurrentCmd->name == C_QSHIT)
|
|
|
|
|
{
|
|
|
|
|
shitlevel = DEFAULTSHITLEVEL;
|
|
|
|
|
days = 86400 * DEFAULTSHITLENGTH;
|
|
|
|
|
if (*rest == 0)
|
|
|
|
|
rest = TEXT_DEFAULTSHIT;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-04-04 06:04:58 +02:00
|
|
|
shitlevel = asc2int(chop(&rest));
|
2014-03-08 19:56:21 -05:00
|
|
|
if (errno)
|
|
|
|
|
goto usage;
|
|
|
|
|
|
|
|
|
|
if (shitlevel < 1 || shitlevel > MAXSHITLEVEL)
|
|
|
|
|
{
|
|
|
|
|
to_user(from,"Valid levels are from 1 thru " MAXSHITLEVELSTRING);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* option: expire in XXX days
|
|
|
|
|
*/
|
|
|
|
|
days = 86400 * 30;
|
|
|
|
|
if (*rest >= '1' && *rest <= '9')
|
|
|
|
|
{
|
2018-04-04 06:04:58 +02:00
|
|
|
days = 86400 * asc2int(chop(&rest));
|
2014-03-08 19:56:21 -05:00
|
|
|
if (errno)
|
|
|
|
|
goto usage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*rest == 0)
|
|
|
|
|
goto usage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef CHANBAN
|
|
|
|
|
if (shitlevel == SHIT_CHANBAN)
|
|
|
|
|
{
|
|
|
|
|
nuh = nick;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif /* CHANBAN */
|
|
|
|
|
{
|
|
|
|
|
if ((nuh = nick2uh(from,nick)) == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (find_shit(nuh,channel))
|
|
|
|
|
{
|
|
|
|
|
to_user(from,TEXT_ALREADYSHITTED,nuh);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (uaccess != OWNERLEVEL)
|
|
|
|
|
{
|
|
|
|
|
shitaccess = get_useraccess(nuh,channel);
|
|
|
|
|
if (shitaccess > uaccess)
|
|
|
|
|
{
|
|
|
|
|
to_user(from,TEXT_SHITLOWACCESS,nuh);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
format_uh(nuh,FUH_USERHOST);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
debug("(do_shit) adding %s to %s (Level %i)\n",nuh,channel,shitlevel);
|
|
|
|
|
#endif /* DEBUG */
|
|
|
|
|
add_shit(from,channel,nuh,rest,shitlevel,now + days);
|
|
|
|
|
|
|
|
|
|
to_user(from,TEXT_HASSHITTED,nuh,channel);
|
2025-11-20 14:55:08 +01:00
|
|
|
to_user(from,TEXT_SHITEXPIRES,maketimestr(now + days,TFMT_FULL));
|
2014-03-08 19:56:21 -05:00
|
|
|
|
|
|
|
|
check_shit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void do_rshit(COMMAND_ARGS)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* on_msg checks: CARGS
|
|
|
|
|
*/
|
|
|
|
|
Shit *shit;
|
|
|
|
|
char *chan,*nick,*nuh;
|
|
|
|
|
int uaccess;
|
|
|
|
|
|
|
|
|
|
chan = chop(&rest);
|
|
|
|
|
if (!chan || !*chan || (!ischannel(chan) && *chan != '*'))
|
|
|
|
|
{
|
|
|
|
|
usage(from); /* usage for CurrentCmd->name */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((uaccess = get_useraccess(from,chan)) < cmdaccess)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if ((nick = chop(&rest)) == NULL)
|
|
|
|
|
{
|
|
|
|
|
to_user(from,"No nick or userhost specified");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if ((nuh = nick2uh(from,nick)) == NULL)
|
|
|
|
|
return;
|
|
|
|
|
if ((shit = find_shit(nuh,chan)) == NULL)
|
|
|
|
|
{
|
|
|
|
|
to_user(from,"%s is not in my shit list on that channel",nuh);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if ((get_useraccess(shit->from,chan)) > uaccess)
|
|
|
|
|
{
|
|
|
|
|
to_user(from,"The person who did this shitlist has a higher level than you");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
remove_shit(shit);
|
|
|
|
|
to_user(from,"User %s is no longer being shitted on %s",nuh,chan);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *shit_actions[MAXSHITLEVEL+1] = { "nothing (0)", "no op/voice (1)", "kickban (2)", "permaban (3)", "chanban (4)" };
|
|
|
|
|
|
|
|
|
|
void do_shitlist(COMMAND_ARGS)
|
|
|
|
|
{
|
|
|
|
|
Shit *shit;
|
|
|
|
|
|
|
|
|
|
table_buffer("\037channel\037\t\037mask\037\t\037action\037\t\037set by\037\t\037reason\037\t\037expires\037");
|
|
|
|
|
for(shit=current->shitlist;shit;shit=shit->next)
|
|
|
|
|
{
|
2018-04-04 08:56:14 +02:00
|
|
|
table_buffer(FMT_6XSTRTAB,shit->chan,shit->mask,shit_actions[shit->action],
|
2025-11-20 14:55:08 +01:00
|
|
|
nickcpy(NULL,shit->from),shit->reason,maketimestr(shit->expire,TFMT_AWAY));
|
2014-03-08 19:56:21 -05:00
|
|
|
}
|
|
|
|
|
table_send(from,2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void do_clearshit(COMMAND_ARGS)
|
|
|
|
|
{
|
|
|
|
|
purge_shitlist();
|
|
|
|
|
to_user(from,TEXT_CLEAREDSHITLIST);
|
|
|
|
|
}
|