add stage exporting

main
Rosalina 2023-03-07 10:09:32 -05:00
parent 93b360d5b2
commit 3f31bc7ea9
No known key found for this signature in database
8 changed files with 169 additions and 103 deletions

View File

@ -14,3 +14,4 @@ export { MultiProgressBar } from "https://deno.land/x/progress@v1.2.8/mod.ts";
export { Mutex } from "https://deno.land/x/semaphore@v1.1.1/mod.ts"; export { Mutex } from "https://deno.land/x/semaphore@v1.1.1/mod.ts";
export type { DeepReadonly } from "https://deno.land/x/ts_essentials@v9.1.2/mod.ts"; export type { DeepReadonly } from "https://deno.land/x/ts_essentials@v9.1.2/mod.ts";
export * as MongoDB from "npm:mongodb"; export * as MongoDB from "npm:mongodb";
export * as splatNet3Types from "npm:splatnet3-types/splatnet3";

View File

@ -14,6 +14,7 @@ const parseArgs = (args: string[]) => {
"monitor": ["m"], "monitor": ["m"],
"skipMode": ["s", "skip-mode"], "skipMode": ["s", "skip-mode"],
"withSummary": "with-summary", "withSummary": "with-summary",
"withStages": "with-stages",
}, },
}); });
return parsed; return parsed;
@ -34,6 +35,7 @@ Options:
--skip-mode <mode>, -s Skip mode (default: null) --skip-mode <mode>, -s Skip mode (default: null)
("vs", "coop") ("vs", "coop")
--with-summary Include summary in the output --with-summary Include summary in the output
--with-stages Include stage records in the output
--help Show this help message and exit`, --help Show this help message and exit`,
); );
Deno.exit(0); Deno.exit(0);

View File

@ -3,7 +3,7 @@ import { DEFAULT_ENV } from "../src/env.ts";
import { MongoDBExporter } from "../src/exporters/mongodb.ts"; import { MongoDBExporter } from "../src/exporters/mongodb.ts";
import { FileStateBackend, Profile } from "../src/state.ts"; import { FileStateBackend, Profile } from "../src/state.ts";
const OLD_BATTLES_END_DATE = new Date('2023-02-28T03:42:47.000+00:00'); const OLD_BATTLES_END_DATE = new Date("2023-02-28T03:42:47.000+00:00");
const env = DEFAULT_ENV; const env = DEFAULT_ENV;
const stateBackend = new FileStateBackend("./profile.json"); const stateBackend = new FileStateBackend("./profile.json");
@ -37,11 +37,13 @@ for await (const doc of cursor) {
const splatNetId = splatNetData.id; const splatNetId = splatNetData.id;
const uniqueId = MongoDBExporter.getGameId(splatNetId); const uniqueId = MongoDBExporter.getGameId(splatNetId);
await battlesCollection.updateOne({ _id }, { "$set": { await battlesCollection.updateOne({ _id }, {
"$set": {
gameId: uniqueId, gameId: uniqueId,
}}); },
});
console.log(`Updated ${splatNetId} to ${uniqueId}`); console.log(`Updated ${splatNetId} to ${uniqueId}`);
} }
console.log("Done!") console.log("Done!");

View File

@ -18,8 +18,8 @@ const battlesCollection = mongoDbClient.db("splashcat").collection("battles");
const filter = { const filter = {
"splatNetData.playedTime": { "splatNetData.playedTime": {
$type: "string" $type: "string",
} },
}; };
const cursor = battlesCollection.find(filter); const cursor = battlesCollection.find(filter);
@ -31,11 +31,17 @@ console.log(`Found ${oldDocuments} old battles to update...`);
for await (const doc of cursor) { for await (const doc of cursor) {
const { splatNetData, _id } = doc; const { splatNetData, _id } = doc;
await battlesCollection.updateOne({ _id }, { "$set": { await battlesCollection.updateOne({ _id }, {
"$set": {
"splatNetData.playedTime": new Date(splatNetData.playedTime), "splatNetData.playedTime": new Date(splatNetData.playedTime),
}}); },
});
console.log(`Updated ${splatNetData.playedTime} to ${new Date(splatNetData.playedTime)}`); console.log(
`Updated ${splatNetData.playedTime} to ${new Date(
splatNetData.playedTime,
)}`,
);
} }
console.log("Done!") console.log("Done!");

View File

