diff --git a/src/cli/splatnet3/dump-album.ts b/src/cli/splatnet3/dump-album.ts index 87aa6f9..848e440 100644 --- a/src/cli/splatnet3/dump-album.ts +++ b/src/cli/splatnet3/dump-album.ts @@ -59,7 +59,7 @@ export async function dumpAlbumPhotos( await splatnet.getPhotoAlbum(); if (typeof refresh !== 'object' || - results.data.photoAlbum.items.nodes[0].id !== refresh.photoAlbum.items.nodes[0].id + results.data.photoAlbum.items.nodes[0]?.id !== refresh.photoAlbum.items.nodes[0]?.id ) { const filename = 'splatnet3-photoalbum-' + Date.now() + '.json'; const file = path.join(directory, filename); diff --git a/src/cli/splatnet3/dump-results.ts b/src/cli/splatnet3/dump-results.ts index c018304..69228e8 100644 --- a/src/cli/splatnet3/dump-results.ts +++ b/src/cli/splatnet3/dump-results.ts @@ -2,12 +2,12 @@ import * as path from 'node:path'; import * as fs from 'node:fs/promises'; import createDebug from 'debug'; import mkdirp from 'mkdirp'; -import { BankaraBattleHistoriesRefetchResult, CoopHistoryResult, LatestBattleHistoriesRefetchResult, LatestBattleHistoriesResult, PrivateBattleHistoriesRefetchResult, RegularBattleHistoriesRefetchResult, RequestId, XBattleHistoriesRefetchResult } from 'splatnet3-types/splatnet3'; +import { BankaraBattleHistoriesRefetchResult, CoopHistoryResult, LatestBattleHistoriesRefetchResult, LatestBattleHistoriesResult, PrivateBattleHistoriesRefetchResult, RefetchableCoopHistory_CoopResultResult, RegularBattleHistoriesRefetchResult, RequestId, XBattleHistoriesRefetchResult } from 'splatnet3-types/splatnet3'; import type { Arguments as ParentArguments } from '../splatnet3.js'; import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js'; import { initStorage } from '../../util/storage.js'; import { getBulletToken } from '../../common/auth/splatnet3.js'; -import SplatNet3Api, { RequestIdSymbol } from '../../api/splatnet3.js'; +import SplatNet3Api, { PersistedQueryResult, RequestIdSymbol } from '../../api/splatnet3.js'; import { ResponseSymbol } from '../../api/util.js'; import { dumpCatalogRecords, dumpHistoryRecords } from './dump-records.js'; @@ -81,14 +81,15 @@ export async function handler(argv: ArgumentsCamelCase) { export async function dumpResults( splatnet: SplatNet3Api, directory: string, - refresh: LatestBattleHistoriesResult | boolean = false + refresh: LatestBattleHistoriesResult | boolean = false, + latest_refetch?: PersistedQueryResult>, ) { debug('Fetching battle results'); console.warn('Fetching battle results'); const [player, battles, battles_regular, battles_anarchy, battles_xmatch, battles_private] = await Promise.all([ refresh ? null : splatnet.getBattleHistoryCurrentPlayer(), - refresh ? splatnet.getLatestBattleHistoriesRefetch() : splatnet.getLatestBattleHistories(), + refresh ? latest_refetch ?? splatnet.getLatestBattleHistoriesRefetch() : splatnet.getLatestBattleHistories(), refresh ? splatnet.getRegularBattleHistoriesRefetch() : splatnet.getRegularBattleHistories(), refresh ? splatnet.getBankaraBattleHistoriesRefetch() : splatnet.getBankaraBattleHistories(), refresh ? splatnet.getXBattleHistoriesRefetch() : splatnet.getXBattleHistories(), @@ -239,13 +240,14 @@ export async function dumpResults( export async function dumpCoopResults( splatnet: SplatNet3Api, directory: string, - refresh: CoopHistoryResult | boolean = false + refresh: CoopHistoryResult | boolean = false, + refetch?: PersistedQueryResult, ) { debug('Fetching coop results'); console.warn('Fetching coop results'); const results = refresh ? - await splatnet.getCoopHistoryRefetch() : + refetch ?? await splatnet.getCoopHistoryRefetch() : await splatnet.getCoopHistory(); const filename = 'splatnet3-coop-summary-' + Date.now() + '.json'; diff --git a/src/cli/splatnet3/monitor.ts b/src/cli/splatnet3/monitor.ts index dbd8c7f..03b0778 100644 --- a/src/cli/splatnet3/monitor.ts +++ b/src/cli/splatnet3/monitor.ts @@ -109,10 +109,10 @@ export async function handler(argv: ArgumentsCamelCase) { console.warn('Monitoring for new data'); if (vs) { - const latest_id = vs.battles.data.latestBattleHistories.historyGroups.nodes[0].historyDetails.nodes[0].id; + const latest_id = vs.battles.data.latestBattleHistories.historyGroups.nodes[0]?.historyDetails.nodes[0]?.id; // If we already had the latest battle result, fetch it again now to match the behavour of Nintendo's app - if (!vs.downloaded.includes(latest_id)) { + if (latest_id && !vs.downloaded.includes(latest_id)) { const id_str = Buffer.from(latest_id, 'base64').toString() || latest_id; const match = id_str.match(/^VsHistoryDetail-(u-[0-9a-z]{20}):([A-Z]+):((\d{8,}T\d{6})_([0-9a-f-]{36}))$/); const id = match ? match[1] + '-' + match[3] : id_str; @@ -124,10 +124,10 @@ export async function handler(argv: ArgumentsCamelCase) { } if (coop) { - const latest_id = coop.results.data.coopResult.historyGroups.nodes[0].historyDetails.nodes[0].id; + const latest_id = coop.results.data.coopResult.historyGroups.nodes[0]?.historyDetails.nodes[0]?.id; // If we already had the latest coop result, fetch it again now to match the behavour of Nintendo's app - if (!coop.downloaded.includes(latest_id)) { + if (latest_id && !coop.downloaded.includes(latest_id)) { const id_str = Buffer.from(latest_id, 'base64').toString() || latest_id; const match = id_str.match(/^CoopHistoryDetail-(u-[0-9a-z]{20}):((\d{8,}T\d{6})_([0-9a-f-]{36}))$/); const id = match ? match[1] + '-' + match[2] : id_str; @@ -187,28 +187,51 @@ async function update( let updated_coop = false; if (vs) { - const latest_id = vs.battles.data.latestBattleHistories.historyGroups.nodes[0].historyDetails.nodes[0].id; + const latest_id = vs.battles.data.latestBattleHistories.historyGroups.nodes[0]?.historyDetails.nodes[0]?.id; - const pager = await splatnet.getBattleHistoryDetailPagerRefetch(latest_id); + if (latest_id) { + const pager = await splatnet.getBattleHistoryDetailPagerRefetch(latest_id); - if (pager.data.vsHistoryDetail?.nextHistoryDetail) { - // New battle results available - debug('New battle result', pager.data.vsHistoryDetail.nextHistoryDetail); - vs = await dumpResults(splatnet, directory, vs.battles.data); - updated_vs = true; + if (pager.data.vsHistoryDetail.nextHistoryDetail) { + // New battle results available + debug('New battle result', pager.data.vsHistoryDetail.nextHistoryDetail); + vs = await dumpResults(splatnet, directory, vs.battles.data); + updated_vs = true; + } + } else { + const latest_refetch = await splatnet.getLatestBattleHistoriesRefetch(); + const latest_id = latest_refetch.data + .latestBattleHistories.historyGroups.nodes[0]?.historyDetails.nodes[0]?.id; + + if (latest_id) { + debug('New battle result'); + vs = await dumpResults(splatnet, directory, vs.battles.data, latest_refetch); + updated_vs = true; + } } } if (coop) { - const latest_id = coop.results.data.coopResult.historyGroups.nodes[0].historyDetails.nodes[0].id; + const latest_id = coop.results.data.coopResult.historyGroups.nodes[0]?.historyDetails.nodes[0]?.id; - const pager = await splatnet.getCoopHistoryDetailRefetch(latest_id); + if (latest_id) { + const pager = await splatnet.getCoopHistoryDetailRefetch(latest_id); - if (pager.data.node?.nextHistoryDetail) { - // New coop results available - debug('New coop result', pager.data.node.nextHistoryDetail); - coop = await dumpCoopResults(splatnet, directory, coop.results.data); - updated_coop = true; + if (pager.data.node.nextHistoryDetail) { + // New coop results available + debug('New coop result', pager.data.node.nextHistoryDetail); + coop = await dumpCoopResults(splatnet, directory, coop.results.data); + updated_coop = true; + } + } else { + const refetch = await splatnet.getCoopHistoryRefetch(); + const latest_id = refetch.data.coopResult.historyGroups.nodes[0]?.historyDetails.nodes[0]?.id; + + if (latest_id) { + debug('New coop result'); + coop = await dumpCoopResults(splatnet, directory, coop.results.data, refetch); + updated_coop = true; + } } }