]>
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 fastmsg ( self
, * args
, ** kwargs
):
32 main
. randbot (). fastmsg ( self
, * args
, ** kwargs
)
35 return self
. auth
is not None
37 def authed ( self
, auth
):
38 if auth
== '0' : self
. auth
= None
39 else : self
. auth
= auth
. lower ()
47 if c
. execute ( "SELECT level FROM users WHERE auth = %s " , ( self
. auth
,)):
50 self
. glevel
= row
[ 'level' ]
58 self
. chans
. append ( chan
)
60 self
. chans
. remove ( chan
)
62 for chan
in self
. chans
:
63 self
. chans
. remove ( chan
)
64 def nickchange ( self
, newnick
):
67 def __str__ ( self
): return self
. nick
68 def __repr__ ( self
): return "<User %r ( %d )>" % ( self
. nick
, self
. glevel
)
70 class Channel ( object ):
71 def __init__ ( self
, name
, bot
):
81 if c
. execute ( "SELECT user, level FROM chusers WHERE chan = %s " , ( self
. name
,)):
83 while row
is not None :
84 self
. levels
[ row
[ 'user' ]] = row
[ 'level' ]
88 def msg ( self
, * args
, ** kwargs
):
89 self
. bot
. msg ( self
, * args
, ** kwargs
)
90 def fastmsg ( self
, * args
, ** kwargs
):
91 self
. bot
. fastmsg ( self
, * args
, ** kwargs
)
93 def levelof ( self
, auth
):
97 if auth
in self
. levels
:
98 return self
. levels
[ auth
]
102 def setlevel ( self
, auth
, level
, savetodb
= True ):
106 if c
. execute ( "REPLACE INTO chusers (chan, user, level) VALUES ( %s , %s , %s )" , ( self
. name
, auth
, level
)):
107 self
. levels
[ auth
] = level
112 def userjoin ( self
, user
, level
= None ):
113 if user
not in self
. users
: self
. users
. append ( user
)
114 if level
== 'op' and user
not in self
. ops
: self
. ops
. append ( user
)
115 if level
== 'voice' and user
not in self
. voices
: self
. voices
. append ( user
)
116 def userpart ( self
, user
):
117 if user
in self
. ops
: self
. ops
. remove ( user
)
118 if user
in self
. voices
: self
. voices
. remove ( user
)
119 if user
in self
. users
: self
. users
. remove ( user
)
121 def userop ( self
, user
):
122 if user
in self
. users
and user
not in self
. ops
: self
. ops
. append ( user
)
123 def uservoice ( self
, user
):
124 if user
in self
. users
and user
not in self
. voices
: self
. voices
. append ( user
)
125 def userdeop ( self
, user
):
126 if user
in self
. ops
: self
. ops
. remove ( user
)
127 def userdevoice ( self
, user
):
128 if user
in self
. voices
: self
. voices
. remove ( user
)
130 def __str__ ( self
): return self
. name
131 def __repr__ ( self
): return "<Channel %r >" % ( self
. name
)
133 def __init__ ( self
, cfg
):
135 self
. trigger
= cfg
. trigger
136 if os
. name
== "posix" :
138 self
. po
= select
. poll ()
139 else : # f.e. os.name == "nt" (Windows)
140 self
. potype
= "select"
143 def newbot ( self
, nick
, user
, bind
, authname
, authpass
, server
, port
, realname
):
144 if bind
is None : bind
= ''
145 obj
= bot
. Bot ( self
, nick
, user
, bind
, authname
, authpass
, server
, port
, realname
)
146 self
. bots
[ nick
. lower ()] = obj
148 def newfd ( self
, obj
, fileno
):
149 self
. fds
[ fileno
] = obj
150 if self
. potype
== "poll" :
151 self
. po
. register ( fileno
, select
. POLLIN
)
152 elif self
. potype
== "select" :
153 self
. fdlist
. append ( fileno
)
155 def bot ( self
, name
): #get Bot() by name (nick)
156 return self
. bots
[ name
. lower ()]
157 def fd ( self
, fileno
): #get Bot() by fd/fileno
158 return self
. fds
[ fileno
]
159 def randbot ( self
): #get Bot() randomly
160 return self
. bots
[ random
. choice ( self
. bots
. keys ())]
162 def user ( self
, _nick
, justjoined
= False ):
164 if nick
in self
. users
:
165 return self
. users
[ nick
]
167 user
= self
. User ( _nick
)
168 self
. users
[ nick
] = user
171 self
. randbot (). conn
. send ( "WHO %s n %% ant,2" % ( nick
))
174 def channel ( self
, name
): #get Channel() by name
175 if name
. lower () in self
. chans
:
176 return self
. chans
[ name
. lower ()]
180 def newchannel ( self
, bot
, name
):
181 chan
= self
. Channel ( name
. lower (), bot
)
182 self
. chans
[ name
. lower ()] = chan
186 if self
. potype
== "poll" :
187 return [ fd
for ( fd
, ev
) in self
. po
. poll ()]
188 elif self
. potype
== "select" :
189 return select
. select ( self
. fdlist
, [], [])[ 0 ]
191 def connectall ( self
):
192 for bot
in self
. bots
. itervalues ():
193 if bot
. conn
. state
== 0 :
196 def module ( self
, name
):
197 return ctlmod
. modules
[ name
]
200 def hook ( self
, word
, handler
):
202 self
. msghandlers
[ word
]. append ( handler
)
204 self
. msghandlers
[ word
] = [ handler
]
205 def unhook ( self
, word
, handler
):
206 if word
in self
. msghandlers
and handler
in self
. msghandlers
[ word
]:
207 self
. msghandlers
[ word
]. remove ( handler
)
208 def hashook ( self
, word
):
209 return word
in self
. msghandlers
and len ( self
. msghandlers
[ word
]) != 0
210 def gethook ( self
, word
):
211 return self
. msghandlers
[ word
]
213 def hooknum ( self
, word
, handler
):
215 self
. numhandlers
[ word
]. append ( handler
)
217 self
. numhandlers
[ word
] = [ handler
]
218 def unhooknum ( self
, word
, handler
):
219 if word
in self
. numhandlers
and handler
in self
. numhandlers
[ word
]:
220 self
. numhandlers
[ word
]. remove ( handler
)
221 def hasnumhook ( self
, word
):
222 return word
in self
. numhandlers
and len ( self
. numhandlers
[ word
]) != 0
223 def getnumhook ( self
, word
):
224 return self
. numhandlers
[ word
]
226 def hookchan ( self
, chan
, handler
):
228 self
. chanhandlers
[ chan
]. append ( handler
)
230 self
. chanhandlers
[ chan
] = [ handler
]
231 def unhookchan ( self
, chan
, handler
):
232 if chan
in self
. chanhandlers
and handler
in self
. chanhandlers
[ chan
]:
233 self
. chanhandlers
[ chan
]. remove ( handler
)
234 def haschanhook ( self
, chan
):
235 return chan
in self
. chanhandlers
and len ( self
. chanhandlers
[ chan
]) != 0
236 def getchanhook ( self
, chan
):
237 return self
. chanhandlers
[ chan
]
240 class MyCursor ( MySQLdb
. cursors
. DictCursor
):
241 def execute ( self
, * args
, ** kwargs
):
242 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
]))
244 super ( self
.__ class
__ , self
). execute (* args
, ** kwargs
)
245 except MySQLdb
. MySQLError
as e
:
246 print " %0 5.3f [SQL] [!] MySQL error! %r " % ( time
. time () % 100000 , e
)
254 main
. db
= MySQLdb
. connect ( host
= cfg
. dbhost
, user
= cfg
. dbuser
, passwd
= cfg
. dbpass
, db
= cfg
. dbname
, cursorclass
= MyCursor
)
259 cfg
= config
. Config ( 'bot.config' )
261 pidfile
= open ( cfg
. pidfile
, 'w' )
262 pidfile
. write ( str ( os
. getpid ()))
267 autoloads
= [ mod
for mod
, yes
in cfg
. items ( 'autoloads' ) if int ( yes
) == 1 ]
268 for mod
in autoloads
:
269 ctlmod
. load ( main
, mod
)
273 if c
. execute ( "SELECT nick, user, bind, authname, authpass FROM bots WHERE active = 1" ):
277 main
. newbot ( row
[ 'nick' ], row
[ 'user' ], row
[ 'bind' ], row
[ 'authname' ], row
[ 'authpass' ], cfg
. host
, cfg
. port
, cfg
. realname
)
281 poready
= main
. poll ()
282 for fileno
in poready
:
283 for line
in main
. fd ( fileno
). getdata ():
284 main
. fd ( fileno
). parse ( line
)
286 if __name__
== '__main__' :
287 try : os
. rename ( 'logfile' , 'oldlogs/ %s ' % ( time
. time ()))
289 sys
. stdout
= open ( 'logfile' , 'w' )
290 sys
. stderr
= sys
. stdout