generated from nhcarrigan/template
feat: migrate from github
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
export const colourRoles = [
|
||||
"883281643098484736",
|
||||
"883283836887261204",
|
||||
"883282544655753268",
|
||||
"883283096378683402",
|
||||
"883283115265642547",
|
||||
"883283650794360852",
|
||||
"883284117343584298",
|
||||
"883284381937065984",
|
||||
];
|
||||
|
||||
export const boosterRole = "712431541531181177";
|
||||
@@ -0,0 +1,49 @@
|
||||
import { RewriteFrames } from "@sentry/integrations";
|
||||
import * as Sentry from "@sentry/node";
|
||||
import { Client, GatewayIntentBits, WebhookClient } from "discord.js";
|
||||
|
||||
import { manageRoles } from "./modules/manageRoles";
|
||||
import { errorHandler } from "./utils/errorHandler";
|
||||
|
||||
Sentry.init({
|
||||
dsn: process.env.SENTRY_DSN,
|
||||
tracesSampleRate: 1.0,
|
||||
integrations: [
|
||||
new RewriteFrames({
|
||||
root: global.__dirname,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const bot = new Client({
|
||||
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers],
|
||||
});
|
||||
|
||||
bot.on("ready", async () => {
|
||||
const hook = new WebhookClient({ url: process.env.DEBUG_HOOK as string });
|
||||
await hook.send({
|
||||
content: "Oogie boogie boostie woostie online!",
|
||||
username: "Boost Monitor",
|
||||
avatarURL: "https://cdn.nhcarrigan.com/avatars/nhcarrigan.png",
|
||||
});
|
||||
|
||||
const guild = bot.guilds.cache.map((el) => el)[0];
|
||||
const members = await guild.members.fetch();
|
||||
await hook.send({
|
||||
content: `Loaded ${members.size} members from ${guild.name}`,
|
||||
username: "Boost Monitor",
|
||||
avatarURL: "https://cdn.nhcarrigan.com/avatars/nhcarrigan.png",
|
||||
});
|
||||
});
|
||||
|
||||
bot.on("guildMemberUpdate", async (_oldMember, newMember) => {
|
||||
await manageRoles(newMember);
|
||||
});
|
||||
|
||||
await bot.login(process.env.DISCORD_TOKEN);
|
||||
} catch (err) {
|
||||
await errorHandler("index", err);
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,26 @@
|
||||
import { GuildMember } from "discord.js";
|
||||
|
||||
import { boosterRole, colourRoles } from "../config/roles";
|
||||
import { errorHandler } from "../utils/errorHandler";
|
||||
|
||||
/**
|
||||
* Attaches to the memberUpdate event, and checks if the member is no longer boosting
|
||||
* the server (based on the premiumSubscriberRole). If true, then removes any of the configured
|
||||
* booster-only roles.
|
||||
*
|
||||
* @param {GuildMember} newMember The state of the member after the update.
|
||||
*/
|
||||
export const manageRoles = async (newMember: GuildMember): Promise<void> => {
|
||||
try {
|
||||
if (!newMember.roles.cache.has(boosterRole)) {
|
||||
for (const roleId of colourRoles) {
|
||||
const target = newMember.roles.cache.find((role) => role.id === roleId);
|
||||
if (target) {
|
||||
await newMember.roles.remove(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
await errorHandler("manageRoles", err);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
import * as Sentry from "@sentry/node";
|
||||
import { EmbedBuilder, WebhookClient } from "discord.js";
|
||||
|
||||
import { logHandler } from "./logHandler";
|
||||
|
||||
/**
|
||||
* Standard error handling module to pipe errors to Sentry and
|
||||
* format the error for logging.
|
||||
*
|
||||
* @param {string} context A description of where the error occurred.
|
||||
* @param {Error} err The error object.
|
||||
*/
|
||||
export const errorHandler = async (context: string, err: unknown) => {
|
||||
const error = err as Error;
|
||||
logHandler.log("error", `There was an error in the ${context}:`);
|
||||
logHandler.log(
|
||||
"error",
|
||||
JSON.stringify({ errorMessage: error.message, errorStack: error.stack })
|
||||
);
|
||||
Sentry.captureException(error);
|
||||
|
||||
const hook = new WebhookClient({ url: process.env.DEBUG_HOOK as string });
|
||||
|
||||
const embed = new EmbedBuilder();
|
||||
embed.setTitle(`There was an error in the ${context}`);
|
||||
embed.setDescription(error.message.slice(0, 2000));
|
||||
embed.addFields([
|
||||
{
|
||||
name: "Stack",
|
||||
value: `\`\`\`${error.stack?.slice(0, 1000) || "no stack"}\`\`\``,
|
||||
},
|
||||
]);
|
||||
|
||||
await hook.send({
|
||||
embeds: [embed],
|
||||
username: "Boost Monitor",
|
||||
avatarURL: "https://cdn.nhcarrigan.com/avatars/nhcarrigan.png",
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
import { createLogger, format, transports, config } from "winston";
|
||||
|
||||
const { combine, timestamp, colorize, printf } = format;
|
||||
|
||||
/**
|
||||
* Standard log handler, using winston to wrap and format
|
||||
* messages. Call with `logHandler.log(level, message)`.
|
||||
*
|
||||
* @param {string} level - The log level to use.
|
||||
* @param {string} message - The message to log.
|
||||
*/
|
||||
export const logHandler = createLogger({
|
||||
levels: config.npm.levels,
|
||||
level: "silly",
|
||||
transports: [new transports.Console()],
|
||||
format: combine(
|
||||
timestamp({
|
||||
format: "YYYY-MM-DD HH:mm:ss",
|
||||
}),
|
||||
colorize(),
|
||||
printf((info) => `${info.level}: ${[info.timestamp]}: ${info.message}`)
|
||||
),
|
||||
exitOnError: false,
|
||||
});
|
||||
Reference in New Issue
Block a user