Esempio n. 1
0
    def start_quest(self):
        HandlerManager.add_handler('on_message', self.on_message)

        redis = RedisManager.get()

        self.load_progress(redis=redis)
        self.load_data(redis=redis)
Esempio n. 2
0
    def command_start(self, **options):
        bot = options['bot']
        source = options['source']
        message = options['message']

        if self.trivia_running:
            bot.safe_me('{}, a trivia is already running'.format(source.username_raw))
            return

        self.trivia_running = True
        self.job.resume()

        try:
            self.point_bounty = int(message)
            if self.point_bounty < 0:
                self.point_bounty = 0
            elif self.point_bounty > 50:
                self.point_bounty = 50
        except:
            self.point_bounty = self.settings['default_point_bounty']

        if self.point_bounty > 0:
            bot.safe_me('The trivia has started! {} points for each right answer!'.format(self.point_bounty))
        else:
            bot.safe_me('The trivia has started!')

        HandlerManager.add_handler('on_message', self.on_message)
Esempio n. 3
0
    def stop_quest(self):
        HandlerManager.remove_handler('on_user_win_hs_bet', self.on_user_win_hs_bet)

        redis = RedisManager.get()

        self.reset_progress(redis=redis)
        redis.delete(self.hsbet_points_key)
Esempio n. 4
0
    def stop_quest(self):
        HandlerManager.remove_handler('on_duel_complete', self.on_duel_complete)

        redis = RedisManager.get()

        self.reset_progress(redis=redis)
        redis.delete(self.points_required_key)
Esempio n. 5
0
    def create_stream(self, status):
        log.info('Attempting to create a stream!')
        with DBManager.create_session_scope(expire_on_commit=False) as db_session:
            stream_chunk = db_session.query(StreamChunk).filter_by(broadcast_id=status['broadcast_id']).one_or_none()
            new_stream = False
            if stream_chunk is not None:
                stream = stream_chunk.stream
            else:
                log.info('checking if there is an active stream already')
                stream = db_session.query(Stream).filter_by(ended=False).order_by(Stream.stream_start.desc()).first()
                new_stream = stream is None

                if new_stream:
                    log.info('No active stream, create new!')
                    stream = Stream(status['created_at'],
                            title=status['title'])
                    db_session.add(stream)
                    db_session.commit()
                    log.info('Successfully added stream!')
                stream_chunk = StreamChunk(stream, status['broadcast_id'], status['created_at'])
                db_session.add(stream_chunk)
                db_session.commit()
                stream.stream_chunks.append(stream_chunk)
                log.info('Created stream chunk')

            self.current_stream = stream
            self.current_stream_chunk = stream_chunk
            db_session.expunge_all()

            if new_stream:
                HandlerManager.trigger('on_stream_start', stop_on_false=False)

            log.info('Successfully created a stream')
Esempio n. 6
0
    def stop_quest(self):
        HandlerManager.remove_handler('on_message', self.on_message)

        redis = RedisManager.get()

        self.reset_progress(redis=redis)
        redis.delete(self.current_emote_key)
Esempio n. 7
0
    def on_usernotice(self, source, message, tags):
        if 'msg-id' not in tags or 'msg-param-months' not in tags:
            return

        if tags['msg-id'] == 'resub':
            num_months = int(tags['msg-param-months'])
            self.on_resub(source, num_months)
            HandlerManager.trigger('on_user_resub', source, num_months)
Esempio n. 8
0
File: bot.py Progetto: jardg/pajbot
    def commit_all(self):
        log.info('Commiting all...')
        for key, manager in self.commitable.items():
            log.info('Commiting {0}'.format(key))
            manager.commit()
            log.info('Done with {0}'.format(key))
        log.info('ok!')

        HandlerManager.trigger('on_commit', stop_on_false=False)
Esempio n. 9
0
    def start_quest(self):
        HandlerManager.add_handler('on_user_win_hs_bet', self.on_user_win_hs_bet)

        redis = RedisManager.get()

        self.load_progress(redis=redis)
        self.load_data(redis=redis)

        self.LIMIT = self.hsbet_points_required
Esempio n. 10
0
    def base_paid_timeout(self, bot, source, message, _time, _cost):
        if message is None or len(message) == 0:
            return False

        target = message.split(' ')[0]
        if len(target) < 2:
            return False

        with bot.users.find_context(target) as victim:
            if victim is None:
                bot.whisper(source.username, 'This user does not exist FailFish')
                return False

            if victim.last_active is None or (datetime.datetime.now() - victim._last_active).total_seconds() > 10 * 60:
                bot.whisper(source.username, 'This user has not been active in chat within the last 10 minutes.')
                return False

            """
            if victim == source:
                bot.whisper(source.username, 'You can\'t timeout yourself FailFish')
                return False
                """

            if victim.moderator is True:
                bot.whisper(source.username, 'This person has mod privileges, timeouting this person is not worth it.')
                return False

            if victim.level >= self.settings['bypass_level']:
                bot.whisper(source.username, 'This person\'s user level is too high, you can\'t timeout this person.')
                return False

            now = datetime.datetime.now()
            if victim.timed_out is True and victim.timeout_end > now:
                victim.timeout_end += datetime.timedelta(seconds=_time)
                bot.whisper(victim.username, '{victim.username}, you were timed out for an additional {time} seconds by {source.username}'.format(
                    victim=victim,
                    source=source,
                    time=_time))
                bot.whisper(source.username, 'You just used {0} points to time out {1} for an additional {2} seconds.'.format(_cost, victim.username, _time))
                num_seconds = int((victim.timeout_end - now).total_seconds())
                bot._timeout(victim.username, num_seconds, reason='Timed out by {}'.format(source.username_raw))
            # songs = session.query(PleblistSong, func.count(PleblistSong.song_info).label('total')).group_by(PleblistSong.youtube_id).order_by('total DESC')
            else:
                bot.whisper(source.username, 'You just used {0} points to time out {1} for {2} seconds.'.format(_cost, victim.username, _time))
                bot.whisper(victim.username, '{0} just timed you out for {1} seconds. /w {2} !$unbanme to unban yourself for points forsenMoney'.format(source.username, _time, bot.nickname))
                bot._timeout(victim.username, _time, reason='Timed out by {}'.format(source.username_raw))
                victim.timed_out = True
                victim.timeout_start = now
                victim.timeout_end = now + datetime.timedelta(seconds=_time)

            if self.settings['show_on_clr']:
                payload = {'user': source.username, 'victim': victim.username}
                bot.websocket_manager.emit('timeout', payload)

            HandlerManager.trigger('on_paid_timeout',
                    source, victim, _cost,
                    stop_on_false=False)
