Skip to content

Commit

Permalink
Add nxapi-powered NSO client
Browse files Browse the repository at this point in the history
  • Loading branch information
misenhower committed Sep 9, 2022
1 parent eea6984 commit 9bd16d2
Show file tree
Hide file tree
Showing 6 changed files with 2,254 additions and 42 deletions.
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# Nintendo API
NINTENDO_TOKEN=

# User agent string
USER_AGENT=

# Twitter API parameters
TWITTER_CONSUMER_KEY=
TWITTER_CONSUMER_SECRET=
Expand Down
45 changes: 45 additions & 0 deletions app/common/ValueCache.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import fs from 'fs/promises';

export default class ValueCache
{
constructor(key) {
this._key = key;
}

get path() {
return `storage/${this._key}.json`;
}

async _getRawItem() {
try {
let data = await fs.readFile(this.path);

return JSON.parse(data);
} catch (e) {
return null;
}
}

async get() {
let item = await this._getRawItem();

// If the cached value is already expired, return null
if (item && item.expires && item.expires < new Date) {
return null;
}

return item;
}

async getData() {
let item = await this.get();

return item && item.data;
}

async setData(data, expires = null) {
let serialized = JSON.stringify({ expires, data }, undefined, 2);

await fs.writeFile(this.path, serialized);
}
}
75 changes: 75 additions & 0 deletions app/nso/NsoClient.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import CoralApi from 'nxapi/coral';
import { addUserAgent } from "nxapi";
import ValueCache from '../common/ValueCache.mjs';

let _nxapiInitialized = false;

function initializeNxapi() {
if (!_nxapiInitialized) {
addUserAgent(process.env.USER_AGENT);
}

_nxapiInitialized = true;
}

export default class NsoClient
{
constructor(nintendoToken = null) {
initializeNxapi();

this.nintendoToken = nintendoToken || process.env.NINTENDO_TOKEN;
this.coralCache = new ValueCache('coral');
}

_calculateCacheExpiry(expiresIn) {
let expires = Date.now() + expiresIn * 1000;

// Expire 5min early to make sure we have time to execute requests
return expires - 5 * 60 * 1000;
}

async getCoralApi() {
let data = await this.coralCache.getData();

if (!data) {
data = await this._createCoralSession();
}

return CoralApi.createWithSavedToken(data);
}

async _createCoralSession() {
console.debug('Creating Coral session');
let { data } = await CoralApi.createWithSessionToken(this.nintendoToken);

let expires = this._calculateCacheExpiry(data.credential.expiresIn);
console.debug(`Caching Coral session until: ${expires}`);
await this.coralCache.setData(data, expires);

return data;
}

async getWebServiceToken(id) {
let tokenCache = new ValueCache(`webservicetoken.${id}`);
let token = await tokenCache.getData();

if (!token) {
token = await this._createWebServiceToken(id, tokenCache);
}

return token.accessToken;
}

async _createWebServiceToken(id, tokenCache) {
let coral = await this.getCoralApi();

console.debug(`Creating web service token for ID ${id}`);
let { result } = await coral.getWebServiceToken(id);

let expires = this._calculateCacheExpiry(result.expiresIn);
console.debug(`Caching web service token for ID ${id} until: ${expires}`);
await tokenCache.setData(result, expires);

return result;
}
}
Loading

0 comments on commit 9bd16d2

Please sign in to comment.