Пример #1
0
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)
Пример #2
0
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)
Пример #3
0
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)
Пример #4
0
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)
Пример #5
0
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)
Пример #6
0
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)
Пример #7
0
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'))
Пример #8
0
def test_get_db():
    flexmock(builtins, open=open(DB_FIXTURE_PATH))
    assert get_db() == {
        'user_id': {
            'channel_id': {
                'archived': {
                    'video_id': 'playlist_id'
                },
                'played': {
                    'video_id': 'timestamp'
                }
            }
        }
    }
Пример #9
0
def yt_get_channel_videos(channel_id):
    """Gets YouTube channel videos.

    Gets all uploaded videos for given YouTube channel. Includes information
        whether they were ``played`` or ``archived`` from the database.

    Args:
        channel_id (str): YouTube channel ID.

    Returns:
        list: YouTube videos uploaded by given channel.
    """

    db = get_db()
    client = yt_get_client()

    try:
        uploaded_id = client.channels().list(
            part='contentDetails', id=channel_id).execute(
            )['items'][0]['contentDetails']['relatedPlaylists']['uploads']

        kwargs = {
            'part': 'snippet',
            'playlistId': uploaded_id,
            'maxResults': 50
        }
        items = []

        while True:
            response = client.playlistItems().list(**kwargs).execute()

            for item in response['items']:
                video_id = item['snippet']['resourceId']['videoId']

                item['played'] = db_get_video(video_id, channel_id, 'played')
                item['archived'] = db_get_video(video_id, channel_id,
                                                'archived')

                items.append(item)

            if 'nextPageToken' not in response:
                return items
            else:
                kwargs['pageToken'] = response['nextPageToken']
    except googleapiclient.errors.Error:
        return []
Пример #10
0
def yt_get_video(video_id):
    """Gets YouTube video.

    Gets information about YouTube video including its rating, playlists,
        comments and data from the database (``played``, ``archived``).

    Args:
        video_id (str): YouTube video ID.

    Returns:
        dict: YouTube video.
    """

    db = get_db()
    client = yt_get_client()

    try:
        video = client.videos().list(
            part='snippet,contentDetails,statistics,status',
            id=video_id).execute()['items'][0]
        channel_id = video['snippet']['channelId']

        video['played'] = db_get_video(video['id'], channel_id, 'played')
        video['archived'] = db_get_video(video['id'], channel_id, 'archived')

        video['playlists'] = {}
        video['rating'] = client.videos().getRating(
            id=video_id).execute()['items'][0]['rating']

        for playlist_id, data in yt_get_playlists(no_items=True).items():
            video['playlists'][playlist_id] = {}
            video['playlists'][playlist_id]['title'] = data['title']
            if video['id'] in data['videos']:
                video['playlists'][playlist_id]['included'] = True
            else:
                video['playlists'][playlist_id]['included'] = False

        video['comments'] = yt_get_comments(video_id)
    except googleapiclient.errors.Error:
        return {}

    return video
Пример #11
0
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)