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))
def delete_sub_not_in_list(subs):
    delete_channels = db_session.query(Channel).filter(
        ~Channel.id.in_(subs)).all()
    for channel in delete_channels:
        if channel.subscribed or channel.subscribed is None:
            channel.subscribed = False
            create_logger(__name__).warning(
                "Setting unsubscribed for channel: {} - {}".format(
                    channel.title, channel.__dict__))
            stmt = update_channel_from_remote(channel)
            engine.execute(stmt)
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
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
Exemple #5
0
    def __init__(self, parent, root, main_model: MainModel):
        super(GridView, self).__init__(parent=parent)
        self.logger = create_logger(__name__)
        self.setMinimumSize(0, 0)
        self.parent = parent
        self.root = root  # MainWindow
        self.clipboard = self.root.clipboard
        self.status_bar = self.root.status_bar
        self.buffer = 10
        self.bar_correction = 0
        self.main_model = main_model
        self.pref_tile_height = read_config('Gui', 'tile_pref_height')
        self.pref_tile_width = read_config('Gui', 'tile_pref_width')
        self.q_labels = {}
        self.grid = QGridLayout()
        self.items_x = read_config('Gui', 'grid_view_x')
        self.items_y = read_config('Gui', 'grid_view_y')

        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        self.grid.setContentsMargins(5, 5, 0, 0)
        self.grid.setSpacing(2)
        self.grid.setAlignment(Qt.AlignTop)
        self.setLayout(self.grid)

        self.setAutoFillBackground(True)
        self.set_bgcolor()

        self.main_model.grid_view_listener.redrawVideos.connect(self.redraw_videos)
Exemple #6
0
    def __init__(self, sane_parent, main_model):
        super(DbStateIcon, self).__init__(parent=sane_parent)
        self.logger = create_logger(__name__)
        self.sane_parent = sane_parent
        self.main_model = main_model

        self.base_icon = QPixmap(os.path.join(ICONS_PATH, 'database.png'))
        self.base_icon = self.base_icon.scaled(
            QSize(self.height(), self.height()), Qt.KeepAspectRatio,
            Qt.SmoothTransformation)
        self.full_icon = self.base_icon.copy()
        self.sane_painter = QPainter(self.full_icon)
        self.default_dot = QPixmap(os.path.join(
            ICONS_PATH, 'default_dot.png')).scaled(
                QSize(self.height() * 0.3,
                      self.height() * 0.3), Qt.KeepAspectRatio,
                Qt.SmoothTransformation)
        self.read_dot = QPixmap(os.path.join(ICONS_PATH,
                                             'blue_dot.png')).scaled(
                                                 QSize(self.height() * 0.3,
                                                       self.height() * 0.3),
                                                 Qt.KeepAspectRatio,
                                                 Qt.SmoothTransformation)
        self.write_dot = QPixmap(os.path.join(
            ICONS_PATH, 'green_dot.png')).scaled(
                QSize(self.height() * 0.3,
                      self.height() * 0.3), Qt.KeepAspectRatio,
                Qt.SmoothTransformation)

        self.setPixmap(self.full_icon)

        DatabaseListener.static_instance.dbStateChanged.connect(
            self.change_state)
Exemple #7
0
def download_thumbnails_threaded(input_vid_list, progress_listener=None):
    logger = create_logger(__name__ + ".download_thumbnails_threaded")

    thread_list = []
    thread_limit = int(read_config('Threading', 'img_threads'))
    force_dl_best = read_config('Thumbnails', 'force_download_best')

    if progress_listener:
        progress_listener.setText.emit('Downloading thumbnails')

    vid_list = []
    chunk_size = math.ceil(len(input_vid_list) / thread_limit)
    for i in range(0, len(input_vid_list), max(chunk_size, 1)):
        vid_list.append(input_vid_list[i:i + chunk_size])
    counter = 0

    logger.info(
        "Starting thumbnail download threads for {} videos in {} threads".
        format(len(input_vid_list), len(vid_list)))
    for vid_list_chunk in tqdm(vid_list,
                               desc="Starting thumbnail threads",
                               disable=read_config('Debug', 'disable_tqdm')):
        t = DownloadThumbnail(vid_list_chunk,
                              force_dl_best=force_dl_best,
                              progress_listener=progress_listener)
        thread_list.append(t)
        t.start()
        counter += 1
        if progress_listener:
            progress_listener.updateProgress.emit()
    for t in tqdm(thread_list,
                  desc="Waiting on thumbnail threads",
                  disable=read_config('Debug', 'disable_tqdm')):
        t.join()
