diff --git a/src/model/playlist.rs b/src/model/playlist.rs index 2f20fd16a..c745f91c0 100644 --- a/src/model/playlist.rs +++ b/src/model/playlist.rs @@ -179,13 +179,9 @@ impl PlaylistItemHeader { } pub fn get_additional_property(&self, field: &str) -> Option<&Value> { - self.additional_properties.as_ref().map_or(None, |v| match v { + self.additional_properties.as_ref().and_then(|v| match v { Value::Object(map) => { - if let Some(updated) = map.get(field) { - Some(updated) - } else { - None - } + map.get(field) } _ => None, }) diff --git a/src/model/xtream.rs b/src/model/xtream.rs index b2bd91a0e..b5c793071 100644 --- a/src/model/xtream.rs +++ b/src/model/xtream.rs @@ -266,16 +266,23 @@ impl XtreamStream { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct XtreamSeriesInfoSeason { + #[serde(default)] pub air_date: String, + #[serde(default)] pub episode_count: u32, + #[serde(default)] pub id: u32, + #[serde(default)] pub name: String, + #[serde(default)] pub overview: String, - #[serde(deserialize_with = "string_or_number_u32")] + #[serde(default, deserialize_with = "string_or_number_u32")] pub season_number: u32, - #[serde(deserialize_with = "string_or_number_f64")] + #[serde(default, deserialize_with = "string_or_number_f64")] pub vote_average: f64, + #[serde(default)] pub cover: String, + #[serde(default)] pub cover_big: String, } @@ -283,64 +290,88 @@ pub struct XtreamSeriesInfoSeason { #[derive(Debug, Clone, Serialize, Deserialize)] #[allow(non_snake_case)] pub struct XtreamSeriesInfoInfo { + #[serde(default)] pub(crate) name: String, + #[serde(default)] cover: String, + #[serde(default)] plot: String, + #[serde(default)] cast: String, + #[serde(default)] director: String, + #[serde(default)] genre: String, + #[serde(default)] releaseDate: String, + #[serde(default)] last_modified: String, - #[serde(deserialize_with = "string_or_number_f64")] + #[serde(default, deserialize_with = "string_or_number_f64")] rating: f64, - #[serde(deserialize_with = "string_or_number_f64")] + #[serde(default, deserialize_with = "string_or_number_f64")] rating_5based: f64, + #[serde(default)] backdrop_path: Vec, + #[serde(default)] youtube_trailer: String, + #[serde(default)] episode_run_time: String, - #[serde(deserialize_with = "string_or_number_u32")] + #[serde(default, deserialize_with = "string_or_number_u32")] category_id: u32, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct XtreamSeriesInfoEpisodeInfo { #[serde(deserialize_with = "opt_string_or_number_u32")] + #[serde(default)] pub tmdb_id: Option, + #[serde(default)] pub releasedate: String, + #[serde(default)] pub plot: String, - #[serde(deserialize_with = "string_or_number_u32")] + #[serde(default, deserialize_with = "string_or_number_u32")] pub duration_secs: u32, + #[serde(default)] pub duration: String, + #[serde(default)] pub movie_image: String, + #[serde(default)] pub video: Value, + #[serde(default)] pub audio: Value, - #[serde(deserialize_with = "string_or_number_u32")] + #[serde(default, deserialize_with = "string_or_number_u32")] pub bitrate: u32, - #[serde(deserialize_with = "string_or_number_f64")] + #[serde(default, deserialize_with = "string_or_number_f64")] pub rating: f64, - #[serde(deserialize_with = "string_or_number_u32")] + #[serde(default, deserialize_with = "string_or_number_u32")] pub season: u32, } // Used for serde_json deserialization, can not be used with bincode #[derive(Debug, Clone, Serialize, Deserialize)] pub struct XtreamSeriesInfoEpisode { + #[serde(default)] pub id: String, - #[serde(deserialize_with = "string_or_number_u32")] + #[serde(default, deserialize_with = "string_or_number_u32")] pub episode_num: u32, + #[serde(default)] pub title: String, + #[serde(default)] pub container_extension: String, pub info: XtreamSeriesInfoEpisodeInfo, + #[serde(default)] pub custom_sid: String, + #[serde(default)] pub added: String, - #[serde(deserialize_with = "string_or_number_u32")] + #[serde(default, deserialize_with = "string_or_number_u32")] pub season: u32, + #[serde(default)] pub direct_source: String, } impl XtreamSeriesInfoEpisode { pub fn get_id(&self) -> u32 { - self.id.parse::().unwrap_or_else(|_| 0) + self.id.parse::().unwrap_or(0) } } diff --git a/src/processing/playlist_processor.rs b/src/processing/playlist_processor.rs index 7694064e8..b1a6ce9fb 100644 --- a/src/processing/playlist_processor.rs +++ b/src/processing/playlist_processor.rs @@ -533,7 +533,9 @@ pub async fn exec_processing(cfg: Arc, targets: Arc) { let start_time = Instant::now(); let (stats, errors) = process_sources(cfg.clone(), targets.clone()).await; // log errors - errors.iter().for_each(|err| error!("{}", err.message)); + for err in &errors { + error!("{}", err.message); + } if let Ok(stats_msg) = serde_json::to_string(&serde_json::Value::Object(serde_json::map::Map::from_iter([("stats".to_string(), serde_json::to_value(stats).unwrap())]))) { // print stats info!("{}", stats_msg); diff --git a/src/processing/xtream_parser.rs b/src/processing/xtream_parser.rs index e1ba3f646..cb9ba7eea 100644 --- a/src/processing/xtream_parser.rs +++ b/src/processing/xtream_parser.rs @@ -46,7 +46,7 @@ pub fn parse_xtream_series_info(info: &Value, group_title: &str, input: &ConfigI match serde_json::from_value::(info.to_owned()) { Ok(series_info) => { - let result: Vec<(XtreamSeriesInfoEpisode, PlaylistItem)> = series_info.episodes.values().flatten().into_iter().map(|episode| { + let result: Vec<(XtreamSeriesInfoEpisode, PlaylistItem)> = series_info.episodes.values().flatten().map(|episode| { let episode_url = create_xtream_series_info_url(url, username, password, episode); (episode.clone(), PlaylistItem { diff --git a/src/processing/xtream_processor.rs b/src/processing/xtream_processor.rs index 825bc9b1e..617de6e17 100644 --- a/src/processing/xtream_processor.rs +++ b/src/processing/xtream_processor.rs @@ -55,7 +55,7 @@ macro_rules! create_resolve_options_function_for_xtream_target { pub(in crate::processing) async fn playlist_resolve_download_playlist_item(pli: &PlaylistItem, input: &ConfigInput, errors: &mut Vec, resolve_delay: u16, cluster: XtreamCluster) -> Option { let mut result = None; - let Some(provider_id) = pli.get_provider_id() else { return None; }; + let provider_id = pli.get_provider_id()?; if let Some(info_url) = download::get_xtream_player_api_info_url(input, cluster, provider_id) { result = match download::get_xtream_stream_info_content(&info_url, input).await { Ok(content) => Some(content), diff --git a/src/repository/kodi_repository.rs b/src/repository/kodi_repository.rs index 21681aee9..c61dd4773 100644 --- a/src/repository/kodi_repository.rs +++ b/src/repository/kodi_repository.rs @@ -41,7 +41,7 @@ fn sanitize_for_filename(text: &str, underscore_whitespace: bool) -> String { } fn extract_match(name: &str, pattern: &Regex) -> (String, Option) { - pattern.find(&name).map_or_else(|| (name.to_string(), None), |m| { + pattern.find(name).map_or_else(|| (name.to_string(), None), |m| { let matched = String::from(&name[m.start()..m.end()]); let new_name = format!("{}{}", &name[0..m.start()], &name[m.end()..]); (new_name, Some(matched)) @@ -83,7 +83,7 @@ fn kodi_style_rename_year( } if let Some(rel_date) = release_date { - if let Some(year) = extract_match(&rel_date, &style.year).1.and_then(|y| y.parse::().ok()) { + if let Some(year) = extract_match(rel_date, &style.year).1.and_then(|y| y.parse::().ok()) { return (name.to_string(), Some(year)); } } @@ -108,7 +108,7 @@ async fn kodi_style_rename(cfg: &Config, strm_item_info: &StrmItemInfo, style: & let (name_1, year) = kodi_style_rename_year(&strm_item_info.title, style, strm_item_info.release_date.as_ref()); let (name_2, season) = kodi_style_rename_season(&name_1, style, strm_item_info.season.as_ref()); let (name_3, episode) = kodi_style_rename_episode(&name_2, style, strm_item_info.episode.as_ref()); - let name_4 = trim_whitespace(&style.whitespace, &*style.alphanumeric.replace_all(&name_3, "")); + let name_4 = trim_whitespace(&style.whitespace, &style.alphanumeric.replace_all(&name_3, "")); let title = &strm_item_info.series_name.as_ref() .filter(|&series_name| name_4.starts_with(series_name)) .and_then(|series_name| trim_string_after_pos(&name_3, series_name.len())); @@ -263,16 +263,16 @@ fn extract_item_info(pli: &PlaylistItem) -> StrmItemInfo { fn prepare_strm_output_directory(cleanup: bool, path: &PathBuf) -> Result<(), M3uFilterError> { if cleanup { - let _ = std::fs::remove_dir_all(&path); + let _ = std::fs::remove_dir_all(path); } - if let Err(e) = std::fs::create_dir_all(&path) { + if let Err(e) = std::fs::create_dir_all(path) { error!("cant create directory: {:?}", &path); return create_m3u_filter_error_result!(M3uFilterErrorKind::Notify, "failed to write strm playlist: {}", e); }; Ok(()) } -fn filter_strm_item(&pli: &&PlaylistItem) -> bool { +fn filter_strm_item(pli: &PlaylistItem) -> bool { let item_type = pli.header.borrow().item_type; item_type == PlaylistItemType::Series || item_type == PlaylistItemType::Live @@ -295,10 +295,10 @@ pub async fn kodi_write_strm_playlist(target: &ConfigTarget, cfg: &Config, new_p let Some(path) = file_utils::get_file_path(&cfg.working_dir, Some(std::path::PathBuf::from(&filename.as_ref().unwrap()))) else { return create_m3u_filter_error_result!(M3uFilterErrorKind::Info, "Failed to get file path for {}", filename.unwrap_or("")); }; - let _ = prepare_strm_output_directory(cleanup, &path)?; + prepare_strm_output_directory(cleanup, &path)?; let mut input_tmdb_indexes: InputTmdbIndexMap = HashMap::new(); for pg in new_playlist { - for pli in pg.channels.iter().filter(filter_strm_item) { + for pli in pg.channels.iter().filter(|&pli: &&PlaylistItem| filter_strm_item(pli)) { // we need to consider // - Live streams // - Xtream Series Episode (has series_name and release_date) diff --git a/src/repository/xtream_repository.rs b/src/repository/xtream_repository.rs index 8a851c0a5..25c6e8e26 100644 --- a/src/repository/xtream_repository.rs +++ b/src/repository/xtream_repository.rs @@ -817,7 +817,7 @@ pub async fn xtream_update_input_series_episodes_record_from_wal_file( break; // End of file } let len = usize::try_from(u32::from_le_bytes(len_bytes)).unwrap_or(0); - if len <= 0 { + if len == 0 { break; } if len > buffer.len() {