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 channel_id: :return: returns response or raises exception """ youtube_oauth = load_youtube_resource_oauth() 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 __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)
def download_thumbnails_threaded(input_vid_list, progress_listener=None): download_thumbnails_threaded_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 download_thumbnails_threaded_logger.info( "Starting thumbnail download threads for {} videos in {} threads". format(len(input_vid_list), len(vid_list))) for vid_list_chunk in vid_list: 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 thread_list: t.join()
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()
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) if root.bgcolor: self.set_bgcolor(root.bgcolor)
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)
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)
def __init__(self, parent, video, vid_id, clipboard, status_bar): QWidget.__init__(self, parent=parent) self.logger = create_logger(__name__) self.clipboard = clipboard self.status_bar = status_bar self.video = video self.id = vid_id self.parent = parent self.root = parent.root # MainWindow self.history = self.root.history self.pref_height = read_config('Gui', 'tile_pref_height') self.pref_width = read_config('Gui', 'tile_pref_width') # NB: If you don't use a fixed size tile loading becomes glitchy as it needs to stretch to size after painting. self.setFixedSize(self.pref_width, self.pref_height) self.layout = QGridLayout() self.layout.setSpacing(0) # Don't use Qt's "global padding" spacing. # Make sure layout items don't overlap self.layout.setContentsMargins(0, 0, 0, 0) self.thumbnail_label = self.init_thumbnail_tile() if read_config('GridView', 'tile_title_lines') != 0: self.title_label = TitleLabel(video.title, self) if read_config('GridView', 'tile_channel_lines') != 0: self.channel_label = ChannelLabel(video.channel_title, self) if read_config('GridView', 'tile_date_lines') != 0: self.date_label = DateLabel('', self) self.setFixedWidth(self.pref_width) # Use a blank QLabel as spacer item for increased control of spacing (avoids global padding). spacer_label = QLabel() spacer_label.setFixedHeight( read_config('GridView', 'tile_line_spacing')) # Add labels to layout self.layout.addWidget(self.thumbnail_label) if read_config('GridView', 'add_thumbnail_spacer'): # This should only be necessary when not using fixed size scaling for ThumbnailTile. self.layout.addWidget(spacer_label) if read_config('GridView', 'tile_title_lines') != 0: self.layout.addWidget(self.title_label) self.layout.addWidget(spacer_label) if read_config('GridView', 'tile_channel_lines') != 0: self.layout.addWidget(self.channel_label) self.layout.addWidget(spacer_label) if read_config('GridView', 'tile_date_lines') != 0: self.layout.addWidget(self.date_label) self.setLayout(self.layout) # Add video on the layout/tile. self.set_video(video)
def __init__(self, videos, videos_limit): super().__init__() self.logger = create_logger(__name__) self.videos_limit = videos_limit self.playview_videos_limit = videos_limit self.videos = videos self.subfeed_videos = [] self.subfeed_videos_removed = {} self.playview_videos = [] self.playview_videos_removed = {} self.download_progress_signals = [] self.logger.info("Creating listeners and threads") self.playback_grid_view_listener = PlaybackGridViewListener(self) self.playback_grid_thread = QThread() self.playback_grid_thread.setObjectName('playback_grid_thread') self.playback_grid_view_listener.moveToThread( self.playback_grid_thread) self.playback_grid_thread.start() self.subfeed_grid_view_listener = SubfeedGridViewListener(self) self.subfeed_grid_thread = QThread() self.subfeed_grid_thread.setObjectName('subfeed_grid_thread') self.subfeed_grid_view_listener.moveToThread(self.subfeed_grid_thread) self.subfeed_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 = DownloadViewListener(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 = YoutubeDirListener(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" ) self.yt_dir_listener = None
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
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.raiseGenericException.connect(self.raise_generic_exception) self.logger = create_logger(__name__ + '.MainWindowListener')
def __init__(self, model): """ Structure/Model for GridViewListeners to inherit. :param model: """ super().__init__() self.model = model self.widget_id = None self.name = 'GridViewListener' self.logger = create_logger(__name__ + '.' + self.name) self.videos_limit = model.videos_limit
def __init__(self, parent, vid_limit=40): super(SubfeedTiledListView, 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
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__ + '.ProgressBarListener')
def __init__(self, model): super().__init__() self.logger = create_logger(__name__ + '.YoutubeDirListener') 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()
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)
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
def __init__(self, parent, vid_limit=40, headers=None): """ SubfeedDetailedListView, a table representation of relevant parts of the Subscription Feed :param clipboard: :param status_bar: :param vid_limit: """ super(SubfeedDetailedListView, 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): """ SubscriptionsDetailedListView, a table representation of relevant parts of the Subscriptions list :param parent: :param clipboard: :param status_bar: :param headers: """ super(SubscriptionsDetailedListView, 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()
def __init__(self, parent, *args, **kwargs): super(DownloadView, self).__init__(parent, *args, **kwargs) self.root = parent.root self.parent = 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 = [] DownloadViewListener.static_self.dbDownloadTiles.connect( self.update_widgets) DownloadViewListener.static_self.newYTDLDownload.connect( self.new_download) DownloadViewListener.static_self.loadDBDownloadTiles.emit()
def __init__(self, parent, root, main_model: MainModel): super().__init__(parent, root, main_model) self.logger = create_logger(__name__ + ".SubfeedGridView") self.root = root self.parent = parent # Signals defined in listener self.main_model.subfeed_grid_view_listener.videosChanged.connect( self.videos_changed) self.main_model.subfeed_grid_view_listener.videosUpdated.connect( self.update_videos) self.main_model.subfeed_grid_view_listener.redrawVideo.connect( self.redraw_video) self.main_model.subfeed_grid_view_listener.redrawVideos.connect( self.redraw_videos) self.main_model.subfeed_grid_view_listener.repaintVideo.connect( self.repaint_video) self.main_model.subfeed_grid_view_listener.repaintVideos.connect( self.repaint_videos) self.logger.debug("Init grid") self.update_grid() self.logger.info("Initialized SubfeedGridView")
def __init__(self, parent, download_progress_listener, db_download_tile=None, *args, **kwargs): super(DownloadTile, self).__init__(parent, *args, **kwargs) self.logger = create_logger(__name__) self.root = parent.root self.parent = parent if download_progress_listener: self.download_progress_listener = download_progress_listener self.video = download_progress_listener.video self.download_progress_listener.updateProgress.connect(self.update_progress) self.download_progress_listener.finishedDownload.connect(self.finished_download) self.download_progress_listener.failedDownload.connect(self.failed_download) elif db_download_tile: self.download_progress_listener = None self.video = db_download_tile.video self.total_bytes = None self.total_bytes_video = None self.total_bytes_audio = None self.video_downloaded = False self.finished = False self.paused = False self.failed = False self.finished_date = None self.started_date = None self.last_event = None self.cleared = False self.setFixedHeight(read_config('DownloadView', 'download_tile_height')) self.sane_layout = QGridLayout() # self.sane_layout.setAlignment(Qt.AlignLeading) self.sane_layout.setContentsMargins(0, 1, 10, 0) # self.setContentsMargins(0, 1, 50, 0) self.title_bar = SmallLabel(self.video.title, parent=self) self.thumbnail = DownloadThumbnailWidget(self, self.video) self.progress_bar = DownloadProgressBar(self) self.percentage_downloaded = 0 # self.progress_bar.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) self.status = SmallLabel("Status:", parent=self) self.start_finish_dates = SmallLabel("Started/Finished on:", parent=self) self.duration = SmallLabel("Duration:", parent=self) self.upload = SmallLabel("Uploaded:", parent=self) self.eta = SmallLabel("ETA:", parent=self) self.speed = SmallLabel("Speed:", parent=self) self.total_size = SmallLabel("Total size:", parent=self) self.status_value = SmallLabel("No update", parent=self) self.start_finish_dates_value = SmallLabel("No update", parent=self) self.duration_value = SmallLabel(format(self.video.duration), parent=self) self.upload_value = SmallLabel(self.video.date_published.strftime("%Y-%m-%d %H:%M:%S"), parent=self) self.eta_value = SmallLabel("No update", parent=self) self.common_eta_str = "N/A" self.common_eta_calc_tick = 0 self.etas = [] self.speed_value = SmallLabel("No update:", parent=self) self.avg_speed_str = "N/A" self.avg_speed_calc_tick = 0 self.speeds = [] self.avg_calc_ticks = 50 self.total_size_value = SmallLabel("No update:", parent=self) self.sane_layout.addWidget(self.title_bar, 0, 0, 1, 4) self.sane_layout.addWidget(self.thumbnail, 1, 0, 6, 1) self.sane_layout.addWidget(self.progress_bar, 8, 0, 1, 4) self.sane_layout.addWidget(self.status, 1, 1) self.sane_layout.addWidget(self.duration, 2, 1) self.sane_layout.addWidget(self.upload, 3, 1) self.sane_layout.addWidget(self.eta, 4, 1) self.sane_layout.addWidget(self.speed, 5, 1) self.sane_layout.addWidget(self.total_size, 6, 1) self.sane_layout.addWidget(self.start_finish_dates, 7, 1) self.sane_layout.addWidget(self.status_value, 1, 2) self.sane_layout.addWidget(self.duration_value, 2, 2) self.sane_layout.addWidget(self.upload_value, 3, 2) self.sane_layout.addWidget(self.eta_value, 4, 2) self.sane_layout.addWidget(self.speed_value, 5, 2) self.sane_layout.addWidget(self.total_size_value, 6, 2) self.sane_layout.addWidget(self.start_finish_dates_value, 7, 2) self.setLayout(self.sane_layout) if db_download_tile: self.update_from_db_tile(db_download_tile) else: pass self.logger.info("Added DL tile from DB: {}".format(self.video))
def __init__(self, parent): super().__init__(parent) self.logger = create_logger(__name__)
import apiclient import httplib2 import json from google_auth_oauthlib.flow import InstalledAppFlow from googleapiclient.discovery import build from oauthlib.oauth2 import MissingCodeError from sane_yt_subfeed.absolute_paths import KEYS_FILE, CLIENT_SECRET_FILE from sane_yt_subfeed.handlers.config_handler import read_config from sane_yt_subfeed.handlers.log_handler import create_logger from sane_yt_subfeed.settings import mutable_settings logger = create_logger(__name__) 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 build_request(http, *args, **kwargs): """ The httplib2.Http() objects are not thread-safe. Create a new Http() object for every request and override the construction of it within the service object.
def __init__(self): super().__init__() self.logger = create_logger(__name__)
def __init__(self, parent, video, vid_id, clipboard, status_bar): super().__init__(parent, video, vid_id, clipboard, status_bar) self.logger = create_logger(__name__) self.root = parent.root self.parent = parent
def __init__(self, videos, force_dl_best=True, progress_listener=None): threading.Thread.__init__(self) self.logger = create_logger(__name__ + ".DownloadThumbnail") self.videos = videos self.force_dl_best = force_dl_best self.progress_listener = progress_listener