Files
bot_Tamiseur/src/events/client/ready.ts
Zachary Guénot e714e94f85
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 3m43s
Fix duplicate streamWatching, locale guild et console log/error
2025-06-11 02:50:58 +02:00

140 lines
6.8 KiB
TypeScript

import { Events, ActivityType, ChannelType } from "discord.js"
import type { Client } from "discord.js"
import { useMainPlayer } from "discord-player"
import { SpotifyExtractor } from "@discord-player/extractor"
import { YoutubeiExtractor } from "discord-player-youtubei"
import { connect } from "mongoose"
import type { Document } from "mongoose"
import { playerDisco, playerReplay } from "@/utils/player"
import { twitchClient, listener, onlineSub, offlineSub, startStreamWatching } from "@/utils/twitch"
import { logConsole, logConsoleError } from "@/utils/console"
import type { GuildPlayer, Disco, GuildTwitch, GuildFbx } from "@/types/schemas"
import * as Freebox from "@/utils/freebox"
import dbGuildInit from "@/utils/dbGuildInit"
import dbGuild from "@/schemas/guild"
export const name = Events.ClientReady
export const once = true
export async function execute(client: Client) {
logConsole('discordjs', 'ready', { tag: client.user?.tag ?? "unknown" })
client.user?.setActivity("some bangers...", { type: ActivityType.Listening })
const player = useMainPlayer()
await player.extractors.register(SpotifyExtractor, {}).then(() => { logConsole('discord_player', 'extractor_loaded', { extractor: 'Spotify' }) }).catch(console.error)
await player.extractors.register(YoutubeiExtractor, {}).then(() => { logConsole('discord_player', 'extractor_loaded', { extractor: 'Youtube' }) }).catch(console.error)
if (process.env.NODE_ENV === "development") console.log(player.scanDeps())
const mongo_url = `mongodb://${process.env.MONGOOSE_USER}:${process.env.MONGOOSE_PASSWORD}@${process.env.MONGOOSE_HOST}/${process.env.MONGOOSE_DATABASE}`
await connect(mongo_url).catch(console.error)
if (process.env.NODE_ENV === "development") await twitchClient.eventSub.deleteAllSubscriptions()
const streamerIds: string[] = []
await Promise.all(client.guilds.cache.map(async guild => {
let guildProfile = await dbGuild.findOne({ guildId: guild.id })
guildProfile ??= await dbGuildInit(guild)
const dbDataPlayer = guildProfile.get("guildPlayer") as GuildPlayer
const botInstance = dbDataPlayer.instances?.find(instance => instance.botId === client.user?.id)
if (botInstance?.replay.trackUrl) await playerReplay(client, dbDataPlayer)
client.disco = { interval: {} as NodeJS.Timeout }
// eslint-disable-next-line @typescript-eslint/no-misused-promises
client.disco.interval = setInterval(async () => {
const guildProfile = await dbGuild.findOne({ guildId: guild.id })
const dbDataDisco = guildProfile?.get("guildPlayer.disco") as Disco
if (dbDataDisco.enabled) {
const state = await playerDisco(client, guild, dbDataDisco)
if (state === "clear") clearInterval(client.disco.interval)
}
}, 3000)
// Gestion du timer LCD Freebox
const dbDataFbx = guildProfile.get("guildFbx") as GuildFbx
if (dbDataFbx.enabled && dbDataFbx.lcd) {
if (dbDataFbx.lcd.enabled && dbDataFbx.lcd.botId === client.user?.id) {
logConsole('freebox', 'lcd_timer_restored', { guild: guild.name })
Freebox.Timer.schedule(client, guild.id, dbDataFbx)
}
}
const dbDataTwitch = guildProfile.get("guildTwitch") as GuildTwitch
if (!dbDataTwitch.enabled) return
if (!dbDataTwitch.streamers.length) { logConsole('twitch', 'ready.no_streamers_configured', { guild: guild.name }); return }
await Promise.all(dbDataTwitch.streamers.map(async streamer => {
if (streamerIds.includes(streamer.twitchUserId)) return
streamerIds.push(streamer.twitchUserId)
const user = await twitchClient.users.getUserById(streamer.twitchUserId)
if (!user) { logConsole('twitch', 'ready.user_not_found', { guild: guild.name, userId: streamer.twitchUserId }); return }
const userSubs = await twitchClient.eventSub.getSubscriptionsForUser(streamer.twitchUserId)
if (!userSubs.data.find(sub => sub.transportMethod === "webhook" && sub.type === "stream.online")) {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
listener.onStreamOnline(streamer.twitchUserId, onlineSub)
logConsole('twitch', 'listener_registered', { type: 'stream.online', name: user.name, id: streamer.twitchUserId })
}
if (!userSubs.data.find(sub => sub.transportMethod === "webhook" && sub.type === "stream.offline")) {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
listener.onStreamOffline(streamer.twitchUserId, offlineSub)
logConsole('twitch', 'listener_registered', { type: 'stream.offline', name: user.name, id: streamer.twitchUserId })
}
logConsole('twitch', 'user_operational', { name: user.name, id: streamer.twitchUserId })
const stream = await user.getStream()
if (stream && streamer.messageId) {
logConsole('twitch', 'ready.stream_restoration', { guild: guild.name, userName: user.name, userId: streamer.twitchUserId })
// Vérifier que le message existe encore
if (!dbDataTwitch.channelId) return
const channel = await guild.channels.fetch(dbDataTwitch.channelId)
if (channel && (channel.type === ChannelType.GuildText || channel.type === ChannelType.GuildAnnouncement)) {
try {
await channel.messages.fetch(streamer.messageId)
startStreamWatching(guild.id, streamer.twitchUserId, user.name, streamer.messageId)
logConsole('twitch', 'ready.monitoring_restored', { guild: guild.name, userName: user.name })
} catch (error) {
logConsoleError('twitch', 'ready.message_not_found', { guild: guild.name, userName: user.name }, error as Error)
await cleanupMessageId(guildProfile, streamer.twitchUserId)
}
}
} else if (streamer.messageId) {
// Il y a un messageId mais le stream n'est plus en ligne, nettoyer
logConsole('twitch', 'ready.stream_offline_cleanup', { guild: guild.name, userName: user.name })
await cleanupMessageId(guildProfile, streamer.twitchUserId)
}
logConsole('twitch', 'user_operational', { name: user.name, id: streamer.twitchUserId })
}))
}))
const subs = await twitchClient.eventSub.getSubscriptions()
await Promise.all(subs.data.map(async sub => {
if (streamerIds.includes(sub.condition.broadcaster_user_id as string)) return
if (sub.type !== "stream.online" && sub.type !== "stream.offline") return
await sub.unsubscribe().catch(console.error)
logConsole('twitch', 'unsubscribed', { type: sub.type, id: sub.condition.broadcaster_user_id as string })
}))
}
async function cleanupMessageId(guildProfile: Document, twitchUserId: string) {
try {
const dbData = guildProfile.get("guildTwitch") as GuildTwitch
const streamerIndex = dbData.streamers.findIndex(s => s.twitchUserId === twitchUserId)
if (streamerIndex === -1) return
dbData.streamers[streamerIndex].messageId = ""
guildProfile.set("guildTwitch", dbData)
guildProfile.markModified("guildTwitch")
await guildProfile.save().catch(console.error)
} catch (error) {
logConsoleError('twitch', 'ready.cleanup_error', { userId: twitchUserId }, error as Error)
}
}