Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds functions for creating a DM group #901

Merged
merged 7 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions bindings_ffi/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions bindings_node/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions xmtp_mls/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,23 @@ where
Ok(group)
}

/// Create a new Direct Message with the default settings
pub fn create_dm(&self, dm_target_inbox_id: InboxId) -> Result<MlsGroup, ClientError> {
log::info!("creating dm with {}", dm_target_inbox_id);

let group = MlsGroup::create_dm_and_insert(
self.context.clone(),
GroupMembershipState::Allowed,
dm_target_inbox_id,
)
.map_err(Box::new)?;

// notify any streams of the new group
let _ = self.local_events.send(LocalEvents::NewGroup(group.clone()));

Ok(group)
}

pub(crate) fn create_sync_group(&self) -> Result<MlsGroup, ClientError> {
log::info!("creating sync group");
let sync_group =
Expand Down
80 changes: 58 additions & 22 deletions xmtp_mls/src/groups/group_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use prost::Message;
use thiserror::Error;

use xmtp_proto::xmtp::mls::message_contents::{
ConversationType as ConversationTypeProto, GroupMetadataV1 as GroupMetadataProto,
ConversationType as ConversationTypeProto, DmMembers as DmMembersProto,
GroupMetadataV1 as GroupMetadataProto, Inbox as InboxProto,
};

#[derive(Debug, Error)]
Expand All @@ -23,39 +24,35 @@ pub struct GroupMetadata {
pub conversation_type: ConversationType,
// TODO: Remove this once transition is completed
pub creator_inbox_id: String,
pub dm_members: Option<DmMembers>,
}

impl GroupMetadata {
pub fn new(conversation_type: ConversationType, creator_inbox_id: String) -> Self {
pub fn new(
conversation_type: ConversationType,
creator_inbox_id: String,
dm_members: Option<DmMembers>,
) -> Self {
Self {
conversation_type,
creator_inbox_id,
dm_members,
}
}

pub(crate) fn from_proto(proto: GroupMetadataProto) -> Result<Self, GroupMetadataError> {
Ok(Self::new(
proto.conversation_type.try_into()?,
proto.creator_inbox_id.clone(),
))
}

pub(crate) fn to_proto(&self) -> Result<GroupMetadataProto, GroupMetadataError> {
let conversation_type: ConversationTypeProto = self.conversation_type.clone().into();
Ok(GroupMetadataProto {
conversation_type: conversation_type as i32,
creator_inbox_id: self.creator_inbox_id.clone(),
creator_account_address: "".to_string(), // TODO: remove from proto
})
}
}

impl TryFrom<GroupMetadata> for Vec<u8> {
type Error = GroupMetadataError;

fn try_from(value: GroupMetadata) -> Result<Self, Self::Error> {
let mut buf = Vec::new();
let proto_val = value.to_proto()?;
let conversation_type: ConversationTypeProto = value.conversation_type.clone().into();
let proto_val = GroupMetadataProto {
conversation_type: conversation_type as i32,
creator_inbox_id: value.creator_inbox_id.clone(),
creator_account_address: "".to_string(), // TODO: remove from proto
dm_members: value.dm_members.clone().map(|dm| dm.into()),
};
let mut buf: Vec<u8> = Vec::new();
proto_val.encode(&mut buf)?;

Ok(buf)
Expand All @@ -67,15 +64,24 @@ impl TryFrom<&Vec<u8>> for GroupMetadata {

fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
let proto_val = GroupMetadataProto::decode(value.as_slice())?;
Self::from_proto(proto_val)
proto_val.try_into()
}
}

impl TryFrom<GroupMetadataProto> for GroupMetadata {
type Error = GroupMetadataError;

fn try_from(value: GroupMetadataProto) -> Result<Self, Self::Error> {
Self::from_proto(value)
let dm_members = if value.dm_members.is_some() {
Some(DmMembers::try_from(value.dm_members.unwrap())?)
} else {
None
};
Ok(Self::new(
value.conversation_type.try_into()?,
value.creator_inbox_id.clone(),
dm_members,
))
}
}

Expand Down Expand Up @@ -120,6 +126,36 @@ impl TryFrom<i32> for ConversationType {
}
}

#[derive(Debug, Clone, PartialEq)]
pub struct DmMembers {
pub member_one_inbox_id: String,
pub member_two_inbox_id: String,
}

impl From<DmMembers> for DmMembersProto {
fn from(value: DmMembers) -> Self {
DmMembersProto {
dm_member_one: Some(InboxProto {
inbox_id: value.member_one_inbox_id.clone(),
}),
dm_member_two: Some(InboxProto {
inbox_id: value.member_two_inbox_id.clone(),
}),
}
}
}

impl TryFrom<DmMembersProto> for DmMembers {
type Error = GroupMetadataError;

fn try_from(value: DmMembersProto) -> Result<Self, Self::Error> {
Ok(Self {
member_one_inbox_id: value.dm_member_one.unwrap().inbox_id.clone(),
member_two_inbox_id: value.dm_member_two.unwrap().inbox_id.clone(),
})
}
}

pub fn extract_group_metadata(group: &OpenMlsGroup) -> Result<GroupMetadata, GroupMetadataError> {
let extension = group
.export_group_context()
Expand Down
29 changes: 29 additions & 0 deletions xmtp_mls/src/groups/group_mutable_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,35 @@ impl GroupMutableMetadata {
}
}

// Admin / super admin is not needed for a DM
pub fn new_dm_default(_creator_inbox_id: String, _dm_target_inbox_id: String) -> Self {
let mut attributes = HashMap::new();
// TODO: would it be helpful to incorporate the dm inbox ids in the name or description?
attributes.insert(
MetadataField::GroupName.to_string(),
DEFAULT_GROUP_NAME.to_string(),
);
attributes.insert(
MetadataField::Description.to_string(),
DEFAULT_GROUP_DESCRIPTION.to_string(),
);
attributes.insert(
MetadataField::GroupImageUrlSquare.to_string(),
DEFAULT_GROUP_IMAGE_URL_SQUARE.to_string(),
);
attributes.insert(
MetadataField::GroupPinnedFrameUrl.to_string(),
DEFAULT_GROUP_PINNED_FRAME_URL.to_string(),
);
let admin_list = vec![];
let super_admin_list = vec![];
Self {
attributes,
admin_list,
super_admin_list,
}
}

// These fields will receive default permission policies for new groups
pub fn supported_fields() -> Vec<MetadataField> {
vec![
Expand Down
Loading