1use crate::model::{drive::DriveFile, id::Id, page::Page, query::Query, user::User};
2
3use serde::Serialize;
4use typed_builder::TypedBuilder;
5
6#[derive(Serialize, Default, Debug, Clone)]
7pub struct UserFieldRequest {
8 pub name: Option<String>,
9 pub value: Option<String>,
10}
11
12#[derive(Serialize, Default, Debug, Clone, TypedBuilder)]
13#[serde(rename_all = "camelCase")]
14#[builder(doc)]
15pub struct Request {
16 #[serde(skip_serializing_if = "Option::is_none")]
17 #[builder(default, setter(strip_option))]
18 pub name: Option<Option<String>>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 #[builder(default, setter(strip_option))]
21 pub description: Option<Option<String>>,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 #[builder(default, setter(strip_option))]
24 pub lang: Option<Option<String>>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 #[builder(default, setter(strip_option))]
27 pub location: Option<Option<String>>,
28 #[serde(skip_serializing_if = "Option::is_none")]
29 #[builder(default, setter(strip_option))]
30 pub birthday: Option<Option<String>>,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 #[builder(default, setter(strip_option))]
33 pub avatar_id: Option<Option<Id<DriveFile>>>,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 #[builder(default, setter(strip_option))]
36 pub banner_id: Option<Option<Id<DriveFile>>>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 #[builder(default, setter(strip_option))]
39 pub fields: Option<[UserFieldRequest; 4]>,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 #[builder(default, setter(strip_option))]
42 pub is_locked: Option<bool>,
43 #[cfg(feature = "12-63-0")]
44 #[cfg_attr(docsrs, doc(cfg(feature = "12-63-0")))]
45 #[serde(skip_serializing_if = "Option::is_none")]
46 #[builder(default, setter(strip_option))]
47 pub is_explorable: Option<bool>,
48 #[serde(skip_serializing_if = "Option::is_none")]
49 #[builder(default, setter(strip_option))]
50 pub careful_bot: Option<bool>,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 #[builder(default, setter(strip_option))]
53 pub auto_accept_followed: Option<bool>,
54 #[serde(skip_serializing_if = "Option::is_none")]
55 #[builder(default, setter(strip_option))]
56 pub is_bot: Option<bool>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 #[builder(default, setter(strip_option))]
59 pub is_cat: Option<bool>,
60 #[cfg(any(docsrs, not(feature = "12-55-0")))]
61 #[cfg_attr(docsrs, doc(cfg(not(feature = "12-55-0"))))]
62 #[serde(skip_serializing_if = "Option::is_none")]
63 #[builder(default, setter(strip_option))]
64 pub auto_watch: Option<bool>,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 #[builder(default, setter(strip_option))]
67 pub inject_featured_note: Option<bool>,
68 #[serde(skip_serializing_if = "Option::is_none")]
69 #[builder(default, setter(strip_option))]
70 pub always_mark_nsfw: Option<bool>,
71 #[serde(skip_serializing_if = "Option::is_none")]
72 #[builder(default, setter(strip_option))]
73 pub pinned_page_id: Option<Option<Id<Page>>>,
74 #[serde(skip_serializing_if = "Option::is_none")]
75 #[builder(default, setter(strip_option))]
76 pub muted_words: Option<Query<String>>,
77 #[cfg(feature = "12-60-0")]
78 #[cfg_attr(docsrs, doc(cfg(feature = "12-60-0")))]
79 #[serde(skip_serializing_if = "Option::is_none")]
80 #[builder(default, setter(strip_option))]
81 pub no_crawle: Option<bool>,
82}
83
84impl misskey_core::Request for Request {
85 type Response = User;
86 const ENDPOINT: &'static str = "i/update";
87}
88
89#[cfg(test)]
90mod tests {
91 use super::{Request, UserFieldRequest};
92 use crate::test::{ClientExt, TestClient};
93
94 #[tokio::test]
95 async fn request() {
96 let client = TestClient::new();
97 client.test(Request::default()).await;
98 }
99
100 #[tokio::test]
101 async fn request_with_options() {
102 use crate::model::query::Query;
103
104 let client = TestClient::new();
105 client
106 .test(Request {
107 name: Some(Some("test".to_string())),
108 description: Some(Some("test description".to_string())),
109 lang: Some(Some("ja-JP".to_string())),
110 location: Some(Some("somewhere".to_string())),
111 birthday: None,
112 avatar_id: None,
113 banner_id: None,
114 fields: Some([
115 UserFieldRequest {
116 name: Some("key".to_string()),
117 value: Some("value".to_string()),
118 },
119 Default::default(),
120 Default::default(),
121 Default::default(),
122 ]),
123 is_locked: Some(true),
124 #[cfg(feature = "12-63-0")]
125 is_explorable: Some(false),
126 careful_bot: Some(true),
127 auto_accept_followed: Some(true),
128 is_bot: Some(true),
129 is_cat: Some(true),
130 #[cfg(not(feature = "12-55-0"))]
131 auto_watch: Some(true),
132 inject_featured_note: Some(true),
133 always_mark_nsfw: Some(true),
134 pinned_page_id: None,
135 muted_words: Some(Query::from_vec(vec![
136 vec!["mute1".to_string(), "mute2".to_string()],
137 vec!["mute3".to_string()],
138 ])),
139 #[cfg(feature = "12-60-0")]
140 no_crawle: Some(true),
141 })
142 .await;
143 }
144
145 #[tokio::test]
146 async fn request_with_null_options() {
147 let client = TestClient::new();
148 client
149 .test(Request {
150 name: Some(None),
151 description: Some(None),
152 lang: Some(None),
153 location: Some(None),
154 birthday: Some(None),
155 avatar_id: Some(None),
156 banner_id: Some(None),
157 fields: None,
158 is_locked: None,
159 #[cfg(feature = "12-63-0")]
160 is_explorable: None,
161 careful_bot: None,
162 auto_accept_followed: None,
163 is_bot: None,
164 is_cat: None,
165 #[cfg(not(feature = "12-55-0"))]
166 auto_watch: None,
167 inject_featured_note: None,
168 always_mark_nsfw: None,
169 pinned_page_id: Some(None),
170 muted_words: None,
171 #[cfg(feature = "12-60-0")]
172 no_crawle: None,
173 })
174 .await;
175 }
176}