From 89c8ea44daa24ddb005907e6a175a3016fd5aa9e Mon Sep 17 00:00:00 2001 From: charlocharlie Date: Mon, 5 Feb 2024 22:40:08 -0600 Subject: [PATCH] Removed notificationTimeout setting. Made it auto-detect timeout based on next scheduled run. Resolves #356 --- src/common/config/classes.ts | 24 ++++++++---------------- src/device-login.ts | 18 ++++++++++++++---- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/common/config/classes.ts b/src/common/config/classes.ts index 5f45e226..8e535ee5 100644 --- a/src/common/config/classes.ts +++ b/src/common/config/classes.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-empty-function, no-useless-constructor, max-classes-per-file */ import 'reflect-metadata'; -import { ClassConstructor, Type } from 'class-transformer'; +import { ClassConstructor, Expose, Type } from 'class-transformer'; import { IsEmail, IsUrl, @@ -21,6 +21,7 @@ import { } from 'class-validator'; import { ServerOptions } from 'https'; import { ListenOptions } from 'net'; +import cronParser from 'cron-parser'; export enum NotificationType { EMAIL = 'email', @@ -682,6 +683,12 @@ export class AppConfig { @IsString() cronSchedule = process.env.CRON_SCHEDULE || '0 0,6,12,18 * * *'; + @Expose({ toClassOnly: true }) + getMsUntilNextRun() { + const cronExpression = cronParser.parseExpression(this.cronSchedule); + return cronExpression.next().getTime() - new Date().getTime(); + } + /** * A list of excluded game titles to skip during processing. * @example ['Gigabash Demo', 'Another Blacklisted Game'] @@ -799,21 +806,6 @@ export class AppConfig { }) notifiers?: AnyNotifierConfig[]; - /** - * Number of hours to wait for a response for a notification. - * The notification wait is blocking, so while other accounts will still continue, the process won't exit until all login requests are solved. - * If the timeout is reached, the process will exit, and the URL in the notification will be inaccessible. - * @example 168 - * @default 24 - * @env NOTIFICATION_TIMEOUT_HOURS - */ - @IsOptional() - @IsNumber() - @Min(0) - notificationTimeoutHours = process.env.NOTIFICATION_TIMEOUT_HOURS - ? parseInt(process.env.NOTIFICATION_TIMEOUT_HOURS, 10) - : 24; - /** * When true, the process will send test notifications with a test redirect to example.com for all configured accounts. * **Be sure to disable this after a successful test.** diff --git a/src/device-login.ts b/src/device-login.ts index 1cef5e01..3c196747 100644 --- a/src/device-login.ts +++ b/src/device-login.ts @@ -62,8 +62,6 @@ export interface DeviceLoginProps { user: string; } -const NOTIFICATION_TIMEOUT = config.notificationTimeoutHours * 60 * 60 * 1000; - const hashAlphabet = 'abcdefghijklmnopqrstuvwxyz'; const hashLength = 4; const hashids = new Hashids(Math.random().toString(), hashLength, hashAlphabet); @@ -129,11 +127,17 @@ export class DeviceLogin { public async testServerNotify(): Promise { const { reqId, url } = getUniqueUrl(); + const notificationTimeout = config.getMsUntilNextRun(); + + logger.trace( + { notificationTimeout: `in ${(notificationTimeout / (60 * 1000)).toFixed(1)} minutes` }, + 'Awaiting test notification response' + ); // Wait on a promise to be resolved by the web redirect completing await Promise.all([ promiseTimeout( - NOTIFICATION_TIMEOUT, + notificationTimeout, new Promise((resolve, reject) => { pendingRedirects.set(reqId, this.onTestVisit(resolve, reject).bind(this)); }) @@ -145,11 +149,17 @@ export class DeviceLogin { public async newDeviceAuthLogin(): Promise { const { reqId, url } = getUniqueUrl(); + const notificationTimeout = config.getMsUntilNextRun(); + + logger.trace( + { notificationTimeout: `in ${(notificationTimeout / (60 * 1000)).toFixed(1)} minutes` }, + 'Awaiting login notification response' + ); // Wait on a promise to be resolved by the web redirect and login completing await Promise.all([ promiseTimeout( - NOTIFICATION_TIMEOUT, + notificationTimeout, new Promise((resolve, reject) => { pendingRedirects.set(reqId, this.onLoginVisit(resolve, reject).bind(this)); })