Skip to content

Commit

Permalink
Added notification support for DNS toggling and validation logic
Browse files Browse the repository at this point in the history
  • Loading branch information
micthiesen committed Oct 26, 2024
1 parent 0e174f9 commit b0e7dac
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 7 deletions.
17 changes: 13 additions & 4 deletions src/dns.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import env from "./env";
import { sendNotification, type PushoverMessage } from "./notify";
import { parseDnsServers } from "./parsing";
import { withSshConnection, type SNodeSSH } from "./ssh";
import { arrayItemsEqual } from "./utils";

let timeoutId: NodeJS.Timeout | null = null;
const RESTORE_DELAY = 1000 * 60 * 2;
export const RESTORE_DELAY_MINUTES = 2;
const RESTORE_DELAY = 1000 * 60 * RESTORE_DELAY_MINUTES;

export async function toggleDns(ssh: SNodeSSH) {
if (timeoutId) clearTimeout(timeoutId);
Expand All @@ -16,17 +18,23 @@ export async function toggleDns(ssh: SNodeSSH) {
console.log(`Scheduled restore in ${RESTORE_DELAY}ms`);
}

export async function validateDns(ssh: SNodeSSH): Promise<string> {
export async function validateDns(ssh: SNodeSSH): Promise<PushoverMessage> {
console.log("Validating DNS servers...");
const currentDnsServers = await getDnsServers(ssh);
console.log(`DNS servers are set to ${currentDnsServers}`);

if (arrayItemsEqual(currentDnsServers, env.PRIMARY_DNS_SERVERS)) {
return "DNS servers are valid";
return {
title: "DNS Servers are valid",
message: `Servers: ${currentDnsServers.join(", ")}`,
};
} else {
await setDnsServers(ssh, env.PRIMARY_DNS_SERVERS);
console.log(`DNS servers restored to ${env.PRIMARY_DNS_SERVERS}`);
return "DNS servers restored";
return {
title: "DNS Servers restored",
message: `Servers: ${currentDnsServers.join(", ")}`,
};
}
}

Expand All @@ -35,6 +43,7 @@ async function restoreDnsServers() {
await withSshConnection(async (ssh) => {
await setDnsServers(ssh, env.PRIMARY_DNS_SERVERS);
});
await sendNotification({ title: "NextDNS re-enabled", message: "" });
}

async function getDnsServers(ssh: SNodeSSH) {
Expand Down
12 changes: 9 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { type HttpBindings, serve } from "@hono/node-server";
import { Hono } from "hono";
import { logger } from "hono/logger";
import { timeout } from "hono/timeout";
import { toggleDns, validateDns } from "./dns";
import { RESTORE_DELAY_MINUTES, toggleDns, validateDns } from "./dns";
import { sendNotification } from "./notify";
import { withSshConnection } from "./ssh";

const app = new Hono<{ Bindings: HttpBindings }>();
Expand All @@ -14,14 +15,19 @@ app.onError(async (err, ctx) => {
app.get("/dns/toggle", async (ctx) => {
return withSshConnection(async (ssh) => {
await toggleDns(ssh);
await sendNotification({
title: "NextDNS temporarily disabled",
message: `It will be restored in ${RESTORE_DELAY_MINUTES} minutes`,
});
return ctx.text("DNS servers toggled");
});
});

app.get("/dns/validate", async (ctx) => {
return withSshConnection(async (ssh) => {
const dnsServers = await validateDns(ssh);
return ctx.text(dnsServers.toString());
const message = await validateDns(ssh);
await sendNotification(message);
return ctx.text(message.title);
});
});

Expand Down
67 changes: 67 additions & 0 deletions src/notify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import https from "node:https";
import { URLSearchParams } from "node:url";
import env from "./env";

export interface PushoverMessage {
message: string;
title: string;
url?: string;
url_title?: string;
priority?: number;
sound?: string;
timestamp?: number;
}

export async function sendNotification(message: PushoverMessage): Promise<void> {
return new Promise((resolve, reject) => {
const params = new URLSearchParams({
token: env.PUSHOVER_TOKEN,
user: env.PUSHOVER_USER,
message: message.message,
...(message.title && { title: message.title }),
...(message.url && { url: message.url }),
...(message.url_title && { url_title: message.url_title }),
...(message.priority !== undefined && {
priority: message.priority.toString(),
}),
...(message.sound && { sound: message.sound }),
...(message.timestamp && { timestamp: message.timestamp.toString() }),
});

const options = {
hostname: "api.pushover.net",
port: 443,
path: "/1/messages.json",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Content-Length": params.toString().length,
},
};

const req = https.request(options, (res) => {
let data = "";

res.on("data", (chunk) => {
data += chunk;
});

res.on("end", () => {
if (res.statusCode === 200) {
resolve();
} else {
reject(
new Error(`Pushover API returned status code ${res.statusCode}: ${data}`),
);
}
});
});

req.on("error", (error) => {
reject(error);
});

req.write(params.toString());
req.end();
});
}

0 comments on commit b0e7dac

Please sign in to comment.