149 lines
4.2 KiB
TypeScript
149 lines
4.2 KiB
TypeScript
import { Client, CommandInteraction, GuildMember, EmbedBuilder, TextChannel, AutocompleteInteraction } from 'discord.js';
|
|
import { getSign } from './util';
|
|
import { Counter, CounterUserLink, 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);
|
|
|
|
let canUse = true;
|
|
if (amount > 0 && counter.allowlistProducer) {
|
|
const userLink = await db<CounterUserLink>('counterUserLink')
|
|
.where('key', type)
|
|
.where('user', member.id)
|
|
.where('producer', true)
|
|
.first();
|
|
|
|
if (!userLink) canUse = false;
|
|
}
|
|
if (amount < 0 && counter.allowlistConsumer) {
|
|
const userLink = await db<CounterUserLink>('counterUserLink')
|
|
.where('key', type)
|
|
.where('user', member.id)
|
|
.where('producer', false)
|
|
.first();
|
|
|
|
if (!userLink) canUse = false;
|
|
}
|
|
|
|
if (!canUse) {
|
|
await interaction.followUp({
|
|
content: `You cannot **${amount > 0 ? 'produce' : 'consume'}** ${counter.emoji}.`
|
|
});
|
|
return;
|
|
}
|
|
|
|
const newCount = await changeCounter(amount, type);
|
|
await updateCounter(interaction.client, counter, newCount);
|
|
await announceCounterUpdate(interaction.client, member, amount, counter, newCount);
|
|
await 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) {
|
|
await 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('emoji', 'key')
|
|
.whereLike('key', `%${focusedValue.toLowerCase()}%`)
|
|
.limit(25);
|
|
|
|
if (guild) {
|
|
query.where('guild', guild);
|
|
}
|
|
|
|
const foundCounters = await query;
|
|
|
|
await interaction.respond(
|
|
foundCounters.map(choice => ({ name: choice.emoji, value: choice.key }))
|
|
);
|
|
} |