feat: add support for album links
- perform little code refactor, create new module spotifypull/1/head
parent
34c294ef0f
commit
cea5958e43
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "songlify"
|
name = "songlify"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
77
src/main.rs
77
src/main.rs
|
@ -1,39 +1,13 @@
|
||||||
use crate::SpotifyURL::Track;
|
|
||||||
use aspotify::{Client, ClientCredentials};
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use aspotify::Client;
|
||||||
use teloxide::prelude::*;
|
use teloxide::prelude::*;
|
||||||
|
|
||||||
enum SpotifyURL {
|
use spotify::SpotifyKind::Track;
|
||||||
Track(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
struct TrackInfo {
|
use crate::spotify::SpotifyKind::Album;
|
||||||
name: String,
|
|
||||||
artist: Vec<String>,
|
|
||||||
duration: Duration,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_spotify_entry(url: &str) -> Option<SpotifyURL> {
|
mod spotify;
|
||||||
if url.contains("https://open.spotify.com/track/") {
|
|
||||||
let track_id = url.rsplit('/').next().and_then(|x| x.split('?').next());
|
|
||||||
return match track_id {
|
|
||||||
Some(id) => Some(SpotifyURL::Track(id.to_string())),
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_spotify_track(spotify: Box<Client>, id: &String) -> Option<TrackInfo> {
|
|
||||||
match spotify.tracks().get_track(id.as_str(), None).await {
|
|
||||||
Ok(track) => Some(TrackInfo {
|
|
||||||
name: track.data.name,
|
|
||||||
artist: track.data.artists.iter().map(|x| x.name.clone()).collect(),
|
|
||||||
duration: track.data.duration,
|
|
||||||
}),
|
|
||||||
Err(_e) => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
@ -42,16 +16,14 @@ async fn main() {
|
||||||
|
|
||||||
let bot = Bot::from_env().auto_send();
|
let bot = Bot::from_env().auto_send();
|
||||||
teloxide::repl(bot, |message| async move {
|
teloxide::repl(bot, |message| async move {
|
||||||
let text = message.update.text().and_then(get_spotify_entry);
|
let text = message.update.text().and_then(spotify::get_spotify_entry);
|
||||||
match text {
|
match text {
|
||||||
Some(spotify) => {
|
Some(spotify) => {
|
||||||
let spotify_creds =
|
let spotify_client = spotify::get_spotify_client();
|
||||||
ClientCredentials::from_env().expect("CLIENT_ID and CLIENT_SECRET not found.");
|
|
||||||
let spotify_client = Box::new(Client::new(spotify_creds));
|
|
||||||
match spotify {
|
match spotify {
|
||||||
Track(id) => {
|
Track(id) => {
|
||||||
log::debug!("Parsing spotify song: {}", id);
|
log::debug!("Parsing spotify song: {}", id);
|
||||||
let track_info = get_spotify_track(spotify_client, &id).await;
|
let track_info = spotify::get_spotify_track(spotify_client, &id).await;
|
||||||
match track_info {
|
match track_info {
|
||||||
Some(info) => {
|
Some(info) => {
|
||||||
let reply = format!(
|
let reply = format!(
|
||||||
|
@ -60,7 +32,7 @@ async fn main() {
|
||||||
🧑🎤 Artist(s): {}\n\
|
🧑🎤 Artist(s): {}\n\
|
||||||
⏳ Duration: {} second(s)",
|
⏳ Duration: {} second(s)",
|
||||||
info.name,
|
info.name,
|
||||||
info.artist.join(", "),
|
info.artists.join(", "),
|
||||||
info.duration.as_secs()
|
info.duration.as_secs()
|
||||||
);
|
);
|
||||||
Some(message.reply_to(reply).await?)
|
Some(message.reply_to(reply).await?)
|
||||||
|
@ -68,6 +40,37 @@ async fn main() {
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Album(id) => {
|
||||||
|
log::debug!("Parsing spotify album: {}", id);
|
||||||
|
let album_info = spotify::get_spotify_album(spotify_client, &id).await;
|
||||||
|
match album_info {
|
||||||
|
Some(info) => {
|
||||||
|
let mut reply = format!(
|
||||||
|
"Album information:\n\
|
||||||
|
🎵 Album name name: {}\n\
|
||||||
|
🧑🎤 Artist(s): {}",
|
||||||
|
info.name,
|
||||||
|
info.artists.join(", ")
|
||||||
|
);
|
||||||
|
if !info.genres.is_empty() {
|
||||||
|
reply.push_str(
|
||||||
|
format!("\n💿 Genre(s): {}", info.genres.join(", "))
|
||||||
|
.as_str(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if !info.songs.is_empty() {
|
||||||
|
let songs = info
|
||||||
|
.songs
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.name.clone() + "\n")
|
||||||
|
.collect::<String>();
|
||||||
|
reply.push_str(format!("\n🎶 Song(s): {}", songs).as_str());
|
||||||
|
}
|
||||||
|
Some(message.reply_to(reply).await?)
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use aspotify::{Client, ClientCredentials};
|
||||||
|
|
||||||
|
pub enum SpotifyKind {
|
||||||
|
Track(String),
|
||||||
|
Album(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_id_in_url(url: &str) -> Option<&str> {
|
||||||
|
url.rsplit('/')
|
||||||
|
.next()
|
||||||
|
.and_then(|x| x.split(' ').next())
|
||||||
|
.and_then(|x| x.split('?').next())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_spotify_entry(url: &str) -> Option<SpotifyKind> {
|
||||||
|
if url.contains("https://open.spotify.com/track/") {
|
||||||
|
let track_id = get_id_in_url(url);
|
||||||
|
return match track_id {
|
||||||
|
Some(id) => Some(SpotifyKind::Track(id.to_string())),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if url.contains("https://open.spotify.com/album/") {
|
||||||
|
let album_id = get_id_in_url(url);
|
||||||
|
return match album_id {
|
||||||
|
Some(id) => Some(SpotifyKind::Album(id.to_string())),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_spotify_client() -> Box<Client> {
|
||||||
|
let spotify_creds =
|
||||||
|
ClientCredentials::from_env().expect("CLIENT_ID and CLIENT_SECRET not found.");
|
||||||
|
let spotify_client = Box::new(Client::new(spotify_creds));
|
||||||
|
spotify_client
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TrackInfo {
|
||||||
|
name: String,
|
||||||
|
artists: Vec<String>,
|
||||||
|
duration: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AlbumInfo {
|
||||||
|
pub(crate) name: String,
|
||||||
|
pub(crate) artists: Vec<String>,
|
||||||
|
pub(crate) genres: Vec<String>,
|
||||||
|
songs: Vec<TrackInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_spotify_track(spotify: Box<Client>, id: &String) -> Option<TrackInfo> {
|
||||||
|
match spotify.tracks().get_track(id.as_str(), None).await {
|
||||||
|
Ok(track) => Some(TrackInfo {
|
||||||
|
name: track.data.name,
|
||||||
|
artists: track.data.artists.iter().map(|x| x.name.clone()).collect(),
|
||||||
|
duration: track.data.duration,
|
||||||
|
}),
|
||||||
|
Err(_e) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_spotify_album(spotify: Box<Client>, id: &String) -> Option<AlbumInfo> {
|
||||||
|
match spotify.albums().get_album(id.as_str(), None).await {
|
||||||
|
Ok(album) => Some(AlbumInfo {
|
||||||
|
name: album.data.name,
|
||||||
|
artists: album.data.artists.iter().map(|x| x.name.clone()).collect(),
|
||||||
|
genres: album.data.genres,
|
||||||
|
songs: vec![], // TODO we could lookup songs and put them here!
|
||||||
|
}),
|
||||||
|
Err(_e) => None,
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue