mirror of
https://github.com/misenhower/splatoon3.ink.git
synced 2026-03-21 17:54:13 -05:00
Uses S3 ListObjectsV2 to build an in-memory file listing at startup, allowing exists() and olderThan() to resolve from the listing instead of requiring files on disk. sync:download now skips assets/splatnet/, data/xrank/, data/festivals.ranking.*, and status-screenshots/. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
81 lines
2.0 KiB
JavaScript
81 lines
2.0 KiB
JavaScript
import fs from 'fs/promises';
|
|
import path from 'path';
|
|
import PQueue from 'p-queue';
|
|
import prefixedConsole from '../common/prefixedConsole.mjs';
|
|
import { normalizeSplatnetResourcePath } from '../common/util.mjs';
|
|
import { exists, mkdirp } from '../common/fs.mjs';
|
|
import vfs from '../common/vfs.mjs';
|
|
|
|
const queue = new PQueue({ concurrency: 4 });
|
|
|
|
export default class ImageProcessor
|
|
{
|
|
destinationDirectory = 'dist';
|
|
outputDirectory = 'assets/splatnet';
|
|
|
|
constructor() {
|
|
this.console = prefixedConsole('Images');
|
|
this.siteUrl = process.env.SITE_URL;
|
|
}
|
|
|
|
async process(url, defer = true) {
|
|
// Normalize the path
|
|
let destination = this.normalize(url);
|
|
|
|
// Download the image if necessary
|
|
let job = () => this.maybeDownload(url, destination);
|
|
// defer ? queue.add(job) : await job();
|
|
if (defer) {
|
|
queue.add(job);
|
|
} else {
|
|
await job();
|
|
}
|
|
|
|
// Return the new public URL
|
|
return [destination, this.publicUrl(destination)];
|
|
}
|
|
|
|
static onIdle() {
|
|
return queue.onIdle();
|
|
}
|
|
|
|
normalize(url) {
|
|
return normalizeSplatnetResourcePath(url);
|
|
}
|
|
|
|
localPath(file) {
|
|
return `${this.destinationDirectory}/${this.outputDirectory}/${file}`;
|
|
}
|
|
|
|
publicUrl(file) {
|
|
return `${this.siteUrl ?? ''}/${this.outputDirectory}/${file}`;
|
|
}
|
|
|
|
async maybeDownload(url, destination) {
|
|
// If the file already exists, we don't need to download it again
|
|
if (await exists(this.localPath(destination))) {
|
|
return;
|
|
}
|
|
|
|
return await this.download(url, destination);
|
|
}
|
|
|
|
async download(url, destination) {
|
|
this.console.info(`Downloading image: ${destination}`);
|
|
|
|
try {
|
|
let result = await fetch(url);
|
|
|
|
if (!result.ok) {
|
|
throw new Error(`Invalid image response code: ${result.status}`);
|
|
}
|
|
|
|
await mkdirp(path.dirname(this.localPath(destination)));
|
|
await fs.writeFile(this.localPath(destination), result.body);
|
|
vfs.track(this.localPath(destination));
|
|
} catch (e) {
|
|
this.console.error(`Image download failed for ${destination}`, e);
|
|
}
|
|
}
|
|
}
|