modified: Cargo.lock

modified:   Cargo.toml
	modified:   src/db.rs
	modified:   src/main_screen.rs
	modified:   src/sync.rs
This commit is contained in:
Michael Wain 2025-02-12 06:16:37 +03:00
parent a72a7b8a25
commit b34032d228
5 changed files with 134 additions and 51 deletions

12
Cargo.lock generated
View File

@ -433,7 +433,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
"windows-sys 0.59.0",
"windows-sys 0.52.0",
]
[[package]]
@ -1021,8 +1021,8 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "itunesdb"
version = "0.1.1"
source = "git+https://gitea.awain.net/alterwain/ITunesDB.git#5a6ca7a9f5eca42959e3498a6eb2700f502b5509"
version = "0.1.2"
source = "git+https://gitea.awain.net/alterwain/ITunesDB.git#2db99df934c29f03b842a43245f1e93d7d4ade27"
dependencies = [
"bincode",
"env_logger",
@ -1662,7 +1662,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.59.0",
"windows-sys 0.52.0",
]
[[package]]
@ -2029,7 +2029,7 @@ dependencies = [
"getrandom 0.3.1",
"once_cell",
"rustix",
"windows-sys 0.59.0",
"windows-sys 0.52.0",
]
[[package]]
@ -2532,7 +2532,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys 0.59.0",
"windows-sys 0.52.0",
]
[[package]]

View File

@ -23,7 +23,7 @@ tokio = { version = "1", features = ["full"] }
tokio-util = { version = "0.7.12", features = ["codec"] }
strum = { version = "0.27", features = ["derive"] }
soundcloud = { version = "0.1.4", git = "https://gitea.awain.net/alterwain/soundcloud_api.git" }
itunesdb = { version = "0.1.1", git = "https://gitea.awain.net/alterwain/ITunesDB.git" }
itunesdb = { version = "0.1.2", git = "https://gitea.awain.net/alterwain/ITunesDB.git" }
ureq = "3.0.5"
color-thief = "0.2"
redb = "2.4.0"

View File

@ -1,5 +1,6 @@
use std::fs::File;
use itunesdb::xobjects::{XArgument, XTrackItem};
use md5::{Digest, Md5};
use redb::{Database, Error, ReadableTable, TableDefinition};
use serde::{Deserialize, Serialize};
@ -66,6 +67,37 @@ impl From<CloudTrack> for Track {
}
}
fn find_str_arg(value: &XTrackItem, arg_type: u32) -> Option<&XArgument> {
value.args.iter().find(|arg| arg.arg_type == arg_type)
}
impl From<XTrackItem> for Track {
fn from(value: XTrackItem) -> Self {
Track {
unique_id: value.data.unique_id,
filetype: value.data.filetype,
stars: value.data.stars,
last_modified_time: value.data.last_modified_time,
size: value.data.size,
length: value.data.length,
year: value.data.year,
bitrate: value.data.bitrate,
sample_rate: value.data.sample_rate,
play_count: value.data.play_count,
dbid: value.data.dbid,
bpm: value.data.bpm,
skip_count: value.data.skip_count,
has_artwork: value.data.has_artwork,
media_type: value.data.media_type,
title: find_str_arg(&value, 1).map_or(String::new(), |a| a.val.clone()),
location: find_str_arg(&value, 2).map_or(String::new(), |a| a.val.clone()),
album: find_str_arg(&value, 3).map_or(String::new(), |a| a.val.clone()),
artist: find_str_arg(&value, 4).map_or(String::new(), |a| a.val.clone()),
genre: find_str_arg(&value, 5).map_or(String::new(), |a| a.val.clone()),
}
}
}
// TODO: implement From (or Into) for Track, convert from Soundcloud Audio or iTunes
pub fn init_db() -> Database {

View File

@ -263,6 +263,32 @@ impl MainScreen {
}
v
}
2 => {
// local
/* let mut v = Vec::new();
v.push(
Row::new(vec!["Id", "Title", "Artist", "Bitrate", "Hash"])
.style(Style::default().fg(Color::Gray)),
);
if let Some(s) = &self.soundcloud {
for (i, playlist) in s.iter().enumerate() {
let date: DateTime<Utc> = playlist.created_at.parse().unwrap();
let mut row = Row::new(vec![
playlist.id.to_string(),
playlist.title.clone(),
[playlist.track_count.to_string(), " songs".to_string()].concat(),
format!("{}", date.format("%Y-%m-%d %H:%M")),
"NO".to_string(),
]);
if self.selected_row == i as i32 {
row = row.style(Style::default().bg(Color::Yellow));
}
v.push(row);
}
}
v*/
Vec::new()
}
_ => Vec::new(),
};

View File

