module formatting tweaks; tabs -> spaces and more

master
mutantmonkey 2012-01-03 14:09:34 -05:00
parent 733d3fd39e
commit 56f116732d
32 changed files with 1307 additions and 1434 deletions

View File

@ -49,4 +49,3 @@ eightball.commands = ['8ball']
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -7,7 +7,7 @@ Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/ http://inamidst.com/phenny/
modified from Wikipedia module modified from Wikipedia module
author: mutantmonkey <mutantmonkey@gmail.com> author: mutantmonkey <mutantmonkey@mutantmonkey.in>
""" """
import re, urllib.request, urllib.parse, urllib.error import re, urllib.request, urllib.parse, urllib.error

View File

@ -1,7 +1,7 @@
#!/usr/bin/python2 #!/usr/bin/python2
""" """
botfight.py - .botfight module botfight.py - .botfight module
author: mutantmonkey <mutantmonkey@gmail.com> author: mutantmonkey <mutantmonkey@mutantmonkey.in>
""" """
import random import random
@ -9,18 +9,17 @@ import random
otherbot = "truncatedcone" otherbot = "truncatedcone"
def botfight(phenny, input): def botfight(phenny, input):
messages = ["hits %s", "punches %s", "kicks %s", "hits %s with a rubber hose", "stabs %s with a clean kitchen knife"] messages = ["hits %s", "punches %s", "kicks %s", "hits %s with a rubber hose", "stabs %s with a clean kitchen knife"]
response = random.choice(messages) response = random.choice(messages)
phenny.do(response % otherbot) phenny.do(response % otherbot)
botfight.commands = ['botfight'] botfight.commands = ['botfight']
botfight.priority = 'low' botfight.priority = 'low'
def bothug(phenny, input): def bothug(phenny, input):
phenny.do("hugs %s" % otherbot) phenny.do("hugs %s" % otherbot)
bothug.commands = ['bothug'] bothug.commands = ['bothug']
bothug.priority = 'low' bothug.priority = 'low'
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -1,7 +1,7 @@
#!/usr/bin/python2 #!/usr/bin/python2
""" """
botsnack.py - .botsnack module (aka simulated hunger 1.0) botsnack.py - .botsnack module (aka simulated hunger 1.0)
author: mutantmonkey <mutantmonkey@gmail.com> author: mutantmonkey <mutantmonkey@mutantmonkey.in>
author: Casey Link <unnamedrambler@gmail.com> author: Casey Link <unnamedrambler@gmail.com>
This module simulates bot hunger and provides a mechanism This module simulates bot hunger and provides a mechanism
@ -106,5 +106,4 @@ botsnack.last_tick = time.time()
botsnack.coolingdown = False botsnack.coolingdown = False
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -15,100 +15,100 @@ r_result = re.compile(r'(?i)<A NAME=results>(.*?)</A>')
r_tag = re.compile(r'<\S+.*?>') r_tag = re.compile(r'<\S+.*?>')
subs = [ subs = [
(' in ', ' -> '), (' in ', ' -> '),
(' over ', ' / '), (' over ', ' / '),
('£', 'GBP '), ('£', 'GBP '),
('', 'EUR '), ('', 'EUR '),
('\$', 'USD '), ('\$', 'USD '),
(r'\bKB\b', 'kilobytes'), (r'\bKB\b', 'kilobytes'),
(r'\bMB\b', 'megabytes'), (r'\bMB\b', 'megabytes'),
(r'\bGB\b', 'kilobytes'), (r'\bGB\b', 'kilobytes'),
('kbps', '(kilobits / second)'), ('kbps', '(kilobits / second)'),
('mbps', '(megabits / second)') ('mbps', '(megabits / second)')
] ]
def calc(phenny, input): def calc(phenny, input):
"""Use the Frink online calculator.""" """Use the Frink online calculator."""
q = input.group(2) q = input.group(2)
if not q: if not q:
return phenny.say('0?') return phenny.say('0?')
query = q[:] query = q[:]
for a, b in subs: for a, b in subs:
query = re.sub(a, b, query) query = re.sub(a, b, query)
query = query.rstrip(' \t') query = query.rstrip(' \t')
precision = 5 precision = 5
if query[-3:] in ('GBP', 'USD', 'EUR', 'NOK'): if query[-3:] in ('GBP', 'USD', 'EUR', 'NOK'):
precision = 2 precision = 2
query = web.quote(query) query = web.quote(query)
uri = 'http://futureboy.us/fsp/frink.fsp?fromVal=' uri = 'http://futureboy.us/fsp/frink.fsp?fromVal='
bytes = web.get(uri + query) bytes = web.get(uri + query)
m = r_result.search(bytes) m = r_result.search(bytes)
if m: if m:
result = m.group(1) result = m.group(1)
result = r_tag.sub('', result) # strip span.warning tags result = r_tag.sub('', result) # strip span.warning tags
result = result.replace('&gt;', '>') result = result.replace('&gt;', '>')
result = result.replace('(undefined symbol)', '(?) ') result = result.replace('(undefined symbol)', '(?) ')
if '.' in result: if '.' in result:
try: result = str(round(float(result), precision)) try: result = str(round(float(result), precision))
except ValueError: pass except ValueError: pass
if not result.strip(): if not result.strip():
result = '?' result = '?'
elif ' in ' in q: elif ' in ' in q:
result += ' ' + q.split(' in ', 1)[1] result += ' ' + q.split(' in ', 1)[1]
phenny.say(q + ' = ' + result[:350]) phenny.say(q + ' = ' + result[:350])
else: phenny.reply("Sorry, can't calculate that.") else: phenny.reply("Sorry, can't calculate that.")
phenny.say('Note that .calc is deprecated, consider using .c') phenny.say('Note that .calc is deprecated, consider using .c')
calc.commands = ['calc'] calc.commands = ['calc']
calc.example = '.calc 5 + 3' calc.example = '.calc 5 + 3'
def c(phenny, input): def c(phenny, input):
"""Google calculator.""" """Google calculator."""
if not input.group(2): if not input.group(2):
return phenny.reply("Nothing to calculate.") return phenny.reply("Nothing to calculate.")
q = input.group(2) q = input.group(2)
q = q.replace('\xcf\x95', 'phi') # utf-8 U+03D5 q = q.replace('\xcf\x95', 'phi') # utf-8 U+03D5
q = q.replace('\xcf\x80', 'pi') # utf-8 U+03C0 q = q.replace('\xcf\x80', 'pi') # utf-8 U+03C0
uri = 'http://www.google.com/ig/calculator?q=' uri = 'http://www.google.com/ig/calculator?q='
bytes = web.get(uri + web.quote(q)) bytes = web.get(uri + web.quote(q))
parts = bytes.split('",') parts = bytes.split('",')
answer = [p for p in parts if p.startswith('rhs: "')][0][6:] answer = [p for p in parts if p.startswith('rhs: "')][0][6:]
if answer: if answer:
#answer = ''.join(chr(ord(c)) for c in answer) #answer = ''.join(chr(ord(c)) for c in answer)
#answer = answer.decode('utf-8') #answer = answer.decode('utf-8')
answer = answer.replace('\xc2\xa0', ',') answer = answer.replace('\xc2\xa0', ',')
answer = answer.replace('<sup>', '^(') answer = answer.replace('<sup>', '^(')
answer = answer.replace('</sup>', ')') answer = answer.replace('</sup>', ')')
answer = web.decode(answer) answer = web.decode(answer)
phenny.say(answer) phenny.say(answer)
else: phenny.say('Sorry, no result.') else: phenny.say('Sorry, no result.')
c.commands = ['c'] c.commands = ['c']
c.example = '.c 5 + 3' c.example = '.c 5 + 3'
def py(phenny, input): def py(phenny, input):
query = input.group(2) query = input.group(2)
uri = 'http://tumbolia.appspot.com/py/' uri = 'http://tumbolia.appspot.com/py/'
answer = web.get(uri + web.quote(query)) answer = web.get(uri + web.quote(query))
if answer: if answer:
phenny.say(answer) phenny.say(answer)
else: phenny.reply('Sorry, no result.') else: phenny.reply('Sorry, no result.')
py.commands = ['py'] py.commands = ['py']
def wa(phenny, input): def wa(phenny, input):
if not input.group(2): if not input.group(2):
return phenny.reply("No search term.") return phenny.reply("No search term.")
query = input.group(2) query = input.group(2)
uri = 'http://tumbolia.appspot.com/wa/' uri = 'http://tumbolia.appspot.com/wa/'
answer = web.get(uri + web.quote(query.replace('+', '%2B'))) answer = web.get(uri + web.quote(query.replace('+', '%2B')))
if answer: if answer:
phenny.say(answer) phenny.say(answer)
else: phenny.reply('Sorry, no result.') else: phenny.reply('Sorry, no result.')
wa.commands = ['wa'] wa.commands = ['wa']
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -143,4 +143,4 @@ chill.commands = ['chill']
chill.priority = 'low' chill.priority = 'low'
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -12,20 +12,20 @@ from decimal import Decimal as dec
from tools import deprecated from tools import deprecated
TimeZones = {'KST': 9, 'CADT': 10.5, 'EETDST': 3, 'MESZ': 2, 'WADT': 9, TimeZones = {'KST': 9, 'CADT': 10.5, 'EETDST': 3, 'MESZ': 2, 'WADT': 9,
'EET': 2, 'MST': -7, 'WAST': 8, 'IST': 5.5, 'B': 2, 'EET': 2, 'MST': -7, 'WAST': 8, 'IST': 5.5, 'B': 2,
'MSK': 3, 'X': -11, 'MSD': 4, 'CETDST': 2, 'AST': -4, 'MSK': 3, 'X': -11, 'MSD': 4, 'CETDST': 2, 'AST': -4,
'HKT': 8, 'JST': 9, 'CAST': 9.5, 'CET': 1, 'CEST': 2, 'HKT': 8, 'JST': 9, 'CAST': 9.5, 'CET': 1, 'CEST': 2,
'EEST': 3, 'EAST': 10, 'METDST': 2, 'MDT': -6, 'A': 1, 'EEST': 3, 'EAST': 10, 'METDST': 2, 'MDT': -6, 'A': 1,
'UTC': 0, 'ADT': -3, 'EST': -5, 'E': 5, 'D': 4, 'G': 7, 'UTC': 0, 'ADT': -3, 'EST': -5, 'E': 5, 'D': 4, 'G': 7,
'F': 6, 'I': 9, 'H': 8, 'K': 10, 'PDT': -7, 'M': 12, 'F': 6, 'I': 9, 'H': 8, 'K': 10, 'PDT': -7, 'M': 12,
'L': 11, 'O': -2, 'MEST': 2, 'Q': -4, 'P': -3, 'S': -6, 'L': 11, 'O': -2, 'MEST': 2, 'Q': -4, 'P': -3, 'S': -6,
'R': -5, 'U': -8, 'T': -7, 'W': -10, 'WET': 0, 'Y': -12, 'R': -5, 'U': -8, 'T': -7, 'W': -10, 'WET': 0, 'Y': -12,
'CST': -6, 'EADT': 11, 'Z': 0, 'GMT': 0, 'WETDST': 1, 'CST': -6, 'EADT': 11, 'Z': 0, 'GMT': 0, 'WETDST': 1,
'C': 3, 'WEST': 1, 'CDT': -5, 'MET': 1, 'N': -1, 'V': -9, 'C': 3, 'WEST': 1, 'CDT': -5, 'MET': 1, 'N': -1, 'V': -9,
'EDT': -4, 'UT': 0, 'PST': -8, 'MEZ': 1, 'BST': 1, 'EDT': -4, 'UT': 0, 'PST': -8, 'MEZ': 1, 'BST': 1,
'ACS': 9.5, 'ATL': -4, 'ALA': -9, 'HAW': -10, 'AKDT': -8, 'ACS': 9.5, 'ATL': -4, 'ALA': -9, 'HAW': -10, 'AKDT': -8,
'AKST': -9, 'AKST': -9,
'BDST': 2} 'BDST': 2}
TZ1 = { TZ1 = {
'NDT': -2.5, 'NDT': -2.5,
@ -183,8 +183,8 @@ TZ2 = {
} }
TZ3 = { TZ3 = {
'AEST': 10, 'AEST': 10,
'AEDT': 11 'AEDT': 11
} }
# TimeZones.update(TZ2) # do these have to be negated? # TimeZones.update(TZ2) # do these have to be negated?
@ -195,109 +195,109 @@ r_local = re.compile(r'\([a-z]+_[A-Z]+\)')
@deprecated @deprecated
def f_time(self, origin, match, args): def f_time(self, origin, match, args):
"""Returns the current time.""" """Returns the current time."""
tz = match.group(2) or 'GMT' tz = match.group(2) or 'GMT'
# Personal time zones, because they're rad # Personal time zones, because they're rad
if hasattr(self.config, 'timezones'): if hasattr(self.config, 'timezones'):
People = self.config.timezones People = self.config.timezones
else: People = {} else: People = {}
if tz in People: if tz in People:
tz = People[tz] tz = People[tz]
elif (not match.group(2)) and origin.nick in People: elif (not match.group(2)) and origin.nick in People:
tz = People[origin.nick] tz = People[origin.nick]
TZ = tz.upper() TZ = tz.upper()
if len(tz) > 30: return if len(tz) > 30: return
if (TZ == 'UTC') or (TZ == 'Z'): if (TZ == 'UTC') or (TZ == 'Z'):
msg = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()) msg = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
self.msg(origin.sender, msg) self.msg(origin.sender, msg)
elif r_local.match(tz): # thanks to Mark Shoulsdon (clsn) elif r_local.match(tz): # thanks to Mark Shoulsdon (clsn)
locale.setlocale(locale.LC_TIME, (tz[1:-1], 'UTF-8')) locale.setlocale(locale.LC_TIME, (tz[1:-1], 'UTF-8'))
msg = time.strftime("%A, %d %B %Y %H:%M:%SZ", time.gmtime()) msg = time.strftime("%A, %d %B %Y %H:%M:%SZ", time.gmtime())
self.msg(origin.sender, msg) self.msg(origin.sender, msg)
elif TZ in TimeZones: elif TZ in TimeZones:
offset = TimeZones[TZ] * 3600 offset = TimeZones[TZ] * 3600
timenow = time.gmtime(time.time() + offset) timenow = time.gmtime(time.time() + offset)
msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(TZ), timenow) msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(TZ), timenow)
self.msg(origin.sender, msg) self.msg(origin.sender, msg)
elif tz and tz[0] in ('+', '-') and 4 <= len(tz) <= 6: elif tz and tz[0] in ('+', '-') and 4 <= len(tz) <= 6:
timenow = time.gmtime(time.time() + (int(tz[:3]) * 3600)) timenow = time.gmtime(time.time() + (int(tz[:3]) * 3600))
msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(tz), timenow) msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(tz), timenow)
self.msg(origin.sender, msg) self.msg(origin.sender, msg)
else: else:
try: t = float(tz) try: t = float(tz)
except ValueError: except ValueError:
import os, re, subprocess import os, re, subprocess
r_tz = re.compile(r'^[A-Za-z]+(?:/[A-Za-z_]+)*$') r_tz = re.compile(r'^[A-Za-z]+(?:/[A-Za-z_]+)*$')
if r_tz.match(tz) and os.path.isfile('/usr/share/zoneinfo/' + tz): if r_tz.match(tz) and os.path.isfile('/usr/share/zoneinfo/' + tz):
cmd, PIPE = 'TZ=%s date' % tz, subprocess.PIPE cmd, PIPE = 'TZ=%s date' % tz, subprocess.PIPE
proc = subprocess.Popen(cmd, shell=True, stdout=PIPE) proc = subprocess.Popen(cmd, shell=True, stdout=PIPE)
self.msg(origin.sender, proc.communicate()[0]) self.msg(origin.sender, proc.communicate()[0])
else: else:
error = "Sorry, I don't know about the '%s' timezone." % tz error = "Sorry, I don't know about the '%s' timezone." % tz
self.msg(origin.sender, origin.nick + ': ' + error) self.msg(origin.sender, origin.nick + ': ' + error)
else: else:
timenow = time.gmtime(time.time() + (t * 3600)) timenow = time.gmtime(time.time() + (t * 3600))
msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(tz), timenow) msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(tz), timenow)
self.msg(origin.sender, msg) self.msg(origin.sender, msg)
f_time.commands = ['t'] f_time.commands = ['t']
f_time.name = 't' f_time.name = 't'
f_time.example = '.t UTC' f_time.example = '.t UTC'
def beats(phenny, input): def beats(phenny, input):
"""Shows the internet time in Swatch beats.""" """Shows the internet time in Swatch beats."""
beats = ((time.time() + 3600) % 86400) / 86.4 beats = ((time.time() + 3600) % 86400) / 86.4
beats = int(math.floor(beats)) beats = int(math.floor(beats))
phenny.say('@%03i' % beats) phenny.say('@%03i' % beats)
beats.commands = ['beats'] beats.commands = ['beats']
beats.priority = 'low' beats.priority = 'low'
def divide(input, by): def divide(input, by):
return (input / by), (input % by) return (input / by), (input % by)
def yi(phenny, input): def yi(phenny, input):
"""Shows whether it is currently yi or not.""" """Shows whether it is currently yi or not."""
quadraels, remainder = divide(int(time.time()), 1753200) quadraels, remainder = divide(int(time.time()), 1753200)
raels = quadraels * 4 raels = quadraels * 4
extraraels, remainder = divide(remainder, 432000) extraraels, remainder = divide(remainder, 432000)
if extraraels == 4: if extraraels == 4:
return phenny.say('Yes! PARTAI!') return phenny.say('Yes! PARTAI!')
elif extraraels == 3: elif extraraels == 3:
return phenny.say('Soon...') return phenny.say('Soon...')
else: phenny.say('Not yet...') else: phenny.say('Not yet...')
yi.commands = ['yi'] yi.commands = ['yi']
yi.priority = 'low' yi.priority = 'low'
def tock(phenny, input): def tock(phenny, input):
"""Shows the time from the USNO's atomic clock.""" """Shows the time from the USNO's atomic clock."""
u = urllib.request.urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl') u = urllib.request.urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl')
info = u.info() info = u.info()
u.close() u.close()
phenny.say('"' + info['Date'] + '" - tycho.usno.navy.mil') phenny.say('"' + info['Date'] + '" - tycho.usno.navy.mil')
tock.commands = ['tock'] tock.commands = ['tock']
tock.priority = 'high' tock.priority = 'high'
def npl(phenny, input): def npl(phenny, input):
"""Shows the time from NPL's SNTP server.""" """Shows the time from NPL's SNTP server."""
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client.sendto('\x1b' + 47 * '\0', ('ntp1.npl.co.uk', 123)) client.sendto('\x1b' + 47 * '\0', ('ntp1.npl.co.uk', 123))
data, address = client.recvfrom(1024) data, address = client.recvfrom(1024)
if data: if data:
buf = struct.unpack('B' * 48, data) buf = struct.unpack('B' * 48, data)
d = dec('0.0') d = dec('0.0')
for i in range(8): for i in range(8):
d += dec(buf[32 + i]) * dec(str(math.pow(2, (3 - i) * 8))) d += dec(buf[32 + i]) * dec(str(math.pow(2, (3 - i) * 8)))
d -= dec(2208988800) d -= dec(2208988800)
a, b = str(d).split('.') a, b = str(d).split('.')
f = '%Y-%m-%d %H:%M:%S' f = '%Y-%m-%d %H:%M:%S'
result = datetime.datetime.fromtimestamp(d).strftime(f) + '.' + b[:6] result = datetime.datetime.fromtimestamp(d).strftime(f) + '.' + b[:6]
phenny.say(result + ' - ntp1.npl.co.uk') phenny.say(result + ' - ntp1.npl.co.uk')
else: phenny.say('No data received, sorry') else: phenny.say('No data received, sorry')
npl.commands = ['npl'] npl.commands = ['npl']
npl.priority = 'high' npl.priority = 'high'
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -19,82 +19,82 @@ r_tag = re.compile(r'<(?!!)[^>]+>')
r_whitespace = re.compile(r'[\t\r\n ]+') r_whitespace = re.compile(r'[\t\r\n ]+')
abbrs = [ abbrs = [
'cf', 'lit', 'etc', 'Ger', 'Du', 'Skt', 'Rus', 'Eng', 'Amer.Eng', 'Sp', 'cf', 'lit', 'etc', 'Ger', 'Du', 'Skt', 'Rus', 'Eng', 'Amer.Eng', 'Sp',
'Fr', 'N', 'E', 'S', 'W', 'L', 'Gen', 'J.C', 'dial', 'Gk', 'Fr', 'N', 'E', 'S', 'W', 'L', 'Gen', 'J.C', 'dial', 'Gk',
'19c', '18c', '17c', '16c', 'St', 'Capt', 'obs', 'Jan', 'Feb', 'Mar', '19c', '18c', '17c', '16c', 'St', 'Capt', 'obs', 'Jan', 'Feb', 'Mar',
'Apr', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'c', 'tr', 'e', 'g' 'Apr', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'c', 'tr', 'e', 'g'
] ]
t_sentence = r'^.*?(?<!%s)(?:\.(?= [A-Z0-9]|\Z)|\Z)' t_sentence = r'^.*?(?<!%s)(?:\.(?= [A-Z0-9]|\Z)|\Z)'
r_sentence = re.compile(t_sentence % ')(?<!'.join(abbrs)) r_sentence = re.compile(t_sentence % ')(?<!'.join(abbrs))
def unescape(s): def unescape(s):
s = s.replace('&gt;', '>') s = s.replace('&gt;', '>')
s = s.replace('&lt;', '<') s = s.replace('&lt;', '<')
s = s.replace('&amp;', '&') s = s.replace('&amp;', '&')
return s return s
def text(html): def text(html):
html = r_tag.sub('', html) html = r_tag.sub('', html)
html = r_whitespace.sub(' ', html) html = r_whitespace.sub(' ', html)
return unescape(html).strip() return unescape(html).strip()
def etymology(word): def etymology(word):
# @@ <nsh> sbp, would it be possible to have a flag for .ety to get 2nd/etc # @@ <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 # entries? - http://swhack.com/logs/2006-07-19#T15-05-29
if len(word) > 25: if len(word) > 25:
raise ValueError("Word too long: %s[...]" % word[:10]) raise ValueError("Word too long: %s[...]" % word[:10])
word = {'axe': 'ax/axe'}.get(word, word) word = {'axe': 'ax/axe'}.get(word, word)
bytes = web.get(etyuri % web.urllib.quote(word)) bytes = web.get(etyuri % web.urllib.quote(word))
definitions = r_definition.findall(bytes) definitions = r_definition.findall(bytes)
if not definitions: if not definitions:
return None return None
defn = text(definitions[0]) defn = text(definitions[0])
m = r_sentence.match(defn) m = r_sentence.match(defn)
if not m: if not m:
return None return None
sentence = m.group(0) sentence = m.group(0)
try: try:
sentence = str(sentence, 'iso-8859-1') sentence = str(sentence, 'iso-8859-1')
except: pass except: pass
maxlength = 275 maxlength = 275
if len(sentence) > maxlength: if len(sentence) > maxlength:
sentence = sentence[:maxlength] sentence = sentence[:maxlength]
words = sentence[:-5].split(' ') words = sentence[:-5].split(' ')
words.pop() words.pop()
sentence = ' '.join(words) + ' [...]' sentence = ' '.join(words) + ' [...]'
sentence = '"' + sentence.replace('"', "'") + '"' sentence = '"' + sentence.replace('"', "'") + '"'
return sentence + ' - ' + (etyuri % word) return sentence + ' - ' + (etyuri % word)
@deprecated @deprecated
def f_etymology(self, origin, match, args): def f_etymology(self, origin, match, args):
word = match.group(2) word = match.group(2)
try: result = etymology(word.encode('iso-8859-1')) try: result = etymology(word.encode('iso-8859-1'))
except IOError: except IOError:
msg = "Can't connect to etymonline.com (%s)" % (etyuri % word) msg = "Can't connect to etymonline.com (%s)" % (etyuri % word)
self.msg(origin.sender, msg) self.msg(origin.sender, msg)
return return
except AttributeError: except AttributeError:
result = None result = None
if result is not None: if result is not None:
self.msg(origin.sender, result) self.msg(origin.sender, result)
else: else:
uri = etysearch % word uri = etysearch % word
msg = 'Can\'t find the etymology for "%s". Try %s' % (word, uri) msg = 'Can\'t find the etymology for "%s". Try %s' % (word, uri)
self.msg(origin.sender, msg) self.msg(origin.sender, msg)
# @@ Cf. http://swhack.com/logs/2006-01-04#T01-50-22 # @@ Cf. http://swhack.com/logs/2006-01-04#T01-50-22
f_etymology.rule = (['ety'], r"(.+?)$") f_etymology.rule = (['ety'], r"(.+?)$")
f_etymology.thread = True f_etymology.thread = True
f_etymology.priority = 'high' f_etymology.priority = 'high'
if __name__=="__main__": if __name__=="__main__":
import sys import sys
print(etymology(sys.argv[1])) print(etymology(sys.argv[1]))

View File

@ -34,4 +34,3 @@ fcc.rule = (['fcc'], r'(.*)')
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -58,4 +58,3 @@ hs.rule = (['hs'], r'(.*)')
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -24,23 +24,23 @@ config.optionxform = str
config_filename = "" config_filename = ""
def setup(self): def setup(self):
fn = self.nick + '-' + self.config.host + '.lastfm.db' fn = self.nick + '-' + self.config.host + '.lastfm.db'
global config_filename global config_filename
config_filename = os.path.join(os.path.expanduser('~/.phenny'), fn) config_filename = os.path.join(os.path.expanduser('~/.phenny'), fn)
if not os.path.exists(config_filename): if not os.path.exists(config_filename):
try: f = open(config_filename, 'w') try: f = open(config_filename, 'w')
except OSError: pass except OSError: pass
else: else:
f.write('') f.write('')
f.close() f.close()
config_file = config.read(config_filename) config_file = config.read(config_filename)
if not config.has_section("Nick2User"): if not config.has_section("Nick2User"):
config.add_section("Nick2User") config.add_section("Nick2User")
if not config.has_section("User2Nick"): if not config.has_section("User2Nick"):
config.add_section("User2Nick") config.add_section("User2Nick")
if not config.has_section("Nick2Verb"): if not config.has_section("Nick2Verb"):
config.add_section("Nick2Verb") config.add_section("Nick2Verb")
def lastfm_set(phenny, input): def lastfm_set(phenny, input):
cmd = input.group(2) cmd = input.group(2)

View File

