134 lines
5.6 KiB
Rust
134 lines
5.6 KiB
Rust
use std::{collections::HashMap, ffi::OsStr, io::{BufReader, Cursor}, path::PathBuf, process::{Command, Stdio}, str::FromStr, sync::{Arc, Mutex, MutexGuard}};
|
|
|
|
use anyhow::anyhow;
|
|
use image::ImageReader;
|
|
use xmpd_manifest::song::{IconType, Song, SourceType};
|
|
|
|
use crate::{downloader::song::SongStatus, DlStatus};
|
|
|
|
lazy_static::lazy_static!(
|
|
static ref ICON_CACHE_DL: Arc<Mutex<IconCacheDl>> = Arc::default();
|
|
);
|
|
|
|
#[derive(Debug, Default, Clone)]
|
|
pub struct IconCacheDl {
|
|
pub jobs: HashMap<uuid::Uuid, DlStatus>,
|
|
pub current_jobs: usize,
|
|
}
|
|
|
|
impl IconCacheDl {
|
|
pub fn get() -> crate::Result<MutexGuard<'static, Self>> {
|
|
match ICON_CACHE_DL.lock() {
|
|
Ok(v) => Ok(v),
|
|
Err(e) => anyhow::bail!(format!("{e:?}"))
|
|
}
|
|
}
|
|
pub fn is_job_list_full(&self) -> bool {
|
|
self.current_jobs >= 5
|
|
}
|
|
|
|
pub fn download(&mut self, sid: uuid::Uuid, song: Song) -> crate::Result<()> {
|
|
match song.icon_type().clone() {
|
|
IconType::FromSource => {
|
|
let tooling = xmpd_settings::Settings::get()?.tooling.clone();
|
|
match song.source_type() {
|
|
SourceType::Youtube => {
|
|
self.jobs.insert(sid.clone(), DlStatus::Downloading);
|
|
let mut path = xmpd_cliargs::CLIARGS.cache_path();
|
|
path.push("icons");
|
|
path.push(sid.to_string());
|
|
|
|
let mut cmd = Command::new(tooling.ytdlp_path);
|
|
cmd.arg(song.url().to_string());
|
|
cmd.arg("-o");
|
|
cmd.arg(&path);
|
|
cmd.args(["--write-thumbnail", "--skip-download"]);
|
|
if xmpd_cliargs::CLIARGS.debug {
|
|
cmd.stdout(Stdio::piped());
|
|
cmd.stderr(Stdio::piped());
|
|
} else {
|
|
cmd.stdout(Stdio::null());
|
|
cmd.stderr(Stdio::null());
|
|
}
|
|
let child = cmd.spawn()?;
|
|
std::thread::spawn(move || {
|
|
if let Ok(output) = child.wait_with_output() {
|
|
for line in String::from_utf8(output.stdout).unwrap().lines() {
|
|
log::info!("CMD: {}", line);
|
|
}
|
|
for line in String::from_utf8(output.stderr).unwrap().lines() {
|
|
log::error!("CMD: {}", line);
|
|
}
|
|
}
|
|
let old_p = path.with_extension("webp"); // Default for yt-dlp
|
|
let new_p = path.with_extension("png"); // Default for all
|
|
let old_img = ImageReader::open(&old_p).unwrap().decode().unwrap();
|
|
old_img.save(&new_p).unwrap();
|
|
std::fs::remove_file(old_p).unwrap();
|
|
let mut cache = IconCacheDl::get().unwrap();
|
|
cache.jobs.insert(sid, DlStatus::Done(Some(new_p.into())));
|
|
});
|
|
}
|
|
SourceType::Spotify => {
|
|
todo!()
|
|
}
|
|
SourceType::Soundcloud => {
|
|
todo!()
|
|
}
|
|
_ => (),
|
|
}
|
|
}
|
|
IconType::CustomUrl(url) => self.download_custom_url_icon(&sid, &url)?,
|
|
IconType::None => ()
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub fn download_custom_url_icon(&mut self, sid: &uuid::Uuid, url: &url::Url) -> crate::Result<()> {
|
|
self.jobs.insert(sid.clone(), DlStatus::Downloading);
|
|
let url_p = PathBuf::from_str(url.path())?;
|
|
let Some(ext) = url_p.extension() else {
|
|
anyhow::bail!("Url without extension, cant continue");
|
|
};
|
|
let ext = ext.to_string_lossy().to_string();
|
|
let mut path = xmpd_cliargs::CLIARGS.cache_path();
|
|
path.push("icons");
|
|
path.push(sid.to_string());
|
|
path.set_extension(ext);
|
|
let sid = sid.clone();
|
|
let url = url.clone();
|
|
std::thread::spawn(move || {
|
|
match reqwest::blocking::get(url.clone()) {
|
|
Ok(v) => {
|
|
match v.bytes() {
|
|
Ok(bytes) => {
|
|
if let Err(e) = std::fs::write(path, bytes) {
|
|
if let Ok(mut cache) = IconCacheDl::get() {
|
|
if let Some(job) = cache.jobs.get_mut(&sid) {
|
|
*job = DlStatus::Error(file!(), line!() as usize, format!("{e:?}"));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Err(e) => {
|
|
if let Ok(mut cache) = IconCacheDl::get() {
|
|
if let Some(job) = cache.jobs.get_mut(&sid) {
|
|
*job = DlStatus::Error(file!(), line!() as usize, format!("{e:?}"));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Err(e) => {
|
|
if let Ok(mut cache) = IconCacheDl::get() {
|
|
if let Some(job) = cache.jobs.get_mut(&sid) {
|
|
*job = DlStatus::Error(file!(), line!() as usize, format!("{e:?}"));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
Ok(())
|
|
}
|
|
}
|