You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
8.7 KiB

import datetime
import os
import flask_restful.inputs
from db import Video, Comment, Association, Emote, Clip, Event
from twitch import Twitch
class Sync(object):
@staticmethod
def _get(d, *keys, default=None):
try:
result = None
for key in keys:
if result:
if isinstance(result, list):
result = result[key]
else:
result = result.get(key, default)
else:
result = d.get(key, default)
return result
except (KeyError, IndexError):
return default
@staticmethod
def _to_datetime(val):
if not val:
return None
result = flask_restful.inputs.datetime_from_iso8601(val)
return result.astimezone(tz=datetime.timezone.utc).replace(tzinfo=None)
@classmethod
def sync_videos(cls, app, db):
app.logger.info('Starting synchronization of videos')
with app.app_context():
twitch = Twitch(os.getenv('TWITCH_CLIENT_ID'), os.getenv('TWITCH_OAUTH_TOKEN'))
channel_id = os.getenv('TWITCH_CHANNEL_ID')
updated = []
for vid in twitch.fetch_videos(channel_id):
id = cls._get(vid, '_id', default='').lstrip('v')
if not id:
continue
if cls._get(vid, 'status') == 'recording':
continue
q = db.session.query(Video).filter(Video.id == id)
video = q.first()
if not video:
video = Video(id=id)
created_at = cls._get(vid, 'created_at')
updated_at = cls._to_datetime(cls._get(vid, 'updated_at', default=created_at))
created_at = cls._to_datetime(created_at)
if not video.updated_at or video.updated_at < updated_at:
updated.append(id)
video.broadcast_type = cls._get(vid, 'broadcast_type')
video.title = cls._get(vid, 'title')
video.description = cls._get(vid, 'description')
video.game = cls._get(vid, 'game')
video.length = cls._get(vid, 'length')
video.thumbnail_small = cls._get(vid, 'thumbnails', 'small', 0, 'url')
video.thumbnail_medium = cls._get(vid, 'thumbnails', 'medium', 0, 'url')
video.thumbnail_large = cls._get(vid, 'thumbnails', 'large', 0, 'url')
video.created_at = created_at
video.updated_at = updated_at
video.recorded_at = cls._to_datetime(cls._get(vid, 'recorded_at'))
video.published_at = cls._to_datetime(cls._get(vid, 'published_at'))
db.session.add(video)
db.session.commit()
app.logger.info('Updated videos: %s', ', '.join(updated) if updated else 'NONE')
for com in twitch.fetch_comments(updated):
q = db.session.query(Video).filter(Video.id == cls._get(com, 'content_id'))
video = q.first()
if not video:
continue
id = cls._get(com, '_id')
q = db.session.query(Comment).filter(Comment.id == id)
comment = q.first()
if not comment:
comment = Comment(id=id)
comment.commenter_id = cls._get(com, 'commenter', '_id')
comment.commenter_name = cls._get(com, 'commenter', 'name')
comment.commenter_display_name = cls._get(com, 'commenter', 'display_name')
comment.commenter_logo = cls._get(com, 'commenter', 'logo')
comment.source = cls._get(com, 'source')
comment.message_body = cls._get(com, 'message', 'body')
comment.message_user_color = cls._get(com, 'message', 'user_color')
badges = cls._get(com, 'message', 'user_badges')
if badges:
badges = ','.join(['{_id}:{version}'.format(**b) for b in badges])
comment.message_user_badges = badges
comment.created_at = cls._to_datetime(cls._get(com, 'created_at'))
comment.updated_at = cls._to_datetime(cls._get(com, 'updated_at'))
q = db.session.query(Association).filter(
Association.video_id == video.id,
Association.comment_id == comment.id)
assoc = q.first()
if not assoc:
assoc = Association()
assoc.comment = comment
assoc.offset = cls._get(com, 'content_offset_seconds')
video.associations.append(assoc)
db.session.add(video)
db.session.commit()
app.logger.info('Synchronization of videos completed')
@classmethod
def sync_emotes(cls, app, db):
app.logger.info('Starting synchronization of emotes')
with app.app_context():
twitch = Twitch(os.getenv('TWITCH_CLIENT_ID'), os.getenv('TWITCH_OAUTH_TOKEN'))
channel_id = os.getenv('TWITCH_CHANNEL_ID')
for em in twitch.fetch_emotes(channel_id):
id = cls._get(em, 'id')
if not id:
continue
q = db.session.query(Emote).filter(Emote.id == id)
emote = q.first()
if not emote:
emote = Emote(id=id)
emote.code = cls._get(em, 'code')
db.session.add(emote)
db.session.commit()
app.logger.info('Synchronization of emotes completed')
@classmethod
def sync_clips(cls, app, db):
app.logger.info('Starting synchronization of clips')
with app.app_context():
twitch = Twitch(os.getenv('TWITCH_CLIENT_ID'), os.getenv('TWITCH_OAUTH_TOKEN'))
channel_name = os.getenv('TWITCH_CHANNEL_NAME')
for clp in twitch.fetch_clips(channel_name):
slug = cls._get(clp, 'slug')
if not slug:
continue
q = db.session.query(Clip).filter(Clip.slug == slug)
clip = q.first()
if not clip:
clip = Clip(slug=slug)
clip.code = cls._get(clp, 'code')
clip.video_id = cls._get(clp, 'vod', 'id')
clip.video_offset = cls._get(clp, 'vod', 'offset')
clip.title = cls._get(clp, 'title')
clip.game = cls._get(clp, 'game')
clip.duration = cls._get(clp, 'duration')
clip.curator_id = cls._get(clp, 'curator', 'id')
clip.curator_name = cls._get(clp, 'curator', 'name')
clip.curator_display_name = cls._get(clp, 'curator', 'display_name')
clip.curator_logo = cls._get(clp, 'curator', 'logo')
clip.thumbnail_tiny = cls._get(clp, 'thumbnails', 'tiny')
clip.thumbnail_small = cls._get(clp, 'thumbnails', 'small')
clip.thumbnail_medium = cls._get(clp, 'thumbnails', 'medium')
clip.created_at = cls._to_datetime(cls._get(clp, 'created_at'))
db.session.add(clip)
db.session.commit()
app.logger.info('Synchronization of clips completed')
@classmethod
def sync_events(cls, app, db):
app.logger.info('Starting synchronization of events')
with app.app_context():
twitch = Twitch(os.getenv('TWITCH_CLIENT_ID'), os.getenv('TWITCH_OAUTH_TOKEN'))
channel_id = os.getenv('TWITCH_CHANNEL_ID')
for evt in twitch.fetch_events(channel_id):
id = cls._get(evt, '_id')
if not id:
continue
q = db.session.query(Event).filter(Event.id == id)
event = q.first()
if not event:
event = Event(id=id)
event.start = cls._to_datetime(cls._get(evt, 'start_time'))
event.end = cls._to_datetime(cls._get(evt, 'end_time'))
event.title = cls._get(evt, 'title')
event.description = cls._get(evt, 'description')
event.cover_image_id = cls._get(evt, 'cover_image_id')
event.cover_image_url = cls._get(evt, 'cover_image_url')
event.game_id = cls._get(evt, 'game', '_id')
event.game_name = cls._get(evt, 'game', 'name')
event.game_box_small = cls._get(evt, 'game', 'box', 'small')
event.game_box_medium = cls._get(evt, 'game', 'box', 'medium')
event.game_box_large = cls._get(evt, 'game', 'box', 'large')
db.session.add(event)
db.session.commit()
app.logger.info('Synchronization of events completed')