Exemple #8
0
 def __init__(self, parent):
     super(AboutView, self).__init__(parent)
     self.logger = create_logger(__name__)
     self.root = parent  # MainWindow
     self.clipboard = self.root.clipboard
     self.status_bar = self.root.status_bar
     self.init_ui()
Exemple #9
0
    def __init__(self, parent, root):
        """
        A GUI Widget that reads and sets config.ini settings
        :param parent:
        :param clipboard:
        :param status_bar:
        """
        super(InputSuper, self).__init__(parent)
        self.parent = parent
        self.root = root  # MainWindow
        self.logger = create_logger(__name__)
        self.clipboard = self.root.clipboard
        self.status_bar = self.root.status_bar
        self.offset = 0
        self.section_count = 0
        self.section_fontsize = 10
        self.section_fontfamily = "Helvetica"
        self.section_fontstyle = QFont.Black

        self.layout = QGridLayout()
        self.layout.setAlignment(Qt.AlignTop)
        # self.layout = QVBoxLayout()

        # Create tabs - Part 2: Set self layout and add tabs to it
        self.setLayout(self.layout)
Exemple #10
0
    def __init__(self, parent):
        QLabel.__init__(self, parent)
        self.parent = parent
        self.logger = create_logger(__name__ + ".ThumbnailTitle")

        margins = self.parent.layout.getContentsMargins()
        self.setFixedSize(self.parent.width() - margins[0] - margins[2],
                          (self.parent.height() - 4 * margins[3]) * 0.6)
Exemple #11
0
 def __init__(self, model):
     super().__init__()
     self.model = model
     self.refreshVideos.connect(self.refresh_videos)
     self.refreshSubs.connect(self.refresh_subs)
     self.testChannels.connect(self.test_channels)
     self.getSingleVideo.connect(self.get_single_video)
     self.addYouTubeChannelSubscriptionById.connect(
         self.add_youtube_channel_subscription_by_id)
     self.addYouTubeChannelSubscriptionByUsername.connect(
         self.add_youtube_channel_subscription_by_username)
     self.logger = create_logger(__name__ + '.MainWindowListener')
Exemple #12
0
    def __init__(self, parent, root, main_model: MainModel):
        super().__init__(parent, root, main_model)
        self.logger = create_logger(__name__ + ".PlayView")

        self.main_model.grid_view_listener.downloadedVideosChanged.connect(
            self.videos_changed)
        self.main_model.grid_view_listener.downloadedVideosUpdated.connect(
            self.update_videos)

        self.logger.debug("Init grid")
        self.update_grid()
        self.logger.info("Initialized PlayView")
    def __init__(self, parent, vid_limit=40):
        super(ListTiledView, self).__init__(parent)
        self.logger = create_logger(__name__)
        self.root = parent  # MainWindow
        self.eqlabels = []
        self.vid_limit = vid_limit
        self.clipboard = self.root.clipboard
        self.status_bar = self.root.status_bar

        # The layouts
        main_layout = QVBoxLayout()
        main_layout.setSpacing(10)
        self.setLayout(main_layout)

        header_layout = QHBoxLayout()
        body_layout = QHBoxLayout()

        main_layout.addLayout(header_layout)
        main_layout.addLayout(body_layout)

        description_layout = QVBoxLayout()
        image_layout = QVBoxLayout()

        body_layout.addLayout(image_layout)
        body_layout.addLayout(description_layout)

        video_title_layout = QHBoxLayout()
        more_layout = QHBoxLayout()
        published_layout = QHBoxLayout()

        description_layout.addLayout(video_title_layout)
        description_layout.addLayout(more_layout)
        description_layout.addLayout(published_layout)

        video_title = QLabel('video title')
        view_count = QLabel('View count')
        date = QLabel('date')
        published = QLabel('more')
        view_description = QLabel('view description')
        image_label = QLabel('image')
        icon_label = QLabel('icon')
        title_label = QLabel('title')

        header_layout.addWidget(icon_label)
        header_layout.addWidget(title_label)
        image_layout.addWidget(image_label)

        video_title_layout.addWidget(video_title)
        more_layout.addWidget(view_count)
        more_layout.addWidget(date)
        more_layout.addWidget(published)
        description_layout.addWidget(view_description)
 def __init__(self, video_list, finished_listeners=None):
     """
     Init GetUploadsThread
     :param thread_id:
     :param channel:
     :param info:
     :param debug:
     """
     self.logger = create_logger(__name__ + ".UpdateVideosThread")
     threading.Thread.__init__(self)
     self.video_list = video_list
     self.finished_listeners = finished_listeners
     self.db_id = 0
