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)