Skip to content

Commit

Permalink
base ntfy provider, needs more work
Browse files Browse the repository at this point in the history
related to #493
  • Loading branch information
MrBrax committed Jan 26, 2024
1 parent c318595 commit 5b032a8
Show file tree
Hide file tree
Showing 6 changed files with 359 additions and 215 deletions.
201 changes: 114 additions & 87 deletions common/Defs.ts
Original file line number Diff line number Diff line change
@@ -1,87 +1,114 @@
export enum SubStatus {
NONE = "0",
WAITING = "1",
SUBSCRIBED = "2",
FAILED = "3",
}

export enum MuteStatus {
UNMUTED = 1,
MUTED = 2,
UNKNOWN = 3,
}

export enum ExistStatus {
EXISTS = 1,
NOT_EXISTS = 2,
NEVER_EXISTED = 3,
UNKNOWN = 4,
}

export const VideoQualityArray: string[] = ["best", "1080p60", "1080p", "720p60", "720p", "480p", "360p", "160p", "140p", "worst", "audio_only"];

export const nonGameCategories = [
"Just Chatting",
"IRL",
"Art",
"Music",
"Pools, Hot Tubs, and Beaches",
"Sports",
"ASMR",
"Talk Shows & Podcasts",
"Special Events",
"Beauty & Body Art",
"Animals, Aquariums, and Zoos",
"Travel & Outdoors",
"Makers & Crafting",
"Software and Game Development",
"Science & Technology",
"Food & Drink",
"Politics",
"Fitness & Health",
];

export type Providers = "base" | "twitch" | "youtube" | "kick";

// twitch vod age is 14 days then it's deleted
export const TwitchVodAge = 14 * 24 * 60 * 60 * 1000;

export enum NotificationProvider {
/** Websocket to all browser clients */
WEBSOCKET = 1 << 0,
/** Telegram bot */
TELEGRAM = 1 << 1,
/** Discord webhook */
DISCORD = 1 << 2,
/** Pushover */
PUSHOVER = 1 << 3,
}

export const NotificationProvidersList = [
{ id: NotificationProvider.WEBSOCKET, name: "WebSocket" },
{ id: NotificationProvider.TELEGRAM, name: "Telegram" },
{ id: NotificationProvider.DISCORD, name: "Discord" },
{ id: NotificationProvider.PUSHOVER, name: "Pushover" },
];

export const NotificationCategories = [
{ "id": "offlineStatusChange", name: "Offline status change" },
{ "id": "streamOnline", name: "Stream online" },
{ "id": "streamOffline", name: "Stream offline" },
{ "id": "streamStatusChange", name: "Stream status change" },
{ "id": "streamStatusChangeFavourite", name: "Stream status change with favourite game" },
{ "id": "vodMuted", name: "VOD muted" },
{ "id": "vodDeleted", name: "VOD deleted" },
{ "id": "debug", name: "Debug" },
{ "id": "system", name: "System" },
];

export type NotificationCategory = "offlineStatusChange" | "streamOnline" | "streamOffline" | "streamStatusChange" | "streamStatusChangeFavourite" | "vodMuted" | "vodDeleted" | "debug" | "system";

export enum JobStatus {
NONE = "NONE",
WAITING = "WAITING",
RUNNING = "RUNNING",
STOPPED = "STOPPED",
ERROR = "ERROR",
}
export enum SubStatus {
NONE = "0",
WAITING = "1",
SUBSCRIBED = "2",
FAILED = "3",
}

export enum MuteStatus {
UNMUTED = 1,
MUTED = 2,
UNKNOWN = 3,
}

export enum ExistStatus {
EXISTS = 1,
NOT_EXISTS = 2,
NEVER_EXISTED = 3,
UNKNOWN = 4,
}

export const VideoQualityArray: string[] = [
"best",
"1080p60",
"1080p",
"720p60",
"720p",
"480p",
"360p",
"160p",
"140p",
"worst",
"audio_only",
];

