Exemple #1
0
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:
                return (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])))
            return (f'@{msg.user} Your suggestions: '
                    f'{", ".join([f"{s.id} ({s.nice_state()})" for s in suggestions])}')
Exemple #2
0
 def c_cookie_optin(self, msg: twitchirc.ChannelMessage):
     if msg.user.lower() in self.cookie_optin:
         self.cookie_optin.remove(msg.user.lower())
         plugin_manager.channel_settings[plugin_manager.SettingScope.GLOBAL.name].update()
         with main.session_scope() as session:
             session.add(plugin_manager.channel_settings[plugin_manager.SettingScope.GLOBAL.name])
         return f'@{msg.user} You have been removed from the cookie opt-in list.'
     else:
         self.cookie_optin.append(msg.user.lower())
         plugin_manager.channel_settings[plugin_manager.SettingScope.GLOBAL.name].update()
         with main.session_scope() as session:
             session.add(plugin_manager.channel_settings[plugin_manager.SettingScope.GLOBAL.name])
         return f'@{msg.user} You have been added to the cookie opt-in list.'
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 _post_init(self):
        global blacklists
        # load all entries
        with main.session_scope() as dank_circle:
            blacklists = BlacklistEntry.load_all(dank_circle)

        # initialize middleware
        main.bot.middleware.append(BlacklistMiddleware())
    def command_manage_blacklists(self, msg: twitchirc.ChannelMessage):
        argv = main.delete_spammer_chrs(msg.text).rstrip(' ').split(' ', 1)
        if len(argv) == 1:
            return f'@{msg.user}, {plugin_help.all_help[plugin_help.SECTION_COMMANDS]["plonk"]}'
        text = argv[1]
        kw = self._parse_blacklist_args(text, msg)
        if isinstance(kw, str):
            return kw
        if kw['command'] is None:
            return f'@{msg.user}, No `command:...` provided.'
        if kw['user'] is None:
            return f'@{msg.user}, No `user:...` provided.'
        with main.session_scope() as session:
            if kw['scope'] == 'global':
                targets = main.User.get_by_name(
                    kw['user'], session) if kw['user'] is not True else None

                if targets is None or len(targets) == 1:
                    obj = BlacklistEntry(
                        target=targets[0] if targets is not None else targets,
                        command=kw['command']
                        if kw['command'] is not True else None,
                        channel=None,
                        expires_on=kw['expires'],
                        is_active=True)
                    blacklists.append(obj)
                    session.add(obj)
                elif len(targets) == 0:
                    return f'@{msg.user} Failed to find user: {kw["user"]}'
                else:
                    return f'@{msg.user} Found multiple users possible with name {kw["user"]}'
            else:
                for ch in kw['scope']:
                    targets = main.User.get_by_name(
                        kw['user'],
                        session) if kw['user'] is not True else None
                    channels = main.User.get_by_name(ch, session)
                    if len(channels) == 1:
                        if targets is None or len(targets) == 1:
                            obj = BlacklistEntry(
                                target=targets[0]
                                if targets is not None else targets,
                                command=kw['command']
                                if kw['command'] is not True else None,
                                channel=channels[0],
                                expires_on=kw['expires'],
                                is_active=True)
                            blacklists.append(obj)
                            session.add(obj)
                        elif len(targets) == 0:
                            return f'@{msg.user} Failed to find user: {kw["user"]}'
                        else:
                            return f'@{msg.user} Found multiple users possible with name {kw["user"]}'
                    elif len(channels) == 0:
                        return f'@{msg.user} Failed to find channel: {ch}'
                    elif len(channels) > 1:
                        return f'@{msg.user} Found multiple channels possible with name {ch}'
        return f'@{msg.user}, Added blacklist for command {kw["command"]} with scope {kw["scope"]} for {kw["user"]}'
    def _mailbox_whatif(self, argv, msg):
        # "!mailbox" "whatif" "ID SCORE SCORE SCORE"
        #                 [2:]
        args = argv[-1].split(' ', 1)
        if len(args) != 2:
            return f'@{msg.user}, Usage: {argv[0]} {argv[1]} ID SCORE SCORE SCORE'
        id_ = args[0]
        matches = args[1]
        if not id_.isnumeric():
            return f'@{msg.user}, Game ID must be a number.'

        with main.session_scope() as session:
            try:
                game = session.query(self.MailboxGame).filter(
                    self.MailboxGame.id == int(id_)).one()
            except sqlalchemy.exc.NoResultFound:
                return f'@{msg.user}, Unable to fetch game ID {int(id_)!r}'

        match = GUESS_PATTERN.match(matches)
        if not match:
            return (
                f'@{msg.user}, Could not extract scores from your message. '
                f'Usage: {argv[0]} {argv[1]} ID SCORE SCORE SCORE')

        good_value = [int(i.rstrip(', -')) for i in match.groups()]

        settings = game.settings
        msgs = []
        for i in game.guesses:
            platform, channel, user, guess = i.split(' ', 3)
            msg = main.StandardizedMessage(guess, user.strip('<>'), channel,
                                           main.Platform[platform.strip('[]')])
            msgs.append(msg)
        possible_guesses = msgs
        print('possible', possible_guesses)
        good_guesses = self._find_good_guesses(possible_guesses, good_value,
                                               settings)
        print('good', good_guesses)
        best = self._best_guess(settings, good_guesses)
        print('best', best)
        print(settings)

        if len(best) == 0:
            return f'No matching guesses.'

        else:
            message = f'Best guesses would be {self._nice_best_guesses(best)}.'
            if len(message) > 500:
                msgs = []
                for i in range(1, math.ceil(len(message) / 500) + 1):
                    msgs.append(message[(i - 1) * 500:i * 500])
                return msgs
            return message
