2013-06-29 22:18:56 +00:00
import eliza
2013-07-06 21:21:27 +00:00
import threading
2013-09-03 12:50:54 +00:00
import random
2014-04-01 19:25:16 +00:00
import re
2015-02-22 14:29:46 +00:00
import time
2021-01-20 18:00:50 +00:00
import functools
2013-07-07 12:43:33 +00:00
2018-07-08 19:23:42 +00:00
blacklist = [ ]
2014-12-06 20:31:17 +00:00
2015-03-01 00:30:59 +00:00
doctor = eliza . eliza ( )
2015-03-27 15:22:40 +00:00
# channel: [user1, user2, ..., userN]
2015-03-03 15:46:19 +00:00
trusted = { }
2015-03-01 00:30:59 +00:00
trustedlock = threading . Lock ( )
2015-03-03 15:46:19 +00:00
gods = { }
2015-03-01 00:30:59 +00:00
godslock = threading . Lock ( )
2016-03-25 21:15:50 +00:00
# receiver: [(sender1, origin1, message1), (sender2, origin2, message2), ..., (senderN, origin2, messageN)]
2015-03-01 00:30:59 +00:00
msgs = { }
msgslock = threading . Lock ( )
2015-03-27 15:22:40 +00:00
# (ID, nick, account)
accountcheck = [ ]
accountcheckid = 0
2015-03-01 12:19:57 +00:00
accountchecklock = threading . Lock ( )
2013-06-29 22:01:33 +00:00
2016-03-21 19:59:57 +00:00
die_expr = re . compile ( " #[0-9]*d([0-9]+| % )([+-][0-9]+)?$ " )
2014-04-01 19:25:16 +00:00
2015-02-22 14:29:46 +00:00
class Cron ( threading . Thread ) :
def __init__ ( self ) :
2015-03-01 00:30:59 +00:00
self . timedjobs = [ ]
self . timedjobslock = threading . Lock ( )
self . cronctrl = [ ]
self . cronctrllock = threading . Lock ( )
2015-02-22 14:29:46 +00:00
threading . Thread . __init__ ( self )
2015-03-01 00:30:59 +00:00
2015-02-22 14:29:46 +00:00
def queuejob ( self , time , fn ) :
self . timedjobslock . acquire ( )
self . timedjobs . append ( ( time , fn ) )
self . timedjobslock . release ( )
2015-03-01 00:30:59 +00:00
2015-02-22 14:29:46 +00:00
def ctrl ( self , cmd ) :
self . cronctrllock . acquire ( )
self . cronctrl . append ( cmd )
self . cronctrllock . release ( )
2015-03-01 00:30:59 +00:00
2015-02-22 14:29:46 +00:00
def run ( self ) :
2015-03-01 00:30:59 +00:00
run = True
2015-02-22 14:29:46 +00:00
while run :
time . sleep ( 1 ) # Accuracy doesn't need to be high
self . cronctrllock . acquire ( )
for cmd in self . cronctrl :
2015-03-01 00:30:59 +00:00
if cmd == ' QUIT ' :
run = False
2015-02-22 14:29:46 +00:00
self . cronctrl = [ ]
self . cronctrllock . release ( )
self . timedjobslock . acquire ( )
2021-01-20 18:00:50 +00:00
self . timedjobs = list ( map ( ( lambda time_fn : ( time_fn [ 0 ] - 1 , time_fn [ 1 ] ) ) , self . timedjobs ) )
torun = list ( map ( ( lambda time_fn : time_fn [ 1 ] ) , filter ( ( lambda time_fn : time_fn [ 0 ] < = 0 ) , self . timedjobs ) ) )
self . timedjobs = list ( filter ( ( lambda time_fn : time_fn [ 0 ] > 0 ) , self . timedjobs ) )
2015-02-22 14:29:46 +00:00
self . timedjobslock . release ( )
for fn in torun :
fn ( )
2015-03-01 00:30:59 +00:00
def loadmessages ( ) :
global msgs , msgslock
2016-03-25 21:15:50 +00:00
with msgslock :
msgs = { }
f = open ( ' msgs.txt ' , ' r ' )
for line in f :
while len ( line ) > 0 and line [ - 1 ] == ' \n ' :
line = line [ : - 1 ]
if len ( line . split ( ' \t ' ) ) == 4 :
receiver , sender , origin , msg = line . split ( ' \t ' )
if receiver not in msgs :
msgs [ receiver ] = [ ]
msgs [ receiver ] . append ( ( sender , origin , msg ) )
f . close ( )
2015-03-01 00:30:59 +00:00
def savemessages ( ) :
global msgs , msgslock
2016-03-25 21:15:50 +00:00
with msgslock :
f = open ( ' msgs.txt ' , ' w ' )
for receiver in msgs :
for sender , origin , msg in msgs [ receiver ] :
f . write ( ' %s \t %s \t %s \t %s \n ' % ( receiver , sender , origin , msg ) )
f . close ( )
2015-03-01 00:30:59 +00:00
loadmessages ( )
2015-03-03 15:46:19 +00:00
def addtrusted ( chan , account ) :
2015-03-01 00:30:59 +00:00
global trusted , trustedlock
2021-05-25 20:19:08 +00:00
if type ( chan ) != str : chan = chan . decode ( )
if type ( account ) != str : account = account . decode ( )
2015-03-01 00:30:59 +00:00
2013-09-25 15:23:38 +00:00
trustedlock . acquire ( )
2015-03-01 00:30:59 +00:00
2015-03-03 15:46:19 +00:00
if chan not in trusted :
trusted [ chan ] = [ ]
if account not in trusted [ chan ] :
trusted [ chan ] . append ( account )
2015-03-01 00:30:59 +00:00
2013-09-25 15:23:38 +00:00
trustedlock . release ( )
2015-03-03 15:46:19 +00:00
def rmtrusted ( chan , account ) :
2015-03-01 00:30:59 +00:00
global trusted , trustedlock
2021-05-25 20:19:08 +00:00
if type ( chan ) != str : chan = chan . decode ( )
if type ( account ) != str : account = account . decode ( )
2013-09-25 15:23:38 +00:00
trustedlock . acquire ( )
2015-03-01 00:30:59 +00:00
2015-03-03 15:46:19 +00:00
if chan in trusted and account in trusted [ chan ] :
trusted [ chan ] . remove ( account )
2015-03-01 00:30:59 +00:00
2013-09-25 15:23:38 +00:00
trustedlock . release ( )
2013-07-08 17:37:00 +00:00
def loadtrusted ( ) :
2015-03-01 00:30:59 +00:00
global trusted , trustedlock
2013-07-08 17:37:00 +00:00
trustedlock . acquire ( )
2015-03-03 15:46:19 +00:00
trusted = { }
2013-09-25 15:23:38 +00:00
trustedlock . release ( )
2015-03-01 00:30:59 +00:00
f = open ( ' trusted.txt ' , ' r ' )
2013-07-08 17:37:00 +00:00
for line in f :
2015-03-01 00:30:59 +00:00
while len ( line ) > 0 and line [ - 1 ] == ' \n ' :
line = line [ : - 1 ]
if len ( line ) > 0 :
2015-03-03 15:46:19 +00:00
chan , account = line . split ( )
addtrusted ( chan , account )
2015-03-01 00:30:59 +00:00
2013-07-08 17:37:00 +00:00
f . close ( )
2013-09-25 15:23:38 +00:00
def loadgods ( ) :
2015-03-01 00:30:59 +00:00
global gods , godslock
2013-09-25 15:23:38 +00:00
godslock . acquire ( )
2015-03-03 15:46:19 +00:00
gods = { }
2015-03-01 00:30:59 +00:00
f = open ( ' gods.txt ' , ' r ' )
2013-09-25 15:23:38 +00:00
for line in f :
2015-03-01 00:30:59 +00:00
while len ( line ) > 0 and line [ - 1 ] == ' \n ' :
line = line [ : - 1 ]
if len ( line ) > 0 :
2015-03-03 15:46:19 +00:00
chan , account = line . split ( )
if chan not in gods :
gods [ chan ] = [ ]
gods [ chan ] . append ( account )
addtrusted ( chan , account )
2015-03-01 00:30:59 +00:00
2013-09-25 15:23:38 +00:00
f . close ( )
godslock . release ( )
def savetrusted ( ) :
2015-03-01 00:30:59 +00:00
global trusted , trustedlock
2013-09-25 15:23:38 +00:00
trustedlock . acquire ( )
2015-03-01 00:30:59 +00:00
f = open ( ' trusted.txt ' , ' w ' )
2015-03-03 15:46:19 +00:00
for chan in trusted :
for account in trusted [ chan ] :
f . write ( ' %s %s \n ' % ( chan , account ) )
2015-03-01 00:30:59 +00:00
2013-09-25 15:23:38 +00:00
f . close
2013-07-08 17:37:00 +00:00
trustedlock . release ( )
2018-07-08 19:23:42 +00:00
def init ( ) :
global cron
cron = Cron ( )
cron . start ( )
loadtrusted ( )
loadgods ( )
2013-07-08 17:37:00 +00:00
2015-02-22 18:24:57 +00:00
def chmode ( irc , chan , nick , mode , args ) :
2021-01-20 18:00:50 +00:00
if type ( nick ) != str : nick = nick . decode ( )
set_unset = mode [ 0 ] . encode ( )
mode = mode [ 1 : ] . encode ( )
2015-03-29 16:00:48 +00:00
if isauthorized ( irc , chan , nick ) :
if args == [ ' ' ] :
2021-01-20 18:00:50 +00:00
irc . send_raw ( b ' MODE %s %s %s ' % ( chan , set_unset + mode , nick . encode ( ) ) )
2015-03-29 16:00:48 +00:00
else :
nicks = [ ]
for nick in args :
2021-01-20 18:00:50 +00:00
nicks . append ( nick . encode ( ) )
2015-03-29 16:00:48 +00:00
if len ( nicks ) == 4 :
2021-01-20 18:00:50 +00:00
irc . send_raw ( b ' MODE %s %s %s ' % ( chan , set_unset + mode * 4 , b ' ' . join ( nicks ) ) )
2015-03-29 16:00:48 +00:00
nicks = [ ]
if nicks :
2021-01-20 18:00:50 +00:00
irc . send_raw ( b ' MODE %s %s %s ' % ( chan , set_unset + mode * len ( nicks ) , b ' ' . join ( nicks ) ) )
2015-02-22 15:25:51 +00:00
2015-03-03 15:46:19 +00:00
def istrusted ( chan , account ) :
2021-01-20 18:00:50 +00:00
if type ( chan ) != str : chan = chan . decode ( )
if type ( account ) != str : account = account . decode ( )
2015-02-22 15:25:51 +00:00
trustedlock . acquire ( )
2015-03-03 15:46:19 +00:00
if chan in trusted and account in trusted [ chan ] :
2015-02-22 15:25:51 +00:00
trustedlock . release ( )
return True
else :
trustedlock . release ( )
return False
2015-03-01 12:19:57 +00:00
def initaccountcheck ( nick ) :
2015-03-27 15:22:40 +00:00
global accountcheck , accountcheckid , accountchecklock
2015-03-01 00:30:59 +00:00
2015-03-01 12:19:57 +00:00
accountchecklock . acquire ( )
2015-03-27 15:22:40 +00:00
id = accountcheckid
accountcheck . append ( ( id , nick , None ) )
accountcheckid + = 1
2015-03-01 12:19:57 +00:00
accountchecklock . release ( )
2015-03-27 15:22:40 +00:00
return id
# Warning: this does no locking, should only be used internally
# The index returned cannot be guaranteed valid if lock is released between call to getindexbyaccountcheckid and use!
def getindexbyaccountcheckid ( id ) :
global accountcheck
for index in range ( len ( accountcheck ) ) :
ckid , cknick , ckaccount = accountcheck [ index ]
if ckid == id :
return index
return None
2015-02-22 15:25:51 +00:00
2015-03-27 15:22:40 +00:00
def setaccountcheckvalue ( id , value ) :
2015-03-01 12:19:57 +00:00
global accountcheck , accountchecklock
2015-03-01 00:30:59 +00:00
2015-03-01 12:19:57 +00:00
accountchecklock . acquire ( )
2015-03-27 15:22:40 +00:00
index = getindexbyaccountcheckid ( id )
if index is not None :
ckid , nick , ckvalue = accountcheck [ index ]
accountcheck [ index ] = ( id , nick , value )
2015-03-01 12:19:57 +00:00
accountchecklock . release ( )
2015-02-22 15:25:51 +00:00
2015-03-27 15:22:40 +00:00
def getaccountcheckvalue ( id ) :
2015-03-01 12:19:57 +00:00
global accountcheck , accountchecklock
2015-03-01 00:30:59 +00:00
2015-03-01 12:19:57 +00:00
accountchecklock . acquire ( )
2015-03-27 15:22:40 +00:00
index = getindexbyaccountcheckid ( id )
if index is not None :
ckid , cknick , value = accountcheck [ index ]
2015-03-01 12:19:57 +00:00
accountchecklock . release ( )
2015-03-01 00:30:59 +00:00
2015-03-01 12:19:57 +00:00
return value
2015-02-22 15:25:51 +00:00
2015-03-27 15:22:40 +00:00
def removeaccountcheck ( id ) :
2015-03-01 12:19:57 +00:00
global accountcheck , accountchecklock
2015-03-01 00:30:59 +00:00
2015-03-01 12:19:57 +00:00
accountchecklock . acquire ( )
2015-03-27 15:22:40 +00:00
index = getindexbyaccountcheckid ( id )
if index is not None :
del accountcheck [ index ]
2015-03-01 12:19:57 +00:00
accountchecklock . release ( )
2015-02-22 15:25:51 +00:00
2015-03-27 15:22:40 +00:00
def getaccountcheckidbynick ( nick ) :
global accountcheck , accountchecklock
2021-01-20 18:00:50 +00:00
if type ( nick ) != str : nick = nick . decode ( )
2015-03-27 15:22:40 +00:00
accountchecklock . acquire ( )
2021-01-20 18:00:50 +00:00
getid = lambda id_nick_account : id_nick_account [ 0 ]
filterbynick = lambda id_cknick_account : id_cknick_account [ 1 ] == nick
ids = list ( map ( getid , filter ( filterbynick , accountcheck ) ) )
2015-03-27 15:22:40 +00:00
accountchecklock . release ( )
return ids
2015-03-01 12:19:57 +00:00
def getaccount ( irc , nick ) :
2021-01-20 18:00:50 +00:00
if type ( nick ) != str : nick = nick . decode ( )
2015-03-27 15:22:40 +00:00
id = initaccountcheck ( nick )
2021-01-20 18:00:50 +00:00
irc . send_raw ( b ' WHOIS ' + nick . encode ( ) )
2015-03-27 15:22:40 +00:00
cron . queuejob ( 5 , ( lambda : setaccountcheckvalue ( id , ' ' ) ) )
2015-03-01 12:19:57 +00:00
account = None
while account == None :
2015-03-27 15:22:40 +00:00
account = getaccountcheckvalue ( id )
2015-02-22 15:25:51 +00:00
time . sleep ( 0.1 )
2015-03-27 15:22:40 +00:00
removeaccountcheck ( id )
2015-02-22 15:25:51 +00:00
2015-03-01 12:19:57 +00:00
if account == ' ' : # '' Signifies failure
return None
else :
return account
2015-03-03 15:46:19 +00:00
def isauthorized ( irc , chan , nick ) :
2021-01-20 18:00:50 +00:00
if type ( nick ) != str : nick = nick . decode ( )
2015-03-01 12:19:57 +00:00
account = getaccount ( irc , nick )
if account :
2015-03-03 15:46:19 +00:00
return istrusted ( chan , account )
2015-03-01 12:19:57 +00:00
else :
2021-01-20 18:00:50 +00:00
irc . bot_response ( nick . encode ( ) , ' Identify with NickServ ' )
2013-07-08 17:37:00 +00:00
2015-02-22 18:24:57 +00:00
class ArgsfmtError ( Exception ) :
def __init__ ( self , msg ) :
self . msg = msg
def __str__ ( self ) :
2015-03-01 00:30:59 +00:00
return ' Error with argument format: ' + msg
2015-02-22 18:24:57 +00:00
ARG_STD = 0
ARG_OPT = 1
ARG_UNL = 2
def parseargsfmt ( args ) :
# parses the argument format used by matchcmd and parsecmd
# e.g. parseargsfmt("foo [bar] {baz} ) -> [ARG_STD, ARG_OPT, ARG_UNL]
args = args . split ( ' ' )
out = [ ]
for arg in args :
if len ( arg ) > = 2 and arg [ 0 ] == ' [ ' and arg [ - 1 ] == ' ] ' : # Optional (0-1) argument: [bar]
out . append ( ARG_OPT )
elif len ( arg ) > = 2 and arg [ 0 ] == ' { ' and arg [ - 1 ] == ' } ' : # Unlimited (0-) number of arguments: {baz}
out . append ( ARG_UNL )
else : # Normal argument: foo
out . append ( ARG_STD )
return out
def getargnums ( argtypes ) :
min = 0
max = 0 # max = None if number of arguments is unlimited
for argtype in argtypes :
if argtype == ARG_STD :
min + = 1
if max != None : # Don't try to increment if max is unlimited
max + = 1
elif argtype == ARG_OPT :
if max != None : # Don't try to increment if max is unlimited
max + = 1
elif argtype == ARG_UNL :
max = None
return min , max
def matchcmd ( line , cmd , args = None ) :
# matchcmd(line, cmd) matched if the command cmd is used, matchcmd(line, cmd, args) checks whether the args match too
if len ( line ) == 0 :
return False
if line [ 0 ] != cmd :
return False
if not args :
return True
min , max = getargnums ( parseargsfmt ( args ) )
if max and len ( line ) - 1 > = min and len ( line ) - 1 < = max :
return True
elif not max and len ( line ) - 1 > = min :
return True
else :
return False
def parsecmd ( line , args ) :
# Returns a tuple containing the arguments. An optional argument that didn't get a value will be assigned ''
argtypes = parseargsfmt ( args )
if len ( argtypes ) > = 1 and ARG_UNL in argtypes [ : - 1 ] : # Disallow non-final unlimited arguments
raise ArgsfmtError ( ' Non-final unlimited argument ' )
2021-01-20 18:00:50 +00:00
if len ( list ( filter ( ( lambda type : type == ARG_OPT or type == ARG_UNL ) , argtypes ) ) ) > 1 : # Disallow more than one optional or unlimited argument per argument string
2015-02-22 18:24:57 +00:00
raise ArgsfmtError ( ' Ambiguous argument format ' )
# Remove the command
if len ( line ) == 0 :
raise ArgsfmtError ( ' No command given ' )
line = line [ 1 : ]
min , max = getargnums ( argtypes )
if len ( line ) == min :
# Only standard arguments given
out = [ ]
for type in argtypes :
if type == ARG_STD :
out . append ( line [ 0 ] )
line = line [ 1 : ]
else :
out . append ( ' ' )
elif max and len ( line ) == max :
# Optional argument given
out = [ ]
for type in argtypes :
if type == ARG_STD or type == ARG_OPT :
out . append ( line [ 0 ] )
line = line [ 1 : ]
else :
out . append ( ' ' )
elif not max and len ( line ) > min :
# Unlimited argument given
out = [ ]
for type in argtypes :
if type == ARG_STD or type == ARG_OPT :
out . append ( line [ 0 ] )
line = line [ 1 : ]
elif type == ARG_UNL :
out . append ( ' ' . join ( line ) )
line = [ ]
else :
raise ArgsfmtError ( ' Number of given arguments not possible for given format string ' )
if len ( out ) == 1 :
return out [ 0 ]
else :
return out
2021-01-20 18:00:50 +00:00
def parse ( nick , chan , command , arguments , irc ) :
2015-03-01 00:30:59 +00:00
global blacklist
global msgs , msgslock
global trusted , trustedlock , gods , godslock
global doctor , die_expr
2021-01-20 18:00:50 +00:00
zwsp = ' \u200b '
2015-02-22 18:24:57 +00:00
2014-12-06 20:31:17 +00:00
if nick in blacklist :
return
2021-01-20 18:00:50 +00:00
elif len ( arguments ) > = 2 and len ( arguments [ 1 ] ) > = len ( zwsp . encode ( ' utf-8 ' ) ) and arguments [ 1 ] [ : len ( zwsp . encode ( ' utf-8 ' ) ) ] == zwsp . encode ( ' utf-8 ' ) : # If line begins with ZWSP
2015-02-13 15:52:15 +00:00
return
2014-12-06 20:31:17 +00:00
2021-01-20 18:00:50 +00:00
if command == b ' PRIVMSG ' and arguments [ 1 ] [ : 1 ] != b ' ' :
2015-03-04 22:25:06 +00:00
reply = chan
2021-01-20 18:00:50 +00:00
cmdline = arguments [ 1 ] . decode ( ' utf-8 ' ) . split ( ' ' )
2015-02-22 18:24:57 +00:00
while ' ' in cmdline :
cmdline . remove ( ' ' )
2015-03-01 00:30:59 +00:00
2015-03-04 22:25:06 +00:00
# #chan: channel override prefix
2018-12-06 13:42:02 +00:00
# Don't allow this in private messages for more transparent bot usage
if matchcmd ( cmdline , ' #chan ' ) and chan != nick :
2015-03-04 22:25:06 +00:00
if matchcmd ( cmdline , ' #chan ' , ' channel {command} ' ) :
newchan , newcmdline = parsecmd ( cmdline , ' channel {command} ' )
newcmdline = newcmdline . split ( ' ' )
if isauthorized ( irc , newchan , nick ) :
2021-01-20 18:00:50 +00:00
chan = newchan . encode ( )
2015-03-04 22:25:06 +00:00
cmdline = newcmdline
else :
2021-01-20 18:00:50 +00:00
irc . bot_response ( chan , usage ( ' #chan ' ) )
2015-03-04 22:25:06 +00:00
2015-05-29 17:21:25 +00:00
if matchcmd ( cmdline , ' #echo ' ) :
2015-02-22 18:24:57 +00:00
text = parsecmd ( cmdline , ' {text} ' )
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , text )
2015-02-22 18:24:57 +00:00
elif matchcmd ( cmdline , ' #op ' ) :
args = parsecmd ( cmdline , ' {args} ' )
chmode ( irc , chan , nick , ' +o ' , args . split ( ' ' ) )
elif matchcmd ( cmdline , ' #deop ' ) :
args = parsecmd ( cmdline , ' {args} ' )
chmode ( irc , chan , nick , ' -o ' , args . split ( ' ' ) )
elif matchcmd ( cmdline , ' #voice ' ) :
args = parsecmd ( cmdline , ' {args} ' )
chmode ( irc , chan , nick , ' +v ' , args . split ( ' ' ) )
2019-03-28 06:13:29 +00:00
elif matchcmd ( cmdline , ' #quiet ' ) :
2021-01-20 18:00:50 +00:00
if matchcmd ( cmdline , ' #quiet ' , ' nick ' ) :
arg = parsecmd ( cmdline , ' nick ' )
chmode ( irc , chan , nick , ' +q ' , [ arg + ' !*@* ' ] )
else :
irc . bot_response ( reply , usage ( ' #quiet ' ) )
2019-03-28 06:13:29 +00:00
elif matchcmd ( cmdline , ' #dequiet ' ) :
2021-01-20 18:00:50 +00:00
if matchcmd ( cmdline , ' #dequiet ' , ' nick ' ) :
arg = parsecmd ( cmdline , ' nick ' )
chmode ( irc , chan , nick , ' -q ' , [ arg + ' !*@* ' ] )
else :
irc . bot_response ( reply , usage ( ' #dequiet ' ) )
2015-02-22 18:24:57 +00:00
elif matchcmd ( cmdline , ' #devoice ' ) :
args = parsecmd ( cmdline , ' {args} ' )
chmode ( irc , chan , nick , ' -v ' , args . split ( ' ' ) )
elif matchcmd ( cmdline , ' #kick ' ) :
if matchcmd ( cmdline , ' #kick ' , ' nick {reason} ' ) :
kicknick , kickreason = parsecmd ( cmdline , ' nick {reason} ' )
2021-01-20 18:00:50 +00:00
if kicknick . lower ( ) == irc . get_nick ( ) . decode ( ' utf-8 ' ) :
irc . send_raw ( b ' KICK %s %s :Fuck you ' % ( chan , nick ) )
2013-09-03 12:50:54 +00:00
else :
2015-03-03 15:46:19 +00:00
if isauthorized ( irc , chan , nick ) :
2021-01-20 18:00:50 +00:00
irc . send_raw ( b ' KICK %s %s : %s ' % ( chan , kicknick . encode ( ) , kickreason . encode ( ) ) )
2013-07-08 16:57:42 +00:00
else :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , usage ( ' #kick ' ) )
2015-02-22 18:24:57 +00:00
elif matchcmd ( cmdline , ' #src ' ) :
2021-01-20 18:05:11 +00:00
irc . bot_response ( reply , ' https://ahti.space/git/nortti/oonbotti2 ' )
2015-02-22 18:24:57 +00:00
elif matchcmd ( cmdline , ' #prefix ' ) and chan == ' #osdev-offtopic ' :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , ' gopher://ayu.smar.fi:7070/0/hash-prefix ' )
2015-02-22 18:24:57 +00:00
elif matchcmd ( cmdline , ' #msg ' ) :
if matchcmd ( cmdline , ' #msg ' , ' nick {message} ' ) :
msgnick , message = parsecmd ( cmdline , ' nick {message} ' )
2016-03-25 21:15:50 +00:00
if chan == nick : # In a query:
origin = " [query] "
else : # In a channel
2021-01-20 18:00:50 +00:00
origin = chan . decode ( )
2016-03-25 21:15:50 +00:00
with msgslock :
if msgnick not in msgs :
msgs [ msgnick ] = [ ]
2021-01-20 18:00:50 +00:00
msgs [ msgnick ] . append ( ( nick . decode ( ) , origin , message ) )
2016-05-28 19:23:10 +00:00
savemessages ( )
2013-07-06 19:10:46 +00:00
else :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , usage ( ' #msg ' ) )
2015-02-22 18:24:57 +00:00
elif matchcmd ( cmdline , ' #trusted? ' ) :
if matchcmd ( cmdline , ' #trusted? ' , ' [nick] ' ) :
trustnick = parsecmd ( cmdline , ' [nick] ' )
if trustnick == ' ' :
2021-01-20 18:00:50 +00:00
trustnick = nick . decode ( )
2015-03-01 12:19:57 +00:00
account = getaccount ( irc , trustnick )
if account :
2015-03-03 15:46:19 +00:00
if istrusted ( chan , account ) :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , ' %s is trusted ' % trustnick )
2015-03-01 12:19:57 +00:00
else :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , ' %s is not trusted ' % trustnick )
2015-02-22 18:24:57 +00:00
else :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , ' Failed to get account for %s ' % trustnick )
2015-02-22 15:25:51 +00:00
else :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , usage ( ' #truste? ' ) )
2015-02-22 18:24:57 +00:00
elif matchcmd ( cmdline , ' #trust ' ) :
if matchcmd ( cmdline , ' #trust ' , ' nick ' ) :
trustnick = parsecmd ( cmdline , ' nick ' )
2015-03-03 15:46:19 +00:00
if isauthorized ( irc , chan , nick ) :
2015-03-01 12:19:57 +00:00
account = getaccount ( irc , trustnick )
if account :
2015-03-03 15:46:19 +00:00
addtrusted ( chan , account )
2016-05-28 19:23:10 +00:00
savetrusted ( )
2015-03-01 12:19:57 +00:00
else :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , ' Failed to get account for %s ' % trustnick )
2013-09-25 15:23:38 +00:00
else :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , usage ( ' #trust ' ) )
2015-02-22 18:24:57 +00:00
elif matchcmd ( cmdline , ' #untrust ' ) :
if matchcmd ( cmdline , ' #untrust ' , ' nick ' ) :
untrustnick = parsecmd ( cmdline , ' nick ' )
2015-03-03 15:46:19 +00:00
if isauthorized ( irc , chan , nick ) :
2015-03-01 12:19:57 +00:00
account = getaccount ( irc , untrustnick )
2016-02-05 15:26:43 +00:00
# If account can't be found (e.g. it has been deleted, use the parameter as-is
if not account :
if istrusted ( chan , untrustnick ) :
account = untrustnick
2015-03-01 12:19:57 +00:00
if account :
godslock . acquire ( )
2021-01-20 18:00:50 +00:00
if chan . decode ( ) not in gods or account not in gods [ chan . decode ( ) ] :
rmtrusted ( chan . decode ( ) , untrustnick )
2015-03-01 12:19:57 +00:00
godslock . release ( )
2016-05-28 19:23:10 +00:00
savetrusted ( )
2015-03-01 12:19:57 +00:00
else :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , ' Failed to get account for %s ' % untrustnick )
2013-09-25 15:23:38 +00:00
else :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , usage ( ' #untrust ' ) )
2015-02-22 18:24:57 +00:00
elif matchcmd ( cmdline , ' #ls-trusted ' ) :
2013-09-25 15:23:38 +00:00
trustedlock . acquire ( )
2021-01-20 18:00:50 +00:00
if chan . decode ( ) in trusted :
2016-02-05 15:19:50 +00:00
lines = [ ]
line = ' '
2021-01-20 18:00:50 +00:00
for account in trusted [ chan . decode ( ) ] :
2016-02-05 15:19:50 +00:00
if line == ' ' :
line = account
elif len ( line + ' , ' + account ) < = 255 : # Playing it safe not to get truncated
line + = ' , ' + account
else :
lines . append ( line )
line = account
if line != ' ' :
lines . append ( line )
for line in lines :
2021-01-20 18:00:50 +00:00
irc . bot_response ( nick , ' %s : %s ' % ( chan . decode ( ) , line ) )
2013-09-25 15:23:38 +00:00
trustedlock . release ( )
2015-02-22 18:24:57 +00:00
elif matchcmd ( cmdline , ' #invite ' ) :
2021-07-25 19:05:21 +00:00
irc . bot_response ( chan , ' %s : #invite has been removed. Use manual invite ' % nick . decode ( ) )
2015-02-22 18:24:57 +00:00
elif matchcmd ( cmdline , ' #help ' ) :
if matchcmd ( cmdline , ' #help ' , ' [command] ' ) :
command = parsecmd ( cmdline , ' [command] ' )
helptext = help ( command )
if helptext :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , helptext )
2015-03-04 22:25:06 +00:00
elif matchcmd ( cmdline , ' #esoteric ' ) and chan == ' #esoteric ' :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , ' Nothing here ' )
elif cmdline [ 0 ] in [ irc . get_nick ( ) . decode ( ) , irc . get_nick ( ) . decode ( ) + ' , ' , irc . get_nick ( ) . decode ( ) + ' : ' ] :
2015-02-22 18:24:57 +00:00
question = parsecmd ( cmdline , ' {question} ' )
2015-03-19 20:11:06 +00:00
if len ( question ) < 2 or question [ : 2 ] != ' :D ' : # Mandated by #osdev-offtopic law
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , ' %s : %s ' % ( nick . decode ( ) , doctor . respond ( question ) ) )
2015-02-22 18:24:57 +00:00
elif die_expr . match ( cmdline [ 0 ] ) :
2015-03-04 22:25:06 +00:00
die = cmdline [ 0 ] [ 1 : ] . split ( ' d ' )
times = int ( die [ 0 ] ) if die [ 0 ] else 1
2015-04-26 16:34:05 +00:00
if ' + ' in die [ 1 ] :
split = die [ 1 ] . index ( ' + ' )
plus = int ( die [ 1 ] [ split + 1 : ] )
die [ 1 ] = die [ 1 ] [ : split ]
elif ' - ' in die [ 1 ] :
split = die [ 1 ] . index ( ' - ' )
plus = - int ( die [ 1 ] [ split + 1 : ] )
die [ 1 ] = die [ 1 ] [ : split ]
else :
plus = 0
2015-03-04 22:25:06 +00:00
die = ' % ' if die [ 1 ] == ' % ' else int ( die [ 1 ] )
2015-04-26 16:34:05 +00:00
2015-03-04 22:25:06 +00:00
if die == ' % ' :
if times != 1 :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , ' Not supported ' )
2014-04-12 14:16:36 +00:00
else :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , ' %s %s ' % ( random . randint ( 0 , 9 ) , random . randint ( 0 , 9 ) ) )
2018-03-25 21:02:21 +00:00
elif die < 1 :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , ' This die is not available in your space-time region. ' )
2015-03-04 22:25:06 +00:00
elif times < 1 :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , ' What exactly do you want me to do? ' )
2015-03-04 22:25:06 +00:00
elif times > 128 :
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , ' Sorry, I don \' t have that many. Can I borrow yours? ' )
2014-04-01 19:25:16 +00:00
else :
2021-01-20 18:00:50 +00:00
rolls = [ random . randint ( 1 , die ) for i in range ( times ) ]
result = functools . reduce ( ( lambda x , y : x + y ) , rolls )
2015-04-26 16:34:05 +00:00
2015-03-04 22:25:06 +00:00
if times > 1 :
2015-04-26 16:34:05 +00:00
text = ' %s ( %s ) ' % ( str ( result ) , ' , ' . join ( [ str ( i ) for i in rolls ] ) )
2014-04-01 19:25:16 +00:00
else :
2015-04-26 16:34:05 +00:00
text = str ( result )
if plus > 0 :
text = ' %i ( %s + %i ) ' % ( result + plus , text , plus )
elif plus < 0 :
text = ' %i ( %s - %i ) ' % ( result + plus , text , - plus )
2021-01-20 18:00:50 +00:00
irc . bot_response ( reply , text )
elif command == b ' 330 ' : # WHOIS: is logged in as
whoisnick = arguments [ 1 ] . decode ( ' utf-8 ' )
account = arguments [ 2 ] . decode ( ' utf-8 ' )
2015-03-27 15:22:40 +00:00
for id in getaccountcheckidbynick ( whoisnick ) :
setaccountcheckvalue ( id , account )
2021-01-20 18:00:50 +00:00
elif command == ' 318 ' : # WHOIS: End of /WHOIS list.
whoisnick = arguments [ 1 ] . decode ( ' utf-8 ' )
2015-03-27 15:22:40 +00:00
for id in getaccountcheckidbynick ( whoisnick ) :
if getaccountcheckvalue ( id ) == None :
setaccountcheckvalue ( id , ' ' ) # Mark as failed, '' is used because None is already reserved
2021-01-20 18:00:50 +00:00
elif command == b ' INVITE ' and arguments [ 0 ] == irc . get_nick ( ) and arguments [ 1 ] in irc . get_channel ( ) . split ( ' ' ) :
if isauthorized ( irc , arguments [ 1 ] , nick ) :
irc . send_raw ( b ' JOIN ' + arguments [ 1 ] )
elif command == b ' 482 ' :
irc . bot_response ( arguments [ 1 ] , ' Not op ' )
2015-03-01 00:30:59 +00:00
2016-05-28 19:23:10 +00:00
msgs_changed = False
2016-03-25 21:15:50 +00:00
with msgslock :
2021-01-20 18:00:50 +00:00
if ( command == b ' PRIVMSG ' or command == b ' JOIN ' ) and nick . decode ( ' utf-8 ' ) in msgs :
for sender , origin , msg in msgs . pop ( nick . decode ( ) ) :
irc . bot_response ( nick , ' %s < %s > %s ' % ( origin , sender , msg ) )
2016-05-28 19:23:10 +00:00
msgs_changed = True
if msgs_changed :
savemessages ( )
2013-07-07 12:43:33 +00:00
2015-03-01 00:30:59 +00:00
def usage ( cmd , message = True ) :
usage = { ' #echo ' : ' text ' ,
' #op ' : ' [nick] ' ,
' #deop ' : ' [nick] ' ,
' #voice ' : ' [nick] ' ,
' #devoice ' : ' [nick] ' ,
2019-03-28 06:13:29 +00:00
' #quiet ' : ' nick ' ,
' #dequiet ' : ' nick ' ,
2015-03-01 00:30:59 +00:00
' #kick ' : ' nick [reason] ' ,
' #src ' : ' ' ,
' #msg ' : ' nick message ' ,
2015-03-03 15:49:32 +00:00
' #trusted? ' : ' [nick] ' ,
2015-03-01 00:30:59 +00:00
' #trust ' : ' nick ' ,
' #untrust ' : ' nick ' ,
' #ls-trusted ' : ' ' ,
2015-03-04 22:25:06 +00:00
' #chan ' : ' channel command ' ,
2015-03-01 00:30:59 +00:00
' #help ' : ' [command] ' }
if cmd in usage :
if message :
return ' Usage: %s %s ' % ( cmd , usage [ cmd ] )
else :
return usage [ cmd ]
else :
return None
2013-07-08 15:09:18 +00:00
def help ( cmd ) :
2015-03-01 00:30:59 +00:00
helptext = { ' #echo ' : ' #echo text back ' ,
' #op ' : ' give nick or yourself op rights in case you are trusted by oonbotti2 and identified with NickServ ' ,
' #deop ' : ' remove your/nick \' s op rights ' ,
' #voice ' : ' give nick or yourself voice in case you are trusted by oonbotti2 and identified with NickServ ' ,
' #devoice ' : ' remove your or nick \' s voice in case you are trusted by oonbotti2 and identified with NickServ ' ,
2019-03-28 06:13:29 +00:00
' #quiet ' : ' give +q to nick!*@* ' ,
' #dequiet ' : ' remove +q from nick!*@* ' ,
2015-03-01 00:30:59 +00:00
' #kick ' : ' kicks nick with specified reason ' ,
' #src ' : ' paste a link to oonbotti2 \' s git repo ' ,
' #msg ' : ' send a message to nick ' ,
' #trusted? ' : ' tell you if nick or yourself is trusted by oonbotti2 ' ,
' #trust ' : ' add nick to trusted list ' ,
' #untrust ' : ' remove nick from trusted list ' ,
' #ls-trusted ' : ' list nicks that are trusted. use only in a query ' ,
2015-03-04 22:25:06 +00:00
' #chan ' : ' Runs the command as if it was sent on the specified channel. Requires user to be trusted ' ,
2015-03-01 00:30:59 +00:00
' #help ' : ' give short info of command or list commands ' }
2013-07-08 15:09:18 +00:00
if cmd == ' ' :
2019-03-28 06:13:29 +00:00
return ' #echo #op #deop #voice #devoice #quiet #dequiet #kick #src #msg #trusted? #trust #untrust #ls-trusted #chan #help '
2014-03-11 19:05:17 +00:00
elif cmd == ' me ' :
return ' I shall. '
2015-03-01 00:30:59 +00:00
elif cmd in helptext :
if helptext [ cmd ] :
return ' %s %s %s ' % ( cmd , usage ( cmd , False ) , helptext [ cmd ] )
else :
return ' %s %s ' % ( cmd , usage ( cmd , False ) )
2013-07-08 15:09:18 +00:00
else :
2014-04-03 18:35:46 +00:00
return None