From 1241795b7dfe733f1aa6d1fde71af89fd74f95a6 Mon Sep 17 00:00:00 2001 From: Kallum Jones Date: Wed, 3 Aug 2022 19:52:34 +0100 Subject: [PATCH] Add mod tracking --- src/mods/mod.ts | 10 ++++++++++ src/mods/mods.ts | 21 ++++++++++++++++--- src/mods/sources/mod_source.ts | 6 ++++-- src/mods/sources/modrinth_source.ts | 31 ++++++++++++++++++++++------- 4 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 src/mods/mod.ts diff --git a/src/mods/mod.ts b/src/mods/mod.ts new file mode 100644 index 0000000..b08c1e7 --- /dev/null +++ b/src/mods/mod.ts @@ -0,0 +1,10 @@ +declare global { + type Mod = { + id: string + name: string + fileName: string, + source: string, + } +} + +export {} \ No newline at end of file diff --git a/src/mods/mods.ts b/src/mods/mods.ts index 8a6871a..4122635 100644 --- a/src/mods/mods.ts +++ b/src/mods/mods.ts @@ -4,6 +4,7 @@ import PrintUtils from "../util/print_utils.js"; import ModrinthSource from "./sources/modrinth_source.js"; import ModSource from "./sources/mod_source.js"; import ModNotFoundError from "../errors/mod_not_found_error.js"; +import {readFileSync, writeFileSync} from "fs"; export default class Mods { @@ -28,9 +29,9 @@ export default class Mods { id = await source.search(mod); } catch (e) { if (e instanceof ModNotFoundError) { - spinner.updateText(`Mod not found on ${source.getName()}`) + spinner.updateText(`Mod not found on ${source.getSourceName()}`) } else { - spinner.error(`An error occurred searching for ${mod} on ${source.getName()}. Skipping ${source.getName()}`) + spinner.error(`An error occurred searching for ${mod} on ${source.getSourceName()}. Skipping ${source.getSourceName()}`) // Try the next source continue; } @@ -40,7 +41,9 @@ export default class Mods { if (id != undefined) { spinner.updateText(`Installing ${mod}...`) try { - await source.install(id); + const modObj: Mod = await source.install(id); + this.trackMod(modObj); + spinner.succeed(`Successfully installed ${mod}`); success = true; } catch (e) { @@ -55,4 +58,16 @@ export default class Mods { public static getModFilePath(): string { return path.join(Initialiser.getModManagerFolderPath(), this.MOD_FILE); } + + private static trackMod(mod: Mod): void { + // Parse current file + const file = readFileSync(this.getModFilePath(), "utf-8"); + const json: Array = JSON.parse(file); + + // Add mod + json.push(mod); + + // Write list back to file + writeFileSync(this.getModFilePath(), JSON.stringify(json, null, 4)); + } } \ No newline at end of file diff --git a/src/mods/sources/mod_source.ts b/src/mods/sources/mod_source.ts index 9238b27..6e95a61 100644 --- a/src/mods/sources/mod_source.ts +++ b/src/mods/sources/mod_source.ts @@ -1,7 +1,9 @@ export default interface ModSource { search(query: string): Promise; - install(id: string): Promise; + install(id: string): Promise; - getName(): string; + getSourceName(): string; + + getProjectName(id: string): Promise; } \ No newline at end of file diff --git a/src/mods/sources/modrinth_source.ts b/src/mods/sources/modrinth_source.ts index f1d1f9d..1d30b95 100644 --- a/src/mods/sources/modrinth_source.ts +++ b/src/mods/sources/modrinth_source.ts @@ -12,6 +12,7 @@ export default class ModrinthSource implements ModSource { private static readonly BASE_URL: string = "https://api.modrinth.com/v2"; private static readonly SEARCH_URL: string = ModrinthSource.BASE_URL + "/search"; private static readonly INSTALL_URL: string = ModrinthSource.BASE_URL + "/project/%s/version"; + private static readonly PROJECT_URL: string = ModrinthSource.BASE_URL + "/project/%s"; /** * Searches Modrinth for the specified query @@ -79,7 +80,7 @@ export default class ModrinthSource implements ModSource { const results = await response.data.hits; if (Util.isArrayEmpty(results)) { - throw new ModNotFoundError(`Mod ${query} could not be found on ${this.getName()}`); + throw new ModNotFoundError(`Mod ${query} could not be found on ${this.getSourceName()}`); } return results[0].project_id; @@ -126,7 +127,7 @@ export default class ModrinthSource implements ModSource { * @throws DownloadError if an error occurs when downloading * @throws ModNotFoundError if there are no versions available for the current Minecraft Version */ - async install(id: string): Promise { + async install(id: string): Promise { const mcVersion = await MinecraftUtils.getCurrentMinecraftVersion(); const params = { @@ -138,26 +139,42 @@ export default class ModrinthSource implements ModSource { const results = await response.data; if (Util.isArrayEmpty(results)) { - throw new ModNotFoundError(`Mod with id ${id} has no available versions on ${this.getName()} for Minecraft version ${mcVersion}`); + throw new ModNotFoundError(`Mod with id ${id} has no available versions on ${this.getSourceName()} for Minecraft version ${mcVersion}`); } const latestFile = results[0].files[0]; + const fileName = latestFile.filename; + const url = latestFile.url; + const task: DownloadTask = { - fileName: latestFile.filename, - url: latestFile.url + fileName: fileName, + url: url } try { FileDownloader.downloadMod(task) + + return { + name: await this.getProjectName(id), + id: id, + fileName: fileName, + source: this.getSourceName() + }; + } catch (e) { - throw new DownloadError(`An error occurred downloading mod with id ${id} from ${this.getName()}`) + throw new DownloadError(`An error occurred downloading mod with id ${id} from ${this.getSourceName()}`) } } - getName(): string { + getSourceName(): string { return "Modrinth"; } + async getProjectName(id: string): Promise { + const response = await axios.get(format(ModrinthSource.PROJECT_URL, id)); + return await response.data.title; + } + } \ No newline at end of file