diff --git a/.agent/work/completed/004-branded-discord-embeds.md b/.agent/work/completed/004-branded-discord-embeds.md new file mode 100644 index 0000000..951163c --- /dev/null +++ b/.agent/work/completed/004-branded-discord-embeds.md @@ -0,0 +1,28 @@ +### Context & Goal + +Enhance the user experience by standardizing the look and feel of Discord embeds. Adding consistent branding like a custom footer (with version info) and using the bot's accent color will make the bot feel more professional. + +### Dependencies + +- None + +### Affected Files + +- `bot/lib/embeds.ts`: Update standard embed creators. +- `shared/lib/constants.ts`: Add branding-related constants (colors, footer text). + +### Technical Constraints & Strategy + +- Implementation: Update `createBaseEmbed` and other helpers to automatically include footers and standard colors. +- Use info from `package.json` for versioning in the footer. +- Ensure the changes don't break existing layouts where custom colors might be needed. + +### Definition of Done (Binary) + +- [x] All standard embeds now include a consistent footer. +- [x] Embeds use a predefined brand color by default. +- [x] Version number is automatically pulled for the footer. + +### New Test Files + +- None. diff --git a/bot/commands/admin/listing.ts b/bot/commands/admin/listing.ts index a9f15b6..7468e18 100644 --- a/bot/commands/admin/listing.ts +++ b/bot/commands/admin/listing.ts @@ -10,7 +10,7 @@ import { } from "discord.js"; import { inventoryService } from "@shared/modules/inventory/inventory.service"; import { createSuccessEmbed, createErrorEmbed, createBaseEmbed } from "@lib/embeds"; -import { UserError } from "@/lib/errors"; +import { UserError } from "@shared/lib/errors"; import { items } from "@db/schema"; import { ilike, isNotNull, and } from "drizzle-orm"; import { DrizzleClient } from "@shared/db/DrizzleClient"; @@ -65,10 +65,10 @@ export const listing = createCommand({ await interaction.editReply({ content: `✅ Listing for **${item.name}** posted in ${targetChannel}.` }); } catch (error: any) { if (error instanceof UserError) { - await interaction.reply({ embeds: [createErrorEmbed(error.message)], ephemeral: true }); + await interaction.editReply({ embeds: [createErrorEmbed(error.message)] }); } else { console.error("Error creating listing:", error); - await interaction.reply({ embeds: [createErrorEmbed("An unexpected error occurred.")], ephemeral: true }); + await interaction.editReply({ embeds: [createErrorEmbed("An unexpected error occurred.")] }); } } }, diff --git a/bot/commands/economy/daily.ts b/bot/commands/economy/daily.ts index 3a6b5c4..09a6b19 100644 --- a/bot/commands/economy/daily.ts +++ b/bot/commands/economy/daily.ts @@ -3,13 +3,14 @@ import { createCommand } from "@shared/lib/utils"; import { SlashCommandBuilder } from "discord.js"; import { economyService } from "@shared/modules/economy/economy.service"; import { createErrorEmbed, createSuccessEmbed } from "@lib/embeds"; -import { UserError } from "@/lib/errors"; +import { UserError } from "@shared/lib/errors"; export const daily = createCommand({ data: new SlashCommandBuilder() .setName("daily") .setDescription("Claim your daily reward"), execute: async (interaction) => { + await interaction.deferReply(); try { const result = await economyService.claimDaily(interaction.user.id); @@ -21,14 +22,14 @@ export const daily = createCommand({ ) .setColor("Gold"); - await interaction.reply({ embeds: [embed] }); + await interaction.editReply({ embeds: [embed] }); } catch (error: any) { if (error instanceof UserError) { - await interaction.reply({ embeds: [createErrorEmbed(error.message)], ephemeral: true }); + await interaction.editReply({ embeds: [createErrorEmbed(error.message)] }); } else { console.error("Error claiming daily:", error); - await interaction.reply({ embeds: [createErrorEmbed("An unexpected error occurred.")], ephemeral: true }); + await interaction.editReply({ embeds: [createErrorEmbed("An unexpected error occurred.")] }); } } } diff --git a/bot/commands/economy/exam.ts b/bot/commands/economy/exam.ts index 890d184..926b2aa 100644 --- a/bot/commands/economy/exam.ts +++ b/bot/commands/economy/exam.ts @@ -2,7 +2,7 @@ import { createCommand } from "@shared/lib/utils"; import { SlashCommandBuilder } from "discord.js"; import { userService } from "@shared/modules/user/user.service"; import { createErrorEmbed, createSuccessEmbed } from "@lib/embeds"; -import { UserError } from "@/lib/errors"; +import { UserError } from "@shared/lib/errors"; import { userTimers, users } from "@db/schema"; import { eq, and, sql } from "drizzle-orm"; import { DrizzleClient } from "@shared/db/DrizzleClient"; @@ -195,10 +195,10 @@ export const exam = createCommand({ } catch (error: any) { if (error instanceof UserError) { - await interaction.reply({ embeds: [createErrorEmbed(error.message)], ephemeral: true }); + await interaction.editReply({ embeds: [createErrorEmbed(error.message)] }); } else { console.error("Error in exam command:", error); - await interaction.reply({ embeds: [createErrorEmbed("An unexpected error occurred.")], ephemeral: true }); + await interaction.editReply({ embeds: [createErrorEmbed("An unexpected error occurred.")] }); } } } diff --git a/bot/commands/economy/pay.ts b/bot/commands/economy/pay.ts index 2d87899..b51163d 100644 --- a/bot/commands/economy/pay.ts +++ b/bot/commands/economy/pay.ts @@ -5,7 +5,7 @@ import { economyService } from "@shared/modules/economy/economy.service"; import { userService } from "@shared/modules/user/user.service"; import { config } from "@shared/lib/config"; import { createErrorEmbed, createSuccessEmbed } from "@lib/embeds"; -import { UserError } from "@/lib/errors"; +import { UserError } from "@shared/lib/errors"; export const pay = createCommand({ data: new SlashCommandBuilder() diff --git a/bot/commands/economy/trivia.ts b/bot/commands/economy/trivia.ts index f35a567..3463bfa 100644 --- a/bot/commands/economy/trivia.ts +++ b/bot/commands/economy/trivia.ts @@ -3,7 +3,7 @@ import { SlashCommandBuilder } from "discord.js"; import { triviaService } from "@shared/modules/trivia/trivia.service"; import { getTriviaQuestionView } from "@/modules/trivia/trivia.view"; import { createErrorEmbed } from "@lib/embeds"; -import { UserError } from "@/lib/errors"; +import { UserError } from "@shared/lib/errors"; import { config } from "@shared/lib/config"; import { TriviaCategory } from "@shared/lib/constants"; diff --git a/bot/commands/inventory/use.ts b/bot/commands/inventory/use.ts index 448a346..d425395 100644 --- a/bot/commands/inventory/use.ts +++ b/bot/commands/inventory/use.ts @@ -5,7 +5,7 @@ import { userService } from "@shared/modules/user/user.service"; import { createErrorEmbed } from "@lib/embeds"; import { getItemUseResultEmbed } from "@/modules/inventory/inventory.view"; import type { ItemUsageData } from "@shared/lib/types"; -import { UserError } from "@/lib/errors"; +import { UserError } from "@shared/lib/errors"; import { config } from "@shared/lib/config"; export const use = createCommand({ diff --git a/bot/lib/errors.ts b/bot/lib/errors.ts deleted file mode 100644 index 32bce8c..0000000 --- a/bot/lib/errors.ts +++ /dev/null @@ -1,18 +0,0 @@ -export class ApplicationError extends Error { - constructor(message: string) { - super(message); - this.name = this.constructor.name; - } -} - -export class UserError extends ApplicationError { - constructor(message: string) { - super(message); - } -} - -export class SystemError extends ApplicationError { - constructor(message: string) { - super(message); - } -} diff --git a/bot/lib/handlers/ComponentInteractionHandler.ts b/bot/lib/handlers/ComponentInteractionHandler.ts index 4773bee..ac4a7eb 100644 --- a/bot/lib/handlers/ComponentInteractionHandler.ts +++ b/bot/lib/handlers/ComponentInteractionHandler.ts @@ -1,6 +1,6 @@ import { ButtonInteraction, StringSelectMenuInteraction, ModalSubmitInteraction, MessageFlags } from "discord.js"; -import { UserError } from "@lib/errors"; +import { UserError } from "@shared/lib/errors"; import { createErrorEmbed } from "@lib/embeds"; type ComponentInteraction = ButtonInteraction | StringSelectMenuInteraction | ModalSubmitInteraction; diff --git a/bot/modules/economy/lootdrop.interaction.ts b/bot/modules/economy/lootdrop.interaction.ts index 72f1893..fae70c3 100644 --- a/bot/modules/economy/lootdrop.interaction.ts +++ b/bot/modules/economy/lootdrop.interaction.ts @@ -1,6 +1,6 @@ import { ButtonInteraction } from "discord.js"; import { lootdropService } from "@shared/modules/economy/lootdrop.service"; -import { UserError } from "@/lib/errors"; +import { UserError } from "@shared/lib/errors"; import { getLootdropClaimedMessage } from "./lootdrop.view"; export async function handleLootdropInteraction(interaction: ButtonInteraction) { diff --git a/bot/modules/economy/shop.interaction.ts b/bot/modules/economy/shop.interaction.ts index 30b470e..0b397ae 100644 --- a/bot/modules/economy/shop.interaction.ts +++ b/bot/modules/economy/shop.interaction.ts @@ -1,7 +1,7 @@ import { ButtonInteraction, MessageFlags } from "discord.js"; import { inventoryService } from "@shared/modules/inventory/inventory.service"; import { userService } from "@shared/modules/user/user.service"; -import { UserError } from "@/lib/errors"; +import { UserError } from "@shared/lib/errors"; export async function handleShopInteraction(interaction: ButtonInteraction) { if (!interaction.customId.startsWith("shop_buy_")) return; diff --git a/bot/modules/feedback/feedback.interaction.ts b/bot/modules/feedback/feedback.interaction.ts index 4ccfc7e..4c67d6d 100644 --- a/bot/modules/feedback/feedback.interaction.ts +++ b/bot/modules/feedback/feedback.interaction.ts @@ -4,7 +4,7 @@ import { config } from "@shared/lib/config"; import { AuroraClient } from "@/lib/BotClient"; import { buildFeedbackMessage, getFeedbackModal } from "./feedback.view"; import { FEEDBACK_CUSTOM_IDS, type FeedbackType, type FeedbackData } from "./feedback.types"; -import { UserError } from "@/lib/errors"; +import { UserError } from "@shared/lib/errors"; export const handleFeedbackInteraction = async (interaction: Interaction) => { // Handle select menu for choosing feedback type diff --git a/bot/modules/trade/trade.interaction.ts b/bot/modules/trade/trade.interaction.ts index ea4a45b..acdc537 100644 --- a/bot/modules/trade/trade.interaction.ts +++ b/bot/modules/trade/trade.interaction.ts @@ -10,7 +10,7 @@ import { import { tradeService } from "@shared/modules/trade/trade.service"; import { inventoryService } from "@shared/modules/inventory/inventory.service"; import { createErrorEmbed, createWarningEmbed, createSuccessEmbed, createInfoEmbed } from "@lib/embeds"; -import { UserError } from "@lib/errors"; +import { UserError } from "@shared/lib/errors"; import { getTradeDashboard, getTradeMoneyModal, getItemSelectMenu, getTradeCompletedEmbed } from "./trade.view"; diff --git a/bot/modules/trivia/trivia.interaction.ts b/bot/modules/trivia/trivia.interaction.ts index 5bf5006..69de286 100644 --- a/bot/modules/trivia/trivia.interaction.ts +++ b/bot/modules/trivia/trivia.interaction.ts @@ -1,7 +1,7 @@ import { ButtonInteraction } from "discord.js"; import { triviaService } from "@shared/modules/trivia/trivia.service"; import { getTriviaResultView, getTriviaTimeoutView } from "./trivia.view"; -import { UserError } from "@/lib/errors"; +import { UserError } from "@shared/lib/errors"; export async function handleTriviaInteraction(interaction: ButtonInteraction) { const parts = interaction.customId.split('_'); diff --git a/bot/modules/user/enrollment.interaction.ts b/bot/modules/user/enrollment.interaction.ts index b15b0aa..bec444a 100644 --- a/bot/modules/user/enrollment.interaction.ts +++ b/bot/modules/user/enrollment.interaction.ts @@ -3,7 +3,7 @@ import { config } from "@shared/lib/config"; import { getEnrollmentSuccessMessage } from "./enrollment.view"; import { classService } from "@shared/modules/class/class.service"; import { userService } from "@shared/modules/user/user.service"; -import { UserError } from "@/lib/errors"; +import { UserError } from "@shared/lib/errors"; import { sendWebhookMessage } from "@/lib/webhookUtils"; export async function handleEnrollmentInteraction(interaction: ButtonInteraction) { diff --git a/package.json b/package.json index 8ac85e5..f4225b0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "app", - "version": "1.0.0", + "version": "1.1.3", "module": "bot/index.ts", "type": "module", "private": true, diff --git a/shared/lib/constants.ts b/shared/lib/constants.ts index 0df339f..653d187 100644 --- a/shared/lib/constants.ts +++ b/shared/lib/constants.ts @@ -88,6 +88,6 @@ export enum TriviaCategory { export const BRANDING = { COLOR: 0x00d4ff as const, - FOOTER_TEXT: 'AuroraBot' as const, + FOOTER_TEXT: 'Aurora' as const, }; diff --git a/shared/modules/economy/economy.service.ts b/shared/modules/economy/economy.service.ts index b093401..6d026e4 100644 --- a/shared/modules/economy/economy.service.ts +++ b/shared/modules/economy/economy.service.ts @@ -87,7 +87,7 @@ export const economyService = { }); if (cooldown && cooldown.expiresAt > now) { - throw new UserError(`Daily already claimed today. Next claim `); + throw new UserError(`You have already claimed your daily reward today.\nNext claim available: ()`); } // Get user for streak logic