Exemple #15
0
    def __init__(self, model, progress_bar):
        super().__init__()
        self.model = model
        self.progress_bar = progress_bar
        self.progress_bar.setTextVisible(True)
        self.progress_bar.setAlignment(Qt.AlignCenter)

        self.setMaximum.connect(self.set_maximum)
        self.setProgress.connect(self.set_progress)
        self.updateProgress.connect(self.update_progress)
        self.setText.connect(self.set_text)
        self.resetBar.connect(self.reset_bar)
        self.logger = create_logger(__name__ + '.ProgressBar')
Exemple #16
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()
Exemple #17
0
    def __init__(self,
                 app: QApplication,
                 main_model: MainModel,
                 dimensions=None,
                 position=None):
        super().__init__()
        self.logger = create_logger(__name__)
        self.app = app
        self.main_model = main_model

        self.themes_list = THEMES_LIST
        self.current_theme = None
        self.current_theme_idx = 0

        self.clipboard = QApplication.clipboard()
        self.status_bar = self.statusBar()
        self.menus = {}
        if dimensions:
            self.dimensions = dimensions
        else:
            self.dimensions = [770, 700]
        self.position = position
        self.central_widget = QStackedWidget()
        self.setCentralWidget(self.central_widget)

        self.grid_view = GridScrollArea(self, main_model)
        self.play_view = GridScrollArea(self, main_model)
        self.grid_view.set_view(SubFeedView(self.grid_view, self, main_model),
                                GRID_VIEW_ID)
        self.play_view.set_view(PlayView(self.play_view, self, main_model),
                                PLAY_VIEW_ID)

        self.download_view = DownloadScrollArea(self, main_model)

        self.hotkeys_view = ConfigWindow(self)
        self.hotkeys_view.setWidget(
            HotkeysViewWidget(self.hotkeys_view,
                              self,
                              icon=QIcon(
                                  os.path.join(ICONS_PATH, 'hotkeys.png'))))
        self.config_view = ConfigViewTabs(
            self, icon=QIcon(os.path.join(ICONS_PATH, 'preferences.png')))

        self.list_detailed_view = ListDetailedView(self)
        self.list_tiled_view = ListTiledView(self)
        self.subs_view = SubscriptionsView(self)
        self.about_view = AboutView(self)

        self.init_ui()
Exemple #18
0
    def __init__(self, model):
        super().__init__()
        self.logger = create_logger(__name__ + '.YtDirListener')
        self.model = model

        self.newFile.connect(self.new_file)
        self.manualCheck.connect(self.manual_check)

        disable_dir_observer = read_config('Play', 'disable_dir_listener')
        if not disable_dir_observer:
            path = read_config('Play', 'yt_file_path', literal_eval=False)
            event_handler = VidEventHandler(self)
            self.observer = Observer()
            self.observer.schedule(event_handler, path)
            self.observer.start()
