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