Files
crafty-mod-installer/curseforge.js
T

88 lines
3.1 KiB
JavaScript

const { CurseForgeClient } = require('curseforge-api');
const axios = require('axios');
const fs = require('fs-extra');
const path = require('path');
const AdmZip = require('adm-zip');
class CurseForgeHandler {
constructor(apiKey) {
this.apiKey = apiKey;
this.client = new CurseForgeClient(apiKey);
}
async getMod(id) {
// Extract ID/slug from URL if needed
let identifier = id;
if (id.includes('curseforge.com')) {
const parts = id.split('/');
identifier = parts[parts.length - 1] || parts[parts.length - 2];
}
if (isNaN(identifier)) {
// 432 is the ID for Minecraft
const results = await this.client.searchMods(432, { slug: identifier });
if (results.data.length === 0) throw new Error('Mod not found');
return results.data[0];
}
return await this.client.getMod(identifier);
}
async getFiles(id) {
const results = await this.client.getModFiles(id);
return results.data;
}
async downloadFile(url, targetPath) {
const response = await axios({
url,
method: 'GET',
responseType: 'stream',
headers: { 'x-api-key': this.apiKey }
});
const writer = fs.createWriteStream(targetPath);
response.data.pipe(writer);
return new Promise((resolve, reject) => {
writer.on('finish', resolve);
writer.on('error', reject);
});
}
async installModpack(modId, fileId, targetDir) {
console.log(`Downloading CurseForge pack (Mod: ${modId}, File: ${fileId})...`);
const file = await this.client.getModFile(modId, fileId);
if (!file.downloadUrl) throw new Error('Download URL not found for this file.');
const tempPath = path.join(process.cwd(), 'temp_pack.zip');
await this.downloadFile(file.downloadUrl, tempPath);
const zip = new AdmZip(tempPath);
const manifestEntry = zip.getEntry('manifest.json');
if (!manifestEntry) throw new Error('Invalid CurseForge pack: missing manifest.json');
const manifest = JSON.parse(zip.readAsText(manifestEntry));
const modsDir = path.join(targetDir, 'mods');
await fs.ensureDir(modsDir);
console.log(`Downloading ${manifest.files.length} mods from CurseForge...`);
for (const fileInfo of manifest.files) {
const modFile = await this.client.getModFile(fileInfo.projectID, fileInfo.fileID);
const destPath = path.join(modsDir, modFile.fileName);
console.log(` Downloading ${modFile.fileName}...`);
await this.downloadFile(modFile.downloadUrl, destPath);
}
// Handle overrides
const overridesEntry = zip.getEntry('overrides/');
if (overridesEntry) {
console.log('Applying overrides...');
zip.extractAllTo(targetDir, true);
}
await fs.remove(tempPath);
console.log('CurseForge installation complete!');
}
}
module.exports = CurseForgeHandler;