mirror of
https://github.com/aljazceru/signal-cli-rest-api.git
synced 2025-12-19 15:44:28 +01:00
started working on JSON-RPC integration
* still WIP
This commit is contained in:
@@ -18,5 +18,10 @@ EOF
|
|||||||
cap_prefix="-cap_"
|
cap_prefix="-cap_"
|
||||||
caps="$cap_prefix$(seq -s ",$cap_prefix" 0 $(cat /proc/sys/kernel/cap_last_cap))"
|
caps="$cap_prefix$(seq -s ",$cap_prefix" 0 $(cat /proc/sys/kernel/cap_last_cap))"
|
||||||
|
|
||||||
|
# TODO: check mode
|
||||||
|
/usr/bin/jsonrpc2-helper
|
||||||
|
service supervisor start
|
||||||
|
supervisorctl start all
|
||||||
|
|
||||||
# Start API as signal-api user
|
# Start API as signal-api user
|
||||||
exec setpriv --reuid=1000 --regid=1000 --init-groups --inh-caps=$caps signal-cli-rest-api -signal-cli-config=${SIGNAL_CLI_CONFIG_DIR}
|
exec setpriv --reuid=1000 --regid=1000 --init-groups --inh-caps=$caps signal-cli-rest-api -signal-cli-config=${SIGNAL_CLI_CONFIG_DIR}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/cyphar/filepath-securejoin"
|
"github.com/cyphar/filepath-securejoin"
|
||||||
"github.com/gabriel-vasile/mimetype"
|
"github.com/gabriel-vasile/mimetype"
|
||||||
"github.com/h2non/filetype"
|
"github.com/h2non/filetype"
|
||||||
|
//"github.com/sourcegraph/jsonrpc2"//"net/rpc/jsonrpc"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
uuid "github.com/gofrs/uuid"
|
uuid "github.com/gofrs/uuid"
|
||||||
@@ -30,26 +31,36 @@ const groupPrefix = "group."
|
|||||||
const signalCliV2GroupError = "Cannot create a V2 group as self does not have a versioned profile"
|
const signalCliV2GroupError = "Cannot create a V2 group as self does not have a versioned profile"
|
||||||
|
|
||||||
type GroupPermission int
|
type GroupPermission int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultGroupPermission GroupPermission = iota + 1
|
DefaultGroupPermission GroupPermission = iota + 1
|
||||||
EveryMember
|
EveryMember
|
||||||
OnlyAdmins
|
OnlyAdmins
|
||||||
)
|
)
|
||||||
|
|
||||||
type GroupLinkState int
|
type SignalCliMode int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultGroupLinkState GroupLinkState = iota + 1
|
Normal SignalCliMode = iota + 1
|
||||||
|
Native
|
||||||
|
JsonRpc
|
||||||
|
)
|
||||||
|
|
||||||
|
type GroupLinkState int
|
||||||
|
|
||||||
|
const (
|
||||||
|
DefaultGroupLinkState GroupLinkState = iota + 1
|
||||||
Enabled
|
Enabled
|
||||||
EnabledWithApproval
|
EnabledWithApproval
|
||||||
Disabled
|
Disabled
|
||||||
)
|
)
|
||||||
|
|
||||||
func (g GroupPermission) String() string {
|
func (g GroupPermission) String() string {
|
||||||
return []string{"", "default", "every-member", "only-admins"}[g]
|
return []string{"", "default", "every-member", "only-admins"}[g]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g GroupLinkState) String() string {
|
func (g GroupLinkState) String() string {
|
||||||
return []string{"", "enabled", "enabled-with-approval", "disabled"}[g]
|
return []string{"", "enabled", "enabled-with-approval", "disabled"}[g]
|
||||||
}
|
}
|
||||||
|
|
||||||
type GroupEntry struct {
|
type GroupEntry struct {
|
||||||
@@ -71,15 +82,30 @@ type IdentityEntry struct {
|
|||||||
SafetyNumber string `json:"safety_number"`
|
SafetyNumber string `json:"safety_number"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SignalCliGroupMember struct {
|
||||||
|
Number string `json:"number"`
|
||||||
|
Uuid string `json:"uuid"`
|
||||||
|
}
|
||||||
|
|
||||||
type SignalCliGroupEntry struct {
|
type SignalCliGroupEntry struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
IsMember bool `json:"isMember"`
|
IsMember bool `json:"isMember"`
|
||||||
IsBlocked bool `json:"isBlocked"`
|
IsBlocked bool `json:"isBlocked"`
|
||||||
Members []string `json:"members"`
|
Members []SignalCliGroupMember `json:"members"`
|
||||||
PendingMembers []string `json:"pendingMembers"`
|
PendingMembers []string `json:"pendingMembers"`
|
||||||
RequestingMembers []string `json:"requestingMembers"`
|
RequestingMembers []string `json:"requestingMembers"`
|
||||||
GroupInviteLink string `json:"groupInviteLink"`
|
GroupInviteLink string `json:"groupInviteLink"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SignalCliIdentityEntry struct {
|
||||||
|
Number string `json:"number"`
|
||||||
|
Uuid string `json:"uuid"`
|
||||||
|
Fingerprint string `json:"fingerprint"`
|
||||||
|
SafetyNumber string `json:"safetyNumber"`
|
||||||
|
ScannableSafetyNumber string `json:"scannableSafetyNumber"`
|
||||||
|
TrustLevel string `json:"trustLevel"`
|
||||||
|
AddedTimestamp int64 `json:"addedTimestamp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type About struct {
|
type About struct {
|
||||||
@@ -252,7 +278,7 @@ func runSignalCli(wait bool, args []string, stdin string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fullCmd := ""
|
fullCmd := ""
|
||||||
if(stdin != "") {
|
if stdin != "" {
|
||||||
fullCmd += "echo '" + stdin + "' | "
|
fullCmd += "echo '" + stdin + "' | "
|
||||||
}
|
}
|
||||||
fullCmd += signalCliBinary + " " + strings.Join(args, " ")
|
fullCmd += signalCliBinary + " " + strings.Join(args, " ")
|
||||||
@@ -323,19 +349,47 @@ func ConvertGroupIdToInternalGroupId(id string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SignalClient struct {
|
type SignalClient struct {
|
||||||
signalCliConfig string
|
signalCliConfig string
|
||||||
attachmentTmpDir string
|
attachmentTmpDir string
|
||||||
avatarTmpDir string
|
avatarTmpDir string
|
||||||
|
signalCliMode SignalCliMode
|
||||||
|
jsonRpc2ClientConfig *utils.JsonRpc2ClientConfig
|
||||||
|
jsonRpc2ClientConfigPath string
|
||||||
|
jsonRpc2Clients map[string]*JsonRpc2Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSignalClient(signalCliConfig string, attachmentTmpDir string, avatarTmpDir string) *SignalClient {
|
func NewSignalClient(signalCliConfig string, attachmentTmpDir string, avatarTmpDir string, signalCliMode SignalCliMode,
|
||||||
|
jsonRpc2ClientConfigPath string) *SignalClient {
|
||||||
return &SignalClient{
|
return &SignalClient{
|
||||||
signalCliConfig: signalCliConfig,
|
signalCliConfig: signalCliConfig,
|
||||||
attachmentTmpDir: attachmentTmpDir,
|
attachmentTmpDir: attachmentTmpDir,
|
||||||
avatarTmpDir: avatarTmpDir,
|
avatarTmpDir: avatarTmpDir,
|
||||||
|
signalCliMode: signalCliMode,
|
||||||
|
jsonRpc2ClientConfigPath: jsonRpc2ClientConfigPath,
|
||||||
|
jsonRpc2Clients: make(map[string]*JsonRpc2Client),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SignalClient) Init() error {
|
||||||
|
if s.signalCliMode == JsonRpc {
|
||||||
|
s.jsonRpc2ClientConfig = utils.NewJsonRpc2ClientConfig()
|
||||||
|
err := s.jsonRpc2ClientConfig.Load(s.jsonRpc2ClientConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tcpPortsNumberMapping := s.jsonRpc2ClientConfig.GetTcpPortsForNumbers()
|
||||||
|
for number, tcpPort := range tcpPortsNumberMapping {
|
||||||
|
s.jsonRpc2Clients[number] = NewJsonRpc2Client()
|
||||||
|
err := s.jsonRpc2Clients[number].Dial("127.0.0.1:" + strconv.FormatInt(tcpPort, 10))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SignalClient) About() About {
|
func (s *SignalClient) About() About {
|
||||||
about := About{SupportedApiVersions: []string{"v1", "v2"}, BuildNr: 2}
|
about := About{SupportedApiVersions: []string{"v1", "v2"}, BuildNr: 2}
|
||||||
return about
|
return about
|
||||||
@@ -372,6 +426,13 @@ func (s *SignalClient) SendV1(number string, message string, recipients []string
|
|||||||
return timestamp, err
|
return timestamp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SignalClient) getJsonRpc2Client(number string) (*JsonRpc2Client, error) {
|
||||||
|
if val, ok := s.jsonRpc2Clients[number]; ok {
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("Number not registered with JSON-RPC")
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SignalClient) SendV2(number string, message string, recps []string, base64Attachments []string) ([]string, error) {
|
func (s *SignalClient) SendV2(number string, message string, recps []string, base64Attachments []string) ([]string, error) {
|
||||||
if len(recps) == 0 {
|
if len(recps) == 0 {
|
||||||
return []string{}, errors.New("Please provide at least one recipient")
|
return []string{}, errors.New("Please provide at least one recipient")
|
||||||
@@ -444,49 +505,81 @@ func (s *SignalClient) Receive(number string, timeout int64) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignalClient) CreateGroup(number string, name string, members []string, description string, editGroupPermission GroupPermission, addMembersPermission GroupPermission, groupLinkState GroupLinkState) (string, error) {
|
func (s *SignalClient) CreateGroup(number string, name string, members []string, description string, editGroupPermission GroupPermission, addMembersPermission GroupPermission, groupLinkState GroupLinkState) (string, error) {
|
||||||
cmd := []string{"--config", s.signalCliConfig, "-u", number, "updateGroup", "-n", name, "-m"}
|
var err error
|
||||||
cmd = append(cmd, members...)
|
var rawData string
|
||||||
|
if s.signalCliMode == JsonRpc {
|
||||||
if addMembersPermission != DefaultGroupPermission {
|
type Request struct {
|
||||||
cmd = append(cmd, []string{"--set-permission-add-member", addMembersPermission.String()}...)
|
Name string `json:"name"`
|
||||||
}
|
Members []string `json:"members"`
|
||||||
|
|
||||||
if editGroupPermission != DefaultGroupPermission {
|
|
||||||
cmd = append(cmd, []string{"--set-permission-edit-details", editGroupPermission.String()}...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if groupLinkState != DefaultGroupLinkState {
|
|
||||||
cmd = append(cmd, []string{"--link", groupLinkState.String()}...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if description != "" {
|
|
||||||
cmd = append(cmd, []string{"--description", description}...)
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := runSignalCli(true, cmd, "")
|
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), signalCliV2GroupError) {
|
|
||||||
return "", errors.New("Cannot create group - please first update your profile.")
|
|
||||||
}
|
}
|
||||||
return "", err
|
request := Request{Name: name, Members: members}
|
||||||
}
|
|
||||||
|
|
||||||
internalGroupId := getStringInBetween(out, `"`, `"`)
|
jsonRpc2Client, err := s.getJsonRpc2Client(number)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
rawData, err = jsonRpc2Client.getRaw("updateGroup", request)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cmd := []string{"--config", s.signalCliConfig, "-u", number, "updateGroup", "-n", name, "-m"}
|
||||||
|
cmd = append(cmd, members...)
|
||||||
|
|
||||||
|
if addMembersPermission != DefaultGroupPermission {
|
||||||
|
cmd = append(cmd, []string{"--set-permission-add-member", addMembersPermission.String()}...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if editGroupPermission != DefaultGroupPermission {
|
||||||
|
cmd = append(cmd, []string{"--set-permission-edit-details", editGroupPermission.String()}...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if groupLinkState != DefaultGroupLinkState {
|
||||||
|
cmd = append(cmd, []string{"--link", groupLinkState.String()}...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if description != "" {
|
||||||
|
cmd = append(cmd, []string{"--description", description}...)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawData, err = runSignalCli(true, cmd, "")
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), signalCliV2GroupError) {
|
||||||
|
return "", errors.New("Cannot create group - please first update your profile.")
|
||||||
|
}
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internalGroupId := getStringInBetween(rawData, `"`, `"`)
|
||||||
groupId := convertInternalGroupIdToGroupId(internalGroupId)
|
groupId := convertInternalGroupIdToGroupId(internalGroupId)
|
||||||
|
|
||||||
return groupId, nil
|
return groupId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignalClient) GetGroups(number string) ([]GroupEntry, error) {
|
func (s *SignalClient) GetGroups(number string) ([]GroupEntry, error) {
|
||||||
groupEntries := []GroupEntry{}
|
groupEntries := []GroupEntry{}
|
||||||
|
|
||||||
out, err := runSignalCli(true, []string{"--config", s.signalCliConfig, "--output", "json", "-u", number, "listGroups", "-d"}, "")
|
var signalCliGroupEntries []SignalCliGroupEntry
|
||||||
if err != nil {
|
var err error
|
||||||
return groupEntries, err
|
var rawData string
|
||||||
|
|
||||||
|
if s.signalCliMode == JsonRpc {
|
||||||
|
jsonRpc2Client, err := s.getJsonRpc2Client(number)
|
||||||
|
if err != nil {
|
||||||
|
return groupEntries, err
|
||||||
|
}
|
||||||
|
rawData, err = jsonRpc2Client.getRaw("listGroups", nil)
|
||||||
|
if err != nil {
|
||||||
|
return groupEntries, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rawData, err = runSignalCli(true, []string{"--config", s.signalCliConfig, "--output", "json", "-u", number, "listGroups", "-d"}, "")
|
||||||
|
if err != nil {
|
||||||
|
return groupEntries, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var signalCliGroupEntries []SignalCliGroupEntry
|
err = json.Unmarshal([]byte(rawData), &signalCliGroupEntries)
|
||||||
|
|
||||||
err = json.Unmarshal([]byte(out), &signalCliGroupEntries)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return groupEntries, err
|
return groupEntries, err
|
||||||
}
|
}
|
||||||
@@ -497,7 +590,13 @@ func (s *SignalClient) GetGroups(number string) ([]GroupEntry, error) {
|
|||||||
groupEntry.Name = signalCliGroupEntry.Name
|
groupEntry.Name = signalCliGroupEntry.Name
|
||||||
groupEntry.Id = convertInternalGroupIdToGroupId(signalCliGroupEntry.Id)
|
groupEntry.Id = convertInternalGroupIdToGroupId(signalCliGroupEntry.Id)
|
||||||
groupEntry.Blocked = signalCliGroupEntry.IsBlocked
|
groupEntry.Blocked = signalCliGroupEntry.IsBlocked
|
||||||
groupEntry.Members = signalCliGroupEntry.Members
|
|
||||||
|
members := []string{}
|
||||||
|
for _, val := range signalCliGroupEntry.Members {
|
||||||
|
members = append(members, val.Number)
|
||||||
|
}
|
||||||
|
groupEntry.Members = members
|
||||||
|
|
||||||
groupEntry.PendingRequests = signalCliGroupEntry.PendingMembers
|
groupEntry.PendingRequests = signalCliGroupEntry.PendingMembers
|
||||||
groupEntry.PendingInvites = signalCliGroupEntry.RequestingMembers
|
groupEntry.PendingInvites = signalCliGroupEntry.RequestingMembers
|
||||||
groupEntry.InviteLink = signalCliGroupEntry.GroupInviteLink
|
groupEntry.InviteLink = signalCliGroupEntry.GroupInviteLink
|
||||||
@@ -602,12 +701,9 @@ func (s *SignalClient) GetAttachment(attachment string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignalClient) UpdateProfile(number string, profileName string, base64Avatar string) error {
|
func (s *SignalClient) UpdateProfile(number string, profileName string, base64Avatar string) error {
|
||||||
cmd := []string{"--config", s.signalCliConfig, "-u", number, "updateProfile", "--name", profileName}
|
var err error
|
||||||
|
var avatarTmpPath string
|
||||||
avatarTmpPaths := []string{}
|
if base64Avatar != "" {
|
||||||
if base64Avatar == "" {
|
|
||||||
cmd = append(cmd, "--remove-avatar")
|
|
||||||
} else {
|
|
||||||
u, err := uuid.NewV4()
|
u, err := uuid.NewV4()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -615,7 +711,7 @@ func (s *SignalClient) UpdateProfile(number string, profileName string, base64Av
|
|||||||
|
|
||||||
avatarBytes, err := base64.StdEncoding.DecodeString(base64Avatar)
|
avatarBytes, err := base64.StdEncoding.DecodeString(base64Avatar)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("Couldn't decode base64 encoded avatar: " +err.Error())
|
return errors.New("Couldn't decode base64 encoded avatar: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
fType, err := filetype.Get(avatarBytes)
|
fType, err := filetype.Get(avatarBytes)
|
||||||
@@ -632,51 +728,113 @@ func (s *SignalClient) UpdateProfile(number string, profileName string, base64Av
|
|||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
if _, err := f.Write(avatarBytes); err != nil {
|
if _, err := f.Write(avatarBytes); err != nil {
|
||||||
cleanupTmpFiles(avatarTmpPaths)
|
cleanupTmpFiles([]string{avatarTmpPath})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := f.Sync(); err != nil {
|
if err := f.Sync(); err != nil {
|
||||||
cleanupTmpFiles(avatarTmpPaths)
|
cleanupTmpFiles([]string{avatarTmpPath})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
f.Close()
|
f.Close()
|
||||||
|
|
||||||
cmd = append(cmd, []string{"--avatar", avatarTmpPath}...)
|
|
||||||
avatarTmpPaths = append(avatarTmpPaths, avatarTmpPath)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := runSignalCli(true, cmd, "")
|
if s.signalCliMode == JsonRpc {
|
||||||
cleanupTmpFiles(avatarTmpPaths)
|
type Request struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Avatar string `json:"avatar,omitempty"`
|
||||||
|
RemoveAvatar bool `json:"remove-avatar"`
|
||||||
|
}
|
||||||
|
request := Request{Name: profileName}
|
||||||
|
if base64Avatar == "" {
|
||||||
|
request.RemoveAvatar = true
|
||||||
|
} else {
|
||||||
|
request.Avatar = avatarTmpPath
|
||||||
|
request.RemoveAvatar = false
|
||||||
|
}
|
||||||
|
jsonRpc2Client, err := s.getJsonRpc2Client(number)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = jsonRpc2Client.getRaw("updateProfile", request)
|
||||||
|
} else {
|
||||||
|
cmd := []string{"--config", s.signalCliConfig, "-u", number, "updateProfile", "--name", profileName}
|
||||||
|
if base64Avatar == "" {
|
||||||
|
cmd = append(cmd, "--remove-avatar")
|
||||||
|
} else {
|
||||||
|
cmd = append(cmd, []string{"--avatar", avatarTmpPath}...)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = runSignalCli(true, cmd, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanupTmpFiles([]string{avatarTmpPath})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignalClient) ListIdentities(number string) (*[]IdentityEntry, error) {
|
func (s *SignalClient) ListIdentities(number string) (*[]IdentityEntry, error) {
|
||||||
out, err := runSignalCli(true, []string{"--config", s.signalCliConfig, "-u", number, "listIdentities"}, "")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
identityEntries := []IdentityEntry{}
|
identityEntries := []IdentityEntry{}
|
||||||
keyValuePairs := parseWhitespaceDelimitedKeyValueStringList(out, []string{"NumberAndTrustStatus", "Added", "Fingerprint", "Safety Number"})
|
if s.signalCliMode == JsonRpc {
|
||||||
for _, keyValuePair := range keyValuePairs {
|
jsonRpc2Client, err := s.getJsonRpc2Client(number)
|
||||||
numberAndTrustStatus := keyValuePair["NumberAndTrustStatus"]
|
if err != nil {
|
||||||
numberAndTrustStatusSplitted := strings.Split(numberAndTrustStatus, ":")
|
return nil, err
|
||||||
|
}
|
||||||
identityEntry := IdentityEntry{Number: strings.Trim(numberAndTrustStatusSplitted[0], " "),
|
rawData, err := jsonRpc2Client.getRaw("listIdentities", nil)
|
||||||
Status: strings.Trim(numberAndTrustStatusSplitted[1], " "),
|
signalCliIdentityEntries := []SignalCliIdentityEntry{}
|
||||||
Added: keyValuePair["Added"],
|
err = json.Unmarshal([]byte(rawData), &signalCliIdentityEntries)
|
||||||
Fingerprint: strings.Trim(keyValuePair["Fingerprint"], " "),
|
if err != nil {
|
||||||
SafetyNumber: strings.Trim(keyValuePair["Safety Number"], " "),
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, signalCliIdentityEntry := range signalCliIdentityEntries {
|
||||||
|
identityEntry := IdentityEntry{
|
||||||
|
Number: signalCliIdentityEntry.Number,
|
||||||
|
Status: signalCliIdentityEntry.TrustLevel,
|
||||||
|
Added: strconv.FormatInt(signalCliIdentityEntry.AddedTimestamp, 10),
|
||||||
|
Fingerprint: signalCliIdentityEntry.Fingerprint,
|
||||||
|
SafetyNumber: signalCliIdentityEntry.SafetyNumber,
|
||||||
|
}
|
||||||
|
identityEntries = append(identityEntries, identityEntry)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rawData, err := runSignalCli(true, []string{"--config", s.signalCliConfig, "-u", number, "listIdentities"}, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
keyValuePairs := parseWhitespaceDelimitedKeyValueStringList(rawData, []string{"NumberAndTrustStatus", "Added", "Fingerprint", "Safety Number"})
|
||||||
|
for _, keyValuePair := range keyValuePairs {
|
||||||
|
numberAndTrustStatus := keyValuePair["NumberAndTrustStatus"]
|
||||||
|
numberAndTrustStatusSplitted := strings.Split(numberAndTrustStatus, ":")
|
||||||
|
|
||||||
|
identityEntry := IdentityEntry{Number: strings.Trim(numberAndTrustStatusSplitted[0], " "),
|
||||||
|
Status: strings.Trim(numberAndTrustStatusSplitted[1], " "),
|
||||||
|
Added: keyValuePair["Added"],
|
||||||
|
Fingerprint: strings.Trim(keyValuePair["Fingerprint"], " "),
|
||||||
|
SafetyNumber: strings.Trim(keyValuePair["Safety Number"], " "),
|
||||||
|
}
|
||||||
|
identityEntries = append(identityEntries, identityEntry)
|
||||||
}
|
}
|
||||||
identityEntries = append(identityEntries, identityEntry)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &identityEntries, nil
|
return &identityEntries, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignalClient) TrustIdentity(number string, numberToTrust string, verifiedSafetyNumber string) error {
|
func (s *SignalClient) TrustIdentity(number string, numberToTrust string, verifiedSafetyNumber string) error {
|
||||||
cmd := []string{"--config", s.signalCliConfig, "-u", number, "trust", numberToTrust, "--verified-safety-number", verifiedSafetyNumber}
|
var err error
|
||||||
_, err := runSignalCli(true, cmd, "")
|
if s.signalCliMode == JsonRpc {
|
||||||
|
type Request struct {
|
||||||
|
VerifiedSafetyNumber string `json:"verified-safety-number"`
|
||||||
|
Recipient string `json:"recipient"`
|
||||||
|
}
|
||||||
|
request := Request{VerifiedSafetyNumber: verifiedSafetyNumber, Recipient: numberToTrust}
|
||||||
|
jsonRpc2Client, err := s.getJsonRpc2Client(number)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = jsonRpc2Client.getRaw("trust", request)
|
||||||
|
} else {
|
||||||
|
cmd := []string{"--config", s.signalCliConfig, "-u", number, "trust", numberToTrust, "--verified-safety-number", verifiedSafetyNumber}
|
||||||
|
_, err = runSignalCli(true, cmd, "")
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -686,11 +844,37 @@ func (s *SignalClient) BlockGroup(number string, groupId string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignalClient) JoinGroup(number string, groupId string) error {
|
func (s *SignalClient) JoinGroup(number string, groupId string) error {
|
||||||
_, err := runSignalCli(true, []string{"--config", s.signalCliConfig, "-u", number, "updateGroup", "-g", groupId}, "")
|
var err error
|
||||||
|
if s.signalCliMode == JsonRpc {
|
||||||
|
type Request struct {
|
||||||
|
GroupId string `json:"groupId"`
|
||||||
|
}
|
||||||
|
request := Request{GroupId: groupId}
|
||||||
|
jsonRpc2Client, err := s.getJsonRpc2Client(number)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = jsonRpc2Client.getRaw("updateGroup", request)
|
||||||
|
} else {
|
||||||
|
_, err = runSignalCli(true, []string{"--config", s.signalCliConfig, "-u", number, "updateGroup", "-g", groupId}, "")
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SignalClient) QuitGroup(number string, groupId string) error {
|
func (s *SignalClient) QuitGroup(number string, groupId string) error {
|
||||||
_, err := runSignalCli(true, []string{"--config", s.signalCliConfig, "-u", number, "quitGroup", "-g", groupId}, "")
|
var err error
|
||||||
|
if s.signalCliMode == JsonRpc {
|
||||||
|
type Request struct {
|
||||||
|
GroupId string `json:"groupId"`
|
||||||
|
}
|
||||||
|
request := Request{GroupId: groupId}
|
||||||
|
jsonRpc2Client, err := s.getJsonRpc2Client(number)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = jsonRpc2Client.getRaw("quitGroup", request)
|
||||||
|
} else {
|
||||||
|
_, err = runSignalCli(true, []string{"--config", s.signalCliConfig, "-u", number, "quitGroup", "-g", groupId}, "")
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
95
src/client/jsonrpc2.go
Normal file
95
src/client/jsonrpc2.go
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"bufio"
|
||||||
|
uuid "github.com/gofrs/uuid"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JsonRpc2Client struct {
|
||||||
|
conn net.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewJsonRpc2Client() *JsonRpc2Client {
|
||||||
|
return &JsonRpc2Client{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *JsonRpc2Client) Dial(address string) error {
|
||||||
|
var err error
|
||||||
|
r.conn, err = net.Dial("tcp", address)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *JsonRpc2Client) getRaw(command string, args interface{}) (string, error) {
|
||||||
|
type Request struct {
|
||||||
|
JsonRpc string `json:"jsonrpc"`
|
||||||
|
Method string `json:"method"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
Params interface{} `json:"params,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Error struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Result json.RawMessage `json:"result"`
|
||||||
|
Err Error `json:"error"`
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := uuid.NewV4()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
fullCommand := Request{JsonRpc: "2.0", Method: command, Id: u.String()}
|
||||||
|
if args != nil {
|
||||||
|
fullCommand.Params = args
|
||||||
|
}
|
||||||
|
|
||||||
|
fullCommandBytes, err := json.Marshal(fullCommand)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("request = ", string(fullCommandBytes))
|
||||||
|
|
||||||
|
_, err = r.conn.Write([]byte(string(fullCommandBytes) + "\n"))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
connbuf := bufio.NewReader(r.conn)
|
||||||
|
for {
|
||||||
|
str, err := connbuf.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp Response
|
||||||
|
err = json.Unmarshal([]byte(str), &resp)
|
||||||
|
if err == nil {
|
||||||
|
if resp.Id == u.String() {
|
||||||
|
log.Info("Response1 = ", string(resp.Result))
|
||||||
|
if resp.Err.Code != 0 {
|
||||||
|
return "", errors.New(resp.Err.Message)
|
||||||
|
}
|
||||||
|
return string(resp.Result), nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Info("Response = ", str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", errors.New("no data")
|
||||||
|
}
|
||||||
@@ -23,5 +23,5 @@ require (
|
|||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
|
||||||
golang.org/x/text v0.3.3 // indirect
|
golang.org/x/text v0.3.3 // indirect
|
||||||
golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f // indirect
|
golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f // indirect
|
||||||
gopkg.in/yaml.v2 v2.3.0 // indirect
|
gopkg.in/yaml.v2 v2.3.0
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrP
|
|||||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/gabriel-vasile/mimetype v1.1.2 h1:gaPnPcNor5aZSVCJVSGipcpbgMWiAAj9z182ocSGbHU=
|
github.com/gabriel-vasile/mimetype v1.1.2 h1:gaPnPcNor5aZSVCJVSGipcpbgMWiAAj9z182ocSGbHU=
|
||||||
github.com/gabriel-vasile/mimetype v1.1.2/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
|
github.com/gabriel-vasile/mimetype v1.1.2/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
|
||||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||||
@@ -70,6 +71,7 @@ github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW
|
|||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/h2non/filetype v1.1.0 h1:Or/gjocJrJRNK/Cri/TDEKFjAR+cfG6eK65NGYB6gBA=
|
github.com/h2non/filetype v1.1.0 h1:Or/gjocJrJRNK/Cri/TDEKFjAR+cfG6eK65NGYB6gBA=
|
||||||
github.com/h2non/filetype v1.1.0/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
|
github.com/h2non/filetype v1.1.0/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
|
||||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
@@ -95,6 +97,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
@@ -143,6 +147,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
@@ -156,9 +161,11 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@@ -188,8 +195,10 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
|
|||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||||
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
|
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|||||||
@@ -73,7 +73,13 @@ func main() {
|
|||||||
log.Fatal("Couldn't set env variable: ", err.Error())
|
log.Fatal("Couldn't set env variable: ", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
signalClient := client.NewSignalClient(*signalCliConfig, *attachmentTmpDir, *avatarTmpDir)
|
jsonRpc2ClientConfigPathPath := *signalCliConfig + "/jsonrpc2.yml"
|
||||||
|
signalClient := client.NewSignalClient(*signalCliConfig, *attachmentTmpDir, *avatarTmpDir, client.JsonRpc, jsonRpc2ClientConfigPathPath)
|
||||||
|
err = signalClient.Init()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Couldn't init Signal Client: ", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
api := api.NewApi(signalClient)
|
api := api.NewApi(signalClient)
|
||||||
v1 := router.Group("/v1")
|
v1 := router.Group("/v1")
|
||||||
{
|
{
|
||||||
|
|||||||
80
src/utils/config.go
Normal file
80
src/utils/config.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"errors"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConfigEntry struct {
|
||||||
|
TcpPort int64 `yaml:"tcp_port"`
|
||||||
|
FifoPathname string `yaml:"fifo_pathname"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Entries map[string]ConfigEntry `yaml:"config,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonRpc2ClientConfig struct {
|
||||||
|
config Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewJsonRpc2ClientConfig() *JsonRpc2ClientConfig {
|
||||||
|
return &JsonRpc2ClientConfig{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *JsonRpc2ClientConfig) Load(path string) error {
|
||||||
|
data, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = yaml.Unmarshal(data, &c.config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *JsonRpc2ClientConfig) GetTcpPortForNumber(number string) (int64, error) {
|
||||||
|
if val, ok := c.config.Entries[number]; ok {
|
||||||
|
return val.TcpPort, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, errors.New("No number found")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *JsonRpc2ClientConfig) GetFifoPathnameForNumber(number string) (string, error) {
|
||||||
|
if val, ok := c.config.Entries[number]; ok {
|
||||||
|
return val.FifoPathname, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", errors.New("No number found")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *JsonRpc2ClientConfig) GetTcpPortsForNumbers() map[string]int64 {
|
||||||
|
mapping := make(map[string]int64)
|
||||||
|
for number, val := range c.config.Entries {
|
||||||
|
mapping[number] = val.TcpPort
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapping
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *JsonRpc2ClientConfig) AddEntry(number string, configEntry ConfigEntry) {
|
||||||
|
if c.config.Entries == nil {
|
||||||
|
c.config.Entries = make(map[string]ConfigEntry)
|
||||||
|
}
|
||||||
|
c.config.Entries[number] = configEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *JsonRpc2ClientConfig) Persist(path string) error {
|
||||||
|
out, err := yaml.Marshal(&c.config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ioutil.WriteFile(path, out, 0644)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user