jillo-bot/src/lib/counter.ts

122 lines
3.5 KiB
TypeScript

import { Client, CommandInteraction, GuildMember, EmbedBuilder, TextChannel, AutocompleteInteraction } from 'discord.js';
import { getSign } from './util';
import { Counter, db } from './db';
export async function getCounter(type: string) {
const counter = await db<Counter>('counters')
.where('key', type)
.first();
if (!counter) throw 'No such counter';
return counter.value;
}
export async function changeCounter(delta: number, type: string) {
const value = await getCounter(type);
const newValue = value + delta;
await db<Counter>('counters')
.where('key', type)
.update({
'value': newValue
});
return newValue;
}
export async function getCounterData(type: string) {
const counter = await db<Counter>('counters')
.select('*')
.where('key', type)
.first();
if (!counter) throw 'No such counter';
return counter;
}
export async function updateCounter(bot: Client, counter: Counter, value: number) {
const channel = await bot.channels.fetch(counter.channel) as TextChannel;
const messageID = counter.message;
const content = `[${counter.emoji}] x${value}`;
// bit janky
// yeah you don't say
try {
if (messageID) {
const message = await channel.messages.fetch(messageID);
if (!message) throw new Error();
await message.edit(content);
} else {
throw new Error();
}
} catch(err) {
const message = await channel.send(content);
message.pin();
await db<Counter>('counters')
.where('key', counter.key)
.update({
'message': message.id
});
}
}
export async function announceCounterUpdate(bot: Client, member: GuildMember, delta: number, counter: Counter, value: number) {
const channel = await bot.channels.fetch(counter.channel) as TextChannel;
const embed = new EmbedBuilder()
.setAuthor({
name: `${member.user.username}#${member.user.discriminator}`,
iconURL: member.user.displayAvatarURL()
})
.setDescription(`**${member.toString()}** has ${delta > 0 ? 'increased' : 'decreased'} the counter by **${Math.abs(delta)}**.`)
.setColor(member.displayColor)
.setTimestamp()
.setFooter({
text: `[${counter.emoji}] x${value}`
});
await channel.send({
embeds: [embed]
});
}
export async function changeCounterInteraction(interaction: CommandInteraction, member: GuildMember, amount: number, type: string) {
try {
const counter = await getCounterData(type);
const newCount = await changeCounter(amount, type);
await updateCounter(interaction.client, counter, newCount);
await announceCounterUpdate(interaction.client, member, amount, counter, newCount);
interaction.followUp({
content: `${counter.emoji} **You have ${amount > 0 ? 'increased' : 'decreased'} the counter.**\n\`\`\`diff\n ${newCount - amount}\n${getSign(amount)}${Math.abs(amount)}\n ${newCount}\`\`\``
});
} catch(err) {
interaction.followUp({
content: (err as Error).toString()
});
}
}
export async function counterAutocomplete(interaction: AutocompleteInteraction) {
const focusedValue = interaction.options.getFocused();
const guild = interaction.guildId;
const query = db<Counter>('counters')
.select('name', 'key')
.whereLike('name', `%${focusedValue.toLowerCase()}%`)
.limit(25);
if (guild) {
query.where('guild', guild);
}
const foundCounters = await query;
await interaction.respond(
foundCounters.map(choice => ({ name: choice.name, value: choice.key }))
);
}