Exemple #7
0
def command_suggest(msg: twitchirc.ChannelMessage):
    cd_state = main.do_cooldown('suggest', msg, global_cooldown=0, local_cooldown=30)
    if cd_state:
        return
    t = main.delete_spammer_chrs(msg.text).rstrip(' ').split(' ', 1)
    if len(t) == 1:
        return f'@{msg.user}, Usage: suggest <text...>'

    s = Suggestion(author=main.User.get_by_message(msg), text=t[1], state=Suggestion.SuggestionState.new,
                   notes='<no notes>')
    with main.session_scope() as session:
        session.add(s)
    return f'@{msg.user} Suggestion saved, hopefully. ID: {s.id}'
 def _periodically_expire(self):
     while 1:
         time.sleep(30)  # don't need to flush this right away.
         to_expire = []
         while 1:
             try:
                 o = expire_queue.get_nowait()
                 to_expire.append(o)
             except queue.Empty:
                 break
         if to_expire:
             with main.session_scope() as session, self.expire_lock:
                 for e in to_expire:
                     e: BlacklistEntry
                     session.delete(e)
 def _fetch_suggestions(rwq):
     print(f'fetch {user_id} p {page_num}')
     with main.session_scope() as session:
         suggestions = (session.query(Suggestion).filter(
             Suggestion.author_alias == user_id).offset(
                 page_num * PAGE_SIZE).limit(PAGE_SIZE).all())
         rwq.put(
             plugin_ipc.format_json({
                 'type':
                 'suggestion_list',
                 'page':
                 page_num,
                 'page_size':
                 PAGE_SIZE,
                 'data': [{
                     'text': suggestion.text,
                     'notes': suggestion.notes,
                     'state': suggestion.state.name,
                     'id': suggestion.id
                 } for suggestion in suggestions]
             }))
 def _fetch_suggestions(rwq):
     print(f'fetch suggestion {suggestion_id}')
     with main.session_scope() as session:
         suggestion = (session.query(Suggestion).filter(
             Suggestion.id == suggestion_id).first())
         rwq.put(
             plugin_ipc.format_json({
                 'type':
                 'suggestion_list',
                 'page':
                 0,
                 'page_size':
                 1,
                 'data': ([{
                     'text': suggestion.text,
                     'notes': suggestion.notes,
                     'state': suggestion.state.name,
                     'id': suggestion.id,
                     'author': {
                         'name': suggestion.author.last_known_username,
                         'alias': suggestion.author.id
                     }
                 }] if suggestion is not None else [])
             }))
