From 61eee729172ca97e4023b4fb40af7703af26b784 Mon Sep 17 00:00:00 2001 From: Hri7566 Date: Fri, 8 Mar 2024 20:58:15 -0500 Subject: [PATCH] Add Discord bot, give command (disabled) --- bun.lockb | Bin 53066 -> 62252 bytes config/discord.yml | 2 + package.json | 1 + src/api/commands/groups/general/help.ts | 2 +- src/api/commands/groups/index.ts | 3 +- src/api/commands/groups/inventory/give.ts | 130 +++++++++++++++ src/discord/bot/Bot.ts | 185 ++++++++++++++++++++++ src/discord/bot/index.ts | 10 ++ src/discord/index.ts | 10 ++ 9 files changed, 341 insertions(+), 2 deletions(-) create mode 100644 config/discord.yml create mode 100644 src/api/commands/groups/inventory/give.ts create mode 100644 src/discord/bot/Bot.ts create mode 100644 src/discord/bot/index.ts create mode 100644 src/discord/index.ts diff --git a/bun.lockb b/bun.lockb index 47beab24d530c2f66555cd764544d71955b6c0bc..8db66774cfd9884f1df344e0c565489dd75cfd55 100755 GIT binary patch delta 15274 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 B6}|uf delta 9736 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 diff --git a/config/discord.yml b/config/discord.yml new file mode 100644 index 0000000..f6b1962 --- /dev/null +++ b/config/discord.yml @@ -0,0 +1,2 @@ +serverID: "841331769051578413" +defaultChannelID: "841331769658703954" diff --git a/package.json b/package.json index a4a00dd..1df75ed 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@trpc/client": "next", "@trpc/server": "next", "cli-markdown": "^3.2.2", + "discord.js": "^14.14.1", "mpp-client-net": "^1.1.3", "prisma": "^5.9.1", "trpc-bun-adapter": "^1.1.0", diff --git a/src/api/commands/groups/general/help.ts b/src/api/commands/groups/general/help.ts index d1d1824..e5d2191 100644 --- a/src/api/commands/groups/general/help.ts +++ b/src/api/commands/groups/general/help.ts @@ -32,7 +32,7 @@ export const help = new Command( } if (list2.length > 0) - list.push(`${group.displayName}: ${list2.join(", ")}`); + list.push(`**${group.displayName}:** ${list2.join(", ")}`); } return `__Fishing:__\n${list.join("\n")}`; diff --git a/src/api/commands/groups/index.ts b/src/api/commands/groups/index.ts index 151ac58..3f4065a 100644 --- a/src/api/commands/groups/index.ts +++ b/src/api/commands/groups/index.ts @@ -21,6 +21,7 @@ import { myid } from "./general/myid"; import { yeet } from "./inventory/yeet"; import { tree } from "./fishing/tree"; import { pick } from "./fishing/pick"; +// import { give } from "./inventory/give"; interface ICommandGroup { id: string; @@ -49,7 +50,7 @@ commandGroups.push(fishingGroup); const inventoryGroup: ICommandGroup = { id: "inventory", displayName: "Inventory", - commands: [inventory, take, eat, sack, pokemon, yeet] + commands: [inventory, take, eat, sack, pokemon, yeet /* give */] }; commandGroups.push(inventoryGroup); diff --git a/src/api/commands/groups/inventory/give.ts b/src/api/commands/groups/inventory/give.ts new file mode 100644 index 0000000..34a6914 --- /dev/null +++ b/src/api/commands/groups/inventory/give.ts @@ -0,0 +1,130 @@ +import type { User } from "@prisma/client"; +import Command from "@server/commands/Command"; +import { getInventory, updateInventory } from "@server/data/inventory"; +import prisma from "@server/data/prisma"; +import { addItem } from "@server/items"; + +export const give = new Command( + "give", + ["give", "govo", "guvu", "gava", "geve", "givi", "g", "donate", "bestow"], + "Give another user something you have", + "give ", + "command.inventory.give", + async ({ id, command, args, prefix, part, user }) => { + const inventory = await getInventory(user.inventoryId); + if (!inventory) return; + + let targetFuzzy = args[0]; + if (!targetFuzzy) return `To whom will you ${prefix}${command} to?`; + + let foundUser: User = user; + foundUser = (await prisma.user.findFirst({ + where: { + name: { + contains: targetFuzzy, + mode: "insensitive" + } + } + })) as User; + + if (!foundUser) return `Who is ${targetFuzzy}? I don't know them.`; + + const foundInventory = await getInventory(foundUser.inventoryId); + if (!foundInventory) return `They have no room, apparently.`; + + if (!args[1]) + return `What are you going to ${prefix}${command} to ${foundUser.name}?`; + const argcat = args.slice(1).join(" "); + let foundObject: IObject | undefined; + + let i = 0; + + for (const item of inventory.items as unknown as IItem[]) { + if (!item.name.toLowerCase().includes(argcat.toLowerCase())) { + i++; + continue; + } + + foundObject = item; + break; + } + + i = 0; + + for (const fish of inventory.fishSack as TFishSack) { + if (!fish.name.toLowerCase().includes(argcat.toLowerCase())) { + i++; + continue; + } + + foundObject = fish; + break; + } + + if (!foundObject) return `You don't have any "${argcat}" to give.`; + + let updated = false; + + if (foundObject.objtype == "item") { + addItem(foundInventory.items as unknown as IItem[], foundObject); + updated = true; + } else if (foundObject.objtype == "fish") { + addItem(foundInventory.items as unknown as IItem[], foundObject); + updated = true; + } + + let shouldRemove = false; + + if (updated) { + await updateInventory(foundInventory); + + if (foundObject.objtype == "fish") { + i = 0; + + for (const fish of inventory.fishSack as TFishSack) { + if (typeof fish.count !== "undefined") { + if (fish.count > 1) { + shouldRemove = false; + ((inventory.fishSack as TFishSack)[i] + .count as number)--; + } else { + shouldRemove = true; + } + } else { + shouldRemove = true; + } + + if (shouldRemove) + (inventory.fishSack as TFishSack).splice(i, 1); + break; + } + } else if (foundObject.objtype == "item") { + i = 0; + + for (const item of inventory.items as unknown as IItem[]) { + if (typeof item.count == "number") { + if (item.count > 1) { + shouldRemove = false; + ((inventory.items as TInventoryItems)[i] + .count as number)--; + } else { + shouldRemove = true; + } + } else { + shouldRemove = true; + } + + if (shouldRemove) + (inventory.items as TInventoryItems).splice(i, 1); + break; + } + } + + return `You ${ + command.endsWith("e") ? `${command}d` : `${command}ed` + } your ${foundObject.name} to ${foundUser.name}.`; + } else { + return `You tried to give your ${foundObject.name} away, but I messed up and the transaction was reverted.`; + } + } +); diff --git a/src/discord/bot/Bot.ts b/src/discord/bot/Bot.ts new file mode 100644 index 0000000..a8bd840 --- /dev/null +++ b/src/discord/bot/Bot.ts @@ -0,0 +1,185 @@ +import { EventEmitter } from "events"; +import Discord from "discord.js"; +import { Logger } from "@util/Logger"; +import { CosmicColor } from "@util/CosmicColor"; +import trpc from "@util/api/trpc"; + +export interface DiscordBotConfig { + serverID: string; + defaultChannelID: string; + token?: string; +} + +export class DiscordBot extends EventEmitter { + public client: Discord.Client; + public logger = new Logger("Discord Bot"); + public token?: string; + public server?: Discord.Guild; + public defaultChannel?: Discord.TextChannel; + public b = new EventEmitter(); + + constructor(public conf: DiscordBotConfig) { + super(); + + this.token = conf.token ?? process.env.DISCORD_TOKEN; + this.client = new Discord.Client({ + intents: [ + "Guilds", + "GuildMessages", + "MessageContent", + "GuildMembers" + ] + }); + + this.bindEventListeners(); + } + + public async start() { + await this.client.login(this.token); + } + + private bindEventListeners() { + this.client.on("ready", async () => { + this.logger.info("Connected to Discord"); + + this.server = await this.client.guilds.fetch(this.conf.serverID); + + const channel = await this.server.channels.fetch( + this.conf.defaultChannelID + ); + + if (!channel) throw "Unable to find default Discord channel."; + + this.defaultChannel = channel as Discord.TextChannel; + }); + + this.client.on("guildMemberAdd", async member => { + if (!this.server) return; + + const color = new CosmicColor( + Math.floor(Math.random() * 255), + Math.floor(Math.random() * 255), + Math.floor(Math.random() * 255) + ); + + const existingRole = this.server.roles.cache.find( + role => role.name === member.id + ); + + if (existingRole) { + await member.roles.add(existingRole); + return; + } + + const role = await this.server.roles.create({ + name: member.id, + color: parseInt(color.toHexa().substring(1), 16) + }); + + await member.roles.add(role); + }); + + this.client.on("messageCreate", async msg => { + if (!this.server) return; + if (msg.guildId !== this.server.id) return; + + const existingRole = this.server.roles.cache.find( + role => role.name === msg.author.id + ); + + if (!existingRole) return; + + let prefixes: string[]; + + try { + prefixes = await trpc.prefixes.query(); + } catch (err) { + this.logger.error(err); + this.logger.warn("Unable to contact server"); + return; + } + + let usedPrefix: string | undefined = prefixes.find(pr => + msg.content.startsWith(pr) + ); + + if (!usedPrefix) return; + + const args = msg.content.split(" "); + + const command = await trpc.command.query({ + args: args.slice(1, args.length), + command: args[0].substring(usedPrefix.length), + prefix: usedPrefix, + user: { + id: msg.author.id, + name: msg.author.displayName, + color: existingRole.hexColor + } + }); + + if (!command) return; + if (command.response) + msg.reply( + command.response + .split(`@${msg.author.id}`) + .join(`<@${msg.author.id}>`) + ); + }); + + setInterval(async () => { + try { + const backs = (await trpc.backs.query()) as IBack[]; + if (backs.length > 0) { + // this.logger.debug(backs); + for (const back of backs) { + if (typeof back.m !== "string") return; + this.b.emit(back.m, back); + } + } + } catch (err) { + return; + } + }, 1000 / 20); + + this.b.on("color", async msg => { + if (typeof msg.color !== "string" || typeof msg.id !== "string") + return; + + if (!this.server) return; + + const existingRole = this.server.roles.cache.find( + role => role.name === msg.id + ); + + if (!existingRole) { + try { + const member = await this.server.members.fetch(msg.id); + if (!member) throw "no member"; + + const role = await this.server.roles.create({ + name: member.id, + color: parseInt(msg.color.substring(1), 16) + }); + + await member.roles.add(role); + return; + } catch (err) { + return; + } + } + + await existingRole.setColor(parseInt(msg.color.substring(1), 16)); + }); + + this.b.on("sendchat", msg => { + // this.logger.debug("sendchat message:", msg); + if (!this.defaultChannel) return; + this.defaultChannel.send( + msg.message + .split(`@${msg.author.id}`) + .join(`<@${msg.author.id}>`) + ); + }); + } +} diff --git a/src/discord/bot/index.ts b/src/discord/bot/index.ts new file mode 100644 index 0000000..8464004 --- /dev/null +++ b/src/discord/bot/index.ts @@ -0,0 +1,10 @@ +import { DiscordBot, type DiscordBotConfig } from "./Bot"; + +export async function initBot(conf: DiscordBotConfig) { + const bot = new DiscordBot(conf); + await bot.start(); +} + +export { DiscordBot as Bot }; + +export default DiscordBot; diff --git a/src/discord/index.ts b/src/discord/index.ts new file mode 100644 index 0000000..086894c --- /dev/null +++ b/src/discord/index.ts @@ -0,0 +1,10 @@ +import { loadConfig } from "@util/config"; +import { initBot } from "./bot"; +import type { DiscordBotConfig } from "./bot/Bot"; + +const config = loadConfig("config/discord.yml", { + serverID: "841331769051578413", + defaultChannelID: "841331769658703954" +}); + +await initBot(config);