コード例 #1
0
def add_subscription_local(youtube_auth, channel_id, by_username=False):
    """
    Add a YouTube subscription (Local/DB).
    :param by_username:
    :param youtube_auth:
    :param channel_id:
    :return:
    """
    # FIXME: Somewhat duplicate code of get_remote_subscriptions, move to own function -- START
    # Get ID of uploads playlist
    # channel_uploads_playlist_id = get_channel_uploads_playlist_id(youtube_auth, channel_id)
    if by_username:
        channel_response = get_channel_by_username(youtube_auth, channel_id)
    else:
        channel_response = get_channel_by_id(youtube_auth, channel_id)
    channel_uploads_playlist_id = channel_response['contentDetails'][
        'relatedPlaylists']['uploads']
    channel = Channel(channel_response,
                      channel_uploads_playlist_id,
                      channel_list_response=True)
    db_channel = engine_execute_first(get_channel_by_id_stmt(channel))
    if db_channel:
        engine_execute(update_channel_from_remote(channel))
    else:
        # TODO: change to sqlalchemy core stmt
        create_logger(__name__ + ".subscriptions").info(
            "Added channel {} - {}".format(channel.title, channel.id))
        db_session.add(channel)

    db_session.commit()
    # FIXME: Somewhat duplicate code of get_remote_subscriptions, move to own function -- END

    logger.info("Added subscription (Local/DB): {} / {}".format(
        channel_id, channel.title))
コード例 #2
0
def add_subscription_remote(channel_id):
    """
    Add a YouTube subscription (On YouTube).

    DEPRECATED: Google doesn't let you, see supported op table https://developers.google.com/youtube/v3/getting-started
    :param youtube_oauth:
    :param channel_id:
    :return: returns response or raises exception
    """
    youtube_oauth = load_youtube()
    response = youtube_oauth.subscriptions().insert(
        part='snippet',
        body=dict(snippet=dict(resourceId=dict(channelId=channel_id))))
    try:
        response.execute()
    except HttpError as exc_http:
        _msg = "Failed adding subscription to '{}', HTTP Error {}".format(
            channel_id, exc_http.resp.status)
        logger.error("{}: {}".format(_msg, exc_http.content),
                     exc_info=exc_http)
        raise exc_http

    except Exception as exc:
        _msg = "Unhandled exception occurred when adding subscription to '{}'".format(
            channel_id)
        logger.critical("{} | response={}".format(_msg, response.__dict__),
                        exc_info=exc)
        raise exc

    # FIXME: Somewhat duplicate code of get_remote_subscriptions, move to own function -- START
    # Get ID of uploads playlist
    channel_uploads_playlist_id = response['items'][0]['contentDetails'][
        'relatedPlaylists']['uploads']
    channel = Channel(channel_id, channel_uploads_playlist_id)
    db_channel = engine_execute_first(get_channel_by_id_stmt(channel))
    if db_channel:
        engine_execute(update_channel_from_remote(channel))
        # subs.append(channel)
    else:
        # TODO: change to sqlalchemy core stmt
        create_logger(__name__ + ".subscriptions").info(
            "Added channel {} - {}".format(channel.title, channel.id))
        db_session.add(channel)
        # subs.append(channel)

    db_session.commit()
    # FIXME: Somewhat duplicate code of get_remote_subscriptions, move to own function -- END

    logger.info("Added subscription: {} / {}".format(
        channel_id, response['snippet']['title']))
    return response
