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'])
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)
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)
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']
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()
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)
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()
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)
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)
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)
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)')
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)
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)
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) }
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)
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) }
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
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 {}
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 = []
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()
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
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
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
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)
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
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)
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))
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()
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
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)
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))
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
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)
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()
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))
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))
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)
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
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))
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()
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
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
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
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)
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)
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)
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()
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()
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))
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)
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)
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
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
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 [], [], []
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)
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
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)
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)
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)')