diff --git a/crates/services/integration/src/lib.rs b/crates/services/integration/src/lib.rs index 04f9356d89..9088540cd5 100644 --- a/crates/services/integration/src/lib.rs +++ b/crates/services/integration/src/lib.rs @@ -165,14 +165,14 @@ impl IntegrationService { return Err(Error::new("Integration is disabled".to_owned())); } let maybe_progress_update = match integration.provider { - IntegrationProvider::Kodi => sink::kodi::yank_progress(payload).await, - IntegrationProvider::Emby => sink::emby::yank_progress(payload, &self.0.db).await, - IntegrationProvider::JellyfinSink => sink::jellyfin::yank_progress(payload).await, + IntegrationProvider::Kodi => sink::kodi::sink_progress(payload).await, + IntegrationProvider::Emby => sink::emby::sink_progress(payload, &self.0.db).await, + IntegrationProvider::JellyfinSink => sink::jellyfin::sink_progress(payload).await, IntegrationProvider::PlexSink => { let specifics = integration.clone().provider_specifics.unwrap(); - sink::plex::yank_progress(payload, &self.0.db, specifics.plex_sink_username).await + sink::plex::sink_progress(payload, &self.0.db, specifics.plex_sink_username).await } - IntegrationProvider::GenericJson => sink::generic_json::yank_progress(payload).await, + IntegrationProvider::GenericJson => sink::generic_json::sink_progress(payload).await, _ => return Err(Error::new("Unsupported integration source".to_owned())), }; match maybe_progress_update { diff --git a/crates/services/integration/src/sink/emby.rs b/crates/services/integration/src/sink/emby.rs index db849b14a2..cb650eff29 100644 --- a/crates/services/integration/src/sink/emby.rs +++ b/crates/services/integration/src/sink/emby.rs @@ -47,7 +47,7 @@ mod models { } } -pub async fn yank_progress(payload: String, db: &DatabaseConnection) -> Result { +pub async fn sink_progress(payload: String, db: &DatabaseConnection) -> Result { let payload: models::EmbyWebhookPayload = serde_json::from_str(&payload)?; let runtime = payload .item diff --git a/crates/services/integration/src/sink/generic_json.rs b/crates/services/integration/src/sink/generic_json.rs index d8c12301f9..1e602fe2f0 100644 --- a/crates/services/integration/src/sink/generic_json.rs +++ b/crates/services/integration/src/sink/generic_json.rs @@ -1,7 +1,7 @@ use anyhow::{bail, Result}; use dependent_models::{CompleteExport, ImportCompletedItem, ImportResult}; -pub async fn yank_progress(payload: String) -> Result { +pub async fn sink_progress(payload: String) -> Result { let payload = match serde_json::from_str::(&payload) { Ok(val) => val, Err(err) => bail!(err), diff --git a/crates/services/integration/src/sink/jellyfin.rs b/crates/services/integration/src/sink/jellyfin.rs index b5e174b250..1c54fb9f3c 100644 --- a/crates/services/integration/src/sink/jellyfin.rs +++ b/crates/services/integration/src/sink/jellyfin.rs @@ -27,14 +27,14 @@ mod models { #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "PascalCase")] pub struct JellyfinWebhookItemPayload { - pub run_time_ticks: Option, #[serde(rename = "Type")] pub item_type: String, - pub provider_ids: JellyfinWebhookItemProviderIdsPayload, #[serde(rename = "ParentIndexNumber")] pub season_number: Option, #[serde(rename = "IndexNumber")] pub episode_number: Option, + pub run_time_ticks: Option, + pub provider_ids: JellyfinWebhookItemProviderIdsPayload, } #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "PascalCase")] @@ -42,11 +42,11 @@ mod models { pub event: Option, pub item: JellyfinWebhookItemPayload, pub series: Option, - pub session: JellyfinWebhookSessionPayload, + pub session: Option, } } -pub async fn yank_progress(payload: String) -> Result { +pub async fn sink_progress(payload: String) -> Result { let payload = serde_json::from_str::(&payload)?; let identifier = payload .item @@ -62,35 +62,43 @@ pub async fn yank_progress(payload: String) -> Result { .ok_or_else(|| anyhow::anyhow!("No TMDb ID associated with this media"))? .clone(); - let runtime = payload - .item - .run_time_ticks - .ok_or_else(|| anyhow::anyhow!("No run time associated with this media"))?; - - let position = payload - .session - .play_state - .position_ticks - .ok_or_else(|| anyhow::anyhow!("No position associated with this media"))?; - let lot = match payload.item.item_type.as_str() { "Episode" => MediaLot::Show, "Movie" => MediaLot::Movie, _ => bail!("Only movies and shows supported"), }; + let mut seen_item = ImportOrExportMetadataItemSeen { + show_season_number: payload.item.season_number, + show_episode_number: payload.item.episode_number, + provider_watched_on: Some("Jellyfin".to_string()), + ..Default::default() + }; + + match payload.event.unwrap_or_default().as_str() { + "MarkPlayed" => {} + _ => { + let runtime = payload + .item + .run_time_ticks + .ok_or_else(|| anyhow::anyhow!("No run time associated with this media"))?; + + let position = payload + .session + .as_ref() + .and_then(|s| s.play_state.position_ticks.as_ref()) + .ok_or_else(|| anyhow::anyhow!("No position associated with this media"))?; + + seen_item.progress = Some(position / runtime * dec!(100)); + } + } + Ok(ImportResult { completed: vec![ImportCompletedItem::Metadata(ImportOrExportMetadataItem { lot, identifier, source: MediaSource::Tmdb, - seen_history: vec![ImportOrExportMetadataItemSeen { - progress: Some(position / runtime * dec!(100)), - show_season_number: payload.item.season_number, - show_episode_number: payload.item.episode_number, - provider_watched_on: Some("Jellyfin".to_string()), - ..Default::default() - }], + seen_history: vec![seen_item], ..Default::default() })], ..Default::default() diff --git a/crates/services/integration/src/sink/kodi.rs b/crates/services/integration/src/sink/kodi.rs index 55326a8d08..93be86d35b 100644 --- a/crates/services/integration/src/sink/kodi.rs +++ b/crates/services/integration/src/sink/kodi.rs @@ -14,7 +14,7 @@ struct IntegrationMediaSeen { show_episode_number: Option, } -pub async fn yank_progress(payload: String) -> Result { +pub async fn sink_progress(payload: String) -> Result { let payload = match serde_json::from_str::(&payload) { Ok(val) => val, Err(err) => bail!(err), diff --git a/crates/services/integration/src/sink/plex.rs b/crates/services/integration/src/sink/plex.rs index 1f8ce65976..26712b0878 100644 --- a/crates/services/integration/src/sink/plex.rs +++ b/crates/services/integration/src/sink/plex.rs @@ -89,7 +89,7 @@ fn calculate_progress(payload: &models::PlexWebhookPayload) -> Result { } } -pub async fn yank_progress( +pub async fn sink_progress( payload: String, db: &DatabaseConnection, plex_user: Option, diff --git a/docs/content/integrations.md b/docs/content/integrations.md index 379549e4d1..93f9a63e74 100644 --- a/docs/content/integrations.md +++ b/docs/content/integrations.md @@ -42,7 +42,7 @@ will work for all the media that have a valid TMDb ID attached to their metadata - Webhook Url => `` - Payload format => `Default` - Listen to events only for => Choose your user - - Events => `Play`, `Pause`, `Resume`, `Stop` and `Progress` + - Events => `Play`, `Pause`, `Resume`, `Stop`, `Progress` and `MarkPlayed` ### Emby