added initial files
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
import path from 'path';
|
||||
import { promises as fs } from 'fs';
|
||||
import fse from 'fs-extra';
|
||||
import pMap from 'p-map';
|
||||
import { getDirectories, normalizeModData, isMod } from '.';
|
||||
import { getFileMurmurHash2 } from '../../../common/utils';
|
||||
import { getAddonsByFingerprint, getAddon } from '../../../common/api';
|
||||
|
||||
const modsFingerprintsScan = async instancesPath => {
|
||||
const mapFolderToInstance = async instance => {
|
||||
try {
|
||||
const configPath = path.join(
|
||||
path.join(instancesPath, instance, 'config.json')
|
||||
);
|
||||
const config = await fse.readJSON(configPath);
|
||||
|
||||
if (!config.loader) {
|
||||
throw new Error(`Config for ${instance} could not be parsed`);
|
||||
}
|
||||
|
||||
const modsFolder = path.join(instancesPath, instance, 'mods');
|
||||
const modsFolderExists = await fse.pathExists(modsFolder);
|
||||
|
||||
if (!modsFolderExists) return { ...config, name: instance };
|
||||
|
||||
// Check if config.mods has a different number of mods than the actual number of mods
|
||||
|
||||
// Count the actual mods inside the folder
|
||||
const files = await fs.readdir(modsFolder);
|
||||
|
||||
const fileNamesToRemove = [];
|
||||
const missingMods = {};
|
||||
/* eslint-disable */
|
||||
// Check for new mods in local storage that are not present in config
|
||||
for (const file of files) {
|
||||
try {
|
||||
const completeFilePath = path.join(modsFolder, file);
|
||||
const stat = await fs.lstat(completeFilePath);
|
||||
if (stat.isFile() && isMod(completeFilePath, instancesPath)) {
|
||||
// Check if file is in config
|
||||
if (!(config?.mods || []).find(mod => mod.fileName === file)) {
|
||||
const murmurHash = await getFileMurmurHash2(completeFilePath);
|
||||
console.log(
|
||||
'[MODS SCANNER] Local mod not found in config',
|
||||
file,
|
||||
murmurHash
|
||||
);
|
||||
missingMods[file] = murmurHash;
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
// Check for old mods in config that are not present on local storage
|
||||
for (const configMod of config?.mods || []) {
|
||||
if (!files.includes(configMod.fileName)) {
|
||||
fileNamesToRemove.push(configMod.fileName);
|
||||
console.log(
|
||||
`[MODS SCANNER] Removing ${configMod.fileName} from config`
|
||||
);
|
||||
}
|
||||
}
|
||||
/* eslint-enable */
|
||||
|
||||
let newMods = config?.mods || [];
|
||||
|
||||
if (Object.values(missingMods).length !== 0) {
|
||||
let success = false;
|
||||
let tries = 10;
|
||||
|
||||
while (!success || tries > 10) {
|
||||
try {
|
||||
const data = await getAddonsByFingerprint(
|
||||
Object.values(missingMods)
|
||||
);
|
||||
|
||||
const matches = await Promise.all(
|
||||
Object.entries(missingMods).map(async ([fileName, hash]) => {
|
||||
const exactMatch = (data.exactMatches || []).find(
|
||||
v => v.file.fileFingerprint === hash
|
||||
);
|
||||
if (exactMatch?.file) {
|
||||
let addonData = null;
|
||||
try {
|
||||
addonData = await getAddon(exactMatch.file.modId);
|
||||
return {
|
||||
...normalizeModData(
|
||||
exactMatch.file,
|
||||
exactMatch.file.modId,
|
||||
addonData.name
|
||||
),
|
||||
fileName
|
||||
};
|
||||
} catch {
|
||||
return {
|
||||
fileName,
|
||||
displayName: fileName,
|
||||
packageFingerprint: hash
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
fileName,
|
||||
displayName: fileName,
|
||||
packageFingerprint: hash
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
newMods = [...newMods, ...matches];
|
||||
success = true;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
tries += 1;
|
||||
await new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 5000);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const filterMods = newMods
|
||||
.filter(_ => _)
|
||||
.filter(v => !fileNamesToRemove.includes(v.fileName));
|
||||
|
||||
const newConfig = {
|
||||
...config,
|
||||
mods: filterMods
|
||||
};
|
||||
|
||||
if (JSON.stringify(config) !== JSON.stringify(newConfig)) {
|
||||
await fse.outputJson(configPath, newConfig);
|
||||
return { ...newConfig, name: instance };
|
||||
}
|
||||
return { ...config, name: instance };
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const folders = await getDirectories(instancesPath);
|
||||
const instances = await pMap(
|
||||
folders.filter(folder => folder !== '.DS_Store'),
|
||||
mapFolderToInstance,
|
||||
{
|
||||
concurrency: 5
|
||||
}
|
||||
);
|
||||
const hashMap = {};
|
||||
// eslint-disable-next-line
|
||||
for (const instance of instances) {
|
||||
// eslint-disable-next-line
|
||||
if (!instance) continue;
|
||||
hashMap[instance.name] = instance;
|
||||
}
|
||||
|
||||
return hashMap;
|
||||
};
|
||||
|
||||
export default modsFingerprintsScan;
|
||||
Reference in New Issue
Block a user