Accept numbers for the hash_method option when generating f parameters

This commit is contained in:
Samuel Elliott 2022-09-07 10:16:16 +01:00
parent 960624cae4
commit 66c8efdb96
No known key found for this signature in database
GPG Key ID: 8420C7CDE43DC4D6
4 changed files with 39 additions and 20 deletions

View File

@ -1,7 +1,7 @@
import fetch, { Response } from 'node-fetch'; import fetch, { Response } from 'node-fetch';
import { v4 as uuidgen } from 'uuid'; import { v4 as uuidgen } from 'uuid';
import createDebug from 'debug'; import createDebug from 'debug';
import { f, FResult } from './f.js'; import { f, FResult, HashMethod } from './f.js';
import { AccountLogin, AccountToken, Announcements, CurrentUser, CurrentUserPermissions, Event, Friends, GetActiveEventResult, PresencePermissions, User, WebServices, WebServiceToken, CoralErrorResponse, CoralResponse, CoralStatus, CoralSuccessResponse, FriendCodeUser, FriendCodeUrl, AccountTokenParameter, AccountLoginParameter } from './coral-types.js'; import { AccountLogin, AccountToken, Announcements, CurrentUser, CurrentUserPermissions, Event, Friends, GetActiveEventResult, PresencePermissions, User, WebServices, WebServiceToken, CoralErrorResponse, CoralResponse, CoralStatus, CoralSuccessResponse, FriendCodeUser, FriendCodeUrl, AccountTokenParameter, AccountLoginParameter } from './coral-types.js';
import { getNintendoAccountToken, getNintendoAccountUser, NintendoAccountToken, NintendoAccountUser } from './na.js'; import { getNintendoAccountToken, getNintendoAccountUser, NintendoAccountToken, NintendoAccountUser } from './na.js';
import { ErrorResponse } from './util.js'; import { ErrorResponse } from './util.js';
@ -178,7 +178,7 @@ export default class CoralApi {
} }
async getWebServiceToken(id: string) { async getWebServiceToken(id: string) {
const data = await f(this.token, '2', this.useragent ?? getAdditionalUserAgents()); const data = await f(this.token, HashMethod.WEB_SERVICE, this.useragent ?? getAdditionalUserAgents());
const req = { const req = {
id, id,
@ -195,7 +195,8 @@ export default class CoralApi {
// Nintendo Account token // Nintendo Account token
const nintendoAccountToken = await getNintendoAccountToken(token, ZNCA_CLIENT_ID); const nintendoAccountToken = await getNintendoAccountToken(token, ZNCA_CLIENT_ID);
const fdata = await f(nintendoAccountToken.id_token, '1', this.useragent ?? getAdditionalUserAgents()); const fdata = await f(nintendoAccountToken.id_token, HashMethod.CORAL,
this.useragent ?? getAdditionalUserAgents());
const req: AccountTokenParameter = { const req: AccountTokenParameter = {
naBirthday: user.birthday, naBirthday: user.birthday,
@ -250,7 +251,7 @@ export default class CoralApi {
// Nintendo Account user data // Nintendo Account user data
const user = await getNintendoAccountUser(nintendoAccountToken); const user = await getNintendoAccountUser(nintendoAccountToken);
const fdata = await f(nintendoAccountToken.id_token, '1', useragent); const fdata = await f(nintendoAccountToken.id_token, HashMethod.CORAL, useragent);
debug('Getting Nintendo Switch Online app token'); debug('Getting Nintendo Switch Online app token');

View File

@ -16,7 +16,12 @@ export abstract class ZncaApi {
public useragent?: string public useragent?: string
) {} ) {}
abstract genf(token: string, hash_method: '1' | '2'): Promise<FResult>; abstract genf(token: string, hash_method: HashMethod): Promise<FResult>;
}
export enum HashMethod {
CORAL = 1,
WEB_SERVICE = 2,
} }
// //
@ -67,7 +72,7 @@ export interface LoginHashApiError {
} }
export async function flapg( export async function flapg(
hash_method: '1' | '2', token: string, hash_method: HashMethod, token: string,
timestamp?: string | number, request_id?: string, timestamp?: string | number, request_id?: string,
useragent?: string useragent?: string
) { ) {
@ -79,7 +84,7 @@ export async function flapg(
}); });
const req: FlapgApiRequest = { const req: FlapgApiRequest = {
hash_method, hash_method: '' + hash_method as `${HashMethod}`,
token, token,
timestamp: typeof timestamp === 'number' ? '' + timestamp : undefined, timestamp: typeof timestamp === 'number' ? '' + timestamp : undefined,
request_id, request_id,
@ -115,7 +120,13 @@ export enum FlapgIid {
APP = 'app', APP = 'app',
} }
export type FlapgApiRequest = IminkFRequest; export interface FlapgApiRequest {
hash_method: '1' | '2';
token: string;
timestamp?: string;
request_id?: string;
}
export type FlapgApiResponse = IminkFResponse; export type FlapgApiResponse = IminkFResponse;
export type FlapgApiError = IminkFError; export type FlapgApiError = IminkFError;
@ -125,7 +136,7 @@ export class ZncaApiFlapg extends ZncaApi {
return getLoginHash(id_token, timestamp, this.useragent); return getLoginHash(id_token, timestamp, this.useragent);
} }
async genf(token: string, hash_method: '1' | '2') { async genf(token: string, hash_method: HashMethod) {
const request_id = uuidgen(); const request_id = uuidgen();
const result = await flapg(hash_method, token, undefined, request_id, this.useragent); const result = await flapg(hash_method, token, undefined, request_id, this.useragent);
@ -145,7 +156,7 @@ export class ZncaApiFlapg extends ZncaApi {
// //
export async function iminkf( export async function iminkf(
hash_method: '1' | '2', token: string, hash_method: HashMethod, token: string,
timestamp?: number, request_id?: string, timestamp?: number, request_id?: string,
useragent?: string useragent?: string
) { ) {
@ -190,9 +201,9 @@ export async function iminkf(
} }
export interface IminkFRequest { export interface IminkFRequest {
hash_method: '1' | '2'; hash_method: 1 | 2 | '1' | '2';
token: string; token: string;
timestamp?: string; timestamp?: string | number;
request_id?: string; request_id?: string;
} }
export interface IminkFResponse { export interface IminkFResponse {
@ -206,7 +217,7 @@ export interface IminkFError {
} }
export class ZncaApiImink extends ZncaApi { export class ZncaApiImink extends ZncaApi {
async genf(token: string, hash_method: '1' | '2') { async genf(token: string, hash_method: HashMethod) {
const request_id = uuidgen(); const request_id = uuidgen();
const result = await iminkf(hash_method, token, undefined, request_id, this.useragent); const result = await iminkf(hash_method, token, undefined, request_id, this.useragent);
@ -226,7 +237,7 @@ export class ZncaApiImink extends ZncaApi {
// //
export async function genf( export async function genf(
url: string, hash_method: '1' | '2', url: string, hash_method: HashMethod,
token: string, timestamp?: number, request_id?: string, token: string, timestamp?: number, request_id?: string,
useragent?: string useragent?: string
) { ) {
@ -235,7 +246,7 @@ export async function genf(
}); });
const req: AndroidZncaFRequest = { const req: AndroidZncaFRequest = {
hash_method, hash_method: '' + hash_method as `${HashMethod}`,
token, token,
timestamp, timestamp,
request_id, request_id,
@ -260,7 +271,7 @@ export async function genf(
if ('error' in data) { if ('error' in data) {
debugZncaApi('Error getting f parameter "%s"', data.error); debugZncaApi('Error getting f parameter "%s"', data.error);
throw new ErrorResponse<AndroidZncaFError>('[znca-api] ' + data.error, response, data); throw new ErrorResponse<AndroidZncaFError>('[znca-api] ' + data.error_message ?? data.error, response, data);
} }
debugZncaApi('Got f parameter', data, response.headers); debugZncaApi('Got f parameter', data, response.headers);
@ -281,6 +292,7 @@ export interface AndroidZncaFResponse {
} }
export interface AndroidZncaFError { export interface AndroidZncaFError {
error: string; error: string;
error_message?: string;
} }
export class ZncaApiNxapi extends ZncaApi { export class ZncaApiNxapi extends ZncaApi {
@ -288,7 +300,7 @@ export class ZncaApiNxapi extends ZncaApi {
super(useragent); super(useragent);
} }
async genf(token: string, hash_method: '1' | '2') { async genf(token: string, hash_method: HashMethod) {
const request_id = uuidgen(); const request_id = uuidgen();
const result = await genf(this.url + '/f', hash_method, token, undefined, request_id, this.useragent); const result = await genf(this.url + '/f', hash_method, token, undefined, request_id, this.useragent);
@ -304,7 +316,9 @@ export class ZncaApiNxapi extends ZncaApi {
} }
} }
export async function f(token: string, hash_method: '1' | '2', useragent?: string): Promise<FResult> { export async function f(token: string, hash_method: HashMethod | `${HashMethod}`, useragent?: string): Promise<FResult> {
if (typeof hash_method === 'string') hash_method = parseInt(hash_method);
const provider = getPreferredZncaApiFromEnvironment(useragent) ?? await getDefaultZncaApi(useragent); const provider = getPreferredZncaApiFromEnvironment(useragent) ?? await getDefaultZncaApi(useragent);
return provider.genf(token, hash_method); return provider.genf(token, hash_method);
@ -312,7 +326,7 @@ export async function f(token: string, hash_method: '1' | '2', useragent?: strin
export type FResult = { export type FResult = {
provider: string; provider: string;
hash_method: '1' | '2'; hash_method: HashMethod;
token: string; token: string;
timestamp: number; timestamp: number;
request_id: string; request_id: string;

View File

@ -183,7 +183,7 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
await ready; await ready;
let data: { let data: {
hash_method: '1' | '2'; hash_method: '1' | '2' | 1 | 2;
token: string; token: string;
timestamp?: string | number; timestamp?: string | number;
request_id?: string; request_id?: string;
@ -203,6 +203,9 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
request_id: data.uuid, request_id: data.uuid,
}; };
if (data && data.hash_method === 1) data.hash_method = '1';
if (data && data.hash_method === 2) data.hash_method = '2';
if ( if (
!data || !data ||
typeof data !== 'object' || typeof data !== 'object' ||

View File

@ -10,6 +10,7 @@ export { default as ZncProxyApi } from '../api/znc-proxy.js';
export { export {
ZncaApi, ZncaApi,
HashMethod,
getPreferredZncaApiFromEnvironment, getPreferredZncaApiFromEnvironment,
getDefaultZncaApi, getDefaultZncaApi,
f, f,