feat: add support for album links
- perform little code refactor, create new module spotify
This commit is contained in:
		
							parent
							
								
									34c294ef0f
								
							
						
					
					
						commit
						cea5958e43
					
				@ -1,6 +1,6 @@
 | 
			
		||||
[package]
 | 
			
		||||
name = "songlify"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
version = "0.2.0"
 | 
			
		||||
edition = "2018"
 | 
			
		||||
 | 
			
		||||
# 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 aspotify::Client;
 | 
			
		||||
use teloxide::prelude::*;
 | 
			
		||||
 | 
			
		||||
enum SpotifyURL {
 | 
			
		||||
    Track(String),
 | 
			
		||||
}
 | 
			
		||||
use spotify::SpotifyKind::Track;
 | 
			
		||||
 | 
			
		||||
struct TrackInfo {
 | 
			
		||||
    name: String,
 | 
			
		||||
    artist: Vec<String>,
 | 
			
		||||
    duration: Duration,
 | 
			
		||||
}
 | 
			
		||||
use crate::spotify::SpotifyKind::Album;
 | 
			
		||||
 | 
			
		||||
fn get_spotify_entry(url: &str) -> Option<SpotifyURL> {
 | 
			
		||||
    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,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
mod spotify;
 | 
			
		||||
 | 
			
		||||
#[tokio::main]
 | 
			
		||||
async fn main() {
 | 
			
		||||
@ -42,16 +16,14 @@ async fn main() {
 | 
			
		||||
 | 
			
		||||
    let bot = Bot::from_env().auto_send();
 | 
			
		||||
    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 {
 | 
			
		||||
            Some(spotify) => {
 | 
			
		||||
                let spotify_creds =
 | 
			
		||||
                    ClientCredentials::from_env().expect("CLIENT_ID and CLIENT_SECRET not found.");
 | 
			
		||||
                let spotify_client = Box::new(Client::new(spotify_creds));
 | 
			
		||||
                let spotify_client = spotify::get_spotify_client();
 | 
			
		||||
                match spotify {
 | 
			
		||||
                    Track(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 {
 | 
			
		||||
                            Some(info) => {
 | 
			
		||||
                                let reply = format!(
 | 
			
		||||
@ -60,7 +32,7 @@ async fn main() {
 | 
			
		||||
                                🧑🎤 Artist(s): {}\n\
 | 
			
		||||
                                ⏳ Duration: {} second(s)",
 | 
			
		||||
                                    info.name,
 | 
			
		||||
                                    info.artist.join(", "),
 | 
			
		||||
                                    info.artists.join(", "),
 | 
			
		||||
                                    info.duration.as_secs()
 | 
			
		||||
                                );
 | 
			
		||||
                                Some(message.reply_to(reply).await?)
 | 
			
		||||
@ -68,6 +40,37 @@ async fn main() {
 | 
			
		||||
                            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,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										76
									
								
								src/spotify/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/spotify/mod.rs
									
									
									
									
									
										Normal file
									
								
							@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user