Esempio n. 11
0
    def disable(self, bot):
        HandlerManager.remove_handler('on_message', self.on_message)
        HandlerManager.remove_handler('on_commit', self.on_commit)

        if self.db_session is not None:
            self.db_session.commit()
            self.db_session.close()
            self.db_session = None
            self.links = {}
Esempio n. 12
0
    def on_usernotice(self, source, message, tags):
        if 'msg-id' not in tags or 'msg-param-months' not in tags:
            return

        if tags['msg-id'] == 'resub':
            # TODO: Should we check room id with streamer ID here? Maybe that's for pajbot2 instead
            num_months = int(tags['msg-param-months'])
            self.on_resub(source, num_months)
            HandlerManager.trigger('on_user_resub', source, num_months)
Esempio n. 13
0
    def start_quest(self):
        HandlerManager.add_handler('on_duel_complete', self.on_duel_complete)

        redis = RedisManager.get()

        self.load_progress(redis=redis)
        self.load_data(redis=redis)

        self.LIMIT = self.points_required
Esempio n. 14
0
 def on_message(self, source, message, emotes, whisper, urls, event):
     if whisper is False and source.username in self.valid_usernames:
         # Did twitchnotify tell us about a new sub?
         m = self.new_sub_regex.search(message)
         if m:
             username = m.group(1)
             with UserManager.get().get_user_context(username) as user:
                 self.on_new_sub(user)
                 HandlerManager.trigger('on_user_sub', user)
Esempio n. 15
0
    def enable(self, bot):
        HandlerManager.add_handler('on_message', self.on_message, priority=200)
        HandlerManager.add_handler('on_commit', self.on_commit)

        if self.db_session is not None:
            self.db_session.commit()
            self.db_session.close()
            self.db_session = None
            self.links = {}
        self.db_session = DBManager.create_session()
Esempio n. 16
0
    def command_stop(self, **options):
        bot = options['bot']
        source = options['source']

        if not self.trivia_running:
            bot.safe_me('{}, no trivia is active right now'.format(source.username_raw))
            return

        self.job.pause()
        self.trivia_running = False
        self.step_end()

        bot.safe_me('The trivia has been stopped.')

        HandlerManager.remove_handler('on_message', self.on_message)
Esempio n. 17
0
    def parse_message(self, msg_raw, source, event, tags={}, whisper=False):
        msg_lower = msg_raw.lower()

        emote_tag = None

        for tag in tags:
            if tag['key'] == 'subscriber' and event.target == self.channel:
                source.subscriber = tag['value'] == '1'
            elif tag['key'] == 'emotes' and tag['value']:
                emote_tag = tag['value']
            elif tag['key'] == 'display-name' and tag['value']:
                source.username_raw = tag['value']
            elif tag['key'] == 'user-type':
                source.moderator = tag['value'] == 'mod' or source.username == self.streamer

        # source.num_lines += 1

        if source is None:
            log.error('No valid user passed to parse_message')
            return False

        if source.banned:
            self.ban(source.username)
            return False

        # If a user types when timed out, we assume he's been unbanned for a good reason and remove his flag.
        if source.timed_out is True:
            source.timed_out = False

        # Parse emotes in the message
        message_emotes = self.emotes.parse_message_twitch_emotes(source, msg_raw, emote_tag, whisper)

        urls = self.find_unique_urls(msg_raw)

        log.debug('{2}{0}: {1}'.format(source.username, msg_raw, '<w>' if whisper else ''))

        res = HandlerManager.trigger('on_message',
                source, msg_raw, message_emotes, whisper, urls, event,
                stop_on_false=True)
        if res is False:
            return False

        source.last_seen = datetime.datetime.now()
        source.last_active = datetime.datetime.now()

        if source.ignored:
            return False

        if msg_lower[:1] == '!':
            msg_lower_parts = msg_lower.split(' ')
            trigger = msg_lower_parts[0][1:]
            msg_raw_parts = msg_raw.split(' ')
            remaining_message = ' '.join(msg_raw_parts[1:]) if len(msg_raw_parts) > 1 else None
            if trigger in self.commands:
                command = self.commands[trigger]
                extra_args = {
                        'emotes': message_emotes,
                        'trigger': trigger,
                        }
                command.run(self, source, remaining_message, event=event, args=extra_args, whisper=whisper)
Esempio n. 18
0
File: bot.py Progetto: jardg/pajbot
    def on_usernotice(self, chatconn, event):
        # We use .lower() in case twitch ever starts sending non-lowercased usernames
        tags = {}
        for d in event.tags:
            tags[d['key']] = d['value']

        if 'login' not in tags:
            return

        username = tags['login']

        with self.users.get_user_context(username) as source:
            msg = ''
            if len(event.arguments) > 0:
                msg = event.arguments[0]
            HandlerManager.trigger('on_usernotice',
                    source, msg, tags)
Esempio n. 19
0
    def go_offline(self):
        with DBManager.create_session_scope(expire_on_commit=False) as db_session:
            self.current_stream.ended = True
            self.current_stream.stream_end = self.first_offline
            self.current_stream_chunk.chunk_end = self.first_offline

            db_session.add(self.current_stream)
            db_session.add(self.current_stream_chunk)

            db_session.commit()

            db_session.expunge_all()

        self.last_stream = self.current_stream
        self.current_stream = None
        self.current_stream_chunk = None

        HandlerManager.trigger('on_stream_stop', stop_on_false=False)
