def check_price(nick,ticker,default_price): checkprice = StockMarket() checkprice.open_db(file_Name) check = StockTrade() check.open_db(saved_stocks) try: curprice = checkprice.get_balance(ticker) checked = check.get_prices(ticker) except: checkprice.add_stock(ticker,default_price) curprice = checkprice.get_balance(ticker) checked = check.get_prices(ticker) ticker = color(bold(ticker + ":"),colors.RED) curprice = color(str(curprice),colors.RED) phrase = ('%s ɷ %s' %(ticker,curprice)) runs = 0 for x in (checked): if nick == checked[runs][0]: name = color(checked[runs][0],colors.RED) else: name = checked[runs][0][:3] owned = (bold(" |") + " %s %s @ %s " % (name.title(), checked[runs][2], checked[runs][1])) phrase += owned runs = runs + 1 return phrase
def rpost_info(bot, trigger, match=None): r = praw.Reddit(user_agent=USER_AGENT) match = match or trigger s = r.get_submission(submission_id=match.group(2)) message = ('[REDDIT] {title} {link}{nsfw} | {points} points ({percent}) | ' '{comments} comments | Posted by {author} | ' 'Created at {created}') subreddit = s.subreddit.display_name if s.is_self: link = '(self.{})'.format(subreddit) else: link = '({}) to r/{}'.format(s.url, subreddit) if s.over_18: if subreddit.lower() in spoiler_subs: nsfw = bold(color(' [SPOILERS]', colors.RED)) else: nsfw = bold(color(' [NSFW]', colors.RED)) sfw = bot.db.get_channel_value(trigger.sender, 'sfw') if sfw: link = '(link hidden)' bot.write([ 'KICK', trigger.sender, trigger.nick, 'Linking to NSFW content in a SFW channel.' ]) else: nsfw = '' if s.author: author = s.author.name else: author = '[deleted]' tz = time.get_timezone(bot.db, bot.config, None, trigger.nick, trigger.sender) time_created = dt.datetime.utcfromtimestamp(s.created_utc) created = time.format_time(bot.db, bot.config, tz, trigger.nick, trigger.sender, time_created) if s.score > 0: point_color = colors.GREEN else: point_color = colors.RED percent = color(unicode(s.upvote_ratio * 100) + '%', point_color) title = unescape(s.title) message = message.format(title=title, link=link, nsfw=nsfw, points=s.score, percent=percent, comments=s.num_comments, author=author, created=created) bot.say(message)
def user_handler(self, trigger_argsdict): subcommand_valid = ['check'] subcommand = spicemanip( [x for x in trigger_argsdict["args"] if x in subcommand_valid], 1) or 'check' userreal = self.reddit_user_exists(trigger_argsdict["command"]) if not userreal["exists"]: return userreal["error"] fulluurul = str("https://www.reddit.com/" + trigger_argsdict["slashcomm"] + "/" + trigger_argsdict["command"]) if subcommand == 'check': u = self.praw.redditor(trigger_argsdict["command"]) message = ['[REDDITOR] ' + u.name] is_cakeday = self.user_cakeday(u.created_utc) if is_cakeday: message.append(bold(color('Cake day', colors.LIGHT_PURPLE))) message.append(fulluurul) if u.is_gold: message.append(bold(color('Gold', colors.YELLOW))) if u.is_mod: message.append(bold(color('Mod', colors.GREEN))) message.append('Link: ' + str(u.link_karma)) message.append('Comment: ' + str(u.comment_karma)) return message
def _vimeo_say_result(bot, trigger, id_, include_link=True): """ Parse and say result """ url = "http://vimeo.com/api/v2/video/{vid}.json".format(vid=id_) try: response = requests.get(url) LOGGER.info(response.url) response = response.json() except: LOGGER.error("something went wrong fetching {}".format(url)) return data = response[0] reply = {} vimeo_tag = color("vimeo", "cyan") reply_string = bold("[{}] ".format(vimeo_tag)) reply['title'] = bold(data['title']) reply['duration'] = _parse_duration(data['duration']) reply['channel'] = "Channel: {}".format(data['user_name']) reply['views'] = "{:,} views".format(data['stats_number_of_plays']) reply['uploaded'] = "Uploaded {}".format( _parse_published_at_relative(bot, trigger, data['upload_date'])) reply_string += " | ".join(reply.values()) bot.say(reply_string)
def commit_info(bot, trigger, match=None): match = match or trigger URL = 'https://api.github.com/repos/%s/commits/%s' % (match.group(1), match.group(2)) try: raw = fetch_api_endpoint(bot, URL) except HTTPError: bot.say('[Github] API returned an error.') return NOLIMIT data = json.loads(raw) try: if len(data['commit']['message'].split('\n')) > 1: body = data['commit']['message'].split('\n')[0] + '...' else: body = data['commit']['message'].split('\n')[0] except (KeyError): bot.say( '[Github] API says this is an invalid commit. Please report this if you know it\'s a correct link!' ) return NOLIMIT if body.strip() == '': body = 'No commit message provided.' response = [ bold('[Github]'), ' [', match.group(1), '] ', data['author']['login'], ': ', body, bold(' | '), str(data['stats']['total']), ' changes in ', str(len(data['files'])), ' files' ] bot.say(''.join(response))
def redditor_info(bot, trigger, match, commanded=False): """Shows information about the given Redditor""" try: u = bot.memory['reddit_praw'].redditor(match) u.id # shortcut to check if the user exists or not except prawcore.exceptions.NotFound: if commanded: bot.reply('No such Redditor.') # Fail silently if it wasn't an explicit command. return plugin.NOLIMIT message = u.name is_cakeday = get_is_cakeday(u.created_utc) if is_cakeday: message = message + ' | ' + bold(color('Cake day', colors.LIGHT_PURPLE)) if commanded: message = message + ' | https://reddit.com/u/' + u.name if u.is_gold: message = message + ' | ' + bold(color('Gold', colors.YELLOW)) if u.is_employee: message = message + ' | ' + bold(color('Employee', colors.RED)) if u.is_mod: message = message + ' | ' + bold(color('Mod', colors.GREEN)) message = message + (' | Link: ' + str(u.link_karma) + ' | Comment: ' + str(u.comment_karma)) bot.say(message)
def cancelled(bot, trigger): """Show current cancelled classes at MUN""" page, headers = web.get(uri, return_headers=True) if headers['_http_status'] != 200: bot.say('Couldn\'t find cancellation information.') return parsed = html.fromstring(page) middle = parsed.get_element_by_id('middle') contents = list(middle) reply = [] if trigger.nick != trigger.sender: bot.reply('I\'m messaging you with a detailed cancellation list!') for element in contents: if element.tag=='p' and element.text_content() == '________________________________________': break elif element.tag=='h2': printed = True text = element.text_content() day = parser.parse(text) if day.date() == datetime.today().date(): reply.append('MUN\'s Cancellations for ' + bold(text) + ' (TODAY):') else: reply.append('MUN\'s Cancellations for ' + bold(text) + ': ') elif element.tag=='p': text = element.text_content() course = list(element)[0].text_content() reply.append(bold(course) + text[len(course):]) for a in reply: bot.msg(trigger.nick, a)
def short_cancelled(bot, trigger): """Display short list of cancelled courses at MUN""" page, headers = web.get(uri, return_headers=True) if headers['_http_status'] != 200: bot.say('Couldn\'t find cancellation information.') return parsed = html.fromstring(page) middle = parsed.get_element_by_id('middle') contents = list(middle) reply = '' for element in contents: if element.tag=='p' and element.text_content() == '________________________________________': break elif element.tag=='h2': printed = True text = element.text_content() day = parser.parse(text) if day.date() == datetime.today().date(): reply += '| MUN\'s Cancellations for ' + bold(text) + ' (TODAY): ' else: reply += '| MUN\'s Cancellations for ' + bold(text) + ': ' elif element.tag=='p': text = element.text_content() course = list(element)[0].text_content() reply += course + ', ' bot.say(reply[2:-2]) bot.say('Use \'.canceldetail\' for more detailed information')
def give_money(bot, trigger): """Give X amount of your money to another user.""" try: data = gambling_checks(bot, trigger) except Exception as msg: return bot.reply(msg) amount = data["bet"] msg = data["msg"] target = data["target"] giver = trigger.nick if not amount: return bot.reply(msg) if giver == target: return bot.reply("You gifted yourself the same amount, I guess?") # Check if the transaction can even occur give_check = bot.db.get_nick_value(giver, "currency_amount") receive_check = bot.db.get_nick_value(target, "currency_amount") if give_check is None: return bot.reply( "You can't do that yet. Please run `.iwantmoney` first.") if receive_check is None: return bot.reply( "{0} hasn't participated yet. {0} needs to run `.iwantmoney` first.".format(target)) if amount > give_check: return bot.reply( "You don't have enough money to complete this transcation, you filthy poor.") # Check for valid target to give money to. if target not in bot.channels[trigger.sender].users: return bot.reply("Please provide a valid user.") giver_new_balance = bot.db.get_nick_value( giver, "currency_amount", 0) - amount target_new_balance = bot.db.get_nick_value( target, "currency_amount", 0) + amount # Take away the money from the giver. bot.db.set_nick_value(giver, "currency_amount", giver_new_balance) # Give the money to the target/reciever. bot.db.set_nick_value(target, "currency_amount", target_new_balance) giver_balance = "${:,}".format(giver_new_balance) target_balance = "${:,}".format(target_new_balance) gifted_amount = "${:,}".format(amount) bot.say( "{} gifted {} to {}. {} now has {} and {} has {}.".format( giver, bold(gifted_amount), target, giver, bold(giver_balance), target, bold(target_balance)))
def url_handler(bot: SopelWrapper, trigger: Trigger): """Checks for malicious URLs.""" mode = bot.db.get_channel_value( trigger.sender, "safety", bot.settings.safety.default_mode, ) if mode == "off": return local_only = "local" in mode or bot.settings.safety.vt_api_key is None strict = "strict" in mode for url in tools.web.search_urls(trigger): safe_url = safeify_url(url) positives = 0 # Number of engines saying it's malicious total = 0 # Number of total engines try: hostname = urlparse(url).hostname.lower() except ValueError: pass # Invalid address else: if any(regex.search(hostname) for regex in known_good): continue # explicitly trusted if hostname in bot.memory[SAFETY_CACHE_LOCAL_KEY]: LOGGER.debug("[local] domain in blocklist: %r", hostname) positives += 1 total += 1 result = virustotal_lookup(bot, url, local_only=local_only) if result: positives += result["positives"] total += result["total"] if positives >= 1: # Possibly malicious URL detected! LOGGER.info( "Possibly malicious link (%s/%s) posted in %s by %s: %r", positives, total, trigger.sender, trigger.nick, safe_url, ) bot.say( "{} {} of {} engine{} flagged a link {} posted as malicious". format( bold(color("WARNING:", colors.RED)), positives, total, "" if total == 1 else "s", bold(trigger.nick), )) if strict: bot.kick(trigger.nick, trigger.sender, "Posted a malicious link")
def rpost_info(bot, trigger, match=None): r = praw.Reddit( user_agent=USER_AGENT, client_id='6EiphT6SSQq7FQ', client_secret=None, ) match = match or trigger s = r.submission(id=match.group(2)) message = ('[REDDIT] {title} {link}{nsfw} | {points} points ({percent}) | ' '{comments} comments | Posted by {author} | ' 'Created at {created}') subreddit = s.subreddit.display_name if s.is_self: link = '(self.{})'.format(subreddit) else: link = '({}) to r/{}'.format(s.url, subreddit) if s.over_18: if subreddit.lower() in spoiler_subs: nsfw = bold(color(' [SPOILERS]', colors.RED)) else: nsfw = bold(color(' [NSFW]', colors.RED)) sfw = bot.db.get_channel_value(trigger.sender, 'sfw') if sfw: link = '(link hidden)' bot.write(['KICK', trigger.sender, trigger.nick, 'Linking to NSFW content in a SFW channel.']) else: nsfw = '' if s.author: author = s.author.name else: author = '[deleted]' tz = time.get_timezone(bot.db, bot.config, None, trigger.nick, trigger.sender) time_created = dt.datetime.utcfromtimestamp(s.created_utc) created = time.format_time(bot.db, bot.config, tz, trigger.nick, trigger.sender, time_created) if s.score > 0: point_color = colors.GREEN else: point_color = colors.RED percent = color(unicode(s.upvote_ratio * 100) + '%', point_color) title = unescape(s.title) message = message.format( title=title, link=link, nsfw=nsfw, points=s.score, percent=percent, comments=s.num_comments, author=author, created=created) bot.say(message)
def parse_games(date): if date: r = requests.get('https://statsapi.web.nhl.com/api/v1/schedule?date={}&expand=schedule.linescore'.format(date)) else: r = requests.get('https://statsapi.web.nhl.com/api/v1/schedule?expand=schedule.linescore') reply = [] for date in r.json()['dates']: # TODO - Figure out what events and matches are for game in date['games']: # Game Is Not Started if game['status']['abstractGameState'] == 'Preview': reply.append('{} @ {} {}'.format( game['teams']['away']['team']['name'], game['teams']['home']['team']['name'], arrow.get(game['gameDate']).to('US/Eastern').format('HH:mm'), )) elif game['status']['abstractGameState'] == 'Final': # Away Team Win if int(game['teams']['away']['score']) > int(game['teams']['home']['score']): reply.append('{} {} {} {} Final'.format( bold(game['teams']['away']['team']['name']), bold(str(game['teams']['away']['score'])), game['teams']['home']['team']['name'], str(game['teams']['home']['score']), )) # Home Team Win elif int(game['teams']['home']['score']) > int(game['teams']['away']['score']): reply.append('{} {} {} {} Final'.format( game['teams']['away']['team']['name'], str(game['teams']['away']['score']), bold(game['teams']['home']['team']['name']), bold(str(game['teams']['home']['score'])), )) # Tie Game else: reply.append('{} {} {} {} Final'.format( game['teams']['away']['team']['name'], game['teams']['away']['score'], game['teams']['home']['team']['name'], game['teams']['home']['score'], )) elif game['status']['abstractGameState'] == 'Live': reply.append('{} {} {} {} {} {}'.format( game['teams']['away']['team']['name'], game['teams']['away']['score'], game['teams']['home']['team']['name'], game['teams']['home']['score'], game['linescore']['currentPeriodOrdinal'], game['linescore']['currentPeriodTimeRemaining'], )) return reply
def redditor_info(bot, trigger, match=None): """Shows information about the given Redditor""" commanded = re.match(bot.config.core.prefix + 'redditor', trigger) r = praw.Reddit( user_agent=USER_AGENT, client_id='6EiphT6SSQq7FQ', client_secret=None, ) match = match or trigger try: # praw <4.0 style u = r.get_redditor(match.group(2)) except AttributeError: # praw >=4.0 style u = r.redditor(match.group(2)) except Exception: # TODO: Be specific if commanded: bot.say('No such Redditor.') return NOLIMIT else: return # Fail silently if it wasn't an explicit command. message = '[REDDITOR] ' + u.name now = dt.datetime.utcnow() cakeday_start = dt.datetime.utcfromtimestamp(u.created_utc) cakeday_start = cakeday_start.replace(year=now.year) day = dt.timedelta(days=1) year_div_by_400 = now.year % 400 == 0 year_div_by_100 = now.year % 100 == 0 year_div_by_4 = now.year % 4 == 0 is_leap = year_div_by_400 or ((not year_div_by_100) and year_div_by_4) if (not is_leap) and ((cakeday_start.month, cakeday_start.day) == (2, 29)): # If cake day is 2/29 and it's not a leap year, cake day is 1/3. # Cake day begins at exact account creation time. is_cakeday = cakeday_start + day <= now <= cakeday_start + (2 * day) else: is_cakeday = cakeday_start <= now <= cakeday_start + day if is_cakeday: message = message + ' | ' + bold(color('Cake day', colors.LIGHT_PURPLE)) if commanded: message = message + ' | https://reddit.com/u/' + u.name if u.is_gold: message = message + ' | ' + bold(color('Gold', colors.YELLOW)) if u.is_mod: message = message + ' | ' + bold(color('Mod', colors.GREEN)) message = message + (' | Link: ' + str(u.link_karma) + ' | Comment: ' + str(u.comment_karma)) bot.say(message)
def parse_games(date): if date: r = requests.get( 'https://statsapi.mlb.com/api/v1/schedule?sportId=1&date={}'. format(date)) else: r = requests.get('https://statsapi.mlb.com/api/v1/schedule?sportId=1') reply = [] for date in r.json()['dates']: # TODO - Figure out what events and matches are for game in date['games']: # Game Is Not Started if game['status']['abstractGameState'] == 'Preview': reply.append('{} @ {} {} Eastern'.format( game['teams']['away']['team']['name'], game['teams']['home']['team']['name'], # TODO - Allow users to specify timezone to return arrow.get(game['gameDate'] ).to('US/Eastern').format('HH:mm'), )) elif game['status']['abstractGameState'] == 'Final': # Away Team Win if int(game['teams']['away']['score']) > int( game['teams']['home']['score']): reply.append('{} {} {} {} Final'.format( bold(game['teams']['away']['team']['name']), bold(str(game['teams']['away']['score'])), game['teams']['home']['team']['name'], str(game['teams']['home']['score']), )) # Home Team Win elif int(game['teams']['home']['score']) > int( game['teams']['away']['score']): reply.append('{} {} {} {} Final'.format( game['teams']['away']['team']['name'], str(game['teams']['away']['score']), bold(game['teams']['home']['team']['name']), bold(str(game['teams']['home']['score'])), )) # Tie Game else: reply.append('{} {} {} {} Final'.format( game['teams']['away']['team']['name'], game['teams']['away']['score'], game['teams']['home']['team']['name'], game['teams']['home']['score'], )) return reply
def meetingsubject(bot, trigger): """ Change the meeting subject.\ See [meetbot module usage]({% link _usage/meetbot-module.md %}) """ if not ismeetingrunning(trigger.sender): bot.say('Can\'t do that, start meeting first') return if not trigger.group(2): bot.say('what is the subject?') return if not ischair(trigger.nick, trigger.sender): bot.say('Only meeting head or chairs can do that') return meetings_dict[trigger.sender]['current_subject'] = trigger.group(2) logfile = codecs.open(meeting_log_path + trigger.sender + '/' + figure_logfile_name(trigger.sender) + '.html', 'a', encoding='utf-8') logfile.write('</ul><h3>' + trigger.group(2) + '</h3><ul>') logfile.close() logplain( 'Current subject: ' + trigger.group(2) + ', (set by ' + trigger.nick + ')', trigger.sender) bot.say(bold('Current subject:') + ' ' + trigger.group(2))
def get_weather(bundle): """Gets weather for a user or location""" url = ("https://api.climacell.co/v3/weather/realtime?lat={lat}&lon={lon}" "&fields={fields}&unit_system={units}&apikey={api_key}").format( lat=bundle['latitude'], lon=bundle['longitude'], fields=bundle['fields'], units=bundle['units'], api_key=bundle['api_key']) data = requests.get(url) LOGGER.debug(data.url) data = data.json() sort_keys = {} for k in data: if SORTED_FIELDS.get(k): sort_keys[k] = SORTED_FIELDS.get(k) else: sort_keys[k] = 999 sorted_dict = { k: data[k] for k in sorted(data, key=lambda x: sort_keys[x]) } parsed_fields = _parse_data(sorted_dict, bundle['tz']) location = bold("[{}]".format(bundle['location'])) base_string = "{} {} | Powered by ClimaCell API (https://www.climacell.co/weather-api)".format( location, parsed_fields) return base_string
def check_money(bot, trigger): """Check how much money you or another user has.""" # We're not using gambling_checks() because it's # tuned for most other commands in this plugin. # Channel Check if trigger.sender == GCHAN: pass else: return bot.reply("This command can only be used in {}".format(GCHAN)) # Target Check target = plain(trigger.group(3) or trigger.nick) if not target: return bot.reply( "If you're seeing this message...everything is horribly broken.") target = tools.Identifier(target) if target == bot.nick: return bot.reply("I just run the place; I don't participate.") if target not in bot.channels[trigger.sender].users: return bot.reply("Please provide a valid user.") # Actual Currency Check currency_amount = bot.db.get_nick_value(target, "currency_amount") if currency_amount is not None: balance = "${:,}".format(currency_amount) bot.say("{} has {}".format(target, bold(balance))) else: bot.say("{} needs to run `.iwantmoney` first.".format(target))
def pick_random_money(bot, trigger): """Pick up some money the bot has randomly dropped on the ground.""" # We're not using gambling_checks() because it's # tuned for most other commands in this plugin. if trigger.sender == GCHAN: pass else: return bot.reply("This command can only be used in {}".format(GCHAN)) target = trigger.nick check_for_money = bot.db.get_nick_value(target, "currency_amount") if check_for_money is None: return bot.reply( "You can't do this yet! Please run the `.iwantmoney` command.") amount = bot.db.get_channel_value(GCHAN, "random_money", 0) if not amount: insults = [ "There's no money to pick up, greedy f**k.", "Sorry you're poor, but there's no money for you." ] return bot.reply(secrets.choice(insults)) elif 10 <= amount <= 100: bot.db.set_channel_value(GCHAN, "random_money", 0) new_balance = check_for_money + amount bot.db.set_nick_value(target, "currency_amount", new_balance) balance = "${:,}".format(new_balance) bot.reply( "Congrats! You picked up ${}. Now you have {}.".format( amount, bold(balance))) else: return bot.say( "xnaas: Error in pick_random_money() or casino_random_money(). Good luck!")
def getticket(bot, trigger): """Look up tickets in Jira and display their information""" if not hasattr(bot.config, 'jira'): bot.say("I don't seem to have a 'jira' section in my config!") return user = bot.config.jira.user password = bot.config.jira.password url = bot.config.jira.url if user is None or password is None or url is None: bot.say('You need to set user, password and url in the jira section of the config') return for issue in findall('[A-Z]+-[0-9]+', trigger): r = requests.get( os.path.join(url, 'rest/api/2/issue', issue), auth=(user, password)) if r.status_code != 200: return j = r.json() bot.say("({} {}) {} [ {} ] {} {}".format( j['fields']['issuetype']['name'], j['key'], j['fields']['summary'], color((j['fields']['assignee']['displayName'] if j['fields']['assignee'] else 'Unassigned'), 'BLUE'), bold(color(j['fields']['status']['name'], 'GREEN')), os.path.join(url, 'browse', j['key'])))
def get_decorated_name(team: Team, string: str) -> str: if team is Team.red: irc_color = irc_format.colors.RED else: irc_color = irc_format.colors.LIGHT_BLUE decorated_name = irc_format.bold(irc_format.color(string, irc_color)) return decorated_name
def endmeeting(bot, trigger): """ End a meeting.\ See [meetbot module usage]({% link _usage/meetbot-module.md %}) """ if not ismeetingrunning(trigger.sender): bot.say('Can\'t do that, start meeting first') return if not ischair(trigger.nick, trigger.sender): bot.say('Only meeting head or chairs can do that') return meeting_length = time.time() - meetings_dict[trigger.sender]['start'] # TODO: Humanize time output bot.say( bold("Meeting ended!") + " total meeting length %d seconds" % meeting_length) logHTML_end(trigger.sender) htmllog_url = meeting_log_baseurl + quote( trigger.sender + '/' + figure_logfile_name(trigger.sender) + '.html') logplain( 'Meeting ended by %s, total meeting length %d seconds' % (trigger.nick, meeting_length), trigger.sender) bot.say('Meeting minutes: ' + htmllog_url) meetings_dict[trigger.sender] = Ddict(dict) del meeting_actions[trigger.sender]
def spymaster_hint(bot, trigger): if not check_phase_play(bot, trigger): return game = get_game(bot) player_team = game.get_player_team(str(trigger.nick)) if player_team is not game.moving_team: return if str(trigger.nick) != game.spymasters[player_team]: return word = trigger.groups(17)[2] number = trigger.groups(17)[3] try: n = int(number) except ValueError: if number != 'unlimited': say( bot, trigger, 'The second argument must either be a number ' 'in the 0-9 range or "unlimited".') return if n < 0 or n > 9: say( bot, trigger, 'The second argument must either be a number ' 'in the 0-9 range or * for unlimited.') return team_name = get_decorated_team_name(player_team) hint = '{word} {number}'.format(word=word.upper(), number=number) decorated_hint = irc_format.bold(irc_format.underline(hint)) response = '{team_name}\'s hint is {hint}'.format(team_name=team_name, hint=decorated_hint) say(bot, trigger, response)
def default_mask(trigger): welcome = formatting.color('Welcome to:', formatting.colors.PURPLE) chan = formatting.color(trigger.sender, formatting.colors.TEAL) topic_ = formatting.bold('Topic:') topic_ = formatting.color('| ' + topic_, formatting.colors.PURPLE) arg = formatting.color('{}', formatting.colors.GREEN) return '{} {} {} {}'.format(welcome, chan, topic_, arg)
def now_playing(bot, trigger): global network db_key = 'lastfm_username' if trigger.group(2): args = trigger.group(2).split(' ') if args[0] in ADD_STRINGS: if len(args) == 1: bot.reply('please provide a username. (.np -s <url>)') else: username = args[1].strip() user_exists = False try: network.get_user(username).get_id() user_exists = True except pylast.WSError: pass if user_exists: bot.db.set_nick_value(trigger.nick, db_key, username) bot.reply('last.fm username set.') else: bot.reply('no such last.fm user. Are you trying to trick me? :^)') return username = bot.db.get_nick_value(trigger.nick, db_key) if not username: bot.reply('you have no last.fm username set. Please set one with .np -s <username>') else: user = network.get_user(username) current_track = user.get_now_playing() if not current_track: bot.say('{0} is not listening to anything right now.'.format(trigger.nick)) else: trackinfo = '{0} - {1}'.format(current_track.get_artist().get_name(), current_track.get_title()) bot.say('{0} is now playing {1} | {2}' .format(trigger.nick, bold(trackinfo), color(current_track.get_url(), colors.BLUE)))
def ytsearch(bot, trigger): """ .youtube <query> - Search YouTube """ if not trigger.group(2): return uri = 'https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&q=' + trigger.group(2) raw = web.get('{0}&key={1}'.format(uri, bot.config.google.public_key)) vid = json.loads(raw)['items'][0]['id']['videoId'] uri = 'https://www.googleapis.com/youtube/v3/videos?id=' + vid + '&part=contentDetails,snippet,statistics' video_info = ytget(bot, trigger, uri) if video_info is None: return title = video_info['snippet']['title'] uploader = video_info['snippet']['channelTitle'] duration = video_info['contentDetails']['duration'] views = video_info['statistics']['viewCount'] likes = video_info['statistics']['likeCount'] dislikes = video_info['statistics']['dislikeCount'] message = '[YT Search] {0} | https://youtu.be/{1} | Duration: {2} | Views: {3} | Uploader: {4} | {5} | {6}'.format( bold(title), video_info['id'], duration, views, uploader, color(likes, colors.GREEN), color(dislikes, colors.RED)) bot.say(message)
def meetinglink(bot, trigger): """ Log a link in the meeing log.\ See [meetbot module usage]({% link _usage/meetbot-module.md %}) """ if not is_meeting_running(trigger.sender): bot.say("There is no active meeting") return if not trigger.group(2): bot.say( "Try `{}link https://relevant-website.example/`".format( bot.config.core.help_prefix ) ) return if not is_chair(trigger.nick, trigger.sender): bot.say("Only meeting head or chairs can do that") return link = trigger.group(2) if not link.startswith("http"): link = "http://" + link try: title = find_title(link, verify=bot.config.core.verify_ssl) except Exception: # TODO: Be specific title = "" log_plain("LINK: %s [%s]" % (link, title), trigger.sender) log_html_listitem('<a href="%s">%s</a>' % (link, title), trigger.sender) bot.say(formatting.bold("LINK:") + " " + link)
def meetingmissão(bot, trigger): """ Change the meeting missão.\ See [bloucobot module usage]({% link _usage/bloucobot-module.md %}) """ if not is_meeting_running(trigger.sender): bot.say("Não tem Blouco aqui") return if not trigger.group(2): bot.say("Qual a missão?") return if not is_chair(trigger.nick, trigger.sender): bot.say("Somente Porta-estandarte e Puxadoras podem fazer isso") return meetings_dict[trigger.sender]["current_missão"] = trigger.group(2) logfile_filename = os.path.join( meeting_log_path + trigger.sender, figure_logfile_name(trigger.sender) + ".html") logfile = codecs.open(logfile_filename, "a", encoding="utf-8") logfile.write("</ul><h3>" + trigger.group(2) + "</h3><ul>") logfile.close() log_plain( "Missão atual: {} (trazida por {})".format(trigger.group(2), trigger.nick), trigger.sender, ) bot.say(formatting.bold("Missão atual:") + " " + trigger.group(2))
def meetingsubject(bot, trigger): """ Change the meeting subject.\ See [meetbot module usage]({% link _usage/meetbot-module.md %}) """ if not is_meeting_running(trigger.sender): bot.say("There is no active meeting") return if not trigger.group(2): bot.say("What is the subject?") return if not is_chair(trigger.nick, trigger.sender): bot.say("Only meeting head or chairs can do that") return meetings_dict[trigger.sender]["current_subject"] = trigger.group(2) logfile_filename = os.path.join( meeting_log_path + trigger.sender, figure_logfile_name(trigger.sender) + ".html" ) logfile = codecs.open(logfile_filename, "a", encoding="utf-8") logfile.write("</ul><h3>" + trigger.group(2) + "</h3><ul>") logfile.close() log_plain( "Current subject: {} (set by {})".format(trigger.group(2), trigger.nick), trigger.sender, ) bot.say(formatting.bold("Current subject:") + " " + trigger.group(2))
def chairs(bot, trigger): """ Set the meeting chairs.\ See [meetbot module usage]({% link _usage/meetbot-module.md %}) """ if not is_meeting_running(trigger.sender): bot.say("There is no active meeting") return if not trigger.group(2): bot.say( "Who are the chairs? Try `{}chairs Alice Bob Cindy`".format( bot.config.core.help_prefix ) ) return if trigger.nick.lower() == meetings_dict[trigger.sender]["head"]: meetings_dict[trigger.sender]["chairs"] = trigger.group(2).lower().split(" ") chairs_readable = trigger.group(2).lower().replace(" ", ", ") log_plain("Meeting chairs are: " + chairs_readable, trigger.sender) log_html_listitem( "<span style='font-weight: bold'>Meeting chairs are:</span> %s" % chairs_readable, trigger.sender, ) bot.say(formatting.bold("Meeting chairs are:") + " " + chairs_readable) else: bot.say("Only meeting head can set chairs")
def endmeeting(bot, trigger): """ End a meeting.\ See [meetbot module usage]({% link _usage/meetbot-module.md %}) """ if not is_meeting_running(trigger.sender): bot.say("There is no active meeting") return if not is_chair(trigger.nick, trigger.sender): bot.say("Only meeting head or chairs can do that") return meeting_length = time.time() - meetings_dict[trigger.sender]["start"] bot.say( formatting.bold("Meeting ended!") + " Total meeting length %d minutes" % (meeting_length // 60) ) log_html_end(trigger.sender) htmllog_url = meeting_log_baseurl + tools.web.quote( trigger.sender + "/" + figure_logfile_name(trigger.sender) + ".html" ) log_plain( "Meeting ended by %s. Total meeting length: %d minutes" % (trigger.nick, meeting_length // 60), trigger.sender, ) bot.say("Meeting minutes: " + htmllog_url) meetings_dict[trigger.sender] = collections.defaultdict(dict) del meeting_actions[trigger.sender]
def fmt_response(bot, trigger, URL, from_regex=False): data = get_data(bot, trigger, URL) if not data: return response = [bold('[Github]'), ' ', str(data['full_name'])] if data['description'] != None: response.append(' - ' + str(data['description'])) if not data['language'].strip() == '': response.extend([' | ', data['language'].strip()]) response.extend([ ' | Last Push: ', str(data['pushed_at']), ' | Stargazers: ', str(data['stargazers_count']), ' | Watchers: ', str(data['subscribers_count']), ' | Forks: ', str(data['forks_count']), ' | Network: ', str(data['network_count']), ' | Open Issues: ', str(data['open_issues']) ]) if not from_regex: response.extend([' | ', data['html_url']]) bot.say(''.join(response))
def generateAcro(self, bot, trigger): self.currentAcro = [] self.countAcros = 1 self.submittedAcros = {} self.voteCount = 0 self.letters = [] if random.randint(1, 100) <= bot.db.get_plugin_value( 'acro', 'custom_chance', 10): customAcros = bot.db.get_plugin_value('acro', 'custom_acros', ['ACRO', 'GAME']) customAcro = random.choice(customAcros).lower() for letter in customAcro: self.currentAcro.append(letter) else: letterPool = bot.db.get_plugin_value('acro', 'letters') for char in letterPool: self.letters.append(char) if (random.randint(0, 5)) == 0: max_length = 6 else: max_length = 4 for _ in range(random.randint(3, max_length)): randomLetter = random.choice(self.letters) self.letters.remove(randomLetter) self.currentAcro.append(randomLetter) self.currentAcroString = bold( color(''.join(self.currentAcro).upper(), colors.ORANGE)) return bot.say(f"Acro for this round: {self.currentAcroString}")
def puxam(bot, trigger): """ Set the meeting puxam.\ See [bloucobot module usage]({% link _usage/bloucobot-module.md %}) """ if not is_meeting_running(trigger.sender): bot.say("Não tem Blouco aqui") return if not trigger.group(2): bot.say("Quem vai puxar? Tente `{}puxam Fulana Beltrana_18 C1cl4n4`". format(bot.config.core.help_prefix)) return if trigger.nick.lower() == meetings_dict[trigger.sender]["head"]: meetings_dict[trigger.sender]["puxam"] = trigger.group( 2).lower().split(" ") puxam_readable = trigger.group(2).lower().replace(" ", ", ") log_plain("Puxadoras: " + puxam_readable, trigger.sender) log_html_listitem( "<span style='font-weight: bold'>Puxadoras:</span> %s" % puxam_readable, trigger.sender, ) bot.say(formatting.bold("Puxadoras:") + " " + puxam_readable) else: bot.say("Somente a Porta-estandarte pode consagrar Puxadoras")
def listactions(bot, trigger): """List all the actions in the meeting summary.""" if not is_meeting_running(trigger.sender): bot.say("There is no active meeting") return for action in meeting_actions[trigger.sender]: bot.say(formatting.bold("ACTION:") + " " + action)
def meetinglink(bot, trigger): """ Log a link in the meeing log.\ See [bloucobot module usage]({% link _usage/bloucobot-module.md %}) """ if not is_meeting_running(trigger.sender): bot.say("Não tem Blouco aqui") return if not trigger.group(2): bot.say("Tente `{}link https://algum-website.exemplo/`".format( bot.config.core.help_prefix)) return if not is_chair(trigger.nick, trigger.sender): bot.say("Somente a Porta-estandarte e as Puxadoras podem fazer isso") return link = trigger.group(2) if not link.startswith("http"): link = "http://" + link try: title = find_title(link) except Exception: # TODO: Be specific title = "" log_plain("LINK: %s [%s]" % (link, title), trigger.sender) log_html_listitem('<a href="%s">%s</a>' % (link, title), trigger.sender) bot.say(formatting.bold("LINK:") + " " + link)
def issue_info(bot, trigger, match=None): if not bot.config.github.url_parsing: return match = match or trigger URL = 'https://api.github.com/repos/%s/issues/%s' % (match.group(1), match.group(2)) if (match.group(3)): URL = 'https://api.github.com/repos/%s/issues/comments/%s' % ( match.group(1), match.group(3)) try: raw = fetch_api_endpoint(bot, URL) except HTTPError: bot.say('[Github] API returned an error.') return NOLIMIT data = json.loads(raw) try: if len(data['body'].split('\n')) > 1 and len( data['body'].split('\n')[0]) > 180: body = data['body'].split('\n')[0] + '...' elif len(data['body'].split('\n')) > 2 and len( data['body'].split('\n')[0]) < 180: body = ' '.join(data['body'].split('\n')[:2]) + '...' else: body = data['body'].split('\n')[0] except (KeyError): bot.say( '[Github] API says this is an invalid issue. Please report this if you know it\'s a correct link!' ) return NOLIMIT if body.strip() == '': body = 'No description provided.' response = [ bold('[Github]'), ' [', match.group(1), ' #', match.group(2), '] ', data['user']['login'], ': ' ] if ('title' in data): response.append(data['title']) response.append(bold(' | ')) response.append(body) bot.say(''.join(response))
def next4_mcu(bot, trigger): """Info on the next MCU release.""" url = "https://whenisthenextmcufilm.com/api" try: # 1st Request r1 = requests.get(url) # 1st Next Item days_until_1 = str(r1.json()["days_until"]) media_title_1 = r1.json()["title"] media_type_1 = r1.json()["type"] # 2nd Next Item days_until_2 = str(r1.json()["following_production"]["days_until"]) media_title_2 = r1.json()["following_production"]["title"] media_type_2 = r1.json()["following_production"]["type"] release_date_2 = r1.json()["following_production"]["release_date"] # 2nd Request date_for_r2 = {"date": release_date_2} r2 = requests.get(url, params=date_for_r2) # 3rd Next Item days_until_3 = str(r2.json()["days_until"]) media_title_3 = r2.json()["title"] media_type_3 = r2.json()["type"] # 4th Next Item days_until_4 = str(r2.json()["following_production"]["days_until"]) media_title_4 = r2.json()["following_production"]["title"] media_type_4 = r2.json()["following_production"]["type"] bot.say("Here are the next 4 upcoming MCU items:") bot.say( "Immediately up next is the {} '{}'. It will be out in {} days.". format(media_type_1, formatting.italic(media_title_1), formatting.bold(days_until_1))) bot.say("After that will be the {} '{}'. It will be out in {} days.". format(media_type_2, formatting.italic(media_title_2), formatting.bold(days_until_2))) bot.say("After that will be the {} '{}'. It will be out in {} days.". format(media_type_3, formatting.italic(media_title_3), formatting.bold(days_until_3))) bot.say( "Finally, after that is the {} '{}'. It will be out in {} days.". format(media_type_4, formatting.italic(media_title_4), formatting.bold(days_until_4))) except BaseException: bot.reply("Error reaching API, probably.")
def nodeinfo(bot, trigger): search_queries = [n for n in trigger.args[1].split(' ')[1:] if len(n) > 0] if len(search_queries) is 0: bot.msg(trigger.sender, "Usage: .nodeinfo [nodename]") for node in search_queries[:2]: possible_nodes = find_node(bot, node) if possible_nodes is None: bot.msg(trigger.sender, "No Data yet") break elif len(possible_nodes) is 0: bot.msg(trigger.sender, "No node with Name {}".format(node)) elif len(possible_nodes) is 1: node = possible_nodes[0] online = node['flags']['online'] time = datetime.strptime(node['lastseen'], '%Y-%m-%dT%H:%M:%S%z') nodename = bold(color(node['hostname'], colors.RED)) if online: nodename = bold(color(node['hostname'], colors.GREEN)) timezone = time.tzinfo time = datetime.now() - timedelta(seconds=node['statistics']['uptime']) time = time.replace(tzinfo=timezone) addr = node['network'].get('addresses', None) if not addr: addr = 'N/A' else: addr = "http://[{}]".format(sorted(addr)[0]) bot.msg(trigger.sender, "{}: {} - {} - {}({})".format(nodename, format_time(time), node['model'], node['software']['firmware']['release'], node['software']['firmware']['base'])) if online: bot.msg(trigger.sender, "Load: {} - Memory: {} - Filesystem: {} - {}".format( color_percentage(int(round(node['statistics'].get('loadavg', 0) * 100))), color_percentage(round(node['statistics'].get('memory_usage', 0) * 100, 2)), color_percentage(round(node['statistics'].get('rootfs_usage', 0) * 100, 2)), addr)) elif len(possible_nodes) > 1: max_full_hostnames = 3 msg_string = ", ".join(map(lambda x: x['hostname'], possible_nodes[:max_full_hostnames])) if(len(possible_nodes) > max_full_hostnames): msg_string = msg_string + " and {} more".format(len(possible_nodes)-max_full_hostnames) bot.msg(trigger.sender, "More than one node containing '{}': {}".format(node, msg_string))
def show_status(bot, trigger): api_user = bot.db.get_nick_value(trigger.nick, 'habitica_api_user') api_key = bot.db.get_nick_value(trigger.nick, 'habitica_api_key') if api_user is None: bot.reply("I do not know you, sorry. Please use '.hero add'.") return else: if api_key is None: user = requests.get(bot.config.habitica.api_url + "members/" + api_user, headers=Common.auth) else: headers = {"x-api-key": api_key, "x-api-user": api_user} user = requests.get(bot.config.habitica.api_url + "user", headers=headers) if user.status_code != 200: bot.say("No connection to Habitica. Please try again later.") return hp = str(round(user.json()["stats"]["hp"], 2)) mp = str(int(user.json()["stats"]["mp"])) gp = str(round(user.json()["stats"]["gp"], 2)) xp = str(int(user.json()["stats"]["exp"])) name = user.json()["profile"]["name"] name_colors = get_name_colors(user.json()) if api_key is not None: max_hp = user.json()["stats"]["maxHealth"] max_mp = user.json()["stats"]["maxMP"] to_next_level = user.json()["stats"]["toNextLevel"] hp = hp + "/" + str(max_hp) mp = mp + "/" + str(max_mp) xp = xp + "/" + str(to_next_level) seperator = " | " bot.say("Status for " + color(Common.name_prefix + name + Common.name_suffix, name_colors[0], name_colors[1]) + " " + color(bold(u"♥ ") + hp + " HP", Common.hp_color) + seperator + color(bold(u"⚡ ") + mp + " MP", Common.mp_color) + seperator + color(bold(u"⭐ ") + xp + " XP", Common.xp_color) + seperator + color(bold(u"⛁ ") + gp + " Gold", Common.gp_color) )
def issue_info(bot, trigger, match=None): match = match or trigger URL = 'https://api.github.com/repos/%s/issues/%s' % (match.group(1), match.group(2)) if (match.group(3)): URL = 'https://api.github.com/repos/%s/issues/comments/%s' % (match.group(1), match.group(3)) try: raw = fetch_api_endpoint(bot, URL) except HTTPError: bot.say('[Github] API returned an error.') return NOLIMIT data = json.loads(raw) try: if len(data['body'].split('\n')) > 1 and len(data['body'].split('\n')[0]) > 180: body = data['body'].split('\n')[0] + '...' elif len(data['body'].split('\n')) > 2 and len(data['body'].split('\n')[0]) < 180: body = ' '.join(data['body'].split('\n')[:2]) + '...' else: body = data['body'].split('\n')[0] except (KeyError): bot.say('[Github] API says this is an invalid issue. Please report this if you know it\'s a correct link!') return NOLIMIT if body.strip() == '': body = 'No description provided.' response = [ bold('[Github]'), ' [', match.group(1), ' #', match.group(2), '] ', data['user']['login'], ': ' ] if ('title' in data): response.append(data['title']) response.append(bold(' | ')) response.append(body) bot.say(''.join(response))
def cmd_epic(bot, trigger, rescue): """ Toggle a case epic/not epic required parameters: client name. """ rescue.epic = not rescue.epic bot.say( "{rescue.client_name}'s case is now {epic}" .format(rescue=rescue, epic=bold('epic') if rescue.epic else 'not as epic') ) save_case_later(bot, rescue)
def cmd_active(bot, trigger, rescue): """ Toggle a case active/inactive required parameters: client name. """ rescue.active = not rescue.active bot.say( "{rescue.client_name}'s case is now {active}" .format(rescue=rescue, active=bold('active') if rescue.active else 'inactive') ) save_case_later(bot, rescue)
def new_node(bot, node, info): addr = info['network'].get('addresses', None) if not addr: addr = 'N/A' else: addr = addr[-1] try: version = info['software']['firmware']['release'] except KeyError: version = 'N/A' bot.msg('#ffda-log', '{} is {}. - {} - http://[{}]'.format(info['hostname'], bold(color('new', colors.BLUE)), version, addr))
def get_post(self): for submission in r.get_subreddit(self.subreddit).get_hot(limit=25): if str(submission.over_18) == 'True': nsfwtag = str("[" + bold(color('NSFW', colors.RED))+ "] ") else: nsfwtag = '' fullthingred = (str(nsfwtag) + str('[' + str(submission.score) + '] ' + (submission.title)) + " - " + str(submission.url + " (" + self.subreddit + ")")) self.posts.append('%s /// %s' % (fullthingred, submission.permalink)) self.chosen_post = random.choice(self.posts) self.chosen_post = self.chosen_post.split('///') self.post_title = (self.chosen_post[0]) self.post_comments = (self.chosen_post[1])
def lookup_name(query): page = requests.get('http://www.sheknows.com/baby-names/name/{}'.format(query)) tree = html.fromstring(page.text) result = tree.xpath('//title')[0].text if result == 'Errors': return ret_list = [] meanings = tree.xpath("//p[@class='origin_descrip']") for m in meanings: mraw = m.text_content() ret_list.append(bold(' '.join(mraw.split(':')[0].split()) + ': ') + ' '.join(mraw.split(':')[2].split())) return query + ': ' + ' '.join(ret_list)
def key_info(bot, trigger): if not trigger.is_privmsg: bot.reply("Opening query for configuration.") bot.msg(trigger.nick, "Please note that the API Token can be used as a " + color("password", "red") + " and you should never give it to anyone you don't trust!") bot.msg(trigger.nick, "Be aware that BAD THINGS can happen, and your API Token might be made public.") bot.msg(trigger.nick, "IN NO EVENT SHALL THE OPERATORS OF THIS BOT BE LIABLE FOR ANY CLAIM, DAMAGES OR " + "OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN" + "CONNECTION WITH THE BOT OR THE USE OR OTHER DEALINGS IN THE BOT.") bot.msg(trigger.nick, "" + color(bold("YOU HAVE BEEN WARNED!"), "red")) bot.msg(trigger.nick, "If you ARE SURE want this bot to save your API Token, add it with " + "'.hero key IHAVEBEENWARNED <API Token>'")
def commit_info(bot, trigger, match=None): match = match or trigger URL = 'https://api.github.com/repos/%s/commits/%s' % (match.group(1), match.group(2)) try: raw = fetch_api_endpoint(bot, URL) except HTTPError: bot.say('[Github] API returned an error.') return NOLIMIT data = json.loads(raw) try: if len(data['commit']['message'].split('\n')) > 1: body = data['commit']['message'].split('\n')[0] + '...' else: body = data['commit']['message'].split('\n')[0] except (KeyError): bot.say('[Github] API says this is an invalid commit. Please report this if you know it\'s a correct link!') return NOLIMIT if body.strip() == '': body = 'No commit message provided.' response = [ bold('[Github]'), ' [', match.group(1), '] ', data['author']['login'], ': ', body, bold(' | '), str(data['stats']['total']), ' changes in ', str(len(data['files'])), ' files' ] bot.say(''.join(response))
def key_configure(argument, bot, trigger): if trigger.is_privmsg: user_keys = Common.uuid_regex.findall(argument) if len(user_keys) > 0: user_key = user_keys[0] else: bot.reply(trigger.nick, "Invalid API Token") return bot.db.set_nick_value(trigger.nick, 'habitica_api_key', user_key) bot.msg(trigger.nick, "Saved your API Token.") else: bot.reply("You just posted your Habitica password in a public channel. " + color(bold("Go change it RIGHT NOW!"), "red"))
def startmeeting(bot, trigger): """ Start a meeting.\ See [meetbot module usage]({% link _usage/meetbot-module.md %}) """ if ismeetingrunning(trigger.sender): bot.say('Can\'t do that, there is already a meeting in progress here!') return if trigger.is_privmsg: bot.say('Can only start meetings in channels') return # Start the meeting meetings_dict[trigger.sender]['start'] = time.time() if not trigger.group(2): meetings_dict[trigger.sender]['title'] = 'Untitled meeting' else: meetings_dict[trigger.sender]['title'] = trigger.group(2) meetings_dict[trigger.sender]['head'] = trigger.nick.lower() meetings_dict[trigger.sender]['running'] = True meetings_dict[trigger.sender]['comments'] = [] global meeting_log_path meeting_log_path = bot.config.meetbot.meeting_log_path if not meeting_log_path.endswith('/'): meeting_log_path = meeting_log_path + '/' global meeting_log_baseurl meeting_log_baseurl = bot.config.meetbot.meeting_log_baseurl if not meeting_log_baseurl.endswith('/'): meeting_log_baseurl = meeting_log_baseurl + '/' if not os.path.isdir(meeting_log_path + trigger.sender): try: os.makedirs(meeting_log_path + trigger.sender) except Exception: # TODO: Be specific bot.say("Can't create log directory for this channel, meeting not started!") meetings_dict[trigger.sender] = Ddict(dict) raise return # Okay, meeting started! logplain('Meeting started by ' + trigger.nick.lower(), trigger.sender) logHTML_start(trigger.sender) meeting_actions[trigger.sender] = [] bot.say(bold('Meeting started!') + ' use .action, .agreed, .info, ' '.chairs, .subject and .comments to control the meeting. to end ' 'the meeting, type .endmeeting') bot.say('Users without speaking permission can use .comment ' + trigger.sender + ' followed by their comment in a PM with me to ' 'vocalize themselves.')
def meetingagreed(bot, trigger): """ Log an agreement in the meeting log.\ See [meetbot module usage]({% link _usage/meetbot-module.md %}) """ if not ismeetingrunning(trigger.sender): bot.say('Can\'t do that, start meeting first') return if not trigger.group(2): bot.say('try .action someone will do something') return if not ischair(trigger.nick, trigger.sender): bot.say('Only meeting head or chairs can do that') return logplain('AGREED: ' + trigger.group(2), trigger.sender) logHTML_listitem('<span style="font-weight: bold">Agreed: </span>' + trigger.group(2), trigger.sender) bot.say(bold('AGREED:') + ' ' + trigger.group(2))
def meetinginfo(bot, trigger): """ Log an informational item in the meeting log.\ See [meetbot module usage]({% link _usage/meetbot-module.md %}) """ if not ismeetingrunning(trigger.sender): bot.say('Can\'t do that, start meeting first') return if not trigger.group(2): bot.say('try .info some informative thing') return if not ischair(trigger.nick, trigger.sender): bot.say('Only meeting head or chairs can do that') return logplain('INFO: ' + trigger.group(2), trigger.sender) logHTML_listitem(trigger.group(2), trigger.sender) bot.say(bold('INFO:') + ' ' + trigger.group(2))
def chairs(bot, trigger): """ Set the meeting chairs.\ See [meetbot module usage]({% link _usage/meetbot-module.md %}) """ if not ismeetingrunning(trigger.sender): bot.say('Can\'t do that, start meeting first') return if not trigger.group(2): bot.say('Who are the chairs?') return if trigger.nick.lower() == meetings_dict[trigger.sender]['head']: meetings_dict[trigger.sender]['chairs'] = trigger.group(2).lower().split(' ') chairs_readable = trigger.group(2).lower().replace(' ', ', ') logplain('Meeting chairs are: ' + chairs_readable, trigger.sender) logHTML_listitem('<span style="font-weight: bold">Meeting chairs are: </span>' + chairs_readable, trigger.sender) bot.say(bold('Meeting chairs are:') + ' ' + chairs_readable) else: bot.say("Only meeting head can set chairs")
def meetingsubject(bot, trigger): """ Change the meeting subject.\ See [meetbot module usage]({% link _usage/meetbot-module.md %}) """ if not ismeetingrunning(trigger.sender): bot.say('Can\'t do that, start meeting first') return if not trigger.group(2): bot.say('what is the subject?') return if not ischair(trigger.nick, trigger.sender): bot.say('Only meeting head or chairs can do that') return meetings_dict[trigger.sender]['current_subject'] = trigger.group(2) logfile = codecs.open(meeting_log_path + trigger.sender + '/' + figure_logfile_name(trigger.sender) + '.html', 'a', encoding='utf-8') logfile.write('</ul><h3>' + trigger.group(2) + '</h3><ul>') logfile.close() logplain('Current subject: ' + trigger.group(2) + ', (set by ' + trigger.nick + ')', trigger.sender) bot.say(bold('Current subject:') + ' ' + trigger.group(2))
def endmeeting(bot, trigger): """ End a meeting.\ See [meetbot module usage]({% link _usage/meetbot-module.md %}) """ if not ismeetingrunning(trigger.sender): bot.say('Can\'t do that, start meeting first') return if not ischair(trigger.nick, trigger.sender): bot.say('Only meeting head or chairs can do that') return meeting_length = time.time() - meetings_dict[trigger.sender]['start'] # TODO: Humanize time output bot.say(bold("Meeting ended!") + " total meeting length %d seconds" % meeting_length) logHTML_end(trigger.sender) htmllog_url = meeting_log_baseurl + quote(trigger.sender + '/' + figure_logfile_name(trigger.sender) + '.html') logplain('Meeting ended by %s, total meeting length %d seconds' % (trigger.nick, meeting_length), trigger.sender) bot.say('Meeting minutes: ' + htmllog_url) meetings_dict[trigger.sender] = Ddict(dict) del meeting_actions[trigger.sender]
def findTickers(ticker, maxresult=5): res = getTicker(ticker, gimme=True) if res[0] is None: out = 'Found no tickers' output(out) return out = 'Found {0} tickers. Max result is {1}.'.format(len(res), maxresult) output(out) count = 0 for r in res: if count == maxresult: break out = r[1] if formatting: out = formatting.bold(out) out += ' ({0})'.format(r[0]) out += ' of type {0}'.format(r[2]) output(out) count += 1
def _say_result(bot, id_, include_link): result = API.videos().list( id=id_, part='snippet,contentDetails,statistics', ).execute().get('items') if not result: return result = result[0] message = ( '[YouTube] {title} | Uploader: {uploader} | Duration: {duration} | ' 'Views: {views} | {likes} | {dislikes}' ) snippet = result['snippet'] details = result['contentDetails'] splitdur = ISO8601_PERIOD_REGEX.match(details['duration']) dur = [] for k, v in splitdur.groupdict().items(): if v is not None: dur.append(v.lower()) duration = ' '.join(dur) for k in result['statistics']: result['statistics'][k] = '{:,}'.format(int(result['statistics'][k])) message = message.format( title=bold(snippet['title']), uploader=snippet['channelTitle'], duration=duration, views=result['statistics']['viewCount'], likes=color(result['statistics']['likeCount'], colors.GREEN), dislikes=color(result['statistics']['dislikeCount'], colors.RED), ) if include_link: message += ' | ' + color('https://youtu.be/{0}' .format(id_), colors.BLUE) bot.say(message)
def help(bot, trigger): """Shows a command's documentation, and possibly an example.""" if trigger.group(2): name = trigger.group(2) name = name.lower() # number of lines of help to show threshold = 3 if name in bot.doc: if len(bot.doc[name][0]) + (1 if bot.doc[name][1] else 0) > threshold: if trigger.nick != trigger.sender: # don't say that if asked in private bot.reply('The documentation for this command is too long; I\'m sending it to you in a private message.') msgfun = lambda l: bot.msg(trigger.nick, l) else: msgfun = bot.reply for line in bot.doc[name][0]: msgfun(line) if bot.doc[name][1]: msgfun('e.g. ' + bot.doc[name][1]) else: if not trigger.is_privmsg: bot.reply("I'm sending you a list of my commands in a private message!") bot.say( 'You can see more info about any of these commands by doing .help ' '<command> (e.g. .help time)', trigger.nick ) name_length = max(6, max(len(k) for k in bot.command_groups.keys())) for category, cmds in bot.command_groups.items(): category = category.upper().ljust(name_length) cmds = ' '.join(cmds) msg = bold(category) + ' ' + cmds indent = ' ' * (name_length + 2) msg = textwrap.wrap(msg, subsequent_indent=indent) for line in msg: bot.say(line, trigger.nick)
def cmd_quote(bot, trigger, rescue): """ Recites all known information for the specified rescue Required parameters: client name or case number. """ tags = ['unknown platform' if not rescue.platform or rescue.platform == 'unknown' else rescue.platform.upper()] if rescue.epic: tags.append("epic") if rescue.codeRed: tags.append(bold(color('CR', colors.RED))) fmt = ( "{client}'s case #{index} at {system} ({tags}) opened {opened} ({opened_ago})," " updated {updated} ({updated_ago})" ) + (" @{id}" if bot.config.ratbot.apiurl else "") bot.say(fmt.format( client=rescue.client_names, index=rescue.boardindex, tags=", ".join(tags), opened=format_timestamp(rescue.createdAt) if rescue.createdAt else '<unknown>', updated=format_timestamp(rescue.lastModified) if rescue.lastModified else '<unknown>', opened_ago=friendly_timedelta(rescue.createdAt) if rescue.createdAt else '???', updated_ago=friendly_timedelta(rescue.lastModified) if rescue.lastModified else '???', id=rescue.id or 'pending', system=rescue.system or 'an unknown system' )) # FIXME: Rats/temprats/etc isn't really handled yet. if rescue.rats: ratnames = [] for rat in rescue.rats: name = getRatName(bot, rat) ratnames.append(name) bot.say("Assigned rats: " + ", ".join(ratnames)) if rescue.unidentifiedRats: bot.say("Assigned unidentifiedRats: " + ", ".join(rescue.unidentifiedRats)) for ix, quote in enumerate(rescue.quotes): bot.say('[{ix}]{quote}'.format(ix=ix, quote=quote))