mangadex_api/v5/user/follows/group/
get.rs

1//! Builder for the followed scanlation groups endpoint.
2//!
3//! <https://api.mangadex.org/docs/swagger.html#/Follows/get-user-follows-group>
4//!
5//! # Examples
6//!
7//! ```rust
8//! use uuid::Uuid;
9//!
10//! use mangadex_api::v5::MangaDexClient;
11//! // use mangadex_api_types::{Password, Username};
12//!
13//! # async fn run() -> anyhow::Result<()> {
14//! let client = MangaDexClient::default();
15//!
16//! /*
17//!
18//!     let _login_res = client
19//!         .auth()
20//!         .login()
21//!         .post()
22//!         .username(Username::parse("myusername")?)
23//!         .password(Password::parse("hunter23")?)
24//!         .send()
25//!         .await?;
26//!
27//!  */
28//!
29//! let res = client
30//!     .user()
31//!     .follows()
32//!     .group()
33//!     .get()
34//!     .limit(1_u32)
35//!     .send()
36//!     .await?;
37//!
38//! println!("followed groups: {:?}", res);
39//! # Ok(())
40//! # }
41//! ```
42
43use derive_builder::Builder;
44use serde::Serialize;
45
46use crate::HttpClientRef;
47use mangadex_api_schema::v5::GroupListResponse;
48use mangadex_api_types::ReferenceExpansionResource;
49
50#[cfg_attr(
51    feature = "deserializable-endpoint",
52    derive(serde::Deserialize, getset::Getters, getset::Setters)
53)]
54#[derive(Debug, Serialize, Clone, Builder, Default)]
55#[serde(rename_all = "camelCase")]
56#[builder(
57    setter(into, strip_option),
58    default,
59    build_fn(error = "mangadex_api_types::error::BuilderError")
60)]
61#[cfg_attr(
62    feature = "custom_list_v2",
63    deprecated(
64        since = "3.0.0-rc.1",
65        note = "After the introduction of the Subscription system, this endpoint will be removed in v3"
66    )
67)]
68pub struct FollowedGroups {
69    /// This should never be set manually as this is only for internal use.
70    #[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_if = "Option::is_none")]
77    pub limit: Option<u32>,
78    #[serde(skip_serializing_if = "Option::is_none")]
79    pub offset: Option<u32>,
80    #[builder(setter(each = "include"), default)]
81    pub includes: Vec<ReferenceExpansionResource>,
82}
83
84endpoint! {
85    GET "/user/follows/group",
86    #[query auth] FollowedGroups,
87    #[flatten_result] GroupListResponse,
88    FollowedGroupsBuilder
89}
90
91#[cfg(test)]
92mod tests {
93    use serde_json::json;
94    use time::OffsetDateTime;
95    use url::Url;
96    use uuid::Uuid;
97    use wiremock::matchers::{header, method, path_regex};
98    use wiremock::{Mock, MockServer, ResponseTemplate};
99
100    use crate::v5::AuthTokens;
101    use crate::{HttpClient, MangaDexClient};
102    use mangadex_api_types::MangaDexDateTime;
103
104    #[tokio::test]
105    async fn get_followed_groups_fires_a_request_to_base_url_ungrouped() -> anyhow::Result<()> {
106        let mock_server = MockServer::start().await;
107        let http_client = HttpClient::builder()
108            .base_url(Url::parse(&mock_server.uri())?)
109            .auth_tokens(AuthTokens {
110                session: "sessiontoken".to_string(),
111                refresh: "refreshtoken".to_string(),
112            })
113            .build()?;
114        let mangadex_client = MangaDexClient::new_with_http_client(http_client);
115
116        let group_id = Uuid::new_v4();
117
118        let datetime = MangaDexDateTime::new(&OffsetDateTime::now_utc());
119
120        let response_body = json!({
121            "result": "ok",
122            "response": "collection",
123            "data": [
124                {
125                    "id": group_id,
126                    "type": "scanlation_group",
127                    "attributes": {
128                        "name": "Scanlation Group",
129                        "altNames": [],
130                        "website": "https://example.org",
131                        "ircServer": null,
132                        "ircChannel": null,
133                        "discord": null,
134                        "contactEmail": null,
135                        "description": null,
136                        "twitter": null,
137                        "focusedLanguages": ["en"],
138                        "locked": false,
139                        "official": false,
140                        "verified": false,
141                        "inactive": false,
142                        "publishDelay": "P6WT5M",
143                        "version": 1,
144                        "createdAt": datetime.to_string(),
145                        "updatedAt": datetime.to_string(),
146                    },
147                    "relationships": []
148                }
149            ],
150            "limit": 1,
151            "offset": 0,
152            "total": 1
153        });
154
155        Mock::given(method("GET"))
156            .and(path_regex(r"/user/follows/group"))
157            .and(header("Authorization", "Bearer sessiontoken"))
158            .respond_with(ResponseTemplate::new(200).set_body_json(response_body))
159            .expect(1)
160            .mount(&mock_server)
161            .await;
162
163        let _ = mangadex_client
164            .user()
165            .follows()
166            .group()
167            .get()
168            .limit(1_u32)
169            .send()
170            .await?;
171
172        Ok(())
173    }
174}