diff --git a/features/groups/group_functionality.go b/features/groups/group_functionality.go index 618b51d..ef0cc14 100644 --- a/features/groups/group_functionality.go +++ b/features/groups/group_functionality.go @@ -5,8 +5,8 @@ import ( "cwtch.im/cwtch/model" "cwtch.im/cwtch/peer" "encoding/base64" - "errors" "fmt" + "git.openprivacy.ca/flutter/libcwtch-go/features" "git.openprivacy.ca/openprivacy/log" "strings" ) @@ -16,6 +16,8 @@ const tofuBundlePrefix = "tofubundle:" const groupPrefix = "torv3" const groupExperiment = "tapir-groups-experiment" +const importBundlePrefix = "importBundle" + const ( // ServerList is a json encoded list of servers ServerList = event.Field("ServerList") @@ -95,20 +97,28 @@ func (gf *GroupFunctionality) HandleImportString(peer peer.CwtchPeer, importStri if strings.HasPrefix(importString, tofuBundlePrefix) { bundle := strings.Split(importString, "||") - gf.HandleImportString(peer, bundle[0][11:]) - gf.HandleImportString(peer, bundle[1]) - return nil + err := gf.HandleImportString(peer, bundle[0][len(tofuBundlePrefix):]) + // if the server import failed then abort the whole process.. + if strings.HasSuffix(err.Error(), "success") == false { + return features.ConstructResponse(importBundlePrefix, err.Error()) + } + return gf.HandleImportString(peer, bundle[1]) } else if strings.HasPrefix(importString, serverPrefix) { // Server Key Bundles are prefixed with - bundle, err := base64.StdEncoding.DecodeString(importString[7:]) + bundle, err := base64.StdEncoding.DecodeString(importString[len(serverPrefix):]) if err == nil { - return peer.AddServer(string(bundle)) + if err = peer.AddServer(string(bundle)); err != nil { + return features.ConstructResponse(importBundlePrefix, err.Error()) + } + return features.ConstructResponse(importBundlePrefix, "success") } - return err + return features.ConstructResponse(importBundlePrefix, err.Error()) } else if strings.HasPrefix(importString, groupPrefix) { //eg: torv3JFDWkXExBsZLkjvfkkuAxHsiLGZBk0bvoeJID9ItYnU=EsEBCiBhOWJhZDU1OTQ0NWI3YmM2N2YxYTM5YjkzMTNmNTczNRIgpHeNaG+6jy750eDhwLO39UX4f2xs0irK/M3P6mDSYQIaOTJjM2ttb29ibnlnaGoyenc2cHd2N2Q1N3l6bGQ3NTNhdW8zdWdhdWV6enB2ZmFrM2FoYzRiZHlkCiJAdVSSVgsksceIfHe41OJu9ZFHO8Kwv3G6F5OK3Hw4qZ6hn6SiZjtmJlJezoBH0voZlCahOU7jCOg+dsENndZxAA== - return peer.ImportGroup(importString) + if err := peer.ImportGroup(importString); err != nil { + return features.ConstructResponse(importBundlePrefix, err.Error()) + } + return features.ConstructResponse(importBundlePrefix, "success") } - - return errors.New("invalid_group_invite_prefix") + return features.ConstructResponse(importBundlePrefix, "invalid_group_invite_prefix") } diff --git a/lib.go b/lib.go index de4b7ed..7bd9d41 100644 --- a/lib.go +++ b/lib.go @@ -240,12 +240,6 @@ func SendProfileEvent(onion string, eventJson string) { if model.Authorization(new_event.Data[event.Authorization]) == model.AuthApproved { peer.PeerWithOnion(new_event.Data[event.RemotePeer]) } - case event.SendMessageToGroup: - // TODO Uncomment and integrate once contacts/messages are loaded. - //groupHandler,err := groups.ExperimentGate(utils.ReadGlobalSettings().Experiments) - //if err == nil { - // err = groupHandler.SendMessage(peer, new_event.Data[event.GroupID], new_event.Data[event.Data]) - //} default: // rebroadcast catch all log.Infof("Received Event %v for %v but no libCwtch handler found, relaying the event directly", new_event, onion) @@ -430,7 +424,9 @@ func GetMessage(profileOnion, handle string, message_index int) string { ph := utils.NewPeerHelper(profile) var message model.Message if ph.IsGroup(handle) { - message = profile.GetGroup(handle).Timeline.Messages[message_index] + if len(profile.GetGroup(handle).Timeline.Messages) > message_index { + message = profile.GetGroup(handle).Timeline.Messages[message_index] + } } else { message = profile.GetContact(handle).Timeline.Messages[message_index] } @@ -459,8 +455,18 @@ func c_SendMessage(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, h SendMessage(profile, handle, msg) } -func SendMessage(profile, handle, msg string) { - application.GetPeer(profile).SendMessageToPeer(handle, msg) +func SendMessage(profileOnion, handle, msg string) { + profile := application.GetPeer(profileOnion) + ph := utils.NewPeerHelper(profile) + if ph.IsGroup(handle) { + groupHandler, err := groups.ExperimentGate(utils.ReadGlobalSettings().Experiments) + if err == nil { + groupHandler.SendMessage(profile, handle, msg) + } + } else { + contactHandler, _ := contact.FunctionalityGate(utils.ReadGlobalSettings().Experiments) + contactHandler.SendMessage(profile, handle, msg) + } } //export c_ResetTor @@ -496,5 +502,24 @@ func CreateGroup(profile string, server string, name string) { } } +//export c_ImportBundle +func c_ImportBundle(profile_ptr *C.char, profile_len C.int, bundle_ptr *C.char, bundle_len C.int) { + profile := C.GoStringN(profile_ptr, profile_len) + name := C.GoStringN(bundle_ptr, bundle_len) + ImportBundle(profile, name) +} + +// ImportGroupInviteString takes in a handle to a profile and an invite string which could have one of many +// different formats (e.g. a group invite, a server key bundle, or a combination) +// TODO: extend to also handle AddContact flow... +func ImportBundle(profileOnion string, bundle string) { + profile := application.GetPeer(profileOnion) + groupHandler, err := groups.ExperimentGate(utils.ReadGlobalSettings().Experiments) + if err == nil { + err = groupHandler.HandleImportString(profile, bundle) + eventHandler.Push(event.NewEvent(event.AppError, map[event.Field]string{event.Data: err.Error()})) + } +} + // Leave as is, needed by ffi func main() {} diff --git a/utils/contacts.go b/utils/contacts.go index a279e0f..2c9aa66 100644 --- a/utils/contacts.go +++ b/utils/contacts.go @@ -11,4 +11,5 @@ type Contact struct { Unread int `json:"numUnread"` LastMessage string `json:"lastMsgTime"` IsGroup bool `json:"isGroup"` + GroupServer string `json:"groupServer"` } diff --git a/utils/eventHandler.go b/utils/eventHandler.go index bd0d1d5..1b619a3 100644 --- a/utils/eventHandler.go +++ b/utils/eventHandler.go @@ -154,11 +154,15 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string { }) } + // We compile and send the groups regardless of the experiment flag, and hide them in the UI for _, groupId := range profile.GetGroups() { group := profile.GetGroup(groupId) ph := NewPeerHelper(profile) cpicPath := ph.GetProfilePic(groupId) + // todo hack for now, auto accept groups + profile.AcceptInvite(groupId) + authorization := model.AuthUnknown if group.Accepted { authorization = model.AuthApproved @@ -175,6 +179,7 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string { Unread: 0, LastMessage: strconv.Itoa(getLastMessageTime(&group.Timeline)), IsGroup: true, + GroupServer: group.GroupServer, }) }