Exemple #11
0
def _init_settings():
    global channel_settings_session

    channel_settings_session = main.Session()
    channel_settings_session.flush = lambda *a, **kw: print(
        'CS: Flushing a readonly session.')
    print('Load channel settings.')
    with main.session_scope() as write_session:
        print('Loading existing channel settings...')
        for i in ChannelSettings.load_all(write_session):
            i.fill_defaults(forced=False)
            i.update()
            if i.channel_alias == -1:  # global settings.
                channel_settings[SettingScope.GLOBAL.name] = i
            else:
                channel_settings[i.channel.last_known_username] = i
        print('OK')
        print('Creating missing channel settings...')
        for j in main.bot.channels_connected + [SettingScope.GLOBAL.name]:
            if j in channel_settings:
                continue
            cs = ChannelSettings()
            if j == SettingScope.GLOBAL.name:
                cs.channel_alias = -1
                write_session.add(cs)
                continue

            channels = main.User.get_by_name(j.lower(), write_session)
            if len(channels) != 1:
                continue
            cs.channel = channels[0]
            write_session.add(cs)
            channel_settings[channels[0].last_known_username] = cs
        print('OK')
        print('Commit.')
    print(f'Done. Loaded {len(channel_settings)} channel settings entries.')
    def _mailbox_draw(self, argv, msg):
        if msg.channel not in self.mailbox_games:
            return f'@{msg.user}, Cannot draw a winner from mailbox minigame, there is none running. FeelsBadMan'
        settings = self.mailbox_games[msg.channel]
        if settings.get('timeout_reason'):
            return (
                f'@{msg.user}, There is no minigame running, however there are automatic timeouts set up. '
                f'Use "{argv[0]} cancel" to stop timing out.')
        action_argv = ' '.join(argv[2:])

        show_closed = False
        if 'end_time' not in settings:
            settings['end_time'] = time.time()
            show_closed = True

        match = GUESS_PATTERN.match(action_argv)
        if not match:
            return (
                f'@{msg.user}, Bad winning value, it should be formatted like "30 32 29" '
                f'{"The game has been automatically closed and is waiting for valid scores." if show_closed else ""}'
            )

        good_value = [int(i.rstrip(', -')) for i in match.groups()]

        msgs = plugin_chat_cache.find_messages(
            msg.channel,
            min_timestamp=settings['start_time'],
            max_timestamp=settings['end_time'])

        possible_guesses = list(
            filter(lambda m: bool(GUESS_PATTERN.match(m.text)), msgs))

        print('possible', possible_guesses)
        good_guesses = self._find_good_guesses(possible_guesses, good_value,
                                               settings)
        print('good', good_guesses)
        best = self._best_guess(settings, good_guesses)
        print('best', best)
        print(settings)
        failed_save = False

        # noinspection PyBroadException
        try:
            with main.session_scope() as session:
                game_obj = self.MailboxGame(
                    main.User.get_by_twitch_id(int(msg.flags['room-id']),
                                               session), settings, best.copy(),
                    good_value, possible_guesses)
                session.add(game_obj)
        except Exception:
            failed_save = True
            traceback.print_exc()

        del self.mailbox_games[msg.channel]
        db_notif = (
            f'{"Failed to save to database. " if failed_save else ""}ID: {game_obj.id if not failed_save else "n/a"}'
        )
        if len(best) == 0:
            return (
                f'{"(automatically closed the game)" if show_closed else ""}'
                f'No one guessed {"even remotely " if settings["find_best"] else ""}right. {db_notif}'
            )

        else:
            message = (
                f'{"(automatically closed the game)" if show_closed else ""}'
                f'Best guesses are {self._nice_best_guesses(best)}. {db_notif}'
            )
            if len(message) > 500:
                msgs = []
                for i in range(1, math.ceil(len(message) / 500) + 1):
                    msgs.append(message[(i - 1) * 500:i * 500])
                return msgs
            return message
 def reload_blacklist(self):
     global blacklists
     with self.expire_lock:  # don't expire black lists while reloading
         with main.session_scope() as dank_circle:
             blacklists = BlacklistEntry.load_all(dank_circle)