export const nonGameCategories = [
"Just Chatting",
"IRL",
"Art",
"Music",
"Pools, Hot Tubs, and Beaches",
"Sports",
"ASMR",
"Talk Shows & Podcasts",
"Special Events",
"Beauty & Body Art",
"Animals, Aquariums, and Zoos",
"Travel & Outdoors",
"Makers & Crafting",
"Software and Game Development",
"Science & Technology",
"Food & Drink",
"Politics",
"Fitness & Health",
];

export type Providers = "base" | "twitch" | "youtube" | "kick";

// twitch vod age is 14 days then it's deleted
export const TwitchVodAge = 14 * 24 * 60 * 60 * 1000;

export enum NotificationProvider {
/** Websocket to all browser clients */
WEBSOCKET = 1 << 0,
/** Telegram bot */
TELEGRAM = 1 << 1,
/** Discord webhook */
DISCORD = 1 << 2,
/** Pushover */
PUSHOVER = 1 << 3,
/** Ntfy */
NTFY = 1 << 4,
}

export const NotificationProvidersList = [
{ id: NotificationProvider.WEBSOCKET, name: "WebSocket" },
{ id: NotificationProvider.TELEGRAM, name: "Telegram" },
{ id: NotificationProvider.DISCORD, name: "Discord" },
{ id: NotificationProvider.PUSHOVER, name: "Pushover" },
{ id: NotificationProvider.NTFY, name: "Ntfy" },
];

export const NotificationCategories = [
{ id: "offlineStatusChange", name: "Offline status change" },
{ id: "streamOnline", name: "Stream online" },
{ id: "streamOffline", name: "Stream offline" },
{ id: "streamStatusChange", name: "Stream status change" },
{
id: "streamStatusChangeFavourite",
name: "Stream status change with favourite game",
},
{ id: "vodMuted", name: "VOD muted" },
{ id: "vodDeleted", name: "VOD deleted" },
{ id: "debug", name: "Debug" },
{ id: "system", name: "System" },
];

export type NotificationCategory =
| "offlineStatusChange"
| "streamOnline"
| "streamOffline"
| "streamStatusChange"
| "streamStatusChangeFavourite"
| "vodMuted"
| "vodDeleted"
| "debug"
| "system";

export enum JobStatus {
NONE = "NONE",
WAITING = "WAITING",
RUNNING = "RUNNING",
STOPPED = "STOPPED",
ERROR = "ERROR",
}
13 changes: 13 additions & 0 deletions common/ServerConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,19 @@ export const settingsFields: Record<string, SettingField> = {
type: "string",
},

"notify.ntfy.enabled": {
group: "Notifications (Ntfy)",
text: "Enable Ntfy notifications",
type: "boolean",
default: false,
},

"notify.ntfy.url": {
group: "Notifications (Ntfy)",
text: "Ntfy url with topic",
type: "string",
},

// discord
discord_enabled: {
group: "Notifications (Discord)",
Expand Down
2 changes: 1 addition & 1 deletion server/.vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.codeActionsOnSave": {
"source.organizeImports": true
"source.organizeImports": "explicit"
}
}
138 changes: 11 additions & 127 deletions server/src/Core/ClientBroker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { BaseConfigPath } from "./BaseConfig";
import { Config } from "./Config";
import { LiveStreamDVR } from "./LiveStreamDVR";
import { LOGLEVEL, log } from "./Log";
import TelegramNotify from "./Notifiers/Telegram";

