misskey_api/endpoint/users/
notes.rs

1use crate::model::{id::Id, note::Note, user::User};
2
3use chrono::{serde::ts_milliseconds_option, DateTime, Utc};
4use mime::Mime;
5use serde::Serialize;
6use typed_builder::TypedBuilder;
7
8#[derive(Serialize, Debug, Clone, TypedBuilder)]
9#[serde(rename_all = "camelCase")]
10#[builder(doc)]
11pub struct Request {
12    pub user_id: Id<User>,
13    #[serde(skip_serializing_if = "Option::is_none")]
14    #[builder(default, setter(strip_option))]
15    pub include_replies: Option<bool>,
16    #[serde(skip_serializing_if = "Option::is_none")]
17    #[builder(default, setter(strip_option))]
18    pub include_my_renotes: Option<bool>,
19    #[serde(skip_serializing_if = "Option::is_none")]
20    #[builder(default, setter(strip_option))]
21    pub with_files: Option<bool>,
22    #[serde(
23        skip_serializing_if = "Option::is_none",
24        serialize_with = "crate::serde::serialize_string_vec_option"
25    )]
26    #[builder(default, setter(strip_option))]
27    pub file_type: Option<Vec<Mime>>,
28    #[serde(skip_serializing_if = "Option::is_none")]
29    #[builder(default, setter(strip_option))]
30    pub exclude_nsfw: Option<bool>,
31    /// 1 .. 100
32    #[serde(skip_serializing_if = "Option::is_none")]
33    #[builder(default, setter(strip_option))]
34    pub limit: Option<u8>,
35    #[serde(skip_serializing_if = "Option::is_none")]
36    #[builder(default, setter(strip_option))]
37    pub since_id: Option<Id<Note>>,
38    #[serde(skip_serializing_if = "Option::is_none")]
39    #[builder(default, setter(strip_option))]
40    pub until_id: Option<Id<Note>>,
41    #[serde(
42        skip_serializing_if = "Option::is_none",
43        with = "ts_milliseconds_option"
44    )]
45    #[builder(default, setter(strip_option, into))]
46    pub since_date: Option<DateTime<Utc>>,
47    #[serde(
48        skip_serializing_if = "Option::is_none",
49        with = "ts_milliseconds_option"
50    )]
51    #[builder(default, setter(strip_option, into))]
52    pub until_date: Option<DateTime<Utc>>,
53}
54
55impl misskey_core::Request for Request {
56    type Response = Vec<Note>;
57    const ENDPOINT: &'static str = "users/notes";
58}
59
60impl_pagination!(Request, Note);
61
62#[cfg(test)]
63mod tests {
64    use super::Request;
65    use crate::test::{ClientExt, TestClient};
66
67    use mime::IMAGE_PNG;
68
69    #[tokio::test]
70    async fn request() {
71        let client = TestClient::new();
72        let user = client.me().await;
73
74        client
75            .test(Request {
76                user_id: user.id,
77                include_replies: None,
78                include_my_renotes: None,
79                with_files: None,
80                file_type: None,
81                exclude_nsfw: None,
82                limit: None,
83                since_id: None,
84                until_id: None,
85                since_date: None,
86                until_date: None,
87            })
88            .await;
89    }
90
91    #[tokio::test]
92    async fn request_with_options() {
93        let client = TestClient::new();
94        let user = client.me().await;
95
96        client
97            .test(Request {
98                user_id: user.id,
99                include_replies: Some(false),
100                include_my_renotes: Some(false),
101                with_files: Some(true),
102                file_type: Some(vec![IMAGE_PNG]),
103                exclude_nsfw: Some(true),
104                limit: None,
105                since_id: None,
106                until_id: None,
107                since_date: None,
108                until_date: None,
109            })
110            .await;
111    }
112
113    #[tokio::test]
114    async fn request_with_limit() {
115        let client = TestClient::new();
116        let user = client.me().await;
117
118        client
119            .test(Request {
120                user_id: user.id,
121                include_replies: None,
122                include_my_renotes: None,
123                with_files: None,
124                file_type: None,
125                exclude_nsfw: None,
126                limit: Some(100),
127                since_id: None,
128                until_id: None,
129                since_date: None,
130                until_date: None,
131            })
132            .await;
133    }
134
135    #[tokio::test]
136    async fn request_paginate() {
137        let client = TestClient::new();
138        let user = client.me().await;
139        let note = client.create_note(Some("test"), None, None).await;
140
141        client
142            .test(Request {
143                user_id: user.id,
144                include_replies: None,
145                include_my_renotes: None,
146                with_files: None,
147                file_type: None,
148                exclude_nsfw: None,
149                limit: None,
150                since_id: Some(note.id.clone()),
151                until_id: Some(note.id.clone()),
152                since_date: None,
153                until_date: None,
154            })
155            .await;
156    }
157
158    #[tokio::test]
159    async fn request_with_date() {
160        let client = TestClient::new();
161        let user = client.me().await;
162        let now = chrono::Utc::now();
163
164        client
165            .test(Request {
166                user_id: user.id,
167                include_replies: None,
168                include_my_renotes: None,
169                with_files: None,
170                file_type: None,
171                exclude_nsfw: None,
172                limit: None,
173                since_id: None,
174                until_id: None,
175                since_date: Some(now),
176                until_date: Some(now),
177            })
178            .await;
179    }
180}