Exemple #1
0
    def update_emotes(self):
        log.debug('Updating BTTV Emotes...')
        global_emotes = self.bttv_api.get_global_emotes()
        channel_emotes = self.bttv_api.get_channel_emotes(StreamHelper.get_streamer())

        self.global_emotes = [emote['code'] for emote in global_emotes]
        self.channel_emotes = [emote['code'] for emote in channel_emotes]

        # Store channel emotes in redis
        streamer = StreamHelper.get_streamer()
        key = '{streamer}:emotes:bttv_channel_emotes'.format(streamer=streamer)
        with RedisManager.pipeline_context() as pipeline:
            pipeline.delete(key)
            for emote in channel_emotes:
                pipeline.hset(key, emote['code'], emote['emote_hash'])

        self.all_emotes = []
        with RedisManager.pipeline_context() as pipeline:
            for emote in global_emotes + channel_emotes:
                # Store all possible emotes, with their regex in an easily
                # accessible list.
                self.all_emotes.append(self.build_emote(emote['code'], emote['emote_hash']))

                # Make sure all available emotes are available in redis
                pipeline.hset('global:emotes:bttv', emote['code'], emote['emote_hash'])
Exemple #2
0
def donations(widget_id, **options):
    redis = RedisManager.get()
    widget = redis.hget(
            '{streamer}:clr:donations'.format(streamer=StreamHelper.get_streamer()),
            widget_id)
    if widget is None:
        abort(404)

    widget = json.loads(widget)

    # Assign indices to all styles and conditions
    i = 0
    log.info(widget['styles'])
    for style in widget['styles']:
        style['index'] = i
        i += 1
    log.info(widget['styles'])
    i = 0
    j = 0
    for condition in widget['conditions']:
        condition['index'] = i
        i += 1
        for style in condition['styles']:
            style['index'] = j
            j += 1
    log.info(widget)

    operator_order = {
            '==': 100,
            '>=': 50,
            '<=': 50,
            }

    widget['conditions'].sort(key=lambda c: (operator_order[c['operator']], c['amount']))

    tts_authentication = ''
    if 'extra' in config:
        tts_authentication = config['extra'].get('tts_authentication', '')

    redis = RedisManager.get()
    twitch_emotes = redis.hgetall('global:emotes:twitch')
    bttv_emotes = redis.hgetall('global:emotes:bttv')
    emotes = []
    for emote in twitch_emotes:
        emotes.append({
            'code': emote,
            'emote_id': twitch_emotes[emote],
            })
    for emote in bttv_emotes:
        emotes.append({
            'code': emote,
            'emote_hash': bttv_emotes[emote],
            })
    emotes.sort(key=lambda emote: len(emote['code']), reverse=True)
    return render_template('clr/donations.html',
            widget=widget,
            emotes=emotes,
            tts_authentication=tts_authentication)
Exemple #3
0
    def load_config(self, config):
        self.config = config

        pajbot.models.user.Config.se_sync_token = config['main'].get('se_sync_token', None)
        pajbot.models.user.Config.se_channel = config['main'].get('se_channel', None)

        self.domain = config['web'].get('domain', 'localhost')

        self.nickname = config['main'].get('nickname', 'pajbot')
        self.password = config['main'].get('password', 'abcdef')

        self.timezone = config['main'].get('timezone', 'UTC')
        os.environ['TZ'] = self.timezone

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

        self.trusted_mods = config.getboolean('main', 'trusted_mods')

        self.phrases = {
                'welcome': ['{nickname} {version} running!'],
                'quit': ['{nickname} {version} shutting down...'],
                }

        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()

        TimeManager.init_timezone(self.timezone)

        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.silent = False
        self.dev = False

        if 'flags' in config:
            self.silent = True if 'silent' in config['flags'] and config['flags']['silent'] == '1' else self.silent
            self.dev = True if 'dev' in config['flags'] and config['flags']['dev'] == '1' else self.dev

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

        redis_options = {}
        if 'redis' in config:
            redis_options = config._sections['redis']

        RedisManager.init(**redis_options)
Exemple #4
0
    def update_global_emotes(self):
        # Try to get cached global emotes from redis
        _global_emotes = RedisManager.get().get('global:emotes:bttv_global')
        if _global_emotes and len(_global_emotes) > 0:
            log.info('Got cached BTTV global emotes!')
            _global_emotes = json.loads(_global_emotes)
        else:
            _global_emotes = self.api.get_global_emotes()
            if _global_emotes and len(_global_emotes) > 0:
                RedisManager.get().setex('global:emotes:bttv_global', time=3600, value=json.dumps(_global_emotes, separators=(',', ':')))

        if _global_emotes and len(_global_emotes) > 0:
            self.global_emotes = {}
            for emote in _global_emotes:
                self.global_emotes[emote['code']] = emote['emote_hash']
