-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.ts
100 lines (85 loc) · 2.76 KB
/
main.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { serve } from "https://deno.land/[email protected]/http/server.ts";
import { Bot } from "https://deno.land/x/[email protected]/mod.ts";
const BOT_TOKEN = Deno.env.get("BOT_TOKEN");
const CHAT_ID = Number(Deno.env.get("CHAT_ID"));
const SECRET = Deno.env.get("SECRET");
if (!BOT_TOKEN || isNaN(CHAT_ID) || !SECRET) {
throw new Error("Missing or invalid environment variables.");
}
const STATUS_PAGE_ROOT = "https://www.githubstatus.com/incidents";
// Documentation of the webhook payload (for future references):
// https://support.atlassian.com/statuspage/docs/enable-webhook-notifications/
type Payload =
& ({
incident: {
name: string;
id: string;
incident_updates: {
status: string;
body: string;
created_at: string;
}[];
};
} | {
component: {
name: string;
description: string;
};
component_update: {
created_at: string;
old_status: string;
new_status: string;
};
})
& { page: { status_description: string } };
const bot = new Bot(BOT_TOKEN);
const redirect = Response.redirect("https://t.me/status_gh");
function send(text: string, disable_notification: boolean) {
return bot.api.sendMessage(CHAT_ID, text, {
disable_notification,
disable_web_page_preview: true,
parse_mode: "HTML",
});
}
function escape(text: string) {
return text
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">");
}
serve(async (req) => {
const { pathname } = new URL(req.url);
if (pathname !== `/${SECRET}`) return redirect;
const payload = await req.json() as Payload;
if ("component" in payload) {
const {
component: { name, description },
component_update: update,
} = payload;
const message = `\
<b>${escape(name)}</b>
${update.old_status} → ${update.new_status}\n
${escape(description)}
<i>${escape(new Date(update.created_at).toUTCString())}</i>`;
const disableNotification = update.old_status !== "operational" &&
update.new_status !== "operational";
await send(message, disableNotification);
} else if ("incident" in payload) {
const { name, incident_updates, id } = payload.incident;
const { status, body, created_at } = incident_updates[0];
const message = `\
<b><a href="${STATUS_PAGE_ROOT}/${id}">${escape(name)}</a></b>
${status[0].toUpperCase() + status.substring(1)}\n
${escape(body) ?? ""}
${escape(new Date(created_at).toUTCString())}`;
const isFirstUpdate = incident_updates.length == 1; // the very first update.
const disableNotification = !isFirstUpdate && status !== "resolved";
await send(message, disableNotification);
}
return new Response();
}, {
onError: (err) => {
console.error(err);
return new Response("Something went wrong.", { status: 500 });
},
});