def main(self, args, env = {}): if not len(args): return '' link = self.google.search(args + ['site:animenewsnetwork.com']) if len(link): if len(link[1]): return gib.ircstr("{0} - ´B{1}´N").format(link[0], link[1]) else: return str(link[0]) else: return gib.ircstr("'´I{0}´N' did not return anything.").format(' '.join(args))
def main(self, args, env = {}): user = '' if len(args) and args[0] and self.userre.match(args[0]): user = args[0] if not user and 'nick' in env: nick = env['nick'].GetNick() if len(args) == 2 and args[0] == '.set': if self.userre.match(args[1]): return self.set_nick(nick, args[1]) else: return gib.ircstr('´I{0}´N is not a valid last.fm username.').format(args[1]) if len(args) == 1 and args[0] == '.unset': return self.unset_nick(nick) user = self.get_nick(nick) if not user and self.userre.match(nick): user = nick if not user: return gib.ircstr("Invalid user ´I{0}´N").format(args[0] if len(args[0]) else env['nick'].GetNick()) last_track = self.get_last_track(user) if 'error' in last_track: if last_track['error'] == 'not found': return gib.ircstr("´I{0}´N not found").format(user) elif last_track['error'] == 'no records': return gib.ircstr("´I{0}´N never played anything").format(user) else: return time = last_track['time'] time = (self.pretty_date(time) + ' ') if time != 0 else '' tags = last_track['tags'][:3] tags = (gib.ircstr('´C7´B´B') + gib.ircstr('´N, ´C7´B´B').join(tags) + gib.N) if len(tags) else 'no tags' loved = gib.ircstr('´C4♥´N ') if last_track['loved'] else '' play = self.ordn(last_track['userplaycount']) album = (gib.ircstr('[´C13´B´B') + last_track['album'].title + gib.ircstr('´N] ')) if last_track['album'] else '' resp = gib.ircstr('´C11{0}´N {1} listening to "´C10´B{2}´N" {3}by ´C12´B{4}´N {5}{6}for the {7} time, {8} plays by {9} listeners. ({10})') resp = resp.format(user, 'was' if time != '' else 'is', last_track['track'], loved, last_track['artist'], album, time, play, last_track['globalplaycount'], last_track['listeners'], tags) # if type(time) == int and time == 0: # resp = gib.ircstr('´C11´I{0}´N is currently listening to "´C10´B{1}´N" by ´C12´I{2}´N{3} {4}for the {5} time, {6} global plays by {7} listeners. ({8})') # resp = resp.format(user, last_track['track'], last_track['artist'], album, loved, play, last_track['globalplaycount'], last_track['listeners'], tags) # else: # resp = gib.ircstr('´C11´I{0}´N was listening to "´C10´B{1}´N" by ´C12´I{2}´N{3} {4}about {5} for the {6} time, {7} global plays by {8} listeners. ({9})') # resp = resp.format(user, last_track['track'], last_track['artist'], album, loved, time, play, last_track['globalplaycount'], last_track['listeners'], tags) return resp
def main(self, args, env = {}): if not len(args): return '' link = self.search(args) if len(link): if len(link[1]): return gib.ircstr("{0} - ´B{1}´N").format(link[0], link[1]) else: return str(link[0]) else: return gib.ircstr("'´I{0}´N' did not match any documents.").format(' '.join(args))
def main(self, args, env = {}): if not len(args): return '' link = self.google.search(args + ['site:anidb.net']) if len(link): if len(link[1]): return gib.ircstr("{0} - ´B{1}´N").format(link[0], link[1].replace(' - AniDB', '')) else: return str(link[0]) else: return gib.ircstr("'´I{0}´N' did not return anything.").format(' '.join(args))
def main(self, args, env={}): if not len(args): return '' link = self.google.search(args + ['site:mangaupdates.com/series.html']) if len(link): page = self.google.open_page(link[0]) page = b''.join(page.readlines()).decode('utf-8', 'ignore') html = lxml.html.document_fromstring(page) rating = self.get_rating(html) volumes = self.get_volumes(html) description = self.get_description(html) name = [str(link[0])] if not volumes in (None, ""): name.append(gib.ircstr('´C6´B´B' + volumes + '´N')) if not rating in (None, ""): name.append(gib.ircstr('´C7´B´B' + rating + '´N')) if not link[1] in (None, ""): name.append( gib.ircstr('´B' + link[1].replace('Baka-Updates Manga - ', '') + '´N')) name = ' :: '.join(name) if not description in (None, ""): name = [name, description] return name else: return gib.ircstr("'´I{0}´N' did not return anything.").format( ' '.join(args))
class RDNS: command = ".rdns" help = gib.ircstr( "´Iipaddress´N | Returns the reverse DNS entry for the IP.") shelp = gib.ircstr("´Iip´N") google = None def __init__(self): self.google = google.Google() def main(self, args, env={}): if not len(args): return '' host = socket.gethostbyaddr(args[0])[0] if host.find('://') == -1: host = "http://{0}/".format(host) page = urlopen( Request( host, None, { 'User-Agent': "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.2 Safari/537.36" })) try: title = self.google.get_title(page) except: title = gib.ircstr("´ITimeout´N") return gib.ircstr("{0} | ´B{1}´N{2}").format( args[0], host, (" - " + title) if len(title) else '')
def main(self, args, env = {}): if not len(args): return '' host = socket.gethostbyaddr(args[0])[0] if host.find('://') == -1: host = "http://{0}/".format(host) page = urlopen(Request(host, None, {'User-Agent':"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.2 Safari/537.36"})) try: title = self.google.get_title(page) except: title = gib.ircstr("´ITimeout´N") return gib.ircstr("{0} | ´B{1}´N{2}").format(args[0], host, (" - " + title) if len(title) else '')
def main(self, args, env={}): if not len(args): return '' link = self.google.search(args + ['site:animenewsnetwork.com']) if len(link): if len(link[1]): return gib.ircstr("{0} - ´B{1}´N").format(link[0], link[1]) else: return str(link[0]) else: return gib.ircstr("'´I{0}´N' did not return anything.").format( ' '.join(args))
def main(self, args, env = {}): if not len(args): return '' link = self.google.search(args + ['site:bato.to']) if len(link): rating = self.get_rating(link[0]) name = [str(link[0])] if len(rating): name.append(gib.ircstr('´C7´B´B' + rating + '´N')) if len(link[1]): name.append(gib.ircstr('´B' + link[1].split('- Scanlations ')[0].split(' - Comic ')[0] + '´N')) name = ' :: '.join(name) return name else: return gib.ircstr("'´I{0}´N' did not return anything.").format(' '.join(args))
def main(self, args, env={}): if not len(args): return '' link = self.search(args) if len(link): if len(link[1]): return gib.ircstr("{0} - ´B{1}´N").format(link[0], link[1]) else: return str(link[0]) else: return gib.ircstr("'´I{0}´N' did not match any documents.").format( ' '.join(args))
def unset_nick(self, ircnick): if self.sqlc: irc = self.sqlc.execute('SELECT * FROM nicks WHERE irc = ?', (ircnick,)).fetchall() if len(irc): self.sqlc.execute('DELETE FROM nicks WHERE irc = ?', (ircnick,)) self.sql.commit() return gib.ircstr('´I{0}´N is not linked with ´I{1}´N anymore.').format(ircnick, irc[0][1]) else: return gib.ircstr('´I{0}´N is not currently linked with any last.fm username.') else: return ''
def main(self, args, env={}): if not len(args): return '' link = self.google.search(args + ['site:anidb.net']) if len(link): if len(link[1]): return gib.ircstr("{0} - ´B{1}´N").format( link[0], link[1].replace(' - AniDB', '')) else: return str(link[0]) else: return gib.ircstr("'´I{0}´N' did not return anything.").format( ' '.join(args))
class WAlpha: command = ".wa" help = gib.ircstr("´Iquery´N | Queries WolframAlpha.") shelp = gib.ircstr("´Iquery´N") client = None def __init__(self): self.client = wolframalpha.Client("KEY") def main(self, args, env = {}): if not len(args): return '' num = 10 if 'nick' in env and env['nick'].GetHost() == 'Potatoe.Developer.AnimeBytes' else 5 r = self.query(' '.join(args), num) if len(r): pods = [gib.ircstr('´C7´B') + r.pop(0)[1] + gib.ircstr('´N :: ')] for s in r: if len(pods[-1]) + len(s[0]) + len(s[1]) >= 400: pods.append('') pods[-1] += gib.ircstr('[ ´C10') + s[0] + gib.ircstr(': ´N') + s[1] + ' ]' # if len(pods[-1]) >= 400: pods.append('') pods = list(filter(None, pods)) # if 'nick' in env and env['nick'].GetHost() != 'Potatoe.Developer.AnimeBytes': pods = pods[0:1] pods = pods[0:1] return pods else: return 'No results!' def query(self, query, num = 5): global ret res = self.client.query(query) ret = [] for p in res.pods: if p.text: ret.append([p.title, ' || '.join([self.clean_wa(c.text) for c in p if c.text])]) if len(ret) > num: break # for r in res.results: # if len(ret) == 4: break # ret.append(gib.B + r.text + gib.N) # if len(ret) < 4: # for p in res.pods: # if len(ret) == 4: break # ret.append(gib.I + p.text + gib.N) return ret def clean_wa(self, toclean): return ' '.join(toclean.replace('\n | ', ' ').replace('\n', ' - ').split()) \ .replace(' )', ')').replace('( ', '(').rstrip(' | ').replace(' | ', ', ') \ .replace(' ~~ ', ' ≒ ').replace('~~ ', '~').replace('>=', '≥').replace('<=', '≤') \ .replace('=>', '⇒').replace(r'\:2224', '∤').replace('(for all)', ' ∀ ') \ .replace(' element ', ' ∈ ').replace('(not element)', ' ∉ ') \ .replace(r'\:2115', 'ℕ').replace(r'\:2124', 'ℤ').replace(r'\:211a', 'ℚ').replace(r'\:211d', 'ℝ').replace(r'\:2102', 'ℂ') \ .strip()
def main(self, args, env={}): user = '' if len(args) and args[0] and self.userre.match(args[0]): user = args[0] if not user and 'nick' in env: nick = env['nick'].GetNick() if len(args) == 2 and args[0] == '.set': if self.userre.match(args[1]): return self.set_nick(nick, args[1]) else: return gib.ircstr( '´I{0}´N is not a valid last.fm username.').format( args[1]) if len(args) == 1 and args[0] == '.unset': return self.unset_nick(nick) user = self.get_nick(nick) if not user and self.userre.match(nick): user = nick if not user: return gib.ircstr("Invalid user ´I{0}´N").format( args[0] if len(args[0]) else env['nick'].GetNick()) last_track = self.get_last_track(user) if 'error' in last_track: if last_track['error'] == 'not found': return gib.ircstr("´I{0}´N not found").format(user) elif last_track['error'] == 'no records': return gib.ircstr("´I{0}´N never played anything").format(user) else: return time = last_track['time'] time = (self.pretty_date(time) + ' ') if time != 0 else '' tags = last_track['tags'][:3] tags = (gib.ircstr('´C7´B´B') + gib.ircstr('´N, ´C7´B´B').join(tags) + gib.N) if len(tags) else 'no tags' loved = gib.ircstr('´C4♥´N ') if last_track['loved'] else '' play = self.ordn(last_track['userplaycount']) album = (gib.ircstr('[´C13´B´B') + last_track['album'].title + gib.ircstr('´N] ')) if last_track['album'] else '' resp = gib.ircstr( '´C11{0}´N {1} listening to "´C10´B{2}´N" {3}by ´C12´B{4}´N {5}{6}for the {7} time, {8} plays by {9} listeners. ({10})' ) resp = resp.format(user, 'was' if time != '' else 'is', last_track['track'], loved, last_track['artist'], album, time, play, last_track['globalplaycount'], last_track['listeners'], tags) # if type(time) == int and time == 0: # resp = gib.ircstr('´C11´I{0}´N is currently listening to "´C10´B{1}´N" by ´C12´I{2}´N{3} {4}for the {5} time, {6} global plays by {7} listeners. ({8})') # resp = resp.format(user, last_track['track'], last_track['artist'], album, loved, play, last_track['globalplaycount'], last_track['listeners'], tags) # else: # resp = gib.ircstr('´C11´I{0}´N was listening to "´C10´B{1}´N" by ´C12´I{2}´N{3} {4}about {5} for the {6} time, {7} global plays by {8} listeners. ({9})') # resp = resp.format(user, last_track['track'], last_track['artist'], album, loved, time, play, last_track['globalplaycount'], last_track['listeners'], tags) return resp
def set_nick(self, ircnick, lfmnick): if self.sqlc: old = self.sqlc.execute('SELECT * FROM nicks WHERE irc = ?', (ircnick,)).fetchall() all = self.sqlc.execute('SELECT * FROM nicks WHERE lastfm = ?', (lfmnick,)).fetchall() if len(old): self.sqlc.execute('UPDATE nicks SET lastfm = ? WHERE irc = ?', (lfmnick, ircnick)) else: self.sqlc.execute('INSERT INTO nicks VALUES (?, ?)', (ircnick, lfmnick)) self.sql.commit() if not (ircnick, lfmnick) in all: all.append((ircnick, lfmnick)) all = [e[0] for e in all] all = gib.ircstr('´N, ´I').join(all) return gib.ircstr('´I{0}´N is now linked with ´I{1}´N.').format(lfmnick, all) else: return ''
def main(self, args, env={}): if not len(args): return '' link = self.google.search(args + ['site:bato.to']) if len(link): rating = self.get_rating(link[0]) name = [str(link[0])] if len(rating): name.append(gib.ircstr('´C7´B´B' + rating + '´N')) if len(link[1]): name.append( gib.ircstr('´B' + link[1].split('- Scanlations ')[0].split( ' - Comic ')[0] + '´N')) name = ' :: '.join(name) return name else: return gib.ircstr("'´I{0}´N' did not return anything.").format( ' '.join(args))
def main(self, args, env={}): if not len(args): return '' host = socket.gethostbyaddr(args[0])[0] if host.find('://') == -1: host = "http://{0}/".format(host) page = urlopen( Request( host, None, { 'User-Agent': "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.2 Safari/537.36" })) try: title = self.google.get_title(page) except: title = gib.ircstr("´ITimeout´N") return gib.ircstr("{0} | ´B{1}´N{2}").format( args[0], host, (" - " + title) if len(title) else '')
def main(self, args, env = {}): if not len(args): return '' num = 10 if 'nick' in env and env['nick'].GetHost() == 'Potatoe.Developer.AnimeBytes' else 5 r = self.query(' '.join(args), num) if len(r): pods = [gib.ircstr('´C7´B') + r.pop(0)[1] + gib.ircstr('´N :: ')] for s in r: if len(pods[-1]) + len(s[0]) + len(s[1]) >= 400: pods.append('') pods[-1] += gib.ircstr('[ ´C10') + s[0] + gib.ircstr(': ´N') + s[1] + ' ]' # if len(pods[-1]) >= 400: pods.append('') pods = list(filter(None, pods)) # if 'nick' in env and env['nick'].GetHost() != 'Potatoe.Developer.AnimeBytes': pods = pods[0:1] pods = pods[0:1] return pods else: return 'No results!'
class Batoto: command = ".btt" help = gib.ircstr("´Isearchterm´N | Searches on Bato.to.") shelp = gib.ircstr("´Iquery´N") google = None def __init__(self): self.google = google.Google() def main(self, args, env={}): if not len(args): return '' link = self.google.search(args + ['site:bato.to']) if len(link): rating = self.get_rating(link[0]) name = [str(link[0])] if len(rating): name.append(gib.ircstr('´C7´B´B' + rating + '´N')) if len(link[1]): name.append( gib.ircstr('´B' + link[1].split('- Scanlations ')[0].split( ' - Comic ')[0] + '´N')) name = ' :: '.join(name) return name else: return gib.ircstr("'´I{0}´N' did not return anything.").format( ' '.join(args)) def get_rating(self, url): if not len(url): return '' page = self.google.open_page(url) page = b''.join(page.readlines()) try: page = page.decode('utf8') except UnicodeDecodeError: try: page = zlib.decompress(page, 15 + 32) except: return '' html = lxml.html.document_fromstring(page) rating = html.xpath('//div[contains(@class, "rating")]') if len(rating) > 0: rating = rating[0].text_content().split('(')[1].split( 'votes')[0] + ' votes' return rating else: return ''
def unset_nick(self, ircnick): if self.sqlc: irc = self.sqlc.execute('SELECT * FROM nicks WHERE irc = ?', (ircnick, )).fetchall() if len(irc): self.sqlc.execute('DELETE FROM nicks WHERE irc = ?', (ircnick, )) self.sql.commit() return gib.ircstr( '´I{0}´N is not linked with ´I{1}´N anymore.').format( ircnick, irc[0][1]) else: return gib.ircstr( '´I{0}´N is not currently linked with any last.fm username.' ) else: return ''
def set_nick(self, ircnick, lfmnick): if self.sqlc: old = self.sqlc.execute('SELECT * FROM nicks WHERE irc = ?', (ircnick, )).fetchall() all = self.sqlc.execute('SELECT * FROM nicks WHERE lastfm = ?', (lfmnick, )).fetchall() if len(old): self.sqlc.execute('UPDATE nicks SET lastfm = ? WHERE irc = ?', (lfmnick, ircnick)) else: self.sqlc.execute('INSERT INTO nicks VALUES (?, ?)', (ircnick, lfmnick)) self.sql.commit() if not (ircnick, lfmnick) in all: all.append((ircnick, lfmnick)) all = [e[0] for e in all] all = gib.ircstr('´N, ´I').join(all) return gib.ircstr('´I{0}´N is now linked with ´I{1}´N.').format( lfmnick, all) else: return ''
class VNDB: command = ".vndb" help = gib.ircstr("´Isearchterm´N | Searches on VNDB.") shelp = gib.ircstr("´Iquery´N") google = None def __init__(self): self.google = google.Google() def main(self, args, env={}): if not len(args): return '' link = self.google.search(args + ['site:vndb.org']) if len(link): if len(link[1]): return gib.ircstr("{0} - ´B{1}´N").format(link[0], link[1]) else: return str(link[0]) else: return "'´I{0}´N' did not return anything.".format(' '.join(args))
class ANN: command = ".ann" help = gib.ircstr("´Isearchterm´N | Searches on AnimeNewsNetwork.") shelp = gib.ircstr("´Iquery´N") google = None def __init__(self): self.google = google.Google() def main(self, args, env={}): if not len(args): return '' link = self.google.search(args + ['site:animenewsnetwork.com']) if len(link): if len(link[1]): return gib.ircstr("{0} - ´B{1}´N").format(link[0], link[1]) else: return str(link[0]) else: return gib.ircstr("'´I{0}´N' did not return anything.").format( ' '.join(args))
def rebuildindices(self): global L, modules, Modules, commands, help commands = {} help = gib.ircstr("´B.help´N [´Icmd´N]") for mod in modules: try: help += ', ' + gib.B + Modules[mod].command + gib.N + ' ' + Modules[mod].shelp commands[Modules[mod].command] = mod except Exception as e: L.log(L.ERROR, "Exception rebuilding indices for " + mod + ": " + str(e), self.GetSavePath() + "/modules.log") traceback.print_exc(file = open(self.GetSavePath() + "/traceback.log", "a")) pass
class MAL: command = ".mal" help = gib.ircstr("´Isearchterm´N | Searches on MyAnimeList.") shelp = gib.ircstr("´Iquery´N") google = None def __init__(self): self.google = google.Google() def main(self, args, env={}): if not len(args): return '' link = self.google.search(args + ['site:myanimelist.net']) if len(link): if len(link[1]): return gib.ircstr("{0} - ´B{1}´N").format( link[0], link[1].replace(' - MyAnimeList.net', '')) else: return str(link[0]) else: return gib.ircstr("'´I{0}´N' did not return anything.".format( ' '.join(args)))
def rebuildindices(self): global L, modules, Modules, commands, help commands = {} help = gib.ircstr("´B.help´N [´Icmd´N]") for mod in modules: try: help += ', ' + gib.B + Modules[ mod].command + gib.N + ' ' + Modules[mod].shelp commands[Modules[mod].command] = mod except Exception as e: L.log( L.ERROR, "Exception rebuilding indices for " + mod + ": " + str(e), self.GetSavePath() + "/modules.log") traceback.print_exc( file=open(self.GetSavePath() + "/traceback.log", "a")) pass
import gib import logger L = logger.Logger() L.setloglevel(L.INFO) L.setlogpath(filepath + '/GIB.log') L.log(L.INFO, 'STARTED') modules = { 'google', 'anidb', 'ann', 'vndb', 'vgmdb', 'mal', 'trans', 'lastfm', 'wa', 'mangaupdates', 'batoto' } modules = dict.fromkeys(modules, '') Modules = modules commands = {} help = gib.ircstr("´B.help´N [´Icmd´N]") # So that we can just import them by name of the script sys.path.append(filepath + '/gib/') for mod in modules: try: del sys.modules[mod] except KeyError: pass modules[mod] = importlib.import_module(mod) try: Modules[mod] = getattr(modules[mod], modules[mod].name)() help += ', ' + gib.B + Modules[mod].command + gib.N + ' ' + Modules[ mod].shelp commands[Modules[mod].command] = mod except Exception as e: L.log(L.ERROR, str(e))
def OnChanMsg(self, nick, channel, message): global L, modules, Modules, commands, help # Get some basic stuff net = self.GetNetwork() me = net.GetNick() msg = message.s msglst = msg.split() nik = nick.GetNick() try: # It's either a znc.CChan or a znc.CNick, everything else we just don't accept chan = channel.GetName() if type(channel) is znc.CChan else channel.GetNick() except Exception: return znc.CONTINUE if nik == "Satsuki": return znc.CONTINUE if (self.use_channel_blacklist and chan in self.channel_blacklist) \ or (self.use_channel_whitelist and not chan in self.channel_whitelist): return znc.CONTINUE # Some anti-flooding procedures. Not the best, but it works vOv if msglst[0] in commands: #if not (nik in self.user_whitelist permstr = channel.FindNick(nik).GetPermStr() if type(channel) is znc.CChan else '' if not (self.abure.sub('\\1', nick.GetHost()) in self.user_whitelist or nik in self.user_whitelist) \ and all(permstr.find(p) < 0 for p in ['~', '&', '@', '%']): if use_user_whitelist: return znc.CONTINUE currenttime = time.mktime(time.gmtime()) if currenttime-self.cooldown[0] < 90: return znc.CONTINUE if currenttime-self.cooldown[-1] < 5: return znc.CONTINUE if currenttime <= self.cooluntil: return znc.CONTINUE if all(t >= currenttime-45 for t in self.cooldown): self.cooluntil = currenttime + 300 self.put_msg(chan, 'Yamete! >///<') L.log(L.INFO, chan + " flooded by " + nik + ", msg: " + msg, self.GetSavePath() + "/modules.log") self.cooldown.append(currenttime) if len(self.cooldown) > 5: self.cooldown.pop(0) if self.cooluntil > currenttime: return znc.CONTINUE if currenttime-self.cooldown[0] < 90: self.put_msg(chan, 'Yamete! >///<') if currenttime-self.cooldown[-1] < 5: self.put_msg(chan, 'Yamete! >///<') if msglst[0] == '.help' \ or (msglst[0].lower() in [me.lower(), 'sawako', 'sadako'] and msglst[1].lower() == 'help') \ or (msglst[0].lower() in ['hi', 'hello', 'yo', 'hey'] and msglst[1].lower() in [me.lower(), 'sawako', 'sadako']): if msglst[0].lower() in ['hi', 'hello', 'yo', 'hey']: greeting = random.choice(['Hi', 'Hello', '今日は', 'Konnichiwa']) self.put_msg(channel.GetName(), greeting + ' ' + nik + '!') if msglst[0] == '.help': args = msglst[1:] else: args = msglst[2:] if not len(args): self.put_notice(nik, 'Possible commands: ' + help) self.put_notice(nik, gib.ircstr('For more details: ´B/msg ' + me + ' help´N')) return znc.CONTINUE if args[0] in commands: mod = Modules[commands[args[0]]] self.put_notice(nik, gib.B + mod.command + gib.N + ' ' + mod.help) return znc.CONTINUE if msglst[0] in commands: cmd = msglst[0] mod = commands[cmd] mod = Modules[mod] args = msglst[1:] now = time.time() ret = '' chan = channel.GetName() chan = (chan[:12] + (chan[12:] and '..')).ljust(14) L.log(L.INFO, chan + " call: " + cmd + ", args: " + str(args), self.GetSavePath() + "/modules.log") try: env = {'nick': nick, 'channel': channel, 'self': self} ret = mod.main(args, env) if len(ret): if 'c' in str(channel.GetModeString()): ret = self.colorre.sub('', ret) self.put_msg(channel, ret) except Exception as e: L.log(L.ERROR, chan + " error: " + str(e), self.GetSavePath() + "/modules.log") traceback.print_exc(file = open(self.GetSavePath() + "/traceback.log", "a")) L.log(L.INFO, chan + " finish: " + cmd + ", (" + str(int((time.time() - now) * 1000)) + "ms)", self.GetSavePath() + "/modules.log") return znc.CONTINUE return znc.CONTINUE
class Google: command = ".g" help = gib.ircstr("´Isearchterm´N | Does a quick google search.") shelp = gib.ircstr("´Iquery´N") resultre = re.compile('<h3 class="r"[^>]*><a href="([^"]+)"[^>]+>(.+)</a>') tire = re.compile('<title>(.*)</title>') htmlparser = html.parser.HTMLParser() apiKey = '' class HTMLStripper(html.parser.HTMLParser): class HTMLP(html.parser.HTMLParser): _data = "" def handle_data(self, data): self._data += str(data) def r(self): self._data = "" self.reset() htmlp = HTMLP() def strip(self, data): self.htmlp.feed(str(data)) self.htmlp.close() nudes = self.htmlp._data self.htmlp.r() return nudes htmlstripper = HTMLStripper() class RedirectHandler(HTTPRedirectHandler): def http_error_403(self, req, fp, code, msg, headers): return 0 def http_error_503(self, req, fp, code, msg, headers): return 0 def http_error_302(self, req, fp, code, msg, headers): result = HTTPRedirectHandler.http_error_302( self, req, fp, code, msg, headers) result.status = code return result def http_error_302(self, req, fp, code, msg, headers): result = HTTPRedirectHandler.http_error_302( self, req, fp, code, msg, headers) result.status = code return result def main(self, args, env={}): if not len(args): return '' link = self.search(args) if len(link): if len(link[1]): return gib.ircstr("{0} - ´B{1}´N").format(link[0], link[1]) else: return str(link[0]) else: return gib.ircstr("'´I{0}´N' did not match any documents.").format( ' '.join(args)) def search(self, query): response = self.open_page( "http://www.google.com/search?ie=UTF-8&oe=UTF-8&sourceid=navclient&complete=0&hl=en&q={0}" .format('+'.join([quote_plus(s) for s in query]))) link = [response.url, ''] found = True match = '' if link[0].find('google.com/search') != -1 or link[0].find( 'google.de/search') != -1: found = False pagestr = '' for line in iter(response.readline, b''): line = line.decode('utf8') pagestr += line if line.find('<h3 class="r">') != -1: match = line.split('</h3>')[0] found = True break if found and len(match): match = self.resultre.search(match) link[0] = self.htmlparser.unescape(match.group(1)) link[1] = self.htmlstripper.strip( self.htmlparser.unescape(match.group(2))) # Since we retrieve the title from Google we don't need to look it up again (with the chance of the page actually blocking us or similar) # if len(link[0]) and link[0]!=html.parser.HTMLParser().unescape(match): link[1] = self.get_title(opener.open(Request(link[0], None, {"User-Agent":"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.2 Safari/537.36"}))) else: link = [self.shorten(link[0]), self.get_title(pagestr)] else: link = [link[0], self.get_title(response)] return link def shorten(self, longUrl): data = "{{'longUrl': '{0}', 'key': '{1}'}}".format( longUrl.replace("'", r"\'"), self.apiKey).encode('utf8') headers = { "Content-Length": len(data), "Content-Type": "application/json" } req = Request('https://www.googleapis.com/urlshortener/v1/url', data, headers) page = urlopen(req) page = b''.join(page.readlines()).decode('utf8') page = json.loads(page) return page["id"] if ("id" in page and page["id"] != "") else longUrl def open_page(self, url): req = Request( url, None, { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.91 Safari/537.36" }) opener = build_opener(self.RedirectHandler()) return opener.open(req) def get_title(self, page, max_title_length=128): err = False try: page = b''.join(page.readlines()) try: page = page.decode('utf8') except UnicodeDecodeError: try: page = zlib.decompress(page, 15 + 32) except zlib.error: err = True except: if not isinstance(page, str): err = True if not err: title = self.tire.search(page.replace('\n', '')) title = title.groups()[0] if title and len( title.groups()) > 0 else '' else: title = '' return title if len( title) < max_title_length else title[0:max_title_length - 1]
class BakaUpdates: command = ".mu" help = gib.ircstr("´Isearchterm´N | Searches manga on Baka-Updates.") shelp = gib.ircstr("´Iquery´N") google = None class HTMLStripper(html.parser.HTMLParser): class HTMLP(html.parser.HTMLParser): _data = "" def handle_starttag(self, tag, attrs): if tag == "br": if self._data[-1] != " ": self._data += " " def handle_data(self, data): self._data += str(data) def r(self): self._data = "" self.reset() htmlp = HTMLP() def strip(self, data): self.htmlp.feed(str(data)) self.htmlp.close() nudes = self.htmlp._data self.htmlp.r() return nudes htmlstripper = HTMLStripper() def __init__(self): self.google = google.Google() def main(self, args, env={}): if not len(args): return '' link = self.google.search(args + ['site:mangaupdates.com/series.html']) if len(link): page = self.google.open_page(link[0]) page = b''.join(page.readlines()).decode('utf-8', 'ignore') html = lxml.html.document_fromstring(page) rating = self.get_rating(html) volumes = self.get_volumes(html) description = self.get_description(html) name = [str(link[0])] if not volumes in (None, ""): name.append(gib.ircstr('´C6´B´B' + volumes + '´N')) if not rating in (None, ""): name.append(gib.ircstr('´C7´B´B' + rating + '´N')) if not link[1] in (None, ""): name.append( gib.ircstr('´B' + link[1].replace('Baka-Updates Manga - ', '') + '´N')) name = ' :: '.join(name) if not description in (None, ""): name = [name, description] return name else: return gib.ircstr("'´I{0}´N' did not return anything.").format( ' '.join(args)) def get_description(self, html): if not html: return '' description = html.xpath( '//div[@class="sCat"]/b[text()="Description"]/../following-sibling::div[@class="sContent"][1]' ) if len(description) > 0: description = self.htmlstripper.strip( lxml.html.tostring( description[0]).decode('utf8').strip(' \n\t\r')).replace( '\n', '').replace('\r', '') #description = description[0].text_content().strip(' \n\t\r') return description if len(description) < 455 else ( description[:450] + ' ...') else: return '' def get_rating(self, html): if not html: return '' rating = html.xpath( '//div[@class="sCat"]/b[text()="User Rating"]/../following-sibling::div[@class="sContent"][1]' ) if len(rating) > 0: rating = rating[0].text_content().split( ' votes)')[0].split('\r')[0].replace('Average: ', '').replace( ' / 10.0 (', ' - ') + ' votes' return rating else: return '' def get_volumes(self, html): if not html: return '' volumes = html.xpath( '//div[@class="sCat"]/b[text()="Status in Country of Origin"]/../following-sibling::div[@class="sContent"][1]' ) if len(volumes) > 0: volumes = volumes[0].text_content().strip(' \n\t\r') return volumes else: return ''
class LastFM: command = ".np" help = gib.ircstr( "[´I.set´N/´I.unset´N] [´Iuser´N] | Returns last played song of ´Iuser´N (or own nick if none given). IRC nicks can be linked and unlinked with last.fm usernames respectively by calling ´I.np .set ´Blastfm-nick´N and ´I.np .unset´N. After this has been done, the linked IRC nick will not have to specify his last.fm username every time he calls ´I.np´N." ) shelp = gib.ircstr("[´Iusr´N]") userre = re.compile('^[a-zA-Z0-9*_-]{,15}$') network = None sql = None sqlc = None def __init__(self): self.network = pylast.LastFMNetwork('ID', 'APIKEY') try: exists = os.path.isfile('lastfm.db') self.sql = sqlite3.connect('lastfm.db') self.sqlc = self.sql.cursor() if not exists: self.sqlc.execute( 'CREATE TABLE nicks (irc varchar(30), lastfm varchar(15));' ) self.sql.commit() except: pass def main(self, args, env={}): user = '' if len(args) and args[0] and self.userre.match(args[0]): user = args[0] if not user and 'nick' in env: nick = env['nick'].GetNick() if len(args) == 2 and args[0] == '.set': if self.userre.match(args[1]): return self.set_nick(nick, args[1]) else: return gib.ircstr( '´I{0}´N is not a valid last.fm username.').format( args[1]) if len(args) == 1 and args[0] == '.unset': return self.unset_nick(nick) user = self.get_nick(nick) if not user and self.userre.match(nick): user = nick if not user: return gib.ircstr("Invalid user ´I{0}´N").format( args[0] if len(args[0]) else env['nick'].GetNick()) last_track = self.get_last_track(user) if 'error' in last_track: if last_track['error'] == 'not found': return gib.ircstr("´I{0}´N not found").format(user) elif last_track['error'] == 'no records': return gib.ircstr("´I{0}´N never played anything").format(user) else: return time = last_track['time'] time = (self.pretty_date(time) + ' ') if time != 0 else '' tags = last_track['tags'][:3] tags = (gib.ircstr('´C7´B´B') + gib.ircstr('´N, ´C7´B´B').join(tags) + gib.N) if len(tags) else 'no tags' loved = gib.ircstr('´C4♥´N ') if last_track['loved'] else '' play = self.ordn(last_track['userplaycount']) album = (gib.ircstr('[´C13´B´B') + last_track['album'].title + gib.ircstr('´N] ')) if last_track['album'] else '' resp = gib.ircstr( '´C11{0}´N {1} listening to "´C10´B{2}´N" {3}by ´C12´B{4}´N {5}{6}for the {7} time, {8} plays by {9} listeners. ({10})' ) resp = resp.format(user, 'was' if time != '' else 'is', last_track['track'], loved, last_track['artist'], album, time, play, last_track['globalplaycount'], last_track['listeners'], tags) # if type(time) == int and time == 0: # resp = gib.ircstr('´C11´I{0}´N is currently listening to "´C10´B{1}´N" by ´C12´I{2}´N{3} {4}for the {5} time, {6} global plays by {7} listeners. ({8})') # resp = resp.format(user, last_track['track'], last_track['artist'], album, loved, play, last_track['globalplaycount'], last_track['listeners'], tags) # else: # resp = gib.ircstr('´C11´I{0}´N was listening to "´C10´B{1}´N" by ´C12´I{2}´N{3} {4}about {5} for the {6} time, {7} global plays by {8} listeners. ({9})') # resp = resp.format(user, last_track['track'], last_track['artist'], album, loved, time, play, last_track['globalplaycount'], last_track['listeners'], tags) return resp def get_last_track(self, user): try: track = self.network.get_user(user).get_now_playing() except pylast.WSError: return {'error': 'not found'} now = True time = 0 if not track: now = False try: track = self.network.get_user(user).get_recent_tracks()[0] except IndexError: return {'error': 'no records'} time = int(track.timestamp) track = track.track album = track.get_album() track.username = user userloved = track.get_userloved() userplays = int(track.get_userplaycount()) + (1 if now else 0) plays = int(track.get_playcount()) listeners = int(track.get_listener_count()) t1 = track._request('track.getInfo').getElementsByTagName('toptags') tags = [] if len(t1): t1 = t1[0].getElementsByTagName('tag') for tag in t1: tags.append( tag.getElementsByTagName('name') [0].childNodes[0].nodeValue) t2 = track.artist._request('artist.getInfo').getElementsByTagName( 'tags') if len(t2): t2 = t2[0].getElementsByTagName('tag') for tag in t2: tags.append( tag.getElementsByTagName('name') [0].childNodes[0].nodeValue) return { 'track': track.title, 'artist': track.artist, 'album': album, 'time': time, 'loved': userloved, 'userplaycount': userplays, 'globalplaycount': plays, 'listeners': listeners, 'tags': tags } def set_nick(self, ircnick, lfmnick): if self.sqlc: old = self.sqlc.execute('SELECT * FROM nicks WHERE irc = ?', (ircnick, )).fetchall() all = self.sqlc.execute('SELECT * FROM nicks WHERE lastfm = ?', (lfmnick, )).fetchall() if len(old): self.sqlc.execute('UPDATE nicks SET lastfm = ? WHERE irc = ?', (lfmnick, ircnick)) else: self.sqlc.execute('INSERT INTO nicks VALUES (?, ?)', (ircnick, lfmnick)) self.sql.commit() if not (ircnick, lfmnick) in all: all.append((ircnick, lfmnick)) all = [e[0] for e in all] all = gib.ircstr('´N, ´I').join(all) return gib.ircstr('´I{0}´N is now linked with ´I{1}´N.').format( lfmnick, all) else: return '' def unset_nick(self, ircnick): if self.sqlc: irc = self.sqlc.execute('SELECT * FROM nicks WHERE irc = ?', (ircnick, )).fetchall() if len(irc): self.sqlc.execute('DELETE FROM nicks WHERE irc = ?', (ircnick, )) self.sql.commit() return gib.ircstr( '´I{0}´N is not linked with ´I{1}´N anymore.').format( ircnick, irc[0][1]) else: return gib.ircstr( '´I{0}´N is not currently linked with any last.fm username.' ) else: return '' def get_nick(self, ircnick): if self.sqlc: nick = self.sqlc.execute('SELECT lastfm FROM nicks WHERE irc = ?', (ircnick, )).fetchall() if len(nick): return nick[0][0] else: return None else: return None def ordn(self, n): # if n <= 10: return ['first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh', 'eighth', 'ninth', 'tenth'][n-1] # else: return str(n)+("th" if 4<=n%100<=20 else {1:"st",2:"nd",3:"rd"}.get(n%10, "th")) return str(n) + ("th" if 4 <= n % 100 <= 20 else { 1: "st", 2: "nd", 3: "rd" }.get(n % 10, "th")) def pretty_date(self, time=False): """ Get a datetime object or a int() Epoch timestamp and return a pretty string like 'an hour ago', 'yesterday', '3 months ago', 'just now', etc """ now = datetime.datetime.now() if type(time) is int: diff = now - datetime.datetime.fromtimestamp(time) elif isinstance(time, datetime.datetime): diff = now - time elif not time: diff = now - now second_diff = diff.seconds day_diff = diff.days if day_diff < 0: return '' if day_diff == 0: if second_diff < 10: return "just now" if second_diff < 60: return str(second_diff) + " seconds ago" if second_diff < 120: return "a minute ago" if second_diff < 3600: return str(int(second_diff / 60)) + " minutes ago" if second_diff < 7200: return "an hour ago" if second_diff < 86400: return str(int(second_diff / 3600)) + " hours ago" if day_diff == 1: return "yesterday" if day_diff < 7: return str(day_diff) + " days ago" if day_diff < 31: return str(int(day_diff / 7)) + " weeks ago" if day_diff < 365: return str(int(day_diff / 30)) + " months ago" return str(int(day_diff / 365)) + " years ago"
try: del sys.modules['gib'] except KeyError: pass try: del sys.modules['logger'] except KeyError: pass import gib import logger L = logger.Logger() L.setloglevel(L.INFO) L.setlogpath(filepath + '/GIB.log') L.log(L.INFO, 'STARTED') modules = {'google', 'anidb', 'ann', 'vndb', 'vgmdb', 'mal', 'trans', 'lastfm', 'wa', 'mangaupdates', 'batoto'} modules = dict.fromkeys(modules, '') Modules = modules commands = {} help = gib.ircstr("´B.help´N [´Icmd´N]") # So that we can just import them by name of the script sys.path.append(filepath + '/gib/') for mod in modules: try: del sys.modules[mod] except KeyError: pass modules[mod] = importlib.import_module(mod) try: Modules[mod] = getattr(modules[mod], modules[mod].name)() help += ', ' + gib.B + Modules[mod].command + gib.N + ' ' + Modules[mod].shelp commands[Modules[mod].command] = mod except Exception as e: L.log(L.ERROR, str(e)) class GIB(znc.Module):
def OnChanMsg(self, nick, channel, message): global L, modules, Modules, commands, help # Get some basic stuff net = self.GetNetwork() me = net.GetNick() msg = message.s msglst = msg.split() nik = nick.GetNick() try: # It's either a znc.CChan or a znc.CNick, everything else we just don't accept chan = channel.GetName( ) if type(channel) is znc.CChan else channel.GetNick() except Exception: return znc.CONTINUE if nik == "Satsuki": return znc.CONTINUE if (self.use_channel_blacklist and chan in self.channel_blacklist) \ or (self.use_channel_whitelist and not chan in self.channel_whitelist): return znc.CONTINUE # Some anti-flooding procedures. Not the best, but it works vOv if msglst[0] in commands: #if not (nik in self.user_whitelist permstr = channel.FindNick( nik).GetPermStr() if type(channel) is znc.CChan else '' if not (self.abure.sub('\\1', nick.GetHost()) in self.user_whitelist or nik in self.user_whitelist) \ and all(permstr.find(p) < 0 for p in ['~', '&', '@', '%']): if use_user_whitelist: return znc.CONTINUE currenttime = time.mktime(time.gmtime()) if currenttime - self.cooldown[0] < 90: return znc.CONTINUE if currenttime - self.cooldown[-1] < 5: return znc.CONTINUE if currenttime <= self.cooluntil: return znc.CONTINUE if all(t >= currenttime - 45 for t in self.cooldown): self.cooluntil = currenttime + 300 self.put_msg(chan, 'Yamete! >///<') L.log(L.INFO, chan + " flooded by " + nik + ", msg: " + msg, self.GetSavePath() + "/modules.log") self.cooldown.append(currenttime) if len(self.cooldown) > 5: self.cooldown.pop(0) if self.cooluntil > currenttime: return znc.CONTINUE if currenttime - self.cooldown[0] < 90: self.put_msg(chan, 'Yamete! >///<') if currenttime - self.cooldown[-1] < 5: self.put_msg(chan, 'Yamete! >///<') if msglst[0] == '.help' \ or (msglst[0].lower() in [me.lower(), 'sawako', 'sadako'] and msglst[1].lower() == 'help') \ or (msglst[0].lower() in ['hi', 'hello', 'yo', 'hey'] and msglst[1].lower() in [me.lower(), 'sawako', 'sadako']): if msglst[0].lower() in ['hi', 'hello', 'yo', 'hey']: greeting = random.choice(['Hi', 'Hello', '今日は', 'Konnichiwa']) self.put_msg(channel.GetName(), greeting + ' ' + nik + '!') if msglst[0] == '.help': args = msglst[1:] else: args = msglst[2:] if not len(args): self.put_notice(nik, 'Possible commands: ' + help) self.put_notice( nik, gib.ircstr('For more details: ´B/msg ' + me + ' help´N')) return znc.CONTINUE if args[0] in commands: mod = Modules[commands[args[0]]] self.put_notice(nik, gib.B + mod.command + gib.N + ' ' + mod.help) return znc.CONTINUE if msglst[0] in commands: cmd = msglst[0] mod = commands[cmd] mod = Modules[mod] args = msglst[1:] now = time.time() ret = '' chan = channel.GetName() chan = (chan[:12] + (chan[12:] and '..')).ljust(14) L.log(L.INFO, chan + " call: " + cmd + ", args: " + str(args), self.GetSavePath() + "/modules.log") try: env = {'nick': nick, 'channel': channel, 'self': self} ret = mod.main(args, env) if len(ret): if 'c' in str(channel.GetModeString()): ret = self.colorre.sub('', ret) self.put_msg(channel, ret) except Exception as e: L.log(L.ERROR, chan + " error: " + str(e), self.GetSavePath() + "/modules.log") traceback.print_exc( file=open(self.GetSavePath() + "/traceback.log", "a")) L.log( L.INFO, chan + " finish: " + cmd + ", (" + str(int((time.time() - now) * 1000)) + "ms)", self.GetSavePath() + "/modules.log") return znc.CONTINUE return znc.CONTINUE