]>
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
)
33 return self
.auth
is not None
35 def authed(self
, auth
):
36 if auth
== '0': self
.auth
= None
37 else: self
.auth
= auth
.lower()
45 if c
.execute("SELECT level FROM users WHERE auth = %s", (self
.auth
,)):
48 self
.glevel
= row
['level']
56 self
.chans
.append(chan
)
58 self
.chans
.remove(chan
)
60 for chan
in self
.chans
:
61 self
.chans
.remove(chan
)
62 def nick(self
, newnick
):
65 def __str__(self
): return self
.nick
66 def __repr__(self
): return "<User %r (%d)>" % (self
.nick
,self
.glevel
)
68 class Channel(object):
69 def __init__(self
, name
, bot
):
79 if c
.execute("SELECT user, level FROM chusers WHERE chan = %s", (self
.name
,)):
81 while row
is not None:
82 self
.levels
[row
['user']] = row
['level']
86 def msg(self
, *args
, **kwargs
):
87 self
.bot
.msg(self
.name
, *args
, **kwargs
)
89 def levelof(self
, auth
):
93 if auth
in self
.levels
:
94 return self
.levels
[auth
]
98 def setlevel(self
, auth
, level
, savetodb
=True):
102 if c
.execute("REPLACE INTO chusers (chan, user, level) VALUES (%s, %s, %s)", (self
.name
, auth
, level
)):
103 self
.levels
[auth
] = level
108 def userjoin(self
, user
, level
=None):
109 if user
not in self
.users
: self
.users
.append(user
)
110 if level
== 'op' and user
not in self
.ops
: self
.ops
.append(user
)
111 if level
== 'voice' and user
not in self
.voices
: self
.voices
.append(user
)
112 def userpart(self
, user
):
113 if user
in self
.ops
: self
.ops
.remove(user
)
114 if user
in self
.voices
: self
.voices
.remove(user
)
115 if user
in self
.users
: self
.users
.remove(user
)
117 def userop(self
, user
):
118 if user
in self
.users
and user
not in self
.ops
: self
.ops
.append(user
)
119 def uservoice(self
, user
):
120 if user
in self
.users
and user
not in self
.voices
: self
.voices
.append(user
)
121 def userdeop(self
, user
):
122 if user
in self
.ops
: self
.ops
.remove(user
)
123 def userdevoice(self
, user
):
124 if user
in self
.voices
: self
.voices
.remove(user
)
126 def __str__(self
): return self
.name
127 def __repr__(self
): return "<Channel %r>" % (self
.name
)
129 def __init__(self
, cfg
):
131 self
.trigger
= cfg
.trigger
132 if os
.name
== "posix":
134 self
.po
= select
.poll()
135 else: # f.e. os.name == "nt" (Windows)
136 self
.potype
= "select"
139 def newbot(self
, nick
, user
, bind
, authname
, authpass
, server
, port
, realname
):
140 if bind
is None: bind
= ''
141 obj
= bot
.Bot(self
, nick
, user
, bind
, authname
, authpass
, server
, port
, realname
)
142 self
.bots
[nick
.lower()] = obj
144 def newfd(self
, obj
, fileno
):
145 self
.fds
[fileno
] = obj
146 if self
.potype
== "poll":
147 self
.po
.register(fileno
, select
.POLLIN
)
148 elif self
.potype
== "select":
149 self
.fdlist
.append(fileno
)
151 def bot(self
, name
): #get Bot() by name (nick)
152 return self
.bots
[name
.lower()]
153 def fd(self
, fileno
): #get Bot() by fd/fileno
154 return self
.fds
[fileno
]
155 def randbot(self
): #get Bot() randomly
156 return self
.bots
[random
.choice(self
.bots
.keys())]
158 def user(self
, _nick
, justjoined
=False):
160 if nick
in self
.users
:
161 return self
.users
[nick
]
163 user
= self
.User(_nick
)
164 self
.users
[nick
] = user
167 self
.randbot().conn
.send("WHO %s n%%ant,2" % (nick
))
170 def channel(self
, name
): #get Channel() by name
171 if name
.lower() in self
.chans
:
172 return self
.chans
[name
.lower()]
176 def newchannel(self
, bot
, name
):
177 chan
= self
.Channel(name
.lower(), bot
)
178 self
.chans
[name
.lower()] = chan
182 if self
.potype
== "poll":
183 return [fd
for (fd
, ev
) in self
.po
.poll()]
184 elif self
.potype
== "select":
185 return select
.select(self
.fdlist
, [], [])[0]
187 def connectall(self
):
188 for bot
in self
.bots
.itervalues():
189 if bot
.conn
.state
== 0:
192 def module(self
, name
):
193 return ctlmod
.modules
[name
]
196 def hook(self
, word
, handler
):
198 self
.msghandlers
[word
].append(handler
)
200 self
.msghandlers
[word
] = [handler
]
201 def unhook(self
, word
, handler
):
202 if word
in self
.msghandlers
and handler
in self
.msghandlers
[word
]:
203 self
.msghandlers
[word
].remove(handler
)
204 def hashook(self
, word
):
205 return word
in self
.msghandlers
and len(self
.msghandlers
[word
]) != 0
206 def gethook(self
, word
):
207 return self
.msghandlers
[word
]
209 def hooknum(self
, word
, handler
):
211 self
.numhandlers
[word
].append(handler
)
213 self
.numhandlers
[word
] = [handler
]
214 def unhooknum(self
, word
, handler
):
215 if word
in self
.numhandlers
and handler
in self
.numhandlers
[word
]:
216 self
.numhandlers
[word
].remove(handler
)
217 def hasnumhook(self
, word
):
218 return word
in self
.numhandlers
and len(self
.numhandlers
[word
]) != 0
219 def getnumhook(self
, word
):
220 return self
.numhandlers
[word
]
222 def hookchan(self
, chan
, handler
):
224 self
.chanhandlers
[chan
].append(handler
)
226 self
.chanhandlers
[chan
] = [handler
]
227 def unhookchan(self
, chan
, handler
):
228 if chan
in self
.chanhandlers
and handler
in self
.chanhandlers
[chan
]:
229 self
.chanhandlers
[chan
].remove(handler
)
230 def haschanhook(self
, chan
):
231 return chan
in self
.chanhandlers
and len(self
.chanhandlers
[chan
]) != 0
232 def getchanhook(self
, chan
):
233 return self
.chanhandlers
[chan
]
236 class MyCursor(MySQLdb
.cursors
.DictCursor
):
237 def execute(self
, *args
, **kwargs
):
238 print "[SQL] [#] MyCursor.execute(self, %s, %s)" % (', '.join([repr(i
) for i
in args
]), ', '.join([str(key
)+"="+repr(kwargs
[key
]) for key
in kwargs
]))
240 super(self
.__class
__, self
).execute(*args
, **kwargs
)
241 except MySQLdb
.MySQLError
as e
:
242 print "[SQL] [!] MySQL error! %r" % (e
)
250 main
.db
= MySQLdb
.connect(host
=cfg
.dbhost
, user
=cfg
.dbuser
, passwd
=cfg
.dbpass
, db
=cfg
.dbname
, cursorclass
=MyCursor
)
255 cfg
= config
.Config('bot.config')
258 autoloads
= [mod
for mod
, yes
in cfg
.items('autoloads') if int(yes
) == 1]
259 for mod
in autoloads
:
260 print "Loading %s" % (mod
)
261 ctlmod
.load(main
, mod
)
265 if c
.execute("SELECT nick, user, bind, authname, authpass FROM bots WHERE active = 1"):
269 main
.newbot(row
['nick'], row
['user'], row
['bind'], row
['authname'], row
['authpass'], cfg
.host
, cfg
.port
, cfg
.realname
)
273 poready
= main
.poll()
274 for fileno
in poready
:
275 for line
in main
.fd(fileno
).getdata():
276 main
.fd(fileno
).parse(line
)
278 if __name__
== '__main__':