diff --git a/src/lib/Video.ts b/src/lib/Video.ts index 8ae2bd4..afa93a4 100644 --- a/src/lib/Video.ts +++ b/src/lib/Video.ts @@ -23,6 +23,7 @@ import { updatePlex } from "./helpers/updatePlex.js"; import { ProgressHeadless } from "./logging/ProgressConsole.js"; import { ProgressBars } from "./logging/ProgressBars.js"; +import { notifyDownloaded, notifyError } from "./notifications/notify.js"; import { nll, withContext } from "./logging/ProgressLogger.js"; import { ffmpegPath } from "./helpers/fetchFFMPEG.js"; @@ -66,7 +67,7 @@ const byteToMbits = 131072; export class Video extends Attachment { private readonly description: string; - private readonly artworkUrl?: string; + public readonly artworkUrl?: string; public static State = VideoState; @@ -136,9 +137,11 @@ export class Video extends Attachment { } this.logger.done(chalk`{cyan Downloaded!}`); promDownloadedTotal.inc(); + notifyDownloaded(this); break; } catch (err) { this.onError(err); + notifyError(message, this); if (retries < Video.MaxRetries) await sleep(5000); } } diff --git a/src/lib/defaults.ts b/src/lib/defaults.ts index 9b30a35..5aa287b 100644 --- a/src/lib/defaults.ts +++ b/src/lib/defaults.ts @@ -68,4 +68,15 @@ export const defaultSettings: Settings = { prometheusExporterPort: null, contributeMetrics: true, }, + notifications: { + telegram: { + enabled: false, + token: "", + chatId: "", + }, + discord: { + enabled: false, + webhookUrl: "", + }, + }, }; diff --git a/src/lib/notifications/discord.ts b/src/lib/notifications/discord.ts new file mode 100644 index 0000000..12a8f36 --- /dev/null +++ b/src/lib/notifications/discord.ts @@ -0,0 +1,62 @@ +import { settings } from "../helpers/index.js"; +import { Video } from "../Video.js"; + +export const discordSendEmbed = async (title: string, video: Video) => { + const discord = settings.notifications.discord; + if (!discord || !discord.enabled || !discord.webhookUrl || !video) return; + + try { + fetch(discord.webhookUrl, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + embeds: [ + { + title: title, + author: { + name: video.channelTitle, + }, + image: { + url: video.artworkUrl, + }, + fields: [ + { + name: "Title", + value: video.videoTitle, + inline: true, + }, + { + name: "Channel", + value: video.channelTitle, + inline: true, + }, + ], + }, + ], + }), + }); + } catch { + console.error("Failed to send discord notification"); + } +}; + +export const discordSendMessage = async (message: string) => { + const discord = settings.notifications.discord; + if (!discord || !discord.enabled || !discord.webhookUrl || !message) return; + + try { + fetch(discord.webhookUrl, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + content: message, + }), + }); + } catch { + console.error("Failed to send discord notification"); + } +}; diff --git a/src/lib/notifications/notify.ts b/src/lib/notifications/notify.ts new file mode 100644 index 0000000..c742921 --- /dev/null +++ b/src/lib/notifications/notify.ts @@ -0,0 +1,15 @@ +import { Video } from "../Video.js"; +import { discordSendEmbed, discordSendMessage } from "./discord.js"; +import telegramSendMessage from "./telegram.js"; + +export const notifyDownloaded = (video: Video) => { + const message = `Downloaded ${video.videoTitle} from ${video.channelTitle}`; + telegramSendMessage(message); + discordSendEmbed("New video downloaded", video); +}; + +export const notifyError = (error: string, video: Video) => { + const message = `Error downloading ${video.videoTitle} from ${video.channelTitle} : ${error}`; + telegramSendMessage(message); + discordSendMessage(message); +}; diff --git a/src/lib/notifications/telegram.ts b/src/lib/notifications/telegram.ts new file mode 100644 index 0000000..8943885 --- /dev/null +++ b/src/lib/notifications/telegram.ts @@ -0,0 +1,21 @@ +import { settings } from "../helpers/index.js"; + +export default async function telegramSendMessage(message: string) { + const telegram = settings.notifications.telegram; + if (!telegram || !telegram.enabled || !telegram.token || !telegram.chatId || !message) return; + + try { + fetch(`https://api.telegram.org/bot${telegram.token}/sendMessage`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + chat_id: telegram.chatId, + text: message, + }), + }); + } catch { + console.error("Failed to send telegram notification"); + } +} diff --git a/src/lib/types.ts b/src/lib/types.ts index d79b826..fd2b8f2 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -49,6 +49,18 @@ export interface Extras extends Record { export type Resolution = ValueOfA; +export type Notification = { + telegram?: { + token: string; + chatId: string; + enabled: boolean; + }; + discord?: { + enabled: boolean; + webhookUrl: string; + }; +}; + export type Settings = { __SettingsWiki: string; runQuickstartPrompts: boolean; @@ -71,4 +83,5 @@ export type Settings = { prometheusExporterPort: number | null; contributeMetrics: boolean; }; + notifications: Notification; };