Exemple #19
0
    def __init__(self, videos, videos_limit):
        super().__init__()
        self.logger = create_logger(__name__)
        self.videos_limit = videos_limit
        self.downloaded_videos_limit = videos_limit
        self.videos = videos
        self.filtered_videos = []
        self.downloaded_videos = []

        self.download_progress_signals = []

        self.logger.info("Creating listeners and threads")
        self.grid_view_listener = GridViewListener(self)
        self.grid_thread = QThread()
        self.grid_thread.setObjectName('grid_thread')
        self.grid_view_listener.moveToThread(self.grid_thread)
        self.grid_thread.start()

        self.database_listener = DatabaseListener(self)
        self.db_thread = QThread()
        self.db_thread.setObjectName('db_thread')
        self.database_listener.moveToThread(self.db_thread)
        self.db_thread.start()

        self.main_window_listener = MainWindowListener(self)
        self.main_w_thread = QThread()
        self.main_w_thread.setObjectName('main_w_thread')
        self.main_window_listener.moveToThread(self.main_w_thread)
        self.main_w_thread.start()

        self.download_handler = DownloadHandler(self)
        self.download_thread = QThread()
        self.download_thread.setObjectName('download_thread')
        self.download_handler.moveToThread(self.download_thread)
        self.download_thread.start()

        if read_config("Play", "yt_file_path", literal_eval=False):
            self.yt_dir_listener = YtDirListener(self)
            self.yt_dir_thread = QThread()
            self.yt_dir_thread.setObjectName('yt_dir_thread')
            self.yt_dir_listener.moveToThread(self.yt_dir_thread)
            self.yt_dir_thread.start()
        else:
            self.logger.warning(
                "No youtube file path provided, directory listener is disabled"
            )
Exemple #20
0
    def __init__(self, model):
        super().__init__()
        self.model = model
        self.logger = create_logger(__name__ + '.GridViewListener')
        GridViewListener.static_self = self
        static_listeners.STATIC_GRID_VIEW_LISTENER = self

        self.tileDownloaded.connect(self.tile_downloaded)
        self.tileWatched.connect(self.tile_watched)
        self.tileDiscarded.connect(self.tile_discarded)
        self.downloadFinished.connect(self.download_finished)
        self.downloadedVideosChangedinDB.connect(self.download_finished_in_db)
        self.updateGridViewFromDb.connect(self.update_grid_view_from_db)
        self.updateFromDb.connect(self.update_from_db)
        self.scrollReachedEndGrid.connect(self.scroll_reached_end_grid)
        self.scrollReachedEndPlay.connect(self.scroll_reached_end_play)
        self.thumbnailDownload.connect(self.thumbnail_download)
        self.decreaseWatchPrio.connect(self.decrease_watch_prio)
class UpdateVideo(threading.Thread):
    logger = create_logger(__name__ + ".UpdateVideo")

    def __init__(self,
                 video_d,
                 update_existing=False,
                 finished_listeners=None):
        """
        Init GetUploadsThread
        :param video_d:
        """
        threading.Thread.__init__(self)
        self.finished_listeners = finished_listeners
        self.video_d = video_d
        self.update_existing = update_existing
        self.db_id = 0

    # TODO: Handle failed requests
    def run(self):
        self.db_id = threading.get_ident()
        DatabaseListener.static_instance.startWrite.emit(self.db_id)
        """
        Override threading.Thread.run() with its own code
        :return:
        """
        # self.logger.debug("Run")
        # start = default_timer()
        lock.acquire()
        stmt = get_video_by_vidd_stmt(Video.video_d_to_video(self.video_d))
        db_video = engine.execute(stmt).first()
        if db_video:
            if self.update_existing:
                engine.execute(update_video_statement_full(self.video_d))
            else:
                pass
        else:
            engine.execute(Video.__table__.insert(), insert_item(self.video_d))
        # print('Updated: {}'.format(self.video_d.title))
        lock.release()

        if self.finished_listeners:
            for listener in self.finished_listeners:
                listener.emit()
        DatabaseListener.static_instance.finishWrite.emit(self.db_id)