Exemple #5
0
    def __init__(self):
        super().__init__()
        self.bets = {}

        redis = RedisManager.get()

        self.last_game_start = None
        self.last_game_id = None
        try:
            last_game_start_timestamp = int(redis.get('{streamer}:last_hsbet_game_start'.format(streamer=StreamHelper.get_streamer())))
            self.last_game_start = datetime.fromtimestamp(last_game_start_timestamp)
        except (TypeError, ValueError):
            # Issue with the int-cast
            pass
        except (OverflowError, OSError):
            # Issue with datetime.fromtimestamp
            pass

        try:
            self.last_game_id = int(redis.get('{streamer}:last_hsbet_game_id'.format(streamer=StreamHelper.get_streamer())))
        except (TypeError, ValueError):
            pass

        self.scheduler = BackgroundScheduler()
        self.scheduler.start()
        self.job = self.scheduler.add_job(self.poll_trackobot, 'interval', seconds=15)
        self.job.pause()
        self.reminder_job = self.scheduler.add_job(self.reminder_bet, 'interval', seconds=1)
        self.reminder_job.pause()
Exemple #6
0
    def stats():
        bot_commands_list = pajbot.web.utils.get_cached_commands()
        top_5_commands = sorted(bot_commands_list, key=lambda c: c['data']['num_uses'] if c['data'] is not None else -1, reverse=True)[:5]

        redis = RedisManager.get()

        # TODO: Make this hideable through some magic setting (NOT config.ini @_@)
        with DBManager.create_session_scope() as db_session:
            top_5_line_farmers = []
            for redis_user in redis.zrevrangebyscore(
                    '{streamer}:users:num_lines'.format(streamer=StreamHelper.get_streamer()),
                    '+inf',
                    '-inf',
                    start=0,
                    num=5,
                    withscores=True,
                    score_cast_func=int):
                user = UserManager.get_static(redis_user[0], db_session=db_session)
                user.save_to_redis = False
                user.num_lines = redis_user[1]
                top_5_line_farmers.append(user)

            return render_template('stats.html',
                    top_5_commands=top_5_commands,
                    top_5_line_farmers=top_5_line_farmers)
Exemple #7
0
    def __init__(self):
        super().__init__()
        self.bets = {}

        redis = RedisManager.get()

        self.last_game_start = None
        self.last_game_id = None
        try:
            last_game_start_timestamp = int(redis.get('{streamer}:last_hsbet_game_start'.format(streamer=StreamHelper.get_streamer())))
            self.last_game_start = datetime.fromtimestamp(last_game_start_timestamp)
        except (TypeError, ValueError):
            # Issue with the int-cast
            pass
        except (OverflowError, OSError):
            # Issue with datetime.fromtimestamp
            pass

        try:
            self.last_game_id = int(redis.get('{streamer}:last_hsbet_game_id'.format(streamer=StreamHelper.get_streamer())))
        except (TypeError, ValueError):
            pass

        self.job = ScheduleManager.execute_every(15, self.poll_trackobot)
        self.job.pause()
        self.reminder_job = ScheduleManager.execute_every(1, self.reminder_bet)
        self.reminder_job.pause()
Exemple #8
0
    def get_follow_relationship(self, username, streamer):
        """Returns the follow relationship between the user and a streamer.

        Returns False if `username` is not following `streamer`.
        Otherwise, return a datetime object.

        This value is cached in Redis for 2 minutes.
        """

        # XXX TODO FIXME
        from pajbot.managers.redis import RedisManager

        redis = RedisManager.get()

        fr_key = 'fr_{username}_{streamer}'.format(username=username, streamer=streamer)
        follow_relationship = redis.get(fr_key)

        if follow_relationship is None:
            try:
                data = self.get(endpoints=['users', username, 'follows', 'channels', streamer], base=self.kraken_url)
                created_at = data['created_at']
                redis.setex(fr_key, time=120, value=created_at)
                return TwitchAPI.parse_datetime(created_at)
            except urllib.error.HTTPError:
                redis.setex(fr_key, time=120, value='-1')
                return False
            except:
                log.exception('Unhandled exception in get_follow_relationship')
                return False
        else:
            if follow_relationship == '-1':
                return False
            else:
                return TwitchAPI.parse_datetime(follow_relationship)
Exemple #9
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)
Exemple #10
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)
Exemple #11
0
    def refresh_stream_status_stage2(self, status):
        try:
            redis = RedisManager.get()

            redis.hmset('stream_data', {
                '{streamer}:online'.format(streamer=self.bot.streamer): status['online'],
                '{streamer}:viewers'.format(streamer=self.bot.streamer): status['viewers'],
                '{streamer}:game'.format(streamer=self.bot.streamer): status['game'],
                })

            self.num_viewers = status['viewers']

            if status['online']:
                if self.current_stream is None:
                    self.create_stream(status)
                if self.current_stream_chunk is None:
                    self.create_stream_chunk(status)
                if self.current_stream_chunk.broadcast_id != status['broadcast_id']:
                    log.debug('Detected a new chunk!')
                    self.create_stream_chunk(status)

                self.num_offlines = 0
                self.first_offline = None
            else:
                if self.online is True:
                    log.info('Offline. {0}'.format(self.num_offlines))
                    if self.first_offline is None:
                        self.first_offline = datetime.datetime.now()

                    if self.num_offlines >= 10:
                        log.info('Switching to offline state!')
                        self.go_offline()
                    self.num_offlines += 1
        except:
            log.exception('Uncaught exception while refreshing stream status (Stage 2)')
