diff options
Diffstat (limited to 'import/src/lib.rs')
-rw-r--r-- | import/src/lib.rs | 110 |
1 files changed, 69 insertions, 41 deletions
diff --git a/import/src/lib.rs b/import/src/lib.rs index d6eb54f..8347833 100644 --- a/import/src/lib.rs +++ b/import/src/lib.rs @@ -11,17 +11,17 @@ pub mod trakt; use crate::tmdb::TmdbKind; use anyhow::{anyhow, bail, Context, Ok}; use async_recursion::async_recursion; -use futures::{executor::block_on, stream::FuturesUnordered, StreamExt}; +use futures::{stream::FuturesUnordered, StreamExt}; use jellybase::{ cache::{async_cache_file, cache_memory}, - database::{DataAcid, ReadableTable, Ser, T_NODE, T_NODE_IMPORT}, + database::{DataAcid, ReadableTable, Ser, T_NODE, T_NODE_EXTENDED, T_NODE_IMPORT}, federation::Federation, AssetLocationExt, CONF, SECRETS, }; use jellyclient::Session; use jellycommon::{ - AssetLocation, AssetRole, ImportOptions, ImportSource, MediaInfo, Node, NodeKind, NodePrivate, - NodePublic, Rating, TrackSource, + AssetLocation, AssetRole, ExtendedNode, ImportOptions, ImportSource, MediaInfo, Node, NodeKind, + NodePrivate, NodePublic, PeopleGroup, Rating, TrackSource, }; use jellymatroska::read::EbmlReader; use jellyremuxer::import::import_metadata; @@ -38,7 +38,7 @@ use std::{ path::{Path, PathBuf}, sync::{Arc, LazyLock}, }; -use tmdb::{parse_release_date, tmdb_image}; +use tmdb::{parse_release_date, Tmdb}; use tokio::{io::AsyncWriteExt, sync::Semaphore, task::spawn_blocking}; use trakt::Trakt; @@ -46,6 +46,7 @@ static IMPORT_SEM: LazyLock<Semaphore> = LazyLock::new(|| Semaphore::new(1)); struct Apis { trakt: Option<Trakt>, + tmdb: Option<Tmdb>, } pub async fn import(db: &DataAcid, fed: &Federation) -> anyhow::Result<()> { @@ -64,6 +65,7 @@ pub async fn import(db: &DataAcid, fed: &Federation) -> anyhow::Result<()> { let ap = Apis { trakt: SECRETS.api.trakt.as_ref().map(|key| Trakt::new(key)), + tmdb: SECRETS.api.tmdb.as_ref().map(|key| Tmdb::new(key)), }; info!("loading sources..."); @@ -251,28 +253,72 @@ async fn process_source( txn.commit()?; Ok(()) }; + let insert_node_ext = move |id: &str, n: ExtendedNode| -> anyhow::Result<()> { + // TODO merge this + let txn = db.inner.begin_write()?; + let mut table = txn.open_table(T_NODE_EXTENDED)?; + table.insert(id, Ser(n))?; + drop(table); + txn.commit()?; + Ok(()) + }; match s { ImportSource::Override(n) => insert_node(&id, n)?, ImportSource::Trakt { id: tid, kind } => { - let trakt_object = ap + info!("trakt {id}"); + let trakt = ap .trakt .as_ref() - .ok_or(anyhow!("trakt api key is required"))? + .ok_or(anyhow!("trakt api key is required"))?; + let trakt_object = trakt .lookup(kind, tid, true) - .await?; + .await + .context("looking up metadata")?; + let trakt_people = trakt + .people(kind, tid, true) + .await + .context("looking up people")?; let mut node = Node::default(); - node.public.title = Some(trakt_object.title.to_owned()); - if let Some(overview) = &trakt_object.overview { - node.public.description = Some(overview.to_owned()) - } - if let Some(tagline) = &trakt_object.tagline { - node.public.tagline = Some(tagline.to_owned()) - } - if let Some(rating) = &trakt_object.rating { - node.public.ratings.insert(Rating::Trakt, *rating); + let mut node_ext = ExtendedNode::default(); + { + node.public.title = Some(trakt_object.title.to_owned()); + if let Some(overview) = &trakt_object.overview { + node.public.description = Some(overview.to_owned()) + } + if let Some(tagline) = &trakt_object.tagline { + node.public.tagline = Some(tagline.to_owned()) + } + if let Some(rating) = &trakt_object.rating { + node.public.ratings.insert(Rating::Trakt, *rating); + } + for p in trakt_people.cast.iter() { + node_ext + .people + .entry(PeopleGroup::Cast) + .or_default() + .push(p.a()) + } + for (group, people) in trakt_people.crew.iter() { + for p in people { + node_ext.people.entry(group.a()).or_default().push(p.a()) + } + } + for (_, ps) in &mut node_ext.people { + for p in ps { + if let Some(id) = p.person.ids.tmdb { + if let Some(tmdb) = &ap.tmdb { + let k = tmdb.person_image(id).await?; + if let Some(prof) = k.profiles.get(0) { + p.person.asset = Some(tmdb.image(&prof.file_path).await?); + } + } + } + } + } } insert_node(&id, node)?; + insert_node_ext(&id, node_ext)?; if let Some(tid) = trakt_object.ids.tmdb { let mut index_path = index_path.to_vec(); @@ -290,39 +336,21 @@ async fn process_source( } } ImportSource::Tmdb { id: tid } => { - info!("tmdb lookup {id}"); - let key = SECRETS - .api + info!("tmdb {id}"); + let tmdb = ap .tmdb .as_ref() - .ok_or(anyhow!("no tmdb api key"))?; + .ok_or(anyhow!("tmdb api key is required"))?; - let details = tokio::task::spawn_blocking(move || { - cache_memory(&["tmdb-details", &format!("{tid}")], || { - block_on(tmdb::tmdb_details(TmdbKind::Movie, tid, key)) - }) - }) - .await??; + let details = tmdb.details(TmdbKind::Movie, tid).await?; let mut node = Node::default(); if let Some(poster) = &details.poster_path { - node.private.poster = Some( - async_cache_file( - &["tmdb-asset", "poster", &format!("{tid}")], - |mut f| async move { Ok(f.write_all(&tmdb_image(&poster).await?).await?) }, - ) - .await?, - ); + node.private.poster = Some(tmdb.image(&poster).await?); } if let Some(backdrop) = &details.backdrop_path { - node.private.backdrop = Some( - async_cache_file( - &["tmdb-asset", "backdrop", &format!("{tid}")], - |mut f| async move { Ok(f.write_all(&tmdb_image(&backdrop).await?).await?) }, - ) - .await?, - ); + node.private.backdrop = Some(tmdb.image(&backdrop).await?); } node.public.tagline = details.tagline.clone(); |