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/client": "next",
|
||||||
"@trpc/server": "next",
|
"@trpc/server": "next",
|
||||||
"cli-markdown": "^3.2.2",
|
"cli-markdown": "^3.2.2",
|
||||||
|
"discord.js": "^14.14.1",
|
||||||
"mpp-client-net": "^1.1.3",
|
"mpp-client-net": "^1.1.3",
|
||||||
"prisma": "^5.9.1",
|
"prisma": "^5.9.1",
|
||||||
"trpc-bun-adapter": "^1.1.0",
|
"trpc-bun-adapter": "^1.1.0",
|
||||||
|
|
|
@ -32,7 +32,7 @@ export const help = new Command(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list2.length > 0)
|
if (list2.length > 0)
|
||||||
list.push(`${group.displayName}: ${list2.join(", ")}`);
|
list.push(`**${group.displayName}:** ${list2.join(", ")}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return `__Fishing:__\n${list.join("\n")}`;
|
return `__Fishing:__\n${list.join("\n")}`;
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { myid } from "./general/myid";
|
||||||
import { yeet } from "./inventory/yeet";
|
import { yeet } from "./inventory/yeet";
|
||||||
import { tree } from "./fishing/tree";
|
import { tree } from "./fishing/tree";
|
||||||
import { pick } from "./fishing/pick";
|
import { pick } from "./fishing/pick";
|
||||||
|
// import { give } from "./inventory/give";
|
||||||
|
|
||||||
interface ICommandGroup {
|
interface ICommandGroup {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -49,7 +50,7 @@ commandGroups.push(fishingGroup);
|
||||||
const inventoryGroup: ICommandGroup = {
|
const inventoryGroup: ICommandGroup = {
|
||||||
id: "inventory",
|
id: "inventory",
|
||||||
displayName: "Inventory",
|
displayName: "Inventory",
|
||||||
commands: [inventory, take, eat, sack, pokemon, yeet]
|
commands: [inventory, take, eat, sack, pokemon, yeet /* give */]
|
||||||
};
|
};
|
||||||
|
|
||||||
commandGroups.push(inventoryGroup);
|
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