Add lyrics command and format playlists list differently

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/2/head
trivernis 3 years ago
parent 0cb0a4c47b
commit 750ee7d0dc
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

1
Cargo.lock generated

@ -2109,6 +2109,7 @@ dependencies = [
"minecraft-data-rs", "minecraft-data-rs",
"rand 0.8.3", "rand 0.8.3",
"regex", "regex",
"reqwest",
"rusqlite", "rusqlite",
"serde", "serde",
"serde_derive", "serde_derive",

@ -28,4 +28,5 @@ fern = "0.6.0"
chrono = "0.4.19" chrono = "0.4.19"
colored = "2.0.0" colored = "2.0.0"
sysinfo = "0.16.5" sysinfo = "0.16.5"
database = {path="./database"} database = {path="./database"}
reqwest = "0.11.2"

@ -0,0 +1,45 @@
use serenity::client::Context;
use serenity::framework::standard::macros::command;
use serenity::framework::standard::CommandResult;
use serenity::model::channel::Message;
use crate::commands::music::get_queue_for_guild;
use crate::providers::music::lyrics::get_lyrics;
#[command]
#[only_in(guilds)]
#[description("Shows the lyrics for the currently playing song")]
#[usage("")]
async fn lyrics(ctx: &Context, msg: &Message) -> CommandResult {
let guild = msg.guild(&ctx.cache).await.unwrap();
log::debug!("Fetching lyrics for song playing in {}", guild.id);
let queue = get_queue_for_guild(ctx, &guild.id).await?;
let queue_lock = queue.lock().await;
if let Some(current) = queue_lock.current() {
log::debug!("Playing music. Fetching lyrics for currently playing song...");
let metadata = current.metadata();
let title = metadata.title.clone().unwrap();
let author = metadata.artist.clone().unwrap();
if let Some(lyrics) = get_lyrics(&*author, &*title).await? {
log::trace!("Lyrics for '{}' are {}", title, lyrics);
msg.channel_id
.send_message(ctx, |m| {
m.embed(|e| e.title(format!("Lyrics for {}", title)).description(lyrics))
})
.await?;
} else {
log::debug!("No lyrics found");
msg.channel_id.say(ctx, "No lyrics found").await?;
}
} else {
msg.channel_id
.say(ctx, "I'm not playing music right now")
.await?;
}
Ok(())
}

@ -16,6 +16,7 @@ use clear::CLEAR_COMMAND;
use current::CURRENT_COMMAND; use current::CURRENT_COMMAND;
use join::JOIN_COMMAND; use join::JOIN_COMMAND;
use leave::LEAVE_COMMAND; use leave::LEAVE_COMMAND;
use lyrics::LYRICS_COMMAND;
use pause::PAUSE_COMMAND; use pause::PAUSE_COMMAND;
use play::PLAY_COMMAND; use play::PLAY_COMMAND;
use play_next::PLAY_NEXT_COMMAND; use play_next::PLAY_NEXT_COMMAND;
@ -39,6 +40,7 @@ mod clear;
mod current; mod current;
mod join; mod join;
mod leave; mod leave;
mod lyrics;
mod pause; mod pause;
mod play; mod play;
mod play_next; mod play_next;
@ -61,7 +63,8 @@ mod skip;
clear, clear,
pause, pause,
save_playlist, save_playlist,
playlists playlists,
lyrics
)] )]
#[prefixes("m", "music")] #[prefixes("m", "music")]
pub struct Music; pub struct Music;

@ -17,8 +17,13 @@ async fn playlists(ctx: &Context, msg: &Message) -> CommandResult {
msg.channel_id msg.channel_id
.send_message(ctx, |m| { .send_message(ctx, |m| {
m.embed(|e| { m.embed(|e| {
e.title("Saved Playlists") e.title("Saved Playlists").description(
.fields(playlists.into_iter().map(|p| (p.name, p.url, true))) playlists
.into_iter()
.map(|p| format!("[{}]({})", p.name, p.url))
.collect::<Vec<String>>()
.join("\n"),
)
}) })
}) })
.await?; .await?;

@ -0,0 +1,24 @@
use crate::utils::error::BotResult;
use regex::Regex;
use serde_derive::Deserialize;
const API_ENDPOINT: &str = "https://api.lyrics.ovh/v1/";
pub async fn get_lyrics(artist: &str, title: &str) -> BotResult<Option<String>> {
lazy_static::lazy_static! { static ref DOUBLE_LB_REGEX: Regex = Regex::new(r"\n\n").unwrap(); }
log::debug!("Requesting lyrics for '{}' by '{}'", title, artist);
let request_url = format!("{}{}/{}", API_ENDPOINT, artist, title);
log::trace!("Request url is {}", request_url);
let response = reqwest::get(request_url).await?;
let response_text = response.text().await?;
log::trace!("Lyrics Response is {}", response_text);
let lyrics: Option<Lyrics> = serde_json::from_str(&*response_text).ok();
Ok(lyrics.map(|l| DOUBLE_LB_REGEX.replace_all(&*l.lyrics, "\n").to_string()))
}
#[derive(Deserialize, Clone, Debug)]
struct Lyrics {
lyrics: String,
}

@ -10,6 +10,7 @@ use std::time::Duration;
use tokio::io::AsyncReadExt; use tokio::io::AsyncReadExt;
use tokio::process::Command; use tokio::process::Command;
pub(crate) mod lyrics;
pub(crate) mod queue; pub(crate) mod queue;
pub(crate) mod responses; pub(crate) mod responses;
pub(crate) mod spotify; pub(crate) mod spotify;

@ -25,6 +25,9 @@ pub enum BotError {
#[error("Spotify API Error: {0}")] #[error("Spotify API Error: {0}")]
SpotifyError(#[from] aspotify::Error), SpotifyError(#[from] aspotify::Error),
#[error("Reqwest Error: {0}")]
Reqwest(#[from] reqwest::Error),
#[error("{0}")] #[error("{0}")]
Msg(String), Msg(String),
} }

Loading…
Cancel
Save