Exemple #22
0
    def __init__(self, parent, *args, **kwargs):
        super(DownloadView, self).__init__(parent, *args, **kwargs)
        self.sane_paret = parent
        self.logger = create_logger(__name__)

        self.sane_layout = QVBoxLayout()
        self.sane_layout.setAlignment(Qt.AlignTop)

        self.buttons_tile = ButtonsTile(self)

        self.sane_layout.addWidget(self.buttons_tile)

        self.setLayout(self.sane_layout)

        self.widgets = []

        DownloadHandler.static_self.dbDownloadTiles.connect(
            self.update_widgets)
        DownloadHandler.static_self.newYTDLDownlaod.connect(self.new_download)

        DownloadHandler.static_self.loadDBDownloadTiles.emit()
Exemple #23
0
 def __init__(self, thread_id, youtube, channel_id, playlist_id, videos, list_pages, search_pages,
              deep_search=False):
     """
     Init GetUploadsThread
     :param thread_id:
     :param channel:
     :param info:
     :param debug:
     """
     threading.Thread.__init__(self)
     self.logger = create_logger(__name__)
     self.videos = videos
     self.thread_id = thread_id
     self.job_done = False
     self.youtube = youtube
     self.search_pages = search_pages
     self.list_pages = list_pages
     self.channel_id = channel_id
     self.playlist_id = playlist_id
     self.deep_search = deep_search
     self.exc = None
Exemple #24
0
 def __init__(self, parent, vid_limit=40, headers=None):
     """
     ListDetailedView, a table representation of relevant parts of the Subscription Feed
     :param clipboard:
     :param status_bar:
     :param vid_limit:
     """
     super(ListDetailedView, self).__init__(parent)
     self.logger = create_logger(__name__)
     self.config_file = None
     self.root = parent  # MainWindow
     self.clipboard = self.root.clipboard
     self.status_bar = self.root.status_bar
     self.vid_limit = vid_limit
     if headers:
         self.headers = headers
     else:
         self.headers = [
             'Channel', 'Title', 'URL', 'Published', 'Description',
             'Missed?', 'Downloaded?', 'Discarded?'
         ]
     self.init_ui()
    def __init__(self, parent, headers=None):
        """
        SubscriptionsView, a table representation of relevant parts of the Subscriptions list
        :param parent:
        :param clipboard:
        :param status_bar:
        :param headers:
        """
        super(SubscriptionsView, self).__init__(parent)
        self.logger = create_logger(__name__)
        self.root = parent  # MainWindow
        self.clipboard = self.root.clipboard
        self.status_bar = self.root.status_bar

        if headers:
            self.headers = headers
        else:
            self.headers = [
                'ID', 'Title', 'Uploaded Videos Playlist ID', 'Description',
                'Subscribed on YouTube?', 'Force subscription?'
            ]
        self.init_ui()
Exemple #26
0
import os
import json

from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build

from sane_yt_subfeed.log_handler import create_logger

# FIXME: module level logger not suggested: https://fangpenlin.com/posts/2012/08/26/good-logging-practice-in-python/
logger = create_logger(__name__)

OS_PATH = os.path.dirname(__file__)

CLIENT_SECRETS_FILE = os.path.join(OS_PATH, 'resources', 'client_secret.json')
KEYS_FILE = os.path.join(OS_PATH, 'resources', 'keys.json')
SCOPES = ['https://www.googleapis.com/auth/youtube.readonly']

API_SERVICE_NAME = 'youtube'
API_VERSION = 'v3'


def get_api_key():
    with open(KEYS_FILE) as keys_json_data_file:
        keys = json.load(keys_json_data_file)
    return keys['api_key']