Esempio n. 20
0
    def end_raffle(self):
        if not self.raffle_running:
            return False

        self.raffle_running = False

        if len(self.raffle_users) == 0:
            self.bot.me('Wow, no one joined the raffle DansGame')
            return False

        winner = random.choice(self.raffle_users)

        self.raffle_users = []

        if self.settings['show_on_clr']:
            self.bot.websocket_manager.emit('notification', {'message': '{} won {} points in the raffle!'.format(winner.username_raw, self.raffle_points)})
            self.bot.me('The raffle has finished! {0} won {1} points! PogChamp'.format(winner.username_raw, self.raffle_points))

        winner.points += self.raffle_points

        winner.save()

        HandlerManager.trigger('on_raffle_win', winner, self.raffle_points)
Esempio n. 21
0
    def on_pubmsg(self, chatconn, event):
        if event.source.user == self.nickname:
            return False

        username = event.source.user.lower()

        # We use .lower() in case twitch ever starts sending non-lowercased usernames
        with self.users.get_user_context(username) as source:
            res = HandlerManager.trigger('on_pubmsg',
                    source, event.arguments[0],
                    stop_on_false=True)
            if res is False:
                return False

            self.parse_message(event.arguments[0], source, event, tags=event.tags)
Esempio n. 22
0
 def do_tick():
     HandlerManager.trigger("on_tick")
Esempio n. 23
0
 def disable(self, bot):
     HandlerManager.remove_handler('on_message', self.on_message)
     HandlerManager.remove_handler('on_usernotice', self.on_usernotice)
Esempio n. 24
0
 def enable(self, bot):
     self.checkjob.resume()
     self.checkPaused = False
     HandlerManager.add_handler("on_quit", self.stop_trivia)
Esempio n. 25
0
 def disable(self, bot):
     self.checkjob.pause()
     self.checkPaused = True
     HandlerManager.remove_handler("on_quit", self.stop_trivia)
Esempio n. 26
0
 def enable(self, bot):
     HandlerManager.add_handler("on_message", self.on_message, priority=150, run_if_propagation_stopped=True)
Esempio n. 27
0
    def __init__(self, config, args=None):
        # Load various configuration variables from the given config object
        # The config object that should be passed through should
        # come from pajbot.utils.load_config
        self.load_config(config)

        # Update the database scheme if necessary using alembic
        # In case of errors, i.e. if the database is out of sync or the alembic
        # binary can't be called, we will shut down the bot.
        pajbot.utils.alembic_upgrade()

        # Actions in this queue are run in a separate thread.
        # This means actions should NOT access any database-related stuff.
        self.action_queue = ActionQueue()
        self.action_queue.start()

        self.reactor = irc.client.Reactor(self.on_connect)
        self.start_time = datetime.datetime.now()
        ActionParser.bot = self

        HandlerManager.init_handlers()

        self.socket_manager = SocketManager(self)
        self.stream_manager = StreamManager(self)

        StreamHelper.init_bot(self, self.stream_manager)
        ScheduleManager.init()

        self.users = UserManager()
        self.decks = DeckManager()
        self.module_manager = ModuleManager(self.socket_manager,
                                            bot=self).load()
        self.commands = CommandManager(socket_manager=self.socket_manager,
                                       module_manager=self.module_manager,
                                       bot=self).load()
        self.filters = FilterManager().reload()
        self.banphrase_manager = BanphraseManager(self).load()
        self.timer_manager = TimerManager(self).load()
        self.kvi = KVIManager()
        self.emotes = EmoteManager(self)
        self.twitter_manager = TwitterManager(self)

        HandlerManager.trigger('on_managers_loaded')

        # Reloadable managers
        self.reloadable = {
            'filters': self.filters,
        }

        # Commitable managers
        self.commitable = {
            'commands': self.commands,
            'filters': self.filters,
            'banphrases': self.banphrase_manager,
        }

        self.execute_every(10 * 60, self.commit_all)

        try:
            self.admin = self.config['main']['admin']
        except KeyError:
            log.warning(
                'No admin user specified. See the [main] section in config.example.ini for its usage.'
            )
        if self.admin:
            with self.users.get_user_context(self.admin) as user:
                user.level = 2000

        self.parse_version()

        relay_host = self.config['main'].get('relay_host', None)
        relay_password = self.config['main'].get('relay_password', None)
        if relay_host is None or relay_password is None:
            self.irc = MultiIRCManager(self)
        else:
            self.irc = SingleIRCManager(self)

        self.reactor.add_global_handler('all_events', self.irc._dispatcher,
                                        -10)

        twitch_client_id = None
        twitch_oauth = None
        if 'twitchapi' in self.config:
            twitch_client_id = self.config['twitchapi'].get('client_id', None)
            twitch_oauth = self.config['twitchapi'].get('oauth', None)

        # A client ID is required for the bot to work properly now, give an error for now
        if twitch_client_id is None:
            log.error(
                'MISSING CLIENT ID, SET "client_id" VALUE UNDER [twitchapi] SECTION IN CONFIG FILE'
            )

        self.twitchapi = TwitchAPI(twitch_client_id, twitch_oauth)

        self.data = {}
        self.data_cb = {}
        self.url_regex = re.compile(self.url_regex_str, re.IGNORECASE)

        self.data['broadcaster'] = self.streamer
        self.data['version'] = self.version
        self.data_cb['status_length'] = self.c_status_length
        self.data_cb['stream_status'] = self.c_stream_status
        self.data_cb['bot_uptime'] = self.c_uptime
        self.data_cb['current_time'] = self.c_current_time

        self.silent = True if args.silent else self.silent

        if self.silent:
            log.info('Silent mode enabled')
        """
        For actions that need to access the main thread,
        we can use the mainthread_queue.
        """
        self.mainthread_queue = ActionQueue()
        self.execute_every(1, self.mainthread_queue.parse_action)

        self.websocket_manager = WebSocketManager(self)

        try:
            if self.config['twitchapi']['update_subscribers'] == '1':
                self.execute_every(30 * 60, self.action_queue.add,
                                   (self.update_subscribers_stage1, ))
        except:
            pass

        # XXX: TEMPORARY UGLY CODE
        HandlerManager.add_handler('on_user_gain_tokens',
                                   self.on_user_gain_tokens)
        HandlerManager.add_handler('send_whisper', self.whisper)