Exemple #12
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)
Exemple #13
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)
Exemple #14
0
    def delete(self, **options):
        # Add a single tag to the email
        args = self.delete_parser.parse_args()

        email = args['email'].lower()
        new_tag = args['tag'].lower()
        streamer = StreamHelper.get_streamer()

        key = '{streamer}:email_tags'.format(streamer=streamer)
        redis = RedisManager.get()

        tags_str = redis.hget(key, email)

        if tags_str is None:
            tags = []
        else:
            tags = json.loads(tags_str)

        # Is the tag already active?
        if new_tag not in tags:
            return {
                    'message': 'This tag is not set on the email.'
                    }, 409

        tags.remove(new_tag)

        if len(tags) > 0:
            redis.hset(key, email, json.dumps(tags))
        else:
            redis.hdel(key, email)

        return {
                'message': 'Successfully removed the tag {} from {}'.format(new_tag, email)
                }
Exemple #15
0
    def timeout(self, timeout_length, warning_module=None, use_warnings=True):
        """ Returns a tuple with the follow data:
        How long to timeout the user for, and what the punishment string is
        set to.
        The punishment string is used to clarify whether this was a warning or the real deal.
        """

        punishment = 'timed out for {} seconds'.format(timeout_length)

        if use_warnings and warning_module is not None:
            redis = RedisManager.get()

            """ How many chances the user has before receiving a full timeout. """
            total_chances = warning_module.settings['total_chances']

            warning_keys = self.get_warning_keys(total_chances, warning_module.settings['redis_prefix'])
            warnings = self.get_warnings(redis, warning_keys)

            chances_used = self.get_chances_used(warnings)

            if chances_used < total_chances:
                """ The user used up one of his warnings.
                Calculate for how long we should time him out. """
                timeout_length = warning_module.settings['base_timeout'] * (chances_used + 1)
                punishment = 'timed out for {} seconds (warning)'.format(timeout_length)

                self.add_warning(redis, warning_module.settings['length'], warning_keys, warnings)

        return (timeout_length, punishment)
Exemple #16
0
    def post(self, **options):
        # Add a single tag to the email
        args = self.post_parser.parse_args()

        email = args['email'].lower()
        new_tag = args['tag'].lower()
        if len(new_tag) == 0:
            return {
                    'message': 'The tag must be at least 1 character long.'
                    }, 400
        streamer = StreamHelper.get_streamer()

        key = '{streamer}:email_tags'.format(streamer=streamer)
        redis = RedisManager.get()

        tags_str = redis.hget(key, email)

        if tags_str is None:
            tags = []
        else:
            tags = json.loads(tags_str)

        # Is the tag already active?
        if new_tag in tags:
            return {
                    'message': 'This tag is already set on the email.'
                    }, 409

        tags.append(new_tag)

        redis.hset(key, email, json.dumps(tags))

        return {
                'message': 'Successfully added the tag {} to {}'.format(new_tag, email)
                }
Exemple #17
0
    def get_emote_epmrecord(self, emote_code):
        redis = RedisManager.get()
        streamer = StreamHelper.get_streamer()

        emote_count = redis.zscore('{streamer}:emotes:epmrecord'.format(streamer=streamer), emote_code)
        if emote_count:
            return int(emote_count)
        return None
Exemple #18
0
 def get_tags(self, redis=None):
     if redis is None:
         redis = RedisManager.get()
     val = redis.hget('global:usertags', self.username)
     if val:
         return json.loads(val)
     else:
         return {}
Exemple #19
0
 def __init__(self):
     from pajbot.apiwrappers import BTTVApi
     self.bttv_api = BTTVApi()
     self.global_emotes = []
     streamer = StreamHelper.get_streamer()
     redis = RedisManager.get()
     self.channel_emotes = redis.lrange('{streamer}:emotes:bttv_channel_emotes'.format(streamer=streamer), 0, -1)
     self.all_emotes = []
Exemple #20
0
 def __init__(self, username, redis=None):
     self.username = username
     self.redis_loaded = False
     self.save_to_redis = True
     self.values = {}
     if redis:
         self.redis = redis
     else:
         self.redis = RedisManager.get()
Exemple #21
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
Exemple #22
0
 def redis_test2(self, username):
     redis = RedisManager.get()
     values = [
             redis.hget('pajlada:users:points', username),
             redis.hget('pajlada:users:ignored', username),
             redis.hget('pajlada:users:banned', username),
             redis.hget('pajlada:users:last_active', username),
             ]
     return values
Exemple #23
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
Exemple #24
0
    def redis_load(self):
        """ Load data from redis using a newly created pipeline """
        if self.redis_loaded:
            return

        with RedisManager.pipeline_context() as pipeline:
            self.queue_up_redis_calls(pipeline)
            data = pipeline.execute()
            self.load_redis_data(data)
Exemple #25
0
 def load_progress(self, redis=None):
     if redis is None:
         redis = RedisManager.get()
     self.progress = {}
     old_progress = redis.hgetall(self.progress_key)
     for user, progress in old_progress.items():
         try:
             self.progress[user] = int(progress)
         except (TypeError, ValueError):
             pass
