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.rs149
1 files changed, 80 insertions, 69 deletions
diff --git a/import/src/lib.rs b/import/src/lib.rs
index 1a1d5ad..d12913f 100644
--- a/import/src/lib.rs
+++ b/import/src/lib.rs
@@ -15,16 +15,16 @@ pub mod wikidata;
pub mod wikimedia_commons;
use jellydb::Database;
-pub use jellyimport_asset_token as asset_token;
-use jellyimport_asset_token::AssetInner;
+use crate::{tmdb::TmdbKind, trakt::TraktKind};
use acoustid::{acoustid_fingerprint, AcoustID};
use anyhow::{anyhow, bail, Context, Result};
use infojson::YVideo;
use jellycache::{cache_file, cache_memory};
use jellycommon::{
- Appearance, Chapter, LocalTrack, MediaInfo, Node, NodeID, NodeKind, ObjectIds, PeopleGroup,
- Person, RatingType, SourceTrack, SourceTrackKind, TmdbKind, TrackSource, TraktKind, Visibility,
+ Appearance, Asset, Chapter, CreditCategory, IdentifierType, LocalTrack, MediaInfo, Node,
+ NodeID, NodeKind, PictureSlot, RatingType, SourceTrack, SourceTrackKind, TrackSource,
+ Visibility,
};
use jellyimport_fallback_generator::generate_fallback;
use jellyremuxer::{
@@ -39,7 +39,7 @@ use serde::{Deserialize, Serialize};
use std::{
collections::{BTreeMap, HashMap},
fs::{read_to_string, File},
- io::{BufReader, Write},
+ io::{self, BufReader, Write},
path::{Path, PathBuf},
sync::{Arc, LazyLock, Mutex},
time::UNIX_EPOCH,
@@ -262,15 +262,23 @@ fn import_file(
match filename.as_ref() {
"poster.jpeg" | "poster.webp" | "poster.png" => {
info!("import poster at {path:?}");
+ let path = cache_file("picture-file", path, |mut f| {
+ io::copy(&mut File::open(path)?, &mut f)?;
+ Ok(())
+ })?;
db.update_node_init(parent, |node| {
- node.poster = Some(AssetInner::Media(path.to_owned()).ser());
+ node.pictures.insert(PictureSlot::Poster, Asset(path.0));
Ok(())
})?;
}
"backdrop.jpeg" | "backdrop.webp" | "backdrop.png" => {
info!("import backdrop at {path:?}");
+ let path = cache_file("picture-file", path, |mut f| {
+ io::copy(&mut File::open(path)?, &mut f)?;
+ Ok(())
+ })?;
db.update_node_init(parent, |node| {
- node.backdrop = Some(AssetInner::Media(path.to_owned()).ser());
+ node.pictures.insert(PictureSlot::Backdrop, Asset(path.0));
Ok(())
})?;
}
@@ -291,7 +299,6 @@ fn import_file(
merge_option(&mut node.description, data.description);
merge_option(&mut node.index, data.index);
merge_option(&mut node.release_date, data.release_date);
- node.identifiers.extend(data.identifiers);
Ok(())
})?;
@@ -323,11 +330,11 @@ fn import_file(
node.kind = NodeKind::Channel;
node.title = Some(clean_uploader_name(&data.title).to_owned());
if let Some(cid) = data.channel_id {
- node.identifiers.insert("youtube.channel".to_string(), cid);
+ node.identifiers.insert(IdentifierType::YoutubeChannel, cid);
}
if let Some(uid) = data.uploader_id {
node.identifiers
- .insert("youtube.channelname".to_string(), uid);
+ .insert(IdentifierType::YoutubeChannelHandle, uid);
}
if let Some(desc) = data.description {
node.description = Some(desc);
@@ -455,27 +462,27 @@ fn import_media_file(
let node = NodeID::from_slug(&slug);
let meta = path.metadata()?;
- let mut eids = BTreeMap::new();
+ let mut eids = BTreeMap::<IdentifierType, String>::new();
for (key, value) in &tags {
match key.as_str() {
"MUSICBRAINZ_TRACKID" => {
- eids.insert("musicbrainz.recording".to_string(), value.to_owned())
+ eids.insert(IdentifierType::MusicbrainzRecording, value.to_owned())
}
"MUSICBRAINZ_ARTISTID" => {
- eids.insert("musicbrainz.artist".to_string(), value.to_owned())
+ eids.insert(IdentifierType::MusicbrainzArtist, value.to_owned())
}
"MUSICBRAINZ_ALBUMID" => {
- eids.insert("musicbrainz.release".to_string(), value.to_owned())
+ eids.insert(IdentifierType::MusicbrainzRelease, value.to_owned())
}
"MUSICBRAINZ_ALBUMARTISTID" => {
- eids.insert("musicbrainz.albumartist".to_string(), value.to_owned())
+ None //? ignore this?
}
"MUSICBRAINZ_RELEASEGROUPID" => {
- eids.insert("musicbrainz.releasegroup".to_string(), value.to_owned())
+ eids.insert(IdentifierType::MusicbrainzReleaseGroup, value.to_owned())
}
- "ISRC" => eids.insert("isrc".to_string(), value.to_owned()),
- "BARCODE" => eids.insert("barcode".to_string(), value.to_owned()),
+ "ISRC" => eids.insert(IdentifierType::Isrc, value.to_owned()),
+ "BARCODE" => eids.insert(IdentifierType::Barcode, value.to_owned()),
_ => None,
};
}
@@ -488,20 +495,18 @@ fn import_media_file(
.ok_or(anyhow!("need acoustid"))?
.get_atid_mbid(&fp),
)? {
- eids.insert("acoustid.track".to_string(), atid);
- eids.insert("musicbrainz.recording".to_string(), mbid);
+ eids.insert(IdentifierType::AcoustIdTrack, atid);
+ eids.insert(IdentifierType::MusicbrainzRecording, mbid);
};
}
- let mbrec = eids.get("musicbrainz.recording").cloned();
+ let mbrec = eids.get(&IdentifierType::MusicbrainzRecording).cloned();
db.update_node_init(node, |node| {
node.slug = slug;
node.title = m.info.title.clone().or(node.title.clone());
node.visibility = iflags.visibility;
- node.poster = cover
- .map(|a| AssetInner::Cache(a).ser())
- .or(node.poster.clone());
+
node.description = tags
.remove("DESCRIPTION")
.or(tags.remove("SYNOPSIS"))
@@ -511,6 +516,10 @@ fn import_media_file(
node.identifiers.extend(eids);
+ if let Some(cover) = cover {
+ node.pictures.insert(PictureSlot::Cover, Asset(cover.0));
+ }
+
if let Some(ct) = tags.get("CONTENT_TYPE") {
node.kind = match ct.to_lowercase().trim() {
"movie" | "documentary" | "film" => NodeKind::Movie,
@@ -545,13 +554,7 @@ fn import_media_file(
} else {
SourceTrackKind::Subtitle
},
- source: TrackSource::Local(
- AssetInner::LocalTrack(LocalTrack {
- path: path.to_owned(),
- track: track.track_number as usize,
- })
- .ser(),
- ),
+ source: TrackSource::Local(path.to_owned(), track.track_number),
})
.collect::<Vec<_>>();
@@ -593,7 +596,7 @@ fn import_media_file(
match infojson.extractor.as_str() {
"youtube" => {
node.identifiers
- .insert("youtube.video".to_string(), infojson.id);
+ .insert(IdentifierType::YoutubeVideo, infojson.id);
node.ratings.insert(
RatingType::YoutubeViews,
infojson.view_count.unwrap_or_default() as f64,
@@ -602,7 +605,10 @@ fn import_media_file(
node.ratings.insert(RatingType::YoutubeLikes, lc as f64);
}
}
- "Bandcamp" => drop(node.identifiers.insert("bandcamp".to_string(), infojson.id)),
+ "Bandcamp" => drop(
+ node.identifiers
+ .insert(IdentifierType::Bandcamp, infojson.id),
+ ),
_ => (),
}
}
@@ -669,8 +675,7 @@ fn import_media_file(
let tmdb_details =
rthandle.block_on(tmdb.episode_details(tmdb_id, season, episode))?;
if let Some(still) = &tmdb_details.still_path {
- poster =
- Some(AssetInner::Cache(rthandle.block_on(tmdb.image(still))?).ser())
+ poster = Some(Asset(rthandle.block_on(tmdb.image(still))?.0))
}
}
}
@@ -679,7 +684,9 @@ fn import_media_file(
node.kind = NodeKind::Episode;
node.index = Some(episode.number);
node.title = Some(episode.title.clone());
- node.poster = poster.or(node.poster.clone());
+ if let Some(poster) = poster {
+ node.pictures.insert(PictureSlot::Poster, poster);
+ }
node.description = episode.overview.clone().or(node.description.clone());
node.ratings.insert(RatingType::Trakt, episode.rating);
Ok(())
@@ -766,11 +773,11 @@ fn apply_musicbrainz_recording(
db.update_node_init(node, |node| {
node.title = Some(rec.title.clone());
node.identifiers
- .insert("musicbrainz.recording".to_string(), rec.id.to_string());
+ .insert(IdentifierType::MusicbrainzRecording, rec.id.to_string());
if let Some(a) = rec.artist_credit.first() {
node.subtitle = Some(a.artist.name.clone());
node.identifiers
- .insert("musicbrainz.artist".to_string(), a.artist.id.to_string());
+ .insert(IdentifierType::MusicbrainzArtist, a.artist.id.to_string());
}
// // TODO proper dedup
@@ -779,12 +786,14 @@ fn apply_musicbrainz_recording(
for rel in &rec.relations {
use musicbrainz::reltypes::*;
let a = match rel.type_id.as_str() {
- INSTRUMENT => Some(("", PeopleGroup::Instrument)),
- VOCAL => Some(("", PeopleGroup::Vocal)),
- PRODUCER => Some(("", PeopleGroup::Producer)),
- MIX => Some(("mix ", PeopleGroup::Engineer)),
- PHONOGRAPHIC_COPYRIGHT => Some(("phonographic copyright ", PeopleGroup::Engineer)),
- PROGRAMMING => Some(("programming ", PeopleGroup::Engineer)),
+ INSTRUMENT => Some(("", CreditCategory::Instrument)),
+ VOCAL => Some(("", CreditCategory::Vocal)),
+ PRODUCER => Some(("", CreditCategory::Producer)),
+ MIX => Some(("mix ", CreditCategory::Engineer)),
+ PHONOGRAPHIC_COPYRIGHT => {
+ Some(("phonographic copyright ", CreditCategory::Engineer))
+ }
+ PROGRAMMING => Some(("programming ", CreditCategory::Engineer)),
_ => None,
};
@@ -808,7 +817,7 @@ fn apply_musicbrainz_recording(
let path = rthandle.block_on(
apis.wikimedia_commons.image_by_filename(filename),
)?;
- image_1 = Some(AssetInner::Cache(path).ser());
+ image_1 = Some(Asset(path.0));
}
}
}
@@ -819,7 +828,7 @@ fn apply_musicbrainz_recording(
if let Some(path) =
rthandle.block_on(apis.vgmdb.get_artist_image(id))?
{
- image_2 = Some(AssetInner::Cache(path).ser());
+ image_2 = Some(Asset(path.0));
}
}
}
@@ -834,27 +843,26 @@ fn apply_musicbrainz_recording(
let headshot = match image_1.or(image_2) {
Some(x) => x,
- None => AssetInner::Cache(cache_file(
- "person-headshot-fallback",
- &artist.sort_name,
- |mut file| {
+ None => Asset(
+ cache_file("person-headshot-fallback", &artist.sort_name, |mut file| {
generate_fallback(&artist.sort_name, &mut file)?;
Ok(())
- },
- )?)
- .ser(),
+ })?
+ .0,
+ ),
};
node.credits.entry(group).or_default().push(Appearance {
jobs,
characters: vec![],
+ node: NodeID([0; 32]), // TODO
});
}
}
for isrc in &rec.isrcs {
node.identifiers
- .insert("isrc".to_string(), isrc.to_string());
+ .insert(IdentifierType::Isrc, isrc.to_string());
}
Ok(())
})?;
@@ -878,9 +886,12 @@ fn apply_trakt_tmdb(
.block_on(trakt.people(trakt_kind, trakt_id))
.context("trakt people lookup")?;
- let mut people_map = BTreeMap::<PeopleGroup, Vec<Appearance>>::new();
+ let mut people_map = BTreeMap::<CreditCategory, Vec<Appearance>>::new();
for p in people.cast.iter() {
- people_map.entry(PeopleGroup::Cast).or_default().push(p.a())
+ people_map
+ .entry(CreditCategory::Cast)
+ .or_default()
+ .push(p.a())
}
for (group, people) in people.crew.iter() {
for p in people {
@@ -908,24 +919,24 @@ fn apply_trakt_tmdb(
let im = rthandle
.block_on(tmdb.image(path))
.context("tmdb backdrop image")?;
- backdrop = Some(AssetInner::Cache(im).ser());
+ backdrop = Some(Asset(im.0));
}
if let Some(path) = &data.poster_path {
let im = rthandle
.block_on(tmdb.image(path))
.context("tmdb poster image")?;
- poster = Some(AssetInner::Cache(im).ser());
+ poster = Some(Asset(im.0));
}
- for p in people_map.values_mut().flatten() {
- if let Some(id) = p.person.ids.tmdb {
- let k = rthandle.block_on(tmdb.person_image(id))?;
- if let Some(prof) = k.profiles.first() {
- let im = rthandle.block_on(tmdb.image(&prof.file_path))?;
- p.person.headshot = Some(AssetInner::Cache(im).ser());
- }
- }
- }
+ // for p in people_map.values_mut().flatten() {
+ // if let Some(id) = p.person.ids.tmdb {
+ // let k = rthandle.block_on(tmdb.person_image(id))?;
+ // if let Some(prof) = k.profiles.first() {
+ // let im = rthandle.block_on(tmdb.image(&prof.file_path))?;
+ // p.person.headshot = Some(AssetInner::Cache(im).ser());
+ // }
+ // }
+ // }
}
db.update_node_init(node, |node| {
@@ -949,10 +960,10 @@ fn apply_trakt_tmdb(
node.ratings.insert(RatingType::Trakt, *rating);
}
if let Some(poster) = poster {
- node.poster = Some(poster);
+ node.pictures.insert(PictureSlot::Poster, poster);
}
if let Some(backdrop) = backdrop {
- node.backdrop = Some(backdrop);
+ node.pictures.insert(PictureSlot::Backdrop, backdrop);
}
if let Some(data) = tmdb_data {
node.title = data.title.clone().or(node.title.clone());