コード例 #3
0
def cli(no_gui, test_channels, update_watch_prio, set_watched_day):
    logger = create_logger(__name__)
    if no_gui:
        run_print()
    if update_watch_prio:
        videos = db_session.query(Video).all()
        watch_prio = read_config('Play', 'default_watch_prio')
        logger.debug("Setting watch_prio {}, for: {} videos".format(watch_prio, len(videos)))
        for video in videos:
            video.watch_prio = watch_prio
        db_session.commit()
        return

    if set_watched_day:
        videos = db_session.query(Video).filter(or_(Video.downloaded == True, (Video.vid_path.is_(None)))).all()
        for video in videos:
            vid_age = datetime.datetime.utcnow() - video.date_published
            if vid_age > datetime.timedelta(days=int(set_watched_day)):
                logger.debug("Setting watched, {} - {} - {}".format(vid_age, video.title, video.__dict__))
                video.watched = True
        db_session.commit()
        return
    if test_channels:
        run_channels_test()
    else:
        """
        PyQT raises and catches exceptions, but doesn't pass them along. 
        Instead it just exits with a status of 1 to show an exception was caught. 
        """
        # Back up the reference to the exceptionhook
        sys._excepthook = sys.excepthook

        def my_exception_hook(exctype, value, traceback):
            # Ignore KeyboardInterrupt so a console python program can exit with Ctrl + C.
            if issubclass(exctype, KeyboardInterrupt):
                sys.__excepthook__(exctype, value, traceback)
                return

            # Log the exception with the logger
            logger.critical("Intercepted Exception", exc_info=(exctype, value, traceback))

            # Call the normal Exception hook after
            sys._excepthook(exctype, value, traceback)

            # sys.exit(1)       # Alternatively, exit

        # Set the exception hook to our wrapping function
        sys.excepthook = my_exception_hook

        run_with_gui()
コード例 #4
0
def get_remote_subscriptions(youtube_oauth):
    """
    Get a list of the authenticated user's subscriptions.
    :param youtube_oauth:
    :param stats:
    :param info: debug lite
    :param debug:
    :param traverse_pages:
    :return: [total, subs, statistics]
    """
    subscription_list_request = youtube_oauth.subscriptions().list(
        part='snippet', mine=True, maxResults=50)
    subs = []
    # Retrieve the list of subscribed channels for authenticated user's channel.
    update_stmts = []
    channel_ids = []
    while subscription_list_request:
        subscription_list_response = subscription_list_request.execute()

        # Grab information about each subscription page
        for page in tqdm(subscription_list_response['items'],
                         desc="Adding and updating channels by page",
                         disable=read_config('Debug', 'disable_tqdm')):
            # Get channel
            channel_response = channels_list(
                youtube_oauth,
                part='contentDetails',
                id=page['snippet']['resourceId']['channelId'])

            # Get ID of uploads playlist
            channel_uploads_playlist_id = channel_response['items'][0][
                'contentDetails']['relatedPlaylists']['uploads']
            channel = Channel(page['snippet'], channel_uploads_playlist_id)
            db_channel = engine_execute_first(get_channel_by_id_stmt(channel))
            if db_channel:
                engine_execute(update_channel_from_remote(channel))
                subs.append(channel)
            else:
                # TODO: change to sqlalchemy core stmt
                create_logger(__name__ + ".subscriptions").info(
                    "Added channel {} - {}".format(channel.title, channel.id))
                db_session.add(channel)
                subs.append(channel)
            channel_ids.append(channel.id)
        subscription_list_request = youtube_oauth.playlistItems().list_next(
            subscription_list_request, subscription_list_response)
    delete_sub_not_in_list(channel_ids)
    db_session.commit()
    return subs
コード例 #5
0
 def update_download_tile(self, download_tile):
     result = db_session.query(DBDownloadTile).filter(
         DBDownloadTile.video_id == format(
             download_tile.video.video_id)).first()
     # stmt = DBDownloadTile.__table__.select().where(
     #     text("video_id = '{}'".format(download_tile.video.video_id)))
     # result = engine.execute(stmt).first()
     if result:
         result.update_tile(download_tile)
         db_session.commit()
         db_session.remove()
     else:
         self.logger.warning(
             "Download tile not found in db, so no update was performed: {}"
             .format(download_tile.__dict__))
コード例 #6
0
 def new_download_tile(self, new_tile):
     lock.acquire()
     result = db_session.query(DBDownloadTile).filter(
         DBDownloadTile.video_id == format(
             new_tile.video.video_id)).first()
     if not result:
         download_tile = DBDownloadTile(new_tile)
         if not download_tile.video:
             self.logger.error("No video in new tile: {}".format(
                 download_tile.__dict__),
                               exc_info=True)
             return
         db_session.add(download_tile)
         db_session.commit()
     db_session.remove()
     lock.release()