Exemple #26
0
    def load_config(self, config):
        self.config = config

        self.domain = config['web'].get('domain', 'localhost')

        self.nickname = config['main'].get('nickname', 'pajbot')
        self.password = config['main'].get('password', 'abcdef')

        self.timezone = config['main'].get('timezone', 'UTC')

        self.trusted_mods = config.getboolean('main', 'trusted_mods')

        TimeManager.init_timezone(self.timezone)

        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.wolfram = None
        if 'wolfram' in config['main']:
            try:
                import wolframalpha
                self.wolfram = wolframalpha.Client(config['main']['wolfram'])
            except ImportError:
                pass

        self.silent = False
        self.dev = False

        if 'flags' in config:
            self.silent = True if 'silent' in config['flags'] and config['flags']['silent'] == '1' else self.silent
            self.dev = True if 'dev' in config['flags'] and config['flags']['dev'] == '1' else self.dev

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

        redis_options = {}
        if 'redis' in config:
            redis_options = config._sections['redis']

        RedisManager.init(**redis_options)
Exemple #27
0
    def __init__(self):
        from pajbot.apiwrappers import BTTVApi
        self.bttv_api = BTTVApi()
        self.global_emotes = []
        streamer = StreamHelper.get_streamer()
        _global_emotes = RedisManager.get().hgetall('global:emotes:bttv')
        try:
            _channel_emotes = RedisManager.get().hgetall('{streamer}:emotes:bttv_channel_emotes'.format(streamer=streamer))
        except:
            _channel_emotes = {}

        self.channel_emotes = list(_channel_emotes.keys())

        _all_emotes = _global_emotes.copy()
        _all_emotes.update(_channel_emotes)

        self.all_emotes = []
        for emote_code, emote_hash in _all_emotes.items():
            self.all_emotes.append(self.build_emote(emote_code, emote_hash))
Exemple #28
0
    def update_chatters_stage2(self, chatters):
        points = 1 if self.bot.is_online else 0

        log.debug('Updating {0} chatters'.format(len(chatters)))

        self.bot.stream_manager.update_chatters(chatters, self.update_chatters_interval)

        with RedisManager.pipeline_context() as pipeline:
            with DBManager.create_session_scope() as db_session:
                user_models = UserManager.get().bulk_load_user_models(chatters, db_session)
                users = []
                for username in chatters:
                    user_model = user_models.get(username, None)
                    user = UserManager.get().get_user(username, db_session=db_session, user_model=user_model, redis=pipeline)
                    users.append(user)

                more_update_data = {}
                if self.bot.is_online:
                    more_update_data['minutes_in_chat_online'] = self.update_chatters_interval
                else:
                    more_update_data['minutes_in_chat_offline'] = self.update_chatters_interval

                points_to_give_out = {}
                dt_now = datetime.datetime.now().timestamp()
                for user in users:
                    user._set_last_seen(dt_now)

                    num_points = points
                    if user.subscriber:
                        num_points *= 5
                    # TODO: Load user tags during the pipeline redis data fetch
                    if self.bot.streamer == 'forsenlol' and 'trumpsc_sub' in user.get_tags():
                        num_points *= 0.5

                    num_points = int(num_points)

                    if num_points not in points_to_give_out:
                        points_to_give_out[num_points] = []

                    points_to_give_out[num_points].append(user.username)

                    user.save(save_to_db=False)

                for num_points, usernames in points_to_give_out.items():
                    payload = {
                            User.points: User.points + num_points,
                            }
                    if self.bot.is_online:
                        payload[User.minutes_in_chat_online] = User.minutes_in_chat_online + self.update_chatters_interval
                    else:
                        payload[User.minutes_in_chat_offline] = User.minutes_in_chat_offline + self.update_chatters_interval
                    db_session.query(User).filter(User.username.in_(usernames)).\
                            update(payload, synchronize_session=False)

                pipeline.execute()
Exemple #29
0
    def get(self, redis=None):
        if redis is None:
            redis = RedisManager.get()

        try:
            raw_value = redis.hget(self.key, self.id)
            value = int(raw_value)
        except (TypeError, ValueError):
            value = 0

        return value
Exemple #30
0
    def winraffle_progress_quest(self, winner):
        user_progress = self.get_user_progress(winner.username, 0) + 1
        if user_progress > 1:
            # User has already finished this quest
            return

        redis = RedisManager.get()

        winner.award_tokens(self.REWARD, redis=redis)

        self.set_user_progress(winner.username, user_progress, redis=redis)
Exemple #31
0
    def add_entry(type, source, message, data={}):
        redis = RedisManager.get()

        payload = {
            'type': type,
            'user_id': source.id,
            'message': message,
            'created_at': str(datetime.datetime.now()),
            'data': data,
        }

        redis.lpush(AdminLogManager.get_key(), json.dumps(payload))
Exemple #32
0
    def load_data(self, redis=None):
        if redis is None:
            redis = RedisManager.get()

        self.current_emote = redis.get(self.current_emote_key)
        if self.current_emote is None:
            # randomize an emote
            global_twitch_emotes = self.bot.emotes.get_global_emotes()
            self.current_emote = random.choice(global_twitch_emotes)
            redis.set(self.current_emote_key, self.current_emote)
        else:
            self.current_emote = self.current_emote
Exemple #33
0
 def redis_test(self, username):
     try:
         pipeline = RedisManager.get().pipeline()
         pipeline.hget('pajlada:users:points', username)
         pipeline.hget('pajlada:users:ignored', username)
         pipeline.hget('pajlada:users:banned', username)
         pipeline.hget('pajlada:users:last_active', username)
     except:
         pipeline.reset()
     finally:
         b = pipeline.execute()
         log.info(b)
