diff options
author | 2024-02-18 23:31:24 -0800 | |
---|---|---|
committer | 2024-02-18 23:33:06 -0800 | |
commit | f1165ab23eda6f5a4afe6a703333025ba68f3b11 (patch) | |
tree | 6180df1fa1a7779d7b6181b9ab583c5ff2320217 | |
parent | f41b46d02ecd9234f16c35c652b01fdd170b9944 (diff) | |
download | trakt-f1165ab23eda6f5a4afe6a703333025ba68f3b11.tar.gz trakt-f1165ab23eda6f5a4afe6a703333025ba68f3b11.tar.zst trakt-f1165ab23eda6f5a4afe6a703333025ba68f3b11.zip |
Finishes comment endpoints
-rw-r--r-- | trakt-rs/src/api/comments.rs | 404 | ||||
-rw-r--r-- | trakt-rs/src/smo.rs | 87 |
2 files changed, 488 insertions, 3 deletions
diff --git a/trakt-rs/src/api/comments.rs b/trakt-rs/src/api/comments.rs index 35f2242..514f72d 100644 --- a/trakt-rs/src/api/comments.rs +++ b/trakt-rs/src/api/comments.rs @@ -96,6 +96,394 @@ pub mod post { pub struct Response(pub Comment); } +pub mod get { + //! Get a comment or reply + //! + //! <https://trakt.docs.apiary.io/#reference/comments/comment/get-a-comment-or-reply> + + use crate::smo::Comment; + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] + #[trakt( + response = Response, + endpoint = "/comments/{id}", + )] + pub struct Request { + pub id: u64, + } + + #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] + pub struct Response(pub Comment); +} + +pub mod update { + //! Update a comment or repl + //! + //! <https://trakt.docs.apiary.io/#reference/comments/comment/update-a-comment-or-reply> + + use bytes::BufMut; + use serde::Serialize; + use serde_json::json; + use trakt_core::{error::IntoHttpError, Context, Metadata}; + + use crate::smo::Comment; + + #[derive(Debug, Clone, Eq, PartialEq, Hash)] + pub struct Request { + pub id: u64, + pub comment: String, + pub spoiler: bool, + } + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize)] + struct RequestParams { + id: u64, + } + + impl trakt_core::Request for Request { + type Response = Response; + const METADATA: Metadata = Metadata { + endpoint: "/comments/{id}", + method: http::Method::PUT, + auth: trakt_core::AuthRequirement::Required, + }; + + fn try_into_http_request<T: Default + BufMut>( + self, + ctx: Context, + ) -> Result<http::Request<T>, IntoHttpError> { + let params = RequestParams { id: self.id }; + let url = + trakt_core::construct_url(ctx.base_url, Self::METADATA.endpoint, ¶ms, &())?; + + let body = T::default(); + let mut writer = body.writer(); + + let json = json!({ + "comment": self.comment, + "spoiler": self.spoiler, + }); + serde_json::to_writer(&mut writer, &json)?; + + let request = http::Request::builder() + .method(Self::METADATA.method) + .uri(url) + .header("Content-Type", "application/json") + .header("trakt-api-version", "2") + .header("trakt-api-key", ctx.client_id); + let request = match ctx.oauth_token { + Some(token) => request.header("Authorization", format!("Bearer {token}")), + None => return Err(IntoHttpError::MissingToken), + }; + + Ok(request.body(writer.into_inner())?) + } + } + + #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] + pub struct Response(pub Comment); +} + +pub mod delete { + //! Delete a comment or reply + //! + //! <https://trakt.docs.apiary.io/#reference/comments/comment/delete-a-comment-or-reply> + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] + #[trakt( + response = Response, + endpoint = "/comments/{id}", + method = DELETE, + auth = Required, + )] + pub struct Request { + pub id: u64, + } + + #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] + #[trakt(expected = NO_CONTENT)] + pub struct Response; +} + +pub mod get_replies { + //! Get comment replies + //! + //! <https://trakt.docs.apiary.io/#reference/comments/comment/get-replies-for-a-comment> + + use crate::smo::Comment; + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] + #[trakt( + response = Response, + endpoint = "/comments/{id}/replies", + auth = Optional, + )] + pub struct Request { + pub id: u64, + } + + #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] + pub struct Response(pub Vec<Comment>); +} + +pub mod post_reply { + //! Post a reply for a comment + //! + //! <https://trakt.docs.apiary.io/#reference/comments/replies/post-a-reply-for-a-comment> + + use bytes::BufMut; + use serde::Serialize; + use serde_json::json; + use trakt_core::{error::IntoHttpError, Context, Metadata}; + + use crate::smo::Comment; + + #[derive(Debug, Clone, Eq, PartialEq, Hash)] + pub struct Request { + pub id: u64, + pub comment: String, + pub spoiler: bool, + } + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize)] + struct RequestParams { + id: u64, + } + + impl trakt_core::Request for Request { + type Response = Response; + const METADATA: Metadata = Metadata { + endpoint: "/comments/{id}/replies", + method: http::Method::POST, + auth: trakt_core::AuthRequirement::Required, + }; + + fn try_into_http_request<T: Default + BufMut>( + self, + ctx: Context, + ) -> Result<http::Request<T>, IntoHttpError> { + let params = RequestParams { id: self.id }; + let url = + trakt_core::construct_url(ctx.base_url, Self::METADATA.endpoint, ¶ms, &())?; + + let body = T::default(); + let mut writer = body.writer(); + + let json = json!({ + "comment": self.comment, + "spoiler": self.spoiler, + }); + serde_json::to_writer(&mut writer, &json)?; + + let request = http::Request::builder() + .method(Self::METADATA.method) + .uri(url) + .header("Content-Type", "application/json") + .header("trakt-api-version", "2") + .header("trakt-api-key", ctx.client_id); + let request = match ctx.oauth_token { + Some(token) => request.header("Authorization", format!("Bearer {token}")), + None => return Err(IntoHttpError::MissingToken), + }; + + Ok(request.body(writer.into_inner())?) + } + } + + #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] + #[trakt(expected = CREATED)] + pub struct Response(pub Comment); +} + +pub mod item { + //! Get attached media item for a comment + //! + //! <https://trakt.docs.apiary.io/#reference/comments/item/get-the-attached-media-item> + + use serde::Deserialize; + + use crate::smo::{Episode, List, Movie, Season, Show}; + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] + #[trakt( + response = Response, + endpoint = "/comments/{id}/item", + )] + pub struct Request { + pub id: u64, + } + + #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] + pub struct Response(pub Item); + + #[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)] + #[serde(rename_all = "lowercase")] + #[serde(tag = "type")] + pub enum Item { + Movie { movie: Box<Movie> }, + Show { show: Box<Show> }, + Season { season: Box<Season> }, + Episode { episode: Box<Episode> }, + List { list: Box<List> }, + } +} + +pub mod likes { + //! Get users who liked a comment + //! + //! <https://trakt.docs.apiary.io/#reference/comments/likes/get-all-users-who-liked-a-comment> + + use time::OffsetDateTime; + use trakt_core::PaginationResponse; + + use crate::smo::User; + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] + #[trakt( + response = Response, + endpoint = "/comments/{id}/likes", + )] + pub struct Request { + pub id: u64, + } + + #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] + pub struct Response { + #[trakt(pagination)] + pub users: PaginationResponse<ResponseItem>, + } + + #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] + pub struct ResponseItem { + #[serde(with = "time::serde::iso8601")] + pub liked_at: OffsetDateTime, + pub user: User, + } +} + +pub mod like { + //! Like a comment + //! + //! <https://trakt.docs.apiary.io/#reference/comments/like/like-a-comment> + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] + #[trakt( + response = Response, + endpoint = "/comments/{id}/like", + method = POST, + auth = Required, + )] + pub struct Request { + pub id: u64, + } + + #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] + #[trakt(expected = NO_CONTENT)] + pub struct Response; +} + +pub mod remove_like { + //! Remove like from a comment + //! + //! <https://trakt.docs.apiary.io/#reference/comments/like/remove-like-on-a-comment> + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] + #[trakt( + response = Response, + endpoint = "/comments/{id}/like", + method = DELETE, + auth = Required, + )] + pub struct Request { + pub id: u64, + } + + #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] + #[trakt(expected = NO_CONTENT)] + pub struct Response; +} + +pub mod trending { + //! Get trending comments + //! + //! <https://trakt.docs.apiary.io/#reference/comments/like/get-trending-comments> + + use trakt_core::PaginationResponse; + + use crate::smo::{CommentItemType, CommentType, CommentWithItem}; + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] + #[trakt( + response = Response, + endpoint = "/comments/trending/{comment_type}/{tp}", + )] + pub struct Request { + pub comment_type: CommentType, + pub tp: CommentItemType, + pub include_replies: bool, + } + + #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] + pub struct Response { + #[trakt(pagination)] + pub comments: PaginationResponse<CommentWithItem>, + } +} + +pub mod recent { + //! Get recently created comments + //! + //! <https://trakt.docs.apiary.io/#reference/comments/trending/get-recently-created-comments> + + use trakt_core::PaginationResponse; + + use crate::smo::{CommentItemType, CommentType, CommentWithItem}; + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] + #[trakt( + response = Response, + endpoint = "/comments/recent/{comment_type}/{tp}", + )] + pub struct Request { + pub comment_type: CommentType, + pub tp: CommentItemType, + pub include_replies: bool, + } + + #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] + pub struct Response { + #[trakt(pagination)] + pub comments: PaginationResponse<CommentWithItem>, + } +} + +pub mod recent_updated { + //! Get recently updated comments + //! + //! <https://trakt.docs.apiary.io/#reference/comments/updates/get-recently-updated-comments> + + use trakt_core::PaginationResponse; + + use crate::smo::{CommentItemType, CommentType, CommentWithItem}; + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)] + #[trakt( + response = Response, + endpoint = "/comments/updates/{comment_type}/{tp}", + )] + pub struct Request { + pub comment_type: CommentType, + pub tp: CommentItemType, + pub include_replies: bool, + } + + #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)] + pub struct Response { + #[trakt(pagination)] + pub comments: PaginationResponse<CommentWithItem>, + } +} + #[cfg(test)] mod tests { use serde_json::json; @@ -181,4 +569,20 @@ mod tests { }; assert_request(CTX, request, "https://api.trakt.tv/comments", &expected); } + + #[test] + fn update_comment_request() { + const COMMENT: &str = "The quick brown fox jumps over the lazy dog."; + + let expected = json!({ + "comment": COMMENT, + "spoiler": false, + }); + let request = update::Request { + id: 42, + comment: COMMENT.to_owned(), + spoiler: false, + }; + assert_request(CTX, request, "https://api.trakt.tv/comments/42", &expected); + } } diff --git a/trakt-rs/src/smo.rs b/trakt-rs/src/smo.rs index 29ce36d..234d20a 100644 --- a/trakt-rs/src/smo.rs +++ b/trakt-rs/src/smo.rs @@ -181,13 +181,13 @@ pub struct UserStats { pub struct List { pub name: EmojiString, pub description: EmojiString, - pub privacy: String, + pub privacy: ListPrivacy, pub share_link: String, pub r#type: ListType, pub display_numbers: bool, pub allow_comments: bool, - pub sort_by: String, - pub sort_how: String, + pub sort_by: ListSortBy, + pub sort_how: ListSortHow, #[serde(with = "time::serde::iso8601")] pub created_at: OffsetDateTime, #[serde(with = "time::serde::iso8601")] @@ -208,6 +208,40 @@ pub enum ListType { Favorites, } +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum ListSortBy { + Rank, + Added, + Title, + Released, + Runtime, + Popularity, + Percentage, + Votes, + MyRating, + Random, + Watched, + Collected, +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum ListSortHow { + Asc, + Desc, +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum ListPrivacy { + #[default] + Private, + Link, + Friends, + Public, +} + #[derive(Debug, Clone, PartialEq, Deserialize)] pub struct Ratings { pub rating: f32, @@ -246,3 +280,50 @@ pub struct Sharing { pub mastodon: bool, pub tumblr: bool, } + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum CommentType { + #[default] + All, + Reviews, + Shouts, +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum CommentItemType { + #[default] + All, + Movies, + Shows, + Seasons, + Episodes, + Lists, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)] +#[serde(rename_all = "lowercase")] +#[serde(tag = "type")] +pub enum CommentWithItem { + Movie { + movie: Box<Movie>, + comment: Comment, + }, + Show { + show: Box<Show>, + comment: Comment, + }, + Season { + season: Box<Season>, + comment: Comment, + }, + Episode { + episode: Box<Episode>, + comment: Comment, + }, + List { + list: Box<List>, + comment: Comment, + }, +} |