Skip to content

Commit

Permalink
Download images from SplatNet
Browse files Browse the repository at this point in the history
  • Loading branch information
misenhower committed Sep 10, 2022
1 parent 2e62e4a commit 67387f9
Show file tree
Hide file tree
Showing 6 changed files with 340 additions and 14 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Site Config
SITE_URL=https://splatoon3.ink

# Nintendo API
NINTENDO_TOKEN=

Expand Down
84 changes: 84 additions & 0 deletions app/data/ImageProcessor.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import fs from 'fs/promises';
import path from 'path';
import mkdirp from 'mkdirp';
import prefixedConsole from "../common/prefixedConsole.mjs";

export default class ImageProcessor
{
destinationDirectory = 'dist';
outputDirectory = 'assets/splatnet';

constructor() {
this.console = prefixedConsole('Images');
this.siteUrl = process.env.SITE_URL;
}

async process(url) {
// Normalize the path
let destination = this.normalize(url);

// Download the image if necessary
await this.maybeDownload(url, destination);

// Return the new public URL
return this.publicUrl(destination);
}

normalize(url) {
// Parse the URL
let u = new URL(url);

// Get just the pathname (without the host, query string, etc.)
let result = u.pathname;

// Remove "/resources/prod" from the beginning if it exists
result = result.replace(/^\/resources\/prod/, '');

// Remove the leading slash
result = result.replace(/^\//, '');

return result;
}

localPath(file) {
return `${this.destinationDirectory}/${this.outputDirectory}/${file}`;
}

publicUrl(file) {
return `${this.siteUrl}/${this.outputDirectory}/${file}`;
}

async exists(file) {
try {
await fs.access(this.localPath(file));

return true;
} catch (e) {
//
}

return false;
}

async maybeDownload(url, destination) {
// If the file already exists, we don't need to download it again
if (await this.exists(destination)) {
return
}

return await this.download(url, destination);
}

async download(url, destination) {
this.console.info(`Downloading image: ${destination}`);

try {
let result = await fetch(url);

await mkdirp(path.dirname(this.localPath(destination)));
await fs.writeFile(this.localPath(destination), result.body);
} catch (e) {
this.console.error(`Image download failed for ${destination}`, e);
}
}
}
29 changes: 29 additions & 0 deletions app/data/updaters/DataUpdater.mjs
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import fs from 'fs/promises';
import path from 'path';
import mkdirp from 'mkdirp';
import jsonpath from 'jsonpath';
import prefixedConsole from "../../common/prefixedConsole.mjs";
import SplatNet3Client from "../../splatnet/SplatNet3Client.mjs";
import ImageProcessor from '../ImageProcessor.mjs';

export default class DataUpdater
{
name = null;
filename = null;
outputDirectory = 'dist/data';

imagePaths = [];

constructor() {
this.splatnet = new SplatNet3Client;
this.imageProcessor = new ImageProcessor;
}

/** @type {Console} */
Expand All @@ -31,12 +36,17 @@ export default class DataUpdater
// Retrieve the data
let data = await this.tryRequest(this.getData());

// Download any new images
await this.downloadImages(data);

// Write the data to disk
await this.writeData(this.path, data);

this.console.info('Done');
}

// Requests

getData() {
//
}
Expand All @@ -51,6 +61,25 @@ export default class DataUpdater
}
}

// Processing

async downloadImages(data) {
for (let expression of this.imagePaths) {
// This JSONPath library is completely synchronous, so we have to
// build a mapping here after transforming all URLs.
let mapping = {};
for (let url of jsonpath.query(data, expression)) {
let publicUrl = await this.imageProcessor.process(url);
mapping[url] = publicUrl;
}

// Now apply the URL transformations
jsonpath.apply(data, expression, url => mapping[url]);
}
}

// File handling

formatDataForWrite(data) {
// If we're running in debug mode, format the JSON output so it's easier to read
let debug = !!process.env.DEBUG;
Expand Down
6 changes: 6 additions & 0 deletions app/data/updaters/StageScheduleUpdater.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ export default class StageScheduleUpdater extends DataUpdater
name = 'Schedules';
filename = 'schedules.json';

imagePaths = [
'$..image.url',
'$..originalImage.url',
'$..thumbnailImage.url',
];

getData() {
return this.splatnet.getStageScheduleData();
}
Expand Down
Loading

0 comments on commit 67387f9

Please sign in to comment.