@ -9,27 +9,26 @@ import web
import json import json
def linx(phenny, input): def linx(phenny, input):
""".linx <url> - Upload a URL to linx.li.""" """.linx <url> - Upload a URL to linx.li."""
url = input.group(2) url = input.group(2)
if not url: if not url:
phenny.reply("No URL provided. CAN I HAS?") phenny.reply("No URL provided. CAN I HAS?")
return return
try: try:
req = web.post("http://linx.li/vtluug", {'url': url}) req = web.post("http://linx.li/vtluug", {'url': url})
except (HTTPError, IOError): except (HTTPError, IOError):
phenny.reply("THE INTERNET IS FUCKING BROKEN. Please try again later.") phenny.reply("THE INTERNET IS FUCKING BROKEN. Please try again later.")
return return
data = json.loads(req) data = json.loads(req)
if len(data) <= 0 or not data['success']: if len(data) <= 0 or not data['success']:
phenny.reply('Sorry, upload failed.') phenny.reply('Sorry, upload failed.')
return return
phenny.reply(data['url']) phenny.reply(data['url'])
linx.rule = (['linx'], r'(.*)') linx.rule = (['linx'], r'(.*)')
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -149,4 +149,3 @@ mlit.commands = ['mlit']
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -10,9 +10,7 @@ def nsfw(phenny, input):
phenny.say(".nsfw <link> - for when a link isn't safe for work") phenny.say(".nsfw <link> - for when a link isn't safe for work")
return return
phenny.say("!!NSFW!! -> %s <- !!NSFW!!" % (link)) phenny.say("!!NSFW!! -> %s <- !!NSFW!!" % (link))
nsfw.rule = (['nsfw'], r'(.*)') nsfw.rule = (['nsfw'], r'(.*)')
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -16,102 +16,102 @@ r_item = re.compile(r'(?i)<li>(.*?)</li>')
r_tag = re.compile(r'<[^>]+>') r_tag = re.compile(r'<[^>]+>')
def mappings(uri): def mappings(uri):
result = {} result = {}
bytes = web.get(uri) bytes = web.get(uri)
for item in r_item.findall(bytes): for item in r_item.findall(bytes):
item = r_tag.sub('', item).strip(' \t\r\n') item = r_tag.sub('', item).strip(' \t\r\n')
if not ' ' in item: continue if not ' ' in item: continue
command, template = item.split(' ', 1) command, template = item.split(' ', 1)
if not command.isalnum(): continue if not command.isalnum(): continue
if not template.startswith('http://'): continue if not template.startswith('http://'): continue
result[command] = template.replace('&amp;', '&') result[command] = template.replace('&amp;', '&')
return result return result
def service(phenny, input, command, args): def service(phenny, input, command, args):
t = o.services[command] t = o.services[command]
template = t.replace('${args}', urllib.parse.quote(args, '')) template = t.replace('${args}', urllib.parse.quote(args, ''))
template = template.replace('${nick}', urllib.parse.quote(input.nick, '')) template = template.replace('${nick}', urllib.parse.quote(input.nick, ''))
uri = template.replace('${sender}', urllib.parse.quote(input.sender, '')) uri = template.replace('${sender}', urllib.parse.quote(input.sender, ''))
info = web.head(uri) info = web.head(uri)
if isinstance(info, list): if isinstance(info, list):
info = info[0] info = info[0]
if not 'text/plain' in info.get('content-type', '').lower(): if not 'text/plain' in info.get('content-type', '').lower():
return phenny.reply("Sorry, the service didn't respond in plain text.") return phenny.reply("Sorry, the service didn't respond in plain text.")
bytes = web.get(uri) bytes = web.get(uri)
lines = bytes.splitlines() lines = bytes.splitlines()
if not lines: if not lines:
return phenny.reply("Sorry, the service didn't respond any output.") return phenny.reply("Sorry, the service didn't respond any output.")
phenny.say(lines[0][:350]) phenny.say(lines[0][:350])
def refresh(phenny): def refresh(phenny):
if hasattr(phenny.config, 'services'): if hasattr(phenny.config, 'services'):
services = phenny.config.services services = phenny.config.services
else: services = definitions else: services = definitions
old = o.services old = o.services
o.serviceURI = services o.serviceURI = services
o.services = mappings(o.serviceURI) o.services = mappings(o.serviceURI)
return len(o.services), set(o.services) - set(old) return len(o.services), set(o.services) - set(old)
def o(phenny, input): def o(phenny, input):
"""Call a webservice.""" """Call a webservice."""
text = input.group(2) text = input.group(2)
if (not o.services) or (text == 'refresh'): if (not o.services) or (text == 'refresh'):
length, added = refresh(phenny) length, added = refresh(phenny)
if text == 'refresh': if text == 'refresh':
msg = 'Okay, found %s services.' % length msg = 'Okay, found %s services.' % length
if added: if added:
msg += ' Added: ' + ', '.join(sorted(added)[:5]) msg += ' Added: ' + ', '.join(sorted(added)[:5])
if len(added) > 5: msg += ', &c.' if len(added) > 5: msg += ', &c.'
return phenny.reply(msg) return phenny.reply(msg)
if not text: if not text:
return phenny.reply('Try %s for details.' % o.serviceURI) return phenny.reply('Try %s for details.' % o.serviceURI)
if ' ' in text: if ' ' in text:
command, args = text.split(' ', 1) command, args = text.split(' ', 1)
else: command, args = text, '' else: command, args = text, ''
command = command.lower() command = command.lower()
if command == 'service': if command == 'service':
msg = o.services.get(args, 'No such service!') msg = o.services.get(args, 'No such service!')
return phenny.reply(msg) return phenny.reply(msg)
if command not in o.services: if command not in o.services:
return phenny.reply('Service not found in %s' % o.serviceURI) return phenny.reply('Service not found in %s' % o.serviceURI)
if hasattr(phenny.config, 'external'): if hasattr(phenny.config, 'external'):
default = phenny.config.external.get('*') default = phenny.config.external.get('*')
manifest = phenny.config.external.get(input.sender, default) manifest = phenny.config.external.get(input.sender, default)
if manifest: if manifest:
commands = set(manifest) commands = set(manifest)
if (command not in commands) and (manifest[0] != '!'): if (command not in commands) and (manifest[0] != '!'):
return phenny.reply('Sorry, %s is not whitelisted' % command) return phenny.reply('Sorry, %s is not whitelisted' % command)
elif (command in commands) and (manifest[0] == '!'): elif (command in commands) and (manifest[0] == '!'):
return phenny.reply('Sorry, %s is blacklisted' % command) return phenny.reply('Sorry, %s is blacklisted' % command)
service(phenny, input, command, args) service(phenny, input, command, args)
o.commands = ['o'] o.commands = ['o']
o.example = '.o servicename arg1 arg2 arg3' o.example = '.o servicename arg1 arg2 arg3'
o.services = {} o.services = {}
o.serviceURI = None o.serviceURI = None
def snippet(phenny, input): def snippet(phenny, input):
if not o.services: if not o.services:
refresh(phenny) refresh(phenny)
search = urllib.parse.quote(input.group(2)) search = urllib.parse.quote(input.group(2))
py = "BeautifulSoup.BeautifulSoup(re.sub('<.*?>|(?<= ) +', '', " + \ py = "BeautifulSoup.BeautifulSoup(re.sub('<.*?>|(?<= ) +', '', " + \
"''.join(chr(ord(c)) for c in " + \ "''.join(chr(ord(c)) for c in " + \
"eval(urllib.urlopen('http://ajax.googleapis.com/ajax/serv" + \ "eval(urllib.urlopen('http://ajax.googleapis.com/ajax/serv" + \
"ices/search/web?v=1.0&q=" + search + "').read()" + \ "ices/search/web?v=1.0&q=" + search + "').read()" + \
".replace('null', 'None'))['responseData']['resul" + \ ".replace('null', 'None'))['responseData']['resul" + \
"ts'][0]['content'].decode('unicode-escape')).replace(" + \ "ts'][0]['content'].decode('unicode-escape')).replace(" + \
"'&quot;', '\x22')), convertEntities=True)" "'&quot;', '\x22')), convertEntities=True)"
service(phenny, input, 'py', py) service(phenny, input, 'py', py)
snippet.commands = ['snippet'] snippet.commands = ['snippet']
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -8,16 +8,16 @@ About: http://inamidst.com/phenny/
import random import random
def hello(phenny, input): def hello(phenny, input):
greeting = random.choice(('Hi', 'Hey', 'Hello')) greeting = random.choice(('Hi', 'Hey', 'Hello'))
punctuation = random.choice(('', '!')) punctuation = random.choice(('', '!'))
phenny.say(greeting + ' ' + input.nick + punctuation) phenny.say(greeting + ' ' + input.nick + punctuation)
hello.rule = r'(?i)(hi|hello|hey) $nickname[ \t]*$' hello.rule = r'(?i)(hi|hello|hey) $nickname[ \t]*$'
def interjection(phenny, input): def interjection(phenny, input):
phenny.say(input.nick + '!') phenny.say(input.nick + '!')
interjection.rule = r'$nickname!' interjection.rule = r'$nickname!'
interjection.priority = 'high' interjection.priority = 'high'
interjection.thread = False interjection.thread = False
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -11,45 +11,45 @@ import sys, os.path, time, imp
import irc import irc
def f_reload(phenny, input): def f_reload(phenny, input):
"""Reloads a module, for use by admins only.""" """Reloads a module, for use by admins only."""
if not input.admin: return if not input.admin: return
name = input.group(2) name = input.group(2)
if name == phenny.config.owner: if name == phenny.config.owner:
return phenny.reply('What?') return phenny.reply('What?')
if (not name) or (name == '*'): if (not name) or (name == '*'):
phenny.variables = None phenny.variables = None
phenny.commands = None phenny.commands = None
phenny.setup() phenny.setup()
return phenny.reply('done') return phenny.reply('done')
if name not in sys.modules: if name not in sys.modules:
return phenny.reply('%s: no such module!' % name) return phenny.reply('%s: no such module!' % name)
# Thanks to moot for prodding me on this # Thanks to moot for prodding me on this
path = sys.modules[name].__file__ path = sys.modules[name].__file__
if path.endswith('.pyc') or path.endswith('.pyo'): if path.endswith('.pyc') or path.endswith('.pyo'):
path = path[:-1] path = path[:-1]
if not os.path.isfile(path): if not os.path.isfile(path):
return phenny.reply('Found %s, but not the source file' % name) return phenny.reply('Found %s, but not the source file' % name)
module = imp.load_source(name, path) module = imp.load_source(name, path)
sys.modules[name] = module sys.modules[name] = module
if hasattr(module, 'setup'): if hasattr(module, 'setup'):
module.setup(phenny) module.setup(phenny)
mtime = os.path.getmtime(module.__file__) mtime = os.path.getmtime(module.__file__)
modified = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(mtime)) modified = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(mtime))
phenny.register(vars(module)) phenny.register(vars(module))
phenny.bind_commands() phenny.bind_commands()
phenny.reply('%r (version: %s)' % (module, modified)) phenny.reply('%r (version: %s)' % (module, modified))
f_reload.name = 'reload' f_reload.name = 'reload'
f_reload.rule = ('$nick', ['reload'], r'(\S+)?') f_reload.rule = ('$nick', ['reload'], r'(\S+)?')
f_reload.priority = 'low' f_reload.priority = 'low'
f_reload.thread = False f_reload.thread = False
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -10,91 +10,91 @@ http://inamidst.com/phenny/
import os, re, time, threading import os, re, time, threading
def filename(self): def filename(self):
name = self.nick + '-' + self.config.host + '.reminders.db' name = self.nick + '-' + self.config.host + '.reminders.db'
return os.path.join(os.path.expanduser('~/.phenny'), name) return os.path.join(os.path.expanduser('~/.phenny'), name)
def load_database(name): def load_database(name):
data = {} data = {}
if os.path.isfile(name): if os.path.isfile(name):
f = open(name, 'r') f = open(name, 'r')
for line in f: for line in f:
unixtime, channel, nick, message = line.split('\t') unixtime, channel, nick, message = line.split('\t')
message = message.rstrip('\n') message = message.rstrip('\n')
t = int(unixtime) t = int(unixtime)
reminder = (channel, nick, message) reminder = (channel, nick, message)
try: data[t].append(reminder) try: data[t].append(reminder)
except KeyError: data[t] = [reminder] except KeyError: data[t] = [reminder]
f.close() f.close()
return data return data
def dump_database(name, data): def dump_database(name, data):
f = open(name, 'w') f = open(name, 'w')
for unixtime, reminders in data.items(): for unixtime, reminders in data.items():
for channel, nick, message in reminders: for channel, nick, message in reminders:
f.write('%s\t%s\t%s\t%s\n' % (unixtime, channel, nick, message)) f.write('%s\t%s\t%s\t%s\n' % (unixtime, channel, nick, message))
f.close() f.close()
def setup(phenny): def setup(phenny):
phenny.rfn = filename(phenny) phenny.rfn = filename(phenny)
phenny.rdb = load_database(phenny.rfn) phenny.rdb = load_database(phenny.rfn)
def monitor(phenny): def monitor(phenny):
time.sleep(5) time.sleep(5)
while True: while True:
now = int(time.time()) now = int(time.time())
unixtimes = [int(key) for key in phenny.rdb] unixtimes = [int(key) for key in phenny.rdb]
oldtimes = [t for t in unixtimes if t <= now] oldtimes = [t for t in unixtimes if t <= now]
if oldtimes: if oldtimes:
for oldtime in oldtimes: for oldtime in oldtimes:
for (channel, nick, message) in phenny.rdb[oldtime]: for (channel, nick, message) in phenny.rdb[oldtime]:
if message: if message:
phenny.msg(channel, nick + ': ' + message) phenny.msg(channel, nick + ': ' + message)
else: phenny.msg(channel, nick + '!') else: phenny.msg(channel, nick + '!')
del phenny.rdb[oldtime] del phenny.rdb[oldtime]
dump_database(phenny.rfn, phenny.rdb) dump_database(phenny.rfn, phenny.rdb)
time.sleep(2.5) time.sleep(2.5)
targs = (phenny,) targs = (phenny,)
t = threading.Thread(target=monitor, args=targs) t = threading.Thread(target=monitor, args=targs)
t.start() t.start()
scaling = { scaling = {
'years': 365.25 * 24 * 3600, 'years': 365.25 * 24 * 3600,
'year': 365.25 * 24 * 3600, 'year': 365.25 * 24 * 3600,
'yrs': 365.25 * 24 * 3600, 'yrs': 365.25 * 24 * 3600,
'y': 365.25 * 24 * 3600, 'y': 365.25 * 24 * 3600,
'months': 29.53059 * 24 * 3600, 'months': 29.53059 * 24 * 3600,
'month': 29.53059 * 24 * 3600, 'month': 29.53059 * 24 * 3600,
'mo': 29.53059 * 24 * 3600, 'mo': 29.53059 * 24 * 3600,
'weeks': 7 * 24 * 3600, 'weeks': 7 * 24 * 3600,
'week': 7 * 24 * 3600, 'week': 7 * 24 * 3600,
'wks': 7 * 24 * 3600, 'wks': 7 * 24 * 3600,
'wk': 7 * 24 * 3600, 'wk': 7 * 24 * 3600,
'w': 7 * 24 * 3600, 'w': 7 * 24 * 3600,
'days': 24 * 3600, 'days': 24 * 3600,
'day': 24 * 3600, 'day': 24 * 3600,
'd': 24 * 3600, 'd': 24 * 3600,
'hours': 3600, 'hours': 3600,
'hour': 3600, 'hour': 3600,
'hrs': 3600, 'hrs': 3600,
'hr': 3600, 'hr': 3600,
'h': 3600, 'h': 3600,
'minutes': 60, 'minutes': 60,
'minute': 60, 'minute': 60,
'mins': 60, 'mins': 60,
'min': 60, 'min': 60,
'm': 60, 'm': 60,
'seconds': 1, 'seconds': 1,
'second': 1, 'second': 1,
'secs': 1, 'secs': 1,
'sec': 1, 'sec': 1,
's': 1 's': 1
} }
periods = '|'.join(list(scaling.keys())) periods = '|'.join(list(scaling.keys()))
@ -102,35 +102,35 @@ p_command = r'\.in ([0-9]+(?:\.[0-9]+)?)\s?((?:%s)\b)?:?\s?(.*)' % periods
r_command = re.compile(p_command) r_command = re.compile(p_command)
def remind(phenny, input): def remind(phenny, input):
m = r_command.match(input.bytes) m = r_command.match(input.bytes)
if not m: if not m:
return phenny.reply("Sorry, didn't understand the input.") return phenny.reply("Sorry, didn't understand the input.")
length, scale, message = m.groups() length, scale, message = m.groups()
length = float(length) length = float(length)
factor = scaling.get(scale, 60) factor = scaling.get(scale, 60)
duration = length * factor duration = length * factor
if duration % 1: if duration % 1:
duration = int(duration) + 1 duration = int(duration) + 1
else: duration = int(duration) else: duration = int(duration)
t = int(time.time()) + duration t = int(time.time()) + duration
reminder = (input.sender, input.nick, message) reminder = (input.sender, input.nick, message)
try: phenny.rdb[t].append(reminder) try: phenny.rdb[t].append(reminder)
except KeyError: phenny.rdb[t] = [reminder] except KeyError: phenny.rdb[t] = [reminder]
dump_database(phenny.rfn, phenny.rdb) dump_database(phenny.rfn, phenny.rdb)
if duration >= 60: if duration >= 60:
w = '' w = ''
if duration >= 3600 * 12: if duration >= 3600 * 12:
w += time.strftime(' on %d %b %Y', time.gmtime(t)) w += time.strftime(' on %d %b %Y', time.gmtime(t))
w += time.strftime(' at %H:%MZ', time.gmtime(t)) w += time.strftime(' at %H:%MZ', time.gmtime(t))
phenny.reply('Okay, will remind%s' % w) phenny.reply('Okay, will remind%s' % w)
else: phenny.reply('Okay, will remind in %s secs' % duration) else: phenny.reply('Okay, will remind in %s secs' % duration)
remind.commands = ['in'] remind.commands = ['in']
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -11,185 +11,185 @@ import re
import web import web
class Grab(web.urllib.request.URLopener): class Grab(web.urllib.request.URLopener):
def __init__(self, *args): def __init__(self, *args):
self.version = 'Mozilla/5.0 (Phenny)' self.version = 'Mozilla/5.0 (Phenny)'
web.urllib.request.URLopener.__init__(self, *args) web.urllib.request.URLopener.__init__(self, *args)
self.addheader('Referer', 'https://github.com/sbp/phenny') self.addheader('Referer', 'https://github.com/sbp/phenny')
def http_error_default(self, url, fp, errcode, errmsg, headers): def http_error_default(self, url, fp, errcode, errmsg, headers):
return web.urllib.addinfourl(fp, [headers, errcode], "http:" + url) return web.urllib.addinfourl(fp, [headers, errcode], "http:" + url)
def google_ajax(query): def google_ajax(query):
"""Search using AjaxSearch, and return its JSON.""" """Search using AjaxSearch, and return its JSON."""
uri = 'http://ajax.googleapis.com/ajax/services/search/web' uri = 'http://ajax.googleapis.com/ajax/services/search/web'
args = '?v=1.0&safe=off&q=' + web.quote(query) args = '?v=1.0&safe=off&q=' + web.quote(query)
handler = web.urllib.request._urlopener handler = web.urllib.request._urlopener
web.urllib.request._urlopener = Grab() web.urllib.request._urlopener = Grab()
bytes = web.get(uri + args) bytes = web.get(uri + args)
web.urllib.request._urlopener = handler web.urllib.request._urlopener = handler
return web.json(bytes) return web.json(bytes)
def google_search(query): def google_search(query):
results = google_ajax(query) results = google_ajax(query)
try: return results['responseData']['results'][0]['unescapedUrl'] try: return results['responseData']['results'][0]['unescapedUrl']
except IndexError: return None except IndexError: return None
except TypeError: except TypeError:
print(results) print(results)
return False return False
def google_count(query): def google_count(query):
results = google_ajax(query) results = google_ajax(query)
if 'responseData' not in results: return '0' if 'responseData' not in results: return '0'
if 'cursor' not in results['responseData']: return '0' if 'cursor' not in results['responseData']: return '0'
if 'estimatedResultCount' not in results['responseData']['cursor']: if 'estimatedResultCount' not in results['responseData']['cursor']:
return '0' return '0'
return results['responseData']['cursor']['estimatedResultCount'] return results['responseData']['cursor']['estimatedResultCount']
def formatnumber(n): def formatnumber(n):
"""Format a number with beautiful commas.""" """Format a number with beautiful commas."""
parts = list(str(n)) parts = list(str(n))
for i in range((len(parts) - 3), 0, -3): for i in range((len(parts) - 3), 0, -3):
parts.insert(i, ',') parts.insert(i, ',')
return ''.join(parts) return ''.join(parts)
def g(phenny, input): def g(phenny, input):
"""Queries Google for the specified input.""" """Queries Google for the specified input."""
query = input.group(2) query = input.group(2)
if not query: if not query:
return phenny.reply('.g what?') return phenny.reply('.g what?')
uri = google_search(query) uri = google_search(query)
if uri: if uri:
phenny.reply(uri) phenny.reply(uri)
if not hasattr(phenny.bot, 'last_seen_uri'): if not hasattr(phenny.bot, 'last_seen_uri'):
phenny.bot.last_seen_uri = {} phenny.bot.last_seen_uri = {}
phenny.bot.last_seen_uri[input.sender] = uri phenny.bot.last_seen_uri[input.sender] = uri
elif uri is False: phenny.reply("Problem getting data from Google.") elif uri is False: phenny.reply("Problem getting data from Google.")
else: phenny.reply("No results found for '%s'." % query) else: phenny.reply("No results found for '%s'." % query)
g.commands = ['g'] g.commands = ['g']
g.priority = 'high' g.priority = 'high'
g.example = '.g swhack' g.example = '.g swhack'
def gc(phenny, input): def gc(phenny, input):
"""Returns the number of Google results for the specified input.""" """Returns the number of Google results for the specified input."""
query = input.group(2) query = input.group(2)
if not query: if not query:
return phenny.reply('.gc what?') return phenny.reply('.gc what?')
num = formatnumber(google_count(query)) num = formatnumber(google_count(query))
phenny.say(query + ': ' + num) phenny.say(query + ': ' + num)
gc.commands = ['gc'] gc.commands = ['gc']
gc.priority = 'high' gc.priority = 'high'
gc.example = '.gc extrapolate' gc.example = '.gc extrapolate'
r_query = re.compile( r_query = re.compile(
r'\+?"[^"\\]*(?:\\.[^"\\]*)*"|\[[^]\\]*(?:\\.[^]\\]*)*\]|\S+' r'\+?"[^"\\]*(?:\\.[^"\\]*)*"|\[[^]\\]*(?:\\.[^]\\]*)*\]|\S+'
) )
def gcs(phenny, input): def gcs(phenny, input):
if not input.group(2): if not input.group(2):
return phenny.reply("Nothing to compare.") return phenny.reply("Nothing to compare.")
queries = r_query.findall(input.group(2)) queries = r_query.findall(input.group(2))
if len(queries) > 6: if len(queries) > 6:
return phenny.reply('Sorry, can only compare up to six things.') return phenny.reply('Sorry, can only compare up to six things.')
results = [] results = []
for i, query in enumerate(queries): for i, query in enumerate(queries):
query = query.strip('[]') query = query.strip('[]')
n = int((formatnumber(google_count(query)) or '0').replace(',', '')) n = int((formatnumber(google_count(query)) or '0').replace(',', ''))
results.append((n, query)) results.append((n, query))
if i >= 2: __import__('time').sleep(0.25) if i >= 2: __import__('time').sleep(0.25)
if i >= 4: __import__('time').sleep(0.25) if i >= 4: __import__('time').sleep(0.25)
results = [(term, n) for (n, term) in reversed(sorted(results))] results = [(term, n) for (n, term) in reversed(sorted(results))]
reply = ', '.join('%s (%s)' % (t, formatnumber(n)) for (t, n) in results) reply = ', '.join('%s (%s)' % (t, formatnumber(n)) for (t, n) in results)
phenny.say(reply) phenny.say(reply)
gcs.commands = ['gcs', 'comp'] gcs.commands = ['gcs', 'comp']
r_bing = re.compile(r'<h3><a href="([^"]+)"') r_bing = re.compile(r'<h3><a href="([^"]+)"')
def bing_search(query, lang='en-GB'): def bing_search(query, lang='en-GB'):
query = web.quote(query) query = web.quote(query)
base = 'http://www.bing.com/search?mkt=%s&q=' % lang base = 'http://www.bing.com/search?mkt=%s&q=' % lang
bytes = web.get(base + query) bytes = web.get(base + query)
m = r_bing.search(bytes) m = r_bing.search(bytes)
if m: return m.group(1) if m: return m.group(1)
def bing(phenny, input): def bing(phenny, input):
"""Queries Bing for the specified input.""" """Queries Bing for the specified input."""
query = input.group(2) query = input.group(2)
if query.startswith(':'): if query.startswith(':'):
lang, query = query.split(' ', 1) lang, query = query.split(' ', 1)
lang = lang[1:] lang = lang[1:]
else: lang = 'en-GB' else: lang = 'en-GB'
if not query: if not query:
return phenny.reply('.bing what?') return phenny.reply('.bing what?')
uri = bing_search(query, lang) uri = bing_search(query, lang)
if uri: if uri:
phenny.reply(uri) phenny.reply(uri)
if not hasattr(phenny.bot, 'last_seen_uri'): if not hasattr(phenny.bot, 'last_seen_uri'):
phenny.bot.last_seen_uri = {} phenny.bot.last_seen_uri = {}
phenny.bot.last_seen_uri[input.sender] = uri phenny.bot.last_seen_uri[input.sender] = uri
else: phenny.reply("No results found for '%s'." % query) else: phenny.reply("No results found for '%s'." % query)
bing.commands = ['bing'] bing.commands = ['bing']
bing.example = '.bing swhack' bing.example = '.bing swhack'
r_duck = re.compile(r'nofollow" class="[^"]+" href="(.*?)">') r_duck = re.compile(r'nofollow" class="[^"]+" href="(.*?)">')
def duck_search(query): def duck_search(query):
query = query.replace('!', '') query = query.replace('!', '')
query = web.quote(query) query = web.quote(query)
uri = 'http://duckduckgo.com/html/?q=%s&kl=uk-en' % query uri = 'http://duckduckgo.com/html/?q=%s&kl=uk-en' % query
bytes = web.get(uri) bytes = web.get(uri)
m = r_duck.search(bytes) m = r_duck.search(bytes)
if m: return web.decode(m.group(1)) if m: return web.decode(m.group(1))
def duck(phenny, input): def duck(phenny, input):
query = input.group(2) query = input.group(2)
if not query: return phenny.reply('.ddg what?') if not query: return phenny.reply('.ddg what?')
uri = duck_search(query) uri = duck_search(query)
if uri: if uri:
phenny.reply(uri) phenny.reply(uri)
if not hasattr(phenny.bot, 'last_seen_uri'): if not hasattr(phenny.bot, 'last_seen_uri'):
phenny.bot.last_seen_uri = {} phenny.bot.last_seen_uri = {}
phenny.bot.last_seen_uri[input.sender] = uri phenny.bot.last_seen_uri[input.sender] = uri
else: phenny.reply("No results found for '%s'." % query) else: phenny.reply("No results found for '%s'." % query)
duck.commands = ['duck', 'ddg'] duck.commands = ['duck', 'ddg']
def search(phenny, input): def search(phenny, input):
if not input.group(2): if not input.group(2):
return phenny.reply('.search for what?') return phenny.reply('.search for what?')
query = input.group(2) query = input.group(2)
gu = google_search(query) or '-' gu = google_search(query) or '-'
bu = bing_search(query) or '-' bu = bing_search(query) or '-'
du = duck_search(query) or '-' du = duck_search(query) or '-'
if (gu == bu) and (bu == du): if (gu == bu) and (bu == du):
result = '%s (g, b, d)' % gu result = '%s (g, b, d)' % gu
elif (gu == bu): elif (gu == bu):
result = '%s (g, b), %s (d)' % (gu, du) result = '%s (g, b), %s (d)' % (gu, du)
elif (bu == du): elif (bu == du):
result = '%s (b, d), %s (g)' % (bu, gu) result = '%s (b, d), %s (g)' % (bu, gu)
elif (gu == du): elif (gu == du):
result = '%s (g, d), %s (b)' % (gu, bu) result = '%s (g, d), %s (b)' % (gu, bu)
else: else:
if len(gu) > 250: gu = '(extremely long link)' if len(gu) > 250: gu = '(extremely long link)'
if len(bu) > 150: bu = '(extremely long link)' if len(bu) > 150: bu = '(extremely long link)'
if len(du) > 150: du = '(extremely long link)' if len(du) > 150: du = '(extremely long link)'
result = '%s (g), %s (b), %s (d)' % (gu, bu, du) result = '%s (g), %s (b), %s (d)' % (gu, bu, du)
phenny.reply(result) phenny.reply(result)
search.commands = ['search'] search.commands = ['search']
def suggest(phenny, input): def suggest(phenny, input):
if not input.group(2): if not input.group(2):
return phenny.reply("No query term.") return phenny.reply("No query term.")
query = input.group(2) query = input.group(2)
uri = 'http://websitedev.de/temp-bin/suggest.pl?q=' uri = 'http://websitedev.de/temp-bin/suggest.pl?q='
answer = web.get(uri + web.quote(query).replace('+', '%2B')) answer = web.get(uri + web.quote(query).replace('+', '%2B'))
if answer: if answer:
phenny.say(answer) phenny.say(answer)
else: phenny.reply('Sorry, no result.') else: phenny.reply('Sorry, no result.')
suggest.commands = ['suggest'] suggest.commands = ['suggest']
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -12,38 +12,38 @@ from tools import deprecated
@deprecated @deprecated
def f_seen(self, origin, match, args): def f_seen(self, origin, match, args):
""".seen <nick> - Reports when <nick> was last seen.""" """.seen <nick> - Reports when <nick> was last seen."""
if origin.sender == '#talis': return if origin.sender == '#talis': return
nick = match.group(2).lower() nick = match.group(2).lower()
if not hasattr(self, 'seen'): if not hasattr(self, 'seen'):
return self.msg(origin.sender, '?') return self.msg(origin.sender, '?')
if nick in self.seen: if nick in self.seen:
channel, t = self.seen[nick] channel, t = self.seen[nick]
t = time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime(t)) 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) msg = "I last saw %s at %s on %s" % (nick, t, channel)
self.msg(origin.sender, str(origin.nick) + ': ' + msg) self.msg(origin.sender, str(origin.nick) + ': ' + msg)
else: self.msg(origin.sender, "Sorry, I haven't seen %s around." % nick) else: self.msg(origin.sender, "Sorry, I haven't seen %s around." % nick)
f_seen.rule = (['seen'], r'(\S+)') f_seen.rule = (['seen'], r'(\S+)')
@deprecated @deprecated
def f_note(self, origin, match, args): def f_note(self, origin, match, args):
def note(self, origin, match, args): def note(self, origin, match, args):
if not hasattr(self.bot, 'seen'): if not hasattr(self.bot, 'seen'):
self.bot.seen = {} self.bot.seen = {}
if origin.sender.startswith('#'): if origin.sender.startswith('#'):
# if origin.sender == '#inamidst': return # if origin.sender == '#inamidst': return
self.seen[origin.nick.lower()] = (origin.sender, time.time()) self.seen[origin.nick.lower()] = (origin.sender, time.time())
# if not hasattr(self, 'chanspeak'): # if not hasattr(self, 'chanspeak'):
# self.chanspeak = {} # self.chanspeak = {}
# if (len(args) > 2) and args[2].startswith('#'): # if (len(args) > 2) and args[2].startswith('#'):
# self.chanspeak[args[2]] = args[0] # self.chanspeak[args[2]] = args[0]
try: note(self, origin, match, args) try: note(self, origin, match, args)
except Exception as e: print(e) except Exception as e: print(e)
f_note.rule = r'(.*)' f_note.rule = r'(.*)'
f_note.priority = 'low' f_note.priority = 'low'
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -37,4 +37,4 @@ slogan.commands = ['slogan']
slogan.example = '.slogan Granola' slogan.example = '.slogan Granola'
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -8,19 +8,19 @@ http://inamidst.com/phenny/
""" """
def startup(phenny, input): def startup(phenny, input):
if hasattr(phenny.config, 'serverpass'): if hasattr(phenny.config, 'serverpass'):
phenny.write(('PASS', phenny.config.serverpass)) phenny.write(('PASS', phenny.config.serverpass))
if hasattr(phenny.config, 'password'): if hasattr(phenny.config, 'password'):
phenny.msg('NickServ', 'IDENTIFY %s' % phenny.config.password) phenny.msg('NickServ', 'IDENTIFY %s' % phenny.config.password)
__import__('time').sleep(5) __import__('time').sleep(5)
# Cf. http://swhack.com/logs/2005-12-05#T19-32-36 # Cf. http://swhack.com/logs/2005-12-05#T19-32-36
for channel in phenny.channels: for channel in phenny.channels:
phenny.write(('JOIN', channel)) phenny.write(('JOIN', channel))
startup.rule = r'(.*)' startup.rule = r'(.*)'
startup.event = '251' startup.event = '251'
startup.priority = 'low' startup.priority = 'low'
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -24,139 +24,139 @@ lispchannels = frozenset([ '#lisp', '#scheme', '#opendarwin', '#macdev',
'#programmering', '#maxima', '#robin', '##concurrency', '#paredit' ]) '#programmering', '#maxima', '#robin', '##concurrency', '#paredit' ])
def loadReminders(fn): def loadReminders(fn):
result = {} result = {}
f = open(fn) f = open(fn)
for line in f: for line in f:
line = line.strip() line = line.strip()
if line: if line:
try: tellee, teller, verb, timenow, msg = line.split('\t', 4) try: tellee, teller, verb, timenow, msg = line.split('\t', 4)
except ValueError: continue # @@ hmm except ValueError: continue # @@ hmm
result.setdefault(tellee, []).append((teller, verb, timenow, msg)) result.setdefault(tellee, []).append((teller, verb, timenow, msg))
f.close() f.close()
return result return result
def dumpReminders(fn, data): def dumpReminders(fn, data):
f = open(fn, 'w') f = open(fn, 'w')
for tellee in data.keys(): for tellee in data.keys():
for remindon in data[tellee]: for remindon in data[tellee]:
line = '\t'.join((tellee,) + remindon) line = '\t'.join((tellee,) + remindon)
try: f.write(line + '\n') try: f.write(line + '\n')
except IOError: break except IOError: break
try: f.close() try: f.close()
except IOError: pass except IOError: pass
return True return True
def setup(self): def setup(self):
fn = self.nick + '-' + self.config.host + '.tell.db' fn = self.nick + '-' + self.config.host + '.tell.db'
self.tell_filename = os.path.join(os.path.expanduser('~/.phenny'), fn) self.tell_filename = os.path.join(os.path.expanduser('~/.phenny'), fn)
if not os.path.exists(self.tell_filename): if not os.path.exists(self.tell_filename):
try: f = open(self.tell_filename, 'w') try: f = open(self.tell_filename, 'w')
except OSError: pass except OSError: pass
else: else:
f.write('') f.write('')
f.close() f.close()
self.reminders = loadReminders(self.tell_filename) # @@ tell self.reminders = loadReminders(self.tell_filename) # @@ tell
def f_remind(phenny, input): def f_remind(phenny, input):
teller = input.nick teller = input.nick
# @@ Multiple comma-separated tellees? Cf. Terje, #swhack, 2006-04-15 # @@ Multiple comma-separated tellees? Cf. Terje, #swhack, 2006-04-15
verb, tellee, msg = input.groups() verb, tellee, msg = input.groups()
verb = verb verb = verb
tellee = tellee tellee = tellee
msg = msg msg = msg
tellee_original = tellee.rstrip('.,:;') tellee_original = tellee.rstrip('.,:;')
tellee = tellee_original.lower() tellee = tellee_original.lower()
if not os.path.exists(phenny.tell_filename): if not os.path.exists(phenny.tell_filename):
return return
if len(tellee) > 20: if len(tellee) > 20:
return phenny.reply('That nickname is too long.') return phenny.reply('That nickname is too long.')
timenow = time.strftime('%d %b %H:%MZ', time.gmtime()) timenow = time.strftime('%d %b %H:%MZ', time.gmtime())
if not tellee in (teller.lower(), phenny.nick, 'me'): # @@ if not tellee in (teller.lower(), phenny.nick, 'me'): # @@
# @@ <deltab> and year, if necessary # @@ <deltab> and year, if necessary
warn = False warn = False
if tellee not in phenny.reminders: if tellee not in phenny.reminders:
phenny.reminders[tellee] = [(teller, verb, timenow, msg)] phenny.reminders[tellee] = [(teller, verb, timenow, msg)]
else: else:
# if len(phenny.reminders[tellee]) >= maximum: # if len(phenny.reminders[tellee]) >= maximum:
# warn = True # warn = True
phenny.reminders[tellee].append((teller, verb, timenow, msg)) phenny.reminders[tellee].append((teller, verb, timenow, msg))
# @@ Stephanie's augmentation # @@ Stephanie's augmentation
response = "I'll pass that on when %s is around." % tellee_original response = "I'll pass that on when %s is around." % tellee_original
# if warn: response += (" I'll have to use a pastebin, though, so " + # if warn: response += (" I'll have to use a pastebin, though, so " +
# "your message may get lost.") # "your message may get lost.")
rand = random.random() rand = random.random()
if rand > 0.9999: response = "yeah, yeah" if rand > 0.9999: response = "yeah, yeah"
elif rand > 0.999: response = "yeah, sure, whatever" elif rand > 0.999: response = "yeah, sure, whatever"
phenny.reply(response) phenny.reply(response)
elif teller.lower() == tellee: elif teller.lower() == tellee:
phenny.say('You can %s yourself that.' % verb) phenny.say('You can %s yourself that.' % verb)
else: phenny.say("Hey, I'm not as stupid as Monty you know!") else: phenny.say("Hey, I'm not as stupid as Monty you know!")
dumpReminders(phenny.tell_filename, phenny.reminders) # @@ tell dumpReminders(phenny.tell_filename, phenny.reminders) # @@ tell
f_remind.rule = ('$nick', ['tell', 'ask'], r'(\S+) (.*)') f_remind.rule = ('$nick', ['tell', 'ask'], r'(\S+) (.*)')
f_remind.thread = False f_remind.thread = False
def getReminders(phenny, channel, key, tellee): def getReminders(phenny, channel, key, tellee):
lines = [] lines = []
template = "%s: %s <%s> %s %s %s" template = "%s: %s <%s> %s %s %s"
today = time.strftime('%d %b', time.gmtime()) today = time.strftime('%d %b', time.gmtime())
for (teller, verb, datetime, msg) in phenny.reminders[key]: for (teller, verb, datetime, msg) in phenny.reminders[key]:
if datetime.startswith(today): if datetime.startswith(today):
datetime = datetime[len(today)+1:] datetime = datetime[len(today)+1:]
lines.append(template % (tellee, datetime, teller, verb, tellee, msg)) lines.append(template % (tellee, datetime, teller, verb, tellee, msg))
try: del phenny.reminders[key] try: del phenny.reminders[key]
except KeyError: phenny.msg(channel, 'Er...') except KeyError: phenny.msg(channel, 'Er...')
return lines return lines
def message(phenny, input): def message(phenny, input):
if not input.sender.startswith('#'): return if not input.sender.startswith('#'): return
tellee = input.nick tellee = input.nick
channel = input.sender channel = input.sender
if not os: return if not os: return
if not os.path.exists(phenny.tell_filename): if not os.path.exists(phenny.tell_filename):
return return
reminders = [] reminders = []
remkeys = list(reversed(sorted(phenny.reminders.keys()))) remkeys = list(reversed(sorted(phenny.reminders.keys())))
for remkey in remkeys: for remkey in remkeys:
if not remkey.endswith('*') or remkey.endswith(':'): if not remkey.endswith('*') or remkey.endswith(':'):
if tellee.lower() == remkey: if tellee.lower() == remkey:
reminders.extend(getReminders(phenny, channel, remkey, tellee))
elif tellee.lower().startswith(remkey.rstrip('*:')):
reminders.extend(getReminders(phenny, channel, remkey, tellee)) reminders.extend(getReminders(phenny, channel, remkey, tellee))
elif tellee.lower().startswith(remkey.rstrip('*:')):
reminders.extend(getReminders(phenny, channel, remkey, tellee))
for line in reminders[:maximum]: for line in reminders[:maximum]:
phenny.say(line) phenny.say(line)
if reminders[maximum:]: if reminders[maximum:]:
phenny.say('Further messages sent privately') phenny.say('Further messages sent privately')
for line in reminders[maximum:]: for line in reminders[maximum:]:
phenny.msg(tellee, line) phenny.msg(tellee, line)
if len(list(phenny.reminders.keys())) != remkeys: if len(list(phenny.reminders.keys())) != remkeys:
dumpReminders(phenny.tell_filename, phenny.reminders) # @@ tell dumpReminders(phenny.tell_filename, phenny.reminders) # @@ tell
message.rule = r'(.*)' message.rule = r'(.*)'
message.priority = 'low' message.priority = 'low'
message.thread = False message.thread = False
def messageAlert(phenny, input): def messageAlert(phenny, input):
if (input.nick.lower() in list(phenny.reminders.keys())): if (input.nick.lower() in list(phenny.reminders.keys())):
phenny.say(input.nick + ': You have messages.') phenny.say(input.nick + ': You have messages.')
messageAlert.event = 'JOIN' messageAlert.event = 'JOIN'
messageAlert.rule = r'.*' messageAlert.rule = r'.*'
messageAlert.priority = 'low' messageAlert.priority = 'low'
messageAlert.thread = False messageAlert.thread = False
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -1,7 +1,7 @@
#!/usr/bin/python3 #!/usr/bin/python3
""" """
tfw.py - the fucking weather module tfw.py - the fucking weather module
author: mutantmonkey <mutantmonkey@gmail.com> author: mutantmonkey <mutantmonkey@mutantmonkey.in>
""" """
from urllib.parse import quote as urlquote from urllib.parse import quote as urlquote
@ -82,4 +82,3 @@ tfwc.rule = (['tfwc'], r'(.*)')
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -13,77 +13,77 @@ import json
import web import web
def translate(text, input='auto', output='en'): def translate(text, input='auto', output='en'):
opener = urllib.request.build_opener() opener = urllib.request.build_opener()
opener.addheaders = [( opener.addheaders = [(
'User-Agent', 'Mozilla/5.0' + 'User-Agent', 'Mozilla/5.0' +
'(X11; U; Linux i686)' + '(X11; U; Linux i686)' +
'Gecko/20071127 Firefox/2.0.0.11' 'Gecko/20071127 Firefox/2.0.0.11'
)] )]
input, output = urllib.parse.quote(input), urllib.parse.quote(output) input, output = urllib.parse.quote(input), urllib.parse.quote(output)
text = urllib.parse.quote(text) text = urllib.parse.quote(text)
result = opener.open('http://translate.google.com/translate_a/t?' + result = opener.open('http://translate.google.com/translate_a/t?' +
('client=t&hl=en&sl=%s&tl=%s&multires=1' % (input, output)) + ('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() ('&otf=1&ssel=0&tsel=0&uptl=en&sc=1&text=%s' % text)).read()
result = result.decode('utf-8') result = result.decode('utf-8')
while ',,' in result: while ',,' in result:
result = result.replace(',,', ',null,') result = result.replace(',,', ',null,')
data = json.loads(result) data = json.loads(result)
try: language = data[-2][0][0] try: language = data[-2][0][0]
except: language = '?' 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): def tr(phenny, context):
"""Translates a phrase, with an optional language hint.""" """Translates a phrase, with an optional language hint."""
input, output, phrase = context.groups() input, output, phrase = context.groups()
phrase = phrase phrase = phrase
if (len(phrase) > 350) and (not context.admin): if (len(phrase) > 350) and (not context.admin):
return phenny.reply('Phrase must be under 350 characters.') return phenny.reply('Phrase must be under 350 characters.')
input = input or 'auto' input = input or 'auto'
input = input.encode('utf-8') input = input.encode('utf-8')
output = (output or 'en').encode('utf-8') output = (output or 'en').encode('utf-8')
if input != output: if input != output:
msg, input = translate(phrase, input, output) msg, input = translate(phrase, input, output)
output = output.decode('utf-8') output = output.decode('utf-8')
if msg: if msg:
msg = web.decode(msg) # msg.replace('&#39;', "'") msg = web.decode(msg) # msg.replace('&#39;', "'")
msg = '"%s" (%s to %s, translate.google.com)' % (msg, input, output) msg = '"%s" (%s to %s, translate.google.com)' % (msg, input, output)
else: msg = 'The %s to %s translation failed, sorry!' % (input, output) else: msg = 'The %s to %s translation failed, sorry!' % (input, output)
phenny.reply(msg) phenny.reply(msg)
else: phenny.reply('Language guessing failed, so try suggesting one!') else: phenny.reply('Language guessing failed, so try suggesting one!')
tr.rule = ('$nick', r'(?:([a-z]{2}) +)?(?:([a-z]{2}) +)?["“](.+?)["”]\? *$') tr.rule = ('$nick', r'(?:([a-z]{2}) +)?(?:([a-z]{2}) +)?["“](.+?)["”]\? *$')
tr.example = '$nickname: "mon chien"? or $nickname: fr "mon chien"?' tr.example = '$nickname: "mon chien"? or $nickname: fr "mon chien"?'
tr.priority = 'low' tr.priority = 'low'
def mangle(phenny, input): def mangle(phenny, input):
phrase = input.group(2) phrase = input.group(2)
for lang in ['fr', 'de', 'es', 'it', 'ja']: for lang in ['fr', 'de', 'es', 'it', 'ja']:
backup = phrase backup = phrase
phrase = translate(phrase, 'en', lang) phrase = translate(phrase, 'en', lang)
if not phrase: if not phrase:
phrase = backup phrase = backup
break break
__import__('time').sleep(0.5) __import__('time').sleep(0.5)
backup = phrase backup = phrase
phrase = translate(phrase, lang, 'en') phrase = translate(phrase, lang, 'en')
if not phrase: if not phrase:
phrase = backup phrase = backup
break break
__import__('time').sleep(0.5) __import__('time').sleep(0.5)
phenny.reply(phrase or 'ERRORS SRY') phenny.reply(phrase or 'ERRORS SRY')
mangle.commands = ['mangle'] mangle.commands = ['mangle']
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -7,7 +7,7 @@ Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/ http://inamidst.com/phenny/
modified from Wikipedia module modified from Wikipedia module
author: mutantmonkey <mutantmonkey@gmail.com> author: mutantmonkey <mutantmonkey@mutantmonkey.in>
""" """
import re, urllib.request, urllib.parse, urllib.error import re, urllib.request, urllib.parse, urllib.error
@ -15,151 +15,151 @@ import web
wikiuri = 'http://uncyclopedia.wikia.com/wiki/%s' wikiuri = 'http://uncyclopedia.wikia.com/wiki/%s'
wikisearch = 'http://uncyclopedia.wikia.com/wiki/Special:Search?' \ wikisearch = 'http://uncyclopedia.wikia.com/wiki/Special:Search?' \
+ 'search=%s&fulltext=Search' + 'search=%s&fulltext=Search'
r_tr = re.compile(r'(?ims)<tr[^>]*>.*?</tr>') r_tr = re.compile(r'(?ims)<tr[^>]*>.*?</tr>')
r_paragraph = re.compile(r'(?ims)<p[^>]*>.*?</p>|<li(?!n)[^>]*>.*?</li>') r_paragraph = re.compile(r'(?ims)<p[^>]*>.*?</p>|<li(?!n)[^>]*>.*?</li>')
r_tag = re.compile(r'<(?!!)[^>]+>') r_tag = re.compile(r'<(?!!)[^>]+>')
r_whitespace = re.compile(r'[\t\r\n ]+') r_whitespace = re.compile(r'[\t\r\n ]+')
r_redirect = re.compile( 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', abbrs = ['etc', 'ca', 'cf', 'Co', 'Ltd', 'Inc', 'Mt', 'Mr', 'Mrs',
'Dr', 'Ms', 'Rev', 'Fr', 'St', 'Sgt', 'pron', 'approx', 'lit', 'Dr', 'Ms', 'Rev', 'Fr', 'St', 'Sgt', 'pron', 'approx', 'lit',
'syn', 'transl', 'sess', 'fl', 'Op'] \ 'syn', 'transl', 'sess', 'fl', 'Op'] \
+ list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') \ + list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') \
+ list('abcdefghijklmnopqrstuvwxyz') + list('abcdefghijklmnopqrstuvwxyz')
t_sentence = r'^.{5,}?(?<!\b%s)(?:\.(?=[\[ ][A-Z0-9]|\Z)|\Z)' t_sentence = r'^.{5,}?(?<!\b%s)(?:\.(?=[\[ ][A-Z0-9]|\Z)|\Z)'
r_sentence = re.compile(t_sentence % r')(?<!\b'.join(abbrs)) r_sentence = re.compile(t_sentence % r')(?<!\b'.join(abbrs))
def unescape(s): def unescape(s):
s = s.replace('&gt;', '>') s = s.replace('&gt;', '>')
s = s.replace('&lt;', '<') s = s.replace('&lt;', '<')
s = s.replace('&amp;', '&') s = s.replace('&amp;', '&')
s = s.replace('&#160;', ' ') s = s.replace('&#160;', ' ')
return s return s
def text(html): def text(html):
html = r_tag.sub('', html) html = r_tag.sub('', html)
html = r_whitespace.sub(' ', html) html = r_whitespace.sub(' ', html)
return unescape(html).strip() return unescape(html).strip()
def search(term): def search(term):
try: from . import search try: from . import search
except ImportError as e: except ImportError as e:
print(e) print(e)
return term return term
if not isinstance(term, str): if not isinstance(term, str):
term = term.decode('utf-8') term = term.decode('utf-8')
term = term.replace('_', ' ') term = term.replace('_', ' ')
try: uri = search.result('site:uncyclopedia.wikia.com %s' % term) try: uri = search.result('site:uncyclopedia.wikia.com %s' % term)
except IndexError: return term except IndexError: return term
if uri: if uri:
return uri[len('http://uncyclopedia.wikia.com/wiki/'):] return uri[len('http://uncyclopedia.wikia.com/wiki/'):]
else: return term else: return term
def uncyclopedia(term, last=False): def uncyclopedia(term, last=False):
global wikiuri global wikiuri
if not '%' in term: if not '%' in term:
if isinstance(term, str): if isinstance(term, str):
t = term t = term
else: t = term else: t = term
q = urllib.parse.quote(t) q = urllib.parse.quote(t)
u = wikiuri % q u = wikiuri % q
bytes = web.get(u) bytes = web.get(u)
else: bytes = web.get(wikiuri % term) else: bytes = web.get(wikiuri % term)
bytes = r_tr.sub('', bytes) bytes = r_tr.sub('', bytes)
if not last: if not last:
r = r_redirect.search(bytes[:4096]) r = r_redirect.search(bytes[:4096])
if r: if r:
term = urllib.parse.unquote(r.group(1)) term = urllib.parse.unquote(r.group(1))
return uncyclopedia(term, last=True) return uncyclopedia(term, last=True)
paragraphs = r_paragraph.findall(bytes) paragraphs = r_paragraph.findall(bytes)
if not paragraphs: if not paragraphs:
if not last: if not last:
term = search(term) term = search(term)
return uncyclopedia(term, last=True) return uncyclopedia(term, last=True)
return None return None
# Pre-process # Pre-process
paragraphs = [para for para in paragraphs paragraphs = [para for para in paragraphs
if (para and 'technical limitations' not in para if (para and 'technical limitations' not in para
and 'window.showTocToggle' not in para and 'window.showTocToggle' not in para
and 'Deletion_policy' not in para and 'Deletion_policy' not in para
and 'Template:AfD_footer' not in para and 'Template:AfD_footer' not in para
and not (para.startswith('<p><i>') and and not (para.startswith('<p><i>') and
para.endswith('</i></p>')) para.endswith('</i></p>'))
and not 'disambiguation)"' in para) and not 'disambiguation)"' in para)
and not '(images and media)' in para and not '(images and media)' in para
and not 'This article contains a' in para and not 'This article contains a' in para
and not 'id="coordinates"' in para and not 'id="coordinates"' in para
and not 'class="thumb' in para and not 'class="thumb' in para
and not 'There is currently no text in this page.' in para] and not 'There is currently no text in this page.' in para]
# and not 'style="display:none"' in para] # and not 'style="display:none"' in para]
for i, para in enumerate(paragraphs): for i, para in enumerate(paragraphs):
para = para.replace('<sup>', '|') para = para.replace('<sup>', '|')
para = para.replace('</sup>', '|') para = para.replace('</sup>', '|')
paragraphs[i] = text(para).strip() paragraphs[i] = text(para).strip()
# Post-process # Post-process
paragraphs = [para for para in paragraphs if paragraphs = [para for para in paragraphs if
(para and not (para.endswith(':') and len(para) < 150))] (para and not (para.endswith(':') and len(para) < 150))]
para = text(paragraphs[0]) para = text(paragraphs[0])
m = r_sentence.match(para) m = r_sentence.match(para)
if not m: if not m:
if not last: if not last:
term = search(term) term = search(term)
return uncyclopedia(term, last=True) return uncyclopedia(term, last=True)
return None return None
sentence = m.group(0) sentence = m.group(0)
maxlength = 275 maxlength = 275
if len(sentence) > maxlength: if len(sentence) > maxlength:
sentence = sentence[:maxlength] sentence = sentence[:maxlength]
words = sentence[:-5].split(' ') words = sentence[:-5].split(' ')
words.pop() words.pop()
sentence = ' '.join(words) + ' [...]' sentence = ' '.join(words) + ' [...]'
if (('using the Article Wizard if you wish' in sentence) if (('using the Article Wizard if you wish' in sentence)
or ('or add a request for it' in sentence)): or ('or add a request for it' in sentence)):
if not last: if not last:
term = search(term) term = search(term)
return uncyclopedia(term, last=True) return uncyclopedia(term, last=True)
return None return None
sentence = '"' + sentence.replace('"', "'") + '"' sentence = '"' + sentence.replace('"', "'") + '"'
return sentence + ' - ' + (wikiuri % term) return sentence + ' - ' + (wikiuri % term)
def uncyc(phenny, input): def uncyc(phenny, input):
origterm = input.groups()[1] origterm = input.groups()[1]
if not origterm: if not origterm:
return phenny.say('Perhaps you meant ".uncyc Zen"?') return phenny.say('Perhaps you meant ".uncyc Zen"?')
origterm = origterm origterm = origterm
term = urllib.parse.unquote(origterm) term = urllib.parse.unquote(origterm)
term = term[0].upper() + term[1:] term = term[0].upper() + term[1:]
term = term.replace(' ', '_') term = term.replace(' ', '_')
try: result = uncyclopedia(term) try: result = uncyclopedia(term)
except IOError: except IOError:
error = "Can't connect to uncyclopedia.wikia.com (%s)" % (wikiuri % term) error = "Can't connect to uncyclopedia.wikia.com (%s)" % (wikiuri % term)
return phenny.say(error) return phenny.say(error)
if result is not None: if result is not None:
phenny.say(result) phenny.say(result)
else: phenny.say('Can\'t find anything in Uncyclopedia for "%s".' % origterm) else: phenny.say('Can\'t find anything in Uncyclopedia for "%s".' % origterm)
uncyc.commands = ['uncyc'] uncyc.commands = ['uncyc']
uncyc.priority = 'high' uncyc.priority = 'high'
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -37,4 +37,3 @@ urbandict.rule = (['urb'], r'(.*)')
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -10,34 +10,34 @@ http://inamidst.com/phenny/
import web import web
def val(phenny, input): def val(phenny, input):
"""Check a webpage using the W3C Markup Validator.""" """Check a webpage using the W3C Markup Validator."""
if not input.group(2): if not input.group(2):
return phenny.reply("Nothing to validate.") return phenny.reply("Nothing to validate.")
uri = input.group(2) uri = input.group(2)
if not uri.startswith('http://'): if not uri.startswith('http://'):
uri = 'http://' + uri uri = 'http://' + uri
path = '/check?uri=%s;output=xml' % web.urllib.quote(uri) path = '/check?uri=%s;output=xml' % web.urllib.quote(uri)
info = web.head('http://validator.w3.org' + path) info = web.head('http://validator.w3.org' + path)
result = uri + ' is ' result = uri + ' is '
if isinstance(info, list): if isinstance(info, list):
return phenny.say('Got HTTP response %s' % info[1]) return phenny.say('Got HTTP response %s' % info[1])
if 'X-W3C-Validator-Status' in info: if 'X-W3C-Validator-Status' in info:
result += str(info['X-W3C-Validator-Status']) result += str(info['X-W3C-Validator-Status'])
if info['X-W3C-Validator-Status'] != 'Valid': if info['X-W3C-Validator-Status'] != 'Valid':
if 'X-W3C-Validator-Errors' in info: if 'X-W3C-Validator-Errors' in info:
n = int(info['X-W3C-Validator-Errors'].split(' ')[0]) n = int(info['X-W3C-Validator-Errors'].split(' ')[0])
if n != 1: if n != 1:
result += ' (%s errors)' % n result += ' (%s errors)' % n
else: result += ' (%s error)' % n else: result += ' (%s error)' % n
else: result += 'Unvalidatable: no X-W3C-Validator-Status' else: result += 'Unvalidatable: no X-W3C-Validator-Status'
phenny.reply(result) phenny.reply(result)
val.rule = (['val'], r'(?i)(\S+)') val.rule = (['val'], r'(?i)(\S+)')
val.example = '.val http://www.w3.org/' val.example = '.val http://www.w3.org/'
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -7,7 +7,7 @@ Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/ http://inamidst.com/phenny/
modified from Wikipedia module modified from Wikipedia module
author: mutantmonkey <mutantmonkey@gmail.com> author: mutantmonkey <mutantmonkey@mutantmonkey.in>
""" """
import re, urllib.request, urllib.parse, urllib.error import re, urllib.request, urllib.parse, urllib.error

