diff --git a/migrations/20231113151937_giveCountersIds.js b/migrations/20231113151937_giveCountersIds.js new file mode 100644 index 0000000..a1424e2 --- /dev/null +++ b/migrations/20231113151937_giveCountersIds.js @@ -0,0 +1,71 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = async function(knex) { + await knex.schema + .createTable('counters_', table => { + table.increments('id').primary().notNullable(); + table.string('key').notNullable(); + table.string('emoji').notNullable(); + table.integer('value').defaultTo(0); + table.string('channel').notNullable(); + table.string('guild').notNullable(); + table.string('message'); + table.string('messageTemplate'); + table.boolean('allowlistConsumer'); + table.boolean('allowlistProducer'); + }); + + // awfulllllllllllllll + const rows = await knex('counters').select('*'); + await knex('counters_').insert(rows); + + await knex.schema + .dropTable('counters') + .renameTable('counters_', 'counters'); + + await knex.schema + .alterTable('counterUserLink', table => { + table.integer('id').references('id').inTable('counters'); + }); + + //await knex('counterUserLink') + // .update({id: true}) + // .whereIn('id', function () { this.select('id').from('counters'); }); + + // uneteknykheyonshtevysfyncenadmyonayakdrmkade + await knex.raw('update counterUserLink set id = (select counters.id from counters where counters.key = counterUserLink.key)'); + + await knex.schema + .alterTable('counterUserLink', table => { + table.dropColumn('key'); + }); + + await knex.schema + .alterTable('counterConfigurations', table => { + table.integer('id').references('id').inTable('counters'); + }); + + //await knex('counterConfigurations') + // .update({id: true}) + // .whereIn('id', function () { this.select('id').from('counters'); }); + + // VEYNEYENSHYCSHJEYNVSYONEHONFEsFOVTKOSHGJEFKOhGKJJDPFURCP&*V(P&*(VC^@ P&*^vC PJFUV@P&*UVP&*(P P@ PF@# P*P&*@# ))) + await knex.raw('update counterConfigurations set id = (select counters.id from counters where counters.key = counterConfigurations.counter)'); + + await knex.schema + .alterTable('counterConfigurations', table => { + table.dropColumn('counter'); + table.dropColumn('guild'); + }); +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +// eslint-disable-next-line @typescript-eslint/no-unused-vars +exports.down = function(knex) { + throw 'Not implemented'; // literally fuck off +}; diff --git a/src/commands/counter.ts b/src/commands/counter.ts index 2033136..d4d2f9f 100644 --- a/src/commands/counter.ts +++ b/src/commands/counter.ts @@ -1,6 +1,6 @@ import { AutocompleteInteraction, Interaction, SlashCommandBuilder } from 'discord.js'; import { Counter, CounterUserLink, db } from '../lib/db'; -import { counterAutocomplete, counterConfigs, getCounterConfigRaw, getCounterData, getOptions, parseConfig, setCounterConfig, toStringConfig, updateCounter } from '../lib/counter'; +import { counterAutocomplete, counterConfigs, findCounter, getCounterConfigRaw, getOptions, parseConfig, setCounterConfig, toStringConfig, updateCounter } from '../lib/counter'; function extendOption(t: string) { return {name: t, value: t}; @@ -193,7 +193,7 @@ module.exports = { let counter; try { - counter = await getCounterData(type); + counter = await findCounter(type, interaction.guildId!); } catch(err) { await interaction.followUp({ content: 'No such counter!' @@ -206,7 +206,7 @@ module.exports = { const userType = interaction.options.getString('usertype', true); const link = await db('counterUserLink') - .where('key', type) + .where('id', counter.id) .where('user', user.id) .where('producer', userType === 'producer') .first(); @@ -220,7 +220,7 @@ module.exports = { await db('counterUserLink') .insert({ - 'key': type, + 'id': counter.id, 'user': user.id, 'producer': userType === 'producer' }); @@ -233,7 +233,7 @@ module.exports = { const userType = interaction.options.getString('usertype', true); const link = await db('counterUserLink') - .where('key', type) + .where('id', counter.id) .where('user', user.id) .where('producer', userType === 'producer') .first(); @@ -254,13 +254,13 @@ module.exports = { if (userType === 'producer') { await db('counters') - .where('key', type) + .where('id', counter.id) .update({ 'allowlistProducer': enabled }); } else { await db('counters') - .where('key', type) + .where('id', counter.id) .update({ 'allowlistConsumer': enabled }); @@ -273,7 +273,7 @@ module.exports = { const userType = interaction.options.getString('usertype', true); const users = await db('counterUserLink') - .where('key', type) + .where('id', counter.id) .where('producer', userType === 'producer'); const enabled = (userType === 'producer') ? counter.allowlistProducer : counter.allowlistConsumer; @@ -290,20 +290,17 @@ module.exports = { const value = interaction.options.getNumber('value') || 0; const guild = interaction.guildId!; - await db('counters') + const [counter] = await db('counters') .insert({ 'key': key, 'emoji': emoji, 'value': value, 'channel': channel.id, 'guild': guild - }); + }) + .returning('*'); - const counter = await db('counters') - .where('key', key) - .first(); - - await updateCounter(interaction.client, counter!, value); + await updateCounter(interaction.client, counter, value); await interaction.followUp({ content: `<#${channel.id}> has been **enriched** with your new counter. Congratulations!` @@ -313,7 +310,7 @@ module.exports = { let counter; try { - counter = await getCounterData(type); + counter = await findCounter(type, interaction.guildId!); } catch(err) { await interaction.followUp({ content: 'No such counter!' @@ -321,7 +318,7 @@ module.exports = { return; } - const config = await getCounterConfigRaw(interaction.options.getString('type') || '', counter); + const config = await getCounterConfigRaw(counter); const key = interaction.options.getString('key', true); const value = interaction.options.getString('value', true); @@ -331,7 +328,7 @@ module.exports = { const parsedValue = parseConfig(value, defaultConfig.type); const restringedValue = toStringConfig(parsedValue, defaultConfig.type); - await setCounterConfig(type, key, restringedValue); + await setCounterConfig(counter.id, key, restringedValue); await interaction.followUp(`${counter.emoji} \`${key}\` is now \`${restringedValue}\`. (was \`${config.get(key) || toStringConfig(defaultConfig.default, defaultConfig.type)}\`)`); } else if (subcommand === 'delete') { @@ -339,7 +336,7 @@ module.exports = { let counter; try { - counter = await getCounterData(type); + counter = await findCounter(type, interaction.guildId!); } catch(err) { await interaction.followUp({ content: 'No such counter!' @@ -348,11 +345,11 @@ module.exports = { } await db('counters') - .where('key', type) + .where('id', counter.id) .delete(); await db('counterUserLink') - .where('key', type) + .where('id', counter.id) .delete(); await interaction.followUp({ @@ -369,9 +366,9 @@ module.exports = { return counterAutocomplete(interaction); } else if (focused.name === 'value') { const type = interaction.options.getString('type', true); - const counter = await getCounterData(type); + const counter = await findCounter(type, interaction.guildId!); - const config = await getCounterConfigRaw(type, counter); + const config = await getCounterConfigRaw(counter); const key = interaction.options.getString('key'); if (!key) return interaction.respond([]); diff --git a/src/lib/counter.ts b/src/lib/counter.ts index 43bbfaa..8da27fb 100644 --- a/src/lib/counter.ts +++ b/src/lib/counter.ts @@ -2,9 +2,10 @@ import { Client, CommandInteraction, GuildMember, EmbedBuilder, TextChannel, Aut import { getSign } from './util'; import { Counter, CounterConfiguration, CounterUserLink, db } from './db'; -export async function getCounter(type: string) { +export async function getCounter(id: number) { const counter = await db('counters') - .where('key', type) + .select('value') + .where('id', id) .first(); if (!counter) throw 'No such counter'; @@ -12,12 +13,12 @@ export async function getCounter(type: string) { return counter.value; } -export async function changeCounter(delta: number, type: string) { - const value = await getCounter(type); +export async function changeCounter(id: number, delta: number) { + const value = await getCounter(id); const newValue = value + delta; await db('counters') - .where('key', type) + .where('id', id) .update({ 'value': newValue }); @@ -25,10 +26,10 @@ export async function changeCounter(delta: number, type: string) { return newValue; } -export async function getCounterData(type: string) { +export async function getCounterData(id: number) { const counter = await db('counters') .select('*') - .where('key', type) + .where('id', id) .first(); if (!counter) throw 'No such counter'; @@ -36,10 +37,22 @@ export async function getCounterData(type: string) { return counter; } -export async function getCounterConfigRaw(type: string, counter: Counter) { +export async function findCounter(key: string, guild: string) { + const counter = await db('counters') + .select('*') + .where('key', key) + .where('guild', guild) + .first(); + + if (!counter) throw 'No such counter'; + + return counter; +} + +export async function getCounterConfigRaw(counter: Counter) { const configs = await db('counterConfigurations') .select('configName', 'value') - .where('counter', type); + .where('id', counter.id); const config = new Map(); configs.forEach(({ configName, value }) => { @@ -53,10 +66,10 @@ export async function getCounterConfigRaw(type: string, counter: Counter) { return config; } -export async function getCounterConfig(type: string, key: string) { +export async function getCounterConfig(id: number, key: string) { const config = await db('counterConfigurations') .select('value') - .where('counter', type) + .where('id', id) .first(); const valueStr = config?.value; @@ -70,10 +83,11 @@ export async function getCounterConfig(type: string, key: string) { return value; } -export async function setCounterConfig(type: string, option: string, value: string) { +export async function setCounterConfig(id: number, option: string, value: string) { // just the ugly way of life if (option === 'emoji') { await db('counters') + .where('id', id) .update({ 'emoji': value }); @@ -81,6 +95,7 @@ export async function setCounterConfig(type: string, option: string, value: stri } if (option === 'messageTemplate') { await db('counters') + .where('id', id) .update({ 'messageTemplate': value }); @@ -91,14 +106,13 @@ export async function setCounterConfig(type: string, option: string, value: stri .update({ value: value }) - .where('counter', type) + .where('id', id) .where('configName', option); if (updated === 0) { await db('counterConfigurations') .insert({ - 'counter': type, - 'guild': '0', //TODO + 'id': id, 'configName': option, 'value': value }); @@ -189,7 +203,7 @@ export async function updateCounter(bot: Client, counter: Counter, value: number message.pin(); await db('counters') - .where('key', counter.key) + .where('id', counter.id) .update({ 'message': message.id }); @@ -200,7 +214,7 @@ export async function announceCounterUpdate(bot: Client, member: GuildMember, de const channel = await bot.channels.fetch(counter.channel) as TextChannel; const template = counter.messageTemplate || counterConfigs.get('messageTemplate')!.default as string; - const anonymous = await getCounterConfig(counter.key, 'anonymous'); + const anonymous = await getCounterConfig(counter.id, 'anonymous'); const embed = new EmbedBuilder() //.setDescription(`**${member.toString()}** has ${delta > 0 ? 'increased' : 'decreased'} the counter by **${Math.abs(delta)}**.`) @@ -231,12 +245,12 @@ export async function announceCounterUpdate(bot: Client, member: GuildMember, de export async function changeCounterInteraction(interaction: CommandInteraction, member: GuildMember, amount: number, type: string) { try { - const counter = await getCounterData(type); + const counter = await findCounter(type, member.guild.id); let canUse = true; if (amount > 0 && counter.allowlistProducer) { const userLink = await db('counterUserLink') - .where('key', type) + .where('id', counter.id) .where('user', member.id) .where('producer', true) .first(); @@ -245,7 +259,7 @@ export async function changeCounterInteraction(interaction: CommandInteraction, } if (amount < 0 && counter.allowlistConsumer) { const userLink = await db('counterUserLink') - .where('key', type) + .where('id', counter.id) .where('user', member.id) .where('producer', false) .first(); @@ -260,7 +274,7 @@ export async function changeCounterInteraction(interaction: CommandInteraction, return; } - const newCount = await changeCounter(amount, type); + const newCount = await changeCounter(counter.id, amount); await updateCounter(interaction.client, counter, newCount); await announceCounterUpdate(interaction.client, member, amount, counter, newCount); await interaction.followUp({ diff --git a/src/lib/db.ts b/src/lib/db.ts index a3f0311..ead541d 100644 --- a/src/lib/db.ts +++ b/src/lib/db.ts @@ -25,6 +25,7 @@ export interface Subscription { guild?: string } export interface Counter { + id: number, key: string, emoji: string, value: number, @@ -36,13 +37,12 @@ export interface Counter { allowlistProducer: boolean } export interface CounterUserLink { - key: string, + id: number, user: string, producer: boolean } export interface CounterConfiguration { - counter: string, - guild: string, + id: number, configName: string, value: string } \ No newline at end of file