147 lines
3.6 KiB
TypeScript
147 lines
3.6 KiB
TypeScript
import { createWriteStream, mkdirSync, rmSync } from 'fs';
|
|
import { Readable } from 'stream';
|
|
|
|
interface Hashes {
|
|
sha1: string
|
|
sha512: string
|
|
}
|
|
interface File {
|
|
hashes: Hashes
|
|
url: string
|
|
filename: string
|
|
primary: boolean
|
|
size: number
|
|
file_type: string
|
|
}
|
|
interface Dependency {
|
|
version_id: string
|
|
project_id: string
|
|
file_name: string
|
|
dependency_type: string
|
|
}
|
|
interface ModVersion {
|
|
game_versions: string[]
|
|
loaders: string[]
|
|
id: string
|
|
project_id: string
|
|
author_id: string
|
|
featured: boolean
|
|
name: string
|
|
version_number: string
|
|
changelog: string
|
|
changelog_url: string
|
|
date_published: string
|
|
downloads: number
|
|
version_type: string
|
|
status: string
|
|
files: File[]
|
|
dependencies: Dependency[]
|
|
}
|
|
|
|
const LOADER = 'fabric';
|
|
|
|
const game_version = process.argv[2] ?? '';
|
|
const action = process.argv[3] ?? 'check';
|
|
|
|
const getVersions = async(slug: string): Promise<ModVersion[]> => {
|
|
const res = await fetch(`https://api.modrinth.com/v2/project/${slug}/version`);
|
|
|
|
return res.ok ?
|
|
await res.json() as ModVersion[] :
|
|
[];
|
|
};
|
|
|
|
const checkModCompat = async(slug: string): Promise<ModVersion | null> => {
|
|
const versions = await getVersions(slug);
|
|
|
|
const matching = versions.filter((ver) =>
|
|
ver.game_versions.includes(game_version) &&
|
|
ver.loaders.includes(LOADER));
|
|
|
|
if (matching.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
const timeSorted = matching.sort((a, b) => {
|
|
const dateA = new Date(a.date_published);
|
|
const dateB = new Date(b.date_published);
|
|
|
|
return dateB.getTime() - dateA.getTime();
|
|
});
|
|
|
|
return timeSorted.some((v) => v.version_type === 'release') ?
|
|
timeSorted.filter((v) => v.version_type === 'release')[0] :
|
|
timeSorted[0];
|
|
};
|
|
|
|
const getDownloadUrls = (version: ModVersion): string[] => version.files.map((file) => file.url);
|
|
|
|
const showModDownloadUrls = async(modName: string): Promise<boolean> => {
|
|
const ver = await checkModCompat(modName);
|
|
|
|
if (ver) {
|
|
const urls = getDownloadUrls(ver);
|
|
|
|
console.log(`\n${modName}:`, urls);
|
|
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
const download = async(url: string, path: string) => Readable
|
|
.fromWeb((await fetch(url)).body!).pipe(createWriteStream(path));
|
|
|
|
const main = () => {
|
|
const mods = [
|
|
'badpackets',
|
|
'c2me-fabric',
|
|
'cloth-config',
|
|
'clumps',
|
|
'fabric-api',
|
|
'ferrite-core',
|
|
'leaves-be-gone',
|
|
'lithium',
|
|
'modernfix',
|
|
'no-chat-reports',
|
|
'noisium',
|
|
'vmp-fabric',
|
|
'wthit',
|
|
];
|
|
|
|
if (action === 'check') {
|
|
mods.forEach(async(modName) => {
|
|
if (!(await showModDownloadUrls(modName))) {
|
|
console.error(`No matching releases of ${modName} were found for ${game_version}`);
|
|
}
|
|
});
|
|
}
|
|
else if (action === 'download') {
|
|
rmSync('./out', { force: true, recursive: true });
|
|
mkdirSync('./out');
|
|
|
|
mods.forEach(async(modName) => {
|
|
const ver = await checkModCompat(modName);
|
|
|
|
if (ver === null) {
|
|
console.error(`No matching releases of ${modName} were found for ${game_version}`);
|
|
|
|
return;
|
|
}
|
|
|
|
const fileName =
|
|
`${modName}-${ver.version_number}.jar`;
|
|
|
|
console.log(`Downloading ${fileName}`);
|
|
|
|
await download(
|
|
ver.files[0].url,
|
|
`./out/${fileName}`,
|
|
);
|
|
});
|
|
}
|
|
};
|
|
|
|
main();
|