From 9c7819dfbdeb8bb53537dcdbbc46aea6e6ae9c7d Mon Sep 17 00:00:00 2001 From: Evgenij Titarenko Date: Sun, 23 Jul 2023 14:15:53 +0300 Subject: [PATCH 1/7] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B8=20=D1=80=D0=B5=D1=81=D1=83=D1=80=D1=81=20?= =?UTF-8?q?=D0=B8=20=D1=88=D0=B5=D0=B9=D0=B4=D0=B5=D1=80=20=D0=BF=D0=B0?= =?UTF-8?q?=D0=BA=D0=BE=D0=B2.=20=D0=92=D1=8B=D0=B1=D1=80=D0=B0=D1=81?= =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BE=D1=88=D0=B8=D0=B1?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=BF=D1=80=D0=B8=20=D0=BF=D0=BE=D0=BF=D1=83?= =?UTF-8?q?=D1=82=D0=BA=D0=B8=20=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=BC=D0=BE=D0=B4=D0=BF=D0=B0=D0=BA=D0=B0=20-?= =?UTF-8?q?=20=D1=82=D1=80=D0=B5=D0=B1=D1=83=D0=B5=D1=82=D1=81=D1=8F=20?= =?UTF-8?q?=D0=B8=D0=B7=D1=83=D1=87=D0=B8=D1=82=D1=8C=20=D0=BA=D0=B0=D0=BA?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=B2=D0=BB=D0=B8=D1=8F=D0=BB=D0=BE=20=20=D0=B8?= =?UTF-8?q?=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D1=86=D0=B5=D1=81=D1=81=D0=B0=20=D1=83=D1=81=D1=82=D0=B0?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mc-get.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/mc-get.py b/mc-get.py index 86d46ab..284336b 100755 --- a/mc-get.py +++ b/mc-get.py @@ -74,15 +74,25 @@ def install(projects: list, version, loader): for project in projects_ids: project_data = api.project(project=project) - versions = api.get_versions(project=project, loaders=f'["{loader}"]', - game_versions=f'["{mc_ver}"]') + match project_data.project_type: + case "resourcepack": + versions = api.get_versions(project=project, game_versions=f'["{mc_ver}"]') + case "mod": + versions = api.get_versions(project=project, loaders=f'["{loader}"]', game_versions=f'["{mc_ver}"]') + case "shader": # TODO: Реализовать поддержку загрузчиков шейдеров + versions = api.get_versions(project=project, game_versions=f'["{mc_ver}"]') + case "modpack": # TODO: [РЕГРЕССИЯ] Реализовать поддержку модпаков + raise NotImplementedError + case _: + raise NotImplementedError + if versions: to_install.append((project_data, versions[0])) dependency_solver(versions[0]) else: unavailable.append(project_data) - - print("To install:", *[project.title + " " + version.version_number for project, version in to_install], sep="\n\t") + if to_install: + print("To install:", *[project.title + " " + version.version_number for project, version in to_install], sep="\n\t") if dependencies_to_install: print("With dependencies:", *[project.title + " " + version.version_number for project, version in dependencies_to_install], @@ -93,14 +103,19 @@ def install(projects: list, version, loader): if unavailable: print("Cannot be installed:", *[project.title for project in unavailable], sep="\n\t") - choose = input("Continue? [y/n]") + all_to_install = to_install + dependencies_to_install + + if not all_to_install: + return + + choose = input("Continue? [y/n] ") if choose.strip().lower() in ["n", "no"]: print("Canceled.") return - for project, version in to_install + dependencies_to_install: + for project, version in all_to_install: file = type("mc_file", (object,), version.files[0]) - filename = project.slug + ".jar" + filename = file.filename download_cache(file.url, filename, file.size) match project.project_type: case "resourcepack": From 3c435c82decdec1b1693c0122f1ce81eb43eaa2e Mon Sep 17 00:00:00 2001 From: Evgenij Titarenko Date: Sun, 23 Jul 2023 15:28:33 +0300 Subject: [PATCH 2/7] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20#2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mc-get.py | 73 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/mc-get.py b/mc-get.py index 284336b..577eabd 100755 --- a/mc-get.py +++ b/mc-get.py @@ -6,7 +6,6 @@ import os import mcgetdb from colorama import Fore, Style -db = mcgetdb.McGetDB(mcfs.mc_dir) def validate(): raise NotImplementedError @@ -92,7 +91,8 @@ def install(projects: list, version, loader): else: unavailable.append(project_data) if to_install: - print("To install:", *[project.title + " " + version.version_number for project, version in to_install], sep="\n\t") + print("To install:", *[project.title + " " + version.version_number for project, version in to_install], + sep="\n\t") if dependencies_to_install: print("With dependencies:", *[project.title + " " + version.version_number for project, version in dependencies_to_install], @@ -159,37 +159,55 @@ def clean(): if __name__ == "__main__": + def exit(): + import sys + sys.exit("MC installation not found. If the program is not installed in the default location, " + "then specify the path to the installation through the MC_DIR environment variable.") + + if not mcfs.is_path_exist(mcfs.mc_dir): + exit() + + db = mcgetdb.McGetDB(mcfs.mc_dir) + + def __select_version(versions): - if len(versions) > 0: - print("Installed MC versions: ") - for id, version in enumerate(versions): - print(id + 1, version.version_number + (f" with {version.modloader}" if version.is_modified else ""), - sep=": ") - if len(versions) > 1: - id_to_use = -1 - while id_to_use not in range(1, len(versions)): - id_input = input(f"Select MC version to use [1-{len(versions)}]: ") - if not id_input.isnumeric(): - continue - id_to_use = int(id_input) - else: - id_to_use = 1 - selected_version = versions[id_to_use - 1] - print("Selected MC version:", selected_version.version_number + - (f" with {selected_version.modloader}" if selected_version.is_modified else "")) - return selected_version + if not versions: + return None + print("Installed MC versions: ") + for id, version in enumerate(versions): + print(id + 1, + version.version_number + (f" with {version.modloader}" if version.is_modified else ""), + sep=": ") + if len(versions) > 1: + id_to_use = -1 + while id_to_use not in range(1, len(versions)): + id_input = input(f"Select MC version to use [1-{len(versions)}]: ") + if not id_input.isnumeric(): + continue + id_to_use = int(id_input) + else: + id_to_use = 1 + selected_version = versions[id_to_use - 1] + print("Selected MC version:", selected_version.version_number + + (f" with {selected_version.modloader}" if selected_version.is_modified else "")) + return selected_version properties = db.get_properties() if not properties: version_to_use = __select_version(mcfs.get_installed_mc_versions()) - if version_to_use.is_modified: # TODO: Добавить иерархию каталогов - db.set_properties(version_to_use.version_number, version_to_use.modloader) + if version_to_use: + if version_to_use.is_modified: # TODO: Добавить иерархию каталогов + db.set_properties(version_to_use.version_number, version_to_use.modloader) + else: + db.set_properties(version_to_use.version_number) + properties = db.get_properties() else: - db.set_properties(version_to_use.version_number) - properties = db.get_properties() - print(properties) - _, mc_ver, loader, _ = properties + properties = None + if properties: + _, mc_ver, loader, _ = properties + else: + mc_ver, loader = None, None desc = "Minecraft mods packet manager based on Modrinth API" parser = argparse.ArgumentParser(description=desc, @@ -208,8 +226,9 @@ if __name__ == "__main__": 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 и пихаем в словарь + if not properties: + exit() globals()[kwargs.pop("method")](**kwargs) # Из глобального контекста получаем функцию с названием как в method, # заодно вытаскивая название метода из списка аргументов, # затем вызываем функцию с распакованным словарём в качестве аргумента From 109168160c8a5dbe39440e591234ed0a79ec5b34 Mon Sep 17 00:00:00 2001 From: Evgenij Titarenko Date: Sun, 23 Jul 2023 17:15:12 +0300 Subject: [PATCH 3/7] =?UTF-8?q?=D0=9C=D0=BE=D0=B4=D0=BF=D0=B0=D0=BA=D0=B8?= =?UTF-8?q?=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D1=8E=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mc-get.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mc-get.py b/mc-get.py index 577eabd..d1eeff0 100755 --- a/mc-get.py +++ b/mc-get.py @@ -76,12 +76,10 @@ def install(projects: list, version, loader): match project_data.project_type: case "resourcepack": versions = api.get_versions(project=project, game_versions=f'["{mc_ver}"]') - case "mod": + case "mod" | "modpack": versions = api.get_versions(project=project, loaders=f'["{loader}"]', game_versions=f'["{mc_ver}"]') case "shader": # TODO: Реализовать поддержку загрузчиков шейдеров versions = api.get_versions(project=project, game_versions=f'["{mc_ver}"]') - case "modpack": # TODO: [РЕГРЕССИЯ] Реализовать поддержку модпаков - raise NotImplementedError case _: raise NotImplementedError From 699b7c5f145b4f074c5aaff99e8056ff5750fc02 Mon Sep 17 00:00:00 2001 From: Evgenij Titarenko Date: Sun, 23 Jul 2023 18:47:01 +0300 Subject: [PATCH 4/7] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA?= =?UTF-8?q?=D0=B0=20=D1=85=D1=8D=D1=88=D0=B0=20=D0=BF=D1=80=D0=B8=20=D1=83?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BA=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mc-get.py | 25 +++++++++++++++++++++---- mcfs.py | 13 ++++++++++++- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/mc-get.py b/mc-get.py index d1eeff0..a2a56f6 100755 --- a/mc-get.py +++ b/mc-get.py @@ -7,11 +7,15 @@ import mcgetdb from colorama import Fore, Style +class HashError(ValueError): + """Incorrect hash""" + + def validate(): raise NotImplementedError -def download_cache(url: str, filename: str, size: int): +def download_cache(url: str, filename: str, size: int, hash: str): cache_file_path = os.path.join(mcfs.cache_dir, filename) if not mcfs.is_path_exist(mcfs.cache_dir): os.mkdir(mcfs.cache_dir) @@ -19,7 +23,9 @@ def download_cache(url: str, filename: str, size: int): api.download(url, size, cache_file_path) else: print(f"{filename} is in cache.") - return filename + if mcfs.check_file_hash(cache_file_path, hash): + os.remove(cache_file_path) + raise HashError(f"Incorrect hash for {filename}") def modpack_install(filename: str): @@ -29,7 +35,7 @@ def modpack_install(filename: str): path = file["path"].split("/") downloads = file["downloads"] print(file["path"]) - download_cache(downloads[0], path[1], file["fileSize"]) + download_cache(downloads[0], path[1], file["fileSize"], file["hashes"]["sha512"]) mcfs.install(path[1], path[0]) print(f"{Fore.YELLOW}Overriding...{Style.RESET_ALL}") mcfs.install_modpacks_override(filename) @@ -111,10 +117,18 @@ def install(projects: list, version, loader): print("Canceled.") return + failed_to_install = [] + for project, version in all_to_install: file = type("mc_file", (object,), version.files[0]) filename = file.filename - download_cache(file.url, filename, file.size) + try: + download_cache(file.url, filename, file.size, file.hashes["sha512"]) + except HashError: + print(f"Failed to install {project.title} ({project.slug}) [{version.version_number}] due to an incorrect " + f"hash") + failed_to_install.append((project, version)) + continue match project.project_type: case "resourcepack": subdir = "resourcepacks" @@ -129,6 +143,9 @@ def install(projects: list, version, loader): raise NotImplementedError mcfs.install(filename, subdir) + if failed_to_install: + print("Failed to install:", + *[project.title + " " + version.version_number for project, version in failed_to_install], sep="\n\t") def search(query: list): diff --git a/mcfs.py b/mcfs.py index c852838..7eb3833 100644 --- a/mcfs.py +++ b/mcfs.py @@ -3,7 +3,7 @@ from sys import platform import shutil import zipfile import json - +from hashlib import sha512 class MCVersion: def __init__(self, version_number, is_modified=False, modloader=None): @@ -118,3 +118,14 @@ def get_installed_mc_versions(): pass versions.append(mc_ver) return sorted(versions, reverse=True) + + +def check_file_hash(path, ref_hash): + buffer_size = 65536 + hash = sha512() + with open(path, 'rb') as f: + data = True + while data: + data = f.read(buffer_size) + hash.update(data) + return hash.hexdigest() == ref_hash From 097512e1e21c63adf28070f282d5b7bd1113d4b2 Mon Sep 17 00:00:00 2001 From: Evgenij Titarenko Date: Sun, 23 Jul 2023 19:04:27 +0300 Subject: [PATCH 5/7] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5?= =?UTF-8?q?=D1=82=D1=80=D0=B0=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8?= =?UTF-8?q?=20install?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mc-get.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mc-get.py b/mc-get.py index a2a56f6..168aa7c 100755 --- a/mc-get.py +++ b/mc-get.py @@ -41,7 +41,7 @@ def modpack_install(filename: str): mcfs.install_modpacks_override(filename) -def install(projects: list, version, loader): +def install(projects: list, mc_ver, loader): to_install = [] dependencies_to_install = [] not_found = [] From c292a7f51679a664a8b27ddaf8b534b27418ce42 Mon Sep 17 00:00:00 2001 From: Evgenij Titarenko Date: Sun, 23 Jul 2023 22:54:55 +0300 Subject: [PATCH 6/7] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B4=D0=BE=D0=BB=D0=B6?= =?UTF-8?q?=D0=B0=D1=8E=20=D0=B8=D0=BC=D0=BF=D0=BB=D0=B5=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=B0=D1=86=D0=B8=D1=8E=20=D0=91=D0=94.=20=D0=A3=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D1=89=D0=B8=D0=BA=20=D1=82=D0=B5?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D1=8C=20=D1=81=D0=BE=D1=85=D1=80=D0=B0=D0=BD?= =?UTF-8?q?=D1=8F=D0=B5=D1=82=20=D0=B8=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C=D0=B7=D1=83=D0=B5=D1=82=20=D0=B8=D0=BD=D1=84=D0=BE=D1=80?= =?UTF-8?q?=D0=BC=D0=B0=D1=86=D0=B8=D1=8E=20=D0=BE=D0=B1=20=D1=83=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D1=85=20=D0=BC=D0=BE=D0=B4=D0=B0=D1=85.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mc-get.py | 40 ++++++++++++++++++++++++++++++---- mcgetdb.py | 64 +++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 95 insertions(+), 9 deletions(-) diff --git a/mc-get.py b/mc-get.py index 168aa7c..dee62b8 100755 --- a/mc-get.py +++ b/mc-get.py @@ -23,7 +23,7 @@ def download_cache(url: str, filename: str, size: int, hash: str): api.download(url, size, cache_file_path) else: print(f"{filename} is in cache.") - if mcfs.check_file_hash(cache_file_path, hash): + if not mcfs.check_file_hash(cache_file_path, hash): os.remove(cache_file_path) raise HashError(f"Incorrect hash for {filename}") @@ -47,8 +47,18 @@ def install(projects: list, mc_ver, loader): not_found = [] unavailable = [] projects_ids = [] + already_installed = [] + + def get_mod_info_from_db(slug): + _db = mcgetdb.McGetDB(mcfs.mc_dir) + return _db.select_mod(slug) + _db.select_shader(slug) + _db.select_resourcepack(slug) + _db.select_modpack(slug) def check_project(slug): + if __name__ == "__main__": + mod_info = get_mod_info_from_db(slug) + if mod_info: + already_installed.append(mod_info[0]) + return id = api.check_project(project=slug) if id: projects_ids.append(id.id) @@ -107,6 +117,9 @@ def install(projects: list, mc_ver, loader): if unavailable: print("Cannot be installed:", *[project.title for project in unavailable], sep="\n\t") + if already_installed: + print("Already installed:", *[name + " " + version for _, name, _, version, _ in already_installed], sep="\n\t") + all_to_install = to_install + dependencies_to_install if not all_to_install: @@ -122,13 +135,15 @@ def install(projects: list, mc_ver, loader): for project, version in all_to_install: file = type("mc_file", (object,), version.files[0]) filename = file.filename + hash = file.hashes["sha512"] try: - download_cache(file.url, filename, file.size, file.hashes["sha512"]) + download_cache(file.url, filename, file.size, hash) except HashError: print(f"Failed to install {project.title} ({project.slug}) [{version.version_number}] due to an incorrect " f"hash") failed_to_install.append((project, version)) continue + match project.project_type: case "resourcepack": subdir = "resourcepacks" @@ -138,10 +153,27 @@ def install(projects: list, mc_ver, loader): subdir = "shaderpacks" case "modpack": modpack_install(filename) - continue + subdir = "modpacks" case _: raise NotImplementedError + if __name__ == "__main__": + db = mcgetdb.McGetDB(mcfs.mc_dir) + match project.project_type: + case "resourcepack": + db.add_resourcepack(slug=project.slug, proj_name=project.title, filename=filename, + version=version.version_number, hash=hash) + case "mod": + db.add_mod(slug=project.slug, proj_name=project.title, filename=filename, + version=version.version_number, hash=hash) + case "shader": + db.add_shader(slug=project.slug, proj_name=project.title, filename=filename, + version=version.version_number, hash=hash) + case "modpack": + db.add_modpack(slug=project.slug, proj_name=project.title, filename=filename, + version=version.version_number, hash=hash) + case _: + raise NotImplementedError mcfs.install(filename, subdir) if failed_to_install: print("Failed to install:", @@ -232,7 +264,7 @@ if __name__ == "__main__": parser_install = subparsers.add_parser("install", help="Install one or more mods or resources") parser_install.add_argument("projects", nargs="+") - parser_install.add_argument("--version", default=mc_ver) + parser_install.add_argument("--mc_ver", default=mc_ver) parser_install.add_argument("--loader", default=loader) parser_search = subparsers.add_parser("search", help="Find a mod or a resource") diff --git a/mcgetdb.py b/mcgetdb.py index 6d0bb38..7e195dc 100644 --- a/mcgetdb.py +++ b/mcgetdb.py @@ -3,6 +3,7 @@ import os DB_VERSION = 1 + class McGetDB: def __init_db(self): @@ -10,8 +11,34 @@ class McGetDB: db.execute(''' CREATE TABLE IF NOT EXISTS mods ( slug TEXT PRIMARY KEY NOT NULL, - install_path TEXT NOT NULL, - version TEXT NOT NULL + proj_name TEXT NOT NULL, + filename TEXT NOT NULL, + version TEXT NOT NULL, + hash TEXT NOT NULL + );''') + db.execute(''' + CREATE TABLE IF NOT EXISTS resourcepacks ( + slug TEXT PRIMARY KEY NOT NULL, + proj_name TEXT NOT NULL, + filename TEXT NOT NULL, + version TEXT NOT NULL, + hash TEXT NOT NULL + );''') + db.execute(''' + CREATE TABLE IF NOT EXISTS shaderpacks ( + slug TEXT PRIMARY KEY NOT NULL, + proj_name TEXT NOT NULL, + filename TEXT NOT NULL, + version TEXT NOT NULL, + hash TEXT NOT NULL + );''') + db.execute(''' + CREATE TABLE IF NOT EXISTS modpacks ( + slug TEXT PRIMARY KEY NOT NULL, + proj_name TEXT NOT NULL, + filename TEXT NOT NULL, + version TEXT NOT NULL, + hash TEXT NOT NULL );''') db.execute(''' CREATE TABLE IF NOT EXISTS properties ( @@ -26,6 +53,16 @@ class McGetDB: self.db = sqlite3.connect(self.db_path) self.__init_db() + self.add_mod = self.__db_insert("mods") + self.add_resourcepack = self.__db_insert("resourcepacks") + self.add_shader = self.__db_insert("shaderpacks") + self.add_modpack = self.__db_insert("modpacks") + + self.select_mod = self.__db_select_by_col("mods", "slug") + self.select_resourcepack = self.__db_select_by_col("resourcepacks", "slug") + self.select_shader = self.__db_select_by_col("shaderpacks", "slug") + self.select_modpack = self.__db_select_by_col("modpacks", "slug") + def get_properties(self): properties = None with self.db as db: @@ -34,7 +71,7 @@ class McGetDB: ''').fetchone() return properties - def set_properties(self, mc_ver, modloader = "NULL", dir_hierarhy = "default"): + def set_properties(self, mc_ver, modloader="NULL", dir_hierarhy="default"): with self.db as db: db.execute(''' DELETE FROM properties; @@ -43,8 +80,25 @@ class McGetDB: INSERT INTO properties VALUES (?, ?, ?, ?) ''', (DB_VERSION, mc_ver, modloader, dir_hierarhy)) - def add_mod(self): - pass + def __db_insert(self, table): + def insertion_func(**kargs): + keys = [] + values = [] + for key, value in kargs.items(): + keys.append(key) + values.append(value) + with self.db as db: + db.execute(f''' + INSERT INTO {table} ({', '.join([key for key in keys])}) VALUES ({', '.join(['?' for _ in values])}) + ''', values) + return insertion_func + + def __db_select_by_col(self, table, col): + def selection_func(col_value): + with self.db as db: + res = db.execute(f'SELECT * FROM {table} WHERE {col} = "{col_value}"') + return res.fetchall() + return selection_func def remove_mod(self): pass From b9fe58a482a5abc62fd81f7e4562a75dce2c5ac1 Mon Sep 17 00:00:00 2001 From: Evgenij Titarenko Date: Sun, 23 Jul 2023 23:31:28 +0300 Subject: [PATCH 7/7] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B4=D0=BE=D0=BB=D0=B6?= =?UTF-8?q?=D0=B0=D1=8E=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=83=20=D0=BD?= =?UTF-8?q?=D0=B0=D0=B4=20=D0=91=D0=94.=20=D0=9D=D0=B0=D1=87=D0=B0=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D0=B0=D1=8F=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D1=8F=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BF=D0=B0=D0=BA=D0=B5=D1=82=D0=BE=D0=B2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mc-get.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- mcfs.py | 8 ++++++++ mcgetdb.py | 12 ++++++++++-- 3 files changed, 68 insertions(+), 4 deletions(-) diff --git a/mc-get.py b/mc-get.py index dee62b8..423e18f 100755 --- a/mc-get.py +++ b/mc-get.py @@ -49,13 +49,13 @@ def install(projects: list, mc_ver, loader): projects_ids = [] already_installed = [] - def get_mod_info_from_db(slug): + def get_project_info_from_db(slug): _db = mcgetdb.McGetDB(mcfs.mc_dir) return _db.select_mod(slug) + _db.select_shader(slug) + _db.select_resourcepack(slug) + _db.select_modpack(slug) def check_project(slug): if __name__ == "__main__": - mod_info = get_mod_info_from_db(slug) + mod_info = get_project_info_from_db(slug) if mod_info: already_installed.append(mod_info[0]) return @@ -204,6 +204,50 @@ def clean(): print("Nothing to clear.") +def remove(projects): # TODO: 1. Проверка зависимостей? 2. Модпаки + if __name__ == "__main__": + db = mcgetdb.McGetDB(mcfs.mc_dir) + + mods_to_remove = [] + resources_to_remove = [] + shaders_to_remove = [] + modpacks_to_remove = [] + + for project in projects: + for res in db.select_mod(project): + mods_to_remove.append(res) + for res in db.select_resourcepack(project): + resources_to_remove.append(res) + for res in db.select_shader(project): + shaders_to_remove.append(res) + for res in db.select_modpack(project): + modpacks_to_remove.append(res) + + for slug, title, filename, version, _ in mods_to_remove: + local_path = os.path.join("mods", filename) + mcfs.remove(local_path) + db.remove_mod(slug) + print(f"Mod {title} v.{version} was removed.") + for _, title, filename, version, _ in resources_to_remove: + local_path = os.path.join("resourcepacks", filename) + mcfs.remove(local_path) + db.remove_resourcepack(slug) + print(f"Resource pack {title} v.{version} was removed.") + for _, title, filename, version, _ in shaders_to_remove: + local_path = os.path.join("shaderpacks", filename) + mcfs.remove(local_path) + db.remove_shader(slug) + print(f"Shader pack {title} v.{version} was removed.") + for _, title, filename, version, _ in modpacks_to_remove: + raise NotImplementedError + # local_path = os.path.join("modpacks", filename) + # mcfs.remove(local_path) + # db.remove_modpack(slug) + # print(f"Mod pack {title} v.{version} was removed.") + else: + raise NotImplementedError("Not available in module mode") + + if __name__ == "__main__": def exit(): @@ -273,6 +317,10 @@ if __name__ == "__main__": parser_validate = subparsers.add_parser("validate", help="Validate the installation") parser_clean = subparsers.add_parser("clean", help="Clean the cache of this program") + + parser_remove = subparsers.add_parser("remove", help="Remove installed packages") + parser_remove.add_argument("projects", nargs="+") + kwargs = vars(parser.parse_args()) # Получаем все поля получившегося Namespace и пихаем в словарь if not properties: exit() diff --git a/mcfs.py b/mcfs.py index 7eb3833..ca6858a 100644 --- a/mcfs.py +++ b/mcfs.py @@ -129,3 +129,11 @@ def check_file_hash(path, ref_hash): data = f.read(buffer_size) hash.update(data) return hash.hexdigest() == ref_hash + + +def remove(mc_dir_rel_path): + path = os.path.join(mc_dir, mc_dir_rel_path) + if is_path_exist(path): + os.remove(path) + else: + raise FileNotFoundError diff --git a/mcgetdb.py b/mcgetdb.py index 7e195dc..8b6caa2 100644 --- a/mcgetdb.py +++ b/mcgetdb.py @@ -63,6 +63,11 @@ class McGetDB: self.select_shader = self.__db_select_by_col("shaderpacks", "slug") self.select_modpack = self.__db_select_by_col("modpacks", "slug") + self.remove_mod = self.__db_remove_by_col("mods", "slug") + self.remove_resourcepack = self.__db_remove_by_col("resourcepacks", "slug") + self.remove_shader = self.__db_remove_by_col("shaderpacks", "slug") + self.remove_modpack = self.__db_remove_by_col("modpacks", "slug") + def get_properties(self): properties = None with self.db as db: @@ -100,8 +105,11 @@ class McGetDB: return res.fetchall() return selection_func - def remove_mod(self): - pass + def __db_remove_by_col(self, table, col): + def removal_func(col_value): + with self.db as db: + db.execute(f'DELETE FROM {table} WHERE {col} = "{col_value}"') + return removal_func def update_mod(self): pass