From f3b68dca33e7fa2bc68b05d6c8d2586ee29fdd1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Pluta?= Date: Fri, 17 Jan 2025 15:37:14 +0100 Subject: [PATCH] Merge reminder & backend features --- src/backend/base.ts | 27 +++++++++++++++++++++++---- src/backend/index.ts | 28 ++++++++++++++++++++++++++++ src/backend/ntfy-sh.ts | 22 ++++++++++------------ src/reminder/index.ts | 21 --------------------- src/types/config.ts | 13 ++++++++++++- 5 files changed, 73 insertions(+), 38 deletions(-) delete mode 100644 src/reminder/index.ts diff --git a/src/backend/base.ts b/src/backend/base.ts index 412faa0..96f270e 100644 --- a/src/backend/base.ts +++ b/src/backend/base.ts @@ -1,9 +1,28 @@ -import { BackendConfig } from "../types/config"; +import { BackendSettings, Config } from "../types/config"; import { Notification } from "../types/notification"; -export abstract class Backend { - constructor(config: BackendConfig) { +export abstract class Backend { + public abstract readonly name: string; + protected abstract requiredFields: readonly (keyof C)[]; + protected abstract notify(config: C, notification: Notification): void; + + #validate(config: Partial): C { + for (const field of this.requiredFields) { + if (config[field] === undefined) { + throw new Error(`The '${String(field)}' configuration field of'${this.name}' consumer is required`) + } + } + + return config as C; } - abstract notify(notification: Notification): void; + public remind(config: Config, notification: Notification) { + const cfg = config.backend[this.name] as Partial; + + if (cfg.enable !== true) { + return + } + + this.notify(this.#validate(cfg), notification); + } } \ No newline at end of file diff --git a/src/backend/index.ts b/src/backend/index.ts index db03e71..8c7b9b3 100644 --- a/src/backend/index.ts +++ b/src/backend/index.ts @@ -1,3 +1,31 @@ +import dayjs from "dayjs"; +import { NotificationDatabase } from "../types/notification"; +import { Config } from "../types/config"; +import { NtfySH } from "./ntfy-sh"; + export { Backend } from "./base"; export { NtfySH } from "./ntfy-sh"; +const backends = [ + new NtfySH() +]; + +/** + * Iterates through all the database notifications for current time + * and triggers the notification using specified backends in the config. + */ +export async function remind(config: Config, db: NotificationDatabase) { + const now = dayjs().format("HH:mm"); + const notifications = db[now] ?? []; + + for (const notification of notifications) { + for (const backend of backends) { + backend.remind(config, notification); + await snooze(1500); + } + } +} + +function snooze(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); +} \ No newline at end of file diff --git a/src/backend/ntfy-sh.ts b/src/backend/ntfy-sh.ts index 364a450..ae9b972 100644 --- a/src/backend/ntfy-sh.ts +++ b/src/backend/ntfy-sh.ts @@ -1,27 +1,25 @@ +import { BackendSettings } from "../types/config"; import { Notification } from "../types/notification"; import { Backend } from "./base"; type Config = { url: string; token: string; - topic: string; -} + topic?: string; +} & BackendSettings; -export class NtfySH extends Backend { - #config: Config; +export class NtfySH extends Backend { + public name = "ntfy.sh"; - constructor(config: Config) { - super(config); - this.#config = config; - } - - notify(notification: Notification): void { - fetch(`https://${this.#config.url}/${this.#config.topic}`, { + protected requiredFields = ['url', 'token'] as const; + + protected notify(config: Config, notification: Notification): void { + fetch(`https://${config.url}/${config.topic || 'obsidian'}`, { method: 'POST', body: notification.text, headers: { 'Title': notification.title, - 'Authorization': `Bearer ${this.#config.token}` + 'Authorization': `Bearer ${config.token}` } }) } diff --git a/src/reminder/index.ts b/src/reminder/index.ts deleted file mode 100644 index 29db4b4..0000000 --- a/src/reminder/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -import dayjs from "dayjs"; -import { NotificationDatabase } from "../types/notification"; -import { Backend } from "../backend"; - -/** - * Iterates through all the database notifications for current time - * and triggers the notification using specified backend. - */ -export async function remind(db: NotificationDatabase, backend: Backend) { - const now = dayjs().format("HH:mm"); - const notifications = db[now] ?? []; - - for (const notification of notifications) { - backend.notify(notification); - await snooze(1500); - } -} - -function snooze(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)); -} \ No newline at end of file diff --git a/src/types/config.ts b/src/types/config.ts index 358ed60..1ffc95e 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -1 +1,12 @@ -export type BackendConfig = Record; \ No newline at end of file +export type BackendSettings = { + enable?: boolean; +}; +export type SupportedBackends = 'ntfy.sh'; +export type BackendConfig = { + backend: SupportedBackends; + settings: BackendSettings; +} + +export type Config = { + backend: Record; +}; \ No newline at end of file