Files
futility-engine/index.js
2025-05-22 22:21:04 +02:00

151 lines
4.6 KiB
JavaScript

import { ActivityType, Client, Events, GatewayIntentBits, OverwriteType, PermissionFlagsBits } from 'discord.js';
import { readFileSync } from "fs";
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildPresences,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.GuildModeration,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMessages
],
});
const config = JSON.parse(readFileSync("config.json", "utf-8"));
const banConfig = JSON.parse(readFileSync("ban_config.json", "utf-8"));
await client.login(readFileSync("token.txt", "utf-8").split("\n")[0]);
const tracker = {};
for (let guild in config) {
tracker[guild] = {};
for (let channel in config[guild]) {
tracker[guild][channel] = new Set();
}
}
async function resyncChannel(channelObj) {
if (tracker[channelObj.guild.id] && tracker[channelObj.guild.id][channelObj.id]) {
tracker[channelObj.guild.id][channelObj.id] = new Set(channelObj.members.map((v, k) => k));
}
}
async function fullSync() {
for (let guild in config) {
const guildObj = await client.guilds.fetch(guild);
for (let channel in config[guild]) {
const channelObj = await guildObj.channels.fetch(channel);
await resyncChannel(channelObj);
await updateChannel(channelObj.id, await guildObj.channels.fetch(config[guild][channel]));
}
}
}
async function updateChannel(vcId, channelObj) {
if (!tracker[channelObj.guild.id] || !tracker[channelObj.guild.id][vcId]) return;
let t = tracker[channelObj.guild.id][vcId];
const permissions = channelObj.permissionOverwrites.cache.filter((v) => v.type === OverwriteType.Member);
let extraneous = permissions.filter((v) => !t.has(v.id));
let missing = Array.from(t).filter(id => !permissions.has(id));
extraneous.each(v => {
channelObj.permissionOverwrites.delete(v.id, "Not in VC");
});
for (let a of missing) {
channelObj.permissionOverwrites.create(
a,
{
ViewChannel: true,
SendMessages: true,
AddReactions: true
},
{
type: OverwriteType.Member,
reason: "User in VC"
}
);
}
}
client.on(Events.GuildAvailable, async g => {
console.log(g.name,"available");
await fullSync();
});
client.on(Events.GuildCreate, async g => {
console.log(g.name,"create");
await fullSync();
});
client.on(Events.ClientReady, async () => {
client.user.setActivity({
type: ActivityType.Competing,
name: "best bot competition 2025"
})
})
client.on(Events.MessageCreate, async m => {
if (!m.guildId) {
console.log("Got non-guild message");
return;
}
if (!banConfig[m.guildId]) {
console.log("Got message in", m.guildId, "/", m.channelId, "without ban config setup.");
return;
}
let channels = banConfig[m.guildId];
if (channels.includes(m.channelId)) {
try {
const dm = await m.author.createDM();
await dm.send("You have been banned for sending a message in the bot trap. Mistake? Appeal here: https://forms.gle/r41Qd12A3Df6kbm56");
} catch(e) {
console.log("Failed to send message", e);
}
try {
await m.guild.bans.create(m.author, {
deleteMessageSeconds: 600,
reason: "Caught in a bot trap like a stupid fly in a glue trap."
})
} catch(e) {
console.log("Failed to issue ban", e);
}
return;
}
});
client.on(Events.VoiceStateUpdate, async (oldState, newState) => {
if (oldState.channelId === newState.channelId) return;
let affectedChannels = new Set();
if (oldState.channelId && tracker[oldState.guild.id] && tracker[oldState.guild.id][oldState.channelId]) {
tracker[oldState.guild.id][oldState.channelId].delete(oldState.id);
affectedChannels.add(oldState.channelId);
}
if (newState.channelId && tracker[newState.guild.id] && tracker[newState.guild.id][newState.channelId]) {
tracker[newState.guild.id][newState.channelId].add(newState.id);
affectedChannels.add(newState.channelId);
}
for (let ch of Array.from(affectedChannels)) {
if ( config[oldState.guild.id] && config[oldState.guild.id][ch]) {
await updateChannel(ch, await oldState.guild.channels.fetch(config[oldState.guild.id][ch]));
}
}
});