misskey_util/builder/
note.rs1use crate::Error;
2
3use chrono::{DateTime, Duration, Utc};
4#[cfg(feature = "12-47-0")]
5use misskey_api::model::channel::Channel;
6use misskey_api::model::{
7 drive::DriveFile,
8 note::{Note, Visibility},
9 user::User,
10};
11use misskey_api::{endpoint, EntityRef};
12use misskey_core::Client;
13
14fn initial_notes_create_request() -> endpoint::notes::create::Request {
15 endpoint::notes::create::Request {
16 visibility: Some(Visibility::Public),
17 visible_user_ids: None,
18 text: None,
19 cw: None,
20 via_mobile: Some(false),
21 local_only: Some(false),
22 no_extract_mentions: Some(false),
23 no_extract_hashtags: Some(false),
24 no_extract_emojis: Some(false),
25 file_ids: None,
26 reply_id: None,
27 renote_id: None,
28 poll: None,
29 #[cfg(feature = "12-47-0")]
30 channel_id: None,
31 }
32}
33
34fn initial_poll_request() -> endpoint::notes::create::PollRequest {
35 endpoint::notes::create::PollRequest {
36 choices: Vec::new(),
37 multiple: Some(false),
38 expires_at: None,
39 expired_after: None,
40 }
41}
42
43pub struct NoteBuilder<C> {
45 client: C,
46 request: endpoint::notes::create::Request,
47}
48
49impl<C> NoteBuilder<C> {
50 pub fn new(client: C) -> Self {
52 NoteBuilder {
53 client,
54 request: initial_notes_create_request(),
55 }
56 }
57
58 pub fn as_request(&self) -> &endpoint::notes::create::Request {
60 &self.request
61 }
62
63 pub fn text(&mut self, text: impl Into<String>) -> &mut Self {
65 self.request.text.replace(text.into());
66 self
67 }
68
69 pub fn poll(&mut self, choices: impl IntoIterator<Item = impl Into<String>>) -> &mut Self {
71 let choices = choices.into_iter().map(Into::into).collect();
72 if let Some(poll) = self.request.poll.as_mut() {
73 poll.choices = choices;
74 } else {
75 self.request.poll = Some(endpoint::notes::create::PollRequest {
76 choices,
77 ..initial_poll_request()
78 });
79 }
80 self
81 }
82
83 pub fn poll_multiple(&mut self, multiple: bool) -> &mut Self {
85 if let Some(poll) = self.request.poll.as_mut() {
86 poll.multiple.replace(multiple);
87 } else {
88 self.request.poll = Some(endpoint::notes::create::PollRequest {
89 multiple: Some(multiple),
90 ..initial_poll_request()
91 });
92 }
93 self
94 }
95
96 pub fn poll_expires_at(&mut self, at: DateTime<Utc>) -> &mut Self {
98 if let Some(poll) = self.request.poll.as_mut() {
99 poll.expires_at.replace(at);
100 poll.expired_after.take();
101 } else {
102 self.request.poll = Some(endpoint::notes::create::PollRequest {
103 expires_at: Some(at),
104 expired_after: None,
105 ..initial_poll_request()
106 });
107 }
108 self
109 }
110
111 pub fn poll_expires_after(&mut self, after: Duration) -> &mut Self {
113 if let Some(poll) = self.request.poll.as_mut() {
114 poll.expired_after.replace(after);
115 poll.expires_at.take();
116 } else {
117 self.request.poll = Some(endpoint::notes::create::PollRequest {
118 expired_after: Some(after),
119 expires_at: None,
120 ..initial_poll_request()
121 });
122 }
123 self
124 }
125
126 pub fn attach_file(&mut self, file: impl EntityRef<DriveFile>) -> &mut Self {
128 let file_id = file.entity_ref();
129 if let Some(ids) = self.request.file_ids.as_mut() {
130 ids.push(file_id);
131 } else {
132 self.request.file_ids = Some(vec![file_id]);
133 }
134 self
135 }
136
137 pub fn attach_files(
139 &mut self,
140 files: impl IntoIterator<Item = impl EntityRef<DriveFile>>,
141 ) -> &mut Self {
142 let it = files.into_iter().map(|file| file.entity_ref());
143 if let Some(ids) = self.request.file_ids.as_mut() {
144 ids.extend(it);
145 } else {
146 self.request.file_ids = Some(it.collect());
147 }
148 self
149 }
150
151 pub fn visibility(&mut self, visibility: Visibility) -> &mut Self {
153 self.request.visibility = Some(visibility);
154 if !matches!(visibility, Visibility::Specified) {
155 self.request.visible_user_ids.take();
156 }
157 self
158 }
159
160 pub fn public(&mut self) -> &mut Self {
164 self.visibility(Visibility::Public)
165 }
166
167 pub fn home_only(&mut self) -> &mut Self {
171 self.visibility(Visibility::Home)
172 }
173
174 pub fn followers_only(&mut self) -> &mut Self {
178 self.visibility(Visibility::Followers)
179 }
180
181 pub fn direct(
183 &mut self,
184 recipients: impl IntoIterator<Item = impl EntityRef<User>>,
185 ) -> &mut Self {
186 self.visibility(Visibility::Specified);
187 self.request.visible_user_ids.replace(
188 recipients
189 .into_iter()
190 .map(|user| user.entity_ref())
191 .collect(),
192 );
193 self
194 }
195
196 pub fn hide_content(&mut self, cw_text: impl Into<String>) -> &mut Self {
198 self.request.cw.replace(cw_text.into());
199 self
200 }
201
202 pub fn via_mobile(&mut self, via_mobile: bool) -> &mut Self {
204 self.request.via_mobile.replace(via_mobile);
205 self
206 }
207
208 pub fn local_only(&mut self, local_only: bool) -> &mut Self {
210 self.request.local_only.replace(local_only);
211 self
212 }
213
214 pub fn extract_mentions(&mut self, extract_mentions: bool) -> &mut Self {
218 self.request.no_extract_mentions.replace(!extract_mentions);
219 self
220 }
221
222 pub fn extract_hashtags(&mut self, extract_hashtags: bool) -> &mut Self {
226 self.request.no_extract_hashtags.replace(!extract_hashtags);
227 self
228 }
229
230 pub fn extract_emojis(&mut self, extract_emojis: bool) -> &mut Self {
234 self.request.no_extract_emojis.replace(!extract_emojis);
235 self
236 }
237
238 pub fn reply(&mut self, note: impl EntityRef<Note>) -> &mut Self {
240 self.request.reply_id.replace(note.entity_ref());
241 self
242 }
243
244 pub fn renote(&mut self, note: impl EntityRef<Note>) -> &mut Self {
246 self.request.renote_id.replace(note.entity_ref());
247 self
248 }
249
250 #[cfg(feature = "12-47-0")]
252 #[cfg_attr(docsrs, doc(cfg(feature = "12-47-0")))]
253 pub fn channel(&mut self, channel: impl EntityRef<Channel>) -> &mut Self {
254 self.request.channel_id.replace(channel.entity_ref());
255 self
256 }
257}
258
259impl<C: Client> NoteBuilder<C> {
260 pub async fn create(&self) -> Result<Note, Error<C::Error>> {
262 let response = self
263 .client
264 .request(&self.request)
265 .await
266 .map_err(Error::Client)?
267 .into_result()?;
268 Ok(response.created_note)
269 }
270}