mangadex_api/v5/manga/id/read/
post.rs1use derive_builder::Builder;
48use serde::Serialize;
49use uuid::Uuid;
50
51use crate::HttpClientRef;
52use mangadex_api_schema::NoData;
53use mangadex_api_types::error::Result;
54
55#[cfg_attr(
59 feature = "deserializable-endpoint",
60 derive(serde::Deserialize, getset::Getters, getset::Setters)
61)]
62#[derive(Debug, Serialize, Clone, Builder, Default)]
63#[serde(rename_all = "camelCase")]
64#[builder(
65 setter(into, strip_option),
66 build_fn(error = "mangadex_api_types::error::BuilderError")
67)]
68pub struct MarkChapterBatch {
69 #[doc(hidden)]
71 #[serde(skip)]
72 #[builder(pattern = "immutable")]
73 #[cfg_attr(feature = "deserializable-endpoint", getset(set = "pub", get = "pub"))]
74 pub http_client: HttpClientRef,
75
76 #[serde(skip_serializing)]
77 pub manga_id: Uuid,
78 #[builder(setter(each = "mark_chapter_read"), default)]
79 pub chapter_ids_read: Vec<Uuid>,
80 #[builder(setter(each = "mark_chapter_unread"), default)]
81 pub chapter_ids_unread: Vec<Uuid>,
82 #[serde(skip_serializing)]
83 #[builder(default)]
84 pub update_history: bool,
85}
86
87endpoint! {
88 POST ("/manga/{}/read?updateHistory={}", manga_id, update_history),
89 #[body auth] MarkChapterBatch,
90 #[discard_result] Result<NoData>,
91 MarkChapterBatchBuilder
92}
93
94#[cfg(test)]
95mod tests {
96 use serde_json::json;
97 use url::Url;
98 use uuid::Uuid;
99 use wiremock::matchers::{body_json, header, method, path_regex};
100 use wiremock::{Mock, MockServer, ResponseTemplate};
101
102 use crate::v5::AuthTokens;
103 use crate::{HttpClient, MangaDexClient};
104
105 #[tokio::test]
106 async fn mark_manga_chapters_read_fires_a_request_to_base_url() -> anyhow::Result<()> {
107 let mock_server = MockServer::start().await;
108 let http_client: HttpClient = HttpClient::builder()
109 .base_url(Url::parse(&mock_server.uri())?)
110 .auth_tokens(AuthTokens {
111 session: "sessiontoken".to_string(),
112 refresh: "refreshtoken".to_string(),
113 })
114 .build()?;
115 let mangadex_client = MangaDexClient::new_with_http_client(http_client);
116
117 let manga_id = Uuid::new_v4();
118 let read_chapter_id = Uuid::new_v4();
119 let unread_chapter_id = Uuid::new_v4();
120 let expected_body = json!({
121 "chapterIdsRead": [read_chapter_id],
122 "chapterIdsUnread": [unread_chapter_id]
123 });
124 let response_body = json!({"result": "ok"});
125
126 Mock::given(method("POST"))
127 .and(path_regex(r"/manga/[0-9a-fA-F-]+/read"))
128 .and(header("Authorization", "Bearer sessiontoken"))
129 .and(body_json(expected_body))
130 .respond_with(ResponseTemplate::new(200).set_body_json(response_body))
131 .expect(1)
132 .mount(&mock_server)
133 .await;
134
135 mangadex_client
136 .manga()
137 .id(manga_id)
138 .read()
139 .post()
140 .mark_chapter_read(read_chapter_id)
141 .mark_chapter_unread(unread_chapter_id)
142 .send()
143 .await?;
144
145 Ok(())
146 }
147}