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