#!/usr/bin/env python3 import argparse import api import mcfs import npyscreen import os from colorama import Fore, Style def validate(): raise NotImplementedError def version_selector_gui(vers: list, project: str): def form(*args): f = npyscreen.Form(name=f"Select {project} version") sel = f.add(npyscreen.TitleSelectOne, value=[0, ], name="versions:", values=[ver.version_number + " for " + ", ".join(ver.game_versions) for ver in vers[::-1]], scroll_exit=True) f.edit() for ver in vers: if ver.version_number == sel.get_selected_objects()[0].split()[0]: return ver return vers[0] return form def download_cache(url: str, filename: str, size: int): cache_file_path = os.path.join(mcfs.cache_dir, filename) if not mcfs.is_path_exist(mcfs.cache_dir): os.mkdir(mcfs.cache_dir) if not mcfs.is_path_exist(cache_file_path): api.download(url, size, cache_file_path) else: print(f"{filename} is in cache.") return filename def modpack_install(filename: str): modpack = mcfs.get_modpack_info(filename) print(f"{Fore.YELLOW}Installing {modpack.name} modpack...{Style.RESET_ALL}") for file in modpack.files: path = file["path"].split("/") downloads = file["downloads"] print(file["path"]) download_cache(downloads[0], path[1], file["fileSize"]) mcfs.install(path[1], path[0]) print(f"{Fore.YELLOW}Overriding...{Style.RESET_ALL}") mcfs.install_modpacks_override(filename) def install(projects: list): to_install = [] for project in projects: project_data = api.project(project=project) to_install.append(project_data) for project in to_install: versions = api.versions(ids=str(project.versions).replace("'", '"')) # I hate this version = npyscreen.wrapper_basic(version_selector_gui(versions, project.slug)) file = type("mc_file", (object,), version.files[0]) filename = file.url.split("/")[-1] download_cache(file.url, filename, file.size) # cache_file_path = os.path.join(mcfs.cache_dir, filename) # if not mcfs.is_path_exist(mcfs.cache_dir): # os.mkdir(mcfs.cache_dir) # if not mcfs.is_path_exist(cache_file_path): # api.download(file.url, file.size, cache_file_path) # else: # print(f"{filename} is in cache.") subdir = "" match project.project_type: case "resourcepack": subdir = "resourcepacks" case "mod": subdir = "mods" case "shader": subdir = "shaderpacks" case "modpack": modpack_install(filename) continue case _: raise NotImplementedError mcfs.install(filename, subdir) def search(query: list): results = api.search(query=' '.join(query)) for result in results.hits: print(Fore.GREEN, end="") print(result.get("slug", "error"), end="") print(Style.RESET_ALL, end="") print(f' [{result.get("project_type", "error")}] ', end="") print( f' : {Fore.GREEN}{result.get("title", "error")}{Style.RESET_ALL} --- {result.get("description", "error")}') def clean(): if mcfs.is_path_exist(mcfs.cache_dir): files = os.listdir(mcfs.cache_dir) if len(files) > 0: for file in files: os.remove(os.path.join(mcfs.cache_dir, file)) print("Cache cleared successfully.") return print("Nothing to clear.") if __name__ == "__main__": desc = "Minecraft mods packet manager based on Modrinth API" parser = argparse.ArgumentParser(description=desc, formatter_class=argparse.RawTextHelpFormatter) subparsers = parser.add_subparsers(dest="method", required=True) # Переменная, в которую будет записано имя подкоманды parser_install = subparsers.add_parser("install", help="Install one or more mods or resources") parser_install.add_argument("projects", nargs="+") parser_search = subparsers.add_parser("search", help="Find a mod or a resource") parser_search.add_argument("query", nargs="+") parser_validate = subparsers.add_parser("validate", help="Validate the installation") parser_clean = subparsers.add_parser("clean", help="Clean the cache of this program") kwargs = vars(parser.parse_args()) # Получаем все поля получившегося Namespace и пихаем в словарь globals()[kwargs.pop("method")](**kwargs) # Из глобального контекста получаем функцию с названием как в method, # заодно вытаскивая название метода из списка аргументов, # затем вызываем функцию с распакованным словарём в качестве аргумента