mirror of
https://github.com/samuelthomas2774/nxapi.git
synced 2026-03-21 18:04:10 -05:00
Update config URL and use config data
This commit is contained in:
parent
e8e5a2f5a4
commit
2d52f17022
|
|
@ -1,9 +1,10 @@
|
|||
{
|
||||
"require_version": [],
|
||||
"coral": {
|
||||
"znca_version": "2.1.1"
|
||||
"znca_version": "2.2.0"
|
||||
},
|
||||
"coral_auth": {
|
||||
"default": "flapg",
|
||||
"splatnet2statink": {},
|
||||
"flapg": {},
|
||||
"imink": {}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import json from '@rollup/plugin-json';
|
|||
|
||||
const dir = path.dirname(fileURLToPath(import.meta.url));
|
||||
const pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf-8'));
|
||||
const default_remote_config =
|
||||
JSON.parse(fs.readFileSync(path.join(dir, 'resources', 'common', 'remote-config.json'), 'utf-8'));
|
||||
|
||||
const git = (() => {
|
||||
try {
|
||||
|
|
@ -46,6 +48,7 @@ const replace_options = {
|
|||
'globalThis.__NXAPI_BUNDLE_PKG__': JSON.stringify(pkg),
|
||||
'globalThis.__NXAPI_BUNDLE_GIT__': JSON.stringify(git),
|
||||
'globalThis.__NXAPI_BUNDLE_RELEASE__': JSON.stringify(release),
|
||||
'globalThis.__NXAPI_BUNDLE_DEFAULT_REMOTE_CONFIG__': JSON.stringify(default_remote_config),
|
||||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV ?? 'development'),
|
||||
},
|
||||
preventAssignment: true,
|
||||
|
|
|
|||
|
|
@ -55,6 +55,16 @@ export enum CoralStatus {
|
|||
|
||||
export type CoralResponse<T = unknown> = CoralSuccessResponse<T> | CoralErrorResponse;
|
||||
|
||||
export interface AccountLoginParameter {
|
||||
naIdToken: string;
|
||||
naBirthday: string;
|
||||
naCountry: string;
|
||||
language: string;
|
||||
timestamp: string;
|
||||
requestId: string;
|
||||
f: string;
|
||||
}
|
||||
|
||||
/** /v3/Account/Login */
|
||||
export interface AccountLogin {
|
||||
user: CurrentUser;
|
||||
|
|
@ -71,6 +81,14 @@ export interface AccountLogin {
|
|||
/** /v3/Account/GetToken */
|
||||
export type AccountToken = AccountLogin;
|
||||
|
||||
export interface AccountTokenParameter {
|
||||
naIdToken: string;
|
||||
naBirthday: string;
|
||||
timestamp: string;
|
||||
requestId: string;
|
||||
f: string;
|
||||
}
|
||||
|
||||
/** /v1/Announcement/List */
|
||||
export type Announcements = Announcement[];
|
||||
|
||||
|
|
@ -254,6 +272,16 @@ export interface CurrentUserPermissions {
|
|||
};
|
||||
}
|
||||
|
||||
export interface UpdateCurrentUserPermissionsParameter {
|
||||
permissions: {
|
||||
presence: {
|
||||
toValue: PresencePermissions;
|
||||
fromValue: PresencePermissions;
|
||||
};
|
||||
};
|
||||
etag: string;
|
||||
}
|
||||
|
||||
/** /v2/Game/GetWebServiceToken */
|
||||
export interface WebServiceToken {
|
||||
accessToken: string;
|
||||
|
|
|
|||
115
src/api/coral.ts
115
src/api/coral.ts
|
|
@ -1,9 +1,9 @@
|
|||
import fetch, { Response } from 'node-fetch';
|
||||
import { v4 as uuidgen } from 'uuid';
|
||||
import createDebug from 'debug';
|
||||
import { f, FlapgIid } from './f.js';
|
||||
import { AccountLogin, AccountToken, Announcements, CurrentUser, CurrentUserPermissions, Event, Friends, GetActiveEventResult, PresencePermissions, User, WebServices, WebServiceToken, CoralErrorResponse, CoralResponse, CoralStatus, CoralSuccessResponse, FriendCodeUser, FriendCodeUrl } from './coral-types.js';
|
||||
import { getNintendoAccountToken, getNintendoAccountUser, NintendoAccountUser } from './na.js';
|
||||
import { f, FlapgIid, FResult } 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 { getNintendoAccountToken, getNintendoAccountUser, NintendoAccountToken, NintendoAccountUser } from './na.js';
|
||||
import { ErrorResponse } from './util.js';
|
||||
import { JwtPayload } from '../util/jwt.js';
|
||||
import { getAdditionalUserAgents } from '../util/useragent.js';
|
||||
|
|
@ -26,9 +26,11 @@ export default class CoralApi {
|
|||
/** @internal */
|
||||
_renewToken: Promise<void> | null = null;
|
||||
|
||||
constructor(
|
||||
protected constructor(
|
||||
public token: string,
|
||||
public useragent: string | null = getAdditionalUserAgents()
|
||||
public useragent: string | null = getAdditionalUserAgents(),
|
||||
readonly znca_version = ZNCA_VERSION,
|
||||
readonly znca_useragent = ZNCA_USER_AGENT,
|
||||
) {}
|
||||
|
||||
async fetch<T = unknown>(
|
||||
|
|
@ -44,10 +46,10 @@ export default class CoralApi {
|
|||
method: method,
|
||||
headers: Object.assign({
|
||||
'X-Platform': ZNCA_PLATFORM,
|
||||
'X-ProductVersion': ZNCA_VERSION,
|
||||
'X-ProductVersion': this.znca_version,
|
||||
'Authorization': 'Bearer ' + this.token,
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
'User-Agent': ZNCA_USER_AGENT,
|
||||
'User-Agent': this.znca_useragent,
|
||||
}, headers),
|
||||
body: body,
|
||||
});
|
||||
|
|
@ -185,22 +187,24 @@ export default class CoralApi {
|
|||
return this.call<WebServiceToken>('/v2/Game/GetWebServiceToken', req);
|
||||
}
|
||||
|
||||
async getToken(token: string, user: NintendoAccountUser) {
|
||||
const uuid = uuidgen();
|
||||
const timestamp = '' + Math.floor(Date.now() / 1000);
|
||||
|
||||
async getToken(token: string, user: NintendoAccountUser): Promise<PartialCoralAuthData> {
|
||||
// Nintendo Account token
|
||||
const nintendoAccountToken = await getNintendoAccountToken(token, ZNCA_CLIENT_ID);
|
||||
|
||||
const id_token = nintendoAccountToken.id_token;
|
||||
const fdata = await f(id_token, timestamp, uuid, FlapgIid.NSO, this.useragent ?? getAdditionalUserAgents());
|
||||
const uuid = uuidgen();
|
||||
const timestamp = '' + Math.floor(Date.now() / 1000);
|
||||
|
||||
const req = {
|
||||
const fdata = await f(
|
||||
nintendoAccountToken.id_token, timestamp, uuid,
|
||||
FlapgIid.NSO, this.useragent ?? getAdditionalUserAgents()
|
||||
);
|
||||
|
||||
const req: AccountTokenParameter = {
|
||||
naBirthday: user.birthday,
|
||||
timestamp,
|
||||
f: fdata.f,
|
||||
requestId: uuid,
|
||||
naIdToken: id_token,
|
||||
naIdToken: nintendoAccountToken.id_token,
|
||||
};
|
||||
|
||||
const data = await this.call<AccountToken>('/v3/Account/GetToken', req, false);
|
||||
|
|
@ -216,15 +220,6 @@ export default class CoralApi {
|
|||
};
|
||||
}
|
||||
|
||||
static async createWithSessionToken(token: string, useragent = getAdditionalUserAgents()) {
|
||||
const data = await this.loginWithSessionToken(token, useragent);
|
||||
|
||||
return {
|
||||
nso: new this(data.credential.accessToken, useragent),
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
async renewToken(token: string, user: NintendoAccountUser) {
|
||||
const data = await this.getToken(token, user);
|
||||
|
||||
|
|
@ -233,9 +228,25 @@ export default class CoralApi {
|
|||
return data;
|
||||
}
|
||||
|
||||
static async loginWithSessionToken(token: string, useragent = getAdditionalUserAgents()) {
|
||||
const uuid = uuidgen();
|
||||
const timestamp = '' + Math.floor(Date.now() / 1000);
|
||||
static async createWithSessionToken(token: string, useragent = getAdditionalUserAgents()) {
|
||||
const data = await this.loginWithSessionToken(token, useragent);
|
||||
return {nso: this.createWithSavedToken(data, useragent), data};
|
||||
}
|
||||
|
||||
static createWithSavedToken(data: CoralAuthData, useragent = getAdditionalUserAgents()) {
|
||||
return new this(
|
||||
data.credential.accessToken,
|
||||
useragent,
|
||||
data.znca_version,
|
||||
data.znca_useragent,
|
||||
);
|
||||
}
|
||||
|
||||
static async loginWithSessionToken(token: string, useragent = getAdditionalUserAgents()): Promise<CoralAuthData> {
|
||||
const { default: { coral: config } } = await import('../common/remote-config.js');
|
||||
|
||||
if (!config) throw new Error('Remote configuration prevents Coral authentication');
|
||||
const znca_useragent = `com.nintendo.znca/${config.znca_version}(${ZNCA_PLATFORM}/${ZNCA_PLATFORM_VERSION})`;
|
||||
|
||||
// Nintendo Account token
|
||||
const nintendoAccountToken = await getNintendoAccountToken(token, ZNCA_CLIENT_ID);
|
||||
|
|
@ -243,29 +254,36 @@ export default class CoralApi {
|
|||
// Nintendo Account user data
|
||||
const user = await getNintendoAccountUser(nintendoAccountToken);
|
||||
|
||||
const id_token = nintendoAccountToken.id_token;
|
||||
const fdata = await f(id_token, timestamp, uuid, FlapgIid.NSO, useragent);
|
||||
const uuid = uuidgen();
|
||||
const timestamp = '' + Math.floor(Date.now() / 1000);
|
||||
|
||||
const fdata = await f(
|
||||
nintendoAccountToken.id_token, timestamp, uuid,
|
||||
FlapgIid.NSO, useragent
|
||||
);
|
||||
|
||||
debug('Getting Nintendo Switch Online app token');
|
||||
|
||||
const parameter: AccountLoginParameter = {
|
||||
naIdToken: nintendoAccountToken.id_token,
|
||||
naBirthday: user.birthday,
|
||||
naCountry: user.country,
|
||||
language: user.language,
|
||||
timestamp,
|
||||
requestId: uuid,
|
||||
f: fdata.f,
|
||||
};
|
||||
|
||||
const response = await fetch(ZNC_URL + '/v3/Account/Login', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Platform': ZNCA_PLATFORM,
|
||||
'X-ProductVersion': ZNCA_VERSION,
|
||||
'X-ProductVersion': config.znca_version,
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
'User-Agent': ZNCA_USER_AGENT,
|
||||
'User-Agent': znca_useragent,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
parameter: {
|
||||
naIdToken: nintendoAccountToken.id_token,
|
||||
naBirthday: user.birthday,
|
||||
naCountry: user.country,
|
||||
language: user.language,
|
||||
timestamp,
|
||||
requestId: uuid,
|
||||
f: fdata.f,
|
||||
},
|
||||
parameter,
|
||||
}),
|
||||
});
|
||||
|
||||
|
|
@ -289,10 +307,27 @@ export default class CoralApi {
|
|||
f: fdata,
|
||||
nsoAccount: data.result,
|
||||
credential: data.result.webApiServerCredential,
|
||||
znca_version: config.znca_version,
|
||||
znca_useragent,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export interface CoralAuthData {
|
||||
uuid: string;
|
||||
timestamp: string;
|
||||
nintendoAccountToken: NintendoAccountToken;
|
||||
user: NintendoAccountUser;
|
||||
f: FResult;
|
||||
nsoAccount: AccountLogin;
|
||||
credential: AccountLogin['webApiServerCredential'];
|
||||
znca_version: string;
|
||||
znca_useragent: string;
|
||||
}
|
||||
|
||||
export type PartialCoralAuthData =
|
||||
Pick<CoralAuthData, 'uuid' | 'timestamp' | 'nintendoAccountToken' | 'f' | 'nsoAccount' | 'credential'>;
|
||||
|
||||
export interface CoralJwtPayload extends JwtPayload {
|
||||
isChildRestricted: boolean;
|
||||
membership: {
|
||||
|
|
|
|||
32
src/api/f.ts
32
src/api/f.ts
|
|
@ -23,6 +23,9 @@ export abstract class ZncaApi {
|
|||
//
|
||||
|
||||
export async function getLoginHash(token: string, timestamp: string | number, useragent?: string) {
|
||||
const { default: { coral_auth: { splatnet2statink: config } } } = await import('../common/remote-config.js');
|
||||
if (!config) throw new Error('Remote configuration prevents splatnet2statink API use');
|
||||
|
||||
debugS2s('Getting login hash');
|
||||
|
||||
const [signal, cancel] = timeoutSignal();
|
||||
|
|
@ -61,6 +64,9 @@ export async function flapg(
|
|||
token: string, timestamp: string | number, guid: string, iid: FlapgIid,
|
||||
useragent?: string
|
||||
) {
|
||||
const { default: { coral_auth: { flapg: config } } } = await import('../common/remote-config.js');
|
||||
if (!config) throw new Error('Remote configuration prevents flapg API use');
|
||||
|
||||
const hash = await getLoginHash(token, timestamp, useragent);
|
||||
|
||||
debugFlapg('Getting f parameter', {
|
||||
|
|
@ -129,6 +135,9 @@ export async function iminkf(
|
|||
token: string, timestamp: string | number, uuid: string, hash_method: '1' | '2',
|
||||
useragent?: string
|
||||
) {
|
||||
const { default: { coral_auth: { imink: config } } } = await import('../common/remote-config.js');
|
||||
if (!config) throw new Error('Remote configuration prevents imink API use');
|
||||
|
||||
debugImink('Getting f parameter', {
|
||||
token, timestamp, uuid, hash_method,
|
||||
});
|
||||
|
|
@ -266,7 +275,7 @@ export async function f(
|
|||
token: string, timestamp: string | number, uuid: string, type: FlapgIid,
|
||||
useragent?: string
|
||||
): Promise<FResult> {
|
||||
const provider = getZncaApiFromEnvironment(useragent);
|
||||
const provider = getPreferredZncaApiFromEnvironment(useragent) ?? await getDefaultZncaApi(useragent);
|
||||
|
||||
return provider.genf(token, '' + timestamp, uuid, type);
|
||||
}
|
||||
|
|
@ -291,7 +300,7 @@ export type FResult = {
|
|||
result: AndroidZncaFResponse;
|
||||
});
|
||||
|
||||
export function getZncaApiFromEnvironment(useragent?: string): ZncaApi {
|
||||
export function getPreferredZncaApiFromEnvironment(useragent?: string): ZncaApi | null {
|
||||
if (process.env.NXAPI_ZNCA_API) {
|
||||
if (process.env.NXAPI_ZNCA_API === 'flapg') {
|
||||
return new ZncaApiFlapg(useragent);
|
||||
|
|
@ -307,5 +316,22 @@ export function getZncaApiFromEnvironment(useragent?: string): ZncaApi {
|
|||
return new ZncaApiNxapi(process.env.ZNCA_API_URL, useragent);
|
||||
}
|
||||
|
||||
return new ZncaApiFlapg(useragent);
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function getDefaultZncaApi(useragent?: string) {
|
||||
const { default: { coral_auth: { default: provider } } } = await import('../common/remote-config.js');
|
||||
|
||||
if (provider === 'flapg') {
|
||||
return new ZncaApiFlapg(useragent);
|
||||
}
|
||||
if (provider === 'imink') {
|
||||
return new ZncaApiImink(useragent);
|
||||
}
|
||||
|
||||
if (provider[0] === 'nxapi') {
|
||||
return new ZncaApiNxapi(provider[1], useragent);
|
||||
}
|
||||
|
||||
throw new Error('Invalid znca API provider');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import fetch from 'node-fetch';
|
||||
import createDebug from 'debug';
|
||||
import { getNintendoAccountToken, getNintendoAccountUser } from './na.js';
|
||||
import { getNintendoAccountToken, getNintendoAccountUser, NintendoAccountToken, NintendoAccountUser } from './na.js';
|
||||
import { ErrorResponse } from './util.js';
|
||||
import { DailySummaries, Devices, MonthlySummaries, MonthlySummary, MoonError, ParentalControlSettingState, SmartDevices, User } from './moon-types.js';
|
||||
import { timeoutSignal } from '../util/misc.js';
|
||||
|
|
@ -12,11 +12,16 @@ export const ZNMA_CLIENT_ID = '54789befb391a838';
|
|||
|
||||
const ZNMA_VERSION = '1.17.0';
|
||||
const ZNMA_BUILD = '261';
|
||||
const ZNMA_USER_AGENT = 'moon_ANDROID/' + ZNMA_VERSION + ' (com.nintendo.znma; build:' + ZNMA_BUILD +
|
||||
'; ANDROID 26)';
|
||||
|
||||
export default class MoonApi {
|
||||
constructor(
|
||||
protected constructor(
|
||||
public token: string,
|
||||
public naId: string
|
||||
public naId: string,
|
||||
readonly znma_version = ZNMA_VERSION,
|
||||
readonly znma_build = ZNMA_BUILD,
|
||||
readonly znma_useragent = ZNMA_USER_AGENT,
|
||||
) {}
|
||||
|
||||
async fetch<T = unknown>(url: string, method = 'GET', body?: string, headers?: object) {
|
||||
|
|
@ -34,10 +39,9 @@ export default class MoonApi {
|
|||
'X-Moon-TimeZone': 'Europe/London',
|
||||
'X-Moon-Os-Language': 'en-GB',
|
||||
'X-Moon-App-Language': 'en-GB',
|
||||
'X-Moon-App-Display-Version': ZNMA_VERSION,
|
||||
'X-Moon-App-Internal-Version': ZNMA_BUILD,
|
||||
'User-Agent': 'moon_ANDROID/' + ZNMA_VERSION + ' (com.nintendo.znma; build:' + ZNMA_BUILD +
|
||||
'; ANDROID 26)',
|
||||
'X-Moon-App-Display-Version': this.znma_version,
|
||||
'X-Moon-App-Internal-Version': this.znma_build,
|
||||
'User-Agent': this.znma_useragent,
|
||||
}, headers),
|
||||
body,
|
||||
signal,
|
||||
|
|
@ -82,15 +86,6 @@ export default class MoonApi {
|
|||
return this.fetch<ParentalControlSettingState>('/v1/devices/' + id + '/parental_control_setting_state');
|
||||
}
|
||||
|
||||
static async createWithSessionToken(token: string) {
|
||||
const data = await this.loginWithSessionToken(token);
|
||||
|
||||
return {
|
||||
moon: new this(data.nintendoAccountToken.access_token!, data.user.id),
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
async renewToken(token: string) {
|
||||
const data = await MoonApi.loginWithSessionToken(token);
|
||||
|
||||
|
|
@ -100,7 +95,29 @@ export default class MoonApi {
|
|||
return data;
|
||||
}
|
||||
|
||||
static async loginWithSessionToken(token: string) {
|
||||
static async createWithSessionToken(token: string) {
|
||||
const data = await this.loginWithSessionToken(token);
|
||||
return {moon: this.createWithSavedToken(data), data};
|
||||
}
|
||||
|
||||
static createWithSavedToken(data: MoonAuthData) {
|
||||
return new this(
|
||||
data.nintendoAccountToken.access_token!,
|
||||
data.user.id,
|
||||
data.znma_version,
|
||||
data.znma_build,
|
||||
data.znma_useragent,
|
||||
);
|
||||
}
|
||||
|
||||
static async loginWithSessionToken(token: string): Promise<MoonAuthData> {
|
||||
const { default: { moon: config } } = await import('../common/remote-config.js');
|
||||
|
||||
if (!config) throw new Error('Remote configuration prevents Moon authentication');
|
||||
|
||||
const znma_useragent = 'moon_ANDROID/' + config.znma_version +
|
||||
' (com.nintendo.znma; build:' + config.znma_build + '; ANDROID 26)';
|
||||
|
||||
// Nintendo Account token
|
||||
const nintendoAccountToken = await getNintendoAccountToken(token, ZNMA_CLIENT_ID);
|
||||
|
||||
|
|
@ -110,6 +127,17 @@ export default class MoonApi {
|
|||
return {
|
||||
nintendoAccountToken,
|
||||
user,
|
||||
znma_version: config.znma_version,
|
||||
znma_build: config.znma_build,
|
||||
znma_useragent: znma_useragent,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export interface MoonAuthData {
|
||||
nintendoAccountToken: NintendoAccountToken;
|
||||
user: NintendoAccountUser;
|
||||
znma_version: string;
|
||||
znma_build: string;
|
||||
znma_useragent: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ export default class ZncProxyApi implements CoralApi {
|
|||
/** @internal */
|
||||
_renewToken: Promise<void> | null = null;
|
||||
|
||||
readonly znca_version = '';
|
||||
readonly znca_useragent = '';
|
||||
|
||||
constructor(
|
||||
private url: string,
|
||||
// ZncApi uses the NSO token (valid for a few hours)
|
||||
|
|
|
|||
|
|
@ -1,26 +1,16 @@
|
|||
import createDebug from 'debug';
|
||||
import * as persist from 'node-persist';
|
||||
import { Response } from 'node-fetch';
|
||||
import { FlapgApiResponse, FResult } from '../../api/f.js';
|
||||
import { NintendoAccountSessionTokenJwtPayload, NintendoAccountToken, NintendoAccountUser } from '../../api/na.js';
|
||||
import { NintendoAccountSessionTokenJwtPayload } from '../../api/na.js';
|
||||
import { Jwt } from '../../util/jwt.js';
|
||||
import { AccountLogin, CoralErrorResponse } from '../../api/coral-types.js';
|
||||
import CoralApi, { ZNCA_CLIENT_ID } from '../../api/coral.js';
|
||||
import { CoralErrorResponse } from '../../api/coral-types.js';
|
||||
import CoralApi, { CoralAuthData, ZNCA_CLIENT_ID } from '../../api/coral.js';
|
||||
import ZncProxyApi from '../../api/znc-proxy.js';
|
||||
import { checkUseLimit, SHOULD_LIMIT_USE } from './util.js';
|
||||
|
||||
const debug = createDebug('nxapi:auth:nso');
|
||||
|
||||
export interface SavedToken {
|
||||
uuid: string;
|
||||
timestamp: string;
|
||||
nintendoAccountToken: NintendoAccountToken;
|
||||
user: NintendoAccountUser;
|
||||
f: FResult;
|
||||
flapg?: FlapgApiResponse['result'];
|
||||
nsoAccount: AccountLogin;
|
||||
credential: AccountLogin['webApiServerCredential'];
|
||||
const debug = createDebug('nxapi:auth:coral');
|
||||
|
||||
export interface SavedToken extends CoralAuthData {
|
||||
expires_at: number;
|
||||
proxy_url?: string;
|
||||
}
|
||||
|
|
@ -92,7 +82,7 @@ export async function getToken(
|
|||
|
||||
const nso = proxy_url ?
|
||||
new ZncProxyApi(proxy_url, token) :
|
||||
new CoralApi(existingToken.credential.accessToken);
|
||||
CoralApi.createWithSavedToken(existingToken);
|
||||
|
||||
nso.onTokenExpired = createTokenExpiredHandler(storage, token, nso, existingToken);
|
||||
|
||||
|
|
@ -114,7 +104,7 @@ async function renewToken(
|
|||
const data = await nso.renewToken(token, previousToken.user);
|
||||
|
||||
const existingToken: SavedToken = {
|
||||
user: previousToken.user,
|
||||
...previousToken,
|
||||
...data,
|
||||
expires_at: Date.now() + (data.credential.expiresIn * 1000),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import createDebug from 'debug';
|
||||
import * as persist from 'node-persist';
|
||||
import { ZNMA_CLIENT_ID } from '../../api/moon.js';
|
||||
import { NintendoAccountSessionTokenJwtPayload, NintendoAccountToken, NintendoAccountUser } from '../../api/na.js';
|
||||
import { MoonAuthData, ZNMA_CLIENT_ID } from '../../api/moon.js';
|
||||
import { NintendoAccountSessionTokenJwtPayload } from '../../api/na.js';
|
||||
import { Jwt } from '../../util/jwt.js';
|
||||
import MoonApi from '../../api/moon.js';
|
||||
import { checkUseLimit, LIMIT_REQUESTS, SHOULD_LIMIT_USE } from './util.js';
|
||||
|
|
@ -11,10 +11,7 @@ const debug = createDebug('nxapi:auth:moon');
|
|||
// Higher rate limit for parental controls, as the token expires sooner
|
||||
const LIMIT_PERIOD = 15 * 60 * 1000; // 15 minutes
|
||||
|
||||
export interface SavedMoonToken {
|
||||
nintendoAccountToken: NintendoAccountToken;
|
||||
user: NintendoAccountUser;
|
||||
|
||||
export interface SavedMoonToken extends MoonAuthData {
|
||||
expires_at: number;
|
||||
}
|
||||
|
||||
|
|
@ -66,7 +63,7 @@ export async function getPctlToken(storage: persist.LocalStorage, token: string,
|
|||
await storage.setItem('NintendoAccountToken-pctl.' + existingToken.user.id, token);
|
||||
|
||||
return {
|
||||
moon: new MoonApi(existingToken.nintendoAccountToken.access_token!, existingToken.user.id),
|
||||
moon: MoonApi.createWithSavedToken(existingToken),
|
||||
data: existingToken,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@ export const GITHUB_MIRROR_URL = 'https://github.com/samuelthomas2774/nxapi';
|
|||
export const ISSUES_URL = 'https://github.com/samuelthomas2774/nxapi/issues';
|
||||
export const ZNCA_API_USE_URL = 'https://gitlab.fancy.org.uk/samuel/nxapi#splatnet2statink-and-flapg';
|
||||
export const USER_AGENT_INFO_URL = 'https://gitlab.fancy.org.uk/samuel/nxapi#user-agent-strings';
|
||||
export const CONFIG_URL = 'https://fancy.org.uk/api/nxapi/config';
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ import { ErrorResponse } from '../api/util.js';
|
|||
import { timeoutSignal } from '../util/misc.js';
|
||||
import { getUserAgent } from '../util/useragent.js';
|
||||
import { paths } from '../util/storage.js';
|
||||
import { dev, dir, git, version } from '../util/product.js';
|
||||
import { dev, dir, embedded_default_remote_config, git, version } from '../util/product.js';
|
||||
import { CONFIG_URL } from './constants.js';
|
||||
|
||||
const debug = createDebug('nxapi:remote-config');
|
||||
|
||||
const CONFIG_URL = 'https://nxapi.ta.fancy.org.uk/data/config.json';
|
||||
/** Maximum time in seconds to consider cached data fresh */
|
||||
const MAX_FRESH = 24 * 60 * 60; // 1 day in seconds
|
||||
/** Maximum time in seconds to allow using cached data after it's considered stale */
|
||||
|
|
@ -19,7 +19,8 @@ const MAX_STALE = 24 * 60 * 60; // 1 day in seconds
|
|||
|
||||
const default_config: NxapiRemoteConfig = {
|
||||
require_version: [version],
|
||||
...JSON.parse(await fs.readFile(path.join(dir, 'resources', 'common', 'remote-config.json'), 'utf-8')),
|
||||
...(embedded_default_remote_config ??
|
||||
JSON.parse(await fs.readFile(path.join(dir, 'resources', 'common', 'remote-config.json'), 'utf-8'))),
|
||||
};
|
||||
|
||||
async function loadRemoteConfig() {
|
||||
|
|
@ -46,6 +47,8 @@ async function loadRemoteConfig() {
|
|||
} catch (err) {}
|
||||
|
||||
try {
|
||||
debug('Getting remote config from %s, must revalidate: %s', url, must_revalidate);
|
||||
|
||||
const config = await getRemoteConfig(url, undefined, data ? {
|
||||
previous: data.data,
|
||||
updated_at: new Date(data.updated_at),
|
||||
|
|
@ -95,8 +98,6 @@ async function getRemoteConfig(url: string, useragent?: string, cache?: {
|
|||
updated_at: Date;
|
||||
etag: string | null;
|
||||
}) {
|
||||
debug('Getting remote config from %s', url);
|
||||
|
||||
const [signal, cancel] = timeoutSignal();
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
|
|
@ -159,7 +160,7 @@ export enum RemoteConfigMode {
|
|||
}
|
||||
|
||||
export const mode =
|
||||
process.env.NXAPI_ENABLE_REMOTE_CONFIG !== '1' ? RemoteConfigMode.DISABLE :
|
||||
process.env.NXAPI_ENABLE_REMOTE_CONFIG === '0' ? RemoteConfigMode.DISABLE :
|
||||
process.env.NXAPI_REMOTE_CONFIG_FALLBACK === '1' ? RemoteConfigMode.OPPORTUNISTIC :
|
||||
RemoteConfigMode.REQUIRE;
|
||||
|
||||
|
|
@ -176,6 +177,8 @@ if (cache && !config.require_version.includes(version)) {
|
|||
|
||||
export default config;
|
||||
|
||||
debug('using config', RemoteConfigMode[mode], config);
|
||||
|
||||
export interface RemoteConfigCacheData {
|
||||
created_at: number;
|
||||
updated_at: number;
|
||||
|
|
@ -200,6 +203,7 @@ export interface NxapiRemoteConfig {
|
|||
// If null the API should not be used
|
||||
coral: CoralRemoteConfig | null;
|
||||
coral_auth: {
|
||||
default: DefaultZncaApiProvider;
|
||||
splatnet2statink: {} | null;
|
||||
flapg: {} | null;
|
||||
imink: {} | null;
|
||||
|
|
@ -207,6 +211,11 @@ export interface NxapiRemoteConfig {
|
|||
moon: MoonRemoteConfig | null;
|
||||
}
|
||||
|
||||
export type DefaultZncaApiProvider =
|
||||
'flapg' |
|
||||
'imink' |
|
||||
['nxapi', string];
|
||||
|
||||
export interface CoralRemoteConfig {
|
||||
znca_version: string; // '2.1.1'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
export { default } from '../api/coral.js';
|
||||
export {
|
||||
default,
|
||||
CoralAuthData,
|
||||
PartialCoralAuthData,
|
||||
} from '../api/coral.js';
|
||||
|
||||
export * from '../api/coral-types.js';
|
||||
|
||||
export { default as ZncProxyApi } from '../api/znc-proxy.js';
|
||||
|
||||
export {
|
||||
ZncaApi,
|
||||
getZncaApiFromEnvironment,
|
||||
getPreferredZncaApiFromEnvironment,
|
||||
getDefaultZncaApi,
|
||||
f,
|
||||
|
||||
ZncaApiFlapg,
|
||||
|
|
|
|||
|
|
@ -1,2 +1,6 @@
|
|||
export { default } from '../api/moon.js';
|
||||
export {
|
||||
default,
|
||||
MoonAuthData,
|
||||
} from '../api/moon.js';
|
||||
|
||||
export * from '../api/moon-types.js';
|
||||
|
|
|
|||
|
|
@ -23,11 +23,13 @@ declare global {
|
|||
changed_files: string[];
|
||||
} | null | undefined;
|
||||
var __NXAPI_BUNDLE_RELEASE__: string | null | undefined;
|
||||
var __NXAPI_BUNDLE_DEFAULT_REMOTE_CONFIG__: any | undefined;
|
||||
}
|
||||
|
||||
const embedded_pkg = globalThis.__NXAPI_BUNDLE_PKG__;
|
||||
const embedded_git = globalThis.__NXAPI_BUNDLE_GIT__;
|
||||
const embedded_release = globalThis.__NXAPI_BUNDLE_RELEASE__;
|
||||
export const embedded_default_remote_config = globalThis.__NXAPI_BUNDLE_DEFAULT_REMOTE_CONFIG__;
|
||||
|
||||
//
|
||||
// Package/version info
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user