Skip to content

Commit

Permalink
Basic support for receiving Signal contact cards
Browse files Browse the repository at this point in the history
  • Loading branch information
smweber committed Nov 13, 2023
1 parent 7125478 commit 7904720
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-pointer v0.0.1 // indirect
github.com/samber/lo v1.38.1 // indirect
github.com/tidwall/gjson v1.16.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down
22 changes: 22 additions & 0 deletions pkg/signalmeow/incoming_messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const (
IncomingSignalMessageTypeExpireTimerChange
IncomingSignalMessageTypeGroupChange
IncomingSignalMessageTypeContactChange
IncomingSignalMessageTypeContactCard
)

type IncomingSignalMessage interface {
Expand All @@ -60,6 +61,7 @@ var _ IncomingSignalMessage = IncomingSignalMessageCall{}
var _ IncomingSignalMessage = IncomingSignalMessageExpireTimerChange{}
var _ IncomingSignalMessage = IncomingSignalMessageGroupChange{}
var _ IncomingSignalMessage = IncomingSignalMessageContactChange{}
var _ IncomingSignalMessage = IncomingSignalMessageContactCard{}

// ** IncomingSignalMessageUnhandled **
type IncomingSignalMessageUnhandled struct {
Expand Down Expand Up @@ -221,6 +223,26 @@ func (i IncomingSignalMessageContactChange) Base() IncomingSignalMessageBase {
return i.IncomingSignalMessageBase
}

// ** IncomingSignalMessageContactCard **
// Note: a "contact card" has nothing to do with a Signal "contact"
// a "contact" (as in the ContactChange above) actually includes the user's UUID and such
// a "contact card" is just information about a person shared from another person, no UUIDs or anything
type IncomingSignalMessageContactCard struct {
IncomingSignalMessageBase
DisplayName string
PhoneNumbers []string
Emails []string
Addresses []string
Organization string
}

func (IncomingSignalMessageContactCard) MessageType() IncomingSignalMessageType {
return IncomingSignalMessageTypeContactCard
}
func (i IncomingSignalMessageContactCard) Base() IncomingSignalMessageBase {
return i.IncomingSignalMessageBase
}

// ** IncomingSignalMessageReceipt **
type IncomingSignalMessageReceiptType int

Expand Down
52 changes: 52 additions & 0 deletions pkg/signalmeow/receiving.go
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,58 @@ func incomingDataMessage(ctx context.Context, device *Device, dataMessage *signa
incomingMessages = append(incomingMessages, incomingMessage)
}

// If there's a contact card share, pass it along
if dataMessage.Contact != nil {
for _, contactCard := range dataMessage.GetContact() {
incomingMessage := IncomingSignalMessageContactCard{
IncomingSignalMessageBase: IncomingSignalMessageBase{
SenderUUID: senderUUID,
RecipientUUID: recipientUUID,
GroupID: gidPointer,
Timestamp: dataMessage.GetTimestamp(),
},
DisplayName: contactCard.GetName().GetDisplayName(),
Organization: contactCard.GetOrganization(),
PhoneNumbers: make([]string, 0),
Emails: make([]string, 0),
Addresses: make([]string, 0),
}
for _, phone := range contactCard.Number {
incomingMessage.PhoneNumbers = append(incomingMessage.PhoneNumbers, *phone.Value)
}
for _, email := range contactCard.Email {
incomingMessage.Emails = append(incomingMessage.Emails, *email.Value)
}
for _, address := range contactCard.Address {
addressParts := make([]string, 0)
if address.Pobox != nil {
addressParts = append(addressParts, "P.O. Box: "+*address.Pobox)
}
if address.Street != nil {
addressParts = append(addressParts, *address.Street)
}
if address.Neighborhood != nil {
addressParts = append(addressParts, *address.Neighborhood)
}
if address.City != nil {
addressParts = append(addressParts, *address.City)
}
if address.Region != nil {
addressParts = append(addressParts, *address.Region)
}
if address.Postcode != nil {
addressParts = append(addressParts, *address.Postcode)
}
if address.Country != nil {
addressParts = append(addressParts, *address.Country)
}
addressString := strings.Join(addressParts, ", ")
incomingMessage.Addresses = append(incomingMessage.Addresses, addressString)
}
incomingMessages = append(incomingMessages, incomingMessage)
}
}

// If it's a expireTimer change, send that along (DMs only)
if dataMessage.Flags != nil && dataMessage.GetFlags()&uint32(signalpb.DataMessage_EXPIRATION_TIMER_UPDATE) != 0 {
newTime := uint32(0)
Expand Down
30 changes: 30 additions & 0 deletions portal.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
cwebp "github.com/chai2010/webp"
"github.com/google/uuid"
"github.com/rs/zerolog"
"github.com/samber/lo"
"golang.org/x/image/webp"

"maunium.net/go/mautrix"
Expand Down Expand Up @@ -904,6 +905,12 @@ func (portal *Portal) handleSignalMessages(portalMessage portalSignalMessage) {
portal.log.Error().Err(err).Msg("Failed to handle call message")
return
}
} else if portalMessage.message.MessageType() == signalmeow.IncomingSignalMessageTypeContactCard {
err := portal.handleSignalContactCardMessage(portalMessage, intent)
if err != nil {
portal.log.Error().Err(err).Msg("Failed to handle contact card message")
return
}
} else if portalMessage.message.MessageType() == signalmeow.IncomingSignalMessageTypeUnhandled {
err := portal.handleSignalUnhandledMessage(portalMessage, intent)
if err != nil {
Expand Down Expand Up @@ -1138,6 +1145,29 @@ func (portal *Portal) handleSignalCallMessage(portalMessage portalSignalMessage,
return nil
}

func (portal *Portal) handleSignalContactCardMessage(portalMessage portalSignalMessage, intent *appservice.IntentAPI) error {
contactCardMessage := (portalMessage.message).(signalmeow.IncomingSignalMessageContactCard)
messageParts := []string{}
messageParts = append(messageParts, contactCardMessage.DisplayName)
messageParts = append(messageParts, contactCardMessage.Organization)
for _, phoneNumber := range contactCardMessage.PhoneNumbers {
messageParts = append(messageParts, phoneNumber)
}
for _, email := range contactCardMessage.Emails {
messageParts = append(messageParts, email)
}
for _, address := range contactCardMessage.Addresses {
messageParts = append(messageParts, address)
}
messageParts = lo.Filter(messageParts, func(s string, i int) bool {
return s != ""
})
message := strings.Join(messageParts, "\n")
intent.SendNotice(portal.MXID, message)

return nil
}

func (portal *Portal) handleSignalUnhandledMessage(portalMessage portalSignalMessage, intent *appservice.IntentAPI) error {
unhandledMessage := (portalMessage.message).(signalmeow.IncomingSignalMessageUnhandled)
portal.log.Warn().Msgf("Received unhandled message type %s, notice: %s", unhandledMessage.Type, unhandledMessage.Notice)
Expand Down

0 comments on commit 7904720

Please sign in to comment.