[Fix] Sometimes Modrinth uses a wrong file as primary

This commit is contained in:
Kir_Antipov 2022-01-05 17:55:13 +03:00
parent 6b37db6f29
commit b98fa4496b
3 changed files with 56 additions and 4 deletions

7
src/utils/hash-utils.ts Normal file
View file

@ -0,0 +1,7 @@
import crypto from "crypto";
import fs from "fs";
export function computeHash(path: string, algorithm: string): Promise<crypto.Hash> {
const hash = crypto.createHash(algorithm);
return new Promise(resolve => fs.createReadStream(path).on("data", data => hash.update(data)).on("end", () => resolve(hash)));
}

View file

@ -2,12 +2,13 @@ import { FormData } from "formdata-node";
import { fileFromPath } from "formdata-node/file-from-path"; import { fileFromPath } from "formdata-node/file-from-path";
import fetch from "node-fetch"; import fetch from "node-fetch";
import { File } from "./file"; import { File } from "./file";
import { computeHash } from "./hash-utils";
export async function createVersion(id: string, data: Record<string, any>, files: File[], token: string): Promise<string> { export async function createVersion(modId: string, data: Record<string, any>, files: File[], token: string): Promise<string> {
data = { data = {
dependencies: [], dependencies: [],
...data, ...data,
mod_id: id, mod_id: modId,
file_parts: files.map((_, i) => i.toString()) file_parts: files.map((_, i) => i.toString())
}; };
@ -32,5 +33,27 @@ export async function createVersion(id: string, data: Record<string, any>, files
throw new Error(`Failed to upload file: ${response.status} (${errorText})`); throw new Error(`Failed to upload file: ${response.status} (${errorText})`);
} }
return (<{ id: string }>await response.json()).id; const versionId = (<{ id: string }>await response.json()).id;
const primaryFile = files[0];
if (primaryFile) {
await makeFilePrimary(versionId, primaryFile.path, token);
}
return versionId;
}
export async function makeFilePrimary(versionId: string, filePath: string, token: string): Promise<boolean> {
const algorithm = "sha1";
const hash = (await computeHash(filePath, algorithm)).digest("hex");
const response = await fetch(`https://api.modrinth.com/api/v1/version/${versionId}`, {
method: "PATCH",
headers: {
"Authorization": token,
"Content-Type": "application/json"
},
body: JSON.stringify({
primary_file: [algorithm, hash]
})
});
return response.ok;
} }

22
test/hast-utils.test.ts Normal file
View file

@ -0,0 +1,22 @@
import { describe, test, expect } from "@jest/globals";
import { computeHash } from "../src/utils/hash-utils";
describe("computeHash", () => {
test("sha1 is supported", async () => {
const algorithm = "sha1";
expect((await computeHash("./test/content/fabric.mod.json", algorithm)).digest("hex")).toBe("be90f16aa5c806e2bbcf151efee4ebce7899256b");
expect((await computeHash("./test/content/mods.toml", algorithm)).digest("hex")).toBe("bf13f9ca36d5a5ebd55a3bda0b432ab4a007791a");
});
test("sha256 is supported", async () => {
const algorithm = "sha256";
expect((await computeHash("./test/content/fabric.mod.json", algorithm)).digest("hex")).toBe("583334cd90510cdc5c5068dd7cc3423adc9674abf8e200b3a165216bb0f6346d");
expect((await computeHash("./test/content/mods.toml", algorithm)).digest("hex")).toBe("c420fd754f32553dde2a5118c27ca83b644ba73d230baf723fa00d5cb5b1aaac");
});
test("sha512 is supported", async () => {
const algorithm = "sha512";
expect((await computeHash("./test/content/fabric.mod.json", algorithm)).digest("hex")).toBe("18582ba1fbec5ab05d5b5679f6d5fa157792959fd22ac091f1be264fc709996d900c8514265f0d24e533c1174da2919fdd7441d1215bbf6866e68f71114979af");
expect((await computeHash("./test/content/mods.toml", algorithm)).digest("hex")).toBe("b15c84290a1f9fad17fa4f3429fbb67d2555feafd617a5399ba95d5b6745659bc50e16e810d3bfe5bbdd4b66720b85daafd5ad78ece9a484c356c358d7b295ec");
});
});