Skip to content

Commit

Permalink
Merge pull request #719 from hatry4/main
Browse files Browse the repository at this point in the history
Lyrics command
  • Loading branch information
LucasB25 authored Sep 12, 2024
2 parents 3d653c3 + 054d932 commit e3dc4cb
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 2 deletions.
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ AUTO_NODE=" false" # true for auto node. It is given from lavainfo-api (https://
SEARCH_ENGINE= "YouTubeMusic" # Search engine to be used when playing the song. You can use: YouTube, YouTubeMusic, SoundCloud, Spotify, Apple, Deezer, Yandex and JioSaavn
MAX_PLAYLIST_SIZE= "100" # Max playlist size.
MAX_QUEUE_SIZE= "100" # Max queue size.
GENIUS_API= "" # Sign up and get your own api at (https://genius.com/) to fetch your lyrics (CLIENT TOKEN)

# Configuration for multiple Lavalink servers
LAVALINK_SERVERS = '[
{"url":"localhost:2333","auth":"youshallnotpass","name":"Local Node","secure":false},
{"url":"localhost:2333","auth":"youshallnotpass2","name":"Another Node","secure":false}
]'
]'
12 changes: 11 additions & 1 deletion locales/EnglishUS.json
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,16 @@
"looping_queue": "**Looping the queue.**",
"looping_off": "**Looping is now off.**"
},
"lyrics": {
"description": "Get's the lyrics of the currently playing track.",
"lyrics_track": "### Lyrics for: [{trackTitle}]({trackUrl})\n**`{lyrics}`**",
"searching": "`🔍` Searching for **{trackTitle}** lyrics...",
"errors": {
"no_results": "No lyrics found for the current track.",
"no_playing": "No track is currently playing.",
"lyrics_error": "An error occurred while getting the lyrics."
}
},
"nowplaying": {
"description": "Shows the currently playing song",
"now_playing": "Now Playing",
Expand Down Expand Up @@ -631,4 +641,4 @@
"Leave a guild": "Leave a guild",
"List all guilds the bot is in": "List all guilds the bot is in",
"Restart the bot": "Restart the bot"
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"@top-gg/sdk": "^3.1.6",
"discord.js": "^14.16.1",
"dotenv": "^16.4.5",
"genius-lyrics-api": "^3.2.1",
"i18n": "^0.15.1",
"node-system-stats": "^1.3.0",
"shoukaku": "github:shipgirlproject/Shoukaku#master",
Expand Down
183 changes: 183 additions & 0 deletions src/commands/music/Lyrics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import { Command, type Context, type Lavamusic } from "../../structures/index.js";
import { getLyrics } from "genius-lyrics-api";
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ComponentType } from "discord.js";