Exemple #14
0
    def command_manage_blacklists(self, msg: twitchirc.ChannelMessage):
        argv = main.delete_spammer_chrs(msg.text).rstrip(' ').split(' ', 1)
        if len(argv) == 1:
            return f'@{msg.user}, {plugin_help.all_help[plugin_help.SECTION_COMMANDS]["plonk"]}'
        text = argv[1]
        try:
            kw = arg_parser.parse_args(text, {
                'scope': str,
                'user': str,
                'command': str,
                'expires': datetime.timedelta
            },
                                       defaults={
                                           'scope': None,
                                           'user': None,
                                           'command': None,
                                           'expires': None
                                       })
        except arg_parser.ParserError as e:
            return e.message

        if kw['command'] is None:
            return f'@{msg.user}, No `command:...` provided.'
        if kw['user'] is None:
            return f'@{msg.user}, No `user:...` provided.'

        kw['user'] = kw['user'].lower()
        if kw['user'] == 'everyone':
            kw['user'] = True

        kw['scope'] = kw['scope'].lower().strip('#')
        if kw['scope'] != 'global':
            sc = []
            for ch in kw['scope'].split(','):
                ch = ch.lstrip('#').lower()
                if ch not in main.bot.channels_connected:
                    return f'@{msg.user}, Invalid `scope`: {kw["scope"]!r}, no such channel.'
                sc.append(ch)
            kw['scope'] = sc
        if kw['command'].lower() == 'all':
            kw['command'] = True
        else:
            cmd = None
            for i in main.bot.commands:
                i: main.Command
                if i.chat_command.lower(
                ) == kw['command'] or kw['command'] in i.aliases:
                    cmd = i.chat_command
            if cmd is None:
                return f'@{msg.user}, Invalid `command`: {kw["command"]!r}. No such command exists.'
            else:
                kw['command'] = cmd
            del cmd

        if kw['expires']:
            kw['expires'] = datetime.datetime.now() + kw['expires']

        with main.session_scope() as session:
            if kw['scope'] == 'global':
                targets = main.User.get_by_name(
                    kw['user'], session) if kw['user'] is not True else None

                if targets is None or len(targets) == 1:
                    obj = BlacklistEntry(
                        target=targets[0] if targets is not None else targets,
                        command=kw['command']
                        if kw['command'] is not True else None,
                        channel=None,
                        expires_on=kw['expires'],
                        is_active=True)
                    blacklists.append(obj)
                    session.add(obj)
                elif len(targets) == 0:
                    return f'@{msg.user} Failed to find user: {kw["user"]}'
                else:
                    return f'@{msg.user} Found multiple users possible with name {kw["user"]}'
            else:
                for ch in kw['scope']:
                    targets = main.User.get_by_name(
                        kw['user'],
                        session) if kw['user'] is not True else None
                    channels = main.User.get_by_name(ch, session)
                    if len(channels) == 1:
                        if targets is None or len(targets) == 1:
                            obj = BlacklistEntry(
                                target=targets[0]
                                if targets is not None else targets,
                                command=kw['command']
                                if kw['command'] is not True else None,
                                channel=channels[0],
                                expires_on=kw['expires'],
                                is_active=True)
                            blacklists.append(obj)
                            session.add(obj)
                        elif len(targets) == 0:
                            return f'@{msg.user} Failed to find user: {kw["user"]}'
                        else:
                            return f'@{msg.user} Found multiple users possible with name {kw["user"]}'
                    elif len(channels) == 0:
                        return f'@{msg.user} Failed to find channel: {ch}'
                    elif len(channels) > 1:
                        return f'@{msg.user} Found multiple channels possible with name {ch}'
        return f'@{msg.user}, Added blacklist for command {kw["command"]} with scope {kw["scope"]} for {kw["user"]}'
def _init():
    log('debug', 'Load ban phrases.')
    with main.session_scope() as s:
        for i in BanPhrase.load_all(s):
            ban_phrases.append(i)
    log('debug', f'Done. Loaded {len(ban_phrases)} ban phrases.')