def c_pyramid(self, msg: twitchirc.ChannelMessage): if not self._get_pyramid_enabled(msg.channel): return f'@{msg.user}, This command is disabled here.' cd_state = main.do_cooldown('pyramid', msg, global_cooldown=60, local_cooldown=60) if cd_state: return t = main.delete_spammer_chrs(msg.text).split(' ', 1) if len(t) == 1: return f'@{msg.user}, Usage: pyramid <size> <text...>' args = t[1].rstrip() size = '' for arg in args.split(' '): arg: str if arg.isnumeric(): size = arg break # prefer first number! if size != '': args: str = args.replace(size, '', 1).rstrip() + ' ' size = int(size) if not args.strip(' '): return f'@{msg.user}, Nothing to send. NaM' for i in range(1, size): main.bot.send(msg.reply(args * i)) for i in range(size, 0, -1): main.bot.send(msg.reply(args * i))
def command_not_active(msg: twitchirc.ChannelMessage): global plebs argv = delete_spammer_chrs(msg.text).split(' ') if len(argv) < 2: bot.send( msg.reply( f'@{msg.user} Usage: not_active <user> Marks the user as not active' )) return text = argv[1:] if len(text) == 1: print(text[0]) rem_count = 0 if text[0] in plebs[msg.channel]: del plebs[msg.channel][text[0]] rem_count += 1 if text[0] in subs[msg.channel]: del subs[msg.channel][text[0]] rem_count += 1 if not rem_count: bot.send( msg.reply(f'@{msg.user} {text[0]!r}: No such chatter found.')) else: bot.send( msg.reply( f'@{msg.user} {text[0]!r}: Marked person as not active.'))
def command_part(msg: twitchirc.ChannelMessage): p = twitchirc.ArgumentParser(prog='!part', add_help=False) p.add_argument('channel', metavar='CHANNEL', nargs='?', const=msg.channel, default=msg.channel) p.add_argument('-h', '--help', action='store_true', dest='help') args = p.parse_args(msg.text.split(' ')[1:]) if args is None or args.help: usage = msg.reply(f'@{msg.user} {p.format_usage()}') bot.send(usage) return if args.channel == '': args.channel = msg.channel channel = args.channel.lower() if channel != msg.channel.lower() and bot.check_permissions( msg, [twitchirc.PERMISSION_COMMAND_PART_OTHER], enable_local_bypass=False): bot.send( msg.reply( f"Cannot part from channel {channel}: your permissions are not valid in that channel." )) return if channel not in bot.channels_connected: bot.send(msg.reply(f'Not in {channel}')) return else: bot.send(msg.reply(f'Parting from {channel}')) m = twitchirc.ChannelMessage('Bye.', 'OUTGOING', channel) m.outgoing = True bot.send(m) bot.flush_single_queue(msg.channel) bot.part(channel)
def command_resolve_suggestion(msg: twitchirc.ChannelMessage): t = main.delete_spammer_chrs(msg.text).split(' ', 3) if len(t) < 3: return f'@{msg.user}, Usage: resolve_suggestion <ID> <state> [notes...]' if not t[1].isnumeric(): return f'@{msg.user}, Unknown suggestion {t[1]!r}.' target = int(t[1]) state_names = [i.name for i in Suggestion.SuggestionState] if t[2] in state_names: state = Suggestion.SuggestionState[t[2]] else: main.bot.send( msg.reply( f'@{msg.user}, Invalid state: {t[2]!r}. Choose between ' f'{", ".join([repr(i.name) for i in Suggestion.SuggestionState])}' )) return if len(t) == 4: notes = t[3] else: notes = None with main.session_scope() as session: suggestion = session.query(Suggestion).filter( Suggestion.id == target).first() suggestion.state = state if notes is not None: suggestion.notes = notes session.add(suggestion) main.bot.send( msg.reply(f'@{msg.user} Modified suggestion id {target!r}, ' f'new state {state}, ' f'new notes {notes}.'))
def chan_msg_handler(self, event: str, msg: twitchirc.ChannelMessage): if msg.user in ['supibot', 'mm2pl'] and msg.text.startswith('HONEYDETECTED RECONNECTED') \ and msg.channel == 'supinic': random_msg = random.choice(RECONNECTION_MESSAGES) while '{ping}' in random_msg: random_msg = random_msg.replace( '{ping}', random.choice(self.random_pings), 1) main.bot.send(msg.reply(random_msg)) if msg.channel in ['supinic', 'mm2pl'] and msg.user in ['thepositivebot', 'linkusbanned'] \ and msg.text.startswith('\x01ACTION [Cookies]'): m = COOKIE_PATTERN.findall( main.delete_spammer_chrs(msg.text.replace('\x01ACTION ', ''))) if m and m[0][1].lower() in self.cookie_optin: time_ = self._time_from_rank(msg.text) main.bot.send( msg.reply( f'$remind {m[0][1].lower()} cookie :) in {time_}')) elif not m: log('warn', f'matching against regex failed: {msg.text!r}') if msg.text.startswith('$ps sneeze') and msg.channel in [ 'supinic', 'mm2pl' ]: self._sneeze = (time.time() + self.cooldown_timeout, msg) if msg.user == 'supibot' and self._sneeze[1] is not None and ( msg.text.startswith( self._sneeze[1].user + ', The playsound\'s cooldown has not passed yet! Try again in' ) or msg.text.startswith(self._sneeze[1].user + ', Playsounds are currently disabled!')): # don't respond if the playsound didn't play self._sneeze = (-1, None)
async def command_reload(msg: twitchirc.ChannelMessage): argv = delete_spammer_chrs(msg.text).rstrip(' ').split(' ', 1) if len(argv) == 1: bot.send( msg.reply( f'Usage: {command_reload.chat_command} <target>, list of possible reloadable targets: ' f'{", ".join(reloadables.keys())}')) else: for name, func in reloadables.items(): if name.lower() == argv[1].lower(): reload_start = time.time() if inspect.iscoroutinefunction(func): bot.send( msg.reply(f'@{msg.user}, reloading {name} (async)...')) try: o = await func() except Exception as e: message = f'@{msg.user}, failed. Error: {e} (Time taken: {time.time() - reload_start}s)' else: message = f'@{msg.user}, done. Output: {o} (Time taken: {time.time() - reload_start}s)' else: bot.send( msg.reply(f'@{msg.user}, reloading {name} (sync)...')) try: o = reloadables[name]() except Exception as e: message = f'@{msg.user}, failed. Error: {e} (Time taken: {time.time() - reload_start}s)' else: message = f'@{msg.user}, done. Output: {o} (Time taken: {time.time() - reload_start}s)' return message return f'@{msg.user} Couldn\'t reload {argv[1]}: no such target.'
def command_vote(msg: twitchirc.ChannelMessage): if msg.user in ['__vote_info', '__vote_results']: return f'@{get_user_name(msg)} No crashing the bot for you ;)' return cd_state = main.do_cooldown('vote', msg, global_cooldown=0, local_cooldown=1 * 60) if cd_state: return if msg.channel not in votes: return f"@{get_user_name(msg)} There's no on-going vote in this channel." else: vote_obj: Vote = votes[msg.channel]['__vote_info'] if vote_obj.closed: return f"@{get_user_name(msg)} There's no on-going vote in this channel." argv = msg.text.split(' ') if len(argv) < 2: return f'@{get_user_name(msg)} Usage: !vote <option(s)>' already_voted = msg.user in votes[msg.channel] if votes[msg.channel]['__vote_info'].allow_multiple: user_votes = argv[1].split(',') if ',' in argv[1] else [argv[1]] invalid_votes = [] for i in user_votes: if i not in vote_obj.options: invalid_votes.append(i) if not invalid_votes: votes[msg.channel][msg.user] = user_votes if already_voted: main.bot.send( msg.reply( f'@{get_user_name(msg)} Successfully overridden vote. ' f'New vote is {user_votes!r}')) else: return f'@{get_user_name(msg)} Successfully voted for {user_votes!r}' else: if len(invalid_votes) == 1: return f'@{get_user_name(msg)} Invalid option: {invalid_votes[0]!r}' else: return f'@{get_user_name(msg)} Invalid option(s): {invalid_votes!r}' if argv[1] in vote_obj.options: votes[msg.channel][msg.user] = argv[1] if already_voted: main.bot.send( msg.reply( f'@{get_user_name(msg)} Successfully overridden vote. ' f'New vote is {argv[1]!r}')) else: return f'@{get_user_name(msg)} Successfully voted for {argv[1]!r}' else: if ',' in argv[1]: return f'@{get_user_name(msg)} Cannot vote for multiple options in this poll.' else: return f'@{get_user_name(msg)} Invalid option: {argv[1]}'
def command_join(msg: twitchirc.ChannelMessage): chan = msg.text.split(' ')[1].lower() if chan in ['all']: bot.send(msg.reply(f'Cannot join #{chan}.')) return if chan in bot.channels_connected: bot.send(msg.reply(f'This bot is already in channel #{chan}.')) else: bot.send(msg.reply(f'Joining channel #{chan}.')) bot.join(chan)
def command_restart(msg: twitchirc.ChannelMessage): if 'debug' in msg.text and not prog_args.debug: return bot.send(msg.reply(f'Restarting MrDestructoid {chr(128299)}')) # Restaring MrDestructoid :gun: print('.') while 1: print( f'\033[A\033[KFlushing queues... Non-empty queues: {list(filter(lambda i: bool(i), bot.queue))}' ) bot.flush_queue(1000) all_empty = True for q in bot.queue: if bot.queue[q]: all_empty = False if all_empty: break print('\033[A\033[KFlushing queues: DONE!') time.sleep(1) bot.stop() python = f'python{sys.version_info.major}.{sys.version_info.minor}' @atexit.register def run_on_shutdown(): if prog_args.debug: _exec(python, [ python, __file__, '--_restart_from', msg.user, msg.channel, '--debug' ]) else: _exec(python, [python, __file__, '--_restart_from', msg.user, msg.channel]) raise SystemExit('restart.')
def command(msg: twitchirc.ChannelMessage): global counters if isinstance(limit_to_channel, (str, list)): if isinstance(limit_to_channel, list) and msg.channel not in limit_to_channel: return if isinstance(limit_to_channel, str) and msg.channel != limit_to_channel: return cd_state = do_cooldown(counter_name, msg, global_cooldown=30, local_cooldown=0) if cd_state: return c = counters[counter_name] if msg.channel not in c: c[msg.channel] = 0 text = msg.text[len(bot.prefix):].replace(counter_name + ' ', '') old_val = c[msg.channel] print(repr(text), msg.text) new_counter_value = counter_difference(text, c[msg.channel]) if new_counter_value is None: bot.send(msg.reply(f'Not a number: {text}')) return else: c[msg.channel] = new_counter_value val = c[msg.channel] bot.send( show_counter_status(val, old_val, counter_name, counter_message, msg))
def c_ping_output(self, msg: twitchirc.ChannelMessage): cd_state = main.do_cooldown('ping_optout', msg, global_cooldown=0, local_cooldown=30) if cd_state: return if msg.user in self.ping_optouts: del self.ping_optouts[msg.user] return f'@{msg.user}, you can be pinged by the bot now.' args = main.delete_spammer_chrs(msg.text).rstrip(' ').split(' ', 1) if len(args) == 1: main.bot.send( msg.reply( f'@{msg.user}, please select a mode. Available modes: ' f'replacement (will replace ping with [PING]), ' f'invisibles (will add invisible characters to pings), ' f'no@ (will remove the @)')) return args = args[1] if self._in(['replace', 'replacement', 'repl', 'r'], args.lower()): mode = OPTOUT_MODE_REPLACEMENT elif self._in( ['invis', 'invisibles', 'invisible', 'characters', 'i', 'chars'], args.lower()): mode = OPTOUT_MODE_INVISIBLE_CHARACTERS elif self._in(['at', 'noat', '@', 'no@', 'n@', 'no_at'], args.lower()): mode = OPTOUT_MODE_NO_AT # noinspection PyUnboundLocalVariable self.ping_optouts[msg.user] = mode return f'@{msg.user}, i will no longer ping you :)'
def command_quick_clip(msg: twitchirc.ChannelMessage): cd_state = do_cooldown(cmd='quick_clip', msg=msg) if cd_state: return bot.send(msg.reply(f'@{msg.flags["display-name"]}: Clip is on the way!')) qc_proc = sp.Popen(['python3.7', 'clip.py', '-cC', msg.channel], stdout=sp.PIPE) tasks.append({'proc': qc_proc, 'owner': msg.user, 'msg': msg})
def count_pleb_command(msg: twitchirc.ChannelMessage): global plebs cd_state = do_cooldown(cmd='count_plebs', msg=msg) if cd_state: return fix_pleb_list(msg.channel) bot.send( msg.reply( f'@{msg.flags["display-name"]} Counted {len(plebs[msg.channel])} ' f'plebs active in chat during the last hour.'))
def permission_error_handler(event, msg: twitchirc.ChannelMessage, command: twitchirc.Command, missing_permissions: typing.List[str]): del event if command is None: return bot.send( msg.reply( f"@{msg.user} You are missing permissions ({', '.join(missing_permissions)}) to use " f"command {command.chat_command}."))
def count_chatters(msg: twitchirc.ChannelMessage): global plebs, subs cd_state = do_cooldown(cmd='count_chatters', msg=msg) if cd_state: return fix_pleb_list(msg.channel) fix_sub_list(msg.channel) bot.send( msg.reply( f'@{msg.flags["display-name"]} Counted {len(plebs[msg.channel]) + len(subs[msg.channel])} ' f'chatters active here in the last hour.'))
def command_check_suggestion(msg: twitchirc.ChannelMessage): cd_state = main.do_cooldown('check_suggestion', msg, global_cooldown=0, local_cooldown=30) if cd_state: return t = main.delete_spammer_chrs(msg.text).split(' ') if len(t) == 1: return f'@{msg.user}, Usage: check_suggestion <ID> or check_suggestion.' target = t[1] if target.isnumeric(): target = int(target) with main.session_scope() as session: suggestion = session.query(Suggestion).filter( Suggestion.id == target).first() if suggestion is None: return f'@{msg.user} Suggestion id {target!r} not found.' else: main.bot.send( msg.reply( f'@{msg.user} ' f'{suggestion.humanize(suggestion.author.last_known_username == msg.user)}' )) else: with main.session_scope() as session: user = main.User.get_by_message(msg, no_create=True) if user is None: return f'@{msg.user}, You are a new user, you don\'t have any suggestions.' suggestions = (session.query(Suggestion).filter( Suggestion.author == user).filter( Suggestion.state.notin_([ Suggestion.SuggestionState.done, Suggestion.SuggestionState.rejected, Suggestion.SuggestionState.not_a_suggestion ]))) main.bot.send( msg.reply( f'@{msg.user} Your suggestions: ' f'{", ".join([f"{s.id} ({s.nice_state()})" for s in suggestions])}' ))
def msg_handler(event, msg: twitchirc.ChannelMessage): if not check_if_command_is_allowed('EMOTE_LIMITER', msg.channel) or msg.text.startswith( main.bot.prefix): return # Ignore commands and non active channels if msg.channel not in channels: make_new_channel(msg.channel) log('info', channels[msg.channel]) cost = _calculate_message_cost(msg) result, limit_blocking, limit_blocking_amount = _check_message_cost( msg, cost) if result: _subtract_cost(msg, cost) else: main.bot.send(msg.reply(f'/timeout {msg.user} 1')) main.bot.send( msg.reply( f'@{msg.user} The channel you tried posting your message on run out of {limit_blocking}' f'your message cost {limit_blocking_amount} {limit_blocking}, but you only have ' f'{channels[msg.channel][limit_blocking]} {limit_blocking}'))
def echo_command(msg: twitchirc.ChannelMessage): cd_state = do_cooldown(cmd=command_name, msg=msg) if cd_state: return data = (echo_data.replace('{user}', msg.user).replace('{cmd}', command_name)) for num, i in enumerate( msg.text.replace(bot.prefix + command_name, '', 1).split(' ')): data = data.replace(f'{{{num}}}', i) data = data.replace('{+}', i + ' {+}') data = data.replace('{+}', '') bot.send(msg.reply(data))
def _no_permission_handler(self, event, message: twitchirc.ChannelMessage, command: typing.Optional[twitchirc.Command], missing_permissions: typing.List[str]): del event if command is None: # ignore cooldown bypass checks return if message.channel in plugin_manager.channel_settings: settings = plugin_manager.channel_settings[message.channel] if settings.get(self.no_perm_handler.name) == NO_PERM_MESSAGE: main.bot.send( message.reply( f"@{message.user} You are missing permissions " f"({', '.join(missing_permissions)}) to use command " f"{command.chat_command}."))
async def _cookie(self, msg: twitchirc.ChannelMessage): m = COOKIE_PATTERN.findall(main.delete_spammer_chrs(msg.text.replace('\x01ACTION ', ''))) print(msg.user, m) if m and m[0][1].lower() in self.cookie_optin: time_ = 2 * 60 * 60 print(time_) print('cookie opt in okay') params = { 'username': m[0][1].lower(), 'text': 'Cookie :)', 'schedule': ( ( datetime.datetime.utcnow() + datetime.timedelta(seconds=time_) ).isoformat() + 'Z' ), 'private': 1, } print(params) async with (await main.supibot_api.request('post /bot/reminder/', params=params)) as r: print(f'request {r}') j = await r.json() print(j) if r.status == 200: await main.bot.send(msg.reply( f'@{m[0][1].lower()}, I set up a cookie reminder for you :), ' f'id: {j["data"]["reminderID"]}' )) else: await main.bot.send(msg.reply( f'@{m[0][1].lower()}, monkaS {chr(0x1f6a8)}' f'failed to create cookie reminder ' )) elif not m: log('warn', f'matching against regex failed: {msg.text!r}')
def command_join_blacklisted(msg: twitchirc.ChannelMessage) -> str: ensure_blacklist(msg.channel) chan = msg.text.split(' ')[1].lower() if chan in ['all']: return f'Cannot join #{chan}.' if chan in main.bot.channels_connected: return f'This bot is already in channel #{chan}.' else: blacklist[msg.channel] = [i.chat_command for i in main.bot.commands] blacklist[msg.channel].remove('mb.blacklist_command') blacklist[msg.channel].remove('mb.unblacklist_command') blacklist[msg.channel].remove('mb.list_blacklisted_commands') main.bot.send( msg.reply( f'Joining channel #{chan} with all commands blacklisted apart from ' f'mb.blacklist_command, mb.unblacklist_command and mb.list_blacklisted_command' )) main.bot.join(chan)
def command_worldrecord(msg: twitchirc.ChannelMessage): if msg.channel in current_categories: category = current_categories[msg.channel] time_ = category.runs[0]["run"].times['primary_t'] players = ' and '.join( [p.name for p in category.runs[0]["run"].players]) return ( f'@{msg.user} Current WR for {current_games[msg.channel].name} ' f'({category.category.name}) is ' f'{_format_time(time_)} by {players}') else: if msg.channel in current_games: return f'@{msg.user}, There is a game set but there is no category set. Cannot fetch WR.' else: main.bot.send( msg.reply( f'@{msg.user}, There is no game set on this channel. Ask a mod to run the ' f'update_game command.'))
def command_update_game(msg: twitchirc.ChannelMessage): picked = (msg.text + ' ').split(' ', 1)[1].rstrip(' ') if picked == '': picked = None elif picked.isnumeric(): picked = int(picked) st, ret_msg, err_name = _refresh_game(msg.channel, picked=picked) if st is False: if err_name == 'multiple': main.bot.send( msg.reply( f'@{msg.user} {ret_msg}. Use {command_update_game.chat_command} [number] ' f'or {command_update_game.chat_command} [game title]' f'or {command_update_game.chat_command} [part of title] to select the game.' )) else: return f'@{msg.user} Error: {ret_msg}' else: return f'@{msg.user}, Okay, set game to {ret_msg}'
def command_say(msg: twitchirc.ChannelMessage): return msg.reply(msg.text.split(' ', 1)[1], True)
def command_perm(msg: twitchirc.ChannelMessage): p = twitchirc.ArgumentParser(prog='!perm', add_help=False) g = p.add_mutually_exclusive_group(required=True) g.add_argument('-a', '--add', metavar=('USER', 'PERMISSION'), nargs=2, dest='add') g.add_argument('-r', '--remove', metavar=('USER', 'PERMISSION'), nargs=2, dest='remove') g.add_argument('-l', '--list', metavar='USER', const=msg.user, default=None, nargs='?', dest='list') g.add_argument('-h', '--help', action='store_true', dest='help') args = p.parse_args(args=msg.text.split(' ')[1:]) if args is None or args.help: usage = msg.reply(f'@{msg.user} {p.format_usage()}') bot.send(usage) return if args.add: if bot.check_permissions(msg, [twitchirc.PERMISSION_COMMAND_PERM_ADD], enable_local_bypass=False): bot.send( msg.reply( f"@{msg.user} You cannot use !perm -a, since you don't have" f"the {twitchirc.PERMISSION_COMMAND_PERM_ADD} permission" )) return if args.add[0] not in bot.permissions: bot.permissions[args.add[0]] = [] if args.add[1] not in bot.permissions[args.add[0]]: bot.permissions[args.add[0]].append(args.add[1]) bot.send( msg.reply( f'@{msg.user} Given permission {args.add[1]} to user {args.add[0]}.' )) else: bot.send( msg.reply( f'@{msg.user} User {args.add[0]} already has permission {args.add[1]}.' )) return elif args.remove: if bot.check_permissions( msg, [twitchirc.PERMISSION_COMMAND_PERM_REMOVE], enable_local_bypass=False): bot.send( msg.reply( f"@{msg.user} You cannot use !perm -r, since you don't have" f"the {twitchirc.PERMISSION_COMMAND_PERM_REMOVE} permission" )) return if args.remove[0] not in bot.permissions: bot.permissions[args.remove[0]] = [] if args.remove[1] not in bot.permissions[args.remove[0]]: bot.send( msg.reply(f"@{msg.user} User {args.remove[0]} already " f"doesn't have permission {args.remove[1]}.")) return else: bot.permissions[args.remove[0]].remove(args.remove[1]) bot.send( msg.reply( f'@{msg.user} Removed permission {args.remove[1]} from user {args.remove[0]}.' )) return elif args.list: if bot.check_permissions(msg, [twitchirc.PERMISSION_COMMAND_PERM_LIST]): bot.send( msg.reply( f"@{msg.user} You cannot use !perm -l, since you don't have" f"the {twitchirc.PERMISSION_COMMAND_PERM_LIST} permission" )) return args.list = args.list.lower() if args.list not in bot.permissions: bot.permissions[args.list] = [] if args.list == msg.user: output = ', '.join(bot.permissions.get_permission_state(msg)) bot.send(msg.reply(f'You have permissions: {output}')) else: output = ', '.join(bot.permissions[args.list]) bot.send( msg.reply(f'User {args.list} has permissions: {output}')) return
def delete_command(msg: twitchirc.ChannelMessage): argv = shlex.split(msg.text.replace('\U000e0000', '')) args = delete_command_parser.parse_args(argv[1:] if len(argv) > 1 else []) if args is None: usage = delete_command_parser.format_usage().replace('\n', '') return f'@{msg.user} {usage}' if args.confirm: if msg.user in delete_list: delete_action = delete_list[msg.user] del delete_list[msg.user] if delete_action.expiration_time < datetime.datetime.now(): return f'@{msg.user} Your request has expired.' if delete_action.command_to_delete.chat_command != args.confirm: return (f'@{msg.user} Cannot confirm deletion of command ' f'{delete_action.command_to_delete.chat_command!r}. ' f'You typed {args.confirm!r}.') else: exit_code, message = _delete_command( delete_action.command_to_delete, msg.channel, args.is_global) if exit_code != 0: return f'@{msg.user} Failed to delete command: {message}' else: return ( f'@{msg.user} Deleted command ' f'{delete_action.command_to_delete.chat_command!r} successfully.' ) return else: return f'@{msg.user} You don\'t have an action to confirm.' else: t = args.target.rstrip().split('#') if len(t) == 2: target, t_info = t else: target = t[0] t_info = None if target in [i.chat_command for i in main.bot.commands]: cmd = None candidates = [] for i in main.bot.commands: if i.chat_command.lower() == target.lower(): if args.is_global: candidates.append(i) elif i.limit_to_channels is not None and msg.channel in i.limit_to_channels: candidates.append(i) if len(candidates) == 1: cmd = candidates[0] elif len(candidates) == 0: return f'@{msg.user} Command {target!r} doesn\'t exist in this scope.' else: if t_info.isnumeric(): t_info = int(t_info) + 1 if t_info > len(candidates) or t_info < 1: main.bot.send( msg.reply( f'@{msg.user} Cannot pick number {t_info} of ' f'{", ".join([i.chat_command for i in candidates])}' )) return cmd = candidates[t_info - 1] else: targets = ", ".join([ f"{i.chat_command} (ch: {i.limit_to_channels})" for i in candidates ]) main.bot.send( msg.reply( f'@{msg.user} Multiple possible target commands: ' f'{targets}')) return delete_list[msg.user] = Deletion( msg.user, cmd, datetime.datetime.now() + datetime.timedelta(seconds=TIME_DELETION)) scope = 'the global scope.' if args.is_global else f'the scope of this channel (#{msg.channel})' main.bot.send( msg.reply( f'@{msg.user} Confirm you want to delete command {target!r} in ' f'{scope} using (prefix)mb.delete_command --confirm-delete COMMAND_NAME. ' f'You have {TIME_DELETION} seconds to do this.')) else: return f'@{msg.user} Command {args.target} doesn\'t exist.'
async def c_braillefy(self, msg: twitchirc.ChannelMessage): cd_state = main.do_cooldown('braille', global_cooldown=0, local_cooldown=60, msg=msg) if cd_state: return try: args = arg_parser.parse_args(msg.text.split(' ', 1)[1], { 'url': str, 'sensitivity_r': float, 'sensitivity_g': float, 'sensitivity_b': float, 'sensitivity_a': float, 'size_percent': float, 'max_y': int, 'pad_y': int, 'reverse': bool, 'hastebin': bool }, strict_escapes=True, strict_quotes=True) except arg_parser.ParserError as e: return f'Error: {e.message}' missing_args = arg_parser.check_required_keys(args, ['url']) if missing_args: return ( f'Error: You are missing the {",".join(missing_args)} ' f'argument{"s" if len(missing_args) > 1 else ""} to run this command.' ) num_defined = sum( [args[f'sensitivity_{i}'] is not Ellipsis for i in 'rgb']) alpha = args['sensitivity_a'] if args[ 'sensitivity_a'] is not Ellipsis else 1 if num_defined == 3: sens: typing.Tuple[float, float, float, float] = (args['sensitivity_r'], args['sensitivity_g'], args['sensitivity_b'], alpha) is_zero = bool(sum([args[f'sensitivity_{i}'] == 0 for i in 'rgba'])) if is_zero: return f'Error: Sensitivity cannot be zero. MEGADANK' elif num_defined == 0: sens = (1, 1, 1, 1) else: return f'Error: you need to define either all sensitivity fields (r, g, b, a) or none.' if args['size_percent'] is not ... and args['max_y'] is not ...: return f'Error: you cannot provide the size percentage and maximum height at the same time.' max_x = 60 if args['size_percent'] is Ellipsis else None max_y = (args['max_y'] if args['max_y'] is not Ellipsis else 60) if args['size_percent'] is Ellipsis else None size_percent = None if args['size_percent'] is Ellipsis else args[ 'size_percent'] img = await braille.download_image(args['url']) img: Image.Image if img.format.lower() != 'gif': img, o = await braille.crop_and_pad_image( True, img, max_x, max_y, '', (60, args['pad_y'] if args['pad_y'] is not Ellipsis else 60), size_percent) o += await braille.to_braille_from_image( img, reverse=True if args['reverse'] is not Ellipsis else False, size_percent=size_percent, max_x=max_x, max_y=max_y, sensitivity=sens, enable_padding=True, pad_size=(60, args['pad_y'] if args['pad_y'] is not Ellipsis else 60), enable_processing=False) else: missing_permissions = main.bot.check_permissions( msg, ['cancer.braille.gif'], enable_local_bypass=False) if missing_permissions: o = 'Note: missing permissions to convert a gif. \n' else: o = '' frame = -1 start_time = time.time() while 1: try: img.seek(frame + 1) except EOFError: break frame += 1 o += f'\nFrame {frame}\n' frame_start = time.time() o += await braille.to_braille_from_image( img.copy(), reverse=True if args['reverse'] is not Ellipsis else False, size_percent=size_percent, max_x=max_x, max_y=max_y, sensitivity=sens, enable_padding=True, pad_size=(60, (args['pad_y'] if args['pad_y'] is not Ellipsis else 60)), enable_processing=True) time_taken = round(time.time() - start_time) frame_time = round(time.time() - frame_start) if frame % self.status_every_frames == 0 and time_taken > self.time_before_status: speed = round(1 / frame_time) main.bot.send( msg.reply( f'@{msg.user}, ppCircle Converted {frame} frames in ' f'{time_taken} seconds, speed: {round(speed)} fps, ' f'eta: {(img.n_frames - frame) * speed} seconds.' )) await asyncio.sleep(0) sendable = ' '.join(o.split('\n')[1:]) if args['hastebin'] is not Ellipsis or len(sendable) > 500: return ( f'{"This braille was too big to be posted." if not args["hastebin"] is not Ellipsis else ""} ' f'Here\'s a link to a hastebin: ' f'{plugin_hastebin.hastebin_addr}' f'{await plugin_hastebin.upload(o)}') else: return sendable
def command_list_blacklisted(msg: twitchirc.ChannelMessage) -> None: ensure_blacklist(msg.channel) main.bot.send( msg.reply( f'@{msg.user}, There are {len(blacklist[msg.channel])} blacklisted commands: ' f'{", ".join(blacklist[msg.channel])}'))
def command_quit(msg: twitchirc.ChannelMessage): bot.send(msg.reply('Quitting.')) bot.stop()
def command_reminder(msg: twitchirc.ChannelMessage): aargs = c_rem_parser.parse_args(msg.text.split(' ')[1:]) if aargs is None or aargs.help: return f'@{msg.user} {c_rem_parser.format_usage()}' # for i in dir(aargs): # if i.startswith('_'): # continue # print(i, getattr(aargs, i, None)) if aargs.for_user: missing_perms = main.bot.check_permissions( msg, ['reminder.reminder.for_other'], enable_local_bypass=True) if missing_perms: return ( f'@{msg.user} Cannot add reminder for other user, you don\'t have the permissions ' f'needed') if aargs.remove: if msg.channel not in reminders: return ( f'@{msg.user} Cannot remove reminders: channel is not registered. ' f'No reminders here.') count = 0 for r in reminders[msg.channel].copy(): if r['user'] == aargs.remove.lower(): count += 1 reminders[msg.channel].remove(r) return f'@{msg.user} removed {count} reminder(s).' if aargs.list: output = '' if msg.channel not in reminders: main.bot.send( msg.reply( f'@{msg.user} Cannot list reminders: channel is not registered. ' f'No reminders here.')) return for r in reminders[msg.channel]: output += f'<{r["text"]!r} on ' \ f'{datetime.datetime.fromtimestamp(r["timestamp"]).strftime("%Y-%M-%d %H:%m:%S")}>, ' output = output[:-2] return f'@{msg.user} List: {output}' if aargs.add: # if not aargs.time: # bot.send(msg.reply(f'@{msg.user} Argument -t/--time is required with -a/--add.')) # return text = ' '.join(aargs.add) seconds = process_time(aargs.time) print(text, seconds) new_timestamp = time.time() + seconds if msg.channel not in reminders: reminders[msg.channel] = [] reminders[msg.channel].append({ 'text': text, 'seconds': seconds, 'timestamp': new_timestamp, 'user': msg.user, 'nr': aargs.nr }) if not aargs.nr: return ( f'@{msg.user} , I will be messaging you in {seconds} seconds ' f'or ({seconds // 3600:.0f} hours, ' f'{seconds % 3600 / 60:.0f} minutes and {seconds % 3600 % 60:.0f} seconds) with ' f'the message {text!r}') else: return ( f'@{msg.user} , I will be messaging you every {seconds} seconds ' f'or ({seconds // 3600:.0f} hours, ' f'{seconds % 3600 / 60:.0f} minutes and {seconds % 3600 % 60:.0f} seconds) with ' f'the message {text!r}')