def _start_playback(self): if self.playback_started: return self.playback_started = True self.plaback_stopped = False self.scrobbled = False self.playback_timestamp = time.time() while self._is_file_playing() and not g.abort_requested(): if (int(self.getTime()) == self.skip_intro_from and self.skip_intro): if (self.force_skip == 0 and not self.intro_skipped): self.seekTime(self.skip_intro_to) self.intro_skipped = True break elif (self.force_skip == 1): self.seekTime(self.skip_intro_to) break else: break g.close_all_dialogs() if self.smart_playlists and self.mediatype == "episode": if g.PLAYLIST.size( ) == 1 and not self.smart_module.is_season_final(): self.smart_module.build_playlist() elif g.PLAYLIST.size() == g.PLAYLIST.getposition() + 1: self.smart_module.append_next_season()
def _run(self): if self.runned_once(): return while not g.abort_requested() and self.running(): if g.wait_for_abort(.100): break g.HOME_WINDOW.setProperty(self._create_key("Running"), 'true')
def _background_info_updater(self): self.update_download_info() self.list_control.reset() while not self.exit_requested and not g.abort_requested(): xbmc.sleep(1000) self.update_download_info() self._populate_menu_items()
def do_cache(self): yesno = self.prompt_download_style() if yesno: xbmcgui.Dialog().ok(g.ADDON_NAME, g.get_language_string(30504)) self.thread_pool.put(self.status_update_loop) return {"result": "background", "source": None} else: try: progress_dialog = xbmcgui.DialogProgress() progress_dialog.create( g.get_language_string(30335), tools.create_multiline_message( line1="Title: {}".format( g.color_string( self.uncached_source["release_title"].upper()) ), line2=self._get_progress_string(), ), ) while not progress_dialog.iscanceled( ) and not g.abort_requested(): xbmc.sleep(5000) self.run_single_status_cycle() if g.KODI_VERSION >= 19: progress_dialog.update( # pylint: disable=unexpected-keyword-arg int(self.current_percent), message=tools.create_multiline_message( line1="Title: {}".format( g.color_string( self.uncached_source["release_title"]. upper())), line2=self._get_progress_string(), ), ) else: progress_dialog.update( # pylint: disable=unexpected-keyword-arg int(self.current_percent), line2=self._get_progress_string(), ) if self.current_percent == 100: progress_dialog.close() break if progress_dialog.iscanceled( ) and self.current_percent != 100: self._handle_cancellation() self.cancel_process() return {"result": "error", "source": None} else: self.uncached_source["debrid_provider"] = self.debrid_slug return { "result": "success", "source": self.uncached_source } finally: del progress_dialog
def background_tasks(self): """ Runs background watcher tasks :return: None :rtype: none """ try: try: progress_bar = self.getControlProgress(3014) except: progress_bar = None while (int(self.getTotalTime()) - int(self.getTime()) > 2 and not self.closed and self.playing_file == self.getPlayingFile() and not g.abort_requested()): xbmc.sleep(500) if progress_bar is not None: progress_bar.setPercent(self.calculate_percent()) if self.skip_intro_activated_time + self.skip_intro_open_time == int( self.getTime()): self.close() except: import traceback g.log_stacktrace() self.close()
def download(self, url, overwrite=False): """ :param url: Web Path to file eg:(http://google.com/images/randomimage.jpeg) :param overwrite: opt. This will trigger a removal any conflicting files prior to download :return: Bool - True = Completed successfully / False = Cancelled """ if not url or not url.startswith("http"): raise InvalidWebPath(url) output_file = self._create_file(url, overwrite) head = requests.head(url) if head.status_code != 200: raise requests.exceptions.ConnectionError self.file_size = int(head.headers.get("content-length", None)) self.progress = 0 self.speed = 0 for chunk in requests.get(url, stream=True).iter_content(1024 * 1024): if g.abort_requested(): self.cancel_download() if self._canceled: return False result = output_file.write(chunk) if not result: self._handle_failure() raise GeneralIOError(self._output_filename) else: self._update_status(len(chunk)) return True
def status_update_loop(self): while not g.abort_requested() and not self.cancelled: if g.wait_for_abort(10): raise KodiShutdownException( "Kodi Shutdown requested, cancelling download") try: self._update_status() g.log( self.progress_message.format( self.status, self.current_percent, self.get_display_speed(), self.seeds, )) if self.status == "finished": self._notify_user_of_completion() self._update_database() break if self.status == "downloading": self._do_download_frame() else: self._handle_failure("Unknown Failure at Debrid Provider") except KodiShutdownException: self._delete_transfer() break except Exception as e: self._delete_transfer() raise e
def background_tasks(self): """ Runs background watcher tasks :return: None :rtype: none """ try: try: progress_bar = self.getControlProgress(3014) except Exception: progress_bar = None while ( (int(self.player.getTotalTime()) - int(self.player.getTime())) > 1 and not self.closed and self.playing_file == self.player.getPlayingFile() and not g.abort_requested() ): xbmc.sleep(500) if progress_bar is not None: progress_bar.setPercent(self.calculate_percent()) if not self.closed: self.player.pause() except Exception: g.log_stacktrace() self.close()
def _do_sync_acitivites(self, remote_activities): total_activities = len(self._sync_activities_list) for idx, activity in enumerate(self._sync_activities_list): try: update_time = str(datetime.utcnow().strftime( g.DATE_TIME_FORMAT)) if g.abort_requested(): return self.current_dialog_text = "Syncing {}".format(activity[0]) self._update_progress( int(float(idx + 1) / total_activities * 100)) last_activity_update = remote_activities if activity[1] is not None: for key in activity[1]: last_activity_update = last_activity_update[key] if not self.requires_update(last_activity_update, self.activities[activity[2]]): g.log("Skipping {}, does not require update".format( activity[0])) continue g.log("Running Activity: {}".format(activity[0])) activity[3]() self._update_activity_record(activity[2], update_time) except ActivitySyncFailure as e: g.log("Falied to sync activity: {} - {}".format( activity[0], e)) self.sync_errors = True continue
def _run_service(service_info): # We only allow 5 failures in a service script before we stop trying to run the script. count = 0 while not g.abort_requested() and count < 5: count += 1 service_info['run_method'](service_info['config']) service_info['running'] = False
def do_cleanup(self): if self._exit or g.abort_requested(): return if g.get_bool_runtime_setting(self._create_key("db.clean.busy")): return g.set_runtime_setting(self._create_key("db.clean.busy"), True) query = "DELETE FROM {} where expires < ?".format(self.cache_table_name) self.execute_sql(query, (self._get_timestamp(),)) g.clear_runtime_setting(self._create_key("db.clean.busy"))
def __exit__(self, exc_type, exc_val, exc_tb): [ g.HOME_WINDOW.clearProperty(self._create_key(i)) for i in self._trakt_ids if g.HOME_WINDOW.getProperty(self._create_key(i)) == self._handle ] while not g.abort_requested() and self._still_processing(): if g.wait_for_abort(.100): break
def do_cleanup(self): if self._exit or g.abort_requested(): return if g.get_bool_runtime_setting(self._create_key("clean.busy")): return g.set_runtime_setting(self._create_key("clean.busy"), True) self._db_cache.do_cleanup() self._mem_cache.do_cleanup() g.set_runtime_setting(self._create_key("clean.lastexecuted"), CacheBase._get_timestamp()) g.clear_runtime_setting(self._create_key("clean.busy"))
def do_cleanup(self): if self._exit or g.abort_requested(): return cur_time = datetime.datetime.utcnow() if g.get_runtime_setting(self._create_key("cache.db.clean.busy")): return g.set_runtime_setting(self._create_key("cache.db.clean.busy"), "busy") query = "DELETE FROM {} where expires < ?".format( self.cache_table_name) self.execute_sql(query, (self._get_timestamp(), )) g.set_runtime_setting(self._create_key("cache.mem.clean.busy"), repr(cur_time)) g.clear_runtime_setting(self._create_key("cache.mem.clean.busy"))
def do_cleanup(self): if self._exit or g.abort_requested(): return cur_timestamp = self._get_timestamp() if g.get_bool_runtime_setting(self._create_key("mem.clean.busy")): return g.set_runtime_setting(self._create_key("mem.clean.busy"), True) self._get_index() for cache_id, expires in self._index: if expires < cur_timestamp: g.clear_runtime_setting(cache_id) g.clear_runtime_setting(self._create_key("mem.clean.busy"))
def do_cleanup(self): if self._exit or g.abort_requested(): return if g.get_runtime_setting(self._create_key("clean.busy")): return g.set_runtime_setting(self._create_key("clean.busy"), "busy") cur_time = datetime.datetime.utcnow() self._db_cache.do_cleanup() self._mem_cache.do_cleanup() g.set_runtime_setting(self._create_key("clean.lastexecuted"), repr(cur_time)) g.clear_runtime_setting(self._create_key("clean.busy"))
def do_cleanup(self): if self._exit or g.abort_requested(): return cur_time = datetime.datetime.utcnow() cur_timestamp = self._get_timestamp() if g.get_runtime_setting(self._create_key("cache.mem.clean.busy")): return g.set_runtime_setting(self._create_key("cache.mem.clean.busy"), "busy") self._get_index() for cache_id, expires in self._index: if expires < cur_timestamp: g.clear_runtime_setting(cache_id) g.set_runtime_setting(self._create_key("cache.mem.clean.busy"), repr(cur_time)) g.clear_runtime_setting(self._create_key("cache.mem.clean.busy"))
def _keep_alive(self): for i in range(0, 480): g.log("waiting") self._running_path = self.getPlayingFile() if self._is_file_playing() or self._playback_has_stopped(): break xbmc.sleep(250) self.total_time = self.getTotalTime() if self.offset and not self.resumed: self.seekTime(self.offset) self.resumed = True self._log_debug_information() self._add_subtitle_if_needed() xbmc.sleep(5000) while self._is_file_playing() and not g.abort_requested(): self._update_progress() if not self.scrobble_started: self._trakt_start_watching() time_left = int(self.total_time) - int(self.current_time) if self.min_time_before_scrape > time_left and not self.pre_scrape_initiated: self._handle_pre_scrape() if (self.watched_percentage >= self.playCountMinimumPercent) and not self.scrobbled: self._trakt_stop_watching() self._handle_bookmark() if self.dialogs_enabled and not self.dialogs_triggered: if time_left <= self.playing_next_time: xbmc.executebuiltin( 'RunPlugin("plugin://plugin.video.seren/?action=runPlayerDialogs")' ) self.dialogs_triggered = True xbmc.sleep(100) self._end_playback()
def do_cleanup(self): """ Process cleaning up expired values from cache locations :return: :rtype: """ if g.abort_requested(): return cur_time = datetime.datetime.utcnow() if g.HOME_WINDOW.getProperty(self._create_key("cache.db.clean.busy")): return g.HOME_WINDOW.setProperty(self._create_key("cache.db.clean.busy"), "busy") query = "DELETE FROM {} where expires < ?".format( self.cache_table_name) self.execute_sql(query, (self._get_timestamp(), )) g.HOME_WINDOW.setProperty(self._create_key("cache.mem.clean.busy"), repr(cur_time)) g.HOME_WINDOW.clearProperty(self._create_key("cache.mem.clean.busy"))
def _create_connection(self): retries = 0 while not retries == 50 and not g.abort_requested(): import sqlite3 try: connection = sqlite3.connect( # pylint: disable=no-member self.path, timeout=30, detect_types=sqlite3.PARSE_DECLTYPES, # pylint: disable=no-member isolation_level=None, check_same_thread=False) self._set_connection_settings(connection) return connection except sqlite3.OperationalError as error: # pylint: disable=no-member if "database is locked" in g.UNICODE(error): g.log( "database is locked waiting: {}".format(self.path), "warning", ) g.wait_for_abort(0.1) retries += 1
def background_tasks(self): """ Runs background watcher tasks :return: """ try: try: progress_bar = self.getControlProgress(3014) except RuntimeError: progress_bar = None while (int(self.getTotalTime()) - int(self.getTime()) > 2 and not self.closed and self.playing_file == self.getPlayingFile() and not g.abort_requested()): xbmc.sleep(500) if progress_bar is not None: progress_bar.setPercent(self.calculate_percent()) self.smart_play_action() except Exception: g.log_stacktrace() self.close()
def _keep_alive(self): for i in range(0, 480): self._running_path = self.getPlayingFile() if self._is_file_playing() or self._playback_has_stopped(): break xbmc.sleep(250) if self.offset and not self.resumed: self.seekTime(self.offset) self.resumed = True while self._is_file_playing() and not g.abort_requested(): if (int(self.getTime()) == self.intro_dialog_delay and self.intro_dialog_enabled and not self.intro_dialog_triggered): xbmc.executebuiltin( 'RunPlugin("plugin://plugin.video.seren/?action=runIntroDialog")' ) self.intro_dialog_triggered = True break elif (int(self.getTime()) >= self.intro_dialog_delay + self.intro_dialog_open_time or not self.intro_dialog_enabled): break self.total_time = self.getTotalTime() self._log_debug_information() self._add_subtitle_if_needed() xbmc.sleep(5000) while self._is_file_playing() and not g.abort_requested(): self._update_progress() self._default_action() if (int(self.getTime()) == self.skip_intro_from and self.skip_intro): if (self.force_skip == 1): self.seekTime(self.skip_intro_to) if not self.scrobble_started: self._trakt_start_watching() time_left = int(self.total_time) - int(self.current_time) if self.min_time_before_scrape > time_left and not self.pre_scrape_initiated: self._handle_pre_scrape() if (self.watched_percentage >= self.playCountMinimumPercent) and not self.scrobbled: self._trakt_stop_watching() self._handle_bookmark() if self.playing_next_dialog_enabled and not self.playing_next_dialog_triggered: if time_left <= self.playing_next_time: xbmc.executebuiltin( 'RunPlugin("plugin://plugin.video.seren/?action=runPlayingNextDialog")' ) self.playing_next_dialog_triggered = True if self.still_watching_dialog_enabled and not self.still_watching_dialog_triggered: if self.watched_percentage == randint( 75, self.playCountMinimumPercent): xbmc.executebuiltin( 'RunPlugin("plugin://plugin.video.seren/?action=runStillWatchingDialog")' ) self.still_watching_dialog_triggered = True xbmc.sleep(100) self._end_playback()
def __exit__(self, exc_type, exc_val, exc_tb): for i in self._running_ids: g.clear_runtime_setting(self._create_key(i)) while not g.abort_requested() and self._still_processing(): if g.wait_for_abort(.100): break
def get_sources(self, overwrite_torrent_cache=False): """ Main endpoint to initiate scraping process :param overwrite_cache: :return: Returns (uncached_sources, sorted playable sources, items metadata) :rtype: tuple """ try: g.log('Starting Scraping', 'debug') g.log("Timeout: {}".format(self.timeout), 'debug') g.log("Pre-term-enabled: {}".format(g.get_setting("preem.enabled")), 'debug') g.log("Pre-term-limit: {}".format(g.get_setting("preem.limit")), 'debug') g.log("Pre-term-movie-res: {}".format(g.get_setting("preem.movieres")), 'debug') g.log("Pre-term-show-res: {}".format(g.get_setting("preem.tvres")), 'debug') g.log("Pre-term-type: {}".format(g.get_setting("preem.type")), 'debug') g.log("Pre-term-cloud-files: {}".format(g.get_setting("preem.cloudfiles")), 'debug') g.log("Pre-term-adaptive-files: {}".format(g.get_setting("preem.adaptiveSources")), 'debug') self._handle_pre_scrape_modifiers() self._get_imdb_info() if overwrite_torrent_cache: self._clear_local_torrent_results() else: self._check_local_torrent_database() self._update_progress() if self._prem_terminate(): return self._finalise_results() self._init_providers() # Add the users cloud inspection to the threads to be run self.torrent_threads.put(self._user_cloud_inspection) # Load threads for all sources self._create_torrent_threads() self._create_hoster_threads() self._create_adaptive_threads() self.window.create() self.window.set_text(g.get_language_string(30054), self.progress, self.sources_information, self.runtime) self.window.set_property('process_started', 'true') # Keep alive for gui display and threading g.log('Entering Keep Alive', 'info') start_time = time.time() while self.progress < 100 and not g.abort_requested(): g.log('Remaining Providers {}'.format(self.sources_information["remainingProviders"])) if self._prem_terminate() is True or (len(self.sources_information["remainingProviders"]) == 0 and self.runtime > 5): # Give some time for scrapers to initiate break if self.canceled: monkey_requests.PRE_TERM_BLOCK = True break self._update_progress() try: self.window.set_text("4K: {} | 1080: {} | 720: {} | SD: {}".format( g.color_string(self.sources_information["torrents_quality"][0] + self.sources_information["hosters_quality"][0]), g.color_string(self.sources_information["torrents_quality"][1] + self.sources_information["hosters_quality"][1]), g.color_string(self.sources_information["torrents_quality"][2] + self.sources_information["hosters_quality"][2]), g.color_string(self.sources_information["torrents_quality"][3] + self.sources_information["hosters_quality"][3]), ), self.progress, self.sources_information, self.runtime) except (KeyError, IndexError) as e: g.log('Failed to set window text, {}'.format(e), 'error') # Update Progress xbmc.sleep(200) self.runtime = time.time() - start_time self.progress = int(100 - float(1 - (self.runtime / float(self.timeout))) * 100) g.log('Exited Keep Alive', 'info') return self._finalise_results() finally: self.window.close()
def _service_trigger_loop(self): while not g.abort_requested(): xbmc.sleep(500) self._handle_messages(self.get_messages())
def download(self, url, overwrite=False): """ :param url: Web Path to file eg:(http://google.com/images/randomimage.jpeg) :param overwrite: opt. This will trigger a removal any conflicting files prior to download :return: Bool - True = Completed successfully / False = Cancelled """ g.log("Downloading file: {}".format(url)) if not url or not url.startswith("http"): raise InvalidWebPath(url) if self.output_filename is None: self.output_filename = url.split("/")[-1] g.log("Filename: {} - Location: {}".format(self.output_filename, self.storage_location)) output_file = self._create_file(url, overwrite) self._output_file = output_file g.log("Created file - {}".format(self._output_path)) head = requests.head(url) if head.status_code != 200: g.log("Server did not respond correctly to the head request") self._handle_failure() raise requests.exceptions.ConnectionError(head.status_code) self.url_hash = tools.md5_hash(url) if not self._add_download_to_dm(): g.log("Failed to create download manager task", "error") self._handle_failure() return self.file_size = int(head.headers.get("content-length", None)) self.progress = 0 self.speed = 0 self.status = "downloading" for chunk in requests.get(url, stream=True).iter_content(1024 * 1024): if g.abort_requested(): self._handle_failure() g.log( "Shutdown requested - Cancelling download: {}".format( self.output_filename), "warning", ) self.cancel_download() if self._is_canceled(): g.log( "User cancellation - Cancelling download: {}".format( self.output_filename), "warning", ) self.cancel_download() self.status = "canceled" return False result = output_file.write(chunk) if not result: self._handle_failure() self.status = "failed" g.log( "Failed to fetch chunk from remote server -" " Cancelling download: {}".format(self.output_filename), "error", ) raise GeneralIOError(self.output_filename) else: self._update_status(len(chunk)) g.log("Download has completed successfully - Filename: {}".format( self.output_filename)) return True
def _run(self): while not g.abort_requested() and self._running(): if g.wait_for_abort(.100): break g.set_runtime_setting(self._create_key("Running"), True) self._check_ran_once_already()