def get_search_folders() -> List[str]: """Get all folders to search for maps""" bot_folders_setting = load_settings().value(BOT_FOLDER_SETTINGS_KEY, type=dict) folders = {} if "folders" in bot_folders_setting: folders = bot_folders_setting["folders"] return [k for k, v in folders.items() if v['visible']]
def init_settings(): settings = load_settings() global bot_folder_settings bot_folder_settings = settings.value(BOT_FOLDER_SETTINGS_KEY, type=dict) if not bot_folder_settings: bot_folder_settings = {'files': {}, 'folders': {}} default_folder = settings.value(DEFAULT_BOT_FOLDER, type=str) if default_folder: bot_folder_settings['folders'][default_folder] = {'visible': True}
def get_team_settings(): settings = load_settings() team_settings = settings.value(TEAM_SETTINGS_KEY, type=dict) if not team_settings: return None return { "blue_team": validate_bots(team_settings["blue_team"]), "orange_team": validate_bots(team_settings["orange_team"]) }
def update_gui_after_botpack_update(botpack_location, botpack_status): if botpack_status is BotpackStatus.SUCCESS: # Configure the folder settings. bot_folder_settings['folders'][str(botpack_location)] = {'visible': True} settings = load_settings() settings.setValue(BOT_FOLDER_SETTINGS_KEY, bot_folder_settings) settings.setValue(COMMIT_ID_KEY, get_last_botpack_commit_id()) settings.sync() scan_for_bots()
def ensure_bot_directory(): content_folder = get_content_folder() bot_directory = content_folder / CREATED_BOTS_FOLDER bot_directory.mkdir(exist_ok=True) bot_folder_settings['folders'][str(bot_directory)] = {'visible': True} settings = load_settings() settings.setValue(BOT_FOLDER_SETTINGS_KEY, bot_folder_settings) settings.sync() return bot_directory
def pick_bot_folder(): filename = pick_location(True) if filename: global bot_folder_settings bot_folder_settings['folders'][filename] = {'visible': True} settings = load_settings() settings.setValue(DEFAULT_BOT_FOLDER, filename) settings.setValue(BOT_FOLDER_SETTINGS_KEY, bot_folder_settings) settings.sync() return scan_for_bots() return []
def update_gui_after_botpack_update(botpack_location, botpack_status, additional_settings=None): if botpack_status is BotpackStatus.SUCCESS: # Configure the folder settings. bot_folder_settings['folders'][str(botpack_location)] = { 'visible': True } settings = load_settings() settings.setValue(BOT_FOLDER_SETTINGS_KEY, bot_folder_settings) if additional_settings: for key, value in additional_settings.items(): settings.setValue(key, value) settings.sync() scan_for_bots()
def download(self, repo_owner: str, repo_name: str, checkout_folder: Path, update_tag_setting=True): repo_full_name = repo_owner + '/' + repo_name folder_suffix = FOLDER_SUFFIX self.status = f'Downloading {repo_full_name}-{folder_suffix}' print(self.status) self.total_progress = 0 # Unfortunately we can't know the size of the zip file before downloading it, # so we have to get the size from the GitHub API. self.estimated_zip_size = get_repo_size(repo_full_name) if self.estimated_zip_size: # Github's compression ratio for the botpack is around 75% self.estimated_zip_size *= 0.75 # If we fail to get the repo size, set it to a fallback value, # so the progress bar will show at least some progress. # Let's assume the zip file is around 60 MB. else: self.estimated_zip_size = 60_000_000 try: latest_release = get_json_from_url( f"https://api.github.com/repos/{repo_owner}/{repo_name}/releases/latest" ) except Exception as err: print(err) return BotpackStatus.SKIPPED success = download_and_extract_zip( download_url=latest_release['zipball_url'], local_folder_path=checkout_folder, local_subfolder_name=f"{repo_name}-{folder_suffix}", clobber=True, progress_callback=self.zip_download_callback, unzip_callback=self.unzip_callback) if success is BotpackStatus.SUCCESS and update_tag_setting: settings = load_settings() settings.setValue(RELEASE_TAG, latest_release["tag_name"]) return success
def get_downloaded_botpack_commit_id(): settings = load_settings() local_commit_id = settings.value(COMMIT_ID_KEY, type=str) return local_commit_id
def save_team_settings(blue_bots, orange_bots): settings = load_settings() settings.setValue(TEAM_SETTINGS_KEY, { "blue_team": blue_bots, "orange_team": orange_bots })
def save_launcher_settings(launcher_settings_map): settings = load_settings() settings.setValue(LAUNCHER_SETTINGS_KEY, launcher_settings_map)
def save_match_settings(match_settings): settings = load_settings() settings.setValue(MATCH_SETTINGS_KEY, match_settings)
def get_match_settings(): settings = load_settings() match_settings = settings.value(MATCH_SETTINGS_KEY, type=dict) return match_settings if match_settings else None
def update(self, repo_owner: str, repo_name: str, checkout_folder: Path): repo_full_name = repo_owner + '/' + repo_name repo_url = 'https://github.com/' + repo_full_name master_folder = repo_name + "-" + FOLDER_SUFFIX settings = load_settings() local_release_tag = settings.value(RELEASE_TAG, type=str) try: latest_release = get_json_from_url(f"https://api.github.com/repos/{repo_owner}/{repo_name}/releases/latest") except Exception as err: print(err) return False # If the botpack is missing, just download the whole botpack if local_release_tag == "" or not os.path.exists(os.path.join(checkout_folder, master_folder)): return BotpackStatus.REQUIRES_FULL_DOWNLOAD if local_release_tag == latest_release["tag_name"]: print("The botpack is already up-to-date!") return BotpackStatus.REQUIRES_FULL_DOWNLOAD releases_to_download = list(range(int(local_release_tag.replace("incr-", "")) + 1, int(latest_release["tag_name"].replace("incr-", "")) + 1)) # If there are too many patches to be applied at once, don't bother and instead do a full redownload of the bot pack. Each patch has a certain # amount of overhead so at some point it becomes faster to do a full download. We also do not want to spam github with too many download requests. if len(releases_to_download) > 50: return BotpackStatus.REQUIRES_FULL_DOWNLOAD local_folder_path = Path(os.path.join(checkout_folder, master_folder)) self.total_steps = len(releases_to_download) with tempfile.TemporaryDirectory() as tmpdir: # Spawn up to 15 download threads, we want to download the updates at a fast speed without saturating the users network connection. # These threads only serve to initiate the download and mostly sit idle. with mp.Pool(min(15, len(releases_to_download))) as p: # It's very important that patches are applied in order # This is why we use imap and not imap_unordered # we want simultaneous downloads, but applying patches out of order would be a very bad idea for tag in p.imap(partial(self.download_single, tmpdir, repo_url), releases_to_download): if tag is False: print("Failed to complete botpack upgrade") return BotpackStatus.SKIPPED # apply incremental patch print(f"Applying patch incr-{tag}") self.update_progressbar_and_status(f"Applying patch {tag}") downloaded_zip_path = os.path.join(tmpdir, f"downloaded-{tag}.zip") with zipfile.ZipFile(downloaded_zip_path, 'r') as zip_ref: zip_ref.extractall(local_folder_path) with open(local_folder_path / ".deleted", "r", encoding="utf-16") as deleted_ref: files = deleted_ref.readlines() for line in files: if line.replace("\n", "").strip() != "": file_name = local_folder_path / line.replace("\n", "") if os.path.isfile(file_name): os.remove(file_name) # encase something goes wrong in the future, we can save our place between commit upgrades settings.setValue(RELEASE_TAG, f"incr-{tag}") self.current_step += 1 remove_empty_folders(local_folder_path) self.update_progressbar_and_status(f"Done") return True