def on_banphrase_update(self, data, conn): try: banphrase_id = int(data['id']) except (KeyError, ValueError): log.warn('No banphrase ID found in on_banphrase_update') return False updated_banphrase = find(lambda banphrase: banphrase.id == banphrase_id, self.banphrases) if updated_banphrase: with DBManager.create_session_scope(expire_on_commit=False) as db_session: db_session.add(updated_banphrase) db_session.refresh(updated_banphrase) db_session.expunge(updated_banphrase) else: with DBManager.create_session_scope(expire_on_commit=False) as db_session: updated_banphrase = db_session.query(Banphrase).filter_by(id=banphrase_id).one_or_none() db_session.expunge_all() if updated_banphrase is not None: self.db_session.add(updated_banphrase.data) if updated_banphrase: if updated_banphrase not in self.banphrases: self.banphrases.append(updated_banphrase) if updated_banphrase.enabled is True and updated_banphrase not in self.enabled_banphrases: self.enabled_banphrases.append(updated_banphrase) for banphrase in self.enabled_banphrases: if banphrase.enabled is False: self.enabled_banphrases.remove(banphrase)
def nl_pos(bot, source, message, event, args): # XXX: This should be a module # These phrases should be module settings nl_0 = '{username} has not typed any messages in this channel BibleThump' nl_pos = '{username} is rank {nl_pos} line-farmer in this channel!' if message: tmp_username = message.split(' ')[0].strip().lower() user = bot.users.find(tmp_username) if user: username = user.username_raw num_lines = user.num_lines else: username = tmp_username num_lines = 0 else: username = source.username_raw num_lines = source.num_lines phrase_data = { 'username': username, 'num_lines': num_lines } if num_lines <= 0: bot.say(nl_0.format(**phrase_data)) else: with DBManager.create_session_scope() as db_session: query_data = db_session.query(func.count(User.id)).filter(User.num_lines > num_lines).one() phrase_data['nl_pos'] = int(query_data[0]) + 1 bot.say(nl_pos.format(**phrase_data))
def commands(**options): from pajbot.models.module import ModuleManager bot_commands = pajbot.managers.command.CommandManager( socket_manager=None, module_manager=ModuleManager(None).load(), bot=None).load(enabled=None) bot_commands_list = bot_commands.parse_for_web() custom_commands = [] point_commands = [] moderator_commands = [] for command in bot_commands_list: if command.id is None: continue if command.level > 100 or command.mod_only: moderator_commands.append(command) elif command.cost > 0: point_commands.append(command) else: custom_commands.append(command) with DBManager.create_session_scope() as db_session: commands_data = db_session.query(CommandData).options(joinedload(CommandData.user), joinedload(CommandData.user2)).all() return render_template( 'admin/commands.html', commands_data=commands_data, custom_commands=sorted(custom_commands, key=lambda f: f.command), point_commands=sorted(point_commands, key=lambda a: (a.cost, a.command)), moderator_commands=sorted(moderator_commands, key=lambda c: (c.level if c.mod_only is False else 500, c.command)), created=session.pop('command_created_id', None), edited=session.pop('command_edited_id', None))
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 post(self, row_id, **options): args = self.post_parser.parse_args() try: new_state = int(args['new_state']) except (ValueError, KeyError): return {'error': 'Invalid `new_state` parameter.'}, 400 with DBManager.create_session_scope() as db_session: row = db_session.query(Module).filter_by(id=row_id).one_or_none() if not row: return { 'error': 'Module with this ID not found' }, 404 if validate_module(row_id) is False: return {'error': 'cannot modify module'}, 400 row.enabled = True if new_state == 1 else False db_session.commit() payload = { 'id': row.id, 'new_state': row.enabled, } AdminLogManager.post('Module toggled', options['user'], 'Enabled' if row.enabled else 'Disabled', row.id) SocketClientManager.send('module.update', payload) return {'success': 'successful toggle', 'new_state': new_state}
def post(self): args = self.post_parser.parse_args() try: pajbot.web.utils.pleblist_login(args['password'], app.bot_config) except pajbot.exc.InvalidLogin as e: return {'error': str(e)}, 401 with DBManager.create_session_scope() as session: try: current_song = session.query(PleblistSong).filter(PleblistSong.id == args['song_id']).order_by(PleblistSong.date_added.asc()).first() except ValueError: return { 'error': 'Invalid data song_id' }, 400 if current_song is None: return { 'error': 'No song active in the pleblist' }, 404 current_song.date_played = datetime.datetime.now() session.commit() # TODO: Add more data. # Was this song forcefully skipped? Or did it end naturally. return { 'success': 'got em!' }, 200
def points(): with DBManager.create_session_scope() as db_session: custom_web_content = db_session.query(WebContent).filter_by(page='points').first() custom_content = '' if custom_web_content and custom_web_content.content: try: custom_content = Markup(markdown.markdown(custom_web_content.content)) except: log.exception('Unhandled exception in def index') rank = 1 index = 1 last_user_points = -13333337 rankings = [] for user in db_session.query(User).order_by(User.points.desc()).limit(30): if user.points != last_user_points: rank = index rankings.append((rank, user)) index += 1 last_user_points = user.points return render_template('points.html', top_30_users=rankings, custom_content=custom_content)
def get_current_song(stream_id): with DBManager.create_session_scope() as session: cur_song = session.query(PleblistSong).filter(PleblistSong.stream_id == stream_id, PleblistSong.date_played.is_(None)).order_by(PleblistSong.date_added.asc(), PleblistSong.id.asc()).first() if cur_song is None: return None session.expunge(cur_song) return cur_song
def post(self): args = self.post_parser.parse_args() try: pajbot.web.utils.pleblist_login(args['password'], app.bot_config) except pajbot.exc.InvalidLogin as e: return {'error': str(e)}, 401 with DBManager.create_session_scope() as session: youtube_id = args['youtube_id'] current_stream = session.query(Stream).filter_by(ended=False).order_by(Stream.stream_start).first() if current_stream is None: return { 'error': 'Stream offline' }, 400 skip_after = args['skip_after'] log.info('Request song youtube ID: {}'.format(youtube_id)) song_requested = PleblistSong(current_stream.id, youtube_id, skip_after=skip_after) session.add(song_requested) song_info = session.query(PleblistSongInfo).filter_by(pleblist_song_youtube_id=youtube_id).first() if song_info is None and song_requested.song_info is None: PleblistManager.init(app.bot_config['youtube']['developer_key']) song_info = PleblistManager.create_pleblist_song_info(song_requested.youtube_id) if song_info is not False: session.add(song_info) session.commit() return { 'success': 'got em!' }, 200
def __init__(self, bot): self.bot = bot self.current_stream_chunk = None # should this even exist? self.num_offlines = 0 self.first_offline = None self.num_viewers = 0 self.bot.execute_every(self.STATUS_CHECK_INTERVAL, self.bot.action_queue.add, (self.refresh_stream_status_stage1, )) self.bot.execute_every(self.VIDEO_URL_CHECK_INTERVAL, self.bot.action_queue.add, (self.refresh_video_url_stage1, )) """ This will load the latest stream so we can post an accurate "time since last online" figure. """ with DBManager.create_session_scope(expire_on_commit=False) as db_session: self.current_stream = db_session.query(Stream).filter_by(ended=False).order_by(Stream.stream_start.desc()).first() self.last_stream = db_session.query(Stream).filter_by(ended=True).order_by(Stream.stream_end.desc()).first() if self.current_stream: self.current_stream_chunk = db_session.query(StreamChunk).filter_by(stream_id=self.current_stream.id).order_by(StreamChunk.chunk_start.desc()).first() log.info('Set current stream chunk here to {0}'.format(self.current_stream_chunk)) db_session.expunge_all()
def modules_edit(module_id, **options): module_manager = ModuleManager(None).load(do_reload=False) current_module = find(lambda m: m.ID == module_id, module_manager.all_modules) if current_module is None: return render_template('admin/module_404.html'), 404 sub_modules = [] for module in module_manager.all_modules: module.db_module = None with DBManager.create_session_scope() as db_session: for db_module in db_session.query(Module): module = find(lambda m: m.ID == db_module.id, module_manager.all_modules) if module: module.db_module = db_module if module.PARENT_MODULE == current_module.__class__: sub_modules.append(module) if current_module.db_module is None: return render_template('admin/module_404.html'), 404 if request.method == 'POST': form_values = {key: value for key, value in request.form.items()} res = current_module.parse_settings(**form_values) if res is False: return render_template('admin/module_404.html'), 404 current_module.db_module.settings = json.dumps(res) db_session.commit() settings = None try: settings = json.loads(current_module.db_module.settings) except (TypeError, ValueError): pass current_module.load(settings=settings) payload = { 'id': current_module.db_module.id, } SocketClientManager.send('module.update', payload) AdminLogManager.post('Module edited', options['user'], current_module.NAME) return render_template('admin/configure_module.html', module=current_module, sub_modules=sub_modules) else: settings = None try: settings = json.loads(current_module.db_module.settings) except (TypeError, ValueError): pass current_module.load(settings=settings) return render_template('admin/configure_module.html', module=current_module, sub_modules=sub_modules)
def point_pos(bot, source, message, event, args): # XXX: This should be a module user = None # This phrase should be a module setting point_pos = '{username_w_verb} rank {point_pos} point-hoarder in this channel with {points} points.' if message: tmp_username = message.split(' ')[0].strip().lower() user = bot.users.find(tmp_username) if not user: user = source phrase_data = { 'points': user.points } if user == source: phrase_data['username_w_verb'] = 'You are' else: phrase_data['username_w_verb'] = '{0} is'.format(user.username_raw) if user.points > 0: with DBManager.create_session_scope() as db_session: query_data = db_session.query(func.count(User.id)).filter(User.points > user.points).one() phrase_data['point_pos'] = int(query_data[0]) + 1 bot.whisper(source.username, point_pos.format(**phrase_data))
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')
def pleblist_history_stream(stream_id): with DBManager.create_session_scope() as session: stream = session.query(Stream).filter_by(id=stream_id).one_or_none() if stream is None: return render_template('pleblist_history_404.html'), 404 previous_stream = session.query(Stream).filter_by(id=stream_id - 1).one_or_none() next_stream = session.query(Stream).filter_by(id=stream_id + 1).one_or_none() q = session.query(PleblistSong, User).outerjoin(User, PleblistSong.user_id == User.id).filter(PleblistSong.stream_id == stream.id).order_by(PleblistSong.id.asc(), PleblistSong.id.asc()) songs = [] for song, user in q: song.user = user songs.append(song) total_length_left = sum([song.skip_after or song.song_info.duration if song.date_played is None and song.song_info is not None else 0 for song in songs]) first_unplayed_song = find(lambda song: song.date_played is None, songs) stream_chunks = session.query(StreamChunk).filter(StreamChunk.stream_id == stream.id).all() return render_template('pleblist_history.html', stream=stream, previous_stream=previous_stream, next_stream=next_stream, songs=songs, total_length_left=total_length_left, first_unplayed_song=first_unplayed_song, stream_chunks=stream_chunks)
def points_rank(self): if self.shared_db_session: query_data = self.shared_db_session.query(sqlalchemy.func.count(User.id)).filter(User.points > self.points).one() else: with DBManager.create_session_scope(expire_on_commit=False) as db_session: query_data = db_session.query(sqlalchemy.func.count(User.id)).filter(User.points > self.points).one() rank = int(query_data[0]) + 1 return rank
def sql_save(self, save_to_db=True): if not self.model_loaded: return if save_to_db and not self.shared_db_session: with DBManager.create_session_scope(expire_on_commit=False) as db_session: db_session.add(self.user_model) UserSQLCache.save(self.user_model)
def remove_highlight(self, id): """ Returns True if a highlight was removed, otherwise return False """ with DBManager.create_session_scope() as db_session: num_rows = db_session.query(StreamChunkHighlight).filter(StreamChunkHighlight.id == id).delete() return (num_rows == 1)
def banphrases_edit(banphrase_id, **options): with DBManager.create_session_scope() as db_session: banphrase = db_session.query(Banphrase).filter_by(id=banphrase_id).one_or_none() if banphrase is None: return render_template('admin/banphrase_404.html'), 404 return render_template('admin/create_banphrase.html', banphrase=banphrase)
def get(self, stream_id): with DBManager.create_session_scope() as session: songs = session.query(PleblistSong).filter_by(stream_id=stream_id) return pajbot.web.utils.jsonify_list( 'songs', songs, base_url=url_for(self.endpoint, stream_id=stream_id, _external=True), )
def remove_command(self, command): self.remove_command_aliases(command) with DBManager.create_session_scope() as db_session: self.db_session.expunge(command.data) db_session.delete(command.data) db_session.delete(command) self.rebuild()
def shared_close_predict(self, bot, source, type): with DBManager.create_session_scope() as db_session: # Check if there is a non-ended, but closed prediction run we can end current_prediction_run = db_session.query(PredictionRun).filter_by(ended=None, open=True, type=type).one_or_none() if current_prediction_run is None: bot.say('{}, There is no open prediction runs we can close right now.'.format(source.username_raw)) return True current_prediction_run.open = False bot.say('{}, Predictions are no longer accepted for prediction run {}'.format(source.username_raw, current_prediction_run.id))
def get(self, banphrase_id, **options): with DBManager.create_session_scope() as db_session: banphrase = db_session.query(Banphrase).filter_by(id=banphrase_id).one_or_none() if banphrase is None: return {'error': 'Invalid banphrase ID'}, 404 AdminLogManager.post('Banphrase removed', options['user'], banphrase.phrase) db_session.delete(banphrase) db_session.delete(banphrase.data) SocketClientManager.send('banphrase.remove', {'id': banphrase.id}) return {'success': 'good job'}, 200
def moderators(**options): with DBManager.create_session_scope() as db_session: moderator_users = db_session.query(User).filter(User.level > 100).order_by(User.level.desc()).all() userlists = collections.OrderedDict() userlists['Admins'] = list(filter(lambda user: user.level >= 2000, moderator_users)) userlists['Super Moderators/Broadcaster'] = list(filter(lambda user: user.level >= 1000 and user.level < 2000, moderator_users)) userlists['Moderators'] = list(filter(lambda user: user.level >= 500 and user.level < 1000, moderator_users)) userlists['Notables/Helpers'] = list(filter(lambda user: user.level >= 101 and user.level < 500, moderator_users)) return render_template('admin/moderators.html', userlists=userlists)
def predictions(**options): with DBManager.create_session_scope() as db_session: predictions = db_session.query(PredictionRun).order_by(PredictionRun.started.desc()).all() for prediction in predictions: prediction.num_entries = db_session.query(PredictionRunEntry).filter_by(prediction_run_id=prediction.id).count() pass return render_template('admin/predictions.html', predictions=predictions)
def follow_user(self, username): """Add `username` to our relevant_users list.""" if self.listener: if username not in self.listener.relevant_users: with DBManager.create_session_scope() as db_session: db_session.add(TwitterUser(username)) self.listener.relevant_users.append(username) log.info('Now following {0}'.format(username)) return True return False
def get_highlight_thumbnails(no_clue_what_this_does): from pajbot.web.models.thumbnail import StreamThumbnailWriter with DBManager.create_session_scope() as db_session: highlights = db_session.query(StreamChunkHighlight).filter_by(thumbnail=None).all() if len(highlights) > 0: log.info('Writing {} thumbnails...'.format(len(highlights))) StreamThumbnailWriter(app.bot_config['main']['streamer'], [h.id for h in highlights]) log.info('Done!') for highlight in highlights: highlight.thumbnail = True
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 refresh_video_url_stage2(self, data): if self.online is False: return if self.current_stream_chunk is None or self.current_stream is None: return log.info('Attempting to fetch video url for broadcast {0}'.format(self.current_stream_chunk.broadcast_id)) stream_chunk = self.current_stream_chunk if self.current_stream_chunk.video_url is None else None video_url, video_preview_image_url, video_recorded_at = self.fetch_video_url_stage2(data) if video_url is not None: log.info('Successfully fetched a video url: {0}'.format(video_url)) if self.current_stream_chunk is None or self.current_stream_chunk.video_url is None: with DBManager.create_session_scope(expire_on_commit=False) as db_session: self.current_stream_chunk.video_url = video_url self.current_stream_chunk.video_preview_image_url = video_preview_image_url db_session.add(self.current_stream_chunk) db_session.commit() db_session.expunge_all() log.info('Successfully commited video url data.') elif self.current_stream_chunk.video_url != video_url: # End current stream chunk self.current_stream_chunk.chunk_end = datetime.datetime.now() DBManager.session_add_expunge(self.current_stream_chunk) with DBManager.create_session_scope(expire_on_commit=False) as db_session: stream_chunk = StreamChunk(self.current_stream, self.current_stream_chunk.broadcast_id, video_recorded_at) self.current_stream_chunk = stream_chunk self.current_stream_chunk.video_url = video_url self.current_stream_chunk.video_preview_image_url = video_preview_image_url db_session.add(self.current_stream_chunk) db_session.commit() db_session.expunge_all() log.info('Successfully commited video url data in a new chunk.') else: log.info('Not video for broadcast found')
def shared_end_predict(self, bot, source, type): with DBManager.create_session_scope() as db_session: # Check if there is a non-ended, but closed prediction run we can end predictions = db_session.query(PredictionRun).filter_by(ended=None, open=False, type=type).all() if len(predictions) == 0: bot.say('{}, There is no closed prediction runs we can end right now.'.format(source.username_raw)) return True for prediction in predictions: prediction.ended = datetime.datetime.now() bot.say('Closed predictions with IDs {}'.format(', '.join([str(p.id) for p in predictions])))
def pleblist_history_redirect(): with DBManager.create_session_scope() as session: current_stream = session.query(Stream).filter_by(ended=False).order_by(Stream.stream_start.desc()).first() if current_stream is not None: return redirect('/pleblist/history/{}/'.format(current_stream.id), 303) last_stream = session.query(Stream).filter_by(ended=True).order_by(Stream.stream_start.desc()).first() if last_stream is not None: return redirect('/pleblist/history/{}/'.format(last_stream.id), 303) return render_template('pleblist_history_no_stream.html'), 404
def onMessage(self, payload, isBinary): if isBinary: log.info(f"Binary message received: {len(payload)} bytes") else: with DBManager.create_session_scope() as db_session: try: message = json.loads(payload) except: self.sendClose() return switcher = { "auth": self._auth, "next_song": self._next_song, "ready": self._ready } if ("event" in message and "data" in message and message["event"] in switcher and switcher[message["event"]]( db_session, message["data"])): pass else: self.sendClose()
def create_command(self, alias_str: str, **options: Any) -> Tuple[Command, bool, str]: aliases = alias_str.lower().replace("!", "").split("|") for alias in aliases: if alias in self.data: return self.data[alias], False, alias command = Command(command=alias_str, **options) command.data = CommandData(command.id, **options) self.add_db_command_aliases(command) with DBManager.create_session_scope( expire_on_commit=False) as db_session: db_session.add(command) db_session.add(command.data) db_session.commit() db_session.expunge(command) db_session.expunge(command.data) self.db_session.add(command.data) self.commit() self.rebuild() return command, True, ""
def onMessage(self, payload, isBinary): with DBManager.create_session_scope() as db_session: if not isBinary: try: json_msg = json.loads(payload) except: self._close_conn() return if "event" not in json_msg: self._close_conn() return switcher = { "AUTH": self._auth, "PAUSE": self._pause, "RESUME": self._resume, "NEXT": self._next, "PREVIOUS": self._previous, "SEEK": self._seek, "VOLUME": self._volume, "SHOWVIDEO": self._showvideo, "HIDEVIDEO": self._hidevideo, "CLOSESR": self._closesr, "OPENSR": self._opensr, "MOVE": self._move, "FAVOURITE": self._favourite, "UNFAVOURITE": self._unfavourite, "BAN": self._ban, "UNBAN": self._unban, "DELETE": self._delete, } method = switcher.get(json_msg["event"], None) if not manager_ext.bot.songrequest_manager.module_state[ "enabled"]: return if not method or not method( db_session, json_msg.get("data", None)): self._close_conn() return
def remove_playsound_command(bot, source, message, **rest): """Method for removing playsounds. Usage: !edit playsound PLAYSOUNDNAME """ playsound_name = message.split(" ")[0].lower() # check for empty string if not playsound_name: bot.whisper( source, "Invalid usage. Correct syntax: !remove playsound <name>") return with DBManager.create_session_scope() as session: playsound = session.query(Playsound).filter( Playsound.name == playsound_name).one_or_none() if playsound is None: bot.whisper(source, "No playsound with that name exists.") return session.delete(playsound) bot.whisper(source, "Successfully deleted your playsound.")
def go_offline(self) -> None: if self.current_stream is None or self.current_stream_chunk is None: return 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)
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: self.bot.say('dank__doge SoBayed') HandlerManager.trigger('on_stream_start', stop_on_false=False) log.info('Successfully created a stream')
def post(self): args = self.post_parser.parse_args() with DBManager.create_session_scope() as session: youtube_id = args['youtube_id'] log.info('Validating youtube ID {}'.format(youtube_id)) song_info = session.query(PleblistSongInfo).filter_by( pleblist_song_youtube_id=youtube_id).first() if song_info is not None: return {'message': 'success', 'song_info': song_info.jsonify()} PleblistManager.init(app.bot_config['youtube']['developer_key']) song_info = PleblistManager.create_pleblist_song_info(youtube_id) if not song_info and len(youtube_id) > 11: youtube_id = youtube_id[:11] song_info = session.query(PleblistSongInfo).filter_by( pleblist_song_youtube_id=youtube_id).first() if song_info is not None: return { 'message': 'success', 'new_youtube_id': youtube_id, 'song_info': song_info.jsonify() } else: song_info = PleblistManager.create_pleblist_song_info( youtube_id) if song_info: log.debug(song_info) session.add(song_info) session.commit() return { 'message': 'success', 'new_youtube_id': youtube_id, 'song_info': song_info.jsonify() } return {'message': 'invalid youtube id', 'song_info': None}
def edit_points(self, bot, source, message, **rest): if not message: return False msg_split = message.split(" ") if len(msg_split) < 2: # The user did not supply enough arguments bot.whisper(source, f"Usage: !{self.command_name} USERNAME POINTS") return False username_input = msg_split[0] try: num_points = int(msg_split[1]) except (ValueError, TypeError): # The user did not specify a valid integer for points bot.whisper( source, f"Invalid amount of points. Usage: !{self.command_name} USERNAME POINTS" ) return False with DBManager.create_session_scope() as db_session: user = User.find_by_user_input(db_session, username_input) if not user: bot.whisper(source, "This user does not exist FailFish") return False user.points += num_points if num_points >= 0: bot.whisper(source, f"Successfully gave {user} {num_points} points.") else: bot.whisper( source, f"Successfully removed {abs(num_points)} points from {user}." )
def post(self): args = self.post_parser.parse_args() with DBManager.create_session_scope() as session: youtube_id = args["youtube_id"] log.info(f"Validating youtube ID {youtube_id}") song_info = session.query(PleblistSongInfo).filter_by( pleblist_song_youtube_id=youtube_id).first() if song_info is not None: return {"message": "success", "song_info": song_info.jsonify()} PleblistManager.init(app.bot_config["youtube"]["developer_key"]) song_info = PleblistManager.create_pleblist_song_info(youtube_id) if not song_info and len(youtube_id) > 11: youtube_id = youtube_id[:11] song_info = session.query(PleblistSongInfo).filter_by( pleblist_song_youtube_id=youtube_id).first() if song_info is not None: return { "message": "success", "new_youtube_id": youtube_id, "song_info": song_info.jsonify() } else: song_info = PleblistManager.create_pleblist_song_info( youtube_id) if song_info: log.debug(song_info) session.add(song_info) session.commit() return { "message": "success", "new_youtube_id": youtube_id, "song_info": song_info.jsonify() } return {"message": "invalid youtube id", "song_info": None}
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] # TODO: Make this hideable through some magic setting (NOT config.ini @_@) with DBManager.create_session_scope() as db_session: data = { "top_5_duel_winners": db_session.query(UserDuelStats).order_by( UserDuelStats.duels_won.desc())[:5], "top_5_duel_points_won": db_session.query(UserDuelStats).order_by( UserDuelStats.profit.desc())[:5], "top_5_duel_points_lost": db_session.query(UserDuelStats).order_by( UserDuelStats.profit.asc())[:5], "top_5_duel_losers": db_session.query(UserDuelStats).order_by( UserDuelStats.duels_lost.desc())[:5], "top_5_duel_winrate": db_session.query(UserDuelStats).filter( UserDuelStats.duels_won >= 5).order_by( UserDuelStats.winrate.desc())[:5], "bottom_5_winrate": db_session.query(UserDuelStats).filter( UserDuelStats.duels_lost >= 5).order_by( UserDuelStats.winrate.asc())[:5], "top_5_commands": top_5_commands, "top_5_line_farmers": db_session.query(User).order_by( User.num_lines.desc()).limit(5).all(), } return render_template("stats.html", **data)
def authorized(): try: resp = twitch.authorized_response() except OAuthException: log.exception('An exception was caught while authorizing') next_url = get_next_url(request, 'state') return redirect(next_url) except: log.exception('Unhandled exception while authorizing') return render_template('login_error.html') print(resp) if resp is None: log.warn('Access denied: reason={}, error={}'.format( request.args['error'], request.args['error_description'])) next_url = get_next_url(request, 'state') return redirect(next_url) elif type(resp) is OAuthException: log.warn(resp.message) log.warn(resp.data) log.warn(resp.type) next_url = get_next_url(request, 'state') return redirect(next_url) session['twitch_token'] = (resp['access_token'], ) me = twitch.get('user') level = 100 with DBManager.create_session_scope() as db_session: db_user = db_session.query(User).filter_by( username=me.data['name'].lower()).one_or_none() if db_user: level = db_user.level session['user'] = { 'username': me.data['name'], 'username_raw': me.data['display_name'], 'level': level, } next_url = get_next_url(request, 'state') return redirect(next_url)
def create_highlight(self, **options): """ Returns an error message (string) if something went wrong, otherwise returns True """ if self.online is False or self.current_stream_chunk is None: return 'The stream is not online' if self.current_stream_chunk.video_url is None: return 'No video URL fetched for this chunk yet, try in 5 minutes' try: highlight = StreamChunkHighlight(self.current_stream_chunk, **options) with DBManager.create_session_scope( expire_on_commit=False) as db_session: db_session.add(highlight) db_session.add(self.current_stream_chunk) except: log.exception('uncaught exception in create_highlight') return 'Unknown reason, ask pajlada' return True
def remove_timeout(self, **options): bot = options["bot"] message = options["message"] source = options["source"] if not message: bot.whisper(source.username, "Invalid usage. !removetimeout user") return False with DBManager.create_session_scope() as session: remTimeout = session.query(LongTimeout).filter_by( username=message.split()[0]).one_or_none() if not remTimeout: bot.whisper(source.username, "User doesn't exist. See !listtimeouts") return False bot.whisper( source.username, "{}'s timeout of {} days has been cancelled.".format( remTimeout.username, (remTimeout.timeout_end - remTimeout.timeout_start).days)) session.delete(remTimeout)
def get_next_song(self, bot, source, message, **rest): with DBManager.create_session_scope() as db_session: next_song = SongrequestQueue._get_next_song(db_session) if next_song: m, s = divmod(next_song.playing_in(db_session), 60) m = int(m) s = int(s) playing_in = f"{m:02d}:{s:02d}" if next_song.requestor: bot.say( self.settings["message_in_chat_when_next_song"].format( title=next_song.song_info.title, requestor=next_song.requestor.username_raw, playing_in=playing_in, )) return True bot.say(self.settings["message_in_chat_when_next_song"].format( title=next_song.song_info.title, requestor="Backup Playlist", playing_in=playing_in)) return True bot.say(self.settings["message_in_chat_when_next_song_none"]) return True
def decline_duel(self, bot, source, **options): """ Declines any active duel requests you've received. How to use: !decline """ if source.id not in self.duel_targets: bot.whisper(source, "You are not being challenged to a duel") return False with DBManager.create_session_scope() as db_session: requestor = User.find_by_id(db_session, self.duel_targets[source.id]) bot.whisper(source, f"You have declined the duel vs {requestor}") bot.whisper(requestor, f"{source} declined the duel challenge with you.") del self.duel_targets[source.id] del self.duel_requests[requestor.id] del self.duel_request_price[requestor.id] del self.duel_begin_time[requestor.id]
def user_profile_connections_unpair(): with DBManager.create_session_scope() as db_session: if "user" not in session: return redirect(f"/login?n=/connections/") user = User.find_by_id(db_session, session["user"]["id"]) if user is None: return render_template("no_user.html"), 404 saved_data = db_session.query(UserConnections).filter_by( twitch_id=session["user"]["id"]).one_or_none() if not saved_data: return render_template("errors/403.html"), 403 redis = RedisManager.get() unlinked_accounts = redis.get("unlinks-subs-discord") if unlinked_accounts is None: unlinked_accounts = {} else: unlinked_accounts = json.loads(unlinked_accounts) unlinked_accounts[saved_data.twitch_id] = saved_data.jsonify() unlinked_accounts = redis.set("unlinks-subs-discord", json.dumps(unlinked_accounts)) saved_data._remove(db_session) db_session.commit() return redirect(f"/connections/")
def post(self, row_id, **options): args = self.post_parser.parse_args() try: new_state = int(args["new_state"]) except (ValueError, KeyError): return {"error": "Invalid `new_state` parameter."}, 400 with DBManager.create_session_scope() as db_session: row = db_session.query(Module).filter_by(id=row_id).one_or_none() if not row: return {"error": "Module with this ID not found"}, 404 if validate_module(row_id) is False: return {"error": "cannot modify module"}, 400 row.enabled = True if new_state == 1 else False db_session.commit() payload = {"id": row.id, "new_state": row.enabled} AdminLogManager.post("Module toggled", options["user"], "Enabled" if row.enabled else "Disabled", row.id) SocketClientManager.send("module.update", payload) return {"success": "successful toggle", "new_state": new_state}
def post(self): args = self.post_parser.parse_args() try: pajbot.web.utils.pleblist_login(args["password"], app.bot_config) except pajbot.exc.InvalidLogin as e: return {"error": str(e)}, 401 with DBManager.create_session_scope() as session: try: current_song = (session.query(PleblistSong).filter( PleblistSong.id == args["song_id"]).order_by( PleblistSong.date_added.asc()).first()) except ValueError: return {"error": "Invalid data song_id"}, 400 if current_song is None: return {"error": "No song active in the pleblist"}, 404 current_song.date_played = utils.now() session.commit() return {"success": "got em!"}, 200
def updatePoints(self, usdPoints, args): if args[0]["type"] != "donation": return False donation = args[0]["message"][0] if "historical" in donation: return False with DBManager.create_session_scope() as db_session: user = User.find_by_user_input(db_session, donation["name"]) if user is None: return False finalValue = int( float(donation["formatted_amount"][1:]) * int(usdPoints)) # formatted_amount changes to USD user.points = user.points + finalValue self.bot.whisper( user, f"You have been given {finalValue} points due to a donation in your name. If you want to see your donation, visit https://donations.admiralbulldog.live", )
def on_pubmsg(self, chatconn, event): tags = { tag["key"]: tag["value"] if tag["value"] is not None else "" for tag in event.tags } id = tags["user-id"] login = event.source.user name = tags["display-name"] if event.source.user == self.nickname: return False with DBManager.create_session_scope( expire_on_commit=False) as db_session: source = User.from_basics(db_session, UserBasics(id, login, name)) res = HandlerManager.trigger("on_pubmsg", source=source, message=event.arguments[0]) if res is False: return False self.parse_message(event.arguments[0], source, event, tags=tags)
def status_duel(self, bot, source, **rest): """ Whispers you the current status of your active duel requests/duel targets How to use: !duelstatus """ with DBManager.create_session_scope() as db_session: msg = [] if source.id in self.duel_requests: duelling = User.find_by_id(db_session, self.duel_requests[source.id]) msg.append(f"You have a duel request for {self.duel_request_price[source.id]} points by {duelling}") if source.id in self.duel_targets: challenger = User.find_by_id(db_session, self.duel_targets[source.id]) msg.append( f"You have a pending duel request from {challenger} for {self.duel_request_price[self.duel_targets[source.id]]} points" ) if len(msg) > 0: bot.whisper(source, ". ".join(msg)) else: bot.whisper(source, "You have no duel request or duel target. Type !duel USERNAME POT to duel someone!")
def request_function(self, video_id, requested_by, queue=None): if not self.enabled: return False with DBManager.create_session_scope() as db_session: requested_by = User.find_by_user_input(db_session, requested_by) if not requested_by: return False requested_by_id = requested_by.id song_info = SongRequestSongInfo._create_or_get( db_session, video_id, self.youtube) if not song_info: log.error("There was an error!") return False skip_after = (self.settings["max_song_length"] if song_info.duration > self.settings["max_song_length"] else None) song = SongrequestQueue._create(db_session, video_id, skip_after, requested_by_id) if queue: song._move_song(db_session, queue) db_session.commit() SongrequestQueue._update_queue() return True
def post(self, **options): args = self.post_parser.parse_args() with DBManager.create_session_scope() as db_session: twitter_user = db_session.query(TwitterUser).filter_by( username=args['username']).one_or_none() if twitter_user is not None: return { 'message': 'We are already following {}'.format(args['username']), }, 409 twitter_user = TwitterUser(args['username'].lower()) db_session.add(twitter_user) db_session.flush() db_session.commit() SocketClientManager.send('twitter.follow', {'username': args['username']}) return { 'message': 'Successfully followed {}'.format(args['username']), }, 200
def ban_function(self, database_id=None, hist_database_id=None): if not self.module_state["enabled"] or (not database_id and not hist_database_id): return False with DBManager.create_session_scope() as db_session: if database_id: song = SongrequestQueue._from_id(db_session, int(database_id)) else: song = SongrequestHistory._from_id(db_session, int(hist_database_id)) if song.song_info.banned: return False song.song_info.banned = True db_session.merge(song.song_info) SongrequestQueue._pruge_videos(db_session, song.video_id) db_session.commit() self._playlist() self._backup_playlist() self._playlist_history() self._favourite_list() self._banned_list() return True
def user_profile(username): with DBManager.create_session_scope() as db_session: user = UserManager.find_static(username, db_session=db_session) if not user: return render_template('no_user.html'), 404 try: roulette_stats, roulettes = get_roulette(app, user) except TypeError: roulette_stats = None roulettes = {} try: dotabet_stats, recent_bets = get_bets(app, user) except TypeError: dotabet_stats = None recent_bets = {} return render_template('user.html', user=user, roulette_stats=roulette_stats, dotabet_stats=dotabet_stats, roulettes=roulettes, bets=recent_bets)
def _cancel_expired_duels(self): now = utils.now() for source_id, started_at in self.duel_begin_time.items(): duel_age = now - started_at if duel_age <= timedelta(minutes=self.settings["max_duel_age"]): # Duel is not too old continue with DBManager.create_session_scope() as db_session: source = User.find_by_id(db_session, source_id) challenged = User.find_by_id(db_session, self.duel_requests[source.id]) if source is not None and challenged is not None: self.bot.whisper( source, f"{challenged} didn't accept your duel request in time, so the duel has been cancelled." ) del self.duel_targets[self.duel_requests[source.id]] del self.duel_requests[source.id] del self.duel_request_price[source.id] del self.duel_begin_time[source.id]
def load(self, do_reload=True): """ Load module classes """ from pajbot.modules import available_modules self.all_modules = [module(self.bot) for module in available_modules] with DBManager.create_session_scope() as db_session: # Make sure there's a row in the DB for each module that's available db_modules = db_session.query(Module).all() for module in self.all_modules: mod = find(lambda db_module, registered_module=module: db_module.id == registered_module.ID, db_modules) if mod is None: log.info(f"Creating row in DB for module {module.ID}") mod = Module(module.ID, enabled=module.ENABLED_DEFAULT) db_session.add(mod) if do_reload is True: self.reload() return self
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")
def level(bot, source, message, **rest): if not message: bot.whisper(source, "Usage: !level USERNAME NEW_LEVEL") return False msg_args = message.split(" ") if len(msg_args) < 2: return False username = msg_args[0].lower() new_level = int(msg_args[1]) if new_level >= source.level: bot.whisper(source, f"You cannot promote someone to the same or higher level as you ({source.level}).") return False # We create the user if the user didn't already exist in the database. with DBManager.create_session_scope() as db_session: user = User.find_or_create_from_user_input(db_session, bot.twitch_helix_api, username) if user is None: bot.whisper(source, f'A user with the name "{username}" could not be found.') return False if user.level >= source.level: bot.whisper( source, f"You cannot change the level of someone who is the same or higher level than you. You are level {source.level}, and {username} is level {user.level}", ) return False old_level = user.level user.level = new_level log_msg = f"{user}'s user level changed from {old_level} to {new_level}" bot.whisper(source, log_msg) AdminLogManager.add_entry("Userlevel edited", source, log_msg)
def __init__(self, bot): self.bot = bot self.current_stream_chunk = None # should this even exist? self.num_offlines = 0 self.first_offline = None self.num_viewers = 0 self.game = 'Loading...' self.title = 'Loading...' self.bot.execute_every(self.STATUS_CHECK_INTERVAL, self.bot.action_queue.add, (self.refresh_stream_status_stage1, )) self.bot.execute_every(self.VIDEO_URL_CHECK_INTERVAL, self.bot.action_queue.add, (self.refresh_video_url_stage1, )) """ This will load the latest stream so we can post an accurate "time since last online" figure. """ with DBManager.create_session_scope( expire_on_commit=False) as db_session: self.current_stream = db_session.query(Stream).filter_by( ended=False).order_by(Stream.stream_start.desc()).first() self.last_stream = db_session.query(Stream).filter_by( ended=True).order_by(Stream.stream_end.desc()).first() if self.current_stream: self.current_stream_chunk = db_session.query( StreamChunk).filter_by( stream_id=self.current_stream.id).order_by( StreamChunk.chunk_start.desc()).first() log.info('Set current stream chunk here to {0}'.format( self.current_stream_chunk)) db_session.expunge_all()