From 643496abbf5ed5ac36bce8b87e5dedab06999a9e Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Fri, 4 Feb 2022 16:25:06 -0500 Subject: [PATCH] adding support for settings for notification policy and content, per convo opt in/outs, and attaching relevant info to messages --- constants/attributes.go | 3 +++ constants/globals.go | 9 +++++++++ utils/contacts.go | 29 +++++++++++++++-------------- utils/eventHandler.go | 12 ++++++++++++ utils/settings.go | 4 ++++ utils/utils.go | 29 +++++++++++++++++++++++++++++ 6 files changed, 72 insertions(+), 14 deletions(-) diff --git a/constants/attributes.go b/constants/attributes.go index 78031c4..678b6d2 100644 --- a/constants/attributes.go +++ b/constants/attributes.go @@ -17,6 +17,9 @@ const PeerOnline = "peer-online" // Description is used on server contacts, const Description = "description" +const NotificationOptIn = "notification-opt-in" +const NotificationOptOut = "notification-opt-out" + const StateProfilePane = "state-profile-pane" const StateSelectedConversation = "state-selected-conversation" const StateSelectedProfileTime = "state-selected-profile-time" diff --git a/constants/globals.go b/constants/globals.go index 8f9dd1a..ea51637 100644 --- a/constants/globals.go +++ b/constants/globals.go @@ -11,3 +11,12 @@ const ( // StatusError is an event response for event.Status signifying a call failed in error, ideally accompanied by a event.Error StatusError = "error" ) + +const ( + // NotificationNone enum for message["notification"] that means no notification + NotificationNone = "None" + // NotificationEvent enum for message["notification"] that means emit a notification that a message event happened only + NotificationEvent = "SimpleEvent" + // NotificationConversation enum for message["notification"] that means emit a notification event with Conversation handle included + NotificationConversation = "ContactInfo" +) diff --git a/utils/contacts.go b/utils/contacts.go index 9ddeabf..fb4349b 100644 --- a/utils/contacts.go +++ b/utils/contacts.go @@ -1,18 +1,19 @@ package utils type Contact struct { - Name string `json:"name"` - Onion string `json:"onion"` - Status string `json:"status"` - Picture string `json:"picture"` - Accepted bool `json:"accepted"` - Blocked bool `json:"blocked"` - SaveHistory string `json:"saveConversationHistory"` - Messages int `json:"numMessages"` - Unread int `json:"numUnread"` - LastMessage string `json:"lastMsgTime"` - IsGroup bool `json:"isGroup"` - GroupServer string `json:"groupServer"` - IsArchived bool `json:"isArchived"` - Identifier int `json:"identifier"` + Name string `json:"name"` + Onion string `json:"onion"` + Status string `json:"status"` + Picture string `json:"picture"` + Accepted bool `json:"accepted"` + Blocked bool `json:"blocked"` + SaveHistory string `json:"saveConversationHistory"` + Messages int `json:"numMessages"` + Unread int `json:"numUnread"` + LastMessage string `json:"lastMsgTime"` + IsGroup bool `json:"isGroup"` + GroupServer string `json:"groupServer"` + IsArchived bool `json:"isArchived"` + Identifier int `json:"identifier"` + Options map[string]string `json:"options"` } diff --git a/utils/eventHandler.go b/utils/eventHandler.go index 3bdcd7a..341804c 100644 --- a/utils/eventHandler.go +++ b/utils/eventHandler.go @@ -204,6 +204,14 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string { lastMessage, _ := profile.GetMostRecentMessages(conversationInfo.ID, 0, 0, 1) + options := make(map[string]string) + if notificationOptIn, exists := conversationInfo.GetAttribute(attr.LocalScope, attr.ProfileZone, constants2.NotificationOptIn); exists { + options[constants2.NotificationOptIn] = notificationOptIn + } + if notificationOptOut, exists := conversationInfo.GetAttribute(attr.LocalScope, attr.ProfileZone, constants2.NotificationOptOut); exists { + options[constants2.NotificationOptOut] = notificationOptOut + } + contacts = append(contacts, Contact{ Name: name, Identifier: conversationInfo.ID, @@ -219,6 +227,7 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string { IsGroup: conversationInfo.IsGroup(), GroupServer: groupServer, IsArchived: isArchived == event.True, + Options: options, }) } } @@ -276,6 +285,8 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string { if ci.Accepted { handleImagePreviews(profile, &ev.Event, ci.ID, ci.ID) } + + ev.Event.Data["notification"] = determineNotification(ci) case event.NewMessageFromGroup: // only needs contact nickname and picture, for displaying on popup notifications ci, err := profile.FetchConversationInfo(ev.Event.Data["RemotePeer"]) @@ -296,6 +307,7 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string { if ci != nil && ci.Accepted { handleImagePreviews(profile, &ev.Event, conversationID, ci.ID) } + ev.Event.Data["notification"] = determineNotification(ci) case event.PeerAcknowledgement: ci, err := profile.FetchConversationInfo(ev.Event.Data["RemotePeer"]) if ci != nil && err == nil { diff --git a/utils/settings.go b/utils/settings.go index 5acfee1..4281a02 100644 --- a/utils/settings.go +++ b/utils/settings.go @@ -34,6 +34,8 @@ type GlobalSettings struct { ExperimentsEnabled bool Experiments map[string]bool BlockUnknownConnections bool + NotificationPolicy string + NotificationContent string StreamerMode bool StateRootPane int FirstTime bool @@ -62,6 +64,8 @@ var DefaultGlobalSettings = GlobalSettings{ StreamerMode: false, UIColumnModePortrait: "DualpaneMode.Single", UIColumnModeLandscape: "DualpaneMode.CopyPortrait", + NotificationPolicy: "NotificationPolicy.OptOut", + NotificationContent: "NotificationContent.SimpleEvent", DownloadPath: "", AllowAdvancedTorConfig: false, CustomTorrc: "", diff --git a/utils/utils.go b/utils/utils.go index fd7ef3b..aaadb7b 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -1,8 +1,11 @@ package utils import ( + "cwtch.im/cwtch/model" + "cwtch.im/cwtch/model/attr" "encoding/base32" "encoding/hex" + "git.openprivacy.ca/cwtch.im/libcwtch-go/constants" "git.openprivacy.ca/openprivacy/log" "strings" ) @@ -27,3 +30,29 @@ func RandomGroupImage(handle string) string { } return "servers/" + choices[int(barr[0])%len(choices)] + ".png" } + +func determineNotification(ci *model.Conversation) string { + settings := ReadGlobalSettings() + + switch settings.NotificationPolicy { + case "NotificationPolicy.None": + return constants.NotificationNone + case "NotificationPolicy.OptOut": + if optOut, exists := ci.GetAttribute(attr.LocalScope, attr.ProfileZone, constants.NotificationOptOut); exists && optOut == "true" { + return constants.NotificationNone + } + if settings.NotificationContent == "NotificationContent.ContactInfo" { + return constants.NotificationConversation + } + return constants.NotificationEvent + case "NotificationPolicy.OptIn": + if optIn, exists := ci.GetAttribute(attr.LocalScope, attr.ProfileZone, constants.NotificationOptIn); exists && optIn == "true" { + if settings.NotificationContent == "NotificationContent.ContactInfo" { + return constants.NotificationConversation + } + return constants.NotificationEvent + } + return constants.NotificationNone + } + return constants.NotificationNone +}