diff --git a/src/ffi.rs b/src/ffi.rs index 586c97f..9ad6aa4 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -442,6 +442,7 @@ fn route_player_policy(method: &str, args_json: &str) -> Outcome { field_str(&args, "streamsJson")?, field_str(&args, "currentStreamJson")?, field_str(&args, "prefsJson")?, + field_str(&args, "nextVideoId")?, )) } diff --git a/src/player_policy.rs b/src/player_policy.rs index d6dd4e2..4e02c09 100644 --- a/src/player_policy.rs +++ b/src/player_policy.rs @@ -941,6 +941,7 @@ pub(crate) fn select_next_episode_stream_json( streams_json: &str, current_stream_json: &str, prefs_json: &str, + next_video_id: &str, ) -> Option { let streams: Vec = serde_json::from_str(streams_json).ok()?; if streams.is_empty() { @@ -949,6 +950,25 @@ pub(crate) fn select_next_episode_stream_json( let current: Value = serde_json::from_str(current_stream_json).ok()?; let prefs: Value = serde_json::from_str(prefs_json).unwrap_or(Value::Null); + let episode_ok = |s: &Value| -> bool { + let field = |key: &str| -> String { + s.get(key) + .and_then(Value::as_str) + .unwrap_or_default() + .to_string() + }; + let behavior_hints = s.get("behaviorHints"); + let filename = behavior_hints + .and_then(|h| h.get("filename")) + .and_then(Value::as_str) + .unwrap_or_default() + .to_string(); + crate::content_identity::stream_matches_episode( + next_video_id, + &[field("title"), field("name"), field("description"), filename], + ) + }; + let try_binge = prefs .get("tryBingeGroup") .and_then(Value::as_bool) @@ -974,6 +994,7 @@ pub(crate) fn select_next_episode_stream_json( .and_then(|h| h.get("bingeGroup")) .and_then(Value::as_str) == Some(group) + && episode_ok(s) }); if let Some(s) = matched { return serde_json::to_string(s).ok(); @@ -1001,13 +1022,20 @@ pub(crate) fn select_next_episode_stream_json( .collect::>() .join(" ") }; - if let Some(matched) = streams.iter().find(|s| re.is_match(&stream_text(s))) { + if let Some(matched) = streams + .iter() + .find(|s| re.is_match(&stream_text(s)) && episode_ok(s)) + { return serde_json::to_string(matched).ok(); } } } - streams.first().and_then(|s| serde_json::to_string(s).ok()) + streams + .iter() + .find(|s| episode_ok(s)) + .or_else(|| streams.first()) + .and_then(|s| serde_json::to_string(s).ok()) } #[cfg(test)]