def action(self, complete): msg = complete.message() user = complete.user() users = {} for nicknick in settingsHandler.readSetting(complete.cmd()[0], "IRCnick, LASTFMnick"): users.update({nicknick[0].lower(): nicknick[1]}) if msg != "": user = msg if len(msg.split()) >= 2: if msg.split()[0] == "-link": settingsHandler.writeSetting( complete.cmd()[0], ["IRCnick", "LASTFMnick"], [complete.user(), " ".join(msg.split()[1:])] ) return ["PRIVMSG $C$ :Linked %s to %s" % (complete.user(), " ".join(msg.split()[1:]))] try: if user.lower() in users.keys(): name = users[user.lower()] else: name = user url = "http://ws.audioscrobbler.com/1.0/user/" + name + "/recenttracks.rss" p = urllib2.urlopen(url).read() p = re.search( "<description>Last 10 tracks submitted to Last.fm</description>(.*)</item>", p, re.DOTALL ).group(1) l = re.search("<link>(.*?)</link>", p, re.DOTALL).group(1) p = re.search("<title>(.*?)</title>", p, re.DOTALL).group(1) if len(l) > 50: l = bitly(l) p = p.split("\xe2\x80\x93") msg = user + " is listening to" + p[1].decode("utf-8") + " by " + p[0].decode("utf-8") + " (" + l + ")" except: msg = "I don't know what " + user + " is listening to. Sorry." return ["PRIVMSG $C$ :" + msg]
def action(self, complete): tags = complete.message() query = urllib.urlencode(dict([["tags",tags]])) url = "http://safebooru.org/index.php?page=dapi&s=post&q=index&limit=200&"+query try: req=urllib2.urlopen(urllib2.Request(url, headers={'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:23.0) Gecko/20100101 Firefox/23.0'})) except urllib2.HTTPError as error: if '406' in str(error): return ["PRIVMSG $C$ :Unacceptable input."] return ["PRIVMSG $C$ :Safebooru seems down!"] except Exception as e: print e return ["PRIVMSG $C$ :ERROR: !animu threw an awful exception..."] content = req.read() matches = re.findall(r'file_url="(.+?)"(?:.+?)rating="(?:s|q)" tags="\s?(.+?)\s?" id="(\d+?)"', content) if matches == []: return ["PRIVMSG $C$ :No pictures found!"] w_matches = [] for match in matches: if not match[2] in self.history: w_matches.append(match) if w_matches == []: return ["PRIVMSG $C$ :No new picture found (Compared to the last 60 pictures)"] match = w_matches[random.randint(0, len(w_matches)-1)] self.history.append(match[2]) self.history = self.history[-60:] url = match[0] tags = match[1].split(' ') total_length = 0 i = 0 for tag in tags: if total_length + len(tag) > 280: tags = tags[:i] + ['...'] break i += 1 total_length += len(tag) tags = ' '.join(tags) return ["PRIVMSG $C$ :" + bitly(url) + " (tags: " + tags + ")"]
def parsePonibooru(url, pageData): print "Getting tags" tags = re.findall("<textarea\s*?name='tag_edit__tags'.*?>(.*?)</textarea>", pageData)[0] print "Stats" stats = re.findall("<div id='Statisticsleft'>(.*?<)/div>", pageData)[0] print "ID" id = re.findall("Id:\s([0-9]*)", stats)[0] print "Size" size = re.findall("Size: (.+?)<", stats)[0].strip() print "Filesize" filesize = re.findall("Filesize: (.+?)<", stats)[0].strip() print "Source" source = re.findall("Source: <a href='(.+?)'", stats) if (source != []): source = source[0].strip() if len(source) > 20: source = bitly(source) else: source = "" return ["PRIVMSG $C$ :Image Tags: %s; Dimensions: %s; Filesize: %s; %s"%(tags, size, filesize, "Source: %s;"%source if source!="" else "")]
def action(self, complete): msg = complete.message() user = complete.user() users = {} for nicknick in settingsHandler.readSetting(complete.cmd()[0], "IRCnick, LASTFMnick"): users.update({nicknick[0].lower(): nicknick[1]}) if msg != "": user = msg if len(msg.split()) >= 2: if msg.split()[0] == "-link": settingsHandler.writeSetting( complete.cmd()[0], ["IRCnick", "LASTFMnick"], [complete.user(), ' '.join(msg.split()[1:])]) return [ "PRIVMSG $C$ :Linked %s to %s" % (complete.user(), ' '.join(msg.split()[1:])) ] try: if user.lower() in users.keys(): name = users[user.lower()] else: name = user url = "http://ws.audioscrobbler.com/1.0/user/" + name + "/recenttracks.rss" p = urllib2.urlopen(url).read() p = re.search( "<description>Last 10 tracks submitted to Last.fm</description>(.*)</item>", p, re.DOTALL).group(1) l = re.search("<link>(.*?)</link>", p, re.DOTALL).group(1) p = re.search("<title>(.*?)</title>", p, re.DOTALL).group(1) if len(l) > 50: l = bitly(l) p = p.split('\xe2\x80\x93') msg = user + " is listening to" + p[1].decode( 'utf-8') + " by " + p[0].decode('utf-8') + " (" + l + ")" except: msg = "I don't know what " + user + " is listening to. Sorry." return ["PRIVMSG $C$ :" + msg]
def __init__(self,Queue, inputQueue, channel): self.Queue=Queue running = True initComplete = False #To silence input before startup is handled colour="\x03" self.Queue.put("#PRIVMSG %s :RSS Reader started up successfully\r\n"%(channel)) feeds = [] feedNames = {} latestFeedItem = {} checkFrequencies=[10,20,30,60,120,180,240,300] lastReadWasBlank=0 checkFrequency=0 while running: while not inputQueue.empty(): data = inputQueue.get() if data=="stop": running = False break if data.split()[0]=="add": feedLink = data.split()[1] if feedLink[:7]=="http://": feedLink = feedLink[7:] feeds.append(feedLink) potentialName = ' '.join(data.split()[2:]) if potentialName.strip()=="": potentialName = feedLink feedNames[feedLink] = potentialName feed=feedparser.parse("http://"+feedLink) if (len(feed.entries) == 0): continue latestFeedItem[feedLink]=feed.entries[0].id if initComplete: Queue.put("#PRIVMSG %s :Added feed to list!\r\n"%channel) if data.split()[0]=="remove": if data.split()[1] in feeds: feeds.remove(data.split()[1]) if initComplete: Queue.put("#PRIVMSG %s :Removed feed from list!\r\n"%channel) else: if initComplete: Queue.put("#PRIVMSG %s :Feed not currently being read!\r\n"%channel) if data.split()[0]=="intervals": checkFrequencies = [int(checkTime) for checkTime in data.split()[1:]] checkFrequency = 0 if initComplete: Queue.put("#PRIVMSG %s :Set check intervals\r\n"%channel) if data.split()[0]=="list": if initComplete: Queue.put("#PRIVMSG %s :RSS Reader for channel %s is following:\r\n"%(channel, channel)) for feed in feeds: Queue.put("#PRIVMSG %s :%s: %s\r\n"%(channel, feedNames[feed], feed)) if data=="--init--": initComplete = True try: for feedName in feeds: feed=feedparser.parse("http://"+feedName) if (len(feed.entries) == 0): continue newFeedItem=feed.entries[0].id newItems=[] if newFeedItem!=latestFeedItem[feedName]: iterateBack=0 while (feed.entries[iterateBack].id!=latestFeedItem[feedName] and iterateBack<len(feed.entries)-1 and iterateBack < 5): newItems.append ((feed.entries[iterateBack].link, feed.entries[iterateBack].title)) iterateBack+=1 latestFeedItem[feedName]=newFeedItem for item in newItems: Queue.put("#PRIVMSG "+channel+" :\x02"+feedNames[feedName]+"\x02: "+item[1]+" (at \x02"+(item[0] if len(item[0])<20 else bitly(item[0]))+"\x02)\r\n") if checkFrequency>0: checkFrequency-=len(newItems) checkFrequency=0 if checkFrequency<0 else checkFrequency if len(newItems)==0: if checkFrequency<len(checkFrequencies)-1 and lastReadWasBlank: checkFrequency+=1 lastReadWasBlank=0 lastReadWasBlank=1 except Exception as detail: print "RSS Grabbing failure! Bad feed?" print detail traceback.print_exc() time.sleep(60) time.sleep(checkFrequencies[checkFrequency]) Queue.put("#PRIVMSG "+channel+" :RSS Reader shut down.\r\n")
def action(self, complete): tags = complete.message() query = urllib.urlencode(dict([["tags",tags]])) url = "http://chan.sankakucomplex.com/en/post/index.content?limit=150&"+query try: req=self.opener.open(url) except urllib2.HTTPError as error: if '406' in str(error): if len(tags.split(' ')) > 4: return ["PRIVMSG $C$ :More than 4 tags are not allowed."] if '-' in tags: return ["PRIVMSG $C$ :You may not search for exclusive tags only."] return ["PRIVMSG $C$ :Unacceptable input (reason unknown)."] return ["PRIVMSG $C$ :Sankaku channel seems down!"] content=req.read() pattern = r'href="(.+?)".+?src="(.+?)".+?title="(.+?)"' matches = re.findall(pattern, content) start = 0 for u, t in self.recent: if t < time.time() - 15 * 60: start += 1 recent = [x for x,y in self.recent[start:]] possibilites = [] for href,src,title in matches: if not href in recent: possibilites.append((href, src, title)) if possibilites == []: return ["PRIVMSG $C$ :No pictures found!"] match = random.choice(possibilites) self.recent.append((match[0], time.time())) if match[1].find('download')>-1: url = 'http://chan.sankakucomplex.com' + match[0] else: url = match[1].replace('preview/','') url = re.sub('http://c\d','http://chan',url) try: urllib2.urlopen(url) except: url = url[:-3] + 'png' try: urllib2.urlopen(url) except: url = url[:-3] + 'gif' try: urllib2.urlopen(url) except: url = match[0] tags = [] tags_old = match[2].split(' ') rating = 'unknown' for tag in tags_old: if tag[:7] == 'rating:': rating = tag[7:] break tags += [tag] total_length = 0 i = 0 for tag in tags: if total_length + len(tag) > 150: tags = tags[:i] + ['...'] break i += 1 total_length += len(tag) tags = ' '.join(tags) print tags return ["PRIVMSG $C$ :" + bitly(url) + " (rating: \x02" + rating + "\x02, tags: " + unicode(tags, 'utf-8') + ")"]
def action(self, complete): m = complete.message().lower() fileName = complete.user() + '.wav' settings = self.re_settings.match(m) if settings: if settings.group(1) and settings.group(1) in self.functions: f = self.functions[settings.group(1)] else: f = self.triangle if settings.group(2): bpm = int(settings.group(2)) else: bpm = 120 else: f = self.triangle bpm = 120 speed = 60.0 * self.framerate / (bpm * 4) if speed < 300: return ["PRIVMSG $C$ :Range error: too fast."] terms = self.re_init.findall(m) if len(terms) == 0: return ["PRIVMSG $C$ :Parsing error: please revise your tune."] data = '' d = {} currentlyPlaying = [] for note in self.deltas: d[note] = 0 length = 0 durations = {} termnotes = {} for term in terms: m = self.re_term.match(term) if m == None: return ["PRIVMSG $C$ :Error: Could not parse term %s" % term] notes = self.re_note.findall(term) for note in notes: if not note in d: return ["PRIVMSG $C$ :Error: Note %s not supported." % note] termnotes[term] = set(notes) duration = 0 for c in m.group('duration'): if c == '.': duration += 1 elif c == '-': duration += 2 elif c == '+': duration += 4 elif c == 'o': duration += 8 durations[term] = duration length += duration * speed if length > 2300000: return ["PRIVMSG $C$ :Error: estimated file size too large."] for term in terms: duration = durations[term] notes = termnotes[term] m = self.re_term.match(term) i = 0 for note in d: if not note in notes: d[note] = 0 fade = 1 while i < duration * speed: a = 0 for note in notes: d[note] += self.deltas[note] if d[note] > 1: d[note] -= 1 a += f(d[note]) a = min(max(int(32767.5 * a * fade / 4),-32768),32767) data += wave.struct.pack('h', a) i += 1 fade -= 0.00001 if fade < 0: fade = 0 w = wave.open('/home/py/public_html/tunes/' + fileName, 'wb') w.setframerate(self.framerate) w.setnchannels(1) w.setsampwidth(2) w.writeframes(data) w.close() return ['PRIVMSG $C$ :' + bitly('http://terminus.mrflea.net:81/~py/tunes/' + fileName)]
def action(self, complete): m = complete.message().lower() fileName = complete.user() + '.wav' settings = self.re_settings.match(m) if settings: if settings.group(1) and settings.group(1) in self.functions: f = self.functions[settings.group(1)] else: f = self.triangle if settings.group(2): bpm = int(settings.group(2)) else: bpm = 120 else: f = self.triangle bpm = 120 speed = 60.0 * self.framerate / (bpm * 4) if speed < 300: return ["PRIVMSG $C$ :Range error: too fast."] terms = self.re_init.findall(m) if len(terms) == 0: return ["PRIVMSG $C$ :Parsing error: please revise your tune."] data = '' d = {} currentlyPlaying = [] for note in self.deltas: d[note] = 0 length = 0 durations = {} termnotes = {} for term in terms: m = self.re_term.match(term) if m == None: return ["PRIVMSG $C$ :Error: Could not parse term %s" % term] notes = self.re_note.findall(term) for note in notes: if not note in d: return [ "PRIVMSG $C$ :Error: Note %s not supported." % note ] termnotes[term] = set(notes) duration = 0 for c in m.group('duration'): if c == '.': duration += 1 elif c == '-': duration += 2 elif c == '+': duration += 4 elif c == 'o': duration += 8 durations[term] = duration length += duration * speed if length > 2300000: return ["PRIVMSG $C$ :Error: estimated file size too large."] for term in terms: duration = durations[term] notes = termnotes[term] m = self.re_term.match(term) i = 0 for note in d: if not note in notes: d[note] = 0 fade = 1 while i < duration * speed: a = 0 for note in notes: d[note] += self.deltas[note] if d[note] > 1: d[note] -= 1 a += f(d[note]) a = min(max(int(32767.5 * a * fade / 4), -32768), 32767) data += wave.struct.pack('h', a) i += 1 fade -= 0.00001 if fade < 0: fade = 0 w = wave.open('/home/py/public_html/tunes/' + fileName, 'wb') w.setframerate(self.framerate) w.setnchannels(1) w.setsampwidth(2) w.writeframes(data) w.close() return [ 'PRIVMSG $C$ :' + bitly('http://terminus.mrflea.net:81/~py/tunes/' + fileName) ]
def action(self, complete): channel = complete.channel().lower() nickFilter = [] nickExclude = [] days = 10 marks = [] nextCommand='' terms = complete.message().split() i = 0 try: while i < len(terms): if terms[i] == '-days': days = int(terms[i+1]) i += 2 elif terms[i] == '-nick': j = i + 1 while j < len(terms) and terms[j][0] != '-': j += 1 nickFilter += map(lambda x: x.lower(), terms[i+1:j]) i = j elif terms[i] == '-not': j = i + 1 while j < len(terms) and terms[j][0] != '-': j += 1 nickExclude += map(lambda x: x.lower(), terms[i+1:j]) i = j elif terms[i] == '-mark': j = i + 1 while j < len(terms) and terms[j][0] != '-': j += 1 marks += map(lambda x: x.lower(), terms[i+1:j]) i = j else: raise Exception("Incorrect input") except Exception as e: print e return ["PRIVMSG $C$ :Invalid usage. Correct usage: %s%s [-days Number of days to " "search] [-mark Words to highlight] [-nick Users to filter on] " "[-not Users to exclude]"%(globalv.commandCharacter, complete.cmd()[0])] wordCollection = {} width = 1024 height = 1024 today=time.gmtime() currentYear=today[0] currentDay=today[7] logFails = 0 relevantNicks = set() for offset in xrange(days): day = currentDay-offset year = currentYear if day <= 0: day += 365 year-=1 path=os.path.join("logs","LogFile - "+channel+"-"+str(year)+"-"+str(day)) if not os.path.exists(path): print path logFails += 1 if logFails > 3: break else: continue data=open(path).readlines() for line in data: line=re.search("^\[.*?\] \* (?P<nick>[^\s]*)( \*)? (?P<message>.+)", line) if line is None: continue nick = line.group('nick').lower() if nick in nickExclude: continue if nickFilter != []: if nick not in nickFilter: continue else: relevantNicks.add(nick) message = line.group('message') message = self.re_markup.sub('',message) words = message.split() for word in words: wordNew = word.rstrip('"\'!?]).,;:').lstrip('"\'([') if wordNew == '': wordNew = word wordNew = wordNew.lower() wordCollection[wordNew] = wordCollection.setdefault(wordNew,0)+1 if len(wordCollection) == 0: return ["PRIVMSG $C$ :No words found!"] relevantNicks = sorted(relevantNicks) fileName = 'picture-%s' % channel if nickFilter != []: fileName += '-%s' % (','.join(relevantNicks)) fileName += '.png' im = wordCloud(wordCollection, marks, r'/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf', width, height) im.save("/home/py/public_html/omgbot/images/%s" % fileName, "PNG") return ["PRIVMSG $C$ :" + bitly('http://achene.phantomflame.com/~py/omgbot/images/%s' % (fileName.replace('#','%23')))]
def __init__(self, Queue, inputQueue, channel): self.Queue = Queue running = True initComplete = False #To silence input before startup is handled colour = "\x03" self.Queue.put("#PRIVMSG %s :RSS Reader started up successfully\r\n" % (channel)) feeds = [] feedNames = {} latestFeedItem = {} checkFrequencies = [10, 20, 30, 60, 120, 180, 240, 300] lastReadWasBlank = 0 checkFrequency = 0 while running: while not inputQueue.empty(): data = inputQueue.get() if data == "stop": running = False break if data.split()[0] == "add": feedLink = data.split()[1] if feedLink[:7] == "http://": feedLink = feedLink[7:] feeds.append(feedLink) potentialName = ' '.join(data.split()[2:]) if potentialName.strip() == "": potentialName = feedLink feedNames[feedLink] = potentialName feed = feedparser.parse("http://" + feedLink) if (len(feed.entries) == 0): continue latestFeedItem[feedLink] = feed.entries[0].id if initComplete: Queue.put("#PRIVMSG %s :Added feed to list!\r\n" % channel) if data.split()[0] == "remove": if data.split()[1] in feeds: feeds.remove(data.split()[1]) if initComplete: Queue.put( "#PRIVMSG %s :Removed feed from list!\r\n" % channel) else: if initComplete: Queue.put( "#PRIVMSG %s :Feed not currently being read!\r\n" % channel) if data.split()[0] == "intervals": checkFrequencies = [ int(checkTime) for checkTime in data.split()[1:] ] checkFrequency = 0 if initComplete: Queue.put("#PRIVMSG %s :Set check intervals\r\n" % channel) if data.split()[0] == "list": if initComplete: Queue.put( "#PRIVMSG %s :RSS Reader for channel %s is following:\r\n" % (channel, channel)) for feed in feeds: Queue.put("#PRIVMSG %s :%s: %s\r\n" % (channel, feedNames[feed], feed)) if data == "--init--": initComplete = True try: for feedName in feeds: feed = feedparser.parse("http://" + feedName) if (len(feed.entries) == 0): continue newFeedItem = feed.entries[0].id newItems = [] if newFeedItem != latestFeedItem[feedName]: iterateBack = 0 while (feed.entries[iterateBack].id != latestFeedItem[feedName] and iterateBack < len(feed.entries) - 1 and iterateBack < 5): newItems.append((feed.entries[iterateBack].link, feed.entries[iterateBack].title)) iterateBack += 1 latestFeedItem[feedName] = newFeedItem for item in newItems: Queue.put("#PRIVMSG " + channel + " :\x02" + feedNames[feedName] + "\x02: " + item[1] + " (at \x02" + (item[0] if len(item[0]) < 20 else bitly( item[0])) + "\x02)\r\n") if checkFrequency > 0: checkFrequency -= len(newItems) checkFrequency = 0 if checkFrequency < 0 else checkFrequency if len(newItems) == 0: if checkFrequency < len( checkFrequencies) - 1 and lastReadWasBlank: checkFrequency += 1 lastReadWasBlank = 0 lastReadWasBlank = 1 except Exception as detail: print "RSS Grabbing failure! Bad feed?" print detail traceback.print_exc() time.sleep(60) time.sleep(checkFrequencies[checkFrequency]) Queue.put("#PRIVMSG " + channel + " :RSS Reader shut down.\r\n")
def action(self, complete): tags = complete.message() query = urllib.urlencode(dict([["tags",tags]])) url = "http://ponibooru.413chan.net/post/list/%s/1"%urllib.quote(tags) try: req=self.opener.open(url) except urllib2.HTTPError as error: if '406' in str(error): if len(tags.split(' ')) > 4: return ["PRIVMSG $C$ :More than 4 tags are not allowed."] if '-' in tags: return ["PRIVMSG $C$ :You may not search for exclusive tags only."] return ["PRIVMSG $C$ :Unacceptable input (reason unknown)."] return ["PRIVMSG $C$ :Sankaku channel seems down!"] content=req.read() pages = re.findall("/post/list/([0-9]+)", content) if pages!=[]: maxPage = int(max(pages, key=lambda x: int(x))) newPage = random.randint(1,maxPage) url = "http://ponibooru.413chan.net/post/list/%s/%s"%(urllib.quote(tags), newPage) content = self.opener.open(url).read() pattern = r"href='(.+?)'.+?title='(.+?) // .+?'.+?src='(.+?)'" matches = re.findall(pattern, content) start = 0 for u, t in self.recent: if t < time.time() - 15 * 60: start += 1 recent = [x for x,y in self.recent[start:]] possibilites = [] for href,title, src in matches: if not href in recent: possibilites.append((href, src, title)) if possibilites == []: return ["PRIVMSG $C$ :No pictures found!"] match = random.choice(possibilites) self.recent.append((match[0], time.time())) url = "http://ponibooru.413chan.net/"+match[0] tags = [] tags_old = match[2].split(' ') rating = 'unknown' for tag in tags_old: if tag[:7] == 'rating:': rating = tag[7:] break tags += [tag] total_length = 0 i = 0 for tag in tags: if total_length + len(tag) > 150: tags = tags[:i] + ['...'] break i += 1 total_length += len(tag) tags = ' '.join(tags) print tags return ["PRIVMSG $C$ :" + bitly(url) + " (tags: " + unicode(tags, 'utf-8') + ")"]
from bitlyServ import bitly import globalv,re class pluginClass(plugin):
# -*- coding: utf-8 -*-