@ -17,6 +17,7 @@ export type Opts = {
noProgress: boolean; noProgress: boolean;
monitor: boolean; monitor: boolean;
withSummary: boolean; withSummary: boolean;
withStages: boolean;
skipMode?: string; skipMode?: string;
cache?: Cache; cache?: Cache;
stateBackend?: StateBackend; stateBackend?: StateBackend;
@ -29,6 +30,7 @@ export const DEFAULT_OPTS: Opts = {
noProgress: false, noProgress: false,
monitor: false, monitor: false,
withSummary: false, withSummary: false,
withStages: true,
env: DEFAULT_ENV, env: DEFAULT_ENV,
}; };
@ -310,6 +312,34 @@ export class App {
throw errors[0]; throw errors[0];
} }
} }
const stageExporters = exporters.filter((e) => e.exportStages);
if (!this.opts.withStages || stageExporters.length === 0) {
this.env.logger.log("Skip exporting stages.");
} else {
const stageRecords = await splatnet.getStageRecords();
await Promise.all(
stageExporters.map((e) =>
showError(
this.env,
e.exportStages!(stageRecords.stageRecords.nodes),
).then((result) => {
if (result.status === "success") {
this.env.logger.log(`Exported stages to ${result.url}`);
} else if (result.status === "skip") {
this.env.logger.log(`Skipped exporting stages to ${e.name}`);
} else {
const _never: never = result;
}
})
.catch((err) => {
errors.push(err);
this.env.logger.error(`\nFailed to export to ${e.name}:`, err);
})
),
);
}
} }
async monitor() { async monitor() {
while (true) { while (true) {

View File

@ -1,6 +1,13 @@
import { MongoDB } from "../../deps.ts"; import { MongoDB } from "../../deps.ts";
import { AGENT_VERSION, NSOAPP_VERSION, S3SI_VERSION } from "../constant.ts"; import { AGENT_VERSION, NSOAPP_VERSION, S3SI_VERSION } from "../constant.ts";
import { CoopHistoryDetail, ExportResult, Game, GameExporter, Summary, VsHistoryDetail } from "../types.ts"; import {
CoopHistoryDetail,
ExportResult,
Game,
GameExporter,
Summary,
VsHistoryDetail,
} from "../types.ts";
import { parseHistoryDetailId } from "../utils.ts"; import { parseHistoryDetailId } from "../utils.ts";
export class MongoDBExporter implements GameExporter { export class MongoDBExporter implements GameExporter {
@ -24,10 +31,14 @@ export class MongoDBExporter implements GameExporter {
return `${uid}_${timestamp}Z`; return `${uid}_${timestamp}Z`;
} }
async notExported({ type, list }: { type: Game["type"], list: string[] }): Promise<string[]> { async notExported(
{ type, list }: { type: Game["type"]; list: string[] },
): Promise<string[]> {
const out: string[] = []; const out: string[] = [];
const collection = type === "CoopInfo" ? this.jobsCollection : this.battlesCollection; const collection = type === "CoopInfo"
? this.jobsCollection
: this.battlesCollection;
for (const id of list) { for (const id of list) {
const uniqueId = MongoDBExporter.getGameId(id); const uniqueId = MongoDBExporter.getGameId(id);
@ -60,11 +71,12 @@ export class MongoDBExporter implements GameExporter {
playedTime: new Date(game.detail.playedTime), playedTime: new Date(game.detail.playedTime),
}; };
const body: const body: {
{ data: Game;
data: Game, splatNetData:
splatNetData: Omit<(VsHistoryDetail | CoopHistoryDetail), "playedTime"> & { playedTime: Date }, & Omit<(VsHistoryDetail | CoopHistoryDetail), "playedTime">
gameId: string, & { playedTime: Date };
gameId: string;
} & typeof common = { } & typeof common = {
...common, ...common,
data: game, data: game,

View File

@ -257,6 +257,12 @@ export class Splatnet3 {
CoopHistoryQuery, CoopHistoryQuery,
}; };
} }
async getStageRecords() {
const resp = await this.request(Queries.StageRecordQuery);
return resp;
}
} }
function getIdsFromGroups<T extends { id: string }>( function getIdsFromGroups<T extends { id: string }>(

View File

@ -1,3 +1,4 @@
import { splatNet3Types } from "../deps.ts";
import { RankState } from "./state.ts"; import { RankState } from "./state.ts";
export enum Queries { export enum Queries {
@ -15,6 +16,7 @@ export enum Queries {
myOutfitCommonDataEquipmentsQuery = "d29cd0c2b5e6bac90dd5b817914832f8", myOutfitCommonDataEquipmentsQuery = "d29cd0c2b5e6bac90dd5b817914832f8",
HistoryRecordQuery = "32b6771f94083d8f04848109b7300af5", HistoryRecordQuery = "32b6771f94083d8f04848109b7300af5",
ConfigureAnalyticsQuery = "f8ae00773cc412a50dd41a6d9a159ddd", ConfigureAnalyticsQuery = "f8ae00773cc412a50dd41a6d9a159ddd",
StageRecordQuery = "f08a932d533845dde86e674e03bbb7d3",
} }
export type VarsMap = { export type VarsMap = {
[Queries.HomeQuery]: []; [Queries.HomeQuery]: [];
@ -34,6 +36,7 @@ export type VarsMap = {
[Queries.myOutfitCommonDataEquipmentsQuery]: []; [Queries.myOutfitCommonDataEquipmentsQuery]: [];
[Queries.HistoryRecordQuery]: []; [Queries.HistoryRecordQuery]: [];
[Queries.ConfigureAnalyticsQuery]: []; [Queries.ConfigureAnalyticsQuery]: [];
[Queries.StageRecordQuery]: [];
}; };
export type Image = { export type Image = {
@ -371,6 +374,9 @@ export type GameExporter = {
) => Promise<string[]>; ) => Promise<string[]>;
exportGame: (game: Game) => Promise<ExportResult>; exportGame: (game: Game) => Promise<ExportResult>;
exportSummary?: (summary: Summary) => Promise<ExportResult>; exportSummary?: (summary: Summary) => Promise<ExportResult>;
exportStages?: (
stages: RespMap[Queries.StageRecordQuery]["stageRecords"]["nodes"],
) => Promise<ExportResult>;
}; };
export type BankaraBattleHistories = { export type BankaraBattleHistories = {
@ -550,6 +556,7 @@ export type RespMap = {
xMatchMaxLf: SimpleXRank; xMatchMaxLf: SimpleXRank;
} | null; } | null;
}; };
[Queries.StageRecordQuery]: splatNet3Types.StageRecordResult;
}; };
export type WeaponWithRatio = { export type WeaponWithRatio = {
weapon: { weapon: {