Exemple #34
0
    def __init__(self, streamer_name, callback):
        self.handlers = {}
        self.pubsub = RedisManager.get().pubsub()
        self.running = True
        self.streamer_name = streamer_name
        self.callback = callback

        self.pubsub.subscribe("test")  # need this for keepalive? idk

        self.thread = threading.Thread(target=self.start,
                                       name="SocketManagerThread")
        self.thread.daemon = True
        self.thread.start()
Exemple #35
0
    def add_entry(entry_type, source, message, data={}):
        redis = RedisManager.get()

        payload = {
            "type": entry_type,
            "user_id": source.id,
            "message": message,
            "created_at":
            str(pajbot.utils.now().strftime("%Y-%m-%d %H:%M:%S %Z")),
            "data": data,
        }

        redis.lpush(AdminLogManager.get_key(), json.dumps(payload))
Exemple #36
0
 def save_cached_subemotes(redis_key, tier_one, tier_two, tier_three):
     try:
         redis = RedisManager.get()
         # emotes expire after 1 hour
         dict = {"1": tier_one, "2": tier_two, "3": tier_three}
         dict = {
             key: [emote.jsonify() for emote in emotes]
             for key, emotes in dict.items()
         }
         redis.setex(redis_key, 60 * 60, json.dumps(dict))
     except:
         log.exception(
             "Error saving subemotes to redis key {}".format(redis_key))
Exemple #37
0
    def update_channel_emotes(self):
        _channel_emotes = self.api.get_channel_emotes(
            StreamHelper.get_streamer())
        self.channel_emotes = {}
        for emote in _channel_emotes:
            self.channel_emotes[emote['code']] = emote['emote_hash']

        # Store channel emotes in redis
        streamer = StreamHelper.get_streamer()
        key = '{streamer}:emotes:bttv_channel_emotes'.format(streamer=streamer)
        with RedisManager.pipeline_context() as pipeline:
            for emote_code, emote_hash in self.channel_emotes.items():
                pipeline.hset(key, emote_code, emote_hash)
Exemple #38
0
    def load_cached_channel_emotes(self):
        streamer = StreamHelper.get_streamer()

        # Try to get the list of global emotes from redis
        try:
            _channel_emotes = RedisManager.get().hgetall(
                '{streamer}:emotes:bttv_channel_emotes'.format(
                    streamer=streamer))
        except:
            _channel_emotes = {}

        for code in _channel_emotes:
            emote_hash = _channel_emotes[code]
            self.channel_emotes[code] = emote_hash
Exemple #39
0
    def __init__(self):
        from pajbot.apiwrappers import FFZApi
        self.api = FFZApi()
        self.global_emotes = []
        streamer = StreamHelper.get_streamer()

        # Try to get the list of global emotes from redis
        _global_emotes = RedisManager.get().hgetall('global:emotes:ffz')
        try:
            _channel_emotes = RedisManager.get().hgetall(
                '{streamer}:emotes:ffz_channel_emotes'.format(
                    streamer=streamer))
        except:
            _channel_emotes = {}

        self.channel_emotes = list(_channel_emotes.keys())

        _all_emotes = _global_emotes.copy()
        _all_emotes.update(_channel_emotes)

        self.all_emotes = []
        for emote_code, emote_hash in _all_emotes.items():
            self.all_emotes.append(self.build_emote(emote_code, emote_hash))
Exemple #40
0
    def __init__(self, streamer_name: str, callback: Callable[[Handler, Any],
                                                              None]) -> None:
        self.handlers: Dict[str, List[Handler]] = {}
        self.pubsub = RedisManager.get().pubsub()
        self.running = True
        self.streamer_name = streamer_name
        self.callback = callback

        self.pubsub.subscribe("test")  # need this for keepalive? idk

        self.thread = threading.Thread(target=self.start,
                                       name="SocketManagerThread")
        self.thread.daemon = True
        self.thread.start()
Exemple #41
0
    def __init__(self, config):
        self.nickname = config["main"]["nickname"]
        self.client_id = config["webtwitchapi"]["client_id"]
        self.client_secret = config["webtwitchapi"]["client_secret"]

        token = RedisManager.get().get("{}:token".format(self.nickname))
        if not token:
            raise ValueError(
                "No token set for bot. Log into the bot using the web interface /bot_login route"
            )

        self.token = json.loads(token)

        self.access_token_expires_at = None
Exemple #42
0
    def add_playsound(bot, source, message, event, args):
        if message is not None and len(message.split(' ')) == 3:
            playsoundCategory = message.split(' ')[0]
            playsoundName = message.split(' ')[1]
            playsoundURL = message.split(' ')[2]
            _savedplaysounds = RedisManager.get().hgetall('playsounds:{}'.format(playsoundCategory))

            if playsoundName in _savedplaysounds:
                bot.say('Name of playsound already exists. Please choose a different name')
                return False

            elif playsoundURL in _savedplaysounds:
                bot.say('URL of playsound already exists. Please choose a different link')
                return False

            with RedisManager.pipeline_context() as pipeline:
                pipeline.hset('playsounds:{}'.format(playsoundCategory), playsoundName, playsoundURL)

            bot.say('Successfully added {} with the name {} to the playsound list'.format(playsoundURL, playsoundName))

        else:
            bot.say('Invalid syntax. Usage: !add playsound category name url')
            return False
