diff --git a/bugzilla.py b/bugzilla.py index de1dddd87e..bf152e9856 100644 --- a/bugzilla.py +++ b/bugzilla.py @@ -9,6 +9,7 @@ from lxml import etree import re from willie import web +from willie.module import rule import urllib import urllib2 @@ -28,27 +29,30 @@ def configure(config): 'Domain:') -def setup(willie): +def setup(bot): regexes = [] - if not (willie.config.has_option('bugzilla', 'domains') - and willie.config.bugzilla.get_list('domains')): + if not (bot.config.has_option('bugzilla', 'domains') + and bot.config.bugzilla.get_list('domains')): return - if not willie.memory.contains('url_callbacks'): - willie.memory['url_callbacks'] = {} + if not bot.memory.contains('url_callbacks'): + bot.memory['url_callbacks'] = {} - domains = '|'.join(willie.config.bugzilla.get_list('domains')) + domains = '|'.join(bot.config.bugzilla.get_list('domains')) regex = re.compile((r'https?://(%s)' '(/show_bug.cgi\?\S*?)' '(id=\d+)') % domains) - willie.memory['url_callbacks'][regex] = show_bug + bot.memory['url_callbacks'][regex] = show_bug -def show_bug(willie, trigger, match=None): +@rule(r'.*https?://(\S+?)' + '(/show_bug.cgi\?\S*?)' + '(id=\d+).*') +def show_bug(bot, trigger, match=None): """Show information about a Bugzilla bug.""" match = match or trigger domain = match.group(1) - if domain not in willie.config.bugzilla.get_list('domains'): + if domain not in bot.config.bugzilla.get_list('domains'): return url = 'https://%s%sctype=xml&%s' % match.groups() data = web.get(url) @@ -70,7 +74,4 @@ def show_bug(willie, trigger, match=None): (bug.find('priority').text + ' ' + bug.find('bug_severity').text), status, bug.find('assigned_to').text, bug.find('creation_ts').text, bug.find('delta_ts').text) - willie.say(message) -show_bug.rule = (r'.*https?://(\S+?)' - '(/show_bug.cgi\?\S*?)' - '(id=\d+).*') + bot.say(message) diff --git a/calc.py b/calc.py index 7693370cc2..c52dd848d0 100644 --- a/calc.py +++ b/calc.py @@ -8,7 +8,8 @@ """ import re -import willie.web as web +from willie import web +from willie.module import command, commands, example from socket import timeout import string import HTMLParser @@ -35,39 +36,41 @@ def calculate(q): return 'Sorry, no result.' -def c(willie, trigger): +@commands('c', 'calc') +@example('.c 5 + 3') +def c(bot, trigger): """Google calculator.""" if not trigger.group(2): - return willie.reply("Nothing to calculate.") + return bot.reply("Nothing to calculate.") result = calculate(trigger.group(2)) - willie.reply(result) -c.commands = ['c', 'calc'] -c.example = '.c 5 + 3' + bot.reply(result) -def py(willie, trigger): +@command('py') +@example('.py len([1,2,3])') +def py(bot, trigger): """Evaluate a Python expression.""" query = trigger.group(2) uri = 'http://tumbolia.appspot.com/py/' answer = web.get(uri + web.quote(query)) if answer: - willie.say(answer) + bot.say(answer) else: - willie.reply('Sorry, no result.') -py.commands = ['py'] -py.example = '.py len([1,2,3])' + bot.reply('Sorry, no result.') -def wa(willie, trigger): +@commands('wa', 'wolfram') +@example('.wa circumference of the sun * pi') +def wa(bot, trigger): """Wolfram Alpha calculator""" if not trigger.group(2): - return willie.reply("No search term.") + return bot.reply("No search term.") query = trigger.group(2) uri = 'http://tumbolia.appspot.com/wa/' try: answer = web.get(uri + web.quote(query.replace('+', '%2B')), 45) except timeout as e: - return willie.say('[WOLFRAM ERROR] Request timed out') + return bot.say('[WOLFRAM ERROR] Request timed out') if answer: answer = answer.decode('string_escape') answer = HTMLParser.HTMLParser().unescape(answer) @@ -81,17 +84,11 @@ def wa(willie, trigger): answer = answer.replace('\:' + char_code, char) waOutputArray = string.split(answer, ";") if(len(waOutputArray) < 2): - willie.say('[WOLFRAM ERROR]' + answer) + bot.say('[WOLFRAM ERROR]' + answer) else: - willie.say('[WOLFRAM] ' + waOutputArray[0] + " = " + bot.say('[WOLFRAM] ' + waOutputArray[0] + " = " + waOutputArray[1]) waOutputArray = [] else: - willie.reply('Sorry, no result.') -wa.commands = ['wa', 'wolfram'] -wa.example = '.wa circumference of the sun * pi' -wa.commands = ['wa'] - -if __name__ == '__main__': - print __doc__.strip() + bot.reply('Sorry, no result.') diff --git a/oblique.py b/oblique.py deleted file mode 100644 index 4fd8547678..0000000000 --- a/oblique.py +++ /dev/null @@ -1,119 +0,0 @@ -""" -oblique.py - Web Services Interface -Copyright 2008-9, Sean B. Palmer, inamidst.com -Licensed under the Eiffel Forum License 2. - -http://willie.dftba.net -""" - -import re, urllib -import willie.web as web - -definitions = 'https://github.com/nslater/oblique/wiki' - -r_item = re.compile(r'(?i)
  • (.*?)
  • ') -r_tag = re.compile(r'<[^>]+>') - -def mappings(uri): - result = {} - bytes = web.get(uri) - for item in r_item.findall(bytes): - item = r_tag.sub('', item).strip(' \t\r\n') - if not ' ' in item: continue - - command, template = item.split(' ', 1) - if not command.isalnum(): continue - if not template.startswith('http://'): continue - result[command] = template.replace('&', '&') - return result - -def service(willie, trigger, command, args): - t = o.services[command] - template = t.replace('${args}', urllib.quote(args.encode('utf-8'), '')) - template = template.replace('${nick}', urllib.quote(trigger.nick, '')) - uri = template.replace('${sender}', urllib.quote(trigger.sender, '')) - - info = web.head(uri) - if isinstance(info, list): - info = info[0] - if not 'text/plain' in info.get('content-type', '').lower(): - return willie.reply("Sorry, the service didn't respond in plain text.") - bytes = web.get(uri) - lines = bytes.splitlines() - if not lines: - return willie.reply("Sorry, the service didn't respond any output.") - willie.say(lines[0][:350]) - -def refresh(willie): - if hasattr(willie.config, 'services'): - services = willie.config.services - else: services = definitions - - old = o.services - o.serviceURI = services - o.services = mappings(o.serviceURI) - return len(o.services), set(o.services) - set(old) - -def o(willie, trigger): - """Call a webservice.""" - if trigger.group(1) == 'urban': - text = 'ud '+ trigger.group(2) - else: - text = trigger.group(2) - - if (not o.services) or (text == 'refresh'): - length, added = refresh(willie) - if text == 'refresh': - msg = 'Okay, found %s services.' % length - if added: - msg += ' Added: ' + ', '.join(sorted(added)[:5]) - if len(added) > 5: msg += ', &c.' - return willie.reply(msg) - - if not text: - return willie.reply('Try %s for details.' % o.serviceURI) - - if ' ' in text: - command, args = text.split(' ', 1) - else: command, args = text, '' - command = command.lower() - - if command == 'service': - msg = o.services.get(args, 'No such service!') - return willie.reply(msg) - - if not o.services.has_key(command): - return willie.reply('Service not found in %s' % o.serviceURI) - - if hasattr(willie.config, 'external'): - default = willie.config.external.get('*') - manifest = willie.config.external.get(trigger.sender, default) - if manifest: - commands = set(manifest) - if (command not in commands) and (manifest[0] != '!'): - return willie.reply('Sorry, %s is not whitelisted' % command) - elif (command in commands) and (manifest[0] == '!'): - return willie.reply('Sorry, %s is blacklisted' % command) - service(willie, trigger, command, args) -o.commands = ['o','urban'] -o.example = '.o servicename arg1 arg2 arg3' -o.services = {} -o.serviceURI = None - -def snippet(willie, trigger): - if not o.services: - refresh(willie) - - search = urllib.quote(trigger.group(2).encode('utf-8')) - py = "BeautifulSoup.BeautifulSoup(re.sub('<.*?>|(?<= ) +', '', " + \ - "''.join(chr(ord(c)) for c in " + \ - "eval(urllib.urlopen('http://ajax.googleapis.com/ajax/serv" + \ - "ices/search/web?v=1.0&q=" + search + "').read()" + \ - ".replace('null', 'None'))['responseData']['resul" + \ - "ts'][0]['content'].decode('unicode-escape')).replace(" + \ - "'"', '\x22')), convertEntities=True)" - service(willie, trigger, 'py', py) -snippet.commands = ['snippet'] - -if __name__ == '__main__': - print __doc__.strip() diff --git a/radio.py b/radio.py index 9623b71559..0b7947d7c6 100644 --- a/radio.py +++ b/radio.py @@ -9,8 +9,10 @@ from time import sleep from xml.dom.minidom import parseString import willie.web as web +from willie.module import command import xml.dom.minidom + def configure(config): """ | [radio] | example | purpose | @@ -23,83 +25,88 @@ def configure(config): config.interactive_add('radio', 'url', 'URL to the ShoutCAST administration page', 'http://127.0.0.1:8000/') config.interactive_add('radio', 'sid', 'Stream ID (only required for multi-stream servers.)', '1') -radioURL = '' # Set once, after the first .radio request. +radioURL = '' # Set once, after the first .radio request. checkSongs = 0 current_song = '' -def getAPI(willie, trigger): + +def getAPI(bot, trigger): #contact the 'heavyweight' XML API try: raw = web.get(radioURL % 'stats') except Exception as e: - willie.say('The radio is not responding to the stats request.') + bot.say('The radio is not responding to the stats request.') return 0 - + #Parse the XML XML = parseString(raw).documentElement status = XML.getElementsByTagName('STREAMSTATUS')[0].firstChild.nodeValue if status == '0': - willie.say('The radio is currently offline.') + bot.say('The radio is currently offline.') return 0 status = 'Online' servername = XML.getElementsByTagName('SERVERTITLE')[0].firstChild.nodeValue curlist = XML.getElementsByTagName('CURRENTLISTENERS')[0].firstChild.nodeValue maxlist = XML.getElementsByTagName('MAXLISTENERS')[0].firstChild.nodeValue - + #Garbage disposal XML.unlink() #print results - willie.say('[%s]Status: %s. Listeners: %s/%s.' % (servername, status, curlist, maxlist)) + bot.say('[%s]Status: %s. Listeners: %s/%s.' % (servername, status, curlist, maxlist)) return 1 -def currentSong(willie, trigger): + +def currentSong(bot, trigger): # This function uses the PLAINTEXT API to get the current song only. try: song = web.get(radioURL % 'currentsong') except Exception as e: - willie.say('The radio is not responding to the song request.') - willie.debug('radio', 'Exception while trying to get current song: %s' % e, 'warning') + bot.say('The radio is not responding to the song request.') + bot.debug('radio', 'Exception while trying to get current song: %s' % e, 'warning') if song: - willie.say('Now playing: '+song) + bot.say('Now playing: ' + song) else: - willie.say('The radio is currently offline.') + bot.say('The radio is currently offline.') -def nextSong(willie, trigger): + +def nextSong(bot, trigger): # This function uses the PLAINTEXT API to get the next song only. try: song = web.get(radioURL % 'nextsong') except Exception as e: - willie.say('The radio is not responding to the song request.') - willie.debug('radio', 'Exception while trying to get next song: %s' % e, 'warning') + bot.say('The radio is not responding to the song request.') + bot.debug('radio', 'Exception while trying to get next song: %s' % e, 'warning') if song: - willie.say('Next up: '+song) + bot.say('Next up: ' + song) else: - willie.say('No songs are queued up.') + bot.say('No songs are queued up.') + -def radio(willie, trigger): +@command('radio') +def radio(bot, trigger): """ Radio functions, valid parameters: on, off, song, now, next, soon, stats. """ global checkSongs, current_song, radioURL if not radioURL: - if not hasattr(willie.config, 'radio'): - willie.say('Radio module not configured') + if not hasattr(bot.config, 'radio'): + bot.say('Radio module not configured') return else: - radioURL = willie.config.radio.url+'%s?sid='+willie.config.radio.sid + radioURL = bot.config.radio.url + '%s?sid=' + bot.config.radio.sid try: args = trigger.group(2).lower().split(' ') except AttributeError: - willie.say('Usage: .radio (next|now|off|on|song|soon|stats)') + bot.say('Usage: .radio (next|now|off|on|song|soon|stats)') return if args[0] == 'on': if not trigger.isop: return if checkSongs != 0: - return willie.reply('Radio data checking is already on.') - if not getAPI(willie, trigger): + return bot.reply('Radio data checking is already on.') + if not getAPI(bot, trigger): checkSongs = 0 - return willie.say('Radio data checking not enabled.') + return bot.say('Radio data checking not enabled.') checkSongs = 10 while checkSongs: last = current_song @@ -109,37 +116,32 @@ def radio(willie, trigger): except Exception as e: checkSongs -= 1 if checkSongs == 0: - willie.debug('radio', 'Exception while trying to get periodic radio data: %s' % e, 'warning') - willie.say('The radio is not responding to the song request.') - willie.say('Turning off radio data checking.') + bot.debug('radio', 'Exception while trying to get periodic radio data: %s' % e, 'warning') + bot.say('The radio is not responding to the song request.') + bot.say('Turning off radio data checking.') break if not current_song == last: if not current_song: csong = 'The radio is currently offline.' else: - csong = 'Now Playing: '+current_song + csong = 'Now Playing: ' + current_song if nextsong and current_song: - willie.say(csong+' | Coming Up: '+nextsong) + bot.say(csong + ' | Coming Up: ' + nextsong) else: - willie.say(csong) + bot.say(csong) sleep(5) elif args[0] == 'off': if not trigger.isop: - return; + return if checkSongs == 0: - willie.reply('Radio data checking is already off.') + bot.reply('Radio data checking is already off.') return checkSongs = 0 current_song = '' - willie.reply('Turning off radio data checking.') + bot.reply('Turning off radio data checking.') elif args[0] == 'song' or args[0] == 'now': - currentSong(willie, trigger) + currentSong(bot, trigger) elif args[0] == 'next' or args[0] == 'soon': - nextSong(willie, trigger) + nextSong(bot, trigger) elif args[0] == 'stats': - getAPI(willie, trigger) -radio.commands = ['radio'] -radio.priority = 'medium' - -if __name__ == '__main__': - print __doc__.strip() + getAPI(bot, trigger) diff --git a/search.py b/search.py index dc3cba41d3..e28743a1d0 100644 --- a/search.py +++ b/search.py @@ -50,33 +50,31 @@ def formatnumber(n): return ''.join(parts) -def g(willie, trigger): +def g(bot, trigger): """Queries Google for the specified input.""" query = trigger.group(2) if not query: - return willie.reply('.g what?') + return bot.reply('.g what?') uri = google_search(query) if uri: - willie.reply(uri) - if not hasattr(willie.bot, 'last_seen_uri'): - willie.bot.last_seen_uri = {} - willie.bot.last_seen_uri[trigger.sender] = uri + bot.reply(uri) + bot.memory['last_seen_url'][trigger.sender] = uri elif uri is False: - willie.reply("Problem getting data from Google.") + bot.reply("Problem getting data from Google.") else: - willie.reply("No results found for '%s'." % query) + bot.reply("No results found for '%s'." % query) g.commands = ['g', 'google'] g.priority = 'high' g.example = '.g swhack' -def gc(willie, trigger): +def gc(bot, trigger): """Returns the number of Google results for the specified input.""" query = trigger.group(2) if not query: - return willie.reply('.gc what?') + return bot.reply('.gc what?') num = formatnumber(google_count(query)) - willie.say(query + ': ' + num) + bot.say(query + ': ' + num) gc.commands = ['gc'] gc.priority = 'high' gc.example = '.gc extrapolate' @@ -86,13 +84,13 @@ def gc(willie, trigger): ) -def gcs(willie, trigger): +def gcs(bot, trigger): """Compare the number of Google search results""" if not trigger.group(2): - return willie.reply("Nothing to compare.") + return bot.reply("Nothing to compare.") queries = r_query.findall(trigger.group(2)) if len(queries) > 6: - return willie.reply('Sorry, can only compare up to six things.') + return bot.reply('Sorry, can only compare up to six things.') results = [] for i, query in enumerate(queries): @@ -106,7 +104,7 @@ def gcs(willie, trigger): results = [(term, n) for (n, term) in reversed(sorted(results))] reply = ', '.join('%s (%s)' % (t, formatnumber(n)) for (t, n) in results) - willie.say(reply) + bot.say(reply) gcs.commands = ['gcs', 'comp'] gcs.example = '.gcs foo bar' @@ -121,32 +119,8 @@ def bing_search(query, lang='en-GB'): if m: return m.group(1) - -def bing(willie, trigger): - """Queries Bing for the specified input.""" - query = trigger.group(2) - if query.startswith(':'): - lang, query = query.split(' ', 1) - lang = lang[1:] - else: - lang = 'en-GB' - if not query: - return willie.reply('.bing what?') - - uri = bing_search(query, lang) - if uri: - willie.reply(uri) - if not hasattr(willie.bot, 'last_seen_uri'): - willie.bot.last_seen_uri = {} - willie.bot.last_seen_uri[trigger.sender] = uri - else: - willie.reply("No results found for '%s'." % query) -bing.commands = ['bing'] -bing.example = '.bing swhack' - r_duck = re.compile(r'nofollow" class="[^"]+" href="(.*?)">') - def duck_search(query): query = query.replace('!', '') query = web.quote(query) @@ -171,35 +145,33 @@ def duck_api(query): return None -def duck(willie, trigger): +def duck(bot, trigger): """Queries Duck Duck Go for the specified input.""" query = trigger.group(2) if not query: - return willie.reply('.ddg what?') + return bot.reply('.ddg what?') #If the API gives us something, say it and stop result = duck_api(query) if result: - willie.reply(result) + bot.reply(result) return #Otherwise, look it up on the HTMl version uri = duck_search(query) if uri: - willie.reply(uri) - if not hasattr(willie.bot, 'last_seen_uri'): - willie.bot.last_seen_uri = {} - willie.bot.last_seen_uri[trigger.sender] = uri + bot.reply(uri) + bot.memory['last_seen_url'][trigger.sender] = uri else: - willie.reply("No results found for '%s'." % query) + bot.reply("No results found for '%s'." % query) duck.commands = ['duck', 'ddg'] -def search(willie, trigger): +def search(bot, trigger): """Searches Google, Bing, and Duck Duck Go.""" if not trigger.group(2): - return willie.reply('.search for what?') + return bot.reply('.search for what?') query = trigger.group(2) gu = google_search(query) or '-' bu = bing_search(query) or '-' @@ -222,22 +194,22 @@ def search(willie, trigger): du = '(extremely long link)' result = '%s (g), %s (b), %s (d)' % (gu, bu, du) - willie.reply(result) + bot.reply(result) search.commands = ['search'] search.example = '.search nerdfighter' -def suggest(willie, trigger): +def suggest(bot, trigger): """Suggest terms starting with given input""" if not trigger.group(2): - return willie.reply("No query term.") + return bot.reply("No query term.") query = trigger.group(2) uri = 'http://websitedev.de/temp-bin/suggest.pl?q=' answer = web.get(uri + web.quote(query).replace('+', '%2B')) if answer: - willie.say(answer) + bot.say(answer) else: - willie.reply('Sorry, no result.') + bot.reply('Sorry, no result.') suggest.commands = ['suggest'] if __name__ == '__main__': diff --git a/seen.py b/seen.py index 69821aeb5b..497c57bab5 100644 --- a/seen.py +++ b/seen.py @@ -12,8 +12,10 @@ import datetime import pytz from willie.tools import Ddict, Nick +from willie.module import command, rule, priority + +seen_dict = Ddict(dict) -seen_dict=Ddict(dict) def get_user_time(willie, nick): tz = 'UTC' @@ -25,13 +27,15 @@ def get_user_time(willie, nick): tz = 'UTC' return (pytz.timezone(tz.strip()), tformat or '%Y-%m-%d %H:%M:%S %Z') + +@command('seen') def seen(willie, trigger): """Reports when and where the user was last seen.""" if not trigger.group(2): willie.say(".seen - Reports when was last seen.") return nick = Nick(trigger.group(2).strip()) - if seen_dict.has_key(nick): + if nick in seen_dict: timestamp = seen_dict[nick]['timestamp'] channel = seen_dict[nick]['channel'] message = seen_dict[nick]['message'] @@ -44,17 +48,13 @@ def seen(willie, trigger): willie.say(str(trigger.nick) + ': ' + msg) else: willie.say("Sorry, I haven't seen %s around." % nick) -seen.commands = ['seen'] + +@rule('(.*)') +@priority('low') def note(willie, trigger): if trigger.sender.startswith('#'): nick = Nick(trigger.nick) seen_dict[nick]['timestamp'] = time.time() seen_dict[nick]['channel'] = trigger.sender seen_dict[nick]['message'] = trigger - -note.rule = r'(.*)' -note.priority = 'low' - -if __name__ == '__main__': - print __doc__.strip() diff --git a/units.py b/units.py index 3d7e1b87f5..c6a5883c6a 100644 --- a/units.py +++ b/units.py @@ -66,7 +66,7 @@ def distance(bot, trigger): meter = numeric / 39.370 elif unit in ("centimeters","centimeter","cm"): meter = numeric / 100 - elif unit in ("feet","foot","ft": + elif unit in ("feet","foot","ft"): meter = numeric / 3.2808 elif unit in ("yards", "yard", "yd"): meter = numeric / (3.2808 * 3) diff --git a/url.py b/url.py index 78d44545b9..0c377bf83f 100644 --- a/url.py +++ b/url.py @@ -10,6 +10,7 @@ import re from htmlentitydefs import name2codepoint import willie.web as web +from willie.module import command, rule import urllib2 import urlparse @@ -74,6 +75,7 @@ def setup(willie): (exclusion_char)) +@command('title') def title_command(willie, trigger): """ Show the title or URL information for the given URL, or the last URL seen @@ -93,9 +95,11 @@ def title_command(willie, trigger): urls = re.findall(url_finder, trigger) results = process_urls(willie, trigger, urls) -title_command.commands = ['title'] + for result in results[:4]: + message = '[ %s ] - %s' % tuple(result) +@rule('(?u).*(https?://\S+).*') def title_auto(willie, trigger): """ Automatically show titles for URLs. For shortened URLs/redirects, find @@ -113,7 +117,6 @@ def title_auto(willie, trigger): message = '[ %s ] - %s' % tuple(result) if message != trigger: willie.say(message) -title_auto.rule = '(?u).*(https?://\S+).*' def process_urls(willie, trigger, urls): @@ -155,7 +158,7 @@ def follow_redirects(url): there's a problem. """ try: - connection = urllib2.urlopen(url) + connection = web.get_urllib_object(url, 60) url = connection.geturl() or url connection.close() except: @@ -183,7 +186,22 @@ def check_callbacks(willie, trigger, url, run=True): def find_title(url): """Return the title for the given URL.""" - content = web.get(url) + content, headers = web.get(url, return_headers=True) + content_type = headers.get('Content-Type') or '' + encoding_match = re.match('.*?charset *= *(\S+)', content_type) + # If they gave us something else instead, try that + if encoding_match: + try: + content = content.decode(encoding_match.group(1)) + except: + encoding_match = None + # They didn't tell us what they gave us, so go with UTF-8 or fail silently. + if not encoding_match: + try: + content = content.decode('utf-8') + except: + return + # Some cleanup that I don't really grok, but was in the original, so # we'll keep it (with the compiled regexes made global) for now. content = title_tag_data.sub(r'<\1title>', content) diff --git a/version.py b/version.py index b8a72bfa47..0276170399 100644 --- a/version.py +++ b/version.py @@ -8,7 +8,7 @@ from datetime import datetime from subprocess import * -from willie import __version__ +import willie def git_info(): @@ -20,49 +20,49 @@ def git_info(): return commit, author, date -def version(willie, trigger): +@willie.module.command('version') +def version(bot, trigger): """Display the latest commit version, if Willie is running in a git repo.""" commit, author, date = git_info() - + if not commit.strip(): - willie.reply("Willie v. " + __version__) + bot.reply("Willie v. " + willie.__version__) return - willie.say(str(trigger.nick) + ": Willie v. %s at commit:" % __version__) - willie.say(" " + commit) - willie.say(" " + author) - willie.say(" " + date) -version.commands = ['version'] + bot.say(str(trigger.nick) + ": Willie v. %s at commit:" % willie.__version__) + bot.say(" " + commit) + bot.say(" " + author) + bot.say(" " + date) -def ctcp_version(willie, trigger): - willie.write(('NOTICE', trigger.nick), - '\x01VERSION Willie IRC Bot version %s\x01' % __version__) -ctcp_version.rule = '\x01VERSION\x01' -ctcp_version.rate = 20 +@willie.module.rule('\x01VERSION\x01') +@willie.module.rate(20) +def ctcp_version(bot, trigger): + bot.write(('NOTICE', trigger.nick), + '\x01VERSION Willie IRC Bot version %s\x01' % willie.__version__) -def ctcp_source(willie, trigger): - willie.write(('NOTICE', trigger.nick), - '\x01SOURCE https://github.com/Embolalia/willie/\x01') -ctcp_source.rule = '\x01SOURCE\x01' -ctcp_source.rate = 20 +@willie.module.rule('\x01SOURCE\x01') +@willie.module.rate(20) +def ctcp_source(bot, trigger): + bot.write(('NOTICE', trigger.nick), + '\x01SOURCE https://github.com/Embolalia/willie/\x01') -def ctcp_ping(willie, trigger): +@willie.module.rule('\x01PING\s(.*)\x01') +@willie.module.rate(10) +def ctcp_ping(bot, trigger): text = trigger.group() text = text.replace("PING ", "") text = text.replace("\x01", "") - willie.write(('NOTICE', trigger.nick), - '\x01PING {0}\x01'.format(text)) -ctcp_ping.rule = '\x01PING\s(.*)\x01' -ctcp_ping.rate = 10 + bot.write(('NOTICE', trigger.nick), + '\x01PING {0}\x01'.format(text)) -def ctcp_time(willie, trigger): +@willie.module.rule('\x01TIME\x01') +@willie.module.rate(20) +def ctcp_time(bot, trigger): dt = datetime.now() current_time = dt.strftime("%A, %d. %B %Y %I:%M%p") - willie.write(('NOTICE', trigger.nick), - '\x01TIME {0}\x01'.format(current_time)) -ctcp_time.rule = '\x01TIME\x01' -ctcp_time.rate = 20 + bot.write(('NOTICE', trigger.nick), + '\x01TIME {0}\x01'.format(current_time)) diff --git a/xkcd.py b/xkcd.py index 610880aaff..9b413bdd7e 100644 --- a/xkcd.py +++ b/xkcd.py @@ -10,11 +10,14 @@ import random from willie.modules.search import google_search from willie.modules.url import find_title +from willie.module import command import urllib2 from lxml import etree import re -def xkcd(willie, trigger): + +@command('xkcd') +def xkcd(bot, trigger): """ .xkcd - Finds an xkcd comic strip. Takes one of 3 inputs: If no input is provided it will return a random comic @@ -28,39 +31,37 @@ def xkcd(willie, trigger): max_int = int(newest.split("/")[-3]) # if no input is given (pre - lior's edits code) - if not trigger.group(2): # get rand comic + if not trigger.group(2): # get rand comic random.seed() - website = "http://xkcd.com/%d/" % random.randint(0,max_int+1) + website = "http://xkcd.com/%d/" % random.randint(0, max_int + 1) else: query = trigger.group(2).strip() # numeric input! get that comic number if it exists if (query.isdigit()): if (int(query) > max_int): - willie.say("Sorry, comic #" + query + " hasn't been posted yet. The last comic was #%d" % max_int) + bot.say("Sorry, comic #" + query + " hasn't been posted yet. The last comic was #%d" % max_int) return - else: website = "http://xkcd.com/" + query - + else: + website = "http://xkcd.com/" + query + # non-numeric input! code lifted from search.g else: - if (query.lower() == "latest" or query.lower() == "newest"): # special commands + if (query.lower() == "latest" or query.lower() == "newest"): # special commands website = "https://xkcd.com/" - else: # just google + else: # just google try: query = query.encode('utf-8') except: pass - website = google_search("site:xkcd.com "+ query) - chkForum = re.match(re.compile(r'.*?([0-9].*?):.*'), find_title(website)) # regex for comic specific forum threads + website = google_search("site:xkcd.com " + query) + chkForum = re.match(re.compile(r'.*?([0-9].*?):.*'), find_title(website)) # regex for comic specific forum threads if (chkForum): website = "http://xkcd.com/" + chkForum.groups()[0].lstrip('0') - if website: # format and say result + if website: # format and say result website += ' [' + find_title(website)[6:] + ']' - willie.say(website) - elif website is False: willie.say("Problem getting data from Google.") - else: willie.say("No results found for '%s'." % query) -xkcd.commands = ['xkcd'] -xkcd.priority = 'low' - -if __name__ == '__main__': - print __doc__.strip() + bot.say(website) + elif website is False: + bot.say("Problem getting data from Google.") + else: + bot.say("No results found for '%s'." % query)