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(database = 'fot') 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 where aid in (select distinct aid from anidb where title ~~* %s and type in (2, 3)) and type = 1', (search,)) else: cur.execute('select * from anidb where aid in (select distinct aid from 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%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' % epcount if int(epcount) > 0 else '', '+%s' % specialep if int(specialep) > 0 else '', ' (ongoing)' if (int(epcount) == 0 or normalep < epcount) 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:]))