diff --git a/.gitignore b/.gitignore
index b6aaca6bb..be18f9e96 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@
*~
*.swp
__pycache__
+desktop.ini
diff --git a/bot.py b/bot.py
index 4925acaf8..bf8bf31db 100755
--- a/bot.py
+++ b/bot.py
@@ -189,6 +189,7 @@ def __new__(cls, text, origin, bytes, match, event, args):
s.args = args
s.admin = s.nick in self.config.admins
s.owner = s.nick == self.config.owner
+ s.chans = self.config.channels
return s
return CommandInput(text, origin, bytes, match, event, args)
@@ -231,7 +232,7 @@ def dispatch(self, origin, args):
if func.thread:
targs = (func, origin, phenny, input)
- t = threading.Thread(target=self.call, args=targs)
+ t = threading.Thread(target=self.call, args=targs, name=func.name)
t.start()
else: self.call(func, origin, phenny, input)
diff --git a/modules/8ball.py b/modules/8ball.py
index 9c14cb8d9..bb9e1a575 100644
--- a/modules/8ball.py
+++ b/modules/8ball.py
@@ -46,6 +46,8 @@ def eightball(phenny, input):
quote = random.choice(quotes)
phenny.reply(quote)
eightball.commands = ['8ball']
+eightball.name = '8ball'
+eightball.example = '.8ball is pie amazing?'
if __name__ == '__main__':
print(__doc__.strip())
diff --git a/modules/apertium_translate.py b/modules/apertium_translate.py
new file mode 100644
index 000000000..88ee8990d
--- /dev/null
+++ b/modules/apertium_translate.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python
+# coding=utf-8
+"""
+apertium_translate.py - Phenny Translation Module
+"""
+
+import re, urllib.request, json
+import web
+from tools import GrumbleError
+
+headers = [(
+ 'User-Agent', 'Mozilla/5.0' +
+ '(X11; U; Linux i686)' +
+ 'Gecko/20071127 Firefox/2.0.0.11'
+)]
+
+APIerrorData = 'Sorry, the apertium API did not return any data ☹'
+APIerrorHttp = 'Sorry, the apertium API gave HTTP error %s: %s ☹'
+
+def translate(translate_me, input_lang, output_lang='en'):
+ opener = urllib.request.build_opener()
+ opener.addheaders = headers
+
+ input_lang, output_lang = web.quote(input_lang), web.quote(output_lang)
+ translate_me = web.quote(translate_me)
+
+ response = opener.open('http://api.apertium.org/json/translate?q='+translate_me+'&langpair='+input_lang+"|"+output_lang).read()
+
+ responseArray = json.loads(response.decode('utf-8'))
+ if int(responseArray['responseStatus']) != 200:
+ raise GrumbleError(APIerrorHttp % (responseArray['responseStatus'], responseArray['responseDetails']))
+ if responseArray['responseData']['translatedText'] == []:
+ raise GrumbleError(APIerrorData)
+
+ translated_text = responseArray['responseData']['translatedText']
+ return translated_text
+
+
+def apertium_translate(phenny, input):
+ """Translates a phrase using the apertium API"""
+ line = input.group(2)
+ if not line:
+ raise GrumbleError("Need something to translate!")
+ #line = line.encode('utf-8')
+
+ pairs = []
+ guidelines = line.split('|')
+ if len(guidelines) > 1:
+ for guideline in guidelines[1:]:
+ #phenny.say(guideline)
+ pairs.append(guideline.strip().split('-'))
+ guidelines = guidelines[0]
+ #phenny.say(str(guidelines))
+ stuff = re.search('(.*) ([a-z]+-[a-z]+)', guidelines)
+ #phenny.say(str(stuff.groups()))
+ pairs.insert(0, stuff.group(2).split('-'))
+ translate_me = stuff.group(1)
+ #phenny.say(str(pairs))
+
+ #output_lang = line.split(' ')[-1]
+ #input_lang = line.split(' ')[-2]
+ #translate_me = ' '.join(line.split(' ')[:-2])
+
+ if (len(translate_me) > 350) and (not input.admin):
+ raise GrumbleError('Phrase must be under 350 characters.')
+
+ msg = translate_me
+ finalmsg = False
+ translated = ""
+ for (input_lang, output_lang) in pairs:
+ if input_lang == output_lang:
+ raise GrumbleError('Stop trying to confuse me! Pick different languages ;)')
+ msg = translate(msg, input_lang, output_lang)
+ if not msg:
+ raise GrumbleError('The %s to %s translation failed, sorry!' % (input_lang, output_lang))
+ msg = web.decode(msg) # msg.replace(''', "'")
+ this_translated = "(%s-%s) %s" % (input_lang, output_lang, msg)
+ translated = msg
+
+ #if not finalmsg:
+ # finalmsg = translated
+ #phenny.reply(finalmsg)
+ phenny.reply(translated)
+
+def apertium_listlangs(phenny, input):
+ """Lists languages available for translation from/to"""
+
+ opener = urllib.request.build_opener()
+ opener.addheaders = headers
+
+ response = opener.open('http://api.apertium.org/json/listPairs').read()
+
+ langs = json.loads(response.decode('utf-8'))
+ if int(langs['responseStatus']) != 200:
+ raise GrumbleError(APIerrorHttp % (langs['responseStatus'], langs['responseDetails']))
+ if langs['responseData'] == []:
+ raise GrumbleError(APIerrorData)
+
+ outlangs = []
+ #phenny.say(str(langs))
+ for pair in langs['responseData']:
+ if pair['sourceLanguage'] not in outlangs:
+ outlangs.append(pair['sourceLanguage'])
+ if pair['targetLanguage'] not in outlangs:
+ outlangs.append(pair['targetLanguage'])
+ #phenny.say(str(outlangs))
+
+ extra = "; more info: .listpairs lg"
+
+ first=True
+ allLangs = ""
+ for lang in outlangs:
+ if not first:
+ allLangs+=", "
+ else:
+ first=False
+ allLangs += lang
+ phenny.say(allLangs + extra)
+
+
+def apertium_listpairs(phenny, input):
+ """Lists translation pairs available to apertium translation"""
+ lang = input.group(2)
+
+ opener = urllib.request.build_opener()
+ opener.addheaders = headers
+
+ response = opener.open('http://api.apertium.org/json/listPairs').read()
+
+ langs = json.loads(response.decode('utf-8'))
+
+ langs = json.loads(response.decode('utf-8'))
+ if langs['responseData'] is []:
+ raise GrumbleError(APIerrorData)
+ if int(langs['responseStatus']) != 200:
+ raise GrumbleError(APIerrorHttp % (langs['responseStatus'], langs['responseDetails']))
+
+ if not lang:
+ allpairs=""
+ first=True
+ for pair in langs['responseData']:
+ if not first:
+ allpairs+=","
+ else:
+ first=False
+ allpairs+="%s→%s" % (pair['sourceLanguage'], pair['targetLanguage'])
+ phenny.say(allpairs)
+ else:
+ toLang = []
+ fromLang = []
+ for pair in langs['responseData']:
+ if pair['sourceLanguage'] == lang:
+ fromLang.append(pair['targetLanguage'])
+ if pair['targetLanguage'] == lang:
+ toLang.append(pair['sourceLanguage'])
+ first=True
+ froms = ""
+ for lg in fromLang:
+ if not first:
+ froms += ", "
+ else:
+ first = False
+ froms += lg
+ first = True
+ tos = ""
+ for lg in toLang:
+ if not first:
+ tos += ", "
+ else:
+ first = False
+ tos += lg
+ #finals = froms + (" → %s → " % lang) + tos
+ finals = tos + (" → %s → " % lang) + froms
+
+ phenny.say(finals)
+
+apertium_listpairs.name = 'listpairs'
+apertium_listpairs.commands = ['listpairs']
+apertium_listpairs.example = '.listpairs ca'
+apertium_listpairs.priority = 'low'
+
+apertium_listlangs.name = 'listlangs'
+apertium_listlangs.commands = ['listlangs']
+apertium_listlangs.example = '.listlangs'
+apertium_listlangs.priority = 'low'
+
+apertium_translate.name = 't'
+apertium_translate.commands = ['t']
+apertium_translate.example = '.t I like pie en-es'
+apertium_translate.priority = 'high'
\ No newline at end of file
diff --git a/modules/away.py b/modules/away.py
new file mode 100644
index 000000000..ec3fa584e
--- /dev/null
+++ b/modules/away.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+"""
+away.py - Phenny's record or who's away/present module
+"""
+
+import os, re, time, random
+import web
+
+statuses = {"alan": "boom bitchezzzz"}
+
+def whereis(phenny, input):
+ """Tells you nick's current status."""
+ whereis_nick = input.split(" ")[1]
+ print(input + " --> " + whereis_nick)
+ if (whereis_nick in list(statuses.keys())):
+ phenny.reply(whereis_nick + " said: " + statuses[whereis_nick])
+ else:
+ phenny.reply("Sorry, " + whereis_nick + " seems to be AWOL...")
+whereis.commands = ["whereis"]
+whereis.priority = 'low'
+whereis.example = '.whereis sushain'
+whereis.thread = False
+
+def away(phenny, input):
+ """Set your status to being away."""
+ nick = input.nick
+ if input.count(" ") == 0:
+ statuses[nick] = "I'm away right now"
+ else:
+ message = str(" ".join(input.split(" ")[1:]))
+ statuses[nick] = message
+away.commands = ['away']
+away.example = '.away eating pie'
+away.priority = 'low'
+away.thread = False
+
+def back(phenny, input):
+ """Set your status to being available."""
+ nick = input.nick
+ if input.count(" ") == 0:
+ statuses[nick] = "I'm around at the minute"
+ else:
+ message = str(" ".join(input.split(" ")[1:]))
+ statuses[nick] = message
+back.commands = ['back']
+back.example = '.back'
+back.priority = 'low'
+back.thread = False
+
+
+if __name__ == '__main__':
+ print(__doc__.strip())
diff --git a/modules/botfun.py b/modules/botfun.py
index a06c1f7ce..10ab18fb7 100644
--- a/modules/botfun.py
+++ b/modules/botfun.py
@@ -17,6 +17,7 @@ def botfight(phenny, input):
phenny.do(response % otherbot)
botfight.commands = ['botfight']
botfight.priority = 'low'
+botfight.example = '.botfight'
def bothug(phenny, input):
""".bothug - Hug the other bot in the channel."""
@@ -24,6 +25,7 @@ def bothug(phenny, input):
phenny.do("hugs %s" % otherbot)
bothug.commands = ['bothug']
bothug.priority = 'low'
+bothug.example = '.bothug'
if __name__ == '__main__':
print(__doc__.strip())
diff --git a/modules/botsnack.py b/modules/botsnack.py
index 485eabeb3..632f49a2a 100644
--- a/modules/botsnack.py
+++ b/modules/botsnack.py
@@ -106,5 +106,14 @@ def botsnack(phenny, input):
botsnack.last_tick = time.time()
botsnack.coolingdown = False
+def botslap(phenny, input):
+ """tell me I'm being a bad bot"""
+ messages = ["hides in corner", "eats own hat", "apologises", "stares at feet", "points at zfe", "didn't do anything", "doesn't deserve this", "hates you guys", "did it on purpose", "is an inconsistent sketchy little bot", "scurries off"]
+ phenny.do(random.choice(messages))
+
+botslap.commands = ['botslap', 'botsmack']
+botslap.rule = r'''^(?:(?:$nickname[ ,:]?)\s+(you suck|I hate you|you ruin everything|you spoil all [themyour]*fun|bad|wtf|lame| [youare']*?stupid|silly)\s*$)|(?:.*?(you suck|I hate you|you ruin everything|you spoil all [themyour]*fun|bad|wtf|lame|[youare']*?stupid|silly)(?:[, ]? $nickname))'''
+botsnack.priority = 'low'
+
if __name__ == '__main__':
print(__doc__.strip())
diff --git a/modules/calc.py b/modules/calc.py
index 0b715a8ad..ffbc32fa2 100644
--- a/modules/calc.py
+++ b/modules/calc.py
@@ -47,6 +47,16 @@ def c(phenny, input):
c.commands = ['c']
c.example = '.c 5 + 3'
+def py(phenny, input):
+ """evaluates a python2 expression via a remote sandbox"""
+ query = input.group(2).encode('utf-8')
+ uri = 'http://tumbolia.appspot.com/py/'
+ answer = web.get(uri + web.quote(query))
+ if answer:
+ phenny.say(answer)
+ else: phenny.reply('Sorry, no result.')
+py.commands = ['py']
+py.example = '.py if not False: print "hello world!"'
def wa(phenny, input):
if not input.group(2):
@@ -68,7 +78,7 @@ def wa(phenny, input):
phenny.say(answer)
wa.commands = ['wa']
-
+wa.example = '.wa answer to life'
if __name__ == '__main__':
print(__doc__.strip())
diff --git a/modules/clock.py b/modules/clock.py
index ad09aefac..d7597637f 100644
--- a/modules/clock.py
+++ b/modules/clock.py
@@ -32,7 +32,7 @@
'EDT': -4, 'UT': 0, 'PST': -8, 'MEZ': 1, 'BST': 1,
'ACS': 9.5, 'ATL': -4, 'ALA': -9, 'HAW': -10, 'AKDT': -8,
'AKST': -9,
- 'BDST': 2}
+ 'BDST': 2, 'KGT': 6}
TZ1 = {
'NDT': -2.5,
@@ -200,40 +200,39 @@
r_local = re.compile(r'\([a-z]+_[A-Z]+\)')
-@deprecated
-def f_time(self, origin, match, args):
+def f_time(phenny, input):
"""Returns the current time."""
- tz = match.group(2) or 'GMT'
+ tz = input.group(2) or 'GMT'
# Personal time zones, because they're rad
- if hasattr(self.config, 'timezones'):
- People = self.config.timezones
+ if hasattr(phenny.config, 'timezones'):
+ People = phenny.config.timezones
else: People = {}
if tz in People:
tz = People[tz]
- elif (not match.group(2)) and origin.nick in People:
- tz = People[origin.nick]
+ elif (not input.group(2)) and input.nick in People:
+ tz = People[input.nick]
TZ = tz.upper()
if len(tz) > 30: return
if (TZ == 'UTC') or (TZ == 'Z'):
msg = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
- self.msg(origin.sender, msg)
+ phenny.reply(msg)
elif r_local.match(tz): # thanks to Mark Shoulsdon (clsn)
locale.setlocale(locale.LC_TIME, (tz[1:-1], 'UTF-8'))
msg = time.strftime("%A, %d %B %Y %H:%M:%SZ", time.gmtime())
- self.msg(origin.sender, msg)
+ phenny.reply(msg)
elif TZ in TimeZones:
offset = TimeZones[TZ] * 3600
timenow = time.gmtime(time.time() + offset)
msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(TZ), timenow)
- self.msg(origin.sender, msg)
+ phenny.reply(msg)
elif tz and tz[0] in ('+', '-') and 4 <= len(tz) <= 6:
timenow = time.gmtime(time.time() + (int(tz[:3]) * 3600))
msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(tz), timenow)
- self.msg(origin.sender, msg)
+ phenny.reply(msg)
else:
try: t = float(tz)
except ValueError:
@@ -242,17 +241,17 @@ def f_time(self, origin, match, args):
if r_tz.match(tz) and os.path.isfile('/usr/share/zoneinfo/' + tz):
cmd, PIPE = 'TZ=%s date' % tz, subprocess.PIPE
proc = subprocess.Popen(cmd, shell=True, stdout=PIPE)
- self.msg(origin.sender, proc.communicate()[0])
+ phenny.reply(proc.communicate()[0])
else:
error = "Sorry, I don't know about the '%s' timezone." % tz
- self.msg(origin.sender, origin.nick + ': ' + error)
+ phenny.reply(error)
else:
timenow = time.gmtime(time.time() + (t * 3600))
msg = time.strftime("%a, %d %b %Y %H:%M:%S " + str(tz), timenow)
- self.msg(origin.sender, msg)
-f_time.commands = ['t']
-f_time.name = 't'
-f_time.example = '.t UTC'
+ phenny.reply(msg)
+f_time.name = 'time'
+f_time.commands = ['time']
+f_time.example = '.time UTC'
def beats(phenny, input):
"""Shows the internet time in Swatch beats."""
diff --git a/modules/eleda.py b/modules/eleda.py
new file mode 100644
index 000000000..d12fb44f8
--- /dev/null
+++ b/modules/eleda.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python
+
+"""
+eleda.py - Begiak Eleda Module
+Any questions can go to Qasim Iqbal (nick: Qasim) (email: me@qas.im)
+"""
+
+import http.client
+import re, json
+import sys
+#from apertium_translate import translate
+import urllib.request, urllib.parse, urllib.error
+import web
+from tools import GrumbleError
+
+follows = []
+
+headers = {
+ 'User-Agent': 'Mozilla/5.0' + '(X11; U; Linux i686)' + 'Gecko/20071127 Firefox/2.0.0.11'
+}
+
+APIerrorData = 'Sorry, the apertium API did not return any data ☹'
+APIerrorHttp = 'Sorry, the apertium API gave HTTP error %s: %s ☹'
+
+def translate(translate_me, input_lang, output_lang='en'):
+ opener = urllib.request.build_opener()
+ opener.addheaders = headers
+
+ input_lang, output_lang = web.quote(input_lang), web.quote(output_lang)
+ translate_me = web.quote(translate_me)
+
+ response = opener.open('http://api.apertium.org/json/translate?q='+translate_me+'&langpair='+input_lang+"|"+output_lang).read()
+
+ responseArray = json.loads(response.decode('utf-8'))
+ if int(responseArray['responseStatus']) != 200:
+ raise GrumbleError(APIerrorHttp % (responseArray['responseStatus'], responseArray['responseDetails']))
+ if responseArray['responseData']['translatedText'] == []:
+ raise GrumbleError(APIerrorData)
+
+ translated_text = responseArray['responseData']['translatedText']
+ return translated_text
+
+class Eleda(object):
+ sender = ""
+ nick = ""
+ dir = []
+ def __init__(self, sender, nick, dir):
+ self.sender = sender
+ self.nick = nick
+ self.dir = dir
+
+def get_page(domain, url, encoding='utf-8'): #get the HTML of a webpage.
+ conn = http.client.HTTPConnection(domain, 80, timeout=60)
+ conn.request("GET", url, headers=headers)
+ res = conn.getresponse()
+ return res.read().decode(encoding)
+
+def follow(phenny, input): #follow a user
+ """Follow someone and translate as they speak."""
+ global follows
+
+ if input.groups()[1] != None:
+ data = input.group(2).split(' ')
+ nick = data[0]
+
+ if nick.lower() == phenny.config.nick.lower():
+ phenny.reply(phenny.config.nick.upper() + " DOES NOT LIKE TO BE FOLLOWED.")
+ return
+
+ try:
+ dir = data[1].split('-')
+ dir[1] = dir[1]
+ except:
+ phenny.reply("Need language pair!")
+ return
+
+ pairs = get_page('api.apertium.org', '/json/listPairs')
+ if '{"sourceLanguage":"'+dir[0]+'","targetLanguage":"'+dir[1]+'"}' not in pairs:
+ phenny.reply("That language pair does not exist!")
+ return
+
+ if len(data) in [2,3]:
+ sender = input.nick
+ if len(data) == 3 and input.admin == True:
+ #only accept follower paramter if it exists and the nick is admin
+ sender = data[2]
+ else:
+ phenny.reply("Unexpected error.")
+ return
+
+ for i in follows:
+ if i.nick == nick and i.dir == dir and i.sender == sender:
+ phenny.say(sender + " is already following " + nick + " with " + '-'.join(dir) + '.')
+ return
+
+ follows.append(Eleda(sender, nick, dir))
+ phenny.reply(sender + " now following " + nick + " (" + '-'.join(dir) + ").")
+ else:
+ phenny.reply("Need nick and language pair!")
+
+def unfollow(phenny, input): #unfollow a user
+ """Stop following someone."""
+ global follows
+
+ following = False
+ for i in range(len(follows)):
+ if follows[i].nick == input.groups()[1] and follows[i].sender == input.nick:
+ #if this person is indeed being followed (and is indeed the creator of the follow)
+ follows[i] = Eleda('', '', ['', ''])
+ following = True
+ if following == True:
+ phenny.reply(input.groups()[1] + " is no longer being followed.")
+ else:
+ phenny.reply("Sorry, you aren't following that user!")
+
+def following(phenny, input): #list followed users
+ """List people currently being followed."""
+ text = []
+ for i in follows:
+ if i.nick != '':
+ #populate list with following list
+ text.append(i.nick + " (" + '-'.join(i.dir) + ") by " + i.sender)
+ if len(text) < 1:
+ phenny.reply("No one is being followed at the moment.")
+ else:
+ phenny.say('Users currently being followed: ' + ', '.join(text) + '. (Translations are private)')
+
+def test(phenny, input): #filter through each message in the channel
+ if '#' in input.sender:
+ if input.groups()[0][0] == '.' or phenny.config.nick.lower() in input.groups()[0].split(' ')[0].lower():
+ #do not translate if it is a begiak function
+ return
+
+ for i in follows:
+ if i.nick != '':
+ if i.nick == input.nick:
+ #this user is being followed, translate them
+ direction = '-'.join(i.dir)
+ translation = translate(input.group(0), i.dir[0], i.dir[1])
+ translation = translation.replace('*', '')
+ if translation != input.group(0):
+ #don't bother sending a notice if the input is the same as the output
+ phenny.write(['NOTICE', i.sender], i.nick + ' (' + '-'.join(i.dir) + '): ' + translation)
+
+follow.commands = ['follow']
+follow.example = '.follow Qasim en-es'
+unfollow.commands = ['unfollow']
+unfollow.example = '.unfollow Qasim'
+following.commands = ['following']
+following.example = '.following'
+test.rule = r'(.*)'
\ No newline at end of file
diff --git a/modules/ethnologue.py b/modules/ethnologue.py
new file mode 100644
index 000000000..da8d0c354
--- /dev/null
+++ b/modules/ethnologue.py
@@ -0,0 +1,139 @@
+#!/usr/bin/python3
+"""
+ethnologue.py - Ethnologue.com language lookup
+author: mattr555
+"""
+
+#from modules.iso639 import ISOcodes
+from lxml import html
+from string import ascii_lowercase
+import os
+import web
+
+def shorten_num(n):
+ if n < 1000:
+ return '{:,}'.format(n)
+ elif n < 1000000:
+ return '{}K'.format(str(round(n/1000, 1)).rstrip('0').rstrip('.'))
+ elif n < 1000000000:
+ return '{}M'.format(str(round(n/1000000, 1)).rstrip('0').rstrip('.'))
+
+def scrape_ethnologue_codes():
+ data = {}
+ base_url = 'http://www.ethnologue.com/browse/codes/'
+ for letter in ascii_lowercase:
+ resp = web.get(base_url + letter)
+ h = html.document_fromstring(resp)
+ for e in h.find_class('views-field-field-iso-639-3'):
+ code = e.find('div/a').text
+ name = e.find('div/a').attrib['title']
+ data[code] = name
+ return data
+
+def filename(phenny):
+ name = phenny.nick + '-' + phenny.config.host + '.ethnologue.db'
+ return os.path.join(os.path.expanduser('~/.phenny'), name)
+
+def write_ethnologue_codes(phenny, raw=None):
+ if raw is None or raw.admin:
+ file = filename(phenny)
+ data = scrape_ethnologue_codes()
+ with open(file, 'w') as f:
+ for k, v in data.items():
+ f.write('{}${}\n'.format(k, v))
+ phenny.ethno_data = data
+ print('Ethnologue iso-639 code fetch successful')
+ if raw:
+ phenny.say('Ethnologue iso-639 code fetch successful')
+ else:
+ phenny.say('Only admins can execute that command!')
+
+write_ethnologue_codes.name = 'write_ethnologue_codes'
+write_ethnologue_codes.commands = ['write-ethno-codes']
+write_ethnologue_codes.priority = 'low'
+
+def read_ethnologue_codes(phenny, raw=None):
+ file = filename(phenny)
+ data = {}
+ with open(file, 'r') as f:
+ for line in f.readlines():
+ code, name = line.split('$')
+ data[code] = name
+ phenny.ethno_data = data
+ print('Ethnologue iso-639 database read successful')
+
+def parse_num_speakers(s):
+ hits = []
+ for i in s.split(' '):
+ if len(i) <= 3 or ',' in i:
+ if i.replace(',', '').replace('.', '').isdigit():
+ hits.append(int(i.replace(',', '').replace('.', '')))
+ if 'ethnic population' in s.lower():
+ return shorten_num(hits[0])
+ return shorten_num(hits[-1])
+
+def ethnologue(phenny, input):
+ """.ethnologue - Reports when
', '.*?
')
@@ -22,6 +23,7 @@
r_context = re.compile(r'{{context\|(.+?)}}')
r_template1 = re.compile(r'{{.+?\|(.+?)}}')
r_template2 = re.compile(r'{{(.+?)}}')
+r_sqrbracket = re.compile(r'\[.+?\]')
def text(html):
text = r_li.sub('', html).strip()
@@ -31,9 +33,11 @@ def text(html):
text = r_context.sub(r'\1:', text)
text = r_template1.sub(r'\1:', text)
text = r_template2.sub(r'\1:', text)
+ text = text.replace("en|", '')
+ text = r_sqrbracket.sub('', text)
return text
-def wiktionary(word):
+def wiktionary(phenny, word):
bytes = web.get(wikiapi.format(web.quote(word)))
pages = json.loads(bytes)
pages = pages['query']['pages']
@@ -50,31 +54,73 @@ def wiktionary(word):
for line in result.splitlines():
if line == '===Etymology===':
mode = 'etymology'
- elif 'Noun' in line:
+ elif '=Noun=' in line:
mode = 'noun'
- elif 'Verb' in line:
+ elif '=Verb=' in line:
mode = 'verb'
- elif 'Adjective' in line:
+ elif '=Adjective=' in line:
mode = 'adjective'
- elif 'Adverb' in line:
+ elif '=Adverb=' in line:
mode = 'adverb'
- elif 'Interjection' in line:
+ elif '=Interjection=' in line:
mode = 'interjection'
- elif 'Particle' in line:
+ elif '=Particle=' in line:
mode = 'particle'
- elif 'Preposition' in line:
+ elif '=Preposition=' in line:
mode = 'preposition'
- elif len(line) == 0:
- mode = None
-
elif mode == 'etymology':
etymology = text(line)
- elif mode is not None and '#' in line:
+
+ if mode is not None and "#" in line and "#:" not in line:
definitions.setdefault(mode, []).append(text(line))
if '====Synonyms====' in line:
break
+
return etymology, definitions
+
+def get_between(strSource, strStart, strEnd): #get first string between 2 other strings
+ try:
+ parse = strSource.split(strStart, 2)[1]
+ parse = parse[:parse.find(strEnd)]
+ except:
+ parse = None
+ return parse
+
+def get_between_all(strSource, strStart, strEnd): #get all the strings between the 2 strings
+ list = []
+ start = 0
+ word = get_between(strSource, strStart, strEnd)
+ while (word != None):
+ list.append(word)
+ start = strSource.find("".join((strStart, word, strEnd)))
+ strSource = strSource[start+len("".join((strStart, word, strEnd))):]
+ word = get_between(strSource, strStart, strEnd)
+ return list
+
+def etymology(phenny, word):
+ ety_value = None
+ try:
+ opener = urllib.request.build_opener()
+ opener.addheaders = [('User-agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17')]
+ bytes = opener.open(uri.format(web.quote(word)))
+ html = bytes.read().decode('utf-8')
+ ety_value = get_between_all(html, '">Etymology