Initial Commit 2
parent
be4ab9b606
commit
d81faf1714
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
admin.py - Phenny Admin Module
|
||||
Copyright 2008-9, Sean B. Palmer, inamidst.com
|
||||
Licensed under the Eiffel Forum License 2.
|
||||
|
||||
http://inamidst.com/phenny/
|
||||
"""
|
||||
|
||||
def join(phenny, input):
|
||||
"""Join the specified channel. This is an admin-only command."""
|
||||
# Can only be done in privmsg by an admin
|
||||
if input.sender.startswith('#'): return
|
||||
if input.admin:
|
||||
channel, key = input.group(1), input.group(2)
|
||||
if not key:
|
||||
phenny.write(['JOIN'], channel)
|
||||
else: phenny.write(['JOIN', channel, key])
|
||||
join.rule = r'\.join (#\S+)(?: *(\S+))?'
|
||||
#join.commands = ['join']
|
||||
join.priority = 'low'
|
||||
join.example = '.join #example or .join #example key'
|
||||
|
||||
def part(phenny, input):
|
||||
"""Part the specified channel. This is an admin-only command."""
|
||||
# Can only be done in privmsg by an admin
|
||||
if input.sender.startswith('#'): return
|
||||
if input.admin:
|
||||
phenny.write(['PART'], input.group(2))
|
||||
part.commands = ['part']
|
||||
part.priority = 'low'
|
||||
part.example = '.part #example'
|
||||
|
||||
def quit(phenny, input):
|
||||
"""Quit from the server. This is an owner-only command."""
|
||||
# Can only be done in privmsg by the owner
|
||||
if input.sender.startswith('#'): return
|
||||
if input.owner:
|
||||
phenny.write(['QUIT'])
|
||||
__import__('os')._exit(0)
|
||||
quit.commands = ['quit']
|
||||
quit.priority = 'low'
|
||||
|
||||
def msg(phenny, input):
|
||||
# Can only be done in privmsg by an admin
|
||||
if input.sender.startswith('#'): return
|
||||
a, b = input.group(2), input.group(3)
|
||||
if (not a) or (not b): return
|
||||
if input.admin:
|
||||
phenny.msg(a, b)
|
||||
msg.rule = (['msg'], r'(#?\S+) (.+)')
|
||||
msg.priority = 'low'
|
||||
|
||||
def me(phenny, input):
|
||||
# Can only be done in privmsg by an admin
|
||||
if input.sender.startswith('#'): return
|
||||
if input.admin:
|
||||
msg = '\x01ACTION %s\x01' % input.group(3)
|
||||
phenny.msg(input.group(2) or input.sender, msg)
|
||||
me.rule = (['me'], r'(#?\S+) (.+)')
|
||||
me.priority = 'low'
|
||||
|
||||
if __name__ == '__main__':
|
||||
print __doc__.strip()
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env python
|
||||
# coding=utf-8
|
||||
"""
|
||||
calc.py - Phenny Calculator Module
|
||||
Copyright 2008, Sean B. Palmer, inamidst.com
|
||||
Modified by Sfan5 2012
|
||||
Licensed under the Eiffel Forum License 2.
|
||||
|
||||
http://inamidst.com/phenny/
|
||||
"""
|
||||
|
||||
import re
|
||||
import web
|
||||
|
||||
r_result = re.compile(r'(?i)<A NAME=results>(.*?)</A>')
|
||||
r_tag = re.compile(r'<\S+.*?>')
|
||||
|
||||
subs = [
|
||||
(' in ', ' -> '),
|
||||
(' over ', ' / '),
|
||||
(u'£', 'GBP '),
|
||||
(u'€', 'EUR '),
|
||||
('\$', 'USD '),
|
||||
(r'\bKB\b', 'kilobytes'),
|
||||
(r'\bMB\b', 'megabytes'),
|
||||
(r'\bGB\b', 'kilobytes'),
|
||||
('kbps', '(kilobits / second)'),
|
||||
('mbps', '(megabits / second)')
|
||||
]
|
||||
|
||||
def c(phenny, input):
|
||||
"""Google calculator."""
|
||||
if not input.group(2):
|
||||
return phenny.reply("Nothing to calculate.")
|
||||
q = input.group(2).encode('utf-8')
|
||||
q = q.replace('\xcf\x95', 'phi') # utf-8 U+03D5
|
||||
q = q.replace('\xcf\x80', 'pi') # utf-8 U+03C0
|
||||
print("[LOG]: %s calculated '%s'" % (input.nick,q))
|
||||
uri = 'http://www.google.com/ig/calculator?q='
|
||||
bytes = web.get(uri + web.urllib.quote(q))
|
||||
parts = bytes.split('",')
|
||||
answer = [p for p in parts if p.startswith('rhs: "')][0][6:]
|
||||
if answer:
|
||||
answer = answer.decode('unicode-escape')
|
||||
answer = ''.join(chr(ord(c)) for c in answer)
|
||||
answer = answer.decode('utf-8')
|
||||
answer = answer.replace(u'\xc2\xa0', ',')
|
||||
answer = answer.replace('<sup>', '^(')
|
||||
answer = answer.replace('</sup>', ')')
|
||||
answer = web.decode(answer)
|
||||
phenny.say(answer)
|
||||
else: phenny.say('Sorry, no result.')
|
||||
c.commands = ['c']
|
||||
c.example = '.c 5 + 3'
|
||||
|
||||
if __name__ == '__main__':
|
||||
print __doc__.strip()
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
ping.py - Phenny Ping Module
|
||||
Author: Sean B. Palmer, inamidst.com
|
||||
About: http://inamidst.com/phenny/
|
||||
"""
|
||||
|
||||
import random
|
||||
|
||||
def hello(phenny, input):
|
||||
greeting = random.choice(('Hi', 'Hey', 'Hello'))
|
||||
punctuation = random.choice(('', '!'))
|
||||
phenny.say(greeting + ' ' + input.nick + punctuation)
|
||||
hello.rule = r'(?i)(hi|hello|hey) $nickname[ \t]*$'
|
||||
|
||||
def interjection(phenny, input):
|
||||
phenny.say(input.nick + '!')
|
||||
interjection.rule = r'$nickname!'
|
||||
interjection.priority = 'high'
|
||||
interjection.thread = False
|
||||
|
||||
if __name__ == '__main__':
|
||||
print __doc__.strip()
|
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
reload.py - Phenny Module Reloader Module
|
||||
Copyright 2008, Sean B. Palmer, inamidst.com
|
||||
Licensed under the Eiffel Forum License 2.
|
||||
|
||||
http://inamidst.com/phenny/
|
||||
"""
|
||||
|
||||
import sys, os.path, time, imp
|
||||
import irc
|
||||
|
||||
def f_reload(phenny, input):
|
||||
"""Reloads a module, for use by admins only."""
|
||||
if not input.admin: return
|
||||
|
||||
name = input.group(2)
|
||||
if name == phenny.config.owner:
|
||||
return phenny.reply('What?')
|
||||
|
||||
if (not name) or (name == '*'):
|
||||
phenny.variables = None
|
||||
phenny.commands = None
|
||||
phenny.setup()
|
||||
return phenny.reply('done')
|
||||
|
||||
if not sys.modules.has_key(name):
|
||||
return phenny.reply('%s: no such module!' % name)
|
||||
|
||||
# Thanks to moot for prodding me on this
|
||||
path = sys.modules[name].__file__
|
||||
if path.endswith('.pyc') or path.endswith('.pyo'):
|
||||
path = path[:-1]
|
||||
if not os.path.isfile(path):
|
||||
return phenny.reply('Found %s, but not the source file' % name)
|
||||
|
||||
module = imp.load_source(name, path)
|
||||
sys.modules[name] = module
|
||||
if hasattr(module, 'setup'):
|
||||
module.setup(phenny)
|
||||
|
||||
mtime = os.path.getmtime(module.__file__)
|
||||
modified = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(mtime))
|
||||
|
||||
phenny.register(vars(module))
|
||||
phenny.bind_commands()
|
||||
|
||||
phenny.reply('%r (version: %s)' % (module, modified))
|
||||
f_reload.name = 'reload'
|
||||
f_reload.rule = ('$nick', ['reload'], r'(\S+)?')
|
||||
f_reload.priority = 'low'
|
||||
f_reload.thread = False
|
||||
|
||||
if __name__ == '__main__':
|
||||
print __doc__.strip()
|
|
@ -0,0 +1,86 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
rssnotify.py - Phenny RssNotify Module
|
||||
Copyright 2012, Sfan5
|
||||
"""
|
||||
import feedparser, time, urllib # sudo easy_install feedparser
|
||||
rssnotify = {}
|
||||
|
||||
def get_arrayindex(array,val):
|
||||
for i in range(0,len(array)):
|
||||
if array[i] == val:
|
||||
return i
|
||||
return -1
|
||||
|
||||
rssnotify["last_updated_feeds"] = {}
|
||||
|
||||
rssnotify["last_update"] = time.time()
|
||||
rssnotify["dont_print_first_message"] = False
|
||||
rssnotify["update_cooldown"] = 30 # in seconds
|
||||
rssnotify["say_to_channel"] = '#minetest'
|
||||
rssnotify["show_commit_link"] = True
|
||||
rssnotify["use_git.io"] = True
|
||||
|
||||
|
||||
|
||||
def rsscheck(phenny, input):
|
||||
t = time.time()
|
||||
if rssnotify["last_update"] > t-rssnotify["update_cooldown"]:
|
||||
return
|
||||
rssnotify["last_update"] = t
|
||||
print("[LOG]: Checking RSS Feeds...")
|
||||
start = time.time()
|
||||
feeds = [
|
||||
'https://github.com/celeron55/minetest/commits/master.atom',
|
||||
'https://github.com/celeron55/minetest_game/commits/master.atom'
|
||||
]
|
||||
for url in feeds:
|
||||
options = {
|
||||
'agent': 'Mozilla/5.0 (MinetestBot)',
|
||||
'referrer': 'http://minetest.net'
|
||||
}
|
||||
feed = feedparser.parse(url, **options)
|
||||
if len(feed.entries) == 0: continue
|
||||
last_entry = feed.entries[0]
|
||||
feednum = get_arrayindex(feeds,url)
|
||||
if not feednum in rssnotify["last_updated_feeds"].keys():
|
||||
rssnotify["last_updated_feeds"][feednum] = -1
|
||||
if rssnotify["last_updated_feeds"][feednum] != last_entry.updated:
|
||||
rssnotify["last_updated_feeds"][feednum] = last_entry.updated
|
||||
commiter = last_entry.authors[0].href.replace('https://github.com/',"")
|
||||
commiter_realname = last_entry.authors[0].name
|
||||
reponame = url.replace("https://github.com/","").replace("/commits/master.atom","")
|
||||
commit_hash = last_entry.links[0].href.replace("https://github.com/" + reponame + "/commit/","")[:10]
|
||||
commit_time = last_entry.updated
|
||||
print("[LOG]: Found RSS Update for URL '%s'" % (url))
|
||||
if rssnotify["dont_print_first_message"]:
|
||||
continue # Don't print first Message
|
||||
if rssnotify["show_commit_link"]:
|
||||
if rssnotify["use_git.io"]:
|
||||
params = urllib.urlencode({'url' : last_entry.link}) # git.io only works with *.github.com links
|
||||
u = urllib.urlopen("http://git.io/create", params)
|
||||
commit_link = "http://git.io/" + u.read()
|
||||
else:
|
||||
commit_link = last_entry.link
|
||||
else:
|
||||
commit_link = ""
|
||||
|
||||
|
||||
if commiter.lower() != commiter_realname.lower():
|
||||
#phenny.say("GIT: %s (%s) commited to %s: %s %s %s" % (commiter,commiter_realname,reponame,last_entry.title,commit_hash,commit_time))
|
||||
phenny.write(['PRIVMSG',rssnotify["say_to_channel"]],"GIT: %s (%s) commited to %s: %s %s %s %s" % (commiter, commiter_realname, reponame, last_entry.title, commit_hash, commit_time, commit_link))
|
||||
else:
|
||||
#phenny.say("GIT: %s commited to %s: %s %s %s" % (commiter,reponame,last_entry.title,commit_hash,commit_time))
|
||||
phenny.write(['PRIVMSG',rssnotify["say_to_channel"]],"GIT: %s commited to %s: %s %s %s %s" % (commiter, reponame, last_entry.title, commit_hash, commit_time, commit_link))
|
||||
end = time.time()
|
||||
if rssnotify["dont_print_first_message"]:
|
||||
rssnotify["dont_print_first_message"] = False
|
||||
print("[LOG]: Checked " + str(len(feeds)) + " RSS Feeds in %0.3f seconds" % (end-start))
|
||||
|
||||
rsscheck.priority = 'high'
|
||||
rsscheck.rule = r'.*'
|
||||
rsscheck.event = '*'
|
||||
rsscheck.thread = True
|
||||
|
||||
if __name__ == '__main__':
|
||||
print __doc__.strip()
|
|
@ -0,0 +1,121 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
search.py - Phenny Web Search Module
|
||||
Copyright 2008-9, Sean B. Palmer, inamidst.com
|
||||
Modified by Sfan5 2012
|
||||
Licensed under the Eiffel Forum License 2.
|
||||
|
||||
http://inamidst.com/phenny/
|
||||
"""
|
||||
|
||||
import web, re
|
||||
|
||||
search_badwords = ["porn","p0rn","pr0n","pron","redtube","sex","pussy","hot","weed","smoking","drug","penis","vagina"] #Thank KikaRz and LandMine for this
|
||||
search_badnicks = ["KikaRz","LandMine","LandMineMT"]
|
||||
|
||||
class Grab(web.urllib.URLopener):
|
||||
def __init__(self, *args):
|
||||
self.version = 'Mozilla/5.0 (MinetestBot)'
|
||||
web.urllib.URLopener.__init__(self, *args)
|
||||
self.addheader('Referer', 'http://minetest.net')
|
||||
def http_error_default(self, url, fp, errcode, errmsg, headers):
|
||||
return web.urllib.addinfourl(fp, [headers, errcode], "http:" + url)
|
||||
|
||||
def google_ajax(query):
|
||||
"""Search using AjaxSearch, and return its JSON."""
|
||||
if isinstance(query, unicode):
|
||||
query = query.encode('utf-8')
|
||||
uri = 'http://ajax.googleapis.com/ajax/services/search/web'
|
||||
args = '?v=1.0&safe=off&q=' + web.urllib.quote(query)
|
||||
handler = web.urllib._urlopener
|
||||
web.urllib._urlopener = Grab()
|
||||
bytes = web.get(uri + args)
|
||||
web.urllib._urlopener = handler
|
||||
return web.json(bytes)
|
||||
|
||||
def google_search(query):
|
||||
results = google_ajax(query)
|
||||
try: return results['responseData']['results'][0]['unescapedUrl']
|
||||
except IndexError: return None
|
||||
except TypeError:
|
||||
print results
|
||||
return False
|
||||
|
||||
def google_count(query):
|
||||
results = google_ajax(query)
|
||||
if not results.has_key('responseData'): return '0'
|
||||
if not results['responseData'].has_key('cursor'): return '0'
|
||||
if not results['responseData']['cursor'].has_key('estimatedResultCount'):
|
||||
return '0'
|
||||
return results['responseData']['cursor']['estimatedResultCount']
|
||||
|
||||
def formatnumber(n):
|
||||
"""Format a number with beautiful commas."""
|
||||
parts = list(str(n))
|
||||
for i in range((len(parts) - 3), 0, -3):
|
||||
parts.insert(i, ',')
|
||||
return ''.join(parts)
|
||||
|
||||
|
||||
def g(phenny, input):
|
||||
"""Queries Google for the specified input."""
|
||||
query = input.group(2)
|
||||
if not query:
|
||||
return phenny.reply('.g what?')
|
||||
for bw in search_badwords:
|
||||
if bw in query:
|
||||
print("[LOG]: %s queried Google Result for '%s' | DENIED: Badword" % (input.nick,query))
|
||||
return phenny.reply("Search term contains badword")
|
||||
for bn in search_badnicks:
|
||||
if bn in input.nick:
|
||||
print("[LOG]: %s queried Google Result for '%s' | DENIED: Badnick" % (input.nick,query))
|
||||
return phenny.reply("Nope!")
|
||||
query = query.encode('utf-8')
|
||||
print("[LOG]: %s queried Google Result for '%s'" % (input.nick,query))
|
||||
uri = google_search(query)
|
||||
if uri:
|
||||
phenny.reply(uri)
|
||||
if not hasattr(phenny.bot, 'last_seen_uri'):
|
||||
phenny.bot.last_seen_uri = {}
|
||||
phenny.bot.last_seen_uri[input.sender] = uri
|
||||
elif uri is False: phenny.reply("Problem getting data from Google.")
|
||||
else: phenny.reply("No results found for '%s'." % query)
|
||||
g.commands = ['g']
|
||||
g.priority = 'high'
|
||||
g.example = '.g minetest'
|
||||
|
||||
def gc(phenny, input):
|
||||
if not input.group(2):
|
||||
return phenny.reply("No query term.")
|
||||
query = input.group(2).encode('utf-8')
|
||||
result = new_gc(query)
|
||||
for bw in search_badwords:
|
||||
if bw in query:
|
||||
print("[LOG]: %s queried Google Result Number for '%s' | DENIED: Badword" % (input.nick,query))
|
||||
return phenny.reply("Search term contains badword")
|
||||
for bn in search_badnicks:
|
||||
if bn in input.nick:
|
||||
print("[LOG]: %s queried Google Result Number for '%s' | DENIED: Badnick" % (input.nick,query))
|
||||
return phenny.reply("Nope!")
|
||||
print("[LOG]: %s queried Google Result Number for '%s'" % (input.nick,query))
|
||||
if result:
|
||||
phenny.say(query + ": " + result)
|
||||
else: phenny.reply("Sorry, couldn't get a result.")
|
||||
|
||||
def new_gc(query):
|
||||
uri = 'https://www.google.com/search?hl=en&q='
|
||||
uri = uri + web.urllib.quote(query).replace('+', '%2B')
|
||||
if '"' in query: uri += '&tbs=li:1'
|
||||
bytes = web.get(uri)
|
||||
if "did not match any documents" in bytes:
|
||||
return "0"
|
||||
for result in re.compile(r'(?ims)([0-9,]+) results?').findall(bytes):
|
||||
return result
|
||||
return None
|
||||
|
||||
gc.commands = ['gc']
|
||||
gc.priority = 'high'
|
||||
gc.example = '.gc minetest'
|
||||
|
||||
if __name__ == '__main__':
|
||||
print __doc__.strip()
|
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
server.py - Phenny Minetest Server Module
|
||||
Copyright 2012, Sfan5
|
||||
"""
|
||||
|
||||
import web, math, random
|
||||
from xml.dom import minidom
|
||||
|
||||
def read_server():
|
||||
bytes = web.get("http://servers.minetest.ru/")
|
||||
shim = '<table>'
|
||||
shim2 = '</table>'
|
||||
if shim in bytes and shim2 in bytes:
|
||||
bytes = bytes.split(shim, 1).pop()
|
||||
bytes = bytes.split(shim2, 1)[0]
|
||||
bytes = "<table>" + bytes + "</table>" # Root Tag needed
|
||||
print("DBG bytes = '%s'" % bytes)
|
||||
dom = minidom.parseString(bytes)
|
||||
l = dom.getElementsByTagName("tr")
|
||||
chosen = l[int(math.floor(random.random()*(len(l)-1))+1)]
|
||||
datas = chosen.getElementsByTagName("td")
|
||||
name = datas[0].firstChild.data # Server Name
|
||||
addr = datas[1].firstChild.data # Server Address
|
||||
status = datas[3].firstChild.data # Status (up/down)
|
||||
statuspercent = datas[4].firstChild.firstChild.data # Status Percent
|
||||
return format(name,addr,status,statuspercent)
|
||||
return "Unknown Error"
|
||||
|
||||
|
||||
def format(name,addr,status,statuspercent):
|
||||
if status == "up":
|
||||
return "%s | %s %s (%s)" % (name,addr,status,statuspercent)
|
||||
else:
|
||||
return "%s | %s %s" % (name,addr,status)
|
||||
def server(phenny, input):
|
||||
phenny.reply(read_server())
|
||||
|
||||
server.commands = ['sv', 'server']
|
||||
server.thread = True
|
||||
|
||||
if __name__ == '__main__':
|
||||
print __doc__
|
|
@ -0,0 +1,49 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
serverup.py - Minetest-Server Ping Module
|
||||
Copyright 2012, sfan5
|
||||
"""
|
||||
|
||||
import socket, time
|
||||
|
||||
def serverup(phenny, input):
|
||||
arg = input.group(2)
|
||||
if not arg:
|
||||
return phenny.reply("Give me a Server Address")
|
||||
if not '.' in arg:
|
||||
return phenny.reply("Invalid Address")
|
||||
if ':' in arg:
|
||||
address = arg.split(':')[0]
|
||||
try:
|
||||
port = int(arg.split(':')[1])
|
||||
except:
|
||||
return phenny.reply("Invalid Port")
|
||||
else:
|
||||
address = arg
|
||||
port = 30000
|
||||
try:
|
||||
start = time.time()
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
sock.settimeout(2.5)
|
||||
buf = "\x4f\x45\x74\x03\x00\x00\x00\x01"
|
||||
sock.sendto(buf, (address, port))
|
||||
data, addr = sock.recvfrom(1000)
|
||||
if data:
|
||||
peer_id = data[12:14]
|
||||
buf = "\x4f\x45\x74\x03" + peer_id + "\x00\x00\x03"
|
||||
sock.sendto(buf, (address, port))
|
||||
sock.close()
|
||||
end = time.time()
|
||||
phenny.reply("%s is up (%0.3fms)" % (arg,end-start))
|
||||
else:
|
||||
phenny.reply("%s seems to be down " % arg)
|
||||
except:
|
||||
phenny.reply("%s seems to be down " % arg)
|
||||
|
||||
|
||||
|
||||
serverup.commands = ['up']
|
||||
serverup.thread = True
|
||||
|
||||
if __name__ == '__main__':
|
||||
print __doc__
|
|
@ -0,0 +1,74 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
startup.py - Phenny Startup Module
|
||||
Copyright 2008, Sean B. Palmer, inamidst.com
|
||||
Licensed under the Eiffel Forum License 2.
|
||||
|
||||
http://inamidst.com/phenny/
|
||||
"""
|
||||
|
||||
import threading, time
|
||||
|
||||
def setup(phenny):
|
||||
# by clsn
|
||||
phenny.data = {}
|
||||
refresh_delay = 300.0
|
||||
|
||||
if hasattr(phenny.config, 'refresh_delay'):
|
||||
try: refresh_delay = float(phenny.config.refresh_delay)
|
||||
except: pass
|
||||
|
||||
def close():
|
||||
print "Nobody PONGed our PING, restarting"
|
||||
phenny.handle_close()
|
||||
|
||||
def pingloop():
|
||||
timer = threading.Timer(refresh_delay, close, ())
|
||||
phenny.data['startup.setup.timer'] = timer
|
||||
phenny.data['startup.setup.timer'].start()
|
||||
# print "PING!"
|
||||
phenny.write(('PING', phenny.config.host))
|
||||
phenny.data['startup.setup.pingloop'] = pingloop
|
||||
|
||||
def pong(phenny, input):
|
||||
try:
|
||||
# print "PONG!"
|
||||
phenny.data['startup.setup.timer'].cancel()
|
||||
time.sleep(refresh_delay + 60.0)
|
||||
pingloop()
|
||||
except: pass
|
||||
pong.event = 'PONG'
|
||||
pong.thread = True
|
||||
pong.rule = r'.*'
|
||||
phenny.variables['pong'] = pong
|
||||
|
||||
# Need to wrap handle_connect to start the loop.
|
||||
inner_handle_connect = phenny.handle_connect
|
||||
|
||||
def outer_handle_connect():
|
||||
inner_handle_connect()
|
||||
if phenny.data.get('startup.setup.pingloop'):
|
||||
phenny.data['startup.setup.pingloop']()
|
||||
|
||||
phenny.handle_connect = outer_handle_connect
|
||||
|
||||
def startup(phenny, input):
|
||||
import time
|
||||
|
||||
if hasattr(phenny.config, 'serverpass'):
|
||||
phenny.write(('PASS', phenny.config.serverpass))
|
||||
|
||||
if hasattr(phenny.config, 'password'):
|
||||
phenny.msg('NickServ', 'IDENTIFY %s' % phenny.config.password)
|
||||
time.sleep(5)
|
||||
|
||||
# Cf. http://swhack.com/logs/2005-12-05#T19-32-36
|
||||
for channel in phenny.channels:
|
||||
phenny.write(('JOIN', channel))
|
||||
time.sleep(0.5)
|
||||
startup.rule = r'(.*)'
|
||||
startup.event = '251'
|
||||
startup.priority = 'low'
|
||||
|
||||
if __name__ == '__main__':
|
||||
print __doc__.strip()
|
|
@ -0,0 +1,94 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
twitter.py - Phenny Twitter Module
|
||||
Copyright 2012, Sean B. Palmer, inamidst.com
|
||||
Modified by Sfan5 2012
|
||||
Licensed under the Eiffel Forum License 2.
|
||||
|
||||
http://inamidst.com/phenny/
|
||||
"""
|
||||
|
||||
import re, time
|
||||
import web
|
||||
|
||||
r_username = re.compile(r'^[a-zA-Z0-9_]{1,15}$')
|
||||
r_link = re.compile(r'^https?://twitter.com/\S+$')
|
||||
r_p = re.compile(r'(?ims)(<p class="js-tweet-text.*?</p>)')
|
||||
r_tag = re.compile(r'(?ims)<[^>]+>')
|
||||
r_anchor = re.compile(r'(?ims)(<a.*?</a>)')
|
||||
r_expanded = re.compile(r'(?ims)data-expanded-url=["\'](.*?)["\']')
|
||||
r_whiteline = re.compile(r'(?ims)[ \t]+[\r\n]+')
|
||||
r_breaks = re.compile(r'(?ims)[\r\n]+')
|
||||
|
||||
def entity(*args, **kargs):
|
||||
return web.entity(*args, **kargs).encode('utf-8')
|
||||
|
||||
def decode(html):
|
||||
return web.r_entity.sub(entity, html)
|
||||
|
||||
def expand(tweet):
|
||||
def replacement(match):
|
||||
anchor = match.group(1)
|
||||
for link in r_expanded.findall(anchor):
|
||||
return link
|
||||
return r_tag.sub('', anchor)
|
||||
return r_anchor.sub(replacement, tweet)
|
||||
|
||||
def read_tweet(url):
|
||||
bytes = web.get(url)
|
||||
shim = '<div class="content clearfix">'
|
||||
if shim in bytes:
|
||||
bytes = bytes.split(shim, 1).pop()
|
||||
|
||||
for text in r_p.findall(bytes):
|
||||
text = expand(text)
|
||||
text = r_tag.sub('', text)
|
||||
text = text.strip()
|
||||
text = r_whiteline.sub(' ', text)
|
||||
text = r_breaks.sub(' ', text)
|
||||
return decode(text)
|
||||
return "Sorry, couldn't get a tweet from %s" % url
|
||||
|
||||
def format(tweet, username):
|
||||
return '%s (@%s)' % (tweet, username)
|
||||
|
||||
def user_tweet(username):
|
||||
tweet = read_tweet('https://twitter.com/' + username + "?" + str(time.time()))
|
||||
return format(tweet, username)
|
||||
|
||||
def id_tweet(tid):
|
||||
link = 'https://twitter.com/twitter/status/' + tid
|
||||
data = web.head(link)
|
||||
message, status = tuple(data)
|
||||
if status == 301:
|
||||
url = message.get("Location")
|
||||
if not url: return "Sorry, couldn't get a tweet from %s" % link
|
||||
username = url.split('/')[3]
|
||||
tweet = read_tweet(url)
|
||||
return format(tweet, username)
|
||||
return "Sorry, couldn't get a tweet from %s" % link
|
||||
|
||||
def twitter(phenny, input):
|
||||
arg = input.group(2)
|
||||
if not arg:
|
||||
return phenny.reply("Give me a link, a username, or a tweet id")
|
||||
|
||||
arg = arg.strip()
|
||||
if isinstance(arg, unicode):
|
||||
arg = arg.encode('utf-8')
|
||||
print("[LOG]: %s queried Twitter for '%s'" % (input.nick,arg))
|
||||
if arg.isdigit():
|
||||
phenny.say(id_tweet(arg))
|
||||
elif r_username.match(arg):
|
||||
phenny.say(user_tweet(arg))
|
||||
elif r_link.match(arg):
|
||||
username = arg.split('/')[3]
|
||||
tweet = read_tweet(arg)
|
||||
phenny.say(format(tweet, username))
|
||||
else: phenny.reply("Give me a link, a username, or a tweet id")
|
||||
|
||||
twitter.commands = ['tw', 'twitter']
|
||||
twitter.thread = True
|
||||
|
||||
if __name__ == '__main__':
|
||||
print __doc__
|
|
@ -0,0 +1,165 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
wikipedia.py - Phenny Wikipedia Module
|
||||
Copyright 2008-9, Sean B. Palmer, inamidst.com
|
||||
Modified by Sfan5 2012
|
||||
Licensed under the Eiffel Forum License 2.
|
||||
|
||||
http://inamidst.com/phenny/
|
||||
"""
|
||||
|
||||
import re, urllib, gzip, StringIO
|
||||
import web
|
||||
|
||||
wikiuri = 'http://wiki.minetest.com/wiki/%s'
|
||||
|
||||
r_tr = re.compile(r'(?ims)<tr[^>]*>.*?</tr>')
|
||||
r_paragraph = re.compile(r'(?ims)<p[^>]*>.*?</p>|<li(?!n)[^>]*>.*?</li>')
|
||||
r_tag = re.compile(r'<(?!!)[^>]+>')
|
||||
r_whitespace = re.compile(r'[\t\r\n ]+')
|
||||
r_redirect = re.compile(
|
||||
r'(?ims)class=.redirectText.>\s*<a\s*href=./wiki/([^"/]+)'
|
||||
)
|
||||
|
||||
abbrs = ['etc', 'ca', 'cf', 'Co', 'Ltd', 'Inc', 'Mt', 'Mr', 'Mrs',
|
||||
'Dr', 'Ms', 'Rev', 'Fr', 'St', 'Sgt', 'pron', 'approx', 'lit',
|
||||
'syn', 'transl', 'sess', 'fl', 'Op', 'Dec', 'Brig', 'Gen'] \
|
||||
+ list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') \
|
||||
+ list('abcdefghijklmnopqrstuvwxyz')
|
||||
t_sentence = r'^.{5,}?(?<!\b%s)(?:\.(?=[\[ ][A-Z0-9]|\Z)|\Z)'
|
||||
r_sentence = re.compile(t_sentence % r')(?<!\b'.join(abbrs))
|
||||
|
||||
def unescape(s):
|
||||
s = s.replace('>', '>')
|
||||
s = s.replace('<', '<')
|
||||
s = s.replace('&', '&')
|
||||
s = s.replace(' ', ' ')
|
||||
return s
|
||||
|
||||
def text(html):
|
||||
html = r_tag.sub('', html)
|
||||
html = r_whitespace.sub(' ', html)
|
||||
return unescape(html).strip()
|
||||
|
||||
def wikipedia(term, language='en', last=False):
|
||||
global wikiuri
|
||||
if not '%' in term:
|
||||
if isinstance(term, unicode):
|
||||
t = term.encode('utf-8')
|
||||
else: t = term
|
||||
q = urllib.quote(t)
|
||||
u = wikiuri % (q)
|
||||
bytes = web.get(u)
|
||||
else: bytes = web.get(wikiuri % (term))
|
||||
|
||||
if bytes.startswith('\x1f\x8b\x08\x00\x00\x00\x00\x00'):
|
||||
f = StringIO.StringIO(bytes)
|
||||
f.seek(0)
|
||||
gzip_file = gzip.GzipFile(fileobj=f)
|
||||
bytes = gzip_file.read()
|
||||
gzip_file.close()
|
||||
f.close()
|
||||
|
||||
bytes = r_tr.sub('', bytes)
|
||||
|
||||
if not last:
|
||||
r = r_redirect.search(bytes[:4096])
|
||||
if r:
|
||||
term = urllib.unquote(r.group(1))
|
||||
return wikipedia(term, language=language, last=True)
|
||||
|
||||
paragraphs = r_paragraph.findall(bytes)
|
||||
|
||||
if not paragraphs:
|
||||
if not last:
|
||||
term = search(term)
|
||||
return wikipedia(term, language=language, last=True)
|
||||
return None
|
||||
|
||||
# Pre-process
|
||||
paragraphs = [para for para in paragraphs
|
||||
if (para and 'technical limitations' not in para
|
||||
and 'window.showTocToggle' not in para
|
||||
and 'Deletion_policy' not in para
|
||||
and 'Template:AfD_footer' not in para
|
||||
and not (para.startswith('<p><i>') and
|
||||
para.endswith('</i></p>'))
|
||||
and not 'disambiguation)"' in para)
|
||||
and not '(images and media)' in para
|
||||
and not 'This article contains a' in para
|
||||
and not 'id="coordinates"' in para
|
||||
and not 'class="thumb' in para]
|
||||
# and not 'style="display:none"' in para]
|
||||
|
||||
for i, para in enumerate(paragraphs):
|
||||
para = para.replace('<sup>', '|')
|
||||
para = para.replace('</sup>', '|')
|
||||
paragraphs[i] = text(para).strip()
|
||||
|
||||
# Post-process
|
||||
paragraphs = [para for para in paragraphs if
|
||||
(para and not (para.endswith(':') and len(para) < 150))]
|
||||
|
||||
para = text(paragraphs[0])
|
||||
m = r_sentence.match(para)
|
||||
|
||||
if not m:
|
||||
if not last:
|
||||
term = search(term)
|
||||
return wikipedia(term, language=language, last=True)
|
||||
return None
|
||||
sentence = m.group(0)
|
||||
|
||||
maxlength = 275
|
||||
if len(sentence) > maxlength:
|
||||
sentence = sentence[:maxlength]
|
||||
words = sentence[:-5].split(' ')
|
||||
words.pop()
|
||||
sentence = ' '.join(words) + ' [...]'
|
||||
|
||||
if (('using the Article Wizard if you wish' in sentence)
|
||||
or ('or add a request for it' in sentence)
|
||||
or ('in existing articles' in sentence)):
|
||||
if not last:
|
||||
term = search(term)
|
||||
return wikipedia(term, language=language, last=True)
|
||||
return None
|
||||
|
||||
sentence = '"' + sentence.replace('"', "'") + '"'
|
||||
sentence = sentence.decode('utf-8').encode('utf-8')
|
||||
wikiuri = wikiuri.decode('utf-8').encode('utf-8')
|
||||
term = term.decode('utf-8').encode('utf-8')
|
||||
return sentence + ' - ' + (wikiuri % (term))
|
||||
|
||||
def wik(phenny, input):
|
||||
origterm = input.groups()[1]
|
||||
if not origterm:
|
||||
return phenny.say('Perhaps you meant ".wik Zen"?')
|
||||
origterm = origterm.encode('utf-8')
|
||||
print("[LOG]: %s queried Minetest Wiki for '%s'" % (input.nick,origterm))
|
||||
|
||||
term = urllib.unquote(origterm)
|
||||
language = 'en'
|
||||
if term.startswith(':') and (' ' in term):
|
||||
a, b = term.split(' ', 1)
|
||||
a = a.lstrip(':')
|
||||
if a.isalpha():
|
||||
language, term = a, b
|
||||
term = term[0].upper() + term[1:]
|
||||
term = term.replace(' ', '_')
|
||||
|
||||
try: result = wikipedia(term, language)
|
||||
except IOError:
|
||||
args = (language, wikiuri % (term))
|
||||
error = "Can't connect to wiki.minetest.com (%s)" % args
|
||||
return phenny.say(error)
|
||||
|
||||
if result is not None:
|
||||
phenny.say(result)
|
||||
else: phenny.say('Can\'t find anything in Wiki for "%s".' % origterm)
|
||||
|
||||
wik.commands = ['wik']
|
||||
wik.priority = 'high'
|
||||
|
||||
if __name__ == '__main__':
|
||||
print __doc__.strip()
|
Loading…
Reference in New Issue