Skip to main content

xmtp_mls/groups/
targets.rs

1//! Membership changes addressed by account or handle targets.
2
3use super::{GroupError, MlsGroup, UpdateGroupMembershipResult};
4use crate::context::XmtpSharedContext;
5use crate::inbox_handles::{IdentityTarget, resolve_targets_in};
6use xmtp_id::InboxId;
7
8/// The inboxes of `targets`, failing with [`GroupError::AddressNotFound`],
9/// which names each account with no inbox in request order.
10pub(crate) fn require_account_inboxes(
11    targets: &[IdentityTarget],
12    inboxes: Vec<Option<InboxId>>,
13) -> Result<Vec<InboxId>, GroupError> {
14    let missing: Vec<String> = targets
15        .iter()
16        .zip(&inboxes)
17        .filter_map(|(target, inbox)| match (target, inbox) {
18            (IdentityTarget::Account(identifier), None) => Some(identifier.to_string()),
19            _ => None,
20        })
21        .collect();
22    if !missing.is_empty() {
23        return Err(GroupError::AddressNotFound(missing));
24    }
25    Ok(inboxes.into_iter().flatten().collect())
26}
27
28impl<Context: XmtpSharedContext> MlsGroup<Context> {
29    /// Add `targets` to the group in one commit. Every target resolves first,
30    /// and the add fails before any commit when a target has no inbox: a
31    /// handle with [`HandleError::NotFound`], an account with
32    /// [`GroupError::AddressNotFound`].
33    pub async fn add_members_by_targets(
34        &self,
35        targets: &[IdentityTarget],
36    ) -> Result<UpdateGroupMembershipResult, GroupError> {
37        let inboxes = resolve_targets_in(&self.context, targets).await?;
38        let inbox_ids = require_account_inboxes(targets, inboxes)?;
39        self.add_members(&inbox_ids).await
40    }
41
42    /// Remove `targets` from the group in one commit. Every target resolves
43    /// first. The removal fails before any commit when a handle has no inbox,
44    /// and skips an account with no inbox.
45    pub async fn remove_members_by_targets(
46        &self,
47        targets: &[IdentityTarget],
48    ) -> Result<(), GroupError> {
49        let inbox_ids: Vec<InboxId> = resolve_targets_in(&self.context, targets)
50            .await?
51            .into_iter()
52            .flatten()
53            .collect();
54        let inbox_ids: Vec<&str> = inbox_ids.iter().map(String::as_str).collect();
55        self.remove_members(&inbox_ids).await
56    }
57}