mirror of
https://github.com/samuelthomas2774/nxapi.git
synced 2026-03-21 18:04:10 -05:00
Merge branch 'main' into i18n
# Conflicts: # src/app/main/index.ts # src/app/main/ipc.ts # src/app/main/menu.ts # src/app/main/monitor.ts # src/app/main/webservices.ts
This commit is contained in:
commit
79e0a5516f
15
README.md
15
README.md
|
|
@ -212,6 +212,18 @@ DEBUG=nxapi:api:* nxapi ...
|
|||
DEBUG=* nxapi ...
|
||||
```
|
||||
|
||||
By default all nxapi logs will be written to a platform-specific location:
|
||||
|
||||
Platform | Log path
|
||||
----------------|----------------
|
||||
macOS | `Library/Logs/nxapi-nodejs`
|
||||
Windows | `%localappdata%\nxapi-nodejs\Log`
|
||||
Linux | `$XDG_STATE_HOME/nxapi-nodejs` or `.local/state/nxapi-nodejs`
|
||||
|
||||
This only applies to the command line and Electron app and can be disabled by setting `NXAPI_DEBUG_FILE` to `0`. Each process writes to a new file. nxapi will automatically delete log files older than 14 days.
|
||||
|
||||
nxapi logs may contain sensitive information such as Nintendo Account access tokens.
|
||||
|
||||
#### Environment variables
|
||||
|
||||
Some options can be set using environment variables. These can be stored in a `.env` file in the data location. Environment variables will be read from the `.env` file in the default location, then the `.env` file in `NXAPI_DATA_PATH` location. `.env` files will not be read from the location set in the `--data-path` option.
|
||||
|
|
@ -234,6 +246,7 @@ Environment variable | Description
|
|||
`NXAPI_SPLATNET3_UPGRADE_QUERIES` | Sets when the SplatNet 3 client is allowed to upgrade persisted query IDs to newer versions. If `0` queries are never upgraded (not recommended). If `1` queries are upgraded if they do not contain potentially breaking changes (not recommended, as like `0` this allows older queries to be sent to the API). If `2` queries are upgraded, requests that would include breaking changes are rejected. If `3` all queries are upgraded, even if they contain potentially breaking changes (default).
|
||||
`NXAPI_SPLATNET3_STRICT` | Disables strict handling of errors from the SplatNet 3 GraphQL API if set to `0`. If set to `1` (default) requests will be rejected if the response includes any errors, even if the response includes a result.
|
||||
`DEBUG` | Used by the [debug](https://github.com/debug-js/debug) package. Sets which modules should have debug logging enabled. See [debug logs](#debug-logs).
|
||||
`NXAPI_DEBUG_FILE` | Disables writing debug logs to a file if set to `0`.
|
||||
|
||||
Other environment variables may also be used by Node.js, Electron or other packages nxapi depends on.
|
||||
|
||||
|
|
@ -302,7 +315,7 @@ The reason Nintendo added this is probably to try and stop people automating acc
|
|||
- Nintendo Switch Online app API docs
|
||||
- https://github.com/ZekeSnider/NintendoSwitchRESTAPI
|
||||
- https://dev.to/mathewthe2/intro-to-nintendo-switch-rest-api-2cm7
|
||||
- nxapi includes TypeScript definitions of all API resources and JSON Web Token payloads at [src/api](src/api)
|
||||
- nxapi includes TypeScript definitions for all API resources and JSON Web Token payloads at [src/api](src/api)
|
||||
- Coral client authentication (`f` parameter)
|
||||
- https://github.com/samuelthomas2774/nxapi/discussions/10
|
||||
- ~~https://github.com/frozenpandaman/splatnet2statink/wiki/api-docs - splatnet2statink and flapg API docs~~
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import createDebug from 'debug';
|
||||
|
||||
createDebug.log = console.warn.bind(console);
|
||||
|
||||
import('../dist/cli.js').then(cli => cli.main.call(null));
|
||||
import('../dist/cli-entry.js');
|
||||
|
|
|
|||
14
package-lock.json
generated
14
package-lock.json
generated
|
|
@ -23,7 +23,7 @@
|
|||
"node-notifier": "^10.0.1",
|
||||
"node-persist": "^3.1.0",
|
||||
"read": "^1.0.7",
|
||||
"splatnet3-types": "^0.2.20230227204004",
|
||||
"splatnet3-types": "^0.2.20230601143335",
|
||||
"supports-color": "^8.1.1",
|
||||
"tslib": "^2.4.1",
|
||||
"uuid": "^8.3.2",
|
||||
|
|
@ -4115,9 +4115,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/splatnet3-types": {
|
||||
"version": "0.2.20230227204004",
|
||||
"resolved": "https://registry.npmjs.org/splatnet3-types/-/splatnet3-types-0.2.20230227204004.tgz",
|
||||
"integrity": "sha512-FAY6pbUcrp5O8c49BNXSKxoyM3UlCrRx2AtA9Y3qlvqOLdHqwxtzcdzbk1b1hRam8ZcrxRzE/ii6ESRiPIAnZw=="
|
||||
"version": "0.2.20230601143335",
|
||||
"resolved": "https://registry.npmjs.org/splatnet3-types/-/splatnet3-types-0.2.20230601143335.tgz",
|
||||
"integrity": "sha512-gZO2DUohuPhhPhwJrEcOR07fYgAvA42ZuXEvaw3x7c5LQzjNzgjkwOQNnpHAMZcE6lIfT2L45v8cjfyu8VcBgA=="
|
||||
},
|
||||
"node_modules/sprintf-js": {
|
||||
"version": "1.1.2",
|
||||
|
|
@ -7861,9 +7861,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"splatnet3-types": {
|
||||
"version": "0.2.20230227204004",
|
||||
"resolved": "https://registry.npmjs.org/splatnet3-types/-/splatnet3-types-0.2.20230227204004.tgz",
|
||||
"integrity": "sha512-FAY6pbUcrp5O8c49BNXSKxoyM3UlCrRx2AtA9Y3qlvqOLdHqwxtzcdzbk1b1hRam8ZcrxRzE/ii6ESRiPIAnZw=="
|
||||
"version": "0.2.20230601143335",
|
||||
"resolved": "https://registry.npmjs.org/splatnet3-types/-/splatnet3-types-0.2.20230601143335.tgz",
|
||||
"integrity": "sha512-gZO2DUohuPhhPhwJrEcOR07fYgAvA42ZuXEvaw3x7c5LQzjNzgjkwOQNnpHAMZcE6lIfT2L45v8cjfyu8VcBgA=="
|
||||
},
|
||||
"sprintf-js": {
|
||||
"version": "1.1.2",
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
"node-notifier": "^10.0.1",
|
||||
"node-persist": "^3.1.0",
|
||||
"read": "^1.0.7",
|
||||
"splatnet3-types": "^0.2.20230227204004",
|
||||
"splatnet3-types": "^0.2.20230601143335",
|
||||
"supports-color": "^8.1.1",
|
||||
"tslib": "^2.4.1",
|
||||
"uuid": "^8.3.2",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"require_version": [],
|
||||
"coral": {
|
||||
"znca_version": "2.5.0"
|
||||
"znca_version": "2.5.1"
|
||||
},
|
||||
"coral_auth": {
|
||||
"default": "imink",
|
||||
|
|
@ -17,8 +17,8 @@
|
|||
"blanco_version": "2.1.1"
|
||||
},
|
||||
"coral_gws_splatnet3": {
|
||||
"app_ver": "3.0.0-0742bda0",
|
||||
"version": "3.0.0",
|
||||
"revision": "0742bda0f28edfcda33ec743b8afc4a95700e27d"
|
||||
"app_ver": "4.0.0-e2ee936d",
|
||||
"version": "4.0.0",
|
||||
"revision": "e2ee936dbecad1fd8582c2a35c2603c63767263f"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,4 +2,9 @@
|
|||
|
||||
mkdir -p /data/android
|
||||
|
||||
# Logs will be captured by Docker if enabled
|
||||
# This is set here so that running another process with `docker exec` (which
|
||||
# doesn't capture logs) will still write to a file by default
|
||||
export NXAPI_DEBUG_FILE=0
|
||||
|
||||
exec /app/bin/nxapi.js --data-path /data "$@"
|
||||
|
|
|
|||
|
|
@ -65,13 +65,14 @@ const watch = {
|
|||
* @type {import('rollup').RollupOptions}
|
||||
*/
|
||||
const main = {
|
||||
input: ['dist/cli-entry.js', 'dist/app/main/index.js'],
|
||||
input: ['dist/cli-entry.js', 'dist/app/app-init.js', 'dist/app/main/index.js'],
|
||||
output: {
|
||||
dir: 'dist/bundle',
|
||||
format: 'es',
|
||||
sourcemap: true,
|
||||
entryFileNames: chunk => {
|
||||
if (chunk.name === 'cli-entry') return 'cli-bundle.js';
|
||||
if (chunk.name === 'app-init') return 'app-init-bundle.js';
|
||||
if (chunk.name === 'index') return 'app-main-bundle.js';
|
||||
return 'entry-' + chunk.name + '.js';
|
||||
},
|
||||
|
|
@ -124,6 +125,7 @@ const app_entry = {
|
|||
include: ['dist/app/app-entry.cjs'],
|
||||
values: {
|
||||
'__NXAPI_BUNDLE_APP_MAIN__': JSON.stringify('./app-main-bundle.js'),
|
||||
'__NXAPI_BUNDLE_APP_INIT__': JSON.stringify('./app-init-bundle.js'),
|
||||
},
|
||||
preventAssignment: true,
|
||||
}),
|
||||
|
|
@ -142,6 +144,8 @@ const app_entry = {
|
|||
external: [
|
||||
'electron',
|
||||
path.resolve(__dirname, 'dist/app/app-main-bundle.js'),
|
||||
path.resolve(__dirname, 'dist/app/app-init-bundle.js'),
|
||||
path.resolve(__dirname, 'dist/app/app-init.js'),
|
||||
path.resolve(__dirname, 'dist/app/main/index.js'),
|
||||
],
|
||||
watch,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import fetch, { Response } from 'node-fetch';
|
||||
import { v4 as uuidgen } from 'uuid';
|
||||
import createDebug from 'debug';
|
||||
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, WebServiceTokenParameter } from './coral-types.js';
|
||||
import { getNintendoAccountToken, getNintendoAccountUser, NintendoAccountToken, NintendoAccountUser } from './na.js';
|
||||
import { ErrorResponse, ResponseSymbol } from './util.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { JwtPayload } from '../util/jwt.js';
|
||||
import { getAdditionalUserAgents } from '../util/useragent.js';
|
||||
import { timeoutSignal } from '../util/misc.js';
|
||||
|
|
@ -41,13 +41,17 @@ export interface ResultData<T> {
|
|||
}
|
||||
|
||||
export default class CoralApi {
|
||||
onTokenExpired: ((data: CoralErrorResponse, res: Response) => Promise<CoralAuthData | void>) | null = null;
|
||||
onTokenExpired: ((data?: CoralErrorResponse, res?: Response) => Promise<CoralAuthData | void>) | null = null;
|
||||
/** @internal */
|
||||
_renewToken: Promise<void> | null = null;
|
||||
/** @internal */
|
||||
_token_expired = false;
|
||||
|
||||
protected constructor(
|
||||
public token: string,
|
||||
public useragent: string | null = getAdditionalUserAgents(),
|
||||
public coral_user_id: string,
|
||||
public na_id: string,
|
||||
readonly znca_version = ZNCA_VERSION,
|
||||
readonly znca_useragent = ZNCA_USER_AGENT,
|
||||
) {}
|
||||
|
|
@ -55,8 +59,18 @@ export default class CoralApi {
|
|||
async fetch<T = unknown>(
|
||||
url: string, method = 'GET', body?: string, headers?: object,
|
||||
/** @internal */ _autoRenewToken = true,
|
||||
/** @internal */ _attempt = 0
|
||||
/** @internal */ _attempt = 0,
|
||||
): Promise<Result<T>> {
|
||||
if (this._token_expired && _autoRenewToken && !this._renewToken) {
|
||||
if (!this.onTokenExpired || _attempt) throw new Error('Token expired');
|
||||
|
||||
this._renewToken = this.onTokenExpired.call(null).then(data => {
|
||||
if (data) this.setTokenWithSavedToken(data);
|
||||
}).finally(() => {
|
||||
this._renewToken = null;
|
||||
});
|
||||
}
|
||||
|
||||
if (this._renewToken && _autoRenewToken) {
|
||||
await this._renewToken;
|
||||
}
|
||||
|
|
@ -84,6 +98,7 @@ export default class CoralApi {
|
|||
const data = await response.json() as CoralResponse<T>;
|
||||
|
||||
if (data.status === CoralStatus.TOKEN_EXPIRED && _autoRenewToken && !_attempt && this.onTokenExpired) {
|
||||
this._token_expired = true;
|
||||
// _renewToken will be awaited when calling fetch
|
||||
this._renewToken = this._renewToken ?? this.onTokenExpired.call(null, data, response).then(data => {
|
||||
if (data) this.setTokenWithSavedToken(data);
|
||||
|
|
@ -214,6 +229,7 @@ export default class CoralApi {
|
|||
platform: ZNCA_PLATFORM,
|
||||
version: this.znca_version,
|
||||
useragent: this.useragent ?? getAdditionalUserAgents(),
|
||||
user: {na_id: this.na_id, coral_user_id: this.coral_user_id},
|
||||
});
|
||||
|
||||
const req: WebServiceTokenParameter = {
|
||||
|
|
@ -250,6 +266,7 @@ export default class CoralApi {
|
|||
platform: ZNCA_PLATFORM,
|
||||
version: this.znca_version,
|
||||
useragent: this.useragent ?? getAdditionalUserAgents(),
|
||||
user: {na_id: user.id, coral_user_id: this.coral_user_id},
|
||||
});
|
||||
|
||||
const req: AccountTokenParameter = {
|
||||
|
|
@ -280,6 +297,9 @@ export default class CoralApi {
|
|||
/** @private */
|
||||
setTokenWithSavedToken(data: CoralAuthData | PartialCoralAuthData) {
|
||||
this.token = data.credential.accessToken;
|
||||
this.coral_user_id = '' + data.nsoAccount.user.id;
|
||||
if ('user' in data) this.na_id = data.user.id;
|
||||
this._token_expired = false;
|
||||
}
|
||||
|
||||
static async createWithSessionToken(token: string, useragent = getAdditionalUserAgents()) {
|
||||
|
|
@ -299,6 +319,8 @@ export default class CoralApi {
|
|||
return new this(
|
||||
data.credential.accessToken,
|
||||
useragent,
|
||||
'' + data.nsoAccount.user.id,
|
||||
data.user.id,
|
||||
data.znca_version,
|
||||
data.znca_useragent,
|
||||
);
|
||||
|
|
@ -320,7 +342,7 @@ export default class CoralApi {
|
|||
static async loginWithNintendoAccountToken(
|
||||
nintendoAccountToken: NintendoAccountToken,
|
||||
user: NintendoAccountUser,
|
||||
useragent = getAdditionalUserAgents()
|
||||
useragent = getAdditionalUserAgents(),
|
||||
) {
|
||||
const { default: { coral: config } } = await import('../common/remote-config.js');
|
||||
|
||||
|
|
@ -331,6 +353,7 @@ export default class CoralApi {
|
|||
platform: ZNCA_PLATFORM,
|
||||
version: config.znca_version,
|
||||
useragent,
|
||||
user: {na_id: user.id},
|
||||
});
|
||||
|
||||
debug('Getting Nintendo Switch Online app token');
|
||||
|
|
|
|||
87
src/api/f.ts
87
src/api/f.ts
|
|
@ -1,12 +1,11 @@
|
|||
import process from 'node:process';
|
||||
import fetch, { Headers } from 'node-fetch';
|
||||
import createDebug from 'debug';
|
||||
import { v4 as uuidgen } from 'uuid';
|
||||
import { defineResponse, ErrorResponse } from './util.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { timeoutSignal } from '../util/misc.js';
|
||||
import { getUserAgent } from '../util/useragent.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');
|
||||
|
|
@ -16,7 +15,10 @@ export abstract class ZncaApi {
|
|||
public useragent?: string
|
||||
) {}
|
||||
|
||||
abstract genf(token: string, hash_method: HashMethod): Promise<FResult>;
|
||||
abstract genf(
|
||||
token: string, hash_method: HashMethod,
|
||||
user?: {na_id: string; coral_user_id?: string;},
|
||||
): Promise<FResult>;
|
||||
}
|
||||
|
||||
export enum HashMethod {
|
||||
|
|
@ -28,49 +30,6 @@ export enum HashMethod {
|
|||
// flapg
|
||||
//
|
||||
|
||||
/** @deprecated The flapg API no longer requires client authentication */
|
||||
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();
|
||||
const response = await fetch('https://elifessler.com/s2s/api/gen2', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'User-Agent': getUserAgent(useragent),
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
naIdToken: token,
|
||||
timestamp: '' + timestamp,
|
||||
}).toString(),
|
||||
signal,
|
||||
}).finally(cancel);
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new ErrorResponse('[s2s] Non-200 status code', response, await response.text());
|
||||
}
|
||||
|
||||
const data = await response.json() as LoginHashApiResponse | LoginHashApiError;
|
||||
|
||||
if ('error' in data) {
|
||||
throw new ErrorResponse('[s2s] ' + data.error, response, data);
|
||||
}
|
||||
|
||||
debugS2s('Got login hash "%s"', data.hash, data);
|
||||
|
||||
return data.hash;
|
||||
}
|
||||
|
||||
export interface LoginHashApiResponse {
|
||||
hash: string;
|
||||
}
|
||||
export interface LoginHashApiError {
|
||||
error: string;
|
||||
}
|
||||
|
||||
export async function flapg(
|
||||
hash_method: HashMethod, token: string,
|
||||
timestamp?: string | number, request_id?: string,
|
||||
|
|
@ -131,11 +90,6 @@ export type FlapgApiResponse = IminkFResponse;
|
|||
export type FlapgApiError = IminkFError;
|
||||
|
||||
export class ZncaApiFlapg extends ZncaApi {
|
||||
/** @deprecated */
|
||||
async getLoginHash(id_token: string, timestamp: string) {
|
||||
return getLoginHash(id_token, timestamp, this.useragent);
|
||||
}
|
||||
|
||||
async genf(token: string, hash_method: HashMethod) {
|
||||
const request_id = uuidgen();
|
||||
|
||||
|
|
@ -158,7 +112,8 @@ export class ZncaApiFlapg extends ZncaApi {
|
|||
export async function iminkf(
|
||||
hash_method: HashMethod, token: string,
|
||||
timestamp?: number, request_id?: string,
|
||||
useragent?: string
|
||||
user?: {na_id: string; coral_user_id?: string;},
|
||||
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');
|
||||
|
|
@ -172,6 +127,7 @@ export async function iminkf(
|
|||
token,
|
||||
timestamp: typeof timestamp === 'number' ? '' + timestamp : undefined,
|
||||
request_id,
|
||||
...user,
|
||||
};
|
||||
|
||||
const [signal, cancel] = timeoutSignal();
|
||||
|
|
@ -217,16 +173,17 @@ export interface IminkFError {
|
|||
}
|
||||
|
||||
export class ZncaApiImink extends ZncaApi {
|
||||
async genf(token: string, hash_method: HashMethod) {
|
||||
async genf(token: string, hash_method: HashMethod, user?: {na_id: string; coral_user_id?: string;}) {
|
||||
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, user, this.useragent);
|
||||
|
||||
return {
|
||||
provider: 'imink' as const,
|
||||
hash_method, token, request_id,
|
||||
timestamp: result.timestamp,
|
||||
f: result.f,
|
||||
user,
|
||||
result,
|
||||
};
|
||||
}
|
||||
|
|
@ -239,10 +196,12 @@ export class ZncaApiImink extends ZncaApi {
|
|||
export async function genf(
|
||||
url: string, hash_method: HashMethod,
|
||||
token: string, timestamp?: number, request_id?: string,
|
||||
app?: {platform?: string; version?: string;}, useragent?: string
|
||||
user?: {na_id: string; coral_user_id?: string;},
|
||||
app?: {platform?: string; version?: string;},
|
||||
useragent?: string,
|
||||
) {
|
||||
debugZncaApi('Getting f parameter', {
|
||||
url, hash_method, token, timestamp, request_id,
|
||||
url, hash_method, token, timestamp, request_id, user,
|
||||
znca_platform: app?.platform, znca_version: app?.version,
|
||||
});
|
||||
|
||||
|
|
@ -251,6 +210,7 @@ export async function genf(
|
|||
token,
|
||||
timestamp,
|
||||
request_id,
|
||||
...user,
|
||||
};
|
||||
|
||||
const headers = new Headers({
|
||||
|
|
@ -294,10 +254,15 @@ export interface AndroidZncaFResponse {
|
|||
f: string;
|
||||
timestamp?: number;
|
||||
request_id?: string;
|
||||
|
||||
warnings?: {error: string; error_message: string}[];
|
||||
}
|
||||
export interface AndroidZncaFError {
|
||||
error: string;
|
||||
error_message?: string;
|
||||
|
||||
errors?: {error: string; error_message: string}[];
|
||||
warnings?: {error: string; error_message: string}[];
|
||||
}
|
||||
|
||||
export class ZncaApiNxapi extends ZncaApi {
|
||||
|
|
@ -305,10 +270,11 @@ export class ZncaApiNxapi extends ZncaApi {
|
|||
super(useragent);
|
||||
}
|
||||
|
||||
async genf(token: string, hash_method: HashMethod) {
|
||||
async genf(token: string, hash_method: HashMethod, user?: {na_id: string; coral_user_id?: string}) {
|
||||
const request_id = uuidgen();
|
||||
|
||||
const result = await genf(this.url + '/f', hash_method, token, undefined, request_id, this.app, this.useragent);
|
||||
const result = await genf(this.url + '/f', hash_method, token, undefined, request_id,
|
||||
user, this.app, this.useragent);
|
||||
|
||||
return {
|
||||
provider: 'nxapi' as const,
|
||||
|
|
@ -316,6 +282,7 @@ export class ZncaApiNxapi extends ZncaApi {
|
|||
hash_method, token, request_id,
|
||||
timestamp: result.timestamp!, // will be included as not sent in request
|
||||
f: result.f,
|
||||
user,
|
||||
result,
|
||||
};
|
||||
}
|
||||
|
|
@ -329,7 +296,7 @@ export async function f(token: string, hash_method: HashMethod | `${HashMethod}`
|
|||
|
||||
const provider = getPreferredZncaApiFromEnvironment(options) ?? await getDefaultZncaApi(options);
|
||||
|
||||
return provider.genf(token, hash_method);
|
||||
return provider.genf(token, hash_method, options?.user);
|
||||
}
|
||||
|
||||
export type FResult = {
|
||||
|
|
@ -339,6 +306,7 @@ export type FResult = {
|
|||
timestamp: number;
|
||||
request_id: string;
|
||||
f: string;
|
||||
user?: {na_id: string; coral_user_id?: string;};
|
||||
result: unknown;
|
||||
} & ({
|
||||
provider: 'flapg';
|
||||
|
|
@ -356,6 +324,7 @@ interface ZncaApiOptions {
|
|||
useragent?: string;
|
||||
platform?: string;
|
||||
version?: string;
|
||||
user?: {na_id: string; coral_user_id?: string;};
|
||||
}
|
||||
|
||||
export function getPreferredZncaApiFromEnvironment(options?: ZncaApiOptions): ZncaApi | null;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import fetch, { Response } from 'node-fetch';
|
||||
import createDebug from 'debug';
|
||||
import { getNintendoAccountToken, getNintendoAccountUser, NintendoAccountToken, NintendoAccountUser } from './na.js';
|
||||
import { defineResponse, ErrorResponse, HasResponse } from './util.js';
|
||||
import { DailySummaries, Devices, MonthlySummaries, MonthlySummary, MoonError, ParentalControlSettingState, SmartDevices, User } from './moon-types.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { timeoutSignal } from '../util/misc.js';
|
||||
|
||||
const debug = createDebug('nxapi:api:moon');
|
||||
|
|
@ -16,9 +16,10 @@ const ZNMA_USER_AGENT = 'moon_ANDROID/' + ZNMA_VERSION + ' (com.nintendo.znma; b
|
|||
'; ANDROID 26)';
|
||||
|
||||
export default class MoonApi {
|
||||
onTokenExpired: ((data: MoonError, res: Response) => Promise<MoonAuthData | PartialMoonAuthData | void>) | null = null;
|
||||
onTokenExpired: ((data?: MoonError, res?: Response) => Promise<MoonAuthData | PartialMoonAuthData | void>) | null = null;
|
||||
/** @internal */
|
||||
_renewToken: Promise<void> | null = null;
|
||||
protected _token_expired = false;
|
||||
|
||||
protected constructor(
|
||||
public token: string,
|
||||
|
|
@ -31,8 +32,18 @@ export default class MoonApi {
|
|||
async fetch<T extends object>(
|
||||
url: string, method = 'GET', body?: string, headers?: object,
|
||||
/** @internal */ _autoRenewToken = true,
|
||||
/** @internal */ _attempt = 0
|
||||
/** @internal */ _attempt = 0,
|
||||
): Promise<HasResponse<T, Response>> {
|
||||
if (this._token_expired && _autoRenewToken && !this._renewToken) {
|
||||
if (!this.onTokenExpired || _attempt) throw new Error('Token expired');
|
||||
|
||||
this._renewToken = this.onTokenExpired.call(null).then(data => {
|
||||
if (data) this.setTokenWithSavedToken(data);
|
||||
}).finally(() => {
|
||||
this._renewToken = null;
|
||||
});
|
||||
}
|
||||
|
||||
if (this._renewToken && _autoRenewToken) {
|
||||
await this._renewToken;
|
||||
}
|
||||
|
|
@ -62,6 +73,7 @@ export default class MoonApi {
|
|||
debug('fetch %s %s, response %s', method, url, response.status);
|
||||
|
||||
if (response.status === 401 && _autoRenewToken && !_attempt && this.onTokenExpired) {
|
||||
this._token_expired = true;
|
||||
const data = await response.json() as MoonError;
|
||||
|
||||
// _renewToken will be awaited when calling fetch
|
||||
|
|
@ -123,6 +135,7 @@ export default class MoonApi {
|
|||
private setTokenWithSavedToken(data: MoonAuthData | PartialMoonAuthData) {
|
||||
this.token = data.nintendoAccountToken.access_token!;
|
||||
if ('user' in data) this.naId = data.user.id;
|
||||
this._token_expired = false;
|
||||
}
|
||||
|
||||
static async createWithSessionToken(token: string) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import fetch from 'node-fetch';
|
||||
import createDebug from 'debug';
|
||||
import { defineResponse, ErrorResponse } from './util.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { JwtPayload } from '../util/jwt.js';
|
||||
import { timeoutSignal } from '../util/misc.js';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import fetch, { Response } from 'node-fetch';
|
||||
import createDebug from 'debug';
|
||||
import { WebServiceToken } from './coral-types.js';
|
||||
import { NintendoAccountUser } from './na.js';
|
||||
import { defineResponse, ErrorResponse, HasResponse } from './util.js';
|
||||
import CoralApi from './coral.js';
|
||||
import { WebServiceError, Users, AuthToken, UserProfile, Newspapers, Newspaper, Emoticons, Reaction, IslandProfile } from './nooklink-types.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { timeoutSignal } from '../util/misc.js';
|
||||
|
||||
const debug = createDebug('nxapi:api:nooklink');
|
||||
|
|
@ -17,9 +17,10 @@ const NOOKLINK_URL = NOOKLINK_WEBSERVICE_URL + '/api';
|
|||
const BLANCO_VERSION = '2.1.1';
|
||||
|
||||
export default class NooklinkApi {
|
||||
onTokenExpired: ((data: WebServiceError, res: Response) => Promise<NooklinkAuthData | void>) | null = null;
|
||||
onTokenExpired: ((data?: WebServiceError, res?: Response) => Promise<NooklinkAuthData | void>) | null = null;
|
||||
/** @internal */
|
||||
_renewToken: Promise<void> | null = null;
|
||||
protected _token_expired = false;
|
||||
|
||||
protected constructor(
|
||||
public gtoken: string,
|
||||
|
|
@ -30,8 +31,18 @@ export default class NooklinkApi {
|
|||
async fetch<T extends object>(
|
||||
url: string, method = 'GET', body?: string | FormData, headers?: object,
|
||||
/** @internal */ _autoRenewToken = true,
|
||||
/** @internal */ _attempt = 0
|
||||
/** @internal */ _attempt = 0,
|
||||
): Promise<HasResponse<T, Response>> {
|
||||
if (this._token_expired && _autoRenewToken && !this._renewToken) {
|
||||
if (!this.onTokenExpired || _attempt) throw new Error('Token expired');
|
||||
|
||||
this._renewToken = this.onTokenExpired.call(null).then(data => {
|
||||
if (data) this.setTokenWithSavedToken(data);
|
||||
}).finally(() => {
|
||||
this._renewToken = null;
|
||||
});
|
||||
}
|
||||
|
||||
if (this._renewToken && _autoRenewToken) {
|
||||
await this._renewToken;
|
||||
}
|
||||
|
|
@ -57,6 +68,7 @@ export default class NooklinkApi {
|
|||
debug('fetch %s %s, response %s', method, url, response.status);
|
||||
|
||||
if (response.status === 401 && _autoRenewToken && !_attempt && this.onTokenExpired) {
|
||||
this._token_expired = true;
|
||||
const data = await response.json() as WebServiceError;
|
||||
|
||||
// _renewToken will be awaited when calling fetch
|
||||
|
|
@ -109,6 +121,7 @@ export default class NooklinkApi {
|
|||
|
||||
private setTokenWithSavedToken(data: NooklinkAuthData) {
|
||||
this.gtoken = data.gtoken;
|
||||
this._token_expired = false;
|
||||
}
|
||||
|
||||
static async createWithCoral(nso: CoralApi, user: NintendoAccountUser) {
|
||||
|
|
@ -195,9 +208,10 @@ export default class NooklinkApi {
|
|||
}
|
||||
|
||||
export class NooklinkUserApi {
|
||||
onTokenExpired: ((data: WebServiceError, res: Response) => Promise<NooklinkUserAuthData | PartialNooklinkUserAuthData | void>) | null = null;
|
||||
onTokenExpired: ((data?: WebServiceError, res?: Response) => Promise<NooklinkUserAuthData | PartialNooklinkUserAuthData | void>) | null = null;
|
||||
/** @internal */
|
||||
_renewToken: Promise<void> | null = null;
|
||||
protected _token_expired = false;
|
||||
|
||||
protected constructor(
|
||||
public user_id: string,
|
||||
|
|
@ -211,8 +225,18 @@ export class NooklinkUserApi {
|
|||
async fetch<T extends object>(
|
||||
url: string, method = 'GET', body?: string | FormData, headers?: object,
|
||||
/** @internal */ _autoRenewToken = true,
|
||||
/** @internal */ _attempt = 0
|
||||
/** @internal */ _attempt = 0,
|
||||
): Promise<HasResponse<T, Response>> {
|
||||
if (this._token_expired && _autoRenewToken && !this._renewToken) {
|
||||
if (!this.onTokenExpired || _attempt) throw new Error('Token expired');
|
||||
|
||||
this._renewToken = this.onTokenExpired.call(null).then(data => {
|
||||
if (data) this.setTokenWithSavedToken(data);
|
||||
}).finally(() => {
|
||||
this._renewToken = null;
|
||||
});
|
||||
}
|
||||
|
||||
if (this._renewToken && _autoRenewToken) {
|
||||
await this._renewToken;
|
||||
}
|
||||
|
|
@ -239,6 +263,7 @@ export class NooklinkUserApi {
|
|||
debug('fetch %s %s, response %s', method, url, response.status);
|
||||
|
||||
if (response.status === 401 && _autoRenewToken && !_attempt && this.onTokenExpired) {
|
||||
this._token_expired = true;
|
||||
const data = await response.json() as WebServiceError;
|
||||
|
||||
// _renewToken will be awaited when calling fetch
|
||||
|
|
@ -327,6 +352,7 @@ export class NooklinkUserApi {
|
|||
this.user_id = data.user_id;
|
||||
this.auth_token = data.token.token;
|
||||
this.gtoken = data.gtoken;
|
||||
this._token_expired = false;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import fetch from 'node-fetch';
|
||||
import createDebug from 'debug';
|
||||
import { v4 as uuidgen } from 'uuid';
|
||||
import { WebServiceToken } from './coral-types.js';
|
||||
import { NintendoAccountUser } from './na.js';
|
||||
import { defineResponse, ErrorResponse } from './util.js';
|
||||
import CoralApi from './coral.js';
|
||||
import { ActiveFestivals, CoopResult, CoopResults, CoopSchedules, HeroRecords, LeagueMatchRankings, NicknameAndIcons, PastFestivals, Records, Result, Results, Schedules, ShareResponse, ShopMerchandises, Stages, Timeline, WebServiceError, XPowerRankingRecords, XPowerRankingSummary } from './splatnet2-types.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { timeoutSignal } from '../util/misc.js';
|
||||
import { toSeasonId, Rule as XPowerRankingRule, Season } from './splatnet2-xrank.js';
|
||||
|
||||
|
|
@ -25,6 +25,8 @@ export const updateIksmSessionLastUsed: {
|
|||
} = {};
|
||||
|
||||
export default class SplatNet2Api {
|
||||
protected _session_expired = false;
|
||||
|
||||
protected constructor(
|
||||
public iksm_session: string,
|
||||
public unique_id: string,
|
||||
|
|
@ -32,6 +34,10 @@ export default class SplatNet2Api {
|
|||
) {}
|
||||
|
||||
async fetch<T extends object>(url: string, method = 'GET', body?: string | FormData, headers?: object) {
|
||||
if (this._session_expired) {
|
||||
throw new Error('Session expired');
|
||||
}
|
||||
|
||||
const [signal, cancel] = timeoutSignal();
|
||||
const response = await fetch(SPLATNET2_URL + url, {
|
||||
method,
|
||||
|
|
@ -52,6 +58,10 @@ export default class SplatNet2Api {
|
|||
|
||||
debug('fetch %s %s, response %s', method, url, response.status);
|
||||
|
||||
if (response.status === 401) {
|
||||
this._session_expired = true;
|
||||
}
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new ErrorResponse('[splatnet2] Non-200 status code', response, await response.text());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import createDebug from 'debug';
|
||||
import fetch, { Response } from 'node-fetch';
|
||||
import { BankaraBattleHistoriesRefetchResult, BankaraBattleHistoriesRefetchVariables, GraphQLRequest, GraphQLResponse, GraphQLSuccessResponse, KnownRequestId, LatestBattleHistoriesRefetchResult, LatestBattleHistoriesRefetchVariables, MyOutfitInput, PagerUpdateBattleHistoriesByVsModeResult, PagerUpdateBattleHistoriesByVsModeVariables, PrivateBattleHistoriesRefetchResult, PrivateBattleHistoriesRefetchVariables, RegularBattleHistoriesRefetchResult, RegularBattleHistoriesRefetchVariables, RequestId, ResultTypes, VariablesTypes, XBattleHistoriesRefetchResult, XBattleHistoriesRefetchVariables } from 'splatnet3-types/splatnet3';
|
||||
import { timeoutSignal } from '../util/misc.js';
|
||||
import { WebServiceToken } from './coral-types.js';
|
||||
import CoralApi from './coral.js';
|
||||
import { NintendoAccountUser } from './na.js';
|
||||
import { BulletToken } from './splatnet3-types.js';
|
||||
import { defineResponse, ErrorResponse, HasResponse, ResponseSymbol } from './util.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { timeoutSignal } from '../util/misc.js';
|
||||
|
||||
const debug = createDebug('nxapi:api:splatnet3');
|
||||
const debugGraphQl = createDebug('nxapi:api:splatnet3:graphql');
|
||||
|
|
@ -74,9 +74,10 @@ enum MapQueriesMode {
|
|||
|
||||
export default class SplatNet3Api {
|
||||
onTokenShouldRenew: ((remaining: number, res: Response) => Promise<SplatNet3AuthData | void>) | null = null;
|
||||
onTokenExpired: ((res: Response) => Promise<SplatNet3AuthData | void>) | null = null;
|
||||
onTokenExpired: ((res?: Response) => Promise<SplatNet3AuthData | void>) | null = null;
|
||||
/** @internal */
|
||||
_renewToken: Promise<void> | null = null;
|
||||
protected _token_expired = false;
|
||||
|
||||
graphql_strict = process.env.NXAPI_SPLATNET3_STRICT !== '0';
|
||||
|
||||
|
|
@ -93,8 +94,18 @@ export default class SplatNet3Api {
|
|||
async fetch<T = unknown>(
|
||||
url: string, method = 'GET', body?: string | FormData, headers?: object,
|
||||
/** @internal */ _log?: string,
|
||||
/** @internal */ _attempt = 0
|
||||
/** @internal */ _attempt = 0,
|
||||
): Promise<HasResponse<T, Response>> {
|
||||
if (this._token_expired && !this._renewToken) {
|
||||
if (!this.onTokenExpired || _attempt) throw new Error('Token expired');
|
||||
|
||||
this._renewToken = this.onTokenExpired.call(null).then(data => {
|
||||
if (data) this.setTokenWithSavedToken(data);
|
||||
}).finally(() => {
|
||||
this._renewToken = null;
|
||||
});
|
||||
}
|
||||
|
||||
if (this._renewToken) {
|
||||
await this._renewToken;
|
||||
}
|
||||
|
|
@ -121,6 +132,7 @@ export default class SplatNet3Api {
|
|||
response.status, version);
|
||||
|
||||
if (response.status === 401 && !_attempt && this.onTokenExpired) {
|
||||
this._token_expired = true;
|
||||
// _renewToken will be awaited when calling fetch
|
||||
this._renewToken = this._renewToken ?? this.onTokenExpired.call(null, response).then(data => {
|
||||
if (data) this.setTokenWithSavedToken(data);
|
||||
|
|
@ -861,7 +873,7 @@ export default class SplatNet3Api {
|
|||
PagerUpdateBattleHistoriesByVsModeVariables
|
||||
>(RequestId.PagerUpdateBattleHistoriesByVsModeQuery, {
|
||||
isBankara: false,
|
||||
isLeague: false,
|
||||
isEvent: false,
|
||||
isPrivate: false,
|
||||
isRegular: false,
|
||||
isXBattle: false,
|
||||
|
|
@ -933,6 +945,7 @@ export default class SplatNet3Api {
|
|||
this.version = data.version;
|
||||
this.language = data.bullet_token.lang;
|
||||
this.useragent = data.useragent;
|
||||
this._token_expired = false;
|
||||
}
|
||||
|
||||
static async createWithCoral(nso: CoralApi, user: NintendoAccountUser) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import fetch, { Response } from 'node-fetch';
|
||||
import createDebug from 'debug';
|
||||
import { ActiveEvent, Announcements, CurrentUser, Event, Friend, Presence, PresencePermissions, User, WebService, WebServiceToken, CoralErrorResponse, CoralStatus, CoralSuccessResponse, FriendCodeUser, FriendCodeUrl } from './coral-types.js';
|
||||
import { defineResponse, ErrorResponse, ResponseSymbol } from './util.js';
|
||||
import CoralApi, { CoralAuthData, CorrelationIdSymbol, PartialCoralAuthData, ResponseDataSymbol, Result } from './coral.js';
|
||||
import { NintendoAccountUser } from './na.js';
|
||||
import { SavedToken } from '../common/auth/coral.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { timeoutSignal } from '../util/misc.js';
|
||||
import { getAdditionalUserAgents, getUserAgent } from '../util/useragent.js';
|
||||
|
||||
|
|
@ -12,10 +12,16 @@ const debug = createDebug('nxapi:api:znc-proxy');
|
|||
|
||||
export default class ZncProxyApi implements CoralApi {
|
||||
// Not used by ZncProxyApi
|
||||
onTokenExpired: ((data: CoralErrorResponse, res: Response) => Promise<CoralAuthData | void>) | null = null;
|
||||
onTokenExpired: ((data?: CoralErrorResponse, res?: Response) => Promise<CoralAuthData | void>) | null = null;
|
||||
/** @internal */
|
||||
_renewToken: Promise<void> | null = null;
|
||||
|
||||
/** @internal */
|
||||
_token_expired = false;
|
||||
/** @internal */
|
||||
na_id = '';
|
||||
/** @internal */
|
||||
coral_user_id = '';
|
||||
readonly znca_version = '';
|
||||
readonly znca_useragent = '';
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@ const electron = require('electron');
|
|||
|
||||
// Do anything that must be run before the app is ready...
|
||||
|
||||
electron.app.whenReady()
|
||||
Promise.all([
|
||||
// @ts-expect-error
|
||||
typeof __NXAPI_BUNDLE_APP_INIT__ !== 'undefined' ? import(__NXAPI_BUNDLE_APP_INIT__) : import('./app-init.js'),
|
||||
electron.app.whenReady(),
|
||||
])
|
||||
// @ts-expect-error
|
||||
.then(() => typeof __NXAPI_BUNDLE_APP_MAIN__ !== 'undefined' ? import(__NXAPI_BUNDLE_APP_MAIN__) : import('./main/index.js'))
|
||||
.then(m => m.init.call(null))
|
||||
|
|
|
|||
5
src/app/app-init.ts
Normal file
5
src/app/app-init.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import { join } from 'node:path';
|
||||
import { init as initDebug } from '../util/debug.js';
|
||||
import { paths } from '../util/product.js';
|
||||
|
||||
await initDebug(join(paths.log, 'app'));
|
||||
|
|
@ -2,25 +2,25 @@ import { app, BrowserWindow, dialog, ipcMain, LoginItemSettingsOptions, Menu } f
|
|||
import process from 'node:process';
|
||||
import * as path from 'node:path';
|
||||
import { EventEmitter } from 'node:events';
|
||||
import createDebug from 'debug';
|
||||
import * as persist from 'node-persist';
|
||||
import { i18n } from 'i18next';
|
||||
import { init as initGlobals } from '../../common/globals.js';
|
||||
import MenuApp from './menu.js';
|
||||
import { handleOpenWebServiceUri } from './webservices.js';
|
||||
import { EmbeddedPresenceMonitor, PresenceMonitorManager } from './monitor.js';
|
||||
import { createWindow } from './windows.js';
|
||||
import { DiscordPresenceConfiguration, LoginItem, LoginItemOptions, WindowType } from '../common/types.js';
|
||||
import { initStorage, paths } from '../../util/storage.js';
|
||||
import { checkUpdates, UpdateCacheData } from '../../common/update.js';
|
||||
import Users, { CoralUser } from '../../common/users.js';
|
||||
import { createModalWindow, createWindow } from './windows.js';
|
||||
import { sendToAllWindows, setupIpc } from './ipc.js';
|
||||
import { dev, dir, git, release, version } from '../../util/product.js';
|
||||
import { addUserAgent } from '../../util/useragent.js';
|
||||
import { askUserForUri } from './util.js';
|
||||
import { setAppInstance, updateMenuLanguage } from './app-menu.js';
|
||||
import { handleAuthUri } from './na-auth.js';
|
||||
import { DiscordPresenceConfiguration, LoginItem, LoginItemOptions, WindowType } from '../common/types.js';
|
||||
import { init as initGlobals } from '../../common/globals.js';
|
||||
import { CREDITS_NOTICE, GITLAB_URL, LICENCE_NOTICE } from '../../common/constants.js';
|
||||
import { checkUpdates, UpdateCacheData } from '../../common/update.js';
|
||||
import Users, { CoralUser } from '../../common/users.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { dev, dir, git, release, version } from '../../util/product.js';
|
||||
import { addUserAgent } from '../../util/useragent.js';
|
||||
import { initStorage, paths } from '../../util/storage.js';
|
||||
import createI18n, { languages } from '../i18n/index.js';
|
||||
|
||||
const debug = createDebug('app:main');
|
||||
|
|
@ -101,17 +101,7 @@ export class App {
|
|||
return this.preferences_window;
|
||||
}
|
||||
|
||||
const window = createWindow(WindowType.PREFERENCES, {}, {
|
||||
show: false,
|
||||
maximizable: false,
|
||||
minimizable: false,
|
||||
width: 580,
|
||||
height: 400,
|
||||
minWidth: 580,
|
||||
maxWidth: 580,
|
||||
minHeight: 400,
|
||||
maxHeight: 400,
|
||||
});
|
||||
const window = createModalWindow(WindowType.PREFERENCES, {});
|
||||
|
||||
window.on('closed', () => this.preferences_window = null);
|
||||
|
||||
|
|
@ -290,19 +280,9 @@ export async function handleOpenFriendCodeUri(app: App, uri: string) {
|
|||
const selected_user = await askUserForUri(app, uri, app.i18n.t('handle_uri:friend_code_select'));
|
||||
if (!selected_user) return;
|
||||
|
||||
createWindow(WindowType.ADD_FRIEND, {
|
||||
createModalWindow(WindowType.ADD_FRIEND, {
|
||||
user: selected_user[1].user.id,
|
||||
friendcode,
|
||||
}, {
|
||||
// show: false,
|
||||
maximizable: false,
|
||||
minimizable: false,
|
||||
width: 560,
|
||||
height: 300,
|
||||
minWidth: 450,
|
||||
maxWidth: 700,
|
||||
minHeight: 300,
|
||||
maxHeight: 300,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,27 +1,24 @@
|
|||
import { BrowserWindow, clipboard, dialog, IpcMain, KeyboardEvent, Menu, MenuItem, Settings, ShareMenu, SharingItem, shell, systemPreferences } from './electron.js';
|
||||
import { BrowserWindow, clipboard, dialog, IpcMain, KeyboardEvent, Menu, MenuItem, ShareMenu, SharingItem, shell, systemPreferences } from './electron.js';
|
||||
import * as util from 'node:util';
|
||||
import createDebug from 'debug';
|
||||
import { User } from 'discord-rpc';
|
||||
import openWebService, { QrCodeReaderOptions, WebServiceIpc, WebServiceValidationError } from './webservices.js';
|
||||
import { createWindow, getWindowConfiguration } from './windows.js';
|
||||
import { DiscordPresenceConfiguration, DiscordPresenceSource, LoginItemOptions, WindowType } from '../common/types.js';
|
||||
import { CurrentUser, Friend, Game, PresenceState, WebService } from '../../api/coral-types.js';
|
||||
import { createModalWindow, createWindow, getWindowConfiguration, setWindowHeight } from './windows.js';
|
||||
import { askAddNsoAccount, askAddPctlAccount } from './na-auth.js';
|
||||
import { App } from './index.js';
|
||||
import { EmbeddedPresenceMonitor } from './monitor.js';
|
||||
import { DiscordPresenceConfiguration, DiscordPresenceSource, LoginItemOptions, WindowType } from '../common/types.js';
|
||||
import { CurrentUser, Friend, Game, PresenceState, WebService } from '../../api/coral-types.js';
|
||||
import { NintendoAccountUser } from '../../api/na.js';
|
||||
import { hrduration } from '../../util/misc.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { DiscordPresence } from '../../discord/types.js';
|
||||
import { getDiscordRpcClients } from '../../discord/rpc.js';
|
||||
import { defaultTitle } from '../../discord/titles.js';
|
||||
import type { FriendProps } from '../browser/friend/index.js';
|
||||
import type { DiscordSetupProps } from '../browser/discord/index.js';
|
||||
import type { AddFriendProps } from '../browser/add-friend/index.js';
|
||||
import { EmbeddedPresenceMonitor } from './monitor.js';
|
||||
|
||||
const debug = createDebug('app:main:ipc');
|
||||
|
||||
const shown_modal_windows = new WeakSet<BrowserWindow>();
|
||||
|
||||
export function setupIpc(appinstance: App, ipcMain: IpcMain) {
|
||||
const store = appinstance.store;
|
||||
const storage = appinstance.store.storage;
|
||||
|
|
@ -85,61 +82,15 @@ export function setupIpc(appinstance: App, ipcMain: IpcMain) {
|
|||
ipcMain.handle('nxapi:coral:addfriend', (e, token: string, nsaid: string) => store.users.get(token).then(u => u.addFriend(nsaid)));
|
||||
|
||||
ipcMain.handle('nxapi:window:showpreferences', () => appinstance.showPreferencesWindow().id);
|
||||
ipcMain.handle('nxapi:window:showfriend', (e, props: FriendProps) => createWindow(WindowType.FRIEND, props, {
|
||||
parent: BrowserWindow.fromWebContents(e.sender) ?? undefined,
|
||||
modal: true,
|
||||
show: false,
|
||||
maximizable: false,
|
||||
minimizable: false,
|
||||
width: 560,
|
||||
height: 300,
|
||||
minWidth: 450,
|
||||
maxWidth: 700,
|
||||
minHeight: 300,
|
||||
maxHeight: 300,
|
||||
}).id);
|
||||
ipcMain.handle('nxapi:window:discord', (e, props: DiscordSetupProps) => createWindow(WindowType.DISCORD_PRESENCE, props, {
|
||||
parent: BrowserWindow.fromWebContents(e.sender) ?? undefined,
|
||||
modal: true,
|
||||
show: false,
|
||||
maximizable: false,
|
||||
minimizable: false,
|
||||
width: 560,
|
||||
height: 300,
|
||||
minWidth: 450,
|
||||
maxWidth: 700,
|
||||
minHeight: 300,
|
||||
maxHeight: 300,
|
||||
}).id);
|
||||
ipcMain.handle('nxapi:window:addfriend', (e, props: AddFriendProps) => createWindow(WindowType.ADD_FRIEND, props, {
|
||||
parent: BrowserWindow.fromWebContents(e.sender) ?? undefined,
|
||||
modal: true,
|
||||
show: false,
|
||||
maximizable: false,
|
||||
minimizable: false,
|
||||
width: 560,
|
||||
height: 300,
|
||||
minWidth: 450,
|
||||
maxWidth: 700,
|
||||
minHeight: 300,
|
||||
maxHeight: 300,
|
||||
}).id);
|
||||
ipcMain.handle('nxapi:window:showfriend', (e, props: FriendProps) =>
|
||||
createModalWindow(WindowType.FRIEND, props, e.sender).id);
|
||||
ipcMain.handle('nxapi:window:discord', (e, props: DiscordSetupProps) =>
|
||||
createModalWindow(WindowType.DISCORD_PRESENCE, props).id);
|
||||
ipcMain.handle('nxapi:window:addfriend', (e, props: AddFriendProps) =>
|
||||
createModalWindow(WindowType.ADD_FRIEND, props, e.sender).id);
|
||||
ipcMain.handle('nxapi:window:setheight', (e, height: number) => {
|
||||
const window = BrowserWindow.fromWebContents(e.sender)!;
|
||||
const [curWidth, curHeight] = window.getSize();
|
||||
const [curContentWidth, curContentHeight] = window.getContentSize();
|
||||
const [minWidth, minHeight] = window.getMinimumSize();
|
||||
const [maxWidth, maxHeight] = window.getMaximumSize();
|
||||
if (height !== curContentHeight && curHeight === minHeight && curHeight === maxHeight) {
|
||||
window.setMinimumSize(minWidth, height + (curHeight - curContentHeight));
|
||||
window.setMaximumSize(maxWidth, height + (curHeight - curContentHeight));
|
||||
}
|
||||
window.setContentSize(curContentWidth, height);
|
||||
|
||||
if (!shown_modal_windows.has(window)) {
|
||||
window.show();
|
||||
shown_modal_windows.add(window);
|
||||
}
|
||||
setWindowHeight(window, height);
|
||||
});
|
||||
|
||||
ipcMain.handle('nxapi:discord:config', () => appinstance.monitors.getDiscordPresenceConfiguration());
|
||||
|
|
@ -256,21 +207,9 @@ function buildUserMenu(app: App, user: NintendoAccountUser, nso?: CurrentUser, m
|
|||
click: () => app.menu?.setActiveDiscordPresenceUser(null)}),
|
||||
] : [
|
||||
new MenuItem({label: t('discord_enable')!,
|
||||
click: () => createWindow(WindowType.DISCORD_PRESENCE, {
|
||||
click: () => createModalWindow(WindowType.DISCORD_PRESENCE, {
|
||||
friend_nsa_id: nso.nsaId,
|
||||
}, {
|
||||
parent: window,
|
||||
modal: true,
|
||||
show: false,
|
||||
maximizable: false,
|
||||
minimizable: false,
|
||||
width: 560,
|
||||
height: 300,
|
||||
minWidth: 450,
|
||||
maxWidth: 700,
|
||||
minHeight: 300,
|
||||
maxHeight: 300,
|
||||
})}),
|
||||
}, window)}),
|
||||
]),
|
||||
new MenuItem({label: t('friend_notifications_enable')!, type: 'checkbox',
|
||||
checked: monitor?.friend_notifications,
|
||||
|
|
@ -279,21 +218,9 @@ function buildUserMenu(app: App, user: NintendoAccountUser, nso?: CurrentUser, m
|
|||
click: () => monitor?.skipIntervalInCurrentLoop(true)}),
|
||||
new MenuItem({type: 'separator'}),
|
||||
new MenuItem({label: t('add_friend')!,
|
||||
click: () => createWindow(WindowType.ADD_FRIEND, {
|
||||
click: () => createModalWindow(WindowType.ADD_FRIEND, {
|
||||
user: user.id,
|
||||
}, {
|
||||
parent: window,
|
||||
modal: true,
|
||||
show: false,
|
||||
maximizable: false,
|
||||
minimizable: false,
|
||||
width: 560,
|
||||
height: 300,
|
||||
minWidth: 450,
|
||||
maxWidth: 700,
|
||||
minHeight: 300,
|
||||
maxHeight: 300,
|
||||
})}),
|
||||
}, window)}),
|
||||
] : []),
|
||||
new MenuItem({type: 'separator'}),
|
||||
new MenuItem({label: t('remove_help')!, enabled: false}),
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
import { app, dialog, Menu, Tray, nativeImage, MenuItem, BrowserWindow, KeyboardEvent } from './electron.js';
|
||||
import path from 'node:path';
|
||||
import * as util from 'node:util';
|
||||
import createDebug from 'debug';
|
||||
import { askAddNsoAccount, askAddPctlAccount } from './na-auth.js';
|
||||
import { App } from './index.js';
|
||||
import { WebService } from '../../api/coral-types.js';
|
||||
import openWebService, { WebServiceValidationError } from './webservices.js';
|
||||
import { SavedToken } from '../../common/auth/coral.js';
|
||||
import { SavedMoonToken } from '../../common/auth/moon.js';
|
||||
import { dev, dir } from '../../util/product.js';
|
||||
import { EmbeddedPresenceMonitor, EmbeddedProxyPresenceMonitor } from './monitor.js';
|
||||
import { createWindow } from './windows.js';
|
||||
import { createModalWindow, createWindow } from './windows.js';
|
||||
import { WindowType } from '../common/types.js';
|
||||
import CoralApi from '../../api/coral.js';
|
||||
import { WebService } from '../../api/coral-types.js';
|
||||
import { SavedToken } from '../../common/auth/coral.js';
|
||||
import { SavedMoonToken } from '../../common/auth/moon.js';
|
||||
import { CachedWebServicesList } from '../../common/users.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { dev, dir } from '../../util/product.js';
|
||||
import { languages } from '../i18n/index.js';
|
||||
|
||||
const debug = createDebug('app:main:menu');
|
||||
|
|
@ -300,18 +300,8 @@ export default class MenuApp {
|
|||
}
|
||||
|
||||
showAddFriendWindow(user: string) {
|
||||
createWindow(WindowType.ADD_FRIEND, {
|
||||
createModalWindow(WindowType.ADD_FRIEND, {
|
||||
user,
|
||||
}, {
|
||||
show: false,
|
||||
maximizable: false,
|
||||
minimizable: false,
|
||||
width: 560,
|
||||
height: 300,
|
||||
minWidth: 450,
|
||||
maxWidth: 700,
|
||||
minHeight: 300,
|
||||
maxHeight: 300,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { dialog, Notification } from './electron.js';
|
||||
import createDebug from 'debug';
|
||||
import { i18n } from 'i18next';
|
||||
import { App } from './index.js';
|
||||
import { tryGetNativeImageFromUrl } from './util.js';
|
||||
import { DiscordPresenceConfiguration, DiscordPresenceExternalMonitorsConfiguration, DiscordPresenceSource } from '../common/types.js';
|
||||
import { CurrentUser, Friend, Game, CoralErrorResponse } from '../../api/coral-types.js';
|
||||
import { ErrorResponse } from '../../api/util.js';
|
||||
import { ZncDiscordPresence, ZncProxyDiscordPresence } from '../../common/presence.js';
|
||||
import { NotificationManager } from '../../common/notify.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { LoopResult } from '../../util/loop.js';
|
||||
import { tryGetNativeImageFromUrl } from './util.js';
|
||||
import { App } from './index.js';
|
||||
import { DiscordPresenceConfiguration, DiscordPresenceExternalMonitorsConfiguration, DiscordPresenceSource } from '../common/types.js';
|
||||
import { DiscordPresence, DiscordPresencePlayTime, ErrorResult } from '../../discord/types.js';
|
||||
import { DiscordRpcClient } from '../../discord/rpc.js';
|
||||
import SplatNet3Monitor, { getConfigFromAppConfig as getSplatNet3MonitorConfigFromAppConfig } from '../../discord/monitor/splatoon3.js';
|
||||
|
|
|
|||
|
|
@ -1,19 +1,20 @@
|
|||
import { app, BrowserWindow, dialog, MessageBoxOptions, Notification, session, shell } from './electron.js';
|
||||
import process from 'node:process';
|
||||
import * as crypto from 'node:crypto';
|
||||
import createDebug from 'debug';
|
||||
import * as persist from 'node-persist';
|
||||
import { app, BrowserWindow, dialog, MessageBoxOptions, Notification, session, shell } from './electron.js';
|
||||
import { getNintendoAccountSessionToken, NintendoAccountSessionToken } from '../../api/na.js';
|
||||
import { protocol_registration_options } from './index.js';
|
||||
import { createModalWindow, createWindow } from './windows.js';
|
||||
import { tryGetNativeImageFromUrl } from './util.js';
|
||||
import { WindowType } from '../common/types.js';
|
||||
import { getNintendoAccountSessionToken, NintendoAccountAuthError, NintendoAccountSessionToken } from '../../api/na.js';
|
||||
import { ZNCA_CLIENT_ID } from '../../api/coral.js';
|
||||
import { ZNMA_CLIENT_ID } from '../../api/moon.js';
|
||||
import { getToken, SavedToken } from '../../common/auth/coral.js';
|
||||
import { getPctlToken, SavedMoonToken } from '../../common/auth/moon.js';
|
||||
import { ErrorResponse } from '../../api/util.js';
|
||||
import { getToken } from '../../common/auth/coral.js';
|
||||
import { getPctlToken } from '../../common/auth/moon.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { Jwt } from '../../util/jwt.js';
|
||||
import { tryGetNativeImageFromUrl } from './util.js';
|
||||
import { ZNCA_API_USE_URL } from '../../common/constants.js';
|
||||
import { createWindow } from './windows.js';
|
||||
import { WindowType } from '../common/types.js';
|
||||
import { protocol_registration_options } from './index.js';
|
||||
|
||||
const debug = createDebug('app:main:na-auth');
|
||||
|
||||
|
|
@ -312,19 +313,9 @@ function askUserForRedirectUri(
|
|||
authoriseurl: string, client_id: string,
|
||||
handleAuthUrl: (url: URL) => void, rj: (reason: any) => void
|
||||
) {
|
||||
const window = createWindow(WindowType.ADD_ACCOUNT_MANUAL_PROMPT, {
|
||||
const window = createModalWindow(WindowType.ADD_ACCOUNT_MANUAL_PROMPT, {
|
||||
authoriseurl,
|
||||
client_id,
|
||||
}, {
|
||||
show: false,
|
||||
maximizable: false,
|
||||
minimizable: false,
|
||||
width: 560,
|
||||
height: 300,
|
||||
minWidth: 450,
|
||||
maxWidth: 700,
|
||||
minHeight: 300,
|
||||
maxHeight: 300,
|
||||
});
|
||||
|
||||
window.webContents.on('will-navigate', (event, url_string) => {
|
||||
|
|
@ -368,43 +359,69 @@ export async function addNsoAccount(storage: persist.LocalStorage, use_in_app_br
|
|||
const nsotoken = await storage.getItem('NintendoAccountToken.' + jwt.payload.sub) as string | undefined;
|
||||
|
||||
if (nsotoken) {
|
||||
const data = await storage.getItem('NsoToken.' + nsotoken) as SavedToken | undefined;
|
||||
debug('Already authenticated', jwt.payload);
|
||||
|
||||
debug('Already authenticated', data);
|
||||
try {
|
||||
const {nso, data} = await getToken(storage, nsotoken, process.env.ZNC_PROXY_URL, false);
|
||||
|
||||
new Notification({
|
||||
title: 'Nintendo Switch Online',
|
||||
body: 'Already signed in as ' + data?.nsoAccount.user.name + ' (' + data?.user.nickname + ')',
|
||||
icon: await tryGetNativeImageFromUrl(data!.nsoAccount.user.imageUri),
|
||||
}).show();
|
||||
new Notification({
|
||||
title: 'Nintendo Switch Online',
|
||||
body: 'Already signed in as ' + data.nsoAccount.user.name + ' (Nintendo Account ' +
|
||||
data.user.nickname + ' / ' + data.user.screenName + ')',
|
||||
icon: await tryGetNativeImageFromUrl(data.nsoAccount.user.imageUri),
|
||||
}).show();
|
||||
|
||||
return getToken(storage, nsotoken, process.env.ZNC_PROXY_URL, false);
|
||||
return {nso, data};
|
||||
} catch (err) {
|
||||
if (err instanceof ErrorResponse && err.response.url.startsWith('https://accounts.nintendo.com/')) {
|
||||
const data: NintendoAccountAuthError = err.data;
|
||||
|
||||
if (data.error === 'invalid_grant') {
|
||||
// The session token has expired/was revoked
|
||||
return authenticateCoralSessionToken(storage, code, verifier, true);
|
||||
}
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
await checkZncaApiUseAllowed(storage, window);
|
||||
|
||||
const token = await getNintendoAccountSessionToken(code, verifier, ZNCA_CLIENT_ID);
|
||||
|
||||
debug('session token', token);
|
||||
|
||||
const {nso, data} = await getToken(storage, token.session_token, process.env.ZNC_PROXY_URL, false);
|
||||
|
||||
const users = new Set(await storage.getItem('NintendoAccountIds') ?? []);
|
||||
users.add(data.user.id);
|
||||
await storage.setItem('NintendoAccountIds', [...users]);
|
||||
|
||||
new Notification({
|
||||
title: 'Nintendo Switch Online',
|
||||
body: 'Authenticated as ' + data.nsoAccount.user.name + ' (NSO ' + data.user.nickname + ')',
|
||||
icon: await tryGetNativeImageFromUrl(data.nsoAccount.user.imageUri),
|
||||
}).show();
|
||||
|
||||
return {nso, data};
|
||||
return authenticateCoralSessionToken(storage, code, verifier);
|
||||
} finally {
|
||||
window?.close();
|
||||
}
|
||||
}
|
||||
|
||||
async function authenticateCoralSessionToken(
|
||||
storage: persist.LocalStorage,
|
||||
code: string, verifier: string,
|
||||
reauthenticate = false,
|
||||
) {
|
||||
const token = await getNintendoAccountSessionToken(code, verifier, ZNCA_CLIENT_ID);
|
||||
|
||||
debug('session token', token);
|
||||
|
||||
const {nso, data} = await getToken(storage, token.session_token, process.env.ZNC_PROXY_URL, false);
|
||||
|
||||
const users = new Set(await storage.getItem('NintendoAccountIds') ?? []);
|
||||
users.add(data.user.id);
|
||||
await storage.setItem('NintendoAccountIds', [...users]);
|
||||
|
||||
new Notification({
|
||||
title: 'Nintendo Switch Online',
|
||||
body: reauthenticate ?
|
||||
'Reauthenticated to ' + data.nsoAccount.user.name + ' (Nintendo Account ' + data.user.nickname + ' / ' +
|
||||
data.user.screenName + ')' :
|
||||
'Authenticated as ' + data.nsoAccount.user.name + ' (Nintendo Account ' + data.user.nickname + ' / ' +
|
||||
data.user.screenName + ')',
|
||||
icon: await tryGetNativeImageFromUrl(data.nsoAccount.user.imageUri),
|
||||
}).show();
|
||||
|
||||
return {nso, data};
|
||||
}
|
||||
|
||||
export async function askAddNsoAccount(storage: persist.LocalStorage, iab = true) {
|
||||
try {
|
||||
return await addNsoAccount(storage, iab);
|
||||
|
|
@ -507,39 +524,63 @@ export async function addPctlAccount(storage: persist.LocalStorage, use_in_app_b
|
|||
const moontoken = await storage.getItem('NintendoAccountToken-pctl.' + jwt.payload.sub) as string | undefined;
|
||||
|
||||
if (moontoken) {
|
||||
const data = await storage.getItem('MoonToken.' + moontoken) as SavedMoonToken | undefined;
|
||||
debug('Already authenticated', jwt.payload);
|
||||
|
||||
debug('Already authenticated', data);
|
||||
try {
|
||||
const {moon, data} = await getPctlToken(storage, moontoken, false);
|
||||
|
||||
new Notification({
|
||||
title: 'Nintendo Switch Parental Controls',
|
||||
body: 'Already signed in as ' + data?.user.nickname,
|
||||
}).show();
|
||||
new Notification({
|
||||
title: 'Nintendo Switch Parental Controls',
|
||||
body: 'Already signed in as ' + data.user.nickname + ' (' + data.user.screenName + ')',
|
||||
}).show();
|
||||
|
||||
return getPctlToken(storage, moontoken, false);
|
||||
return {moon, data};
|
||||
} catch (err) {
|
||||
if (err instanceof ErrorResponse && err.response.url.startsWith('https://accounts.nintendo.com/')) {
|
||||
const data: NintendoAccountAuthError = err.data;
|
||||
|
||||
if (data.error === 'invalid_grant') {
|
||||
// The session token has expired/was revoked
|
||||
return authenticateMoonSessionToken(storage, code, verifier, true);
|
||||
}
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
const token = await getNintendoAccountSessionToken(code, verifier, ZNMA_CLIENT_ID);
|
||||
|
||||
debug('session token', token);
|
||||
|
||||
const {moon, data} = await getPctlToken(storage, token.session_token, false);
|
||||
|
||||
const users = new Set(await storage.getItem('NintendoAccountIds') ?? []);
|
||||
users.add(data.user.id);
|
||||
await storage.setItem('NintendoAccountIds', [...users]);
|
||||
|
||||
new Notification({
|
||||
title: 'Nintendo Switch Parental Controls',
|
||||
body: 'Authenticated as ' + data.user.nickname,
|
||||
}).show();
|
||||
|
||||
return {moon, data};
|
||||
return authenticateMoonSessionToken(storage, code, verifier);
|
||||
} finally {
|
||||
window?.close();
|
||||
}
|
||||
}
|
||||
|
||||
async function authenticateMoonSessionToken(
|
||||
storage: persist.LocalStorage,
|
||||
code: string, verifier: string,
|
||||
reauthenticate = false,
|
||||
) {
|
||||
|
||||
const token = await getNintendoAccountSessionToken(code, verifier, ZNMA_CLIENT_ID);
|
||||
|
||||
debug('session token', token);
|
||||
|
||||
const {moon, data} = await getPctlToken(storage, token.session_token, false);
|
||||
|
||||
const users = new Set(await storage.getItem('NintendoAccountIds') ?? []);
|
||||
users.add(data.user.id);
|
||||
await storage.setItem('NintendoAccountIds', [...users]);
|
||||
|
||||
new Notification({
|
||||
title: 'Nintendo Switch Parental Controls',
|
||||
body: reauthenticate ?
|
||||
'Reauthenticated to ' + data.user.nickname + ' (' + data.user.screenName + ')' :
|
||||
'Authenticated as ' + data.user.nickname + ' (' + data.user.screenName + ')',
|
||||
}).show();
|
||||
|
||||
return {moon, data};
|
||||
}
|
||||
|
||||
export async function askAddPctlAccount(storage: persist.LocalStorage, iab = true) {
|
||||
try {
|
||||
return await addPctlAccount(storage, iab);
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
import { app, BrowserWindow, clipboard, dialog, IpcMainInvokeEvent, nativeImage, nativeTheme, Notification, ShareMenu, shell, WebContents } from './electron.js';
|
||||
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, clipboard, dialog, IpcMainInvokeEvent, nativeImage, nativeTheme, Notification, ShareMenu, shell, WebContents } from './electron.js';
|
||||
import fetch from 'node-fetch';
|
||||
import CoralApi from '../../api/coral.js';
|
||||
import { CurrentUser, WebService, WebServiceToken } from '../../api/coral-types.js';
|
||||
import { App, Store } from './index.js';
|
||||
import type { DownloadImagesRequest, NativeShareRequest, NativeShareUrlRequest, QrCodeReaderCameraOptions, QrCodeReaderCheckinOptions, QrCodeReaderCheckinResult, QrCodeReaderPhotoLibraryOptions, SendMessageOptions } from '../preload-webservice/znca-js-api.js';
|
||||
import { SavedToken } from '../../common/auth/coral.js';
|
||||
import { createWebServiceWindow } from './windows.js';
|
||||
import { askUserForUri } from './util.js';
|
||||
import type { DownloadImagesRequest, NativeShareRequest, NativeShareUrlRequest, QrCodeReaderCameraOptions, QrCodeReaderCheckinOptions, QrCodeReaderCheckinResult, QrCodeReaderPhotoLibraryOptions, SendMessageOptions } from '../preload-webservice/znca-js-api.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import CoralApi from '../../api/coral.js';
|
||||
import { CurrentUser, WebService, WebServiceToken } from '../../api/coral-types.js';
|
||||
import { NintendoAccountUser } from '../../api/na.js';
|
||||
import { SavedToken } from '../../common/auth/coral.js';
|
||||
|
||||
const debug = createDebug('app:main:webservices');
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const windows = new WeakMap<WebContents, WindowConfiguration>();
|
|||
|
||||
export function createWindow<T extends WindowType>(
|
||||
type: T, props: WindowConfiguration<T>['props'],
|
||||
options?: BrowserWindowConstructorOptions
|
||||
options?: BrowserWindowConstructorOptions,
|
||||
) {
|
||||
// Create the browser window
|
||||
const window = new BrowserWindow({
|
||||
|
|
@ -51,6 +51,62 @@ export function getWindowConfiguration(webcontents: WebContents): WindowConfigur
|
|||
return data;
|
||||
}
|
||||
|
||||
const modal_window_width = new WeakMap<BrowserWindow, number>();
|
||||
const modal_window_shown = new WeakSet<BrowserWindow>();
|
||||
|
||||
export function createModalWindow<T extends WindowType>(
|
||||
type: T, props: WindowConfiguration<T>['props'],
|
||||
parent?: BrowserWindow | WebContents,
|
||||
options?: BrowserWindowConstructorOptions,
|
||||
) {
|
||||
if (parent && !(parent instanceof BrowserWindow)) {
|
||||
parent = BrowserWindow.fromWebContents(parent) ?? undefined;
|
||||
}
|
||||
|
||||
const window = createWindow(type, props, {
|
||||
parent,
|
||||
modal: !!parent,
|
||||
show: false,
|
||||
maximizable: false,
|
||||
minimizable: false,
|
||||
width: 560,
|
||||
height: 300,
|
||||
minWidth: 450,
|
||||
maxWidth: 700,
|
||||
minHeight: 300,
|
||||
maxHeight: 300,
|
||||
|
||||
...options,
|
||||
});
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
// Use a fixed window width on Windows due to a bug getting/setting window size
|
||||
window.setResizable(false);
|
||||
modal_window_width.set(window, options?.width ?? 560);
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
export function setWindowHeight(window: BrowserWindow, height: number) {
|
||||
const [curWidth, curHeight] = window.getSize();
|
||||
const [curContentWidth, curContentHeight] = window.getContentSize();
|
||||
const [minWidth, minHeight] = window.getMinimumSize();
|
||||
const [maxWidth, maxHeight] = window.getMaximumSize();
|
||||
|
||||
if (height !== curContentHeight && curHeight === minHeight && curHeight === maxHeight) {
|
||||
window.setMinimumSize(minWidth, height + (curHeight - curContentHeight));
|
||||
window.setMaximumSize(maxWidth, height + (curHeight - curContentHeight));
|
||||
}
|
||||
|
||||
window.setContentSize(modal_window_width.get(window) ?? curContentWidth, height);
|
||||
|
||||
if (!modal_window_shown.has(window)) {
|
||||
window.show();
|
||||
modal_window_shown.add(window);
|
||||
}
|
||||
}
|
||||
|
||||
const BACKGROUND_COLOUR_MAIN_LIGHT = process.platform === 'win32' ? '#ffffff' : '#ececec';
|
||||
const BACKGROUND_COLOUR_MAIN_DARK = process.platform === 'win32' ? '#000000' : '#252424';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
import createDebug from 'debug';
|
||||
import { join } from 'node:path';
|
||||
import { init as initDebug } from './util/debug.js';
|
||||
import { paths } from './util/product.js';
|
||||
|
||||
//
|
||||
// cli entrypoint for Rollup bundle
|
||||
// cli entrypoint
|
||||
//
|
||||
|
||||
createDebug.log = console.warn.bind(console);
|
||||
if (process.env.NXAPI_DEBUG_FILE !== '0') {
|
||||
await initDebug(join(paths.log, 'cli'));
|
||||
}
|
||||
|
||||
import('./cli.js').then(cli => cli.main.call(null));
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import process from 'node:process';
|
||||
import createDebug from 'debug';
|
||||
import Yargs from 'yargs';
|
||||
import * as commands from './cli/index.js';
|
||||
import { checkUpdates } from './common/update.js';
|
||||
import createDebug from './util/debug.js';
|
||||
import { dev } from './util/product.js';
|
||||
import { paths } from './util/storage.js';
|
||||
import { YargsArguments } from './util/yargs.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import process from 'node:process';
|
||||
import createDebug from 'debug';
|
||||
import createDebug from '../util/debug.js';
|
||||
import type { Arguments as ParentArguments } from '../cli.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../util/yargs.js';
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import process from 'node:process';
|
|||
import { createRequire } from 'node:module';
|
||||
import * as path from 'node:path';
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../cli.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../util/yargs.js';
|
||||
import { dir } from '../util/product.js';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import process from 'node:process';
|
||||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../cli.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { Argv, YargsArguments } from '../util/yargs.js';
|
||||
import * as commands from './nooklink/index.js';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import * as fs from 'node:fs/promises';
|
||||
import * as path from 'node:path';
|
||||
import createDebug from 'debug';
|
||||
import mkdirp from 'mkdirp';
|
||||
import type { Arguments as ParentArguments } from '../nooklink.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getUserToken } from '../../common/auth/nooklink.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../nooklink.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getUserToken, getWebServiceToken } from '../../common/auth/nooklink.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../nooklink.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getUserToken } from '../../common/auth/nooklink.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../nooklink.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getUserToken } from '../../common/auth/nooklink.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../nooklink.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getUserToken } from '../../common/auth/nooklink.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../nooklink.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getUserToken } from '../../common/auth/nooklink.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../nooklink.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getUserToken } from '../../common/auth/nooklink.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../nooklink.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getUserToken } from '../../common/auth/nooklink.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../nooklink.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getUserToken } from '../../common/auth/nooklink.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../nooklink.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getWebServiceToken } from '../../common/auth/nooklink.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import process from 'node:process';
|
||||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../cli.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { Argv, YargsArguments } from '../util/yargs.js';
|
||||
import * as commands from './nso/index.js';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getToken, Login } from '../../common/auth/coral.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getToken } from '../../common/auth/coral.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getToken } from '../../common/auth/coral.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import * as crypto from 'node:crypto';
|
||||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getToken } from '../../common/auth/coral.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getToken, Login } from '../../common/auth/coral.js';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import { PresenceState } from '../../api/coral-types.js';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { hrduration } from '../../util/misc.js';
|
||||
|
|
|
|||
|
|
@ -1,24 +1,24 @@
|
|||
import * as net from 'node:net';
|
||||
import * as os from 'node:os';
|
||||
import createDebug from 'debug';
|
||||
import * as persist from 'node-persist';
|
||||
import express, { Request, RequestHandler, Response } from 'express';
|
||||
import bodyParser from 'body-parser';
|
||||
import { v4 as uuidgen } from 'uuid';
|
||||
import { Announcement, CoralStatus, CurrentUser, Friend, FriendCodeUrl, FriendCodeUser, Presence } from '../../api/coral-types.js';
|
||||
import CoralApi from '../../api/coral.js';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import CoralApi from '../../api/coral.js';
|
||||
import { Announcement, CoralStatus, CurrentUser, Friend, FriendCodeUrl, FriendCodeUser, Presence } from '../../api/coral-types.js';
|
||||
import { AuthPolicy, AuthToken, ZncPresenceEventStreamEvent } from '../../api/znc-proxy.js';
|
||||
import { ErrorResponse } from '../../api/util.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { SavedToken } from '../../common/auth/coral.js';
|
||||
import { NotificationManager, PresenceEvent, ZncNotifications } from '../../common/notify.js';
|
||||
import { product } from '../../util/product.js';
|
||||
import { parseListenAddress } from '../../util/net.js';
|
||||
import { AuthPolicy, AuthToken, ZncPresenceEventStreamEvent } from '../../api/znc-proxy.js';
|
||||
import { addCliFeatureUserAgent } from '../../util/useragent.js';
|
||||
import { ErrorResponse } from '../../api/util.js';
|
||||
import Users, { CoralUser } from '../../common/users.js';
|
||||
import { EventStreamResponse, HttpServer, ResponseError } from '../util/http-server.js';
|
||||
import { SavedToken } from '../../common/auth/coral.js';
|
||||
import { NotificationManager, PresenceEvent, ZncNotifications } from '../../common/notify.js';
|
||||
import Users, { CoralUser } from '../../common/users.js';
|
||||
|
||||
declare global {
|
||||
namespace Express {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getToken, Login } from '../../common/auth/coral.js';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import * as path from 'node:path';
|
||||
import createDebug from 'debug';
|
||||
import persist from 'node-persist';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getToken } from '../../common/auth/coral.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import { PresencePermissions } from '../../api/coral-types.js';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getToken, Login } from '../../common/auth/coral.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getToken } from '../../common/auth/coral.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getToken } from '../../common/auth/coral.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getToken, Login } from '../../common/auth/coral.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getToken, Login } from '../../common/auth/coral.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getToken, Login } from '../../common/auth/coral.js';
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import createDebug from 'debug';
|
||||
import fetch from 'node-fetch';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../nso.js';
|
||||
import { getToken } from '../../common/auth/coral.js';
|
||||
import { AuthPolicy, AuthToken } from '../../api/znc-proxy.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { Argv } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getUserAgent } from '../../util/useragent.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../cli.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { Argv, YargsArguments } from '../util/yargs.js';
|
||||
import * as commands from './pctl/index.js';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import * as crypto from 'node:crypto';
|
||||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../pctl.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getPctlToken } from '../../common/auth/moon.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../pctl.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { hrduration } from '../../util/misc.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../pctl.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getPctlToken } from '../../common/auth/moon.js';
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import * as path from 'node:path';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import createDebug from 'debug';
|
||||
import mkdirp from 'mkdirp';
|
||||
import type { Arguments as ParentArguments } from '../pctl.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getPctlToken } from '../../common/auth/moon.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../pctl.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getPctlToken } from '../../common/auth/moon.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../pctl.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getPctlToken } from '../../common/auth/moon.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../pctl.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getPctlToken } from '../../common/auth/moon.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../pctl.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getPctlToken } from '../../common/auth/moon.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../pctl.js';
|
||||
import { getPctlToken } from '../../common/auth/moon.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
|
||||
|
|
|
|||
|
|
@ -2,26 +2,26 @@ import * as net from 'node:net';
|
|||
import * as os from 'node:os';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import * as path from 'node:path';
|
||||
import createDebug from 'debug';
|
||||
import express, { Request, Response } from 'express';
|
||||
import fetch from 'node-fetch';
|
||||
import * as persist from 'node-persist';
|
||||
import mkdirp from 'mkdirp';
|
||||
import { BankaraMatchMode, BankaraMatchSetting_schedule, CoopRule, CoopSetting_schedule, DetailFestRecordDetailResult, DetailVotingStatusResult, FestMatchSetting_schedule, FestRecordResult, FestState, FestTeam_schedule, FestTeam_votingStatus, FestVoteState, Fest_schedule, FriendListResult, FriendOnlineState, Friend_friendList, GraphQLSuccessResponse, KnownRequestId, LeagueMatchSetting_schedule, RegularMatchSetting_schedule, StageScheduleResult, VsMode, XMatchSetting_schedule } from 'splatnet3-types/splatnet3';
|
||||
import StageScheduleQuery_730cd98 from 'splatnet3-types/graphql/730cd98e84f1030d3e9ac86b6f1aae13';
|
||||
import type { Arguments as ParentArguments } from '../cli.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../util/yargs.js';
|
||||
import { initStorage } from '../util/storage.js';
|
||||
import { addCliFeatureUserAgent, getUserAgent } from '../util/useragent.js';
|
||||
import { parseListenAddress } from '../util/net.js';
|
||||
import { product, version } from '../util/product.js';
|
||||
import Users, { CoralUser } from '../common/users.js';
|
||||
import { Friend } from '../api/coral-types.js';
|
||||
import { getBulletToken, SavedBulletToken } from '../common/auth/splatnet3.js';
|
||||
import SplatNet3Api, { PersistedQueryResult, RequestIdSymbol } from '../api/splatnet3.js';
|
||||
import { ErrorResponse, ResponseSymbol } from '../api/util.js';
|
||||
import { getBulletToken, SavedBulletToken } from '../common/auth/splatnet3.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { initStorage } from '../util/storage.js';
|
||||
import { addCliFeatureUserAgent, getUserAgent } from '../util/useragent.js';
|
||||
import { parseListenAddress } from '../util/net.js';
|
||||
import { EventStreamResponse, HttpServer, ResponseError } from './util/http-server.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../util/yargs.js';
|
||||
import { getTitleIdFromEcUrl } from '../util/misc.js';
|
||||
import StageScheduleQuery_730cd98 from 'splatnet3-types/graphql/730cd98e84f1030d3e9ac86b6f1aae13';
|
||||
|
||||
const debug = createDebug('cli:presence-server');
|
||||
const debugSplatnet3Proxy = createDebug('cli:presence-server:splatnet3-proxy');
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import process from 'node:process';
|
||||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../cli.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { Argv, YargsArguments } from '../util/yargs.js';
|
||||
import * as commands from './splatnet2/index.js';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getIksmToken } from '../../common/auth/splatnet2.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getIksmToken } from '../../common/auth/splatnet2.js';
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import * as path from 'node:path';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import createDebug from 'debug';
|
||||
import mkdirp from 'mkdirp';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getIksmToken } from '../../common/auth/splatnet2.js';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import * as path from 'node:path';
|
||||
import createDebug from 'debug';
|
||||
import mkdirp from 'mkdirp';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getIksmToken } from '../../common/auth/splatnet2.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getIksmToken } from '../../common/auth/splatnet2.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import * as path from 'node:path';
|
||||
import createDebug from 'debug';
|
||||
import { getIksmToken } from '../../common/auth/splatnet2.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getIksmToken } from '../../common/auth/splatnet2.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getIksmToken } from '../../common/auth/splatnet2.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getIksmToken } from '../../common/auth/splatnet2.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getIksmToken } from '../../common/auth/splatnet2.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getIksmToken } from '../../common/auth/splatnet2.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { getAllSeasons } from '../../api/splatnet2-xrank.js';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import process from 'node:process';
|
||||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../cli.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { Argv, YargsArguments } from '../util/yargs.js';
|
||||
import * as commands from './splatnet3/index.js';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import createDebug from 'debug';
|
||||
import { Judgement } from 'splatnet3-types/splatnet3';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet3.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import * as path from 'node:path';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import createDebug from 'debug';
|
||||
import mkdirp from 'mkdirp';
|
||||
import fetch from 'node-fetch';
|
||||
import { PhotoAlbumResult } from 'splatnet3-types/splatnet3';
|
||||
import type { Arguments as ParentArguments } from '../splatnet3.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import * as path from 'node:path';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import createDebug from 'debug';
|
||||
import mkdirp from 'mkdirp';
|
||||
import { FestState, Fest_detail, RequestId } from 'splatnet3-types/splatnet3';
|
||||
import type { Arguments as ParentArguments } from '../splatnet3.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import * as path from 'node:path';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import createDebug from 'debug';
|
||||
import mkdirp from 'mkdirp';
|
||||
import type { Arguments as ParentArguments } from '../splatnet3.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import * as path from 'node:path';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import createDebug from 'debug';
|
||||
import mkdirp from 'mkdirp';
|
||||
import { BankaraBattleHistoriesRefetchResult, CoopHistoryResult, LatestBattleHistoriesRefetchResult, LatestBattleHistoriesResult, PrivateBattleHistoriesRefetchResult, RefetchableCoopHistory_CoopResultResult, RegularBattleHistoriesRefetchResult, RequestId, XBattleHistoriesRefetchResult } from 'splatnet3-types/splatnet3';
|
||||
import type { Arguments as ParentArguments } from '../splatnet3.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import createDebug from 'debug';
|
||||
import { FestState } from 'splatnet3-types/splatnet3';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet3.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet3.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import createDebug from 'debug';
|
||||
import { FriendOnlineState, Friend_friendList } from 'splatnet3-types/splatnet3';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet3.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import * as path from 'node:path';
|
||||
import createDebug from 'debug';
|
||||
import mkdirp from 'mkdirp';
|
||||
import type { Arguments as ParentArguments } from '../splatnet3.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import Table from '../util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet3.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../splatnet3.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../splatnet3.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import createDebug from 'debug';
|
||||
import * as persist from 'node-persist';
|
||||
import Table from './util/table.js';
|
||||
import type { Arguments as ParentArguments } from '../cli.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { Argv } from '../util/yargs.js';
|
||||
import { initStorage, iterateLocalStorage } from '../util/storage.js';
|
||||
import { SavedToken } from '../common/auth/coral.js';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../cli.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { Argv, YargsArguments } from '../util/yargs.js';
|
||||
import { dev } from '../util/product.js';
|
||||
import * as commands from './util/index.js';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import * as crypto from 'node:crypto';
|
||||
import { Buffer } from 'node:buffer';
|
||||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../util.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { Argv } from '../../util/yargs.js';
|
||||
|
||||
const debug = createDebug('cli:util:captureid');
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import process from 'node:process';
|
||||
import createDebug from 'debug';
|
||||
import fetch from 'node-fetch';
|
||||
import { getPresenceFromUrl } from '../../api/znc-proxy.js';
|
||||
import { ActiveEvent, CurrentUser, Friend, Game, Presence, PresenceState } from '../../api/coral-types.js';
|
||||
import type { Arguments as ParentArguments } from '../util.js';
|
||||
import { getDiscordPresence, getInactiveDiscordPresence } from '../../discord/util.js';
|
||||
import { DiscordPresenceContext, DiscordPresencePlayTime } from '../../discord/types.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getToken, Login } from '../../common/auth/coral.js';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import createDebug from 'debug';
|
||||
import type { Arguments as ParentArguments } from '../util.js';
|
||||
import { DiscordRpcClient, getAllIpcSockets } from '../../discord/rpc.js';
|
||||
import { defaultTitle } from '../../discord/titles.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
|
||||
const debug = createDebug('cli:util:discord-rpc');
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import fetch from 'node-fetch';
|
||||
import type { Arguments as ParentArguments } from '../util.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { titles as unsorted_titles } from '../../discord/titles.js';
|
||||
import { DiscordApplicationRpc, getDiscordApplicationRpc } from './discord-activity.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import createDebug from 'debug';
|
||||
import { NextFunction, Request, RequestHandler, Response } from 'express';
|
||||
import { ErrorResponse } from '../../api/util.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { temporary_http_errors, temporary_system_errors } from '../../util/errors.js';
|
||||
|
||||
const debug = createDebug('cli:util:http-server');
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user