View File

@ -1,116 +0,0 @@
#!/usr/bin/python2
# -*- coding: utf-8 -*-
"""
wargame.py - wargame module for the vtluug wargame
http://wargame.vtluug.org
author: Casey Link <unnamedrambler@gmail.com>
"""
import random
import configparser, os
from urllib.parse import quote as urlquote
from urllib.request import urlopen
from urllib.error import HTTPError
from lxml import etree
from lxml import objectify
from datetime import datetime
import re
APIURL = "http://wargame.vtluug.org/scoreboard.xml"
class server(object):
def __init__(self, name):
self.name = name
self.players = []
def __str__(self):
s = "%s - %d players: " %(self.name, len(self.players))
s += ", ".join([str(p) for p in self.players])
return s
class player(object):
def __init__(self, name):
self.name = name
self.score = "-1"
self.isOwner = False
def __str__(self):
return "%s%s: %s points" %(self.name, " (Current King)" if self.isOwner else "", self.score)
def __cmp__(self, other):
if int(self.score) < int(other.score):
return -1
elif int(self.score) == int(other.score):
return 0
else:
return 1
def parse_player(player_element):
p = player( player_element.attrib.get("name") )
p.score = player_element.attrib.get("score")
p.isOwner = player_element.attrib.get("isOwner") == "True"
return p
def parse_server(server_element):
s = server( server_element.name.text )
for player_e in server_element.players.player:
s.players.append( parse_player( player_e ) )
s.players.sort()
s.players.reverse()
return s
def wargame(phenny, input):
if input.group(2) is not None:
rest = input.group(2)
m = re.match("^scores\s+(\S+)\s*$",rest)
if m is not None and len( m.groups() ) == 1:
return wargame_scores(phenny, m.group(1))
m = re.match("^scores\s*$",rest)
if m is not None:
return wargame_scores(phenny, "Total")
m = re.match("^help\s*$",rest)
if m is not None:
phenny.say("VTLUUG King of the Root - http://wargame.vtluug.org'")
phenny.say("syntax: '.wargame' to see network status and target list'")
phenny.say("syntax: '.wargame scores <target name>' to get current scores for a target'")
return
else:
phenny.say("hmm.. I don't know what you mean. try '.wargame help'")
return
try:
req = urlopen(APIURL)
except HTTPError as e:
phenny.say("uhoh. try again later, mmkay?")
return
root = objectify.parse(req).getroot()
online = root.attrib.get("online") == "True"
updated = root.attrib.get("updated")
servers = []
for server_e in root.servers.server:
servers.append( parse_server( server_e ) )
phenny.say( "wargame network is %s. last updated %s. available targets: %s" % ( "ONLINE" if online else "OFFLINE", updated, ", ".join([s.name for s in servers])) )
def wargame_scores(phenny, s_name):
try:
req = urlopen(APIURL)
except HTTPError as e:
phenny.say("uhoh. try again later, mmkay?")
return
root = objectify.parse(req).getroot()
online = root.attrib.get("online") == "True"
updated = root.attrib.get("updated")
servers = {}
for server_e in root.servers.server:
s = parse_server( server_e )
servers[s.name] = s
if not s_name in servers:
phenny.say("sorry, i couldn't find %s" % ( s_name ))
return
phenny.say( str(servers[s_name]) )
wargame.commands = ['wargame']

