diff --git a/src/zulip/api.rs b/src/zulip/api.rs index 0c53c6e..9e31923 100644 --- a/src/zulip/api.rs +++ b/src/zulip/api.rs @@ -126,6 +126,21 @@ impl ZulipApi { Ok(response) } + /// Is a Zulip stream private? + pub(crate) fn is_stream_private(&self, stream_id: u64) -> anyhow::Result { + #[derive(Deserialize)] + struct OneZulipStream { + stream: ZulipStream, + } + + Ok(self + .req(reqwest::Method::GET, &format!("/streams/{stream_id}"), None)? + .error_for_status()? + .json::()? + .stream + .invite_only) + } + pub(crate) fn update_user_group_members( &self, user_group_id: u64, @@ -224,13 +239,19 @@ impl ZulipApi { Ok(()) }; - let subscriptions = format!("{{\"name\": \"{stream_name}\", \"description\": \"\"}}"); - let add_ids = serialize_as_array(add_ids); - submit(reqwest::Method::POST, subscriptions, add_ids)?; + if !add_ids.is_empty() { + let subscriptions = format!("{{\"name\": \"{stream_name}\", \"description\": \"\"}}"); + let add_ids = serialize_as_array(add_ids); + submit(reqwest::Method::POST, subscriptions, add_ids)?; + } - let subscriptions = format!("[{stream_name}]"); - let remove_ids = serialize_as_array(remove_ids); - submit(reqwest::Method::DELETE, subscriptions, remove_ids) + if !remove_ids.is_empty() { + let subscriptions = format!("[{stream_name}]"); + let remove_ids = serialize_as_array(remove_ids); + submit(reqwest::Method::DELETE, subscriptions, remove_ids)?; + } + + Ok(()) } /// Perform a request against the Zulip API @@ -302,6 +323,7 @@ struct ZulipStreams { pub(crate) struct ZulipStream { pub(crate) stream_id: u64, pub(crate) name: String, + pub(crate) invite_only: bool, } /// Membership of a Zulip stream diff --git a/src/zulip/mod.rs b/src/zulip/mod.rs index 41b93e2..77066f6 100644 --- a/src/zulip/mod.rs +++ b/src/zulip/mod.rs @@ -126,6 +126,7 @@ impl SyncZulip { )); } }; + let is_stream_private = self.zulip_controller.is_stream_private(stream_id)?; let existing_members = self.zulip_controller.stream_members_from_id(stream_id)?; log::debug!( @@ -136,11 +137,15 @@ impl SyncZulip { .filter(|i| !existing_members.contains(i)) .copied() .collect::>(); - let remove_ids = existing_members - .iter() - .filter(|i| !member_ids.contains(i)) - .copied() - .collect::>(); + let remove_ids = if is_stream_private { + existing_members + .iter() + .filter(|i| !member_ids.contains(i)) + .copied() + .collect::>() + } else { + vec![] + }; if add_ids.is_empty() && remove_ids.is_empty() { log::debug!("'{stream_name}' stream ({stream_id}) does not need to be updated"); Ok(None) @@ -463,4 +468,8 @@ impl ZulipController { fn stream_members_from_id(&self, stream_id: u64) -> anyhow::Result> { self.zulip_api.get_stream_members(stream_id) } + + fn is_stream_private(&self, stream_id: u64) -> anyhow::Result { + self.zulip_api.is_stream_private(stream_id) + } }