aboutsummaryrefslogtreecommitdiff
path: root/import/src/plugins/tmdb.rs
diff options
context:
space:
mode:
Diffstat (limited to 'import/src/plugins/tmdb.rs')
-rw-r--r--import/src/plugins/tmdb.rs170
1 files changed, 111 insertions, 59 deletions
diff --git a/import/src/plugins/tmdb.rs b/import/src/plugins/tmdb.rs
index 206781b..6b70d46 100644
--- a/import/src/plugins/tmdb.rs
+++ b/import/src/plugins/tmdb.rs
@@ -4,12 +4,14 @@
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
use crate::{
- NodeID, USER_AGENT,
+ USER_AGENT,
plugins::{ImportContext, ImportPlugin, PluginInfo},
};
use anyhow::{Context, Result, anyhow, bail};
+use chrono::{Utc, format::Parsed};
use jellycache::{EscapeKey, HashKey, cache_memory, cache_store};
-use jellycommon::jellyobject::Object;
+use jellycommon::*;
+use jellydb::table::RowNum;
use log::info;
use reqwest::{
Client, ClientBuilder,
@@ -107,7 +109,7 @@ impl Tmdb {
})
.context("tmdb person images")
}
- pub fn image(&self, path: &str, rt: &Handle) -> Result<Asset> {
+ pub fn image(&self, path: &str, rt: &Handle) -> Result<String> {
cache_store(
format!("ext/tmdb/image/{}.image", EscapeKey(path)),
move || {
@@ -126,14 +128,13 @@ impl Tmdb {
},
)
.context("tmdb image download")
- .map(Asset)
}
pub fn episode_details(
&self,
series_id: u64,
- season: usize,
- episode: usize,
+ season: u64,
+ episode: u64,
rt: &Handle,
) -> Result<Arc<TmdbEpisode>> {
cache_memory(&format!("ext/tmdb/episode-details/{series_id}-S{season}-E{episode}.json"), move || {
@@ -161,37 +162,46 @@ impl ImportPlugin for Tmdb {
..Default::default()
}
}
- fn process(&self, ct: &ImportContext, node: NodeID, data: Object) -> Result<()> {
- self.process_primary(ct, node, data)?;
- self.process_episode(ct, node, data)?;
+ fn process(&self, ct: &ImportContext, node: RowNum) -> Result<()> {
+ self.process_primary(ct, node)?;
+ self.process_episode(ct, node)?;
Ok(())
}
}
impl Tmdb {
- fn process_primary(&self, ct: &ImportContext, node: NodeID, data: Object) -> Result<()> {
- let (tmdb_kind, tmdb_id): (_, u64) =
- if let Some(id) = data.identifiers.get(&IdentifierType::TmdbSeries) {
- (TmdbKind::Tv, id.parse()?)
- } else if let Some(id) = data.identifiers.get(&IdentifierType::TmdbMovie) {
- (TmdbKind::Movie, id.parse()?)
- } else {
- return Ok(());
- };
+ fn process_primary(&self, ct: &ImportContext, node: RowNum) -> Result<()> {
+ let data = ct.dba.get_node(node)?.unwrap();
+ let data = data.as_object();
+
+ let (tmdb_kind, tmdb_id): (_, u64) = if let Some(id) = data
+ .get(NO_IDENTIFIERS)
+ .unwrap_or_default()
+ .get(IDENT_TMDB_SERIES)
+ {
+ (TmdbKind::Tv, id.parse()?)
+ } else if let Some(id) = data
+ .get(NO_IDENTIFIERS)
+ .unwrap_or_default()
+ .get(IDENT_TMDB_MOVIE)
+ {
+ (TmdbKind::Movie, id.parse()?)
+ } else {
+ return Ok(());
+ };
let details = self.details(tmdb_kind, tmdb_id, ct.rt)?;
- let mut images = Vec::new();
- if let Some(path) = &details.backdrop_path {
- images.push((
- PictureSlot::Backdrop,
- self.image(path, ct.rt).context("backdrop image")?,
- ));
- }
- if let Some(path) = &details.poster_path {
- images.push((
- PictureSlot::Cover,
- self.image(path, ct.rt).context("poster image")?,
- ));
- }
+ let backdrop = details
+ .backdrop_path
+ .as_ref()
+ .map(|path| self.image(&path, ct.rt))
+ .transpose()
+ .context("backdrop image")?;
+ let poster = details
+ .poster_path
+ .as_ref()
+ .map(|path| self.image(&path, ct.rt))
+ .transpose()
+ .context("poster image")?;
let release_date = details
.release_date
@@ -200,46 +210,88 @@ impl Tmdb {
.transpose()?
.flatten();
- ct.dba.update_node_by_nodeid(node, |node| {
- node.title = details.title.clone().or(node.title.clone());
- node.tagline = details.tagline.clone().or(node.tagline.clone());
- node.description = Some(details.overview.clone());
- node.ratings.insert(RatingType::Tmdb, details.vote_average);
- node.pictures.extend(images);
- node.release_date = release_date.or(node.release_date);
+ ct.dba.update_node(node, |mut node| {
+ if let Some(title) = &details.title {
+ node = node.as_object().insert(NO_TITLE, &title);
+ }
+ if let Some(tagline) = &details.tagline {
+ node = node.as_object().insert(NO_TAGLINE, &tagline);
+ }
+ node = node.as_object().insert(NO_DESCRIPTION, &details.overview);
+ node = node.as_object().update(NO_RATINGS, |rat| {
+ rat.insert(RTYP_TMDB, details.vote_average)
+ });
+ if let Some(poster) = &poster {
+ node = node
+ .as_object()
+ .update(NO_PICTURES, |rat| rat.insert(PICT_COVER, &poster));
+ }
+ if let Some(backdrop) = &backdrop {
+ node = node
+ .as_object()
+ .update(NO_PICTURES, |rat| rat.insert(PICT_BACKDROP, &backdrop));
+ }
+ if let Some(releasedate) = release_date {
+ node = node.as_object().insert(NO_RELEASEDATE, releasedate);
+ }
+ node
})?;
Ok(())
}
- fn process_episode(&self, ct: &ImportContext, node: NodeID, data: &Node) -> Result<()> {
- let (Some(episode), Some(season)) = (data.index, data.season_index) else {
+ fn process_episode(&self, ct: &ImportContext, node: RowNum) -> Result<()> {
+ let data = ct.dba.get_node(node)?.unwrap();
+ let data = data.as_object();
+
+ let (Some(episode), Some(season)) = (data.get(NO_INDEX), data.get(NO_SEASON_INDEX)) else {
return Ok(());
};
let mut series_id = None;
- for &parent in &data.parents {
- let parent_data = ct.db.get_node(parent)?.ok_or(anyhow!("parent missing"))?;
- if let Some(id) = parent_data.identifiers.get(&IdentifierType::TmdbSeries) {
- series_id = Some(id.parse::<u64>()?);
- break;
+ ct.dba.db.read_transaction(&mut |txn| {
+ for parent in data.iter(NO_PARENT) {
+ let parent_data = ct
+ .dba
+ .nodes
+ .get(txn, parent)?
+ .ok_or(anyhow!("parent missing"))?;
+ if let Some(id) = parent_data
+ .as_object()
+ .get(NO_IDENTIFIERS)
+ .unwrap_or_default()
+ .get(IDENT_TMDB_SERIES)
+ {
+ series_id = Some(id.parse::<u64>()?);
+ break;
+ }
}
- }
+ Ok(())
+ })?;
let Some(series_id) = series_id else {
return Ok(());
};
let details = self.episode_details(series_id, season, episode, ct.rt)?;
- let mut images = Vec::new();
- if let Some(path) = &details.still_path {
- images.push((PictureSlot::Cover, self.image(path, ct.rt)?))
- }
-
+ let cover = details
+ .still_path
+ .as_ref()
+ .map(|path| self.image(&path, ct.rt))
+ .transpose()
+ .context("still image download")?;
let release_date = parse_release_date(&details.air_date)?;
- ct.db.update_node_init(node, |node| {
- node.title = Some(details.name.clone());
- node.description = Some(details.overview.clone());
- node.release_date = release_date.or(node.release_date);
- node.ratings.insert(RatingType::Tmdb, details.vote_average);
- node.pictures.extend(images);
- })?;
- Ok(())
+ ct.dba.update_node(node, |mut node| {
+ node = node.as_object().insert(NO_TITLE, &details.name);
+ node = node.as_object().insert(NO_DESCRIPTION, &details.overview);
+ if let Some(release_date) = release_date {
+ node = node.as_object().insert(NO_RELEASEDATE, release_date)
+ }
+ node = node.as_object().update(NO_RATINGS, |rat| {
+ rat.insert(RTYP_TMDB, details.vote_average)
+ });
+ if let Some(cover) = &cover {
+ node = node
+ .as_object()
+ .update(NO_PICTURES, |picts| picts.insert(PICT_COVER, &cover));
+ }
+ node
+ })
}
}