forked from syntaxbullet/AuroraBot-discord
feat: Refactor terminal message to use new Discord.js UI builders for structured output.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { TextChannel, Message } from "discord.js";
|
import { TextChannel, Message, ContainerBuilder, TextDisplayBuilder, SectionBuilder } from "discord.js";
|
||||||
import { AuroraClient } from "@/lib/BotClient";
|
import { AuroraClient } from "@/lib/BotClient";
|
||||||
import { DrizzleClient } from "@/lib/DrizzleClient";
|
import { DrizzleClient } from "@/lib/DrizzleClient";
|
||||||
import { users, transactions, lootdrops } from "@/db/schema";
|
import { users, transactions, lootdrops } from "@/db/schema";
|
||||||
@@ -67,8 +67,10 @@ export const terminalService = {
|
|||||||
const message = await channel.messages.fetch(terminalService.data.messageId);
|
const message = await channel.messages.fetch(terminalService.data.messageId);
|
||||||
if (!message) return;
|
if (!message) return;
|
||||||
|
|
||||||
const content = await terminalService.buildMessage();
|
const containers = await terminalService.buildMessage();
|
||||||
await message.edit({ content: content, embeds: [] });
|
// Using 'containers' property as per hypothetical new Discord.js API feature
|
||||||
|
// CASTING to any because TS might not know about 'containers' in MessageEditOptions yet if types aren't perfect
|
||||||
|
await message.edit({ content: "", containers: containers, embeds: [] } as any);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to update terminal:", error);
|
console.error("Failed to update terminal:", error);
|
||||||
@@ -76,12 +78,12 @@ export const terminalService = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
buildMessage: async () => {
|
buildMessage: async () => {
|
||||||
// 1. Global Stats
|
// 1. Data Fetching
|
||||||
const allUsers = await DrizzleClient.select().from(users);
|
const allUsers = await DrizzleClient.select().from(users);
|
||||||
const totalUsers = allUsers.length;
|
const totalUsers = allUsers.length;
|
||||||
const totalWealth = allUsers.reduce((acc, u) => acc + (u.balance || 0n), 0n);
|
const totalWealth = allUsers.reduce((acc, u) => acc + (u.balance || 0n), 0n);
|
||||||
|
|
||||||
// 2. Leaderboards
|
// 2. Leaderboards Calculation
|
||||||
const topLevels = [...allUsers].sort((a, b) => (b.level || 0) - (a.level || 0)).slice(0, 3);
|
const topLevels = [...allUsers].sort((a, b) => (b.level || 0) - (a.level || 0)).slice(0, 3);
|
||||||
const topWealth = [...allUsers].sort((a, b) => Number(b.balance || 0n) - Number(a.balance || 0n)).slice(0, 3);
|
const topWealth = [...allUsers].sort((a, b) => Number(b.balance || 0n) - Number(a.balance || 0n)).slice(0, 3);
|
||||||
|
|
||||||
@@ -93,7 +95,7 @@ export const terminalService = {
|
|||||||
const levelText = topLevels.map((u, i) => `> ${formatUser(u, i)} • Lvl ${u.level}`).join("\n") || "> *The sky is empty...*";
|
const levelText = topLevels.map((u, i) => `> ${formatUser(u, i)} • Lvl ${u.level}`).join("\n") || "> *The sky is empty...*";
|
||||||
const wealthText = topWealth.map((u, i) => `> ${formatUser(u, i)} • ${u.balance} AU`).join("\n") || "> *The sky is empty...*";
|
const wealthText = topWealth.map((u, i) => `> ${formatUser(u, i)} • ${u.balance} AU`).join("\n") || "> *The sky is empty...*";
|
||||||
|
|
||||||
// 3. Lootdrops (Active/Recent)
|
// 3. Lootdrops Data
|
||||||
const activeDrops = await DrizzleClient.query.lootdrops.findMany({
|
const activeDrops = await DrizzleClient.query.lootdrops.findMany({
|
||||||
where: (lootdrops, { isNull }) => isNull(lootdrops.claimedBy),
|
where: (lootdrops, { isNull }) => isNull(lootdrops.claimedBy),
|
||||||
limit: 1,
|
limit: 1,
|
||||||
@@ -106,28 +108,47 @@ export const terminalService = {
|
|||||||
orderBy: desc(lootdrops.createdAt)
|
orderBy: desc(lootdrops.createdAt)
|
||||||
});
|
});
|
||||||
|
|
||||||
let phenomenaSection = "";
|
// --- CONTAINER 1: Header ---
|
||||||
|
const headerContainer = new ContainerBuilder()
|
||||||
|
.setAccentColor(0x00ff99)
|
||||||
|
.addSectionComponents(
|
||||||
|
new SectionBuilder().addTextDisplayComponents(
|
||||||
|
new TextDisplayBuilder().setContent("# 🌌 AURORA OBSERVATORY"),
|
||||||
|
new TextDisplayBuilder().setContent("*Current Moon Phase: Waxing Crescent 🌒*")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// --- CONTAINER 2: Observation Log ---
|
||||||
|
let phenomenaContent = "";
|
||||||
|
|
||||||
if (activeDrops.length > 0 && activeDrops[0]) {
|
if (activeDrops.length > 0 && activeDrops[0]) {
|
||||||
const drop = activeDrops[0];
|
const drop = activeDrops[0];
|
||||||
phenomenaSection = `
|
phenomenaContent = `\n**SHOOTING STAR DETECTED**\nRadiance: \`${drop.rewardAmount} ${drop.currency}\`\nCoordinates: <#${drop.channelId}>\nImpact: <t:${Math.floor(drop.expiresAt!.getTime() / 1000)}:R>`;
|
||||||
## 🌠 **SHOOTING STAR DETECTED**
|
|
||||||
> **Radiance**: \`${drop.rewardAmount} ${drop.currency}\`
|
|
||||||
> **Coordinates**: <#${drop.channelId}>
|
|
||||||
> **Impact**: <t:${Math.floor(drop.expiresAt!.getTime() / 1000)}:R>`;
|
|
||||||
} else if (recentDrops.length > 0 && recentDrops[0]) {
|
} else if (recentDrops.length > 0 && recentDrops[0]) {
|
||||||
const drop = recentDrops[0];
|
const drop = recentDrops[0];
|
||||||
const claimer = allUsers.find(u => u.id === drop.claimedBy);
|
const claimer = allUsers.find(u => u.id === drop.claimedBy);
|
||||||
phenomenaSection = `
|
phenomenaContent = `\n**RECENT EVENT**\nStar yielded \`${drop.rewardAmount} ${drop.currency}\` to **${claimer?.username || 'Unknown'}**`;
|
||||||
## 🌑 **RECENT CELESTIAL EVENTS**
|
|
||||||
> A star fell in <#${drop.channelId}> and was caught by **${claimer?.username || 'Unknown'}**
|
|
||||||
> **Yield**: \`${drop.rewardAmount} ${drop.currency}\``;
|
|
||||||
} else {
|
|
||||||
phenomenaSection = `
|
|
||||||
## 🌑 **THE NIGHT IS QUIET**
|
|
||||||
> *Scanning the horizon for falling stars...*`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Recent Activity
|
const logContainer = new ContainerBuilder()
|
||||||
|
.addSectionComponents(
|
||||||
|
new SectionBuilder().addTextDisplayComponents(
|
||||||
|
new TextDisplayBuilder().setContent("## 🔭 OBSERVATION LOG"),
|
||||||
|
new TextDisplayBuilder().setContent(`> **Stargazers**: \`${totalUsers}\`\n> **Astral Wealth**: \`${totalWealth.toLocaleString()} AU\`${phenomenaContent}`)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// --- CONTAINER 3: Leaders ---
|
||||||
|
const leaderContainer = new ContainerBuilder()
|
||||||
|
.addSectionComponents(
|
||||||
|
new SectionBuilder().addTextDisplayComponents(
|
||||||
|
new TextDisplayBuilder().setContent("## ✨ CONSTELLATION LEADERS"),
|
||||||
|
new TextDisplayBuilder().setContent(`**Brightest Stars**\n${levelText}`),
|
||||||
|
new TextDisplayBuilder().setContent(`**Gilded Nebulas**\n${wealthText}`)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// --- CONTAINER 4: Echoes ---
|
||||||
const recentTx = await DrizzleClient.query.transactions.findMany({
|
const recentTx = await DrizzleClient.query.transactions.findMany({
|
||||||
limit: 5,
|
limit: 5,
|
||||||
orderBy: [desc(transactions.createdAt)]
|
orderBy: [desc(transactions.createdAt)]
|
||||||
@@ -135,35 +156,22 @@ export const terminalService = {
|
|||||||
|
|
||||||
const activityLines = recentTx.map(tx => {
|
const activityLines = recentTx.map(tx => {
|
||||||
const time = Math.floor(tx.createdAt!.getTime() / 1000);
|
const time = Math.floor(tx.createdAt!.getTime() / 1000);
|
||||||
let icon = "<EFBFBD>";
|
let icon = "💫";
|
||||||
if (tx.type.includes("LOOT")) icon = "<EFBFBD>";
|
if (tx.type.includes("LOOT")) icon = "🌠";
|
||||||
if (tx.type.includes("GIFT")) icon = "🌕";
|
if (tx.type.includes("GIFT")) icon = "🌕";
|
||||||
|
|
||||||
const user = allUsers.find(u => u.id === tx.userId);
|
const user = allUsers.find(u => u.id === tx.userId);
|
||||||
return `<t:${time}:T> ${icon} **${user?.username || 'Unknown'}**: ${tx.description}`;
|
return `\`[<t:${time}:T>]\` ${icon} **${user?.username || 'Unknown'}**: ${tx.description}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const activityText = activityLines.join("\n") || "*Silence in the cosmos...*";
|
const echoesContainer = new ContainerBuilder()
|
||||||
|
.addSectionComponents(
|
||||||
|
new SectionBuilder().addTextDisplayComponents(
|
||||||
|
new TextDisplayBuilder().setContent("## 📡 COSMIC ECHOES"),
|
||||||
|
new TextDisplayBuilder().setContent(activityLines.join("\n") || "Silence...")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// Construct the "Container" style message
|
|
||||||
return `
|
|
||||||
# 🌌 **AURORA OBSERVATORY**
|
|
||||||
*Current Moon Phase: Waxing Crescent 🌒*
|
|
||||||
|
|
||||||
## 🔭 **OBSERVATION LOG**
|
return [headerContainer, logContainer, leaderContainer, echoesContainer];
|
||||||
> **Enrolled Stargazers**: \`${totalUsers}\`
|
|
||||||
> **Total Astral Wealth**: \`${totalWealth.toLocaleString()} AU\`
|
|
||||||
${phenomenaSection}
|
|
||||||
|
|
||||||
## ✨ **CONSTELLATION LEADERS**
|
|
||||||
**Brightest Stars (Level)**
|
|
||||||
${levelText}
|
|
||||||
|
|
||||||
**Gilded Nebulas (Wealth)**
|
|
||||||
${wealthText}
|
|
||||||
|
|
||||||
## 📡 **COSMIC ECHOES**
|
|
||||||
${activityText}
|
|
||||||
`;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user