From 6fcebb07bd68b2300b2cbd647e73ad45bbe37d46 Mon Sep 17 00:00:00 2001 From: spacemeowx2 Date: Tue, 15 Nov 2022 03:29:31 +0800 Subject: [PATCH] feat: add geardata exporter --- scripts/export-geardata.ts | 60 ++++++++++++++++++++++++++++++++++++++ src/splatnet3.ts | 18 ++++++++++++ src/types.ts | 8 +++++ 3 files changed, 86 insertions(+) create mode 100644 scripts/export-geardata.ts diff --git a/scripts/export-geardata.ts b/scripts/export-geardata.ts new file mode 100644 index 0000000..2c81199 --- /dev/null +++ b/scripts/export-geardata.ts @@ -0,0 +1,60 @@ +/** + * Export your gear database to json format used in: + * https://leanny.github.io/splat3seedchecker/#/settings + * + * This script get token from `./profile.json`. And export geardata + * to `./geardata_${timestamp}.json`. + * Make sure to update token before running this script. + */ + +import Murmurhash3 from "https://deno.land/x/murmurhash@v1.0.0/mod.ts"; +import { base64 } from "../deps.ts"; +import { getGears, getLatestBattleHistoriesQuery } from "../src/splatnet3.ts"; +import { FileStateBackend } from "../src/state.ts"; +import { parseHistoryDetailId } from "../src/utils.ts"; + +function encryptKey(uid: string) { + const hasher = new Murmurhash3(); + hasher.hash(uid); + const hash = hasher.result(); + const key = hash & 0xff; + const encrypted = base64.encode( + new TextEncoder().encode(uid).map((i) => i ^ key), + ); + return { + key: encrypted, + h: hash, + }; +} + +const state = await new FileStateBackend("./profile.json").read(); + +console.log("Fetching uid..."); +const { latestBattleHistories: { historyGroups } } = + await getLatestBattleHistoriesQuery(state); + +const id = historyGroups.nodes?.[0].historyDetails.nodes?.[0].id; + +if (!id) { + console.log("No battle history found"); + Deno.exit(0); +} + +const { uid } = parseHistoryDetailId(id); + +console.log("Fetching gears..."); +const data = await getGears(state); +const timestamp = Math.floor(new Date().getTime() / 1000); + +await Deno.writeTextFile( + `./geardata_${timestamp}.json`, + JSON.stringify({ + ...encryptKey(uid), + timestamp, + gear: { + data, + }, + }), +); + +console.log("Done"); diff --git a/src/splatnet3.ts b/src/splatnet3.ts index 9e3e021..b681f98 100644 --- a/src/splatnet3.ts +++ b/src/splatnet3.ts @@ -171,3 +171,21 @@ export async function getGearPower(state: State) { return resp; } + +export async function getLatestBattleHistoriesQuery(state: State) { + const resp = await request( + state, + Queries.LatestBattleHistoriesQuery, + ); + + return resp; +} + +export async function getGears(state: State) { + const resp = await request( + state, + Queries.myOutfitCommonDataEquipmentsQuery, + ); + + return resp; +} diff --git a/src/types.ts b/src/types.ts index b0dbf91..0c0339b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -11,6 +11,7 @@ export enum Queries { CoopHistoryDetailQuery = "f3799a033f0a7ad4b1b396f9a3bafb1e", myOutfitCommonDataFilteringConditionQuery = "d02ab22c9dccc440076055c8baa0fa7a", + myOutfitCommonDataEquipmentsQuery = "d29cd0c2b5e6bac90dd5b817914832f8", } export type VarsMap = { [Queries.HomeQuery]: []; @@ -26,6 +27,7 @@ export type VarsMap = { coopHistoryDetailId: string; }]; [Queries.myOutfitCommonDataFilteringConditionQuery]: []; + [Queries.myOutfitCommonDataEquipmentsQuery]: []; }; export type Image = { @@ -250,6 +252,12 @@ export type RespMap = { }[]; }; }; + [Queries.myOutfitCommonDataEquipmentsQuery]: { + weapons: unknown[]; + headGears: unknown[]; + clothingGears: unknown[]; + shoesGears: unknown[]; + }; }; export type GraphQLResponse = { data: T;