Skip to main content

hanzo_client/apis/
channels_api.rs

1/*
2 * Hanzo Cloud API
3 *
4 * The Hanzo Cloud API as a customer calls it: every operation under /v1/ except the operator's admin product, relay routes, legacy spellings and capabilities still reached by flag. Tagged by product: the first path segment after /v1/.
5 *
6 * The version of the OpenAPI document: v1
7 * 
8 * Generated by: https://openapi-generator.tech
9 */
10
11
12use reqwest;
13use serde::{Deserialize, Serialize, de::Error as _};
14use crate::{apis::ResponseContent, models};
15use super::{Error, configuration, ContentType};
16
17
18/// struct for typed errors of method [`get_channels`]
19#[derive(Debug, Clone, Serialize, Deserialize)]
20#[serde(untagged)]
21pub enum GetChannelsError {
22    UnknownValue(serde_json::Value),
23}
24
25/// struct for typed errors of method [`get_channels_allowlist`]
26#[derive(Debug, Clone, Serialize, Deserialize)]
27#[serde(untagged)]
28pub enum GetChannelsAllowlistError {
29    UnknownValue(serde_json::Value),
30}
31
32/// struct for typed errors of method [`get_channels_inbox`]
33#[derive(Debug, Clone, Serialize, Deserialize)]
34#[serde(untagged)]
35pub enum GetChannelsInboxError {
36    UnknownValue(serde_json::Value),
37}
38
39/// struct for typed errors of method [`get_channels_pairing`]
40#[derive(Debug, Clone, Serialize, Deserialize)]
41#[serde(untagged)]
42pub enum GetChannelsPairingError {
43    UnknownValue(serde_json::Value),
44}
45
46/// struct for typed errors of method [`post_channels_by_channel_send`]
47#[derive(Debug, Clone, Serialize, Deserialize)]
48#[serde(untagged)]
49pub enum PostChannelsByChannelSendError {
50    UnknownValue(serde_json::Value),
51}
52
53/// struct for typed errors of method [`post_channels_pairing_approve`]
54#[derive(Debug, Clone, Serialize, Deserialize)]
55#[serde(untagged)]
56pub enum PostChannelsPairingApproveError {
57    UnknownValue(serde_json::Value),
58}
59
60/// struct for typed errors of method [`put_channels_allowlist`]
61#[derive(Debug, Clone, Serialize, Deserialize)]
62#[serde(untagged)]
63pub enum PutChannelsAllowlistError {
64    UnknownValue(serde_json::Value),
65}
66
67
68/// Reports every chat channel this org can send through, and whether it can send through it right now.  A channel appears here whether or not it is connected — an empty list would leave a caller unable to tell \"this org has no Slack\" from \"Slack is down\", which are different problems with different fixes. Each entry carries the connection behind it, so the answer to \"why can I not post?\" is in the same response as the channel that cannot post.
69pub async fn get_channels(configuration: &configuration::Configuration, ) -> Result<models::ChatChannels, Error<GetChannelsError>> {
70
71    let uri_str = format!("{}/v1/channels", configuration.base_path);
72    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
73
74    if let Some(ref user_agent) = configuration.user_agent {
75        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
76    }
77    if let Some(ref token) = configuration.bearer_access_token {
78        req_builder = req_builder.bearer_auth(token.to_owned());
79    };
80
81    let req = req_builder.build()?;
82    let resp = configuration.client.execute(req).await?;
83
84    let status = resp.status();
85    let content_type = resp
86        .headers()
87        .get("content-type")
88        .and_then(|v| v.to_str().ok())
89        .unwrap_or("application/octet-stream");
90    let content_type = super::ContentType::from(content_type);
91
92    if !status.is_client_error() && !status.is_server_error() {
93        let content = resp.text().await?;
94        match content_type {
95            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
96            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::ChatChannels`"))),
97            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::ChatChannels`")))),
98        }
99    } else {
100        let content = resp.text().await?;
101        let entity: Option<GetChannelsError> = serde_json::from_str(&content).ok();
102        Err(Error::ResponseError(ResponseContent { status, content, entity }))
103    }
104}
105
106/// Returns the caller org's access policy for one channel: whether DMs are pairing-gated, allowlisted or open, whether group rooms are open, allowlisted or disabled, the config-managed DM and group allow entries, the senders approved through PAIRING (read-only here), and the org's named access groups. An unknown channel is a 404.
107pub async fn get_channels_allowlist(configuration: &configuration::Configuration, channel: Option<&str>) -> Result<models::AllowlistView, Error<GetChannelsAllowlistError>> {
108    // add a prefix to parameters to efficiently prevent name collisions
109    let p_channel = channel;
110
111    let uri_str = format!("{}/v1/channels/allowlist", configuration.base_path);
112    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
113
114    if let Some(ref param_value) = p_channel {
115        req_builder = req_builder.query(&[("channel", &param_value.to_string())]);
116    }
117    if let Some(ref user_agent) = configuration.user_agent {
118        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
119    }
120    if let Some(ref token) = configuration.bearer_access_token {
121        req_builder = req_builder.bearer_auth(token.to_owned());
122    };
123
124    let req = req_builder.build()?;
125    let resp = configuration.client.execute(req).await?;
126
127    let status = resp.status();
128    let content_type = resp
129        .headers()
130        .get("content-type")
131        .and_then(|v| v.to_str().ok())
132        .unwrap_or("application/octet-stream");
133    let content_type = super::ContentType::from(content_type);
134
135    if !status.is_client_error() && !status.is_server_error() {
136        let content = resp.text().await?;
137        match content_type {
138            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
139            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::AllowlistView`"))),
140            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::AllowlistView`")))),
141        }
142    } else {
143        let content = resp.text().await?;
144        let entity: Option<GetChannelsAllowlistError> = serde_json::from_str(&content).ok();
145        Err(Error::ResponseError(ResponseContent { status, content, entity }))
146    }
147}
148
149/// Returns the messages people have sent to the caller org's connected chat bots, oldest first, in the portable envelope shape every transport normalises into. It is a CURSOR feed, not a search: pass the returned cursor back as `since` to get only what has arrived since. Only this org's messages are stored under this org, so the feed can never carry another tenant's chat.
150pub async fn get_channels_inbox(configuration: &configuration::Configuration, since: Option<&str>, limit: Option<&str>) -> Result<models::InboxPage, Error<GetChannelsInboxError>> {
151    // add a prefix to parameters to efficiently prevent name collisions
152    let p_since = since;
153    let p_limit = limit;
154
155    let uri_str = format!("{}/v1/channels/inbox", configuration.base_path);
156    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
157
158    if let Some(ref param_value) = p_since {
159        req_builder = req_builder.query(&[("since", &param_value.to_string())]);
160    }
161    if let Some(ref param_value) = p_limit {
162        req_builder = req_builder.query(&[("limit", &param_value.to_string())]);
163    }
164    if let Some(ref user_agent) = configuration.user_agent {
165        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
166    }
167    if let Some(ref token) = configuration.bearer_access_token {
168        req_builder = req_builder.bearer_auth(token.to_owned());
169    };
170
171    let req = req_builder.build()?;
172    let resp = configuration.client.execute(req).await?;
173
174    let status = resp.status();
175    let content_type = resp
176        .headers()
177        .get("content-type")
178        .and_then(|v| v.to_str().ok())
179        .unwrap_or("application/octet-stream");
180    let content_type = super::ContentType::from(content_type);
181
182    if !status.is_client_error() && !status.is_server_error() {
183        let content = resp.text().await?;
184        match content_type {
185            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
186            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::InboxPage`"))),
187            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::InboxPage`")))),
188        }
189    } else {
190        let content = resp.text().await?;
191        let entity: Option<GetChannelsInboxError> = serde_json::from_str(&content).ok();
192        Err(Error::ResponseError(ResponseContent { status, content, entity }))
193    }
194}
195
196/// Returns the pairing requests waiting for the caller org to approve — one per person who messaged a connected bot on a channel whose DM policy is \"pairing\" and who is not allowed yet. Each row carries the CODE an org admin passes to POST /v1/channels/pairing/approve. Expired requests are not returned. Codes are capability strings: they are shown here, and never logged.
197pub async fn get_channels_pairing(configuration: &configuration::Configuration, ) -> Result<models::PairingQueue, Error<GetChannelsPairingError>> {
198
199    let uri_str = format!("{}/v1/channels/pairing", configuration.base_path);
200    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
201
202    if let Some(ref user_agent) = configuration.user_agent {
203        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
204    }
205    if let Some(ref token) = configuration.bearer_access_token {
206        req_builder = req_builder.bearer_auth(token.to_owned());
207    };
208
209    let req = req_builder.build()?;
210    let resp = configuration.client.execute(req).await?;
211
212    let status = resp.status();
213    let content_type = resp
214        .headers()
215        .get("content-type")
216        .and_then(|v| v.to_str().ok())
217        .unwrap_or("application/octet-stream");
218    let content_type = super::ContentType::from(content_type);
219
220    if !status.is_client_error() && !status.is_server_error() {
221        let content = resp.text().await?;
222        match content_type {
223            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
224            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::PairingQueue`"))),
225            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::PairingQueue`")))),
226        }
227    } else {
228        let content = resp.text().await?;
229        let entity: Option<GetChannelsPairingError> = serde_json::from_str(&content).ok();
230        Err(Error::ResponseError(ResponseContent { status, content, entity }))
231    }
232}
233
234/// Delivers text, attachments and actions to one room on a connected chat transport — discord, slack, teams, telegram or whatsapp — and answers that transport's own receipt, the `messageId` it assigned and the Unix second it landed. An unknown channel is a 404.  The body is the envelope's NARROW outbound projection: `room`, `text`, `attachments`, `actions`, `replyTo` and `idempotency`, and nothing else. Identity is not a field — the channel is the path segment and the sender is the caller's validated org — so a body carrying `sender`, `account` or `channel` is refused with 400 rather than having it silently dropped. `room.id` is required, and so is something to say: text, or at least one attachment.  Requires a validated principal; 403 without one. The room must already belong to the caller's org — each transport verifies the binding itself, so a room this org has not bound is 403 and a room whose route the bot has never learned is 409, meaning someone has to message the bot there first. A route learned only so a pairing reply could be delivered lasts exactly as long as that pairing request does, so a room whose sender was never approved goes back to 409 within the hour. A transport that fails answers 502 carrying status and shape only, never a token.  Sending is at-most-once only if you ask for it: pass an `idempotency` string and a replay answers 200 with the PRIOR receipt instead of sending twice, while a send that fails releases the key so the caller can re-attempt. Bodies over 1 MiB are refused. Every transport currently renders text only, so attachments and actions are flattened deterministically to one line each after the text rather than dropped.
235pub async fn post_channels_by_channel_send(configuration: &configuration::Configuration, channel: &str) -> Result<(), Error<PostChannelsByChannelSendError>> {
236    // add a prefix to parameters to efficiently prevent name collisions
237    let p_channel = channel;
238
239    let uri_str = format!("{}/v1/channels/{channel}/send", configuration.base_path, channel=crate::apis::urlencode(p_channel));
240    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
241
242    if let Some(ref user_agent) = configuration.user_agent {
243        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
244    }
245    if let Some(ref token) = configuration.bearer_access_token {
246        req_builder = req_builder.bearer_auth(token.to_owned());
247    };
248
249    let req = req_builder.build()?;
250    let resp = configuration.client.execute(req).await?;
251
252    let status = resp.status();
253
254    if !status.is_client_error() && !status.is_server_error() {
255        Ok(())
256    } else {
257        let content = resp.text().await?;
258        let entity: Option<PostChannelsByChannelSendError> = serde_json::from_str(&content).ok();
259        Err(Error::ResponseError(ResponseContent { status, content, entity }))
260    }
261}
262
263/// Turns one pending pairing code into a standing allow entry, so that person can DM the org's bot on that channel from now on. It requires ORG ADMIN, not merely membership. The first approval an org makes on a channel also bootstraps that sender as the channel's owner, which the answer reports. An unknown or expired code is a 404, and a code always belongs to exactly one org, so it can never approve someone into another tenant.
264pub async fn post_channels_pairing_approve(configuration: &configuration::Configuration, approve_pairing_in: models::ApprovePairingIn) -> Result<models::PairingApproved, Error<PostChannelsPairingApproveError>> {
265    // add a prefix to parameters to efficiently prevent name collisions
266    let p_approve_pairing_in = approve_pairing_in;
267
268    let uri_str = format!("{}/v1/channels/pairing/approve", configuration.base_path);
269    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
270
271    if let Some(ref user_agent) = configuration.user_agent {
272        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
273    }
274    if let Some(ref token) = configuration.bearer_access_token {
275        req_builder = req_builder.bearer_auth(token.to_owned());
276    };
277    req_builder = req_builder.json(&p_approve_pairing_in);
278
279    let req = req_builder.build()?;
280    let resp = configuration.client.execute(req).await?;
281
282    let status = resp.status();
283    let content_type = resp
284        .headers()
285        .get("content-type")
286        .and_then(|v| v.to_str().ok())
287        .unwrap_or("application/octet-stream");
288    let content_type = super::ContentType::from(content_type);
289
290    if !status.is_client_error() && !status.is_server_error() {
291        let content = resp.text().await?;
292        match content_type {
293            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
294            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::PairingApproved`"))),
295            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::PairingApproved`")))),
296        }
297    } else {
298        let content = resp.text().await?;
299        let entity: Option<PostChannelsPairingApproveError> = serde_json::from_str(&content).ok();
300        Err(Error::ResponseError(ResponseContent { status, content, entity }))
301    }
302}
303
304/// Edits the caller org's access policy for one channel and answers the policy as GET would, so both verbs return ONE shape. It requires ORG ADMIN. Every field but `channel` is optional and applied only when provided: an empty policy string leaves that policy alone, an absent or null list leaves that list alone, and an EMPTY list clears it. It writes only CONFIG-sourced allow entries — senders approved through pairing belong to the approval flow, so a policy edit can never revoke one. An unknown channel is a 404.
305pub async fn put_channels_allowlist(configuration: &configuration::Configuration, allowlist_put_in: models::AllowlistPutIn) -> Result<models::AllowlistView, Error<PutChannelsAllowlistError>> {
306    // add a prefix to parameters to efficiently prevent name collisions
307    let p_allowlist_put_in = allowlist_put_in;
308
309    let uri_str = format!("{}/v1/channels/allowlist", configuration.base_path);
310    let mut req_builder = configuration.client.request(reqwest::Method::PUT, &uri_str);
311
312    if let Some(ref user_agent) = configuration.user_agent {
313        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
314    }
315    if let Some(ref token) = configuration.bearer_access_token {
316        req_builder = req_builder.bearer_auth(token.to_owned());
317    };
318    req_builder = req_builder.json(&p_allowlist_put_in);
319
320    let req = req_builder.build()?;
321    let resp = configuration.client.execute(req).await?;
322
323    let status = resp.status();
324    let content_type = resp
325        .headers()
326        .get("content-type")
327        .and_then(|v| v.to_str().ok())
328        .unwrap_or("application/octet-stream");
329    let content_type = super::ContentType::from(content_type);
330
331    if !status.is_client_error() && !status.is_server_error() {
332        let content = resp.text().await?;
333        match content_type {
334            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
335            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::AllowlistView`"))),
336            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::AllowlistView`")))),
337        }
338    } else {
339        let content = resp.text().await?;
340        let entity: Option<PutChannelsAllowlistError> = serde_json::from_str(&content).ok();
341        Err(Error::ResponseError(ResponseContent { status, content, entity }))
342    }
343}
344