]> jfr.im git - irc/rizon/acid.git/blame - pyva/pyva/src/main/python/internets/internets.py
Internets will now send a notice instead of spamming the channel when the output...
[irc/rizon/acid.git] / pyva / pyva / src / main / python / internets / internets.py
CommitLineData
685e346e
A
1#!/usr/bin/python pseudoserver.py
2# psm_internets.py
3# module for pypseudoserver
4# written by ElChE <elche@rizon.net>, martin <martin@rizon.net>
5
6import sys
7import traceback
8import types
9import logging
10
11from istring import istring
12from datetime import datetime
13from decimal import Decimal, InvalidOperation
14
15from utils import *
16from pyva import *
17from core import *
18from plugin import *
19import mythreading as threading
20from pseudoclient import sys_antiflood, sys_auth, sys_channels, sys_log, sys_options, cmd_manager, inviteable
21
22import cmd_admin, cmd_user, erepparser, internets_users
9c9f0247 23from api import bing, calc, google, imdb, ipinfo, lastfm, quotes, urbandictionary, urls, weather, wolfram, words, steam
685e346e 24from internets_utils import *
9c9f0247 25from api.steam import SteamUser
685e346e 26
2d09c59a 27import pyva_net_rizon_acid_core_Acidictive as Acidictive
f6353b7a 28import pyva_net_rizon_acid_core_AcidCore as AcidCore
2d09c59a 29import pyva_net_rizon_acid_core_User as User
f6353b7a 30
685e346e
A
31class internets(
32 AcidPlugin,
33 inviteable.InviteablePseudoclient
34):
35 initialized = False
36
37 def bind_function(self, function):
38 func = types.MethodType(function, self, internets)
39 setattr(internets, function.__name__, func)
40 return func
41
42 def bind_admin_commands(self):
43 list = cmd_admin.get_commands()
44 self.commands_admin = []
45
46 for command in list:
47 self.commands_admin.append(
48 (command,
49 {
50 'permission': 'e',
51 'callback': self.bind_function(list[command][0]),
52 'usage': list[command][1]
53 }
54 )
55 )
56
57 def __init__(self):
58 AcidPlugin.__init__(self)
59
60 self.name = "internets"
61 self.log = logging.getLogger(__name__)
62
63 try:
41ae6aae 64 self.nick = istring(self.config.get('internets').get('nick'))
685e346e
A
65 except Exception, err:
66 self.log.exception("Error reading 'internets:nick' configuration option: %s" % err)
67 raise
68
69 try:
41ae6aae 70 self.chan = istring(self.config.get('internets').get('channel'))
685e346e
A
71 except Exception, err:
72 self.log.exception("Error reading 'internets:channel' configuration option: %s" % err)
73 raise
74
d0baaf8a
D
75 try:
76 self.output_limit = int(self.config.get('internets').get('outputlimit'))
77 except Exception, err:
78 self.log.exception("Error reading 'internets:outputlimit' configuration option: %s" % err)
79 raise
80
685e346e
A
81 self.bind_admin_commands()
82
83 def start_threads(self):
84 self.options.start()
85 self.channels.start()
86 self.users.start()
87 self.auth.start()
88 self.antiflood.start()
89
90 def start(self):
91 try:
92 AcidPlugin.start(self)
93 inviteable.InviteablePseudoclient.start(self)
94
95 self.options = sys_options.OptionManager(self)
96 self.elog = sys_log.LogManager(self)
97 self.commands_user = cmd_user.UserCommandManager()
98 except Exception, err:
99 self.log.exception('Error initializing core subsystems for internets module (%s)' % err)
100 raise
101
102 self.elog.debug('Started core subsystems.')
103
104 try:
105 self.channels = sys_channels.ChannelManager(self)
106 self.users = internets_users.InternetsUserManager(self)
107 self.auth = sys_auth.AuthManager(self)
108 self.antiflood = sys_antiflood.AntiFloodManager(self)
109 except Exception, err:
110 self.log.exception('Error initializing subsystems for internets module (%s)' % err)
111 raise
112
113 self.elog.debug('Started subsystems.')
114
115 try:
116 try:
41ae6aae 117 self.bing = bing.Bing(self.config.get('internets').get('bing_appid'))
685e346e
A
118 except Exception, err:
119 self.log.exception('Error initializing internets bing API (%s)' % err)
120 self.nsp = calc.NumericStringParser()
41ae6aae 121 self.google = google.Google(self.config.get('internets').get('key_google'))
685e346e 122 self.imdb = imdb.Imdb()
41ae6aae 123 self.ipinfo = ipinfo.IpInfo(self.config.get('internets').get('key_ipinfodb'))
124 self.lastfm = lastfm.LastFm(self.config.get('internets').get('key_lastfm'))
125 self.quotes = quotes.Quotes(self.config.get('internets').get('key_fml'))
685e346e 126 self.urbandictionary = urbandictionary.UrbanDictionary()
41ae6aae 127 self.urls = urls.Urls(self.config.get('internets').get('user_bitly'), self.config.get('internets').get('key_bitly'))
128 self.weather = weather.Weather(self.config.get('internets').get('key_openweathermap'))
129 self.wolfram = wolfram.Wolfram(self.config.get('internets').get('key_wolframalpha'))
130 self.wordnik = words.Words(self.config.get('internets').get('key_wordnik'))
131 self.steam = steam.Steam(self.config.get('internets').get('key_steam'))
685e346e
A
132 except Exception, err:
133 self.log.exception('Error initializing internets module (%s)' % err)
134 raise
135
e7697283
A
136 for channel in self.channels.list_valid():
137 self.join(channel.name)
685e346e 138
e7697283 139 self.log.debug('Joined channels.')
685e346e
A
140
141 try:
142 self.start_threads()
143 except Exception, err:
144 self.log.exception('Error starting threads for internets module (%s)' % err)
145 raise
146
147 self.initialized = True
148 self.online = True
149 self.elog.debug('Started threads.')
150 return True
151
685e346e
A
152 def stop(self):
153 if hasattr(self, 'antiflood'):
154 self.antiflood.stop()
155
156 if hasattr(self, 'auth'):
157 self.auth.stop()
158
159 if hasattr(self, 'users'):
160 if self.initialized:
161 self.users.force()
162
163 self.users.stop()
164 self.users.db_close()
165
166 if hasattr(self, 'channels'):
167 if self.initialized:
168 self.channels.force()
169
170 self.channels.stop()
171 self.channels.db_close()
172
173 if hasattr(self, 'options'):
174 if self.initialized:
175 self.options.force()
176
177 self.options.stop()
178 self.options.db_close()
179
685e346e
A
180 def errormsg(self, target, message):
181 self.msg(target, '@b@c4Error:@o %s' % message)
182
183 def usagemsg(self, target, description, examples):
184 message = '@errsep @bUsage@b %s @errsep' % description
185
186 if examples != None:
187 message += ' @bExamples@b %s @errsep' % ', '.join(examples)
188
189 self.msg(target, message)
190
191 def msg(self, target, message):
192 if message != '':
2d09c59a 193 Acidictive.privmsg(self.nick, target, format_ascii_irc(message))
685e346e
A
194
195 def multimsg(self, target, count, intro, separator, pieces, outro = ''):
196 cur = 0
197
198 while cur < len(pieces):
199 self.msg(target, intro + separator.join(pieces[cur:cur + count]) + outro)
200 cur += count
201
202 def notice(self, target, message):
203 if message != '':
2d09c59a 204 Acidictive.notice(self.nick, target, format_ascii_irc(message))
685e346e
A
205
206 def execute(self, manager, command, argument, channel, sender, userinfo):
207 full_command = '%s%s' % (command, ' %s' % argument if len(argument) else '')
208 cmd = manager.get_command(command)
209
210 if cmd == None:
211 self.msg(channel, manager.invalid)
212 self.elog.debug('Parsed command @b%s@b: invalid command.' % full_command)
213 return
214
215 if self.users.is_banned(sender) or self.antiflood.check_user(sender, command, argument):
216 user = self.users[sender]
217 message = 'You were banned by @b%s@b.' % user.ban_source
218
219 if user.ban_reason != None:
220 message += ' Reason: @b%s@b.' % user.ban_reason
221
222 if user.ban_expiry != None:
223 message += ' Expires: @b%s@b.' % datetime.fromtimestamp(user.ban_expiry)
224
225 self.notice(sender, message)
226 self.elog.debug('Parsed command @b%s@b: user is banned.' % full_command)
227 return
228
229 self.elog.command('%s%s > %s' % (sender, ':%s' % channel if channel != sender else '', full_command))
230
231 parser = erepparser.ErepublikParser(add_help_option = False, option_class = erepparser.ErepublikParserOption)
232 cmd_type = cmd[1]
233 cmd_args = cmd[3]
234
235 parser.add_option('-?', '--help', action = 'store_true')
236
237 for cmd_arg in cmd_args:
238 parser.add_option(cmd_arg[1], '--' + cmd_arg[0], **cmd_arg[3])
239
240 try:
241 (popts, pargs) = parser.parse_args(args = argument.split(' '))
242 except erepparser.ErepublikParserError, err:
243 self.msg(channel, str(err)) #TODO: Avoid str, use unicode.
244 parser.destroy()
245 self.elog.debug('Parsed command @b%s@b: invalid options.' % full_command)
246 return
247
248 if popts.help == True:
249 manager.commands['help'][0](self, manager, {}, command, channel, sender)
250 parser.destroy()
251 self.elog.debug('Parsed command @b%s@b: help intercepted.' % full_command)
252 return
253
254 opt_dict = {}
255 larg = ' '.join(pargs).strip()
256 is_offline = True
257
258 for cmd_arg in cmd_args:
259 parg = getattr(popts, cmd_arg[0])
260
261 if parg != None:
262 if len(cmd_arg) <= 4 or not (cmd_arg[4] & cmd_manager.ARG_OFFLINE):
263 is_offline = False
264
265 if len(cmd_arg) > 4 and (cmd_arg[4] & cmd_manager.ARG_YES) and larg == '':
266 self.msg(channel, 'Error: %s option requires an argument.' % cmd_arg[1])
267 parser.destroy()
268 self.elog.debug('Parsed command @b%s@b: option constraint was broken.' % full_command)
269 return
270
271 opt_dict[cmd_arg[0]] = parg
272 elif len(cmd_arg) > 4 and (cmd_arg[4] & cmd_manager.ARG_OFFLINE and cmd_arg[4] & cmd_manager.ARG_OFFLINE_REQ):
273 is_offline = False
274
275 if not self.online and ((len(pargs) > 0 and not (cmd_type & cmd_manager.ARG_OFFLINE)) or not is_offline):
276 self.notice(sender, 'The eRepublik API is offline. Please retry later.')
277 parser.destroy()
278 self.elog.debug('Parsed command @b%s@b: offline.' % full_command)
279 return
280
281 if (cmd_type & cmd_manager.ARG_YES) and (larg == None or larg == ''):
282 self.notice(sender, '@bUsage@b: %s @b%s@b' % (command, cmd[4] if len(cmd) > 4 else 'argument'))
283 else:
284 try:
285 cmd[0](self, manager, opt_dict, larg, channel, sender, userinfo)
286 except Exception, e:
287 tb = traceback.extract_tb(sys.exc_info()[2])
288 longest = 0
289
290 for entry in tb:
291 length = len(entry[2])
292
293 if length > longest:
294 longest = length
295
296 self.elog.exception('%s%s > @b%s@b: %s' % (sender, ':%s' % channel if channel != sender else '', full_command, e))
297 self.log.exception("internets error!")
298
299 for entry in tb:
300 self.elog.traceback('@b%-*s@b : %d %s' % (longest, entry[2], entry[1], entry[3]))
301
302 self.msg(channel, 'An exception occurred and has been reported to the developers. If this error persists please do not use the faulty command until it has been fixed.')
303
304 parser.destroy()
305 self.elog.debug('Parsed command @b%s@b: execution terminated.' % full_command)
306
307 def onChanModes(self, prefix, channel, modes):
308 if not self.initialized:
309 return
310
311 if not modes == '-z':
312 return
313
314 if channel in self.channels:
315 self.channels.remove(channel)
316 self.elog.request('Channel @b%s@b was dropped. Deleting it.' % channel)
317
318 def getCommands(self):
319 return self.commands_admin
320
321 def get_location(self, opts, arg, channel, sender):
322 nick = None
323 location = None
324
325 if 'nick' in opts:
326 nick = arg
327 elif arg == '':
328 nick = sender
329 else:
330 location = arg
331
332 if nick:
333 location = self.users.get(nick, 'location')
334
335 if not location:
336 if 'nick' in opts:
337 self.msg(channel, 'No location found linked to nick %s.' % arg)
338 else:
9c9f0247 339 self.msg(channel, 'No location found linked to your nick. To link one, type: @b%sregister_location <location>@b' % self.commands_user.get_prefix())
685e346e
A
340
341 return location
9c9f0247
M
342
343 def get_steamid(self, opts, arg, channel, sender):
344 """Gets the steamid from the database."""
345 nick = None
346 steamid = None
347
348 if 'nick' in opts:
349 nick = arg
350 else:
351 nick = sender
352
353 steamid = self.users.get(nick, 'steamid')
354
355 if not steamid:
356 if 'nick' in opts:
357 self.msg(channel, 'No steamid found linked to nick %s.' % arg)
358 return
359 else:
360 self.msg(channel, 'No steamid found linked to your nick. To link one, type: @b%sregister_steam <steamid>@b' % self.commands_user.get_prefix())
361 return
362 else:
363 return SteamUser(nick, steamid)