diff options
Diffstat (limited to 'import/src/lib.rs')
| -rw-r--r-- | import/src/lib.rs | 161 |
1 files changed, 99 insertions, 62 deletions
diff --git a/import/src/lib.rs b/import/src/lib.rs index af13316..e31127e 100644 --- a/import/src/lib.rs +++ b/import/src/lib.rs @@ -20,10 +20,10 @@ use crate::{tmdb::TmdbKind, trakt::TraktKind}; use acoustid::{acoustid_fingerprint, AcoustID}; use anyhow::{anyhow, bail, Context, Result}; use infojson::YVideo; -use jellycache::{cache, cache_memory, cache_store, CacheKey}; +use jellycache::{cache_memory, cache_read, cache_store, HashKey}; use jellycommon::{ - Appearance, Chapter, CreditCategory, IdentifierType, MediaInfo, Node, NodeID, NodeKind, - Picture, PictureSlot, RatingType, SourceTrack, SourceTrackKind, TrackSource, Visibility, + Appearance, Asset, Chapter, CreditCategory, IdentifierType, MediaInfo, Node, NodeID, NodeKind, + PictureSlot, RatingType, SourceTrack, SourceTrackKind, TrackSource, Visibility, }; use jellyimport_fallback_generator::generate_fallback; use jellyremuxer::{ @@ -261,27 +261,31 @@ fn import_file( match filename.as_ref() { "poster.jpeg" | "poster.webp" | "poster.png" => { info!("import poster at {path:?}"); - let key = CacheKey::new_image(path); - cache(key, || { - let mut data = Vec::new(); - File::open(path)?.read_to_end(&mut data)?; - Ok(data) - })?; + let asset = Asset(cache_store( + format!("media/literal/{}-poster.image", HashKey(path)), + || { + let mut data = Vec::new(); + File::open(path)?.read_to_end(&mut data)?; + Ok(data) + }, + )?); db.update_node_init(parent, |node| { - node.pictures.insert(PictureSlot::Cover, Picture(key.0)); + node.pictures.insert(PictureSlot::Cover, asset); Ok(()) })?; } "backdrop.jpeg" | "backdrop.webp" | "backdrop.png" => { info!("import backdrop at {path:?}"); - let key = CacheKey::new_image(path); - cache(key, || { - let mut data = Vec::new(); - File::open(path)?.read_to_end(&mut data)?; - Ok(data) - })?; + let asset = Asset(cache_store( + format!("media/literal/{}-poster.image", HashKey(path)), + || { + let mut data = Vec::new(); + File::open(path)?.read_to_end(&mut data)?; + Ok(data) + }, + )?); db.update_node_init(parent, |node| { - node.pictures.insert(PictureSlot::Backdrop, Picture(key.0)); + node.pictures.insert(PictureSlot::Backdrop, asset); Ok(()) })?; } @@ -356,25 +360,63 @@ fn import_file( } pub fn read_media_metadata(path: &Path) -> Result<Arc<matroska::Segment>> { - cache_memory(CacheKey::new_json(path), move || { - let media = File::open(path)?; - let mut media = - create_demuxer_autodetect(Box::new(media))?.ok_or(anyhow!("media format unknown"))?; + cache_memory( + &format!("media/metadata/{}.json", HashKey(path)), + move || { + let media = File::open(path)?; + let mut media = create_demuxer_autodetect(Box::new(media))? + .ok_or(anyhow!("media format unknown"))?; - let info = media.info()?; - let tracks = media.tracks()?; - let tags = media.tags()?; - let attachments = media.attachments()?; - let chapters = media.chapters()?; - Ok(Segment { - info, - tracks, - tags: tags.into_iter().collect(), - attachments, - chapters, - ..Default::default() - }) - }) + let info = media.info()?; + let tracks = media.tracks()?; + let tags = media.tags()?; + let mut attachments = media.attachments()?; + let chapters = media.chapters()?; + + // Replace data of useful attachments with cache key; delete data of all others + if let Some(attachments) = &mut attachments { + for att in &mut attachments.files { + if let Some(fname) = attachment_types::is_useful_attachment(&att) { + let key = cache_store( + format!("media/attachment/{}-{fname}", HashKey(path)), + || Ok(att.data.clone()), + )?; + att.data = key.as_bytes().to_vec(); + } else { + att.data.clear(); + } + } + } + + Ok(Segment { + info, + tracks, + tags: tags.into_iter().collect(), + attachments, + chapters, + ..Default::default() + }) + }, + ) +} + +mod attachment_types { + use jellyremuxer::matroska::AttachedFile; + + pub fn is_useful_attachment(a: &AttachedFile) -> Option<&'static str> { + match a { + _ if is_info_json(&a) => Some("info.json"), + _ if is_cover(&a) => Some("cover.image"), + _ => None, + } + } + + pub fn is_info_json(a: &&AttachedFile) -> bool { + a.name == "info.json" && a.media_type == "application/json" + } + pub fn is_cover(a: &&AttachedFile) -> bool { + a.name.starts_with("cover") && a.media_type.starts_with("image/") + } } fn import_media_file( @@ -392,8 +434,12 @@ fn import_media_file( .attachments .iter() .flat_map(|a| &a.files) - .find(|a| a.name == "info.json" && a.media_type == "application/json") - .map(|d| serde_json::from_slice::<infojson::YVideo>(&d.data)) + .find(attachment_types::is_info_json) + .map(|att| { + let data = cache_read(str::from_utf8(&att.data).unwrap())? + .ok_or(anyhow!("info json cache missing"))?; + anyhow::Ok(serde_json::from_slice::<infojson::YVideo>(&data)?) + }) .transpose() .context("infojson parsing")?; @@ -401,13 +447,8 @@ fn import_media_file( .attachments .iter() .flat_map(|a| &a.files) - .find(|a| a.name.starts_with("cover") && a.media_type.starts_with("image/")) - .map(|att| { - cache_store(CacheKey::new_image(("cover", path)), || { - Ok(att.data.clone()) - }) - }) - .transpose()?; + .find(attachment_types::is_cover) + .map(|att| Asset(att.data.clone().try_into().unwrap())); let mut tags = m .tags @@ -519,7 +560,7 @@ fn import_media_file( node.identifiers.extend(eids); if let Some(cover) = cover { - node.pictures.insert(PictureSlot::Cover, Picture(cover.0)); + node.pictures.insert(PictureSlot::Cover, cover); } if let Some(ct) = tags.get("CONTENT_TYPE") { @@ -676,7 +717,7 @@ fn import_media_file( let tmdb_details = tmdb.episode_details(tmdb_id, season, episode, rthandle)?; if let Some(still) = &tmdb_details.still_path { - poster = Some(Picture(tmdb.image(still, rthandle)?.0)) + poster = Some(tmdb.image(still, rthandle)?) } } } @@ -816,10 +857,10 @@ fn apply_musicbrainz_recording( if let Some(filename) = apis.wikidata.query_image_path(id.to_owned(), rthandle)? { - let path = apis - .wikimedia_commons - .image_by_filename(filename, rthandle)?; - image_1 = Some(Picture(path.0)); + image_1 = Some( + apis.wikimedia_commons + .image_by_filename(filename, rthandle)?, + ); } } } @@ -828,7 +869,7 @@ fn apply_musicbrainz_recording( if let Some(id) = url.strip_prefix("https://vgmdb.net/artist/") { let id = id.parse::<u64>().context("parse vgmdb id")?; if let Some(path) = apis.vgmdb.get_artist_image(id, rthandle)? { - image_2 = Some(Picture(path.0)); + image_2 = Some(path); } } } @@ -841,14 +882,12 @@ fn apply_musicbrainz_recording( } jobs.extend(rel.attributes.clone()); - let headshot = match image_1.or(image_2) { + let _headshot = match image_1.or(image_2) { Some(x) => x, - None => Picture( - cache_store(CacheKey::new_image(("fallback", &artist.sort_name)), || { - generate_fallback(&artist.sort_name) - })? - .0, - ), + None => Asset(cache_store( + format!("fallback/{}.image", HashKey(&artist.sort_name)), + || generate_fallback(&artist.sort_name), + )?), }; node.credits.entry(group).or_default().push(Appearance { @@ -913,12 +952,10 @@ fn apply_trakt_tmdb( tmdb_data = Some(data.clone()); if let Some(path) = &data.backdrop_path { - let im = tmdb.image(path, rthandle).context("tmdb backdrop image")?; - backdrop = Some(Picture(im.0)); + backdrop = Some(tmdb.image(path, rthandle).context("tmdb backdrop image")?); } if let Some(path) = &data.poster_path { - let im = tmdb.image(path, rthandle).context("tmdb poster image")?; - poster = Some(Picture(im.0)); + poster = Some(tmdb.image(path, rthandle).context("tmdb poster image")?); } // for p in people_map.values_mut().flatten() { |