Add mod tracking

This commit is contained in:
Kallum Jones 2022-08-03 19:52:34 +01:00
parent dbe0ae9a48
commit 1241795b7d
No known key found for this signature in database
GPG Key ID: D7F4589C4D7F81A9
4 changed files with 56 additions and 12 deletions

10
src/mods/mod.ts Normal file
View File

@ -0,0 +1,10 @@
declare global {
type Mod = {
id: string
name: string
fileName: string,
source: string,
}
}
export {}

View File

@ -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<Mod> = JSON.parse(file);
// Add mod
json.push(mod);
// Write list back to file
writeFileSync(this.getModFilePath(), JSON.stringify(json, null, 4));
}
}

View File

@ -1,7 +1,9 @@
export default interface ModSource {
search(query: string): Promise<string>;
install(id: string): Promise<void>;
install(id: string): Promise<Mod>;
getName(): string;
getSourceName(): string;
getProjectName(id: string): Promise<string>;
}

View File

@ -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<void> {
async install(id: string): Promise<Mod> {
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<string> {
const response = await axios.get(format(ModrinthSource.PROJECT_URL, id));
return await response.data.title;
}
}