Add lyrics command and format playlists list differently

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/2/head
trivernis 4 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",
"rand 0.8.3",
"regex",
"reqwest",
"rusqlite",
"serde",
"serde_derive",

@ -29,3 +29,4 @@ chrono = "0.4.19"
colored = "2.0.0"
sysinfo = "0.16.5"
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 join::JOIN_COMMAND;
use leave::LEAVE_COMMAND;
use lyrics::LYRICS_COMMAND;
use pause::PAUSE_COMMAND;
use play::PLAY_COMMAND;
use play_next::PLAY_NEXT_COMMAND;
@ -39,6 +40,7 @@ mod clear;
mod current;
mod join;
mod leave;
mod lyrics;
mod pause;
mod play;
mod play_next;
@ -61,7 +63,8 @@ mod skip;
clear,
pause,
save_playlist,
playlists
playlists,
lyrics
)]
#[prefixes("m", "music")]
pub struct Music;

@ -17,8 +17,13 @@ async fn playlists(ctx: &Context, msg: &Message) -> CommandResult {
msg.channel_id
.send_message(ctx, |m| {
m.embed(|e| {
e.title("Saved Playlists")
.fields(playlists.into_iter().map(|p| (p.name, p.url, true)))
e.title("Saved Playlists").description(
playlists
.into_iter()
.map(|p| format!("[{}]({})", p.name, p.url))
.collect::<Vec<String>>()
.join("\n"),
)
})
})
.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::process::Command;
pub(crate) mod lyrics;
pub(crate) mod queue;
pub(crate) mod responses;
pub(crate) mod spotify;

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

Loading…
Cancel
Save