コード例 #7
0
def get_remote_subscriptions(youtube_oauth):
    """
    Get a list of the authenticated user's subscriptions.
    :param youtube_oauth:
    :return: [subs]
    """
    if youtube_oauth is None:
        logger.critical("YouTube API OAuth object was NoneType, aborting!")
        return None
    subscription_list_request = youtube_oauth.subscriptions().list(part='snippet', mine=True,
                                                                   maxResults=50)
    subs = []
    # Retrieve the list of subscribed channels for authenticated user's channel.
    channel_ids = []
    while subscription_list_request:
        subscription_list_response = subscription_list_request.execute()

        # Grab information about each subscription page
        for page in subscription_list_response['items']:
            # Get channel
            channel_response = channels_list(youtube_oauth, part='contentDetails',
                                             id=page['snippet']['resourceId']['channelId'])

            # Get ID of uploads playlist
            channel_uploads_playlist_id = channel_response['items'][0]['contentDetails']['relatedPlaylists']['uploads']
            channel = Channel(page['snippet'], channel_uploads_playlist_id)
            db_channel = engine_execute_first(get_channel_by_id_stmt(channel))
            if db_channel:
                engine_execute(update_channel_from_remote(channel))
                subs.append(channel)
            else:
                # TODO: change to sqlalchemy core stmt
                create_logger(__name__ + ".subscriptions").info(
                    "Added channel {} - {}".format(channel.title, channel.id))
                db_session.add(channel)
                subs.append(channel)
            channel_ids.append(channel.id)
        subscription_list_request = youtube_oauth.playlistItems().list_next(
            subscription_list_request, subscription_list_response)
    delete_sub_not_in_list(channel_ids)
    db_session.commit()
    return subs
コード例 #8
0
def run_channels_test():
    logger.info('Running Channels Test')
    subscriptions = get_subscriptions(cached_subs)
    youtube_keys = load_keys(len(subscriptions))
    test_threads = []
    results = []
    logger.info("Channels Test: Starting miss and pages tests")
    for subscription, youtube_key in (subscriptions, youtube_keys):
        test = RunTestsThreaded(subscription, youtube_key, results)
        test.start()
        test_threads.append(test)

    logger.info("Channels Test: Waiting for test threads")
    for thread in test_threads:
        thread.join()

    for result in results:
        test = Test(result[0], result[1], result[2], result[3])
        db_session.add(test)
    db_session.commit()
    db_session.remove()
コード例 #9
0
    def new_file(self, vid_id, vid_path):
        vid = db_session.query(Video).get(vid_id)
        if vid:
            if not vid.downloaded:
                vid.vid_path = vid_path
                vid.date_downloaded = datetime.datetime.utcnow()
                vid.downloaded = True

                thumb_path = os.path.join(THUMBNAILS_PATH,
                                          '{}.jpg'.format(vid.video_id))
                downloaded_thumbnail = os.path.isfile(thumb_path)
                if downloaded_thumbnail and (not vid.thumbnail_path):
                    vid.thumbnail_path = thumb_path
                    self.logger.warning(
                        "Thumbnail downloaded, but path didn't exist in db, for video: {}"
                        .format(vid.__dict__))
                elif (not vid.thumbnail_path) or (not downloaded_thumbnail):
                    if not downloaded_thumbnail:
                        self.logger.warning(
                            "Thumbnail path in db, but not on disk, for video: {}"
                            .format(vid.__dict__))
                    self.logger.info("Downloading thumbnail for: {}".format(
                        vid.__dict__))
                    download_thumbnails_threaded([vid])

                self.logger.info(
                    "Updating existing record in db: {} - {}".format(
                        vid.title, vid.__dict__))
                db_session.commit()
                self.model.update_subfeed_videos_from_db()
                self.model.update_playback_videos_from_db()
            else:
                self.logger.info(
                    "File already downloaded by this system: {} - {}".format(
                        vid.title, vid.__dict__))
            db_session.remove()

        else:
            db_session.remove()
            youtube_keys = load_keys(1)
            self.logger.info(
                "Grabbing new video information from youtube: {}".format(
                    vid_id))
            response_videos = list_uploaded_videos_videos(
                youtube_keys[0], [vid_id], 1)
            if len(response_videos) > 0:
                video = response_videos[0]
                video.vid_path = vid_path
                video.downloaded = True
                video.watched = False
                video.date_downloaded = datetime.datetime.utcnow()
                self.logger.info("Downloading thumbnail: {} - {}".format(
                    video.title, video.__dict__))
                download_thumbnails_threaded([video])
                self.logger.info("Adding new file to db: {} - {}".format(
                    video.title, video.__dict__))
                UpdateVideo(video,
                            finished_listeners=[
                                self.model.playback_grid_view_listener.
                                downloadedVideosChangedinDB
                            ]).start()
            else:
                self.logger.warning(
                    "Video with id {}, not found on youtube servers".format(
                        vid_id))
