diff --git a/.env.example b/.env.example index be534fb47..3de0c8b79 100644 --- a/.env.example +++ b/.env.example @@ -15,4 +15,4 @@ DATABASE_URL="" # Your database url (If you want to use sqlite, then you can lea AUTO_NODE=="false" # true for auto node. It is given from lavainfo-api (https://lavainfo-api.deno.dev). SEARCH_ENGINE="YouTubeMusic" # Search engine to be used when playing the song. You can use: YouTube, YouTubeMusic, SoundCloud, Spotify, Apple, Deezer, Yandex and JioSaavn GENIUS_API="" # Sign up and get your own api at (https://genius.com/) to fetch your lyrics (CLIENT TOKEN) -NODES=[{"id":"Local Node","host":"localhost","port":2333,"authorization":"youshallnotpass","retryAmount":5,"retryDelay":60000,"secure":"false"}] +NODES=[{"id":"Local Node","host":"localhost","port":2333,"authorization":"youshallnotpass","secure":"false","retryAmount":5,"retryDelay":60000}] diff --git a/Dockerfile b/Dockerfile index 43d6a7160..27e049a33 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Stage 1: Build TypeScript -FROM node:22 AS builder +FROM node:23 AS builder WORKDIR /opt/lavamusic/ @@ -15,7 +15,7 @@ RUN npx prisma db push && \ npm run build # Stage 2: Create production image -FROM node:22-slim +FROM node:23-slim ENV NODE_ENV=production diff --git a/biome.json b/biome.json index 1405b9c85..f9dbaa5fe 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/1.9.2/schema.json", + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", "vcs": { "enabled": true, "clientKind": "git", diff --git a/package.json b/package.json index 924fa67c2..31b8bb367 100644 --- a/package.json +++ b/package.json @@ -33,16 +33,16 @@ }, "homepage": "https://github.com/appujet/lavamusic#readme", "devDependencies": { - "@biomejs/biome": "^1.9.2", + "@biomejs/biome": "^1.9.4", "@types/i18n": "^0.13.12", - "@types/node": "^22.7.4", + "@types/node": "^22.7.7", "@types/signale": "^1.4.7", - "prisma": "^5.20.0", - "tslib": "^2.7.0", - "typescript": "^5.6.2" + "prisma": "^5.21.1", + "tslib": "^2.8.0", + "typescript": "^5.6.3" }, "dependencies": { - "@prisma/client": "^5.20.0", + "@prisma/client": "^5.21.1", "@top-gg/sdk": "^3.1.6", "discord.js": "^14.16.3", "dotenv": "^16.4.5", @@ -52,7 +52,7 @@ "node-system-stats": "^1.3.0", "signale": "^1.4.0", "topgg-autoposter": "^2.0.2", - "undici": "^6.19.8", + "undici": "^6.20.1", "zod": "^3.23.8" }, "signale": { diff --git a/src/commands/music/Lyrics.ts b/src/commands/music/Lyrics.ts index ea6ad68af..b258fb40b 100644 --- a/src/commands/music/Lyrics.ts +++ b/src/commands/music/Lyrics.ts @@ -1,4 +1,11 @@ -import { ActionRowBuilder, ButtonBuilder, type ButtonInteraction, ButtonStyle, ComponentType, type TextChannel, } from 'discord.js'; +import { + ActionRowBuilder, + ButtonBuilder, + type ButtonInteraction, + ButtonStyle, + ComponentType, + type TextChannel, +} from 'discord.js'; import { getLyrics } from 'genius-lyrics-api'; import { Command, type Context, type Lavamusic } from '../../structures/index'; @@ -7,9 +14,9 @@ export default class Lyrics extends Command { super(client, { name: 'lyrics', description: { - content: 'cmd.lyrics.description', - examples: ['lyrics'], - usage: 'lyrics', + content: 'cmd.lyrics.description', + examples: ['lyrics'], + usage: 'lyrics', }, category: 'music', aliases: ['ly'], @@ -33,8 +40,8 @@ export default class Lyrics extends Command { } public async run(client: Lavamusic, ctx: Context): Promise { - let player = client.manager.getPlayer(ctx.guild!.id); - if (!player) return await ctx.sendMessage(ctx.locale('event.message.no_music_playing')) + const player = client.manager.getPlayer(ctx.guild!.id); + if (!player) return await ctx.sendMessage(ctx.locale('event.message.no_music_playing')); const embed = this.client.embed(); const track = player.queue.current!; diff --git a/src/events/client/InteractionCreate.ts b/src/events/client/InteractionCreate.ts index 3a1abdd50..7a9fdcd5a 100644 --- a/src/events/client/InteractionCreate.ts +++ b/src/events/client/InteractionCreate.ts @@ -240,13 +240,13 @@ export default class InteractionCreate extends Event { const embed = new EmbedBuilder() .setAuthor({ name: 'Slash - Command Logs', - iconURL: this.client.user?.avatarURL({ - size: 2048, - })!, + iconURL: this.client.user?.avatarURL({ size: 2048 })!, }) .setColor(this.client.config.color.blue) - .setDescription( - `**\`${command.name}\`** | Used By **${interaction.user.tag} \`${interaction.user.id}\`** From **${interaction.guild.name} \`${interaction.guild.id}\`**`, + .addFields( + { name: 'Command', value: `\`${command.name}\``, inline: true }, + { name: 'User', value: `${interaction.user.tag} (\`${interaction.user.id}\`)`, inline: true }, + { name: 'Guild', value: `${interaction.guild.name} (\`${interaction.guild.id}\`)`, inline: true }, ) .setTimestamp(); diff --git a/src/events/client/MessageCreate.ts b/src/events/client/MessageCreate.ts index ef36a26d4..b58e9e77d 100644 --- a/src/events/client/MessageCreate.ts +++ b/src/events/client/MessageCreate.ts @@ -259,8 +259,10 @@ export default class MessageCreate extends Event { iconURL: this.client.user?.avatarURL({ size: 2048 })!, }) .setColor(this.client.config.color.green) - .setDescription( - `**\`${command.name}\`** | Used By **${message.author.tag} \`${message.author.id}\`** From **${message.guild.name} \`${message.guild.id}\`**`, + .addFields( + { name: 'Command', value: `\`${command.name}\``, inline: true }, + { name: 'User', value: `${message.author.tag} (\`${message.author.id}\`)`, inline: true }, + { name: 'Guild', value: `${message.guild.name} (\`${message.guild.id}\`)`, inline: true }, ) .setTimestamp(); diff --git a/src/events/client/VoiceStateUpdate.ts b/src/events/client/VoiceStateUpdate.ts index 3413ee977..47d6fbdb1 100644 --- a/src/events/client/VoiceStateUpdate.ts +++ b/src/events/client/VoiceStateUpdate.ts @@ -47,7 +47,7 @@ export default class VoiceStateUpdate extends Event { handale = { async join(newState: VoiceState, client: Lavamusic) { - await new Promise((resolve) => setTimeout(resolve, 3000)); + await new Promise(resolve => setTimeout(resolve, 3000)); const bot = newState.guild.voiceStates.cache.get(client.user!.id); if (!bot) return; @@ -58,7 +58,7 @@ export default class VoiceStateUpdate extends Event { bot.suppress ) { if (bot.channel && bot.member && bot.channel.permissionsFor(bot.member!).has('MuteMembers')) { - await bot.setSuppressed(false) + await bot.setSuppressed(false); } } @@ -114,7 +114,7 @@ export default class VoiceStateUpdate extends Event { async move(newState: VoiceState, client: Lavamusic) { // delay for 3 seconds - await new Promise((resolve) => setTimeout(resolve, 3000)); + await new Promise(resolve => setTimeout(resolve, 3000)); const bot = newState.guild.voiceStates.cache.get(client.user!.id); if (!bot) return; @@ -125,7 +125,7 @@ export default class VoiceStateUpdate extends Event { bot.suppress ) { if (bot.channel && bot.member && bot.channel.permissionsFor(bot.member!).has('MuteMembers')) { - await bot.setSuppressed(false) + await bot.setSuppressed(false); } } }, diff --git a/src/events/player/PlayerDestroy.ts b/src/events/player/PlayerDestroy.ts index f5ead1230..bfa9fb3aa 100644 --- a/src/events/player/PlayerDestroy.ts +++ b/src/events/player/PlayerDestroy.ts @@ -4,35 +4,35 @@ import { Event, type Lavamusic } from '../../structures/index'; import { updateSetup } from '../../utils/SetupSystem'; export default class PlayerDestroy extends Event { - constructor(client: Lavamusic, file: string) { - super(client, file, { - name: 'playerDestroy', - }); - } + constructor(client: Lavamusic, file: string) { + super(client, file, { + name: 'playerDestroy', + }); + } - public async run(player: Player, _reason: string): Promise { - const guild = this.client.guilds.cache.get(player.guildId); - if (!guild) return; - const locale = await this.client.db.getLanguage(player.guildId); - await updateSetup(this.client, guild, locale); + public async run(player: Player, _reason: string): Promise { + const guild = this.client.guilds.cache.get(player.guildId); + if (!guild) return; + const locale = await this.client.db.getLanguage(player.guildId); + await updateSetup(this.client, guild, locale); - const messageId = player.get('messageId'); - if (!messageId) return; + const messageId = player.get('messageId'); + if (!messageId) return; - const channel = guild.channels.cache.get(player.textChannelId!) as TextChannel; - if (!channel) return; + const channel = guild.channels.cache.get(player.textChannelId!) as TextChannel; + if (!channel) return; - const message = await channel.messages.fetch(messageId).catch(() => { - null; - }); - if (!message) return; + const message = await channel.messages.fetch(messageId).catch(() => { + null; + }); + if (!message) return; - if (message.editable) { - await message.edit({ components: [] }).catch(() => { - null; - }); - } - } + if (message.editable) { + await message.edit({ components: [] }).catch(() => { + null; + }); + } + } } /** diff --git a/src/events/player/PlayerDisconnect.ts b/src/events/player/PlayerDisconnect.ts index 630e5a8f7..78183fb77 100644 --- a/src/events/player/PlayerDisconnect.ts +++ b/src/events/player/PlayerDisconnect.ts @@ -4,35 +4,35 @@ import { Event, type Lavamusic } from '../../structures/index'; import { updateSetup } from '../../utils/SetupSystem'; export default class PlayerDisconnect extends Event { - constructor(client: Lavamusic, file: string) { - super(client, file, { - name: 'playerDisconnect', - }); - } + constructor(client: Lavamusic, file: string) { + super(client, file, { + name: 'playerDisconnect', + }); + } - public async run(player: Player, _voiceChannelId: string): Promise { - const guild = this.client.guilds.cache.get(player.guildId); - if (!guild) return; - const locale = await this.client.db.getLanguage(player.guildId); - await updateSetup(this.client, guild, locale); + public async run(player: Player, _voiceChannelId: string): Promise { + const guild = this.client.guilds.cache.get(player.guildId); + if (!guild) return; + const locale = await this.client.db.getLanguage(player.guildId); + await updateSetup(this.client, guild, locale); - const messageId = player.get('messageId'); - if (!messageId) return; + const messageId = player.get('messageId'); + if (!messageId) return; - const channel = guild.channels.cache.get(player.textChannelId!) as TextChannel; - if (!channel) return; + const channel = guild.channels.cache.get(player.textChannelId!) as TextChannel; + if (!channel) return; - const message = await channel.messages.fetch(messageId).catch(() => { - null; - }); - if (!message) return; + const message = await channel.messages.fetch(messageId).catch(() => { + null; + }); + if (!message) return; - if (message.editable) { - await message.edit({ components: [] }).catch(() => { - null; - }); - } - } + if (message.editable) { + await message.edit({ components: [] }).catch(() => { + null; + }); + } + } } /** diff --git a/src/utils/genius-lyrics-api.d.ts b/src/utils/genius-lyrics-api.d.ts index 177debc18..9b56c3595 100644 --- a/src/utils/genius-lyrics-api.d.ts +++ b/src/utils/genius-lyrics-api.d.ts @@ -1,36 +1,36 @@ declare module 'genius-lyrics-api' { - interface SearchOptions { - apiKey: string; - title: string; - artist?: string; - optimizeQuery?: boolean; - } + interface SearchOptions { + apiKey: string; + title: string; + artist?: string; + optimizeQuery?: boolean; + } - interface Song { - id: number; - title: string; - url: string; - } + interface Song { + id: number; + title: string; + url: string; + } - interface LyricsOptions { - title: string; - artist: string; - } + interface LyricsOptions { + title: string; + artist: string; + } - interface AlbumArtOptions { - title: string; - artist: string; - } + interface AlbumArtOptions { + title: string; + artist: string; + } - interface SongByIdOptions { - id: number; - apiKey: string; - } + interface SongByIdOptions { + id: number; + apiKey: string; + } - export function search(options: SearchOptions): Promise; - export function getSong(options: { id: number; apiKey: string }): Promise; - export function getLyrics(options: LyricsOptions): Promise; - export function getAlbumArt(options: AlbumArtOptions): Promise; - export function getSongById(options: SongByIdOptions): Promise; - export function searchSong(options: SearchOptions): Promise; + export function search(options: SearchOptions): Promise; + export function getSong(options: { id: number; apiKey: string }): Promise; + export function getLyrics(options: LyricsOptions): Promise; + export function getAlbumArt(options: AlbumArtOptions): Promise; + export function getSongById(options: SongByIdOptions): Promise; + export function searchSong(options: SearchOptions): Promise; } diff --git a/tsconfig.json b/tsconfig.json index 4a46aa3b0..d3742575b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,11 +1,13 @@ { "compilerOptions": { - "module": "CommonJS", "target": "ESNext", "lib": ["ESNext", "WebWorker"], + "module": "CommonJS", "moduleResolution": "node", "declaration": true, "sourceMap": false, + "removeComments": true, + "importHelpers": true, "strict": true, "esModuleInterop": true, "experimentalDecorators": true,