mirror of
https://github.com/samuelthomas2774/nxapi.git
synced 2026-03-21 18:04:10 -05:00
Coral 3.2.0
This commit is contained in:
parent
e993706671
commit
8cae29d035
|
|
@ -81,6 +81,20 @@ export interface AccountLogin {
|
|||
/** /v3/Account/GetToken, /v3/Extension/Account/GetToken */
|
||||
export type AccountToken = AccountLogin;
|
||||
|
||||
/** /v4/Account/Login */
|
||||
export interface AccountLogin_4 {
|
||||
user: Exclude<CurrentUser, 'links'> & {
|
||||
links: Exclude<CurrentUser['links'], 'nintendoAccount'>;
|
||||
};
|
||||
webApiServerCredential: {
|
||||
accessToken: string;
|
||||
expiresIn: number;
|
||||
};
|
||||
}
|
||||
|
||||
/** /v4/Account/GetToken, /v4/Extension/Account/GetToken */
|
||||
export type AccountToken_4 = AccountLogin_4;
|
||||
|
||||
export interface AccountTokenParameter {
|
||||
naIdToken: string;
|
||||
naBirthday: string;
|
||||
|
|
@ -177,22 +191,38 @@ export interface FriendRoute {
|
|||
userName: string;
|
||||
shopUri: string;
|
||||
imageUri: string;
|
||||
// if not IN_APP all other properties are empty strings
|
||||
// if not IN_APP/NINTENDO_ACCOUNT all other properties are empty strings
|
||||
channel: FriendRouteChannel;
|
||||
}
|
||||
|
||||
export enum FriendRouteChannel {
|
||||
/** Added from friend code lookup on a Switch console or using coral */
|
||||
FRIEND_CODE = 'FRIEND_CODE',
|
||||
/** Added from users you've played with */
|
||||
IN_APP = 'IN_APP',
|
||||
/** Added from search for local users */
|
||||
NX_FACED = 'NX_FACED',
|
||||
/**
|
||||
* Added from users you've played with
|
||||
* Shows the application details (appName, shopUri, imageUri) and in-game name (userName)
|
||||
*/
|
||||
IN_APP = 'IN_APP',
|
||||
/**
|
||||
* Added from friend suggestions for smart device game friends linked to the same Nintendo Account
|
||||
* Shows the client name (FriendRoute.appName)
|
||||
*/
|
||||
NINTENDO_ACCOUNT = 'NINTENDO_ACCOUNT',
|
||||
'3DS' = '3DS',
|
||||
|
||||
// Wii U, Facebook, Twitter suggestions?
|
||||
NNID = 'NNID',
|
||||
TWITTER = 'TWITTER',
|
||||
FACEBOOK = 'FACEBOOK',
|
||||
WECHAT = 'WECHAT',
|
||||
/** Added from GameChat */
|
||||
CAMPUS = 'CAMPUS',
|
||||
}
|
||||
|
||||
export type CreateFriendRequestChannel =
|
||||
FriendRouteChannel.FRIEND_CODE |
|
||||
FriendRouteChannel.CAMPUS;
|
||||
|
||||
export interface Presence {
|
||||
state: PresenceState;
|
||||
/**
|
||||
|
|
@ -624,6 +654,8 @@ export enum FeedbackTopic {
|
|||
// - /v1/Voip/Mute
|
||||
// - /v5/Chat/Show
|
||||
// - /v5/Chat/List
|
||||
// - /v5/Chat/Member/Show
|
||||
// - /v5/Chat/FriendCandidate/List
|
||||
// - /v1/Support/ReportUser
|
||||
//
|
||||
// Also, announcement types other than OPERATION and FRIEND_REQUEST
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { JwtPayload } from '../util/jwt.js';
|
|||
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_4, BlockingUsers, CoralError, CoralResponse, CoralStatus, CoralSuccessResponse, CurrentUser, CurrentUserPermissions, Event, Friend_4, FriendCodeUrl, FriendCodeUser, Friends_4, GetActiveEventResult, ListChat, ListHashtag, ListHashtagParameter, ListMedia, ListMediaParameter, ListPushNotificationSettings, Media, PlayLogPermissions, PresencePermissions, PushNotificationPlayInvitationScope, ReceivedFriendRequest, ReceivedFriendRequests, SentFriendRequests, ShowUserLogin, UpdatePushNotificationSettingsParameter, UpdatePushNotificationSettingsParameterItem, User, UserPlayLog, WebServices_4, WebServiceToken, WebServiceTokenParameter } from './coral-types.js';
|
||||
import { AccountLogin, AccountLogin_4, AccountLoginParameter, AccountToken, AccountToken_4, AccountTokenParameter, Announcements_4, BlockingUsers, CoralError, CoralResponse, CoralStatus, CoralSuccessResponse, CreateFriendRequestChannel, CurrentUser, CurrentUserPermissions, Event, Friend_4, FriendCodeUrl, FriendCodeUser, FriendRouteChannel, Friends_4, GetActiveEventResult, ListChat, ListHashtag, ListHashtagParameter, ListMedia, ListPushNotificationSettings, Media, PlayLogPermissions, PresencePermissions, PushNotificationPlayInvitationScope, ReceivedFriendRequest, ReceivedFriendRequests, SentFriendRequests, ShowUserLogin, UpdatePushNotificationSettingsParameter, UpdatePushNotificationSettingsParameterItem, User, UserPlayLog, WebServices_4, WebServiceToken, WebServiceTokenParameter } from './coral-types.js';
|
||||
import { createZncaApi, DecryptResponseResult, FResult, HashMethod, RequestEncryptionProvider, ZncaApi, ZncaApiNxapi } from './f.js';
|
||||
import { generateAuthData, getNintendoAccountToken, getNintendoAccountUser, NintendoAccountScope, NintendoAccountSessionAuthorisation, NintendoAccountToken, NintendoAccountUser } from './na.js';
|
||||
import { ErrorResponse, ResponseSymbol } from './util.js';
|
||||
|
|
@ -15,9 +15,11 @@ const debug = createDebug('nxapi:api:coral');
|
|||
|
||||
const ZNCA_PLATFORM = 'Android';
|
||||
const ZNCA_PLATFORM_VERSION = '12';
|
||||
export const ZNCA_VERSION = '3.0.2'; // TODO: update to 3.1.0
|
||||
export const ZNCA_VERSION = '3.2.0'; // TODO: update to 3.1.0
|
||||
const ZNCA_USER_AGENT = `com.nintendo.znca/${ZNCA_VERSION}(${ZNCA_PLATFORM}/${ZNCA_PLATFORM_VERSION})`;
|
||||
|
||||
export const ZNCA_API_COMPATIBILITY_VERSION = 'hio87-mJks_e9GNF';
|
||||
|
||||
const ZNC_URL = 'https://api-lp1.znc.srv.nintendo.net';
|
||||
export const ZNCA_CLIENT_ID = '71b963c1b7b6d119';
|
||||
|
||||
|
|
@ -93,9 +95,7 @@ export abstract class AbstractCoralApi {
|
|||
}
|
||||
|
||||
async getMedia() {
|
||||
return this.call<ListMedia, ListMediaParameter>('/v4/Media/List', {
|
||||
count: 100,
|
||||
});
|
||||
return this.call<ListMedia>('/v4/Media/List');
|
||||
}
|
||||
|
||||
async getHashtags(media: Media) {
|
||||
|
|
@ -186,9 +186,10 @@ export abstract class AbstractCoralApi {
|
|||
});
|
||||
}
|
||||
|
||||
async sendFriendRequest(nsa_id: string) {
|
||||
return this.call('/v3/FriendRequest/Create', {
|
||||
async sendFriendRequest(nsa_id: string, channel: CreateFriendRequestChannel = FriendRouteChannel.FRIEND_CODE) {
|
||||
return this.call('/v4/FriendRequest/Create', {
|
||||
nsaId: nsa_id,
|
||||
channel,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -591,7 +592,7 @@ export default class CoralApi extends AbstractCoralApi implements CoralApiInterf
|
|||
const fdata = await provider.genf(nintendoAccountToken.id_token, HashMethod.CORAL, {
|
||||
na_id: user.id, coral_user_id: '' + this[CoralUserIdSymbol],
|
||||
}, provider.supportsEncryption() ? {
|
||||
url: ZNC_URL + '/v3/Account/GetToken',
|
||||
url: ZNC_URL + '/v4/Account/GetToken',
|
||||
parameter,
|
||||
} : undefined);
|
||||
|
||||
|
|
@ -609,13 +610,13 @@ export default class CoralApi extends AbstractCoralApi implements CoralApiInterf
|
|||
});
|
||||
|
||||
if (provider.supportsEncryption()) {
|
||||
const result = await provider.encryptRequest(ZNC_URL + '/v3/Account/GetToken', null, body);
|
||||
const result = await provider.encryptRequest(ZNC_URL + '/v4/Account/GetToken', null, body);
|
||||
|
||||
body = new EncryptedRequestBody(provider, result.data, body);
|
||||
}
|
||||
}
|
||||
|
||||
const data = await this.fetch<AccountToken>('/v3/Account/GetToken', 'POST', body, undefined, {
|
||||
const data = await this.fetch<AccountToken_4>('/v4/Account/GetToken', 'POST', body, undefined, {
|
||||
[RequestFlagAddPlatformSymbol]: true,
|
||||
[RequestFlagAddProductVersionSymbol]: true,
|
||||
[RequestFlagNoAuthenticationSymbol]: true,
|
||||
|
|
@ -719,7 +720,7 @@ export default class CoralApi extends AbstractCoralApi implements CoralApiInterf
|
|||
const fdata = await provider.genf(nintendoAccountToken.id_token, HashMethod.CORAL, {
|
||||
na_id: user.id,
|
||||
}, provider.supportsEncryption() ? {
|
||||
url: ZNC_URL + '/v3/Account/Login',
|
||||
url: ZNC_URL + '/v4/Account/Login',
|
||||
parameter,
|
||||
} : undefined);
|
||||
|
||||
|
|
@ -743,7 +744,7 @@ export default class CoralApi extends AbstractCoralApi implements CoralApiInterf
|
|||
});
|
||||
|
||||
if (provider.supportsEncryption()) {
|
||||
const result = await provider.encryptRequest(ZNC_URL + '/v3/Account/Login', null, body);
|
||||
const result = await provider.encryptRequest(ZNC_URL + '/v4/Account/Login', null, body);
|
||||
|
||||
encrypted = [provider];
|
||||
body = result.data;
|
||||
|
|
@ -759,22 +760,22 @@ export default class CoralApi extends AbstractCoralApi implements CoralApiInterf
|
|||
});
|
||||
|
||||
const [signal, cancel] = timeoutSignal();
|
||||
const response = await fetch(ZNC_URL + '/v3/Account/Login', {
|
||||
const response = await fetch(ZNC_URL + '/v4/Account/Login', {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body,
|
||||
signal,
|
||||
}).finally(cancel);
|
||||
|
||||
debug('fetch %s %s, response %s', 'POST', '/v3/Account/Login', response.status);
|
||||
debug('fetch %s %s, response %s', 'POST', '/v4/Account/Login', response.status);
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw await CoralErrorResponse.fromResponse(response, '[znc] Non-200 status code');
|
||||
}
|
||||
|
||||
const data: CoralResponse<AccountLogin> = encrypted ?
|
||||
const data: CoralResponse<AccountLogin_4> = encrypted ?
|
||||
JSON.parse((await encrypted[0].decryptResponse(new Uint8Array(await response.arrayBuffer()))).data) :
|
||||
await response.json() as CoralResponse<AccountLogin>;
|
||||
await response.json() as CoralResponse<AccountLogin_4>;
|
||||
|
||||
if ('errorMessage' in data) {
|
||||
throw new CoralErrorResponse('[znc] ' + data.errorMessage, response, data);
|
||||
|
|
@ -1048,7 +1049,7 @@ export interface CoralAuthData {
|
|||
nintendoAccountToken: NintendoAccountToken;
|
||||
user: NintendoAccountUserCoral;
|
||||
f: FResult;
|
||||
nsoAccount: AccountLogin;
|
||||
nsoAccount: AccountLogin | AccountLogin_4;
|
||||
credential: AccountLogin['webApiServerCredential'];
|
||||
znca_version: string;
|
||||
znca_useragent: string;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import createDebug from '../util/debug.js';
|
|||
import { timeoutSignal } from '../util/misc.js';
|
||||
import { getUserAgent } from '../util/useragent.js';
|
||||
import { client_assertion_provider, client_auth_provider, ClientAssertionProviderInterface } from '../util/nxapi-auth.js';
|
||||
import { ZNCA_VERSION } from './coral.js';
|
||||
import { ZNCA_API_COMPATIBILITY_VERSION } from './coral.js';
|
||||
import { AccountLoginParameter, AccountTokenParameter, WebServiceTokenParameter } from './coral-types.js';
|
||||
|
||||
const debugFlapg = createDebug('nxapi:api:flapg');
|
||||
|
|
@ -345,6 +345,7 @@ export class ZncaApiNxapi extends ZncaApi implements RequestEncryptionProvider {
|
|||
this.auth = auth;
|
||||
|
||||
this.headers.set('User-Agent', getUserAgent(useragent));
|
||||
this.headers.append('X-znca-Client-Version', ZNCA_API_COMPATIBILITY_VERSION);
|
||||
}
|
||||
|
||||
static create(
|
||||
|
|
@ -384,7 +385,6 @@ export class ZncaApiNxapi extends ZncaApi implements RequestEncryptionProvider {
|
|||
headers.set('Accept', 'application/json');
|
||||
if (this.app?.platform) headers.append('X-znca-Platform', this.app.platform);
|
||||
if (this.app?.version) headers.append('X-znca-Version', this.app.version);
|
||||
if (ZNCA_VERSION) headers.append('X-znca-Client-Version', ZNCA_VERSION);
|
||||
if (this.auth?.token) headers.append('Authorization', 'Bearer ' + this.auth.token.token);
|
||||
|
||||
const [signal, cancel] = timeoutSignal();
|
||||
|
|
@ -450,7 +450,6 @@ export class ZncaApiNxapi extends ZncaApi implements RequestEncryptionProvider {
|
|||
headers.set('Accept', 'application/octet-stream');
|
||||
if (this.app?.platform) headers.append('X-znca-Platform', this.app.platform);
|
||||
if (this.app?.version) headers.append('X-znca-Version', this.app.version);
|
||||
if (ZNCA_VERSION) headers.append('X-znca-Client-Version', ZNCA_VERSION);
|
||||
if (this.auth?.token) headers.append('Authorization', 'Bearer ' + this.auth.token.token);
|
||||
|
||||
const [signal, cancel] = timeoutSignal();
|
||||
|
|
@ -504,7 +503,6 @@ export class ZncaApiNxapi extends ZncaApi implements RequestEncryptionProvider {
|
|||
headers.set('Accept', request_nsa_assertion ? 'application/json' : 'text/plain');
|
||||
if (this.app?.platform) headers.append('X-znca-Platform', this.app.platform);
|
||||
if (this.app?.version) headers.append('X-znca-Version', this.app.version);
|
||||
if (ZNCA_VERSION) headers.append('X-znca-Client-Version', ZNCA_VERSION);
|
||||
if (this.auth?.token) headers.append('Authorization', 'Bearer ' + this.auth.token.token);
|
||||
|
||||
const [signal, cancel] = timeoutSignal();
|
||||
|
|
|
|||
|
|
@ -43,6 +43,6 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
nso.getCurrentUser(),
|
||||
]) : [];
|
||||
|
||||
console.log('Nintendo Account', data.user);
|
||||
console.log('Nintendo Account', data.user, 'naUser' in data.nsoAccount ? data.nsoAccount.naUser : null);
|
||||
console.log('Nintendo Switch user', current_user ?? data.nsoAccount.user);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user