1#[allow(unused_imports)]
9use alloc::collections::BTreeMap;
10
11#[allow(unused_imports)]
12use core::marker::PhantomData;
13use jacquard_common::{CowStr, BosStr, DefaultStr, FromStaticStr};
14use jacquard_common::deps::smol_str::SmolStr;
15use jacquard_common::types::ident::AtIdentifier;
16use jacquard_common::types::string::{Language, UriValue};
17use jacquard_common::types::value::Data;
18use jacquard_derive::{IntoStatic, open_union};
19use serde::{Serialize, Deserialize};
20use crate::app_bsky::feed::PostView;
21
22#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
23#[serde(rename_all = "camelCase", bound(deserialize = "S: Deserialize<'de> + BosStr"))]
24pub struct SearchPosts<S: BosStr = DefaultStr> {
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub author: Option<AtIdentifier<S>>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub cursor: Option<S>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub domain: Option<S>,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 pub lang: Option<Language>,
33 #[serde(default = "_default_limit")]
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub limit: Option<i64>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub mentions: Option<AtIdentifier<S>>,
39 pub q: S,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 pub since: Option<S>,
42 #[serde(default = "_default_sort")]
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub sort: Option<S>,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub tag: Option<Vec<S>>,
48 #[serde(skip_serializing_if = "Option::is_none")]
49 pub until: Option<S>,
50 #[serde(skip_serializing_if = "Option::is_none")]
51 pub url: Option<UriValue<S>>,
52}
53
54
55#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
56#[serde(rename_all = "camelCase", bound(deserialize = "S: Deserialize<'de> + BosStr"))]
57pub struct SearchPostsOutput<S: BosStr = DefaultStr> {
58 #[serde(skip_serializing_if = "Option::is_none")]
59 pub cursor: Option<S>,
60 #[serde(skip_serializing_if = "Option::is_none")]
62 pub hits_total: Option<i64>,
63 pub posts: Vec<PostView<S>>,
64 #[serde(flatten, default, skip_serializing_if = "Option::is_none")]
65 pub extra_data: Option<BTreeMap<SmolStr, Data<S>>>,
66}
67
68
69#[derive(
70 Serialize,
71 Deserialize,
72 Debug,
73 Clone,
74 PartialEq,
75 Eq,
76 thiserror::Error,
77 miette::Diagnostic
78)]
79
80#[serde(tag = "error", content = "message")]
81pub enum SearchPostsError {
82 #[serde(rename = "BadQueryString")]
83 BadQueryString(Option<SmolStr>),
84 #[serde(untagged)]
86 Other { error: SmolStr, message: Option<SmolStr> },
87}
88
89impl core::fmt::Display for SearchPostsError {
90 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
91 match self {
92 Self::BadQueryString(msg) => {
93 write!(f, "BadQueryString")?;
94 if let Some(msg) = msg {
95 write!(f, ": {}", msg)?;
96 }
97 Ok(())
98 }
99 Self::Other { error, message } => {
100 write!(f, "{}", error)?;
101 if let Some(msg) = message {
102 write!(f, ": {}", msg)?;
103 }
104 Ok(())
105 }
106 }
107 }
108}
109
110pub struct SearchPostsResponse;
114impl jacquard_common::xrpc::XrpcResp for SearchPostsResponse {
115 const NSID: &'static str = "app.bsky.feed.searchPosts";
116 const ENCODING: &'static str = "application/json";
117 type Output<S: BosStr> = SearchPostsOutput<S>;
118 type Err = SearchPostsError;
119}
120
121impl<S: BosStr> jacquard_common::xrpc::XrpcRequest for SearchPosts<S> {
122 const NSID: &'static str = "app.bsky.feed.searchPosts";
123 const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query;
124 type Response = SearchPostsResponse;
125}
126
127pub struct SearchPostsRequest;
131impl jacquard_common::xrpc::XrpcEndpoint for SearchPostsRequest {
132 const PATH: &'static str = "/xrpc/app.bsky.feed.searchPosts";
133 const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query;
134 type Request<S: BosStr> = SearchPosts<S>;
135 type Response = SearchPostsResponse;
136}
137
138fn _default_limit() -> Option<i64> {
139 Some(25i64)
140}
141
142fn _default_sort<S: jacquard_common::FromStaticStr>() -> Option<S> {
143 Some(S::from_static("latest"))
144}
145
146pub mod search_posts_state {
147
148 pub use crate::builder_types::{Set, Unset, IsSet, IsUnset};
149 #[allow(unused)]
150 use ::core::marker::PhantomData;
151 mod sealed {
152 pub trait Sealed {}
153 }
154 pub trait State: sealed::Sealed {
156 type Q;
157 }
158 pub struct Empty(());
160 impl sealed::Sealed for Empty {}
161 impl State for Empty {
162 type Q = Unset;
163 }
164 pub struct SetQ<St: State = Empty>(PhantomData<fn() -> St>);
166 impl<St: State> sealed::Sealed for SetQ<St> {}
167 impl<St: State> State for SetQ<St> {
168 type Q = Set<members::q>;
169 }
170 #[allow(non_camel_case_types)]
172 pub mod members {
173 pub struct q(());
175 }
176}
177
178pub struct SearchPostsBuilder<St: search_posts_state::State, S: BosStr = DefaultStr> {
180 _state: PhantomData<fn() -> St>,
181 _fields: (
182 Option<AtIdentifier<S>>,
183 Option<S>,
184 Option<S>,
185 Option<Language>,
186 Option<i64>,
187 Option<AtIdentifier<S>>,
188 Option<S>,
189 Option<S>,
190 Option<S>,
191 Option<Vec<S>>,
192 Option<S>,
193 Option<UriValue<S>>,
194 ),
195 _type: PhantomData<fn() -> S>,
196}
197
198impl SearchPosts<DefaultStr> {
199 pub fn new() -> SearchPostsBuilder<search_posts_state::Empty, DefaultStr> {
201 SearchPostsBuilder::new()
202 }
203}
204
205impl<S: BosStr> SearchPosts<S> {
206 pub fn builder() -> SearchPostsBuilder<search_posts_state::Empty, S> {
208 SearchPostsBuilder::builder()
209 }
210}
211
212impl SearchPostsBuilder<search_posts_state::Empty, DefaultStr> {
213 pub fn new() -> Self {
215 SearchPostsBuilder {
216 _state: PhantomData,
217 _fields: (
218 None,
219 None,
220 None,
221 None,
222 None,
223 None,
224 None,
225 None,
226 None,
227 None,
228 None,
229 None,
230 ),
231 _type: PhantomData,
232 }
233 }
234}
235
236impl<S: BosStr> SearchPostsBuilder<search_posts_state::Empty, S> {
237 pub fn builder() -> Self {
239 SearchPostsBuilder {
240 _state: PhantomData,
241 _fields: (
242 None,
243 None,
244 None,
245 None,
246 None,
247 None,
248 None,
249 None,
250 None,
251 None,
252 None,
253 None,
254 ),
255 _type: PhantomData,
256 }
257 }
258}
259
260impl<St: search_posts_state::State, S: BosStr> SearchPostsBuilder<St, S> {
261 pub fn author(mut self, value: impl Into<Option<AtIdentifier<S>>>) -> Self {
263 self._fields.0 = value.into();
264 self
265 }
266 pub fn maybe_author(mut self, value: Option<AtIdentifier<S>>) -> Self {
268 self._fields.0 = value;
269 self
270 }
271}
272
273impl<St: search_posts_state::State, S: BosStr> SearchPostsBuilder<St, S> {
274 pub fn cursor(mut self, value: impl Into<Option<S>>) -> Self {
276 self._fields.1 = value.into();
277 self
278 }
279 pub fn maybe_cursor(mut self, value: Option<S>) -> Self {
281 self._fields.1 = value;
282 self
283 }
284}
285
286impl<St: search_posts_state::State, S: BosStr> SearchPostsBuilder<St, S> {
287 pub fn domain(mut self, value: impl Into<Option<S>>) -> Self {
289 self._fields.2 = value.into();
290 self
291 }
292 pub fn maybe_domain(mut self, value: Option<S>) -> Self {
294 self._fields.2 = value;
295 self
296 }
297}
298
299impl<St: search_posts_state::State, S: BosStr> SearchPostsBuilder<St, S> {
300 pub fn lang(mut self, value: impl Into<Option<Language>>) -> Self {
302 self._fields.3 = value.into();
303 self
304 }
305 pub fn maybe_lang(mut self, value: Option<Language>) -> Self {
307 self._fields.3 = value;
308 self
309 }
310}
311
312impl<St: search_posts_state::State, S: BosStr> SearchPostsBuilder<St, S> {
313 pub fn limit(mut self, value: impl Into<Option<i64>>) -> Self {
315 self._fields.4 = value.into();
316 self
317 }
318 pub fn maybe_limit(mut self, value: Option<i64>) -> Self {
320 self._fields.4 = value;
321 self
322 }
323}
324
325impl<St: search_posts_state::State, S: BosStr> SearchPostsBuilder<St, S> {
326 pub fn mentions(mut self, value: impl Into<Option<AtIdentifier<S>>>) -> Self {
328 self._fields.5 = value.into();
329 self
330 }
331 pub fn maybe_mentions(mut self, value: Option<AtIdentifier<S>>) -> Self {
333 self._fields.5 = value;
334 self
335 }
336}
337
338impl<St, S: BosStr> SearchPostsBuilder<St, S>
339where
340 St: search_posts_state::State,
341 St::Q: search_posts_state::IsUnset,
342{
343 pub fn q(
345 mut self,
346 value: impl Into<S>,
347 ) -> SearchPostsBuilder<search_posts_state::SetQ<St>, S> {
348 self._fields.6 = Option::Some(value.into());
349 SearchPostsBuilder {
350 _state: PhantomData,
351 _fields: self._fields,
352 _type: PhantomData,
353 }
354 }
355}
356
357impl<St: search_posts_state::State, S: BosStr> SearchPostsBuilder<St, S> {
358 pub fn since(mut self, value: impl Into<Option<S>>) -> Self {
360 self._fields.7 = value.into();
361 self
362 }
363 pub fn maybe_since(mut self, value: Option<S>) -> Self {
365 self._fields.7 = value;
366 self
367 }
368}
369
370impl<St: search_posts_state::State, S: BosStr> SearchPostsBuilder<St, S> {
371 pub fn sort(mut self, value: impl Into<Option<S>>) -> Self {
373 self._fields.8 = value.into();
374 self
375 }
376 pub fn maybe_sort(mut self, value: Option<S>) -> Self {
378 self._fields.8 = value;
379 self
380 }
381}
382
383impl<St: search_posts_state::State, S: BosStr> SearchPostsBuilder<St, S> {
384 pub fn tag(mut self, value: impl Into<Option<Vec<S>>>) -> Self {
386 self._fields.9 = value.into();
387 self
388 }
389 pub fn maybe_tag(mut self, value: Option<Vec<S>>) -> Self {
391 self._fields.9 = value;
392 self
393 }
394}
395
396impl<St: search_posts_state::State, S: BosStr> SearchPostsBuilder<St, S> {
397 pub fn until(mut self, value: impl Into<Option<S>>) -> Self {
399 self._fields.10 = value.into();
400 self
401 }
402 pub fn maybe_until(mut self, value: Option<S>) -> Self {
404 self._fields.10 = value;
405 self
406 }
407}
408
409impl<St: search_posts_state::State, S: BosStr> SearchPostsBuilder<St, S> {
410 pub fn url(mut self, value: impl Into<Option<UriValue<S>>>) -> Self {
412 self._fields.11 = value.into();
413 self
414 }
415 pub fn maybe_url(mut self, value: Option<UriValue<S>>) -> Self {
417 self._fields.11 = value;
418 self
419 }
420}
421
422impl<St, S: BosStr> SearchPostsBuilder<St, S>
423where
424 St: search_posts_state::State,
425 St::Q: search_posts_state::IsSet,
426{
427 pub fn build(self) -> SearchPosts<S> {
429 SearchPosts {
430 author: self._fields.0,
431 cursor: self._fields.1,
432 domain: self._fields.2,
433 lang: self._fields.3,
434 limit: self._fields.4,
435 mentions: self._fields.5,
436 q: self._fields.6.unwrap(),
437 since: self._fields.7,
438 sort: self._fields.8,
439 tag: self._fields.9,
440 until: self._fields.10,
441 url: self._fields.11,
442 }
443 }
444}