@ -1,6 +1,7 @@
use std::path::{Path, PathBuf};
use itunesdb::xobjects::XDatabase;
use itunesdb::xobjects::{XDatabase, XSomeList};
use redb::Database;
use soundcloud::sobjects::{CloudPlaylist, CloudPlaylists};
use tokio::{
fs::File,
@ -55,49 +56,8 @@ pub fn initialize_async_service(
}*/
let _ = sender.send(AppEvent::IPodFound("/Users/michael/Documents/ipod/iTunes/iTunesDB".to_string())).await;
},
AppEvent::ParseItunes(path) => {
// todo: parse itunes
let cd = get_temp_itunesdb();
let p: PathBuf = Path::new(&path).into();
// p.push("iPod_Control");
// p.push("iTunes");
// p.set_file_name("iTunesDB");
let _ = std::fs::copy(p, &cd);
let mut file = File::open(cd).await.unwrap();
let mut contents = vec![];
file.read_to_end(&mut contents).await.unwrap();
let xdb = itunesdb::deserializer::parse_bytes(&contents);
let _ = sender.send(AppEvent::ITunesParsed(xdb)).await;
let p = get_config_path();
if !p.exists() {
let config = LyricaConfiguration::default();
let cfg_str = toml::to_string_pretty(&config).unwrap();
let mut file = File::create(&p).await.unwrap();
file.write(cfg_str.as_bytes()).await;
}
let mut file = File::open(p).await.unwrap();
let mut content = String::new();
file.read_to_string(&mut content).await.unwrap();
let config: LyricaConfiguration = toml::from_str(&content).unwrap();
let app_version = soundcloud::get_app().await.unwrap().unwrap();
let client_id = soundcloud::get_client_id().await.unwrap().unwrap();
let playlists = soundcloud::get_playlists(config.get_soundcloud().user_id, client_id, app_version).await.unwrap();
let _ = sender.send(AppEvent::SoundcloudGot(playlists)).await;
},
AppEvent::DownloadPlaylist(playlist) => {
if let Ok(()) = dlp::download_from_soundcloud(&playlist.permalink_url, &get_temp_dl_dir(), sender.clone()).await {
let tracks = playlist.tracks;
for track in tracks {
if track.title.is_none() { continue; }
let mut t: Track = track.into();
t.unique_id = db::get_last_track_id(&database).unwrap_or(80) + 1;
let _ = db::insert_track(&database, t);
}
}
},
AppEvent::ParseItunes(path) => parse_itunes(&database, &sender, path).await,
AppEvent::DownloadPlaylist(playlist) => download_playlist(playlist, &database, &sender).await,
_ => {}
}
}
@ -106,3 +66,68 @@ pub fn initialize_async_service(
}
});
}
async fn download_playlist(
playlist: CloudPlaylist,
database: &Database,
sender: &Sender<AppEvent>,
) {
if let Ok(()) =
dlp::download_from_soundcloud(&playlist.permalink_url, &get_temp_dl_dir(), sender.clone())
.await
{
let tracks = playlist.tracks;
for track in tracks {
if track.title.is_none() {
continue;
}
let mut t: Track = track.into();
t.unique_id = db::get_last_track_id(database).unwrap_or(80) + 1;
let _ = db::insert_track(database, t);
}
}
}
async fn parse_itunes(database: &Database, sender: &Sender<AppEvent>, path: String) {
// todo: parse itunes
let cd = get_temp_itunesdb();
let p: PathBuf = Path::new(&path).into();
// p.push("iPod_Control");
// p.push("iTunes");
// p.set_file_name("iTunesDB");
let _ = std::fs::copy(p, &cd);
let mut file = File::open(cd).await.unwrap();
let mut contents = vec![];
file.read_to_end(&mut contents).await.unwrap();
let mut xdb = itunesdb::deserializer::parse_bytes(&contents);
if let XSomeList::TrackList(tracks) = &xdb.find_dataset(1).child {
for track in tracks {
let t: Track = track.clone().into();
let _ = db::insert_track(database, t);
}
}
let _ = sender.send(AppEvent::ITunesParsed(xdb)).await;
let p = get_config_path();
if !p.exists() {
let config = LyricaConfiguration::default();
let cfg_str = toml::to_string_pretty(&config).unwrap();
let mut file = File::create(&p).await.unwrap();
file.write(cfg_str.as_bytes()).await;
}
let mut file = File::open(p).await.unwrap();
let mut content = String::new();
file.read_to_string(&mut content).await.unwrap();
let config: LyricaConfiguration = toml::from_str(&content).unwrap();
let app_version = soundcloud::get_app().await.unwrap().unwrap();
let client_id = soundcloud::get_client_id().await.unwrap().unwrap();
let playlists =
soundcloud::get_playlists(config.get_soundcloud().user_id, client_id, app_version)
.await
.unwrap();
let _ = sender.send(AppEvent::SoundcloudGot(playlists)).await;
}