mirror of
https://github.com/BrenBroZAYT/uptime-kuma-discord-bot.git
synced 2026-06-13 16:40:03 +00:00
Refactor configuration management to support multiple guilds, including migration from single-guild format. Update Discord service to handle multiple channels and improve command handling for guild-specific settings. Add reset configuration command and enhance logging for better error tracking.
if you were on the build before the multi-guild configuration existed, run /reset-config to properly continue using the bot.
This commit is contained in:
+139
-69
@@ -7,7 +7,7 @@ export interface MonitorGroup {
|
|||||||
monitorIds: number[];
|
monitorIds: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BotConfig {
|
export interface GuildConfig {
|
||||||
channelId: string | null;
|
channelId: string | null;
|
||||||
messageIds: string[];
|
messageIds: string[];
|
||||||
monitorIds: number[];
|
monitorIds: number[];
|
||||||
@@ -17,9 +17,13 @@ export interface BotConfig {
|
|||||||
statusMessage: string;
|
statusMessage: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MultiGuildConfig {
|
||||||
|
guilds: Record<string, GuildConfig>;
|
||||||
|
}
|
||||||
|
|
||||||
export class ConfigStorage {
|
export class ConfigStorage {
|
||||||
private configPath: string;
|
private configPath: string;
|
||||||
private config: BotConfig;
|
private config: MultiGuildConfig;
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -34,35 +38,38 @@ export class ConfigStorage {
|
|||||||
this.config = this.load();
|
this.config = this.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
private load(): BotConfig {
|
private load(): MultiGuildConfig {
|
||||||
if (existsSync(this.configPath)) {
|
if (existsSync(this.configPath)) {
|
||||||
try {
|
try {
|
||||||
const data = readFileSync(this.configPath, 'utf-8');
|
const data = readFileSync(this.configPath, 'utf-8');
|
||||||
const loaded = JSON.parse(data);
|
const loaded = JSON.parse(data);
|
||||||
|
|
||||||
|
// Migration: Convert old single-guild format to multi-guild
|
||||||
|
if (loaded.channelId !== undefined && !loaded.guilds) {
|
||||||
|
this.logger.info('Migrating old config format to multi-guild format');
|
||||||
|
return {
|
||||||
|
guilds: {
|
||||||
|
'legacy': {
|
||||||
|
channelId: loaded.channelId || null,
|
||||||
|
messageIds: loaded.messageIds || [],
|
||||||
|
monitorIds: loaded.monitorIds || [],
|
||||||
|
groups: loaded.groups || [],
|
||||||
|
updateInterval: loaded.updateInterval || parseInt(process.env.UPDATE_INTERVAL || '60', 10) * 1000,
|
||||||
|
embedColor: loaded.embedColor || parseInt(process.env.EMBED_COLOR || '5814783', 10),
|
||||||
|
statusMessage: loaded.statusMessage || 'Service Status',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
this.logger.info('Loaded configuration from storage');
|
this.logger.info('Loaded configuration from storage');
|
||||||
return {
|
return loaded;
|
||||||
channelId: loaded.channelId || null,
|
|
||||||
messageIds: loaded.messageIds || [],
|
|
||||||
monitorIds: loaded.monitorIds || [],
|
|
||||||
groups: loaded.groups || [],
|
|
||||||
updateInterval: loaded.updateInterval || parseInt(process.env.UPDATE_INTERVAL || '60', 10) * 1000,
|
|
||||||
embedColor: loaded.embedColor || parseInt(process.env.EMBED_COLOR || '5814783', 10),
|
|
||||||
statusMessage: loaded.statusMessage || 'Service Status',
|
|
||||||
};
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
this.logger.error(`Failed to load config: ${error.message}`);
|
this.logger.error(`Failed to load config: ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return { guilds: {} };
|
||||||
channelId: null,
|
|
||||||
messageIds: [],
|
|
||||||
monitorIds: [],
|
|
||||||
groups: [],
|
|
||||||
updateInterval: parseInt(process.env.UPDATE_INTERVAL || '60', 10) * 1000,
|
|
||||||
embedColor: parseInt(process.env.EMBED_COLOR || '5814783', 10),
|
|
||||||
statusMessage: 'Service Status',
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private save(): void {
|
private save(): void {
|
||||||
@@ -74,117 +81,179 @@ export class ConfigStorage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getMonitorIds(): number[] {
|
private getDefaultConfig(): GuildConfig {
|
||||||
return [...this.config.monitorIds];
|
return {
|
||||||
|
channelId: null,
|
||||||
|
messageIds: [],
|
||||||
|
monitorIds: [],
|
||||||
|
groups: [],
|
||||||
|
updateInterval: parseInt(process.env.UPDATE_INTERVAL || '60', 10) * 1000,
|
||||||
|
embedColor: parseInt(process.env.EMBED_COLOR || '5814783', 10),
|
||||||
|
statusMessage: 'Service Status',
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public setMonitorIds(ids: number[]): void {
|
private getGuildConfig(guildId: string, createIfMissing: boolean = true): GuildConfig {
|
||||||
this.config.monitorIds = ids;
|
if (!this.config.guilds[guildId]) {
|
||||||
this.save();
|
if (!createIfMissing) {
|
||||||
|
return this.getDefaultConfig(); // Return default without saving
|
||||||
|
}
|
||||||
|
this.config.guilds[guildId] = this.getDefaultConfig();
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
return this.config.guilds[guildId];
|
||||||
}
|
}
|
||||||
|
|
||||||
public addMonitor(id: number): boolean {
|
public guildExists(guildId: string): boolean {
|
||||||
if (!this.config.monitorIds.includes(id)) {
|
return !!this.config.guilds[guildId];
|
||||||
this.config.monitorIds.push(id);
|
}
|
||||||
|
|
||||||
|
public getAllGuildIds(): string[] {
|
||||||
|
return Object.keys(this.config.guilds);
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeGuild(guildId: string): boolean {
|
||||||
|
if (this.config.guilds[guildId]) {
|
||||||
|
delete this.config.guilds[guildId];
|
||||||
this.save();
|
this.save();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeMonitor(id: number): boolean {
|
public getMonitorIds(guildId: string): number[] {
|
||||||
const index = this.config.monitorIds.indexOf(id);
|
const config = this.getGuildConfig(guildId);
|
||||||
|
return [...config.monitorIds];
|
||||||
|
}
|
||||||
|
|
||||||
|
public setMonitorIds(guildId: string, ids: number[]): void {
|
||||||
|
const config = this.getGuildConfig(guildId);
|
||||||
|
config.monitorIds = ids;
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public addMonitor(guildId: string, id: number): boolean {
|
||||||
|
const config = this.getGuildConfig(guildId);
|
||||||
|
if (!config.monitorIds.includes(id)) {
|
||||||
|
config.monitorIds.push(id);
|
||||||
|
this.save();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeMonitor(guildId: string, id: number): boolean {
|
||||||
|
const config = this.getGuildConfig(guildId);
|
||||||
|
const index = config.monitorIds.indexOf(id);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
this.config.monitorIds.splice(index, 1);
|
config.monitorIds.splice(index, 1);
|
||||||
this.save();
|
this.save();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public clearMonitors(): void {
|
public clearMonitors(guildId: string): void {
|
||||||
this.config.monitorIds = [];
|
const config = this.getGuildConfig(guildId);
|
||||||
|
config.monitorIds = [];
|
||||||
this.save();
|
this.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getUpdateInterval(): number {
|
public getUpdateInterval(guildId: string): number {
|
||||||
return this.config.updateInterval;
|
const config = this.getGuildConfig(guildId);
|
||||||
|
return config.updateInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setUpdateInterval(interval: number): void {
|
public setUpdateInterval(guildId: string, interval: number): void {
|
||||||
if (interval >= 10000) {
|
if (interval >= 10000) {
|
||||||
this.config.updateInterval = interval;
|
const config = this.getGuildConfig(guildId);
|
||||||
|
config.updateInterval = interval;
|
||||||
this.save();
|
this.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getEmbedColor(): number {
|
public getEmbedColor(guildId: string): number {
|
||||||
return this.config.embedColor;
|
const config = this.getGuildConfig(guildId);
|
||||||
|
return config.embedColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setEmbedColor(color: number): void {
|
public setEmbedColor(guildId: string, color: number): void {
|
||||||
this.config.embedColor = color;
|
const config = this.getGuildConfig(guildId);
|
||||||
|
config.embedColor = color;
|
||||||
this.save();
|
this.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getConfig(): BotConfig {
|
public getConfig(guildId: string): GuildConfig {
|
||||||
return { ...this.config };
|
return { ...this.getGuildConfig(guildId, false) }; // Don't auto-create when just reading
|
||||||
}
|
}
|
||||||
|
|
||||||
public getChannelId(): string | null {
|
public getChannelId(guildId: string): string | null {
|
||||||
return this.config.channelId;
|
if (!this.guildExists(guildId)) {
|
||||||
|
return null; // Don't auto-create guild just to check channel
|
||||||
|
}
|
||||||
|
const config = this.getGuildConfig(guildId, false);
|
||||||
|
return config.channelId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setChannelId(channelId: string): void {
|
public setChannelId(guildId: string, channelId: string): void {
|
||||||
this.config.channelId = channelId;
|
const config = this.getGuildConfig(guildId);
|
||||||
|
config.channelId = channelId;
|
||||||
this.save();
|
this.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getStatusMessage(): string {
|
public getStatusMessage(guildId: string): string {
|
||||||
return this.config.statusMessage;
|
const config = this.getGuildConfig(guildId);
|
||||||
|
return config.statusMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setStatusMessage(message: string): void {
|
public setStatusMessage(guildId: string, message: string): void {
|
||||||
this.config.statusMessage = message;
|
const config = this.getGuildConfig(guildId);
|
||||||
|
config.statusMessage = message;
|
||||||
this.save();
|
this.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getMessageIds(): string[] {
|
public getMessageIds(guildId: string): string[] {
|
||||||
return [...this.config.messageIds];
|
const config = this.getGuildConfig(guildId);
|
||||||
|
return [...config.messageIds];
|
||||||
}
|
}
|
||||||
|
|
||||||
public setMessageIds(ids: string[]): void {
|
public setMessageIds(guildId: string, ids: string[]): void {
|
||||||
this.config.messageIds = ids;
|
const config = this.getGuildConfig(guildId);
|
||||||
|
config.messageIds = ids;
|
||||||
this.save();
|
this.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getGroups(): MonitorGroup[] {
|
public getGroups(guildId: string): MonitorGroup[] {
|
||||||
return [...this.config.groups];
|
const config = this.getGuildConfig(guildId);
|
||||||
|
return [...config.groups];
|
||||||
}
|
}
|
||||||
|
|
||||||
public addGroup(name: string): boolean {
|
public addGroup(guildId: string, name: string): boolean {
|
||||||
if (this.config.groups.some(g => g.name.toLowerCase() === name.toLowerCase())) {
|
const config = this.getGuildConfig(guildId);
|
||||||
|
if (config.groups.some(g => g.name.toLowerCase() === name.toLowerCase())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.config.groups.push({ name, monitorIds: [] });
|
config.groups.push({ name, monitorIds: [] });
|
||||||
this.save();
|
this.save();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeGroup(name: string): boolean {
|
public removeGroup(guildId: string, name: string): boolean {
|
||||||
const index = this.config.groups.findIndex(g => g.name.toLowerCase() === name.toLowerCase());
|
const config = this.getGuildConfig(guildId);
|
||||||
|
const index = config.groups.findIndex(g => g.name.toLowerCase() === name.toLowerCase());
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
this.config.groups.splice(index, 1);
|
config.groups.splice(index, 1);
|
||||||
this.save();
|
this.save();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public addMonitorToGroup(groupName: string, monitorId: number): boolean {
|
public addMonitorToGroup(guildId: string, groupName: string, monitorId: number): boolean {
|
||||||
const group = this.config.groups.find(g => g.name.toLowerCase() === groupName.toLowerCase());
|
const config = this.getGuildConfig(guildId);
|
||||||
|
const group = config.groups.find(g => g.name.toLowerCase() === groupName.toLowerCase());
|
||||||
if (group && !group.monitorIds.includes(monitorId)) {
|
if (group && !group.monitorIds.includes(monitorId)) {
|
||||||
for (const g of this.config.groups) {
|
for (const g of config.groups) {
|
||||||
const idx = g.monitorIds.indexOf(monitorId);
|
const idx = g.monitorIds.indexOf(monitorId);
|
||||||
if (idx > -1) {
|
if (idx > -1) {
|
||||||
g.monitorIds.splice(idx, 1);
|
g.monitorIds.splice(idx, 1);
|
||||||
@@ -197,9 +266,10 @@ export class ConfigStorage {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeMonitorFromGroup(monitorId: number): boolean {
|
public removeMonitorFromGroup(guildId: string, monitorId: number): boolean {
|
||||||
|
const config = this.getGuildConfig(guildId);
|
||||||
let found = false;
|
let found = false;
|
||||||
for (const group of this.config.groups) {
|
for (const group of config.groups) {
|
||||||
const index = group.monitorIds.indexOf(monitorId);
|
const index = group.monitorIds.indexOf(monitorId);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
group.monitorIds.splice(index, 1);
|
group.monitorIds.splice(index, 1);
|
||||||
|
|||||||
+9
-9
@@ -89,23 +89,23 @@ class UptimeKumaDiscordBot {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const trackedIds = configStorage.getMonitorIds();
|
const monitors = this.uptimeKuma.getMonitorStats();
|
||||||
const monitors = this.uptimeKuma.getMonitorStats(trackedIds);
|
|
||||||
this.discord.updateMonitorStatus(monitors).catch(error => {
|
this.discord.updateMonitorStatus(monitors).catch(error => {
|
||||||
this.logger.error(`Failed to update Discord status: ${error.message}`);
|
this.logger.error(`Failed to update Discord status: ${error.message}`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const interval = configStorage.getUpdateInterval();
|
// Use a default interval; guilds can have different intervals but we'll use a common update cycle
|
||||||
this.updateInterval = setInterval(updateFn, interval);
|
const defaultInterval = parseInt(process.env.UPDATE_INTERVAL || '60', 10) * 1000;
|
||||||
|
this.updateInterval = setInterval(updateFn, defaultInterval);
|
||||||
|
|
||||||
this.logger.info(`Update interval set to ${interval / 1000} seconds`);
|
this.logger.info(`Update interval set to ${defaultInterval / 1000} seconds`);
|
||||||
|
|
||||||
const trackedIds = configStorage.getMonitorIds();
|
const guildIds = configStorage.getAllGuildIds();
|
||||||
if (trackedIds.length > 0) {
|
if (guildIds.length > 0) {
|
||||||
this.logger.info(`Tracking ${trackedIds.length} specific monitor(s): ${trackedIds.join(', ')}`);
|
this.logger.info(`Configured for ${guildIds.length} guild(s)`);
|
||||||
} else {
|
} else {
|
||||||
this.logger.info('Tracking all monitors');
|
this.logger.info('No guilds configured yet. Use /set-channel in a Discord server to get started.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -157,6 +157,12 @@ export class CommandsService {
|
|||||||
.setDescription('Show current bot configuration'),
|
.setDescription('Show current bot configuration'),
|
||||||
execute: this.showConfig.bind(this),
|
execute: this.showConfig.bind(this),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
data: new SlashCommandBuilder()
|
||||||
|
.setName('reset-config')
|
||||||
|
.setDescription('⚠️ Reset this server\'s configuration to defaults'),
|
||||||
|
execute: this.resetConfig.bind(this),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const command of commands) {
|
for (const command of commands) {
|
||||||
@@ -190,11 +196,15 @@ export class CommandsService {
|
|||||||
uptimeKuma: UptimeKumaService
|
uptimeKuma: UptimeKumaService
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!await this.checkAdmin(interaction)) return;
|
if (!await this.checkAdmin(interaction)) return;
|
||||||
|
if (!interaction.guildId) {
|
||||||
|
await interaction.reply({ content: '❌ This command can only be used in a server.', flags: MessageFlags.Ephemeral });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const monitorIdStr = interaction.options.getString('monitor', true);
|
const monitorIdStr = interaction.options.getString('monitor', true);
|
||||||
const monitorId = parseInt(monitorIdStr, 10);
|
const monitorId = parseInt(monitorIdStr, 10);
|
||||||
|
|
||||||
const currentIds = configStorage.getMonitorIds();
|
const currentIds = configStorage.getMonitorIds(interaction.guildId);
|
||||||
if (currentIds.includes(monitorId)) {
|
if (currentIds.includes(monitorId)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: '⚠️ This monitor is already being tracked.',
|
content: '⚠️ This monitor is already being tracked.',
|
||||||
@@ -204,7 +214,7 @@ export class CommandsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const newIds = [...currentIds, monitorId];
|
const newIds = [...currentIds, monitorId];
|
||||||
configStorage.setMonitorIds(newIds);
|
configStorage.setMonitorIds(interaction.guildId, newIds);
|
||||||
|
|
||||||
const monitors = uptimeKuma.getAllMonitors();
|
const monitors = uptimeKuma.getAllMonitors();
|
||||||
const monitorName = monitors.get(monitorId)?.name || `ID ${monitorId}`;
|
const monitorName = monitors.get(monitorId)?.name || `ID ${monitorId}`;
|
||||||
@@ -223,11 +233,15 @@ export class CommandsService {
|
|||||||
uptimeKuma: UptimeKumaService
|
uptimeKuma: UptimeKumaService
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!await this.checkAdmin(interaction)) return;
|
if (!await this.checkAdmin(interaction)) return;
|
||||||
|
if (!interaction.guildId) {
|
||||||
|
await interaction.reply({ content: '❌ This command can only be used in a server.', flags: MessageFlags.Ephemeral });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const monitorIdStr = interaction.options.getString('monitor', true);
|
const monitorIdStr = interaction.options.getString('monitor', true);
|
||||||
const monitorId = parseInt(monitorIdStr, 10);
|
const monitorId = parseInt(monitorIdStr, 10);
|
||||||
|
|
||||||
const currentIds = configStorage.getMonitorIds();
|
const currentIds = configStorage.getMonitorIds(interaction.guildId);
|
||||||
const newIds = currentIds.filter(id => id !== monitorId);
|
const newIds = currentIds.filter(id => id !== monitorId);
|
||||||
|
|
||||||
if (currentIds.length === newIds.length) {
|
if (currentIds.length === newIds.length) {
|
||||||
@@ -238,7 +252,7 @@ export class CommandsService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
configStorage.setMonitorIds(newIds);
|
configStorage.setMonitorIds(interaction.guildId, newIds);
|
||||||
|
|
||||||
const monitors = uptimeKuma.getAllMonitors();
|
const monitors = uptimeKuma.getAllMonitors();
|
||||||
const monitorName = monitors.get(monitorId)?.name || `ID ${monitorId}`;
|
const monitorName = monitors.get(monitorId)?.name || `ID ${monitorId}`;
|
||||||
@@ -257,8 +271,12 @@ export class CommandsService {
|
|||||||
uptimeKuma: UptimeKumaService
|
uptimeKuma: UptimeKumaService
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!await this.checkAdmin(interaction)) return;
|
if (!await this.checkAdmin(interaction)) return;
|
||||||
|
if (!interaction.guildId) {
|
||||||
|
await interaction.reply({ content: '❌ This command can only be used in a server.', flags: MessageFlags.Ephemeral });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
configStorage.clearMonitors();
|
configStorage.clearMonitors(interaction.guildId);
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setColor(0x0099ff)
|
.setColor(0x0099ff)
|
||||||
@@ -276,6 +294,10 @@ export class CommandsService {
|
|||||||
uptimeKuma: UptimeKumaService
|
uptimeKuma: UptimeKumaService
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!await this.checkAdmin(interaction)) return;
|
if (!await this.checkAdmin(interaction)) return;
|
||||||
|
if (!interaction.guildId) {
|
||||||
|
await interaction.reply({ content: '❌ This command can only be used in a server.', flags: MessageFlags.Ephemeral });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||||
|
|
||||||
@@ -284,7 +306,7 @@ export class CommandsService {
|
|||||||
try {
|
try {
|
||||||
const discordService = (interaction.client as any).discordService;
|
const discordService = (interaction.client as any).discordService;
|
||||||
if (discordService) {
|
if (discordService) {
|
||||||
await discordService.setChannel(channel.id);
|
await discordService.setChannel(interaction.guildId, channel.id);
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setColor(0x00ff00)
|
.setColor(0x00ff00)
|
||||||
@@ -308,10 +330,14 @@ export class CommandsService {
|
|||||||
uptimeKuma: UptimeKumaService
|
uptimeKuma: UptimeKumaService
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!await this.checkAdmin(interaction)) return;
|
if (!await this.checkAdmin(interaction)) return;
|
||||||
|
if (!interaction.guildId) {
|
||||||
|
await interaction.reply({ content: '❌ This command can only be used in a server.', flags: MessageFlags.Ephemeral });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const message = interaction.options.getString('message', true);
|
const message = interaction.options.getString('message', true);
|
||||||
|
|
||||||
configStorage.setStatusMessage(message);
|
configStorage.setStatusMessage(interaction.guildId, message);
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setColor(0x00ff00)
|
.setColor(0x00ff00)
|
||||||
@@ -327,15 +353,19 @@ export class CommandsService {
|
|||||||
uptimeKuma: UptimeKumaService
|
uptimeKuma: UptimeKumaService
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!await this.checkAdmin(interaction)) return;
|
if (!await this.checkAdmin(interaction)) return;
|
||||||
|
if (!interaction.guildId) {
|
||||||
|
await interaction.reply({ content: '❌ This command can only be used in a server.', flags: MessageFlags.Ephemeral });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const botConfig = configStorage.getConfig();
|
const botConfig = configStorage.getConfig(interaction.guildId);
|
||||||
const trackedIds = botConfig.monitorIds;
|
const trackedIds = botConfig.monitorIds;
|
||||||
const channelId = botConfig.channelId;
|
const channelId = botConfig.channelId;
|
||||||
const groups = configStorage.getGroups();
|
const groups = configStorage.getGroups(interaction.guildId);
|
||||||
const monitors = uptimeKuma.getAllMonitors();
|
const monitors = uptimeKuma.getAllMonitors();
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setColor(configStorage.getEmbedColor())
|
.setColor(configStorage.getEmbedColor(interaction.guildId))
|
||||||
.setTitle('⚙️ Bot Configuration & Status')
|
.setTitle('⚙️ Bot Configuration & Status')
|
||||||
.addFields(
|
.addFields(
|
||||||
{
|
{
|
||||||
@@ -401,15 +431,111 @@ export class CommandsService {
|
|||||||
await interaction.reply({ embeds: [embed], flags: MessageFlags.Ephemeral });
|
await interaction.reply({ embeds: [embed], flags: MessageFlags.Ephemeral });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async resetConfig(
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
uptimeKuma: UptimeKumaService
|
||||||
|
): Promise<void> {
|
||||||
|
if (!await this.checkAdmin(interaction)) return;
|
||||||
|
if (!interaction.guildId) {
|
||||||
|
await interaction.reply({ content: '❌ This command can only be used in a server.', flags: MessageFlags.Ephemeral });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||||
|
|
||||||
|
let messagesDeleted = 0;
|
||||||
|
|
||||||
|
// Delete existing embed messages for this guild
|
||||||
|
const channelId = configStorage.getChannelId(interaction.guildId);
|
||||||
|
const messageIds = configStorage.getMessageIds(interaction.guildId);
|
||||||
|
|
||||||
|
if (channelId && messageIds.length > 0) {
|
||||||
|
try {
|
||||||
|
const channel = await interaction.client.channels.fetch(channelId);
|
||||||
|
if (channel && channel.isTextBased() && !channel.isDMBased()) {
|
||||||
|
for (const messageId of messageIds) {
|
||||||
|
try {
|
||||||
|
const message = await (channel as any).messages.fetch(messageId);
|
||||||
|
await message.delete();
|
||||||
|
messagesDeleted++;
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.warn(`Failed to delete message ${messageId}: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.warn(`Failed to fetch channel for message deletion: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also delete legacy guild messages if they exist
|
||||||
|
const allGuildIds = configStorage.getAllGuildIds();
|
||||||
|
const legacyGuilds = allGuildIds.filter(id => id === 'legacy');
|
||||||
|
let cleanedLegacy = false;
|
||||||
|
|
||||||
|
if (legacyGuilds.length > 0) {
|
||||||
|
for (const legacyId of legacyGuilds) {
|
||||||
|
const legacyChannelId = configStorage.getChannelId(legacyId);
|
||||||
|
const legacyMessageIds = configStorage.getMessageIds(legacyId);
|
||||||
|
|
||||||
|
if (legacyChannelId && legacyMessageIds.length > 0) {
|
||||||
|
try {
|
||||||
|
const channel = await interaction.client.channels.fetch(legacyChannelId);
|
||||||
|
if (channel && channel.isTextBased() && !channel.isDMBased()) {
|
||||||
|
for (const messageId of legacyMessageIds) {
|
||||||
|
try {
|
||||||
|
const message = await (channel as any).messages.fetch(messageId);
|
||||||
|
await message.delete();
|
||||||
|
messagesDeleted++;
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.warn(`Failed to delete legacy message ${messageId}: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.warn(`Failed to fetch channel for legacy message deletion: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configStorage.removeGuild(legacyId);
|
||||||
|
cleanedLegacy = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the entire guild configuration so it starts completely fresh
|
||||||
|
configStorage.removeGuild(interaction.guildId);
|
||||||
|
|
||||||
|
const embed = new EmbedBuilder()
|
||||||
|
.setColor(0xff9900)
|
||||||
|
.setTitle('⚠️ Configuration Reset')
|
||||||
|
.setDescription(
|
||||||
|
'**This server\'s configuration has been completely reset.**\n\n' +
|
||||||
|
(messagesDeleted > 0 ? `✅ Deleted ${messagesDeleted} status embed message(s)\n` : '') +
|
||||||
|
'✅ All configuration data removed\n' +
|
||||||
|
(cleanedLegacy ? '✅ Legacy migration data cleaned up\n' : '') +
|
||||||
|
'\n⚠️ You will need to reconfigure everything:\n' +
|
||||||
|
'• Use `/set-channel` to set your status channel\n' +
|
||||||
|
'• Use `/track` to add monitors\n' +
|
||||||
|
'• Use `/group-create` to create groups'
|
||||||
|
)
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
await interaction.editReply({ embeds: [embed] });
|
||||||
|
}
|
||||||
|
|
||||||
private async addGroup(
|
private async addGroup(
|
||||||
interaction: ChatInputCommandInteraction,
|
interaction: ChatInputCommandInteraction,
|
||||||
uptimeKuma: UptimeKumaService
|
uptimeKuma: UptimeKumaService
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!await this.checkAdmin(interaction)) return;
|
if (!await this.checkAdmin(interaction)) return;
|
||||||
|
if (!interaction.guildId) {
|
||||||
|
await interaction.reply({ content: '❌ This command can only be used in a server.', flags: MessageFlags.Ephemeral });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const name = interaction.options.getString('name', true);
|
const name = interaction.options.getString('name', true);
|
||||||
|
|
||||||
const success = configStorage.addGroup(name);
|
const success = configStorage.addGroup(interaction.guildId, name);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
@@ -432,10 +558,14 @@ export class CommandsService {
|
|||||||
uptimeKuma: UptimeKumaService
|
uptimeKuma: UptimeKumaService
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!await this.checkAdmin(interaction)) return;
|
if (!await this.checkAdmin(interaction)) return;
|
||||||
|
if (!interaction.guildId) {
|
||||||
|
await interaction.reply({ content: '❌ This command can only be used in a server.', flags: MessageFlags.Ephemeral });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const groupName = interaction.options.getString('group', true);
|
const groupName = interaction.options.getString('group', true);
|
||||||
|
|
||||||
const success = configStorage.removeGroup(groupName);
|
const success = configStorage.removeGroup(interaction.guildId, groupName);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
@@ -458,12 +588,16 @@ export class CommandsService {
|
|||||||
uptimeKuma: UptimeKumaService
|
uptimeKuma: UptimeKumaService
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!await this.checkAdmin(interaction)) return;
|
if (!await this.checkAdmin(interaction)) return;
|
||||||
|
if (!interaction.guildId) {
|
||||||
|
await interaction.reply({ content: '❌ This command can only be used in a server.', flags: MessageFlags.Ephemeral });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const groupName = interaction.options.getString('group', true);
|
const groupName = interaction.options.getString('group', true);
|
||||||
const monitorIdStr = interaction.options.getString('monitor', true);
|
const monitorIdStr = interaction.options.getString('monitor', true);
|
||||||
const monitorId = parseInt(monitorIdStr, 10);
|
const monitorId = parseInt(monitorIdStr, 10);
|
||||||
|
|
||||||
const success = configStorage.addMonitorToGroup(groupName, monitorId);
|
const success = configStorage.addMonitorToGroup(interaction.guildId, groupName, monitorId);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
const monitors = uptimeKuma.getAllMonitors();
|
const monitors = uptimeKuma.getAllMonitors();
|
||||||
@@ -489,11 +623,15 @@ export class CommandsService {
|
|||||||
uptimeKuma: UptimeKumaService
|
uptimeKuma: UptimeKumaService
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!await this.checkAdmin(interaction)) return;
|
if (!await this.checkAdmin(interaction)) return;
|
||||||
|
if (!interaction.guildId) {
|
||||||
|
await interaction.reply({ content: '❌ This command can only be used in a server.', flags: MessageFlags.Ephemeral });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const monitorIdStr = interaction.options.getString('monitor', true);
|
const monitorIdStr = interaction.options.getString('monitor', true);
|
||||||
const monitorId = parseInt(monitorIdStr, 10);
|
const monitorId = parseInt(monitorIdStr, 10);
|
||||||
|
|
||||||
const success = configStorage.removeMonitorFromGroup(monitorId);
|
const success = configStorage.removeMonitorFromGroup(interaction.guildId, monitorId);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
const monitors = uptimeKuma.getAllMonitors();
|
const monitors = uptimeKuma.getAllMonitors();
|
||||||
@@ -519,8 +657,12 @@ export class CommandsService {
|
|||||||
uptimeKuma: UptimeKumaService
|
uptimeKuma: UptimeKumaService
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!await this.checkAdmin(interaction)) return;
|
if (!await this.checkAdmin(interaction)) return;
|
||||||
|
if (!interaction.guildId) {
|
||||||
|
await interaction.reply({ content: '❌ This command can only be used in a server.', flags: MessageFlags.Ephemeral });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const groups = configStorage.getGroups();
|
const groups = configStorage.getGroups(interaction.guildId);
|
||||||
|
|
||||||
if (groups.length === 0) {
|
if (groups.length === 0) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
@@ -532,7 +674,7 @@ export class CommandsService {
|
|||||||
|
|
||||||
const monitors = uptimeKuma.getAllMonitors();
|
const monitors = uptimeKuma.getAllMonitors();
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setColor(configStorage.getEmbedColor())
|
.setColor(configStorage.getEmbedColor(interaction.guildId))
|
||||||
.setTitle('📋 Monitor Groups')
|
.setTitle('📋 Monitor Groups')
|
||||||
.setTimestamp();
|
.setTimestamp();
|
||||||
|
|
||||||
@@ -625,7 +767,12 @@ export class CommandsService {
|
|||||||
interaction: AutocompleteInteraction,
|
interaction: AutocompleteInteraction,
|
||||||
query: string
|
query: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const groups = configStorage.getGroups();
|
if (!interaction.guildId) {
|
||||||
|
await interaction.respond([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const groups = configStorage.getGroups(interaction.guildId);
|
||||||
const lowerQuery = query.toLowerCase();
|
const lowerQuery = query.toLowerCase();
|
||||||
|
|
||||||
const filtered = groups
|
const filtered = groups
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { Logger } from '../utils/logger';
|
|||||||
|
|
||||||
export class DiscordService {
|
export class DiscordService {
|
||||||
private client: Client;
|
private client: Client;
|
||||||
private channel: TextChannel | null = null;
|
private channels: Map<string, TextChannel> = new Map();
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
private maxMonitorsPerEmbed = 20;
|
private maxMonitorsPerEmbed = 20;
|
||||||
private commandsService: CommandsService;
|
private commandsService: CommandsService;
|
||||||
@@ -39,7 +39,7 @@ export class DiscordService {
|
|||||||
this.logger.info(`Discord bot logged in as ${client.user?.tag}`);
|
this.logger.info(`Discord bot logged in as ${client.user?.tag}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.initializeChannel();
|
await this.initializeChannels();
|
||||||
await this.registerCommands();
|
await this.registerCommands();
|
||||||
this.setupCommandHandler();
|
this.setupCommandHandler();
|
||||||
resolve();
|
resolve();
|
||||||
@@ -119,28 +119,39 @@ export class DiscordService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async initializeChannel(): Promise<void> {
|
private async initializeChannels(): Promise<void> {
|
||||||
const channelId = configStorage.getChannelId();
|
const guildIds = configStorage.getAllGuildIds();
|
||||||
|
|
||||||
if (!channelId) {
|
if (guildIds.length === 0) {
|
||||||
throw new Error('No channel configured. Use /set-channel command to set one.');
|
this.logger.info('No guilds configured yet');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
for (const guildId of guildIds) {
|
||||||
const channel = await this.client.channels.fetch(channelId);
|
const channelId = configStorage.getChannelId(guildId);
|
||||||
|
|
||||||
if (!channel || !channel.isTextBased() || channel.isDMBased()) {
|
if (!channelId) {
|
||||||
throw new Error('Invalid channel or channel is not a text channel');
|
this.logger.warn(`No channel configured for guild ${guildId}`);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.channel = channel as TextChannel;
|
try {
|
||||||
this.logger.info(`Initialized channel: ${this.channel.name}`);
|
const channel = await this.client.channels.fetch(channelId);
|
||||||
} catch (error: any) {
|
|
||||||
throw new Error(`Failed to initialize Discord channel: ${error.message}`);
|
if (!channel || !channel.isTextBased() || channel.isDMBased()) {
|
||||||
|
this.logger.warn(`Invalid channel ${channelId} for guild ${guildId}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.channels.set(guildId, channel as TextChannel);
|
||||||
|
this.logger.info(`Initialized channel for guild ${guildId}: ${(channel as TextChannel).name}`);
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.error(`Failed to initialize channel for guild ${guildId}: ${error.message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setChannel(channelId: string): Promise<void> {
|
public async setChannel(guildId: string, channelId: string): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const channel = await this.client.channels.fetch(channelId);
|
const channel = await this.client.channels.fetch(channelId);
|
||||||
|
|
||||||
@@ -148,52 +159,66 @@ export class DiscordService {
|
|||||||
throw new Error('Invalid channel or channel is not a text channel');
|
throw new Error('Invalid channel or channel is not a text channel');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.channel = channel as TextChannel;
|
const textChannel = channel as TextChannel;
|
||||||
configStorage.setMessageIds([]);
|
this.channels.set(guildId, textChannel);
|
||||||
configStorage.setChannelId(channelId);
|
configStorage.setMessageIds(guildId, []);
|
||||||
this.logger.info(`Changed status channel to: ${this.channel.name}`);
|
configStorage.setChannelId(guildId, channelId);
|
||||||
|
this.logger.info(`Changed status channel for guild ${guildId} to: ${textChannel.name}`);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
throw new Error(`Failed to set channel: ${error.message}`);
|
throw new Error(`Failed to set channel: ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateMonitorStatus(monitors: MonitorStats[]): Promise<void> {
|
public async updateMonitorStatus(monitors: MonitorStats[]): Promise<void> {
|
||||||
if (!this.channel) {
|
const guildIds = configStorage.getAllGuildIds();
|
||||||
this.logger.warn('Channel not initialized, skipping update');
|
|
||||||
|
if (guildIds.length === 0) {
|
||||||
|
this.logger.warn('No guilds configured, skipping update');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
for (const guildId of guildIds) {
|
||||||
const trackedIds = configStorage.getMonitorIds();
|
// Skip if guild doesn't actually exist in config (shouldn't happen but safety check)
|
||||||
const filteredMonitors = trackedIds.length === 0
|
if (!configStorage.guildExists(guildId)) {
|
||||||
? monitors
|
continue;
|
||||||
: monitors.filter(m => trackedIds.includes(m.monitor.id));
|
|
||||||
|
|
||||||
if (filteredMonitors.length === 0) {
|
|
||||||
this.logger.warn('No monitors to display after filtering');
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const embeds = this.createEmbeds(filteredMonitors, monitors.length);
|
const channel = this.channels.get(guildId);
|
||||||
|
if (!channel) {
|
||||||
const messageIds = configStorage.getMessageIds();
|
continue;
|
||||||
if (messageIds.length === 0) {
|
}
|
||||||
await this.createNewMessages(embeds);
|
|
||||||
} else {
|
try {
|
||||||
await this.updateExistingMessages(embeds);
|
const trackedIds = configStorage.getMonitorIds(guildId);
|
||||||
|
const filteredMonitors = trackedIds.length === 0
|
||||||
|
? monitors
|
||||||
|
: monitors.filter(m => trackedIds.includes(m.monitor.id));
|
||||||
|
|
||||||
|
if (filteredMonitors.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const embeds = this.createEmbeds(guildId, filteredMonitors, monitors.length);
|
||||||
|
|
||||||
|
const messageIds = configStorage.getMessageIds(guildId);
|
||||||
|
if (messageIds.length === 0) {
|
||||||
|
await this.createNewMessages(guildId, channel, embeds);
|
||||||
|
} else {
|
||||||
|
await this.updateExistingMessages(guildId, channel, embeds);
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.error(`Failed to update monitor status for guild ${guildId}: ${error.message}`);
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
|
||||||
this.logger.error(`Failed to update monitor status: ${error.message}`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private createEmbeds(monitors: MonitorStats[], totalMonitors: number): EmbedBuilder[] {
|
private createEmbeds(guildId: string, monitors: MonitorStats[], totalMonitors: number): EmbedBuilder[] {
|
||||||
const embeds: EmbedBuilder[] = [];
|
const embeds: EmbedBuilder[] = [];
|
||||||
const statusMessage = configStorage.getStatusMessage();
|
const statusMessage = configStorage.getStatusMessage(guildId);
|
||||||
const groups = configStorage.getGroups();
|
const groups = configStorage.getGroups(guildId);
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setColor(configStorage.getEmbedColor())
|
.setColor(configStorage.getEmbedColor(guildId))
|
||||||
.setTitle(statusMessage)
|
.setTitle(statusMessage)
|
||||||
.setTimestamp()
|
.setTimestamp()
|
||||||
.setFooter({ text: 'Last updated' });
|
.setFooter({ text: 'Last updated' });
|
||||||
@@ -306,39 +331,35 @@ export class DiscordService {
|
|||||||
`🔵 **Maintenance:** ${statusCounts.maintenance}`;
|
`🔵 **Maintenance:** ${statusCounts.maintenance}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createNewMessages(embeds: EmbedBuilder[]): Promise<void> {
|
private async createNewMessages(guildId: string, channel: TextChannel, embeds: EmbedBuilder[]): Promise<void> {
|
||||||
if (!this.channel) return;
|
|
||||||
|
|
||||||
const newMessageIds: string[] = [];
|
const newMessageIds: string[] = [];
|
||||||
for (const embed of embeds) {
|
for (const embed of embeds) {
|
||||||
const message = await this.channel.send({ embeds: [embed] });
|
const message = await channel.send({ embeds: [embed] });
|
||||||
newMessageIds.push(message.id);
|
newMessageIds.push(message.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
configStorage.setMessageIds(newMessageIds);
|
configStorage.setMessageIds(guildId, newMessageIds);
|
||||||
this.logger.info(`Created ${embeds.length} new status message(s)`);
|
this.logger.info(`Created ${embeds.length} new status message(s) for guild ${guildId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async updateExistingMessages(embeds: EmbedBuilder[]): Promise<void> {
|
private async updateExistingMessages(guildId: string, channel: TextChannel, embeds: EmbedBuilder[]): Promise<void> {
|
||||||
if (!this.channel) return;
|
const messageIds = configStorage.getMessageIds(guildId);
|
||||||
|
|
||||||
const messageIds = configStorage.getMessageIds();
|
|
||||||
const newMessageIds: string[] = [];
|
const newMessageIds: string[] = [];
|
||||||
|
|
||||||
for (let i = 0; i < embeds.length; i++) {
|
for (let i = 0; i < embeds.length; i++) {
|
||||||
try {
|
try {
|
||||||
if (i < messageIds.length) {
|
if (i < messageIds.length) {
|
||||||
const message = await this.channel.messages.fetch(messageIds[i]);
|
const message = await channel.messages.fetch(messageIds[i]);
|
||||||
await message.edit({ embeds: [embeds[i]] });
|
await message.edit({ embeds: [embeds[i]] });
|
||||||
newMessageIds.push(messageIds[i]);
|
newMessageIds.push(messageIds[i]);
|
||||||
} else {
|
} else {
|
||||||
const message = await this.channel.send({ embeds: [embeds[i]] });
|
const message = await channel.send({ embeds: [embeds[i]] });
|
||||||
newMessageIds.push(message.id);
|
newMessageIds.push(message.id);
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
this.logger.error(`Failed to update message: ${error.message}`);
|
this.logger.error(`Failed to update message for guild ${guildId}: ${error.message}`);
|
||||||
configStorage.setMessageIds([]);
|
configStorage.setMessageIds(guildId, []);
|
||||||
await this.createNewMessages(embeds);
|
await this.createNewMessages(guildId, channel, embeds);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,7 +368,7 @@ export class DiscordService {
|
|||||||
const toDelete = messageIds.slice(embeds.length);
|
const toDelete = messageIds.slice(embeds.length);
|
||||||
for (const messageId of toDelete) {
|
for (const messageId of toDelete) {
|
||||||
try {
|
try {
|
||||||
const message = await this.channel.messages.fetch(messageId);
|
const message = await channel.messages.fetch(messageId);
|
||||||
await message.delete();
|
await message.delete();
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
this.logger.warn(`Failed to delete message ${messageId}: ${error.message}`);
|
this.logger.warn(`Failed to delete message ${messageId}: ${error.message}`);
|
||||||
@@ -355,7 +376,7 @@ export class DiscordService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configStorage.setMessageIds(newMessageIds);
|
configStorage.setMessageIds(guildId, newMessageIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private chunkArray<T>(array: T[], size: number): T[][] {
|
private chunkArray<T>(array: T[], size: number): T[][] {
|
||||||
|
|||||||
Reference in New Issue
Block a user