Skip to content

Commit

Permalink
New listener updateOengusSchedule
Browse files Browse the repository at this point in the history
Listener that will receive data with the marathon name and an Oengus schedule with runs that will be updated on Oengus.
Only the runs included will be modified (matching on id) and you cannot add nor delete runs
  • Loading branch information
gaeldemarseille committed Apr 17, 2021
1 parent 84a5d2f commit e1e1081
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 1 deletion.
1 change: 1 addition & 0 deletions configschema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface Configschema {
};
oengus: {
defaultMarathon: string;
token?: string;
useJapanese: boolean;
disableSpeedrunComLookup: boolean;
};
Expand Down
4 changes: 4 additions & 0 deletions configschema.json
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@
"type": "string",
"default": "SHORTNAME"
},
"token": {
"type": "string",
"default": "TOKEN"
},
"useJapanese": {
"type": "boolean",
"default": false
Expand Down
1 change: 1 addition & 0 deletions schemas/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './defaultSetupTime';
export * from './horaroImportSavedOpts';
export * from './horaroImportStatus';
export * from './oengusImportStatus';
export * from './oengusUpdateStatus';
export * from './runDataActiveRun';
export * from './runDataActiveRunSurrounding';
export * from './runDataArray';
Expand Down
10 changes: 10 additions & 0 deletions schemas/oengusUpdateStatus.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* tslint:disable */
/**
* This file was automatically generated by json-schema-to-typescript.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run json-schema-to-typescript to regenerate this file.
*/

export interface OengusUpdateStatus {
updating?: boolean;
}
11 changes: 11 additions & 0 deletions schemas/oengusUpdateStatus.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"additionalProperties": false,
"properties": {
"updating": {
"type": "boolean",
"default": false
}
}
}
90 changes: 89 additions & 1 deletion src/extension/oengus-import.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import { Duration, parse as isoParse, toSeconds } from 'iso8601-duration';
import needle, { NeedleResponse } from 'needle';
import { mapSeries } from 'p-iteration';
import { DefaultSetupTime, OengusImportStatus } from 'schemas';
import { DefaultSetupTime, OengusImportStatus, OengusUpdateStatus } from 'schemas';
import { OengusMarathon, OengusSchedule, RunData, RunDataArray, RunDataPlayer, RunDataTeam } from 'types'; // eslint-disable-line object-curly-newline, max-len
import { v4 as uuid } from 'uuid';
import { searchForTwitchGame, searchForUserDataMultiple } from './srcom-api';
import { verifyTwitchDir } from './twitch-api';
import { bundleConfig, checkGameAgainstIgnoreList, getTwitchUserFromURL, padTimeNumber, processAck, to } from './util/helpers'; // eslint-disable-line object-curly-newline, max-len
import { get as ncgGet } from './util/nodecg';
import * as events from './util/events';

const nodecg = ncgGet();
const config = bundleConfig();
const importStatus = nodecg.Replicant<OengusImportStatus>('oengusImportStatus', {
persistent: false,
});
const updateStatus = nodecg.Replicant<OengusUpdateStatus>('oengusUpdateStatus', {
persistent: false,
});
const runDataArray = nodecg.Replicant<RunDataArray>('runDataArray');
const defaultSetupTime = nodecg.Replicant<DefaultSetupTime>('defaultSetupTime');

Expand Down Expand Up @@ -50,6 +54,44 @@ async function get(endpoint: string): Promise<NeedleResponse> {
}
}

/**
* Make a PUT request to Oengus API.
* @param endpoint Oengus API endpoint you want to access.
* @param oengusSchedule Oengus schedule.
*/
async function put(endpoint: string, oengusSchedule: any): Promise<void> {
if (config.oengus.token) {
try {
nodecg.log.debug(`[Oengus Update] API request processing on ${endpoint}`);
const resp = await needle(
'put',
`https://oengus.io/api${endpoint}`,
oengusSchedule,
{
headers: {
'Authorization': `Bearer ${config.oengus.token}`,
'User-Agent': 'nodecg-speedcontrol',
'Content-Type': 'application/json',
},
},
);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: parser exists but isn't in the typings
if (resp.statusCode !== 204) {
throw new Error('Response status was not 204' + JSON.stringify(resp.body));
}
nodecg.log.debug(`[Oengus Update] API request successful on ${endpoint}`);
} catch (err) {
nodecg.log.debug(`[Oengus Update] API request error on ${endpoint}:`, err);
throw err;
}
} else {
nodecg.log.debug(`[Oengus Update] No Authorization provided`);
throw new Error('No Authorization provided');
}
}


/**
* Format to time string from Duration object.
* @param duration Duration object you want to format.
Expand Down Expand Up @@ -82,6 +124,14 @@ function resetImportStatus(): void {
nodecg.log.debug('[Oengus Import] Import status restored to default');
}

/**
* Resets the replicant's values to default.
*/
function resetUpdateStatus(): void {
updateStatus.value.updating = false;
nodecg.log.debug('[Oengus Update] Export status restored to default');
}

/**
* Import schedule data in from Oengus.
* @param marathonShort Oengus' marathon shortname you want to import.
Expand Down Expand Up @@ -223,3 +273,41 @@ nodecg.listenFor('importOengusSchedule', async (data, ack) => {
processAck(ack, err);
}
});

events.listenFor('updateOengusSchedule', async (data, ack) => {
try {
if (updateStatus.value.updating) {
throw new Error('Already exporting schedule');
}
nodecg.log.info('[Oengus Update] Started exporting schedule');
var schedule = data.schedule;
if (!isOengusSchedule(schedule)) {
throw new Error('Did not receive schedule data from bundle correctly');
}
var marathonName = data.marathonName;
if(!marathonName){
throw new Error('No marathon name set');
}

const getResponse = await get(`/marathon/${marathonName}/schedule`);
if (!isOengusSchedule(getResponse.body)) {
throw new Error('Did not receive schedule data from Oengus');
}
var oengusSchedule = getResponse.body;

schedule.lines.forEach( runWithUpdatedValues =>{
var currentRun = oengusSchedule.lines.find(run => run.id === runWithUpdatedValues.id);
if(!currentRun){
throw new Error(`Did not find run with oengus id:${runWithUpdatedValues.id} `);
}
Object.assign(currentRun, runWithUpdatedValues);
});

await put(`/marathon/${marathonName}/schedule`, oengusSchedule);
nodecg.log.info('[Oengus Update] Successfully updated schedule to Oengus');
processAck(ack, null);
} catch (err) {
nodecg.log.warn('[Oengus Update] Error updating schedule:', err);
processAck(ack, err);
}
});
6 changes: 6 additions & 0 deletions types/Events.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ export interface SendMessageArgsMap {

// Speedrun.com
srcomSearchForUserDataMultiple: { type: 'name' | 'twitch', val: (string | undefined | null) }[];

// Oengus
updateOengusSchedule: any;
}

export interface SendMessageReturnMap {
Expand Down Expand Up @@ -68,6 +71,9 @@ export interface SendMessageReturnMap {

// Speedrun.com
srcomSearchForUserDataMultiple: UserData | undefined;

// Oengus
updateOengusSchedule: void;
}

export type SendMessageAck = HandledSendMessageAck | UnhandledSendMessageAck;
Expand Down

0 comments on commit e1e1081

Please sign in to comment.