Esempio n. 28
0
 def enable(self, bot):
     HandlerManager.add_handler("on_message", self.on_message)
Esempio n. 29
0
    def start_quest(self):
        HandlerManager.add_handler('on_user_win_hs_bet', self.on_user_win_hs_bet)

        redis = RedisManager.get()

        self.load_progress(redis=redis)
Esempio n. 30
0
 def enable(self, bot):
     HandlerManager.add_handler('on_pubmsg', self.on_pubmsg)
     self.bot = bot
Esempio n. 31
0
    def __init__(self, config, args):
        self.config = config
        self.args = args

        self.last_ping = utils.now()
        self.last_pong = utils.now()

        ScheduleManager.init()

        DBManager.init(self.config["main"]["db"])

        # redis
        redis_options = {}
        if "redis" in config:
            redis_options = dict(config.items("redis"))
        RedisManager.init(**redis_options)
        wait_for_redis_data_loaded(RedisManager.get())

        self.nickname = config["main"].get("nickname", "pajbot")

        if config["main"].getboolean("verified", False):
            TMI.promote_to_verified()

        # phrases
        self.phrases = {
            "welcome": ["{nickname} {version} running! HeyGuys"],
            "quit": ["{nickname} {version} shutting down... BibleThump"],
        }
        if "phrases" in config:
            phrases = config["phrases"]
            if "welcome" in phrases:
                self.phrases["welcome"] = phrases["welcome"].splitlines()
            if "quit" in phrases:
                self.phrases["quit"] = phrases["quit"].splitlines()

        # streamer
        if "streamer" in config["main"]:
            self.streamer = config["main"]["streamer"]
            self.channel = "#" + self.streamer
        elif "target" in config["main"]:
            self.channel = config["main"]["target"]
            self.streamer = self.channel[1:]

        self.bot_domain = self.config["web"]["domain"]
        log.debug("Loaded config")

        # do this earlier since schema upgrade can depend on the helix api
        self.api_client_credentials = ClientCredentials(
            self.config["twitchapi"]["client_id"],
            self.config["twitchapi"]["client_secret"],
            self.config["twitchapi"]["redirect_uri"],
        )

        HandlerManager.init_handlers()

        self.twitch_id_api = TwitchIDAPI(self.api_client_credentials)
        self.twitch_tmi_api = TwitchTMIAPI()
        self.app_token_manager = AppAccessTokenManager(self.twitch_id_api,
                                                       RedisManager.get())

        self.twitch_helix_api = TwitchHelixAPI(RedisManager.get(),
                                               self.app_token_manager)
        self.twitch_v5_api = TwitchKrakenV5API(self.api_client_credentials,
                                               RedisManager.get())
        self.spotify_api = None
        self.spotify_token_manager = None
        if ("client_id" in config["spotify"]
                and "client_secret" in config["spotify"]
                and "redirect_uri" in config["spotify"]
                and "user_id" in config["spotify"]):
            if (config["spotify"]["client_id"] != ""
                    and config["spotify"]["client_secret"] != ""
                    and config["spotify"]["redirect_uri"] != ""
                    and config["spotify"]["user_id"] != ""):
                self.spotify_api = SpotifyApi(
                    RedisManager.get(),
                    config["spotify"]["client_id"],
                    config["spotify"]["client_secret"],
                    config["spotify"]["redirect_uri"],
                )
                self.spotify_token_manager = SpotifyAccessTokenManager(
                    self.spotify_api, RedisManager.get(),
                    config["spotify"]["user_id"])
                log.info("Spotify Loaded")

        self.streamlabs_api = None
        if "socket_access_token" in config["streamlabs"]:
            socket_access_token = config["streamlabs"]["socket_access_token"]
            if socket_access_token is not None and socket_access_token != "":
                self.streamlabs_api = StreamLabsAPI(socket_access_token)

        self.bot_user_id = self.twitch_helix_api.get_user_id(self.nickname)
        if self.bot_user_id is None:
            raise ValueError(
                "The bot login name you entered under [main] does not exist on twitch."
            )

        self.streamer_user_id = self.twitch_helix_api.get_user_id(
            self.streamer)
        if self.streamer_user_id is None:
            raise ValueError(
                "The streamer login name you entered under [main] does not exist on twitch."
            )

        self.pubsub_api = PubSubAPI(
            self,
            UserAccessTokenManager(api=self.twitch_id_api,
                                   redis=RedisManager.get(),
                                   username=self.streamer,
                                   user_id=self.streamer_user_id),
        )

        StreamHelper.init_streamer(self.streamer, self.streamer_user_id)

        # SQL migrations
        with DBManager.create_dbapi_connection_scope() as sql_conn:
            sql_migratable = DatabaseMigratable(sql_conn)
            sql_migration = Migration(sql_migratable,
                                      pajbot.migration_revisions.db, self)
            sql_migration.run()

        # Redis migrations
        redis_migratable = RedisMigratable(redis_options=redis_options,
                                           namespace=self.streamer)
        redis_migration = Migration(redis_migratable,
                                    pajbot.migration_revisions.redis, self)
        redis_migration.run()

        # Thread pool executor for async actions
        self.action_queue = ActionQueue()

        # refresh points_rank and num_lines_rank regularly
        UserRanksRefreshManager.start(self.action_queue)

        self.reactor = irc.client.Reactor(self.on_connect)
        # SafeDefaultScheduler makes the bot not exit on exception in the main thread
        # e.g. on actions via bot.execute_now, etc.
        self.reactor.scheduler_class = SafeDefaultScheduler
        self.reactor.scheduler = SafeDefaultScheduler()

        self.start_time = utils.now()
        ActionParser.bot = self

        self.socket_manager = SocketManager(self.streamer, self.execute_now)
        self.stream_manager = StreamManager(self)
        StreamHelper.init_stream_manager(self.stream_manager)

        self.decks = DeckManager()
        self.banphrase_manager = BanphraseManager(self).load()
        self.timer_manager = TimerManager(self).load()
        self.kvi = KVIManager()

        self.websocket_manager = WebSocketManager(self)

        # bot access token
        if "password" in self.config["main"]:
            log.warning(
                "DEPRECATED - Using bot password/oauth token from file. "
                "You should authenticate in web gui using route /bot_login "
                "and remove password from config file")

            access_token = self.config["main"]["password"]

            if access_token.startswith("oauth:"):
                access_token = access_token[6:]

            self.bot_token_manager = UserAccessTokenManager(
                api=None,
                redis=None,
                username=self.nickname,
                user_id=self.bot_user_id,
                token=UserAccessToken.from_implicit_auth_flow_token(
                    access_token),
            )
        else:
            self.bot_token_manager = UserAccessTokenManager(
                api=self.twitch_id_api,
                redis=RedisManager.get(),
                username=self.nickname,
                user_id=self.bot_user_id)

        self.songrequest_manager = SongrequestManager(self)
        self.songrequest_websocket_manager = SongRequestWebSocketManager(self)
        self.emote_manager = EmoteManager(self.twitch_v5_api,
                                          self.action_queue)
        self.epm_manager = EpmManager()
        self.ecount_manager = EcountManager()
        if "twitter" in self.config and self.config["twitter"].get(
                "streaming_type", "twitter") == "tweet-provider":
            self.twitter_manager = PBTwitterManager(self)
        else:
            self.twitter_manager = TwitterManager(self)
        self.discord_bot_manager = DiscordBotManager(self, RedisManager.get())
        self.module_manager = ModuleManager(self.socket_manager,
                                            bot=self).load()
        self.commands = CommandManager(socket_manager=self.socket_manager,
                                       module_manager=self.module_manager,
                                       bot=self).load()
        self.spotify_streamlabs_manager = SpotifyStreamLabsManager(self)

        HandlerManager.trigger("on_managers_loaded")

        # Commitable managers
        self.commitable = {
            "commands": self.commands,
            "banphrases": self.banphrase_manager
        }

        self.execute_every(60, self.commit_all)
        self.execute_every(1, self.do_tick)

        # promote the admin to level 2000
        self.admin = self.config["main"].get("admin", None)
        if self.admin is None:
            log.warning(
                "No admin user specified. See the [main] section in the example config for its usage."
            )
        else:
            with DBManager.create_session_scope() as db_session:
                admin_user = User.find_or_create_from_login(
                    db_session, self.twitch_helix_api, self.admin)
                if admin_user is None:
                    log.warning(
                        "The login name you entered for the admin user does not exist on twitch. "
                        "No admin user has been created.")
                else:
                    admin_user.level = 2000

        # silent mode
        self.silent = ("flags" in config and "silent" in config["flags"]
                       and config["flags"]["silent"] == "1") or args.silent
        if self.silent:
            log.info("Silent mode enabled")

        # dev mode
        self.dev = "flags" in config and "dev" in config["flags"] and config[
            "flags"]["dev"] == "1"
        if self.dev:
            self.version_long = extend_version_if_possible(VERSION)
        else:
            self.version_long = VERSION

        self.irc = IRCManager(self)

        relay_host = self.config["main"].get("relay_host", None)
        relay_password = self.config["main"].get("relay_password", None)
        if relay_host is not None or relay_password is not None:
            log.warning(
                "DEPRECATED - Relaybroker support is no longer implemented. relay_host and relay_password are ignored"
            )

        self.reactor.add_global_handler("all_events", self.irc._dispatcher,
                                        -10)

        self.data = {
            "broadcaster": self.streamer,
            "version": self.version_long,
            "version_brief": VERSION,
            "bot_name": self.nickname,
            "bot_domain": self.bot_domain,
        }

        self.data_cb = {
            "status_length": self.c_status_length,
            "stream_status": self.c_stream_status,
            "bot_uptime": self.c_uptime,
            "current_time": self.c_current_time,
            "molly_age_in_years": self.c_molly_age_in_years,
        }
        self.user_agent = f"pajbot1/{VERSION} ({self.nickname})"
