Skip to content

Commit 8c70fef

Browse files
authored
Merge pull request #32 from AmRo045/dev
Fix sync job & improve notification channel logic
2 parents bc933ce + 2b521ad commit 8c70fef

File tree

6 files changed

+67
-19
lines changed

6 files changed

+67
-19
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "outline-admin",
3-
"version": "0.3.1",
3+
"version": "0.3.2",
44
"private": true,
55
"scripts": {
66
"compile": "tsc -p tsconfig.scripts.json && tscpaths -p tsconfig.scripts.tscpaths.json -s ./dist -o ./dist",

scripts/health-check.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { sendNotificationViaTelegramChannel } from "@/src/core/actions/notificat
99

1010
let logger = createLogger(LoggerContext.HealthCheckJob);
1111

12-
async function handleUnavailableServer(server: any) {
12+
async function handleUnavailableServer(server: any, errorMessage: string) {
1313
const healthCheck = server.healthCheck;
1414
const now = new Date();
1515

@@ -37,7 +37,7 @@ async function handleUnavailableServer(server: any) {
3737
if (healthCheck.notification === HealthCheckNotificationType.Telegram && server.healthCheck.notificationConfig) {
3838
try {
3939
logger.info("Sending Telegram notification...");
40-
await sendNotificationViaTelegramChannel(server);
40+
await sendNotificationViaTelegramChannel(server, errorMessage);
4141

4242
await prisma.healthCheck.update({
4343
where: { serverId: server.id },
@@ -107,7 +107,13 @@ async function checkServerHealth(server: any) {
107107
if (!response.ok) {
108108
logger.error(`[${server.name}] HTTP ${response.status} - ${response.statusText}`);
109109

110-
return await handleUnavailableServer(server);
110+
const errorText = await response.text();
111+
const errorMessage = JSON.stringify({
112+
status: response.status,
113+
message: errorText
114+
});
115+
116+
return await handleUnavailableServer(server, errorMessage);
111117
}
112118

113119
logger.info(`[${server.name}] Healthy (${response.status}) — ${duration.toFixed(0)}ms`);
@@ -130,7 +136,7 @@ async function checkServerHealth(server: any) {
130136
});
131137
} catch (error: any) {
132138
logger.error(`[${server.name}] Error:`, error.message);
133-
await handleUnavailableServer(server);
139+
await handleUnavailableServer(server, error.message);
134140
}
135141
}
136142

src/components/notification-channel-form.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,13 @@ export default function NotificationChannelForm({ channel }: Props) {
100100
let config = null;
101101

102102
if (data.type === "Telegram") {
103+
const messageTemplate = data.telegramMessageTemplate ?? "";
104+
103105
config = JSON.stringify({
104106
apiUrl: data.telegramApiUrl!,
105107
botToken: data.telegramBotToken!,
106108
chatId: data.telegramChatId!,
107-
messageTemplate: data.telegramMessageTemplate!
109+
messageTemplate: messageTemplate.length > 0 ? messageTemplate : app.defaultTelegramNotificationTemplate
108110
});
109111
}
110112

@@ -261,15 +263,13 @@ export default function NotificationChannelForm({ channel }: Props) {
261263

262264
<Textarea
263265
color="primary"
264-
description="Available placeholders: {{serverName}} {{serverHostnameOrIp}}"
266+
description="Available placeholders: {{serverName}} {{serverHostnameOrIp}} {{errorMessage}}"
265267
errorMessage={formState.errors.telegramMessageTemplate?.message}
266268
isInvalid={!!formState.errors.telegramMessageTemplate}
267-
label="Message template"
268-
placeholder={`e.g. "{{serverName}} ({{serverHostnameOrIp}})" is out of reach!`}
269+
label="Message template (Markdown)"
270+
placeholder={`e.g. ${app.defaultTelegramNotificationTemplate}`}
269271
variant="underlined"
270-
{...register("telegramMessageTemplate", {
271-
required: "Message template is required"
272-
})}
272+
{...register("telegramMessageTemplate")}
273273
/>
274274
</div>
275275
)}

src/core/actions/notification-channel.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Telegraf } from "telegraf";
66

77
import prisma from "@/prisma/db";
88
import { ServerWithHealthCheck, TelegramNotificationChannelConfig } from "@/src/core/definitions";
9+
import { app } from "@/src/core/config";
910

1011
export async function createNotificationChannel(data: any): Promise<void> {
1112
await prisma.notificationChannel.create({ data });
@@ -67,7 +68,10 @@ export async function deleteNotificationChannel(id: number): Promise<void> {
6768
revalidatePath(`/notification-channels/${id}`);
6869
}
6970

70-
export async function sendNotificationViaTelegramChannel(server: ServerWithHealthCheck): Promise<void> {
71+
export async function sendNotificationViaTelegramChannel(
72+
server: ServerWithHealthCheck,
73+
errorMessage: string
74+
): Promise<void> {
7175
const channel = await getNotificationChannelById(server.healthCheck!.notificationChannelId!);
7276

7377
if (!channel) {
@@ -85,10 +89,16 @@ export async function sendNotificationViaTelegramChannel(server: ServerWithHealt
8589
const userId = config.chatId;
8690

8791
const message = config.messageTemplate
92+
.replaceAll("{{errorMessage}}", errorMessage)
8893
.replaceAll("{{serverName}}", server.name)
8994
.replaceAll("{{serverHostnameOrIp}}", server.hostnameOrIp);
9095

91-
await bot.telegram.sendMessage(userId, message);
96+
await bot.telegram.sendMessage(userId, message, {
97+
parse_mode: "Markdown",
98+
link_preview_options: {
99+
is_disabled: true
100+
}
101+
});
92102
}
93103

94104
export async function testTelegramNotificationChannel(
@@ -116,10 +126,7 @@ export async function testTelegramNotificationChannel(
116126
}
117127

118128
if (!config.messageTemplate) {
119-
return {
120-
ok: false,
121-
message: "Message Template is required"
122-
};
129+
config.messageTemplate = app.defaultTelegramNotificationTemplate;
123130
}
124131

125132
try {
@@ -132,10 +139,16 @@ export async function testTelegramNotificationChannel(
132139
const userId = config.chatId;
133140

134141
const message = config.messageTemplate
142+
.replaceAll("{{errorMessage}}", "Example server error message")
135143
.replaceAll("{{serverName}}", "Example Server")
136144
.replaceAll("{{serverHostnameOrIp}}", "10.11.12.13");
137145

138-
await bot.telegram.sendMessage(userId, message);
146+
await bot.telegram.sendMessage(userId, message, {
147+
parse_mode: "Markdown",
148+
link_preview_options: {
149+
is_disabled: true
150+
}
151+
});
139152

140153
return {
141154
ok: true,

src/core/config.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@ export const app = {
1515
description:
1616
"Outline Admin is a web interface for the Outline Manager API, providing a simple and user-friendly UI for managing VPN servers.",
1717

18+
defaultTelegramNotificationTemplate: `⚠️ OUTLINE ADMIN ⚠️
19+
20+
**\`{{serverName}}\`** (\`{{serverHostnameOrIp}}\`) is out of reach!
21+
22+
23+
[[Error]]:
24+
\`\`\`
25+
{{errorMessage}}
26+
\`\`\``,
27+
1828
links: {
1929
github: "https://github.com/AmRo045/OutlineAdmin",
2030
x: "https://x.com/AmRo045",

src/core/outline/outline-sync-service.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,25 @@ export class OutlineSyncService {
4444
this.logger.info("Getting server usage metrics...");
4545
const metrics = await this.client.metricsTransfer();
4646

47+
const allMetrics = Object.values(metrics.bytesTransferredByUserId);
48+
const totalUsageMetrics = allMetrics.reduce(
49+
(previousValue, currentValue) => previousValue + currentValue,
50+
0
51+
);
52+
53+
this.logger.info("Updating server info in local database...");
54+
await prisma.server.update({
55+
where: { id: this.server.id },
56+
data: {
57+
name: remoteServerInfo.name,
58+
hostnameOrIp: remoteServerInfo.hostnameForAccessKeys,
59+
hostnameForNewAccessKeys: remoteServerInfo.hostnameForAccessKeys,
60+
portForNewAccessKeys: remoteServerInfo.portForNewAccessKeys,
61+
isMetricsEnabled: remoteServerInfo.metricsEnabled,
62+
totalDataUsage: totalUsageMetrics
63+
}
64+
});
65+
4766
await this.syncAccessKeys(metrics);
4867
}
4968
}

0 commit comments

Comments
 (0)