summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
authorAlexander Sulfrian <alexander@sulfrian.net>2013-07-25 19:26:52 +0200
committerAlexander Sulfrian <alexander@sulfrian.net>2015-12-03 03:29:37 +0100
commitf3b86ed2d5bce85b3b9c27eb949cd88cf7d526bc (patch)
treea187725f5ec7f1c67d2b9a471b4000ad40a16b04 /modules
parent4b905606692a2f147946505abe6ade1c241d1000 (diff)
downloadbot-f3b86ed2d5bce85b3b9c27eb949cd88cf7d526bc.tar.gz
bot-f3b86ed2d5bce85b3b9c27eb949cd88cf7d526bc.tar.bz2
bot-f3b86ed2d5bce85b3b9c27eb949cd88cf7d526bc.zip
fix indentation and trailing whitespaces
Diffstat (limited to 'modules')
-rwxr-xr-xmodules/admin.py74
-rwxr-xr-xmodules/calc.py160
-rwxr-xr-xmodules/clock.py494
-rwxr-xr-xmodules/codepoints.py230
-rwxr-xr-xmodules/etymology.py160
-rwxr-xr-xmodules/head.py322
-rwxr-xr-xmodules/info.py118
-rwxr-xr-xmodules/oblique.py190
-rwxr-xr-xmodules/ping.py16
-rwxr-xr-xmodules/reload.py76
-rwxr-xr-xmodules/remind.py292
-rwxr-xr-xmodules/search.py414
-rwxr-xr-xmodules/seen.py68
-rwxr-xr-xmodules/startup.py92
-rwxr-xr-xmodules/tell.py250
-rwxr-xr-xmodules/translate.py206
-rwxr-xr-xmodules/twitter.py106
-rwxr-xr-xmodules/validate.py58
-rwxr-xr-xmodules/weather.py786
-rwxr-xr-xmodules/wikipedia.py306
-rwxr-xr-xmodules/wiktionary.py140
21 files changed, 2279 insertions, 2279 deletions
diff --git a/modules/admin.py b/modules/admin.py
index b42822a..93f8448 100755
--- a/modules/admin.py
+++ b/modules/admin.py
@@ -7,57 +7,57 @@ Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/
"""
-def join(phenny, input):
- """Join the specified channel. This is an admin-only command."""
- # Can only be done in privmsg by an admin
- if input.sender.startswith('#'): return
- if input.admin:
- channel, key = input.group(1), input.group(2)
- if not key:
- phenny.write(['JOIN'], channel)
- else: phenny.write(['JOIN', channel, key])
+def join(phenny, input):
+ """Join the specified channel. This is an admin-only command."""
+ # Can only be done in privmsg by an admin
+ if input.sender.startswith('#'): return
+ if input.admin:
+ channel, key = input.group(1), input.group(2)
+ if not key:
+ phenny.write(['JOIN'], channel)
+ else: phenny.write(['JOIN', channel, key])
join.rule = r'\.join (#\S+)(?: *(\S+))?'
join.priority = 'low'
join.example = '.join #example or .join #example key'
-def part(phenny, input):
- """Part the specified channel. This is an admin-only command."""
- # Can only be done in privmsg by an admin
- if input.sender.startswith('#'): return
- if input.admin:
- phenny.write(['PART'], input.group(2))
+def part(phenny, input):
+ """Part the specified channel. This is an admin-only command."""
+ # Can only be done in privmsg by an admin
+ if input.sender.startswith('#'): return
+ if input.admin:
+ phenny.write(['PART'], input.group(2))
part.commands = ['part']
part.priority = 'low'
part.example = '.part #example'
-def quit(phenny, input):
- """Quit from the server. This is an owner-only command."""
- # Can only be done in privmsg by the owner
- if input.sender.startswith('#'): return
- if input.owner:
- phenny.write(['QUIT'])
- __import__('os')._exit(0)
+def quit(phenny, input):
+ """Quit from the server. This is an owner-only command."""
+ # Can only be done in privmsg by the owner
+ if input.sender.startswith('#'): return
+ if input.owner:
+ phenny.write(['QUIT'])
+ __import__('os')._exit(0)
quit.commands = ['quit']
quit.priority = 'low'
-def msg(phenny, input):
- # Can only be done in privmsg by an admin
- if input.sender.startswith('#'): return
- a, b = input.group(2), input.group(3)
- if (not a) or (not b): return
- if input.admin:
- phenny.msg(a, b)
+def msg(phenny, input):
+ # Can only be done in privmsg by an admin
+ if input.sender.startswith('#'): return
+ a, b = input.group(2), input.group(3)
+ if (not a) or (not b): return
+ if input.admin:
+ phenny.msg(a, b)
msg.rule = (['msg'], r'(#?\S+) (.+)')
msg.priority = 'low'
-def me(phenny, input):
- # Can only be done in privmsg by an admin
- if input.sender.startswith('#'): return
- if input.admin:
- msg = '\x01ACTION %s\x01' % input.group(3)
- phenny.msg(input.group(2) or input.sender, msg)
+def me(phenny, input):
+ # Can only be done in privmsg by an admin
+ if input.sender.startswith('#'): return
+ if input.admin:
+ msg = '\x01ACTION %s\x01' % input.group(3)
+ phenny.msg(input.group(2) or input.sender, msg)
me.rule = (['me'], r'(#?\S+) (.+)')
me.priority = 'low'
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/calc.py b/modules/calc.py
index 9a5b187..b58b730 100755
--- a/modules/calc.py
+++ b/modules/calc.py
@@ -15,101 +15,101 @@ r_result = re.compile(r'(?i)<A NAME=results>(.*?)</A>')
r_tag = re.compile(r'<\S+.*?>')
subs = [
- (' in ', ' -> '),
- (' over ', ' / '),
- (u'£', 'GBP '),
- (u'€', 'EUR '),
- ('\$', 'USD '),
- (r'\bKB\b', 'kilobytes'),
- (r'\bMB\b', 'megabytes'),
- (r'\bGB\b', 'kilobytes'),
- ('kbps', '(kilobits / second)'),
- ('mbps', '(megabits / second)')
+ (' in ', ' -> '),
+ (' over ', ' / '),
+ (u'£', 'GBP '),
+ (u'€', 'EUR '),
+ ('\$', 'USD '),
+ (r'\bKB\b', 'kilobytes'),
+ (r'\bMB\b', 'megabytes'),
+ (r'\bGB\b', 'kilobytes'),
+ ('kbps', '(kilobits / second)'),
+ ('mbps', '(megabits / second)')
]
-def calc(phenny, input):
- """Use the Frink online calculator."""
- q = input.group(2)
- if not q:
- return phenny.say('0?')
+def calc(phenny, input):
+ """Use the Frink online calculator."""
+ q = input.group(2)
+ if not q:
+ return phenny.say('0?')
- query = q[:]
- for a, b in subs:
- query = re.sub(a, b, query)
- query = query.rstrip(' \t')
+ query = q[:]
+ for a, b in subs:
+ query = re.sub(a, b, query)
+ query = query.rstrip(' \t')
- precision = 5
- if query[-3:] in ('GBP', 'USD', 'EUR', 'NOK'):
- precision = 2
- query = web.urllib.quote(query.encode('utf-8'))
+ precision = 5
+ if query[-3:] in ('GBP', 'USD', 'EUR', 'NOK'):
+ precision = 2
+ query = web.urllib.quote(query.encode('utf-8'))
- uri = 'http://futureboy.us/fsp/frink.fsp?fromVal='
- bytes = web.get(uri + query)
- m = r_result.search(bytes)
- if m:
- result = m.group(1)
- result = r_tag.sub('', result) # strip span.warning tags
- result = result.replace('&gt;', '>')
- result = result.replace('(undefined symbol)', '(?) ')
+ uri = 'http://futureboy.us/fsp/frink.fsp?fromVal='
+ bytes = web.get(uri + query)
+ m = r_result.search(bytes)
+ if m:
+ result = m.group(1)
+ result = r_tag.sub('', result) # strip span.warning tags
+ result = result.replace('&gt;', '>')
+ result = result.replace('(undefined symbol)', '(?) ')
- if '.' in result:
- try: result = str(round(float(result), precision))
- except ValueError: pass
+ if '.' in result:
+ try: result = str(round(float(result), precision))
+ except ValueError: pass
- if not result.strip():
- result = '?'
- elif ' in ' in q:
- result += ' ' + q.split(' in ', 1)[1]
+ if not result.strip():
+ result = '?'
+ elif ' in ' in q:
+ result += ' ' + q.split(' in ', 1)[1]
- phenny.say(q + ' = ' + result[:350])
- else: phenny.reply("Sorry, can't calculate that.")
- phenny.say('Note that .calc is deprecated, consider using .c')
+ phenny.say(q + ' = ' + result[:350])
+ else: phenny.reply("Sorry, can't calculate that.")
+ phenny.say('Note that .calc is deprecated, consider using .c')
calc.commands = ['calc']
calc.example = '.calc 5 + 3'
-def c(phenny, input):
- """Google calculator."""
- if not input.group(2):
- return phenny.reply("Nothing to calculate.")
- q = input.group(2).encode('utf-8')
- q = q.replace('\xcf\x95', 'phi') # utf-8 U+03D5
- q = q.replace('\xcf\x80', 'pi') # utf-8 U+03C0
- uri = 'http://www.google.com/ig/calculator?q='
- bytes = web.get(uri + web.urllib.quote(q))
- parts = bytes.split('",')
- answer = [p for p in parts if p.startswith('rhs: "')][0][6:]
- if answer:
- answer = answer.decode('unicode-escape')
- answer = ''.join(chr(ord(c)) for c in answer)
- answer = answer.decode('utf-8')
- answer = answer.replace(u'\xc2\xa0', ',')
- answer = answer.replace('<sup>', '^(')
- answer = answer.replace('</sup>', ')')
- answer = web.decode(answer)
- phenny.say(answer)
- else: phenny.say('Sorry, no result.')
+def c(phenny, input):
+ """Google calculator."""
+ if not input.group(2):
+ return phenny.reply("Nothing to calculate.")
+ q = input.group(2).encode('utf-8')
+ q = q.replace('\xcf\x95', 'phi') # utf-8 U+03D5
+ q = q.replace('\xcf\x80', 'pi') # utf-8 U+03C0
+ uri = 'http://www.google.com/ig/calculator?q='
+ bytes = web.get(uri + web.urllib.quote(q))
+ parts = bytes.split('",')
+ answer = [p for p in parts if p.startswith('rhs: "')][0][6:]
+ if answer:
+ answer = answer.decode('unicode-escape')
+ answer = ''.join(chr(ord(c)) for c in answer)
+ answer = answer.decode('utf-8')
+ answer = answer.replace(u'\xc2\xa0', ',')
+ answer = answer.replace('<sup>', '^(')
+ answer = answer.replace('</sup>', ')')
+ answer = web.decode(answer)
+ phenny.say(answer)
+ else: phenny.say('Sorry, no result.')
c.commands = ['c']
c.example = '.c 5 + 3'
-def py(phenny, input):
- query = input.group(2).encode('utf-8')
- uri = 'http://tumbolia.appspot.com/py/'
- answer = web.get(uri + web.urllib.quote(query))
- if answer:
- phenny.say(answer)
- else: phenny.reply('Sorry, no result.')
+def py(phenny, input):
+ query = input.group(2).encode('utf-8')
+ uri = 'http://tumbolia.appspot.com/py/'
+ answer = web.get(uri + web.urllib.quote(query))
+ if answer:
+ phenny.say(answer)
+ else: phenny.reply('Sorry, no result.')
py.commands = ['py']
-def wa(phenny, input):
- if not input.group(2):
- return phenny.reply("No search term.")
- query = input.group(2).encode('utf-8')
- uri = 'http://tumbolia.appspot.com/wa/'
- answer = web.get(uri + web.urllib.quote(query.replace('+', '%2B')))
- if answer:
- phenny.say(answer)
- else: phenny.reply('Sorry, no result.')
+def wa(phenny, input):
+ if not input.group(2):
+ return phenny.reply("No search term.")
+ query = input.group(2).encode('utf-8')
+ uri = 'http://tumbolia.appspot.com/wa/'
+ answer = web.get(uri + web.urllib.quote(query.replace('+', '%2B')))
+ if answer:
+ phenny.say(answer)
+ else: phenny.reply('Sorry, no result.')
wa.commands = ['wa']
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/clock.py b/modules/clock.py
index 91f2d5b..e0c237c 100755
--- a/modules/clock.py
+++ b/modules/clock.py
@@ -11,180 +11,180 @@ import re, math, time, urllib, locale, socket, struct, datetime
from decimal import Decimal as dec
from tools import deprecated
-TimeZones = {'KST': 9, 'CADT': 10.5, 'EETDST': 3, 'MESZ': 2, 'WADT': 9,
- 'EET': 2, 'MST': -7, 'WAST': 8, 'IST': 5.5, 'B': 2,
- 'MSK': 3, 'X': -11, 'MSD': 4, 'CETDST': 2, 'AST': -4,
- 'HKT': 8, 'JST': 9, 'CAST': 9.5, 'CET': 1, 'CEST': 2,
- 'EEST': 3, 'EAST': 10, 'METDST': 2, 'MDT': -6, 'A': 1,
- 'UTC': 0, 'ADT': -3, 'EST': -5, 'E': 5, 'D': 4, 'G': 7,
- 'F': 6, 'I': 9, 'H': 8, 'K': 10, 'PDT': -7, 'M': 12,
- 'L': 11, 'O': -2, 'MEST': 2, 'Q': -4, 'P': -3, 'S': -6,
- 'R': -5, 'U': -8, 'T': -7, 'W': -10, 'WET': 0, 'Y': -12,
- 'CST': -6, 'EADT': 11, 'Z': 0, 'GMT': 0, 'WETDST': 1,
- 'C': 3, 'WEST': 1, 'CDT': -5, 'MET': 1, 'N': -1, 'V': -9,
- 'EDT': -4, 'UT': 0, 'PST': -8, 'MEZ': 1, 'BST': 1,
- 'ACS': 9.5, 'ATL': -4, 'ALA': -9, 'HAW': -10, 'AKDT': -8,
- 'AKST': -9,
- 'BDST': 2}
+TimeZones = {'KST': 9, 'CADT': 10.5, 'EETDST': 3, 'MESZ': 2, 'WADT': 9,
+ 'EET': 2, 'MST': -7, 'WAST': 8, 'IST': 5.5, 'B': 2,
+ 'MSK': 3, 'X': -11, 'MSD': 4, 'CETDST': 2, 'AST': -4,
+ 'HKT': 8, 'JST': 9, 'CAST': 9.5, 'CET': 1, 'CEST': 2,
+ 'EEST': 3, 'EAST': 10, 'METDST': 2, 'MDT': -6, 'A': 1,
+ 'UTC': 0, 'ADT': -3, 'EST': -5, 'E': 5, 'D': 4, 'G': 7,
+ 'F': 6, 'I': 9, 'H': 8, 'K': 10, 'PDT': -7, 'M': 12,
+ 'L': 11, 'O': -2, 'MEST': 2, 'Q': -4, 'P': -3, 'S': -6,
+ 'R': -5, 'U': -8, 'T': -7, 'W': -10, 'WET': 0, 'Y': -12,
+ 'CST': -6, 'EADT': 11, 'Z': 0, 'GMT': 0, 'WETDST': 1,
+ 'C': 3, 'WEST': 1, 'CDT': -5, 'MET': 1, 'N': -1, 'V': -9,
+ 'EDT': -4, 'UT': 0, 'PST': -8, 'MEZ': 1, 'BST': 1,
+ 'ACS': 9.5, 'ATL': -4, 'ALA': -9, 'HAW': -10, 'AKDT': -8,
+ 'AKST': -9,
+ 'BDST': 2}
TZ1 = {
- 'NDT': -2.5,
- 'BRST': -2,
- 'ADT': -3,
- 'EDT': -4,
- 'CDT': -5,
- 'MDT': -6,
- 'PDT': -7,
- 'YDT': -8,
- 'HDT': -9,
- 'BST': 1,
- 'MEST': 2,
- 'SST': 2,
- 'FST': 2,
- 'CEST': 2,
- 'EEST': 3,
- 'WADT': 8,
- 'KDT': 10,
- 'EADT': 13,
- 'NZD': 13,
- 'NZDT': 13,
- 'GMT': 0,
- 'UT': 0,
- 'UTC': 0,
- 'WET': 0,
- 'WAT': -1,
- 'AT': -2,
- 'FNT': -2,
- 'BRT': -3,
- 'MNT': -4,
- 'EWT': -4,
- 'AST': -4,
- 'EST': -5,
- 'ACT': -5,
- 'CST': -6,
- 'MST': -7,
- 'PST': -8,
- 'YST': -9,
- 'HST': -10,
- 'CAT': -10,
- 'AHST': -10,
- 'NT': -11,
- 'IDLW': -12,
- 'CET': 1,
- 'MEZ': 1,
- 'ECT': 1,
- 'MET': 1,
- 'MEWT': 1,
- 'SWT': 1,
- 'SET': 1,
- 'FWT': 1,
- 'EET': 2,
- 'UKR': 2,
- 'BT': 3,
- 'ZP4': 4,
- 'ZP5': 5,
- 'ZP6': 6,
- 'WST': 8,
- 'HKT': 8,
- 'CCT': 8,
- 'JST': 9,
- 'KST': 9,
- 'EAST': 10,
- 'GST': 10,
- 'NZT': 12,
- 'NZST': 12,
+ 'NDT': -2.5,
+ 'BRST': -2,
+ 'ADT': -3,
+ 'EDT': -4,
+ 'CDT': -5,
+ 'MDT': -6,
+ 'PDT': -7,
+ 'YDT': -8,
+ 'HDT': -9,
+ 'BST': 1,
+ 'MEST': 2,
+ 'SST': 2,
+ 'FST': 2,
+ 'CEST': 2,
+ 'EEST': 3,
+ 'WADT': 8,
+ 'KDT': 10,
+ 'EADT': 13,
+ 'NZD': 13,
+ 'NZDT': 13,
+ 'GMT': 0,
+ 'UT': 0,
+ 'UTC': 0,
+ 'WET': 0,
+ 'WAT': -1,
+ 'AT': -2,
+ 'FNT': -2,
+ 'BRT': -3,
+ 'MNT': -4,
+ 'EWT': -4,
+ 'AST': -4,
+ 'EST': -5,
+ 'ACT': -5,
+ 'CST': -6,
+ 'MST': -7,
+ 'PST': -8,
+ 'YST': -9,
+ 'HST': -10,
+ 'CAT': -10,
+ 'AHST': -10,
+ 'NT': -11,
+ 'IDLW': -12,
+ 'CET': 1,
+ 'MEZ': 1,
+ 'ECT': 1,
+ 'MET': 1,
+ 'MEWT': 1,
+ 'SWT': 1,
+ 'SET': 1,
+ 'FWT': 1,
+ 'EET': 2,
+ 'UKR': 2,
+ 'BT': 3,
+ 'ZP4': 4,
+ 'ZP5': 5,
+ 'ZP6': 6,
+ 'WST': 8,
+ 'HKT': 8,
+ 'CCT': 8,
+ 'JST': 9,
+ 'KST': 9,
+ 'EAST': 10,
+ 'GST': 10,
+ 'NZT': 12,
+ 'NZST': 12,
'IDLE': 12
}
TZ2 = {
- 'ACDT': 10.5,
- 'ACST': 9.5,
- 'ADT': 3,
+ 'ACDT': 10.5,
+ 'ACST': 9.5,
+ 'ADT': 3,
'AEDT': 11, # hmm
'AEST': 10, # hmm
- 'AHDT': 9,
- 'AHST': 10,
- 'AST': 4,
- 'AT': 2,
- 'AWDT': -9,
- 'AWST': -8,
- 'BAT': -3,
- 'BDST': -2,
- 'BET': 11,
- 'BST': -1,
- 'BT': -3,
- 'BZT2': 3,
- 'CADT': -10.5,
- 'CAST': -9.5,
- 'CAT': 10,
- 'CCT': -8,
- # 'CDT': 5,
- 'CED': -2,
- 'CET': -1,
- 'CST': 6,
- 'EAST': -10,
- # 'EDT': 4,
- 'EED': -3,
- 'EET': -2,
- 'EEST': -3,
- 'EST': 5,
- 'FST': -2,
- 'FWT': -1,
- 'GMT': 0,
- 'GST': -10,
- 'HDT': 9,
- 'HST': 10,
- 'IDLE': -12,
- 'IDLW': 12,
- # 'IST': -5.5,
- 'IT': -3.5,
- 'JST': -9,
- 'JT': -7,
- 'KST': -9,
- 'MDT': 6,
- 'MED': -2,
- 'MET': -1,
- 'MEST': -2,
- 'MEWT': -1,
- 'MST': 7,
- 'MT': -8,
- 'NDT': 2.5,
- 'NFT': 3.5,
- 'NT': 11,
- 'NST': -6.5,
- 'NZ': -11,
- 'NZST': -12,
- 'NZDT': -13,
- 'NZT': -12,
- # 'PDT': 7,
- 'PST': 8,
- 'ROK': -9,
- 'SAD': -10,
- 'SAST': -9,
- 'SAT': -9,
- 'SDT': -10,
- 'SST': -2,
- 'SWT': -1,
- 'USZ3': -4,
- 'USZ4': -5,
- 'USZ5': -6,
- 'USZ6': -7,
- 'UT': 0,
- 'UTC': 0,
- 'UZ10': -11,
- 'WAT': 1,
- 'WET': 0,
- 'WST': -8,
- 'YDT': 8,
- 'YST': 9,
- 'ZP4': -4,
- 'ZP5': -5,
+ 'AHDT': 9,
+ 'AHST': 10,
+ 'AST': 4,
+ 'AT': 2,
+ 'AWDT': -9,
+ 'AWST': -8,
+ 'BAT': -3,
+ 'BDST': -2,
+ 'BET': 11,
+ 'BST': -1,
+ 'BT': -3,
+ 'BZT2': 3,
+ 'CADT': -10.5,
+ 'CAST': -9.5,
+ 'CAT': 10,
+ 'CCT': -8,
+ # 'CDT': 5,
+ 'CED': -2,
+ 'CET': -1,
+ 'CST': 6,
+ 'EAST': -10,
+ # 'EDT': 4,
+ 'EED': -3,
+ 'EET': -2,
+ 'EEST': -3,
+ 'EST': 5,
+ 'FST': -2,
+ 'FWT': -1,
+ 'GMT': 0,
+ 'GST': -10,
+ 'HDT': 9,
+ 'HST': 10,
+ 'IDLE': -12,
+ 'IDLW': 12,
+ # 'IST': -5.5,
+ 'IT': -3.5,
+ 'JST': -9,
+ 'JT': -7,
+ 'KST': -9,
+ 'MDT': 6,
+ 'MED': -2,
+ 'MET': -1,
+ 'MEST': -2,
+ 'MEWT': -1,
+ 'MST': 7,
+ 'MT': -8,
+ 'NDT': 2.5,
+ 'NFT': 3.5,
+ 'NT': 11,
+ 'NST': -6.5,
+ 'NZ': -11,
+ 'NZST': -12,
+ 'NZDT': -13,
+ 'NZT': -12,
+ # 'PDT': 7,
+ 'PST': 8,
+ 'ROK': -9,
+ 'SAD': -10,
+ 'SAST': -9,
+ 'SAT': -9,
+ 'SDT': -10,
+ 'SST': -2,
+ 'SWT': -1,
+ 'USZ3': -4,
+ 'USZ4': -5,
+ 'USZ5': -6,
+ 'USZ6': -7,
+ 'UT': 0,
+ 'UTC': 0,
+ 'UZ10': -11,
+ 'WAT': 1,
+ 'WET': 0,
+ 'WST': -8,
+ 'YDT': 8,
+ 'YST': 9,
+ 'ZP4': -4,
+ 'ZP5': -5,
'ZP6': -6
}
TZ3 = {
- 'AEST': 10,
- 'AEDT': 11
+ 'AEST': 10,
+ 'AEDT': 11
}
# TimeZones.update(TZ2) # do these have to be negated?
@@ -194,109 +194,109 @@ TimeZones.update(TZ3)
r_local = re.compile(r'\([a-z]+_[A-Z]+\)')
@deprecated
-def f_time(self, origin, match, args):
- """Returns the current time."""
- tz = match.group(2) or 'GMT'
+def f_time(self, origin, match, args):
+ """Returns the current time."""
+ tz = match.group(2) or 'GMT'
- # Personal time zones, because they're rad
- if hasattr(self.config, 'timezones'):
- People = self.config.timezones
- else: People = {}
+ # Personal time zones, because they're rad
+ if hasattr(self.config, 'timezones'):
+ People = self.config.timezones
+ else: People = {}
- if People.has_key(tz):
- tz = People[tz]
- elif (not match.group(2)) and People.has_key(origin.nick):
- tz = People[origin.nick]
+ if People.has_key(tz):
+ tz = People[tz]
+ elif (not match.group(2)) and People.has_key(origin.nick):
+ tz = People[origin.nick]
- TZ = tz.upper()
- if len(tz) > 30: return
+ TZ = tz.upper()
+ if len(tz) > 30: return
- if (TZ == 'UTC') or (TZ == 'Z'):
- msg = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
- self.msg(origin.sender, msg)
- elif r_local.match(tz): # thanks to Mark Shoulsdon (clsn)
- locale.setlocale(locale.LC_TIME, (tz[1:-1], 'UTF-8'))
- msg = time.strftime("%A, %d %B %Y %H:%M:%SZ", time.gmtime())
- self.msg(origin.sender, msg)
- elif TimeZones.has_key(TZ):
- offset = TimeZones[TZ] * 3600
- timenow = time.gmtime(time.time() + offset)
- msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(TZ), timenow)
- self.msg(origin.sender, msg)
- elif tz and tz[0] in ('+', '-') and 4 <= len(tz) <= 6:
- timenow = time.gmtime(time.time() + (int(tz[:3]) * 3600))
- msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(tz), timenow)
- self.msg(origin.sender, msg)
- else:
- try: t = float(tz)
- except ValueError:
- import os, re, subprocess
- r_tz = re.compile(r'^[A-Za-z]+(?:/[A-Za-z_]+)*$')
- if r_tz.match(tz) and os.path.isfile('/usr/share/zoneinfo/' + tz):
- cmd, PIPE = 'TZ=%s date' % tz, subprocess.PIPE
- proc = subprocess.Popen(cmd, shell=True, stdout=PIPE)
- self.msg(origin.sender, proc.communicate()[0])
- else:
- error = "Sorry, I don't know about the '%s' timezone." % tz
- self.msg(origin.sender, origin.nick + ': ' + error)
- else:
- timenow = time.gmtime(time.time() + (t * 3600))
- msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(tz), timenow)
- self.msg(origin.sender, msg)
+ if (TZ == 'UTC') or (TZ == 'Z'):
+ msg = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
+ self.msg(origin.sender, msg)
+ elif r_local.match(tz): # thanks to Mark Shoulsdon (clsn)
+ locale.setlocale(locale.LC_TIME, (tz[1:-1], 'UTF-8'))
+ msg = time.strftime("%A, %d %B %Y %H:%M:%SZ", time.gmtime())
+ self.msg(origin.sender, msg)
+ elif TimeZones.has_key(TZ):
+ offset = TimeZones[TZ] * 3600
+ timenow = time.gmtime(time.time() + offset)
+ msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(TZ), timenow)
+ self.msg(origin.sender, msg)
+ elif tz and tz[0] in ('+', '-') and 4 <= len(tz) <= 6:
+ timenow = time.gmtime(time.time() + (int(tz[:3]) * 3600))
+ msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(tz), timenow)
+ self.msg(origin.sender, msg)
+ else:
+ try: t = float(tz)
+ except ValueError:
+ import os, re, subprocess
+ r_tz = re.compile(r'^[A-Za-z]+(?:/[A-Za-z_]+)*$')
+ if r_tz.match(tz) and os.path.isfile('/usr/share/zoneinfo/' + tz):
+ cmd, PIPE = 'TZ=%s date' % tz, subprocess.PIPE
+ proc = subprocess.Popen(cmd, shell=True, stdout=PIPE)
+ self.msg(origin.sender, proc.communicate()[0])
+ else:
+ error = "Sorry, I don't know about the '%s' timezone." % tz
+ self.msg(origin.sender, origin.nick + ': ' + error)
+ else:
+ timenow = time.gmtime(time.time() + (t * 3600))
+ msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(tz), timenow)
+ self.msg(origin.sender, msg)
f_time.commands = ['t']
f_time.name = 't'
f_time.example = '.t UTC'
-def beats(phenny, input):
- """Shows the internet time in Swatch beats."""
- beats = ((time.time() + 3600) % 86400) / 86.4
- beats = int(math.floor(beats))
- phenny.say('@%03i' % beats)
+def beats(phenny, input):
+ """Shows the internet time in Swatch beats."""
+ beats = ((time.time() + 3600) % 86400) / 86.4
+ beats = int(math.floor(beats))
+ phenny.say('@%03i' % beats)
beats.commands = ['beats']
beats.priority = 'low'
-def divide(input, by):
- return (input / by), (input % by)
+def divide(input, by):
+ return (input / by), (input % by)
-def yi(phenny, input):
- """Shows whether it is currently yi or not."""
- quadraels, remainder = divide(int(time.time()), 1753200)
- raels = quadraels * 4
- extraraels, remainder = divide(remainder, 432000)
- if extraraels == 4:
- return phenny.say('Yes! PARTAI!')
- else: phenny.say('Not yet...')
+def yi(phenny, input):
+ """Shows whether it is currently yi or not."""
+ quadraels, remainder = divide(int(time.time()), 1753200)
+ raels = quadraels * 4
+ extraraels, remainder = divide(remainder, 432000)
+ if extraraels == 4:
+ return phenny.say('Yes! PARTAI!')
+ else: phenny.say('Not yet...')
yi.commands = ['yi']
yi.priority = 'low'
-def tock(phenny, input):
- """Shows the time from the USNO's atomic clock."""
- u = urllib.urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl')
- info = u.info()
- u.close()
- phenny.say('"' + info['Date'] + '" - tycho.usno.navy.mil')
+def tock(phenny, input):
+ """Shows the time from the USNO's atomic clock."""
+ u = urllib.urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl')
+ info = u.info()
+ u.close()
+ phenny.say('"' + info['Date'] + '" - tycho.usno.navy.mil')
tock.commands = ['tock']
tock.priority = 'high'
-def npl(phenny, input):
- """Shows the time from NPL's SNTP server."""
- # for server in ('ntp1.npl.co.uk', 'ntp2.npl.co.uk'):
- client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- client.sendto('\x1b' + 47 * '\0', ('ntp1.npl.co.uk', 123))
- data, address = client.recvfrom(1024)
- if data:
- buf = struct.unpack('B' * 48, data)
- d = dec('0.0')
- for i in range(8):
- d += dec(buf[32 + i]) * dec(str(math.pow(2, (3 - i) * 8)))
- d -= dec(2208988800L)
- a, b = str(d).split('.')
- f = '%Y-%m-%d %H:%M:%S'
- result = datetime.datetime.fromtimestamp(d).strftime(f) + '.' + b[:6]
- phenny.say(result + ' - ntp1.npl.co.uk')
- else: phenny.say('No data received, sorry')
+def npl(phenny, input):
+ """Shows the time from NPL's SNTP server."""
+ # for server in ('ntp1.npl.co.uk', 'ntp2.npl.co.uk'):
+ client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ client.sendto('\x1b' + 47 * '\0', ('ntp1.npl.co.uk', 123))
+ data, address = client.recvfrom(1024)
+ if data:
+ buf = struct.unpack('B' * 48, data)
+ d = dec('0.0')
+ for i in range(8):
+ d += dec(buf[32 + i]) * dec(str(math.pow(2, (3 - i) * 8)))
+ d -= dec(2208988800L)
+ a, b = str(d).split('.')
+ f = '%Y-%m-%d %H:%M:%S'
+ result = datetime.datetime.fromtimestamp(d).strftime(f) + '.' + b[:6]
+ phenny.say(result + ' - ntp1.npl.co.uk')
+ else: phenny.say('No data received, sorry')
npl.commands = ['npl']
npl.priority = 'high'
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/codepoints.py b/modules/codepoints.py
index eb9c8bf..a83d292 100755
--- a/modules/codepoints.py
+++ b/modules/codepoints.py
@@ -10,125 +10,125 @@ http://inamidst.com/phenny/
import re, unicodedata
from itertools import islice
-def about(u, cp=None, name=None):
- if cp is None:
- cp = ord(u)
- if name is None:
- try: name = unicodedata.name(u)
- except ValueError:
- return 'U+%04X (No name found)' % cp
-
- if not unicodedata.combining(u):
- template = 'U+%04X %s (%s)'
- else: template = 'U+%04X %s (\xe2\x97\x8c%s)'
- return template % (cp, name, u.encode('utf-8'))
-
-def codepoint_simple(arg):
- arg = arg.upper()
-
- r_label = re.compile('\\b' + arg.replace(' ', '.*\\b') + '\\b')
-
- results = []
- for cp in xrange(0xFFFF):
- u = unichr(cp)
- try: name = unicodedata.name(u)
- except ValueError: continue
-
- if r_label.search(name):
- results.append((len(name), u, cp, name))
- if not results:
- r_label = re.compile('\\b' + arg.replace(' ', '.*\\b'))
- for cp in xrange(0xFFFF):
- u = unichr(cp)
- try: name = unicodedata.name(u)
- except ValueError: continue
-
- if r_label.search(name):
+def about(u, cp=None, name=None):
+ if cp is None:
+ cp = ord(u)
+ if name is None:
+ try: name = unicodedata.name(u)
+ except ValueError:
+ return 'U+%04X (No name found)' % cp
+
+ if not unicodedata.combining(u):
+ template = 'U+%04X %s (%s)'
+ else: template = 'U+%04X %s (\xe2\x97\x8c%s)'
+ return template % (cp, name, u.encode('utf-8'))
+
+def codepoint_simple(arg):
+ arg = arg.upper()
+
+ r_label = re.compile('\\b' + arg.replace(' ', '.*\\b') + '\\b')
+
+ results = []
+ for cp in xrange(0xFFFF):
+ u = unichr(cp)
+ try: name = unicodedata.name(u)
+ except ValueError: continue
+
+ if r_label.search(name):
results.append((len(name), u, cp, name))
-
- if not results:
- return None
-
- length, u, cp, name = sorted(results)[0]
- return about(u, cp, name)
-
-def codepoint_extended(arg):
- arg = arg.upper()
- try: r_search = re.compile(arg)
- except: raise ValueError('Broken regexp: %r' % arg)
-
- for cp in xrange(1, 0x10FFFF):
- u = unichr(cp)
- name = unicodedata.name(u, '-')
-
- if r_search.search(name):
- yield about(u, cp, name)
-
-def u(phenny, input):
- """Look up unicode information."""
- arg = input.bytes[3:]
- # phenny.msg('#inamidst', '%r' % arg)
- if not arg:
- return phenny.reply('You gave me zero length input.')
- elif not arg.strip(' '):
- if len(arg) > 1: return phenny.reply('%s SPACEs (U+0020)' % len(arg))
- return phenny.reply('1 SPACE (U+0020)')
-
- # @@ space
- if set(arg.upper()) - set(
- 'ABCDEFGHIJKLMNOPQRSTUVWYXYZ0123456789- .?+*{}[]\\/^$'):
- printable = False
- elif len(arg) > 1:
- printable = True
- else: printable = False
-
- if printable:
- extended = False
- for c in '.?+*{}[]\\/^$':
- if c in arg:
- extended = True
- break
-
- if len(arg) == 4:
- try: u = unichr(int(arg, 16))
- except ValueError: pass
- else: return phenny.say(about(u))
-
- if extended:
- # look up a codepoint with regexp
- results = list(islice(codepoint_extended(arg), 4))
- for i, result in enumerate(results):
- if (i < 2) or ((i == 2) and (len(results) < 4)):
- phenny.say(result)
- elif (i == 2) and (len(results) > 3):
- phenny.say(result + ' [...]')
- if not results:
- phenny.reply('Sorry, no results')
- else:
- # look up a codepoint freely
- result = codepoint_simple(arg)
- if result is not None:
- phenny.say(result)
- else: phenny.reply("Sorry, no results for %r." % arg)
- else:
- text = arg.decode('utf-8')
- # look up less than three podecoints
- if len(text) <= 3:
- for u in text:
- phenny.say(about(u))
- # look up more than three podecoints
- elif len(text) <= 10:
- phenny.reply(' '.join('U+%04X' % ord(c) for c in text))
- else: phenny.reply('Sorry, your input is too long!')
+ if not results:
+ r_label = re.compile('\\b' + arg.replace(' ', '.*\\b'))
+ for cp in xrange(0xFFFF):
+ u = unichr(cp)
+ try: name = unicodedata.name(u)
+ except ValueError: continue
+
+ if r_label.search(name):
+ results.append((len(name), u, cp, name))
+
+ if not results:
+ return None
+
+ length, u, cp, name = sorted(results)[0]
+ return about(u, cp, name)
+
+def codepoint_extended(arg):
+ arg = arg.upper()
+ try: r_search = re.compile(arg)
+ except: raise ValueError('Broken regexp: %r' % arg)
+
+ for cp in xrange(1, 0x10FFFF):
+ u = unichr(cp)
+ name = unicodedata.name(u, '-')
+
+ if r_search.search(name):
+ yield about(u, cp, name)
+
+def u(phenny, input):
+ """Look up unicode information."""
+ arg = input.bytes[3:]
+ # phenny.msg('#inamidst', '%r' % arg)
+ if not arg:
+ return phenny.reply('You gave me zero length input.')
+ elif not arg.strip(' '):
+ if len(arg) > 1: return phenny.reply('%s SPACEs (U+0020)' % len(arg))
+ return phenny.reply('1 SPACE (U+0020)')
+
+ # @@ space
+ if set(arg.upper()) - set(
+ 'ABCDEFGHIJKLMNOPQRSTUVWYXYZ0123456789- .?+*{}[]\\/^$'):
+ printable = False
+ elif len(arg) > 1:
+ printable = True
+ else: printable = False
+
+ if printable:
+ extended = False
+ for c in '.?+*{}[]\\/^$':
+ if c in arg:
+ extended = True
+ break
+
+ if len(arg) == 4:
+ try: u = unichr(int(arg, 16))
+ except ValueError: pass
+ else: return phenny.say(about(u))
+
+ if extended:
+ # look up a codepoint with regexp
+ results = list(islice(codepoint_extended(arg), 4))
+ for i, result in enumerate(results):
+ if (i < 2) or ((i == 2) and (len(results) < 4)):
+ phenny.say(result)
+ elif (i == 2) and (len(results) > 3):
+ phenny.say(result + ' [...]')
+ if not results:
+ phenny.reply('Sorry, no results')
+ else:
+ # look up a codepoint freely
+ result = codepoint_simple(arg)
+ if result is not None:
+ phenny.say(result)
+ else: phenny.reply("Sorry, no results for %r." % arg)
+ else:
+ text = arg.decode('utf-8')
+ # look up less than three podecoints
+ if len(text) <= 3:
+ for u in text:
+ phenny.say(about(u))
+ # look up more than three podecoints
+ elif len(text) <= 10:
+ phenny.reply(' '.join('U+%04X' % ord(c) for c in text))
+ else: phenny.reply('Sorry, your input is too long!')
u.commands = ['u']
u.example = '.u 203D'
-def bytes(phenny, input):
- """Show the input as pretty printed bytes."""
- b = input.bytes
- phenny.reply('%r' % b[b.find(' ') + 1:])
+def bytes(phenny, input):
+ """Show the input as pretty printed bytes."""
+ b = input.bytes
+ phenny.reply('%r' % b[b.find(' ') + 1:])
bytes.commands = ['bytes']
bytes.example = '.bytes \xe3\x8b\xa1'
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/etymology.py b/modules/etymology.py
index cc93cfe..9edd218 100755
--- a/modules/etymology.py
+++ b/modules/etymology.py
@@ -19,96 +19,96 @@ r_definition = re.compile(r'(?ims)<dd[^>]*>.*?</dd>')
r_tag = re.compile(r'<(?!!)[^>]+>')
r_whitespace = re.compile(r'[\t\r\n ]+')
-class Grab(urllib.URLopener):
- def __init__(self, *args):
- self.version = 'Mozilla/5.0 (Phenny)'
- urllib.URLopener.__init__(self, *args)
- def http_error_default(self, url, fp, errcode, errmsg, headers):
- return urllib.addinfourl(fp, [headers, errcode], "http:" + url)
+class Grab(urllib.URLopener):
+ def __init__(self, *args):
+ self.version = 'Mozilla/5.0 (Phenny)'
+ urllib.URLopener.__init__(self, *args)
+ def http_error_default(self, url, fp, errcode, errmsg, headers):
+ return urllib.addinfourl(fp, [headers, errcode], "http:" + url)
abbrs = [
- 'cf', 'lit', 'etc', 'Ger', 'Du', 'Skt', 'Rus', 'Eng', 'Amer.Eng', 'Sp',
- 'Fr', 'N', 'E', 'S', 'W', 'L', 'Gen', 'J.C', 'dial', 'Gk',
- '19c', '18c', '17c', '16c', 'St', 'Capt', 'obs', 'Jan', 'Feb', 'Mar',
- 'Apr', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'c', 'tr', 'e', 'g'
+ 'cf', 'lit', 'etc', 'Ger', 'Du', 'Skt', 'Rus', 'Eng', 'Amer.Eng', 'Sp',
+ 'Fr', 'N', 'E', 'S', 'W', 'L', 'Gen', 'J.C', 'dial', 'Gk',
+ '19c', '18c', '17c', '16c', 'St', 'Capt', 'obs', 'Jan', 'Feb', 'Mar',
+ 'Apr', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'c', 'tr', 'e', 'g'
]
t_sentence = r'^.*?(?<!%s)(?:\.(?= [A-Z0-9]|\Z)|\Z)'
r_sentence = re.compile(t_sentence % ')(?<!'.join(abbrs))
-def unescape(s):
- s = s.replace('&gt;', '>')
- s = s.replace('&lt;', '<')
- s = s.replace('&amp;', '&')
- return s
-
-def text(html):
- html = r_tag.sub('', html)
- html = r_whitespace.sub(' ', html)
- return unescape(html).strip()
-
-def etymology(word):
- # @@ <nsh> sbp, would it be possible to have a flag for .ety to get 2nd/etc
- # entries? - http://swhack.com/logs/2006-07-19#T15-05-29
-
- if len(word) > 25:
- raise ValueError("Word too long: %s[...]" % word[:10])
- word = {'axe': 'ax/axe'}.get(word, word)
-
- grab = urllib._urlopener
- urllib._urlopener = Grab()
- urllib._urlopener.addheader("Referer", "http://www.etymonline.com/")
- bytes = web.get(etyuri % web.urllib.quote(word))
- urllib._urlopener = grab
- definitions = r_definition.findall(bytes)
-
- if not definitions:
- return None
-
- defn = text(definitions[0])
- m = r_sentence.match(defn)
- if not m:
- return None
- sentence = m.group(0)
-
- # try:
- # sentence = unicode(sentence, 'iso-8859-1')
- # sentence = sentence.encode('utf-8')
- # except: pass
- sentence = web.decode(sentence)
-
- maxlength = 275
- if len(sentence) > maxlength:
- sentence = sentence[:maxlength]
- words = sentence[:-5].split(' ')
- words.pop()
- sentence = ' '.join(words) + ' [...]'
-
- sentence = '"' + sentence.replace('"', "'") + '"'
- return sentence + ' - ' + ('http://etymonline.com/index.php?term=%s' % web.urllib.quote(word))
+def unescape(s):
+ s = s.replace('&gt;', '>')
+ s = s.replace('&lt;', '<')
+ s = s.replace('&amp;', '&')
+ return s
+
+def text(html):
+ html = r_tag.sub('', html)
+ html = r_whitespace.sub(' ', html)
+ return unescape(html).strip()
+
+def etymology(word):
+ # @@ <nsh> sbp, would it be possible to have a flag for .ety to get 2nd/etc
+ # entries? - http://swhack.com/logs/2006-07-19#T15-05-29
+
+ if len(word) > 25:
+ raise ValueError("Word too long: %s[...]" % word[:10])
+ word = {'axe': 'ax/axe'}.get(word, word)
+
+ grab = urllib._urlopener
+ urllib._urlopener = Grab()
+ urllib._urlopener.addheader("Referer", "http://www.etymonline.com/")
+ bytes = web.get(etyuri % web.urllib.quote(word))
+ urllib._urlopener = grab
+ definitions = r_definition.findall(bytes)
+
+ if not definitions:
+ return None
+
+ defn = text(definitions[0])
+ m = r_sentence.match(defn)
+ if not m:
+ return None
+ sentence = m.group(0)
+
+ # try:
+ # sentence = unicode(sentence, 'iso-8859-1')
+ # sentence = sentence.encode('utf-8')
+ # except: pass
+ sentence = web.decode(sentence)
+
+ maxlength = 275
+ if len(sentence) > maxlength:
+ sentence = sentence[:maxlength]
+ words = sentence[:-5].split(' ')
+ words.pop()
+ sentence = ' '.join(words) + ' [...]'
+
+ sentence = '"' + sentence.replace('"', "'") + '"'
+ return sentence + ' - ' + ('http://etymonline.com/index.php?term=%s' % web.urllib.quote(word))
@deprecated
-def f_etymology(self, origin, match, args):
- word = match.group(2)
-
- try: result = etymology(word.encode('iso-8859-1'))
- except IOError:
- msg = "Can't connect to etymonline.com (%s)" % (etyuri % word)
- self.msg(origin.sender, msg)
- return
- except AttributeError:
- result = None
-
- if result is not None:
- self.msg(origin.sender, result)
- else:
- uri = etysearch % word
- msg = 'Can\'t find the etymology for "%s". Try %s' % (word, ('http://etymonline.com/index.php?term=%s' % web.urllib.quote(word)))
- self.msg(origin.sender, msg)
+def f_etymology(self, origin, match, args):
+ word = match.group(2)
+
+ try: result = etymology(word.encode('iso-8859-1'))
+ except IOError:
+ msg = "Can't connect to etymonline.com (%s)" % (etyuri % word)
+ self.msg(origin.sender, msg)
+ return
+ except AttributeError:
+ result = None
+
+ if result is not None:
+ self.msg(origin.sender, result)
+ else:
+ uri = etysearch % word
+ msg = 'Can\'t find the etymology for "%s". Try %s' % (word, ('http://etymonline.com/index.php?term=%s' % web.urllib.quote(word)))
+ self.msg(origin.sender, msg)
# @@ Cf. http://swhack.com/logs/2006-01-04#T01-50-22
f_etymology.rule = (['ety'], r"(.+?)$")
f_etymology.thread = True
f_etymology.priority = 'high'
-if __name__=="__main__":
- import sys
- print etymology(sys.argv[1])
+if __name__=="__main__":
+ import sys
+ print etymology(sys.argv[1])
diff --git a/modules/head.py b/modules/head.py
index 66e9eef..939ac3c 100755
--- a/modules/head.py
+++ b/modules/head.py
@@ -12,56 +12,56 @@ from htmlentitydefs import name2codepoint
import web
from tools import deprecated
-def head(phenny, input):
- """Provide HTTP HEAD information."""
- uri = input.group(2)
- uri = (uri or '').encode('utf-8')
- if ' ' in uri:
- uri, header = uri.rsplit(' ', 1)
- else: uri, header = uri, None
-
- if not uri and hasattr(phenny, 'last_seen_uri'):
- try: uri = phenny.last_seen_uri[input.sender]
- except KeyError: return phenny.say('?')
-
- if not uri.startswith('htt'):
- uri = 'http://' + uri
- # uri = uri.replace('#!', '?_escaped_fragment_=')
-
- try: info = web.head(uri)
- except IOError: return phenny.say("Can't connect to %s" % uri)
- except httplib.InvalidURL: return phenny.say("Not a valid URI, sorry.")
-
- if not isinstance(info, list):
- try: info = dict(info)
- except TypeError:
- return phenny.reply('Try .head http://example.org/ [optional header]')
- info['Status'] = '200'
- else:
- newInfo = dict(info[0])
- newInfo['Status'] = str(info[1])
- info = newInfo
-
- if header is None:
- data = []
- if info.has_key('Status'):
- data.append(info['Status'])
- if info.has_key('content-type'):
- data.append(info['content-type'].replace('; charset=', ', '))
- if info.has_key('last-modified'):
- modified = info['last-modified']
- modified = time.strptime(modified, '%a, %d %b %Y %H:%M:%S %Z')
- data.append(time.strftime('%Y-%m-%d %H:%M:%S UTC', modified))
- if info.has_key('content-length'):
- data.append(info['content-length'] + ' bytes')
- phenny.reply(', '.join(data))
- else:
- headerlower = header.lower()
- if info.has_key(headerlower):
- phenny.say(header + ': ' + info.get(headerlower))
- else:
- msg = 'There was no %s header in the response.' % header
- phenny.say(msg)
+def head(phenny, input):
+ """Provide HTTP HEAD information."""
+ uri = input.group(2)
+ uri = (uri or '').encode('utf-8')
+ if ' ' in uri:
+ uri, header = uri.rsplit(' ', 1)
+ else: uri, header = uri, None
+
+ if not uri and hasattr(phenny, 'last_seen_uri'):
+ try: uri = phenny.last_seen_uri[input.sender]
+ except KeyError: return phenny.say('?')
+
+ if not uri.startswith('htt'):
+ uri = 'http://' + uri
+ # uri = uri.replace('#!', '?_escaped_fragment_=')
+
+ try: info = web.head(uri)
+ except IOError: return phenny.say("Can't connect to %s" % uri)
+ except httplib.InvalidURL: return phenny.say("Not a valid URI, sorry.")
+
+ if not isinstance(info, list):
+ try: info = dict(info)
+ except TypeError:
+ return phenny.reply('Try .head http://example.org/ [optional header]')
+ info['Status'] = '200'
+ else:
+ newInfo = dict(info[0])
+ newInfo['Status'] = str(info[1])
+ info = newInfo
+
+ if header is None:
+ data = []
+ if info.has_key('Status'):
+ data.append(info['Status'])
+ if info.has_key('content-type'):
+ data.append(info['content-type'].replace('; charset=', ', '))
+ if info.has_key('last-modified'):
+ modified = info['last-modified']
+ modified = time.strptime(modified, '%a, %d %b %Y %H:%M:%S %Z')
+ data.append(time.strftime('%Y-%m-%d %H:%M:%S UTC', modified))
+ if info.has_key('content-length'):
+ data.append(info['content-length'] + ' bytes')
+ phenny.reply(', '.join(data))
+ else:
+ headerlower = header.lower()
+ if info.has_key(headerlower):
+ phenny.say(header + ': ' + info.get(headerlower))
+ else:
+ msg = 'There was no %s header in the response.' % header
+ phenny.say(msg)
head.commands = ['head']
head.example = '.head http://www.w3.org/'
@@ -69,121 +69,121 @@ r_title = re.compile(r'(?ims)<title[^>]*>(.*?)</title\s*>')
r_entity = re.compile(r'&[A-Za-z0-9#]+;')
@deprecated
-def f_title(self, origin, match, args):
- """.title <URI> - Return the title of URI."""
- uri = match.group(2)
- uri = (uri or '').encode('utf-8')
-
- if not uri and hasattr(self, 'last_seen_uri'):
- uri = self.last_seen_uri.get(origin.sender)
- if not uri:
- return self.msg(origin.sender, 'I need a URI to give the title of...')
-
- if not ':' in uri:
- uri = 'http://' + uri
- uri = uri.replace('#!', '?_escaped_fragment_=')
-
- localhost = [
- 'http://localhost/', 'http://localhost:80/',
- 'http://localhost:8080/', 'http://127.0.0.1/',
- 'http://127.0.0.1:80/', 'http://127.0.0.1:8080/',
- 'https://localhost/', 'https://localhost:80/',
- 'https://localhost:8080/', 'https://127.0.0.1/',
- 'https://127.0.0.1:80/', 'https://127.0.0.1:8080/',
- ]
- for s in localhost:
- if uri.startswith(s):
- return phenny.reply('Sorry, access forbidden.')
-
- try:
- redirects = 0
- while True:
- headers = {
- 'Accept': 'text/html',
- 'User-Agent': 'Mozilla/5.0 (Phenny)'
- }
- req = urllib2.Request(uri, headers=headers)
- u = urllib2.urlopen(req)
- info = u.info()
- u.close()
- # info = web.head(uri)
-
- if not isinstance(info, list):
- status = '200'
- else:
- status = str(info[1])
- info = info[0]
- if status.startswith('3'):
- uri = urlparse.urljoin(uri, info['Location'])
- else: break
-
- redirects += 1
- if redirects >= 25:
- self.msg(origin.sender, origin.nick + ": Too many redirects")
+def f_title(self, origin, match, args):
+ """.title <URI> - Return the title of URI."""
+ uri = match.group(2)
+ uri = (uri or '').encode('utf-8')
+
+ if not uri and hasattr(self, 'last_seen_uri'):
+ uri = self.last_seen_uri.get(origin.sender)
+ if not uri:
+ return self.msg(origin.sender, 'I need a URI to give the title of...')
+
+ if not ':' in uri:
+ uri = 'http://' + uri
+ uri = uri.replace('#!', '?_escaped_fragment_=')
+
+ localhost = [
+ 'http://localhost/', 'http://localhost:80/',
+ 'http://localhost:8080/', 'http://127.0.0.1/',
+ 'http://127.0.0.1:80/', 'http://127.0.0.1:8080/',
+ 'https://localhost/', 'https://localhost:80/',
+ 'https://localhost:8080/', 'https://127.0.0.1/',
+ 'https://127.0.0.1:80/', 'https://127.0.0.1:8080/',
+ ]
+ for s in localhost:
+ if uri.startswith(s):
+ return phenny.reply('Sorry, access forbidden.')
+
+ try:
+ redirects = 0
+ while True:
+ headers = {
+ 'Accept': 'text/html',
+ 'User-Agent': 'Mozilla/5.0 (Phenny)'
+ }
+ req = urllib2.Request(uri, headers=headers)
+ u = urllib2.urlopen(req)
+ info = u.info()
+ u.close()
+ # info = web.head(uri)
+
+ if not isinstance(info, list):
+ status = '200'
+ else:
+ status = str(info[1])
+ info = info[0]
+ if status.startswith('3'):
+ uri = urlparse.urljoin(uri, info['Location'])
+ else: break
+
+ redirects += 1
+ if redirects >= 25:
+ self.msg(origin.sender, origin.nick + ": Too many redirects")
+ return
+
+ try: mtype = info['content-type']
+ except:
+ err = ": Couldn't get the Content-Type, sorry"
+ return self.msg(origin.sender, origin.nick + err)
+ if not (('/html' in mtype) or ('/xhtml' in mtype)):
+ self.msg(origin.sender, origin.nick + ": Document isn't HTML")
return
- try: mtype = info['content-type']
- except:
- err = ": Couldn't get the Content-Type, sorry"
- return self.msg(origin.sender, origin.nick + err)
- if not (('/html' in mtype) or ('/xhtml' in mtype)):
- self.msg(origin.sender, origin.nick + ": Document isn't HTML")
- return
-
- u = urllib2.urlopen(req)
- bytes = u.read(262144)
- u.close()
-
- except IOError:
- self.msg(origin.sender, "Can't connect to %s" % uri)
- return
-
- m = r_title.search(bytes)
- if m:
- title = m.group(1)
- title = title.strip()
- title = title.replace('\t', ' ')
- title = title.replace('\r', ' ')
- title = title.replace('\n', ' ')
- while ' ' in title:
- title = title.replace(' ', ' ')
- if len(title) > 200:
- title = title[:200] + '[...]'
-
- def e(m):
- entity = m.group(0)
- if entity.startswith('&#x'):
- cp = int(entity[3:-1], 16)
- return unichr(cp).encode('utf-8')
- elif entity.startswith('&#'):
- cp = int(entity[2:-1])
- return unichr(cp).encode('utf-8')
- else:
- char = name2codepoint[entity[1:-1]]
- return unichr(char).encode('utf-8')
- title = r_entity.sub(e, title)
-
- if title:
- try: title.decode('utf-8')
- except:
- try: title = title.decode('iso-8859-1').encode('utf-8')
- except: title = title.decode('cp1252').encode('utf-8')
- else: pass
- else: title = '[The title is empty.]'
-
- title = title.replace('\n', '')
- title = title.replace('\r', '')
- self.msg(origin.sender, origin.nick + ': ' + title)
- else: self.msg(origin.sender, origin.nick + ': No title found')
+ u = urllib2.urlopen(req)
+ bytes = u.read(262144)
+ u.close()
+
+ except IOError:
+ self.msg(origin.sender, "Can't connect to %s" % uri)
+ return
+
+ m = r_title.search(bytes)
+ if m:
+ title = m.group(1)
+ title = title.strip()
+ title = title.replace('\t', ' ')
+ title = title.replace('\r', ' ')
+ title = title.replace('\n', ' ')
+ while ' ' in title:
+ title = title.replace(' ', ' ')
+ if len(title) > 200:
+ title = title[:200] + '[...]'
+
+ def e(m):
+ entity = m.group(0)
+ if entity.startswith('&#x'):
+ cp = int(entity[3:-1], 16)
+ return unichr(cp).encode('utf-8')
+ elif entity.startswith('&#'):
+ cp = int(entity[2:-1])
+ return unichr(cp).encode('utf-8')
+ else:
+ char = name2codepoint[entity[1:-1]]
+ return unichr(char).encode('utf-8')
+ title = r_entity.sub(e, title)
+
+ if title:
+ try: title.decode('utf-8')
+ except:
+ try: title = title.decode('iso-8859-1').encode('utf-8')
+ except: title = title.decode('cp1252').encode('utf-8')
+ else: pass
+ else: title = '[The title is empty.]'
+
+ title = title.replace('\n', '')
+ title = title.replace('\r', '')
+ self.msg(origin.sender, origin.nick + ': ' + title)
+ else: self.msg(origin.sender, origin.nick + ': No title found')
f_title.commands = ['title']
-def noteuri(phenny, input):
- uri = input.group(1).encode('utf-8')
- if not hasattr(phenny.bot, 'last_seen_uri'):
- phenny.bot.last_seen_uri = {}
- phenny.bot.last_seen_uri[input.sender] = uri
+def noteuri(phenny, input):
+ uri = input.group(1).encode('utf-8')
+ if not hasattr(phenny.bot, 'last_seen_uri'):
+ phenny.bot.last_seen_uri = {}
+ phenny.bot.last_seen_uri[input.sender] = uri
noteuri.rule = r'.*(http[s]?://[^<> "\x01]+)[,.]?'
noteuri.priority = 'low'
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/info.py b/modules/info.py
index dbf2d44..1e41864 100755
--- a/modules/info.py
+++ b/modules/info.py
@@ -7,83 +7,83 @@ Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/
"""
-def doc(phenny, input):
- """Shows a command's documentation, and possibly an example."""
- name = input.group(1)
- name = name.lower()
+def doc(phenny, input):
+ """Shows a command's documentation, and possibly an example."""
+ name = input.group(1)
+ name = name.lower()
- if phenny.doc.has_key(name):
- phenny.reply(phenny.doc[name][0])
- if phenny.doc[name][1]:
- phenny.say('e.g. ' + phenny.doc[name][1])
+ if phenny.doc.has_key(name):
+ phenny.reply(phenny.doc[name][0])
+ if phenny.doc[name][1]:
+ phenny.say('e.g. ' + phenny.doc[name][1])
doc.rule = ('$nick', '(?i)(?:help|doc) +([A-Za-z]+)(?:\?+)?$')
doc.example = '$nickname: doc tell?'
doc.priority = 'low'
-def commands(phenny, input):
- # This function only works in private message
- if input.sender.startswith('#'): return
- names = ', '.join(sorted(phenny.doc.iterkeys()))
- phenny.say('Commands I recognise: ' + names + '.')
- phenny.say(("For help, do '%s: help example?' where example is the " +
- "name of the command you want help for.") % phenny.nick)
+def commands(phenny, input):
+ # This function only works in private message
+ if input.sender.startswith('#'): return
+ names = ', '.join(sorted(phenny.doc.iterkeys()))
+ phenny.say('Commands I recognise: ' + names + '.')
+ phenny.say(("For help, do '%s: help example?' where example is the " +
+ "name of the command you want help for.") % phenny.nick)
commands.commands = ['commands']
commands.priority = 'low'
-def help(phenny, input):
- response = (
- 'Hi, I\'m a bot. Say ".commands" to me in private for a list ' +
- 'of my commands, or see http://inamidst.com/phenny/ for more ' +
- 'general details. My owner is %s.'
- ) % phenny.config.owner
- phenny.reply(response)
+def help(phenny, input):
+ response = (
+ 'Hi, I\'m a bot. Say ".commands" to me in private for a list ' +
+ 'of my commands, or see http://inamidst.com/phenny/ for more ' +
+ 'general details. My owner is %s.'
+ ) % phenny.config.owner
+ phenny.reply(response)
help.rule = ('$nick', r'(?i)help(?:[?!]+)?$')
help.priority = 'low'
-def stats(phenny, input):
- """Show information on command usage patterns."""
- commands = {}
- users = {}
- channels = {}
+def stats(phenny, input):
+ """Show information on command usage patterns."""
+ commands = {}
+ users = {}
+ channels = {}
- ignore = set(['f_note', 'startup', 'message', 'noteuri'])
- for (name, user), count in phenny.stats.items():
- if name in ignore: continue
- if not user: continue
+ ignore = set(['f_note', 'startup', 'message', 'noteuri'])
+ for (name, user), count in phenny.stats.items():
+ if name in ignore: continue
+ if not user: continue
- if not user.startswith('#'):
- try: users[user] += count
- except KeyError: users[user] = count
- else:
- try: commands[name] += count
- except KeyError: commands[name] = count
+ if not user.startswith('#'):
+ try: users[user] += count
+ except KeyError: users[user] = count
+ else:
+ try: commands[name] += count
+ except KeyError: commands[name] = count
- try: channels[user] += count
- except KeyError: channels[user] = count
+ try: channels[user] += count
+ except KeyError: channels[user] = count
- comrank = sorted([(b, a) for (a, b) in commands.iteritems()], reverse=True)
- userank = sorted([(b, a) for (a, b) in users.iteritems()], reverse=True)
- charank = sorted([(b, a) for (a, b) in channels.iteritems()], reverse=True)
+ comrank = sorted([(b, a) for (a, b) in commands.iteritems()], reverse=True)
+ userank = sorted([(b, a) for (a, b) in users.iteritems()], reverse=True)
+ charank = sorted([(b, a) for (a, b) in channels.iteritems()], reverse=True)
- # most heavily used commands
- creply = 'most used commands: '
- for count, command in comrank[:10]:
- creply += '%s (%s), ' % (command, count)
- phenny.say(creply.rstrip(', '))
+ # most heavily used commands
+ creply = 'most used commands: '
+ for count, command in comrank[:10]:
+ creply += '%s (%s), ' % (command, count)
+ phenny.say(creply.rstrip(', '))
- # most heavy users
- reply = 'power users: '
- for count, user in userank[:10]:
- reply += '%s (%s), ' % (user, count)
- phenny.say(reply.rstrip(', '))
+ # most heavy users
+ reply = 'power users: '
+ for count, user in userank[:10]:
+ reply += '%s (%s), ' % (user, count)
+ phenny.say(reply.rstrip(', '))
- # most heavy channels
- chreply = 'power channels: '
- for count, channel in charank[:3]:
- chreply += '%s (%s), ' % (channel, count)
- phenny.say(chreply.rstrip(', '))
+ # most heavy channels
+ chreply = 'power channels: '
+ for count, channel in charank[:3]:
+ chreply += '%s (%s), ' % (channel, count)
+ phenny.say(chreply.rstrip(', '))
stats.commands = ['stats']
stats.priority = 'low'
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/oblique.py b/modules/oblique.py
index d93446e..3a5f35a 100755
--- a/modules/oblique.py
+++ b/modules/oblique.py
@@ -15,105 +15,105 @@ definitions = 'https://github.com/nslater/oblique/wiki'
r_item = re.compile(r'(?i)<li>(.*?)</li>')
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('&amp;', '&')
- return result
-
-def service(phenny, input, command, args):
- t = o.services[command]
- template = t.replace('${args}', urllib.quote(args.encode('utf-8'), ''))
- template = template.replace('${nick}', urllib.quote(input.nick, ''))
- uri = template.replace('${sender}', urllib.quote(input.sender, ''))
-
- info = web.head(uri)
- if isinstance(info, list):
- info = info[0]
- if not 'text/plain' in info.get('content-type', '').lower():
- return phenny.reply("Sorry, the service didn't respond in plain text.")
- bytes = web.get(uri)
- lines = bytes.splitlines()
- if not lines:
- return phenny.reply("Sorry, the service didn't respond any output.")
- try: line = lines[0].encode('utf-8')[:350]
- except: line = lines[0][:250]
- phenny.say(line)
-
-def refresh(phenny):
- if hasattr(phenny.config, 'services'):
- services = phenny.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(phenny, input):
- """Call a webservice."""
- text = input.group(2)
-
- if (not o.services) or (text == 'refresh'):
- length, added = refresh(phenny)
- if text == 'refresh':
- msg = 'Okay, found %s services.' % length
- if added:
- msg += ' Added: ' + ', '.join(sorted(added)[:5])
- if len(added) > 5: msg += ', &c.'
- return phenny.reply(msg)
-
- if not text:
- return phenny.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 phenny.reply(msg)
-
- if not o.services.has_key(command):
- return phenny.reply('Service not found in %s' % o.serviceURI)
-
- if hasattr(phenny.config, 'external'):
- default = phenny.config.external.get('*')
- manifest = phenny.config.external.get(input.sender, default)
- if manifest:
- commands = set(manifest)
- if (command not in commands) and (manifest[0] != '!'):
- return phenny.reply('Sorry, %s is not whitelisted' % command)
- elif (command in commands) and (manifest[0] == '!'):
- return phenny.reply('Sorry, %s is blacklisted' % command)
- service(phenny, input, command, args)
+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('&amp;', '&')
+ return result
+
+def service(phenny, input, command, args):
+ t = o.services[command]
+ template = t.replace('${args}', urllib.quote(args.encode('utf-8'), ''))
+ template = template.replace('${nick}', urllib.quote(input.nick, ''))
+ uri = template.replace('${sender}', urllib.quote(input.sender, ''))
+
+ info = web.head(uri)
+ if isinstance(info, list):
+ info = info[0]
+ if not 'text/plain' in info.get('content-type', '').lower():
+ return phenny.reply("Sorry, the service didn't respond in plain text.")
+ bytes = web.get(uri)
+ lines = bytes.splitlines()
+ if not lines:
+ return phenny.reply("Sorry, the service didn't respond any output.")
+ try: line = lines[0].encode('utf-8')[:350]
+ except: line = lines[0][:250]
+ phenny.say(line)
+
+def refresh(phenny):
+ if hasattr(phenny.config, 'services'):
+ services = phenny.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(phenny, input):
+ """Call a webservice."""
+ text = input.group(2)
+
+ if (not o.services) or (text == 'refresh'):
+ length, added = refresh(phenny)
+ if text == 'refresh':
+ msg = 'Okay, found %s services.' % length
+ if added:
+ msg += ' Added: ' + ', '.join(sorted(added)[:5])
+ if len(added) > 5: msg += ', &c.'
+ return phenny.reply(msg)
+
+ if not text:
+ return phenny.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 phenny.reply(msg)
+
+ if not o.services.has_key(command):
+ return phenny.reply('Service not found in %s' % o.serviceURI)
+
+ if hasattr(phenny.config, 'external'):
+ default = phenny.config.external.get('*')
+ manifest = phenny.config.external.get(input.sender, default)
+ if manifest:
+ commands = set(manifest)
+ if (command not in commands) and (manifest[0] != '!'):
+ return phenny.reply('Sorry, %s is not whitelisted' % command)
+ elif (command in commands) and (manifest[0] == '!'):
+ return phenny.reply('Sorry, %s is blacklisted' % command)
+ service(phenny, input, command, args)
o.commands = ['o']
o.example = '.o servicename arg1 arg2 arg3'
o.services = {}
o.serviceURI = None
-def snippet(phenny, input):
- if not o.services:
- refresh(phenny)
-
- search = urllib.quote(input.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(" + \
- "'&quot;', '\x22')), convertEntities=True)"
- service(phenny, input, 'py', py)
+def snippet(phenny, input):
+ if not o.services:
+ refresh(phenny)
+
+ search = urllib.quote(input.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(" + \
+ "'&quot;', '\x22')), convertEntities=True)"
+ service(phenny, input, 'py', py)
snippet.commands = ['snippet']
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/ping.py b/modules/ping.py
index 23219ac..9ce7429 100755
--- a/modules/ping.py
+++ b/modules/ping.py
@@ -7,17 +7,17 @@ About: http://inamidst.com/phenny/
import random
-def hello(phenny, input):
- greeting = random.choice(('Hi', 'Hey', 'Hello'))
- punctuation = random.choice(('', '!'))
- phenny.say(greeting + ' ' + input.nick + punctuation)
+def hello(phenny, input):
+ greeting = random.choice(('Hi', 'Hey', 'Hello'))
+ punctuation = random.choice(('', '!'))
+ phenny.say(greeting + ' ' + input.nick + punctuation)
hello.rule = r'(?i)(hi|hello|hey) $nickname[ \t]*$'
-def interjection(phenny, input):
- phenny.say(input.nick + '!')
+def interjection(phenny, input):
+ phenny.say(input.nick + '!')
interjection.rule = r'$nickname!'
interjection.priority = 'high'
interjection.thread = False
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/reload.py b/modules/reload.py
index dfd0e8e..bef2f19 100755
--- a/modules/reload.py
+++ b/modules/reload.py
@@ -10,46 +10,46 @@ http://inamidst.com/phenny/
import sys, os.path, time, imp
import irc
-def f_reload(phenny, input):
- """Reloads a module, for use by admins only."""
- if not input.admin: return
-
- name = input.group(2)
- if name == phenny.config.owner:
- return phenny.reply('What?')
-
- if (not name) or (name == '*'):
- phenny.variables = None
- phenny.commands = None
- phenny.setup()
- return phenny.reply('done')
-
- if not sys.modules.has_key(name):
- return phenny.reply('%s: no such module!' % name)
-
- # Thanks to moot for prodding me on this
- path = sys.modules[name].__file__
- if path.endswith('.pyc') or path.endswith('.pyo'):
- path = path[:-1]
- if not os.path.isfile(path):
- return phenny.reply('Found %s, but not the source file' % name)
-
- module = imp.load_source(name, path)
- sys.modules[name] = module
- if hasattr(module, 'setup'):
- module.setup(phenny)
-
- mtime = os.path.getmtime(module.__file__)
- modified = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(mtime))
-
- phenny.register(vars(module))
- phenny.bind_commands()
-
- phenny.reply('%r (version: %s)' % (module, modified))
+def f_reload(phenny, input):
+ """Reloads a module, for use by admins only."""
+ if not input.admin: return
+
+ name = input.group(2)
+ if name == phenny.config.owner:
+ return phenny.reply('What?')
+
+ if (not name) or (name == '*'):
+ phenny.variables = None
+ phenny.commands = None
+ phenny.setup()
+ return phenny.reply('done')
+
+ if not sys.modules.has_key(name):
+ return phenny.reply('%s: no such module!' % name)
+
+ # Thanks to moot for prodding me on this
+ path = sys.modules[name].__file__
+ if path.endswith('.pyc') or path.endswith('.pyo'):
+ path = path[:-1]
+ if not os.path.isfile(path):
+ return phenny.reply('Found %s, but not the source file' % name)
+
+ module = imp.load_source(name, path)
+ sys.modules[name] = module
+ if hasattr(module, 'setup'):
+ module.setup(phenny)
+
+ mtime = os.path.getmtime(module.__file__)
+ modified = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(mtime))
+
+ phenny.register(vars(module))
+ phenny.bind_commands()
+
+ phenny.reply('%r (version: %s)' % (module, modified))
f_reload.name = 'reload'
f_reload.rule = ('$nick', ['reload'], r'(\S+)?')
f_reload.priority = 'low'
f_reload.thread = False
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/remind.py b/modules/remind.py
index fbfd258..871d585 100755
--- a/modules/remind.py
+++ b/modules/remind.py
@@ -9,133 +9,133 @@ http://inamidst.com/phenny/
import os, re, time, threading
-def filename(self):
- name = self.nick + '-' + self.config.host + '.reminders.db'
- return os.path.join(os.path.expanduser('~/.phenny'), name)
-
-def load_database(name):
- data = {}
- if os.path.isfile(name):
- f = open(name, 'rb')
- for line in f:
- unixtime, channel, nick, message = line.split('\t')
- message = message.rstrip('\n')
- t = int(unixtime)
- reminder = (channel, nick, message)
- try: data[t].append(reminder)
- except KeyError: data[t] = [reminder]
- f.close()
- return data
-
-def dump_database(name, data):
- f = open(name, 'wb')
- for unixtime, reminders in data.iteritems():
- for channel, nick, message in reminders:
- f.write('%s\t%s\t%s\t%s\n' % (unixtime, channel, nick, message))
- f.close()
-
-def setup(phenny):
- phenny.rfn = filename(phenny)
-
- # phenny.sending.acquire()
- phenny.rdb = load_database(phenny.rfn)
- # phenny.sending.release()
-
- def monitor(phenny):
- time.sleep(5)
- while True:
- now = int(time.time())
- unixtimes = [int(key) for key in phenny.rdb]
- oldtimes = [t for t in unixtimes if t <= now]
- if oldtimes:
- for oldtime in oldtimes:
- for (channel, nick, message) in phenny.rdb[oldtime]:
- if message:
- phenny.msg(channel, nick + ': ' + message)
- else: phenny.msg(channel, nick + '!')
- del phenny.rdb[oldtime]
-
- # phenny.sending.acquire()
- dump_database(phenny.rfn, phenny.rdb)
- # phenny.sending.release()
- time.sleep(2.5)
-
- targs = (phenny,)
- t = threading.Thread(target=monitor, args=targs)
- t.start()
+def filename(self):
+ name = self.nick + '-' + self.config.host + '.reminders.db'
+ return os.path.join(os.path.expanduser('~/.phenny'), name)
+
+def load_database(name):
+ data = {}
+ if os.path.isfile(name):
+ f = open(name, 'rb')
+ for line in f:
+ unixtime, channel, nick, message = line.split('\t')
+ message = message.rstrip('\n')
+ t = int(unixtime)
+ reminder = (channel, nick, message)
+ try: data[t].append(reminder)
+ except KeyError: data[t] = [reminder]
+ f.close()
+ return data
+
+def dump_database(name, data):
+ f = open(name, 'wb')
+ for unixtime, reminders in data.iteritems():
+ for channel, nick, message in reminders:
+ f.write('%s\t%s\t%s\t%s\n' % (unixtime, channel, nick, message))
+ f.close()
+
+def setup(phenny):
+ phenny.rfn = filename(phenny)
+
+ # phenny.sending.acquire()
+ phenny.rdb = load_database(phenny.rfn)
+ # phenny.sending.release()
+
+ def monitor(phenny):
+ time.sleep(5)
+ while True:
+ now = int(time.time())
+ unixtimes = [int(key) for key in phenny.rdb]
+ oldtimes = [t for t in unixtimes if t <= now]
+ if oldtimes:
+ for oldtime in oldtimes:
+ for (channel, nick, message) in phenny.rdb[oldtime]:
+ if message:
+ phenny.msg(channel, nick + ': ' + message)
+ else: phenny.msg(channel, nick + '!')
+ del phenny.rdb[oldtime]
+
+ # phenny.sending.acquire()
+ dump_database(phenny.rfn, phenny.rdb)
+ # phenny.sending.release()
+ time.sleep(2.5)
+
+ targs = (phenny,)
+ t = threading.Thread(target=monitor, args=targs)
+ t.start()
scaling = {
- 'years': 365.25 * 24 * 3600,
- 'year': 365.25 * 24 * 3600,
- 'yrs': 365.25 * 24 * 3600,
- 'y': 365.25 * 24 * 3600,
-
- 'months': 29.53059 * 24 * 3600,
- 'month': 29.53059 * 24 * 3600,
- 'mo': 29.53059 * 24 * 3600,
-
- 'weeks': 7 * 24 * 3600,
- 'week': 7 * 24 * 3600,
- 'wks': 7 * 24 * 3600,
- 'wk': 7 * 24 * 3600,
- 'w': 7 * 24 * 3600,
-
- 'days': 24 * 3600,
- 'day': 24 * 3600,
- 'd': 24 * 3600,
-
- 'hours': 3600,
- 'hour': 3600,
- 'hrs': 3600,
- 'hr': 3600,
- 'h': 3600,
-
- 'minutes': 60,
- 'minute': 60,
- 'mins': 60,
- 'min': 60,
- 'm': 60,
-
- 'seconds': 1,
- 'second': 1,
- 'secs': 1,
- 'sec': 1,
- 's': 1
+ 'years': 365.25 * 24 * 3600,
+ 'year': 365.25 * 24 * 3600,
+ 'yrs': 365.25 * 24 * 3600,
+ 'y': 365.25 * 24 * 3600,
+
+ 'months': 29.53059 * 24 * 3600,
+ 'month': 29.53059 * 24 * 3600,
+ 'mo': 29.53059 * 24 * 3600,
+
+ 'weeks': 7 * 24 * 3600,
+ 'week': 7 * 24 * 3600,
+ 'wks': 7 * 24 * 3600,
+ 'wk': 7 * 24 * 3600,
+ 'w': 7 * 24 * 3600,
+
+ 'days': 24 * 3600,
+ 'day': 24 * 3600,
+ 'd': 24 * 3600,
+
+ 'hours': 3600,
+ 'hour': 3600,
+ 'hrs': 3600,
+ 'hr': 3600,
+ 'h': 3600,
+
+ 'minutes': 60,
+ 'minute': 60,
+ 'mins': 60,
+ 'min': 60,
+ 'm': 60,
+
+ 'seconds': 1,
+ 'second': 1,
+ 'secs': 1,
+ 'sec': 1,
+ 's': 1
}
periods = '|'.join(scaling.keys())
p_command = r'\.in ([0-9]+(?:\.[0-9]+)?)\s?((?:%s)\b)?:?\s?(.*)' % periods
r_command = re.compile(p_command)
-def remind(phenny, input):
- m = r_command.match(input.bytes)
- if not m:
- return phenny.reply("Sorry, didn't understand the input.")
- length, scale, message = m.groups()
+def remind(phenny, input):
+ m = r_command.match(input.bytes)
+ if not m:
+ return phenny.reply("Sorry, didn't understand the input.")
+ length, scale, message = m.groups()
- length = float(length)
- factor = scaling.get(scale, 60)
- duration = length * factor
+ length = float(length)
+ factor = scaling.get(scale, 60)
+ duration = length * factor
- if duration % 1:
- duration = int(duration) + 1
- else: duration = int(duration)
+ if duration % 1:
+ duration = int(duration) + 1
+ else: duration = int(duration)
- t = int(time.time()) + duration
- reminder = (input.sender, input.nick, message)
+ t = int(time.time()) + duration
+ reminder = (input.sender, input.nick, message)
- try: phenny.rdb[t].append(reminder)
- except KeyError: phenny.rdb[t] = [reminder]
+ try: phenny.rdb[t].append(reminder)
+ except KeyError: phenny.rdb[t] = [reminder]
- dump_database(phenny.rfn, phenny.rdb)
+ dump_database(phenny.rfn, phenny.rdb)
- if duration >= 60:
- w = ''
- if duration >= 3600 * 12:
- w += time.strftime(' on %d %b %Y', time.gmtime(t))
- w += time.strftime(' at %H:%MZ', time.gmtime(t))
- phenny.reply('Okay, will remind%s' % w)
- else: phenny.reply('Okay, will remind in %s secs' % duration)
+ if duration >= 60:
+ w = ''
+ if duration >= 3600 * 12:
+ w += time.strftime(' on %d %b %Y', time.gmtime(t))
+ w += time.strftime(' at %H:%MZ', time.gmtime(t))
+ phenny.reply('Okay, will remind%s' % w)
+ else: phenny.reply('Okay, will remind in %s secs' % duration)
remind.commands = ['in']
r_time = re.compile(r'^([0-9]{2}[:.][0-9]{2})')
@@ -145,49 +145,49 @@ import calendar
from clock import TimeZones
def at(phenny, input):
- bytes = input[4:]
+ bytes = input[4:]
- m = r_time.match(bytes)
- if not m:
- return phenny.reply("Sorry, didn't understand the time spec.")
- t = m.group(1).replace('.', ':')
- bytes = bytes[len(t):]
+ m = r_time.match(bytes)
+ if not m:
+ return phenny.reply("Sorry, didn't understand the time spec.")
+ t = m.group(1).replace('.', ':')
+ bytes = bytes[len(t):]
- m = r_zone.match(bytes)
- if not m:
- return phenny.reply("Sorry, didn't understand the zone spec.")
- z = m.group(2)
- bytes = bytes[len(m.group(1)):].strip().encode("utf-8")
+ m = r_zone.match(bytes)
+ if not m:
+ return phenny.reply("Sorry, didn't understand the zone spec.")
+ z = m.group(2)
+ bytes = bytes[len(m.group(1)):].strip().encode("utf-8")
- if z.startswith('+') or z.startswith('-'):
- tz = int(z)
+ if z.startswith('+') or z.startswith('-'):
+ tz = int(z)
- if TimeZones.has_key(z):
- tz = TimeZones[z]
- else: return phenny.reply("Sorry, didn't understand the time zone.")
+ if TimeZones.has_key(z):
+ tz = TimeZones[z]
+ else: return phenny.reply("Sorry, didn't understand the time zone.")
- d = time.strftime("%Y-%m-%d", time.gmtime())
- d = time.strptime(("%s %s" % (d, t)).encode("utf-8"), "%Y-%m-%d %H:%M")
+ d = time.strftime("%Y-%m-%d", time.gmtime())
+ d = time.strptime(("%s %s" % (d, t)).encode("utf-8"), "%Y-%m-%d %H:%M")
- d = int(calendar.timegm(d) - (3600 * tz))
- duration = int((d - time.time()) / 60)
+ d = int(calendar.timegm(d) - (3600 * tz))
+ duration = int((d - time.time()) / 60)
- if duration < 1:
- return phenny.reply("Sorry, that date is this minute or in the past. And only times in the same day are supported!")
+ if duration < 1:
+ return phenny.reply("Sorry, that date is this minute or in the past. And only times in the same day are supported!")
- # phenny.say("%s %s %s" % (t, tz, d))
+ # phenny.say("%s %s %s" % (t, tz, d))
- reminder = (input.sender, input.nick, bytes)
- # phenny.say(str((d, reminder)))
- try: phenny.rdb[d].append(reminder)
- except KeyError: phenny.rdb[d] = [reminder]
+ reminder = (input.sender, input.nick, bytes)
+ # phenny.say(str((d, reminder)))
+ try: phenny.rdb[d].append(reminder)
+ except KeyError: phenny.rdb[d] = [reminder]
- phenny.sending.acquire()
- dump_database(phenny.rfn, phenny.rdb)
- phenny.sending.release()
+ phenny.sending.acquire()
+ dump_database(phenny.rfn, phenny.rdb)
+ phenny.sending.release()
- phenny.reply("Reminding at %s %s - in %s minute(s)" % (t, z, duration))
+ phenny.reply("Reminding at %s %s - in %s minute(s)" % (t, z, duration))
at.commands = ['at']
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/search.py b/modules/search.py
index 5d038af..bd71d71 100755
--- a/modules/search.py
+++ b/modules/search.py
@@ -11,255 +11,255 @@ import re
import web
class Grab(web.urllib.URLopener):
- def __init__(self, *args):
- self.version = 'Mozilla/5.0 (Phenny)'
- web.urllib.URLopener.__init__(self, *args)
- self.addheader('Referer', 'https://github.com/sbp/phenny')
- def http_error_default(self, url, fp, errcode, errmsg, headers):
- return web.urllib.addinfourl(fp, [headers, errcode], "http:" + url)
-
-def google_ajax(query):
- """Search using AjaxSearch, and return its JSON."""
- if isinstance(query, unicode):
- query = query.encode('utf-8')
- uri = 'http://ajax.googleapis.com/ajax/services/search/web'
- args = '?v=1.0&safe=off&q=' + web.urllib.quote(query)
- handler = web.urllib._urlopener
- web.urllib._urlopener = Grab()
- bytes = web.get(uri + args)
- web.urllib._urlopener = handler
- return web.json(bytes)
-
-def google_search(query):
- results = google_ajax(query)
- try: return results['responseData']['results'][0]['unescapedUrl']
- except IndexError: return None
- except TypeError:
- print results
- return False
-
-def google_count(query):
- results = google_ajax(query)
- if not results.has_key('responseData'): return '0'
- if not results['responseData'].has_key('cursor'): return '0'
- if not results['responseData']['cursor'].has_key('estimatedResultCount'):
- return '0'
- return results['responseData']['cursor']['estimatedResultCount']
-
-def formatnumber(n):
- """Format a number with beautiful commas."""
- parts = list(str(n))
- for i in range((len(parts) - 3), 0, -3):
- parts.insert(i, ',')
- return ''.join(parts)
+ def __init__(self, *args):
+ self.version = 'Mozilla/5.0 (Phenny)'
+ web.urllib.URLopener.__init__(self, *args)
+ self.addheader('Referer', 'https://github.com/sbp/phenny')
+ def http_error_default(self, url, fp, errcode, errmsg, headers):
+ return web.urllib.addinfourl(fp, [headers, errcode], "http:" + url)
+
+def google_ajax(query):
+ """Search using AjaxSearch, and return its JSON."""
+ if isinstance(query, unicode):
+ query = query.encode('utf-8')
+ uri = 'http://ajax.googleapis.com/ajax/services/search/web'
+ args = '?v=1.0&safe=off&q=' + web.urllib.quote(query)
+ handler = web.urllib._urlopener
+ web.urllib._urlopener = Grab()
+ bytes = web.get(uri + args)
+ web.urllib._urlopener = handler
+ return web.json(bytes)
+
+def google_search(query):
+ results = google_ajax(query)
+ try: return results['responseData']['results'][0]['unescapedUrl']
+ except IndexError: return None
+ except TypeError:
+ print results
+ return False
+
+def google_count(query):
+ results = google_ajax(query)
+ if not results.has_key('responseData'): return '0'
+ if not results['responseData'].has_key('cursor'): return '0'
+ if not results['responseData']['cursor'].has_key('estimatedResultCount'):
+ return '0'
+ return results['responseData']['cursor']['estimatedResultCount']
+
+def formatnumber(n):
+ """Format a number with beautiful commas."""
+ parts = list(str(n))
+ for i in range((len(parts) - 3), 0, -3):
+ parts.insert(i, ',')
+ return ''.join(parts)
def old_gc(query):
- return formatnumber(google_count(query))
-
-def g(phenny, input):
- """Queries Google for the specified input."""
- query = input.group(2)
- if not query:
- return phenny.reply('.g what?')
- query = query.encode('utf-8')
- uri = google_search(query)
- if uri:
- phenny.reply(uri)
- if not hasattr(phenny.bot, 'last_seen_uri'):
- phenny.bot.last_seen_uri = {}
- phenny.bot.last_seen_uri[input.sender] = uri
- elif uri is False: phenny.reply("Problem getting data from Google.")
- else: phenny.reply("No results found for '%s'." % query)
+ return formatnumber(google_count(query))
+
+def g(phenny, input):
+ """Queries Google for the specified input."""
+ query = input.group(2)
+ if not query:
+ return phenny.reply('.g what?')
+ query = query.encode('utf-8')
+ uri = google_search(query)
+ if uri:
+ phenny.reply(uri)
+ if not hasattr(phenny.bot, 'last_seen_uri'):
+ phenny.bot.last_seen_uri = {}
+ phenny.bot.last_seen_uri[input.sender] = uri
+ elif uri is False: phenny.reply("Problem getting data from Google.")
+ else: phenny.reply("No results found for '%s'." % query)
g.commands = ['g']
g.priority = 'high'
g.example = '.g swhack'
-def oldgc(phenny, input):
- """Returns the number of Google results for the specified input."""
- query = input.group(2)
- if not query:
- return phenny.reply('.gc what?')
- query = query.encode('utf-8')
- num = formatnumber(google_count(query))
- phenny.say(query + ': ' + num)
+def oldgc(phenny, input):
+ """Returns the number of Google results for the specified input."""
+ query = input.group(2)
+ if not query:
+ return phenny.reply('.gc what?')
+ query = query.encode('utf-8')
+ num = formatnumber(google_count(query))
+ phenny.say(query + ': ' + num)
oldgc.commands = ['ogc', 'oldgc']
oldgc.example = '.oldgc extrapolate'
r_query = re.compile(
- r'\+?"[^"\\]*(?:\\.[^"\\]*)*"|\[[^]\\]*(?:\\.[^]\\]*)*\]|\S+'
+ r'\+?"[^"\\]*(?:\\.[^"\\]*)*"|\[[^]\\]*(?:\\.[^]\\]*)*\]|\S+'
)
-def gcs(phenny, input):
- if not input.group(2):
- return phenny.reply("Nothing to compare.")
- queries = r_query.findall(input.group(2))
- if len(queries) > 6:
- return phenny.reply('Sorry, can only compare up to six things.')
-
- results = []
- for i, query in enumerate(queries):
- query = query.strip('[]')
- query = query.encode('utf-8')
- n = int((formatnumber(google_count(query)) or '0').replace(',', ''))
- results.append((n, query))
- if i >= 2: __import__('time').sleep(0.25)
- if i >= 4: __import__('time').sleep(0.25)
-
- results = [(term, n) for (n, term) in reversed(sorted(results))]
- reply = ', '.join('%s (%s)' % (t, formatnumber(n)) for (t, n) in results)
- phenny.say(reply)
+def gcs(phenny, input):
+ if not input.group(2):
+ return phenny.reply("Nothing to compare.")
+ queries = r_query.findall(input.group(2))
+ if len(queries) > 6:
+ return phenny.reply('Sorry, can only compare up to six things.')
+
+ results = []
+ for i, query in enumerate(queries):
+ query = query.strip('[]')
+ query = query.encode('utf-8')
+ n = int((formatnumber(google_count(query)) or '0').replace(',', ''))
+ results.append((n, query))
+ if i >= 2: __import__('time').sleep(0.25)
+ if i >= 4: __import__('time').sleep(0.25)
+
+ results = [(term, n) for (n, term) in reversed(sorted(results))]
+ reply = ', '.join('%s (%s)' % (t, formatnumber(n)) for (t, n) in results)
+ phenny.say(reply)
gcs.commands = ['gcs', 'comp']
r_bing = re.compile(r'<h3><a href="([^"]+)"')
-def bing_search(query, lang='en-GB'):
- query = web.urllib.quote(query)
- base = 'http://www.bing.com/search?mkt=%s&q=' % lang
- bytes = web.get(base + query)
- for result in r_bing.findall(bytes):
- if "r.msn.com/" in result: continue
- return result
-
-def bing(phenny, input):
- """Queries Bing for the specified input."""
- query = input.group(2)
- if query.startswith(':'):
- lang, query = query.split(' ', 1)
- lang = lang[1:]
- else: lang = 'en-GB'
- if not query:
- return phenny.reply('.bing what?')
-
- query = query.encode('utf-8')
- uri = bing_search(query, lang)
- if uri:
- phenny.reply(uri)
- if not hasattr(phenny.bot, 'last_seen_uri'):
- phenny.bot.last_seen_uri = {}
- phenny.bot.last_seen_uri[input.sender] = uri
- else: phenny.reply("No results found for '%s'." % query)
+def bing_search(query, lang='en-GB'):
+ query = web.urllib.quote(query)
+ base = 'http://www.bing.com/search?mkt=%s&q=' % lang
+ bytes = web.get(base + query)
+ for result in r_bing.findall(bytes):
+ if "r.msn.com/" in result: continue
+ return result
+
+def bing(phenny, input):
+ """Queries Bing for the specified input."""
+ query = input.group(2)
+ if query.startswith(':'):
+ lang, query = query.split(' ', 1)
+ lang = lang[1:]
+ else: lang = 'en-GB'
+ if not query:
+ return phenny.reply('.bing what?')
+
+ query = query.encode('utf-8')
+ uri = bing_search(query, lang)
+ if uri:
+ phenny.reply(uri)
+ if not hasattr(phenny.bot, 'last_seen_uri'):
+ phenny.bot.last_seen_uri = {}
+ phenny.bot.last_seen_uri[input.sender] = uri
+ else: phenny.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.urllib.quote(query)
- uri = 'http://duckduckgo.com/html/?q=%s&kl=uk-en' % query
- bytes = web.get(uri)
- m = r_duck.search(bytes)
- if m: return web.decode(m.group(1))
-
-def duck(phenny, input):
- query = input.group(2)
- if not query: return phenny.reply('.ddg what?')
-
- query = query.encode('utf-8')
- uri = duck_search(query)
- if uri:
- phenny.reply(uri)
- if not hasattr(phenny.bot, 'last_seen_uri'):
- phenny.bot.last_seen_uri = {}
- phenny.bot.last_seen_uri[input.sender] = uri
- else: phenny.reply("No results found for '%s'." % query)
+def duck_search(query):
+ query = query.replace('!', '')
+ query = web.urllib.quote(query)
+ uri = 'http://duckduckgo.com/html/?q=%s&kl=uk-en' % query
+ bytes = web.get(uri)
+ m = r_duck.search(bytes)
+ if m: return web.decode(m.group(1))
+
+def duck(phenny, input):
+ query = input.group(2)
+ if not query: return phenny.reply('.ddg what?')
+
+ query = query.encode('utf-8')
+ uri = duck_search(query)
+ if uri:
+ phenny.reply(uri)
+ if not hasattr(phenny.bot, 'last_seen_uri'):
+ phenny.bot.last_seen_uri = {}
+ phenny.bot.last_seen_uri[input.sender] = uri
+ else: phenny.reply("No results found for '%s'." % query)
duck.commands = ['duck', 'ddg']
-def search(phenny, input):
- if not input.group(2):
- return phenny.reply('.search for what?')
- query = input.group(2).encode('utf-8')
- gu = google_search(query) or '-'
- bu = bing_search(query) or '-'
- du = duck_search(query) or '-'
-
- if (gu == bu) and (bu == du):
- result = '%s (g, b, d)' % gu
- elif (gu == bu):
- result = '%s (g, b), %s (d)' % (gu, du)
- elif (bu == du):
- result = '%s (b, d), %s (g)' % (bu, gu)
- elif (gu == du):
- result = '%s (g, d), %s (b)' % (gu, bu)
- else:
- if len(gu) > 250: gu = '(extremely long link)'
- if len(bu) > 150: bu = '(extremely long link)'
- if len(du) > 150: du = '(extremely long link)'
- result = '%s (g), %s (b), %s (d)' % (gu, bu, du)
-
- phenny.reply(result)
+def search(phenny, input):
+ if not input.group(2):
+ return phenny.reply('.search for what?')
+ query = input.group(2).encode('utf-8')
+ gu = google_search(query) or '-'
+ bu = bing_search(query) or '-'
+ du = duck_search(query) or '-'
+
+ if (gu == bu) and (bu == du):
+ result = '%s (g, b, d)' % gu
+ elif (gu == bu):
+ result = '%s (g, b), %s (d)' % (gu, du)
+ elif (bu == du):
+ result = '%s (b, d), %s (g)' % (bu, gu)
+ elif (gu == du):
+ result = '%s (g, d), %s (b)' % (gu, bu)
+ else:
+ if len(gu) > 250: gu = '(extremely long link)'
+ if len(bu) > 150: bu = '(extremely long link)'
+ if len(du) > 150: du = '(extremely long link)'
+ result = '%s (g), %s (b), %s (d)' % (gu, bu, du)
+
+ phenny.reply(result)
search.commands = ['search']
-def suggest(phenny, input):
- if not input.group(2):
- return phenny.reply("No query term.")
- query = input.group(2).encode('utf-8')
- uri = 'http://websitedev.de/temp-bin/suggest.pl?q='
- answer = web.get(uri + web.urllib.quote(query).replace('+', '%2B'))
- if answer:
- phenny.say(answer)
- else: phenny.reply('Sorry, no result.')
+def suggest(phenny, input):
+ if not input.group(2):
+ return phenny.reply("No query term.")
+ query = input.group(2).encode('utf-8')
+ uri = 'http://websitedev.de/temp-bin/suggest.pl?q='
+ answer = web.get(uri + web.urllib.quote(query).replace('+', '%2B'))
+ if answer:
+ phenny.say(answer)
+ else: phenny.reply('Sorry, no result.')
suggest.commands = ['suggest']
def new_gc(query):
- uri = 'https://www.google.com/search?hl=en&q='
- uri = uri + web.urllib.quote(query).replace('+', '%2B')
- # if '"' in query: uri += '&tbs=li:1'
- bytes = web.get(uri)
- if "did not match any documents" in bytes:
- return "0"
- for result in re.compile(r'(?ims)([0-9,]+) results?').findall(bytes):
- return result
- return None
+ uri = 'https://www.google.com/search?hl=en&q='
+ uri = uri + web.urllib.quote(query).replace('+', '%2B')
+ # if '"' in query: uri += '&tbs=li:1'
+ bytes = web.get(uri)
+ if "did not match any documents" in bytes:
+ return "0"
+ for result in re.compile(r'(?ims)([0-9,]+) results?').findall(bytes):
+ return result
+ return None
def newest_gc(query):
- uri = 'https://www.google.com/search?hl=en&q='
- uri = uri + web.urllib.quote(query).replace('+', '%2B')
- bytes = web.get(uri + '&tbs=li:1')
- if "did not match any documents" in bytes:
- return "0"
- for result in re.compile(r'(?ims)([0-9,]+) results?').findall(bytes):
- return result
- return None
+ uri = 'https://www.google.com/search?hl=en&q='
+ uri = uri + web.urllib.quote(query).replace('+', '%2B')
+ bytes = web.get(uri + '&tbs=li:1')
+ if "did not match any documents" in bytes:
+ return "0"
+ for result in re.compile(r'(?ims)([0-9,]+) results?').findall(bytes):
+ return result
+ return None
def newerest_gc(query):
- uri = 'https://www.google.com/search?hl=en&q='
- uri = uri + web.urllib.quote(query).replace('+', '%2B')
- bytes = web.get(uri + '&prmd=imvns&start=950')
- if "did not match any documents" in bytes:
- return "0"
- for result in re.compile(r'(?ims)([0-9,]+) results?').findall(bytes):
- return result
- return None
+ uri = 'https://www.google.com/search?hl=en&q='
+ uri = uri + web.urllib.quote(query).replace('+', '%2B')
+ bytes = web.get(uri + '&prmd=imvns&start=950')
+ if "did not match any documents" in bytes:
+ return "0"
+ for result in re.compile(r'(?ims)([0-9,]+) results?').findall(bytes):
+ return result
+ return None
def ngc(phenny, input):
- if not input.group(2):
- return phenny.reply("No query term.")
- query = input.group(2).encode('utf-8')
- result = new_gc(query)
- if result:
- phenny.say(query + ": " + result)
- else: phenny.reply("Sorry, couldn't get a result.")
+ if not input.group(2):
+ return phenny.reply("No query term.")
+ query = input.group(2).encode('utf-8')
+ result = new_gc(query)
+ if result:
+ phenny.say(query + ": " + result)
+ else: phenny.reply("Sorry, couldn't get a result.")
ngc.commands = ['ngc']
ngc.priority = 'high'
ngc.example = '.ngc extrapolate'
def gc(phenny, input):
- if not input.group(2):
- return phenny.reply("No query term.")
- query = input.group(2).encode('utf-8')
- result = query + ": "
- result += (old_gc(query) or "?") + " (api)"
- result += ", " + (newerest_gc(query) or "?") + " (end)"
- result += ", " + (new_gc(query) or "?") + " (site)"
- if '"' in query:
- result += ", " + (newest_gc(query) or "?") + " (verbatim)"
- phenny.say(result)
+ if not input.group(2):
+ return phenny.reply("No query term.")
+ query = input.group(2).encode('utf-8')
+ result = query + ": "
+ result += (old_gc(query) or "?") + " (api)"
+ result += ", " + (newerest_gc(query) or "?") + " (end)"
+ result += ", " + (new_gc(query) or "?") + " (site)"
+ if '"' in query:
+ result += ", " + (newest_gc(query) or "?") + " (verbatim)"
+ phenny.say(result)
gc.commands = ['gc']
gc.priority = 'high'
gc.example = '.gc extrapolate'
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/seen.py b/modules/seen.py
index 8ed41a8..06dca3e 100755
--- a/modules/seen.py
+++ b/modules/seen.py
@@ -10,43 +10,43 @@ http://inamidst.com/phenny/
import time
from tools import deprecated
-def seen(phenny, input):
- """.seen <nick> - Reports when <nick> was last seen."""
- nick = input.group(2)
- if not nick:
- return phenny.reply("Need a nickname to search for...")
- nick = nick.lower()
-
- if not hasattr(phenny, 'seen'):
- return phenny.reply("?")
-
- if phenny.seen.has_key(nick):
- channel, t = phenny.seen[nick]
- t = time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime(t))
-
- msg = "I last saw %s at %s on %s" % (nick, t, channel)
- phenny.reply(msg)
- else: phenny.reply("Sorry, I haven't seen %s around." % nick)
+def seen(phenny, input):
+ """.seen <nick> - Reports when <nick> was last seen."""
+ nick = input.group(2)
+ if not nick:
+ return phenny.reply("Need a nickname to search for...")
+ nick = nick.lower()
+
+ if not hasattr(phenny, 'seen'):
+ return phenny.reply("?")
+
+ if phenny.seen.has_key(nick):
+ channel, t = phenny.seen[nick]
+ t = time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime(t))
+
+ msg = "I last saw %s at %s on %s" % (nick, t, channel)
+ phenny.reply(msg)
+ else: phenny.reply("Sorry, I haven't seen %s around." % nick)
seen.rule = (['seen'], r'(\S+)')
@deprecated
-def f_note(self, origin, match, args):
- def note(self, origin, match, args):
- if not hasattr(self.bot, 'seen'):
- self.bot.seen = {}
- if origin.sender.startswith('#'):
- # if origin.sender == '#inamidst': return
- self.seen[origin.nick.lower()] = (origin.sender, time.time())
-
- # if not hasattr(self, 'chanspeak'):
- # self.chanspeak = {}
- # if (len(args) > 2) and args[2].startswith('#'):
- # self.chanspeak[args[2]] = args[0]
-
- try: note(self, origin, match, args)
- except Exception, e: print e
+def f_note(self, origin, match, args):
+ def note(self, origin, match, args):
+ if not hasattr(self.bot, 'seen'):
+ self.bot.seen = {}
+ if origin.sender.startswith('#'):
+ # if origin.sender == '#inamidst': return
+ self.seen[origin.nick.lower()] = (origin.sender, time.time())
+
+ # if not hasattr(self, 'chanspeak'):
+ # self.chanspeak = {}
+ # if (len(args) > 2) and args[2].startswith('#'):
+ # self.chanspeak[args[2]] = args[0]
+
+ try: note(self, origin, match, args)
+ except Exception, e: print e
f_note.rule = r'(.*)'
f_note.priority = 'low'
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/startup.py b/modules/startup.py
index 81b3ecf..b9ad910 100755
--- a/modules/startup.py
+++ b/modules/startup.py
@@ -9,61 +9,61 @@ http://inamidst.com/phenny/
import threading, time
-def setup(phenny):
- print("Setting up phenny")
- # by clsn
- phenny.data = {}
- refresh_delay = 300.0
+def setup(phenny):
+ print("Setting up phenny")
+ # by clsn
+ phenny.data = {}
+ refresh_delay = 300.0
- if hasattr(phenny.config, 'refresh_delay'):
- try: refresh_delay = float(phenny.config.refresh_delay)
- except: pass
+ if hasattr(phenny.config, 'refresh_delay'):
+ try: refresh_delay = float(phenny.config.refresh_delay)
+ except: pass
- def close():
- print "Nobody PONGed our PING, restarting"
- phenny.handle_close()
-
- def pingloop():
- timer = threading.Timer(refresh_delay, close, ())
- phenny.data['startup.setup.timer'] = timer
- phenny.data['startup.setup.timer'].start()
- # print "PING!"
- phenny.write(('PING', phenny.config.host))
- phenny.data['startup.setup.pingloop'] = pingloop
+ def close():
+ print "Nobody PONGed our PING, restarting"
+ phenny.handle_close()
- def pong(phenny, input):
- try:
- # print "PONG!"
- phenny.data['startup.setup.timer'].cancel()
- time.sleep(refresh_delay + 60.0)
- pingloop()
- except: pass
- pong.event = 'PONG'
- pong.thread = True
- pong.rule = r'.*'
- phenny.variables['pong'] = pong
+ def pingloop():
+ timer = threading.Timer(refresh_delay, close, ())
+ phenny.data['startup.setup.timer'] = timer
+ phenny.data['startup.setup.timer'].start()
+ # print "PING!"
+ phenny.write(('PING', phenny.config.host))
+ phenny.data['startup.setup.pingloop'] = pingloop
-def startup(phenny, input):
- import time
+ def pong(phenny, input):
+ try:
+ # print "PONG!"
+ phenny.data['startup.setup.timer'].cancel()
+ time.sleep(refresh_delay + 60.0)
+ pingloop()
+ except: pass
+ pong.event = 'PONG'
+ pong.thread = True
+ pong.rule = r'.*'
+ phenny.variables['pong'] = pong
- # Start the ping loop. Has to be done after USER on e.g. quakenet
- if phenny.data.get('startup.setup.pingloop'):
- phenny.data['startup.setup.pingloop']()
+def startup(phenny, input):
+ import time
- if hasattr(phenny.config, 'serverpass'):
- phenny.write(('PASS', phenny.config.serverpass))
+ # Start the ping loop. Has to be done after USER on e.g. quakenet
+ if phenny.data.get('startup.setup.pingloop'):
+ phenny.data['startup.setup.pingloop']()
- if hasattr(phenny.config, 'password'):
- phenny.msg('NickServ', 'IDENTIFY %s' % phenny.config.password)
- time.sleep(5)
+ if hasattr(phenny.config, 'serverpass'):
+ phenny.write(('PASS', phenny.config.serverpass))
- # Cf. http://swhack.com/logs/2005-12-05#T19-32-36
- for channel in phenny.channels:
- phenny.write(('JOIN', channel))
- time.sleep(0.5)
+ if hasattr(phenny.config, 'password'):
+ phenny.msg('NickServ', 'IDENTIFY %s' % phenny.config.password)
+ time.sleep(5)
+
+ # Cf. http://swhack.com/logs/2005-12-05#T19-32-36
+ for channel in phenny.channels:
+ phenny.write(('JOIN', channel))
+ time.sleep(0.5)
startup.rule = r'(.*)'
startup.event = '251'
startup.priority = 'low'
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/tell.py b/modules/tell.py
index a82fad1..f230c06 100755
--- a/modules/tell.py
+++ b/modules/tell.py
@@ -23,136 +23,136 @@ lispchannels = frozenset([ '#lisp', '#scheme', '#opendarwin', '#macdev',
'#perl6', '#sdlperl', '#ksvg', '#rcirc', '#code4lib', '#linux-quebec',
'#programmering', '#maxima', '#robin', '##concurrency', '#paredit' ])
-def loadReminders(fn):
- result = {}
- f = open(fn)
- for line in f:
- line = line.strip()
- if line:
- try: tellee, teller, verb, timenow, msg = line.split('\t', 4)
- except ValueError: continue # @@ hmm
- result.setdefault(tellee, []).append((teller, verb, timenow, msg))
- f.close()
- return result
-
-def dumpReminders(fn, data):
- f = open(fn, 'w')
- for tellee in data.iterkeys():
- for remindon in data[tellee]:
- line = '\t'.join((tellee,) + remindon)
- try: f.write(line + '\n')
- except IOError: break
- try: f.close()
- except IOError: pass
- return True
-
-def setup(self):
- fn = self.nick + '-' + self.config.host + '.tell.db'
- self.tell_filename = os.path.join(os.path.expanduser('~/.phenny'), fn)
- if not os.path.exists(self.tell_filename):
- try: f = open(self.tell_filename, 'w')
- except OSError: pass
- else:
- f.write('')
- f.close()
- self.reminders = loadReminders(self.tell_filename) # @@ tell
-
-def f_remind(phenny, input):
- teller = input.nick
-
- # @@ Multiple comma-separated tellees? Cf. Terje, #swhack, 2006-04-15
- verb, tellee, msg = input.groups()
- verb = verb.encode('utf-8')
- tellee = tellee.encode('utf-8')
- msg = msg.encode('utf-8')
-
- tellee_original = tellee.rstrip('.,:;')
- tellee = tellee_original.lower()
-
- if not os.path.exists(phenny.tell_filename):
- return
-
- if len(tellee) > 20:
- return phenny.reply('That nickname is too long.')
-
- timenow = time.strftime('%d %b %H:%MZ', time.gmtime())
- if not tellee in (teller.lower(), phenny.nick, 'me'): # @@
- # @@ <deltab> and year, if necessary
- warn = False
- if not phenny.reminders.has_key(tellee):
- phenny.reminders[tellee] = [(teller, verb, timenow, msg)]
- else:
- # if len(phenny.reminders[tellee]) >= maximum:
- # warn = True
- phenny.reminders[tellee].append((teller, verb, timenow, msg))
- # @@ Stephanie's augmentation
- response = "I'll pass that on when %s is around." % tellee_original
- # if warn: response += (" I'll have to use a pastebin, though, so " +
- # "your message may get lost.")
-
- rand = random.random()
- if rand > 0.9999: response = "yeah, yeah"
- elif rand > 0.999: response = "yeah, sure, whatever"
-
- phenny.reply(response)
- elif teller.lower() == tellee:
- phenny.say('You can %s yourself that.' % verb)
- else: phenny.say("Hey, I'm not as stupid as Monty you know!")
-
- dumpReminders(phenny.tell_filename, phenny.reminders) # @@ tell
+def loadReminders(fn):
+ result = {}
+ f = open(fn)
+ for line in f:
+ line = line.strip()
+ if line:
+ try: tellee, teller, verb, timenow, msg = line.split('\t', 4)
+ except ValueError: continue # @@ hmm
+ result.setdefault(tellee, []).append((teller, verb, timenow, msg))
+ f.close()
+ return result
+
+def dumpReminders(fn, data):
+ f = open(fn, 'w')
+ for tellee in data.iterkeys():
+ for remindon in data[tellee]:
+ line = '\t'.join((tellee,) + remindon)
+ try: f.write(line + '\n')
+ except IOError: break
+ try: f.close()
+ except IOError: pass
+ return True
+
+def setup(self):
+ fn = self.nick + '-' + self.config.host + '.tell.db'
+ self.tell_filename = os.path.join(os.path.expanduser('~/.phenny'), fn)
+ if not os.path.exists(self.tell_filename):
+ try: f = open(self.tell_filename, 'w')
+ except OSError: pass
+ else:
+ f.write('')
+ f.close()
+ self.reminders = loadReminders(self.tell_filename) # @@ tell
+
+def f_remind(phenny, input):
+ teller = input.nick
+
+ # @@ Multiple comma-separated tellees? Cf. Terje, #swhack, 2006-04-15
+ verb, tellee, msg = input.groups()
+ verb = verb.encode('utf-8')
+ tellee = tellee.encode('utf-8')
+ msg = msg.encode('utf-8')
+
+ tellee_original = tellee.rstrip('.,:;')
+ tellee = tellee_original.lower()
+
+ if not os.path.exists(phenny.tell_filename):
+ return
+
+ if len(tellee) > 20:
+ return phenny.reply('That nickname is too long.')
+
+ timenow = time.strftime('%d %b %H:%MZ', time.gmtime())
+ if not tellee in (teller.lower(), phenny.nick, 'me'): # @@
+ # @@ <deltab> and year, if necessary
+ warn = False
+ if not phenny.reminders.has_key(tellee):
+ phenny.reminders[tellee] = [(teller, verb, timenow, msg)]
+ else:
+ # if len(phenny.reminders[tellee]) >= maximum:
+ # warn = True
+ phenny.reminders[tellee].append((teller, verb, timenow, msg))
+ # @@ Stephanie's augmentation
+ response = "I'll pass that on when %s is around." % tellee_original
+ # if warn: response += (" I'll have to use a pastebin, though, so " +
+ # "your message may get lost.")
+
+ rand = random.random()
+ if rand > 0.9999: response = "yeah, yeah"
+ elif rand > 0.999: response = "yeah, sure, whatever"
+
+ phenny.reply(response)
+ elif teller.lower() == tellee:
+ phenny.say('You can %s yourself that.' % verb)
+ else: phenny.say("Hey, I'm not as stupid as Monty you know!")
+
+ dumpReminders(phenny.tell_filename, phenny.reminders) # @@ tell
f_remind.rule = ('$nick', ['tell', 'ask'], r'(\S+) (.*)')
-def getReminders(phenny, channel, key, tellee):
- lines = []
- template = "%s: %s <%s> %s %s %s"
- today = time.strftime('%d %b', time.gmtime())
-
- for (teller, verb, datetime, msg) in phenny.reminders[key]:
- if datetime.startswith(today):
- datetime = datetime[len(today)+1:]
- lines.append(template % (tellee, datetime, teller, verb, tellee, msg))
-
- try: del phenny.reminders[key]
- except KeyError: phenny.msg(channel, 'Er...')
- return lines
-
-def message(phenny, input):
- if not input.sender.startswith('#'): return
-
- tellee = input.nick
- channel = input.sender
-
- if not os: return
- if not os.path.exists(phenny.tell_filename):
- return
-
- reminders = []
- remkeys = list(reversed(sorted(phenny.reminders.keys())))
- for remkey in remkeys:
- if not remkey.endswith('*') or remkey.endswith(':'):
- if tellee.lower() == remkey:
+def getReminders(phenny, channel, key, tellee):
+ lines = []
+ template = "%s: %s <%s> %s %s %s"
+ today = time.strftime('%d %b', time.gmtime())
+
+ for (teller, verb, datetime, msg) in phenny.reminders[key]:
+ if datetime.startswith(today):
+ datetime = datetime[len(today)+1:]
+ lines.append(template % (tellee, datetime, teller, verb, tellee, msg))
+
+ try: del phenny.reminders[key]
+ except KeyError: phenny.msg(channel, 'Er...')
+ return lines
+
+def message(phenny, input):
+ if not input.sender.startswith('#'): return
+
+ tellee = input.nick
+ channel = input.sender
+
+ if not os: return
+ if not os.path.exists(phenny.tell_filename):
+ return
+
+ reminders = []
+ remkeys = list(reversed(sorted(phenny.reminders.keys())))
+ for remkey in remkeys:
+ if not remkey.endswith('*') or remkey.endswith(':'):
+ if tellee.lower() == remkey:
+ phenny.sending.acquire()
+ reminders.extend(getReminders(phenny, channel, remkey, tellee))
+ phenny.sending.release()
+ elif tellee.lower().strip("0123456789_-[]`") == remkey.rstrip('*:'):
phenny.sending.acquire()
reminders.extend(getReminders(phenny, channel, remkey, tellee))
phenny.sending.release()
- elif tellee.lower().strip("0123456789_-[]`") == remkey.rstrip('*:'):
- phenny.sending.acquire()
- reminders.extend(getReminders(phenny, channel, remkey, tellee))
- phenny.sending.release()
-
- for line in reminders[:maximum]:
- phenny.say(line)
-
- if reminders[maximum:]:
- phenny.say('Further messages sent privately')
- for line in reminders[maximum:]:
- phenny.msg(tellee, line)
-
- if len(phenny.reminders.keys()) != remkeys:
- phenny.sending.acquire()
- dumpReminders(phenny.tell_filename, phenny.reminders) # @@ tell
- phenny.sending.release()
+
+ for line in reminders[:maximum]:
+ phenny.say(line)
+
+ if reminders[maximum:]:
+ phenny.say('Further messages sent privately')
+ for line in reminders[maximum:]:
+ phenny.msg(tellee, line)
+
+ if len(phenny.reminders.keys()) != remkeys:
+ phenny.sending.acquire()
+ dumpReminders(phenny.tell_filename, phenny.reminders) # @@ tell
+ phenny.sending.release()
message.rule = r'(.*)'
message.priority = 'low'
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/translate.py b/modules/translate.py
index 11e4f28..dce080e 100755
--- a/modules/translate.py
+++ b/modules/translate.py
@@ -11,135 +11,135 @@ http://inamidst.com/phenny/
import re, urllib
import web
-def translate(text, input='auto', output='en'):
- raw = False
- if output.endswith('-raw'):
- output = output[:-4]
- raw = True
+def translate(text, input='auto', output='en'):
+ raw = False
+ if output.endswith('-raw'):
+ output = output[:-4]
+ raw = True
- import urllib2, json
- opener = urllib2.build_opener()
- opener.addheaders = [(
- 'User-Agent', 'Mozilla/5.0' +
- '(X11; U; Linux i686)' +
- 'Gecko/20071127 Firefox/2.0.0.11'
- )]
+ import urllib2, json
+ opener = urllib2.build_opener()
+ opener.addheaders = [(
+ 'User-Agent', 'Mozilla/5.0' +
+ '(X11; U; Linux i686)' +
+ 'Gecko/20071127 Firefox/2.0.0.11'
+ )]
- input, output = urllib.quote(input), urllib.quote(output)
- text = urllib.quote(text)
+ input, output = urllib.quote(input), urllib.quote(output)
+ text = urllib.quote(text)
- result = opener.open('http://translate.google.com/translate_a/t?' +
- ('client=t&hl=en&sl=%s&tl=%s&multires=1' % (input, output)) +
- ('&otf=1&ssel=0&tsel=0&uptl=en&sc=1&text=%s' % text)).read()
+ result = opener.open('http://translate.google.com/translate_a/t?' +
+ ('client=t&hl=en&sl=%s&tl=%s&multires=1' % (input, output)) +
+ ('&otf=1&ssel=0&tsel=0&uptl=en&sc=1&text=%s' % text)).read()
- while ',,' in result:
- result = result.replace(',,', ',null,')
- data = json.loads(result)
+ while ',,' in result:
+ result = result.replace(',,', ',null,')
+ data = json.loads(result)
- if raw:
- return str(data), 'en-raw'
+ if raw:
+ return str(data), 'en-raw'
- try: language = data[2] # -2][0][0]
- except: language = '?'
+ try: language = data[2] # -2][0][0]
+ except: language = '?'
- return ''.join(x[0] for x in data[0]), language
+ return ''.join(x[0] for x in data[0]), language
-def tr(phenny, context):
- """Translates a phrase, with an optional language hint."""
- input, output, phrase = context.groups()
+def tr(phenny, context):
+ """Translates a phrase, with an optional language hint."""
+ input, output, phrase = context.groups()
- phrase = phrase.encode('utf-8')
+ phrase = phrase.encode('utf-8')
- if (len(phrase) > 350) and (not context.admin):
- return phenny.reply('Phrase must be under 350 characters.')
+ if (len(phrase) > 350) and (not context.admin):
+ return phenny.reply('Phrase must be under 350 characters.')
- input = input or 'auto'
- input = input.encode('utf-8')
- output = (output or 'en').encode('utf-8')
+ input = input or 'auto'
+ input = input.encode('utf-8')
+ output = (output or 'en').encode('utf-8')
- if input != output:
- msg, input = translate(phrase, input, output)
- if isinstance(msg, str):
- msg = msg.decode('utf-8')
- if msg:
- msg = web.decode(msg) # msg.replace('&#39;', "'")
- msg = '"%s" (%s to %s, translate.google.com)' % (msg, input, output)
- else: msg = 'The %s to %s translation failed, sorry!' % (input, output)
+ if input != output:
+ msg, input = translate(phrase, input, output)
+ if isinstance(msg, str):
+ msg = msg.decode('utf-8')
+ if msg:
+ msg = web.decode(msg) # msg.replace('&#39;', "'")
+ msg = '"%s" (%s to %s, translate.google.com)' % (msg, input, output)
+ else: msg = 'The %s to %s translation failed, sorry!' % (input, output)
- phenny.reply(msg)
- else: phenny.reply('Language guessing failed, so try suggesting one!')
+ phenny.reply(msg)
+ else: phenny.reply('Language guessing failed, so try suggesting one!')
tr.rule = ('$nick', ur'(?:([a-z]{2}) +)?(?:([a-z]{2}|en-raw) +)?["“](.+?)["”]\? *$')
tr.example = '$nickname: "mon chien"? or $nickname: fr "mon chien"?'
tr.priority = 'low'
-def tr2(phenny, input):
- """Translates a phrase, with an optional language hint."""
- command = input.group(2)
- if not command:
- return phenny.reply("Need something to translate!")
- command = command.encode('utf-8')
-
- def langcode(p):
- return p.startswith(':') and (2 < len(p) < 10) and p[1:].isalpha()
-
- args = ['auto', 'en']
-
- for i in xrange(2):
- if not ' ' in command: break
- prefix, cmd = command.split(' ', 1)
- if langcode(prefix):
- args[i] = prefix[1:]
- command = cmd
- phrase = command
-
- # if (len(phrase) > 350) and (not input.admin):
- # return phenny.reply('Phrase must be under 350 characters.')
-
- src, dest = args
- if src != dest:
- msg, src = translate(phrase, src, dest)
- if isinstance(msg, str):
- msg = msg.decode('utf-8')
- if msg:
- msg = web.decode(msg) # msg.replace('&#39;', "'")
- if len(msg) > 450: msg = msg[:450] + '[...]'
- msg = '"%s" (%s to %s, translate.google.com)' % (msg, src, dest)
- else: msg = 'The %s to %s translation failed, sorry!' % (src, dest)
-
- phenny.reply(msg)
- else: phenny.reply('Language guessing failed, so try suggesting one!')
+def tr2(phenny, input):
+ """Translates a phrase, with an optional language hint."""
+ command = input.group(2)
+ if not command:
+ return phenny.reply("Need something to translate!")
+ command = command.encode('utf-8')
+
+ def langcode(p):
+ return p.startswith(':') and (2 < len(p) < 10) and p[1:].isalpha()
+
+ args = ['auto', 'en']
+
+ for i in xrange(2):
+ if not ' ' in command: break
+ prefix, cmd = command.split(' ', 1)
+ if langcode(prefix):
+ args[i] = prefix[1:]
+ command = cmd
+ phrase = command
+
+ # if (len(phrase) > 350) and (not input.admin):
+ # return phenny.reply('Phrase must be under 350 characters.')
+
+ src, dest = args
+ if src != dest:
+ msg, src = translate(phrase, src, dest)
+ if isinstance(msg, str):
+ msg = msg.decode('utf-8')
+ if msg:
+ msg = web.decode(msg) # msg.replace('&#39;', "'")
+ if len(msg) > 450: msg = msg[:450] + '[...]'
+ msg = '"%s" (%s to %s, translate.google.com)' % (msg, src, dest)
+ else: msg = 'The %s to %s translation failed, sorry!' % (src, dest)
+
+ phenny.reply(msg)
+ else: phenny.reply('Language guessing failed, so try suggesting one!')
tr2.commands = ['tr']
tr2.priority = 'low'
-def mangle(phenny, input):
- import time
+def mangle(phenny, input):
+ import time
- phrase = input.group(2).encode('utf-8')
- for lang in ['fr', 'de', 'es', 'it', 'ja']:
- backup = phrase[:]
- phrase, _lang = translate(phrase, 'en', lang)
- phrase = phrase.encode("utf-8")
+ phrase = input.group(2).encode('utf-8')
+ for lang in ['fr', 'de', 'es', 'it', 'ja']:
+ backup = phrase[:]
+ phrase, _lang = translate(phrase, 'en', lang)
+ phrase = phrase.encode("utf-8")
- if not phrase:
- phrase = backup[:]
- break
- time.sleep(0.25)
+ if not phrase:
+ phrase = backup[:]
+ break
+ time.sleep(0.25)
- backup = phrase[:]
- phrase, _lang = translate(phrase, lang, 'en')
- phrase = phrase.encode("utf-8")
+ backup = phrase[:]
+ phrase, _lang = translate(phrase, lang, 'en')
+ phrase = phrase.encode("utf-8")
- if not phrase:
- phrase = backup[:]
- break
- time.sleep(0.25)
+ if not phrase:
+ phrase = backup[:]
+ break
+ time.sleep(0.25)
- phrase = phrase.replace(' ,', ',').replace(' .', '.')
- phrase = phrase.strip(' ,')
- phenny.reply(phrase or 'ERRORS SRY')
+ phrase = phrase.replace(' ,', ',').replace(' .', '.')
+ phrase = phrase.strip(' ,')
+ phenny.reply(phrase or 'ERRORS SRY')
mangle.commands = ['mangle']
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/twitter.py b/modules/twitter.py
index afd1d5c..0ec4744 100755
--- a/modules/twitter.py
+++ b/modules/twitter.py
@@ -20,74 +20,74 @@ r_whiteline = re.compile(r'(?ims)[ \t]+[\r\n]+')
r_breaks = re.compile(r'(?ims)[\r\n]+')
def entity(*args, **kargs):
- return web.entity(*args, **kargs).encode('utf-8')
+ return web.entity(*args, **kargs).encode('utf-8')
-def decode(html):
- return web.r_entity.sub(entity, html)
+def decode(html):
+ return web.r_entity.sub(entity, html)
def expand(tweet):
- def replacement(match):
- anchor = match.group(1)
- for link in r_expanded.findall(anchor):
- return link
- return r_tag.sub('', anchor)
- return r_anchor.sub(replacement, tweet)
+ def replacement(match):
+ anchor = match.group(1)
+ for link in r_expanded.findall(anchor):
+ return link
+ return r_tag.sub('', anchor)
+ return r_anchor.sub(replacement, tweet)
def read_tweet(url):
- bytes = web.get(url)
- shim = '<div class="content clearfix">'
- if shim in bytes:
- bytes = bytes.split(shim, 1).pop()
-
- for text in r_p.findall(bytes):
- text = expand(text)
- text = r_tag.sub('', text)
- text = text.strip()
- text = r_whiteline.sub(' ', text)
- text = r_breaks.sub(' ', text)
- return decode(text)
- return "Sorry, couldn't get a tweet from %s" % url
+ bytes = web.get(url)
+ shim = '<div class="content clearfix">'
+ if shim in bytes:
+ bytes = bytes.split(shim, 1).pop()
+
+ for text in r_p.findall(bytes):
+ text = expand(text)
+ text = r_tag.sub('', text)
+ text = text.strip()
+ text = r_whiteline.sub(' ', text)
+ text = r_breaks.sub(' ', text)
+ return decode(text)
+ return "Sorry, couldn't get a tweet from %s" % url
def format(tweet, username):
- return '%s (@%s)' % (tweet, username)
+ return '%s (@%s)' % (tweet, username)
def user_tweet(username):
- tweet = read_tweet('https://twitter.com/' + username + "?" + str(time.time()))
- return format(tweet, username)
+ tweet = read_tweet('https://twitter.com/' + username + "?" + str(time.time()))
+ return format(tweet, username)
def id_tweet(tid):
- link = 'https://twitter.com/twitter/status/' + tid
- data = web.head(link)
- message, status = tuple(data)
- if status == 301:
- url = message.get("Location")
- if not url: return "Sorry, couldn't get a tweet from %s" % link
- username = url.split('/')[3]
- tweet = read_tweet(url)
- return format(tweet, username)
- return "Sorry, couldn't get a tweet from %s" % link
+ link = 'https://twitter.com/twitter/status/' + tid
+ data = web.head(link)
+ message, status = tuple(data)
+ if status == 301:
+ url = message.get("Location")
+ if not url: return "Sorry, couldn't get a tweet from %s" % link
+ username = url.split('/')[3]
+ tweet = read_tweet(url)
+ return format(tweet, username)
+ return "Sorry, couldn't get a tweet from %s" % link
def twitter(phenny, input):
- arg = input.group(2)
- if not arg:
- return phenny.reply("Give me a link, a username, or a tweet id")
-
- arg = arg.strip()
- if isinstance(arg, unicode):
- arg = arg.encode('utf-8')
-
- if arg.isdigit():
- phenny.say(id_tweet(arg))
- elif r_username.match(arg):
- phenny.say(user_tweet(arg))
- elif r_link.match(arg):
- username = arg.split('/')[3]
- tweet = read_tweet(arg)
- phenny.say(format(tweet, username))
- else: phenny.reply("Give me a link, a username, or a tweet id")
+ arg = input.group(2)
+ if not arg:
+ return phenny.reply("Give me a link, a username, or a tweet id")
+
+ arg = arg.strip()
+ if isinstance(arg, unicode):
+ arg = arg.encode('utf-8')
+
+ if arg.isdigit():
+ phenny.say(id_tweet(arg))
+ elif r_username.match(arg):
+ phenny.say(user_tweet(arg))
+ elif r_link.match(arg):
+ username = arg.split('/')[3]
+ tweet = read_tweet(arg)
+ phenny.say(format(tweet, username))
+ else: phenny.reply("Give me a link, a username, or a tweet id")
twitter.commands = ['tw', 'twitter']
twitter.thread = True
if __name__ == '__main__':
- print __doc__
+ print __doc__
diff --git a/modules/validate.py b/modules/validate.py
index 85815d1..ac036f5 100755
--- a/modules/validate.py
+++ b/modules/validate.py
@@ -9,35 +9,35 @@ http://inamidst.com/phenny/
import web
-def val(phenny, input):
- """Check a webpage using the W3C Markup Validator."""
- if not input.group(2):
- return phenny.reply("Nothing to validate.")
- uri = input.group(2)
- if not uri.startswith('http://'):
- uri = 'http://' + uri
-
- path = '/check?uri=%s;output=xml' % web.urllib.quote(uri)
- info = web.head('http://validator.w3.org' + path)
-
- result = uri + ' is '
-
- if isinstance(info, list):
- return phenny.say('Got HTTP response %s' % info[1])
-
- if info.has_key('X-W3C-Validator-Status'):
- result += str(info['X-W3C-Validator-Status'])
- if info['X-W3C-Validator-Status'] != 'Valid':
- if info.has_key('X-W3C-Validator-Errors'):
- n = int(info['X-W3C-Validator-Errors'].split(' ')[0])
- if n != 1:
- result += ' (%s errors)' % n
- else: result += ' (%s error)' % n
- else: result += 'Unvalidatable: no X-W3C-Validator-Status'
-
- phenny.reply(result)
+def val(phenny, input):
+ """Check a webpage using the W3C Markup Validator."""
+ if not input.group(2):
+ return phenny.reply("Nothing to validate.")
+ uri = input.group(2)
+ if not uri.startswith('http://'):
+ uri = 'http://' + uri
+
+ path = '/check?uri=%s;output=xml' % web.urllib.quote(uri)
+ info = web.head('http://validator.w3.org' + path)
+
+ result = uri + ' is '
+
+ if isinstance(info, list):
+ return phenny.say('Got HTTP response %s' % info[1])
+
+ if info.has_key('X-W3C-Validator-Status'):
+ result += str(info['X-W3C-Validator-Status'])
+ if info['X-W3C-Validator-Status'] != 'Valid':
+ if info.has_key('X-W3C-Validator-Errors'):
+ n = int(info['X-W3C-Validator-Errors'].split(' ')[0])
+ if n != 1:
+ result += ' (%s errors)' % n
+ else: result += ' (%s error)' % n
+ else: result += 'Unvalidatable: no X-W3C-Validator-Status'
+
+ phenny.reply(result)
val.rule = (['val'], r'(?i)(\S+)')
val.example = '.val http://www.w3.org/'
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/weather.py b/modules/weather.py
index 29b01e5..5999b79 100755
--- a/modules/weather.py
+++ b/modules/weather.py
@@ -13,400 +13,400 @@ from tools import deprecated
r_from = re.compile(r'(?i)([+-]\d+):00 from')
-def location(name):
- name = urllib.quote(name.encode('utf-8'))
- uri = 'http://ws.geonames.org/searchJSON?q=%s&maxRows=1' % name
- for i in xrange(10):
- u = urllib.urlopen(uri)
- if u is not None: break
- bytes = u.read()
- u.close()
-
- results = web.json(bytes)
- try: name = results['geonames'][0]['name']
- except IndexError:
- return '?', '?', '0', '0'
- countryName = results['geonames'][0]['countryName']
- lat = results['geonames'][0]['lat']
- lng = results['geonames'][0]['lng']
- return name, countryName, lat, lng
-
-class GrumbleError(object):
- pass
-
-def local(icao, hour, minute):
- uri = ('http://www.flightstats.com/' +
- 'go/Airport/airportDetails.do?airportCode=%s')
- try: bytes = web.get(uri % icao)
- except AttributeError:
- raise GrumbleError('A WEBSITE HAS GONE DOWN WTF STUPID WEB')
- m = r_from.search(bytes)
- if m:
- offset = m.group(1)
- lhour = int(hour) + int(offset)
- lhour = lhour % 24
- return (str(lhour) + ':' + str(minute) + ', ' + str(hour) +
- str(minute) + 'Z')
- # return (str(lhour) + ':' + str(minute) + ' (' + str(hour) +
- # ':' + str(minute) + 'Z)')
- return str(hour) + ':' + str(minute) + 'Z'
-
-def code(phenny, search):
- from icao import data
-
- if search.upper() in [loc[0] for loc in data]:
- return search.upper()
- else:
- name, country, latitude, longitude = location(search)
- if name == '?': return False
- sumOfSquares = (99999999999999999999999999999, 'ICAO')
- for icao_code, lat, lon in data:
- latDiff = abs(latitude - lat)
- lonDiff = abs(longitude - lon)
- diff = (latDiff * latDiff) + (lonDiff * lonDiff)
- if diff < sumOfSquares[0]:
- sumOfSquares = (diff, icao_code)
- return sumOfSquares[1]
+def location(name):
+ name = urllib.quote(name.encode('utf-8'))
+ uri = 'http://ws.geonames.org/searchJSON?q=%s&maxRows=1' % name
+ for i in xrange(10):
+ u = urllib.urlopen(uri)
+ if u is not None: break
+ bytes = u.read()
+ u.close()
+
+ results = web.json(bytes)
+ try: name = results['geonames'][0]['name']
+ except IndexError:
+ return '?', '?', '0', '0'
+ countryName = results['geonames'][0]['countryName']
+ lat = results['geonames'][0]['lat']
+ lng = results['geonames'][0]['lng']
+ return name, countryName, lat, lng
+
+class GrumbleError(object):
+ pass
+
+def local(icao, hour, minute):
+ uri = ('http://www.flightstats.com/' +
+ 'go/Airport/airportDetails.do?airportCode=%s')
+ try: bytes = web.get(uri % icao)
+ except AttributeError:
+ raise GrumbleError('A WEBSITE HAS GONE DOWN WTF STUPID WEB')
+ m = r_from.search(bytes)
+ if m:
+ offset = m.group(1)
+ lhour = int(hour) + int(offset)
+ lhour = lhour % 24
+ return (str(lhour) + ':' + str(minute) + ', ' + str(hour) +
+ str(minute) + 'Z')
+ # return (str(lhour) + ':' + str(minute) + ' (' + str(hour) +
+ # ':' + str(minute) + 'Z)')
+ return str(hour) + ':' + str(minute) + 'Z'
+
+def code(phenny, search):
+ from icao import data
+
+ if search.upper() in [loc[0] for loc in data]:
+ return search.upper()
+ else:
+ name, country, latitude, longitude = location(search)
+ if name == '?': return False
+ sumOfSquares = (99999999999999999999999999999, 'ICAO')
+ for icao_code, lat, lon in data:
+ latDiff = abs(latitude - lat)
+ lonDiff = abs(longitude - lon)
+ diff = (latDiff * latDiff) + (lonDiff * lonDiff)
+ if diff < sumOfSquares[0]:
+ sumOfSquares = (diff, icao_code)
+ return sumOfSquares[1]
@deprecated
-def f_weather(self, origin, match, args):
- """.weather <ICAO> - Show the weather at airport with the code <ICAO>."""
- if origin.sender == '#talis':
- if args[0].startswith('.weather '): return
-
- icao_code = match.group(2)
- if not icao_code:
- return self.msg(origin.sender, 'Try .weather London, for example?')
-
- icao_code = code(self, icao_code)
-
- if not icao_code:
- self.msg(origin.sender, 'No ICAO code found, sorry')
- return
-
- uri = 'http://weather.noaa.gov/pub/data/observations/metar/stations/%s.TXT'
- try: bytes = web.get(uri % icao_code)
- except AttributeError:
- raise GrumbleError('OH CRAP NOAA HAS GONE DOWN THE WEB IS BROKEN')
- if 'Not Found' in bytes:
- self.msg(origin.sender, icao_code+': no such ICAO code, or no NOAA data')
- return
-
- metar = bytes.splitlines().pop()
- metar = metar.split(' ')
-
- if len(metar[0]) == 4:
- metar = metar[1:]
-
- if metar[0].endswith('Z'):
- time = metar[0]
- metar = metar[1:]
- else: time = None
-
- if metar[0] == 'AUTO':
- metar = metar[1:]
- if metar[0] == 'VCU':
- self.msg(origin.sender, icao_code + ': no data provided')
- return
-
- if metar[0].endswith('KT'):
- wind = metar[0]
- metar = metar[1:]
- else: wind = None
-
- if ('V' in metar[0]) and (metar[0] != 'CAVOK'):
- vari = metar[0]
- metar = metar[1:]
- else: vari = None
-
- if ((len(metar[0]) == 4) or
- metar[0].endswith('SM')):
- visibility = metar[0]
- metar = metar[1:]
- else: visibility = None
-
- while metar[0].startswith('R') and (metar[0].endswith('L')
- or 'L/' in metar[0]):
- metar = metar[1:]
-
- if len(metar[0]) == 6 and (metar[0].endswith('N') or
- metar[0].endswith('E') or
- metar[0].endswith('S') or
- metar[0].endswith('W')):
- metar = metar[1:] # 7000SE?
-
- cond = []
- while (((len(metar[0]) < 5) or
- metar[0].startswith('+') or
- metar[0].startswith('-')) and (not (metar[0].startswith('VV') or
- metar[0].startswith('SKC') or metar[0].startswith('CLR') or
- metar[0].startswith('FEW') or metar[0].startswith('SCT') or
- metar[0].startswith('BKN') or metar[0].startswith('OVC')))):
- cond.append(metar[0])
- metar = metar[1:]
-
- while '/P' in metar[0]:
- metar = metar[1:]
-
- if not metar:
- self.msg(origin.sender, icao_code + ': no data provided')
- return
-
- cover = []
- while (metar[0].startswith('VV') or metar[0].startswith('SKC') or
- metar[0].startswith('CLR') or metar[0].startswith('FEW') or
- metar[0].startswith('SCT') or metar[0].startswith('BKN') or
- metar[0].startswith('OVC')):
- cover.append(metar[0])
- metar = metar[1:]
- if not metar:
- self.msg(origin.sender, icao_code + ': no data provided')
- return
-
- if metar[0] == 'CAVOK':
- cover.append('CLR')
- metar = metar[1:]
-
- if metar[0] == 'PRFG':
- cover.append('CLR') # @@?
- metar = metar[1:]
-
- if metar[0] == 'NSC':
- cover.append('CLR')
- metar = metar[1:]
-
- if ('/' in metar[0]) or (len(metar[0]) == 5 and metar[0][2] == '.'):
- temp = metar[0]
- metar = metar[1:]
- else: temp = None
-
- if metar[0].startswith('QFE'):
- metar = metar[1:]
-
- if metar[0].startswith('Q') or metar[0].startswith('A'):
- pressure = metar[0]
- metar = metar[1:]
- else: pressure = None
-
- if time:
- hour = time[2:4]
- minute = time[4:6]
- time = local(icao_code, hour, minute)
- else: time = '(time unknown)'
-
- if wind:
- speed = int(wind[3:5])
- if speed < 1:
- description = 'Calm'
- elif speed < 4:
- description = 'Light air'
- elif speed < 7:
- description = 'Light breeze'
- elif speed < 11:
- description = 'Gentle breeze'
- elif speed < 16:
- description = 'Moderate breeze'
- elif speed < 22:
- description = 'Fresh breeze'
- elif speed < 28:
- description = 'Strong breeze'
- elif speed < 34:
- description = 'Near gale'
- elif speed < 41:
- description = 'Gale'
- elif speed < 48:
- description = 'Strong gale'
- elif speed < 56:
- description = 'Storm'
- elif speed < 64:
- description = 'Violent storm'
- else: description = 'Hurricane'
-
- degrees = wind[0:3]
- if degrees == 'VRB':
- degrees = u'\u21BB'.encode('utf-8')
- elif (degrees <= 22.5) or (degrees > 337.5):
- degrees = u'\u2191'.encode('utf-8')
- elif (degrees > 22.5) and (degrees <= 67.5):
- degrees = u'\u2197'.encode('utf-8')
- elif (degrees > 67.5) and (degrees <= 112.5):
- degrees = u'\u2192'.encode('utf-8')
- elif (degrees > 112.5) and (degrees <= 157.5):
- degrees = u'\u2198'.encode('utf-8')
- elif (degrees > 157.5) and (degrees <= 202.5):
- degrees = u'\u2193'.encode('utf-8')
- elif (degrees > 202.5) and (degrees <= 247.5):
- degrees = u'\u2199'.encode('utf-8')
- elif (degrees > 247.5) and (degrees <= 292.5):
- degrees = u'\u2190'.encode('utf-8')
- elif (degrees > 292.5) and (degrees <= 337.5):
- degrees = u'\u2196'.encode('utf-8')
-
- if not icao_code.startswith('EN') and not icao_code.startswith('ED'):
- wind = '%s %skt (%s)' % (description, speed, degrees)
- elif icao_code.startswith('ED'):
- kmh = int(round(speed * 1.852, 0))
- wind = '%s %skm/h (%skt) (%s)' % (description, kmh, speed, degrees)
- elif icao_code.startswith('EN'):
- ms = int(round(speed * 0.514444444, 0))
- wind = '%s %sm/s (%skt) (%s)' % (description, ms, speed, degrees)
- else: wind = '(wind unknown)'
-
- if visibility:
- visibility = visibility + 'm'
- else: visibility = '(visibility unknown)'
-
- if cover:
- level = None
- for c in cover:
- if c.startswith('OVC') or c.startswith('VV'):
- if (level is None) or (level < 8):
- level = 8
- elif c.startswith('BKN'):
- if (level is None) or (level < 5):
- level = 5
- elif c.startswith('SCT'):
- if (level is None) or (level < 3):
- level = 3
- elif c.startswith('FEW'):
- if (level is None) or (level < 1):
- level = 1
- elif c.startswith('SKC') or c.startswith('CLR'):
- if level is None:
- level = 0
-
- if level == 8:
- cover = u'Overcast \u2601'.encode('utf-8')
- elif level == 5:
- cover = 'Cloudy'
- elif level == 3:
- cover = 'Scattered'
- elif (level == 1) or (level == 0):
- cover = u'Clear \u263C'.encode('utf-8')
- else: cover = 'Cover Unknown'
- else: cover = 'Cover Unknown'
-
- if temp:
- if '/' in temp:
- temp = temp.split('/')[0]
- else: temp = temp.split('.')[0]
- if temp.startswith('M'):
- temp = '-' + temp[1:]
- try: temp = int(temp)
- except ValueError: temp = '?'
- else: temp = '?'
-
- if pressure:
- if pressure.startswith('Q'):
- pressure = pressure.lstrip('Q')
- if pressure != 'NIL':
- pressure = str(int(pressure)) + 'mb'
- else: pressure = '?mb'
- elif pressure.startswith('A'):
- pressure = pressure.lstrip('A')
- if pressure != 'NIL':
- inches = pressure[:2] + '.' + pressure[2:]
- mb = int(float(inches) * 33.7685)
- pressure = '%sin (%smb)' % (inches, mb)
- else: pressure = '?mb'
-
- if isinstance(temp, int):
- f = round((temp * 1.8) + 32, 2)
- temp = u'%s\u2109 (%s\u2103)'.encode('utf-8') % (f, temp)
- else: pressure = '?mb'
- if isinstance(temp, int):
- temp = u'%s\u2103'.encode('utf-8') % temp
-
- if cond:
- conds = cond
- cond = ''
-
- intensities = {
- '-': 'Light',
- '+': 'Heavy'
- }
-
- descriptors = {
- 'MI': 'Shallow',
- 'PR': 'Partial',
- 'BC': 'Patches',
- 'DR': 'Drifting',
- 'BL': 'Blowing',
- 'SH': 'Showers of',
- 'TS': 'Thundery',
- 'FZ': 'Freezing',
- 'VC': 'In the vicinity:'
- }
-
- phenomena = {
- 'DZ': 'Drizzle',
- 'RA': 'Rain',
- 'SN': 'Snow',
- 'SG': 'Snow Grains',
- 'IC': 'Ice Crystals',
- 'PL': 'Ice Pellets',
- 'GR': 'Hail',
- 'GS': 'Small Hail',
- 'UP': 'Unknown Precipitation',
- 'BR': 'Mist',
- 'FG': 'Fog',
- 'FU': 'Smoke',
- 'VA': 'Volcanic Ash',
- 'DU': 'Dust',
- 'SA': 'Sand',
- 'HZ': 'Haze',
- 'PY': 'Spray',
- 'PO': 'Whirls',
- 'SQ': 'Squalls',
- 'FC': 'Tornado',
- 'SS': 'Sandstorm',
- 'DS': 'Duststorm',
- # ? Cf. http://swhack.com/logs/2007-10-05#T07-58-56
- 'TS': 'Thunderstorm',
- 'SH': 'Showers'
- }
-
- for c in conds:
- if c.endswith('//'):
- if cond: cond += ', '
- cond += 'Some Precipitation'
- elif len(c) == 5:
- intensity = intensities[c[0]]
- descriptor = descriptors[c[1:3]]
- phenomenon = phenomena.get(c[3:], c[3:])
- if cond: cond += ', '
- cond += intensity + ' ' + descriptor + ' ' + phenomenon
- elif len(c) == 4:
- descriptor = descriptors.get(c[:2], c[:2])
- phenomenon = phenomena.get(c[2:], c[2:])
- if cond: cond += ', '
- cond += descriptor + ' ' + phenomenon
- elif len(c) == 3:
- intensity = intensities.get(c[0], c[0])
- phenomenon = phenomena.get(c[1:], c[1:])
- if cond: cond += ', '
- cond += intensity + ' ' + phenomenon
- elif len(c) == 2:
- phenomenon = phenomena.get(c, c)
- if cond: cond += ', '
- cond += phenomenon
-
- # if not cond:
- # format = u'%s at %s: %s, %s, %s, %s'
- # args = (icao, time, cover, temp, pressure, wind)
- # else:
- # format = u'%s at %s: %s, %s, %s, %s, %s'
- # args = (icao, time, cover, temp, pressure, cond, wind)
-
- if not cond:
- format = u'%s, %s, %s, %s - %s %s'
- args = (cover, temp, pressure, wind, str(icao_code), time)
- else:
- format = u'%s, %s, %s, %s, %s - %s, %s'
- args = (cover, temp, pressure, cond, wind, str(icao_code), time)
-
- self.msg(origin.sender, format.encode('utf-8') % args)
+def f_weather(self, origin, match, args):
+ """.weather <ICAO> - Show the weather at airport with the code <ICAO>."""
+ if origin.sender == '#talis':
+ if args[0].startswith('.weather '): return
+
+ icao_code = match.group(2)
+ if not icao_code:
+ return self.msg(origin.sender, 'Try .weather London, for example?')
+
+ icao_code = code(self, icao_code)
+
+ if not icao_code:
+ self.msg(origin.sender, 'No ICAO code found, sorry')
+ return
+
+ uri = 'http://weather.noaa.gov/pub/data/observations/metar/stations/%s.TXT'
+ try: bytes = web.get(uri % icao_code)
+ except AttributeError:
+ raise GrumbleError('OH CRAP NOAA HAS GONE DOWN THE WEB IS BROKEN')
+ if 'Not Found' in bytes:
+ self.msg(origin.sender, icao_code+': no such ICAO code, or no NOAA data')
+ return
+
+ metar = bytes.splitlines().pop()
+ metar = metar.split(' ')
+
+ if len(metar[0]) == 4:
+ metar = metar[1:]
+
+ if metar[0].endswith('Z'):
+ time = metar[0]
+ metar = metar[1:]
+ else: time = None
+
+ if metar[0] == 'AUTO':
+ metar = metar[1:]
+ if metar[0] == 'VCU':
+ self.msg(origin.sender, icao_code + ': no data provided')
+ return
+
+ if metar[0].endswith('KT'):
+ wind = metar[0]
+ metar = metar[1:]
+ else: wind = None
+
+ if ('V' in metar[0]) and (metar[0] != 'CAVOK'):
+ vari = metar[0]
+ metar = metar[1:]
+ else: vari = None
+
+ if ((len(metar[0]) == 4) or
+ metar[0].endswith('SM')):
+ visibility = metar[0]
+ metar = metar[1:]
+ else: visibility = None
+
+ while metar[0].startswith('R') and (metar[0].endswith('L')
+ or 'L/' in metar[0]):
+ metar = metar[1:]
+
+ if len(metar[0]) == 6 and (metar[0].endswith('N') or
+ metar[0].endswith('E') or
+ metar[0].endswith('S') or
+ metar[0].endswith('W')):
+ metar = metar[1:] # 7000SE?
+
+ cond = []
+ while (((len(metar[0]) < 5) or
+ metar[0].startswith('+') or
+ metar[0].startswith('-')) and (not (metar[0].startswith('VV') or
+ metar[0].startswith('SKC') or metar[0].startswith('CLR') or
+ metar[0].startswith('FEW') or metar[0].startswith('SCT') or
+ metar[0].startswith('BKN') or metar[0].startswith('OVC')))):
+ cond.append(metar[0])
+ metar = metar[1:]
+
+ while '/P' in metar[0]:
+ metar = metar[1:]
+
+ if not metar:
+ self.msg(origin.sender, icao_code + ': no data provided')
+ return
+
+ cover = []
+ while (metar[0].startswith('VV') or metar[0].startswith('SKC') or
+ metar[0].startswith('CLR') or metar[0].startswith('FEW') or
+ metar[0].startswith('SCT') or metar[0].startswith('BKN') or
+ metar[0].startswith('OVC')):
+ cover.append(metar[0])
+ metar = metar[1:]
+ if not metar:
+ self.msg(origin.sender, icao_code + ': no data provided')
+ return
+
+ if metar[0] == 'CAVOK':
+ cover.append('CLR')
+ metar = metar[1:]
+
+ if metar[0] == 'PRFG':
+ cover.append('CLR') # @@?
+ metar = metar[1:]
+
+ if metar[0] == 'NSC':
+ cover.append('CLR')
+ metar = metar[1:]
+
+ if ('/' in metar[0]) or (len(metar[0]) == 5 and metar[0][2] == '.'):
+ temp = metar[0]
+ metar = metar[1:]
+ else: temp = None
+
+ if metar[0].startswith('QFE'):
+ metar = metar[1:]
+
+ if metar[0].startswith('Q') or metar[0].startswith('A'):
+ pressure = metar[0]
+ metar = metar[1:]
+ else: pressure = None
+
+ if time:
+ hour = time[2:4]
+ minute = time[4:6]
+ time = local(icao_code, hour, minute)
+ else: time = '(time unknown)'
+
+ if wind:
+ speed = int(wind[3:5])
+ if speed < 1:
+ description = 'Calm'
+ elif speed < 4:
+ description = 'Light air'
+ elif speed < 7:
+ description = 'Light breeze'
+ elif speed < 11:
+ description = 'Gentle breeze'
+ elif speed < 16:
+ description = 'Moderate breeze'
+ elif speed < 22:
+ description = 'Fresh breeze'
+ elif speed < 28:
+ description = 'Strong breeze'
+ elif speed < 34:
+ description = 'Near gale'
+ elif speed < 41:
+ description = 'Gale'
+ elif speed < 48:
+ description = 'Strong gale'
+ elif speed < 56:
+ description = 'Storm'
+ elif speed < 64:
+ description = 'Violent storm'
+ else: description = 'Hurricane'
+
+ degrees = wind[0:3]
+ if degrees == 'VRB':
+ degrees = u'\u21BB'.encode('utf-8')
+ elif (degrees <= 22.5) or (degrees > 337.5):
+ degrees = u'\u2191'.encode('utf-8')
+ elif (degrees > 22.5) and (degrees <= 67.5):
+ degrees = u'\u2197'.encode('utf-8')
+ elif (degrees > 67.5) and (degrees <= 112.5):
+ degrees = u'\u2192'.encode('utf-8')
+ elif (degrees > 112.5) and (degrees <= 157.5):
+ degrees = u'\u2198'.encode('utf-8')
+ elif (degrees > 157.5) and (degrees <= 202.5):
+ degrees = u'\u2193'.encode('utf-8')
+ elif (degrees > 202.5) and (degrees <= 247.5):
+ degrees = u'\u2199'.encode('utf-8')
+ elif (degrees > 247.5) and (degrees <= 292.5):
+ degrees = u'\u2190'.encode('utf-8')
+ elif (degrees > 292.5) and (degrees <= 337.5):
+ degrees = u'\u2196'.encode('utf-8')
+
+ if not icao_code.startswith('EN') and not icao_code.startswith('ED'):
+ wind = '%s %skt (%s)' % (description, speed, degrees)
+ elif icao_code.startswith('ED'):
+ kmh = int(round(speed * 1.852, 0))
+ wind = '%s %skm/h (%skt) (%s)' % (description, kmh, speed, degrees)
+ elif icao_code.startswith('EN'):
+ ms = int(round(speed * 0.514444444, 0))
+ wind = '%s %sm/s (%skt) (%s)' % (description, ms, speed, degrees)
+ else: wind = '(wind unknown)'
+
+ if visibility:
+ visibility = visibility + 'm'
+ else: visibility = '(visibility unknown)'
+
+ if cover:
+ level = None
+ for c in cover:
+ if c.startswith('OVC') or c.startswith('VV'):
+ if (level is None) or (level < 8):
+ level = 8
+ elif c.startswith('BKN'):
+ if (level is None) or (level < 5):
+ level = 5
+ elif c.startswith('SCT'):
+ if (level is None) or (level < 3):
+ level = 3
+ elif c.startswith('FEW'):
+ if (level is None) or (level < 1):
+ level = 1
+ elif c.startswith('SKC') or c.startswith('CLR'):
+ if level is None:
+ level = 0
+
+ if level == 8:
+ cover = u'Overcast \u2601'.encode('utf-8')
+ elif level == 5:
+ cover = 'Cloudy'
+ elif level == 3:
+ cover = 'Scattered'
+ elif (level == 1) or (level == 0):
+ cover = u'Clear \u263C'.encode('utf-8')
+ else: cover = 'Cover Unknown'
+ else: cover = 'Cover Unknown'
+
+ if temp:
+ if '/' in temp:
+ temp = temp.split('/')[0]
+ else: temp = temp.split('.')[0]
+ if temp.startswith('M'):
+ temp = '-' + temp[1:]
+ try: temp = int(temp)
+ except ValueError: temp = '?'
+ else: temp = '?'
+
+ if pressure:
+ if pressure.startswith('Q'):
+ pressure = pressure.lstrip('Q')
+ if pressure != 'NIL':
+ pressure = str(int(pressure)) + 'mb'
+ else: pressure = '?mb'
+ elif pressure.startswith('A'):
+ pressure = pressure.lstrip('A')
+ if pressure != 'NIL':
+ inches = pressure[:2] + '.' + pressure[2:]
+ mb = int(float(inches) * 33.7685)
+ pressure = '%sin (%smb)' % (inches, mb)
+ else: pressure = '?mb'
+
+ if isinstance(temp, int):
+ f = round((temp * 1.8) + 32, 2)
+ temp = u'%s\u2109 (%s\u2103)'.encode('utf-8') % (f, temp)
+ else: pressure = '?mb'
+ if isinstance(temp, int):
+ temp = u'%s\u2103'.encode('utf-8') % temp
+
+ if cond:
+ conds = cond
+ cond = ''
+
+ intensities = {
+ '-': 'Light',
+ '+': 'Heavy'
+ }
+
+ descriptors = {
+ 'MI': 'Shallow',
+ 'PR': 'Partial',
+ 'BC': 'Patches',
+ 'DR': 'Drifting',
+ 'BL': 'Blowing',
+ 'SH': 'Showers of',
+ 'TS': 'Thundery',
+ 'FZ': 'Freezing',
+ 'VC': 'In the vicinity:'
+ }
+
+ phenomena = {
+ 'DZ': 'Drizzle',
+ 'RA': 'Rain',
+ 'SN': 'Snow',
+ 'SG': 'Snow Grains',
+ 'IC': 'Ice Crystals',
+ 'PL': 'Ice Pellets',
+ 'GR': 'Hail',
+ 'GS': 'Small Hail',
+ 'UP': 'Unknown Precipitation',
+ 'BR': 'Mist',
+ 'FG': 'Fog',
+ 'FU': 'Smoke',
+ 'VA': 'Volcanic Ash',
+ 'DU': 'Dust',
+ 'SA': 'Sand',
+ 'HZ': 'Haze',
+ 'PY': 'Spray',
+ 'PO': 'Whirls',
+ 'SQ': 'Squalls',
+ 'FC': 'Tornado',
+ 'SS': 'Sandstorm',
+ 'DS': 'Duststorm',
+ # ? Cf. http://swhack.com/logs/2007-10-05#T07-58-56
+ 'TS': 'Thunderstorm',
+ 'SH': 'Showers'
+ }
+
+ for c in conds:
+ if c.endswith('//'):
+ if cond: cond += ', '
+ cond += 'Some Precipitation'
+ elif len(c) == 5:
+ intensity = intensities[c[0]]
+ descriptor = descriptors[c[1:3]]
+ phenomenon = phenomena.get(c[3:], c[3:])
+ if cond: cond += ', '
+ cond += intensity + ' ' + descriptor + ' ' + phenomenon
+ elif len(c) == 4:
+ descriptor = descriptors.get(c[:2], c[:2])
+ phenomenon = phenomena.get(c[2:], c[2:])
+ if cond: cond += ', '
+ cond += descriptor + ' ' + phenomenon
+ elif len(c) == 3:
+ intensity = intensities.get(c[0], c[0])
+ phenomenon = phenomena.get(c[1:], c[1:])
+ if cond: cond += ', '
+ cond += intensity + ' ' + phenomenon
+ elif len(c) == 2:
+ phenomenon = phenomena.get(c, c)
+ if cond: cond += ', '
+ cond += phenomenon
+
+ # if not cond:
+ # format = u'%s at %s: %s, %s, %s, %s'
+ # args = (icao, time, cover, temp, pressure, wind)
+ # else:
+ # format = u'%s at %s: %s, %s, %s, %s, %s'
+ # args = (icao, time, cover, temp, pressure, cond, wind)
+
+ if not cond:
+ format = u'%s, %s, %s, %s - %s %s'
+ args = (cover, temp, pressure, wind, str(icao_code), time)
+ else:
+ format = u'%s, %s, %s, %s, %s - %s, %s'
+ args = (cover, temp, pressure, cond, wind, str(icao_code), time)
+
+ self.msg(origin.sender, format.encode('utf-8') % args)
f_weather.rule = (['weather'], r'(.*)')
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/wikipedia.py b/modules/wikipedia.py
index 1a406b3..489afe9 100755
--- a/modules/wikipedia.py
+++ b/modules/wikipedia.py
@@ -12,171 +12,171 @@ import web
wikiuri = 'http://%s.wikipedia.org/wiki/%s'
# wikisearch = 'http://%s.wikipedia.org/wiki/Special:Search?' \
-# + 'search=%s&fulltext=Search'
+# + 'search=%s&fulltext=Search'
r_tr = re.compile(r'(?ims)<tr[^>]*>.*?</tr>')
r_paragraph = re.compile(r'(?ims)<p[^>]*>.*?</p>|<li(?!n)[^>]*>.*?</li>')
r_tag = re.compile(r'<(?!!)[^>]+>')
r_whitespace = re.compile(r'[\t\r\n ]+')
r_redirect = re.compile(
- r'(?ims)class=.redirectText.>\s*<a\s*href=./wiki/([^"/]+)'
+ r'(?ims)class=.redirectText.>\s*<a\s*href=./wiki/([^"/]+)'
)
-abbrs = ['etc', 'ca', 'cf', 'Co', 'Ltd', 'Inc', 'Mt', 'Mr', 'Mrs',
- 'Dr', 'Ms', 'Rev', 'Fr', 'St', 'Sgt', 'pron', 'approx', 'lit',
- 'syn', 'transl', 'sess', 'fl', 'Op', 'Dec', 'Brig', 'Gen'] \
- + list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') \
- + list('abcdefghijklmnopqrstuvwxyz')
+abbrs = ['etc', 'ca', 'cf', 'Co', 'Ltd', 'Inc', 'Mt', 'Mr', 'Mrs',
+ 'Dr', 'Ms', 'Rev', 'Fr', 'St', 'Sgt', 'pron', 'approx', 'lit',
+ 'syn', 'transl', 'sess', 'fl', 'Op', 'Dec', 'Brig', 'Gen'] \
+ + list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') \
+ + list('abcdefghijklmnopqrstuvwxyz')
t_sentence = r'^.{5,}?(?<!\b%s)(?:\.(?=[\[ ][A-Z0-9]|\Z)|\Z)'
r_sentence = re.compile(t_sentence % r')(?<!\b'.join(abbrs))
-def unescape(s):
- s = s.replace('&gt;', '>')
- s = s.replace('&lt;', '<')
- s = s.replace('&amp;', '&')
- s = s.replace('&#160;', ' ')
- return s
-
-def text(html):
- html = r_tag.sub('', html)
- html = r_whitespace.sub(' ', html)
- return unescape(html).strip()
-
-def search(term):
- try: import search
- except ImportError, e:
- print e
- return term
-
- if isinstance(term, unicode):
- term = term.encode('utf-8')
- else: term = term.decode('utf-8')
-
- term = term.replace('_', ' ')
- try: uri = search.google_search('site:en.wikipedia.org %s' % term)
- except IndexError: return term
- if uri:
- return uri[len('http://en.wikipedia.org/wiki/'):]
- else: return term
-
-def wikipedia(term, language='en', last=False):
- global wikiuri
- if not '%' in term:
- if isinstance(term, unicode):
- t = term.encode('utf-8')
- else: t = term
- q = urllib.quote(t)
- u = wikiuri % (language, q)
- bytes = web.get(u)
- else: bytes = web.get(wikiuri % (language, term))
-
- if bytes.startswith('\x1f\x8b\x08\x00\x00\x00\x00\x00'):
- f = StringIO.StringIO(bytes)
- f.seek(0)
- gzip_file = gzip.GzipFile(fileobj=f)
- bytes = gzip_file.read()
- gzip_file.close()
- f.close()
-
- bytes = r_tr.sub('', bytes)
-
- if not last:
- r = r_redirect.search(bytes[:4096])
- if r:
- term = urllib.unquote(r.group(1))
- return wikipedia(term, language=language, last=True)
-
- paragraphs = r_paragraph.findall(bytes)
-
- if not paragraphs:
- if not last:
- term = search(term)
- return wikipedia(term, language=language, last=True)
- return None
-
- # Pre-process
- paragraphs = [para for para in paragraphs
- if (para and 'technical limitations' not in para
- and 'window.showTocToggle' not in para
- and 'Deletion_policy' not in para
- and 'Template:AfD_footer' not in para
- and not (para.startswith('<p><i>') and
- para.endswith('</i></p>'))
- and not 'disambiguation)"' in para)
- and not '(images and media)' in para
- and not 'This article contains a' in para
- and not 'id="coordinates"' in para
- and not 'class="thumb' in para]
- # and not 'style="display:none"' in para]
-
- for i, para in enumerate(paragraphs):
- para = para.replace('<sup>', '|')
- para = para.replace('</sup>', '|')
- paragraphs[i] = text(para).strip()
-
- # Post-process
- paragraphs = [para for para in paragraphs if
- (para and not (para.endswith(':') and len(para) < 150))]
-
- para = text(paragraphs[0])
- m = r_sentence.match(para)
-
- if not m:
- if not last:
- term = search(term)
- return wikipedia(term, language=language, last=True)
- return None
- sentence = m.group(0)
-
- maxlength = 275
- if len(sentence) > maxlength:
- sentence = sentence[:maxlength]
- words = sentence[:-5].split(' ')
- words.pop()
- sentence = ' '.join(words) + ' [...]'
-
- if (('using the Article Wizard if you wish' in sentence)
- or ('or add a request for it' in sentence)
- or ('in existing articles' in sentence)):
- if not last:
- term = search(term)
- return wikipedia(term, language=language, last=True)
- return None
-
- sentence = '"' + sentence.replace('"', "'") + '"'
- sentence = sentence.decode('utf-8').encode('utf-8')
- wikiuri = wikiuri.decode('utf-8').encode('utf-8')
- term = term.decode('utf-8').encode('utf-8')
- return sentence + ' - ' + (wikiuri % (language, term))
-
-def wik(phenny, input):
- origterm = input.groups()[1]
- if not origterm:
- return phenny.say('Perhaps you meant ".wik Zen"?')
- origterm = origterm.encode('utf-8')
-
- term = urllib.unquote(origterm)
- language = 'en'
- if term.startswith(':') and (' ' in term):
- a, b = term.split(' ', 1)
- a = a.lstrip(':')
- if a.isalpha():
- language, term = a, b
- term = term[0].upper() + term[1:]
- term = term.replace(' ', '_')
-
- try: result = wikipedia(term, language)
- except IOError:
- args = (language, wikiuri % (language, term))
- error = "Can't connect to %s.wikipedia.org (%s)" % args
- return phenny.say(error)
-
- if result is not None:
- phenny.say(result)
- else: phenny.say('Can\'t find anything in Wikipedia for "%s".' % origterm)
+def unescape(s):
+ s = s.replace('&gt;', '>')
+ s = s.replace('&lt;', '<')
+ s = s.replace('&amp;', '&')
+ s = s.replace('&#160;', ' ')
+ return s
+
+def text(html):
+ html = r_tag.sub('', html)
+ html = r_whitespace.sub(' ', html)
+ return unescape(html).strip()
+
+def search(term):
+ try: import search
+ except ImportError, e:
+ print e
+ return term
+
+ if isinstance(term, unicode):
+ term = term.encode('utf-8')
+ else: term = term.decode('utf-8')
+
+ term = term.replace('_', ' ')
+ try: uri = search.google_search('site:en.wikipedia.org %s' % term)
+ except IndexError: return term
+ if uri:
+ return uri[len('http://en.wikipedia.org/wiki/'):]
+ else: return term
+
+def wikipedia(term, language='en', last=False):
+ global wikiuri
+ if not '%' in term:
+ if isinstance(term, unicode):
+ t = term.encode('utf-8')
+ else: t = term
+ q = urllib.quote(t)
+ u = wikiuri % (language, q)
+ bytes = web.get(u)
+ else: bytes = web.get(wikiuri % (language, term))
+
+ if bytes.startswith('\x1f\x8b\x08\x00\x00\x00\x00\x00'):
+ f = StringIO.StringIO(bytes)
+ f.seek(0)
+ gzip_file = gzip.GzipFile(fileobj=f)
+ bytes = gzip_file.read()
+ gzip_file.close()
+ f.close()
+
+ bytes = r_tr.sub('', bytes)
+
+ if not last:
+ r = r_redirect.search(bytes[:4096])
+ if r:
+ term = urllib.unquote(r.group(1))
+ return wikipedia(term, language=language, last=True)
+
+ paragraphs = r_paragraph.findall(bytes)
+
+ if not paragraphs:
+ if not last:
+ term = search(term)
+ return wikipedia(term, language=language, last=True)
+ return None
+
+ # Pre-process
+ paragraphs = [para for para in paragraphs
+ if (para and 'technical limitations' not in para
+ and 'window.showTocToggle' not in para
+ and 'Deletion_policy' not in para
+ and 'Template:AfD_footer' not in para
+ and not (para.startswith('<p><i>') and
+ para.endswith('</i></p>'))
+ and not 'disambiguation)"' in para)
+ and not '(images and media)' in para
+ and not 'This article contains a' in para
+ and not 'id="coordinates"' in para
+ and not 'class="thumb' in para]
+ # and not 'style="display:none"' in para]
+
+ for i, para in enumerate(paragraphs):
+ para = para.replace('<sup>', '|')
+ para = para.replace('</sup>', '|')
+ paragraphs[i] = text(para).strip()
+
+ # Post-process
+ paragraphs = [para for para in paragraphs if
+ (para and not (para.endswith(':') and len(para) < 150))]
+
+ para = text(paragraphs[0])
+ m = r_sentence.match(para)
+
+ if not m:
+ if not last:
+ term = search(term)
+ return wikipedia(term, language=language, last=True)
+ return None
+ sentence = m.group(0)
+
+ maxlength = 275
+ if len(sentence) > maxlength:
+ sentence = sentence[:maxlength]
+ words = sentence[:-5].split(' ')
+ words.pop()
+ sentence = ' '.join(words) + ' [...]'
+
+ if (('using the Article Wizard if you wish' in sentence)
+ or ('or add a request for it' in sentence)
+ or ('in existing articles' in sentence)):
+ if not last:
+ term = search(term)
+ return wikipedia(term, language=language, last=True)
+ return None
+
+ sentence = '"' + sentence.replace('"', "'") + '"'
+ sentence = sentence.decode('utf-8').encode('utf-8')
+ wikiuri = wikiuri.decode('utf-8').encode('utf-8')
+ term = term.decode('utf-8').encode('utf-8')
+ return sentence + ' - ' + (wikiuri % (language, term))
+
+def wik(phenny, input):
+ origterm = input.groups()[1]
+ if not origterm:
+ return phenny.say('Perhaps you meant ".wik Zen"?')
+ origterm = origterm.encode('utf-8')
+
+ term = urllib.unquote(origterm)
+ language = 'en'
+ if term.startswith(':') and (' ' in term):
+ a, b = term.split(' ', 1)
+ a = a.lstrip(':')
+ if a.isalpha():
+ language, term = a, b
+ term = term[0].upper() + term[1:]
+ term = term.replace(' ', '_')
+
+ try: result = wikipedia(term, language)
+ except IOError:
+ args = (language, wikiuri % (language, term))
+ error = "Can't connect to %s.wikipedia.org (%s)" % args
+ return phenny.say(error)
+
+ if result is not None:
+ phenny.say(result)
+ else: phenny.say('Can\'t find anything in Wikipedia for "%s".' % origterm)
wik.commands = ['wik']
wik.priority = 'high'
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()
diff --git a/modules/wiktionary.py b/modules/wiktionary.py
index 9229194..d3321c5 100755
--- a/modules/wiktionary.py
+++ b/modules/wiktionary.py
@@ -14,87 +14,87 @@ uri = 'http://en.wiktionary.org/w/index.php?title=%s&printable=yes'
r_tag = re.compile(r'<[^>]+>')
r_ul = re.compile(r'(?ims)<ul>.*?</ul>')
-def text(html):
- text = r_tag.sub('', html).strip()
- text = text.replace('\n', ' ')
- text = text.replace('\r', '')
- text = text.replace('(intransitive', '(intr.')
- text = text.replace('(transitive', '(trans.')
- return text
+def text(html):
+ text = r_tag.sub('', html).strip()
+ text = text.replace('\n', ' ')
+ text = text.replace('\r', '')
+ text = text.replace('(intransitive', '(intr.')
+ text = text.replace('(transitive', '(trans.')
+ return text
-def wiktionary(word):
- bytes = web.get(uri % web.urllib.quote(word.encode('utf-8')))
- bytes = r_ul.sub('', bytes)
+def wiktionary(word):
+ bytes = web.get(uri % web.urllib.quote(word.encode('utf-8')))
+ bytes = r_ul.sub('', bytes)
- mode = None
- etymology = None
- definitions = {}
- for line in bytes.splitlines():
- if 'id="Etymology"' in line:
- mode = 'etymology'
- elif 'id="Noun"' in line:
- mode = 'noun'
- elif 'id="Verb"' in line:
- mode = 'verb'
- elif 'id="Adjective"' in line:
- mode = 'adjective'
- elif 'id="Adverb"' in line:
- mode = 'adverb'
- elif 'id="Interjection"' in line:
- mode = 'interjection'
- elif 'id="Particle"' in line:
- mode = 'particle'
- elif 'id="Preposition"' in line:
- mode = 'preposition'
- elif 'id="' in line:
- mode = None
+ mode = None
+ etymology = None
+ definitions = {}
+ for line in bytes.splitlines():
+ if 'id="Etymology"' in line:
+ mode = 'etymology'
+ elif 'id="Noun"' in line:
+ mode = 'noun'
+ elif 'id="Verb"' in line:
+ mode = 'verb'
+ elif 'id="Adjective"' in line:
+ mode = 'adjective'
+ elif 'id="Adverb"' in line:
+ mode = 'adverb'
+ elif 'id="Interjection"' in line:
+ mode = 'interjection'
+ elif 'id="Particle"' in line:
+ mode = 'particle'
+ elif 'id="Preposition"' in line:
+ mode = 'preposition'
+ elif 'id="' in line:
+ mode = None
- elif (mode == 'etmyology') and ('<p>' in line):
- etymology = text(line)
- elif (mode is not None) and ('<li>' in line):
- definitions.setdefault(mode, []).append(text(line))
+ elif (mode == 'etmyology') and ('<p>' in line):
+ etymology = text(line)
+ elif (mode is not None) and ('<li>' in line):
+ definitions.setdefault(mode, []).append(text(line))
- if '<hr' in line:
- break
- return etymology, definitions
+ if '<hr' in line:
+ break
+ return etymology, definitions
-parts = ('preposition', 'particle', 'noun', 'verb',
- 'adjective', 'adverb', 'interjection')
+parts = ('preposition', 'particle', 'noun', 'verb',
+ 'adjective', 'adverb', 'interjection')
-def format(word, definitions, number=2):
- result = '%s' % word.encode('utf-8')
- for part in parts:
- if definitions.has_key(part):
- defs = definitions[part][:number]
- result += u' \u2014 '.encode('utf-8') + ('%s: ' % part)
- n = ['%s. %s' % (i + 1, e.strip(' .')) for i, e in enumerate(defs)]
- result += ', '.join(n)
- return result.strip(' .,')
+def format(word, definitions, number=2):
+ result = '%s' % word.encode('utf-8')
+ for part in parts:
+ if definitions.has_key(part):
+ defs = definitions[part][:number]
+ result += u' \u2014 '.encode('utf-8') + ('%s: ' % part)
+ n = ['%s. %s' % (i + 1, e.strip(' .')) for i, e in enumerate(defs)]
+ result += ', '.join(n)
+ return result.strip(' .,')
-def w(phenny, input):
- if not input.group(2):
- return phenny.reply("Nothing to define.")
- word = input.group(2)
- etymology, definitions = wiktionary(word)
- if not definitions:
- phenny.say("Couldn't get any definitions for %s." % word)
- return
+def w(phenny, input):
+ if not input.group(2):
+ return phenny.reply("Nothing to define.")
+ word = input.group(2)
+ etymology, definitions = wiktionary(word)
+ if not definitions:
+ phenny.say("Couldn't get any definitions for %s." % word)
+ return
- result = format(word, definitions)
- if len(result) < 150:
- result = format(word, definitions, 3)
- if len(result) < 150:
- result = format(word, definitions, 5)
+ result = format(word, definitions)
+ if len(result) < 150:
+ result = format(word, definitions, 3)
+ if len(result) < 150:
+ result = format(word, definitions, 5)
- if len(result) > 300:
- result = result[:295] + '[...]'
- phenny.say(result)
+ if len(result) > 300:
+ result = result[:295] + '[...]'
+ phenny.say(result)
w.commands = ['w']
w.example = '.w bailiwick'
-def encarta(phenny, input):
- return phenny.reply('Microsoft removed Encarta, try .w instead!')
+def encarta(phenny, input):
+ return phenny.reply('Microsoft removed Encarta, try .w instead!')
encarta.commands = ['dict']
-if __name__ == '__main__':
- print __doc__.strip()
+if __name__ == '__main__':
+ print __doc__.strip()