Esempio n. 32
0
    def start_quest(self):
        HandlerManager.add_handler("on_duel_complete", self.on_duel_complete)

        redis = RedisManager.get()

        self.load_progress(redis=redis)
Esempio n. 33
0
 def disable(self, bot):
     HandlerManager.remove_handler("on_user_sub", self.on_user_sub)
     HandlerManager.remove_handler("on_user_resub", self.on_user_resub)
Esempio n. 34
0
    def enable(self, bot):
        self.bot = bot

        HandlerManager.add_handler("on_user_sub", self.on_user_sub)
        HandlerManager.add_handler("on_user_resub", self.on_user_resub)
Esempio n. 35
0
    def enable(self, bot):
        if not bot:
            return

        HandlerManager.add_handler("on_pubnotice", self.on_pubnotice)
Esempio n. 36
0
    def multi_end_raffle(self):
        if not self.raffle_running:
            return False

        self.raffle_running = False

        if len(self.raffle_users) == 0:
            self.bot.me('Wow, no one joined the raffle DansGame')
            return False

        # Shuffle the list of participants
        random.shuffle(self.raffle_users)

        num_participants = len(self.raffle_users)

        abs_points = abs(self.raffle_points)

        max_winners = min(num_participants, 200)
        min_point_award = 100
        negative = self.raffle_points < 0

        # Decide how we should pick the winners
        log.info('Num participants: {}'.format(num_participants))
        for winner_percentage in [x * 0.01 for x in range(1, 10)]:
            log.info('Winner percentage: {}'.format(winner_percentage))
            num_winners = math.ceil(num_participants * winner_percentage)
            points_per_user = math.ceil(abs_points / num_winners)
            log.info('nw: {}, ppu: {}'.format(num_winners, points_per_user))

            if num_winners > max_winners:
                num_winners = max_winners
                points_per_user = math.ceil(abs_points / num_winners)
                break
            elif points_per_user < min_point_award:
                num_winners = max(
                    1,
                    min(math.floor(abs_points / min_point_award),
                        num_participants))
                points_per_user = math.ceil(abs_points / num_winners)
                break

        winners = self.raffle_users[:num_winners]
        self.raffle_users = []

        if negative:
            points_per_user *= -1

        for winner in winners:
            if not winner.subscriber and random.randint(1, 10) > 5:
                winners.remove(winner)
                continue

        points_per_user = math.ceil(abs_points / len(winners))

        self.bot.me(
            'The multi-raffle has finished! {0} users won {1} points each! PogChamp'
            .format(len(winners), points_per_user))

        winners_arr = []

        for winner in winners:
            winner.points += points_per_user
            winners_arr.append(winner)

            winners_str = generate_winner_list(winners_arr)
            if len(winners_str) > 300:
                self.bot.me('{} won {} points each!'.format(
                    winners_str, points_per_user))
                winners_arr = []

            winner.save()

        if len(winners_arr) > 0:
            winners_str = generate_winner_list(winners_arr)
            self.bot.me('{} won {} points each!'.format(
                winners_str, points_per_user))

        HandlerManager.trigger('on_multiraffle_win', winners, points_per_user)
