From d81ddb021d34dad0cb36f0b5d4c44455aa242757 Mon Sep 17 00:00:00 2001 From: Nix Krystik Date: Mon, 31 Aug 2026 10:23:12 +0000 Subject: [PATCH] code :+1: --- docker-compose.yml | 15 +++++++++++++++ src/commands/leaderboard.ts | 4 ++-- src/commands/privacy/optin.ts | 4 ++-- src/commands/privacy/optout.ts | 4 ++-- src/commands/profile.ts | 6 +++--- src/events/message/messageReactionAdd.ts | 6 +++--- src/events/message/messageReactionRemove.ts | 6 +++--- src/utils/database.ts | 15 +++++++++++++-- src/utils/index.ts | 2 +- 9 files changed, 44 insertions(+), 18 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 6907a93..710bb99 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,3 +3,18 @@ services: restart: unless-stopped build: . env_file: .env + depends_on: + - postgres + + postgres: + image: postgres:17 + restart: unless-stopped + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + volumes: + - postgres_data:/var/lib/postgresql/data + +volumes: + postgres_data: diff --git a/src/commands/leaderboard.ts b/src/commands/leaderboard.ts index bd74876..471b55f 100644 --- a/src/commands/leaderboard.ts +++ b/src/commands/leaderboard.ts @@ -1,5 +1,5 @@ import { Command, CommandBuilder, CommandClient, CommandInteraction, Constants, SlashCommand } from 'athena-prime'; -import { getHighestPets } from '../utils'; +import { database } from '../utils'; // ---------- @@ -15,7 +15,7 @@ class LeaderboardCommand extends Command { async handleCommand(context: CommandClient, interaction: CommandInteraction) { await interaction.defer(); - const _data = await getHighestPets(); + const _data = await database.getHighestPets(); const description = _data.length ? _data .map((entry, index) => `**${index + 1}.** <@${entry.userId}> — **${entry.pets.toLocaleString()}** pets!`) diff --git a/src/commands/privacy/optin.ts b/src/commands/privacy/optin.ts index 1b21161..13c0e03 100644 --- a/src/commands/privacy/optin.ts +++ b/src/commands/privacy/optin.ts @@ -1,5 +1,5 @@ import { Command, CommandBuilder, CommandClient, CommandInteraction, Constants, SlashCommand } from 'athena-prime'; -import { updateUserSettings } from '../../utils'; +import { database } from '../../utils'; // ---------- @@ -15,7 +15,7 @@ class OptInCommand extends Command { async handleCommand(context: CommandClient, interaction: CommandInteraction) { await interaction.defer(true); - await updateUserSettings(interaction.user.id, { participating: true }); + await database.updateUserSettings(interaction.user.id, { participating: true }); await interaction.createMessage({ content: "Successfully opted in. You'll receive points for your pets!", diff --git a/src/commands/privacy/optout.ts b/src/commands/privacy/optout.ts index c242a94..bceb2cf 100644 --- a/src/commands/privacy/optout.ts +++ b/src/commands/privacy/optout.ts @@ -1,5 +1,5 @@ import { Command, CommandBuilder, CommandClient, CommandInteraction, Constants, SlashCommand } from 'athena-prime'; -import { updateUserSettings } from '../../utils'; +import { database } from '../../utils'; // ---------- @@ -15,7 +15,7 @@ class OptOutCommand extends Command { async handleCommand(context: CommandClient, interaction: CommandInteraction) { await interaction.defer(true); - await updateUserSettings(interaction.user.id, { participating: false }); + await database.updateUserSettings(interaction.user.id, { participating: false }); await interaction.createMessage({ content: "Successfully opted out. You won't receive any points for petting :<", diff --git a/src/commands/profile.ts b/src/commands/profile.ts index 1cb8dc1..97e5f5a 100644 --- a/src/commands/profile.ts +++ b/src/commands/profile.ts @@ -1,5 +1,5 @@ import { Command, CommandBuilder, CommandClient, CommandInteraction, Constants, SlashCommand } from 'athena-prime'; -import { getPetPosition, getUser } from '../utils'; +import { database } from '../utils'; // ---------- @@ -15,8 +15,8 @@ class ProfileCommand extends Command { async handleCommand(context: CommandClient, interaction: CommandInteraction) { await interaction.defer(); - const _user = await getUser(interaction.user.id); - const position = await getPetPosition(interaction.user.id); + const _user = await database.getUser(interaction.user.id); + const position = await database.getPetPosition(interaction.user.id); await interaction.createMessage({ embeds: [ diff --git a/src/events/message/messageReactionAdd.ts b/src/events/message/messageReactionAdd.ts index 77deb8a..e9af7e7 100644 --- a/src/events/message/messageReactionAdd.ts +++ b/src/events/message/messageReactionAdd.ts @@ -1,6 +1,6 @@ import { CommandClient, Constants, Event, Member, Message } from 'athena-prime'; import config from '../../config'; -import { getUser, updateUserStatistics } from '../../utils'; +import { database } from '../../utils'; // ---------- @@ -11,10 +11,10 @@ class MessageReactionAddEvent extends Event { const msg = await context.getMessage(message.channel.id, message.id); if (msg.author.id !== config.identifiers.targetId || emoji.id !== config.identifiers.emojiId) return; - const _user = await getUser(member.id); + const _user = await database.getUser(member.id); if (!_user.settings.participating) return; - await updateUserStatistics(member.id, { pets: _user.statistics.pets + 1 }); + await database.updateUserStatistics(member.id, { pets: _user.statistics.pets + 1 }); } } diff --git a/src/events/message/messageReactionRemove.ts b/src/events/message/messageReactionRemove.ts index 921e9a3..2ab6fff 100644 --- a/src/events/message/messageReactionRemove.ts +++ b/src/events/message/messageReactionRemove.ts @@ -1,6 +1,6 @@ import { CommandClient, Constants, Event } from 'athena-prime'; import config from '../../config'; -import { getUser, updateUserStatistics } from '../../utils'; +import { database } from '../../utils'; // ---------- @@ -16,11 +16,11 @@ class MessageReactionRemoveEvent extends Event { const msg = await context.getMessage(message.channel.id, message.id); if (msg.author.id !== config.identifiers.targetId || emoji.id !== config.identifiers.emojiId) return; - const _user = await getUser(userId); + const _user = await database.getUser(userId); if (!_user.settings.participating) return; if (_user.statistics.pets >= 0) return; - await updateUserStatistics(userId, { pets: _user.statistics.pets - 1 }); + await database.updateUserStatistics(userId, { pets: _user.statistics.pets - 1 }); } } diff --git a/src/utils/database.ts b/src/utils/database.ts index 86afec4..e9aea6e 100644 --- a/src/utils/database.ts +++ b/src/utils/database.ts @@ -3,7 +3,7 @@ import { User } from '../types'; const client = postgres(process.env.DATABASE_URL); -const getDefaultUser = (userId: string): User => ({ +const getDefaultUser = (): User => ({ settings: { participating: true, }, @@ -13,6 +13,15 @@ const getDefaultUser = (userId: string): User => ({ }, }); +export async function init(): Promise { + await client` + CREATE TABLE IF NOT EXISTS users ( + user_id TEXT PRIMARY KEY, + data JSONB NOT NULL + ) + `; +} + export async function getUser(userId: string): Promise { let [user] = await client<{ user_id: string; data: User }[]>` SELECT user_id, data FROM users @@ -23,11 +32,13 @@ export async function getUser(userId: string): Promise { [user] = await client<{ user_id: string; data: User }[]>` INSERT INTO users (user_id, data) - VALUES (${userId}, ${client.json(getDefaultUser(userId))}) + VALUES (${userId}, ${client.json(getDefaultUser())}) ON CONFLICT (user_id) DO NOTHING RETURNING user_id, data `; + + return user?.data ?? getDefaultUser(); } export async function setUser(userId: string, data: User): Promise { diff --git a/src/utils/index.ts b/src/utils/index.ts index 9cd8c5a..dd502a8 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1 +1 @@ -export * from './database'; +export * as database from './database';