def web_archive_import_playlist(id): """Imports playlist to archive. Imports entire playlist to the first available archive. Creates new archive if all are full. Args: id (str): YouTube playlist ID. """ db = get_db() user_id = flask.session['user']['id'] for item in yt_get_playlist_items(id): video_id = item['snippet']['resourceId']['videoId'] video = yt_get_video(video_id) channel_id = video['snippet']['channelId'] archive = None for playlist in db_get_archives(): if playlist['contentDetails']['itemCount'] < 5000: archive = playlist break if archive is None: archive = yt_create_playlist() if yt_insert_to_playlist(video_id, archive['id']): if channel_id not in db[user_id]: db[user_id][channel_id] = {'played': {}, 'archived': {}} db[user_id][channel_id]['archived'][video_id] = archive['id'] update_db(db)
def web_channels_update_tracks(tracks): """Handles channel tracking using connected account. Tracks or untracks YouTube channels using connected account. Args: tracks (string): URL encoded JSON data (``channel_id``: ``tracked?``). """ db = get_db() user_id = flask.session['user']['id'] for channel_id, tracked in json.loads( urllib.parse.unquote(tracks)).items(): if tracked: if channel_id not in db[user_id]: db[user_id][channel_id] = {'played': {}, 'archived': {}} else: if channel_id in db[user_id]: channel = db[user_id][channel_id] for video_id, archive_id in channel['archived'].items(): yt_remove_from_playlist(video_id, archive_id) db[user_id].pop(channel_id) update_db(db)
def web_channels_update_query(query): """Handles channel tracking by user query. Tracks or untracks YouTube channels by user query. Args: query (string): URL encoded JSON data (``type``: ``url`` or ``id``, ``value``: ``value``). """ db = get_db() query_data = json.loads(urllib.parse.unquote(query)) user_id = flask.session['user']['id'] if query_data['type'] == 'url': url = query_data['value'] if '/user/' in url: user = re.search('^.+\/user\/([^\/]+)(\/.*|$)', url, re.IGNORECASE).group(1) channel = yt_get_channel('snippet', user=user) db[user_id][channel['id']] = {'played': {}, 'archived': {}} elif '/channel/' in url: channel_id = url.rsplit('/', 1)[-1] channel = yt_get_channel('snippet', channel_id=channel_id) db[user_id][channel['id']] = {'played': {}, 'archived': {}} else: raise elif query_data['type'] == 'user': channel = yt_get_channel('snippet', user=query_data['value']) db[user_id][channel['id']] = {'played': {}, 'archived': {}} elif query_data['type'] == 'id': channel = yt_get_channel('snippet', id=query_data['value']) db[user_id][channel['id']] = {'played': {}, 'archived': {}} update_db(db)
def api_video_unplay(channel=None, video=None): """API video unplay route handler. Handles marking video as unplayed. Args: channel (Optional[str]): YouTube channel ID. video (Optional[str]): YouTube video ID. Returns: flask.Response: Whether operation has succeeded (bool in JSON). """ try: auth_check() except Exception as e: return flask.jsonify(False) if channel is not None and video is not None: db = get_db() if video in db[flask.session['user']['id']][channel]['played']: db[flask.session['user']['id']][channel]['played'].pop(video) update_db(db) return flask.jsonify(True)
def api_video_play(channel=None, video=None): """API video play route handler. Handles marking video as played. Args: channel (Optional[str]): YouTube channel ID. video (Optional[str]): YouTube video ID. Returns: flask.Response: Whether operation has succeeded (bool in JSON). """ try: auth_check() except Exception as e: return flask.jsonify(False) if channel is not None and video is not None: db = get_db() user_id = flask.session['user']['id'] if video not in db[user_id][channel]['played']: db[user_id][channel]['played'][video] = ( datetime.datetime.utcnow().replace( microsecond=0, tzinfo=datetime.timezone.utc).isoformat()) update_db(db) return flask.jsonify(True)
def api_video_unarchive(channel=None, video=None): """API video unarchive route handler. Handles video unarchiving. Args: channel (Optional[str]): YouTube channel ID. video (Optional[str]): YouTube video ID. Returns: flask.Response: Whether operation has succeeded (bool in JSON). """ try: auth_check() except Exception as e: return flask.jsonify(False) if channel is not None and video is not None: db = get_db() user_id = flask.session['user']['id'] if video in db[user_id][channel]['archived']: if yt_remove_from_playlist( video, db[user_id][channel]['archived'][video]): db[user_id][channel]['archived'].pop(video) update_db(db) else: return flask.jsonify(False) return flask.jsonify(True)
def auth_oauth2callback(): """OAuth 2.0 callback route handler. Completes authorization process (stores obtained credentials, gets user information and registers him if needed) and redirects to index. Returns: flask.Response: Index page. """ state = flask.session['state'] flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=SCOPES, state=state) flow.redirect_uri = flask.url_for('oauth2callback', _external=True) authorization_response = flask.request.url flow.fetch_token(authorization_response=authorization_response) credentials = flow.credentials flask.session['credentials'] = { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'scopes': credentials.scopes } flask.session['user'] = yt_get_user() db = get_db() if flask.session['user']['id'] not in db: db[flask.session['user']['id']] = {} update_db(db) return flask.redirect(flask.url_for('index'))
def test_update_db(): db = json.load(open(DB_FIXTURE_PATH)) storage = io.StringIO() flexmock(builtins, open=storage) flexmock(storage, close=True) db['user_id']['channel_id']['played']['video_id'] = 'modified' update_db(db) assert json.loads(storage.getvalue()) == { 'user_id': { 'channel_id': { 'archived': { 'video_id': 'playlist_id' }, 'played': { 'video_id': 'modified' } } } } storage.close()
def api_video_archive(channel=None, video=None): """API video archive route handler. Handles video archiving. Args: channel (Optional[str]): YouTube channel ID. video (Optional[str]): YouTube video ID. Returns: flask.Response: Whether operation has succeeded (bool in JSON). """ try: auth_check() except Exception as e: return flask.jsonify(False) if channel is not None and video is not None: db = get_db() archive = None for playlist in db_get_archives(): if playlist['contentDetails']['itemCount'] < 5000: archive = playlist break if archive is None: archive = yt_create_playlist() if yt_insert_to_playlist(video, archive['id']): db[flask.session['user'] ['id']][channel]['archived'][video] = archive['id'] update_db(db) return flask.jsonify(True) else: return flask.jsonify(False)