mirror of
https://github.com/samuelthomas2774/nxapi.git
synced 2026-09-06 18:45:05 -05:00
Fix web service ID type in token request, handle errors requesting a new token
This commit is contained in:
@@ -205,7 +205,7 @@ export default class CoralApi {
|
||||
});
|
||||
}
|
||||
|
||||
async getWebServiceToken(id: string) {
|
||||
async getWebServiceToken(id: number) {
|
||||
const data = await f(this.token, HashMethod.WEB_SERVICE, this.useragent ?? getAdditionalUserAgents());
|
||||
|
||||
const req = {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { timeoutSignal } from '../util/misc.js';
|
||||
|
||||
const debug = createDebug('nxapi:api:nooklink');
|
||||
|
||||
export const NOOKLINK_WEBSERVICE_ID = '4953919198265344';
|
||||
export const NOOKLINK_WEBSERVICE_ID = 4953919198265344;
|
||||
export const NOOKLINK_WEBSERVICE_URL = 'https://web.sd.lp1.acbaa.srv.nintendo.net';
|
||||
export const NOOKLINK_WEBSERVICE_USERAGENT = 'Mozilla/5.0 (Linux; Android 8.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/58.0.3029.125 Mobile Safari/537.36';
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import { toSeasonId, Rule as XPowerRankingRule, Season } from './splatnet2-xrank
|
||||
|
||||
const debug = createDebug('nxapi:api:splatnet2');
|
||||
|
||||
export const SPLATNET2_WEBSERVICE_ID = '5741031244955648';
|
||||
export const SPLATNET2_WEBSERVICE_ID = 5741031244955648;
|
||||
export const SPLATNET2_WEBSERVICE_URL = 'https://app.splatoon2.nintendo.net/';
|
||||
export const SPLATNET2_WEBSERVICE_USERAGENT = 'Mozilla/5.0 (Linux; Android 8.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/58.0.3029.125 Mobile Safari/537.36';
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { BankaraBattleHistoriesResult, BattleHistoryCurrentPlayerResult, BulletT
|
||||
|
||||
const debug = createDebug('nxapi:api:splatnet3');
|
||||
|
||||
export const SPLATNET3_WEBSERVICE_ID = '4834290508791808';
|
||||
export const SPLATNET3_WEBSERVICE_ID = 4834290508791808;
|
||||
export const SPLATNET3_WEBSERVICE_URL = 'https://api.lp1.av5ja.srv.nintendo.net';
|
||||
export const SPLATNET3_WEBSERVICE_USERAGENT = 'Mozilla/5.0 (Linux; Android 8.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/58.0.3029.125 Mobile Safari/537.36';
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ export default class ZncProxyApi implements CoralApi {
|
||||
throw new Error('Not supported in ZncProxyApi');
|
||||
}
|
||||
|
||||
async getWebServiceToken(id: string) {
|
||||
async getWebServiceToken(id: number) {
|
||||
const result = await this.fetch<{token: WebServiceToken}>('/webservice/' + id + '/token');
|
||||
return createResult(result, result.token);
|
||||
}
|
||||
|
||||
@@ -64,9 +64,8 @@ export function setupIpc(appinstance: App, ipcMain: IpcMain) {
|
||||
store.users.get(token).then(u => openWebService(store, token, u.nso, u.data, webservice, qs)
|
||||
.catch(err => dialog.showMessageBox(BrowserWindow.fromWebContents(e.sender)!, {
|
||||
type: 'error',
|
||||
title: (err instanceof Error ? err.name : 'Error') + ' opening web service',
|
||||
message: err.message,
|
||||
detail: (err instanceof Error ? err.stack ?? '' : err) + '\n\n' + util.inspect({
|
||||
message: (err instanceof Error ? err.name : 'Error') + ' opening web service',
|
||||
detail: (err instanceof Error ? err.stack ?? err.message : err) + '\n\n' + util.inspect({
|
||||
webservice: {
|
||||
id: webservice.id,
|
||||
name: webservice.name,
|
||||
|
||||
@@ -2,8 +2,9 @@ import * as path from 'node:path';
|
||||
import { constants } from 'node:fs';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import { Buffer } from 'node:buffer';
|
||||
import * as util from 'node:util';
|
||||
import createDebug from 'debug';
|
||||
import { app, BrowserWindow, dialog, IpcMainInvokeEvent, Menu, MenuItem, nativeTheme, ShareMenu, shell, WebContents } from './electron.js';
|
||||
import { app, BrowserWindow, dialog, IpcMainInvokeEvent, nativeTheme, ShareMenu, shell, WebContents } from './electron.js';
|
||||
import fetch from 'node-fetch';
|
||||
import CoralApi from '../../api/coral.js';
|
||||
import { dev } from '../../util/product.js';
|
||||
@@ -76,7 +77,7 @@ export default async function openWebService(
|
||||
return {action: 'deny'};
|
||||
});
|
||||
|
||||
const webserviceToken = await nso.getWebServiceToken('' + webservice.id);
|
||||
const webserviceToken = await nso.getWebServiceToken(webservice.id);
|
||||
|
||||
const url = new URL(webservice.uri);
|
||||
url.search = new URLSearchParams({
|
||||
@@ -277,13 +278,43 @@ export class WebServiceIpc {
|
||||
}
|
||||
|
||||
async requestGameWebToken(event: IpcMainInvokeEvent): Promise<string> {
|
||||
const {nso, nsoAccount, webservice} = this.getWindowData(event.sender);
|
||||
const {nso, user, nsoAccount, webservice} = this.getWindowData(event.sender);
|
||||
|
||||
debug('Web service %s, user %s, called requestGameWebToken', webservice.name, nsoAccount.user.name);
|
||||
|
||||
const webserviceToken = await nso.getWebServiceToken('' + webservice.id);
|
||||
try {
|
||||
const webserviceToken = await nso.getWebServiceToken(webservice.id);
|
||||
|
||||
return webserviceToken.accessToken;
|
||||
return webserviceToken.accessToken;
|
||||
} catch (err) {
|
||||
const window = BrowserWindow.fromWebContents(event.sender)!;
|
||||
|
||||
const result = await dialog.showMessageBox(window, {
|
||||
type: 'error',
|
||||
message: (err instanceof Error ? err.name : 'Error') + ' requesting web service token',
|
||||
detail: (err instanceof Error ? err.stack ?? err.message : err) + '\n\n' + util.inspect({
|
||||
webservice: {
|
||||
id: webservice.id,
|
||||
name: webservice.name,
|
||||
uri: webservice.uri,
|
||||
},
|
||||
user_na_id: user.id,
|
||||
user_nsa_id: nsoAccount.user.nsaId,
|
||||
user_coral_id: nsoAccount.user.id,
|
||||
}, {compact: true}),
|
||||
buttons: ['Retry', 'Close ' + webservice.name, 'Ignore'],
|
||||
});
|
||||
|
||||
if (result.response === 0) {
|
||||
return this.requestGameWebToken(event);
|
||||
}
|
||||
if (result.response === 1) {
|
||||
window.close();
|
||||
throw new Error('Error requesting web service token, closing web service');
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async restorePersistentData(event: IpcMainInvokeEvent): Promise<string | undefined> {
|
||||
|
||||
@@ -43,14 +43,18 @@ declare global {
|
||||
|
||||
// Unused
|
||||
sendMessage?(data: string): void;
|
||||
// Unused
|
||||
// SplatNet 3
|
||||
copyToClipboard?(data: string): void;
|
||||
|
||||
// SplatNet 3
|
||||
openQRCodeReaderForCheckin?(data: string): void;
|
||||
onQRCodeReadForCheckin?(data: string): void;
|
||||
// SplatNet 3
|
||||
downloadImages?(imagesJson: string): void;
|
||||
// SplatNet 3
|
||||
completeLoading?(): void;
|
||||
// SplatNet 3
|
||||
closeWebView?(): void;
|
||||
// SplatNet 3
|
||||
reloadExtension?(): void;
|
||||
}
|
||||
}
|
||||
@@ -58,8 +62,6 @@ declare global {
|
||||
//
|
||||
// Share
|
||||
//
|
||||
// Used by SplatNet 2 and Smash World (but both have a different implementation because Nintendo)
|
||||
//
|
||||
|
||||
export interface NativeShareRequest {
|
||||
text: string;
|
||||
@@ -90,14 +92,14 @@ window.invokeNativeShareUrl = invokeNativeShareUrl;
|
||||
//
|
||||
// Web service token
|
||||
//
|
||||
// Used by NookLink
|
||||
//
|
||||
|
||||
function requestGameWebToken() {
|
||||
debug('requestGameWebToken called');
|
||||
|
||||
ipc.requestGameWebToken().then(token => {
|
||||
window.onGameWebTokenReceive?.call(null, token);
|
||||
}).catch(async err => {
|
||||
debug('Error requesting web service token', err);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -106,8 +108,6 @@ window.requestGameWebToken = requestGameWebToken;
|
||||
//
|
||||
// Persistent data
|
||||
//
|
||||
// Used by NookLink
|
||||
//
|
||||
|
||||
function restorePersistentData() {
|
||||
debug('restorePersistentData called');
|
||||
@@ -131,8 +131,6 @@ window.storePersistentData = storePersistentData;
|
||||
//
|
||||
// QR code scanner
|
||||
//
|
||||
// Used by NookLink
|
||||
//
|
||||
|
||||
function openQrCodeReader(data: string) {
|
||||
debug('openQRCodeReader called', data);
|
||||
@@ -179,14 +177,16 @@ window.openQRCodeReaderForCheckin = openQRCodeReaderForCheckin;
|
||||
|
||||
function sendMessage(data: string) {
|
||||
//
|
||||
debug('sendMessage called', data);
|
||||
}
|
||||
|
||||
function copyToClipboard(data: string) {
|
||||
//
|
||||
debug('copyToClipboard called', data);
|
||||
}
|
||||
|
||||
function downloadImages(imagesJson: string) {
|
||||
//
|
||||
debug('downloadImages called', imagesJson);
|
||||
}
|
||||
|
||||
function completeLoading() {
|
||||
@@ -198,7 +198,7 @@ function closeWebView() {
|
||||
}
|
||||
|
||||
function reloadExtension() {
|
||||
//
|
||||
debug('reloadExtension called');
|
||||
}
|
||||
|
||||
window.sendMessage = sendMessage;
|
||||
|
||||
@@ -627,7 +627,7 @@ function createApp(
|
||||
|
||||
app.get('/api/znc/webservice/:id/token', nsoAuth, async (req, res) => {
|
||||
try {
|
||||
const token = await req.znc!.getWebServiceToken(req.params.id);
|
||||
const token = await req.znc!.getWebServiceToken(parseInt(req.params.id));
|
||||
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({token}));
|
||||
|
||||
@@ -61,7 +61,7 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
||||
if (!active) throw new Error('Nintendo Switch Online membership required');
|
||||
}
|
||||
|
||||
const webserviceToken = await nso.getWebServiceToken(argv.id);
|
||||
const webserviceToken = await nso.getWebServiceToken(webservice.id);
|
||||
|
||||
// https://app.splatoon2.nintendo.net/?lang=en-GB&na_country=GB&na_lang=en-GB
|
||||
const url = new URL(webservice.uri);
|
||||
|
||||
Reference in New Issue
Block a user