export default class Lyrics extends Command {
constructor(client: Lavamusic) {
super(client, {
name: "lyrics",
description: {
content: "cmd.lyrics.description",
examples: ["lyrics"],
usage: "lyrics",
},
category: "music",
aliases: ["ly"],
cooldown: 3,
args: false,
vote: false,
player: {
voice: true,
dj: false,
active: true,
djPerm: null,
},
permissions: {
dev: false,
client: ["SendMessages", "ReadMessageHistory", "ViewChannel", "EmbedLinks"],
user: [],
},
slashCommand: true,
options: [],
});
}

public async run(client: Lavamusic, ctx: Context): Promise<any> {
const player = client.queue.get(ctx.guild!.id);
const embed = this.client.embed();

if (!(player && !player.isPlaying)) {
return await ctx.sendMessage({
embeds: [embed.setColor(client.color.red).setDescription(ctx.locale("cmd.lyrics.errors.no_playing"))],
});
}

const currentTrack = player.current;
const trackTitle = currentTrack.info.title.replace(/\[.*?\]/g, "").trim();
const artistName = currentTrack.info.author.replace(/\[.*?\]/g, "").trim();
const trackUrl = currentTrack.info.uri;
const artworkUrl = currentTrack.info.artworkUrl;

await ctx.sendDeferMessage(ctx.locale("cmd.lyrics.searching", { trackTitle }));

const options = {
apiKey: client.config.lyricsApi,
title: trackTitle,
artist: artistName,
optimizeQuery: true,
};

try {
const lyrics = await getLyrics(options);
if (lyrics) {
const lyricsPages = this.paginateLyrics(lyrics);
let currentPage = 0;

const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId("prev")
.setEmoji(this.client.emoji.page.back)
.setStyle(ButtonStyle.Secondary)
.setDisabled(true),
new ButtonBuilder().setCustomId("stop").setEmoji(this.client.emoji.page.cancel).setStyle(ButtonStyle.Danger),
new ButtonBuilder()
.setCustomId("next")
.setEmoji(this.client.emoji.page.next)
.setStyle(ButtonStyle.Secondary)
.setDisabled(lyricsPages.length <= 1),
);

await ctx.editMessage({
embeds: [
embed
.setColor(client.color.main)
.setDescription(
ctx.locale("cmd.lyrics.lyrics_track", { trackTitle, trackUrl, lyrics: lyricsPages[currentPage] }),
)
.setThumbnail(artworkUrl)
.setTimestamp(),
],
components: [row],
});

const filter = (interaction) => interaction.user.id === ctx.author.id;
const collector = ctx.channel.createMessageComponentCollector({
filter,
componentType: ComponentType.Button,
time: 60000,
});

collector.on("collect", async (interaction) => {
if (interaction.customId === "prev") {
currentPage--;
} else if (interaction.customId === "next") {
currentPage++;
} else if (interaction.customId === "stop") {
collector.stop();
return interaction.update({ components: [] });
}

await interaction.update({
embeds: [
embed
.setDescription(
ctx.locale("cmd.lyrics.lyrics_track", { trackTitle, trackUrl, lyrics: lyricsPages[currentPage] }),
)
.setThumbnail(artworkUrl)
.setTimestamp(),
],
components: [
new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId("prev")
.setEmoji(this.client.emoji.page.back)
.setStyle(ButtonStyle.Secondary)
.setDisabled(currentPage === 0),
new ButtonBuilder()
.setCustomId("stop")
.setEmoji(this.client.emoji.page.cancel)
.setStyle(ButtonStyle.Danger),
new ButtonBuilder()
.setCustomId("next")
.setEmoji(this.client.emoji.page.next)
.setStyle(ButtonStyle.Secondary)
.setDisabled(currentPage === lyricsPages.length - 1),
),
],
});
});

collector.on("end", () => {
ctx.editMessage({ components: [] });
});
} else {
await ctx.editMessage({
embeds: [embed.setColor(client.color.red).setDescription(ctx.locale("cmd.lyrics.errors.no_results"))],
});
}
} catch (error) {
console.error(error);
await ctx.editMessage({
embeds: [embed.setColor(client.color.red).setDescription(ctx.locale("cmd.lyrics.errors.lyrics_error"))],
});
}
}

paginateLyrics(lyrics) {
const lines = lyrics.split("\n");
const pages = [];
let page = "";

for (const line of lines) {
if (page.length + line.length > 2048) {
pages.push(page);
page = "";
}
page += `${line}\n`;
}

if (page) pages.push(page);
return pages;
}
}

/**
* Project: lavamusic
* Author: Appu
* Main Contributor: LucasB25
* Company: Coders
* Copyright (c) 2024. All rights reserved.
* This code is the property of Coder and may not be reproduced or
* modified without permission. For more information, contact us at
* https://discord.gg/ns8CTk9J3e
*/
1 change: 1 addition & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export default {
guildId: process.env.GUILD_ID,
logChannelId: process.env.LOG_CHANNEL_ID,
commandLogs: process.env.LOG_COMMANDS_ID,
lyricsApi: process.env.GENIUS_API,
links: {
img: process.env.IMG_LINK || "https://i.imgur.com/ud3EWNh.jpg",
},
Expand Down

0 comments on commit e3dc4cb

Please sign in to comment.