View File

@ -14,397 +14,397 @@ from tools import deprecated
r_from = re.compile(r'(?i)([+-]\d+):00 from') r_from = re.compile(r'(?i)([+-]\d+):00 from')
def location(name): def location(name):
name = urllib.parse.quote(name) name = urllib.parse.quote(name)
uri = 'http://ws.geonames.org/searchJSON?q=%s&maxRows=1' % name uri = 'http://ws.geonames.org/searchJSON?q=%s&maxRows=1' % name
for i in range(10): for i in range(10):
bytes = web.get(uri) bytes = web.get(uri)
if bytes is not None: break if bytes is not None: break
results = web.json(bytes) results = web.json(bytes)
try: name = results['geonames'][0]['name'] try: name = results['geonames'][0]['name']
except IndexError: except IndexError:
return '?', '?', '0', '0' return '?', '?', '0', '0'
countryName = results['geonames'][0]['countryName'] countryName = results['geonames'][0]['countryName']
lat = results['geonames'][0]['lat'] lat = results['geonames'][0]['lat']
lng = results['geonames'][0]['lng'] lng = results['geonames'][0]['lng']
return name, countryName, lat, lng return name, countryName, lat, lng
class GrumbleError(object): class GrumbleError(object):
pass pass
def local(icao, hour, minute): def local(icao, hour, minute):
uri = ('http://www.flightstats.com/' + uri = ('http://www.flightstats.com/' +
'go/Airport/airportDetails.do?airportCode=%s') 'go/Airport/airportDetails.do?airportCode=%s')
try: bytes = web.get(uri % icao) try: bytes = web.get(uri % icao)
except AttributeError: except AttributeError:
raise GrumbleError('A WEBSITE HAS GONE DOWN WTF STUPID WEB') raise GrumbleError('A WEBSITE HAS GONE DOWN WTF STUPID WEB')
m = r_from.search(bytes) m = r_from.search(bytes)
if m: if m:
offset = m.group(1) offset = m.group(1)
lhour = int(hour) + int(offset) lhour = int(hour) + int(offset)
lhour = lhour % 24 lhour = lhour % 24
return (str(lhour) + ':' + str(minute) + ', ' + str(hour) + return (str(lhour) + ':' + str(minute) + ', ' + str(hour) +
str(minute) + 'Z') str(minute) + 'Z')
# return (str(lhour) + ':' + str(minute) + ' (' + str(hour) + # return (str(lhour) + ':' + str(minute) + ' (' + str(hour) +
# ':' + str(minute) + 'Z)') # ':' + str(minute) + 'Z)')
return str(hour) + ':' + str(minute) + 'Z' return str(hour) + ':' + str(minute) + 'Z'
def code(phenny, search): def code(phenny, search):
from icao import data from icao import data
if search.upper() in [loc[0] for loc in data]: if search.upper() in [loc[0] for loc in data]:
return search.upper() return search.upper()
else: else:
name, country, latitude, longitude = location(search) name, country, latitude, longitude = location(search)
if name == '?': return False if name == '?': return False
sumOfSquares = (99999999999999999999999999999, 'ICAO') sumOfSquares = (99999999999999999999999999999, 'ICAO')
for icao_code, lat, lon in data: for icao_code, lat, lon in data:
latDiff = abs(latitude - lat) latDiff = abs(latitude - lat)
lonDiff = abs(longitude - lon) lonDiff = abs(longitude - lon)
diff = (latDiff * latDiff) + (lonDiff * lonDiff) diff = (latDiff * latDiff) + (lonDiff * lonDiff)
if diff < sumOfSquares[0]: if diff < sumOfSquares[0]:
sumOfSquares = (diff, icao_code) sumOfSquares = (diff, icao_code)
return sumOfSquares[1] return sumOfSquares[1]
@deprecated @deprecated
def f_weather(self, origin, match, args): def f_weather(self, origin, match, args):
""".weather <ICAO> - Show the weather at airport with the code <ICAO>.""" """.weather <ICAO> - Show the weather at airport with the code <ICAO>."""
if origin.sender == '#talis': if origin.sender == '#talis':
if args[0].startswith('.weather '): return if args[0].startswith('.weather '): return
icao_code = match.group(2) icao_code = match.group(2)
if not icao_code: if not icao_code:
return self.msg(origin.sender, 'Try .weather London, for example?') return self.msg(origin.sender, 'Try .weather London, for example?')
icao_code = code(self, icao_code) icao_code = code(self, icao_code)
if not icao_code: if not icao_code:
self.msg(origin.sender, 'No ICAO code found, sorry') self.msg(origin.sender, 'No ICAO code found, sorry')
return return
uri = 'http://weather.noaa.gov/pub/data/observations/metar/stations/%s.TXT' uri = 'http://weather.noaa.gov/pub/data/observations/metar/stations/%s.TXT'
try: bytes = web.get(uri % icao_code) try: bytes = web.get(uri % icao_code)
except AttributeError: except AttributeError:
raise GrumbleError('OH CRAP NOAA HAS GONE DOWN THE WEB IS BROKEN') raise GrumbleError('OH CRAP NOAA HAS GONE DOWN THE WEB IS BROKEN')
if 'Not Found' in bytes: if 'Not Found' in bytes:
self.msg(origin.sender, icao_code+': no such ICAO code, or no NOAA data') self.msg(origin.sender, icao_code+': no such ICAO code, or no NOAA data')
return return
metar = bytes.splitlines().pop() metar = bytes.splitlines().pop()
metar = metar.split(' ') metar = metar.split(' ')
if len(metar[0]) == 4: if len(metar[0]) == 4:
metar = metar[1:] metar = metar[1:]
if metar[0].endswith('Z'): if metar[0].endswith('Z'):
time = metar[0] time = metar[0]
metar = metar[1:] metar = metar[1:]
else: time = None else: time = None
if metar[0] == 'AUTO': if metar[0] == 'AUTO':
metar = metar[1:] metar = metar[1:]
if metar[0] == 'VCU': if metar[0] == 'VCU':
self.msg(origin.sender, icao_code + ': no data provided') self.msg(origin.sender, icao_code + ': no data provided')
return return
if metar[0].endswith('KT'): if metar[0].endswith('KT'):
wind = metar[0] wind = metar[0]
metar = metar[1:] metar = metar[1:]
else: wind = None else: wind = None
if ('V' in metar[0]) and (metar[0] != 'CAVOK'): if ('V' in metar[0]) and (metar[0] != 'CAVOK'):
vari = metar[0] vari = metar[0]
metar = metar[1:] metar = metar[1:]
else: vari = None else: vari = None
if ((len(metar[0]) == 4) or if ((len(metar[0]) == 4) or
metar[0].endswith('SM')): metar[0].endswith('SM')):
visibility = metar[0] visibility = metar[0]
metar = metar[1:] metar = metar[1:]
else: visibility = None else: visibility = None
while metar[0].startswith('R') and (metar[0].endswith('L') while metar[0].startswith('R') and (metar[0].endswith('L')
or 'L/' in metar[0]): or 'L/' in metar[0]):
metar = metar[1:] metar = metar[1:]
if len(metar[0]) == 6 and (metar[0].endswith('N') or if len(metar[0]) == 6 and (metar[0].endswith('N') or
metar[0].endswith('E') or metar[0].endswith('E') or
metar[0].endswith('S') or metar[0].endswith('S') or
metar[0].endswith('W')): metar[0].endswith('W')):
metar = metar[1:] # 7000SE? metar = metar[1:] # 7000SE?
cond = [] cond = []
while (((len(metar[0]) < 5) or while (((len(metar[0]) < 5) or
metar[0].startswith('+') or metar[0].startswith('+') or
metar[0].startswith('-')) and (not (metar[0].startswith('VV') or metar[0].startswith('-')) and (not (metar[0].startswith('VV') or
metar[0].startswith('SKC') or metar[0].startswith('CLR') or metar[0].startswith('SKC') or metar[0].startswith('CLR') or
metar[0].startswith('FEW') or metar[0].startswith('SCT') or metar[0].startswith('FEW') or metar[0].startswith('SCT') or
metar[0].startswith('BKN') or metar[0].startswith('OVC')))): metar[0].startswith('BKN') or metar[0].startswith('OVC')))):
cond.append(metar[0]) cond.append(metar[0])
metar = metar[1:] metar = metar[1:]
while '/P' in metar[0]: while '/P' in metar[0]:
metar = metar[1:] metar = metar[1:]
if not metar: if not metar:
self.msg(origin.sender, icao_code + ': no data provided') self.msg(origin.sender, icao_code + ': no data provided')
return return
cover = [] cover = []
while (metar[0].startswith('VV') or metar[0].startswith('SKC') or while (metar[0].startswith('VV') or metar[0].startswith('SKC') or
metar[0].startswith('CLR') or metar[0].startswith('FEW') or metar[0].startswith('CLR') or metar[0].startswith('FEW') or
metar[0].startswith('SCT') or metar[0].startswith('BKN') or metar[0].startswith('SCT') or metar[0].startswith('BKN') or
metar[0].startswith('OVC')): metar[0].startswith('OVC')):
cover.append(metar[0]) cover.append(metar[0])
metar = metar[1:] metar = metar[1:]
if not metar: if not metar:
self.msg(origin.sender, icao_code + ': no data provided') self.msg(origin.sender, icao_code + ': no data provided')
return return
if metar[0] == 'CAVOK': if metar[0] == 'CAVOK':
cover.append('CLR') cover.append('CLR')
metar = metar[1:] metar = metar[1:]
if metar[0] == 'PRFG': if metar[0] == 'PRFG':
cover.append('CLR') # @@? cover.append('CLR') # @@?
metar = metar[1:] metar = metar[1:]
if metar[0] == 'NSC': if metar[0] == 'NSC':
cover.append('CLR') cover.append('CLR')
metar = metar[1:] metar = metar[1:]
if ('/' in metar[0]) or (len(metar[0]) == 5 and metar[0][2] == '.'): if ('/' in metar[0]) or (len(metar[0]) == 5 and metar[0][2] == '.'):
temp = metar[0] temp = metar[0]
metar = metar[1:] metar = metar[1:]
else: temp = None else: temp = None
if metar[0].startswith('QFE'): if metar[0].startswith('QFE'):
metar = metar[1:] metar = metar[1:]
if metar[0].startswith('Q') or metar[0].startswith('A'): if metar[0].startswith('Q') or metar[0].startswith('A'):
pressure = metar[0] pressure = metar[0]
metar = metar[1:] metar = metar[1:]
else: pressure = None else: pressure = None
if time: if time:
hour = time[2:4] hour = time[2:4]
minute = time[4:6] minute = time[4:6]
time = local(icao_code, hour, minute) time = local(icao_code, hour, minute)
else: time = '(time unknown)' else: time = '(time unknown)'
if wind: if wind:
speed = int(wind[3:5]) speed = int(wind[3:5])
if speed < 1: if speed < 1:
description = 'Calm' description = 'Calm'
elif speed < 4: elif speed < 4:
description = 'Light air' description = 'Light air'
elif speed < 7: elif speed < 7:
description = 'Light breeze' description = 'Light breeze'
elif speed < 11: elif speed < 11:
description = 'Gentle breeze' description = 'Gentle breeze'
elif speed < 16: elif speed < 16:
description = 'Moderate breeze' description = 'Moderate breeze'
elif speed < 22: elif speed < 22:
description = 'Fresh breeze' description = 'Fresh breeze'
elif speed < 28: elif speed < 28:
description = 'Strong breeze' description = 'Strong breeze'
elif speed < 34: elif speed < 34:
description = 'Near gale' description = 'Near gale'
elif speed < 41: elif speed < 41:
description = 'Gale' description = 'Gale'
elif speed < 48: elif speed < 48:
description = 'Strong gale' description = 'Strong gale'
elif speed < 56: elif speed < 56:
description = 'Storm' description = 'Storm'
elif speed < 64: elif speed < 64:
description = 'Violent storm' description = 'Violent storm'
else: description = 'Hurricane' else: description = 'Hurricane'
degrees = float(wind[0:3]) degrees = float(wind[0:3])
#if degrees == 'VRB': #if degrees == 'VRB':
# degrees = '\u21BB' # degrees = '\u21BB'
if (degrees <= 22.5) or (degrees > 337.5): if (degrees <= 22.5) or (degrees > 337.5):
degrees = '\u2191' degrees = '\u2191'
elif (degrees > 22.5) and (degrees <= 67.5): elif (degrees > 22.5) and (degrees <= 67.5):
degrees = '\u2197' degrees = '\u2197'
elif (degrees > 67.5) and (degrees <= 112.5): elif (degrees > 67.5) and (degrees <= 112.5):
degrees = '\u2192' degrees = '\u2192'
elif (degrees > 112.5) and (degrees <= 157.5): elif (degrees > 112.5) and (degrees <= 157.5):
degrees = '\u2198' degrees = '\u2198'
elif (degrees > 157.5) and (degrees <= 202.5): elif (degrees > 157.5) and (degrees <= 202.5):
degrees = '\u2193' degrees = '\u2193'
elif (degrees > 202.5) and (degrees <= 247.5): elif (degrees > 202.5) and (degrees <= 247.5):
degrees = '\u2199' degrees = '\u2199'
elif (degrees > 247.5) and (degrees <= 292.5): elif (degrees > 247.5) and (degrees <= 292.5):
degrees = '\u2190' degrees = '\u2190'
elif (degrees > 292.5) and (degrees <= 337.5): elif (degrees > 292.5) and (degrees <= 337.5):
degrees = '\u2196' degrees = '\u2196'
if not icao_code.startswith('EN') and not icao_code.startswith('ED'): if not icao_code.startswith('EN') and not icao_code.startswith('ED'):
wind = '%s %skt (%s)' % (description, speed, degrees) wind = '%s %skt (%s)' % (description, speed, degrees)
elif icao_code.startswith('ED'): elif icao_code.startswith('ED'):
kmh = int(round(speed * 1.852, 0)) kmh = int(round(speed * 1.852, 0))
wind = '%s %skm/h (%skt) (%s)' % (description, kmh, speed, degrees) wind = '%s %skm/h (%skt) (%s)' % (description, kmh, speed, degrees)
elif icao_code.startswith('EN'): elif icao_code.startswith('EN'):
ms = int(round(speed * 0.514444444, 0)) ms = int(round(speed * 0.514444444, 0))
wind = '%s %sm/s (%skt) (%s)' % (description, ms, speed, degrees) wind = '%s %sm/s (%skt) (%s)' % (description, ms, speed, degrees)
else: wind = '(wind unknown)' else: wind = '(wind unknown)'
if visibility: if visibility:
visibility = visibility + 'm' visibility = visibility + 'm'
else: visibility = '(visibility unknown)' else: visibility = '(visibility unknown)'
if cover: if cover:
level = None level = None
for c in cover: for c in cover:
if c.startswith('OVC') or c.startswith('VV'): if c.startswith('OVC') or c.startswith('VV'):
if (level is None) or (level < 8): if (level is None) or (level < 8):
level = 8 level = 8
elif c.startswith('BKN'): elif c.startswith('BKN'):
if (level is None) or (level < 5): if (level is None) or (level < 5):
level = 5 level = 5
elif c.startswith('SCT'): elif c.startswith('SCT'):
if (level is None) or (level < 3): if (level is None) or (level < 3):
level = 3 level = 3
elif c.startswith('FEW'): elif c.startswith('FEW'):
if (level is None) or (level < 1): if (level is None) or (level < 1):
level = 1 level = 1
elif c.startswith('SKC') or c.startswith('CLR'): elif c.startswith('SKC') or c.startswith('CLR'):
if level is None: if level is None:
level = 0 level = 0
if level == 8: if level == 8:
cover = 'Overcast \u2601' cover = 'Overcast \u2601'
elif level == 5: elif level == 5:
cover = 'Cloudy' cover = 'Cloudy'
elif level == 3: elif level == 3:
cover = 'Scattered' cover = 'Scattered'
elif (level == 1) or (level == 0): elif (level == 1) or (level == 0):
cover = 'Clear \u263C' cover = 'Clear \u263C'
else: cover = 'Cover Unknown' else: cover = 'Cover Unknown'
else: cover = 'Cover Unknown' else: cover = 'Cover Unknown'
if temp: if temp:
if '/' in temp: if '/' in temp:
temp = temp.split('/')[0] temp = temp.split('/')[0]
else: temp = temp.split('.')[0] else: temp = temp.split('.')[0]
if temp.startswith('M'): if temp.startswith('M'):
temp = '-' + temp[1:] temp = '-' + temp[1:]
try: temp = int(temp) try: temp = int(temp)
except ValueError: temp = '?' except ValueError: temp = '?'
else: temp = '?' else: temp = '?'
if pressure: if pressure:
if pressure.startswith('Q'): if pressure.startswith('Q'):
pressure = pressure.lstrip('Q') pressure = pressure.lstrip('Q')
if pressure != 'NIL': if pressure != 'NIL':
pressure = str(int(pressure)) + 'mb' pressure = str(int(pressure)) + 'mb'
else: pressure = '?mb' else: pressure = '?mb'
elif pressure.startswith('A'): elif pressure.startswith('A'):
pressure = pressure.lstrip('A') pressure = pressure.lstrip('A')
if pressure != 'NIL': if pressure != 'NIL':
inches = pressure[:2] + '.' + pressure[2:] inches = pressure[:2] + '.' + pressure[2:]
mb = int(float(inches) * 33.7685) mb = int(float(inches) * 33.7685)
pressure = '%sin (%smb)' % (inches, mb) pressure = '%sin (%smb)' % (inches, mb)
else: pressure = '?mb' else: pressure = '?mb'
if isinstance(temp, int): if isinstance(temp, int):
f = round((temp * 1.8) + 32, 2) f = round((temp * 1.8) + 32, 2)
temp = '%s\u2109 (%s\u2103)' % (f, temp) temp = '%s\u2109 (%s\u2103)' % (f, temp)
else: pressure = '?mb' else: pressure = '?mb'
if isinstance(temp, int): if isinstance(temp, int):
temp = '%s\u2103' % temp temp = '%s\u2103' % temp
if cond: if cond:
conds = cond conds = cond
cond = '' cond = ''
intensities = { intensities = {
'-': 'Light', '-': 'Light',
'+': 'Heavy' '+': 'Heavy'
} }
descriptors = { descriptors = {
'MI': 'Shallow', 'MI': 'Shallow',
'PR': 'Partial', 'PR': 'Partial',
'BC': 'Patches', 'BC': 'Patches',
'DR': 'Drifting', 'DR': 'Drifting',
'BL': 'Blowing', 'BL': 'Blowing',
'SH': 'Showers of', 'SH': 'Showers of',
'TS': 'Thundery', 'TS': 'Thundery',
'FZ': 'Freezing', 'FZ': 'Freezing',
'VC': 'In the vicinity:' 'VC': 'In the vicinity:'
} }
phenomena = { phenomena = {
'DZ': 'Drizzle', 'DZ': 'Drizzle',
'RA': 'Rain', 'RA': 'Rain',
'SN': 'Snow', 'SN': 'Snow',
'SG': 'Snow Grains', 'SG': 'Snow Grains',
'IC': 'Ice Crystals', 'IC': 'Ice Crystals',
'PL': 'Ice Pellets', 'PL': 'Ice Pellets',
'GR': 'Hail', 'GR': 'Hail',
'GS': 'Small Hail', 'GS': 'Small Hail',
'UP': 'Unknown Precipitation', 'UP': 'Unknown Precipitation',
'BR': 'Mist', 'BR': 'Mist',
'FG': 'Fog', 'FG': 'Fog',
'FU': 'Smoke', 'FU': 'Smoke',
'VA': 'Volcanic Ash', 'VA': 'Volcanic Ash',
'DU': 'Dust', 'DU': 'Dust',
'SA': 'Sand', 'SA': 'Sand',
'HZ': 'Haze', 'HZ': 'Haze',
'PY': 'Spray', 'PY': 'Spray',
'PO': 'Whirls', 'PO': 'Whirls',
'SQ': 'Squalls', 'SQ': 'Squalls',
'FC': 'Tornado', 'FC': 'Tornado',
'SS': 'Sandstorm', 'SS': 'Sandstorm',
'DS': 'Duststorm', 'DS': 'Duststorm',
# ? Cf. http://swhack.com/logs/2007-10-05#T07-58-56 # ? Cf. http://swhack.com/logs/2007-10-05#T07-58-56
'TS': 'Thunderstorm', 'TS': 'Thunderstorm',
'SH': 'Showers' 'SH': 'Showers'
} }
for c in conds: for c in conds:
if c.endswith('//'): if c.endswith('//'):
if cond: cond += ', ' if cond: cond += ', '
cond += 'Some Precipitation' cond += 'Some Precipitation'
elif len(c) == 5: elif len(c) == 5:
intensity = intensities[c[0]] intensity = intensities[c[0]]
descriptor = descriptors[c[1:3]] descriptor = descriptors[c[1:3]]
phenomenon = phenomena.get(c[3:], c[3:]) phenomenon = phenomena.get(c[3:], c[3:])
if cond: cond += ', ' if cond: cond += ', '
cond += intensity + ' ' + descriptor + ' ' + phenomenon cond += intensity + ' ' + descriptor + ' ' + phenomenon
elif len(c) == 4: elif len(c) == 4:
descriptor = descriptors.get(c[:2], c[:2]) descriptor = descriptors.get(c[:2], c[:2])
phenomenon = phenomena.get(c[2:], c[2:]) phenomenon = phenomena.get(c[2:], c[2:])
if cond: cond += ', ' if cond: cond += ', '
cond += descriptor + ' ' + phenomenon cond += descriptor + ' ' + phenomenon
elif len(c) == 3: elif len(c) == 3:
intensity = intensities.get(c[0], c[0]) intensity = intensities.get(c[0], c[0])
phenomenon = phenomena.get(c[1:], c[1:]) phenomenon = phenomena.get(c[1:], c[1:])
if cond: cond += ', ' if cond: cond += ', '
cond += intensity + ' ' + phenomenon cond += intensity + ' ' + phenomenon
elif len(c) == 2: elif len(c) == 2:
phenomenon = phenomena.get(c, c) phenomenon = phenomena.get(c, c)
if cond: cond += ', ' if cond: cond += ', '
cond += phenomenon cond += phenomenon
# if not cond: # if not cond:
# format = u'%s at %s: %s, %s, %s, %s' # format = u'%s at %s: %s, %s, %s, %s'
# args = (icao, time, cover, temp, pressure, wind) # args = (icao, time, cover, temp, pressure, wind)
# else: # else:
# format = u'%s at %s: %s, %s, %s, %s, %s' # format = u'%s at %s: %s, %s, %s, %s, %s'
# args = (icao, time, cover, temp, pressure, cond, wind) # args = (icao, time, cover, temp, pressure, cond, wind)
if not cond: if not cond:
format = '%s, %s, %s, %s - %s %s' format = '%s, %s, %s, %s - %s %s'
args = (cover, temp, pressure, wind, str(icao_code), time) args = (cover, temp, pressure, wind, str(icao_code), time)
else: else:
format = '%s, %s, %s, %s, %s - %s, %s' format = '%s, %s, %s, %s, %s - %s, %s'
args = (cover, temp, pressure, cond, wind, str(icao_code), time) args = (cover, temp, pressure, cond, wind, str(icao_code), time)
self.msg(origin.sender, format % args) self.msg(origin.sender, format % args)
f_weather.rule = (['weather'], r'(.*)') f_weather.rule = (['weather'], r'(.*)')
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())