Esempio n. 37
0
    def enable(self, bot):
        self.bot = bot

        HandlerManager.add_handler('on_tick', self.on_tick)
Esempio n. 38
0
    def parse_message(self, msg_raw, source, event, tags={}, whisper=False):
        msg_lower = msg_raw.lower()

        emote_tag = None

        for tag in tags:
            if tag['key'] == 'subscriber' and event.target == self.channel:
                source.subscriber = tag['value'] == '1'
            elif tag['key'] == 'emotes' and tag['value']:
                emote_tag = tag['value']
            elif tag['key'] == 'display-name' and tag['value']:
                source.username_raw = tag['value']
            elif tag['key'] == 'user-type':
                source.moderator = tag[
                    'value'] == 'mod' or source.username == self.streamer

        # source.num_lines += 1

        if source is None:
            log.error('No valid user passed to parse_message')
            return False

        if source.banned:
            self.ban(source.username)
            return False

        # If a user types when timed out, we assume he's been unbanned for a good reason and remove his flag.
        if source.timed_out is True:
            source.timed_out = False

        # Parse emotes in the message
        message_emotes = self.emotes.parse_message_twitch_emotes(
            source, msg_raw, emote_tag, whisper)

        urls = self.find_unique_urls(msg_raw)

        log.debug('{2}{0}: {1}'.format(source.username, msg_raw,
                                       '<w>' if whisper else ''))

        res = HandlerManager.trigger('on_message',
                                     source,
                                     msg_raw,
                                     message_emotes,
                                     whisper,
                                     urls,
                                     event,
                                     stop_on_false=True)
        if res is False:
            return False

        source.last_seen = datetime.datetime.now()
        source.last_active = datetime.datetime.now()
        """
        if self.streamer == 'forsenlol' and whisper is False:
            follow_time = self.twitchapi.get_follow_relationship2(source.username, self.streamer)

            if follow_time is False:
                self._timeout(source.username, 600, '2 years follow mode (or api is down?)')
                return

            follow_age = datetime.datetime.now() - follow_time
            log.debug(follow_age)

            if follow_age.days < 730:
                log.debug('followed less than 730 days LUL')
                self._timeout(source.username, 600, '2 years follow mode')
                """

        if source.ignored:
            return False

        if msg_lower[:1] == '!':
            msg_lower_parts = msg_lower.split(' ')
            trigger = msg_lower_parts[0][1:]
            msg_raw_parts = msg_raw.split(' ')
            remaining_message = ' '.join(
                msg_raw_parts[1:]) if len(msg_raw_parts) > 1 else None
            if trigger in self.commands:
                command = self.commands[trigger]
                extra_args = {
                    'emotes': message_emotes,
                    'trigger': trigger,
                }
                command.run(self,
                            source,
                            remaining_message,
                            event=event,
                            args=extra_args,
                            whisper=whisper)
Esempio n. 39
0
    def enable(self, bot):
        self.bot = bot

        HandlerManager.add_handler('on_user_sub', self.on_user_sub)
        HandlerManager.add_handler('on_user_resub', self.on_user_resub)
        HandlerManager.add_handler('on_tick', self.on_tick)
Esempio n. 40
0
 def disable(self, bot):
     HandlerManager.remove_handler('on_message', self.on_message)
Esempio n. 41
0
    def parse_message(self, message, source, event, tags={}, whisper=False):
        msg_lower = message.lower()

        emote_tag = tags["emotes"]
        msg_id = tags.get("id", None)  # None on whispers!

        if not whisper and event.target == self.channel:
            # Moderator or broadcaster, both count
            source.moderator = tags[
                "mod"] == "1" or source.id == self.streamer_user_id
            source.subscriber = tags["subscriber"] == "1"

        if not whisper and source.banned:
            self.ban(source)
            return False

        # Parse emotes in the message
        emote_instances, emote_counts = self.emote_manager.parse_all_emotes(
            message, emote_tag)

        now = utils.now()
        source.last_seen = now
        source.last_active = now

        if not whisper:
            # increment epm and ecount
            self.epm_manager.handle_emotes(emote_counts)
            self.ecount_manager.handle_emotes(emote_counts)

        urls = self.find_unique_urls(message)

        res = HandlerManager.trigger(
            "on_message",
            source=source,
            message=message,
            emote_instances=emote_instances,
            emote_counts=emote_counts,
            whisper=whisper,
            urls=urls,
            msg_id=msg_id,
            event=event,
        )
        if res is False:
            return False

        if source.ignored:
            return False

        if msg_lower[:1] == "!":
            msg_lower_parts = msg_lower.split(" ")
            trigger = msg_lower_parts[0][1:]
            msg_raw_parts = message.split(" ")
            remaining_message = " ".join(
                msg_raw_parts[1:]) if len(msg_raw_parts) > 1 else None
            if trigger in self.commands:
                command = self.commands[trigger]
                extra_args = {
                    "emote_instances": emote_instances,
                    "emote_counts": emote_counts,
                    "trigger": trigger,
                    "msg_id": msg_id,
                }
                command.run(self,
                            source,
                            remaining_message,
                            event=event,
                            args=extra_args,
                            whisper=whisper)
