an extremely barebone, but working two way signald bridge

I relied on learning from https://gitlab.com/signald/signald-go but because that project is under GPL and there are no plans on re-licensing (see <https://gitlab.com/signald/signald-go/-/issues/7>) it can't be directly used in matterbridge, which is Apache 2.0

Anyway: as it currently is, this module is crude, probably extremely prone to errors, and nowhere remotely close to stable or production use.
Regardless of that, any help with it would be welcome.
This commit is contained in:
Peter Molnar 2021-02-28 18:18:38 +00:00
parent 952af5ceb3
commit 271df11556
3 changed files with 120 additions and 38 deletions

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "vendor/gitlab.com/signald/signald-go"]
path = vendor/gitlab.com/signald/signald-go
url = https://gitlab.com/signald/signald-go

View File

@ -6,9 +6,6 @@ import (
"encoding/json" "encoding/json"
"github.com/42wim/matterbridge/bridge" "github.com/42wim/matterbridge/bridge"
"github.com/42wim/matterbridge/bridge/config" "github.com/42wim/matterbridge/bridge/config"
"gitlab.com/signald/signald-go/signald"
//"gitlab.com/signald/signald-go/signald/client-protocol/v0"
"gitlab.com/signald/signald-go/signald/client-protocol/v1"
) )
type JSONCMD map[string]interface{} type JSONCMD map[string]interface{}
@ -19,12 +16,103 @@ const (
cfgGroupID = "GroupID" cfgGroupID = "GroupID"
) )
type envelopeResponse struct { type signaldMessage struct {
ID string
Type string
Error json.RawMessage
Data json.RawMessage
}
type signaldUnexpectedError struct {
Message string
}
type signaldMessageData struct {
ID string `json:",omitempty"` ID string `json:",omitempty"`
Data v1.JsonMessageEnvelope `json:",omitempty"` Data signaldData `json:",omitempty"`
Type string `json:",omitempty"` Type string `json:",omitempty"`
} }
type signaldData struct {
CallMessage json.RawMessage `json:"callMessage,omitempty"`
DataMessage *signaldDataMessage `json:"dataMessage,omitempty"`
HasContent bool `json:"hasContent,omitempty"`
HasLegacyMessage bool `json:"hasLegacyMessage,omitempty"`
IsUnidentifiedSender bool `json:"isUnidentifiedSender,omitempty"`
Receipt json.RawMessage `json:"receipt,omitempty"`
Relay string `json:"relay,omitempty"`
ServerDeliveredTimestamp int64 `json:"serverDeliveredTimestamp,omitempty"`
ServerTimestamp int64 `json:"serverTimestamp,omitempty"`
Source *signaldAccount `json:"source,omitempty"`
SourceDevice int32 `json:"sourceDevice,omitempty"`
SyncMessage json.RawMessage `json:"syncMessage,omitempty"`
Timestamp int64 `json:"timestamp,omitempty"`
TimestampISO string `json:"timestampISO,omitempty"`
Type string `json:"type,omitempty"`
Typing json.RawMessage `json:"typing,omitempty"`
Username string `json:"username,omitempty"`
UUID string `json:"uuid,omitempty"`
}
type signaldAccount struct {
Number string `json:"number,omitempty"`
Relay string `json:"relay,omitempty"`
UUID string `json:"uuid,omitempty"`
}
type signaldDataMessage struct {
Attachments json.RawMessage `json:"attachments,omitempty"`
Body string `json:"body,omitempty"`
Contacts json.RawMessage `json:"contacts,omitempty"`
EndSession bool `json:"endSession,omitempty"`
ExpiresInSeconds int32 `json:"expiresInSeconds,omitempty"`
Group *signaldGroupInfo `json:"group,omitempty"`
GroupV2 *signaldGroupV2Info `json:"groupV2,omitempty"`
Mentions json.RawMessage `json:"mentions,omitempty"`
Previews json.RawMessage `json:"previews,omitempty"`
ProfileKeyUpdate bool `json:"profileKeyUpdate,omitempty"`
Quote json.RawMessage `json:"quote,omitempty"`
Reaction json.RawMessage `json:"reaction,omitempty"`
RemoteDelete json.RawMessage `json:"remoteDelete,omitempty"`
Sticker json.RawMessage `json:"sticker,omitempty"`
Timestamp int64 `json:"timestamp,omitempty"`
ViewOnce bool `json:"viewOnce,omitempty"`
}
type signaldGroupInfo struct {
AvatarId int64 `json:"avatarId,omitempty"`
GroupId string `json:"groupId,omitempty"`
Members json.RawMessage `json:"members,omitempty"`
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
}
type signaldGroupV2Info struct {
AccessControl json.RawMessage `json:"accessControl,omitempty"`
Avatar string `json:"avatar,omitempty"`
ID string `json:"id,omitempty"`
InviteLink string `json:"inviteLink,omitempty"`
MemberDetail json.RawMessage `json:"memberDetail,omitempty"`
Members json.RawMessage `json:"members,omitempty"`
PendingMemberDetail json.RawMessage `json:"pendingMemberDetail,omitempty"`
PendingMembers json.RawMessage `json:"pendingMembers,omitempty"`
RequestingMembers json.RawMessage `json:"requestingMembers,omitempty"`
Revision int32 `json:"revision,omitempty"`
Timer int32 `json:"timer,omitempty"`
Title string `son:"title,omitempty"`
}
type signaldSendMessage struct {
Username string `json:"username,omitempty"`
//RecipientAddress signaldAccount `json:"recipientAddress,omitempty"`
RecipientGroupId string `json:"recipientGroupId,omitempty"`
MessageBody string `json:"messageBody,omitempty"`
//Attachments json.RawMessage `json:"attachments,omitempty"`
//Quote json.RawMessage `json:"quote,omitempty"`
//Timestamp int64 `json:"timestamp,omitempty"`
//Mentions json.RawMessage `json:"mentions,omitempty"`
}
type Bsignald struct { type Bsignald struct {
*bridge.Config *bridge.Config
socketpath string socketpath string
@ -83,43 +171,45 @@ func (b *Bsignald) Listen() {
} }
raw := b.reader.Text() raw := b.reader.Text()
b.Log.Debugln(raw);
var msg signald.BasicResponse var msg signaldMessage
if err := json.Unmarshal([]byte(raw), &msg); err != nil { if err := json.Unmarshal([]byte(raw), &msg); err != nil {
b.Log.Errorln("Error unmarshaling raw response:", err.Error()) b.Log.Errorln("Error unmarshaling raw response:", err.Error())
continue continue
} }
if msg.Type == "unexpected_error" { if msg.Type == "unexpected_error" {
var errorResponse signald.UnexpectedError var errorResponse signaldUnexpectedError
if err := json.Unmarshal(msg.Data, &errorResponse); err != nil { if err := json.Unmarshal(msg.Data, &errorResponse); err != nil {
b.Log.Errorln("signald-go: Error unmarshaling error response:", err.Error()) b.Log.Errorln("Error unmarshaling error response:", err.Error())
continue continue
} }
b.Log.Errorln("signald-go: Unexpected error", errorResponse.Message) b.Log.Errorln("Unexpected error", errorResponse.Message)
continue continue
} }
if msg.Type != "message" { if msg.Type != "message" {
b.Log.Debugln("not 'message' from signald: ", raw); b.Log.Debugln("skipping: not 'message'");
continue continue
} else {
b.Log.Debugln("FOUND A MESSAGE!", raw);
} }
response := envelopeResponse{ID: msg.ID, Type: msg.Type} response := signaldMessageData{ID: msg.ID, Type: msg.Type}
if err := json.Unmarshal(msg.Data, &response.Data); err != nil { if err := json.Unmarshal(msg.Data, &response.Data); err != nil {
b.Log.Errorln("signald-go receive error: ", err) b.Log.Errorln("receive error: ", err)
continue continue
} }
b.Log.Debugf("%#v", response); //b.Log.Debugf("%#v", response);
if response.Data.DataMessage != nil { if response.Data.DataMessage != nil {
if response.Data.DataMessage.GroupV2 != nil { if response.Data.DataMessage.GroupV2 != nil {
if b.groupid == response.Data.DataMessage.GroupV2.ID { if b.groupid == response.Data.DataMessage.GroupV2.ID {
rmsg := config.Message{ rmsg := config.Message{
UserID: response.Data.Username, UserID: response.Data.Source.UUID,
Username: response.Data.Username, Username: response.Data.Source.Number,
Text: response.Data.DataMessage.Body, Text: response.Data.DataMessage.Body,
Channel: response.Data.DataMessage.GroupV2.ID, Channel: response.Data.DataMessage.GroupV2.ID,
Account: b.Account, Account: b.Account,
@ -174,22 +264,18 @@ func (b *Bsignald) Disconnect() error {
} }
func (b *Bsignald) Send(msg config.Message) (string, error) { func (b *Bsignald) Send(msg config.Message) (string, error) {
b.Log.Debugf("message to forward into signal: %#v", msg)
//req := v1.SendRequest{ msgJSON := JSONCMD{
//Username: account, "type": "send",
//MessageBody: strings.Join(args[1:], " "), "username": b.GetString(cfgNumber),
//} "recipientGroupId": b.groupid,
"messageBody": msg.Text,
}
err := json.NewEncoder(b.socket).Encode(msgJSON)
if err != nil {
b.Log.Errorln(err.Error())
}
//if strings.HasPrefix(args[0], "+") { return "", err
//req.RecipientAddress = &v1.JsonAddress{Number: args[0]}
//} else {
//req.RecipientGroupID = args[0]
//}
//resp, err := req.Submit(common.Signald)
//if err != nil {
//log.Fatal("error sending request to signald: ", err)
//}
return "", nil
} }

@ -1 +0,0 @@
Subproject commit 60778761c21dd68e082db03f7668097d03f86acc