129 lines
5.1 KiB
Go
129 lines
5.1 KiB
Go
package extensions
|
|
|
|
import (
|
|
"cwtch.im/cwtch/event"
|
|
"cwtch.im/cwtch/model"
|
|
"cwtch.im/cwtch/model/attr"
|
|
"cwtch.im/cwtch/model/constants"
|
|
"cwtch.im/cwtch/peer"
|
|
"cwtch.im/cwtch/protocol/connections"
|
|
"cwtch.im/cwtch/settings"
|
|
"git.openprivacy.ca/openprivacy/log"
|
|
"strconv"
|
|
)
|
|
|
|
// ProfileValueExtension implements custom Profile Names over Cwtch
|
|
type ProfileValueExtension struct {
|
|
}
|
|
|
|
func (pne ProfileValueExtension) NotifySettingsUpdate(_ settings.GlobalSettings) {
|
|
}
|
|
|
|
func (pne ProfileValueExtension) EventsToRegister() []event.Type {
|
|
return []event.Type{event.PeerStateChange, event.Heartbeat}
|
|
}
|
|
|
|
func (pne ProfileValueExtension) ExperimentsToRegister() []string {
|
|
return nil
|
|
}
|
|
|
|
func (pne ProfileValueExtension) requestProfileInfo(profile peer.CwtchPeer, ci *model.Conversation) {
|
|
profile.SendScopedZonedGetValToContact(ci.ID, attr.PublicScope, attr.ProfileZone, constants.Name)
|
|
profile.SendScopedZonedGetValToContact(ci.ID, attr.PublicScope, attr.ProfileZone, constants.ProfileStatus)
|
|
profile.SendScopedZonedGetValToContact(ci.ID, attr.PublicScope, attr.ProfileZone, constants.ProfileAttribute1)
|
|
profile.SendScopedZonedGetValToContact(ci.ID, attr.PublicScope, attr.ProfileZone, constants.ProfileAttribute2)
|
|
profile.SendScopedZonedGetValToContact(ci.ID, attr.PublicScope, attr.ProfileZone, constants.ProfileAttribute3)
|
|
}
|
|
|
|
func (pne ProfileValueExtension) OnEvent(ev event.Event, profile peer.CwtchPeer) {
|
|
switch ev.EventType {
|
|
case event.Heartbeat:
|
|
// once every heartbeat, loop through conversations and, if they are online, request an update to any long info..
|
|
conversations, err := profile.FetchConversations()
|
|
if err == nil {
|
|
for _, ci := range conversations {
|
|
if profile.GetPeerState(ci.Handle) == connections.AUTHENTICATED {
|
|
pne.requestProfileInfo(profile, ci)
|
|
}
|
|
}
|
|
}
|
|
case event.PeerStateChange:
|
|
ci, err := profile.FetchConversationInfo(ev.Data["RemotePeer"])
|
|
if err == nil {
|
|
// if we have re-authenticated with thie peer then request their profile image...
|
|
if connections.ConnectionStateToType()[ev.Data[event.ConnectionState]] == connections.AUTHENTICATED {
|
|
// Request some profile information...
|
|
pne.requestProfileInfo(profile, ci)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// OnContactReceiveValue for ProfileValueExtension handles saving specific Public Profile Values like Profile Name
|
|
func (pne ProfileValueExtension) OnContactReceiveValue(profile peer.CwtchPeer, conversation model.Conversation, szp attr.ScopedZonedPath, value string, exists bool) {
|
|
// Allow public profile parameters to be added as contact specific attributes...
|
|
scope, zone, _ := szp.GetScopeZonePath()
|
|
if exists && scope.IsPublic() && zone == attr.ProfileZone {
|
|
|
|
// Check the current value of the attribute
|
|
currentValue, err := profile.GetConversationAttribute(conversation.ID, szp)
|
|
if err == nil && currentValue == value {
|
|
// Value exists and the value is the same, short-circuit
|
|
return
|
|
}
|
|
|
|
// Save the new Attribute
|
|
err = profile.SetConversationAttribute(conversation.ID, szp, value)
|
|
if err != nil {
|
|
// Something else wen't wrong.. short-circuit
|
|
log.Errorf("error setting conversation attribute %v", err)
|
|
return
|
|
}
|
|
|
|
// Finally publish an update for listeners to react to.
|
|
scope, zone, zpath := szp.GetScopeZonePath()
|
|
profile.PublishEvent(event.NewEvent(event.UpdatedConversationAttribute, map[event.Field]string{
|
|
event.Scope: string(scope),
|
|
event.Path: string(zone.ConstructZonedPath(zpath)),
|
|
event.Data: value,
|
|
event.RemotePeer: conversation.Handle,
|
|
event.ConversationID: strconv.Itoa(conversation.ID),
|
|
}))
|
|
}
|
|
}
|
|
|
|
// OnContactRequestValue for ProfileValueExtension handles returning Public Profile Values
|
|
func (pne ProfileValueExtension) OnContactRequestValue(profile peer.CwtchPeer, conversation model.Conversation, eventID string, szp attr.ScopedZonedPath) {
|
|
scope, zone, zpath := szp.GetScopeZonePath()
|
|
log.Debugf("Looking up public | conversation scope/zone %v", szp.ToString())
|
|
if scope.IsPublic() || scope.IsConversation() {
|
|
val, exists := profile.GetScopedZonedAttribute(scope, zone, zpath)
|
|
|
|
// NOTE: Temporary Override because UI currently wipes names if it can't find them...
|
|
if !exists && zone == attr.UnknownZone && zpath == constants.Name {
|
|
val, exists = profile.GetScopedZonedAttribute(attr.PublicScope, attr.ProfileZone, constants.Name)
|
|
}
|
|
|
|
// NOTE: Cwtch 1.15+ requires that profiles be able to restrict file downloading to specific contacts. As such we need an ACL check here
|
|
// on the fileshareing zone.
|
|
// TODO: Split this functionality into FilesharingFunctionality, and restrict this function to only considering Profile zoned attributes?
|
|
if zone == attr.FilesharingZone {
|
|
if !conversation.GetPeerAC().ShareFiles {
|
|
return
|
|
}
|
|
}
|
|
|
|
// Construct a Response
|
|
resp := event.NewEvent(event.SendRetValMessageToPeer, map[event.Field]string{event.ConversationID: strconv.Itoa(conversation.ID), event.RemotePeer: conversation.Handle, event.Exists: strconv.FormatBool(exists)})
|
|
resp.EventID = eventID
|
|
if exists {
|
|
resp.Data[event.Data] = val
|
|
} else {
|
|
resp.Data[event.Data] = ""
|
|
}
|
|
|
|
log.Debugf("Responding with SendRetValMessageToPeer exists:%v data: %v\n", exists, val)
|
|
profile.PublishEvent(resp)
|
|
}
|
|
}
|