ourfor / blog

利用GitHub的Issues记录
https://github.com/ourfor/blog/issues
1 stars 0 forks source link

Switch游戏整理 #72

Open ourfor opened 2 years ago

ourfor commented 2 years ago
import { green, white, yellow, bold, italic } from "https://deno.land/std/fmt/colors.ts"
const { readFileSync, writeFile, readDirSync, renameSync, args } = Deno
const encoder = new TextEncoder()
const decoder = new TextDecoder("utf-8")
const log = console

type GameModel = {
    id: string,
    name: string,
    iconUrl: string,
    bannerUrl: string
}

type GameFileModel = {
    name: string,
    id: string,
    content: string,
    ext: string,
    icon?: string,
    banner?: string
}

function database(): Map<string, GameModel> {
    const map = new Map<string, GameModel>()
    const data = readFileSync('titledb/HK.zh.json')
    const json = decoder.decode(data)
    const titleMap = JSON.parse(json)
    const models = Object.values(titleMap) as GameModel[]
    for (const model of models) {
        map.set(model.id, model)
    }
    return map
}

function organize(paths: string[], map: Map<string, GameModel>): Map<string, GameFileModel> {
    const idReg = /.*(0100[0-9A-Za-z]{10,20}).*/
    const extReg = /.*\.(xci|nsp)$/
    const contentReg = /.*([0-9]{1,3}G[+]?[0-9]{0,3}U?[+]?[0-9]{0,3}D?).*/
    const games = paths.map<GameFileModel>(path => {
        const id = path.replace(idReg, "$1").toUpperCase()
        const ext = path.replace(extReg, "$1")
        const model = map.get(id)
        const name = model ? model.name : "Unknow"
        let content = path.replace(contentReg, "$1") ?? ""
        if (!contentReg.test(path)) {
            content = ""
        }
        return { id, ext, name, content, icon: model?.iconUrl, banner: model?.bannerUrl }
    })
    const gameMap = new Map<string, GameFileModel>()
    for (let i = 0; i < paths.length; i++) {
        gameMap.set(paths[i], games[i]);
    }
    return gameMap
}

async function format(map: Map<string, GameFileModel>, path: string) {
    map.forEach(async (game, name) => {
        const originPath = `${path}/${name}`
        const newName = `[${game.id}][${game.name}]${game.content != "" ? `[${game.content}]` : ""}.${game.ext}`
        const modifyPath = `${path}/library/${newName}`
        log.info(`${yellow(bold("MOVE"))} ${originPath} ${green(italic("->"))} ${modifyPath}`);
        const imagePath = modifyPath.substring(0, modifyPath.length - 4)
        if (game.icon) {
            await download(game.icon, `${imagePath}-icon.jpg`)
        }
        if (game.banner) {
            await download(game.banner, `${imagePath}-banner.jpg`)
        }
        renameSync(originPath, modifyPath)
    })
}

function scan(path: string): string[] {
    const files = []
    const items = readDirSync(path)
    const extReg = /(xci|nsp)$/
    for (const item of items) {
        if (item.isFile && extReg.test(item.name)) {
            files.push(item.name)
        }
    }
    return files
}

async function download(url: string, path: string) {
    log.info(`${white(bold("DOWNLOAD"))} ${path}`)
    const resp = await fetch(url)
    const blob = await resp.blob()
    const data = new Uint8Array(await blob.arrayBuffer())
    await writeFile(path, data)
    log.info(`${white(bold("WRITE"))} ${path}`)
}

async function main(...paths: string[]) {
    const map = database()
    for (const path of paths) {
        log.info(`${white(bold("SCAN"))} ${green(path)}`)
        const files = scan(path)
        const gameMap = organize(files, map)
        await format(gameMap, path)
    }
}

await main(...args)

titledb来自nut