Skip to main content

proto_blue_api/generated/app/bsky/feed/
searchPosts.rs

1// Generated by atproto-codegen. Do not edit.
2//! Lexicon: app.bsky.feed.searchPosts
3#![allow(clippy::pedantic, clippy::nursery, clippy::all)]
4
5use serde::{Deserialize, Serialize};
6
7/// Find posts matching search criteria, returning views of those posts. Note that this API endpoint may require authentication (eg, not public) for some service providers and implementations.
8/// XRPC Query: app.bsky.feed.searchPosts
9#[derive(Debug, Clone, Serialize, Deserialize)]
10#[serde(rename_all = "camelCase")]
11pub struct Params {
12    #[serde(skip_serializing_if = "Option::is_none")]
13    pub author: Option<proto_blue_syntax::AtIdentifier>,
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub cursor: Option<String>,
16    #[serde(skip_serializing_if = "Option::is_none")]
17    pub domain: Option<String>,
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub lang: Option<String>,
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub limit: Option<i64>,
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub mentions: Option<proto_blue_syntax::AtIdentifier>,
24    pub q: String,
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub since: Option<String>,
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub sort: Option<String>,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub tag: Option<Vec<String>>,
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub until: Option<String>,
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub url: Option<String>,
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
38#[serde(rename_all = "camelCase")]
39pub struct Output {
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub cursor: Option<String>,
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub hits_total: Option<i64>,
44    pub posts: Vec<crate::app::bsky::feed::defs::PostView>,
45}
46
47/// Errors a `call()` on this method can return.
48#[derive(Debug, thiserror::Error)]
49pub enum CallError {
50    #[error("BadQueryString")]
51    BadQueryString,
52    #[error("{0}")]
53    Xrpc(proto_blue_xrpc::XrpcError),
54    #[error(transparent)]
55    Transport(#[from] proto_blue_xrpc::Error),
56    #[error(transparent)]
57    Json(#[from] serde_json::Error),
58}
59
60fn map_xrpc_error(err: proto_blue_xrpc::XrpcError) -> CallError {
61    match err.error.as_deref() {
62        Some("BadQueryString") => CallError::BadQueryString,
63        _ => CallError::Xrpc(err),
64    }
65}
66
67fn to_query_params(p: &Params) -> proto_blue_xrpc::QueryParams {
68    let mut qp = proto_blue_xrpc::QueryParams::new();
69    if let Some(v) = &p.author {
70        qp.insert(
71            "author".to_string(),
72            proto_blue_xrpc::QueryValue::String(v.to_string()),
73        );
74    }
75    if let Some(v) = &p.cursor {
76        qp.insert(
77            "cursor".to_string(),
78            proto_blue_xrpc::QueryValue::String(v.to_string()),
79        );
80    }
81    if let Some(v) = &p.domain {
82        qp.insert(
83            "domain".to_string(),
84            proto_blue_xrpc::QueryValue::String(v.to_string()),
85        );
86    }
87    if let Some(v) = &p.lang {
88        qp.insert(
89            "lang".to_string(),
90            proto_blue_xrpc::QueryValue::String(v.to_string()),
91        );
92    }
93    if let Some(v) = &p.limit {
94        qp.insert(
95            "limit".to_string(),
96            proto_blue_xrpc::QueryValue::Integer(*v),
97        );
98    }
99    if let Some(v) = &p.mentions {
100        qp.insert(
101            "mentions".to_string(),
102            proto_blue_xrpc::QueryValue::String(v.to_string()),
103        );
104    }
105    {
106        let v = &p.q;
107        qp.insert(
108            "q".to_string(),
109            proto_blue_xrpc::QueryValue::String(v.to_string()),
110        );
111    }
112    if let Some(v) = &p.since {
113        qp.insert(
114            "since".to_string(),
115            proto_blue_xrpc::QueryValue::String(v.to_string()),
116        );
117    }
118    if let Some(v) = &p.sort {
119        qp.insert(
120            "sort".to_string(),
121            proto_blue_xrpc::QueryValue::String(v.to_string()),
122        );
123    }
124    if let Some(v) = &p.tag {
125        qp.insert(
126            "tag".to_string(),
127            proto_blue_xrpc::QueryValue::Array(
128                v.iter()
129                    .map(|x| proto_blue_xrpc::QueryValue::String(x.to_string()))
130                    .collect(),
131            ),
132        );
133    }
134    if let Some(v) = &p.until {
135        qp.insert(
136            "until".to_string(),
137            proto_blue_xrpc::QueryValue::String(v.to_string()),
138        );
139    }
140    if let Some(v) = &p.url {
141        qp.insert(
142            "url".to_string(),
143            proto_blue_xrpc::QueryValue::String(v.to_string()),
144        );
145    }
146    qp
147}
148
149/// Execute the query.
150pub async fn call(
151    client: &proto_blue_xrpc::XrpcClient,
152    params: Option<&Params>,
153    opts: Option<&proto_blue_xrpc::CallOptions>,
154) -> Result<Output, CallError> {
155    let qp = params.map(to_query_params);
156    let response = match client
157        .query("app.bsky.feed.searchPosts", qp.as_ref(), opts)
158        .await
159    {
160        Ok(r) => r,
161        Err(proto_blue_xrpc::Error::Xrpc(x)) => return Err(map_xrpc_error(x)),
162        Err(e) => return Err(CallError::Transport(e)),
163    };
164    Ok(serde_json::from_value(response.data)?)
165}
166
167/// Register a typed handler for this method on an [`proto_blue_xrpc::XrpcServer`].
168#[cfg(feature = "server")]
169pub fn register<F, Fut>(
170    server: proto_blue_xrpc::XrpcServer,
171    handler: F,
172) -> proto_blue_xrpc::XrpcServer
173where
174    F: Fn(proto_blue_xrpc::HandlerContext, Option<Params>) -> Fut + Send + Sync + 'static,
175    Fut: std::future::Future<Output = Result<Output, proto_blue_xrpc::XrpcServerError>>
176        + Send
177        + 'static,
178{
179    let handler = std::sync::Arc::new(handler);
180    server.query("app.bsky.feed.searchPosts", move |ctx| {
181        let handler = handler.clone();
182        async move {
183            let params = params_from_ctx(&ctx);
184            let out = handler(ctx, params).await?;
185            let value = serde_json::to_value(&out).map_err(|e| {
186                proto_blue_xrpc::XrpcServerError::new(
187                    proto_blue_xrpc::ResponseType::InternalServerError,
188                    format!("output serialize: {e}"),
189                )
190            })?;
191            Ok::<_, proto_blue_xrpc::XrpcServerError>(value)
192        }
193    })
194}
195
196#[cfg(feature = "server")]
197fn params_from_ctx(ctx: &proto_blue_xrpc::HandlerContext) -> Option<Params> {
198    // Always construct a `Params` — required fields are
199    // validated upstream by the lexicon validator when enabled;
200    // missing values surface as runtime errors from the handler.
201    Some(Params {
202        author: ctx
203            .params
204            .get("author")
205            .and_then(|v| proto_blue_syntax::AtIdentifier::new(v).ok()),
206        cursor: ctx.params.get("cursor").cloned(),
207        domain: ctx.params.get("domain").cloned(),
208        lang: ctx.params.get("lang").cloned(),
209        limit: ctx.params.get("limit").and_then(|v| v.parse::<i64>().ok()),
210        mentions: ctx
211            .params
212            .get("mentions")
213            .and_then(|v| proto_blue_syntax::AtIdentifier::new(v).ok()),
214        q: (ctx.params.get("q").cloned())?,
215        since: ctx.params.get("since").cloned(),
216        sort: ctx.params.get("sort").cloned(),
217        tag: Some(
218            ctx.params
219                .get("tag")
220                .map(|v| v.split(',').map(String::from).collect::<Vec<_>>())
221                .unwrap_or_default(),
222        ),
223        until: ctx.params.get("until").cloned(),
224        url: ctx.params.get("url").cloned(),
225    })
226}