Skip to main content

io_gmail/v1/rest/threads/
modify.rs

1//! Modify Gmail thread labels (`users.threads.modify`).
2//!
3//! <https://developers.google.com/gmail/api/reference/rest/v1/users.threads/modify>
4
5use alloc::{format, string::String};
6
7use io_http::rfc6750::bearer::HttpAuthBearer;
8use log::{debug, trace};
9use serde::Serialize;
10use url::Url;
11
12use crate::{
13    coroutine::*,
14    gmail_try,
15    v1::rest::threads::GmailThread,
16    v1::send::{GMAIL_API_BASE, GmailSend, GmailSendError, GmailSendOutput},
17};
18
19#[derive(Debug, Serialize)]
20#[serde(rename_all = "camelCase")]
21struct GmailThreadModifyRequest<'a> {
22    add_label_ids: &'a [String],
23    remove_label_ids: &'a [String],
24}
25
26/// Gmail REST thread label modification, wrapping the updated `GmailThread`.
27pub struct GmailThreadModify {
28    send: GmailSend<GmailThread>,
29}
30
31impl GmailThreadModify {
32    /// Builds the `users.threads.modify` request from the given label ids.
33    ///
34    /// Fails with [`GmailSendError::InvalidRequest`] when both label id
35    /// lists are empty.
36    pub fn new(
37        auth: &HttpAuthBearer,
38        user_id: &str,
39        id: &str,
40        add_label_ids: &[String],
41        remove_label_ids: &[String],
42    ) -> Result<Self, GmailSendError> {
43        debug!("prepare gmail thread modification");
44        trace!("add_label_ids: {add_label_ids:?}");
45        trace!("remove_label_ids: {remove_label_ids:?}");
46
47        if add_label_ids.is_empty() && remove_label_ids.is_empty() {
48            return Err(GmailSendError::InvalidRequest(String::from(
49                "Modify requires at least one label update",
50            )));
51        }
52
53        let url =
54            Url::parse(GMAIL_API_BASE)?.join(&format!("users/{user_id}/threads/{id}/modify"))?;
55        let body = GmailThreadModifyRequest {
56            add_label_ids,
57            remove_label_ids,
58        };
59        let send = GmailSend::post_json(auth, url, &body)?;
60
61        Ok(Self { send })
62    }
63}
64
65impl GmailCoroutine for GmailThreadModify {
66    type Yield = GmailYield;
67    type Return = Result<GmailSendOutput<GmailThread>, GmailSendError>;
68
69    fn resume(&mut self, arg: Option<&[u8]>) -> GmailCoroutineState<Self::Yield, Self::Return> {
70        let out = gmail_try!(&mut self.send, arg);
71        debug!("thread modified");
72        trace!("out: {out:?}");
73        GmailCoroutineState::Complete(Ok(out))
74    }
75}