Skip to content

Commit

Permalink
Added dm group functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
cameronvoell committed Jul 14, 2024
1 parent 24e314a commit ab18943
Show file tree
Hide file tree
Showing 11 changed files with 1,549 additions and 817 deletions.
2 changes: 1 addition & 1 deletion dev/gen_protos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ if ! cargo install --list | grep "protoc-gen-prost-crate" > /dev/null; then
fi
fi

if ! buf generate https://github.com/xmtp/proto.git#branch=main,subdir=proto; then
if ! buf generate https://github.com/xmtp/proto.git#branch=cv/dm-member-constraints,subdir=proto; then
echo "Failed to generate protobuf definitions"
exit 1
fi
Expand Down
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

0 comments on commit ab18943

Please sign in to comment.