UNPKG

dmclc

Version:

Dolphin Minecraft Launcher Core

207 lines (206 loc) 6.58 kB
import fsPromises from 'fs/promises'; import got from "got"; import { murmur2 } from 'murmurhash2'; import { ContentType } from "../ContentService.js"; import { Algorithm, RelationType } from "./CurseForgeModels.js"; const loaderToCurseForge = { forge: 1, fabric: 2, quilt: 3 }; const contentTypeToCurseForge = { [ContentType.MODPACK]: 4471, [ContentType.SHADER]: 4546, [ContentType.MOD]: 6, [ContentType.RESOURCE_PACK]: 12, [ContentType.WORLD]: 17, }; const curseForgeToContentType = { [4471]: ContentType.MODPACK, [4546]: ContentType.SHADER, [6]: ContentType.MOD, [12]: ContentType.RESOURCE_PACK, [17]: ContentType.WORLD, }; export const CurseForgeSortField = { FEATURED: 1, POPULARITY: 2, LAST_UPDATED: 3, NAME: 4, AUTHOR: 5, TOTAL_DOWNLOADS: 6, CATEGORY: 7, GAME_VERSION: 8 }; const white = [0x9, 0xa, 0xd, 0x20]; export class CurseForgeContentVersion { model; got; isVersion = true; content; constructor(model, got) { this.model = model; this.got = got; // } async getContent() { if (!this.content) { const response = await this.got("mods/" + this.model.modId).json(); return this.content = new CurseForgeContent(response.data, this.got); } return this.content; } async getVersionFileName() { return this.model.fileName; } async getVersionNumber() { return this.model.displayName; } async getVersionChangelog() { const res = await this.got(`mods/${this.model.modId}/files/${this.model.id}/changelog`).json(); return res.data; } async getVersionFileSHA1() { return this.model.hashes[0].algo === Algorithm.SHA1 ? this.model.hashes[0].value : this.model.hashes[1].value; } async listDependencies() { const result = []; for (const i of this.model.dependencies) { if (i.relationType === RelationType.RequiredDependency) { const response = await this.got("mods/" + i.modId).json(); result.push(new CurseForgeContent(response.data, this.got)); } } return result; } async getVersionFileURL() { return this.model.downloadUrl; } } export class CurseForgeContent { model; got; isVersion = false; constructor(model, got) { this.model = model; this.got = got; // } getType() { return curseForgeToContentType[this.model.classId]; } async isLibrary() { return this.model.categories.findIndex(v => v.slug === "library-api") != -1; } async getBody() { const res = await this.got(`mods/${this.model.id}/description`).json(); return res.data; } async getTitle() { return this.model.name; } async getDescription() { return this.model.summary; } async getIconURL() { return this.model.logo.url; } async getURLs() { return new Map([ ["issues", this.model.links.issuesUrl], ["source", this.model.links.sourceUrl], ["website", this.model.links.websiteUrl], ["wiki", this.model.links.wikiUrl] ]); } async getScreenshots() { return this.model.screenshots; } async getOtherInformation() { const res = new Map(); if (this.model.downloadCount) { res.set("downloads", this.model.downloadCount.toString()); } if (this.model.authors) { res.set("authors", this.model.authors.join(", ")); } if (this.model.dateCreated) { res.set("published", this.model.dateCreated); } if (this.model.dateModified) { res.set("modified", this.model.dateModified); } if (this.model.dateReleased) { res.set("updated", this.model.dateReleased); } return res; } async listVersions(forVersion) { const searchParams = {}; if (forVersion) { searchParams.gameVersion = forVersion.extras.version; searchParams.modLoaderType = loaderToCurseForge[forVersion.extras.loaders[0].name]; } const files = await this.got(`mods/${this.model.id}/files`, { searchParams }).json(); return files.data.filter(v => v.isAvailable).map(v => new CurseForgeContentVersion(v, this.got)); } } export default class CurseForgeContentService { launcher; got; constructor(launcher) { this.launcher = launcher; this.got = got.extend({ prefixUrl: "https://api.curseforge.com/v1/", headers: { "x-api-key": "$2a$10$VhDVvjRWDxOlbRnuqi1GEOCxcZ.fZGRLf2kg7pdN8i4dowykR4huy" } }); } async getVersionFromFile(path) { const out = Buffer.of(); const content = await fsPromises.readFile(path); content.filter(i => !white.includes(i)).forEach(content.writeUInt8); const response = await this.got.post("v1/fingerprints", { json: { fingerprints: [murmur2(out.toString(), 1)] } }).json(); if (response.data.exactMatches.length === 0) return null; return new CurseForgeContentVersion(response.data.exactMatches[0].file, this.got); } getDefaultSortField() { return CurseForgeSortField.FEATURED; } getUnsupportedContentTypes() { return [ContentType.DATA_PACK]; } getSortFields() { return CurseForgeSortField; } async searchContent(name, skip, limit, type, sortField, forVersion) { if (type === ContentType.DATA_PACK) return []; const searchParams = { gameId: 432, classId: contentTypeToCurseForge[type], searchFilter: name, index: skip, pageSize: limit, sortField: sortField }; if (forVersion) { searchParams.gameVersion = forVersion.extras.version; searchParams.modLoaderType = loaderToCurseForge[forVersion.extras.loaders[0].name]; } const response = await this.got("mods/search", { searchParams }).json(); return response.data.map(v => new CurseForgeContent(v, this.got)); } async getContentVersion(projectID, fileID) { const response = await this.got(`mods/${projectID}/files/${fileID}`).json(); return new CurseForgeContentVersion(response.data, this.got); } }