def answer(self, msg): correct = False for ans in self.a: dist = self.DL(str.lower(msg.args[1]), str.lower(ans)) flexibility = self.registryValue('flexibility', self.channel) if dist <= len(ans) / flexibility: correct = True #if self.registryValue('debug'): # self.reply('Distance: %d' % dist) if correct: if not msg.nick in self.scores: self.scores[msg.nick] = 0 self.scores[msg.nick] += 1 if not msg.nick in self.roundscores: self.roundscores[msg.nick] = 0 self.roundscores[msg.nick] += 1 self.unanswered = 0 gotit = '%s got it!' % (msg.nick) gotit = ircutils.bold(gotit) points= ircutils.bold('Points') self.reply('%s The full answer was: %s. %s: %d' % (gotit, self.a[0], points, self.scores[msg.nick])) schedule.removeEvent('next_%s' % self.channel) self.writeScores() self.newquestion()
def doPrivmsg(self, irc, msg): if self.registryValue("enable", msg.args[0]): # If this is a youtube link, commence lookup if msg.args[1].find("youtu") != -1: for word in msg.args[1].split(" "): if word.find("youtu") != -1: try: videoid = urlparse(word.replace("#!", "?"))[4].split("v=")[1].split("&")[0] except: videoid = urlparse(word)[2].split("/")[1] f = urllib.urlopen("http://gdata.youtube.com/feeds/videos/%s" % (videoid)) parser = xml.sax.make_parser() handler = YoutubeHandler() parser.setContentHandler(handler) parser.parse(f) # log.critical('Title: %s' % handler.title) # log.critical('Author: %s' % handler.author) # log.critical('Rating: %s' % handler.rating) # log.critical('Views: %s' % handler.views) # log.critical('Rating Count: %s' % handler.rating_count) # log.critical('Duration: %s' % handler.duration) irc.reply( "Title: %s, Views: %s, Rating: %s%%" % ( ircutils.bold(handler.title), ircutils.bold(handler.views), ircutils.bold(handler.rating), ) )
def lastfm(self, irc, msg, args, method, optionalId): """<method> [<id>] Lists LastFM info where <method> is in [friends, neighbours, profile, recenttracks, tags, topalbums, topartists, toptracks]. Set your LastFM ID with the set method (default is your current nick) or specify <id> to switch for one call. """ id = (optionalId or self.db.getId(msg.nick) or msg.nick) channel = msg.args[0] maxResults = self.registryValue("maxResults", channel) method = method.lower() url = "%s/%s/%s.txt" % (self.APIURL_1_0, id, method) try: f = urllib2.urlopen(url) except urllib2.HTTPError: irc.error("Unknown ID (%s) or unknown method (%s)" % (msg.nick, method)) return lines = f.read().split("\n") content = map(lambda s: s.split(",")[-1], lines) id = id + "'s" id = ircutils.bold(id) method = method + ":" method = ircutils.bold(method) irc.reply("%s %s %s (with a total number of %i entries)" % (id, method, ", ".join(content[0:maxResults]), len(content)))
def newquestion(self): inactiveShutoff = self.registryValue('inactiveShutoff', self.channel) if self.num == 0: self.active = False elif self.unanswered > inactiveShutoff and inactiveShutoff >= 0: shutoff = ircutils.bold('Seems like no one\'s playing any more.') self.reply('%s.' % shutoff) self.active = False elif len(self.questions) == 0: self.reply('Oops! I ran out of questions!') self.active = False if not self.active: self.stop() return self.hints = 0 self.num -= 1 self.numAsked += 1 which = self.rng.randint(0, len(self.questions)-1) q = self.questions.pop(which) sep = self.registryValue('questionFileSeparator') self.q = q[:q.find(sep)] self.a = q[q.find(sep)+len(sep):].split(sep) color = self.registryValue('color', self.channel) qnum = '#%d of %d' % (self.numAsked, self.total) qnum = ircutils.bold(qnum) self.reply('%s: \x03%s%s' % (qnum, color, self.q)) def event(): self.timedEvent() timeout = self.registryValue('timeout', self.channel) numHints = self.registryValue('numHints', self.channel) eventTime = time.time() + timeout / (numHints + 1) if self.active: schedule.addEvent(event, eventTime, 'next_%s' % self.channel)
def tv(self, irc, msg, args, text): """<show name> searches tvrage.com for <show name> and returns info about both the previous and upcoming episodes """ re_last = re.compile(r'Latest\sEpisode@(.*?\d{4})') re_next = re.compile(r'Next\sEpisode@(.*?\d{4})') re_show = re.compile(r'Show\sName@(.*?)\sShow') re_time = re.compile(r'Airtime@(.*?)\sRun') showsrc = self.search(text) showname = re_show.findall(showsrc) lastep = re_last.findall(showsrc) nextep = re_next.findall(showsrc) airtime = re_time.findall(showsrc) if not showname: irc.reply("Could not find the series.") elif not lastep and not nextep: irc.reply(format("%s: No episodes have aired", ircutils.bold(showname[0])), prefixNick=False) elif not lastep and len(nextep)>0: nextep = nextep[0].split("^") irc.reply(format('%s: Next episode (%s), "%s", airs %s', ircutils.bold(showname[0]), nextep[0], nextep[1], nextep[2]), airtime[0], prefixNick=False) elif not nextep and len(lastep)>0: lastep = lastep[0].split("^") irc.reply(format('%s: Last episode (%s), "%s", aired %s', ircutils.bold(showname[0]), lastep[0],lastep[1],lastep[2]), prefixNick=False) else: lastep = lastep[0].split("^") irc.reply(format('%s: Last episode (%s), "%s", aired %s', ircutils.bold(showname[0]), lastep[0],lastep[1],lastep[2]), prefixNick=False) nextep = nextep[0].split("^") irc.reply(format('%s: Next episode (%s), "%s", airs %s', ircutils.bold(showname[0]), nextep[0], nextep[1], nextep[2]), airtime[0], prefixNick=False)
def _method_reply(self, refid, signature_only = False): '''Returns a reply describing the given method. This is an internal class method meant to be used when the actual method being printed has already been found.''' filename = refid.rsplit('_', 1)[0] docs = make_instance(get_xml_path(self.api, filename + '.xml')) section_nodes = docs.compounddef.sectiondef md = [n for m in [n.memberdef for n in section_nodes] for n in m if n.id == refid][0] overloads = [n for m in [n.memberdef for n in section_nodes] for n in m if n.id != refid and n.name.PCDATA == md.name.PCDATA] details = [utils.bold(md.definition.PCDATA + md.argsstring.PCDATA)] for method in overloads: details += [utils.bold(method.definition.PCDATA + method.argsstring.PCDATA)] try: brief = cleaner(md.briefdescription).reply except: brief = '' try: detailed = cleaner(md.detaileddescription).reply except: detailed = '' full = '%s %s' % (brief, detailed) full = full.strip() if full is '': full = '%s has no description.' % md.name.PCDATA if signature_only: return details return details + [full]
def roulette(self, irc, msg, args, spin): """[spin] Fires the revolver. If the bullet was in the chamber, you're dead. Tell me to spin the chambers and I will. """ if spin: self._rouletteBullet = random.randrange(0, 6) irc.reply(ircutils.bold(ircutils.mircColor('*SPIN*','10')) + ' Are you feeling lucky?', prefixNick=True) return channel = msg.args[0] if self._rouletteChamber == self._rouletteBullet: self._rouletteBullet = random.randrange(0, 6) self._rouletteChamber = random.randrange(0, 6) if irc.nick in irc.state.channels[channel].ops or \ irc.nick in irc.state.channels[channel].halfops: irc.queueMsg(ircmsgs.kick(channel, msg.nick, ircutils.bold(ircutils.mircColor('BANG!','4')))) else: irc.reply(ircutils.bold(ircutils.mircColor('*BANG*','4')) + '...Hey, who put a blank in here?!', prefixNick=True) irc.reply('reloads and spins the chambers.', action=True) else: irc.reply(ircutils.bold(ircutils.mircColor('*click*','14')),prefixNick=True) self._rouletteChamber += 1 self._rouletteChamber %= 6
def doPrivmsg(self, irc, msg): if(self.registryValue('enable', msg.args[0])): # If this is a youtube link, commence lookup if(msg.args[1].find("youtube") != -1 or msg.args[1].find("youtu.be") != -1): youtube_pattern = re.compile('(?:www\.)?youtu(?:be\.com/watch\?v=|\.be/)([\w\?=\-]*)(&(amp;)?[\w\?=]*)?') m = youtube_pattern.search(msg.args[1]); if(m): r = requests.get('http://gdata.youtube.com/feeds/api/videos/%s?v=2&alt=json' % m.group(1)) data = json.loads(r.content) likes = float(data['entry']["yt$rating"]['numLikes']) dislikes = float(data['entry']["yt$rating"]['numDislikes']) rating = (likes/(likes+dislikes))*100 message = 'Title: %s, Views: %s, Rating: %s%%' % (ircutils.bold(data['entry']['title']['$t']), ircutils.bold(data['entry']['yt$statistics']['viewCount']), ircutils.bold(round(float(rating)))) message = message.encode("utf-8", "replace") irc.queueMsg(ircmsgs.privmsg(msg.args[0], message)) if(msg.args[1].find("vimeo") != -1): vimeo_pattern = re.compile('vimeo.com/(\\d+)') m = vimeo_pattern.search(msg.args[1]); if(m): r = requests.get("http://vimeo.com/api/v2/video/%s.json" % m.group(1)) data = json.loads(r.content) message = 'Title: %s, Views: %s, Likes: %s' % (ircutils.bold(data[0]['title']), ircutils.bold(data[0]['stats_number_of_plays']), ircutils.bold(data[0]['stats_number_of_likes'])) message = message.encode("utf-8", "replace") irc.queueMsg(ircmsgs.privmsg(msg.args[0], message))
def get_class_desc(self, keyword): class_info = [(refid, name) for refid, (name, methods) in self.classes.items() if name == keyword] if not class_info: return None (refid, name) = class_info[0] docs = make_instance(get_xml_path(self.api, refid + '.xml')) details = [utils.bold(name)] try: details += ['[#include "%s"]' % docs.compounddef.includes.PCDATA] except: pass try: details += ['(Super-classes: %s)' % ', '.join([utils.bold(c.PCDATA) for c in docs.compounddef.basecompoundref])] except: pass try: details += ['(Sub-classes: %s)' % ', '.join([utils.bold(c.PCDATA) for c in docs.compounddef.derivedcompoundref])] except: pass details = ' '.join(details) try: brief = cleaner(docs.compounddef.briefdescription).reply except: brief = '' try: detailed = cleaner(docs.compounddef.detaileddescription).reply except: detailed = '' full = '%s %s' % (brief, detailed) full = full.strip() if full is '': full = '%s has no description.' % name return [details, full]
def smelt(self, irc, msg, args, item): """<item> Attempts to look up smelting recipes from the Minecraft wiki. """ soup = self.get_page(irc, item) # Find the "smelting" table displayed in the Wiki page. smelting_tables = soup.find_all('table', attrs={"data-description": 'Smelting recipes'}) if not smelting_tables: irc.error("No smelting information found.", Raise=True) irc.reply("Smelting recipes involving %s:" % ircutils.bold(item)) for table in smelting_tables: # Get the first smelting result. smelt_data = table.find_all('tr')[1] # Show the resulting item and the ingredients needed to smelt it. ingredients = format_text(smelt_data.td.get_text()) try: result = format_text(smelt_data.th.get_text()) except AttributeError: # If the text of the result item isn't explicitly shown, dig # deeper to extract the item name from the smelting table UI. smelting_ui = smelt_data.find_all('td')[1].div.span output = smelting_ui.find('span', class_='mcui-output') result = output.find('span', class_='sprite') result = result.get('title') irc.reply("%s: %s" % (ircutils.bold(result), ingredients))
def _lookUpYouTube(self, irc, msg): (recipients, text) = msg.args yt_service = self.service try: if "https" in text: url = text.split("https://")[1] else: url = text.split("http://")[1] url = url.split(" ")[0] except: url = text vid_id = self._video_id("http://"+url) entry = yt_service.GetYouTubeVideoEntry(video_id=vid_id) title = "" rating = "" views = 0 try: title = ircutils.bold(entry.media.title.text) except: pass try: views = ircutils.bold(entry.statistics.view_count) except: views = ircutils.bold('0') try: rating = ircutils.bold('{:.2%}'.format((float(entry.rating.average)/5))) except: rating = ircutils.bold("n/a") irc.reply('Title: %s Views: %s Rating: %s ' % (title, views, rating),prefixNick=False)
def _Ulastbgs(self, irc, msg, args, count): if not count: count = self.registryValue('defaultLastBGCount') r = [] h = reversed(irc.state.history) for m in h: if len(r) == count: break if m.nick.lower() == msg.nick.lower() and m.tagged('bg'): r.append(m) if len(r) == 0: irc.reply("Sorry, no BGs on file.") return f = [] for m in r: s = "" now = datetime.now() dat = datetime.fromtimestamp(m.tagged('receivedAt')) if now - dat > timedelta(7): s += dat.strftime("[%b %d %H:%M] ") elif now - dat > timedelta(1): s += dat.strftime("[%a %H:%M] ") else: s += dat.strftime("[%H:%M] ") if m.tagged('bg') <= self.registryValue('measurementTransitionValue'): s += ircutils.bold("{0:.1f}".format(m.tagged('bg'))) else: s += ircutils.bold("{0:.0f}".format(m.tagged('bg'))) f.append(s) irc.reply(utils.str.commaAndify(f))
def doPrivmsg(self, irc, msg): channel = msg.args[0] # Ignore messages that start with the command qualifier if msg.args[1].startswith('@'): return # Don't parse non-command messages if a trivia game isn't running # or if there is no active question if channel not in self.running or channel not in self.curQuestion: return else: self.curQuestion[channel].check(msg.args[1]) if self.curQuestion[channel].isCorrect(msg.args[1]) == False: if self.lastHint[channel] != self.curQuestion[channel].hint: irc.queueMsg(ircmsgs.privmsg(channel,ircutils.bold("Answer: ") + self.curQuestion[channel].hint)) self.lastHint[channel] = self.curQuestion[channel].hint else: # Answer is correct, assign points irc.queueMsg(ircmsgs.privmsg(channel,ircutils.bold("Answer: ") + "%s is correct!!" % self.curQuestion[channel].answer)) irc.queueMsg(ircmsgs.privmsg(channel,"%s gets 5 points!!" % ircutils.bold(msg.nick))) self.scores[channel].add(msg.nick,5) irc.queueMsg(ircmsgs.privmsg(msg.args[0],("Scores: %s" % self.getFormattedScores(msg.args[0])))) self.curQuestion.pop(channel) self.ask(irc,msg) return
def present_listing_first(res, original_link=False, color_score=False): try: d = res.get("data", {}).get("children", [{}])[0].get("data",{}) if d: if not original_link: d["url"] = "http://www.reddit.com/r/%(subreddit)s/comments/%(id)s/" % d if color_score: score_part = "(%s|%s)[%s]" % (ircutils.bold(ircutils.mircColor("%(ups)s", "orange")), ircutils.bold(ircutils.mircColor("%(downs)s", "12")), ircutils.bold(ircutils.mircColor("%(num_comments)s", "dark grey"))) else: score_part = "(%(score)s)" title_part = "%(title)s" url_part = ircutils.underline("%(url)s") nsfw_part = "NSFW"*d['over_18'] or '' nsfw_part =ircutils.bold(ircutils.mircColor(nsfw_part, 'red')) template = "%s %s %s %s" % (nsfw_part, score_part, title_part, url_part) template = (template % d) template = template.replace('\n', ' ') template = template.replace('&','&') if d["created_utc"] < time.time() - 2678400: return False return template except IndexError: return None
def _lookup_youtube(self, irc, msg): (recipients, text) = msg.args yt_service = apiclient.discovery.build(self.YOUTUBE_API_SERVICE_NAME, self.YOUTUBE_API_VERSION, developerKey=self.developer_key) try: if "https" in text: url = text.split("https://")[1] else: url = text.split("http://")[1] url = url.split(" ")[0] except: url = text vid_id = self._video_id("http://" + url) entry = yt_service.videos().list( part="snippet, statistics", id=vid_id ).execute() title = "" try: title = ircutils.bold(entry['items'][0]['snippet']['title']) except: pass try: views = ircutils.bold(entry['items'][0]['statistics']['viewCount']) except: views = ircutils.bold('0') try: like_dislike_ratio = float(entry['items'][0]['statistics']['likeCount']) / ( float(entry['items'][0]['statistics']['likeCount']) + float( entry['items'][0]['statistics']['dislikeCount'])) rating = ircutils.bold('{:.2%}'.format(like_dislike_ratio)) except: rating = ircutils.bold("n/a") irc.reply('Title: %s Views: %s Rating: %s ' % (title, views, rating), prefixNick=False)
def stop(self): stopgame = ircutils.bold('Trivia stopping.') self.reply('%s' % stopgame) self.active = False try: schedule.removeEvent('next_%s' % self.channel) except KeyError: pass scores = self.roundscores.iteritems() sorted = [] for i in range(0, len(self.roundscores)): item = scores.next() sorted.append(item) def cmp(a, b): return b[1] - a[1] sorted.sort(cmp) max = 3 if len(sorted) < max: max = len(sorted) #self.reply('max: %d. len: %d' % (max, len(sorted))) s = ircutils.bold('Top finishers') + ':' if max > 0: recipients = [] maxp = sorted[0][1] for i in range(0, max): item = sorted[i] s = '%s %s %s.' % (s, item[0], item[1]) self.reply(s) del self.games[self.channel]
def genText_Results(daMap): for link in daMap[u'Results']: if u'Topics' in link: for topic in link[u'Topics']: yield ircutils.bold(topic[u'Text']) + ": " + topic[u'FirstURL'] else: yield ircutils.bold(link[u'Text']) + ": " + link[u'FirstURL']
def files(r): """ Prints the number of files and total size of the release as a formatted string for IRC messages. """ if r.files or r.size: return "%sF/%sMB" % (irc.bold(r.files), irc.bold(r.size)) return irc.mircColor('?', fg=7)
def testStripFormatting(self): self.assertEqual(ircutils.stripFormatting(ircutils.bold("foo")), "foo") self.assertEqual(ircutils.stripFormatting(ircutils.italic("foo")), "foo") self.assertEqual(ircutils.stripFormatting(ircutils.reverse("foo")), "foo") self.assertEqual(ircutils.stripFormatting(ircutils.underline("foo")), "foo") self.assertEqual(ircutils.stripFormatting("\x02bold\x0302,04foo\x03" "bar\x0f"), "boldfoobar") s = ircutils.mircColor("[", "blue") + ircutils.bold("09:21") self.assertEqual(ircutils.stripFormatting(s), "[09:21")
def nba(self, irc, msg, args, optdate): """<YYYYmmdd> Display NBA scores. Optional: add in date to specify games/scores on date. """ if optdate: testdate = self._validate(optdate, '%Y%m%d') if not testdate: irc.reply("Invalid year. Must be YYYYmmdd. Ex: 20120904") return else: # use today's date here, instead of with others. optdate = datetime.datetime.now().strftime("%Y%m%d") url = 'nba/scoreboard?' if optdate: url += 'date=%s' % optdate html = self._fetch(url) if html == 'None': irc.reply("Cannot fetch NBA scores.") return soup = BeautifulSoup(html) divs = soup.findAll('div', attrs={'id':re.compile('game.*?')}) append_list = [] for div in divs: game = self._stringFmt(div.getText()) # strip all past , game = self._colorizeString(game) # colorize the status. if " at " not in game: gamesplit = game.split(' ') awayteam = gamesplit[0] awayscore = gamesplit[1] hometeam = gamesplit[2] homescore = gamesplit[3] time = gamesplit[4:] time = " ".join(time) # bold the leader if int(awayscore) > int(homescore): awayteam = ircutils.bold(awayteam) awayscore = ircutils.bold(awayscore) elif int(homescore) > int(awayscore): hometeam = ircutils.bold(hometeam) homescore = ircutils.bold(homescore) game = str(awayteam + " " + awayscore + " " + hometeam + " " + homescore + " " + time) append_list.append(game) if len(append_list) > 0: irc.reply(string.join([item for item in append_list], " | ")) else: irc.reply("No current NBA games.")
def cfbschedule(self, irc, msg, args, optteam): """[team] Display the schedule/results for team. """ lookupteam = self._lookupTeam(optteam) if lookupteam == "0": irc.reply("I could not find a schedule for: %s" % optteam) return url = 'http://www.cbssports.com/collegefootball/teams/schedule/%s/' % lookupteam try: req = urllib2.Request(url) html = (urllib2.urlopen(req)).read() except: irc.reply("Failed to open: %s" % url) return html = html.replace('&','&').replace(';','') soup = BeautifulSoup(html) if soup.find('table', attrs={'class':'data stacked'}).find('tr', attrs={'class':'title'}).find('td'): title = soup.find('table', attrs={'class':'data stacked'}).find('tr', attrs={'class':'title'}).find('td') else: irc.reply("Something broke with schedules. Did formatting change?") return div = soup.find('div', attrs={'id':'layoutTeamsPage'}) # must use this div first since there is an identical table. table = div.find('table', attrs={'class':'data', 'width':'100%'}) rows = table.findAll('tr', attrs={'class':re.compile('^row[1|2]')}) append_list = [] for row in rows: date = row.find('td') team = date.findNext('td').find('a') time = team.findNext('td') if team.text.startswith('@'): # underline home team = team.text else: team = ircutils.underline(team.text) if time.find('span'): # span has score time. empty otherwise. time = time.find('span').string append_list.append(date.text + " - " + ircutils.bold(team) + " (" + time + ")") else: time = time.string append_list.append(date.text + " - " + ircutils.bold(team)) descstring = string.join([item for item in append_list], " | ") output = "{0} for {1} :: {2}".format(title.text, ircutils.bold(optteam.title()), descstring) irc.reply(output)
def _colorize(self, s, bold=True, color=None): if not (color or bold): raise ValueError("bold or color must be set") elif color and bold: return ircutils.bold(ircutils.mircColor(s, color)) elif bold: return ircutils.bold(s) elif color: return ircutils.mircColor(s, color)
def _boldleader(self, awayteam, awayscore, hometeam, homescore): """Conveinence function to bold the leader.""" if (int(awayscore) > int(homescore)): # visitor winning. return "{0} {1} {2} {3}".format(ircutils.bold(awayteam), ircutils.bold(awayscore), hometeam, homescore) elif (int(awayscore) < int(homescore)): # home winning. return "{0} {1} {2} {3}".format(awayteam, awayscore, ircutils.bold(hometeam), ircutils.bold(homescore)) else: # tie. return "{0} {1} {2} {3}".format(awayteam, awayscore, hometeam, homescore)
def hunt(self,irc,msg,args): """ performs a random hunt """ player = msg.nick currentTime = time.time() if player in self._huntersEndTime and self._huntersEndTime[player] > currentTime: irc.reply("Hold on, your weapon is reloading...") else: endTime = currentTime + timeoutLength self._huntersEndTime[player] = endTime if(self.registryValue('enable', msg.args[0])): animals = [' bear', ' gopher', ' rabbit', ' hunter', ' deer', ' fox', ' duck', ' moose', ' pokemon named Pikachu', ' park ranger', ' Yogi Bear', ' Boo Boo Bear', ' dog named Benji', ' cow', ' raccoon', ' koala bear', ' camper', ' channel lamer', ' your mom'] places = ['in some bushes', 'in a hunting blind', 'in a hole', 'up in a tree', 'in a hiding place', 'out in the open', 'in the middle of a field', 'downtown', 'on a street corner', 'at the local mall'] with open(conf.supybot.directories.data.dirize('hunttrophy.txt'), 'r') as file: data = file.readlines() highScore = data[2].rstrip('\n') huntrandom = random.getstate() random.seed(time.time()) currentWhat = random.choice(animals) currentWhere = random.choice(places) weight = random.randint(int(highScore)/2,int(highScore)+10) weightType = self.registryValue('weightType') thisHunt = (ircutils.bold(msg.nick) + " goes hunting " + currentWhere + " for a " + str(weight) + weightType + currentWhat+".") irc.reply(thisHunt) irc.reply("Aims...") irc.reply("Fires...") time.sleep(random.randint(4,8))#pauses the output between line 1 and 2 for 4-8 seconds huntChance = random.randint(1,100) successRate = self.registryValue('SuccessRate') random.setstate(huntrandom) if huntChance < successRate: win = ("Way to go, " + ircutils.bold(msg.nick) + ". You killed the " + str(weight) + weightType + currentWhat+"!") irc.reply(win) with open(conf.supybot.directories.data.dirize('hunttrophy.txt'), 'r') as file: data = file.readlines() bigHunt = data[2].rstrip('\n') if weight > int(bigHunt): with open(conf.supybot.directories.data.dirize('hunttrophy.txt'), 'w') as file: data[0] = msg.nick data[1] = currentWhat data[2] = weight file.writelines(str(data[0])) file.writelines('\n') file.writelines(str(data[1])) file.writelines('\n') file.writelines(str(data[2])) irc.reply("You got a new highscore!") else: lose = ("Oops, you missed, " + msg.nick+". :(") irc.reply(lose)
def fish(self,irc,msg,args): """ performs a random fishing trip """ player = msg.nick currentTime = time.time() if player in self._fishersEndTime and self._fishersEndTime[player] > currentTime: irc.reply("Hold on, still putting bait on your fishing pole...") else: endTime = currentTime + timeoutLength self._fishersEndTime[player] = endTime if(self.registryValue('enable', msg.args[0])): fishes = (' salmon', ' herring', ' yellowfin tuna', ' pink salmon', ' chub', ' barbel', ' perch', ' northern pike', ' brown trout', ' arctic char', ' roach', ' brayling', ' bleak', ' cat fish', ' sun fish', ' old tire', ' rusty tin can', ' genie lamp', ' love message in a bottle', ' old log', ' rubber boot' , ' dead body', ' Loch Ness Monster', ' old fishing lure', ' piece of the Titanic', ' chunk of atlantis', ' squid', ' whale', ' dolphin', ' porpoise' , ' stingray', ' submarine', ' seal', ' seahorse', ' jellyfish', ' starfish', ' electric eel', ' great white shark', ' scuba diver' , ' lag monster', ' virus', ' soggy pack of smokes', ' bag of weed', ' boat anchor', ' pair Of floaties', ' mermaid', ' merman', ' halibut', ' tiddler', ' sock', ' trout') fishSpots = ('a stream', 'a lake', 'a river', 'a pond', 'an ocean', 'a bathtub', 'a kiddie swimming pool', 'a toilet', 'a pile of vomit', 'a pool of urine', 'a kitchen sink', 'a bathroom sink', 'a mud puddle', 'a bucket of water', 'a bowl of Jell-O', 'a wash basin', 'a rain barrel', 'an aquarium', 'a snowBank', 'a waterFall', 'a cup of coffee', 'a glass of milk') with open(conf.supybot.directories.data.dirize('fishtrophy.txt'), 'r') as file: data = file.readlines() highScore = data[2].rstrip('\n') fishrandom = random.getstate() random.seed(time.time()) currentWhat = random.choice(fishes) currentWhere = random.choice(fishSpots) weight = random.randint(int(highScore)/2,int(highScore)+10) weightType = self.registryValue('weightType') thisFishing = (ircutils.bold(msg.nick) + " goes fishing in " + currentWhere+".") irc.reply(thisFishing) irc.reply("Casts in...") irc.reply("A " + str(weight) + weightType + currentWhat + " is biting...") time.sleep(random.randint(4,8))#pauses the output between line 1 and 2 for 4-8 seconds huntChance = random.randint(1,100) successRate = self.registryValue('SuccessRate') random.setstate(fishrandom) if huntChance < successRate: win = ("Way to go, " + ircutils.bold(msg.nick) + "! You caught the " + str(weight) + weightType + currentWhat+"!") irc.reply(win) with open(conf.supybot.directories.data.dirize('fishtrophy.txt'), 'r') as file: data = file.readlines() bigFish = data[2].rstrip('\n') if weight > int(bigFish): with open(conf.supybot.directories.data.dirize('fishtrophy.txt'), 'w') as file: data[0] = msg.nick data[1] = currentWhat data[2] = weight file.writelines(str(data[0])) file.writelines('\n') file.writelines(str(data[1])) file.writelines('\n') file.writelines(str(data[2])) irc.reply("You got a new highscore!") else: lose = ("Oops, it got away, " + msg.nick+". :(") irc.reply(lose)
def ask(self, irc, msg): channel = msg.args[0] if channel not in self.curQuestion: self.curQuestion[channel] = self.getQuestion() irc.queueMsg(ircmsgs.privmsg(channel,u"%s: %s?" % (ircutils.bold(self.curQuestion[channel].id), self.curQuestion[channel].question))) irc.queueMsg(ircmsgs.privmsg(channel,ircutils.bold("Answer: ") + self.curQuestion[channel].hint)) # Print answer to log for debugging purposes only log.critical(self.curQuestion[channel].answer) return
def getUserTemp(user, temp_f): savedTemp = user.temperature if not savedTemp or savedTemp == 'f': temp = ircutils.bold(temp_f) + 'F' elif savedTemp == 'c': temp = ircutils.bold('%.1f' % ((float(temp_f) - 32) / 1.8)) + 'C' elif savedTemp == 'k': temp = ircutils.bold('%.1f' % (((float(temp_f) - 32) / 1.8) + 273)) + 'K' return temp
def _finalgame(self, gamedate, gameid): """Grabs the boxscore json and prints a final statline.""" url = b64decode('aHR0cDovL2RhdGEubmJhLmNvbS9qc29uL2Ntcy9ub3NlYXNvbi9nYW1lLw==') + '%s/%s/boxscore.json' % (str(gamedate), str(gameid)) html = self._httpget(url) if not html: self.log.error("ERROR: Could not _finalgame.") return None # process json. throw this thing in a try/except block. try: jsonf = json.loads(html.decode('utf-8')) game = jsonf['sports_content']['game'] if len(game) == 0: self.log.error("_finalgame :: I found no games in the json data.") return None # output dict. we preset DD/TD for later. gamestats = {'Double-double':[], 'Triple-double':[]} # iterate over the home/visitor. for var in ['visitor', 'home']: team = game[var]['abbreviation'] fgp = game[var]['stats']['field_goals_percentage'] tpp = game[var]['stats']['three_pointers_percentage'] ftp = game[var]['stats']['free_throws_percentage'] to = game[var]['stats']['turnovers'] rb = (int(game[var]['stats']['rebounds_offensive'])+int(game[var]['stats']['rebounds_defensive'])) # total rb. ptsl = sorted(game[var]['players']['player'], key=lambda t: int(t['points']), reverse=True)[0] # sort by points astl = sorted(game[var]['players']['player'], key=lambda t: int(t['assists']), reverse=True)[0] # sort by assists. below we sort by adding rebounds. rbll = sorted(game[var]['players']['player'], key=lambda x: (int(x['rebounds_offensive']) + int(x['rebounds_defensive'])), reverse=True)[0] # inject into our gamestats dict with the text. gamestats[team] = "{0}: {1} {2}: {3} {4}: {5} {6}: {7} {8}: {9} {10} :: {11} {12} {13} {14} {15} {16} {17} {18} {19}".format(\ ircutils.bold("FG%"), fgp, ircutils.bold("FT%"), ftp, ircutils.bold("3PT%"), tpp, ircutils.bold("TO"), to, ircutils.bold("RB"), rb, ircutils.bold(ircutils.underline("LEADERS")), ircutils.bold("PTS"), ptsl['last_name'].encode('utf-8'), ptsl['points'], ircutils.bold("AST"), astl['last_name'].encode('utf-8'), astl['assists'], ircutils.bold("RB"), rbll['last_name'].encode('utf-8'), (int(rbll['rebounds_offensive'])+int(rbll['rebounds_defensive']))) # look for DD/TD for x in game[var]['players']['player']: # iterate over. tmp = {} # we make a dict with the key as the stat for later. tmp['rb'] = int(x['rebounds_offensive']) + int(x['rebounds_defensive']) tmp['blocks'] = int(x['blocks']) tmp['a'] = int(x['assists']) tmp['p'] = int(x['points']) tmp['s'] = int(x['steals']) # we only inject into matching the category and stat if 10 or over. matching = [str(z.upper()) + ": " + str(p) for (z, p) in tmp.items() if p >= 10] if len(matching) == 2: # dd. inject into gamestats in the right category. gamestats['Double-double'].append("{0}({1}) :: {2}".format(x['last_name'].encode('utf-8'), team, " | ".join(matching))) if len(matching) > 2: # likewise with td. gamestats['Triple-double'].append("{0}({1}) :: {2}".format(x['last_name'].encode('utf-8'), team, " | ".join(matching))) # return the dict. return gamestats except Exception, e: self.log.error("_finalgame: ERROR on {0} :: {1}".format(url, e)) return None
def testStripFormatting(self): self.assertEqual(ircutils.stripFormatting(ircutils.bold('foo')), 'foo') self.assertEqual(ircutils.stripFormatting(ircutils.reverse('foo')), 'foo') self.assertEqual(ircutils.stripFormatting(ircutils.underline('foo')), 'foo') self.assertEqual(ircutils.stripFormatting('\x02bold\x0302,04foo\x03' 'bar\x0f'), 'boldfoobar') s = ircutils.mircColor('[', 'blue') + ircutils.bold('09:21') self.assertEqual(ircutils.stripFormatting(s), '[09:21')
def map(self, irc, msg, args): if msg.args[0] == "#togetheralone": irc.reply(ircutils.bold("""Map for /r/togetheralone: """) + "https://www.zeemaps.com/map?group=489050#") if msg.args[0] == "#ta-support": irc.reply(ircutils.bold("""Map for /r/togetheralone: """) + "https://www.zeemaps.com/map?group=489050#") if msg.args[0] == "#ta-lounge": irc.reply(ircutils.bold("""Map for /r/togetheralone: """) + "https://www.zeemaps.com/map?group=489050#") if msg.args[0] == "#tamods": irc.reply(ircutils.bold("""Map for /r/togetheralone: """) + "https://www.zeemaps.com/map?group=489050#") else: return
def random(self, irc, msg, args, channel): """[<channel>] Returns a random factoid from the database for <channel>. <channel> is only necessary if the message isn't sent in the channel itself. """ db = self.getDb(channel) cursor = db.cursor() cursor.execute("""SELECT fact, key_id FROM factoids ORDER BY random() LIMIT 3""") if cursor.rowcount != 0: L = [] for (factoid, id) in cursor.fetchall(): cursor.execute("""SELECT key FROM keys WHERE id=%s""", id) (key, ) = cursor.fetchone() L.append('"%s": %s' % (ircutils.bold(key), factoid)) irc.reply('; '.join(L)) else: irc.error('I couldn\'t find a factoid.')
def formatter(command): command = list( map(callbacks.canonicalName, command.split(' '))) doc = callback.getCommandMethod(command).__doc__ if not doc: return '<tr><td>%s</td><td> </td></tr>' % \ ' '.join(command) doclines = doc.splitlines() if self._plugin.registryValue('withFullName'): s = '%s %s %s' % (name, ' '.join(command), doclines.pop(0)) else: s = doclines.pop(0) s = cgi.escape(s) if doclines: help_ = cgi.escape('\n'.join(doclines)) s = '<strong>%s</strong><br />%s' % \ (ircutils.bold(s), help_) return '<tr><td>%s</td><td>%s</td></tr>' % \ (' '.join(command), s)
def formatData(self, data, bold=True, max=0): if isinstance(data, basestring): return data results = [] if max: data = data[:max] for result in data: title = utils.web.htmlToText(result['titleNoFormatting']\ .encode('utf-8')) url = result['unescapedUrl'].encode('utf-8') if title: if bold: title = ircutils.bold(title) results.append(format('%s: %u', title, url)) else: results.append(url) if not results: return format('No matches found.') else: return format('; '.join(results))
def topartists(self, irc, msg, args, user, duration): """[<user>] [<duration>] Reports the top 10 artists for the user. Duration: overall | 7day | 1month | 3month | 6month | 12month (default: 6 months) """ #irc.error("This command is not ready yet. Stay tuned!", Raise=True) nick, user = self.check_user(msg, user, irc) artists, duration, duration_dict = self.get_topartists( irc, msg, user, duration) outstr = "%s's top artists %s are:" % (nick, duration_dict[duration]) for artist in artists: outstr = outstr + ( " %s [%s]," % (ircutils.bold(artist['name']), artist['playcount'])) outstr = outstr[:-1] irc.reply(outstr)
def get(self, irc, msg, args): """takes no arguments Retrieve your recommendations.""" try: outputString = "Your recommendations: %s." if not db.hasRecord(msg.nick): raise LastFMUsernameNotSetError recs = db.getRecs(msg.nick) if recs == None: irc.reply("You have no recommendations.") else: recsText = commaAndify([ircutils.bold(rec.sender) + " recommends " + rec.data for rec in recs]).encode("utf-8") output = outputString % recsText irc.reply(output.encode("utf-8")) except LastFMUsernameNotSetError: irc.error("Set your Last.FM nick first using setusername.") except pylast.WSError, e: irc.error(str(e))
def list(self, irc, msg, args, channel): """[<channel>|global] Lists regexps present in the triggers database. <channel> is only necessary if the message isn't sent in the channel itself. Regexp ID listed in parentheses. """ db = self.getDb(channel) cursor = db.cursor() cursor.execute("SELECT regexp, id FROM triggers ORDER BY id") results = cursor.fetchall() if len(results) != 0: regexps = results else: irc.reply(_('There are no regexp triggers in the database.')) return s = [ "%s: %s" % (ircutils.bold('#'+str(regexp[1])), regexp[0]) for regexp in regexps ] separator = self.registryValue('listSeparator', channel, irc.network) irc.reply(separator.join(s))
def evecommands(self, irc, msg, args): """ Prints an overview of available commands """ desc = "\n".join(("EVESpai commands:", "{0} {1}".format( ircutils.bold("'evecommands'"), "List available commands." ), "{0} {1}".format( ircutils.bold("'pos [<system>]'"), "Lists all POSes." ), "{0} {1}".format(ircutils.bold( "'evetime'" ), "Get current time on Tranquility."), "{0} {1}".format( ircutils .bold("'whereis <character>'" ), "List the location and currently boarded ship of <character>." ), "{0} {1}".format(ircutils.bold( "'cache <calltype>'" ), "List the cache time of given call type."), "{0} {1}".format( ircutils .bold("'whoat <system>'" ), "List characters and their ships in <system>. If --all is given, ignore the max lines limitation." ), "{0} {1}".format( ircutils.bold("'ship <shiptype>'"), "List characters in <shiptype>." ), "{0} {1}".format(ircutils.bold( "'chars <user>'" ), "List all cha)racters belonging to <user>"), "{0} {1}".format( ircutils .bold("'price [--location=(<solarsystem>|<region>)] <typeName>'"), "List buy/sell/volume of <type> in <location>, defaults to Jita."), "{0} {1}".format(ircutils.bold("'markets'"), "List all price indexed markets."), "{0} {1}".format( ircutils.bold("'player <character>'"), "List username of those who own *<character>*"))) for line in desc.splitlines(): irc.reply(line.strip(), prefixNick=False)
def filesearch(self, irc, msg, args, release, query): """<release> <file query> Searches what package in Debian or Ubuntu has which file. <release> is the codename/release name (e.g. xenial or stretch).""" release = release.lower() distro = self._guess_distro_from_release(release) try: url = '%ssearch?keywords=%s&searchon=contents&suite=%s' % (DEBIAN_ADDRS[distro], quote(query), quote(release)) except KeyError: irc.error("Unknown distribution. This command only supports " "package lookup for Debian and Ubuntu.", Raise=True) try: fd = utils.web.getUrl(url).decode("utf-8") except utils.web.Error as e: irc.error(str(e), Raise=True) soup = BeautifulSoup(fd) results = [] # Get results from table entries, minus the first one which is used for headings. contentdiv = soup.find('div', attrs={'id': "pcontentsres"}) if contentdiv: for tr in contentdiv.find_all("tr")[1:]: tds = tr.find_all('td') try: filename, packages = map(_normalize, [tds[0].get_text(), tds[1].get_text()]) except IndexError: continue results.append('%s: %s' % (ircutils.bold(filename), packages)) if results: irc.reply('; '.join(results)) else: try: e = _normalize(soup.find("div", class_="perror").get_text()) except AttributeError: e = "No results found." irc.error(e)
def list(self, irc, msg, args, optlist): """[--channel <#channel>] [--keys] [--unlocked|--locked] Lists all Akas defined for <channel>. If <channel> is not specified, lists all global Akas. If --keys is given, lists only the Aka names and not their commands.""" channel = 'global' filterlocked = filterunlocked = False for (option, arg) in optlist: if option == 'channel': if not ircutils.isChannel(arg): irc.error(_('%r is not a valid channel.') % arg, Raise=True) channel = arg if option == 'locked': filterlocked = True if option == 'unlocked': filterunlocked = True aka_list = self._db.get_aka_list(channel) if filterlocked and filterunlocked: irc.error(_('--locked and --unlocked are incompatible options.'), Raise=True) elif filterlocked: aka_list = [aka for aka in aka_list if self._db.get_aka_lock(channel, aka)[0]] elif filterunlocked: aka_list = [aka for aka in aka_list if not self._db.get_aka_lock(channel, aka)[0]] if aka_list: if 'keys' in dict(optlist): # Strange, aka_list is a list of one length tuples s = [k[0] for k in aka_list] oneToOne = True else: aka_values = [self._db.get_alias(channel, aka) for aka in aka_list] s = ('{0}: "{1}"'.format(ircutils.bold(k), v) for (k, v) in zip(aka_list, aka_values)) oneToOne = None irc.replies(s, oneToOne=oneToOne) else: irc.error(_("No Akas found."))
def tp(self, irc, msg, args, text): """tp <text> Translates <text> through multiple rounds of Google Translate to get amusing results. """ outlang = self.registryValue('language', msg.args[0]) if outlang not in self.langs: irc.error( "Unrecognized output language. Please set " "'config plugins.wte.language' correctly.", Raise=True) # Randomly choose 4 to 8 languages from the list of supported languages. # The amount can be adjusted if you really wish - 4 to 8 is reasonable # in that it gives interesting results but doesn't spam Google's API # (and risk getting blocked) too much. ll = random.sample(self.langs.keys(), random.randint(4, 8)) self.log.debug( format("TranslateParty: Using %i languages: %L " "(outlang %s)", len(ll), ll, outlang)) # For every language in this list, translate the text given from # auto-detect into the target language, and replace the original text # with it. for targetlang in ll: text = self.getTranslation(irc, "auto", targetlang, text) text = self.getTranslation(irc, "auto", outlang, text) text = text.strip() if self.registryValue("verbose", msg.args[0]): # Verbose output was requested, show the language codes AND # names that we translated through. languages = [ ircutils.bold("%s [%s]" % (self.langs[lang], lang)) for lang in ll ] irc.reply( format( "Translated through \x02%i\x02 languages: %L " "(output language %s)", len(ll), languages, outlang)) irc.reply(text)
def schedule(self, irc, msg, args): """ """ shows = fetch(False) l = [] if shows: for show in shows: if show['show']['type'] == 'Scripted': this_show = format( '%s [%s] (%s)', ircutils.bold(show['show']['name']), str(show['season']) + 'x' + str(show['number']), show['airtime']) l.append(this_show) tonight_shows = ', '.join(l) irc.reply( format('%s: %s', ircutils.underline("Tonight's Shows"), tonight_shows))
def markets(self, irc, msg, args): """ List all price indexed markets. """ locationIDs = self._sql(""" SELECT "locationID" FROM evecentral_market""", None, single=False) if len(locationIDs) == 0: irc.reply('No prices have been indexed yet.', prefixNick=False) return output = [] for locationID in locationIDs: locationID = locationID[0] location = self._get_location(locationID) if locationID < 30000000: # This would be a region output.append(ircutils.bold(location['itemName'])) else: output.append(self._colorize_system(location)) irc.reply(', '.join(output), prefixNick=False)
def _newHeadlines(self, irc, channels, name, url): try: # We acquire the lock here so there's only one announcement thread # in this code at any given time. Otherwise, several announcement # threads will getFeed (all blocking, in turn); then they'll all # want to send their news messages to the appropriate channels. # Note that we're allowed to acquire this lock twice within the # same thread because it's an RLock and not just a normal Lock. self.acquireLock(url) try: oldresults = self.cachedFeeds[url] oldheadlines = self.getHeadlines(oldresults) except KeyError: oldheadlines = [] newresults = self.getFeed(url) newheadlines = self.getHeadlines(newresults) if len(newheadlines) == 1: s = newheadlines[0][0] if s in ('Timeout downloading feed.', 'Unable to download feed.'): self.log.debug('%s %u', s, url) return def normalize(headline): return (tuple(headline[0].lower().split()), headline[1]) oldheadlines = set(map(normalize, oldheadlines)) for (i, headline) in enumerate(newheadlines): if normalize(headline) in oldheadlines: newheadlines[i] = None newheadlines = filter(None, newheadlines) # Removes Nones. if newheadlines: for channel in channels: bold = self.registryValue('bold', channel) sep = self.registryValue('headlineSeparator', channel) if bold: sep = ircutils.bold(sep) headlines = self.buildHeadlines(newheadlines, channel) irc.replies(headlines, prefixer='', joiner=sep, to=channel, prefixNick=False, private=True) finally: self.releaseLock(url)
def omdb(self, irc, msg, args, opts, movie): """[--year <int>] <movie> Shows some information about the given movie title. """ apikey = self.registryValue('apikey') if not apikey or apikey == "Not set": irc.reply( "API key not set. See 'config help supybot.plugins.OMDb.apikey'." ) return url = self.url url += "apikey=" + apikey url += "&t=" + urllib.parse.quote(movie) url += "&plot=short" url += "&tomatoes=true" url += "&r=json" if opts: opts = dict(opts) year = opts.get('year') if year: url += "&y=" + str(year) jsonstr = utils.web.getUrl(url).decode() j = json.loads(jsonstr) error = j.get("Error") if error: irc.reply(error) return retval = "[{0}] ({1}) {2} Metacritic: [{3}] RT: [{4} / {5}] IMDb: [{6}] Actors: [{7}] {8}".format( ircutils.bold(j.get("Title")), j.get("Year"), j.get("Genre"), self.metacolor(j.get("Metascore")), self.rtcolor(j.get("tomatoMeter")), self.rtcolor(j.get("tomatoUserMeter")), self.imdbcolor(j.get("imdbRating")), j.get("Actors"), j.get("Plot")) irc.reply(retval)
def shrinkSnarfer(self, irc, msg, match): channel = msg.channel network = irc.network if not channel: return if self.registryValue('shrinkSnarfer', channel, network): url = match.group(0) r = self.registryValue('nonSnarfingRegexp', channel, network) if r and r.search(url) is not None: self.log.debug('Matched nonSnarfingRegexp: %u', url) return minlen = self.registryValue('minimumLength', channel, network) try: cmd = self.registryValue('serviceRotation', channel, network, value=False) cmd = cmd.getService().capitalize() except ValueError: cmd = self.registryValue('default', channel, network) \ .capitalize() if len(url) >= minlen: try: shorturl = getattr(self, '_get%sUrl' % cmd)(url) except (utils.web.Error, AttributeError, ShrinkError): self.log.info('Couldn\'t get shorturl for %u', url) return if self.registryValue('shrinkSnarfer.showDomain', channel, network): domain = ' (at %s)' % utils.web.getDomain(url) else: domain = '' if self.registryValue('bold'): s = format('%u%s', ircutils.bold(shorturl), domain) else: s = format('%u%s', shorturl, domain) m = irc.reply(s, prefixNick=False) if m is not None: m.tag('shrunken')
def last(self, irc, msg, args): """ Gets the last comment or machine status """ url = 'http://lblogbook.cern.ch/Shift/elog.rdf' self.log.debug('Fetching %u', url) feed = self.getFeed(url) if irc.isChannel(msg.args[0]): channel = msg.args[0] else: channel = None headlines = self.getHeadlines(feed) if not headlines: irc.error('Couldn\'t get RSS feed.') return headlines = self.buildHeadlines(headlines, channel) headlines = headlines[:1] sep = self.registryValue('headlineSeparator', channel) if self.registryValue('bold', channel): sep = ircutils.bold(sep) irc.replies(headlines, joiner=sep)
def rss(self, irc, msg, args, url, n): """<url> [<number of headlines>] Gets the title components of the given RSS feed. If <number of headlines> is given, return only that many headlines. """ self.log.debug('Fetching %u', url) feed = self.getFeed(url) if irc.isChannel(msg.args[0]): channel = msg.args[0] else: channel = None headlines = self.getHeadlines(feed) if not headlines: irc.error('Couldn\'t get RSS feed.') return headlines = self.buildHeadlines(headlines, channel, 'showLinks') if n: headlines = headlines[:n] sep = self.registryValue('headlineSeparator', channel) if self.registryValue('bold', channel): sep = ircutils.bold(sep) irc.replies(headlines, joiner=sep)
def last_played(self, user, plays=True): self.set_apikey() data = urllib.parse.urlencode({ 'user': user, 'limit': 1, 'api_key': self.apikey, 'format': 'json', 'method': 'user.getRecentTracks' }).encode('utf-8') text = utils.web.getUrl(url, data=data) text = text.decode() other, user, np, artist, track, plays, when = self._parseJson( text, plays) if other: if other == -1: return return other now = lambda n: 'np.' if n else 'last played' time_since = lambda w: ' (%s)' % ircutils.bold(w) if w else '' reply = '%s %s %s - %s%s%s' % (user, now(np), artist, track, plays, time_since(when)) return reply
def horo(self, irc, msg, args, midnight_check, psign): """[bool: Only print when local hour is 0 - default False] [sign: if not set will dump all signs] Returns horoscope in french for one zodiacal sign or all """ signs = [] tsigns = [ 'belier', 'taureau', 'gemeaux', 'cancer', 'lion', 'vierge', 'balance', 'scorpion', 'sagittaire', 'capricorne', 'verseau', 'poissons' ] if midnight_check and int( datetime.datetime.fromtimestamp(time()).strftime('%H')): self.log.info( "Horoscope plugin: checked and not [00:00-00:59] local time") return if psign: if psign not in tsigns: irc.error("Same player try again!") else: signs = [psign] else: signs = tsigns for sign in signs: url = "https://www.lhoroscope.com/horoscope-general/horoscope-%s-du-jour.asp" % sign try: result = requests.get(url) soup = BeautifulSoup(result.content) h = soup.find(class_="panel-body").text.strip() h = fix_encoding(h) except Exception as e: irc.error("Error {}".format(e)) break else: irc.reply(ircutils.bold(sign.title()) + " : " + h, prefixNick=False) sleep(2)
def fml(self, irc, msg, args, query): """[<id>] Displays an entry from fmylife.com. If <id> is not given, fetch a random entry from the API.""" query = query or 'random' url = ('http://api.betacie.com/view/%s/nocomment' '?key=4be9c43fc03fe&language=en' % query) try: data = utils.web.getUrl(url) except utils.web.Error as e: irc.error(str(e), Raise=True) tree = ElementTree.fromstring(data.decode('utf-8')) tree = tree.find('items/item') try: category = tree.find('category').text text = tree.find('text').text fmlid = tree.attrib['id'] url = tree.find('short_url').text except AttributeError as e: self.log.debug("FML: Error fetching FML %s from URL %s: %s", query, url, e) irc.error( "That FML does not exist or there was an error " "fetching data from the API.", Raise=True) if not fmlid: irc.error("That FML does not exist.", Raise=True) votes = ircutils.bold( "[Agreed: %s / Deserved: %s]" % (tree.find('agree').text, tree.find('deserved').text)) s = format('\x02#%i [%s]\x02: %s - %s %u', fmlid, category, text, votes, url) irc.reply(s)
def whoat(self, irc, msg, args, channel, optlist, system): """[<channel>] [--all] <system> List characters and their ships in <system>. If --all is given, ignore the max lines limitation. """ if not self.registryValue('full_access', channel): irc.reply('Concord denies you access on this channel!') return rows = self._sql(""" SELECT * FROM corporation_membertracking WHERE location ILIKE %s AND owner_id=%s""", ['%%{0}%%'.format(system), self.corporationID], single=False) if len(rows) == 0: irc.reply('Found 0 characters in "{0}"'.format(system), prefixNick=False) return if len(rows) <= self.registryValue('max_lines', channel) or ('all', True) in optlist \ and len(rows) > 0: for row in rows: if row['shipType'] == 'Unknown Type': ship = 'Pod' else: ship = row['shipType'] irc.reply('{0} :: {1} :: {2}'.format( ircutils.bold(row['name']), self._colorize_system( self._get_location_by_name(row['location'])), ship), prefixNick=False) elif len(rows) > self.registryValue('max_lines', channel): irc.reply( 'Found {0} characters in "{1}", but will not name them all'. format(len(rows), system), prefixNick=False)
def formatData(self, data, bold=True, max=0, onetoone=False): data = self.decode(data) results = [] if max: data = data[:max] for result in data: title = utils.web.htmlToText(result['title']\ .encode('utf-8')) url = result['url'] url = url.encode('utf-8') if title: if bold: title = ircutils.bold(title) results.append(format('%s: %u', title, url)) else: results.append(url) repl = lambda x: x if isinstance(x, unicode) else unicode(x, 'utf8') results = list(map(repl, results)) if not results: return ['No matches found.'] elif onetoone: return results else: return ['; '.decode('utf-8').join(results)]
def info(self, irc, msg, args, text): """<show name> searches tvrage.com for <show name> and returns some basic information about that show """ re_url = re.compile(r'Show\sURL@(.*?)\s') re_show = re.compile(r'Show\sName@(.*?)\sShow') re_time = re.compile(r'Airtime@(.*?)\sRun') re_genre = re.compile(r'Genres@(.*)\s') re_status = re.compile(r'Status@(.*?)\s') re_network = re.compile(r'Network@(.*?)\s') showsrc = self.search(text) showname = re_show.findall(showsrc) showurl = re_url.findall(showsrc) genres = re_genre.findall(showsrc) airtime = re_time.findall(showsrc) status = re_status.findall(showsrc) network = re_network.findall(showsrc) if not showname: irc.reply("Could not find the series.") else: irc.reply(format('%s: Status: %s. Airs on %s on %s. Genres: %s %s', ircutils.bold(showname[0]), status[0], network[0], airtime[0], genres[0], showurl[0]), prefixNick=False)
def recipes(self, irc, msg, args, item): """<item> Returns Minecraft crafting recipes using the given item. """ soup = self.get_page(irc, item) # First, look for the "Crafting ingredient" header (usually under a # section called "Usage"). Only here will we find the recipes for each # item. header = '' for header in soup.find_all('h3'): if header.span and header.span.get_text().strip().lower( ) == 'crafting ingredient': break else: irc.error("No recipes found.", Raise=True) for tag in header.next_siblings: # Only look at crafting table UIs after this header. if tag.name == 'table' and tag.get( "data-description").lower() == 'crafting recipes': recipes = [] # Iterate over all the recipes shown and get their names. for crafting_data in tag.find_all('tr')[1:]: recipes.append(format_text(crafting_data.th.get_text())) # After we've found these results, we can stop looking for # crafting table UIs. break out_s = format('Recipes using %s include: %L', ircutils.bold(item), sorted(recipes)) irc.reply(out_s)
def zeroclick(self, irc, msg, args, text): """<text> Looks up <text> on DuckDuckGo's zero-click engine.""" # Zero-click can give multiple replies for things if the # query is ambiguous, sort of like an encyclopedia. # For example, looking up "2^3" will give both: # Zero-click info: 8 (number) # Zero-click info: 8 replies = {} for td in self._ddgurl(text)[-1]: if td.text.startswith("Zero-click info:"): # Make a dictionary of things item = td.text.split("Zero-click info:", 1)[1].strip() td = td.parent.next_sibling.next_sibling.\ find("td") # Condense newlines (<br> tags). XXX: make these separators configurable. for br in td.find_all('br'): br.replace_with(' - ') res = ' | '.join(td.text.strip().split("\n")) try: # Some zero-click results have an attached link to them. link = td.a.get('href') # Others have a piece of meaningless JavaScript... if link != "javascript:;": res += format(" %u", link) except AttributeError: pass replies[item] = res else: if not replies: irc.error("No zero-click info could be found for '%s'." % text, Raise=True) s = ["%s - %s" % (ircutils.bold(k), v) for k, v in replies.items()] irc.reply("; ".join(s))
def howmany(self, irc, msg, args, channel, typeName, locationName): """[<channel>] <typeName> <locationName> List how many items matching <typeName> at location matching <locationName>. """ if not self.registryValue('full_access', channel): irc.reply('Concord denies you access on this channel!') return rows = self._sql(""" SELECT "typeName", "locationName", SUM("quantity") as amount FROM corporation_asset WHERE "typeName" ILIKE %s AND "locationName" ILIKE %s AND owner_id = %s GROUP BY "typeName", "locationName" """, [ '%%{0}%%'.format(typeName), '%%{0}%%'.format(locationName), self.corporationID ], single=False) if len(rows) == 0: irc.reply('Found 0 items at that location') return for row in rows: location = self._get_location_by_name(row['locationName']) irc.reply('{0} :: {1} :: {2}'.format( row['typeName'], self._colorize_system(location), ircutils.bold('{:,f}'.format(row['amount']))), prefixNick=False)
def random(self, irc, msg, args, channel): """[<channel>] Returns random factoids from the database for <channel>. <channel> is only necessary if the message isn't sent in the channel itself. """ db = self.getDb(channel) cursor = db.cursor() cursor.execute("""SELECT id, key_id, fact_id FROM relations ORDER BY random() LIMIT 3""") results = cursor.fetchall() if len(results) != 0: L = [] for (relationid, keyid, factid) in results: cursor.execute("""SELECT keys.key, factoids.fact FROM keys, factoids WHERE factoids.id=? AND keys.id=?""", (factid,keyid,)) (key,factoid) = cursor.fetchall()[0] L.append('"%s": %s' % (ircutils.bold(key), factoid)) irc.reply('; '.join(L)) else: irc.error(_('I couldn\'t find a factoid.'))
def _bu(self, string): """Returns a bold/underline string.""" return ircutils.bold(ircutils.underline(string))
def _bold(self, string): """Returns a bold string.""" return ircutils.bold(string)
def craft(self, irc, msg, args, item): """<item> Attempts to look up crafting information from the Minecraft wiki. """ soup = self.get_page(irc, item) # Find the "Crafting table" displayed in the Wiki page showing how to craft the item. crafting_table = soup.find('table', attrs={"data-description": 'Crafting recipes'}) if not crafting_table: irc.error("No crafting information found.", Raise=True) for tag in crafting_table.previous_siblings: # We only want the instructions on how to craft the item, not the items crafted WITH it. # TODO: maybe this behavior could be a different command? if tag.name == 'h3': t = tag.contents[0].get_text().strip() if t == 'Crafting ingredient': irc.error("The item '%s' cannot be crafted." % item, Raise=True) # Get the first crafting result. TODO: optionally show all recipes if there are more than one. crafting_data = crafting_table.find_all('tr')[1] # Shows the text of the ingredients used to craft (e.g. "Glass + Any dye") ingredients = format_text(crafting_data.td.get_text()) recipe = [] # This tracks how long the longest item name is. Used for formatting the crafting table on # IRC with the right dimensions. maxitemlength = 0 # Now, parse the layout of the 3x3 crafting grid the wiki shows for items. for rowdata in crafting_data.div.span.span.children: rowitems = [] # Iterate over the rows of the crafting grid, and then the items in each. for itemslot in rowdata.children: itemlink = itemslot.a if itemlink: # Item exists. Get the name of the item using the caption of its wiki page link. itemname = itemlink.get('title') # Replace spaces with hyphens in the display to make the display monospace. #itemname = itemname.replace(' ', '-') # Update the existing max item length if the length of the current one is # greater. if len(itemname) > maxitemlength: maxitemlength = len(itemname) rowitems.append(itemname) elif itemslot.find('br'): # Empty square. rowitems.append('') if rowitems: recipe.append(rowitems) irc.reply("Recipe for %s uses: %s" % (ircutils.bold(item), ircutils.bold(ingredients))) for row in filter(any, recipe): # Only output rows that have filled squares. # For each item, center its name based on the length of the longest item name in the # recipe. This gives the grid a more monospace-y feel. items = [s.center(maxitemlength, '-') for s in row] irc.reply('|%s|' % '|'.join(items))