From dcebcafcc52ae847077890b551b8319d80d36d91 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Sat, 14 Nov 2009 01:28:23 +0100 Subject: A much needed inital import. --- modules/__init__.py | 0 modules/anidb.py | 100 +++++++++++++++++++++++++++++++++++++++++++ modules/quotes.py | 33 +++++++++++++++ modules/url_titles.py | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 248 insertions(+) create mode 100644 modules/__init__.py create mode 100644 modules/anidb.py create mode 100644 modules/quotes.py create mode 100644 modules/url_titles.py (limited to 'modules') diff --git a/modules/__init__.py b/modules/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/modules/anidb.py b/modules/anidb.py new file mode 100644 index 0000000..c5862e8 --- /dev/null +++ b/modules/anidb.py @@ -0,0 +1,100 @@ +info = { + 'author': 'Jon Bergli Heier', + 'title': 'anidb', + 'description': 'Fetches anime info from anidb.net.', +} + +import urllib2, gzip, os, time +from pyPgSQL import PgSQL +from lxml import etree +import pyanidb +import ConfigParser +import marshal + +anidb_cfg = {} +cp = ConfigParser.ConfigParser() +cp.read(os.path.expanduser('~/.pyanidb.conf')) +for option in ('username', 'password'): + anidb_cfg[option] = cp.get('pyanidb', option) + +class Module: + def __init__(self, bot): + self.irc = bot + self.db = PgSQL.connect() + + def get_aid(self, msg, short = False): + if msg.isdigit(): + return [(int(msg), 'N/A')] + search = '%'.join(msg.split()) + if not search: + return + if not short: + search = '%%%s%%' % search + cur = self.db.cursor() + if short: + cur.execute('select * from anidb.anidb where aid in (select distinct aid from anidb.anidb where title ~~* %s and type in (2, 3)) and type = 1', (search,)) + else: + cur.execute('select * from anidb.anidb where aid in (select distinct aid from anidb.anidb where title ~~* %s) and type = 1', (search,)) + r = cur.fetchall() + cur.close() + return [(r[0][0], r[0][3])] if len(r) == 1 else [(x[0], x[3]) for x in r] + + def get_info(self, aid): + cachepath = os.path.expanduser('~/.fotanidbcache/a%d.dat' % aid) + if os.access(cachepath, os.F_OK | os.R_OK) and time.time() - os.stat(cachepath).st_mtime < 60*60*24*7: + cache = open(cachepath, 'r').read() + data = marshal.loads(cache) + else: + amask = '33a0c0f0000080' + try: + anidb = pyanidb.AniDB(anidb_cfg['username'], anidb_cfg['password']) + anidb.auth() + data = anidb.get_anime(aid = aid, amask = amask) + anidb.logout() + open(cachepath, 'w').write(marshal.dumps(data)) + except: + return 'Failed to get data from anidb' + year, type, catlist, catweight, romaji, english, epcount, normalep, rating, ratingcount, temprating, tempcount, specialep = data + if '-' in year: + syear, eyear = [int(x) for x in year.split('-')] + if syear == eyear: + year = syear + catlist = catlist.split(',') + catweight = catweight.split(',') + try: + catn = max(catweight.index(str(int(catweight[0]-1))), 10) + except: + catn = 10 + rating = float(rating) / 100 + temprating = float(temprating) / 100 + catl = ', '.join(catlist[:catn] + (['+%d more' % (len(catlist)-catn)] if len(catlist) > catn else [])) + return '%s%s is: %s, year %s, %s%s eps%s, cats: %s | rating: %.2f (%s), temp: %.2f (%s) | http://anidb.net/a%d' % (romaji, ' aka. %s' % english if english else '', type, year, normalep, '+%s' % specialep if int(specialep) > 0 else '', ' (ongoing)' if int(epcount) == 0 else '', catl or '(None)', rating, ratingcount, temprating, tempcount, aid) + + def get_anime(self, msg): + short = msg.startswith('-s ') + if short: + msg = ' '.join(msg.split()[1:]) + aid = self.get_aid(msg, short) + if len(aid) == 1: + return self.get_info(aid[0][0]) + else: + if len(aid) == 0: + return 'anidb: No results' + else: + return 'anidb: %s%s' % ('%d/%d results: ' % (5, len(aid)) if len(aid) > 5 else '', ', '.join(['%s (%d)' % (x[1], x[0]) for x in aid[:5]])) + + def __call__(self, nick, channel, msg): + if msg.startswith('!anidb'): + target = channel if not channel == self.irc.nickname else nick.split('!')[0] + args = msg.split() + if len(args) == 1: + self.irc.msg(target, 'Usage: !anidb [-s] search|aid') + return + info = self.get_anime(' '.join(args[1:])) + if info: + self.irc.msg(target, info) + +if __name__ == '__main__': + import sys + m = Module(None) + print m.get_anime(' '.join(sys.argv[1:])) diff --git a/modules/quotes.py b/modules/quotes.py new file mode 100644 index 0000000..b8eb988 --- /dev/null +++ b/modules/quotes.py @@ -0,0 +1,33 @@ +info = { + 'author': 'Jon Bergli Heier', + 'title': 'IRC Quotes', + 'description': 'Allows users to access a quote database.', +} + +import sys +sys.path.insert(0, '/home/snakebite/py') +from quotelib import IRCHandler as Quote_IRCHandler +quote_handler = Quote_IRCHandler('/home/snakebite/quotes.db') + +class Module: + def __init__(self, bot): + self.irc = bot + + def __call__(self, nick, channel, msg): + if not msg.startswith('!quote'): + return + args = msg.split(' ') + if msg.startswith('!quote'): + args = args[1:] + cmd = args[0] if len(args) and len(args[0].strip()) else 'random' + args = args[1:] + + if cmd.isdigit() or (cmd[0] == '#' and cmd[1:].isdigit()): + cmd, args = 'get', [cmd] + + quote_handler.nick = nick.split('!')[0] + if hasattr(quote_handler, cmd) and callable(getattr(quote_handler, cmd)): + for line in getattr(quote_handler, cmd)(*args): + self.irc.msg(channel if not channel == self.irc.nickname else nick.split('!')[0], line) + else: + self.irc.msg(channel if not channel == self.irc.nickname else nick.split('!')[0], '%s, invalid command "%s"' % (nick.split('!')[0], cmd)) diff --git a/modules/url_titles.py b/modules/url_titles.py new file mode 100644 index 0000000..fe5181c --- /dev/null +++ b/modules/url_titles.py @@ -0,0 +1,115 @@ +info = { + 'author': 'Jon Bergli Heier', + 'title': 'URL Titles', + 'description': 'Fetches the title tags off of URLs.', +} + +import re, urllib2, htmlentitydefs, gzip, cStringIO, spotimeta + +class Module: + re_http = re.compile(r'(http://[^\ ]+)') + re_title = re.compile(r'(.*?)', re.S | re.I) + metadata = spotimeta.Metadata(cache = {}) + + def __init__(self, bot): + self.irc = bot + + def spotify(self, s): + try: + data = self.metadata.lookup(s) + except: + return 'Failed to fetch metadata from spotify.' + if data['type'] == 'artist': + return 'Spotify: %s' % data['result']['name'] + else: + return 'Spotify: %s - %s' % (data['result']['artist']['name'], data['result']['name']) + + def get_titles(self, s): + def parse_url(url): + s = url[7:].split('/', 1)[0:] + host = s[0] + path = '/' if len(s) == 1 else '/' + s[1] + return host, path + + def unescape(text): + def fixup(m): + text = m.group(0) + if text[:2] == "&#": + # character reference + try: + if text[:3] == "&#x": + return unichr(int(text[3:-1], 16)).encode('utf-8') + else: + return unichr(int(text[2:-1])).encode('utf-8') + except ValueError: + pass + else: + # named entity + try: + text = unichr(htmlentitydefs.name2codepoint[text[1:-1]]).encode('utf-8') + except KeyError: + pass + return text # leave as is + return re.sub("&#?\w+;", fixup, text) + + def format_text(s): + s = s.replace('\n', ' ').replace('\r', ' ').replace('\t', ' ') + while ' ' in s: + s = s.replace(' ', ' ') + s = unescape(s) + return s + + m = self.re_http.findall(s) + if not m: + return + titles = [] + for url in m: + if any([x in url for x in ('open.spotify.com', 'spotify:track:', 'spotify:artist:', 'spotify:album:')]): + titles.append(self.spotify(url).encode('utf8')) + continue + try: + u = urllib2.urlopen(url) + except: + return + #enc = ct.split('encoding=') + #if len(enc) == 2: + #enc = enc[1] + #else: + #enc = None + if u.headers['content-type'].startswith('text/html'): + #s = u.read() + if 'content-encoding' in u.headers and u.headers['content-encoding'] == 'gzip': + s = cStringIO.StringIO(u.read()) + s.seek(0) + s = gzip.GzipFile(fileobj = s).read() + m = self.re_title.search(s) + else: + s = '' + m = None + buf = u.read(1024) + while buf: + s += buf + m = self.re_title.search(s) + if m: + break + buf = u.read(1024) + if m: + titles.append(m.groups()[0]) + u.close() + if len(titles) == 1: + s = format_text(titles[0]) + else: + s = '' + for i in range(len(titles)): + s += '\002[%d]\002 %s ' % (i+1, format_text(titles[i])) + return s.strip() + + def __call__(self, nick, channel, msg): + titles = self.get_titles(msg) + if titles: + self.irc.msg(channel if not channel == self.irc.nickname else nick.split('!')[0], titles) + +if __name__ == '__main__': + import sys + m = Module(None) + print m.get_titles(' '.join(sys.argv[1:])) -- cgit v1.2.3