aboutsummaryrefslogtreecommitdiff
path: root/import/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'import/src/lib.rs')
-rw-r--r--import/src/lib.rs161
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() {