mirror of
https://github.com/samuelthomas2774/nxapi.git
synced 2026-04-24 23:16:53 -05:00
Fix f parameter generation
This fixes `f` parameter generation with nxapi's custom server. This will also work with imink/flapg *if the system time exactly matches the imink/flapg Android device's time*. This commit also makes nxapi's API compatible with imink's API and adds some information about the Android device and NSO app to response headers.
This commit is contained in:
parent
7a37d7f7df
commit
428f7131a1
|
|
@ -60,7 +60,7 @@ export interface AccountLoginParameter {
|
|||
naBirthday: string;
|
||||
naCountry: string;
|
||||
language: string;
|
||||
timestamp: string;
|
||||
timestamp: number;
|
||||
requestId: string;
|
||||
f: string;
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ export type AccountToken = AccountLogin;
|
|||
export interface AccountTokenParameter {
|
||||
naIdToken: string;
|
||||
naBirthday: string;
|
||||
timestamp: string;
|
||||
timestamp: number;
|
||||
requestId: string;
|
||||
f: string;
|
||||
}
|
||||
|
|
@ -188,6 +188,20 @@ export interface WebServiceAttribute {
|
|||
attrKey: string;
|
||||
}
|
||||
|
||||
export interface WebServiceTokenParameter {
|
||||
id: number;
|
||||
registrationToken: string;
|
||||
timestamp: number;
|
||||
requestId: string;
|
||||
f: string;
|
||||
}
|
||||
|
||||
/** /v2/Game/GetWebServiceToken */
|
||||
export interface WebServiceToken {
|
||||
accessToken: string;
|
||||
expiresIn: number;
|
||||
}
|
||||
|
||||
/** /v1/Event/GetActiveEvent */
|
||||
export type GetActiveEventResult = ActiveEvent | {};
|
||||
|
||||
|
|
@ -281,9 +295,3 @@ export interface UpdateCurrentUserPermissionsParameter {
|
|||
};
|
||||
etag: string;
|
||||
}
|
||||
|
||||
/** /v2/Game/GetWebServiceToken */
|
||||
export interface WebServiceToken {
|
||||
accessToken: string;
|
||||
expiresIn: number;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import fetch, { Response } from 'node-fetch';
|
||||
import { v4 as uuidgen } from 'uuid';
|
||||
import createDebug from 'debug';
|
||||
import { f, FlapgIid, FResult } from './f.js';
|
||||
import { f, FResult } from './f.js';
|
||||
import { AccountLogin, AccountToken, Announcements, CurrentUser, CurrentUserPermissions, Event, Friends, GetActiveEventResult, PresencePermissions, User, WebServices, WebServiceToken, CoralErrorResponse, CoralResponse, CoralStatus, CoralSuccessResponse, FriendCodeUser, FriendCodeUrl, AccountTokenParameter, AccountLoginParameter } from './coral-types.js';
|
||||
import { getNintendoAccountToken, getNintendoAccountUser, NintendoAccountToken, NintendoAccountUser } from './na.js';
|
||||
import { ErrorResponse } from './util.js';
|
||||
|
|
@ -178,17 +178,14 @@ export default class CoralApi {
|
|||
}
|
||||
|
||||
async getWebServiceToken(id: string) {
|
||||
const uuid = uuidgen();
|
||||
const timestamp = '' + Math.floor(Date.now() / 1000);
|
||||
|
||||
const data = await f(this.token, timestamp, uuid, FlapgIid.APP, this.useragent ?? getAdditionalUserAgents());
|
||||
const data = await f(this.token, '2', this.useragent ?? getAdditionalUserAgents());
|
||||
|
||||
const req = {
|
||||
id,
|
||||
registrationToken: this.token,
|
||||
registrationToken: '',
|
||||
f: data.f,
|
||||
requestId: uuid,
|
||||
timestamp,
|
||||
requestId: data.request_id,
|
||||
timestamp: data.timestamp,
|
||||
};
|
||||
|
||||
return this.call<WebServiceToken>('/v2/Game/GetWebServiceToken', req);
|
||||
|
|
@ -198,27 +195,19 @@ export default class CoralApi {
|
|||
// Nintendo Account token
|
||||
const nintendoAccountToken = await getNintendoAccountToken(token, ZNCA_CLIENT_ID);
|
||||
|
||||
const uuid = uuidgen();
|
||||
const timestamp = '' + Math.floor(Date.now() / 1000);
|
||||
|
||||
const fdata = await f(
|
||||
nintendoAccountToken.id_token, timestamp, uuid,
|
||||
FlapgIid.NSO, this.useragent ?? getAdditionalUserAgents()
|
||||
);
|
||||
const fdata = await f(nintendoAccountToken.id_token, '1', this.useragent ?? getAdditionalUserAgents());
|
||||
|
||||
const req: AccountTokenParameter = {
|
||||
naBirthday: user.birthday,
|
||||
timestamp,
|
||||
timestamp: fdata.timestamp,
|
||||
f: fdata.f,
|
||||
requestId: uuid,
|
||||
requestId: fdata.request_id,
|
||||
naIdToken: nintendoAccountToken.id_token,
|
||||
};
|
||||
|
||||
const data = await this.call<AccountToken>('/v3/Account/GetToken', req, false);
|
||||
|
||||
return {
|
||||
uuid,
|
||||
timestamp,
|
||||
nintendoAccountToken,
|
||||
// user,
|
||||
f: fdata,
|
||||
|
|
@ -261,13 +250,7 @@ export default class CoralApi {
|
|||
// Nintendo Account user data
|
||||
const user = await getNintendoAccountUser(nintendoAccountToken);
|
||||
|
||||
const uuid = uuidgen();
|
||||
const timestamp = '' + Math.floor(Date.now() / 1000);
|
||||
|
||||
const fdata = await f(
|
||||
nintendoAccountToken.id_token, timestamp, uuid,
|
||||
FlapgIid.NSO, useragent
|
||||
);
|
||||
const fdata = await f(nintendoAccountToken.id_token, '1', useragent);
|
||||
|
||||
debug('Getting Nintendo Switch Online app token');
|
||||
|
||||
|
|
@ -276,8 +259,8 @@ export default class CoralApi {
|
|||
naBirthday: user.birthday,
|
||||
naCountry: user.country,
|
||||
language: user.language,
|
||||
timestamp,
|
||||
requestId: uuid,
|
||||
timestamp: fdata.timestamp,
|
||||
requestId: fdata.request_id,
|
||||
f: fdata.f,
|
||||
};
|
||||
|
||||
|
|
@ -314,8 +297,6 @@ export default class CoralApi {
|
|||
debug('Got Nintendo Switch Online app token', data);
|
||||
|
||||
return {
|
||||
uuid,
|
||||
timestamp,
|
||||
nintendoAccountToken,
|
||||
user,
|
||||
f: fdata,
|
||||
|
|
@ -328,8 +309,6 @@ export default class CoralApi {
|
|||
}
|
||||
|
||||
export interface CoralAuthData {
|
||||
uuid: string;
|
||||
timestamp: string;
|
||||
nintendoAccountToken: NintendoAccountToken;
|
||||
user: NintendoAccountUser;
|
||||
f: FResult;
|
||||
|
|
@ -340,7 +319,7 @@ export interface CoralAuthData {
|
|||
}
|
||||
|
||||
export type PartialCoralAuthData =
|
||||
Pick<CoralAuthData, 'uuid' | 'timestamp' | 'nintendoAccountToken' | 'f' | 'nsoAccount' | 'credential'>;
|
||||
Pick<CoralAuthData, 'nintendoAccountToken' | 'f' | 'nsoAccount' | 'credential'>;
|
||||
|
||||
export interface CoralJwtPayload extends JwtPayload {
|
||||
isChildRestricted: boolean;
|
||||
|
|
|
|||
66
src/api/f.ts
66
src/api/f.ts
|
|
@ -1,6 +1,7 @@
|
|||
import process from 'node:process';
|
||||
import fetch from 'node-fetch';
|
||||
import createDebug from 'debug';
|
||||
import { v4 as uuidgen } from 'uuid';
|
||||
import { ErrorResponse } from './util.js';
|
||||
import { timeoutSignal } from '../util/misc.js';
|
||||
import { getUserAgent } from '../util/useragent.js';
|
||||
|
|
@ -15,7 +16,7 @@ export abstract class ZncaApi {
|
|||
public useragent?: string
|
||||
) {}
|
||||
|
||||
abstract genf(token: string, timestamp: string, uuid: string, type: FlapgIid): Promise<FResult>;
|
||||
abstract genf(token: string, hash_method: '1' | '2'): Promise<FResult>;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -123,12 +124,16 @@ export class ZncaApiFlapg extends ZncaApi {
|
|||
return getLoginHash(id_token, timestamp, this.useragent);
|
||||
}
|
||||
|
||||
async genf(token: string, timestamp: string, uuid: string, type: FlapgIid) {
|
||||
const result = await flapg(token, timestamp, uuid, type, this.useragent);
|
||||
async genf(token: string, hash_method: '1' | '2') {
|
||||
const timestamp = Date.now();
|
||||
const request_id = uuidgen();
|
||||
const type = hash_method === '2' ? FlapgIid.APP : FlapgIid.NSO;
|
||||
|
||||
const result = await flapg(token, timestamp, request_id, type, this.useragent);
|
||||
|
||||
return {
|
||||
provider: 'flapg' as const,
|
||||
token, timestamp, uuid, type,
|
||||
token, timestamp, request_id, hash_method, type,
|
||||
f: result.result.f,
|
||||
result,
|
||||
};
|
||||
|
|
@ -198,12 +203,15 @@ export interface IminkFError {
|
|||
}
|
||||
|
||||
export class ZncaApiImink extends ZncaApi {
|
||||
async genf(token: string, timestamp: string, uuid: string, type: FlapgIid) {
|
||||
const result = await iminkf(token, timestamp, uuid, type === FlapgIid.APP ? '2' : '1', this.useragent);
|
||||
async genf(token: string, hash_method: '1' | '2') {
|
||||
const timestamp = Date.now();
|
||||
const request_id = uuidgen();
|
||||
|
||||
const result = await iminkf(token, timestamp, request_id, hash_method, this.useragent);
|
||||
|
||||
return {
|
||||
provider: 'imink' as const,
|
||||
token, timestamp, uuid, type,
|
||||
token, timestamp, request_id, hash_method,
|
||||
f: result.f,
|
||||
result,
|
||||
};
|
||||
|
|
@ -215,18 +223,19 @@ export class ZncaApiImink extends ZncaApi {
|
|||
//
|
||||
|
||||
export async function genf(
|
||||
url: string, token: string, timestamp: string | number, uuid: string, type: FlapgIid,
|
||||
url: string, hash_method: '1' | '2',
|
||||
token: string, timestamp?: number, request_id?: string,
|
||||
useragent?: string
|
||||
) {
|
||||
debugZncaApi('Getting f parameter', {
|
||||
url, token, timestamp, uuid,
|
||||
url, token, timestamp, request_id,
|
||||
});
|
||||
|
||||
const req: AndroidZncaFRequest = {
|
||||
type,
|
||||
hash_method,
|
||||
token,
|
||||
timestamp: '' + timestamp,
|
||||
uuid,
|
||||
timestamp,
|
||||
request_id,
|
||||
};
|
||||
|
||||
const [signal, cancel] = timeoutSignal();
|
||||
|
|
@ -251,19 +260,21 @@ export async function genf(
|
|||
throw new ErrorResponse('[znca-api] ' + data.error, response, data);
|
||||
}
|
||||
|
||||
debugZncaApi('Got f parameter "%s"', data.f);
|
||||
debugZncaApi('Got f parameter', data, response.headers);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
export interface AndroidZncaFRequest {
|
||||
type: FlapgIid;
|
||||
hash_method: '1' | '2';
|
||||
token: string;
|
||||
timestamp: string;
|
||||
uuid: string;
|
||||
timestamp?: string | number;
|
||||
request_id?: string;
|
||||
}
|
||||
export interface AndroidZncaFResponse {
|
||||
f: string;
|
||||
timestamp?: number;
|
||||
request_id?: string;
|
||||
}
|
||||
export interface AndroidZncaFError {
|
||||
error: string;
|
||||
|
|
@ -274,38 +285,39 @@ export class ZncaApiNxapi extends ZncaApi {
|
|||
super(useragent);
|
||||
}
|
||||
|
||||
async genf(token: string, timestamp: string, uuid: string, type: FlapgIid) {
|
||||
const result = await genf(this.url + '/f', token, timestamp, uuid, type, this.useragent);
|
||||
async genf(token: string, hash_method: '1' | '2') {
|
||||
const result = await genf(this.url + '/f', hash_method, token, undefined, undefined, this.useragent);
|
||||
|
||||
return {
|
||||
provider: 'nxapi' as const,
|
||||
url: this.url + '/f',
|
||||
token, timestamp, uuid, type,
|
||||
token,
|
||||
timestamp: result.timestamp!, // will be included as not sent in request
|
||||
request_id: result.request_id!,
|
||||
hash_method,
|
||||
f: result.f,
|
||||
result,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function f(
|
||||
token: string, timestamp: string | number, uuid: string, type: FlapgIid,
|
||||
useragent?: string
|
||||
): Promise<FResult> {
|
||||
export async function f(token: string, hash_method: '1' | '2', useragent?: string): Promise<FResult> {
|
||||
const provider = getPreferredZncaApiFromEnvironment(useragent) ?? await getDefaultZncaApi(useragent);
|
||||
|
||||
return provider.genf(token, '' + timestamp, uuid, type);
|
||||
return provider.genf(token, hash_method);
|
||||
}
|
||||
|
||||
export type FResult = {
|
||||
provider: string;
|
||||
token: string;
|
||||
timestamp: string;
|
||||
uuid: string;
|
||||
type: FlapgIid;
|
||||
timestamp: number;
|
||||
request_id: string;
|
||||
hash_method: '1' | '2';
|
||||
f: string;
|
||||
result: unknown;
|
||||
} & ({
|
||||
provider: 'flapg';
|
||||
type: FlapgIid;
|
||||
result: FlapgApiResponse;
|
||||
} | {
|
||||
provider: 'imink';
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import * as net from 'node:net';
|
|||
import * as fs from 'node:fs/promises';
|
||||
import * as crypto from 'node:crypto';
|
||||
import createDebug from 'debug';
|
||||
import { v4 as uuidgen } from 'uuid';
|
||||
import express from 'express';
|
||||
import bodyParser from 'body-parser';
|
||||
import mkdirp from 'mkdirp';
|
||||
|
|
@ -50,6 +51,45 @@ export function builder(yargs: Argv<ParentArguments>) {
|
|||
|
||||
type Arguments = YargsArguments<ReturnType<typeof builder>>;
|
||||
|
||||
interface PackageInfo {
|
||||
name: string;
|
||||
version: string;
|
||||
build: number;
|
||||
}
|
||||
interface SystemInfo {
|
||||
board: string;
|
||||
bootloader: string;
|
||||
brand: string;
|
||||
abis: string[];
|
||||
device: string;
|
||||
display: string;
|
||||
fingerprint: string;
|
||||
hardware: string;
|
||||
host: string;
|
||||
id: string;
|
||||
manufacturer: string;
|
||||
model: string;
|
||||
product: string;
|
||||
tags: string;
|
||||
time: string;
|
||||
type: string;
|
||||
user: string;
|
||||
|
||||
version: {
|
||||
codename: string;
|
||||
release: string;
|
||||
// release_display: string;
|
||||
sdk: string;
|
||||
sdk_int: number;
|
||||
security_patch: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface FResult {
|
||||
f: string;
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
||||
await mkdirp(script_dir);
|
||||
|
||||
|
|
@ -61,10 +101,15 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
|
||||
let api: {
|
||||
ping(): Promise<true>;
|
||||
genAudioH(token: string, timestamp: string, uuid: string): Promise<string>;
|
||||
genAudioH2(token: string, timestamp: string, uuid: string): Promise<string>;
|
||||
getPackageInfo(): Promise<PackageInfo>;
|
||||
getSystemInfo(): Promise<SystemInfo>;
|
||||
genAudioH(token: string, timestamp: string | number | undefined, request_id: string): Promise<FResult>;
|
||||
genAudioH2(token: string, timestamp: string | number | undefined, request_id: string): Promise<FResult>;
|
||||
} = script.exports as any;
|
||||
|
||||
let system_info = await api.getSystemInfo();
|
||||
let package_info = await api.getPackageInfo();
|
||||
|
||||
const onexit = (code: number | NodeJS.Signals) => {
|
||||
// @ts-expect-error
|
||||
process.removeListener('exit', onexit);
|
||||
|
|
@ -89,11 +134,24 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
|
||||
debug('Attempting to reconnect to the device');
|
||||
|
||||
ready = attach(argv).then(a => {
|
||||
ready = attach(argv).then(async a => {
|
||||
ready = null;
|
||||
session = a.session;
|
||||
script = a.script;
|
||||
api = script.exports as any;
|
||||
|
||||
const new_system_info = await api.getSystemInfo();
|
||||
const new_package_info = await api.getPackageInfo();
|
||||
|
||||
if (system_info.version.sdk_int !== new_system_info.version.sdk_int) {
|
||||
debug('Android system version updated while disconnected');
|
||||
}
|
||||
if (package_info.build !== new_package_info.build) {
|
||||
debug('znca version updated while disconnected');
|
||||
}
|
||||
|
||||
system_info = new_system_info;
|
||||
package_info = new_package_info;
|
||||
}).catch(err => {
|
||||
console.error('Reattach failed', err);
|
||||
process.exit(1);
|
||||
|
|
@ -110,6 +168,12 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
req.headers['user-agent']);
|
||||
|
||||
res.setHeader('Server', product + ' android-znca-api-frida');
|
||||
res.setHeader('X-Android-Build-Type', system_info.type);
|
||||
res.setHeader('X-Android-Release', system_info.version.release);
|
||||
res.setHeader('X-Android-Platform-Version', system_info.version.sdk_int);
|
||||
res.setHeader('X-znca-Platform', 'Android');
|
||||
res.setHeader('X-znca-Version', package_info.version);
|
||||
res.setHeader('X-znca-Build', package_info.build);
|
||||
|
||||
next();
|
||||
});
|
||||
|
|
@ -118,19 +182,34 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
try {
|
||||
await ready;
|
||||
|
||||
const data: {
|
||||
let data: {
|
||||
hash_method: '1' | '2';
|
||||
token: string;
|
||||
timestamp?: string | number;
|
||||
request_id?: string;
|
||||
} | {
|
||||
type: 'nso' | 'app';
|
||||
token: string;
|
||||
timestamp: string;
|
||||
uuid: string;
|
||||
timestamp?: string;
|
||||
uuid?: string;
|
||||
} = req.body;
|
||||
|
||||
if (data && 'type' in data) data = {
|
||||
hash_method:
|
||||
data.type === 'nso' ? '1' :
|
||||
data.type === 'app' ? '2' : null!,
|
||||
token: data.token,
|
||||
timestamp: '' + data.timestamp,
|
||||
request_id: data.uuid,
|
||||
};
|
||||
|
||||
if (
|
||||
!data ||
|
||||
typeof data !== 'object' ||
|
||||
(data.type !== 'nso' && data.type !== 'app') ||
|
||||
(data.hash_method !== '1' && data.hash_method !== '2') ||
|
||||
typeof data.token !== 'string' ||
|
||||
typeof data.timestamp !== 'string' ||
|
||||
typeof data.uuid !== 'string'
|
||||
(data.timestamp && typeof data.timestamp !== 'string' && typeof data.timestamp !== 'number') ||
|
||||
(data.request_id && typeof data.request_id !== 'string')
|
||||
) {
|
||||
res.statusCode = 400;
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
|
|
@ -143,13 +222,13 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
|
||||
const check_signature = jwt.payload.iss === 'https://accounts.nintendo.com';
|
||||
|
||||
if (data.type === 'nso' && jwt.payload.iss !== 'https://accounts.nintendo.com') {
|
||||
if (data.hash_method === '1' && jwt.payload.iss !== 'https://accounts.nintendo.com') {
|
||||
throw new Error('Invalid token issuer');
|
||||
}
|
||||
if (data.type === 'nso' && jwt.payload.aud !== ZNCA_CLIENT_ID) {
|
||||
if (data.hash_method === '1' && jwt.payload.aud !== ZNCA_CLIENT_ID) {
|
||||
throw new Error('Invalid token audience');
|
||||
}
|
||||
if (data.type === 'app' && jwt.payload.iss !== 'api-lp1.znc.srv.nintendo.net') {
|
||||
if (data.hash_method === '2' && jwt.payload.iss !== 'api-lp1.znc.srv.nintendo.net') {
|
||||
throw new Error('Invalid token issuer');
|
||||
}
|
||||
|
||||
|
|
@ -197,16 +276,21 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
}
|
||||
}
|
||||
|
||||
debugApi('Calling %s', data.type === 'app' ? 'genAudioH2' : 'genAudioH');
|
||||
const timestamp = data.timestamp ? '' + data.timestamp : undefined;
|
||||
const request_id = data.request_id ? data.request_id : uuidgen();
|
||||
|
||||
const result = data.type === 'app' ?
|
||||
await api.genAudioH2(data.token, data.timestamp, data.uuid) :
|
||||
await api.genAudioH(data.token, data.timestamp, data.uuid);
|
||||
debugApi('Calling %s', data.hash_method === '2' ? 'genAudioH2' : 'genAudioH');
|
||||
|
||||
const result = data.hash_method === '2' ?
|
||||
await api.genAudioH2(data.token, timestamp, request_id) :
|
||||
await api.genAudioH(data.token, timestamp, request_id);
|
||||
|
||||
debugApi('Returned %s', result);
|
||||
|
||||
const response = {
|
||||
f: result,
|
||||
f: result.f,
|
||||
timestamp: data.timestamp ? undefined : result.timestamp,
|
||||
request_id: data.request_id ? undefined : request_id,
|
||||
};
|
||||
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
|
|
@ -245,29 +329,108 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
throw err;
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
debug('System info', system_info);
|
||||
debug('Package info', package_info);
|
||||
|
||||
try {
|
||||
debug('Test gen_audio_h');
|
||||
const result = await api.genAudioH('id_token', 'timestamp', 'request_id');
|
||||
debug('Test returned', result);
|
||||
} catch (err) {
|
||||
debug('Test failed', err);
|
||||
}
|
||||
}
|
||||
|
||||
const frida_script = `
|
||||
const perform = callback => new Promise((rs, rj) => {
|
||||
Java.scheduleOnMainThread(() => {
|
||||
try {
|
||||
rs(callback());
|
||||
} catch (err) {
|
||||
rj(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
rpc.exports = {
|
||||
ping() {
|
||||
return true;
|
||||
},
|
||||
genAudioH(token, timestamp, uuid) {
|
||||
return new Promise(resolve => {
|
||||
Java.perform(() => {
|
||||
const libvoip = Java.use('com.nintendo.coral.core.services.voip.LibvoipJni');
|
||||
getPackageInfo() {
|
||||
return perform(() => {
|
||||
const context = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext();
|
||||
|
||||
resolve(libvoip.genAudioH(token, timestamp, uuid));
|
||||
});
|
||||
const info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
|
||||
|
||||
return {
|
||||
name: info.packageName.value,
|
||||
version: info.versionName.value,
|
||||
build: info.versionCode.value,
|
||||
// build: info.getLongVersionCode(),
|
||||
};
|
||||
});
|
||||
},
|
||||
genAudioH2(token, timestamp, uuid) {
|
||||
return new Promise(resolve => {
|
||||
Java.perform(() => {
|
||||
const libvoip = Java.use('com.nintendo.coral.core.services.voip.LibvoipJni');
|
||||
getSystemInfo() {
|
||||
return perform(() => {
|
||||
const Build = Java.use('android.os.Build');
|
||||
const Version = Java.use('android.os.Build$VERSION');
|
||||
|
||||
resolve(libvoip.genAudioH2(token, timestamp, uuid));
|
||||
});
|
||||
return {
|
||||
board: Build.BOARD.value,
|
||||
bootloader: Build.BOOTLOADER.value,
|
||||
brand: Build.BRAND.value,
|
||||
abis: Build.SUPPORTED_ABIS.value,
|
||||
device: Build.DEVICE.value,
|
||||
display: Build.DISPLAY.value,
|
||||
fingerprint: Build.FINGERPRINT.value,
|
||||
hardware: Build.HARDWARE.value,
|
||||
host: Build.HOST.value,
|
||||
id: Build.ID.value,
|
||||
manufacturer: Build.MANUFACTURER.value,
|
||||
model: Build.MODEL.value,
|
||||
product: Build.PRODUCT.value,
|
||||
tags: Build.TAGS.value,
|
||||
time: Build.TIME.value,
|
||||
type: Build.TYPE.value,
|
||||
user: Build.USER.value,
|
||||
|
||||
version: {
|
||||
codename: Version.CODENAME.value,
|
||||
release: Version.RELEASE.value,
|
||||
sdk: Version.SDK.value,
|
||||
sdk_int: Version.SDK_INT.value,
|
||||
security_patch: Version.SECURITY_PATCH.value,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
genAudioH(token, timestamp, request_id) {
|
||||
return perform(() => {
|
||||
const libvoip = Java.use('com.nintendo.coral.core.services.voip.LibvoipJni');
|
||||
const context = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext();
|
||||
libvoip.init(context);
|
||||
|
||||
if (!timestamp) timestamp = Date.now();
|
||||
|
||||
return {
|
||||
f: libvoip.genAudioH(token, '' + timestamp, request_id),
|
||||
timestamp,
|
||||
};
|
||||
});
|
||||
},
|
||||
genAudioH2(token, timestamp, request_id) {
|
||||
return perform(() => {
|
||||
const libvoip = Java.use('com.nintendo.coral.core.services.voip.LibvoipJni');
|
||||
const context = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext();
|
||||
libvoip.init(context);
|
||||
|
||||
if (!timestamp) timestamp = Date.now();
|
||||
|
||||
return {
|
||||
f: libvoip.genAudioH2(token, '' + timestamp, request_id),
|
||||
timestamp,
|
||||
};
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user