generated from nhcarrigan/template
feat: migrate to dedicated log platform
This commit is contained in:
@@ -6,3 +6,4 @@ DISCORD_WEBHOOK_URL="op://Environment Variables - Naomi/Alert Server/discord_hoo
|
|||||||
STRIPE_SECRET_KEY="op://Environment Variables - Naomi/Alert Server/stripe"
|
STRIPE_SECRET_KEY="op://Environment Variables - Naomi/Alert Server/stripe"
|
||||||
STRIPE_WEBHOOK_SECRET="op://Environment Variables - Naomi/Alert Server/stripe_webhook"
|
STRIPE_WEBHOOK_SECRET="op://Environment Variables - Naomi/Alert Server/stripe_webhook"
|
||||||
DISCORD_TOKEN="op://Environment Variables - Naomi/Alert Server/discord_token"
|
DISCORD_TOKEN="op://Environment Variables - Naomi/Alert Server/discord_token"
|
||||||
|
LOG_TOKEN="op://Environment Variables - Naomi/Alert Server/log_token"
|
||||||
@@ -17,6 +17,9 @@ export const auth = (request: FastifyRequest): boolean => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const token = request.headers.authorization;
|
const token = request.headers.authorization;
|
||||||
|
if (token === "" || process.env.API_AUTH === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (token !== process.env.API_AUTH) {
|
if (token !== process.env.API_AUTH) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
/**
|
|
||||||
* @copyright nhcarrigan
|
|
||||||
* @license Naomi's Public License
|
|
||||||
* @author Naomi Carrigan
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a Discord webhook notification.
|
|
||||||
* @param subject - The subject of the email.
|
|
||||||
* @param body - The text content of the email.
|
|
||||||
*/
|
|
||||||
export const sendDiscord = async(
|
|
||||||
subject: string,
|
|
||||||
body: string,
|
|
||||||
): Promise<void> => {
|
|
||||||
await fetch(`https://discord.com/api/v10/channels/1355232348840394785/messages`, {
|
|
||||||
body: JSON.stringify({
|
|
||||||
components: [
|
|
||||||
{
|
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- Needs to match Discord's structure.
|
|
||||||
accent_color: 15_418_782,
|
|
||||||
components: [
|
|
||||||
{
|
|
||||||
content: `# ${subject}`,
|
|
||||||
type: 10,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
divider: true,
|
|
||||||
spacing: 1,
|
|
||||||
type: 14,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: body,
|
|
||||||
type: 10,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
spoiler: false,
|
|
||||||
type: 17,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
flags: 32_768,
|
|
||||||
}),
|
|
||||||
headers: {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- Needs to match Discord's structure.
|
|
||||||
"Authorization": `Bot ${process.env.DISCORD_TOKEN ?? ""}`,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- Needs to match Discord's structure.
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
method: "POST",
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* @copyright NHCarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
|
||||||
|
const priority: Record<string, number> = {
|
||||||
|
debug: 0,
|
||||||
|
error: 3,
|
||||||
|
info: 1,
|
||||||
|
warn: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pipes a log message to the Gotify server.
|
||||||
|
* @param appName - The name of the application.
|
||||||
|
* @param message - The message to log.
|
||||||
|
* @param level - The level of the log, used for priority.
|
||||||
|
*/
|
||||||
|
export const pipeLog = async(
|
||||||
|
appName: string,
|
||||||
|
message: string,
|
||||||
|
level: string,
|
||||||
|
): Promise<void> => {
|
||||||
|
const logToken = process.env.LOG_TOKEN;
|
||||||
|
if (logToken === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await fetch(`https://graylog.nhcarrigan.com/message?token=${logToken}`, {
|
||||||
|
body: JSON.stringify({
|
||||||
|
message: message,
|
||||||
|
priority: priority[level] ?? priority.debug,
|
||||||
|
title: appName,
|
||||||
|
}),
|
||||||
|
headers: {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/naming-convention -- Standard header.
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
method: "POST",
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
import { webcrypto } from "node:crypto";
|
import { webcrypto } from "node:crypto";
|
||||||
import { verify } from "discord-verify/node";
|
import { verify } from "discord-verify/node";
|
||||||
import { applicationData } from "../config/applicationData.js";
|
import { applicationData } from "../config/applicationData.js";
|
||||||
import { sendDiscord } from "./discord.js";
|
import { pipeLog } from "./pipeLog.js";
|
||||||
import type { Entitlement } from "../interfaces/entitlement.js";
|
import type { Entitlement } from "../interfaces/entitlement.js";
|
||||||
import type { FastifyRequest } from "fastify";
|
import type { FastifyRequest } from "fastify";
|
||||||
|
|
||||||
@@ -27,7 +27,11 @@ export const validateWebhook = async(
|
|||||||
const { application_id: applicationId } = request.body;
|
const { application_id: applicationId } = request.body;
|
||||||
const appData = applicationData[applicationId];
|
const appData = applicationData[applicationId];
|
||||||
if (appData === undefined) {
|
if (appData === undefined) {
|
||||||
void sendDiscord(`[NOTIFICATION]: Invalid Application ID`, `Received an entitlement event for an invalid application ID: ${applicationId}`);
|
await pipeLog(
|
||||||
|
"Alert Server",
|
||||||
|
`Received an entitlement event for an invalid application ID: ${applicationId}`,
|
||||||
|
"warn",
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const signature = request.headers["x-signature-ed25519"];
|
const signature = request.headers["x-signature-ed25519"];
|
||||||
@@ -41,9 +45,10 @@ export const validateWebhook = async(
|
|||||||
webcrypto.subtle,
|
webcrypto.subtle,
|
||||||
);
|
);
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
void sendDiscord(
|
await pipeLog(
|
||||||
`[NOTIFICATION]: Invalid Webhook Signature`,
|
"Alert Server",
|
||||||
`Received an entitlement event with an invalid signature.\nApplication ID: ${applicationId}\nSignature: ${signature}\nTimestamp: ${timestamp}\nRaw Body: ${rawBody}`,
|
`Received an entitlement event with an invalid signature for application ${appData.name} (${applicationId}).`,
|
||||||
|
"warn",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return isValid;
|
return isValid;
|
||||||
|
|||||||
+104
-45
@@ -10,7 +10,7 @@ import rawBody from "fastify-raw-body";
|
|||||||
import StripeApp from "stripe";
|
import StripeApp from "stripe";
|
||||||
import { applicationData } from "../config/applicationData.js";
|
import { applicationData } from "../config/applicationData.js";
|
||||||
import { auth } from "../modules/auth.js";
|
import { auth } from "../modules/auth.js";
|
||||||
import { sendDiscord } from "../modules/discord.js";
|
import { pipeLog } from "../modules/pipeLog.js";
|
||||||
import { sendMail } from "../modules/sendMail.js";
|
import { sendMail } from "../modules/sendMail.js";
|
||||||
import { validateWebhook } from "../modules/validateWebhook.js";
|
import { validateWebhook } from "../modules/validateWebhook.js";
|
||||||
import { errorSchema } from "../schemas/errorSchema.js";
|
import { errorSchema } from "../schemas/errorSchema.js";
|
||||||
@@ -85,7 +85,7 @@ export const instantiateServer = async(): Promise<void> => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { application, level, message } = request.body;
|
const { application, level, message } = request.body;
|
||||||
await sendDiscord(`[${level}]: ${application}`, message);
|
await pipeLog(application, message, level);
|
||||||
await response.status(200).send({ success: true });
|
await response.status(200).send({ success: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await errorHandler(error, "Log Webhook");
|
await errorHandler(error, "Log Webhook");
|
||||||
@@ -108,9 +108,10 @@ export const instantiateServer = async(): Promise<void> => {
|
|||||||
`[ERROR]: ${context} - ${application}`,
|
`[ERROR]: ${context} - ${application}`,
|
||||||
`${message}\n\n${stack}`,
|
`${message}\n\n${stack}`,
|
||||||
);
|
);
|
||||||
await sendDiscord(
|
await pipeLog(
|
||||||
`[ERROR]: ${context} - ${application}`,
|
application,
|
||||||
`${message}\n\n\`\`\`\n${stack}\n\`\`\``,
|
`${context} - ${message}\n${stack}`,
|
||||||
|
"error",
|
||||||
);
|
);
|
||||||
await response.status(200).send({ success: true });
|
await response.status(200).send({ success: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -132,7 +133,7 @@ export const instantiateServer = async(): Promise<void> => {
|
|||||||
}
|
}
|
||||||
const { application, message } = request.body;
|
const { application, message } = request.body;
|
||||||
await sendMail(`[UPTIME]: ${application}`, message);
|
await sendMail(`[UPTIME]: ${application}`, message);
|
||||||
await sendDiscord(`[UPTIME]: ${application}`, message);
|
await pipeLog(application, message, "info");
|
||||||
await response.status(200).send({ success: true });
|
await response.status(200).send({ success: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await errorHandler(error, "Uptime Webhook");
|
await errorHandler(error, "Uptime Webhook");
|
||||||
@@ -141,13 +142,17 @@ export const instantiateServer = async(): Promise<void> => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- Body must be capitalised for Fastify.
|
server.post<{
|
||||||
server.post<{ Body: Entitlement; Headers: {
|
// eslint-disable-next-line @typescript-eslint/naming-convention -- Header must be formatted for Fastify.
|
||||||
|
Body: Entitlement;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/naming-convention -- Header must be formatted for Fastify.
|
||||||
|
Headers: {
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- Header must be formatted for Fastify.
|
// eslint-disable-next-line @typescript-eslint/naming-convention -- Header must be formatted for Fastify.
|
||||||
"x-signature-ed25519": string;
|
"x-signature-ed25519": string;
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- Header must be formatted for Fastify.
|
// eslint-disable-next-line @typescript-eslint/naming-convention -- Header must be formatted for Fastify.
|
||||||
"x-signature-timestamp": string;
|
"x-signature-timestamp": string;
|
||||||
}; }>(
|
};
|
||||||
|
}>(
|
||||||
"/entitlement",
|
"/entitlement",
|
||||||
// eslint-disable-next-line complexity -- Fuck off.
|
// eslint-disable-next-line complexity -- Fuck off.
|
||||||
async(request, response) => {
|
async(request, response) => {
|
||||||
@@ -157,9 +162,10 @@ export const instantiateServer = async(): Promise<void> => {
|
|||||||
const isValid = await validateWebhook(request);
|
const isValid = await validateWebhook(request);
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
await response.status(401).send({ success: false });
|
await response.status(401).send({ success: false });
|
||||||
void sendDiscord(
|
await pipeLog(
|
||||||
`[ENTITLEMENT]: ${appInfo?.name ?? applicationId}`,
|
appInfo?.name ?? applicationId,
|
||||||
"An invalid webhook signature was received.",
|
"An invalid webhook signature was received.",
|
||||||
|
"error",
|
||||||
);
|
);
|
||||||
void sendMail(
|
void sendMail(
|
||||||
`[ENTITLEMENT]: ${appInfo?.name ?? applicationId}`,
|
`[ENTITLEMENT]: ${appInfo?.name ?? applicationId}`,
|
||||||
@@ -169,9 +175,10 @@ export const instantiateServer = async(): Promise<void> => {
|
|||||||
}
|
}
|
||||||
await response.status(204).send();
|
await response.status(204).send();
|
||||||
if (type === 0) {
|
if (type === 0) {
|
||||||
void sendDiscord(
|
await pipeLog(
|
||||||
`[ENTITLEMENT]: ${appInfo?.name ?? applicationId}`,
|
appInfo?.name ?? applicationId,
|
||||||
"Received a ping from Discord.",
|
"Received a ping from Discord.",
|
||||||
|
"info",
|
||||||
);
|
);
|
||||||
void sendMail(
|
void sendMail(
|
||||||
`[ENTITLEMENT]: ${appInfo?.name ?? applicationId}`,
|
`[ENTITLEMENT]: ${appInfo?.name ?? applicationId}`,
|
||||||
@@ -184,9 +191,10 @@ export const instantiateServer = async(): Promise<void> => {
|
|||||||
guild_id: guildId,
|
guild_id: guildId,
|
||||||
ends_at: endsAt,
|
ends_at: endsAt,
|
||||||
} = event.data;
|
} = event.data;
|
||||||
await sendDiscord(
|
await pipeLog(
|
||||||
`[ENTITLEMENT]: ${appInfo?.name ?? applicationId}`,
|
appInfo?.name ?? applicationId,
|
||||||
`Entitlement purchased!\n- **User ID**: ${userId}\n- **Guild ID**: ${guildId}\n- **Ends At**: ${endsAt}`,
|
`Entitlement purchased!\n- **User ID**: ${userId}\n- **Guild ID**: ${guildId}\n- **Ends At**: ${endsAt}`,
|
||||||
|
"info",
|
||||||
);
|
);
|
||||||
await sendMail(
|
await sendMail(
|
||||||
`[ENTITLEMENT]: ${appInfo?.name ?? applicationId}`,
|
`[ENTITLEMENT]: ${appInfo?.name ?? applicationId}`,
|
||||||
@@ -211,53 +219,109 @@ export const instantiateServer = async(): Promise<void> => {
|
|||||||
try {
|
try {
|
||||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Nah fam.
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Nah fam.
|
||||||
const raw = request.rawBody as Buffer;
|
const raw = request.rawBody as Buffer;
|
||||||
const event = await stripe.webhooks.constructEventAsync(
|
const event = await stripe.webhooks.
|
||||||
|
constructEventAsync(
|
||||||
raw,
|
raw,
|
||||||
request.headers["stripe-signature"] ?? "",
|
request.headers["stripe-signature"] ?? "",
|
||||||
process.env.STRIPE_WEBHOOK_SECRET ?? "",
|
process.env.STRIPE_WEBHOOK_SECRET ?? "",
|
||||||
).catch(() => {
|
).
|
||||||
|
catch(() => {
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
if (event === null) {
|
if (event === null) {
|
||||||
await response.status(400).send({
|
await response.status(400).send({
|
||||||
error: "Invalid Stripe webhook signature.",
|
error: "Invalid Stripe webhook signature.",
|
||||||
});
|
});
|
||||||
void sendDiscord(
|
await pipeLog(
|
||||||
`[STRIPE]: Invalid Webhook Signature`,
|
`[STRIPE]: Invalid Webhook Signature`,
|
||||||
`Received an invalid webhook signature from Stripe.\n- **Headers**: ${JSON.stringify(request.headers)}\n- **Body**: ${JSON.stringify(raw, null, 2)}`,
|
`Received an invalid webhook signature from Stripe.\n- **Headers**: ${JSON.stringify(
|
||||||
|
request.headers,
|
||||||
|
)}\n- **Body**: ${JSON.stringify(raw, null, 2)}`,
|
||||||
|
"error",
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await response.status(200).send({ received: true });
|
await response.status(200).send({ received: true });
|
||||||
if (event.type === "checkout.session.completed") {
|
if (event.type === "checkout.session.completed") {
|
||||||
const checkoutSessionCompleted = event.data.object;
|
const checkoutSessionCompleted = event.data.object;
|
||||||
await sendDiscord(`[STRIPE]: Checkout Session Completed`, `A checkout session has been completed.\n - **ITEMS**: ${checkoutSessionCompleted.line_items?.data.map((datum) => {
|
await pipeLog(
|
||||||
return `${datum.description ?? "unknown"} (${String(datum.quantity)})`;
|
"Stripe",
|
||||||
}).join(", ") ?? "unknown"}\n- **TOTAL**: ${String(checkoutSessionCompleted.amount_total)}`);
|
`A checkout session has been completed.\n - **ITEMS**: ${
|
||||||
await sendMail(`[STRIPE]: Checkout Session Completed`, `A checkout session has been completed.\n - **ITEMS**: ${checkoutSessionCompleted.line_items?.data.map((datum) => {
|
checkoutSessionCompleted.line_items?.data.
|
||||||
return `${datum.description ?? "unknown"} (${String(datum.quantity)})`;
|
map((datum) => {
|
||||||
}).join(", ") ?? "unknown"}\n- **TOTAL**: ${String(checkoutSessionCompleted.amount_total)}`);
|
return `${datum.description ?? "unknown"} (${String(
|
||||||
|
datum.quantity,
|
||||||
|
)})`;
|
||||||
|
}).
|
||||||
|
join(", ") ?? "unknown"
|
||||||
|
}\n- **TOTAL**: ${String(checkoutSessionCompleted.amount_total)}`,
|
||||||
|
"info",
|
||||||
|
);
|
||||||
|
await sendMail(
|
||||||
|
`[STRIPE]: Checkout Session Completed`,
|
||||||
|
`A checkout session has been completed.\n - **ITEMS**: ${
|
||||||
|
checkoutSessionCompleted.line_items?.data.
|
||||||
|
map((datum) => {
|
||||||
|
return `${datum.description ?? "unknown"} (${String(
|
||||||
|
datum.quantity,
|
||||||
|
)})`;
|
||||||
|
}).
|
||||||
|
join(", ") ?? "unknown"
|
||||||
|
}\n- **TOTAL**: ${String(checkoutSessionCompleted.amount_total)}`,
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event.type === "invoice.paid") {
|
if (event.type === "invoice.paid") {
|
||||||
const invoicePaid = event.data.object;
|
const invoicePaid = event.data.object;
|
||||||
await sendDiscord(`[STRIPE]: Invoice Paid`, `An invoice has been paid.\n - **ITEMS**: ${invoicePaid.lines.data.map((datum) => {
|
await pipeLog(
|
||||||
return `${datum.description ?? "unknown"} (${String(datum.quantity)})`;
|
"Stripe",
|
||||||
}).join(", ")}\n- **TOTAL**: ${String(invoicePaid.amount_paid)}`);
|
`An invoice has been paid.\n - **ITEMS**: ${invoicePaid.lines.data.
|
||||||
await sendMail(`[STRIPE]: Invoice Paid`, `An invoice has been paid.\n - **ITEMS**: ${invoicePaid.lines.data.map((datum) => {
|
map((datum) => {
|
||||||
return `${datum.description ?? "unknown"} (${String(datum.quantity)})`;
|
return `${datum.description ?? "unknown"} (${String(
|
||||||
}).join(", ")}\n- **TOTAL**: ${String(invoicePaid.amount_paid)}`);
|
datum.quantity,
|
||||||
|
)})`;
|
||||||
|
}).
|
||||||
|
join(", ")}\n- **TOTAL**: ${String(invoicePaid.amount_paid)}`,
|
||||||
|
"info",
|
||||||
|
);
|
||||||
|
await sendMail(
|
||||||
|
`[STRIPE]: Invoice Paid`,
|
||||||
|
`An invoice has been paid.\n - **ITEMS**: ${invoicePaid.lines.data.
|
||||||
|
map((datum) => {
|
||||||
|
return `${datum.description ?? "unknown"} (${String(
|
||||||
|
datum.quantity,
|
||||||
|
)})`;
|
||||||
|
}).
|
||||||
|
join(", ")}\n- **TOTAL**: ${String(invoicePaid.amount_paid)}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (event.type === "payment_intent.succeeded") {
|
if (event.type === "payment_intent.succeeded") {
|
||||||
const paymentIntentSucceeded = event.data.object;
|
const paymentIntentSucceeded = event.data.object;
|
||||||
await sendDiscord(`[STRIPE]: Payment Intent Succeeded`, `A payment intent has succeeded.\n- **AMOUNT**: ${String(paymentIntentSucceeded.amount)}`);
|
await pipeLog(
|
||||||
await sendMail(`[STRIPE]: Payment Intent Succeeded`, `A payment intent has succeeded.\n- **AMOUNT**: ${String(paymentIntentSucceeded.amount)}`);
|
"Stripe",
|
||||||
|
`A payment intent has succeeded.\n- **AMOUNT**: ${String(
|
||||||
|
paymentIntentSucceeded.amount,
|
||||||
|
)}`,
|
||||||
|
"info",
|
||||||
|
);
|
||||||
|
await sendMail(
|
||||||
|
`[STRIPE]: Payment Intent Succeeded`,
|
||||||
|
`A payment intent has succeeded.\n- **AMOUNT**: ${String(
|
||||||
|
paymentIntentSucceeded.amount,
|
||||||
|
)}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (event.type === "subscription_schedule.completed") {
|
if (event.type === "subscription_schedule.completed") {
|
||||||
const subscriptionScheduleCompleted = event.data.object;
|
const subscriptionScheduleCompleted = event.data.object;
|
||||||
// Then define and call a function to handle the event subscription_schedule.completed
|
await pipeLog(
|
||||||
await sendDiscord(`[STRIPE]: Subscription Completed`, `A subscription has been completed.\n- **ID**: ${subscriptionScheduleCompleted.id}`);
|
"Stripe",
|
||||||
await sendMail(`[STRIPE]: Subscription Completed`, `A subscription has been completed.\n- **ID**: ${subscriptionScheduleCompleted.id}`);
|
`A subscription has been completed.\n- **ID**: ${subscriptionScheduleCompleted.id}`,
|
||||||
|
"info",
|
||||||
|
);
|
||||||
|
await sendMail(
|
||||||
|
`[STRIPE]: Subscription Completed`,
|
||||||
|
`A subscription has been completed.\n- **ID**: ${subscriptionScheduleCompleted.id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await errorHandler(error, "Stripe Webhook");
|
await errorHandler(error, "Stripe Webhook");
|
||||||
@@ -266,6 +330,7 @@ export const instantiateServer = async(): Promise<void> => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
server.listen({ port: 5003 }, (error) => {
|
server.listen({ port: 5003 }, (error) => {
|
||||||
|
// eslint-disable-next-line max-lines -- This block is long because of logging.
|
||||||
const application = "Alert Server";
|
const application = "Alert Server";
|
||||||
if (error) {
|
if (error) {
|
||||||
const { message, stack } = error;
|
const { message, stack } = error;
|
||||||
@@ -274,16 +339,13 @@ export const instantiateServer = async(): Promise<void> => {
|
|||||||
`[ERROR]: ${context} - ${application}`,
|
`[ERROR]: ${context} - ${application}`,
|
||||||
`${message}\n\n${String(stack)}`,
|
`${message}\n\n${String(stack)}`,
|
||||||
);
|
);
|
||||||
void sendDiscord(
|
void pipeLog(application, `${message}\n\n${String(stack)}`, "error");
|
||||||
`[ERROR]: ${context} - ${application}`,
|
|
||||||
`${message}\n\n\`\`\`\n${String(stack)}\n\`\`\``,
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const level = "debug";
|
const level = "debug";
|
||||||
const message = `Server listening on port 5003.`;
|
const message = `Server listening on port 5003.`;
|
||||||
void sendMail(`[${level}]: ${application}`, message);
|
void sendMail(`[${level}]: ${application}`, message);
|
||||||
void sendDiscord(`[${level}]: ${application}`, message);
|
void pipeLog(application, message, level);
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const application = "Alert Server";
|
const application = "Alert Server";
|
||||||
@@ -294,9 +356,6 @@ export const instantiateServer = async(): Promise<void> => {
|
|||||||
`[ERROR]: ${context} - ${application}`,
|
`[ERROR]: ${context} - ${application}`,
|
||||||
`${message}\n\n${stack}`,
|
`${message}\n\n${stack}`,
|
||||||
);
|
);
|
||||||
void sendDiscord(
|
void pipeLog(application, `${message}\n\n${stack}`, "error");
|
||||||
`[ERROR]: ${context} - ${application}`,
|
|
||||||
`${message}\n\n\`\`\`\n${stack}\n\`\`\``,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user