Skip to content

Latest commit

 

History

History
537 lines (407 loc) · 14.3 KB

File metadata and controls

537 lines (407 loc) · 14.3 KB
title Community
description Community operations — create, deactivate, and manage community subgroups

The Community feature provides methods for managing WhatsApp communities, including creation, subgroup linking/unlinking, and metadata queries. Community mutations use IQ stanzas (w:g2 namespace) while metadata queries use MEX (GraphQL).

Access

Access community operations through the client:

let community = client.community();

Methods

create

Create a new community.

pub async fn create(
    &self,
    options: CreateCommunityOptions,
) -> Result<CreateCommunityResult, CommunityError>

Parameters:

Returns:

  • CreateCommunityResult — Contains the full metadata: GroupMetadata for the created community parent group

Example:

use whatsapp_rust::features::community::CreateCommunityOptions;

let mut options = CreateCommunityOptions::new("My Community");
options.description = Some("A great community".to_string());
options.closed = true;

let result = client.community().create(options).await?;
println!("Created community: {} ({})", result.metadata.subject, result.metadata.id);
if let Some(desc) = &result.metadata.description {
    println!("Description: {}", desc);
}
Since v0.6, `community().create()` returns the full `GroupMetadata` instead of just the JID. The library inlines the community description directly into the create stanza (matching WA Web), so the returned metadata already contains it — no separate `set_description` round-trip is needed. If you previously read `result.gid`, switch to `result.metadata.id` (`GroupMetadata` uses `id: Jid`).

get_participating

Fetch all parent/community groups the logged-in account currently participates in.

pub async fn get_participating(&self) -> Result<HashMap<Jid, GroupMetadata>, CommunityError>

Returns:

  • HashMap<Jid, GroupMetadata> — Map of community JID to metadata

Example:

let communities = client.community().get_participating().await?;

for (jid, metadata) in communities {
    println!("Community: {} ({})", metadata.subject, jid);
}

deactivate

Deactivate (delete) a community. Subgroups are unlinked but not deleted.

pub async fn deactivate(&self, community_jid: &Jid) -> Result<(), CommunityError>

Parameters:

  • community_jid — JID of the community to deactivate

Example:

client.community().deactivate(&community_jid).await?;

link_subgroups

Link existing groups as subgroups of a community.

pub async fn link_subgroups(
    &self,
    community_jid: &Jid,
    subgroup_jids: &[Jid],
) -> Result<LinkSubgroupsResult, CommunityError>

Parameters:

  • community_jid — JID of the parent community
  • subgroup_jids — Array of group JIDs to link

Returns:

  • LinkSubgroupsResult — Contains linked_jids (successfully linked) and failed_groups (JID + error code pairs)

Example:

let subgroup_jids = vec![
    "120363001111111@g.us".parse()?,
    "120363002222222@g.us".parse()?,
];

let result = client.community()
    .link_subgroups(&community_jid, &subgroup_jids)
    .await?;

println!("Linked: {:?}", result.linked_jids);
for (jid, error_code) in &result.failed_groups {
    eprintln!("Failed: {} (error {})", jid, error_code);
}

create_subgroup

Create a new group that is already linked as a subgroup of a community, in one call.

pub async fn create_subgroup(
    &self,
    name: &str,
    participants: &[Jid],
    parent_jid: &Jid,
) -> Result<CreateCommunityResult, CommunityError>

Parameters:

  • name — Name of the new subgroup
  • participants — Initial participant JIDs to add to the subgroup
  • parent_jid — JID of the parent community to link the new subgroup under

Returns:

  • CreateCommunityResult — Contains the full metadata: GroupMetadata for the created subgroup

Example:

let participants = vec![
    "5511999999999@s.whatsapp.net".parse()?,
];

let result = client.community()
    .create_subgroup("My Subgroup", &participants, &community_jid)
    .await?;

