diff --git a/locales/EnglishUS.json b/locales/EnglishUS.json index baa0c56b3..97d742a84 100644 --- a/locales/EnglishUS.json +++ b/locales/EnglishUS.json @@ -360,6 +360,7 @@ "options": { "song": "The song you want to search" }, + "select": "Please select the song you want to play", "errors": { "no_results": "No results found.", "search_error": "There was an error while searching." diff --git a/locales/Korean.json b/locales/Korean.json index 133cbbddc..1237085b2 100644 --- a/locales/Korean.json +++ b/locales/Korean.json @@ -360,6 +360,7 @@ "options": { "song": "검색하려는 노래 제목 또는 URL" }, + "select": "재생하고자 하는 노래를 선택해주세요.", "errors": { "no_results": "검색 결과가 없어요", "search_error": "노래를 검색하는 도중 문제가 발생했어요." diff --git a/src/commands/music/Search.ts b/src/commands/music/Search.ts index 871c57b69..158e05349 100644 --- a/src/commands/music/Search.ts +++ b/src/commands/music/Search.ts @@ -1,4 +1,4 @@ -import { ActionRowBuilder, ButtonBuilder, ButtonStyle, type TextChannel, type VoiceChannel } from 'discord.js'; +import { ActionRowBuilder, StringSelectMenuBuilder, type TextChannel, type VoiceChannel } from 'discord.js'; import type { SearchResult, Track } from 'lavalink-client'; import { Command, type Context, type Lavamusic } from '../../structures/index'; @@ -61,13 +61,18 @@ export default class Search extends Command { embeds: [embed.setDescription(ctx.locale('cmd.search.errors.no_results')).setColor(this.client.color.red)], }); } - const row = new ActionRowBuilder().addComponents( - new ButtonBuilder().setCustomId('1').setLabel('1').setStyle(ButtonStyle.Primary), - new ButtonBuilder().setCustomId('2').setLabel('2').setStyle(ButtonStyle.Primary), - new ButtonBuilder().setCustomId('3').setLabel('3').setStyle(ButtonStyle.Primary), - new ButtonBuilder().setCustomId('4').setLabel('4').setStyle(ButtonStyle.Primary), - new ButtonBuilder().setCustomId('5').setLabel('5').setStyle(ButtonStyle.Primary), - ); + const selectMenu = new StringSelectMenuBuilder() + .setCustomId('select-track') + .setPlaceholder(ctx.locale('cmd.search.select')) + .addOptions( + response.tracks.slice(0, 10).map((track: Track, index: number) => ({ + label: `${index + 1}. ${track.info.title}`, + description: track.info.author, + value: index.toString(), + })), + ); + const row = new ActionRowBuilder().addComponents(selectMenu); + if (response.loadType === 'search' && response.tracks.length > 5) { const embeds = response.tracks.map( (track: Track, index: number) => @@ -85,7 +90,7 @@ export default class Search extends Command { idle: 60000 / 2, }); collector.on('collect', async (int: any) => { - const track = response.tracks[Number.parseInt(int.customId) - 1]; + const track = response.tracks[Number.parseInt(int.values[0])]; await int.deferUpdate(); if (!track) return; player.queue.add(track); diff --git a/src/env.ts b/src/env.ts index 6b8218d26..57b1beade 100644 --- a/src/env.ts +++ b/src/env.ts @@ -23,59 +23,16 @@ const LavalinkNodeSchema = z.object({ }); const envSchema = z.object({ - /** - * The discord app token - */ TOKEN: z.string(), - - /** - * The client id - */ CLIENT_ID: z.string(), - - /** - * The default language - */ DEFAULT_LANGUAGE: z.string().default('EnglishUS'), - - /** - * The bot prefix - */ PREFIX: z.string().default('!'), - - /** - * The owner ids - */ OWNER_IDS: z.preprocess(val => (typeof val === 'string' ? JSON.parse(val) : val), z.string().array().optional()), - - /** - * The guild id for devlopment purposes - */ GUILD_ID: z.string().optional(), - - /** - * The Top.gg api key - */ TOPGG: z.string().optional(), - - /** - * The keep alive boolean - */ KEEP_ALIVE: z.preprocess(val => val === 'true', z.boolean().default(false)), - - /** - * The log channel id - */ LOG_CHANNEL_ID: z.string().optional(), - - /** - * The log command id - */ LOG_COMMANDS_ID: z.string().optional(), - - /** - * The bot status online | idle | dnd | invisible - */ BOT_STATUS: z.preprocess( val => { if (typeof val === 'string') { @@ -85,29 +42,14 @@ const envSchema = z.object({ }, z.enum(['online', 'idle', 'dnd', 'invisible']).default('online'), ), - - /** - * The bot activity - */ BOT_ACTIVITY: z.string().default('Lavamusic'), - - /** - * The bot activity type - */ BOT_ACTIVITY_TYPE: z.preprocess(val => { if (typeof val === 'string') { return Number.parseInt(val, 10); } return val; }, z.number().default(0)), - /** - * The database url - */ DATABASE_URL: z.string().optional(), - - /** - * Search engine - */ SEARCH_ENGINE: z.preprocess( val => { if (typeof val === 'string') { @@ -119,26 +61,17 @@ const envSchema = z.object({ .enum(['youtube', 'youtubemusic', 'soundcloud', 'spotify', 'apple', 'deezer', 'yandex', 'jiosaavn']) .default('youtube'), ), - /** - * Node in json - */ NODES: z.preprocess(val => (typeof val === 'string' ? JSON.parse(val) : val), z.array(LavalinkNodeSchema)), - /** - * Genius api - */ GENIUS_API: z.string().optional(), }); type Env = z.infer; -/** - * The environment variables - */ export const env: Env = envSchema.parse(process.env); for (const key in env) { if (!(key in env)) { - throw new Error(`Missing env variable: ${key}`); + throw new Error(`Missing env variable: ${key}. Please check the .env file and try again.`); } }