class Collection_handler(Api_handler): __schema__ = good.Schema(__schema__) @Level(1) async def post(self, channel_id): data = self.validate() data['channel_id'] = channel_id data['created_at'] = datetime.utcnow() data['updated_at'] = datetime.utcnow() data['next_run'] = datetime.utcnow()+timedelta(minutes=data.get('interval', 5)) if 'messages' in data: data['messages'] = utils.json_dumps(data['messages']) fields = ','.join(['`'+f+'`' for f in data]) values = ','.join(['%s' for f in data]) interval = data.get('interval', 5) r = await self.db.execute( 'INSERT INTO twitch_timers ({}) VALUES ({})'.format(fields, values), list(data.values()) ) t = await get_timer(self, channel_id, r.lastrowid) if not t: raise Api_exception(400, 'Unknown timer') self.set_status(201) self.write_object(t) @Level(1) async def get(self, channel_id): timers = await self.db.fetchall( 'SELECT * FROM twitch_timers WHERE channel_id=%s', (channel_id,) ) for t in timers: t.pop('messages') self.write_object(timers)
class Handler(base.Handler): '''Edit a play server. The user must be the owner.''' __schema__ = good.Schema(_schema, default_keys=good.Optional) @authenticated(0) async def get(self, id_): server = await self._get(id_) self.write_object(server) @authenticated(0) async def put(self, id_): ps = await self._put(id_) self.write_object(ps) @authenticated(0) async def delete(self, id_): await self._delete(id_) self.set_status(204) @run_on_executor def _get(self, id_): with new_session() as session: q = session.query(models.Play_server).filter( models.Play_server.id == id_, models.Play_server.user_id == self.current_user.id, ).options(sa.orm.undefer_group('secret')).first() if not q: raise exceptions.Not_found('play server not found') return q.serialize() @run_on_executor def _put(self, id_): data = self.validate() if 'url' in data: data['url'] = data['url'].rstrip('/') with new_session() as session: ps = session.query(models.Play_server).filter( models.Play_server.id == id_, models.Play_server.user_id == self.current_user.id, ).options(sa.orm.undefer_group('secret')).first() if not ps: raise exceptions.Not_found('play server not found') self.update_model(ps, data, overwrite=True) session.commit() ps = session.query(models.Play_server).options( sa.orm.undefer_group('secret')).get(ps.id) return ps.serialize() @run_on_executor def _delete(self, id_): with new_session() as session: ps = session.query(models.Play_server).filter( models.Play_server.id == id_, models.Play_server.user_id == self.current_user.id, ).first() if not ps: raise exceptions.Not_found('play server not found') session.delete(ps) session.commit()
def validate_schema(schema, data, **kwargs): """Validates `schema` against `data`. Returns the data modified by the validator. ``schema`` can be a dict or an instance of `good.Schema`. If it's a dict a `good.Schema` instance will be created from it. Raises `Validation_exception` """ try: if not isinstance(schema, good.Schema): schema = good.Schema(schema, **kwargs) return schema(data) except good.MultipleInvalid as ee: data = [] for e in ee: data.append({ 'field': u'.'.join(str(x) for x in e.path), 'message': e.message, }) raise Validation_exception(errors=data) except good.Invalid as e: data = [{ 'field': u'.'.join(str(x) for x in e.path), 'message': e.message, }] raise Validation_exception(errors=data)
class Handler(Api_handler): __schema__ = good.Schema({ 'length': good.Coerce(int), }) @Level(3) async def post(self, channel_id): data = self.validate() try: data = await twitch_channel_token_request( self, channel_id=channel_id, url='https://api.twitch.tv/helix/channels/commercial', method='POST', json={ 'broadcaster_id': channel_id, 'length': data['length'], }) self.write({ 'retry_after': data['data'][0]['retry_after'], 'message': data['data'][0]['message'], }) except Twitch_request_error as e: raise Api_exception(e.status_code, e.message)
class Collection_handler(Api_handler): __schema__ = good.Schema(_schema, default_keys=good.Required) @Level(1) async def get(self, channel_id): cmds = await self.db.fetchall( ''' SELECT * FROM twitch_commands WHERE channel_id=%s ORDER BY updated_at DESC ''', (channel_id, )) self.write_object(cmds) @Level(1) async def post(self, channel_id): data = self.validate() data['channel_id'] = channel_id data['created_at'] = datetime.utcnow() data['updated_at'] = datetime.utcnow() fields = ','.join([f for f in data]) vfields = ','.join(['%s' for f in data]) values = list(data.values()) c = await self.db.execute( 'INSERT INTO twitch_commands ({}) VALUES ({})'.format( fields, vfields), values) cmd = await get_command(self, channel_id, c.lastrowid) self.set_status(201) self.write_object(cmd)
class Pagination_handler(Handler): __arguments_schema__ = good.Schema({ 'per_page': good.Any( good.All( [good.All(good.Coerce(int), good.Range(min=1))], good.Length(max=1), ), good.Default([constants.PER_PAGE]) ), 'page': good.Any( good.All( [good.All(good.Coerce(int), good.Range(min=1))], good.Length(max=1), ), good.Default([1]) ), }, default_keys=good.Required, extra_keys=good.Allow,) def get(self, *args, **kwargs): args = self.validate_arguments(Pagination_handler.__arguments_schema__) self.per_page = args.pop('per_page', [0])[0] self.page = args.pop('page', [0])[0] self.request.arguments.pop('per_page', None) self.request.arguments.pop('page', None)
class Handler(base.Handler): __schema__ = good.Schema( { 'subtitle_lang': good.Maybe(good.All(good.Lower(), good.Length(min=1, max=20))), 'audio_lang': good.Maybe(good.All(good.Lower(), good.Length(min=1, max=20))) }, default_keys=good.Optional) @authenticated(constants.LEVEL_USER) def get(self, show_id): data = models.User_show_subtitle_lang.get( user_id=self.current_user.id, show_id=show_id, ) if data: self.write_object(data) else: self.set_status(204) @authenticated(constants.LEVEL_USER) async def put(self, show_id): await self._put(show_id) self.set_status(204) @run_on_executor def _put(self, show_id): data = self.validate() with new_session() as session: d = models.User_show_subtitle_lang( user_id=self.current_user.id, show_id=show_id, subtitle_lang=data.get('subtitle_lang', None), audio_lang=data.get('audio_lang', None), ) session.merge(d) session.commit() @authenticated(constants.LEVEL_USER) async def patch(self, show_id): await self._patch(show_id) self.set_status(204) @run_on_executor def _patch(self, show_id): data = self.validate() with new_session() as session: d = models.User_show_subtitle_lang( user_id=self.current_user.id, show_id=show_id, ) if 'subtitle_lang' in data: d.subtitle_lang = data['subtitle_lang'] if 'audio_lang' in data: d.audio_lang = data['audio_lang'] session.merge(d) session.commit()
class Collection_handler(base.Handler): __schema__ = good.Schema({ 'name': good.All( str, good.Length(min=1, max=45), good.Match(re.compile(r'^[a-z0-9-_]+$', re.I), message='must only contain a-z, 0-9, _ and -')), 'email': good.All(str, good.Length(min=1, max=100), schemas.validate_email), 'password': good.All(str, good.Length(min=6)), }) async def get(self): users = await self.get_users() self.write_object(users) async def post(self, user_id=None): if user_id: raise exceptions.Parameter_restricted('user_id must not be set.') user = await self.create() self.set_status(201) self.write_object(user) @run_on_executor def get_users(self): username = self.get_argument('username') with new_session() as session: user = session.query(models.User).filter( models.User.name == username, ).first() if user: return [self.user_wrapper(user.serialize())] return [] @run_on_executor def create(self): user = self.validate() with new_session() as session: u = session.query(models.User.id).filter( models.User.email == user['email']).first() if u: raise exceptions.User_email_duplicate() u = session.query(models.User.id).filter( models.User.name == user['name']).first() if u: raise exceptions.User_username_duplicate() user = models.User( name=user['name'], email=user['email'], password=pbkdf2_sha256.encrypt(user['password']), ) session.add(user) session.commit() return user.serialize()
class Slots_handler(Api_handler): __schema__ = good.Schema({ 'emote_pool_size': good.All(good.Coerce(int), good.Range(min=2)), 'payout_percent': good.All(good.Coerce(int), good.Range(min=1)), 'min_bet': good.All(good.Coerce(int), good.Range(min=1)), 'max_bet': good.All(good.Coerce(int), good.Range(min=0)), 'emotes': [str], 'win_message': good.All(good.Coerce(str), good.Length(min=1, max=250)), 'allin_win_message': good.All(good.Coerce(str), good.Length(min=1, max=250)), 'lose_message': good.All(good.Coerce(str), good.Length(min=1, max=250)), 'allin_lose_message': good.All(good.Coerce(str), good.Length(min=1, max=250)), }) async def get(self, channel_id): settings = await self.db.fetchone( 'select * from twitch_gambling_slots_settings where channel_id=%s', (channel_id), ) if not settings: self.set_status(204) else: settings.pop('channel_id') settings['emotes'] = json.loads(settings['emotes']) self.write_object(settings) @Level(3) async def put(self, channel_id): data = self.validate() if 'emotes' in data: data['emotes'] = json.dumps(data['emotes']) fields = ','.join([f for f in data]) values = ','.join(['%s' for f in data]) dup = ','.join([f'{f}=VALUES({f})' for f in data]) await self.db.execute( f''' INSERT INTO twitch_gambling_slots_settings (channel_id, {fields}) VALUES (%s, {values}) ON DUPLICATE KEY UPDATE {dup} ''', ( channel_id, *data.values(), )) self.set_status(204)
def validate(inputs, state, outputs): """ Validate the data structures for this vertex. """ inputs_schema = good.Schema({'ctrl': good.Any(), 'stt': good.Any()}) state_schema = good.Schema({}) outputs_schema = good.Schema({ 'ltt': good.Any(), 'diag': good.Any(), 'slog': good.Any(), 'elog': good.Any() }) inputs_schema(inputs) state_schema(state) outputs_schema(outputs)
class Handler(base.Handler): __schema__ = good.Schema({ 'rating': good.All(int, good.Range(min=1, max=10)), }) @authenticated(0) async def put(self, show_id): await self.save(show_id) self.set_status(204) @authenticated(0) async def get(self, show_id): r = await self.get_rating(show_id) self.write_object(r) @authenticated(0) async def delete(self, show_id): await self.delete_rating(show_id) self.set_status(204) @run_on_executor def save(self, show_id): d = self.validate() with new_session() as session: r = models.User_show_rating( show_id=show_id, user_id=self.current_user.id, rating=d['rating'], updated_at=datetime.utcnow(), ) session.merge(r) session.commit() @run_on_executor def get_rating(self, show_id): with new_session() as session: r = session.query(models.User_show_rating.rating).filter( models.User_show_rating.user_id == self.current_user.id, models.User_show_rating.show_id == show_id, ).first() return { 'rating': r.rating if r else None, } @run_on_executor def delete_rating(self, show_id): with new_session() as session: session.query(models.User_show_rating).filter( models.User_show_rating.user_id == self.current_user.id, models.User_show_rating.show_id == show_id, ).delete() session.commit()
def __init__(self, schema, required=False, extra=PREVENT_EXTRA): self.schema = schema self.required = required self.extra = extra try: # It's a callable anyway, let it be here self._compiled = good.Schema( schema, default_keys=self._required_arg_map[required], extra_keys=self._extra_arg_map[extra]) except good.SchemaError as e: raise SchemaError(e.message)
class Handler(Api_handler): __schema__ = good.Schema({ 'message': good.All(str, good.Length(min=1, max=500)), 'webhook_url': good.Any(good.Url('https'), good.All(str, good.Length(max=0))), }) @Level(3) async def get(self, channel_id): r = await self.db.fetchone( 'SELECT webhook_url, message FROM twitch_discord_live_notification WHERE channel_id=%s', (channel_id, )) if not r: self.set_status(204) else: self.write_object({ 'webhook_url': r['webhook_url'], 'message': r['message'], }) @Level(3) async def put(self, channel_id): data = self.validate() r = await self.db.fetchone( 'SELECT webhook_url, message FROM twitch_discord_live_notification WHERE channel_id=%s', (channel_id, )) if not r: await self.db.execute( ''' INSERT INTO twitch_discord_live_notification (channel_id, webhook_url, message) VALUES (%s, %s, %s); ''', ( channel_id, data['webhook_url'], data['message'], )) else: await self.db.execute( ''' UPDATE twitch_discord_live_notification SET webhook_url=%s, message=%s WHERE channel_id=%s ''', ( data['webhook_url'], data['message'], channel_id, ))
class Handler(Api_handler): __schema__ = good.Schema({ str: [{ 'message': good.All(str, good.Length(min=0, max=200)), good.Optional('min_amount'): good.All(good.Coerce(int), good.Range(min=0, max=1000)), }], }, default_keys=good.Optional) @Level(1) async def get(self, channel_id): alerts = await self.db.fetchall( 'SELECT type, message, min_amount FROM twitch_chat_alerts WHERE channel_id=%s', (channel_id,) ) grouped_alerts = {} for a in alerts: l = grouped_alerts.setdefault(a['type'], []) l.append({ 'message': a['message'], 'min_amount': a['min_amount'] or 0, }) self.write_object(grouped_alerts) @Level(1) async def put(self, channel_id): data = self.validate() for key in data: ins = [] for d in data[key]: if d['message']: ins.append(( channel_id, key, d['message'], d.get('min_amount', 0), )) await self.db.execute( 'DELETE FROM twitch_chat_alerts WHERE channel_id=%s AND type=%s;', (channel_id, key,) ) if ins: await self.db.executemany(''' INSERT INTO twitch_chat_alerts (channel_id, type, message, min_amount) VALUES (%s, %s, %s, %s) ''', ins ) await self.get(channel_id)
class Banned_words_handler(Api_handler): __schema__ = good.Schema({ 'banned_words': good.All(str, good.Length(min=1, max=1000)), }) @Level(1) async def post(self, channel_id, filter_id): d = self.validate() c = await self.db.execute(''' INSERT INTO twitch_filter_banned_words (channel_id, filter_id, banned_words) VALUES (%s, %s, %s) ''', (channel_id, filter_id, d['banned_words'])) r = await self.redis.publish_json( 'tbot:server:commands', ['reload_filter_banned_words', channel_id, filter_id] ) self.set_status(201) self.write_object({ 'id': c.lastrowid, 'banned_words': d['banned_words'], }) @Level(1) async def put(self, channel_id, filter_id, id_): d = self.validate() await self.db.execute(''' UPDATE twitch_filter_banned_words SET banned_words=%s WHERE id=%s and channel_id=%s and filter_id=%s ''', (d['banned_words'], id_, channel_id, filter_id,)) r = await self.redis.publish_json( 'tbot:server:commands', ['reload_filter_banned_words', channel_id, filter_id] ) self.set_status(204) @Level(1) async def delete(self, channel_id, filter_id, id_): await self.db.execute(''' DELETE FROM twitch_filter_banned_words WHERE id=%s and channel_id=%s and filter_id=%s ''', (id_, channel_id, filter_id,)) r = await self.redis.publish_json( 'tbot:server:commands', ['reload_filter_banned_words', channel_id, filter_id] ) self.set_status(204)
def validate(inputs, state, outputs): """ Validate the data structures for this vertex. """ inputs_schema = good.Schema({ 'cfg': { 'enable_ui': bool }, 'ctrl': {}, 'ctk': good.Any(), 'vid': good.Any(), 'diag': good.Any(), 'slog': good.Any(), 'elog': good.Any() }) state_schema = good.Schema({}) outputs_schema = good.Schema({}) inputs_schema(inputs) state_schema(state) outputs_schema(outputs)
class Banned_words_test_handler(Api_handler): __schema__ = good.Schema({ 'message': str, }) @Level(1) async def post(self, channel_id, filter_id): d = self.validate() banned_words = await self.db.fetchall(''' SELECT banned_words FROM twitch_filter_banned_words WHERE channel_id=%s AND filter_id=%s ''', (channel_id, filter_id,)) self.write_object({ 'match': utils.check_message(d['message'], [bw['banned_words'] for bw in banned_words]) })
class Collection_handler(base.Pagination_handler): '''List of play servers that the user is owner of''' __schema__ = good.Schema(_schema) @authenticated(0) async def get(self): super().get() servers = await self._get() self.write_object(servers) @authenticated(0) async def post(self): ps = await self._post() self.set_status(201) self.write_object(ps) @run_on_executor def _get(self): with new_session() as session: p = session.query(models.Play_server).filter( models.Play_server.user_id == self.current_user.id, ).order_by( models.Play_server.name).paginate( page=self.page, per_page=self.per_page, ) p.records = [r.serialize() for r in p.records] return p @run_on_executor def _post(self): data = self.validate() if 'url' in data: data['url'] = data['url'].rstrip('/') with new_session() as session: ps = models.Play_server(user_id=self.current_user.id, **data) session.add(ps) session.commit() ps = session.query(models.Play_server).options( sa.orm.undefer_group('secret')).get(ps.id) return ps.serialize()
class Handler(Api_handler): __schema__ = good.Schema(_schema, default_keys=good.Optional) @Level(1) async def get(self, channel_id, id_): cmd = await get_command(self, channel_id, id_) if not cmd: self.set_status(404) self.write_object({'error': 'Unknown command'}) else: self.write_object(cmd) @Level(1) async def put(self, channel_id, id_): data = self.validate() data['updated_at'] = datetime.utcnow() fields = ','.join(['{}=%s'.format(k) for k in data]) values = list(data.values()) values.append(channel_id) values.append(id_) await self.db.execute( 'UPDATE twitch_commands SET {} WHERE channel_id=%s AND id=%s'. format(fields), values) cmd = await get_command(self, channel_id, id_) self.write_object(cmd) @Level(1) async def delete(self, channel_id, id_): cmd = await self.db.execute( ''' DELETE FROM twitch_commands WHERE channel_id=%s and id=%s ''', ( channel_id, id_, )) self.set_status(204)
class Handler(Api_handler): __schema__ = good.Schema(__schema__, default_keys=good.Optional) @Level(1) async def put(self, channel_id, id_): data = self.validate() data['updated_at'] = datetime.utcnow() if 'interval' in data: data['next_run'] = datetime.utcnow()+timedelta(minutes=data['interval']) if 'messages' in data: data['messages'] = utils.json_dumps(data['messages']) fields = ', '.join(['`{}`=%s'.format(k) for k in data]) values = list(data.values()) values.append(channel_id) values.append(id_) await self.db.execute( 'UPDATE twitch_timers SET {} WHERE channel_id=%s AND id=%s'.format(fields), values ) t = await get_timer(self, channel_id, id_) self.write_object(t) @Level(1) async def get(self, channel_id, id_): t = await get_timer(self, channel_id, id_) if not t: raise Api_exception(404, 'Unknown timer') self.write_object(t) @Level(1) async def delete(self, channel_id, id_): t = await self.db.execute( 'DELETE FROM twitch_timers WHERE channel_id=%s AND id=%s', (channel_id, id_,) ) self.set_status(204)
class Change_password_handler(base.Handler): __schema__ = good.Schema({ 'password': str, 'new_password': good.All(str, good.Length(min=6)), }) @authenticated(constants.LEVEL_USER) async def post(self, user_id=None): user_id = user_id if user_id else self.current_user.id self.check_user_edit(user_id) await self.change_password(user_id) self.set_status(204) @run_on_executor def change_password(self, user_id): data = self.validate() if not models.User.login(int(user_id), data['password']): raise exceptions.Wrong_email_or_password_exception() with new_session() as session: models.User.change_password( user_id=user_id, new_password=data['new_password'], session=session, ) tokens = session.query(models.Token).filter( models.Token.user_id == user_id, or_( models.Token.expires >= datetime.utcnow(), models.Token.expires == None, )).all() for token in tokens: if token.token == self.access_token: continue session.delete(token) session.commit()
class Channel_admins(Api_handler): __schema__ = good.Schema({ 'user': good.All(str, good.Length(min=4, max=25)), 'level': good.All(good.Coerce(int), good.Range(min=1, max=3)), }) __update_schema__ = good.Schema({ 'level': good.All(good.Coerce(int), good.Range(min=1, max=3)), }) @Level(3) async def get(self, channel_id): admins = await self.db.fetchall( ''' SELECT user_id as id, user as name, level FROM twitch_channel_admins WHERE channel_id=%s ORDER BY level DESC ''', (channel_id, )) self.write_object(admins) @Level(3) async def post(self, channel_id): data = self.validate() url = 'https://api.twitch.tv/helix/users' users = await twitch_request(self.ahttp, url, { 'login': data['user'], }) if not users['data']: raise Api_exception(400, 'User does not exist on Twitch') user = users['data'][0] await self.db.execute( ''' INSERT INTO twitch_channel_admins (channel_id, user_id, user, level, created_at, updated_at) VALUES (%s, %s, %s, %s, now(), now()) ON DUPLICATE KEY UPDATE user=VALUES(user), level=VALUES(level), updated_at=VALUES(updated_at) ''', (channel_id, user['id'], user['display_name'], data['level'])) self.set_status(204) @Level(3) async def put(self, channel_id, user_id): data = self.validate(self.__update_schema__) await self.db.execute( 'UPDATE twitch_channel_admins SET level=%s WHERE channel_id=%s AND user_id=%s', (data['level'], channel_id, user_id)) @Level(3) async def delete(self, channel_id, user_id): await self.db.execute( 'DELETE FROM twitch_channel_admins WHERE channel_id=%s AND user_id=%s', (channel_id, user_id)) self.set_status(204)
class Handler(base.Pagination_handler): __arguments_schema__ = good.Schema( { 'genre': [str], 'expand': [str], 'sort': [str], }, default_keys=good.Optional, extra_keys=good.Allow) async def get(self, user_id): user_id = self.user_id_or_current(user_id) super().get() r = await self.get_shows(user_id) self.write_object(r) @run_on_executor def get_shows(self, user_id): args = self.validate_arguments() with new_session() as session: elw = models.Episode_watching ew = models.Episode_watched query = session.query( models.Show, models.Episode_watched, models.Episode, ).filter( elw.user_id == user_id, ew.user_id == elw.user_id, ew.show_id == elw.show_id, ew.episode_number == elw.episode_number, models.Show.id == elw.show_id, models.Episode.show_id == elw.show_id, models.Episode.number == elw.episode_number, ) sort = args.get('sort', ['watched_at'])[0] if sort == 'user_rating': query = query.outerjoin( (models.User_show_rating, sa.and_( models.User_show_rating.show_id == models.Show.id, models.User_show_rating.user_id == user_id, ))).order_by(sa.desc(models.User_show_rating.rating), sa.desc(ew.watched_at), sa.desc(elw.show_id)) else: query = query.order_by(sa.desc(ew.watched_at), sa.desc(elw.show_id)) genres = list(filter(None, args.get('genre', []))) if genres: query = query.filter( models.Show_genre.show_id == models.Show.id, models.Show_genre.genre.in_(genres), ) p = query.paginate(self.page, self.per_page) records = [] for r in p.records: d = r.Show.serialize() d['user_watching'] = r.Episode_watched.serialize() d['user_watching']['episode'] = r.Episode.serialize() records.append(d) expand = args.get('expand', []) if 'user_rating' in expand: self.expand_user_rating(records, user_id) p.records = records return p
class Points_settings_handler(Api_handler): __schema__ = good.Schema({ 'enabled': good.Boolean(), 'points_name': good.All(str, good.Length(min=1, max=45)), 'points_per_min': good.All(good.Coerce(int), good.Range(min=0)), 'points_per_min_sub_multiplier': good.All(good.Coerce(int), good.Range(min=0)), 'points_per_sub': good.All(good.Coerce(int), good.Range(min=0)), 'points_per_cheer': good.All(good.Coerce(int), good.Range(min=0)), 'ignore_users': [str], }) async def get(self, channel_id): settings = await self.db.fetchone( 'select * from twitch_channel_point_settings where channel_id=%s', (channel_id), ) if not settings: self.set_status(204) else: self.write_object({ 'enabled': True if settings['enabled'] == 1 else False, 'points_name': settings['points_name'], 'points_per_min': settings['points_per_min'], 'points_per_min_sub_multiplier': settings['points_per_min_sub_multiplier'], 'points_per_sub': settings['points_per_sub'], 'points_per_cheer': settings['points_per_cheer'], 'ignore_users': json.loads(settings['ignore_users']), }) @Level(3) async def put(self, channel_id): data = self.validate() if 'ignore_users' in data: data['ignore_users'] = json.dumps(data['ignore_users']) fields = ','.join([f for f in data]) values = ','.join(['%s' for f in data]) dup = ','.join([f'{f}=VALUES({f})' for f in data]) await self.db.execute( f''' INSERT INTO twitch_channel_point_settings (channel_id, {fields}) VALUES (%s, {values}) ON DUPLICATE KEY UPDATE {dup} ''', ( channel_id, *data.values(), )) self.set_status(204)
""" SELECT * FROM bot %s ORDER BY bot_id ASC LIMIT %%s OFFSET %%s """ % where, *params) def get_bot(bot_id): with db.connect() as c: return c.get( """ SELECT * FROM bot WHERE bot_id = %s """, bot_id) @endpoint("bot/query", G.Schema({ "name": G.Maybe(str), "page": G.Any(int, G.Default(0), G.Range(0, 999)), "page_size": G.Any(int, G.Default(100), G.Range(1, 200)) })) def bot_query(params): return query_bots(**params) @endpoint("bot/get", G.Schema({"bot_id": int})) def bot_get(params): return get_bot(params.bot_id)
def validate_email(email): """Validate email.""" if not "@" in email: raise good.Invalid("this is an invalid email address") return email def SHOW_EPISODE_TYPE(msg=None): def f(v): if v not in constants.SHOW_EPISODE_TYPE: raise good.Invalid('invalid episodes type: {}'.format(v)) return v return f Description_schema = good.Schema({ 'text': good.Maybe(str), 'title': good.Maybe(str), 'url': good.Maybe(str), }, default_keys=good.Optional) _Episode_schema = { 'title': good.Maybe(str), good.Required('number'): good.All(good.Coerce(int), good.Range(min=1)), good.Optional('season'): good.Maybe(good.All(good.Coerce(int), good.Range(min=1))), good.Optional('episode'): good.Maybe(good.All(good.Coerce(int), good.Range(min=1))), 'air_date': good.Maybe(date_()), 'air_time': good.Maybe(time_()), 'air_datetime': good.Maybe(iso8601_to_utc()), 'description': good.Any(None, Description_schema), 'runtime': good.Maybe(good.Coerce(int)), } Episode_schema = good.Schema(_Episode_schema, default_keys=good.Optional) External_schema = good.Schema({
def validate(schema, d, *arg, **args): if not isinstance(schema, good.Schema): schema = good.Schema(schema, *arg, **args) return schema(d)
bots = json.loads(row.bots) if bot_id in bots: bots.remove(bot_id) kill_pending_messages(stream_id, bot_id) return c.query( """ UPDATE stream SET bots=%s WHERE stream_id=%s """, json.dumps(bots), stream_id) @endpoint("stream/create") def stream_create(params): return {"stream_id": create_stream()} @endpoint("stream/append", G.Schema({"stream_id": G.Maybe(int), "text": str})) def stream_append(params): if params.stream_id is None: params.stream_id = create_stream() message_id = create_message(stream_id=params.stream_id, text=params.text) return {"message_id": message_id, "stream_id": params.stream_id} @endpoint("stream/query", G.Schema({ "stream_id": int, "updated_since": G.Maybe(int), "page":
class Handler(base.Handler): __schema__ = good.Schema( { 'times': good.All(int, good.Range(min=-20, max=20)), }, default_keys=good.Optional) @authenticated(constants.LEVEL_PROGRESS) async def get(self, show_id, episode_number): w = await self._get( show_id=show_id, episode_number=episode_number, ) if w: self.write_object(w) else: self.set_status(204) @authenticated(constants.LEVEL_PROGRESS) async def put(self, show_id, episode_number): w = await self._put(show_id, episode_number) if w: self.write_object(w) else: self.set_status(204) @authenticated(0) async def delete(self, show_id, episode_number): await self._delete(show_id, episode_number) self.set_status(204) @run_on_executor def _get(self, show_id, episode_number): with new_session() as session: ew = session.query(models.Episode_watched).filter( models.Episode_watched.show_id == show_id, models.Episode_watched.episode_number == episode_number, models.Episode_watched.user_id == self.current_user.id, ).first() if ew: return ew.serialize() @run_on_executor def _put(self, show_id, episode_number): data = self.validate() with new_session() as session: ew = set_watched( session=session, user_id=self.current_user.id, show_id=show_id, episode_number=episode_number, times=data.get('times', 1), ) session.commit() if ew: return ew.serialize() @run_on_executor def _delete(self, show_id, episode_number): with new_session() as session: ew = session.query(models.Episode_watched).filter( models.Episode_watched.show_id == show_id, models.Episode_watched.episode_number == episode_number, models.Episode_watched.user_id == self.current_user.id, ).first() if ew: ew.set_prev_as_watching() session.delete(ew) session.commit()
class Handler(base.Handler): __schema__ = good.Schema({ 'position': good.All(int, good.Range(min=0, max=86400)), }) @authenticated(constants.LEVEL_PROGRESS) async def get(self, show_id, episode_number): w = await self._get(show_id, episode_number) if not w: self.set_status(204) else: self.write_object(w) @run_on_executor def _get(self, show_id, episode_number): with new_session() as session: r = session.query(models.Episode_watched).filter( models.Episode_watched.show_id == show_id, models.Episode_watched.episode_number == episode_number, ).first() if r: return r.serialize() @authenticated(constants.LEVEL_PROGRESS) async def put(self, show_id, episode_number): await self._put(show_id, episode_number) self.set_status(204) @authenticated(constants.LEVEL_PROGRESS) async def delete(self, show_id, episode_number): self.request.body = {'position': 0} await self.reset_position(show_id, episode_number) self.set_status(204) @run_on_executor def _put(self, show_id, episode_number): data = self.validate(self.__schema__) with new_session() as session: episode = session.query(models.Episode).filter( models.Episode.show_id == show_id, models.Episode.number == episode_number, ).first() if not episode: raise exceptions.Episode_unknown() ew = session.query(models.Episode_watched).filter( models.Episode_watched.show_id == show_id, models.Episode_watched.episode_number == episode_number, models.Episode_watched.user_id == self.current_user.id, ).first() if not ew: ew = models.Episode_watched( show_id=show_id, episode_number=episode_number, user_id=self.current_user.id, ) session.add(ew) ew.position = data['position'] if ew.position > 0: ew.watched_at = datetime.utcnow() ew.set_as_watching() else: ew.set_prev_as_watching() if ew.times == 0 and ew.position == 0: session.delete(ew) session.commit() @run_on_executor def reset_position(self, show_id, episode_number): with new_session() as session: ew = session.query(models.Episode_watched).filter( models.Episode_watched.show_id == show_id, models.Episode_watched.episode_number == episode_number, models.Episode_watched.user_id == self.current_user.id, ).first() if ew: ew.position = 0 if ew.times == 0: ew.set_prev_as_watching() session.delete(ew) session.commit()