penguin-band/index.js

427 lines
12 KiB
JavaScript

import fs from "fs";
import path from "path";
import { Client, GatewayIntentBits, Partials } from "discord.js";
const {
TOKEN,
GUILD_ID,
COMMAND_CHANNEL_ID,
ADDUP_ID,
PICKING_ID,
BLU_ID,
RED_ID,
FK_ID,
CAPTAIN_ID,
RANKING_WHITELIST,
} = require("./config.json");
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildPresences,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.DirectMessages,
GatewayIntentBits.MessageContent,
],
partials: [Partials.Channel, Partials.Message],
});
const backticks = "```";
const rankingsPath = path.join(__dirname, "rankings.json");
const matchString = (str, search) => {
if (!str || !search) return false;
return str.toLowerCase().includes(search.toLowerCase());
};
const findPlayer = (guild, searchName) => {
// search display name
let player = guild.members.cache.find((member) =>
matchString(member.displayName, searchName)
);
if (!player) {
// search global name
player = guild.members.cache.find((member) =>
matchString(member.user.globalName, searchName)
);
}
if (!player) {
// search username
player = guild.members.cache.find((member) =>
matchString(member.user.username, searchName)
);
}
if (!player) {
// match id
player = guild.members.cache.find((member) => member.id === searchName);
}
return player;
};
client.on("ready", () => {
console.log(`Logged in as ${client.user.tag}!`);
console.log(
`Deleting old messages from this bot in command channel: ${COMMAND_CHANNEL_ID}...`
);
let channel = client.channels.cache.get(COMMAND_CHANNEL_ID);
if (!channel) return console.error("(ready) Can't find command channel");
channel.messages
.fetch({ limit: 100 })
.then((messages) => {
messages.forEach((message) => {
if (message.author.id === client.user.id) {
message.delete();
}
});
})
.catch(console.error);
});
// send message on error
client.on("error", (error) => {
console.error(error);
let channel = client.channels.cache.get(COMMAND_CHANNEL_ID);
if (!channel) return console.error("Can't find command channel");
client.channels.cache
.get(COMMAND_CHANNEL_ID)
.send(`error: ${error.message}`)
.catch(console.error);
});
client.on("interactionCreate", async (interaction) => {
const command = interaction.commandName;
if (!interaction.isChatInputCommand()) return;
if (
command === "scout" ||
command === "soldier" ||
command === "pyro" ||
command === "demoman" ||
command === "demo" ||
command === "heavy" ||
command === "engineer" ||
command === "engi" ||
command === "medic" ||
command === "sniper" ||
command === "spy"
) {
// get voice channels
const picking = interaction.guild.channels.cache.find(
(channel) => channel.name === "picking" || channel.id === PICKING_ID
);
if (!picking) return console.error("Can't find channel 'picking'!");
const captain = interaction.guild.channels.cache.find(
(channel) => channel.name === "captains" || channel.id === CAPTAIN_ID
);
if (!captain) return console.error("Can't find channel 'captains'!");
// make sure user is in picking or captain channel
if (
!picking.members.has(interaction.user.id) &&
!captain.members.has(interaction.user.id)
) {
await interaction.reply({
content: "must be in picking or captains channel to use this command",
ephemeral: true,
});
return;
} else {
await interaction.reply({
content: "checking picking channel...",
ephemeral: true,
});
// set role name
let roleName = command;
if (command === "demoman") roleName = "demo";
if (command === "engi") roleName = "engineer";
// check each member in picking channel for role
let str = `In picking (${roleName}):`;
for (const member of picking.members.values()) {
if (member.roles.cache.find((role) => role.name === roleName)) {
if (str !== `In picking (${roleName}):`) str += ",";
str += " " + member.user.globalName;
}
}
if (str === `In picking (${roleName}):`)
str = `None found ¯\\_(ツ)_/¯ (${roleName})`;
// respond
return await interaction.followUp(str);
}
}
if (interaction.channelId !== COMMAND_CHANNEL_ID) {
await interaction.reply({
content: "wrong channel, or you lack the required permissions",
ephemeral: true,
});
return;
}
if (command === "hello") {
await interaction.reply("world");
}
if (
command === "topicking" ||
command === "end" ||
command === "resetteams"
) {
await interaction.reply("moving members...");
// get voice channels
const blu = interaction.guild.channels.cache.find(
(channel) => channel.name === "blu" || channel.id === BLU_ID
);
if (!blu) return console.error("Can't find channel 'blu'!");
const red = interaction.guild.channels.cache.find(
(channel) => channel.name === "red" || channel.id === RED_ID
);
if (!red) return console.error("Can't find channel 'red'!");
const addup = interaction.guild.channels.cache.find(
(channel) => channel.name === "add-up" || channel.id === ADDUP_ID
);
if (!addup) return console.error("Can't find channel 'add-up'!");
const picking = interaction.guild.channels.cache.find(
(channel) => channel.name === "picking" || channel.id === PICKING_ID
);
if (!picking) return console.error("Can't find channel 'picking'!");
// get members in voice channel
let members = blu.members.concat(red.members);
if (command !== "resetteams") members = members.concat(addup.members);
if (members.size === 0) {
return await interaction.followUp(
`found no members in ${
command === "resetteams" ? "blu" : "addup, blu,"
} or red`
);
}
// move members to addup
let idx = 0,
eCount = 0;
const moveToAddup = async (member) => {
try {
await member.voice.setChannel(picking);
} catch (error) {
console.error(error);
eCount++;
}
};
const moveAllToAddup = async () => {
return Promise.all(
Array.from(members, async ([memberId, member]) => {
await moveToAddup(member);
})
);
};
moveAllToAddup().then(() =>
interaction.followUp(
`moved members in ${
command === "resetteams" ? "blu" : "addup, blu,"
} and red${eCount > 0 ? ` (error moving ${eCount} members)` : ""}`
)
);
}
if (command === "fk" || command === "fatkid") {
await interaction.reply("moving fatkids...");
// get voice channels
const picking = interaction.guild.channels.cache.find(
(channel) => channel.name === "picking" || channel.id === PICKING_ID
);
if (!picking) return console.error("Can't find channel 'add-up'!");
const fk = interaction.guild.channels.cache.find(
(channel) => channel.name === "fatkid" || channel.id === FK_ID
);
if (!fk) return console.error("Can't find channel 'fatkid'!");
// get members in voice channel
const members = picking.members;
if (members.size === 0) {
return await interaction.followUp("found no members in picking");
}
let str = "",
eCount = 0;
const logFk = async (member) => {
try {
await member.voice.setChannel(fk);
if (str.length > 0) str += ", ";
str += member.user.globalName;
} catch (error) {
console.error(error);
eCount++;
}
};
const logAllFks = async () => {
return Promise.all(
Array.from(members, async ([memberId, member]) => {
await logFk(member);
})
);
};
logAllFks().then(() =>
interaction.followUp(
`fatkids: ${str}${
eCount > 0 ? ` (error moving ${eCount} members)` : ""
}`
)
);
}
if (command === "clear" || command === "bclear") {
await interaction.reply("clearing messages...");
let channel = client.channels.cache.get(COMMAND_CHANNEL_ID);
if (!channel) return console.error("Can't find command channel");
channel.messages
.fetch({ limit: 100 })
.then((messages) => {
messages.forEach((message) => {
if (message.author.id === client.user.id) {
message.delete();
}
});
})
.catch(console.error);
}
});
client.on("messageCreate", async (message) => {
if (message.author.bot || message.guild) return;
// check if user is whitelisted
if (!RANKING_WHITELIST.includes(message.author.id)) {
return;
}
if (message.content.toLowerCase().includes("hello penguin")) {
await message.reply(`hello ${message.author.username}`);
return;
}
const args = message.content.toLowerCase().split(" ");
if (args[0] === "setrank") {
if (args.length < 3) {
await message.reply(
"invalid number of arguments. usage: `setrank <player name or id> <rank (0-5)>`"
);
return;
}
const pickupGuild = client.guilds.cache.get(GUILD_ID);
if (!pickupGuild) {
await message.reply("could not find guild");
return;
}
const player = findPlayer(pickupGuild, args[1]);
if (!player) {
await message.reply(
`could not find player ${args[1]}. if this issue persists, try copy/pasting the player's discord handle or user id`
);
return;
}
const playerId = player.id;
const applicableName =
player.displayName ||
player.user.globalName ||
player.user.username ||
playerId;
const rank = parseInt(args[2]);
if (isNaN(rank) || rank < 0 || rank > 5) {
await message.reply(
`invalid rank ${args[2]}. must be an integer between 0 and 5`
);
return;
}
// create rankings.json if it doesn't exist
const rankingsPath = path.join(__dirname, "rankings.json");
if (!fs.existsSync(rankingsPath)) {
fs.writeFileSync(rankingsPath, "{}");
}
// rankings.json is a map of player's id to rank
const rankings = JSON.parse(fs.readFileSync(rankingsPath));
rankings[playerId] = rank;
console.log(
`setting rank of ${applicableName}, ${playerId} to ${rank} at ${rankingsPath}...`
);
new Promise((resolve, reject) => {
fs.writeFile(rankingsPath, JSON.stringify(rankings), (err) => {
if (err) reject(err);
else resolve();
});
}).then((res, err) => {
if (err) {
console.error(err);
message.reply(`error setting rank: ${err.message}`);
} else {
message.reply(`set rank of ${applicableName} to ${rank}`);
}
});
}
if (args[0] === "getrank") {
if (args.length < 2) {
await message.reply(
"invalid number of arguments. usage: `getrank <player name or id>`"
);
return;
}
const pickupGuild = client.guilds.cache.get(GUILD_ID);
if (!pickupGuild) {
await message.reply("could not find guild");
return;
}
const player = findPlayer(pickupGuild, args[1]);
if (!player) {
await message.reply(
`could not find player ${args[1]}. if this issue persists, try using the player's id`
);
return;
}
const playerId = player.id;
const applicableName =
player.displayName ||
player.user.globalName ||
player.user.username ||
playerId;
try {
console.log(
`getting rank of ${applicableName}, ${playerId} at ${rankingsPath}...`
);
const rankings = JSON.parse(fs.readFileSync(rankingsPath));
await message.reply(
`${backticks}${applicableName} - ${"*".repeat(
rankings[playerId]
)}${backticks}`
);
} catch (error) {
console.error(error);
await message.reply(`error getting rank: ${error.message}`);
}
}
});
client.login(TOKEN);