Update to use latest librespot from GithHub repo

This commit is contained in:
grufkork 2024-09-08 13:24:17 +02:00
parent f0a8720853
commit ec66b5ad91
6 changed files with 1370 additions and 708 deletions

1997
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -30,7 +30,7 @@ reqwest = "0"
colored = "2" colored = "2"
lame = "0" lame = "0"
aspotify = "0" aspotify = "0"
librespot = { git = "ssh://git@github.com/oSumAtrIX/free-librespot.git" } librespot = { git = "https://github.com/librespot-org/librespot" }
async-std = { version = "1", features = ["attributes", "tokio1"] } async-std = { version = "1", features = ["attributes", "tokio1"] }
serde_json = "1" serde_json = "1"
async-stream = "0" async-stream = "0"

View file

@ -1,3 +1,4 @@
use aspotify::Tracks;
use async_std::channel::{bounded, Receiver, Sender}; use async_std::channel::{bounded, Receiver, Sender};
use async_stream::try_stream; use async_stream::try_stream;
use chrono::NaiveDate; use chrono::NaiveDate;
@ -7,7 +8,8 @@ use librespot::audio::{AudioDecrypt, AudioFile};
use librespot::core::audio_key::AudioKey; use librespot::core::audio_key::AudioKey;
use librespot::core::session::Session; use librespot::core::session::Session;
use librespot::core::spotify_id::SpotifyId; use librespot::core::spotify_id::SpotifyId;
use librespot::metadata::{FileFormat, Metadata, Track}; use librespot::metadata::{Metadata, Track};
use librespot::protocol::metadata::audio_file::Format as FileFormat;
use sanitize_filename::sanitize; use sanitize_filename::sanitize;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Display; use std::fmt::Display;
@ -483,16 +485,20 @@ impl DownloaderInternal {
Ok(()) Ok(())
} }
async fn find_alternative(session: &Session, track: Track) -> Result<Track, SpotifyError> { async fn find_alternative(session: &Session, track: Track) -> Result<Track, SpotifyError> {
for alt in track.alternatives { let librespot::metadata::track::Tracks(ids) = track.alternatives;
let t = Track::get(session, alt).await?; for alt in ids {
if t.available { let t = Track::get(session, &alt).await.unwrap(); // TODO ?
return Ok(t); let librespot::metadata::availability::Availabilities(avalabilities) = t.availability;
} for a in avalabilities {
} // TODO: figure out if available
}
}
Err(SpotifyError::Unavailable)
}
Err(SpotifyError::Unavailable)
}
/// Download track by id /// Download track by id
async fn download_track( async fn download_track(
@ -504,12 +510,12 @@ impl DownloaderInternal {
job_id: i64, job_id: i64,
) -> Result<(PathBuf, AudioFormat), SpotifyError> { ) -> Result<(PathBuf, AudioFormat), SpotifyError> {
let id = SpotifyId::from_base62(id)?; let id = SpotifyId::from_base62(id)?;
let mut track = Track::get(session, id).await?; let mut track = Track::get(session, &id).await?;
// Fallback if unavailable // Fallback if unavailable
if !track.available { /*if !track.available {
track = DownloaderInternal::find_alternative(session, track).await?; track = DownloaderInternal::find_alternative(session, track).await?;
} }*/ //TODO
// Quality fallback // Quality fallback
let mut quality = config.quality; let mut quality = config.quality;
@ -554,8 +560,8 @@ impl DownloaderInternal {
let path_clone = path.clone(); let path_clone = path.clone();
let key = session.audio_key().request(track.id, *file_id).await?; let key = session.audio_key().request(track.id, *file_id).await?;
let encrypted = AudioFile::open(session, *file_id, 1024 * 1024, true).await?; let encrypted = AudioFile::open(session, *file_id, 1024 * 1024).await?;
let size = encrypted.get_stream_loader_controller().len(); let size = encrypted.get_stream_loader_controller()?.len();
// Download // Download
let s = match config.convert_to_mp3 { let s = match config.convert_to_mp3 {
true => { true => {
@ -604,7 +610,7 @@ impl DownloaderInternal {
) -> impl Stream<Item = Result<usize, SpotifyError>> { ) -> impl Stream<Item = Result<usize, SpotifyError>> {
try_stream! { try_stream! {
let mut file = File::create(path).await?; let mut file = File::create(path).await?;
let mut decrypted = AudioDecrypt::new(key, encrypted); let mut decrypted = AudioDecrypt::new(Some(key), encrypted);
// Skip (i guess encrypted shit) // Skip (i guess encrypted shit)
let mut skip: [u8; 0xa7] = [0; 0xa7]; let mut skip: [u8; 0xa7] = [0; 0xa7];
let mut decrypted = tokio::task::spawn_blocking(move || { let mut decrypted = tokio::task::spawn_blocking(move || {
@ -642,7 +648,7 @@ impl DownloaderInternal {
) -> impl Stream<Item = Result<usize, SpotifyError>> { ) -> impl Stream<Item = Result<usize, SpotifyError>> {
try_stream! { try_stream! {
let mut file = File::create(path).await?; let mut file = File::create(path).await?;
let mut decrypted = AudioDecrypt::new(key, encrypted); let mut decrypted = AudioDecrypt::new(Some(key), encrypted);
// Skip (i guess encrypted shit) // Skip (i guess encrypted shit)
let mut skip: [u8; 0xa7] = [0; 0xa7]; let mut skip: [u8; 0xa7] = [0; 0xa7];
let decrypted = tokio::task::spawn_blocking(move || { let decrypted = tokio::task::spawn_blocking(move || {
@ -711,12 +717,9 @@ impl From<FileFormat> for AudioFormat {
FileFormat::MP3_160 => Self::Mp3, FileFormat::MP3_160 => Self::Mp3,
FileFormat::MP3_96 => Self::Mp3, FileFormat::MP3_96 => Self::Mp3,
FileFormat::MP3_160_ENC => Self::Mp3, FileFormat::MP3_160_ENC => Self::Mp3,
FileFormat::MP4_128_DUAL => Self::Mp4, FileFormat::AAC_24 => Self::Aac,
FileFormat::OTHER3 => Self::Unknown, FileFormat::AAC_48 => Self::Aac,
FileFormat::AAC_160 => Self::Aac, FileFormat::FLAC_FLAC => Self::Unknown
FileFormat::AAC_320 => Self::Aac,
FileFormat::MP4_128 => Self::Mp4,
FileFormat::OTHER5 => Self::Unknown,
} }
} }
} }
@ -727,13 +730,13 @@ impl Quality {
match self { match self {
Self::Q320 => vec![ Self::Q320 => vec![
FileFormat::OGG_VORBIS_320, FileFormat::OGG_VORBIS_320,
FileFormat::AAC_320, FileFormat::AAC_48, // TODO
FileFormat::MP3_320, FileFormat::MP3_320,
], ],
Self::Q256 => vec![FileFormat::MP3_256], Self::Q256 => vec![FileFormat::MP3_256],
Self::Q160 => vec![ Self::Q160 => vec![
FileFormat::OGG_VORBIS_160, FileFormat::OGG_VORBIS_160,
FileFormat::AAC_160, FileFormat::AAC_24, // TODO
FileFormat::MP3_160, FileFormat::MP3_160,
], ],
Self::Q96 => vec![FileFormat::OGG_VORBIS_96, FileFormat::MP3_96], Self::Q96 => vec![FileFormat::OGG_VORBIS_96, FileFormat::MP3_96],

View file

@ -19,6 +19,8 @@ pub enum SpotifyError {
ID3Error(String, String), ID3Error(String, String),
Reqwest(String), Reqwest(String),
InvalidFormat, InvalidFormat,
NotConnected,
UnknownPacket(u8),
AlreadyDownloaded, AlreadyDownloaded,
} }
@ -43,6 +45,8 @@ impl fmt::Display for SpotifyError {
SpotifyError::ID3Error(k, e) => write!(f, "ID3 Error: {} {}", k, e), SpotifyError::ID3Error(k, e) => write!(f, "ID3 Error: {} {}", k, e),
SpotifyError::Reqwest(e) => write!(f, "Reqwest Error: {}", e), SpotifyError::Reqwest(e) => write!(f, "Reqwest Error: {}", e),
SpotifyError::InvalidFormat => write!(f, "Invalid Format!"), SpotifyError::InvalidFormat => write!(f, "Invalid Format!"),
SpotifyError::NotConnected => write!(f, "Not Connected"),
SpotifyError::UnknownPacket(e) => write!(f, "Unknown Packet: {}", e),
SpotifyError::AlreadyDownloaded => write!(f, "Already Downloaded"), SpotifyError::AlreadyDownloaded => write!(f, "Already Downloaded"),
} }
} }
@ -70,7 +74,9 @@ impl From<librespot::core::session::SessionError> for SpotifyError {
librespot::core::session::SessionError::IoError(e) => e.into(), librespot::core::session::SessionError::IoError(e) => e.into(),
librespot::core::session::SessionError::AuthenticationError(_) => { librespot::core::session::SessionError::AuthenticationError(_) => {
SpotifyError::AuthenticationError SpotifyError::AuthenticationError
} },
librespot::core::session::SessionError::NotConnected => SpotifyError::NotConnected,
librespot::core::session::SessionError::Packet(e) => SpotifyError::UnknownPacket(e)
} }
} }
} }

View file

@ -14,6 +14,7 @@ use async_std::task;
use colored::Colorize; use colored::Colorize;
use downloader::{DownloadState, Downloader}; use downloader::{DownloadState, Downloader};
use error::SpotifyError; use error::SpotifyError;
use librespot::core::spotify_id::SpotifyIdResult;
use settings::Settings; use settings::Settings;
use spotify::Spotify; use spotify::Spotify;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
@ -26,6 +27,12 @@ async fn main() {
start().await; start().await;
} }
impl From<librespot::core::error::Error> for SpotifyError {
fn from(e: librespot::core::error::Error) -> Self {
SpotifyError::Error(e.to_string())
}
}
#[cfg(windows)] #[cfg(windows)]
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {

View file

@ -12,6 +12,7 @@ use url::Url;
use crate::error::SpotifyError; use crate::error::SpotifyError;
pub struct Spotify { pub struct Spotify {
// librespotify sessopm // librespotify sessopm
pub session: Session, pub session: Session,
@ -34,13 +35,9 @@ impl Spotify {
Some(creds) => creds, Some(creds) => creds,
None => Credentials::with_password(username, password), None => Credentials::with_password(username, password),
}; };
let (session, _) = Session::connect(
SessionConfig::default(), let session = Session::new(SessionConfig::default(), Some(cache));
credentials, session.connect(credentials, true).await?;
Some(cache),
true,
)
.await?;
//aspotify //aspotify
let credentials = ClientCredentials { let credentials = ClientCredentials {