def reporthook(num_blocks, block_size, file_size, dlg, start_time, filename): try: percent = min(num_blocks * block_size * 100 / file_size, 100) currently_downloaded = float(num_blocks) * block_size / (1024 * 1024) kbps_speed = num_blocks * block_size / (time.time() - start_time) eta = 0 if kbps_speed > 0: eta = (file_size - num_blocks * block_size) / kbps_speed if eta < 0: eta = 0 kbps_speed = kbps_speed / 1024 eta = divmod(eta, 60) file_size_mb = float(file_size) / (1024 * 1024) status = '{:.02f} MB of {:.02f} MB '.format(currently_downloaded, file_size_mb) status += '{} {:.02f} Kb/s '.format(get_local_string(30501), kbps_speed) status += '{} {:02d}:{:02d}'.format(get_local_string(30502), int(eta[0]), int(eta[1])) dlg.update( int(percent), '{}[CR]{}[CR]{}'.format(get_local_string(30500), filename, status)) except Exception as exc: LOG.error('[download_file] reporthook raised an error: {}', exc) dlg.update(100) if dlg.iscanceled(): raise InterruptedError
def delete_task(self, pathitems=None): # pylint: disable=unused-argument if not kodi_ops.dlg_confirm(kodi_ops.get_local_string(30051), kodi_ops.get_local_string(30043)): return with kodi_ops.show_busy_dialog(): if misc.check_task(): misc.run_manage_task('delete') if misc.check_task(): # Task deletion failed kodi_ops.show_notification(kodi_ops.get_local_string(30047)) return kodi_ops.show_notification(kodi_ops.get_local_string(30046))
def install(pathitems, params): LOG.info('Start install Kodi "{}" (params "{}")', pathitems[-1], params) use_task_scheduler = G.ADDON.getSettingBool('usetaskscheduler') save_downloads = G.ADDON.getSettingBool('save_downloads') # Download the file if not kodi_ops.dlg_confirm( kodi_ops.get_local_string(30070), kodi_ops.get_local_string(30071).format(pathitems[-1])): return # Check if the task is installed if use_task_scheduler and not misc.check_task(): kodi_ops.dlg_ok(kodi_ops.get_local_string(30070), kodi_ops.get_local_string(30072)) return # Check if destination path exist if not folder_exists(G.INSTALLER_TEMP_PATH): create_folder(G.INSTALLER_TEMP_PATH) # Check if the setup installer is already downloaded dwn_filepath = join_folders_paths(G.DOWNLOADS_PATH, '/'.join(pathitems[:-1]), pathitems[-1]) # Temp file path will be used by the Windows Task scheduled temp_filepath = join_folders_paths(G.INSTALLER_TEMP_PATH, G.INSTALLER_TEMP_NAME) if params.get('is_local', 'False') == 'True': # Get the file to install from "downloads" folder if not file_exists(dwn_filepath): raise FileExistsError('The file {] not exists'.format( pathitems[:-1])) copy_file(dwn_filepath, temp_filepath) else: # Download the file if save_downloads and file_exists(dwn_filepath): # Copy the existing file to the temp file path copy_file(dwn_filepath, temp_filepath) else: # Download the setup installer file url_file_path = '/'.join(pathitems) if not download_file(G.MIRROR_BASE_URL + url_file_path, temp_filepath, pathitems[-1]): # Download cancelled kodi_ops.show_notification(kodi_ops.get_local_string(30073)) return # Save the setup installer file if save_downloads: copy_file(temp_filepath, dwn_filepath) with kodi_ops.show_busy_dialog(): # Run the "AutoUpdateWorker" bash script _run_auto_update_worker(use_task=use_task_scheduler) # Wait a bit before close Kodi, # the bash script have to read the executable path from the Kodi process before continue time.sleep(2) kodi_ops.json_rpc('Application.Quit')
def add_task(self, pathitems=None): # pylint: disable=unused-argument if not kodi_ops.dlg_confirm(kodi_ops.get_local_string(30050), kodi_ops.get_local_string(30042)): return with kodi_ops.show_busy_dialog(): if misc.check_task(): self.delete_task() misc.run_manage_task('create') if not misc.check_task(): # Task creation failed kodi_ops.dlg_ok(kodi_ops.get_local_string(30050), kodi_ops.get_local_string(30045)) return kodi_ops.show_notification(kodi_ops.get_local_string(30044))
def get_git_history(self, pathitems=None): # Query github data filename = pathitems[0] data = _get_git_history(filename) # Generate list from github data list_items = [] for commit_data in reversed(data['commits']): # Show only "Merge" commits if not commit_data['commit']['message'].startswith('Merge'): continue list_item = xbmcgui.ListItem( label=_generate_label_from_commit(commit_data), offscreen=True) list_item.setContentLookup(False) list_items.append(list_item) # Show dialog index = 0 while index != -1: # Show "Merged PR's of: ..." dialog index = xbmcgui.Dialog().select( kodi_ops.get_local_string(30081).format(filename), list_items, preselect=index) if not index == -1: # Get PR number pr_number = re.findall(r'#(\d+)', list_items[index].getLabel()) xbmcgui.Dialog().textviewer(list_items[index].getLabel(), _get_pr_details(pr_number))
def subfolder(self, pathitems=None): G.FILES_LIST.clear() add_github_menu = 'master' in pathitems and 'nightlies' in pathitems and not self.is_local( ) folder_list = [] file_list = [] if self.is_local(): current_path = G.DOWNLOADS_PATH + '\\'.join(pathitems) for item in os.listdir(current_path): if os.path.isfile(os.path.join(current_path, item)): file_list.append(item) else: folder_list.append(item) else: url = G.MIRROR_BASE_URL + '/'.join(pathitems) + '/' from urllib.request import Request, urlopen page_response = urlopen(Request(url), timeout=10).read() # Find the folders in the webpage folder_list = re.findall(r'href="([^\/"\.]+)\/"', page_response.decode()) # Find the executables names in the webpage file_list = re.findall(r'href="([^"]*\.exe)"', page_response.decode()) directory_items = [] # Create the directory items for folder_name in folder_list: pathitems_value = ['subfolder'] + pathitems + [folder_name] directory_items.append( create_listitem(pathitems_value, is_folder=True, label=folder_name, is_local=self.is_local())) # Create the directory file items for filename in file_list: # Memorize filename in to globals, allow to find other info from items for github operations G.FILES_LIST.append(filename) pathitems_value = pathitems + [filename] if add_github_menu: # Add "View github history" menu menu_item = [(kodi_ops.get_local_string(30080), kodi_ops.run_plugin_action( build_url(['get_git_history', filename], mode=G.MODE_ACTION)))] else: menu_item = None directory_items.append( create_listitem(pathitems_value, is_folder=False, label=filename, menu_items=menu_item, is_local=self.is_local(), art_thumb='DefaultAddon.png')) title = ARCHITECTURES.get(pathitems[-1], pathitems[-1]) finalize_directory(directory_items, title=title) end_of_directory(False)
def download_file(url, dest_path, filename): start_time = time.time() dlg = xbmcgui.DialogProgress() dlg.create(G.ADDON_ID, get_local_string(30499)) try: urlretrieve( url.rstrip('/'), dest_path, lambda num_blocks, block_size, file_size: reporthook( num_blocks, block_size, file_size, dlg, start_time, filename)) return True except InterruptedError: LOG.error('Download interrupted by user') except Exception as exc: LOG.error('Download failed due to an error: {}', exc) raise Exception('Download failed') from exc finally: dlg.close() return False
def run(argv): # Initialize globals right away to avoid stale values from the last addon invocation. # Otherwise Kodi's reuseLanguageInvoker will cause some really quirky behavior! # PR: https://github.com/xbmc/xbmc/pull/13814 G.init_globals(argv) LOG.info('Started (Version {})'.format(G.VERSION_RAW)) LOG.info('URL is {}'.format(G.URL)) success = False try: pathitems = [part for part in G.REQUEST_PATH.split('/') if part] success = route(pathitems) except Exception as exc: import traceback LOG.error(traceback.format_exc()) kodi_ops.dlg_ok( 'AutoUpdateKodi', kodi_ops.get_local_string(30700).format('[{}] {}'.format( exc.__class__.__name__, exc))) if not success: from xbmcplugin import endOfDirectory endOfDirectory(handle=G.PLUGIN_HANDLE, succeeded=False) LOG.log_time_trace()
def delete_downloads(self, pathitems=None): # pylint: disable=unused-argument if kodi_ops.dlg_confirm(kodi_ops.get_local_string(30074), kodi_ops.get_local_string(30075)): with kodi_ops.show_busy_dialog(): delete_folder_contents(G.DOWNLOADS_PATH, delete_subfolders=True)
def show_notification_disconnected(**kwargs): kodi_ops.show_notification( kodi_ops.get_local_string(32001).format(**kwargs))