First build

This commit is contained in:
olcxja 2026-09-25 17:09:38 +02:00
commit fd773f5832
954 changed files with 305115 additions and 2 deletions

99
src/importer.js Normal file
View file

@ -0,0 +1,99 @@
'use strict'
const fsp = require('fs').promises
const path = require('path')
const fs = require('fs')
const { DIRS } = require('./paths')
const { newGame } = require('./library')
function walk(dir, base) {
return fsp.readdir(dir, { withFileTypes: true }).then(async entries => {
let total = 0
for (const e of entries) {
const full = path.join(dir, e.name)
if (e.isDirectory()) total += await walk(full, base)
else if (e.isFile()) {
const st = await fsp.stat(full)
total += st.size
}
}
return total
}).catch(() => 0)
}
function copyRecursive(src, dst, onProgress) {
return fsp.readdir(src, { withFileTypes: true }).then(async entries => {
await fsp.mkdir(dst, { recursive: true })
for (const e of entries) {
const s = path.join(src, e.name)
const d = path.join(dst, e.name)
if (e.isDirectory()) {
await copyRecursive(s, d, onProgress)
} else if (e.isFile()) {
await fsp.copyFile(s, d)
if (onProgress) onProgress(s)
}
}
})
}
function moveFolder(src, dst, onProgress) {
if (path.parse(src).root !== path.parse(dst).root) {
return copyRecursive(src, dst, onProgress).then(() => fsp.rm(src, { recursive: true, force: true }))
}
return fsp.rename(src, dst).catch(() => copyRecursive(src, dst, onProgress).then(() => fsp.rm(src, { recursive: true, force: true })))
}
function dedupeName(base, name) {
let candidate = path.join(base, name)
let n = 2
while (fs.existsSync(candidate)) {
candidate = path.join(base, `${name} (${n})`)
n++
}
return candidate
}
async function importGame(srcDir, mode, onProgress) {
const name = path.basename(srcDir)
let workdir = srcDir
if (mode === 'copy') {
const dst = dedupeName(DIRS.GAMES, name)
await copyRecursive(srcDir, dst, onProgress)
workdir = dst
} else if (mode === 'move') {
const dst = dedupeName(DIRS.GAMES, name)
await moveFolder(srcDir, dst, onProgress)
workdir = dst
}
const exePath = await findDefaultExe(workdir)
const game = newGame({ name, exePath, workdir, mode })
return game
}
async function findDefaultExe(dir) {
let best = ''
const walk = async d => {
let entries = []
try {
entries = await fsp.readdir(d, { withFileTypes: true })
} catch {
return
}
for (const e of entries) {
const full = path.join(d, e.name)
if (e.isDirectory()) {
const lower = e.name.toLowerCase()
if (lower === 'redist' || lower === 'directx' || lower === '_commonredist' || lower === 'support' || lower === 'dotnet' || lower === 'vc') continue
await walk(full)
} else if (e.name.toLowerCase().endsWith('.exe')) {
const st = await fsp.stat(full)
if (!best || st.size > (await fsp.stat(best)).size) best = full
}
}
}
await walk(dir)
return best
}
module.exports = { importGame, findDefaultExe, copyRecursive, moveFolder, walk }