Merge pull request #434 from bbernhard/multimaster_mode

Multimaster mode
This commit is contained in:
Bernhard B
2023-10-30 20:03:28 +01:00
committed by GitHub
5 changed files with 157 additions and 168 deletions

View File

@@ -385,7 +385,7 @@ func (a *Api) SendV2(c *gin.Context) {
} }
func (a *Api) handleSignalReceive(ws *websocket.Conn, number string, stop chan struct{}) { func (a *Api) handleSignalReceive(ws *websocket.Conn, number string, stop chan struct{}) {
receiveChannel, err := a.signalClient.GetReceiveChannel(number) receiveChannel, err := a.signalClient.GetReceiveChannel()
if err != nil { if err != nil {
log.Error("Couldn't get receive channel: ", err.Error()) log.Error("Couldn't get receive channel: ", err.Error())
return return
@@ -405,12 +405,24 @@ func (a *Api) handleSignalReceive(ws *websocket.Conn, number string, stop chan s
if err == nil { if err == nil {
if data != "" { if data != "" {
err = ws.WriteMessage(websocket.TextMessage, []byte(data)) type Response struct {
Account string `json:"account"`
}
var response Response
err = json.Unmarshal([]byte(data), &response)
if err != nil { if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) { log.Error("Couldn't parse message ", data, ":", err.Error())
log.Error("Couldn't write message: " + err.Error()) continue
}
if response.Account == number {
err = ws.WriteMessage(websocket.TextMessage, []byte(data))
if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
log.Error("Couldn't write message: " + err.Error())
}
return
} }
return
} }
} }
} else { } else {

View File

@@ -377,7 +377,7 @@ func (s *SignalClient) send(number string, message string,
} }
if s.signalCliMode == JsonRpc { if s.signalCliMode == JsonRpc {
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -431,7 +431,7 @@ func (s *SignalClient) send(number string, message string,
request.TextStyles = signalCliTextFormatStrings request.TextStyles = signalCliTextFormatStrings
} }
rawData, err := jsonRpc2Client.getRaw("send", request) rawData, err := jsonRpc2Client.getRaw("send", &number, request)
if err != nil { if err != nil {
cleanupAttachmentEntries(attachmentEntries) cleanupAttachmentEntries(attachmentEntries)
return nil, err return nil, err
@@ -527,20 +527,41 @@ func (s *SignalClient) About() About {
func (s *SignalClient) RegisterNumber(number string, useVoice bool, captcha string) error { func (s *SignalClient) RegisterNumber(number string, useVoice bool, captcha string) error {
if s.signalCliMode == JsonRpc { if s.signalCliMode == JsonRpc {
return errors.New(endpointNotSupportedInJsonRpcMode) type Request struct {
} UseVoice bool `json:"voice,omitempty"`
command := []string{"--config", s.signalCliConfig, "-a", number, "register"} Captcha string `json:"captcha,omitempty"`
Account string `json:"account,omitempty"`
}
request := Request{Account: number}
if useVoice { if useVoice {
command = append(command, "--voice") request.UseVoice = useVoice
} }
if captcha != "" { if captcha != "" {
command = append(command, []string{"--captcha", captcha}...) request.Captcha = captcha
} }
_, err := s.cliClient.Execute(true, command, "") jsonRpc2Client, err := s.getJsonRpc2Client()
return err if err != nil {
return err
}
_, err = jsonRpc2Client.getRaw("register", nil, request)
return err
} else {
command := []string{"--config", s.signalCliConfig, "-a", number, "register"}
if useVoice {
command = append(command, "--voice")
}
if captcha != "" {
command = append(command, []string{"--captcha", captcha}...)
}
_, err := s.cliClient.Execute(true, command, "")
return err
}
} }
func (s *SignalClient) UnregisterNumber(number string, deleteAccount bool, deleteLocalData bool) error { func (s *SignalClient) UnregisterNumber(number string, deleteAccount bool, deleteLocalData bool) error {
@@ -570,17 +591,33 @@ func (s *SignalClient) UnregisterNumber(number string, deleteAccount bool, delet
func (s *SignalClient) VerifyRegisteredNumber(number string, token string, pin string) error { func (s *SignalClient) VerifyRegisteredNumber(number string, token string, pin string) error {
if s.signalCliMode == JsonRpc { if s.signalCliMode == JsonRpc {
return errors.New(endpointNotSupportedInJsonRpcMode) type Request struct {
} VerificationCode string `json:"verificationCode,omitempty"`
Account string `json:"account,omitempty"`
Pin string `json:"pin,omitempty"`
}
request := Request{Account: number, VerificationCode: token}
cmd := []string{"--config", s.signalCliConfig, "-a", number, "verify", token} if pin != "" {
if pin != "" { request.Pin = pin
cmd = append(cmd, "--pin") }
cmd = append(cmd, pin)
}
_, err := s.cliClient.Execute(true, cmd, "") jsonRpc2Client, err := s.getJsonRpc2Client()
return err if err != nil {
return err
}
_, err = jsonRpc2Client.getRaw("verify", nil, request)
return err
} else {
cmd := []string{"--config", s.signalCliConfig, "-a", number, "verify", token}
if pin != "" {
cmd = append(cmd, "--pin")
cmd = append(cmd, pin)
}
_, err := s.cliClient.Execute(true, cmd, "")
return err
}
} }
func (s *SignalClient) SendV1(number string, message string, recipients []string, base64Attachments []string, isGroup bool) (*SendResponse, error) { func (s *SignalClient) SendV1(number string, message string, recipients []string, base64Attachments []string, isGroup bool) (*SendResponse, error) {
@@ -588,8 +625,8 @@ func (s *SignalClient) SendV1(number string, message string, recipients []string
return timestamp, err return timestamp, err
} }
func (s *SignalClient) getJsonRpc2Client(number string) (*JsonRpc2Client, error) { func (s *SignalClient) getJsonRpc2Client() (*JsonRpc2Client, error) {
if val, ok := s.jsonRpc2Clients[number]; ok { if val, ok := s.jsonRpc2Clients[utils.MULTI_ACCOUNT_NUMBER]; ok {
return val, nil return val, nil
} }
return nil, errors.New("Number not registered with JSON-RPC") return nil, errors.New("Number not registered with JSON-RPC")
@@ -692,8 +729,8 @@ func (s *SignalClient) Receive(number string, timeout int64, ignoreAttachments b
} }
} }
func (s *SignalClient) GetReceiveChannel(number string) (chan JsonRpc2ReceivedMessage, error) { func (s *SignalClient) GetReceiveChannel() (chan JsonRpc2ReceivedMessage, error) {
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -729,11 +766,11 @@ func (s *SignalClient) CreateGroup(number string, name string, members []string,
request.AddMembersPermissions = addMembersPermission.String() request.AddMembersPermissions = addMembersPermission.String()
} }
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return "", err return "", err
} }
rawData, err := jsonRpc2Client.getRaw("updateGroup", request) rawData, err := jsonRpc2Client.getRaw("updateGroup", &number, request)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -817,11 +854,11 @@ func (s *SignalClient) updateGroupMembers(number string, groupId string, members
request.RemoveMembers = append(request.RemoveMembers, members...) request.RemoveMembers = append(request.RemoveMembers, members...)
} }
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return err return err
} }
_, err = jsonRpc2Client.getRaw("updateGroup", request) _, err = jsonRpc2Client.getRaw("updateGroup", &number, request)
} else { } else {
cmd := []string{"--config", s.signalCliConfig, "-a", number, "updateGroup", "-g", internalGroupId} cmd := []string{"--config", s.signalCliConfig, "-a", number, "updateGroup", "-g", internalGroupId}
@@ -880,11 +917,11 @@ func (s *SignalClient) updateGroupAdmins(number string, groupId string, admins [
request.RemoveAdmins = append(request.RemoveAdmins, admins...) request.RemoveAdmins = append(request.RemoveAdmins, admins...)
} }
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return err return err
} }
_, err = jsonRpc2Client.getRaw("updateGroup", request) _, err = jsonRpc2Client.getRaw("updateGroup", &number, request)
} else { } else {
cmd := []string{"--config", s.signalCliConfig, "-a", number, "updateGroup", "-g", internalGroupId} cmd := []string{"--config", s.signalCliConfig, "-a", number, "updateGroup", "-g", internalGroupId}
@@ -916,11 +953,11 @@ func (s *SignalClient) GetGroups(number string) ([]GroupEntry, error) {
var rawData string var rawData string
if s.signalCliMode == JsonRpc { if s.signalCliMode == JsonRpc {
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return groupEntries, err return groupEntries, err
} }
rawData, err = jsonRpc2Client.getRaw("listGroups", nil) rawData, err = jsonRpc2Client.getRaw("listGroups", &number, nil)
if err != nil { if err != nil {
return groupEntries, err return groupEntries, err
} }
@@ -999,11 +1036,11 @@ func (s *SignalClient) DeleteGroup(number string, groupId string) error {
} }
request := Request{GroupId: groupId} request := Request{GroupId: groupId}
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return err return err
} }
_, err = jsonRpc2Client.getRaw("quitGroup", request) _, err = jsonRpc2Client.getRaw("quitGroup", &number, request)
return err return err
} else { } else {
ret, err := s.cliClient.Execute(true, []string{"--config", s.signalCliConfig, "-a", number, "quitGroup", "-g", string(groupId)}, "") ret, err := s.cliClient.Execute(true, []string{"--config", s.signalCliConfig, "-a", number, "quitGroup", "-g", string(groupId)}, "")
@@ -1139,11 +1176,11 @@ func (s *SignalClient) UpdateProfile(number string, profileName string, base64Av
request.Avatar = avatarTmpPath request.Avatar = avatarTmpPath
request.RemoveAvatar = false request.RemoveAvatar = false
} }
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return err return err
} }
_, err = jsonRpc2Client.getRaw("updateProfile", request) _, err = jsonRpc2Client.getRaw("updateProfile", &number, request)
} else { } else {
cmd := []string{"--config", s.signalCliConfig, "-a", number, "updateProfile", "--given-name", profileName} cmd := []string{"--config", s.signalCliConfig, "-a", number, "updateProfile", "--given-name", profileName}
if base64Avatar == "" { if base64Avatar == "" {
@@ -1162,11 +1199,11 @@ func (s *SignalClient) UpdateProfile(number string, profileName string, base64Av
func (s *SignalClient) ListIdentities(number string) (*[]IdentityEntry, error) { func (s *SignalClient) ListIdentities(number string) (*[]IdentityEntry, error) {
identityEntries := []IdentityEntry{} identityEntries := []IdentityEntry{}
if s.signalCliMode == JsonRpc { if s.signalCliMode == JsonRpc {
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return nil, err return nil, err
} }
rawData, err := jsonRpc2Client.getRaw("listIdentities", nil) rawData, err := jsonRpc2Client.getRaw("listIdentities", &number, nil)
signalCliIdentityEntries := []SignalCliIdentityEntry{} signalCliIdentityEntries := []SignalCliIdentityEntry{}
err = json.Unmarshal([]byte(rawData), &signalCliIdentityEntries) err = json.Unmarshal([]byte(rawData), &signalCliIdentityEntries)
if err != nil { if err != nil {
@@ -1224,11 +1261,11 @@ func (s *SignalClient) TrustIdentity(number string, numberToTrust string, verifi
request.TrustAllKnownKeys = *trustAllKnownKeys request.TrustAllKnownKeys = *trustAllKnownKeys
} }
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return err return err
} }
_, err = jsonRpc2Client.getRaw("trust", request) _, err = jsonRpc2Client.getRaw("trust", &number, request)
} else { } else {
cmd := []string{"--config", s.signalCliConfig, "-a", number, "trust", numberToTrust} cmd := []string{"--config", s.signalCliConfig, "-a", number, "trust", numberToTrust}
@@ -1252,11 +1289,11 @@ func (s *SignalClient) BlockGroup(number string, groupId string) error {
GroupId string `json:"groupId"` GroupId string `json:"groupId"`
} }
request := Request{GroupId: groupId} request := Request{GroupId: groupId}
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return err return err
} }
_, err = jsonRpc2Client.getRaw("block", request) _, err = jsonRpc2Client.getRaw("block", &number, request)
} else { } else {
_, err = s.cliClient.Execute(true, []string{"--config", s.signalCliConfig, "-a", number, "block", "-g", groupId}, "") _, err = s.cliClient.Execute(true, []string{"--config", s.signalCliConfig, "-a", number, "block", "-g", groupId}, "")
} }
@@ -1270,11 +1307,11 @@ func (s *SignalClient) JoinGroup(number string, groupId string) error {
GroupId string `json:"groupId"` GroupId string `json:"groupId"`
} }
request := Request{GroupId: groupId} request := Request{GroupId: groupId}
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return err return err
} }
_, err = jsonRpc2Client.getRaw("updateGroup", request) _, err = jsonRpc2Client.getRaw("updateGroup", &number, request)
} else { } else {
_, err = s.cliClient.Execute(true, []string{"--config", s.signalCliConfig, "-a", number, "updateGroup", "-g", groupId}, "") _, err = s.cliClient.Execute(true, []string{"--config", s.signalCliConfig, "-a", number, "updateGroup", "-g", groupId}, "")
} }
@@ -1288,11 +1325,11 @@ func (s *SignalClient) QuitGroup(number string, groupId string) error {
GroupId string `json:"groupId"` GroupId string `json:"groupId"`
} }
request := Request{GroupId: groupId} request := Request{GroupId: groupId}
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return err return err
} }
_, err = jsonRpc2Client.getRaw("quitGroup", request) _, err = jsonRpc2Client.getRaw("quitGroup", &number, request)
} else { } else {
_, err = s.cliClient.Execute(true, []string{"--config", s.signalCliConfig, "-a", number, "quitGroup", "-g", groupId}, "") _, err = s.cliClient.Execute(true, []string{"--config", s.signalCliConfig, "-a", number, "quitGroup", "-g", groupId}, "")
} }
@@ -1354,11 +1391,11 @@ func (s *SignalClient) UpdateGroup(number string, groupId string, base64Avatar *
request.Name = groupName request.Name = groupName
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return err return err
} }
_, err = jsonRpc2Client.getRaw("updateGroup", request) _, err = jsonRpc2Client.getRaw("updateGroup", &number, request)
} else { } else {
cmd := []string{"--config", s.signalCliConfig, "-a", number, "updateGroup", "-g", groupId} cmd := []string{"--config", s.signalCliConfig, "-a", number, "updateGroup", "-g", groupId}
if base64Avatar != nil { if base64Avatar != nil {
@@ -1420,11 +1457,11 @@ func (s *SignalClient) SendReaction(number string, recipient string, emoji strin
if remove { if remove {
request.Remove = remove request.Remove = remove
} }
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return err return err
} }
_, err = jsonRpc2Client.getRaw("sendReaction", request) _, err = jsonRpc2Client.getRaw("sendReaction", &number, request)
return err return err
} }
@@ -1470,11 +1507,11 @@ func (s *SignalClient) SendStartTyping(number string, recipient string) error {
request.GroupId = recp request.GroupId = recp
} }
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return err return err
} }
_, err = jsonRpc2Client.getRaw("sendTyping", request) _, err = jsonRpc2Client.getRaw("sendTyping", &number, request)
} else { } else {
cmd := []string{"--config", s.signalCliConfig, "-a", number, "sendTyping"} cmd := []string{"--config", s.signalCliConfig, "-a", number, "sendTyping"}
if !isGroup { if !isGroup {
@@ -1513,11 +1550,11 @@ func (s *SignalClient) SendStopTyping(number string, recipient string) error {
request.GroupId = recp request.GroupId = recp
} }
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return err return err
} }
_, err = jsonRpc2Client.getRaw("sendTyping", request) _, err = jsonRpc2Client.getRaw("sendTyping", &number, request)
} else { } else {
cmd := []string{"--config", s.signalCliConfig, "-a", number, "sendTyping", "--stop"} cmd := []string{"--config", s.signalCliConfig, "-a", number, "sendTyping", "--stop"}
if !isGroup { if !isGroup {
@@ -1547,7 +1584,7 @@ func (s *SignalClient) SearchForNumbers(number string, numbers []string) ([]Sear
return searchResultEntries, errors.New("No JsonRpc2Client registered!") return searchResultEntries, errors.New("No JsonRpc2Client registered!")
} }
for _, jsonRpc2Client := range jsonRpc2Clients { for _, jsonRpc2Client := range jsonRpc2Clients {
rawData, err = jsonRpc2Client.getRaw("getUserStatus", request) rawData, err = jsonRpc2Client.getRaw("getUserStatus", &number, request)
if err == nil { //getUserStatus doesn't need an account to work, so try all the registered acounts and stop until we succeed if err == nil { //getUserStatus doesn't need an account to work, so try all the registered acounts and stop until we succeed
break break
} }
@@ -1592,11 +1629,11 @@ func (s *SignalClient) SearchForNumbers(number string, numbers []string) ([]Sear
func (s* SignalClient) SendContacts(number string) error { func (s* SignalClient) SendContacts(number string) error {
var err error var err error
if s.signalCliMode == JsonRpc { if s.signalCliMode == JsonRpc {
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return err return err
} }
_, err = jsonRpc2Client.getRaw("sendContacts", nil) _, err = jsonRpc2Client.getRaw("sendContacts", &number, nil)
} else { } else {
cmd := []string{"--config", s.signalCliConfig, "-a", number, "sendContacts"} cmd := []string{"--config", s.signalCliConfig, "-a", number, "sendContacts"}
_, err = s.cliClient.Execute(true, cmd, "") _, err = s.cliClient.Execute(true, cmd, "")
@@ -1619,11 +1656,11 @@ func (s *SignalClient) UpdateContact(number string, recipient string, name *stri
if expirationInSeconds != nil { if expirationInSeconds != nil {
request.Expiration = *expirationInSeconds request.Expiration = *expirationInSeconds
} }
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return err return err
} }
_, err = jsonRpc2Client.getRaw("updateContact", request) _, err = jsonRpc2Client.getRaw("updateContact", &number, request)
} else { } else {
cmd := []string{"--config", s.signalCliConfig, "-a", number, "updateContact", recipient} cmd := []string{"--config", s.signalCliConfig, "-a", number, "updateContact", recipient}
if name != nil { if name != nil {
@@ -1644,11 +1681,11 @@ func (s *SignalClient) AddDevice(number string, uri string) error {
Uri string `json:"uri"` Uri string `json:"uri"`
} }
request := Request{Uri: uri} request := Request{Uri: uri}
jsonRpc2Client, err := s.getJsonRpc2Client(number) jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil { if err != nil {
return err return err
} }
_, err = jsonRpc2Client.getRaw("addDevice", request) _, err = jsonRpc2Client.getRaw("addDevice", &number, request)
} else { } else {
cmd := []string{"--config", s.signalCliConfig, "-a", number, "addDevice", "--uri", uri} cmd := []string{"--config", s.signalCliConfig, "-a", number, "addDevice", "--uri", uri}
_, err = s.cliClient.Execute(true, cmd, "") _, err = s.cliClient.Execute(true, cmd, "")

View File

@@ -59,7 +59,7 @@ func (r *JsonRpc2Client) Dial(address string) error {
return nil return nil
} }
func (r *JsonRpc2Client) getRaw(command string, args interface{}) (string, error) { func (r *JsonRpc2Client) getRaw(command string, account *string, args interface{}) (string, error) {
type Request struct { type Request struct {
JsonRpc string `json:"jsonrpc"` JsonRpc string `json:"jsonrpc"`
Method string `json:"method"` Method string `json:"method"`
@@ -99,6 +99,13 @@ func (r *JsonRpc2Client) getRaw(command string, args interface{}) (string, error
} }
} }
if account != nil {
fullCommandBytes, err = sjson.SetBytes(fullCommandBytes, "params.account", account)
if err != nil {
return "", err
}
}
log.Debug("full command: ", string(fullCommandBytes)) log.Debug("full command: ", string(fullCommandBytes))
_, err = r.conn.Write([]byte(string(fullCommandBytes) + "\n")) _, err = r.conn.Write([]byte(string(fullCommandBytes) + "\n"))

View File

@@ -1,16 +1,12 @@
package main package main
import ( import (
"encoding/json"
"fmt" "fmt"
"github.com/bbernhard/signal-cli-rest-api/utils" "github.com/bbernhard/signal-cli-rest-api/utils"
"github.com/gabriel-vasile/mimetype"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path/filepath"
"strconv"
"strings" "strings"
) )
@@ -18,7 +14,7 @@ const supervisorctlConfigTemplate = `
[program:%s] [program:%s]
environment=JAVA_HOME=/opt/java/openjdk environment=JAVA_HOME=/opt/java/openjdk
process_name=%s process_name=%s
command=bash -c "nc -l -p %d <%s | signal-cli --output=json -u %s --config %s jsonRpc >%s" command=bash -c "nc -l -p %d <%s | signal-cli --output=json --config %s jsonRpc >%s"
autostart=true autostart=true
autorestart=true autorestart=true
startretries=10 startretries=10
@@ -32,37 +28,6 @@ stdout_logfile_backups=10
numprocs=1 numprocs=1
` `
func isSignalCliLinkedNumberConfigFile(filename string) (bool, error) {
fileExtension := filepath.Ext(filename)
if fileExtension != "" {
return false, nil
}
mimetype, err := mimetype.DetectFile(filename)
if err != nil {
return false, err
}
if mimetype.String() == "application/json" {
return true, nil
}
return false, nil
}
func getUsernameFromLinkedNumberConfigFile(filename string) (string, error) {
type LinkedNumberConfigFile struct {
Username string `json:"username"`
}
bytes, err := ioutil.ReadFile(filename)
if err != nil {
return "", err
}
var linkedNumberConfigFile LinkedNumberConfigFile
err = json.Unmarshal(bytes, &linkedNumberConfigFile)
if err != nil {
return "", err
}
return linkedNumberConfigFile.Username, nil
}
func main() { func main() {
signalCliConfigDir := "/home/.local/share/signal-cli/" signalCliConfigDir := "/home/.local/share/signal-cli/"
signalCliConfigDirEnv := utils.GetEnv("SIGNAL_CLI_CONFIG_DIR", "") signalCliConfigDirEnv := utils.GetEnv("SIGNAL_CLI_CONFIG_DIR", "")
@@ -73,81 +38,47 @@ func main() {
} }
} }
signalCliConfigDataDir := signalCliConfigDir + "data"
jsonRpc2ClientConfig := utils.NewJsonRpc2ClientConfig() jsonRpc2ClientConfig := utils.NewJsonRpc2ClientConfig()
var tcpBasePort int64 = 6000 var tcpPort int64 = 6001
fifoBasePathName := "/tmp/sigsocket" fifoPathname := "/tmp/sigsocket1"
var ctr int64 = 0
items, err := ioutil.ReadDir(signalCliConfigDataDir) jsonRpc2ClientConfig.AddEntry(utils.MULTI_ACCOUNT_NUMBER, utils.JsonRpc2ClientConfigEntry{TcpPort: tcpPort, FifoPathname: fifoPathname})
os.Remove(fifoPathname) //remove any existing named pipe
_, err := exec.Command("mkfifo", fifoPathname).Output()
if err != nil { if err != nil {
log.Fatal("Couldn't read contents of ", signalCliConfigDataDir, ". Is your phone number properly registered? Please be aware that registering a phone number only works in normal/native mode and is currently not supported in json-rpc mode!") log.Fatal("Couldn't create fifo with name ", fifoPathname, ": ", err.Error())
} }
for _, item := range items {
if item.IsDir() {
continue
}
filename := filepath.Base(item.Name())
isSignalCliLinkedNumberConfigFile, err := isSignalCliLinkedNumberConfigFile(signalCliConfigDataDir + "/" + filename)
if err != nil {
log.Error("Couldn't determine whether file ", filename, " is a signal-cli config file: ", err.Error())
continue
}
if strings.HasPrefix(filename, "+") || isSignalCliLinkedNumberConfigFile { uid := utils.GetEnv("SIGNAL_CLI_UID", "1000")
var number string = "" gid := utils.GetEnv("SIGNAL_CLI_GID", "1000")
if utils.IsPhoneNumber(filename) { _, err = exec.Command("chown", uid+":"+gid, fifoPathname).Output()
number = filename if err != nil {
} else if isSignalCliLinkedNumberConfigFile { log.Fatal("Couldn't change permissions of fifo with name ", fifoPathname, ": ", err.Error())
number, err = getUsernameFromLinkedNumberConfigFile(signalCliConfigDataDir + "/" + filename) }
if err != nil {
log.Debug("Skipping ", filename, " as it is not a valid signal-cli config file: ", err.Error())
continue
}
} else {
log.Error("Skipping ", filename, " as it is not a valid phone number!")
continue
}
fifoPathname := fifoBasePathName + strconv.FormatInt(ctr, 10) supervisorctlProgramName := "signal-cli-json-rpc-1"
tcpPort := tcpBasePort + ctr supervisorctlLogFolder := "/var/log/" + supervisorctlProgramName
jsonRpc2ClientConfig.AddEntry(number, utils.JsonRpc2ClientConfigEntry{TcpPort: tcpPort, FifoPathname: fifoPathname}) _, err = exec.Command("mkdir", "-p", supervisorctlLogFolder).Output()
ctr += 1 if err != nil {
log.Fatal("Couldn't create log folder ", supervisorctlLogFolder, ": ", err.Error())
}
os.Remove(fifoPathname) //remove any existing named pipe log.Info("Updated jsonrpc2.yml")
_, err = exec.Command("mkfifo", fifoPathname).Output() //write supervisorctl config
if err != nil { supervisorctlConfigFilename := "/etc/supervisor/conf.d/" + "signal-cli-json-rpc-1.conf"
log.Fatal("Couldn't create fifo with name ", fifoPathname, ": ", err.Error())
}
uid := utils.GetEnv("SIGNAL_CLI_UID", "1000")
gid := utils.GetEnv("SIGNAL_CLI_GID", "1000")
_, err = exec.Command("chown", uid+":"+gid, fifoPathname).Output()
if err != nil {
log.Fatal("Couldn't change permissions of fifo with name ", fifoPathname, ": ", err.Error())
}
supervisorctlProgramName := "signal-cli-json-rpc-" + strconv.FormatInt(ctr, 10) supervisorctlConfig := fmt.Sprintf(supervisorctlConfigTemplate, supervisorctlProgramName, supervisorctlProgramName,
supervisorctlLogFolder := "/var/log/" + supervisorctlProgramName tcpPort, fifoPathname, signalCliConfigDir, fifoPathname, supervisorctlProgramName, supervisorctlProgramName)
_, err = exec.Command("mkdir", "-p", supervisorctlLogFolder).Output()
if err != nil {
log.Fatal("Couldn't create log folder ", supervisorctlLogFolder, ": ", err.Error())
}
log.Info("Found number ", number, " and added it to jsonrpc2.yml") err = ioutil.WriteFile(supervisorctlConfigFilename, []byte(supervisorctlConfig), 0644)
if err != nil {
//write supervisorctl config log.Fatal("Couldn't write ", supervisorctlConfigFilename, ": ", err.Error())
supervisorctlConfigFilename := "/etc/supervisor/conf.d/" + "signal-cli-json-rpc-" + strconv.FormatInt(ctr, 10) + ".conf"
supervisorctlConfig := fmt.Sprintf(supervisorctlConfigTemplate, supervisorctlProgramName, supervisorctlProgramName,
tcpPort, fifoPathname, number, signalCliConfigDir, fifoPathname, supervisorctlProgramName, supervisorctlProgramName)
err = ioutil.WriteFile(supervisorctlConfigFilename, []byte(supervisorctlConfig), 0644)
if err != nil {
log.Fatal("Couldn't write ", supervisorctlConfigFilename, ": ", err.Error())
}
}
} }
// write jsonrpc.yml config file // write jsonrpc.yml config file

View File

@@ -6,6 +6,8 @@ import (
"io/ioutil" "io/ioutil"
) )
const MULTI_ACCOUNT_NUMBER string = "<multi-account>"
type JsonRpc2ClientConfigEntry struct { type JsonRpc2ClientConfigEntry struct {
TcpPort int64 `yaml:"tcp_port"` TcpPort int64 `yaml:"tcp_port"`
FifoPathname string `yaml:"fifo_pathname"` FifoPathname string `yaml:"fifo_pathname"`