dmclc
Version:
Dolphin Minecraft Launcher Core
207 lines (206 loc) • 6.58 kB
JavaScript
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);
}
}