def load_aliased_images(bot, event, *args): file_exception = False try: imageids_filename = 'imageids.json' imageids = json.loads(open(imageids_filename, encoding='utf-8').read(), encoding='utf-8') except IOError as e: if e.errno == errno.ENOENT: imageids = {} else: print('Exception:') print(str(e)) file_exception = True # loop through values in image_aliases.json aliases = load_json('image_aliases.json') for v in aliases.values(): print('V = ' + str(v)) for url in v if not isinstance(v, str) else [v]: print('URL = ' + url) # if url is not in imageids, upload it and store filename,id image_id = imageids.get(url) if image_id is None: print('URL = ' + url) filename = UtilBot.download_image(url, 'images') image_id = yield from UtilBot.upload_image(bot, filename) if not file_exception: imageids[url] = image_id with open(imageids_filename, 'w') as f: json.dump(imageids, f, indent=2, sort_keys=True) os.remove(filename)
def _karma(bot, event, *args): username = '******'.join(args) username = username.replace('@', '') add = username.count("+") sub = username.count("-") if add > 6: add = 6 if sub > 6: sub = 6 username = username.replace("+", "") username = username.replace("-", "") username = username.lower() for u in sorted(event.conv.users, key=lambda x: x.full_name.split()[-1]): if username not in u.full_name.lower(): continue if u.id_ == event.user.id_: bot.send_message(event.conv, "Your Karma changes with actions upon others, not actions upon oneself.") return new_karma = None if add >= 2 and sub == 0: new_karma = UtilBot.change_karma(u.id_[0], add - 1) elif sub >= 2 and add == 0: new_karma = UtilBot.change_karma(u.id_[0], (sub - 1) * -1) if new_karma is not None: bot.send_message(event.conv, "{}'s karma is now {}".format(u.full_name, new_karma)) return yield from bot._client.settyping(event.conv_id, schemas.TypingStatus.STOPPED)
def finish(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *Finish* Usage: /finish <lyrics to finish> <optional: * symbol to show guessed song> Purpose: Finish a lyric! """) yield from bot.send_message_segments(event.conv, segments) else: showguess = False if args[-1] == '*': showguess = True args = args[0:-1] lyric = ' '.join(args) songs = Genius.search_songs(lyric) if len(songs) < 1: yield from bot.send_message(event.conv, "I couldn't find your lyrics.") if songs[0].artist.name == 'James Joyce': yield from bot.send_message(event.conv, "Sorry, that author is banned.") return lyrics = songs[0].raw_lyrics anchors = {} lyrics = lyrics.split('\n') currmin = (0, UtilBot.levenshtein_distance(lyrics[0], lyric)[0]) for x in range(1, len(lyrics) - 1): try: currlyric = lyrics[x] if not currlyric.isspace(): # Returns the distance and whether or not the lyric had to be chopped to compare result = UtilBot.levenshtein_distance(currlyric, lyric) else: continue distance = abs(result[0]) lyrics[x] = lyrics[x], result[1] if currmin[1] > distance: currmin = (x, distance) if currlyric.startswith('[') and currlyric not in anchors: next = UtilBot.find_next_non_blank(lyrics, x) anchors[currlyric] = lyrics[next] except Exception: pass next = UtilBot.find_next_non_blank(lyrics, currmin[0]) chopped = lyrics[currmin[0]][1] found_lyric = lyrics[currmin[0]][0] + " " + lyrics[next][0] if chopped else lyrics[next][0] if found_lyric.startswith('['): found_lyric = anchors[found_lyric] if showguess: segments = [hangups.ChatMessageSegment(found_lyric), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK), hangups.ChatMessageSegment(songs[0].name)] yield from bot.send_message_segments(event.conv, segments) else: yield from bot.send_message(event.conv, found_lyric) return
def finish(bot, event, *args): if ''.join(args) == '?': segments = [hangups.ChatMessageSegment('Finish', is_bold=True), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK), hangups.ChatMessageSegment( 'Usage: /finish <lyrics to finish> <optional: * symbol to show guessed song>'), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK), hangups.ChatMessageSegment('Purpose: Finish a lyric!')] bot.send_message_segments(event.conv, segments) else: showguess = False if args[-1] == '*': showguess = True args = args[0:-1] lyric = ' '.join(args) songs = Genius.search_songs(lyric) if len(songs) < 1: bot.send_message(event.conv, "I couldn't find your lyrics.") lyrics = songs[0].raw_lyrics anchors = {} lyrics = lyrics.split('\n') currmin = (0, UtilBot.levenshtein_distance(lyrics[0], lyric)[0]) for x in range(1, len(lyrics) - 1): try: currlyric = lyrics[x] if not currlyric.isspace(): # Returns the distance and whether or not the lyric had to be chopped to compare result = UtilBot.levenshtein_distance(currlyric, lyric) else: continue distance = abs(result[0]) lyrics[x] = lyrics[x], result[1] if currmin[1] > distance: currmin = (x, distance) if currlyric.startswith('[') and currlyric not in anchors: next = UtilBot.find_next_non_blank(lyrics, x) anchors[currlyric] = lyrics[next] except Exception: pass next = UtilBot.find_next_non_blank(lyrics, currmin[0]) chopped = lyrics[currmin[0]][1] found_lyric = lyrics[currmin[0]][0] + " " + lyrics[next][0] if chopped else lyrics[next][0] if found_lyric.startswith('['): found_lyric = anchors[found_lyric] if showguess: segments = [hangups.ChatMessageSegment(found_lyric), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK), hangups.ChatMessageSegment(songs[0].name)] bot.send_message_segments(event.conv, segments) else: bot.send_message(event.conv, found_lyric) return
def karma(bot, event, name=None, *args): if name: if name[0] == '@': name = name[1:] lower_name = name.lower() for u in sorted(event.conv.users, key=lambda x: x.full_name.split()[-1]): if lower_name not in u.full_name.lower(): continue segments = [hangups.ChatMessageSegment('%s:' % u.full_name, is_bold=True), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK), hangups.ChatMessageSegment('Karma: ' + str(UtilBot.get_current_karma(u.id_[0])))] bot.send_message_segments(event.conv, segments) return bot.send_message(event.conv, 'No user found matching "%s".' % name) else: karma_list = [] list_num = min(5, int(len(event.conv.users) / 2) + 1) for u in event.conv.users: karma_list.append((u.full_name, UtilBot.get_current_karma(u.id_[0]))) karma_list.sort(key=lambda x: -x[1]) segments = [hangups.ChatMessageSegment("Karma Stats:", is_bold=True), hangups.ChatMessageSegment("\n", segment_type=hangups.SegmentType.LINE_BREAK), hangups.ChatMessageSegment("Top:", is_italic=True), hangups.ChatMessageSegment("\n", segment_type=hangups.SegmentType.LINE_BREAK)] if len(event.conv.users) > 10: for i in range(0, min(list_num, len(event.conv.users))): segments.append(hangups.ChatMessageSegment("{}: {}".format(karma_list[i][0], karma_list[i][1]))) segments.append(hangups.ChatMessageSegment("\n", segment_type=hangups.SegmentType.LINE_BREAK)) segments.append(hangups.ChatMessageSegment("\n", segment_type=hangups.SegmentType.LINE_BREAK)) segments.append(hangups.ChatMessageSegment("Bottom:", is_italic=True)) segments.append(hangups.ChatMessageSegment("\n", segment_type=hangups.SegmentType.LINE_BREAK)) for i in range(-1, -min(list_num, len(event.conv.users)) - 1, -1): segments.append(hangups.ChatMessageSegment("{}: {}".format(karma_list[i][0], karma_list[i][1]))) segments.append(hangups.ChatMessageSegment("\n", segment_type=hangups.SegmentType.LINE_BREAK)) else: for i in range(0, len(event.conv.users)): segments.append(hangups.ChatMessageSegment("{}: {}".format(karma_list[i][0], karma_list[i][1]))) segments.append(hangups.ChatMessageSegment("\n", segment_type=hangups.SegmentType.LINE_BREAK)) segments.append(hangups.ChatMessageSegment("\n", segment_type=hangups.SegmentType.LINE_BREAK)) segments.append(hangups.ChatMessageSegment("Average Karma:", is_italic=True)) segments.append(hangups.ChatMessageSegment("\n", segment_type=hangups.SegmentType.LINE_BREAK)) segments.append(hangups.ChatMessageSegment('{}'.format((sum([i[1] for i in karma_list]) / len(karma_list))))) bot.send_message_segments(event.conv, segments)
def rate(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *Rate smileys* Usage: /rate <key> Purpose: Send a rating smiley, key can be: agree, disagree, funny, winner, zing, informative, friendly, useful, optimistic, artistic, late, dumb or box. """) yield from bot.send_message_segments(event.conv, segments) else: ratings = dict(agree="\u2714", disagree="\u274c", funny="\U0001f604", winner="\U0001f31f", zing="\u26a1", informative="\u2139", friendly="\u2764", useful="\U0001f527", optimistic="\U0001f308", artistic="\U0001f3a8", late="\u23f0", dumb="\U0001f4e6", box="\U0001f4e6") try: yield from bot.send_message(event.conv, ratings[args[0].lower()]) except KeyError: yield from bot.send_message( event.conv, "That's not a valid rating. You are \U0001f4e6 x 1")
def flip(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *Flip* Usage: /flip <optional: number of times to flip> Purpose: Flips a coin. """) bot.send_message_segments(event.conv, segments) else: times = 1 if len(args) > 0 and args[-1].isdigit(): times = int(args[-1]) if int(args[-1]) < 1000000 else 1000000 heads, tails = 0, 0 for x in range(0, times): n = random.randint(0, 1) if n == 1: heads += 1 else: tails += 1 if times == 1: bot.send_message(event.conv, "Heads!" if heads > tails else "Tails!") else: bot.send_message(event.conv, "Winner: " + ( "Heads!" if heads > tails else "Tails!" if tails > heads else "Tie!") + " Heads: " + str( heads) + " Tails: " + str(tails) + " Ratio: " + (str( Fraction(heads, tails)) if heads > 0 and tails > 0 else str(heads) + '/' + str(tails)))
def imagesearch(bot, event, *args): num_requested = 0 if len(args) == 0: bot.send_message(event.conv, "Error: requires more than 0 arguments.") return else: if args[-1][0] == '@' and UtilBot.is_integer(args[-1][1:]): # we subtract one here because image #1 is the 0 item in the list num_requested = int(args[-1][1:]) - 1 args = args[:-1] if num_requested > 7 or num_requested < 0: bot.send_message(event.conv, "Error: result number must be between 1 and 8.") return query = ' '.join(args) url = 'http://ajax.googleapis.com/ajax/services/search/images?v=1.0&rsz=8&' \ + parse.urlencode({'q': query}) resp = request.urlopen(url) image_json = json.loads(resp.read().decode()) url = image_json['responseData']['results'][num_requested]['unescapedUrl'] yield from send_image(bot, event, url)
def img(bot, event, *args): if len(args) > 0: yield from bot.send_typing(event.conv) url = args[0] file_exception = False try: imageids_filename = os.path.join('images', 'imageids.json') imageids = json.loads(open(imageids_filename, encoding='utf-8').read(), encoding='utf-8') imageID = imageids.get(url) except IOError as e: if e.errno == errno.ENOENT: imageids = {} else: print('Exception:') print(str(e)) file_exception = True imageID = None if imageID is None: filename = UtilBot.download_image(url, 'images') imageID = yield from bot._client.upload_image(filename) if not file_exception: imageids[url] = imageID with open(imageids_filename, 'w') as f: json.dump(imageids, f, indent=2, sort_keys=True) os.remove(filename) bot.send_image(event.conv, imageID)
def navyseals(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ **Navy Seals** Usage: /navyseals Purpose: Shits fury all over you. """) bot.send_message_segments(event.conv, segments) else: bot.send_message(event.conv, '''What the f**k did you just f*****g say about me, you little bitch? \ I'll have you know I graduated top of my class in the Navy Seals, and \ I've been involved in numerous secret raids on Al-Quaeda, and I have over \ 300 confirmed kills. I am trained in gorilla warfare and I'm the top sniper \ in the entire US armed forces. You are nothing to me but just another target. \ I will wipe you the f**k out with precision the likes of which has never \ been seen before on this Earth, mark my f*****g words. You think you can \ get away with saying that shit to me over the Internet? Think again, f****r. \ As we speak I am contacting my secret network of spies across the USA and \ your IP is being traced right now so you better prepare for the storm, \ maggot. The storm that wipes out the pathetic little thing you call your \ life. You're f*****g dead, kid. I can be anywhere, anytime, and I can kill \ you in over seven hundred ways, and that's just with my bare hands. Not only \ am I extensively trained in unarmed combat, but I have access to the entire \ arsenal of the United States Marine Corps and I will use it to its full \ extent to wipe your miserable ass off the face of the continent, you little \ shit. If only you could have known what unholy retribution your little \ "clever" comment was about to bring down upon you, maybe you would have held \ your f*****g tongue. But you couldn't, you didn't, and now you're paying the \ price, you goddamn idiot. I will shit fury all over you and you will drown in \ it. You're f*****g dead, kiddo.''')
def roulette(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ **Roulette** Usage: /roulette Purpose: Spins the chamber and tries to shoot you in the head """) bot.send_message_segments(event.conv, segments) else: #static variables if not hasattr(roulette, "_rouletteChamber"): roulette._rouletteChamber = random.randrange(0, 6) if not hasattr(roulette, "_rouletteBullet"): roulette._rouletteBullet = random.randrange(0, 6) if len(args) > 0 and args[0] == 'spin': roulette._rouletteBullet = random.randrange(0, 6) bot.send_message(event.conv, '*SPIN* Are you feeling lucky?') return if roulette._rouletteChamber == roulette._rouletteBullet: roulette._rouletteBullet = random.randrange(0, 6) roulette._rouletteChamber = random.randrange(0, 6) bot.send_message(event.conv, '*BANG*') else: bot.send_message(event.conv, '*click*') roulette._rouletteChamber += 1 roulette._rouletteChamber %= 6
def config(bot, event, cmd=None, *args): if cmd == 'get' or cmd is None: config_args = list(args) value = bot.config.get_by_path(config_args) if config_args else dict(bot.config) elif cmd == 'set': config_args = list(args[:-1]) if len(args) >= 2: bot.config.set_by_path(config_args, json.loads(args[-1])) bot.config.save() value = bot.config.get_by_path(config_args) else: yield from DispatcherSingleton.unknown_command(bot, event) return else: yield from DispatcherSingleton.unknown_command(bot, event) return if value is None: value = 'Parameter does not exist!' config_path = ' '.join(k for k in ['config'] + config_args) segments = [hangups.ChatMessageSegment('{}:'.format(config_path), is_bold=True), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK)] segments.extend(UtilBot.text_to_segments(json.dumps(value, indent=2, sort_keys=True))) bot.send_message_segments(event.conv, segments)
def send_webpage_screenshot(bot, event, url, viewportsize='1280x1024'): filename = 'screenie.png' cliprectsize = '0x0x' + viewportsize; try: cmd = ['capturejs', '--uri', url, '--viewportsize', viewportsize, '--output', filename, '--cliprect', cliprectsize] output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) output = output.decode(encoding='UTF-8') if output != '': bot.send_message(event.conv, output) image_id = yield from UtilBot.upload_image(bot, filename) send_image(bot, event, image_id) os.remove(filename) except http.client.BadStatusLine as e: display.stop() bot.send_message(event.conv, 'Error: BadStatusLine')
def flip(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *Flip* Usage: /flip <optional: number of times to flip> Purpose: Flips a coin. """) yield from bot.send_message_segments(event.conv, segments) else: times = 1 if len(args) > 0 and args[-1].isdigit(): times = int(args[-1]) if int(args[-1]) < 1000000 else 1000000 heads, tails = 0, 0 for x in range(0, times): n = random.randint(0, 1) if n == 1: heads += 1 else: tails += 1 if times == 1: yield from bot.send_message(event.conv, "Heads!" if heads > tails else "Tails!") else: yield from bot.send_message(event.conv, "Winner: " + ( "Heads!" if heads > tails else "Tails!" if tails > heads else "Tie!") + " Heads: " + str( heads) + " Tails: " + str(tails) + " Ratio: " + (str( Fraction(heads, tails)) if heads > 0 and tails > 0 else str(heads) + '/' + str(tails)))
def rate(bot, event, *args): ratings = dict( agree ="\u2714" ,disagree ="\u274c" ,funny ="\U0001f604" ,winner ="\U0001f31f" ,zing ="\u26a1" ,informative="\u2139" ,friendly ="\u2764" ,useful ="\U0001f527" ,optimistic ="\U0001f308" ,artistic ="\U0001f3a8" ,late ="\u23f0" ,dumb ="\U0001f4e6" ,box ="\U0001f4e6" ) if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ **Rate** Usage: /rate <rating> Purpose: Responds to your rating, ratings are agree, disagree, funny, winner, zing, informative, friendly, optimistic, artistic, late, dumb and box. """) bot.send_message_segments(event.conv, segments) else: try: bot.send_message(event.conv, ratings[args[0]]) except KeyError: bot.send_message(event.conv, "That's not a valid rating. You are \U0001f4e6 x 1")
def block(bot, event, username=None, *args): if not username: segments = [hangups.ChatMessageSegment("Blocked Users: ", is_bold=True), hangups.ChatMessageSegment("\n", segment_type=hangups.SegmentType.LINE_BREAK), hangups.ChatMessageSegment("No users blocked.")] if len(UtilBot.get_blocked_users_in_conversations(event.conv_id)) > 0: segments.pop() for user in event.conv.users: if UtilBot.is_user_blocked(event.conv_id, user.id_): segments.append(hangups.ChatMessageSegment(user.full_name)) segments.append(hangups.ChatMessageSegment("\n", segment_type=hangups.SegmentType.LINE_BREAK)) segments.pop() bot.send_message_segments(event.conv, segments) return username_lower = username.strip().lower() for u in sorted(event.conv.users, key=lambda x: x.full_name.split()[-1]): if not username_lower in u.full_name.lower() or event.user.is_self: continue if u.id_ == event.user.id_: bot.send_message(event.conv, "Aborting block as it would block calling user. ({})".format(u.full_name)) return if UtilBot.is_user_blocked(event.conv_id, u.id_): UtilBot.remove_from_blocklist(event.conv_id, u.id_) bot.send_message(event.conv, "Unblocked User: {}".format(u.full_name)) return UtilBot.add_to_blocklist(event.conv_id, u.id_) bot.send_message(event.conv, "Blocked User: {}".format(u.full_name)) return
def _reminder_on_connect_listener(bot): reminders = UtilBot.get_all_reminders() for reminder in reminders: reminder_time = dateutil.parser.parse(reminder[2]) reminder_interval = (reminder_time - datetime.now()).seconds conv = bot._conv_list.get(reminder[0]) reminder_timer = threading.Timer(reminder_interval, send_reminder, [bot, conv, reminder_interval, reminder[1], asyncio.get_event_loop()]) reminder_timer.start()
def udefine(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *Urbanly Define* Usage: /udefine <word to search for> \ <optional: definition number [defaults to 1st]> Purpose: Define a word. """) yield from bot.send_message_segments(event.conv, segments) else: yield from bot.send_typing(event.conv) api_host = 'http://urbanscraper.herokuapp.com/search/' num_requested = 0 returnall = False if len(args) == 0: yield from bot.send_message(event.conv, "Invalid usage of /udefine.") return else: if args[-1] == '*': args = args[:-1] returnall = True if args[-1].isdigit(): # we subtract one here because def #1 is the 0 item in the list num_requested = int(args[-1]) - 1 args = args[:-1] term = parse.quote('.'.join(args)) response = requests.get(api_host + term) error_response = 'No definition found for \"{}\".'.format( ' '.join(args)) if response.status_code != 200: yield from bot.send_message(event.conv, error_response) result = response.content.decode() result_list = json.loads(result) num_requested = min(num_requested, len(result_list) - 1) num_requested = max(0, num_requested) result = result_list[num_requested].get('definition', error_response) if returnall: segments = [] for string in result_list: segments.append(hangups.ChatMessageSegment(string)) segments.append( hangups.ChatMessageSegment( '\n', hangups.SegmentType.LINE_BREAK)) yield from bot.send_message_segments(event.conv, segments) else: segments = [ hangups.ChatMessageSegment(' '.join(args), is_bold=True), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK), hangups.ChatMessageSegment(result + ' [{0} of {1}]'.format( num_requested + 1, len(result_list))) ] yield from bot.send_message_segments(event.conv, segments)
def xfiles(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ **Xfiles** Usage: /xfiles Purpose: but what if bot is not kill """) bot.send_message_segments(event.conv, segments) else: args = ['xfiles','theme'] youtube(bot, event, *args)
def _reminder_on_connect_listener(bot): reminders = UtilBot.get_all_reminders() for reminder in reminders: reminder_time = dateutil.parser.parse(reminder[2]) reminder_interval = (reminder_time - datetime.now()).seconds conv = bot._conv_list.get(reminder[0]) reminder_timer = threading.Timer(reminder_interval, send_reminder, [ bot, conv, reminder_interval, reminder[1], asyncio.get_event_loop() ]) reminder_timer.start()
def help(bot, event, command=None, *args): docstring = """ *Current Implemented Commands:* {} Use: /<command name> ? or /help <command name> to find more information about the command. """.format(', '.join(sorted(DispatcherSingleton.commands.keys()))) if command == '?' or command is None: yield from bot.send_message_segments( event.conv, UtilBot.text_to_segments(docstring)) else: if command in DispatcherSingleton.commands.keys(): func = DispatcherSingleton.commands[command] if func.__doc__: yield from bot.send_message_segments( event.conv, UtilBot.text_to_segments(func.__doc__)) else: # Compatibility purposes for the old way of showing help text. args = ['?'] yield from func(bot, event, *args) else: yield from bot.send_message( "The command {} is not registered.".format(command))
def run(self, bot, event, bot_command_char, *args, **kwds): bot_command_char = bot_command_char.strip() # For cases like "/bot " or " / " if args[0] == bot_command_char: # Either the command char is like "/bot" or the user did "/ ping" args = list(args[1:]) if args[0].startswith(bot_command_char): command = args[0][len(bot_command_char):] else: command = args[0] if command[:2] == 'r/': command = 'subreddit' args = list(args) print(args) args.insert(1, args[0][3:]) elif command[:2] == 'v/': command = 'subverse' args = list(args) print(args) args.insert(1, args[0][3:]) try: func = self.commands[command] except KeyError: try: if event.user.is_self: func = self.hidden_commands[command] else: raise KeyError except KeyError: if self.unknown_command: func = self.unknown_command else: raise NoCommandFoundError( "Command {} is not registered. Furthermore, no command found to handle unknown commands.".format (command)) func = asyncio.coroutine(func) args = list(args[1:]) # For help cases. if len(args) > 0 and args[0] == '?': if func.__doc__: bot.send_message_segments(event.conv, UtilBot.text_to_segments(func.__doc__)) return try: asyncio.async(func(bot, event, *args, **kwds)) except Exception as e: log = open('log.txt', 'a+') log.writelines(str(datetime.now()) + ":\n " + traceback.format_exc() + "\n\n") log.close() print(traceback.format_exc())
def latex(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ **LaTeX** Usage: /latex <LaTeX code> Purpose: Renders LaTeX code to an image and sends it """) bot.send_message_segments(event.conv, segments) else: cmd = "texvc /tmp images '" + \ ' '.join(args).replace("'", "'\\''") + \ "' utf-8 'rgb 1.0 1.0 1.0'" print('args: ') print(cmd) output = subprocess.check_output(cmd, shell=True) output = output.decode(encoding='UTF-8') print(output) filename = output[1:33] + '.png' filename = os.path.join('images', filename) image_id = yield from UtilBot.upload_image(bot, filename) send_image(bot, event, image_id)
def ytban(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ **YTBan** Usage: /ytban <search parameters> Purpose: Get the first result from YouTube\'s search using search parameter, then bans it! """) bot.send_message_segments(event.conv, segments) else: search_terms = " ".join(args) youtube_info = UtilBot.find_youtube_info(search_terms) youtube_banlist = load_json('youtube_banlist.json') if youtube_info['item_id'] not in youtube_banlist: youtube_banlist.append(youtube_info['item_id']) bot.send_message(event.conv, 'Video "{title}" with ID "{id}" is now banned'.format( title=youtube_info['item_title'], id=youtube_info['item_id'])) save_json('youtube_banlist.json', youtube_banlist)
def eightball(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ **Eightball** Usage: /eightball Purpose: Tells fortunes! """) bot.send_message_segments(event.conv, segments) else: if len(args) > 0: bot.send_message(event.conv, _checkTheBall(len(' '.join(args)))) else: bot.send_message(event.conv, _checkTheBall(random.randint(0, 2)))
def fliptext(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ **Flip Text** Usage: /fliptext <text> Purpose: Flips your message 180 degrees """) bot.send_message_segments(event.conv, segments) else: args = ' '.join(args) output = ''.join([fliptextdict.get(letter, letter) for letter in args]) output = output[::-1] bot.send_message(event.conv, output)
def fliptext(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *Flip Text* Usage: /fliptext <text> Purpose: Flips your message 180 degrees """) yield from bot.send_message_segments(event.conv, segments) else: args = ' '.join(args) output = ''.join([fliptextdict.get(letter, letter) for letter in args]) output = output[::-1] yield from bot.send_message(event.conv, output)
def navyseals(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *Navy Seals* Usage: /navyseals Purpose: Shits fury all over you. """) yield from bot.send_message_segments(event.conv, segments) else: yield from bot.send_message( event.conv, "What the f**k did you just f*****g say about me, you little bitch? I'll have you know I graduated top of my class in the Navy Seals, and I've been involved in numerous secret raids on Al-Quaeda, and I have over 300 confirmed kills. I am trained in gorilla warfare and I'm the top sniper in the entire US armed forces. You are nothing to me but just another target. I will wipe you the f**k out with precision the likes of which has never been seen before on this Earth, mark my f*****g words. You think you can get away with saying that shit to me over the Internet? Think again, f****r. As we speak I am contacting my secret network of spies across the USA and your IP is being traced right now so you better prepare for the storm, maggot. The storm that wipes out the pathetic little thing you call your life. You're f*****g dead, kid. I can be anywhere, anytime, and I can kill you in over seven hundred ways, and that's just with my bare hands. Not only am I extensively trained in unarmed combat, but I have access to the entire arsenal of the United States Marine Corps and I will use it to its full extent to wipe your miserable ass off the face of the continent, you little shit. If only you could have known what unholy retribution your little “clever” comment was about to bring down upon you, maybe you would have held your f*****g tongue. But you couldn't, you didn't, and now you're paying the price, you goddamn idiot. I will shit fury all over you and you will drown in it. You're f*****g dead, kiddo." )
def help(bot, event, command=None, *args): valid_user_commands = [] for command_test in sorted(DispatcherSingleton.commands.keys()): if UtilBot.check_if_can_run_command(bot, event, command_test): valid_user_commands.append(command_test) docstring = """ **Current Implemented Commands:** {} Use: /<command name> ? or /help <command name> to find more information about the command. """.format(', '.join(valid_user_commands)) if command == '?' or command is None: bot.send_message_segments(event.conv, UtilBot.text_to_segments(docstring)) else: if command in DispatcherSingleton.commands.keys(): func = DispatcherSingleton.commands[command] if func.__doc__: bot.send_message_segments(event.conv, UtilBot.text_to_segments(func.__doc__)) else: # Compatibility purposes for the old way of showing help text. args = ['?'] func(bot, event, *args) else: bot.send_message("The command {} is not registered.".format(command))
def youtube(bot, event, *args): Segment = hangups.ChatMessageSegment if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ **YouTube** Usage: /youtube <optional: search parameter> Purpose: Get the first result from YouTube\'s search using search parameter. """) bot.send_message_segments(event.conv, segments) else: search_terms = " ".join(args) youtube_info = UtilBot.find_youtube_info(search_terms) youtube_banlist = load_json('youtube_banlist.json') if youtube_info['item_id'] in youtube_banlist: bot.send_message(event.conv, 'Sorry, that video is banned.') else: bot.send_message_segments(event.conv, [hangups.ChatMessageSegment('Result:', is_bold=True), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK), hangups.ChatMessageSegment(youtube_info['item_title'], hangups.SegmentType.LINK, link_target=youtube_info['item_url'])])
def udefine(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *Urbanly Define* Usage: /udefine <word to search for> \ <optional: definition number [defaults to 1st]> Purpose: Define a word. """) bot.send_message_segments(event.conv, segments) else: api_host = 'http://urbanscraper.herokuapp.com/search/' num_requested = 0 returnall = False if len(args) == 0: bot.send_message(event.conv, "Invalid usage of /udefine.") return else: if args[-1] == '*': args = args[:-1] returnall = True if args[-1].isdigit(): # we subtract one here because def #1 is the 0 item in the list num_requested = int(args[-1]) - 1 args = args[:-1] term = parse.quote('.'.join(args)) response = requests.get(api_host + term) error_response = 'No definition found for \"{}\".'.format(' '.join(args)) if response.status_code != 200: bot.send_message(event.conv, error_response) result = response.content.decode() result_list = json.loads(result) if len(result_list) == 0: bot.send_message(event.conv, error_response) return num_requested = min(num_requested, len(result_list) - 1) num_requested = max(0, num_requested) result = result_list[num_requested].get( 'definition', error_response) if returnall: segments = [] for string in result_list: segments.append(hangups.ChatMessageSegment(string)) segments.append(hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK)) bot.send_message_segments(event.conv, segments) else: segments = [hangups.ChatMessageSegment(' '.join(args), is_bold=True), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK), hangups.ChatMessageSegment(result + ' [{0} of {1}]'.format( num_requested + 1, len(result_list)))] bot.send_message_segments(event.conv, segments)
def source(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ **Source** Usage: /source Purpose: Links to the GitHub """) bot.send_message_segments(event.conv, segments) else: url = 'https://github.com/ShaunOfTheLive/HangoutsBot' segments = [hangups.ChatMessageSegment(url, hangups.SegmentType.LINK, link_target=url)] bot.send_message_segments(event.conv, segments)
def log(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ **Log** Usage: /log <text> Purpose: Logs text to the log.txt file. """) bot.send_message_segments(event.conv, segments) else: msg = ' '.join(args) log = open('log.txt', 'a+') log.writelines(msg + "\n") for c in msg: log.writelines(hex(ord(c)) + " ") log.writelines("\n") log.close()
def run(self, bot, event, bot_command_char, *args, **kwds): bot_command_char = bot_command_char.strip( ) # For cases like "/bot " or " / " if args[0] == bot_command_char: # Either the command char is like "/bot" or the user did "/ ping" args = list(args[1:]) if args[0].startswith(bot_command_char): command = args[0][len(bot_command_char):] else: command = args[0] try: func = self.commands[command] except KeyError: try: if event.user.is_self: func = self.hidden_commands[command] else: raise KeyError except KeyError: if self.unknown_command: func = self.unknown_command else: raise NoCommandFoundError( "Command {} is not registered. Furthermore, no command found to handle unknown commands." .format(command)) func = asyncio.coroutine(func) args = list(args[1:]) # For help cases. if len(args) > 0 and args[0] == '?': if func.__doc__: bot.send_message_segments( event.conv, UtilBot.text_to_segments(func.__doc__)) return try: asyncio. async (func(bot, event, *args, **kwds)) except Exception as e: log = open('log.txt', 'a+') log.writelines( str(datetime.now()) + ":\n " + traceback.format_exc() + "\n\n") log.close() print(traceback.format_exc())
def spoof(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *Spoof* Usage: /spoof Purpose: Who knows... """) yield from bot.send_message_segments(event.conv, segments) else: segments = [hangups.ChatMessageSegment('!!! CAUTION !!!', is_bold=True), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK), hangups.ChatMessageSegment('User ')] link = 'https://plus.google.com/u/0/{}/about'.format(event.user.id_.chat_id) segments.append(hangups.ChatMessageSegment(event.user.full_name, hangups.SegmentType.LINK, link_target=link)) segments.append(hangups.ChatMessageSegment(' has just been reporting to the NSA for attempted spoofing!')) yield from bot.send_message_segments(event.conv, segments)
def spoof(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *Spoof* Usage: /spoof Purpose: Who knows... """) bot.send_message_segments(event.conv, segments) else: segments = [hangups.ChatMessageSegment('!!! CAUTION !!!', is_bold=True), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK), hangups.ChatMessageSegment('User ')] link = 'https://plus.google.com/u/0/{}/about'.format(event.user.id_.chat_id) segments.append(hangups.ChatMessageSegment(event.user.full_name, hangups.SegmentType.LINK, link_target=link)) segments.append(hangups.ChatMessageSegment(' has just been reporting to the NSA for attempted spoofing!')) bot.send_message_segments(event.conv, segments)
def youtube(bot, event, *args): Segment = hangups.ChatMessageSegment if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *YouTube* Usage: /youtube <optional: search parameter> Purpose: Get the first result from YouTube\'s search using search parameter. """) bot.send_message_segments(event.conv, segments) else: yield from bot.send_typing(event.conv) search_terms = " ".join(args) if search_terms == "" or search_terms == " ": search_terms = "Fabulous Secret Powers" query = parse.urlencode({ 'search_query': search_terms, 'filters': 'video' }) results_url = 'https://www.youtube.com/results?%s' \ % query headers = { 'User-agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36' } req = request.Request(results_url, None, headers) resp = request.urlopen(req) soup = BeautifulSoup(resp) item_id = soup.find_all("div", class_="yt-lockup")[0]['data-context-item-id'] query = parse.urlencode({'v': item_id}) item_url = 'https://www.youtube.com/watch?%s' \ % query item_title = soup.find_all("a", class_="yt-uix-tile-link")[0]['title'] if item_id in youtube_banlist: yield from bot.send_message(event.conv, 'Sorry, that video is banned.') else: yield from bot.send_message_segments(event.conv, [ hangups.ChatMessageSegment('Result:', is_bold=True), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK), hangups.ChatMessageSegment( item_title, hangups.SegmentType.LINK, link_target=item_url) ])
def load_images_from_folder(bot, event, *args): folder = args[0] # loop through folder for filename in glob(os.path.join('images', folder, '*')): # if filename not in imageids, upload it and store filename,id filetail = os.path.split(filename)[1] filehead = os.path.split(os.path.split(filename)[0])[1] filekey = os.path.join(filehead, filetail) print(filekey) image_id = UtilDB.get_imageid_for_filename(filekey) if image_id is None: bot.send_message(event.conv, "Uploading {}".format(filekey)) image_id = yield from UtilBot.upload_image(bot, filename) UtilDB.set_imageid_for_filename(filekey, image_id) ####os.remove(filename) UtilDB.set_alias_for_filename(filekey, folder) bot.send_message(event.conv, "Done.")
def color(bot, event, *args): filename = 'color.png' cmd = ['convert', '-size', '500x500', 'xc:%s' % ' '.join(args), filename] try: output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) output = output.decode(encoding='UTF-8') if output != '': bot.send_message(event.conv, output) image_id = yield from UtilBot.upload_image(bot, filename) send_image(bot, event, image_id) os.remove(filename) except subprocess.CalledProcessError as e: output = e.output.decode(encoding='UTF-8') if output != '': bot.send_message(event.conv, output)
def latex(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *LaTeX* Usage: /latex <LaTeX code> Purpose: Renders LaTeX code to an image and sends it """) yield from bot.send_message_segments(event.conv, segments) else: cmd = "texvc /tmp images '" + \ ' '.join(args).replace("'", "'\\''") + \ "' utf-8 'rgb 1.0 1.0 1.0'" print('args: ') print(cmd) output = subprocess.check_output(cmd, shell=True) output = output.decode(encoding='UTF-8') print(output) filename = output[1:33] + '.png' filename = os.path.join('images', filename) imageID = yield from bot._client.upload_image(filename) bot.send_image(event.conv, imageID)
def quote(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *Quote* Usage: /quote <optional: terms to search for> \ <optional: number of quote to show> Purpose: Shows a quote. """) yield from bot.send_message_segments(event.conv, segments) else: USER_ID = "3696" DEV_ID = "ZWBWJjlb5ImJiwqV" QUERY_TYPE = "RANDOM" fetch = 0 if len(args) > 0 and args[-1].isdigit(): fetch = int(args[-1]) args = args[:-1] query = '+'.join(args) if len(query) > 0: QUERY_TYPE = "SEARCH" url = "http://www.stands4.com/services/v2/quotes.php?uid=" + USER_ID + "&tokenid=" + DEV_ID + "&searchtype=" + QUERY_TYPE + "&query=" + query soup = BeautifulSoup(request.urlopen(url)) if QUERY_TYPE == "SEARCH": children = list(soup.results.children) numQuotes = len(children) if numQuotes == 0: yield from bot.send_message(event.conv, "Unable to find quote.") return if fetch > numQuotes - 1: fetch = numQuotes elif fetch < 1: fetch = 1 yield from bot.send_message(event.conv, "\"" + children[fetch - 1].quote.text + "\"" + ' - ' + children[ fetch - 1].author.text + ' [' + str( fetch) + ' of ' + str(numQuotes) + ']') else: yield from bot.send_message(event.conv, "\"" + soup.quote.text + "\"" + ' -' + soup.author.text)
def quote(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *Quote* Usage: /quote <optional: terms to search for> \ <optional: number of quote to show> Purpose: Shows a quote. """) bot.send_message_segments(event.conv, segments) else: USER_ID = "3696" DEV_ID = "ZWBWJjlb5ImJiwqV" QUERY_TYPE = "RANDOM" fetch = 0 if len(args) > 0 and args[-1].isdigit(): fetch = int(args[-1]) args = args[:-1] query = '+'.join(args) if len(query) > 0: QUERY_TYPE = "SEARCH" url = "http://www.stands4.com/services/v2/quotes.php?uid=" + USER_ID + "&tokenid=" + DEV_ID + "&searchtype=" + QUERY_TYPE + "&query=" + query soup = BeautifulSoup(request.urlopen(url)) if QUERY_TYPE == "SEARCH": children = list(soup.results.children) numQuotes = len(children) if numQuotes == 0: bot.send_message(event.conv, "Unable to find quote.") return if fetch > numQuotes - 1: fetch = numQuotes elif fetch < 1: fetch = 1 bot.send_message(event.conv, "\"" + children[fetch - 1].quote.text + "\"" + ' - ' + children[ fetch - 1].author.text + ' [' + str( fetch) + ' of ' + str(numQuotes) + ']') else: bot.send_message(event.conv, "\"" + soup.quote.text + "\"" + ' -' + soup.author.text)
def greentext(bot, event, *args): """ **Greentext** Usage: /greentext <text> Purpose: makes your text green and adds an epic maymay arrow, add more maymay arrows for more fun """ filename = 'greentext.png' message = ' '.join(args) if message[0] == '>': message = message[1:] message = message.replace('>', '\n>') message = '>' + message print(message) cmd = ['convert', '-size', '164x', '-font', '/usr/share/fonts/TTF/arial.ttf', '-pointsize', '13', '-fill', '#789922', '-background', '#ffffee', 'caption:%s' % message, filename] try: output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) output = output.decode(encoding='UTF-8') if output != '': bot.send_message(event.conv, output) image_id = yield from UtilBot.upload_image(bot, filename) send_image(bot, event, image_id) os.remove(filename) except subprocess.CalledProcessError as e: output = e.output.decode(encoding='UTF-8') if output != '': bot.send_message(event.conv, output)
def webshot(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ **Webshot** Usage: /webshot <url> Purpose: Screenshots a webpage """) bot.send_message_segments(event.conv, segments) else: if len(args) == 1: url = args[0] viewportsize = '1280x1024' elif len(args) > 1: url = args[0] viewportsize = args[1] if not is_valid_url(url): url = 'http://' + url if not is_valid_url(url): bot.send_message(event.conv, "Error: invalid URL.") return yield from send_webpage_screenshot(bot, event, url, viewportsize)
def remind(bot, event, *args): # TODO Implement a private chat feature. Have reminders save across reboots? if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *Remind* Usage: /remind <optional: date [defaults to today]> \ <optional: time [defaults to an hour from now]> Message Usage: /remind Usage: /remind delete <index to delete> Purpose: Will post a message the date and time specified to \ the current chat. With no arguments, it'll list all the reminders. """) yield from bot.send_message_segments(event.conv, segments) else: if len(args) == 0: segments = [hangups.ChatMessageSegment('Reminders:', is_bold=True), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK)] if len(reminders) > 0: for x in range(0, len(reminders)): reminder = reminders[x] reminder_timer = reminder[0] reminder_text = reminder[1] date_to_post = datetime.now() + timedelta(seconds=reminder_timer.interval) segments.append( hangups.ChatMessageSegment( str(x + 1) + ' - ' + date_to_post.strftime('%m/%d/%y %I:%M%p') + ' : ' + reminder_text)) segments.append(hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK)) segments.pop() yield from bot.send_message_segments(event.conv, segments) else: yield from bot.send_message(event.conv, "No reminders are currently set.") return if args[0] == 'delete': try: x = int(args[1]) x -= 1 except ValueError: yield from bot.send_message(event.conv, 'Invalid integer: ' + args[1]) return if x in range(0, len(reminders)): reminder_to_remove_text = reminders[x][1] reminders[x][0].cancel() reminders.remove(reminders[x]) yield from bot.send_message(event.conv, 'Removed reminder: ' + reminder_to_remove_text) else: yield from bot.send_message(event.conv, 'Invalid integer: ' + str(x + 1)) return def send_reminder(bot, conv, reminder_time, reminder_text, loop): asyncio.set_event_loop(loop) yield from bot.send_message(conv, reminder_text) for reminder in reminders: if reminder[0].interval == reminder_time and reminder[1] == reminder_text: reminders.remove(reminder) args = list(args) date = str(datetime.now().today().date()) time = str((datetime.now() + timedelta(hours=1)).time()) set_date = False set_time = False index = 0 while index < len(args): item = args[index] if item[0].isnumeric(): if '/' in item or '-' in item: date = item args.remove(date) set_date = True index -= 1 else: time = item args.remove(time) set_time = True index -= 1 if set_date and set_time: break index += 1 reminder_time = date + ' ' + time if len(args) > 0: reminder_text = ' '.join(args) else: yield from bot.send_message(event.conv, 'No reminder text set.') return current_time = datetime.now() try: reminder_time = parser.parse(reminder_time) except (ValueError, TypeError): yield from bot.send_message(event.conv, "Couldn't parse " + reminder_time + " as a valid date.") return if reminder_time < current_time: reminder_time = current_time + timedelta(hours=1) reminder_interval = (reminder_time - current_time).seconds reminder_timer = threading.Timer(reminder_interval, send_reminder, [bot, event.conv, reminder_interval, reminder_text, asyncio.get_event_loop()]) reminders.append((reminder_timer, reminder_text)) reminder_timer.start() bot.send_message(event.conv, "Reminder set for " + reminder_time.strftime('%B %d, %Y %I:%M%p'))
def define(bot, event, *args): """ **Define:** Usage: /define <word to search for> <optional: definition number [defaults to 1] OR * to show all definitions> Usage: /define <word to search for> <start index and end index in form of int:int (e.g., /define test 1:3)> Purpose: Show definitions for a word. """ if args[-1].isdigit(): definition, length = UtilBot.define(' '.join(args[0:-1]), num=int(args[-1])) segments = [hangups.ChatMessageSegment(' '.join(args[0:-1]).title(), is_bold=True), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK), hangups.ChatMessageSegment( definition.replace('\n', ''))] bot.send_message_segments(event.conv, segments) elif args[-1] == '*': args = list(args) args[-1] = '1:*' if ':' in args[-1]: start, end = re.split(':', args[-1]) try: start = int(start) except ValueError: start = 1 display_all = False if end == '*': end = 100 display_all = True else: try: end = int(end) except ValueError: end = 3 if start < 1: start = 1 if start > end: end, start = start, end if start == end: end += 1 if len(args) <= 1: bot.send_message(event.conv, "Invalid usage for /define.") return query = ' '.join(args[:-1]) definition_segments = [hangups.ChatMessageSegment(query.title(), is_bold=True), hangups.ChatMessageSegment('', segment_type=hangups.SegmentType.LINE_BREAK)] if start < end: x = start while x <= end: definition, length = UtilBot.define(query, num=x) definition_segments.append(hangups.ChatMessageSegment(definition)) if x != end: definition_segments.append( hangups.ChatMessageSegment('', segment_type=hangups.SegmentType.LINE_BREAK)) definition_segments.append( hangups.ChatMessageSegment('', segment_type=hangups.SegmentType.LINE_BREAK)) if end > length: end = length if display_all: end = length display_all = False x += 1 bot.send_message_segments(event.conv, definition_segments) return else: args = list(args) args.append("1:3") define(bot, event, *args) return
def record(bot, event, *args): if ''.join(args) == '?': segments = UtilBot.text_to_segments("""\ *Record* Usage: /record <text to record> Usage: /record date <date to show records from> Usage: /record list Usage: /record search <search term> Usage: /record strike Usage: /record Purpose: Store/Show records of conversations. Note: All records will be prepended by: "On the day of <date>," automatically. """) yield from bot.send_message_segments(event.conv, segments) else: import datetime global last_recorded, last_recorder directory = "Records" + os.sep + str(event.conv_id) if not os.path.exists(directory): os.makedirs(directory) filename = str(datetime.date.today()) + ".txt" filepath = os.path.join(directory, filename) file = None # Deletes the record for the day. TODO Is it possible to make this admin only? if ''.join(args) == "clear": file = open(filepath, "a+") file.seek(0) file.truncate() # Shows the record for the day. elif ''.join(args) == '': file = open(filepath, "a+") # If the mode is r+, it won't create the file. If it's a+, I have to seek to the beginning. file.seek(0) segments = [hangups.ChatMessageSegment( 'On the day of ' + datetime.date.today().strftime('%B %d, %Y') + ':', is_bold=True), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK)] for line in file: segments.append( hangups.ChatMessageSegment(line)) segments.append(hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK)) segments.append(hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK)) yield from bot.send_message_segments(event.conv, segments) # Removes the last line recorded, iff the user striking is the same as the person who recorded last. # TODO This isn't working properly across multiple chats. elif args[0] == "strike": if event.user.id_ == last_recorder: file = open(filepath, "a+") file.seek(0) file_lines = file.readlines() if last_recorded is not None and last_recorded in file_lines: file_lines.remove(last_recorded) file.seek(0) file.truncate() file.writelines(file_lines) last_recorded = None last_recorder = None else: yield from bot.send_message(event.conv, "You do not have the authority to strike from the Record.") # Lists every record available. TODO Paginate this? elif args[0] == "list": files = os.listdir(directory) segments = [] for name in files: segments.append(hangups.ChatMessageSegment(name.replace(".txt", ""))) segments.append(hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK)) yield from bot.send_message_segments(event.conv, segments) # Shows a list of records that match the search criteria. elif args[0] == "search": args = args[1:] searched_term = ' '.join(args) escaped_args = [] for item in args: escaped_args.append(re.escape(item)) term = '.*'.join(escaped_args) term = term.replace(' ', '.*') if len(args) > 1: term = '.*' + term else: term = '.*' + term + '.*' foundin = [] for name in glob.glob(directory + os.sep + '*.txt'): with open(name) as f: contents = f.read() if re.match(term, contents, re.IGNORECASE | re.DOTALL): foundin.append(name.replace(directory, "").replace(".txt", "").replace("\\", "")) if len(foundin) > 0: segments = [hangups.ChatMessageSegment("Found "), hangups.ChatMessageSegment(searched_term, is_bold=True), hangups.ChatMessageSegment(" in:"), hangups.ChatMessageSegment("\n", hangups.SegmentType.LINE_BREAK)] for filename in foundin: segments.append(hangups.ChatMessageSegment(filename)) segments.append(hangups.ChatMessageSegment("\n", hangups.SegmentType.LINE_BREAK)) yield from bot.send_message_segments(event.conv, segments) else: segments = [hangups.ChatMessageSegment("Couldn't find "), hangups.ChatMessageSegment(searched_term, is_bold=True), hangups.ChatMessageSegment(" in any records.")] yield from bot.send_message_segments(event.conv, segments) # Lists a record from the specified date. elif args[0] == "date": from dateutil import parser args = args[1:] try: dt = parser.parse(' '.join(args)) except Exception as e: yield from bot.send_message(event.conv, "Couldn't parse " + ' '.join(args) + " as a valid date.") return filename = str(dt.date()) + ".txt" filepath = os.path.join(directory, filename) try: file = open(filepath, "r") except IOError: yield from bot.send_message(event.conv, "No record for the day of " + dt.strftime('%B %d, %Y') + '.') return segments = [hangups.ChatMessageSegment('On the day of ' + dt.strftime('%B %d, %Y') + ':', is_bold=True), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK)] for line in file: segments.append(hangups.ChatMessageSegment(line)) segments.append(hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK)) segments.append(hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK)) yield from bot.send_message_segments(event.conv, segments) # Saves a record. else: file = open(filepath, "a+") file.write(' '.join(args) + '\n') yield from bot.send_message(event.conv, "Record saved successfully.") last_recorder = event.user.id_ last_recorded = ' '.join(args) + '\n' if file is not None: file.close()
def vote(bot, event, set_vote=None, *args): """**Vote:** Usage: /vote <subject to vote on> Usage: /vote <yea|yes|for|nay|no|against (used to cast a vote)> Usage: /vote cancel Usage: /vote abstain Usage: /vote start <subject to vote on> Usage: /vote start admin (used to start a vote for a new conversation admin) """ # Abstains user from voting. if set_vote is not None and set_vote.lower() == 'abstain': if UtilBot.is_vote_started(event.conv_id): bot.send_message(event.conv, 'User {} has abstained from voting.'.format(event.user.full_name)) if UtilBot.abstain_voter(event.conv_id, event.user.full_name): bot.send_message(event.conv, "The vote has ended because all voters have abstained.") return else: bot.send_message(event.conv, 'No vote currently in process to abstain from.') return # Check if the vote has ended vote_result = UtilBot.check_if_vote_finished(event.conv_id) if vote_result is not None: if vote_result != 0: bot.send_message(event.conv, 'In the matter of: "' + UtilBot.get_vote_subject(event.conv_id) + '", the ' + ( 'Yeas' if vote_result > 0 else 'Nays') + ' have it.') else: bot.send_message(event.conv, "The vote ended in a tie in the matter of: {}".format( UtilBot.get_vote_subject(event.conv_id))) UtilBot.end_vote(event.conv_id) return # Cancels the vote if set_vote is not None and set_vote.lower() == "cancel": if UtilBot.is_vote_started(event.conv_id): bot.send_message(event.conv, 'Vote "{}" cancelled.'.format(UtilBot.get_vote_subject(event.conv_id))) UtilBot.end_vote(event.conv_id) else: bot.send_message(event.conv, 'No vote currently started.') return # Starts a new vote if not UtilBot.is_vote_started(event.conv_id) and set_vote == "start": vote_subject = ' '.join(args) vote_callback = None # TODO Refactor this into a more easily extensible system. if vote_subject.lower().strip() == "admin": # For the special Conversation Admin case. vote_subject = '{} for Conversation Admin for chat {}'.format(event.user.full_name, get_conv_name(event.conv)) def set_conv_admin(won): if won: try: bot.config["conversations"][event.conv_id]["conversation_admin"] = event.user.id_[0] except (KeyError, TypeError): bot.config["conversations"][event.conv_id] = {} bot.config["conversations"][event.conv_id]["admin"] = event.user.id_[0] bot.config.save() vote_callback = set_conv_admin UtilBot.set_vote_subject(event.conv_id, vote_subject) UtilBot.init_new_vote(event.conv_id, event.conv.users) if vote_callback is not None: UtilBot.set_vote_callback(event.conv_id, vote_callback) bot.send_message(event.conv, "Vote started for subject: " + vote_subject) return # Cast a vote. if set_vote is not None and UtilBot.is_vote_started(event.conv_id): if UtilBot.can_user_vote(event.conv_id, event.user): set_vote = set_vote.lower() if set_vote == "true" or set_vote == "yes" or set_vote == "yea" or set_vote == "for" or set_vote == "yay" or set_vote == "aye": UtilBot.set_vote(event.conv_id, event.user.full_name, True) elif set_vote == "false" or set_vote == "no" or set_vote == "nay" or set_vote == "against": UtilBot.set_vote(event.conv_id, event.user.full_name, False) else: bot.send_message(event.conv, "{}, you did not enter a valid vote parameter.".format(event.user.full_name)) return # Check if the vote has ended vote_result = UtilBot.check_if_vote_finished(event.conv_id) if vote_result is not None: if vote_result != 0: bot.send_message(event.conv, 'In the matter of: "' + UtilBot.get_vote_subject(event.conv_id) + '", the ' + ( 'Yeas' if vote_result > 0 else 'Nays') + ' have it.') else: bot.send_message(event.conv, "The vote ended in a tie in the matter of: {}".format( UtilBot.get_vote_subject(event.conv_id))) UtilBot.end_vote(event.conv_id, vote_result) return else: bot.send_message(event.conv_id, 'User {} is not allowed to vote.'.format(event.user.full_name)) return # Check the status of a vote. if UtilBot.is_vote_started(event.conv_id): status = UtilBot.get_vote_status(event.conv_id) if len(status) > 1: bot.send_message_segments(event.conv, UtilBot.text_to_segments('\n'.join(status))) else: bot.send_message(event.conv, "No vote currently started.") else: bot.send_message(event.conv, "No vote currently started.")
def remind(bot, event, *args): # TODO Implement a private chat feature. Have reminders save across reboots? """ **Remind:** Usage: /remind <optional: date [defaults to today]> <optional: time [defaults to an hour from now]> <message> {/remind 1/1/15 2:00PM Call mom} Usage: /remind Usage /remind delete <index to delete> {/remind delete 1} Purpose: Will post a message on the date and time specified to the current chat. With no arguments, it'll list all the reminders.""" # Show all reminders if len(args) == 0: segments = [ hangups.ChatMessageSegment('Reminders:', is_bold=True), hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK) ] reminders = UtilBot.get_all_reminders(event.conv_id) if len(reminders) > 0: for x in range(0, len(reminders)): reminder = reminders[x] reminder_text = reminder[1] date_to_post = dateutil.parser.parse(reminder[2]) segments.append( hangups.ChatMessageSegment( str(x + 1) + ' - ' + date_to_post.strftime('%m/%d/%y %I:%M%p') + ' : ' + reminder_text)) segments.append( hangups.ChatMessageSegment('\n', hangups.SegmentType.LINE_BREAK)) segments.pop() bot.send_message_segments(event.conv, segments) if len(segments) <= 2: bot.send_message(event.conv, "No reminders set for this chat.") return # Delete a reminder if args[0] == 'delete': try: x = int(args[1]) x -= 1 except ValueError: bot.send_message(event.conv, 'Invalid integer: ' + args[1]) return reminders = UtilBot.get_all_reminders(event.conv_id) reminder_to_delete_text = None if x in range(0, len(reminders)): to_delete_reminder = reminders[x] for running_reminder in currently_running_reminders: if running_reminder[1] == to_delete_reminder: running_reminder[0].cancel() if reminder_to_delete_text: bot.send_message( event.conv, 'Removed reminder: ' + str(reminder_to_delete_text)) else: bot.send_message(event.conv, 'The reminder chosen is not currently running.') return # Set a new reminder args = list(args) reminder_text = ' '.join(args) c = parsedatetime.Calendar() result = c.nlp(reminder_text) if result is None: bot.send_message( event.conv, "Couldn't parse a valid date from {}'s message.".format( event.user.full_name)) return reminder_time = result[0][0] reminder_text = reminder_text.replace(result[0][-1], '') if reminder_text.strip() == '': bot.send_message(event.conv, 'No reminder text set.') return current_time = datetime.now() if reminder_time < current_time: bot.send_message("Invalid Date: {}".format( reminder_time.strftime('%B %d, %Y %I:%M%p'))) reminder_interval = (reminder_time - current_time).total_seconds() reminder_timer = threading.Timer(reminder_interval, send_reminder, [ bot, event.conv, reminder_interval, reminder_text, asyncio.get_event_loop() ]) UtilBot.add_reminder(event.conv_id, reminder_text, reminder_time) reminder_timer.start() currently_running_reminders.append( (reminder_timer, (event.conv_id, reminder_text, reminder_time))) bot.send_message( event.conv, "Reminder set for " + reminder_time.strftime('%B %d, %Y %I:%M%p'))
def send_reminder(bot, conv, reminder_time, reminder_text, loop): asyncio.set_event_loop(loop) bot.send_message(conv, "Reminder: " + reminder_text) UtilBot.delete_reminder(conv.id_, reminder_text, reminder_time)
def count(bot, event, *args): words = ' '.join(args) count = UtilBot.syllable_count(words) bot.send_message( event.conv, '"' + words + '"' + " has " + str(count) + (' syllable.' if count == 1 else ' syllables.'))