mirror of
https://github.com/samuelthomas2774/nxapi.git
synced 2026-09-07 10:55:09 -05:00
Add an option to use the imink API to generate f parameters
https://github.com/JoneWang/imink/wiki/imink-API-Documentation https://github.com/JoneWang
This commit is contained in:
205
src/api/f.ts
205
src/api/f.ts
@@ -5,8 +5,13 @@ import { version } from '../util/product.js';
|
||||
|
||||
const debugS2s = createDebug('nxapi:api:s2s');
|
||||
const debugFlapg = createDebug('nxapi:api:flapg');
|
||||
const debugImink = createDebug('nxapi:api:imink');
|
||||
const debugZncaApi = createDebug('nxapi:api:znca-api');
|
||||
|
||||
//
|
||||
// splatnet2statink + flapg
|
||||
//
|
||||
|
||||
export async function getLoginHash(token: string, timestamp: string | number, useragent?: string) {
|
||||
debugS2s('Getting login hash');
|
||||
|
||||
@@ -33,6 +38,13 @@ export async function getLoginHash(token: string, timestamp: string | number, us
|
||||
return data.hash;
|
||||
}
|
||||
|
||||
export interface LoginHashApiResponse {
|
||||
hash: string;
|
||||
}
|
||||
export interface LoginHashApiError {
|
||||
error: string;
|
||||
}
|
||||
|
||||
export async function flapg(
|
||||
token: string, timestamp: string | number, guid: string, iid: FlapgIid,
|
||||
useragent?: string
|
||||
@@ -59,9 +71,82 @@ export async function flapg(
|
||||
|
||||
debugFlapg('Got f parameter "%s"', data.result.f);
|
||||
|
||||
return data.result;
|
||||
return data;
|
||||
}
|
||||
|
||||
export enum FlapgIid {
|
||||
/** Nintendo Switch Online app token */
|
||||
NSO = 'nso',
|
||||
/** Web service token */
|
||||
APP = 'app',
|
||||
}
|
||||
|
||||
export interface FlapgApiResponse {
|
||||
result: {
|
||||
f: string;
|
||||
p1: string;
|
||||
p2: string;
|
||||
p3: string;
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// imink
|
||||
//
|
||||
|
||||
export async function iminkf(
|
||||
token: string, timestamp: string | number, uuid: string, hash_method: '1' | '2',
|
||||
useragent?: string
|
||||
) {
|
||||
debugImink('Getting f parameter', {
|
||||
token, timestamp, uuid, hash_method,
|
||||
});
|
||||
|
||||
const req: IminkFRequest = {
|
||||
hash_method,
|
||||
token,
|
||||
timestamp: '' + timestamp,
|
||||
request_id: uuid,
|
||||
};
|
||||
|
||||
const response = await fetch('https://api.imink.app/f', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': (useragent ? useragent + ' ' : '') + 'nxapi/' + version,
|
||||
},
|
||||
body: JSON.stringify(req),
|
||||
});
|
||||
|
||||
const data = await response.json() as IminkFResponse | IminkFError;
|
||||
|
||||
if ('error' in data) {
|
||||
throw new ErrorResponse('[imink] ' + data.reason, response, data);
|
||||
}
|
||||
|
||||
debugImink('Got f parameter "%s"', data.f);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
export interface IminkFRequest {
|
||||
timestamp: string;
|
||||
request_id: string;
|
||||
hash_method: '1' | '2';
|
||||
token: string;
|
||||
}
|
||||
export interface IminkFResponse {
|
||||
f: string;
|
||||
}
|
||||
export interface IminkFError {
|
||||
reason: string;
|
||||
error: true;
|
||||
}
|
||||
|
||||
//
|
||||
// nxapi znca API server
|
||||
//
|
||||
|
||||
export async function genf(
|
||||
url: string, token: string, timestamp: string | number, uuid: string, type: FlapgIid,
|
||||
useragent?: string
|
||||
@@ -95,46 +180,7 @@ export async function genf(
|
||||
|
||||
debugZncaApi('Got f parameter "%s"', data.f);
|
||||
|
||||
return data.f;
|
||||
}
|
||||
|
||||
export async function genfc(
|
||||
url: string, token: string, timestamp: string | number, uuid: string, type: FlapgIid,
|
||||
useragent?: string
|
||||
) {
|
||||
const f = await genf(url, token, timestamp, uuid, type, useragent);
|
||||
|
||||
return {
|
||||
f,
|
||||
p1: token,
|
||||
p2: '' + timestamp,
|
||||
p3: uuid,
|
||||
|
||||
url,
|
||||
};
|
||||
}
|
||||
|
||||
export interface LoginHashApiResponse {
|
||||
hash: string;
|
||||
}
|
||||
export interface LoginHashApiError {
|
||||
error: string;
|
||||
}
|
||||
|
||||
export enum FlapgIid {
|
||||
/** Nintendo Switch Online app token */
|
||||
NSO = 'nso',
|
||||
/** Web service token */
|
||||
APP = 'app',
|
||||
}
|
||||
|
||||
export interface FlapgApiResponse {
|
||||
result: {
|
||||
f: string;
|
||||
p1: string;
|
||||
p2: string;
|
||||
p3: string;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
|
||||
export interface AndroidZncaFRequest {
|
||||
@@ -149,3 +195,80 @@ export interface AndroidZncaFResponse {
|
||||
export interface AndroidZncaFError {
|
||||
error: string;
|
||||
}
|
||||
|
||||
export async function f(
|
||||
token: string, timestamp: string | number, uuid: string, type: FlapgIid,
|
||||
useragent?: string,
|
||||
provider: FApi = getEnvApi()
|
||||
): Promise<FResult> {
|
||||
if (provider === 'flapg') {
|
||||
const result = await flapg(token, timestamp, uuid, type, useragent);
|
||||
return {
|
||||
provider: 'flapg',
|
||||
token, timestamp: '' + timestamp, uuid, type,
|
||||
f: result.result.f, result,
|
||||
};
|
||||
}
|
||||
if (provider === 'imink') {
|
||||
const result = await iminkf(token, timestamp, uuid, type === FlapgIid.APP ? '2' : '1', useragent);
|
||||
return {
|
||||
provider: 'imink',
|
||||
token, timestamp: '' + timestamp, uuid, type,
|
||||
f: result.f, result,
|
||||
};
|
||||
}
|
||||
if (provider[0] === 'nxapi') {
|
||||
const result = await genf(provider[1], token, timestamp, uuid, type, useragent);
|
||||
return {
|
||||
provider: 'nxapi', url: provider[1],
|
||||
token, timestamp: '' + timestamp, uuid, type,
|
||||
f: result.f, result,
|
||||
};
|
||||
}
|
||||
|
||||
throw new Error('Unknown znca API provider');
|
||||
}
|
||||
|
||||
export type FApi =
|
||||
'flapg' |
|
||||
'imink' |
|
||||
['nxapi', string];
|
||||
|
||||
export type FResult = {
|
||||
provider: string;
|
||||
token: string;
|
||||
timestamp: string;
|
||||
uuid: string;
|
||||
type: FlapgIid;
|
||||
f: string;
|
||||
result: unknown;
|
||||
} & ({
|
||||
provider: 'flapg';
|
||||
result: FlapgApiResponse;
|
||||
} | {
|
||||
provider: 'imink';
|
||||
result: IminkFResponse;
|
||||
} | {
|
||||
provider: 'nxapi';
|
||||
url: string;
|
||||
result: AndroidZncaFResponse;
|
||||
});
|
||||
|
||||
function getEnvApi(): FApi {
|
||||
if (process.env.NXAPI_ZNCA_API) {
|
||||
if (process.env.NXAPI_ZNCA_API === 'flapg') {
|
||||
return 'flapg';
|
||||
}
|
||||
if (process.env.NXAPI_ZNCA_API === 'imink') {
|
||||
return 'imink';
|
||||
}
|
||||
|
||||
throw new Error('Unknown znca API provider');
|
||||
}
|
||||
|
||||
if (process.env.ZNCA_API_URL?.startsWith('https://')) {
|
||||
return ['nxapi', process.env.ZNCA_API_URL + '/f'];
|
||||
}
|
||||
|
||||
return 'flapg';
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fetch from 'node-fetch';
|
||||
import { v4 as uuidgen } from 'uuid';
|
||||
import createDebug from 'debug';
|
||||
import { flapg, FlapgIid, genfc } from './f.js';
|
||||
import { f, FlapgIid } from './f.js';
|
||||
import { AccountLogin, AccountToken, Announcements, CurrentUser, CurrentUserPermissions, Event, Friends, GetActiveEventResult, PresencePermissions, User, WebServices, WebServiceToken, ZncResponse, ZncStatus } from './znc-types.js';
|
||||
import { getNintendoAccountToken, getNintendoAccountUser, NintendoAccountUser } from './na.js';
|
||||
import { ErrorResponse } from './util.js';
|
||||
@@ -126,9 +126,7 @@ export default class ZncApi {
|
||||
const timestamp = '' + Math.floor(Date.now() / 1000);
|
||||
|
||||
const useragent = this.useragent ?? undefined;
|
||||
const data = process.env.ZNCA_API_URL ?
|
||||
await genfc(process.env.ZNCA_API_URL + '/f', this.token, timestamp, uuid, FlapgIid.APP, useragent) :
|
||||
await flapg(this.token, timestamp, uuid, FlapgIid.APP, useragent);
|
||||
const data = await f(this.token, timestamp, uuid, FlapgIid.APP, useragent);
|
||||
|
||||
const req = {
|
||||
id,
|
||||
@@ -150,14 +148,12 @@ export default class ZncApi {
|
||||
|
||||
const id_token = nintendoAccountToken.id_token;
|
||||
const useragent = this.useragent ?? undefined;
|
||||
const flapgdata = process.env.ZNCA_API_URL ?
|
||||
await genfc(process.env.ZNCA_API_URL + '/f', id_token, timestamp, uuid, FlapgIid.NSO, useragent) :
|
||||
await flapg(id_token, timestamp, uuid, FlapgIid.NSO, useragent);
|
||||
const fdata = await f(id_token, timestamp, uuid, FlapgIid.NSO, useragent);
|
||||
|
||||
const req = {
|
||||
naBirthday: user.birthday,
|
||||
timestamp,
|
||||
f: flapgdata.f,
|
||||
f: fdata.f,
|
||||
requestId: uuid,
|
||||
naIdToken: id_token,
|
||||
};
|
||||
@@ -169,7 +165,7 @@ export default class ZncApi {
|
||||
timestamp,
|
||||
nintendoAccountToken,
|
||||
// user,
|
||||
flapg: flapgdata,
|
||||
f: fdata,
|
||||
nsoAccount: data.result,
|
||||
credential: data.result.webApiServerCredential,
|
||||
};
|
||||
@@ -203,9 +199,7 @@ export default class ZncApi {
|
||||
const user = await getNintendoAccountUser(nintendoAccountToken);
|
||||
|
||||
const id_token = nintendoAccountToken.id_token;
|
||||
const flapgdata = process.env.ZNCA_API_URL ?
|
||||
await genfc(process.env.ZNCA_API_URL + '/f', id_token, timestamp, uuid, FlapgIid.NSO, useragent ?? undefined) :
|
||||
await flapg(id_token, timestamp, uuid, FlapgIid.NSO, useragent ?? undefined);
|
||||
const fdata = await f(id_token, timestamp, uuid, FlapgIid.NSO, useragent ?? undefined);
|
||||
|
||||
debug('Getting Nintendo Switch Online app token');
|
||||
|
||||
@@ -225,11 +219,12 @@ export default class ZncApi {
|
||||
language: user.language,
|
||||
timestamp,
|
||||
requestId: uuid,
|
||||
f: flapgdata.f,
|
||||
f: fdata.f,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
debug('fetch %s %s, response %s', 'POST', '/v3/Account/Login', response.status);
|
||||
const data = await response.json() as ZncResponse<AccountLogin>;
|
||||
|
||||
if ('errorMessage' in data) {
|
||||
@@ -246,7 +241,7 @@ export default class ZncApi {
|
||||
timestamp,
|
||||
nintendoAccountToken,
|
||||
user,
|
||||
flapg: flapgdata,
|
||||
f: fdata,
|
||||
nsoAccount: data.result,
|
||||
credential: data.result.webApiServerCredential,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user