Exemple #43
0
    def get(self, redis: Optional[RedisType] = None) -> int:
        if redis is None:
            redis = RedisManager.get()

        value: int = 0

        try:
            raw_value = redis.hget(self.key, self.id)
            if raw_value:
                value = int(raw_value)
        except (TypeError, ValueError):
            value = 0

        return value
Exemple #44
0
        def spotify_auth():
            try:
                resp = spotify.authorized_response(spotify=True)
            except OAuthException as e:
                log.error(e)
                log.exception("An exception was caught while authorizing")
                next_url = get_next_url(request, "state")
                return redirect(next_url)
            except Exception as e:
                log.error(e)
                log.exception("Unhandled exception while authorizing")
                return render_template("login_error.html")

            session["spotify_token"] = (resp["access_token"], )
            if resp is None:
                if "error" in request.args and "error_description" in request.args:
                    log.warning(
                        f"Access denied: reason={request.args['error']}, error={request.args['error_description']}"
                    )
                next_url = get_next_url(request, "state")
                return redirect(next_url)
            elif type(resp) is OAuthException:
                log.warning(resp.message)
                log.warning(resp.data)
                log.warning(resp.type)
                next_url = get_next_url(request, "state")
                return redirect(next_url)

            data = f'{app.bot_config["spotify"]["client_id"]}:{app.bot_config["spotify"]["client_secret"]}'
            encoded = str(base64.b64encode(data.encode("utf-8")), "utf-8")
            headers = {"Authorization": f"Basic {encoded}"}

            me_api_response = spotify.get("me", headers=headers)

            redis = RedisManager.get()
            token_json = UserAccessToken.from_api_response(resp).jsonify()

            redis.set(
                f"authentication:spotify-access-token:{me_api_response.data['id']}",
                json.dumps(token_json))
            redis.set(
                f"authentication:user-refresh-token:{me_api_response.data['id']}",
                token_json["refresh_token"])
            log.info(
                f"Successfully updated spotify token in redis for user {me_api_response.data['id']}"
            )

            next_url = get_next_url(request, "state")
            return redirect(next_url)
Exemple #45
0
    def home():
        custom_content = ''

        redis = RedisManager.get()
        streamer = StreamHelper.get_streamer()

        keys = ('online', 'viewers', 'game')
        stream_data_keys = [
            '{streamer}:{key}'.format(streamer=streamer, key=key)
            for key in keys
        ]
        stream_data_list = redis.hmget('stream_data', stream_data_keys)
        stream_data = {
            keys[x]: stream_data_list[x]
            for x in range(0, len(keys))
        }

        keys = StreamHelper.social_keys
        streamer_info_keys = [
            '{streamer}:{key}'.format(streamer=streamer, key=key)
            for key in keys.keys()
        ]
        log.info(streamer_info_keys)
        streamer_info_list = redis.hmget('streamer_info', streamer_info_keys)
        streamer_info = collections.OrderedDict()
        for key in keys:
            value = streamer_info_list.pop(0)
            if value:
                streamer_info[key] = {
                    'value': keys[key]['format'].format(value),
                    'title': keys[key]['title'],
                    'format': keys[key]['format'],
                }

        current_quest_key = '{streamer}:current_quest'.format(
            streamer=StreamHelper.get_streamer())
        current_quest_id = redis.get(current_quest_key)
        if current_quest_id is not None:
            current_quest = app.module_manager[current_quest_id]
            if current_quest:
                current_quest.load_data()
        else:
            current_quest = None

        return render_template('home.html',
                               custom_content=custom_content,
                               current_quest=current_quest,
                               stream_data=stream_data,
                               streamer_info=streamer_info)
Exemple #46
0
    def get_viewer_data(self, redis=None):
        if self.offline:
            return False

        if not redis:
            redis = RedisManager.get()

        data = redis.hget("{streamer}:viewer_data".format(streamer=self.bot.streamer), self.current_stream.id)

        if data is None:
            data = {}
        else:
            data = json.loads(data)

        return data
    def load_data(self, redis=None):
        if redis is None:
            redis = RedisManager.get()

        self.hsbet_points_required = redis.get(self.hsbet_points_key)
        try:
            self.hsbet_points_required = int(self.hsbet_points_required)
        except (TypeError, ValueError):
            pass
        if self.hsbet_points_required is None:
            try:
                self.hsbet_points_required = random.randint(self.settings["min_value"], self.settings["max_value"] + 1)
            except ValueError:
                self.hsbet_points_required = 500
            redis.set(self.hsbet_points_key, self.hsbet_points_required)
