]>
jfr.im git - erebus.git/blob - erebus.py
3 # Erebus IRC bot - Author: John Runyon
6 import os
, sys
, select
, MySQLdb
, MySQLdb
. cursors
, time
, random
7 import bot
, config
, ctlmod
22 def __init__ ( self
, nick
, auth
= None ):
29 def msg ( self
, * args
, ** kwargs
):
30 main
. randbot (). msg ( self
, * args
, ** kwargs
)
31 def slowmsg ( self
, * args
, ** kwargs
):
32 main
. randbot (). slowmsg ( self
, * args
, ** kwargs
)
33 def fastmsg ( self
, * args
, ** kwargs
):
34 main
. randbot (). fastmsg ( self
, * args
, ** kwargs
)
37 return self
. auth
is not None
39 def authed ( self
, auth
):
40 if auth
== '0' : self
. auth
= None
41 else : self
. auth
= auth
. lower ()
49 if c
. execute ( "SELECT level FROM users WHERE auth = %s " , ( self
. auth
,)):
52 self
. glevel
= row
[ 'level' ]
60 self
. chans
. append ( chan
)
62 self
. chans
. remove ( chan
)
64 for chan
in self
. chans
:
65 self
. chans
. remove ( chan
)
66 def nickchange ( self
, newnick
):
69 def __str__ ( self
): return self
. nick
70 def __repr__ ( self
): return "<User %r ( %d )>" % ( self
. nick
, self
. glevel
)
72 class Channel ( object ):
73 def __init__ ( self
, name
, bot
):
83 if c
. execute ( "SELECT user, level FROM chusers WHERE chan = %s " , ( self
. name
,)):
85 while row
is not None :
86 self
. levels
[ row
[ 'user' ]] = row
[ 'level' ]
90 def msg ( self
, * args
, ** kwargs
):
91 self
. bot
. msg ( self
, * args
, ** kwargs
)
92 def slowmsg ( self
, * args
, ** kwargs
):
93 self
. bot
. slowmsg ( self
, * args
, ** kwargs
)
94 def fastmsg ( self
, * args
, ** kwargs
):
95 self
. bot
. fastmsg ( self
, * args
, ** kwargs
)
97 def levelof ( self
, auth
):
101 if auth
in self
. levels
:
102 return self
. levels
[ auth
]
106 def setlevel ( self
, auth
, level
, savetodb
= True ):
110 if c
. execute ( "REPLACE INTO chusers (chan, user, level) VALUES ( %s , %s , %s )" , ( self
. name
, auth
, level
)):
111 self
. levels
[ auth
] = level
116 def userjoin ( self
, user
, level
= None ):
117 if user
not in self
. users
: self
. users
. append ( user
)
118 if level
== 'op' and user
not in self
. ops
: self
. ops
. append ( user
)
119 if level
== 'voice' and user
not in self
. voices
: self
. voices
. append ( user
)
120 def userpart ( self
, user
):
121 if user
in self
. ops
: self
. ops
. remove ( user
)
122 if user
in self
. voices
: self
. voices
. remove ( user
)
123 if user
in self
. users
: self
. users
. remove ( user
)
125 def userop ( self
, user
):
126 if user
in self
. users
and user
not in self
. ops
: self
. ops
. append ( user
)
127 def uservoice ( self
, user
):
128 if user
in self
. users
and user
not in self
. voices
: self
. voices
. append ( user
)
129 def userdeop ( self
, user
):
130 if user
in self
. ops
: self
. ops
. remove ( user
)
131 def userdevoice ( self
, user
):
132 if user
in self
. voices
: self
. voices
. remove ( user
)
134 def __str__ ( self
): return self
. name
135 def __repr__ ( self
): return "<Channel %r >" % ( self
. name
)
137 def __init__ ( self
, cfg
):
139 self
. trigger
= cfg
. trigger
140 if os
. name
== "posix" :
142 self
. po
= select
. poll ()
143 else : # f.e. os.name == "nt" (Windows)
144 self
. potype
= "select"
147 def newbot ( self
, nick
, user
, bind
, authname
, authpass
, server
, port
, realname
):
148 if bind
is None : bind
= ''
149 obj
= bot
. Bot ( self
, nick
, user
, bind
, authname
, authpass
, server
, port
, realname
)
150 self
. bots
[ nick
. lower ()] = obj
152 def newfd ( self
, obj
, fileno
):
153 self
. fds
[ fileno
] = obj
154 if self
. potype
== "poll" :
155 self
. po
. register ( fileno
, select
. POLLIN
)
156 elif self
. potype
== "select" :
157 self
. fdlist
. append ( fileno
)
159 def bot ( self
, name
): #get Bot() by name (nick)
160 return self
. bots
[ name
. lower ()]
161 def fd ( self
, fileno
): #get Bot() by fd/fileno
162 return self
. fds
[ fileno
]
163 def randbot ( self
): #get Bot() randomly
164 return self
. bots
[ random
. choice ( self
. bots
. keys ())]
166 def user ( self
, _nick
, justjoined
= False ):
168 if nick
in self
. users
:
169 return self
. users
[ nick
]
171 user
= self
. User ( _nick
)
172 self
. users
[ nick
] = user
175 self
. randbot (). conn
. send ( "WHO %s n %% ant,2" % ( nick
))
178 def channel ( self
, name
): #get Channel() by name
179 if name
. lower () in self
. chans
:
180 return self
. chans
[ name
. lower ()]
184 def newchannel ( self
, bot
, name
):
185 chan
= self
. Channel ( name
. lower (), bot
)
186 self
. chans
[ name
. lower ()] = chan
190 if self
. potype
== "poll" :
191 return [ fd
for ( fd
, ev
) in self
. po
. poll ()]
192 elif self
. potype
== "select" :
193 return select
. select ( self
. fdlist
, [], [])[ 0 ]
195 def connectall ( self
):
196 for bot
in self
. bots
. itervalues ():
197 if bot
. conn
. state
== 0 :
200 def module ( self
, name
):
201 return ctlmod
. modules
[ name
]
204 def hook ( self
, word
, handler
):
206 self
. msghandlers
[ word
]. append ( handler
)
208 self
. msghandlers
[ word
] = [ handler
]
209 def unhook ( self
, word
, handler
):
210 if word
in self
. msghandlers
and handler
in self
. msghandlers
[ word
]:
211 self
. msghandlers
[ word
]. remove ( handler
)
212 def hashook ( self
, word
):
213 return word
in self
. msghandlers
and len ( self
. msghandlers
[ word
]) != 0
214 def gethook ( self
, word
):
215 return self
. msghandlers
[ word
]
217 def hooknum ( self
, word
, handler
):
219 self
. numhandlers
[ word
]. append ( handler
)
221 self
. numhandlers
[ word
] = [ handler
]
222 def unhooknum ( self
, word
, handler
):
223 if word
in self
. numhandlers
and handler
in self
. numhandlers
[ word
]:
224 self
. numhandlers
[ word
]. remove ( handler
)
225 def hasnumhook ( self
, word
):
226 return word
in self
. numhandlers
and len ( self
. numhandlers
[ word
]) != 0
227 def getnumhook ( self
, word
):
228 return self
. numhandlers
[ word
]
230 def hookchan ( self
, chan
, handler
):
232 self
. chanhandlers
[ chan
]. append ( handler
)
234 self
. chanhandlers
[ chan
] = [ handler
]
235 def unhookchan ( self
, chan
, handler
):
236 if chan
in self
. chanhandlers
and handler
in self
. chanhandlers
[ chan
]:
237 self
. chanhandlers
[ chan
]. remove ( handler
)
238 def haschanhook ( self
, chan
):
239 return chan
in self
. chanhandlers
and len ( self
. chanhandlers
[ chan
]) != 0
240 def getchanhook ( self
, chan
):
241 return self
. chanhandlers
[ chan
]
244 class MyCursor ( MySQLdb
. cursors
. DictCursor
):
245 def execute ( self
, * args
, ** kwargs
):
246 print " %0 5.3f [SQL] [#] MyCursor.execute(self, %s , %s )" % ( time
. time () % 100000 , ', ' . join ([ repr ( i
) for i
in args
]), ', ' . join ([ str ( key
)+ "=" + repr ( kwargs
[ key
]) for key
in kwargs
]))
248 super ( self
.__ class
__ , self
). execute (* args
, ** kwargs
)
249 except MySQLdb
. MySQLError
as e
:
250 print " %0 5.3f [SQL] [!] MySQL error! %r " % ( time
. time () % 100000 , e
)
258 main
. db
= MySQLdb
. connect ( host
= cfg
. dbhost
, user
= cfg
. dbuser
, passwd
= cfg
. dbpass
, db
= cfg
. dbname
, cursorclass
= MyCursor
)
263 cfg
= config
. Config ( 'bot.config' )
265 pidfile
= open ( cfg
. pidfile
, 'w' )
266 pidfile
. write ( str ( os
. getpid ()))
271 autoloads
= [ mod
for mod
, yes
in cfg
. items ( 'autoloads' ) if int ( yes
) == 1 ]
272 for mod
in autoloads
:
273 ctlmod
. load ( main
, mod
)
277 if c
. execute ( "SELECT nick, user, bind, authname, authpass FROM bots WHERE active = 1" ):
281 main
. newbot ( row
[ 'nick' ], row
[ 'user' ], row
[ 'bind' ], row
[ 'authname' ], row
[ 'authpass' ], cfg
. host
, cfg
. port
, cfg
. realname
)
285 poready
= main
. poll ()
286 for fileno
in poready
:
287 for line
in main
. fd ( fileno
). getdata ():
288 main
. fd ( fileno
). parse ( line
)
290 if __name__
== '__main__' :
291 try : os
. rename ( 'logfile' , 'oldlogs/ %s ' % ( time
. time ()))
293 sys
. stdout
= open ( 'logfile' , 'w' )
294 sys
. stderr
= sys
. stdout