diff --git a/.dockerignore b/.dockerignore
index 07827cc..96ef862 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,2 +1,2 @@
target/
-.idea/
\ No newline at end of file
+.idea/
diff --git a/.gitignore b/.gitignore
index 62bd1a4..70b1c1c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,4 +9,3 @@ Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
-
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..37c5bdd
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..1a0176a
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/.idea/google-java-format.xml b/.idea/google-java-format.xml
new file mode 100644
index 0000000..7c69eed
--- /dev/null
+++ b/.idea/google-java-format.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bfecbb1..9360735 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,7 +3,4 @@
-
-
-
-
\ No newline at end of file
+
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 68e6503..c56df5b 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -5,4 +5,4 @@
-
\ No newline at end of file
+
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
index 797acea..a1fe99e 100644
--- a/.idea/runConfigurations.xml
+++ b/.idea/runConfigurations.xml
@@ -7,4 +7,4 @@
-
\ No newline at end of file
+
diff --git a/.idea/sbt.xml b/.idea/sbt.xml
new file mode 100644
index 0000000..a6f46a0
--- /dev/null
+++ b/.idea/sbt.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 35eb1dd..dcb6b8c 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -3,4 +3,4 @@
-
\ No newline at end of file
+
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..683049a
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,17 @@
+# See https://pre-commit.com for more information
+# See https://pre-commit.com/hooks.html for more hooks
+repos:
+- repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v3.2.0
+ hooks:
+ - id: trailing-whitespace
+ - id: check-merge-conflict
+ - id: end-of-file-fixer
+ - id: check-yaml
+ - id: check-added-large-files
+- repo: https://github.com/doublify/pre-commit-rust
+ rev: v1.0
+ hooks:
+ - id: fmt
+ args: ['--verbose', '--']
+ - id: cargo-check
diff --git a/Cargo.toml b/Cargo.toml
index 7a80f6f..60d374c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "songlify"
-version = "0.2.0"
+version = "0.2.1"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -10,4 +10,4 @@ teloxide = { version = "0.5", features = ["auto-send", "macros"] }
log = "0.4"
pretty_env_logger = "0.4.0"
tokio = { version = "1.8", features = ["rt-multi-thread", "macros"] }
-aspotify = "0.7.0"
\ No newline at end of file
+aspotify = "0.7.0"
diff --git a/Dockerfile b/Dockerfile
index 0dbde9c..c42db36 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -15,4 +15,4 @@ COPY --from=builder /build/target/release/songlify /usr/bin/songlify
COPY --from=builder /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib/x86_64-linux-gnu/
COPY --from=builder /usr/lib/x86_64-linux-gnu/libstdc++.so.6 /usr/lib/x86_64-linux-gnu/
-ENTRYPOINT /usr/bin/songlify
\ No newline at end of file
+ENTRYPOINT /usr/bin/songlify
diff --git a/README.md b/README.md
index b4b27b7..17eeeed 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,3 @@
# Songlify
-A Telegram bot that gives you information about the song other people share with you in chat.
\ No newline at end of file
+A Telegram bot that gives you information about the song other people share with you in chat.
diff --git a/songlify.iml b/songlify.iml
index 2fecef3..601d455 100644
--- a/songlify.iml
+++ b/songlify.iml
@@ -9,4 +9,4 @@
-
\ No newline at end of file
+
diff --git a/src/main.rs b/src/main.rs
index b5e2379..c1ff728 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,8 +1,9 @@
use teloxide::prelude::*;
+use crate::spotify::TrackInfo;
use spotify::SpotifyKind::Track;
-use crate::spotify::SpotifyKind::Album;
+use crate::spotify::SpotifyKind::{Album, Playlist};
mod spotify;
@@ -44,9 +45,10 @@ async fn main() {
Some(info) => {
let mut reply = format!(
"Album information:\n\
- šµ Album name name: {}\n\
- š§āš¤ Artist(s): {}",
+ šµ Album name: {}\n\
+ š§āš¤ {} artist(s): {}",
info.name,
+ info.artists.len(),
info.artists.join(", ")
);
if !info.genres.is_empty() {
@@ -55,15 +57,34 @@ async fn main() {
.as_str(),
);
}
- if !info.songs.is_empty() {
- let songs = info
- .songs
- .iter()
- .map(|x| x.name.clone() + "\n")
- .collect::();
- reply.push_str(format!("\nš¶ Song(s): {}", songs).as_str());
- }
- Some(message.reply_to(reply).await?)
+ Some(
+ message
+ .reply_to(add_track_section(info.tracks, reply))
+ .await?,
+ )
+ }
+ None => None,
+ }
+ }
+ Playlist(id) => {
+ log::debug!("Parsing spotify playlist: {}", id);
+ let playlist_info =
+ spotify::get_spotify_playlist(spotify_client, &id).await;
+ match playlist_info {
+ Some(info) => {
+ let reply = format!(
+ "Playlist information:\n\
+ āļø Playlist name: {}\n\
+ š§āš¤ {} artist(s): {}",
+ info.name,
+ info.artists.len(),
+ info.artists.join(", ")
+ );
+ Some(
+ message
+ .reply_to(add_track_section(info.tracks, reply))
+ .await?,
+ )
}
None => None,
}
@@ -78,3 +99,16 @@ async fn main() {
log::info!("Exiting...");
}
+
+fn add_track_section(tracks: Vec, reply: String) -> String {
+ if !tracks.is_empty() {
+ let songs = tracks
+ .iter()
+ .map(|x| x.name.clone() + "\n")
+ .collect::();
+ reply
+ .clone()
+ .push_str(format!("\nš¶ {} Track(s): {}", tracks.len(), songs).as_str())
+ }
+ reply
+}
diff --git a/src/spotify/mod.rs b/src/spotify/mod.rs
index cb54cb6..d77ef4c 100644
--- a/src/spotify/mod.rs
+++ b/src/spotify/mod.rs
@@ -1,10 +1,12 @@
use std::time::Duration;
-use aspotify::{Client, ClientCredentials};
+use aspotify::PlaylistItemType::{Episode, Track};
+use aspotify::{Client, ClientCredentials, TrackSimplified};
pub enum SpotifyKind {
Track(String),
Album(String),
+ Playlist(String),
}
fn get_id_in_url(url: &str) -> Option<&str> {
@@ -29,6 +31,13 @@ pub fn get_spotify_entry(url: &str) -> Option {
None => None,
};
}
+ if url.contains("https://open.spotify.com/playlist/") {
+ let playlist_id = get_id_in_url(url);
+ return match playlist_id {
+ Some(id) => Some(SpotifyKind::Playlist(id.to_string())),
+ None => None,
+ };
+ }
return None;
}
@@ -49,7 +58,13 @@ pub struct AlbumInfo {
pub(crate) name: String,
pub(crate) artists: Vec,
pub(crate) genres: Vec,
- pub(crate) songs: Vec,
+ pub(crate) tracks: Vec,
+}
+
+pub struct PlaylistInfo {
+ pub(crate) name: String,
+ pub(crate) artists: Vec,
+ pub(crate) tracks: Vec,
}
pub async fn get_spotify_track(spotify: Box, id: &String) -> Option {
@@ -69,7 +84,61 @@ pub async fn get_spotify_album(spotify: Box, id: &String) -> Option None,
+ }
+}
+
+fn extract_artists_from_tracks(tracks: Vec) -> Vec {
+ tracks
+ .iter()
+ .flat_map(|t| t.artists.iter().map(|a| a.name.clone()))
+ .collect()
+}
+
+pub async fn get_spotify_playlist(spotify: Box, id: &String) -> Option {
+ match spotify.playlists().get_playlist(id.as_str(), None).await {
+ Ok(playlist) => Some(PlaylistInfo {
+ name: playlist.data.name,
+ artists: playlist
+ .data
+ .tracks
+ .items
+ .iter()
+ .flat_map(|p| {
+ p.item.as_ref().map_or(Vec::new(), |x| match x {
+ Track(t) => extract_artists_from_tracks(vec![t.clone().simplify()]),
+ Episode(_e) => Vec::new(),
+ })
+ })
+ .collect(),
+ tracks: playlist
+ .data
+ .tracks
+ .items
+ .iter()
+ .flat_map(|p| {
+ p.item.as_ref().map_or(None, |x| match x {
+ Track(t) => Some(TrackInfo {
+ name: t.name.clone(),
+ artists: extract_artists_from_tracks(vec![t.clone().simplify()]),
+ duration: t.duration,
+ }),
+ Episode(_e) => None,
+ })
+ })
+ .collect(),
}),
Err(_e) => None,
}