Esempio n. 42
0
 def enable(self, bot):
     HandlerManager.add_handler('on_pubmsg', self.on_pubmsg)
     self.bot = bot
Esempio n. 43
0
 def disable(self, bot):
     HandlerManager.remove_handler("on_message", self.on_message)
Esempio n. 44
0
 def disable(self, bot):
     HandlerManager.remove_handler('on_user_sub', self.on_user_sub)
     HandlerManager.remove_handler('on_user_resub', self.on_user_resub)
     HandlerManager.remove_handler('on_tick', self.on_tick)
Esempio n. 45
0
File: bot.py Progetto: jardg/pajbot
    def __init__(self, config, args=None):
        # Load various configuration variables from the given config object
        # The config object that should be passed through should
        # come from pajbot.utils.load_config
        self.load_config(config)

        # Update the database scheme if necessary using alembic
        # In case of errors, i.e. if the database is out of sync or the alembic
        # binary can't be called, we will shut down the bot.
        pajbot.utils.alembic_upgrade()

        # Actions in this queue are run in a separate thread.
        # This means actions should NOT access any database-related stuff.
        self.action_queue = ActionQueue()
        self.action_queue.start()

        self.reactor = irc.client.Reactor(self.on_connect)
        self.start_time = datetime.datetime.now()
        ActionParser.bot = self

        HandlerManager.init_handlers()

        self.socket_manager = SocketManager(self)
        self.stream_manager = StreamManager(self)

        StreamHelper.init_bot(self, self.stream_manager)
        ScheduleManager.init()

        self.users = UserManager()
        self.decks = DeckManager()
        self.module_manager = ModuleManager(self.socket_manager, bot=self).load()
        self.commands = CommandManager(
                socket_manager=self.socket_manager,
                module_manager=self.module_manager,
                bot=self).load()
        self.filters = FilterManager().reload()
        self.banphrase_manager = BanphraseManager(self).load()
        self.timer_manager = TimerManager(self).load()
        self.kvi = KVIManager()
        self.emotes = EmoteManager(self)
        self.twitter_manager = TwitterManager(self)

        HandlerManager.trigger('on_managers_loaded')

        # Reloadable managers
        self.reloadable = {
                'filters': self.filters,
                }

        # Commitable managers
        self.commitable = {
                'commands': self.commands,
                'filters': self.filters,
                'banphrases': self.banphrase_manager,
                }

        self.execute_every(10 * 60, self.commit_all)
        self.execute_every(1, self.do_tick)

        try:
            self.admin = self.config['main']['admin']
        except KeyError:
            log.warning('No admin user specified. See the [main] section in config.example.ini for its usage.')
        if self.admin:
            with self.users.get_user_context(self.admin) as user:
                user.level = 2000

        self.parse_version()

        relay_host = self.config['main'].get('relay_host', None)
        relay_password = self.config['main'].get('relay_password', None)
        if relay_host is None or relay_password is None:
            self.irc = MultiIRCManager(self)
        else:
            self.irc = SingleIRCManager(self)

        self.reactor.add_global_handler('all_events', self.irc._dispatcher, -10)

        twitch_client_id = None
        twitch_oauth = None
        if 'twitchapi' in self.config:
            twitch_client_id = self.config['twitchapi'].get('client_id', None)
            twitch_oauth = self.config['twitchapi'].get('oauth', None)

        # A client ID is required for the bot to work properly now, give an error for now
        if twitch_client_id is None:
            log.error('MISSING CLIENT ID, SET "client_id" VALUE UNDER [twitchapi] SECTION IN CONFIG FILE')

        self.twitchapi = TwitchAPI(twitch_client_id, twitch_oauth)

        self.data = {}
        self.data_cb = {}
        self.url_regex = re.compile(self.url_regex_str, re.IGNORECASE)

        self.data['broadcaster'] = self.streamer
        self.data['version'] = self.version
        self.data['version_brief'] = self.version_brief
        self.data['bot_name'] = self.nickname
        self.data_cb['status_length'] = self.c_status_length
        self.data_cb['stream_status'] = self.c_stream_status
        self.data_cb['bot_uptime'] = self.c_uptime
        self.data_cb['current_time'] = self.c_current_time

        self.silent = True if args.silent else self.silent

        if self.silent:
            log.info('Silent mode enabled')

        """
        For actions that need to access the main thread,
        we can use the mainthread_queue.
        """
        self.mainthread_queue = ActionQueue()
        self.execute_every(1, self.mainthread_queue.parse_action)

        self.websocket_manager = WebSocketManager(self)

        try:
            if self.config['twitchapi']['update_subscribers'] == '1':
                self.execute_every(30 * 60,
                                   self.action_queue.add,
                                   (self.update_subscribers_stage1, ))
        except:
            pass

        # XXX: TEMPORARY UGLY CODE
        HandlerManager.add_handler('on_user_gain_tokens', self.on_user_gain_tokens)
        HandlerManager.add_handler('send_whisper', self.whisper)
Esempio n. 46
0
 def disable(self, bot):
     HandlerManager.remove_handler('on_stream_start', self.on_stream_start)
     HandlerManager.remove_handler('on_stream_stop', self.on_stream_stop)
     HandlerManager.remove_handler('on_managers_loaded',
                                   self.on_managers_loaded)
Esempio n. 47
0
 def enable(self, bot):
     HandlerManager.add_handler('on_message', self.on_message)
     HandlerManager.add_handler('on_usernotice', self.on_usernotice)
     self.bot = bot
Esempio n. 48
0
 def enable(self, bot):
     HandlerManager.add_handler("on_message", self.on_message, priority=150)
Esempio n. 49
0
    def disable(self, bot):
        # Web interface, nothing to do
        if not bot:
            return

        HandlerManager.remove_handler("on_pubnotice", self.on_pubnotice)
