diff --git a/src/api/coral.ts b/src/api/coral.ts index 9f3f14d..d9df262 100644 --- a/src/api/coral.ts +++ b/src/api/coral.ts @@ -6,7 +6,7 @@ import { timeoutSignal } from '../util/misc.js'; import { getAdditionalUserAgents } from '../util/useragent.js'; import type { CoralRemoteConfig } from '../common/remote-config.js'; import { AccountLogin, AccountLoginParameter, AccountToken, AccountTokenParameter, Announcements, Announcements_4, BlockingUsers, CoralError, CoralResponse, CoralStatus, CoralSuccessResponse, CurrentUser, CurrentUserPermissions, Event, Friend_4, FriendCodeUrl, FriendCodeUser, Friends, Friends_4, GetActiveEventResult, ListChat, ListHashtag, ListHashtagParameter, ListMedia, ListMediaParameter, ListPushNotificationSettings, Media, PlayLogPermissions, PresencePermissions, PushNotificationPlayInvitationScope, ReceivedFriendRequest, ReceivedFriendRequests, SentFriendRequests, ShowUserLogin, UpdatePushNotificationSettingsParameter, UpdatePushNotificationSettingsParameterItem, User, UserPlayLog, WebServices, WebServices_4, WebServiceToken, WebServiceTokenParameter } from './coral-types.js'; -import { createZncaApi, FResult, getDefaultZncaApi, getPreferredZncaApiFromEnvironment, HashMethod, RequestEncryptionProvider, ZncaApi, ZncaApiNxapi } from './f.js'; +import { createZncaApi, DecryptResponseResult, FResult, getDefaultZncaApi, getPreferredZncaApiFromEnvironment, HashMethod, RequestEncryptionProvider, ZncaApi, ZncaApiNxapi } from './f.js'; import { generateAuthData, getNintendoAccountToken, getNintendoAccountUser, NintendoAccountScope, NintendoAccountSessionAuthorisation, NintendoAccountToken, NintendoAccountUser } from './na.js'; import { ErrorResponse, ResponseSymbol } from './util.js'; import { ErrorDescription, ErrorDescriptionSymbol, HasErrorDescription } from '../util/errors.js'; @@ -24,6 +24,7 @@ export const ZNCA_CLIENT_ID = '71b963c1b7b6d119'; const FRIEND_CODE = /^\d{4}-\d{4}-\d{4}$/; const FRIEND_CODE_HASH = /^[A-Za-z0-9]{10}$/; +export const ResponseEncryptionSymbol = Symbol('ResponseEncryption'); export const ResponseDataSymbol = Symbol('ResponseData'); export const CorrelationIdSymbol = Symbol('CorrelationId'); @@ -31,6 +32,7 @@ export type Result = T & ResultData; export interface ResultData { [ResponseSymbol]: Response; + [ResponseEncryptionSymbol]: ResponseEncryption | null; [ResponseDataSymbol]: CoralSuccessResponse; [CorrelationIdSymbol]: string; @@ -41,6 +43,10 @@ export interface ResultData { /** @deprecated */ correlationId: string; } +export interface ResponseEncryption { + encrypted: Uint8Array; + decrypt_result: DecryptResponseResult; +} export interface CoralApiInterface { getAnnouncements(): Promise>; @@ -881,7 +887,7 @@ class CoralApiRequest { return this.handleEncryptedJsonResponse(response, data, request_encryption, _attempt); } - return this.decodeJsonResponse(response, data, _attempt); + return this.decodeJsonResponse(response, data, null, _attempt); } if (!response.ok) { @@ -898,11 +904,16 @@ class CoralApiRequest { ) { const decrypted = await request_encryption.decryptResponse(data); - return this.decodeJsonResponse(response, decrypted.data, _attempt); + const encryption: ResponseEncryption = { + encrypted: data, + decrypt_result: decrypted, + }; + + return this.decodeJsonResponse(response, decrypted.data, encryption, _attempt); } private async decodeJsonResponse( - response: Response, data: string | Uint8Array, + response: Response, data: string | Uint8Array, encryption: ResponseEncryption | null, /** @internal */ _attempt: number, ) { let json: CoralResponse; @@ -922,11 +933,11 @@ class CoralApiRequest { throw new CoralErrorResponse('[znc] Non-200 status code', response, json as CoralError); } - return this.handleJsonResponse(response, json, _attempt); + return this.handleJsonResponse(response, json, encryption, _attempt); } private async handleJsonResponse( - response: Response, data: CoralResponse, + response: Response, data: CoralResponse, encryption: ResponseEncryption | null, /** @internal */ _attempt: number, ) { debug('fetch %s %s, response %s, status %d %s, correlationId %s', this.method, this.url, response.status, @@ -954,6 +965,7 @@ class CoralApiRequest { const result = data.result; Object.defineProperty(result, ResponseSymbol, {enumerable: false, value: response}); + Object.defineProperty(result, ResponseEncryptionSymbol, {enumerable: false, value: encryption}); Object.defineProperty(result, ResponseDataSymbol, {enumerable: false, value: data}); Object.defineProperty(result, CorrelationIdSymbol, {enumerable: false, value: data.correlationId}); diff --git a/src/api/znc-proxy.ts b/src/api/znc-proxy.ts index 23c3d16..0b272f5 100644 --- a/src/api/znc-proxy.ts +++ b/src/api/znc-proxy.ts @@ -1,7 +1,7 @@ import { fetch, Response } from 'undici'; import { ActiveEvent, CurrentUser, Event, Friend, Presence, PresencePermissions, User, WebServiceToken, CoralStatus, CoralSuccessResponse, FriendCodeUser, FriendCodeUrl, WebService_4, Media, Announcements_4, Friend_4, PresenceOnline_4, PresenceOnline, PresenceOffline } from './coral-types.js'; import { defineResponse, ErrorResponse, ResponseSymbol } from './util.js'; -import { AbstractCoralApi, CoralApiInterface, CoralAuthData, CorrelationIdSymbol, PartialCoralAuthData, RequestFlagAddPlatformSymbol, RequestFlagAddProductVersionSymbol, RequestFlagNoParameterSymbol, RequestFlagRequestIdSymbol, RequestFlags, ResponseDataSymbol, Result } from './coral.js'; +import { AbstractCoralApi, CoralApiInterface, CoralAuthData, CorrelationIdSymbol, PartialCoralAuthData, RequestFlagAddPlatformSymbol, RequestFlagAddProductVersionSymbol, RequestFlagNoParameterSymbol, RequestFlagRequestIdSymbol, RequestFlags, ResponseDataSymbol, ResponseEncryptionSymbol, Result } from './coral.js'; import { NintendoAccountToken, NintendoAccountUser } from './na.js'; import { SavedToken } from '../common/auth/coral.js'; import createDebug from '../util/debug.js'; @@ -207,6 +207,7 @@ function createResult(data: R & {[ResponseSymbol]: Response}, r }; Object.defineProperty(result, ResponseSymbol, {enumerable: false, value: data[ResponseSymbol]}); + Object.defineProperty(result, ResponseEncryptionSymbol, {enumerable: false, value: null}); Object.defineProperty(result, ResponseDataSymbol, {enumerable: false, value: coral_result}); Object.defineProperty(result, CorrelationIdSymbol, {enumerable: false, value: ''});