Some refactoring and staging limbo command

This commit is contained in:
2026-08-22 17:27:02 -04:00
parent a0b7dd5338
commit 3f2474f3f4
7 changed files with 116 additions and 32 deletions
+2 -2
View File
@@ -11,7 +11,7 @@ const roleService = new RoleService(client);
client.once(Events.ClientReady, async (readyClient) => { client.once(Events.ClientReady, async (readyClient) => {
// Initialize & validate // Initialize & validate
await commandService.init(); await commandService.init();
roleService.validate(); roleService.validate(client.guilds.cache);
// Ready! // Ready!
console.log(`Ready! Logged in as ${readyClient.user.tag}`); console.log(`Ready! Logged in as ${readyClient.user.tag}`);
@@ -30,7 +30,7 @@ client.on("messageCreate", async (message) => {
Bun.cron("0 */6 * * *", async () => { Bun.cron("0 */6 * * *", async () => {
for (const guild of client.guilds.cache.values()) { for (const guild of client.guilds.cache.values()) {
const lurkerRole = roleService.getRoleByName(guild, roleService.ROLES["LURKER"]); const lurkerRole = roleService.getRoleByName(guild, RoleService.ROLES["LURKER"]?.name);
if (!lurkerRole) continue; if (!lurkerRole) continue;
await guild.members.prune({ days: 5, roles: [lurkerRole] }); await guild.members.prune({ days: 5, roles: [lurkerRole] });
+14 -4
View File
@@ -4,11 +4,21 @@ import Chan from "../../../util/chan";
export default { export default {
name: "chan", name: "chan",
description: "Get random media from a 4chan board. Usage: .chan <board> [search]", description: "Get random media from a 4chan board.",
usage: ".chan <board> [search]",
execute: async (message: Message) => { execute: async (message: Message) => {
const [, board, search] = message.content.split(/\s+/); const [, board, search] = message.content.split(/\s+/);
if (!board) return message.reply("Usage: .chan <board> [search]");
if (Chan.isNsfwBoard(board)) return message.reply("Fuck off nigger"); if (!board) {
await message.reply("Usage: .chan <board> [search]")
return;
};
if (Chan.isNsfwBoard(board)) {
await message.reply("Fuck off nigger")
return;
};
await message.reply(await Chan.getMediaLink(board, search)); await message.reply(await Chan.getMediaLink(board, search));
} }
} as Command; } satisfies Command;
+3 -2
View File
@@ -4,10 +4,11 @@ import Chan from "../../../util/chan";
export default { export default {
name: "comfy", name: "comfy",
description: "Get comfy content from 4chan", description: "Get comfy content from 4chan.",
usage: ".comfy",
execute: async (message: Message) => { execute: async (message: Message) => {
const boards = ["wsg", "wg"]; const boards = ["wsg", "wg"];
const board = boards[Math.floor(Math.random() * boards.length)] ?? "wsg"; const board = boards[Math.floor(Math.random() * boards.length)] ?? "wsg";
await message.reply(await Chan.getMediaLink(board, "comfy")); await message.reply(await Chan.getMediaLink(board, "comfy"));
} }
} as Command; } satisfies Command;
+10
View File
@@ -0,0 +1,10 @@
import type { Message } from "discord.js";
import type { Command } from "../service";
export default {
name: "limbo",
description: "Toggles on/off limbo mode. When limbo mode is on, new members will be placed in #limbo. When off, new members will be placed in #chat-and-shitpost.",
usage: ".limbo [on|off]",
execute: async (message: Message) => {
}
} satisfies Command;
+3 -2
View File
@@ -3,12 +3,13 @@ import type { Command } from "../service";
export default { export default {
name: "redpillme", name: "redpillme",
description: "Receive wisdom from the Unabomber", description: "Receive wisdom from the Unabomber.",
usage: ".redpillme",
execute: async (message: Message) => { execute: async (message: Message) => {
const quote = quotes[Math.floor(Math.random() * quotes.length)]; const quote = quotes[Math.floor(Math.random() * quotes.length)];
await message.reply(quote!); await message.reply(quote!);
} }
} as Command; } satisfies Command;
const quotes = [ const quotes = [
"Our society tends to regard as a sickness any mode of thought or behavior that is inconvenient for the system and this is plausible because when an individual doesn't fit into the system it causes pain to the individual as well as problems for the system. Thus the manipulation of an individual to adjust him to the system is seen as a cure for a sickness and therefore as good.", "Our society tends to regard as a sickness any mode of thought or behavior that is inconvenient for the system and this is plausible because when an individual doesn't fit into the system it causes pain to the individual as well as problems for the system. Thus the manipulation of an individual to adjust him to the system is seen as a cure for a sickness and therefore as good.",
+1
View File
@@ -6,6 +6,7 @@ const CMD_PREFIX = ".";
export interface Command { export interface Command {
name: string, name: string,
description: string, description: string,
usage: string,
execute: (message: Message) => void | Promise<void> execute: (message: Message) => void | Promise<void>
} }
+79 -18
View File
@@ -1,42 +1,103 @@
import type { Client, Guild, GuildMember } from "discord.js"; import type { Client, Guild, GuildMember, Collection, RoleCreateOptions } from "discord.js";
export default class RoleService { export default class RoleService {
ROLES = { static readonly ROLES: Record<string, RoleCreateOptions> = {
"ROBOT": "robot", // Main
"NORMALFAG": "normalfag", "ROBOT": {
"FEMOID": "femoid", name: "robot",
"GAY": "gay", colors: { primaryColor: "#58a9df" },
"TROID": "troid", hoist: true,
"LURKER": "lurker", mentionable: true,
"NEWFAG": "newfag", position: 1,
"LIMBO": "limbo" },
"FEMOID": {
name: "femoid",
colors: { primaryColor: "#ffb2f4" },
hoist: true,
mentionable: true,
position: 2,
},
"NORMALFAG": {
name: "normalfag",
colors: { primaryColor: "#e26254" },
hoist: true,
mentionable: true,
position: 3,
},
"GAY": {
name: "gay",
colors: { primaryColor: "#71368a" },
hoist: true,
mentionable: true,
position: 4,
},
"TROID": {
name: "troid",
colors: { primaryColor: "#992d22" },
hoist: true,
mentionable: true,
position: 5,
},
"LURKER": {
name: "lurker",
colors: { primaryColor: "#546e7a" },
hoist: true,
mentionable: true,
position: 6,
},
// Utility
"NEWFAG": {
name: "newfag",
mentionable: true,
position: 7,
},
"LIMBO": {
name: "limbo",
position: 8,
}
}; };
private client: Client static readonly STARTER_ROLES = [RoleService.ROLES["LURKER"], RoleService.ROLES["NEWFAG"]];
private starterRoles = [this.ROLES["LURKER"], this.ROLES["NEWFAG"]]; private client: Client
constructor(client: Client) { constructor(client: Client) {
this.client = client; this.client = client;
} }
validate(): void { validate(guilds: Collection<string, Guild>): void {
this.client.guilds.cache.forEach(guild => { guilds.forEach(guild => {
const missing = Object.values(this.ROLES).filter(name => !guild.roles.cache.find(r => r.name === name)); const missing = Object.values(RoleService.ROLES).filter(role => !this.getRoleByName(guild, role.name));
if (missing.length) console.error(`${guild.name} is missing roles: ${missing.join(",")}`); if (missing.length) console.error(`${guild.name} is missing roles: ${missing.join(",")}`);
}); });
} }
async createRoles(guild: Guild, roles: RoleCreateOptions[]) {
for (const role of roles) {
try {
await guild.roles.create(role);
}
catch (err) {
console.error(`Failed to create role: ${role.name}`, err);
}
}
}
async giveStarterRoles(guildMember: GuildMember) { async giveStarterRoles(guildMember: GuildMember) {
for (const starterRole of this.starterRoles) { for (const starterRole of RoleService.STARTER_ROLES) {
const role = this.getRoleByName(guildMember.guild, starterRole); const role = this.getRoleByName(guildMember.guild, starterRole?.name);
if (!role) continue; if (!role) continue;
try {
await guildMember.roles.add(role); await guildMember.roles.add(role);
} }
catch (err) {
console.error(`Failed to add starter role: ${role.name}`, err);
}
}
} }
getRoleByName(guild: Guild, roleName: string) { getRoleByName(guild: Guild, roleName?: string) {
return guild.roles.cache.find(role => role.name === roleName); return guild.roles.cache.find(role => role.name === roleName);
} }
} }