Exemple #48
0
def upgrade():
    bind = op.get_bind()
    session = Session(bind=bind)

    config_data = RedisManager.get().config_get('maxmemory')
    max_memory = config_data['maxmemory']
    print('redis max memory: {}'.format(max_memory))
    RedisManager.get().config_set('maxmemory', str(int(max_memory) * 10))
    with RedisManager.pipeline_context() as pipeline:
        streamer = pb_config['main']['streamer']

        num_lines_key = '{streamer}:users:num_lines'.format(streamer=streamer)
        ignored_key = '{streamer}:users:ignored'.format(streamer=streamer)
        last_active_key = '{streamer}:users:last_active'.format(
            streamer=streamer)
        last_seen_key = '{streamer}:users:last_seen'.format(streamer=streamer)
        banned_key = '{streamer}:users:banned'.format(streamer=streamer)
        username_raw_key = '{streamer}:users:username_raw'.format(
            streamer=streamer)
        pipeline.delete(num_lines_key, ignored_key, last_active_key,
                        last_seen_key, banned_key, username_raw_key)

        for user in session.query(User):
            if user.num_lines > 0:
                pipeline.zadd(num_lines_key, user.username, user.num_lines)

            if user.ignored:
                pipeline.hset(ignored_key, user.username, 1)

            if user.banned:
                pipeline.hset(banned_key, user.username, 1)

            if user.username != user.username_raw:
                pipeline.hset(username_raw_key, user.username,
                              user.username_raw)

            if user._last_seen:
                pipeline.hset(last_seen_key, user.username,
                              user._last_seen.timestamp())

            if user._last_active:
                pipeline.hset(last_active_key, user.username,
                              user._last_active.timestamp())

    RedisManager.get().config_set('maxmemory', int(max_memory))

    ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table('tb_user') as batch_op:
        batch_op.drop_column('num_lines')
        batch_op.drop_column('ignored')
        batch_op.drop_column('last_active')
        batch_op.drop_column('last_seen')
        batch_op.drop_column('banned')
    ### end Alembic commands ###

    session.commit()
Exemple #49
0
    def get(username):
        user = UserManager.find_static(username)
        if not user:
            return {"error": "Not found"}, 404

        redis = RedisManager.get()
        key = "{streamer}:users:num_lines".format(
            streamer=StreamHelper.get_streamer())
        rank = redis.zrevrank(key, user.username)
        if rank is None:
            rank = redis.zcard(key)
        else:
            rank = rank + 1

        return user.jsonify()
Exemple #50
0
    def command_masspoints(self, **options):
        bot = options["bot"]
        source = options["source"]
        message = options["message"]

        if not message:
            return False

        pointsArgument = message.split(" ")[0]
        givePoints = 0

        try:
            givePoints = int(pointsArgument)
        except ValueError:
            bot.whisper(source.username_raw, "Error: You must give an integer")
            return False

        currentChatters = bot.twitch_tmi_api.get_chatters(bot.streamer)
        numUsers = len(currentChatters)
        if not currentChatters:
            bot.say("Error fetching chatters")
            return False

        with RedisManager.pipeline_context() as pipeline:
            with DBManager.create_session_scope() as db_session:
                userModels = UserManager.get().bulk_load_user_models(
                    currentChatters, db_session)
                for userName in currentChatters:
                    userModel = userModels.get(userName, None)
                    userInstance = UserManager.get().get_user(
                        userName,
                        db_session=db_session,
                        user_model=userModel,
                        redis=pipeline)

                    # Bot/idler check. Quicker than removing from list?
                    if userInstance.num_lines < 5:
                        numUsers -= 1
                        continue

                    if userInstance.subscriber:
                        userInstance.points += givePoints * self.settings[
                            "sub_points"]
                    else:
                        userInstance.points += givePoints

        bot.say("{} just gave {} viewers {} points each! Enjoy FeelsGoodMan".
                format(source.username_raw, numUsers, givePoints))
Exemple #51
0
    def clr_donations_edit(widget_id, **options):
        redis = RedisManager.get()
        widget = redis.hget(
            '{streamer}:clr:donations'.format(
                streamer=StreamHelper.get_streamer()), widget_id)
        new = False
        if widget is None:
            widget = {}
            new = True
        else:
            widget = json.loads(widget)

        return render_template('admin/clr/donations/edit.html',
                               widget_id=widget_id,
                               widget_data=json.dumps(widget),
                               new=new)
Exemple #52
0
    def on_duel_complete(self, winner, loser, points_won, points_bet):
        if points_won < 1:
            return

        user_progress = self.get_user_progress(winner.username, default=0)
        if user_progress >= self.get_limit():
            return

        user_progress += 1

        redis = RedisManager.get()

        if user_progress == self.get_limit():
            self.finish_quest(redis, winner)

        self.set_user_progress(winner.username, user_progress, redis=redis)
Exemple #53
0
        def post(self, widget_id, **options):
            args = self.post_parser.parse_args()

            # special case for boolean values
            args['tts'] = args['tts'] == 'true'

            # parse json from these string values
            args['styles'] = json.loads(args['styles'])
            args['conditions'] = json.loads(args['conditions'])

            streamer = StreamHelper.get_streamer()
            key = '{streamer}:clr:donations'.format(streamer=streamer)
            redis = RedisManager.get()
            redis.hset(key, widget_id, json.dumps(args))

            return {'message': 'GOT EM'}, 200
Exemple #54
0
def _load_secret_key(bot_id: str, streamer_id: str) -> str:
    from secrets import token_urlsafe

    from pajbot.managers.redis import RedisManager

    redis = RedisManager.get()

    key = f"web_secret_key:{bot_id}:{streamer_id}"

    value = redis.get(key)

    if value is None:
        value = token_urlsafe(64)
        redis.set(key, value, ex=SECRET_KEY_EXPIRY_SECONDS)

    return value
Exemple #55
0
 def load_cached_subemotes(redis_key):
     try:
         redis = RedisManager.get()
         redis_result = redis.get(redis_key)
         if redis_result is None:
             return None, None, None
         obj = {
             key: [Emote(**args) for args in value]
             for key, value in json.loads(redis_result).items()
         }
         return obj["1"], obj["2"], obj["3"]
     except:
         log.exception(
             "Failed to get subemotes from key {} from redis".format(
                 redis_key))
         return [], [], []