Esempio n. 50
0
    def enable(self, bot):
        if not bot:
            return

        HandlerManager.add_handler("on_redeem", self.on_redeem)
Esempio n. 51
0
    def commit_all(self):
        for key, manager in self.commitable.items():
            manager.commit()

        HandlerManager.trigger("on_commit", stop_on_false=False)
Esempio n. 52
0
File: bot.py Progetto: jardg/pajbot
 def do_tick(self):
     HandlerManager.trigger('on_tick')
Esempio n. 53
0
    def disable(self, bot):
        if not bot:
            return

        HandlerManager.remove_handler("on_redeem", self.on_redeem)
Esempio n. 54
0
 def disable(self, bot):
     HandlerManager.remove_handler('on_pubmsg', self.on_pubmsg)
Esempio n. 55
0
 def enable(self, bot):
     HandlerManager.add_handler("on_pubmsg", self.on_pubmsg)
Esempio n. 56
0
    def pull(self, **options):
        log.debug('pull xd')
        message = options['message']
        user = options['source']
        bot = options['bot']

        if message is None:
            bot.whisper(user.username, 'I didn\'t recognize your bet! Usage: !slotmachine 150 to bet 150 points')
            return False

        low_tier_emotes = self.settings['low_tier_emotes'].split()
        high_tier_emotes = self.settings['high_tier_emotes'].split()

        if len(low_tier_emotes) == 0 or len(high_tier_emotes) == 0:
            return False

        msg_split = message.split(' ')
        try:
            bet = pajbot.utils.parse_points_amount(user, msg_split[0])
        except pajbot.exc.InvalidPointAmount as e:
            bot.whisper(user.username, str(e))
            return False

        if not user.can_afford(bet):
            bot.whisper(user.username, 'You don\'t have enough points to do a slot machine pull for {} points :('.format(bet))
            return False

        if bet < self.settings['min_bet']:
            bot.whisper(user.username, 'You have to bet at least {} point! :('.format(self.settings['min_bet']))
            return False

        # how much of the users point they're expected to get back (basically how much the house yoinks)
        expected_return = 1.0

        ltsw = self.settings['ltsw'] / 100.0
        htsw = self.settings['htsw'] / 100.0
        ltbw = self.settings['ltbw'] / 100.0
        htbw = self.settings['htbw'] / 100.0

        bet_return, randomized_emotes = pull_lol(low_tier_emotes, high_tier_emotes, bet, expected_return, ltsw, htsw, ltbw, htbw)

        # Calculating the result
        if bet_return <= 0.0:
            points = -bet
        else:
            points = bet * bet_return

        user.points += points

        arguments = {
            'bet': bet,
            'result': points,
            'user': user.username_raw,
            'points': user.points_available(),
            'win': points > 0,
            'emotes': ' '.join(randomized_emotes),
        }

        if points > 0:
            out_message = self.get_phrase('message_won', **arguments)
        else:
            out_message = self.get_phrase('message_lost', **arguments)

        if self.settings['options_output'] == '4. Combine output in chat':
            if bot.is_online:
                self.add_message(bot, arguments)
            else:
                bot.me(out_message)
        if self.settings['options_output'] == '1. Show results in chat':
            bot.me(out_message)
        if self.settings['options_output'] == '2. Show results in whispers':
            bot.whisper(user.username, out_message)
        if self.settings['options_output'] == '3. Show results in chat if it\'s over X points else it will be whispered.':
            if abs(points) >= self.settings['min_show_points']:
                bot.me(out_message)
            else:
                bot.whisper(user.username, out_message)

        HandlerManager.trigger('on_slot_machine_finish', user, points)
Esempio n. 57
0
 def disable(self, bot):
     HandlerManager.remove_handler("on_pubmsg", self.on_pubmsg)
Esempio n. 58
0
 def disable(self, bot):
     HandlerManager.remove_handler('on_tick', self.on_tick)
Esempio n. 59
0
    def roulette(self, **options):
        if self.settings['only_roulette_after_sub']:
            if self.last_sub is None:
                return False
            if datetime.datetime.now() - self.last_sub > datetime.timedelta(
                    seconds=self.settings['after_sub_roulette_time']):
                return False

        message = options['message']
        user = options['source']
        bot = options['bot']

        if message is None:
            bot.whisper(
                user.username,
                'I didn\'t recognize your bet! Usage: !roulette 150 to bet 150 points'
            )
            return False

        msg_split = message.split(' ')
        try:
            bet = pajbot.utils.parse_points_amount(user, msg_split[0])
        except pajbot.exc.InvalidPointAmount as e:
            bot.whisper(user.username, str(e))
            return False

        if not user.can_afford(bet):
            bot.whisper(
                user.username,
                'You don\'t have enough points to do a roulette for {} points :('
                .format(bet))
            return False

        if bet < self.settings['min_roulette_amount']:
            bot.whisper(
                user.username, 'You have to bet at least {} point! :('.format(
                    self.settings['min_roulette_amount']))
            return False

        # Calculating the result
        result = self.rigged_random_result()
        points = bet if result else -bet
        user.points += points

        with DBManager.create_session_scope() as db_session:
            r = Roulette(user.id, points)
            db_session.add(r)

        arguments = {
            'bet': bet,
            'user': user.username_raw,
            'points': user.points_available(),
            'win': points > 0,
        }

        if points > 0:
            out_message = self.get_phrase('message_won', **arguments)
        else:
            out_message = self.get_phrase('message_lost', **arguments)

        if self.settings['options_output'] == '4. Combine output in chat':
            self.add_message(bot, arguments)
        if self.settings['options_output'] == '1. Show results in chat':
            bot.me(out_message)
        if self.settings['options_output'] == '2. Show results in whispers':
            bot.whisper(user.username, out_message)
        if self.settings[
                'options_output'] == '3. Show results in chat if it\'s over X points else it will be whispered.':
            if abs(points) >= self.settings['min_show_points']:
                bot.me(out_message)
            else:
                bot.whisper(user.username, out_message)

        HandlerManager.trigger('on_roulette_finish', user, points)