コード例 #10
0
ファイル: run.py プロジェクト: BluABK/sane-subfeed
def cli(no_gui, test_channels, update_watch_prio, set_watched_day,
        refresh_and_print_subfeed, print_subscriptions, print_watched_videos,
        print_discarded_videos, print_downloaded_videos, print_playlist_items,
        print_playlist_items_url_only, auth_oauth2):
    logger = create_logger(__name__)

    if update_watch_prio:
        videos = db_session.query(Video).all()
        watch_prio = read_config('Play', 'default_watch_prio')
        logger.debug("Setting watch_prio {}, for: {} videos".format(
            watch_prio, len(videos)))
        for video in videos:
            video.watch_prio = watch_prio
        db_session.commit()
        return

    if set_watched_day:
        videos = db_session.query(Video).filter(
            or_(Video.downloaded == True, (Video.vid_path.is_(None)))).all()
        for video in videos:
            vid_age = datetime.datetime.utcnow() - video.date_published
            if vid_age > datetime.timedelta(days=int(set_watched_day)):
                logger.debug("Setting watched, {} - {} - {}".format(
                    vid_age, video.title, video.__dict__))
                video.watched = True
        db_session.commit()
        return

    if test_channels:
        run_channels_test()

    if refresh_and_print_subfeed:
        cli_refresh_and_print_subfeed()

    if print_subscriptions:
        cached_subs = True
        subs = get_subscriptions(cached_subs)
        for channel in subs:
            if channel.subscribed_override:
                print(("[{}]    {} [Subscription override]".format(
                    channel.id, channel.title)))
            else:
                print(("[{}]    {}".format(channel.id, channel.title)))

    if print_watched_videos:
        videos = db_session.query(Video).filter(
            and_(Video.watched is True, (Video.vid_path.isnot(None)))).all()
        print_functions.print_videos(videos, path_only=True)

    if print_discarded_videos:
        videos = db_session.query(Video).filter(
            and_(Video.discarded is True, (Video.vid_path.isnot(None)))).all()
        print_functions.print_videos(videos, path_only=True)

    if print_downloaded_videos:
        videos = db_session.query(Video).filter(
            and_(Video.downloaded is True,
                 (Video.vid_path.isnot(None)))).all()
        print_functions.print_videos(videos, path_only=True)

    if print_playlist_items:
        youtube_auth_resource = load_keys(1)[0]
        playlist_video_items = []
        youtube.youtube_requests.list_uploaded_videos(youtube_auth_resource,
                                                      playlist_video_items,
                                                      print_playlist_items, 50)
        for vid in playlist_video_items:
            if print_playlist_items_url_only:
                print(vid.url_video)
            else:
                print(vid)

    if auth_oauth2:
        youtube_oauth = youtube_auth_oauth()
        if youtube_oauth is None:
            logger.critical("Failed to authenticate YouTube API OAuth2!")
            return None
        save_youtube_resource_oauth(youtube_oauth)

    if no_gui:
        run_with_cli()
    else:
        if LEGACY_EXCEPTION_HANDLER:
            """
            PyQT raises and catches exceptions, but doesn't pass them along. 
            Instead it just exits with a status of 1 to show an exception was caught. 
            """
            # Back up the reference to the exceptionhook
            sys._excepthook = sys.excepthook

            def my_exception_hook(exctype, value, traceback):
                global exc_id, exceptions
                # Ignore KeyboardInterrupt so a console python program can exit with Ctrl + C.
                if issubclass(exctype, KeyboardInterrupt):
                    sys.__excepthook__(exctype, value, traceback)
                    return

                # Log the exception with the logger
                logger.exception("Intercepted Exception #{}".format(exc_id),
                                 exc_info=(exctype, value, traceback))

                # Store intercepted exceptions in a reference list of lists
                exceptions.append([exctype, value, traceback, exc_id])

                # Increment Exception Identifier
                exc_id += 1

                # Call the normal Exception hook after
                # noinspection PyProtectedMember
                sys._excepthook(exctype, value, traceback)

                # sys.exit(1)       # Alternatively, exit

            # Set the exception hook to our wrapping function
            sys.excepthook = my_exception_hook

        run_with_gui()