Skip to main content

io_gmail/v1/rest/messages/
modify.rs

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