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 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 Range(min=None, max=None, min_included=True, max_included=True, msg=None): # Alter min, max when the range is not inclusive if min is not None and not min_included: min += 1 if max is not None and not max_included: max -= 1 # Finish return _wrapMsg(good.Range(min, max), msg)
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()
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 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)
try: utils.validate_cmd_response(v) return v except Exception as e: raise good.Invalid(str(e)) return f _schema = { 'cmd': good.All(str, validate_cmd()), 'response': good.All(str, validate_response()), good.Optional('user_level'): good.All(good.Coerce(int), good.Range(min=0, max=9)), good.Optional('enabled_status'): good.All(good.Coerce(int), good.Range(min=0, max=2)), good.Optional('global_cooldown'): good.All(good.Coerce(int), good.Range(min=0, max=86400)), good.Optional('user_cooldown'): good.All(good.Coerce(int), good.Range(min=0, max=86400)), good.Optional('mod_cooldown'): good.All(good.Coerce(int), good.Range(min=0, max=86400)), good.Optional('enabled'): good.All(good.Coerce(int), good.Range(min=0, max=1)), good.Optional('public'): good.All(good.Coerce(int), good.Range(min=0, max=1)), good.Optional('group_name'): good.Maybe(good.All(str, good.Length(min=0, max=50))), }
import logging, good, asyncio from ..base import Api_handler, Level, Api_exception from tbot import config, utils from datetime import datetime, timedelta __schema__ = { 'name': good.All(str, good.Length(min=1, max=100)), 'messages': good.All([good.All(str, good.Length(min=1, max=500))], good.Length(min=1, max=100)), good.Optional('enabled'): good.All(good.Coerce(int), good.Range(min=0, max=1)), good.Optional('enabled_status'): good.All(good.Coerce(int), good.Range(min=0, max=2)), good.Optional('interval'): good.All(good.Coerce(int), good.Range(min=1, max=10080)), good.Optional('send_message_order'): good.All(good.Coerce(int), good.Range(min=1, max=2)), } 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(
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()
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()
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": G.Any(int, G.Default(0), G.Range(0, 999)), "page_size": G.Any(int, G.Default(20), G.Range(1, 200)), "order_dir": G.Any("DESC", "ASC", G.Default("DESC")), "order_by": G.Any("created", "updated", G.Default("updated")) })) def stream_query(params): return query_messages(**params) @endpoint("stream/ping", G.Schema({"stream_id": G.Maybe(int)})) def stream_ping(params): return {"success": ping_stream(params.stream_id)}
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({ good.All(good.Length(min=1, max=45)):good.Any(None, good.All(good.Coerce(str), good.Length(min=1, max=45))) }, default_keys=good.Optional) Importer_schema = good.Schema( {key: good.Maybe(good.All(str, good.Length(min=1, max=45))) \ for key in constants.IMPORTER_TYPE_NAMES},
""" 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)
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)
class Handler(base.Handler): __arguments_schema__ = good.Schema( { 'days_back': good.Any( good.All(good.Coerce(int), good.Range(min=0, max=7)), good.Default(2), ), 'days_ahead': good.Any(good.All(good.Coerce(int), good.Range(min=0, max=14)), good.Default(7)), }, default_keys=good.Required) async def get(self, user_id): user_id = self.user_id_or_current(user_id) shows_episodes = await self.get_shows_episodes(user_id) if not shows_episodes: self.write_object([]) return ids = [] shows = {se[0]['id']: se[0] for se in shows_episodes} airdates = OrderedDict() airdate_shows = OrderedDict() prev = None for se in shows_episodes: if prev == None: prev = se[1]['air_datetime'].date() if prev != se[1]['air_datetime'].date(): airdates[prev] = list(airdate_shows.values()) prev = se[1]['air_datetime'].date() airdate_shows = {} if se[1]['show_id'] not in airdate_shows: airdate_shows[se[1]['show_id']] = copy.copy( shows[se[1]['show_id']]) show = airdate_shows[se[1]['show_id']] show.setdefault('episodes', []) show['episodes'].append(self.episode_wrapper(se[1])) if shows_episodes: airdates[prev] = list(airdate_shows.values()) self.write_object([{'air_date': ad, 'shows': airdates[ad]}\ for ad in airdates]) @run_on_executor def get_shows_episodes(self, user_id): args = self.validate_arguments() now = datetime.utcnow() from_ = (now - timedelta(days=args['days_back'])).date() to_ = (now + timedelta(days=args['days_ahead'])).date() with new_session() as session: rows = session.query(models.Episode, models.Show).filter( models.Show_fan.user_id == user_id, models.Show_fan.show_id == models.Show.id, models.Episode.show_id == models.Show.id, sa.func.date(models.Episode.air_datetime) >= from_, sa.func.date(models.Episode.air_datetime) <= to_, ).order_by( models.Episode.air_datetime, models.Show.id, ).all() return [(r.Show.serialize(), r.Episode.serialize()) for r in rows]