View File

@ -15,86 +15,86 @@ r_tag = re.compile(r'<[^>]+>')
r_ul = re.compile(r'(?ims)<ul>.*?</ul>') r_ul = re.compile(r'(?ims)<ul>.*?</ul>')
def text(html): def text(html):
text = r_tag.sub('', html).strip() text = r_tag.sub('', html).strip()
text = text.replace('\n', ' ') text = text.replace('\n', ' ')
text = text.replace('\r', '') text = text.replace('\r', '')
text = text.replace('(intransitive', '(intr.') text = text.replace('(intransitive', '(intr.')
text = text.replace('(transitive', '(trans.') text = text.replace('(transitive', '(trans.')
return text return text
def wiktionary(word): def wiktionary(word):
bytes = web.get(uri % web.quote(word)) bytes = web.get(uri % web.quote(word))
bytes = r_ul.sub('', bytes) bytes = r_ul.sub('', bytes)
mode = None mode = None
etymology = None etymology = None
definitions = {} definitions = {}
for line in bytes.splitlines(): for line in bytes.splitlines():
if 'id="Etymology"' in line: if 'id="Etymology"' in line:
mode = 'etymology' mode = 'etymology'
elif 'id="Noun"' in line: elif 'id="Noun"' in line:
mode = 'noun' mode = 'noun'
elif 'id="Verb"' in line: elif 'id="Verb"' in line:
mode = 'verb' mode = 'verb'
elif 'id="Adjective"' in line: elif 'id="Adjective"' in line:
mode = 'adjective' mode = 'adjective'
elif 'id="Adverb"' in line: elif 'id="Adverb"' in line:
mode = 'adverb' mode = 'adverb'
elif 'id="Interjection"' in line: elif 'id="Interjection"' in line:
mode = 'interjection' mode = 'interjection'
elif 'id="Particle"' in line: elif 'id="Particle"' in line:
mode = 'particle' mode = 'particle'
elif 'id="Preposition"' in line: elif 'id="Preposition"' in line:
mode = 'preposition' mode = 'preposition'
elif 'id="' in line: elif 'id="' in line:
mode = None mode = None
elif (mode == 'etmyology') and ('<p>' in line): elif (mode == 'etmyology') and ('<p>' in line):
etymology = text(line) etymology = text(line)
elif (mode is not None) and ('<li>' in line): elif (mode is not None) and ('<li>' in line):
definitions.setdefault(mode, []).append(text(line)) definitions.setdefault(mode, []).append(text(line))
if '<hr' in line: if '<hr' in line:
break break
return etymology, definitions return etymology, definitions
parts = ('preposition', 'particle', 'noun', 'verb', parts = ('preposition', 'particle', 'noun', 'verb',
'adjective', 'adverb', 'interjection') 'adjective', 'adverb', 'interjection')
def format(word, definitions, number=2): def format(word, definitions, number=2):
result = '%s' % word result = '%s' % word
for part in parts: for part in parts:
if part in definitions: if part in definitions:
defs = definitions[part][:number] defs = definitions[part][:number]
result += ' \u2014 ' + ('%s: ' % part) result += ' \u2014 ' + ('%s: ' % part)
n = ['%s. %s' % (i + 1, e.strip(' .')) for i, e in enumerate(defs)] n = ['%s. %s' % (i + 1, e.strip(' .')) for i, e in enumerate(defs)]
result += ', '.join(n) result += ', '.join(n)
return result.strip(' .,') return result.strip(' .,')
def w(phenny, input): def w(phenny, input):
if not input.group(2): if not input.group(2):
return phenny.reply("Nothing to define.") return phenny.reply("Nothing to define.")
word = input.group(2) word = input.group(2)
etymology, definitions = wiktionary(word) etymology, definitions = wiktionary(word)
if not definitions: if not definitions:
phenny.say("Couldn't get any definitions for %s." % word) phenny.say("Couldn't get any definitions for %s." % word)
return return
result = format(word, definitions) result = format(word, definitions)
if len(result) < 150: if len(result) < 150:
result = format(word, definitions, 3) result = format(word, definitions, 3)
if len(result) < 150: if len(result) < 150:
result = format(word, definitions, 5) result = format(word, definitions, 5)
if len(result) > 300: if len(result) > 300:
result = result[:295] + '[...]' result = result[:295] + '[...]'
phenny.say(result) phenny.say(result)
w.commands = ['w'] w.commands = ['w']
w.example = '.w bailiwick' w.example = '.w bailiwick'
def encarta(phenny, input): def encarta(phenny, input):
return phenny.reply('Microsoft removed Encarta, try .w instead!') return phenny.reply('Microsoft removed Encarta, try .w instead!')
encarta.commands = ['dict'] encarta.commands = ['dict']
if __name__ == '__main__': if __name__ == '__main__':
print(__doc__.strip()) print(__doc__.strip())