println!("Created subgroup: {} ({})", result.metadata.subject, result.metadata.id);
Equivalent to creating a group and then calling [`link_subgroups`](#link_subgroups), but done in a single round-trip.

unlink_subgroups

Unlink subgroups from a community.

pub async fn unlink_subgroups(
    &self,
    community_jid: &Jid,
    subgroup_jids: &[Jid],
    remove_orphan_members: bool,
) -> Result<UnlinkSubgroupsResult, CommunityError>

Parameters:

  • community_jid — JID of the parent community
  • subgroup_jids — Array of subgroup JIDs to unlink
  • remove_orphan_members — Whether to remove members who are only in the community through the unlinked subgroups

Returns:

  • UnlinkSubgroupsResult — Contains unlinked_jids (successfully unlinked) and failed_groups (JID + error code pairs)

Example:

let result = client.community()
    .unlink_subgroups(&community_jid, &subgroup_jids, true)
    .await?;

println!("Unlinked: {:?}", result.unlinked_jids);

get_subgroups

Fetch all subgroups of a community via MEX (GraphQL).

pub async fn get_subgroups(
    &self,
    community_jid: &Jid,
) -> Result<Vec<CommunitySubgroup>, CommunityError>

Parameters:

  • community_jid — JID of the community

Returns:

  • Vec<CommunitySubgroup> — List of subgroups with metadata

Example:

let subgroups = client.community()
    .get_subgroups(&community_jid)
    .await?;

for sg in &subgroups {
    println!("{}: {} (default: {}, general: {})",
        sg.id, sg.subject, sg.is_default_sub_group, sg.is_general_chat);
}

get_subgroup_participant_counts

Fetch participant counts per subgroup via MEX (GraphQL).

pub async fn get_subgroup_participant_counts(
    &self,
    community_jid: &Jid,
) -> Result<Vec<(Jid, u32)>, CommunityError>

Parameters:

  • community_jid — JID of the community

Returns:

  • Vec<(Jid, u32)> — Pairs of subgroup JID and participant count

Example:

let counts = client.community()
    .get_subgroup_participant_counts(&community_jid)
    .await?;

for (jid, count) in &counts {
    println!("{}: {} participants", jid, count);
}

query_linked_group

Query a linked subgroup's metadata from the parent community.

pub async fn query_linked_group(
    &self,
    community_jid: &Jid,
    subgroup_jid: &Jid,
) -> Result<GroupMetadata, CommunityError>

Parameters:

  • community_jid — JID of the parent community
  • subgroup_jid — JID of the subgroup to query

Returns:

  • GroupMetadata — Full group metadata (see Groups API)

Example:

let metadata = client.community()
    .query_linked_group(&community_jid, &subgroup_jid)
    .await?;

println!("Subject: {}", metadata.subject);

join_subgroup

Join a linked subgroup via the parent community.

pub async fn join_subgroup(
    &self,
    community_jid: &Jid,
    subgroup_jid: &Jid,
) -> Result<GroupMetadata, CommunityError>

Parameters:

  • community_jid — JID of the parent community
  • subgroup_jid — JID of the subgroup to join

Returns:

  • GroupMetadata — Metadata of the joined subgroup

Example:

let metadata = client.community()
    .join_subgroup(&community_jid, &subgroup_jid)
    .await?;

println!("Joined: {}", metadata.subject);

get_linked_groups_participants

Get all participants across all linked groups of a community.

pub async fn get_linked_groups_participants(
    &self,
    community_jid: &Jid,
) -> Result<Vec<GroupParticipant>, CommunityError>

Parameters:

  • community_jid — JID of the community

Returns:

  • Vec<GroupParticipant> — List of participants across all subgroups

Example:

let participants = client.community()
    .get_linked_groups_participants(&community_jid)
    .await?;

for p in &participants {
    println!("{} (admin: {})", p.jid, p.is_admin);
}

remove_participants

Remove participants from a community.

pub async fn remove_participants(
    &self,
    community_jid: &Jid,
    participants: &[Jid],
) -> Result<Vec<ParticipantChangeResponse>, CommunityError>

Parameters:

  • community_jid — JID of the community
  • participants — Array of participant JIDs to remove

Returns:

Example:

let to_remove = vec!["15551234567@s.whatsapp.net".parse()?];

let results = client.community()
    .remove_participants(&community_jid, &to_remove)
    .await?;

for result in results {
    println!("{}: status {:?}", result.jid, result.status);
}

Types

CreateCommunityOptions

Options for creating a new community. Implements PartialEq and Eq.

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CreateCommunityOptions {
    pub name: String,
    pub description: Option<String>,
    pub closed: bool,
    pub allow_non_admin_sub_group_creation: bool,
    pub create_general_chat: bool,
}

Fields:

  • name — Community name
  • description — Optional description. Since v0.6 it's inlined as a <description> child of the create stanza, so the community is created with the description in a single round-trip (no follow-up set_description IQ needed).
  • closed — Whether the community requires approval to join (default: false)
  • allow_non_admin_sub_group_creation — Whether non-admin members can create subgroups (default: false)
  • create_general_chat — Whether to create a general chat subgroup (default: true)

Constructor:

let options = CreateCommunityOptions::new("My Community");

CreateCommunityResult

Result of creating a community.

#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct CreateCommunityResult {
    pub metadata: GroupMetadata,
}