def youtube_auth_oauth():
    """
    Authorize the request and store authorization credentials.
    :return:
Exemple #27
0
 def __init__(self, parent, video, vid_id, clipboard, status_bar):
     super().__init__(parent, video, vid_id, clipboard, status_bar)
     self.logger = create_logger(__name__)
class UpdateVideosThread(threading.Thread):
    logger = create_logger(__name__ + ".UpdateVideosThread")

    def __init__(self,
                 video_list,
                 update_existing=False,
                 uniques_check=True,
                 finished_listeners=None,
                 only_thumbnails=False):
        """
        Init GetUploadsThread
        :param thread_id:
        :param channel:
        :param info:
        :param debug:
        """
        threading.Thread.__init__(self)
        self.video_list = video_list
        self.update_existing = update_existing
        self.uniques_check = uniques_check
        self.finished_listeners = finished_listeners
        self.db_id = 0
        self.only_thumbnails = only_thumbnails

    # TODO: Handle failed requests
    def run(self):
        """
        Override threading.Thread.run() with its own code
        :return:
        """
        self.db_id = threading.get_ident()
        if self.uniques_check:
            self.video_list = check_for_unique(self.video_list)

        items_to_add = []
        items_to_update = []
        # bulk_items_to_add = []
        lock.acquire()
        self.logger.debug("Thread {} - Acquired lock".format(
            self.db_id, len(items_to_update)))
        DatabaseListener.static_instance.startRead.emit(self.db_id)
        select_step = 500
        for i in range(0, len(self.video_list), select_step):
            videos_bulk = self.video_list[i:i + select_step]
            video_ids_bulk = set(video.video_id for video in videos_bulk)
            stmt = get_video_ids_by_video_ids_stmt(video_ids_bulk)
            db_videos = Video.to_video_ds(engine.execute(stmt))
            db_videos_ids = set(video.video_id for video in db_videos)
            items_to_add.extend(
                insert_item(video) for video in videos_bulk
                if video.video_id not in db_videos_ids)
            if self.update_existing:
                items_to_update.extend(video for video in videos_bulk
                                       if video.video_id in db_videos_ids)

        DatabaseListener.static_instance.finishRead.emit(self.db_id)
        DatabaseListener.static_instance.startWrite.emit(self.db_id)
        step = 1000
        if len(items_to_add) > 0:
            self.logger.debug("Thread {} - inserting {} new videos".format(
                self.db_id, len(items_to_add)))
            for i in range(0, len(items_to_add), step):
                engine.execute(Video.__table__.insert(),
                               items_to_add[i:i + step])
        if len(items_to_update) > 0:
            self.logger.debug("Thread {} - updating {} items".format(
                self.db_id, len(items_to_update)))
            update_list = []
            # FIXME: add step to update
            for item in items_to_update:
                item_dict = item.__dict__
                item_dict["_video_id"] = item.video_id
                update_list.append(item_dict)
            engine.execute(update_video_stmt(), update_list)
        DatabaseListener.static_instance.finishWrite.emit(self.db_id)
        lock.release()
        if self.finished_listeners:
            for listener in self.finished_listeners:
                listener.emit()
Exemple #29
0
 def __init__(self):
     super().__init__()
     self.logger = create_logger(__name__)
from sane_yt_subfeed.database.models import Channel
from sane_yt_subfeed.database.orm import db_session, engine
from sane_yt_subfeed.database.write_operations import engine_execute_first, engine_execute, delete_sub_not_in_list
from sane_yt_subfeed.database.engine_statements import update_channel_from_remote, get_channel_by_id_stmt
from sane_yt_subfeed.log_handler import create_logger
from sane_yt_subfeed.pickle_handler import load_sub_list, load_youtube, dump_youtube, dump_sub_list
from sane_yt_subfeed.print_functions import remove_empty_kwargs
import datetime

YOUTUBE_URL = "https://www.youtube.com/"
YOUTUBE_PARM_VIDEO = "watch?v="
YOUTUBE_PARM_PLIST = "playlist?list ="
YT_VIDEO_URL = YOUTUBE_URL + YOUTUBE_PARM_VIDEO

# FIXME: module level logger not suggested: https://fangpenlin.com/posts/2012/08/26/good-logging-practice-in-python/
logger = create_logger(__name__)

# FIXME: integrate with socket system
logger_list_search = create_logger("youtube_requests: list()/search()",
                                   logfile="debug_list_search.log")


def get_channel_uploads_playlist_id(youtube_key, channel_id):
    """
    Get a channel's "Uploaded videos" playlist ID, given channel ID.
    :param youtube_key:
    :param channel_id:
    :return: list_uploaded_videos(channel_uploads_playlist_id, debug=debug, limit=limit)
    """
    # Get channel
    channel = channels_list(youtube_key, part='contentDetails',