Skip to content

Instantly share code, notes, and snippets.

@Erisa
Last active September 5, 2023 09:05
Show Gist options
  • Save Erisa/9558fe4d270343ac6341e7318e6d98d0 to your computer and use it in GitHub Desktop.
Save Erisa/9558fe4d270343ac6341e7318e6d98d0 to your computer and use it in GitHub Desktop.
tunnel status cf alert with https://repeat.dev
const tunnelStatusTypes = {
TUNNEL_STATUS_TYPE_INVALID: {
color: 3553599,
name: 'Invalid',
},
TUNNEL_STATUS_TYPE_INACTIVE: {
color: 3553599,
name: 'Inactive',
},
TUNNEL_STATUS_TYPE_DOWN: {
color: 15614771,
name: 'Down',
},
TUNNEL_STATUS_TYPE_DEGRADED: {
color: 16742144,
name: 'Degraded',
},
TUNNEL_STATUS_TYPE_HEALTHY: {
color: 5557316,
name: 'Healthy',
},
};
const tunnelEventTypes = {
TUNNEL_EVENT_TYPE_INVALID: {
color: 3553599,
name: 'UNKNOWN',
},
TUNNEL_EVENT_TYPE_CREATED: {
color: 5557316,
name: 'Created',
},
TUNNEL_EVENT_TYPE_UPDATED: {
color: 16705116,
name: 'Updated',
},
TUNNEL_EVENT_TYPE_DELETED: {
color: 15614771,
name: 'Deleted',
},
};
const welcomeString =
'Hello World! This is a test message sent from https://cloudflare.com. If you can see this, your webhook is configured correctly.';
export default {
async webhook(request: Request, env: Repeat.Env) {
let alert: CloudflareAlert = await request.json();
console.log(JSON.stringify(alert));
if (alert.text == welcomeString) {
return new Response('hello cloudflare');
}
// if (!['tunnel_health_event', 'tunnel_update_event'].includes(alert.alert_type)) {
// return new Response('bad request.', { status: 400 });
// }
const tunnelUrl = `https://one.dash.cloudflare.com/${alert.account_id}/access/tunnels/edit/${alert.data.tunnel_id}`;
let message: Webhooks.Discord.Payload;
if (alert.alert_type == 'tunnel_health_event') {
message = {
// @ts-ignore
username: 'Cloudflare Tunnel',
avatar_url:
'https://cdn.discordapp.com/avatars/967016512940564520/82ff7a47f2126b383798033377c493a8.png?size=4096',
embeds: [
{
title: `Health change for ${alert.data.tunnel_name}`,
url: tunnelUrl,
color: tunnelStatusTypes[alert.data.new_status].color,
timestamp: alert.data.timestamp,
description: `Tunnel [${alert.data.tunnel_name}](${tunnelUrl}) is now **${
tunnelStatusTypes[alert.data.new_status].name
}**!`,
fields: [
{
name: 'Tunnel ID',
value: alert.data.tunnel_id,
},
{
name: 'Event time',
value: `<t:${alert.ts}:R>`,
},
],
},
],
};
} else if (alert.alert_type == 'tunnel_update_event') {
message = {
// @ts-ignore
username: 'Cloudflare Tunnel',
avatar_url:
'https://cdn.discordapp.com/avatars/967016512940564520/82ff7a47f2126b383798033377c493a8.png?size=4096',
embeds: [
{
title: `Tunnel update event (${alert.data.tunnel_name})`,
url: tunnelUrl,
color: tunnelEventTypes[alert.data.event].color,
//timestamp: (new Date(alert.ts)).toISOString(),
description: `Tunnel [${alert.data.tunnel_name}](${tunnelUrl}) was **${
tunnelEventTypes[alert.data.event].name
}**!`,
fields: [
{
name: 'Tunnel ID',
value: alert.data.tunnel_id,
},
{
name: 'Event time',
value: `<t:${alert.ts}:R>`,
},
{
name: 'User',
value: alert.data.auth_info.actor_email,
},
],
},
],
};
} else {
return new Response('bad request.', { status: 400 });
}
console.log(JSON.stringify(message));
let resp = await fetch(
new Request(env.variables.WEBHOOK_URL, {
body: JSON.stringify(message),
headers: {
'content-type': 'application/json',
},
method: 'POST',
})
);
console.log(await resp.clone().text());
return resp;
},
};
export interface CloudflareAlert {
name: string;
text: string;
data: Data;
ts: number;
account_id: string;
alert_type: string;
}
export interface Data {
alert_name: string;
tunnel_id: string;
tunnel_name: string;
new_status: string;
status_reason: string;
timestamp: string;
dashboard_link: string;
event: string;
auth_info: AuthInfo;
}
export interface AuthInfo {
account_tag: string;
account_name: string;
actor_email: string;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment