//! Show related endpoints //! //! pub mod trending { //! Get trending shows //! //! use http::StatusCode; use serde::Deserialize; use trakt_core::{ error::FromHttpError, handle_response_body, parse_from_header, Pagination, PaginationResponse, }; use crate::smo::Show; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/trending", )] pub struct Request { #[serde(flatten)] pub pagination: Pagination, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Paginated)] pub struct Response { #[trakt(pagination)] pub items: PaginationResponse, pub trending_user_count: u64, } #[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)] pub struct ResponseItem { pub watchers: u64, pub show: Show, } impl trakt_core::Response for Response { fn try_from_http_response>( response: http::Response, ) -> Result { let body = handle_response_body(&response, StatusCode::OK)?; let items = PaginationResponse::from_headers(body, response.headers())?; Ok(Self { items, trending_user_count: parse_from_header( response.headers(), "X-Trending-User-Count", )?, }) } } } pub mod popular { //! Get popular shows //! //! use trakt_core::{Pagination, PaginationResponse}; use crate::smo::Show; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/popular", )] pub struct Request { #[serde(flatten)] pub pagination: Pagination, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] #[trakt(expected = OK)] pub struct Response { #[trakt(pagination)] pub items: PaginationResponse, } #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] pub struct ResponseItem { pub watchers: u64, pub show: Show, } } pub mod favorited { //! Get most favorited shows //! //! use trakt_core::{Pagination, PaginationResponse}; use crate::smo::Show; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/favorited", )] pub struct Request { #[serde(flatten)] pub pagination: Pagination, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] #[trakt(expected = OK)] pub struct Response { #[trakt(pagination)] pub items: PaginationResponse, } #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] pub struct ResponseItem { pub user_count: u64, pub show: Show, } } pub mod played { //! Get most played shows //! //! use trakt_core::{Pagination, PaginationResponse}; use crate::smo::{Period, Show}; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/played/{period}", )] pub struct Request { pub period: Period, #[serde(flatten)] pub pagination: Pagination, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] #[trakt(expected = OK)] pub struct Response { #[trakt(pagination)] pub items: PaginationResponse, } #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] pub struct ResponseItem { pub watcher_count: u64, pub play_count: u64, pub collected_count: u64, pub collector_count: u64, pub show: Show, } } pub mod watched { //! Get most watched shows //! //! use trakt_core::{Pagination, PaginationResponse}; use crate::smo::{Period, Show}; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/watched/{period}", )] pub struct Request { pub period: Period, #[serde(flatten)] pub pagination: Pagination, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response { #[trakt(pagination)] pub items: PaginationResponse, } #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] pub struct ResponseItem { pub watcher_count: u64, pub play_count: u64, pub collected_count: u64, pub collector_count: u64, pub show: Show, } } pub mod collected { //! Get most collected shows //! //! use trakt_core::{Pagination, PaginationResponse}; use crate::smo::{Period, Show}; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/collected", )] pub struct Request { pub period: Period, #[serde(flatten)] pub pagination: Pagination, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response { #[trakt(pagination)] pub items: PaginationResponse, } #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] pub struct ResponseItem { pub watcher_count: u64, pub play_count: u64, pub collector_count: u64, pub collected_count: u64, pub show: Show, } } pub mod anticipated { //! Get most anticipated shows //! //! use trakt_core::{Pagination, PaginationResponse}; use crate::smo::Show; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/anticipated", )] pub struct Request { #[serde(flatten)] pub pagination: Pagination, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response { #[trakt(pagination)] pub items: PaginationResponse, } #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] pub struct ResponseItem { pub list_count: u64, pub show: Show, } } pub mod updates { //! Get all shows updated since a specific date //! //! use time::OffsetDateTime; use trakt_core::{Pagination, PaginationResponse}; use crate::smo::Show; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/updates/{start_date}", )] pub struct Request { #[serde(with = "time::serde::iso8601")] pub start_date: OffsetDateTime, #[serde(flatten)] pub pagination: Pagination, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response { #[trakt(pagination)] pub items: PaginationResponse, } #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] pub struct ResponseItem { pub updated_at: OffsetDateTime, pub show: Show, } } pub mod updates_id { //! Get recently updated show IDs since a specific date //! //! use time::OffsetDateTime; use trakt_core::Pagination; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/updates/id/{start_date}", )] pub struct Request { #[serde(with = "time::serde::iso8601")] pub start_date: OffsetDateTime, #[serde(flatten)] pub pagination: Pagination, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response(pub Vec); } pub mod summary { //! Get a single show //! //! use crate::smo::{Id, Show}; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}", )] pub struct Request { pub id: Id, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response(pub Show); } pub mod aliases { //! Gets all title aliases for a show //! //! use crate::smo::{Country, Id}; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/aliases", )] pub struct Request { pub id: Id, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response(pub Vec); #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] pub struct ResponseItem { pub title: String, pub country: Country, } } pub mod certifications { //! Gets all content certifications for a show //! //! use crate::smo::{Country, Id}; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/certifications", )] pub struct Request { pub id: Id, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response(pub Vec); #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] pub struct ResponseItem { pub certification: String, pub country: Country, } } pub mod translation { //! Gets all show translations //! //! use crate::smo::{Country, Id, Language}; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/translations/{language}", )] pub struct Request { pub id: Id, pub language: Language, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response(pub Vec); #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] pub struct ResponseItem { pub title: String, pub overview: String, pub tagline: Option, pub language: Language, pub country: Country, } } pub mod comments { //! Get all top level comments for a show //! //! If oauth is provided, comments from blocked users will be filtered out. //! //! use trakt_core::PaginationResponse; use crate::smo::{Comment, Id, Sort}; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/comments/{sort}", auth = Optional, )] pub struct Request { id: Id, sort: Sort, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response { #[trakt(pagination)] pub comments: PaginationResponse, } } pub mod lists { //! Get all lists that contain this show //! //! use serde::Serialize; use trakt_core::{Pagination, PaginationResponse}; use crate::smo::{Id, List}; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/lists/{tp}/{sort}" )] pub struct Request { pub id: Id, pub tp: Option, pub sort: Option, #[serde(flatten)] pub pagination: Pagination, } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, Serialize)] pub enum Type { #[default] All, Personal, Official, Watchlist, Favorites, } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, Serialize)] #[serde(rename_all = "lowercase")] pub enum Sort { #[default] Popular, Likes, Comments, Items, Added, Updated, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response { #[trakt(pagination)] pub lists: PaginationResponse, } } pub mod collection_progress { //! Get show collection progress //! //! use crate::smo::{Episode, Id, Season}; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/progress/collection", auth = Required, )] pub struct Request { pub id: Id, pub hidden: bool, pub specials: bool, pub count_specials: bool, } #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize, trakt_macros::Response)] pub struct Response { pub aired: u64, pub completed: u64, #[serde(with = "time::serde::iso8601::option")] pub last_collected_at: Option, pub seasons: Vec, pub hidden_seasons: Vec, pub next_episode: Option, pub last_episode: Option, } #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] pub struct SeasonCollection { pub number: u64, pub title: String, pub aired: u64, pub completed: u64, pub episodes: Vec, } #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] pub struct EpisodeCollection { pub number: u64, pub completed: bool, #[serde(with = "time::serde::iso8601::option")] pub collected_at: Option, } } pub mod watched_progress { //! Get show watched progress //! //! use crate::smo::{Episode, Id, Season}; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/progress/watched", auth = Required, )] pub struct Request { pub id: Id, pub hidden: bool, pub specials: bool, pub count_specials: bool, } #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize, trakt_macros::Response)] pub struct Response { pub aired: u64, pub completed: u64, #[serde(with = "time::serde::iso8601::option")] pub last_watched_at: Option, pub seasons: Vec, pub hidden_seasons: Vec, pub next_episode: Option, pub last_episode: Option, } #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] pub struct SeasonWatched { pub number: u64, pub title: String, pub aired: u64, pub completed: u64, pub episodes: Vec, } #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] pub struct EpisodeWatched { pub number: u64, pub completed: bool, #[serde(with = "time::serde::iso8601::option")] pub last_watched_at: Option, } } pub mod reset { //! Resetting show progress //! //! #[allow(clippy::module_inception)] pub mod reset { //! Reset show progress //! //! use crate::smo::Id; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/progress/watched/reset", method = POST, auth = Required, )] pub struct Request { pub id: Id, } #[derive( Debug, Copy, Clone, Eq, PartialEq, Hash, serde::Deserialize, trakt_macros::Response, )] pub struct Response { #[serde(with = "time::serde::iso8601")] pub reset_at: time::OffsetDateTime, } } pub mod undo { //! Undo show progress reset //! //! use crate::smo::Id; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/progress/watched/reset", method = DELETE, auth = Required, )] pub struct Request { pub id: Id, } #[derive( Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, trakt_macros::Response, )] #[trakt(expected = NO_CONTENT)] pub struct Response; } } pub mod people { //! TODO: Implement } pub mod ratings { //! Get show ratings //! //! use crate::smo::{Id, Ratings}; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/ratings", )] pub struct Request { pub id: Id, } #[derive(Debug, Clone, PartialEq, serde::Deserialize, trakt_macros::Response)] pub struct Response(pub Ratings); } pub mod related { //! Get related shows //! //! use trakt_core::{Pagination, PaginationResponse}; use crate::smo::{Id, Show}; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/related", )] pub struct Request { pub id: Id, pub pagination: Pagination, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response { #[trakt(pagination)] pub items: PaginationResponse, } } pub mod stats { //! Get show stats //! //! use crate::smo::Id; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/stats", )] pub struct Request { pub id: Id, } #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize, trakt_macros::Response)] pub struct Response { pub watchers: u64, pub plays: u64, pub collectors: u64, pub collected_episodes: u64, pub comments: u64, pub lists: u64, pub votes: u64, pub favorited: u64, } } pub mod studio { //! Get show studios //! //! use crate::smo::{Id, Studio}; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/studios", )] pub struct Request { pub id: Id, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response(pub Vec); } pub mod watching { //! Get users watching a show right now //! //! use crate::smo::{Id, User}; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/watching", )] pub struct Request { pub id: Id, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response(pub Vec); } pub mod next_episode { //! Get next scheduled to air episode //! //! use crate::smo::{Episode, Id}; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/next_episode", )] pub struct Request { pub id: Id, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response(pub Episode); } pub mod last_episode { //! Gets the most recently aired episode //! //! use crate::smo::{Episode, Id}; #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] #[trakt( response = Response, endpoint = "/shows/{id}/last_episode", )] pub struct Request { pub id: Id, } #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] pub struct Response(pub Episode); } #[cfg(test)] mod tests { use httpmock::prelude::*; use serde_json::json; use trakt_core::{Context, PaginatedResponse, Request}; use super::*; #[test] fn test_trending() { let server = MockServer::start(); let trending_mock = server.mock(|when, then| { when.method(GET) .path("/shows/trending") .header("Content-Type", "application/json") .header("trakt-api-version", "2") .header("trakt-api-key", "abc") .query_param("page", "1") .query_param("limit", "10"); then.status(200) .header("Content-Type", "application/json") .header("X-Trending-User-Count", "123") .header("X-Pagination-Page", "1") .header("X-Pagination-Limit", "10") .header("X-Pagination-Page-Count", "1") .header("X-Pagination-Item-Count", "1") .json_body(json!([ { "watchers": 123, "show": { "title": "The Dark Knight", "year": 2008, "ids": { "trakt": 16, "slug": "the-dark-knight-2008", "imdb": "tt0468569", "tmdb": 155 } } } ])); }); let ctx = Context { base_url: &server.base_url(), client_id: "abc", oauth_token: None, }; let request = trending::Request::default(); let http_req: http::Request> = request.try_into_http_request(ctx).unwrap(); assert_eq!( http_req.uri(), &*format!("{}/shows/trending?page=1&limit=10", server.base_url()) ); assert_eq!(http_req.method(), http::Method::GET); assert_eq!( http_req.headers().get("Content-Type").unwrap(), "application/json" ); assert_eq!(http_req.headers().get("trakt-api-key").unwrap(), "abc"); assert_eq!(http_req.headers().get("trakt-api-version").unwrap(), "2"); assert_eq!(http_req.headers().get("Authorization"), None); assert!(http_req.body().is_empty()); let response = crate::test::execute(ctx, request).unwrap(); assert_eq!(response.items().len(), 1); assert_eq!(response.items()[0].watchers, 123); assert_eq!(response.items()[0].show.title, "The Dark Knight"); assert_eq!(response.items()[0].show.year, 2008); assert_eq!(response.items()[0].show.ids.trakt, Some(16)); assert_eq!(response.next_page(), None); trending_mock.assert(); } }