Add Discord bot, give command (disabled)
This commit is contained in:
parent
f1602461f7
commit
61eee72917
|
@ -0,0 +1,2 @@
|
|||
serverID: "841331769051578413"
|
||||
defaultChannelID: "841331769658703954"
|
|
@ -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",
|
||||
|
|
|
@ -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")}`;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 <user> <item>",
|
||||
"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.`;
|
||||
}
|
||||
}
|
||||
);
|
|
@ -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<unknown>[];
|
||||
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}>`)
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -0,0 +1,10 @@
|
|||
import { loadConfig } from "@util/config";
|
||||
import { initBot } from "./bot";
|
||||
import type { DiscordBotConfig } from "./bot/Bot";
|
||||
|
||||
const config = loadConfig<DiscordBotConfig>("config/discord.yml", {
|
||||
serverID: "841331769051578413",
|
||||
defaultChannelID: "841331769658703954"
|
||||
});
|
||||
|
||||
await initBot(config);
|
Loading…
Reference in New Issue