interface Client {
id: string;
Expand All @@ -24,19 +25,6 @@ interface Client {
authenticated: boolean;
}

interface TelegramSendMessagePayload {
chat_id: number;
text: string;
parse_mode?: "MarkdownV2" | "Markdown" | "HTML";
entities?: unknown;
disable_web_page_preview?: boolean;
disable_notification?: boolean;
protect_content?: boolean;
reply_to_message_id?: number;
allow_sending_without_reply?: boolean;
reply_markup?: unknown;
}

interface DiscordSendMessagePayload {
content: string;
username?: string;
Expand Down Expand Up @@ -351,121 +339,17 @@ export class ClientBroker {
NotificationProvider.TELEGRAM
)
) {
// escape with backslash
// const escaped_title = title.replace(/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/g, "\\$&");
// const escaped_body = body.replace(/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/g, "\\$&");
TelegramNotify(title, body, icon, category, url, tts);
}

const token = Config.getInstance().cfg("telegram_token");
const chatId = Config.getInstance().cfg("telegram_chat_id");

if (token && chatId) {
axios
.post(`https://api.telegram.org/bot${token}/sendMessage`, {
chat_id: chatId,
text:
`<strong>${title}</strong>\n` +
`${body}` +
`${url ? `\n\n<a href="${url}">${url}</a>` : ""}`,
parse_mode: "HTML",
} as TelegramSendMessagePayload)
.then((res) => {
log(
LOGLEVEL.DEBUG,
"clientBroker.notify",
"Telegram response",
res.data
);
})
.catch((err: Error) => {
if (axios.isAxiosError(err)) {
// const data = err.response?.data;
// TwitchlogAdvanced(LOGLEVEL.ERROR, "notify", `Telegram axios error: ${err.message} (${data})`, { err: err, response: data });
// console.error(chalk.bgRed.whiteBright(`Telegram axios error: ${err.message} (${data})`), JSON.stringify(err, null, 2));

if (err.response) {
log(
LOGLEVEL.ERROR,
"clientBroker.notify",
`Telegram axios error response: ${err.message} (${err.response.data})`,
{ err: err, response: err.response.data }
);
console.error(
chalk.bgRed.whiteBright(
`Telegram axios error response : ${err.message} (${err.response.data})`
),
JSON.stringify(err, null, 2)
);
} else if (err.request) {
log(
LOGLEVEL.ERROR,
"clientBroker.notify",
`Telegram axios error request: ${err.message} (${err.request})`,
{ err: err, request: err.request }
);
console.error(
chalk.bgRed.whiteBright(
`Telegram axios error request: ${err.message} (${err.request})`
),
JSON.stringify(err, null, 2)
);
} else {
log(
LOGLEVEL.ERROR,
"clientBroker.notify",
`Telegram axios error: ${err.message}`,
err
);
console.error(
chalk.bgRed.whiteBright(
`Telegram axios error: ${err.message}`
),
JSON.stringify(err, null, 2)
);
}
} else {
log(
LOGLEVEL.ERROR,
"clientBroker.notify",
`Telegram error: ${err.message}`,
err
);
console.error(
chalk.bgRed.whiteBright(
`Telegram error: ${err.message}`
)
);
}
});
} else if (!token && chatId) {
log(
LOGLEVEL.ERROR,
"clientBroker.notify",
"Telegram token not set"
);
console.error(
chalk.bgRed.whiteBright("Telegram token not set")
);
} else if (!chatId && token) {
log(
LOGLEVEL.ERROR,
"clientBroker.notify",
"Telegram chat ID not set"
);
console.error(
chalk.bgRed.whiteBright("Telegram chat ID not set")
);
} else {
log(
LOGLEVEL.ERROR,
"clientBroker.notify",
"Telegram token and chat ID not set"
);
console.error(
chalk.bgRed.whiteBright(
"Telegram token and chat ID not set"
)
);
}
if (
Config.getInstance().cfg("notify.ntfy.enabled") &&
ClientBroker.getNotificationSettingForProvider(
category,
NotificationProvider.NTFY
)
) {
TelegramNotify(title, body, icon, category, url, tts);
}

if (
Expand Down
Loading

0 comments on commit 5b032a8

Please sign in to comment.