s3si.ts/src/exporters/file.ts

182 lines
4.4 KiB
TypeScript
Raw Normal View History

2022-11-26 09:45:44 -05:00
import {
CoopInfo,
ExportResult,
Game,
GameExporter,
Summary,
2022-11-26 09:45:44 -05:00
VsInfo,
} from "../types.ts";
2022-10-22 06:40:20 -04:00
import { path } from "../../deps.ts";
2022-10-20 09:45:59 -04:00
import { NSOAPP_VERSION, S3SI_VERSION } from "../constant.ts";
import { parseHistoryDetailId, urlSimplify } from "../utils.ts";
2022-10-20 09:45:59 -04:00
export type FileExporterTypeCommon = {
2022-10-20 09:45:59 -04:00
nsoVersion: string;
s3siVersion: string;
exportTime: string;
};
export type FileExporterType =
& ({
type: "VS";
data: VsInfo;
} | {
type: "COOP";
data: CoopInfo;
} | {
type: "SUMMARY";
data: Summary;
})
& FileExporterTypeCommon;
2022-10-21 03:56:43 -04:00
/**
* Don't save url in exported file
*/
function replacer(key: string, value: unknown): unknown {
if (!["url", "maskImageUrl", "overlayImageUrl"].includes(key)) {
return value;
}
return typeof value === "string" ? urlSimplify(value) : undefined;
2022-10-21 03:56:43 -04:00
}
2022-10-20 09:45:59 -04:00
/**
* Exporter to file.
*
* This is useful for debugging. It will write each battle detail to a file.
2022-10-20 23:14:29 -04:00
* Timestamp is used as filename. Example: 20210101T000000Z.json
2022-10-20 09:45:59 -04:00
*/
2022-10-24 14:45:36 -04:00
export class FileExporter implements GameExporter {
2022-10-20 09:45:59 -04:00
name = "file";
constructor(private exportPath: string) {
}
2022-10-20 23:14:29 -04:00
getFilenameById(id: string) {
2022-10-24 14:45:36 -04:00
const { uid, timestamp } = parseHistoryDetailId(id);
2022-10-21 03:56:43 -04:00
2022-10-22 06:40:20 -04:00
return `${uid}_${timestamp}Z.json`;
2022-10-20 23:14:29 -04:00
}
/**
* Get all exported files
*/
async exportedGames(
{ uid, type }: { uid: string; type: Game["type"] },
): Promise<{ id: string; getContent: () => Promise<Game> }[]> {
const out: { id: string; filepath: string; timestamp: string }[] = [];
for await (const entry of Deno.readDir(this.exportPath)) {
const filename = entry.name;
const [fileUid, timestamp] = filename.split("_", 2);
if (!entry.isFile || fileUid !== uid) {
continue;
}
const filepath = path.join(this.exportPath, filename);
const content = await Deno.readTextFile(filepath);
const body = JSON.parse(content) as FileExporterType;
if (body.type === "SUMMARY") {
continue;
}
if (body.type === "VS" && type === "VsInfo") {
out.push({
id: body.data.detail.id,
filepath,
timestamp,
});
} else if (body.type === "COOP" && type === "CoopInfo") {
out.push({
id: body.data.detail.id,
filepath,
timestamp,
});
}
}
return out.sort((a, b) => b.timestamp.localeCompare(a.timestamp)).map((
{ id, filepath },
) => ({
id,
getContent: async () => {
const content = await Deno.readTextFile(filepath);
const body = JSON.parse(content) as FileExporterType;
// summary is excluded
return body.data as Game;
},
}));
}
async exportSummary(summary: Summary): Promise<ExportResult> {
const filename = `${summary.uid}_summary.json`;
const filepath = path.join(this.exportPath, filename);
const body: FileExporterType = {
type: "SUMMARY",
nsoVersion: NSOAPP_VERSION,
s3siVersion: S3SI_VERSION,
exportTime: new Date().toISOString(),
data: summary,
};
await Deno.writeTextFile(
filepath,
2022-11-29 02:05:53 -05:00
JSON.stringify(body),
);
return {
status: "success",
url: filepath,
};
}
2022-11-26 09:45:44 -05:00
async exportGame(info: Game): Promise<ExportResult> {
2022-10-20 09:45:59 -04:00
await Deno.mkdir(this.exportPath, { recursive: true });
2022-10-24 14:45:36 -04:00
const filename = this.getFilenameById(info.detail.id);
2022-10-20 09:45:59 -04:00
const filepath = path.join(this.exportPath, filename);
const common: FileExporterTypeCommon = {
2022-10-20 09:45:59 -04:00
nsoVersion: NSOAPP_VERSION,
s3siVersion: S3SI_VERSION,
exportTime: new Date().toISOString(),
};
const dataType = info.type === "VsInfo"
? {
type: "VS" as const,
data: info,
}
: {
type: "COOP" as const,
data: info,
};
const body: FileExporterType = {
...common,
...dataType,
2022-10-20 09:45:59 -04:00
};
2022-10-21 03:56:43 -04:00
await Deno.writeTextFile(
filepath,
JSON.stringify(body, replacer),
);
2022-10-31 00:33:00 -04:00
return {
2022-11-26 09:45:44 -05:00
status: "success",
2022-10-31 00:33:00 -04:00
url: filepath,
};
2022-10-20 09:45:59 -04:00
}
2022-10-24 14:45:36 -04:00
async notExported({ list }: { list: string[] }): Promise<string[]> {
const out: string[] = [];
for (const id of list) {
2022-10-20 23:14:29 -04:00
const filename = this.getFilenameById(id);
const filepath = path.join(this.exportPath, filename);
const isFile = await Deno.stat(filepath).then((f) => f.isFile).catch(() =>
false
);
2022-10-20 22:57:08 -04:00
if (!isFile) {
out.push(id);
}
}
return out;
2022-10-20 09:45:59 -04:00
}
}