mirror of
https://github.com/noothenoot/crafty-mod-installer.git
synced 2026-07-21 21:37:00 +00:00
Initial commit: Crafty Mod Installer
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
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) {
|
||||
// identifier can be numeric ID or slug (though the library might need specific search for slug)
|
||||
if (isNaN(id)) {
|
||||
const results = await this.client.searchMods({ slug: id });
|
||||
if (results.data.length === 0) throw new Error('Mod not found');
|
||||
return results.data[0];
|
||||
}
|
||||
return await this.client.getMod(id);
|
||||
}
|
||||
|
||||
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;
|
||||
Reference in New Issue
Block a user