The metadata field carries the full community parent metadata from the server, with the inline description: Option<String> already populated. See GroupMetadata for the full field list.

CreateCommunityResult is #[non_exhaustive]: struct-literal construction and exhaustive struct destructuring from outside the crate are both disallowed. Field reads are unaffected; add .. to any exhaustive destructuring patterns.

Prior to v0.6 this struct exposed only `gid: Jid` and derived `PartialEq, Eq`. The `Eq` derives were dropped because `GroupMetadata` does not implement them.

CommunitySubgroup

A subgroup within a community. Implements PartialEq and Eq.

#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct CommunitySubgroup {
    pub id: Jid,
    pub subject: String,
    pub participant_count: Option<u32>,
    pub is_default_sub_group: bool,
    pub is_general_chat: bool,
    pub creation: Option<u64>,
    pub owner: Option<Jid>,
}

CommunitySubgroup is #[non_exhaustive]: struct-literal construction and exhaustive struct destructuring from outside the crate are both disallowed. Field reads are unaffected; add .. to any exhaustive destructuring patterns.

Fields:

  • id — Subgroup JID
  • subject — Subgroup name
  • participant_count — Number of participants (if available)
  • is_default_sub_group — Whether this is the default announcement subgroup
  • is_general_chat — Whether this is the general chat subgroup
  • creation — Subgroup creation timestamp (Unix seconds), if available
  • owner — JID of the subgroup owner, if available

LinkSubgroupsResult

Result of linking subgroups to a community. Implements PartialEq and Eq.

#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct LinkSubgroupsResult {
    pub linked_jids: Vec<Jid>,
    pub failed_groups: Vec<(Jid, u32)>,
}

LinkSubgroupsResult is #[non_exhaustive]: struct-literal construction and exhaustive struct destructuring from outside the crate are both disallowed. Field reads are unaffected; add .. to any exhaustive destructuring patterns.

UnlinkSubgroupsResult

Result of unlinking subgroups from a community. Implements PartialEq and Eq.

#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct UnlinkSubgroupsResult {
    pub unlinked_jids: Vec<Jid>,
    pub failed_groups: Vec<(Jid, u32)>,
}

UnlinkSubgroupsResult is #[non_exhaustive]: struct-literal construction and exhaustive struct destructuring from outside the crate are both disallowed. Field reads are unaffected; add .. to any exhaustive destructuring patterns.

GroupType

Classification of a group within the community hierarchy. Implements PartialEq and Eq.

#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GroupType {
    Default,
    Community,
    LinkedSubgroup,
    LinkedAnnouncementGroup,
    LinkedGeneralGroup,
}

GroupType is #[non_exhaustive], so match statements should include a wildcard arm to handle future variants.

Variants:

  • Default — Regular standalone group
  • Community — Community parent group
  • LinkedSubgroup — A subgroup linked to a community
  • LinkedAnnouncementGroup — The default announcement subgroup of a community
  • LinkedGeneralGroup — The general chat subgroup of a community

Use the group_type() function to classify a group:

use whatsapp_rust::features::community::{group_type, GroupType};

let metadata = client.groups().get_metadata(&group_jid).await?;
let gtype = group_type(&metadata);

Error handling

All community methods return Result<T, CommunityError>:

#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum CommunityError {
    #[error(transparent)]
    Iq(#[from] IqError),
    #[error(transparent)]
    Mex(#[from] MexError),
    #[error(transparent)]
    Group(#[from] GroupError),
    #[error("invalid community request: {0}")]
    InvalidRequest(String),
}
use whatsapp_rust::CommunityError;

match client.community().deactivate(&community_jid).await {
    Ok(_) => println!("Community deactivated"),
    Err(CommunityError::Iq(e)) => eprintln!("Server error: {}", e),
    Err(CommunityError::Mex(e)) => eprintln!("MEX error: {}", e),
    Err(e) => eprintln!("Error: {}", e),
}