1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
use std::collections::HashMap; use futures::stream::StreamExt; use crate::EpisodeLink; use crate::Error; use crate::Title; use crate::TitleType; use crate::get_episodes_filtered; use crate::stream_titles_filtered; pub async fn get_shows_filtered(ids: &[u64]) -> Result<Vec<Show>, Error> { let mut episode_links = get_episodes_filtered(ids).await?; let all_ids = { let mut v = Vec::from(ids); v.extend(episode_links.iter().map(|(id, _)| id)); v }; let mut episodes_by_show = HashMap::new(); let mut shows = Vec::with_capacity(ids.len()); let mut stream = stream_titles_filtered(&all_ids).await?; while let Some(result) = stream.next().await { let title = result?; if let Some(link) = episode_links.remove(&title.imdb_id) { let series_id = link.series_imdb_id; if let Some(result) = Episode::from_title_and_link(title, link) { let episode = result?; let episodes = episodes_by_show.entry(series_id).or_insert_with(|| Vec::new()); episodes.push(episode); } continue; } shows.push(match Show::from_title(&title) { Some(Ok(v)) => v, Some(Err(e)) => return Err(e), None => continue }); } for show in shows.iter_mut() { show.episodes = match episodes_by_show.remove(&show.imdb_id) { Some(v) => v, None => Vec::new() }; } Ok(shows) } #[derive(Debug)] pub struct Show { pub imdb_id: u64, pub title: String, pub is_adult: bool, pub start_year: u16, pub end_year: Option<u16>, pub runtime_minutes: Option<u16>, pub genres: Vec<String>, pub episodes: Vec<Episode> } impl Show { pub(crate) fn from_title(input: &Title) -> Option<Result<Self, Error>> { match input.title_type { TitleType::TVSeries => Some(Ok(Self{ imdb_id: input.imdb_id, title: input.primary_title.clone(), is_adult: input.is_adult != 0, start_year: match input.start_year { Some(v) => v, None => return Some(Err(Error::YearMissing.into())) }, end_year: input.end_year, runtime_minutes: input.runtime_minutes, genres: input.genres.clone(), episodes: Vec::new() })), _ => None } } fn from_wrapped_title(input: Result<Title, Error>) -> Option<Result<Self, Error>> { match input { Ok(t) => Self::from_title(&t), Err(e) => Some(Err(e)) } } } #[derive(Debug)] pub struct Episode { pub season: u16, pub episode: u16, pub imdb_id: u64, pub title: String, pub runtime_minutes: Option<u16> } impl Episode { pub(crate) fn from_title_and_link(title: Title, link: EpisodeLink) -> Option<Result<Self, Error>> { match title.title_type { TitleType::Episode => Some(Ok(Self{ season: match link.season { Some(v) => v, None => return Some(Err(Error::SeasonMissing.into())) }, episode: match link.episode { Some(v) => v, None => return Some(Err(Error::EpisodeMissing.into())) }, imdb_id: title.imdb_id, title: title.primary_title, runtime_minutes: title.runtime_minutes })), _ => None } } }