Exemple #56
0
    def on_user_win_hs_bet(self, user, points_won, **rest):
        if points_won < 1:
            return

        user_progress = self.get_user_progress(user, default=0)
        if user_progress >= self.hsbet_points_required:
            return

        user_progress += points_won

        redis = RedisManager.get()

        if user_progress >= self.hsbet_points_required:
            self.finish_quest(redis, user)

        self.set_user_progress(user, user_progress, redis=redis)
Exemple #57
0
    def update_emotes(self):
        base_url = 'https://twitchemotes.com/api_cache/v2/{0}.json'
        endpoints = [
            'global',
            'subscriber',
        ]

        twitch_emotes = {}
        twitch_subemotes = {}

        for endpoint in endpoints:
            log.debug('Refreshing {0} emotes...'.format(endpoint))

            try:
                data = requests.get(base_url.format(endpoint)).json()
            except ValueError:
                continue

            if 'channels' in data:
                for channel in data['channels']:
                    chan = data['channels'][channel]
                    # chan_id = chan['id']
                    emotes = chan['emotes']

                    emote_codes = []
                    pending_emotes = []

                    for emote in emotes:
                        emote_codes.append(emote['code'])
                        pending_emotes.append(emote)

                    prefix = os.path.commonprefix(emote_codes)
                    if len(prefix) > 1 and ''.join(
                            filter(lambda c: c.isalpha(), prefix)).islower():
                        for emote in pending_emotes:
                            twitch_emotes[emote['code']] = emote['image_id']
                            twitch_subemotes[emote['code']] = channel
            else:
                for code, emote_data in data['emotes'].items():
                    twitch_emotes[code] = emote_data['image_id']

        with RedisManager.pipeline_context() as pipeline:
            pipeline.delete('global:emotes:twitch_subemotes')
            pipeline.hmset('global:emotes:twitch', twitch_emotes)
            pipeline.hmset('global:emotes:twitch_subemotes', twitch_subemotes)

        self.subemotes = twitch_subemotes
Exemple #58
0
def donations(widget_id, **options):
    redis = RedisManager.get()
    widget = redis.hget(
        '{streamer}:clr:donations'.format(
            streamer=StreamHelper.get_streamer()), widget_id)
    if widget is None:
        abort(404)

    widget = json.loads(widget)

    # Assign indices to all styles and conditions
    i = 0
    log.info(widget['styles'])
    for style in widget['styles']:
        style['index'] = i
        i += 1
    log.info(widget['styles'])
    i = 0
    j = 0
    for condition in widget['conditions']:
        condition['index'] = i
        i += 1
        for style in condition['styles']:
            style['index'] = j
            j += 1
    log.info(widget)

    operator_order = {
        '==': 100,
        '>=': 50,
        '<=': 50,
    }

    widget['conditions'].sort(
        key=lambda c: (operator_order[c['operator']], c['amount']))

    tts_authentication = ''
    if 'extra' in config:
        tts_authentication = config['extra'].get('tts_authentication', '')

    with DBManager.create_session_scope() as db_session:
        emotes = db_session.query(Emote).join(EmoteStats).all()
        emotes.sort(key=lambda emote: len(emote.code), reverse=True)
        return render_template('clr/donations.html',
                               widget=widget,
                               emotes=emotes,
                               tts_authentication=tts_authentication)
Exemple #59
0
    def on_user_win_hs_bet(self, user, points_reward):
        # User needs to make 1 point profit at least
        # if points_reward < 1:
        #    return

        user_progress = self.get_user_progress(user.username, default=0)
        if user_progress >= self.get_limit():
            return

        user_progress += 1

        redis = RedisManager.get()

        if user_progress == self.get_limit():
            self.finish_quest(redis, user)

        self.set_user_progress(user.username, user_progress, redis=redis)
Exemple #60
0
    def refresh_stream_status_stage2(self, status):
        try:
            redis = RedisManager.get()

            redis.hmset(
                'stream_data', {
                    '{streamer}:online'.format(streamer=self.bot.streamer):
                    status['online'],
                    '{streamer}:viewers'.format(streamer=self.bot.streamer):
                    status['viewers'],
                    '{streamer}:game'.format(streamer=self.bot.streamer):
                    status['game'],
                })

            self.num_viewers = status['viewers']
            # log.debug('Loading stream data...')
            self.game = status['game']
            self.title = status['title']

            # log.debug('Game is now {} and title is now {}'.format(self.game, self.title))

            if status['online']:
                if self.current_stream is None:
                    self.create_stream(status)
                if self.current_stream_chunk is None:
                    self.create_stream_chunk(status)
                if self.current_stream_chunk.broadcast_id != status[
                        'broadcast_id']:
                    log.debug('Detected a new chunk!')
                    self.create_stream_chunk(status)

                self.num_offlines = 0
                self.first_offline = None
            else:
                if self.online is True:
                    log.info('Offline. {0}'.format(self.num_offlines))
                    if self.first_offline is None:
                        self.first_offline = datetime.datetime.now()

                    if self.num_offlines > 3:
                        log.info('Switching to offline state!')
                        self.go_offline()
                    self.num_offlines += 1
        except:
            log.exception(
                'Uncaught exception while refreshing stream status (Stage 2)')