Merge branch 'generated' into 'main'
Generated client for documented parts of protocol See merge request signald/signald-go!2
This commit is contained in:
commit
10ff70408d
24 changed files with 1965 additions and 137 deletions
|
@ -2,25 +2,27 @@ stages:
|
||||||
- build
|
- build
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
image: nixery.dev/shell/go/golangci-lint
|
image: nixery.dev/shell/diffutils/go/golangci-lint
|
||||||
stage: build
|
stage: build
|
||||||
before_script:
|
before_script:
|
||||||
- cp /share/go/bin/go /bin && mkdir /tmp # fix weirdness from nixery image
|
- cp /share/go/bin/go /bin && mkdir /tmp # fix weirdness from nixery image
|
||||||
- mkdir -p /go/src/git.callpipe.com/finn/signald-go
|
- mkdir -p /go/src/src/gitlab.com/signald/signald-go
|
||||||
- cp -r * /go/src/git.callpipe.com/finn/signald-go
|
- cp -r * /go/src/src/gitlab.com/signald/signald-go
|
||||||
- cd /go/src/git.callpipe.com/finn/signald-go
|
- cd /go/src/src/gitlab.com/signald/signald-go
|
||||||
script:
|
script:
|
||||||
- golangci-lint run
|
- golangci-lint run
|
||||||
|
- go mod tidy
|
||||||
|
- diff --color=always go.mod "${CI_PROJECT_DIR}/go.mod"
|
||||||
|
- diff --color=always go.sum "${CI_PROJECT_DIR}/go.sum"
|
||||||
|
|
||||||
build:
|
build:
|
||||||
stage: build
|
stage: build
|
||||||
image: golang:latest
|
image: golang:latest
|
||||||
before_script:
|
before_script:
|
||||||
- mkdir -p /go/src/git.callpipe.com/finn/signald-go
|
- mkdir -p /go/src/gitlab.com/signald/signald-go
|
||||||
- cp -r * /go/src/git.callpipe.com/finn/signald-go
|
- cp -r * /go/src/gitlab.com/signald/signald-go
|
||||||
- cd /go/src/git.callpipe.com/finn/signald-go
|
- cd /go/src/gitlab.com/signald/signald-go
|
||||||
script:
|
script:
|
||||||
- go get ./... # TODO: Improve how dependencies are handled
|
|
||||||
- go build -o "${CI_PROJECT_DIR}/signald-cli" ./cmd/signald-cli
|
- go build -o "${CI_PROJECT_DIR}/signald-cli" ./cmd/signald-cli
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
|
|
12
Makefile
Normal file
12
Makefile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
signald-cli: signald/client-protocol
|
||||||
|
go build -o signald-cli ./cmd/signald-cli
|
||||||
|
|
||||||
|
protocol.json:
|
||||||
|
echo '{"type": "protocol", "version": "v1alpha1"}' | nc -q0 -U /var/run/signald/signald.sock | jq 'select(.type == "protocol").data' > protocol.json
|
||||||
|
|
||||||
|
signald/client-protocol: protocol.json tools/generator/*
|
||||||
|
go run ./tools/generator < protocol.json
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf protocol.json
|
||||||
|
rm -rf signald/client-protocol/*
|
|
@ -24,7 +24,7 @@ import (
|
||||||
"github.com/mdp/qrterminal"
|
"github.com/mdp/qrterminal"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"git.callpipe.com/finn/signald-go/signald"
|
"gitlab.com/signald/signald-go/signald/client-protocol/v0"
|
||||||
)
|
)
|
||||||
|
|
||||||
var uriOrQR bool
|
var uriOrQR bool
|
||||||
|
@ -36,7 +36,7 @@ var linkCmd = &cobra.Command{
|
||||||
Long: `Get a URI or QR code to link to an existing Signal account`,
|
Long: `Get a URI or QR code to link to an existing Signal account`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
requestID := fmt.Sprint("signald-cli-", rand.Intn(1000))
|
requestID := fmt.Sprint("signald-cli-", rand.Intn(1000))
|
||||||
err := s.SendRequest(signald.Request{
|
err := s.RawRequest(v0.LegacyRequest{
|
||||||
Type: "link",
|
Type: "link",
|
||||||
ID: requestID,
|
ID: requestID,
|
||||||
})
|
})
|
||||||
|
@ -44,7 +44,7 @@ var linkCmd = &cobra.Command{
|
||||||
log.Fatal("error sending request: ", err)
|
log.Fatal("error sending request: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c := make(chan signald.Response)
|
c := make(chan v0.LegacyResponse)
|
||||||
go s.Listen(c)
|
go s.Listen(c)
|
||||||
for {
|
for {
|
||||||
message := <-c
|
message := <-c
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"git.callpipe.com/finn/signald-go/signald"
|
"gitlab.com/signald/signald-go/signald/client-protocol/v0"
|
||||||
)
|
)
|
||||||
|
|
||||||
// listAccountsCmd represents the listAccounts command
|
// listAccountsCmd represents the listAccounts command
|
||||||
|
@ -32,7 +32,7 @@ var listAccountsCmd = &cobra.Command{
|
||||||
Long: `Prints a list of all users to stdout.`,
|
Long: `Prints a list of all users to stdout.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
requestID := fmt.Sprint("signald-cli-", rand.Intn(1000))
|
requestID := fmt.Sprint("signald-cli-", rand.Intn(1000))
|
||||||
err := s.SendRequest(signald.Request{
|
err := s.RawRequest(v0.LegacyRequest{
|
||||||
Type: "list_accounts",
|
Type: "list_accounts",
|
||||||
ID: requestID,
|
ID: requestID,
|
||||||
})
|
})
|
||||||
|
@ -40,7 +40,7 @@ var listAccountsCmd = &cobra.Command{
|
||||||
log.Fatal("error sending request: ", err)
|
log.Fatal("error sending request: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c := make(chan signald.Response)
|
c := make(chan v0.LegacyResponse)
|
||||||
go s.Listen(c)
|
go s.Listen(c)
|
||||||
for {
|
for {
|
||||||
message := <-c
|
message := <-c
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"git.callpipe.com/finn/signald-go/signald"
|
"gitlab.com/signald/signald-go/signald/client-protocol/v0"
|
||||||
)
|
)
|
||||||
|
|
||||||
// listGroupsCmd represents the listGroups command
|
// listGroupsCmd represents the listGroups command
|
||||||
|
@ -32,7 +32,7 @@ var listGroupsCmd = &cobra.Command{
|
||||||
Long: `Prints a list of all groups the user is in to stdout.`,
|
Long: `Prints a list of all groups the user is in to stdout.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
requestID := fmt.Sprint("signald-cli-", rand.Intn(1000))
|
requestID := fmt.Sprint("signald-cli-", rand.Intn(1000))
|
||||||
err := s.SendRequest(signald.Request{
|
err := s.RawRequest(v0.LegacyRequest{
|
||||||
Type: "list_groups",
|
Type: "list_groups",
|
||||||
Username: username,
|
Username: username,
|
||||||
ID: requestID,
|
ID: requestID,
|
||||||
|
@ -41,7 +41,7 @@ var listGroupsCmd = &cobra.Command{
|
||||||
log.Fatal("error sending request: ", err)
|
log.Fatal("error sending request: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c := make(chan signald.Response)
|
c := make(chan v0.LegacyResponse)
|
||||||
go s.Listen(c)
|
go s.Listen(c)
|
||||||
for {
|
for {
|
||||||
message := <-c
|
message := <-c
|
||||||
|
|
|
@ -23,7 +23,7 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
"git.callpipe.com/finn/signald-go/signald"
|
"gitlab.com/signald/signald-go/signald"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cfgFile string
|
var cfgFile string
|
||||||
|
|
|
@ -16,13 +16,14 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.callpipe.com/finn/signald-go/signald"
|
"gitlab.com/signald/signald-go/signald/client-protocol/v0"
|
||||||
"git.callpipe.com/finn/signald-go/signald/client-protocol/v1"
|
"gitlab.com/signald/signald-go/signald/client-protocol/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -39,13 +40,10 @@ var sendCmd = &cobra.Command{
|
||||||
Short: "send a message to another user or group",
|
Short: "send a message to another user or group",
|
||||||
Long: `send a message to another user or group on Signal`,
|
Long: `send a message to another user or group on Signal`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
request := signald.Request{
|
request := v1.SendRequest{Username: username}
|
||||||
Type: "send",
|
|
||||||
Username: username,
|
|
||||||
}
|
|
||||||
|
|
||||||
if toUser != "" {
|
if toUser != "" {
|
||||||
request.RecipientAddress = v1.JsonAddress{Number: toUser}
|
request.RecipientAddress = &v1.JsonAddress{Number: toUser}
|
||||||
} else if toGroup != "" {
|
} else if toGroup != "" {
|
||||||
request.RecipientGroupID = toGroup
|
request.RecipientGroupID = toGroup
|
||||||
} else {
|
} else {
|
||||||
|
@ -57,25 +55,16 @@ var sendCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
|
|
||||||
if attachment != "" {
|
if attachment != "" {
|
||||||
request.AttachmentFilenames = []string{attachment}
|
request.Attachments = []*v0.JsonAttachment{{Filename: attachment}}
|
||||||
}
|
}
|
||||||
err := s.SendRequest(request)
|
go s.Listen(nil)
|
||||||
|
response, err := request.Submit(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("error sending request: ", err)
|
log.Fatal("error submitting request to signald: ", err)
|
||||||
}
|
}
|
||||||
|
err = json.NewEncoder(os.Stdout).Encode(response)
|
||||||
timeout := 10
|
if err != nil {
|
||||||
|
log.Fatal("error encoding output ", err)
|
||||||
// Wait for the response
|
|
||||||
c := make(chan signald.Response)
|
|
||||||
|
|
||||||
go s.Listen(c)
|
|
||||||
select {
|
|
||||||
case <-c:
|
|
||||||
log.Println("Ok.")
|
|
||||||
case <-time.After(1 * time.Second):
|
|
||||||
// But timeout after a while
|
|
||||||
log.Fatalf("Timeout after %d seconds\n", timeout)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
49
cmd/signald-cli/cmd/version.go
Normal file
49
cmd/signald-cli/cmd/version.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright © 2018 Finn Herzfeld <finn@janky.solutions>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"gitlab.com/signald/signald-go/signald/client-protocol/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// versionCmd represents the version command
|
||||||
|
var versionCmd = &cobra.Command{
|
||||||
|
Use: "version",
|
||||||
|
Short: "print the signald version",
|
||||||
|
Long: `print the signald version`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
go s.Listen(nil)
|
||||||
|
r := v1.VersionRequest{}
|
||||||
|
response, err := r.Submit(s)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
err = json.NewEncoder(os.Stdout).Encode(response)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("error encoding output ", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
RootCmd.AddCommand(versionCmd)
|
||||||
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "git.callpipe.com/finn/signald-go/cmd/signald-cli/cmd"
|
import "gitlab.com/signald/signald-go/cmd/signald-cli/cmd"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cmd.Execute()
|
cmd.Execute()
|
||||||
|
|
7
go.mod
7
go.mod
|
@ -1,9 +1,14 @@
|
||||||
module git.callpipe.com/finn/signald-go
|
module gitlab.com/signald/signald-go
|
||||||
|
|
||||||
go 1.14
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||||
github.com/mdp/qrterminal v1.0.1
|
github.com/mdp/qrterminal v1.0.1
|
||||||
github.com/spf13/cobra v1.0.0
|
github.com/spf13/cobra v1.0.0
|
||||||
github.com/spf13/viper v1.7.0
|
github.com/spf13/viper v1.7.0
|
||||||
|
github.com/stretchr/testify v1.4.0 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 // indirect
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.3.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
11
go.sum
11
go.sum
|
@ -43,6 +43,8 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
@ -184,6 +186,8 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
|
@ -256,6 +260,9 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
|
||||||
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
|
@ -306,6 +313,8 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
|
||||||
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 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
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/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
||||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
@ -315,6 +324,8 @@ 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 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||||
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=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|
945
protocol.json
Normal file
945
protocol.json
Normal file
|
@ -0,0 +1,945 @@
|
||||||
|
{
|
||||||
|
"doc_version": "v1alpha1",
|
||||||
|
"version": {
|
||||||
|
"name": "signald",
|
||||||
|
"version": "0.10.0+git2020-12-06rcea5cb72.51",
|
||||||
|
"branch": "refactor-client-request-handling",
|
||||||
|
"commit": "cea5cb720355afdca460aa30257bdd1317494c7b"
|
||||||
|
},
|
||||||
|
"info": "This document describes objects that may be used when communicating with signald. If this document lacks something you need to generate a client, please open an issue (https://gitlab.com/thefinn93/signald/-/issues/new). This is an initial proposal for the format, and I expect to change it before finalizing it. If it workswell, I hope to slowly move things out of the legacy request types.",
|
||||||
|
"types": {
|
||||||
|
"v1": {
|
||||||
|
"JsonMessageEnvelope": {
|
||||||
|
"fields": {
|
||||||
|
"username": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"sourceDevice": {
|
||||||
|
"type": "int"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"relay": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"type": "long"
|
||||||
|
},
|
||||||
|
"timestampISO": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"serverTimestamp": {
|
||||||
|
"type": "long"
|
||||||
|
},
|
||||||
|
"serverDeliveredTimestamp": {
|
||||||
|
"type": "long"
|
||||||
|
},
|
||||||
|
"hasLegacyMessage": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"hasContent": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isUnidentifiedSender": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"dataMessage": {
|
||||||
|
"type": "JsonDataMessage",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"syncMessage": {
|
||||||
|
"type": "JsonSyncMessage",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"callMessage": {
|
||||||
|
"type": "JsonCallMessage",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"receipt": {
|
||||||
|
"type": "JsonReceiptMessage",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"typing": {
|
||||||
|
"type": "JsonTypingMessage",
|
||||||
|
"version": "v0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SendRequest": {
|
||||||
|
"fields": {
|
||||||
|
"username": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"recipientAddress": {
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"recipientGroupId": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"messageBody": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"attachments": {
|
||||||
|
"list": true,
|
||||||
|
"type": "JsonAttachment",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"quote": {
|
||||||
|
"type": "JsonQuote",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"type": "Long"
|
||||||
|
},
|
||||||
|
"mentions": {
|
||||||
|
"list": true,
|
||||||
|
"type": "JsonMention",
|
||||||
|
"version": "v1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SendResponse": {
|
||||||
|
"fields": {
|
||||||
|
"results": {
|
||||||
|
"list": true,
|
||||||
|
"type": "JsonSendMessageResult",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"type": "long"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ReactRequest": {
|
||||||
|
"fields": {
|
||||||
|
"username": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"recipientAddress": {
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"recipientGroupId": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"reaction": {
|
||||||
|
"type": "JsonReaction",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"type": "long"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"doc": "react to a previous message"
|
||||||
|
},
|
||||||
|
"VersionRequest": {
|
||||||
|
"fields": {}
|
||||||
|
},
|
||||||
|
"JsonVersionMessage": {
|
||||||
|
"fields": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"branch": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"commit": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonAddress": {
|
||||||
|
"fields": {
|
||||||
|
"number": {
|
||||||
|
"type": "String",
|
||||||
|
"doc": "An e164 phone number, starting with +. Currently the only available user-facing Signal identifier."
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"type": "UUID",
|
||||||
|
"doc": "A UUID, the unique identifier for a particular Signal account."
|
||||||
|
},
|
||||||
|
"relay": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonDataMessage": {
|
||||||
|
"fields": {
|
||||||
|
"timestamp": {
|
||||||
|
"type": "long",
|
||||||
|
"doc": "the (unix) timestamp that the message was sent at, according to the sender's device. This is used to uniquely identify this message for things like reactions and quotes."
|
||||||
|
},
|
||||||
|
"attachments": {
|
||||||
|
"list": true,
|
||||||
|
"type": "JsonAttachment",
|
||||||
|
"version": "v0",
|
||||||
|
"doc": "files attached to the incoming message"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "String",
|
||||||
|
"doc": "the text body of the incoming message."
|
||||||
|
},
|
||||||
|
"group": {
|
||||||
|
"type": "JsonGroupInfo",
|
||||||
|
"version": "v1",
|
||||||
|
"doc": "if the incoming message was sent to a v1 group, information about that group will be here"
|
||||||
|
},
|
||||||
|
"groupV2": {
|
||||||
|
"type": "JsonGroupV2Info",
|
||||||
|
"version": "v1",
|
||||||
|
"doc": "is the incoming message was sent to a v2 group, basic identifying information about that group will be here. For full information, use list_groups"
|
||||||
|
},
|
||||||
|
"endSession": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"expiresInSeconds": {
|
||||||
|
"type": "int",
|
||||||
|
"doc": "the expiry timer on the incoming message. Clients should delete records of the message within this number of seconds"
|
||||||
|
},
|
||||||
|
"profileKeyUpdate": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"quote": {
|
||||||
|
"type": "JsonQuote",
|
||||||
|
"version": "v1",
|
||||||
|
"doc": "if the incoming message is a quote or reply to another message, this will contain information about that message"
|
||||||
|
},
|
||||||
|
"contacts": {
|
||||||
|
"list": true,
|
||||||
|
"type": "SharedContact",
|
||||||
|
"version": "v0",
|
||||||
|
"doc": "if the incoming message has a shared contact, the contact's information will be here"
|
||||||
|
},
|
||||||
|
"previews": {
|
||||||
|
"list": true,
|
||||||
|
"type": "JsonPreview",
|
||||||
|
"version": "v0",
|
||||||
|
"doc": "if the incoming message has a link preview, information about that preview will be here"
|
||||||
|
},
|
||||||
|
"sticker": {
|
||||||
|
"type": "JsonSticker",
|
||||||
|
"version": "v0",
|
||||||
|
"doc": "if the incoming message is a sticker, information about the sicker will be here"
|
||||||
|
},
|
||||||
|
"viewOnce": {
|
||||||
|
"type": "boolean",
|
||||||
|
"doc": "indicates the message is a view once message. View once messages typically include no body and a single image attachment. Official Signal clients will prevent the user from saving the image, and once the user has viewed the image once they will destroy the image."
|
||||||
|
},
|
||||||
|
"reaction": {
|
||||||
|
"type": "JsonReaction",
|
||||||
|
"version": "v1",
|
||||||
|
"doc": "if the message adds or removes a reaction to another message, this will indicate what change is being made"
|
||||||
|
},
|
||||||
|
"remoteDelete": {
|
||||||
|
"type": "RemoteDelete",
|
||||||
|
"version": "v0",
|
||||||
|
"doc": "if the inbound message is deleting a previously sent message, indicates which message should be deleted"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonSyncMessage": {
|
||||||
|
"fields": {
|
||||||
|
"sent": {
|
||||||
|
"type": "JsonSentTranscriptMessage",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"contacts": {
|
||||||
|
"type": "JsonAttachment",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"contactsComplete": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"groups": {
|
||||||
|
"type": "JsonAttachment",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"blockedList": {
|
||||||
|
"type": "JsonBlockedListMessage",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"request": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"readMessages": {
|
||||||
|
"list": true,
|
||||||
|
"type": "JsonReadMessage",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"viewOnceOpen": {
|
||||||
|
"type": "JsonViewOnceOpenMessage",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"verified": {
|
||||||
|
"type": "JsonVerifiedMessage",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"configuration": {
|
||||||
|
"type": "ConfigurationMessage",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"stickerPackOperations": {
|
||||||
|
"list": true,
|
||||||
|
"type": "JsonStickerPackOperationMessage",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"fetchType": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"messageRequestResponse": {
|
||||||
|
"type": "JsonMessageRequestResponseMessage",
|
||||||
|
"version": "v1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonQuote": {
|
||||||
|
"fields": {
|
||||||
|
"id": {
|
||||||
|
"type": "long"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"text": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"attachments": {
|
||||||
|
"list": true,
|
||||||
|
"type": "JsonQuotedAttachment",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"mentions": {
|
||||||
|
"list": true,
|
||||||
|
"type": "Mention",
|
||||||
|
"version": "v0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"doc": "A quote is a reply to a previous message. ID is the sent time of the message being replied to"
|
||||||
|
},
|
||||||
|
"JsonMention": {
|
||||||
|
"fields": {
|
||||||
|
"uuid": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"start": {
|
||||||
|
"type": "int"
|
||||||
|
},
|
||||||
|
"length": {
|
||||||
|
"type": "int"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonSendMessageResult": {
|
||||||
|
"fields": {
|
||||||
|
"address": {
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"success": {
|
||||||
|
"type": "Success",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"networkFailure": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"unregisteredFailure": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"identityFailure": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonReaction": {
|
||||||
|
"fields": {
|
||||||
|
"emoji": {
|
||||||
|
"type": "String",
|
||||||
|
"doc": "the emoji to react with"
|
||||||
|
},
|
||||||
|
"remove": {
|
||||||
|
"type": "boolean",
|
||||||
|
"doc": "set to true to remove the reaction. requires emoji be set to previously reacted emoji"
|
||||||
|
},
|
||||||
|
"targetAuthor": {
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1",
|
||||||
|
"doc": "the author of the message being reacted to"
|
||||||
|
},
|
||||||
|
"targetSentTimestamp": {
|
||||||
|
"type": "long",
|
||||||
|
"doc": "the client timestamp of the message being reacted to"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonGroupInfo": {
|
||||||
|
"fields": {
|
||||||
|
"groupId": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"members": {
|
||||||
|
"list": true,
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"avatarId": {
|
||||||
|
"type": "long"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonGroupV2Info": {
|
||||||
|
"fields": {
|
||||||
|
"id": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"masterKey": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"revision": {
|
||||||
|
"type": "int"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"timer": {
|
||||||
|
"type": "int"
|
||||||
|
},
|
||||||
|
"members": {
|
||||||
|
"list": true,
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"pendingMembers": {
|
||||||
|
"list": true,
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"requestingMembers": {
|
||||||
|
"list": true,
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"inviteLinkPassword": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonSentTranscriptMessage": {
|
||||||
|
"fields": {
|
||||||
|
"destination": {
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"type": "long"
|
||||||
|
},
|
||||||
|
"expirationStartTimestamp": {
|
||||||
|
"type": "long"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "JsonDataMessage",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"unidentifiedStatus": {
|
||||||
|
"type": "Map"
|
||||||
|
},
|
||||||
|
"isRecipientUpdate": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonBlockedListMessage": {
|
||||||
|
"fields": {
|
||||||
|
"addresses": {
|
||||||
|
"list": true,
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"groupIds": {
|
||||||
|
"list": true,
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonReadMessage": {
|
||||||
|
"fields": {
|
||||||
|
"sender": {
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"type": "long"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonViewOnceOpenMessage": {
|
||||||
|
"fields": {
|
||||||
|
"sender": {
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"type": "long"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonVerifiedMessage": {
|
||||||
|
"fields": {
|
||||||
|
"destination": {
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"identityKey": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"verified": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"type": "long"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonMessageRequestResponseMessage": {
|
||||||
|
"fields": {
|
||||||
|
"person": {
|
||||||
|
"type": "JsonAddress",
|
||||||
|
"version": "v1"
|
||||||
|
},
|
||||||
|
"groupId": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"v0": {
|
||||||
|
"JsonAccountList": {
|
||||||
|
"fields": {
|
||||||
|
"accounts": {
|
||||||
|
"list": true,
|
||||||
|
"type": "JsonAccount",
|
||||||
|
"version": "v0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonCallMessage": {
|
||||||
|
"fields": {
|
||||||
|
"offerMessage": {
|
||||||
|
"type": "OfferMessage",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"answerMessage": {
|
||||||
|
"type": "AnswerMessage",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"busyMessage": {
|
||||||
|
"type": "BusyMessage",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"hangupMessage": {
|
||||||
|
"type": "HangupMessage",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"iceUpdateMessages": {
|
||||||
|
"list": true,
|
||||||
|
"type": "IceUpdateMessage",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"destinationDeviceId": {
|
||||||
|
"type": "int"
|
||||||
|
},
|
||||||
|
"isMultiRing": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonReceiptMessage": {
|
||||||
|
"fields": {
|
||||||
|
"type": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"timestamps": {
|
||||||
|
"list": true,
|
||||||
|
"type": "Long"
|
||||||
|
},
|
||||||
|
"when": {
|
||||||
|
"type": "long"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonTypingMessage": {
|
||||||
|
"fields": {
|
||||||
|
"action": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"type": "long"
|
||||||
|
},
|
||||||
|
"groupId": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonAccount": {
|
||||||
|
"fields": {
|
||||||
|
"deviceId": {
|
||||||
|
"type": "int"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"filename": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"registered": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"has_keys": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"subscribed": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonAttachment": {
|
||||||
|
"fields": {
|
||||||
|
"contentType": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"size": {
|
||||||
|
"type": "int"
|
||||||
|
},
|
||||||
|
"storedFilename": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"filename": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"customFilename": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"caption": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"width": {
|
||||||
|
"type": "int"
|
||||||
|
},
|
||||||
|
"height": {
|
||||||
|
"type": "int"
|
||||||
|
},
|
||||||
|
"voiceNote": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"digest": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"blurhash": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SharedContact": {
|
||||||
|
"fields": {
|
||||||
|
"name": {
|
||||||
|
"type": "Name",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"avatar": {
|
||||||
|
"type": "Optional",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"phone": {
|
||||||
|
"type": "Optional",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"type": "Optional",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"address": {
|
||||||
|
"type": "Optional",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"organization": {
|
||||||
|
"type": "Optional",
|
||||||
|
"version": "v0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonPreview": {
|
||||||
|
"fields": {
|
||||||
|
"url": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"attachment": {
|
||||||
|
"type": "JsonAttachment",
|
||||||
|
"version": "v0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonSticker": {
|
||||||
|
"fields": {
|
||||||
|
"packID": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"packKey": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"stickerID": {
|
||||||
|
"type": "int"
|
||||||
|
},
|
||||||
|
"attachment": {
|
||||||
|
"type": "JsonAttachment",
|
||||||
|
"version": "v0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"RemoteDelete": {
|
||||||
|
"fields": {
|
||||||
|
"targetSentTimestamp": {
|
||||||
|
"type": "long"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConfigurationMessage": {
|
||||||
|
"fields": {
|
||||||
|
"readReceipts": {
|
||||||
|
"type": "Optional",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"unidentifiedDeliveryIndicators": {
|
||||||
|
"type": "Optional",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"typingIndicators": {
|
||||||
|
"type": "Optional",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"linkPreviews": {
|
||||||
|
"type": "Optional",
|
||||||
|
"version": "v0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonStickerPackOperationMessage": {
|
||||||
|
"fields": {
|
||||||
|
"packID": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"packKey": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"OfferMessage": {
|
||||||
|
"fields": {
|
||||||
|
"id": {
|
||||||
|
"type": "long"
|
||||||
|
},
|
||||||
|
"sdp": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "Type",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"opaque": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AnswerMessage": {
|
||||||
|
"fields": {
|
||||||
|
"id": {
|
||||||
|
"type": "long"
|
||||||
|
},
|
||||||
|
"sdp": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"opaque": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"BusyMessage": {
|
||||||
|
"fields": {
|
||||||
|
"id": {
|
||||||
|
"type": "long"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"HangupMessage": {
|
||||||
|
"fields": {
|
||||||
|
"id": {
|
||||||
|
"type": "long"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "Type",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"deviceId": {
|
||||||
|
"type": "int"
|
||||||
|
},
|
||||||
|
"legacy": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IceUpdateMessage": {
|
||||||
|
"fields": {
|
||||||
|
"id": {
|
||||||
|
"type": "long"
|
||||||
|
},
|
||||||
|
"opaque": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"sdp": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JsonQuotedAttachment": {
|
||||||
|
"fields": {
|
||||||
|
"contentType": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"fileName": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"thumbnail": {
|
||||||
|
"type": "JsonAttachment",
|
||||||
|
"version": "v0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Mention": {
|
||||||
|
"fields": {
|
||||||
|
"uuid": {
|
||||||
|
"type": "UUID"
|
||||||
|
},
|
||||||
|
"start": {
|
||||||
|
"type": "int"
|
||||||
|
},
|
||||||
|
"length": {
|
||||||
|
"type": "int"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Success": {
|
||||||
|
"fields": {
|
||||||
|
"unidentified": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"needsSync": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"duration": {
|
||||||
|
"type": "long"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"fields": {
|
||||||
|
"display": {
|
||||||
|
"type": "Optional",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"given": {
|
||||||
|
"type": "Optional",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"family": {
|
||||||
|
"type": "Optional",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"prefix": {
|
||||||
|
"type": "Optional",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"suffix": {
|
||||||
|
"type": "Optional",
|
||||||
|
"version": "v0"
|
||||||
|
},
|
||||||
|
"middle": {
|
||||||
|
"type": "Optional",
|
||||||
|
"version": "v0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Optional": {
|
||||||
|
"fields": {
|
||||||
|
"present": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"fields": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"v1alpha1": {
|
||||||
|
"ProtocolRequest": {
|
||||||
|
"fields": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"actions": {
|
||||||
|
"v1": {
|
||||||
|
"send": {
|
||||||
|
"request": "SendRequest",
|
||||||
|
"response": "SendResponse"
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"request": "ReactRequest",
|
||||||
|
"response": "SendResponse",
|
||||||
|
"doc": "react to a previous message"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"request": "VersionRequest",
|
||||||
|
"response": "JsonVersionMessage"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"v1alpha1": {
|
||||||
|
"protocol": {
|
||||||
|
"request": "ProtocolRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,19 +13,15 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package signald
|
package v0
|
||||||
|
|
||||||
import (
|
|
||||||
"git.callpipe.com/finn/signald-go/signald/client-protocol/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Request represents a message sent to signald
|
// Request represents a message sent to signald
|
||||||
type Request struct {
|
type LegacyRequest struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
Username string `json:"username,omitempty"`
|
Username string `json:"username,omitempty"`
|
||||||
MessageBody string `json:"messageBody,omitempty"`
|
MessageBody string `json:"messageBody,omitempty"`
|
||||||
RecipientAddress v1.JsonAddress `json:"recipientAddress,omitempty"`
|
RecipientAddress JsonAddress `json:"recipientAddress,omitempty"`
|
||||||
RecipientGroupID string `json:"recipientGroupId,omitempty"`
|
RecipientGroupID string `json:"recipientGroupId,omitempty"`
|
||||||
Voice bool `json:"voice,omitempty"`
|
Voice bool `json:"voice,omitempty"`
|
||||||
Code string `json:"code,omitempty"`
|
Code string `json:"code,omitempty"`
|
||||||
|
@ -38,11 +34,7 @@ type Request struct {
|
||||||
Avatar string `json:"avatar,omitempty"`
|
Avatar string `json:"avatar,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type JsonAttachment struct {
|
type JsonAddress struct {
|
||||||
Filename string `json:"filename"`
|
Number string
|
||||||
Caption string `json:"caption"`
|
UUID string
|
||||||
Width int `json:"width"`
|
|
||||||
Height int `json:"height"`
|
|
||||||
VoiceNote bool `json:"voiceNote"`
|
|
||||||
Preview bool `json:"preview"`
|
|
||||||
}
|
}
|
|
@ -1,30 +1,25 @@
|
||||||
package signald
|
package v0
|
||||||
|
|
||||||
import (
|
type LegacyResponse struct {
|
||||||
"git.callpipe.com/finn/signald-go/signald/client-protocol/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Response is a response to a request to signald, or a new inbound message
|
|
||||||
type Response struct {
|
|
||||||
ID string
|
ID string
|
||||||
Data ResponseData
|
Data LegacyResponseData
|
||||||
Type string
|
Type string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResponseData is where most of the data in the response is stored.
|
// ResponseData is where most of the data in the response is stored.
|
||||||
type ResponseData struct {
|
type LegacyResponseData struct {
|
||||||
Groups []Group
|
Groups []Group
|
||||||
Accounts []Account
|
Accounts []Account
|
||||||
URI string
|
URI string
|
||||||
DataMessage DataMessage
|
DataMessage DataMessage
|
||||||
Message string
|
Message string
|
||||||
Username string
|
Username string
|
||||||
Source v1.JsonAddress
|
Source JsonAddress
|
||||||
SourceDevice int
|
SourceDevice int
|
||||||
Type string
|
Type string
|
||||||
IsReceipt bool
|
IsReceipt bool
|
||||||
Timestamp float64
|
Timestamp int64
|
||||||
ServerTimestamp float64
|
ServerTimestamp int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group represents a group in signal
|
// Group represents a group in signal
|
||||||
|
@ -47,10 +42,10 @@ type Account struct {
|
||||||
|
|
||||||
// DataMessage is the main component of incoming text messages
|
// DataMessage is the main component of incoming text messages
|
||||||
type DataMessage struct {
|
type DataMessage struct {
|
||||||
Timestamp float64
|
Timestamp int64
|
||||||
Message string
|
Body string
|
||||||
ExpiresInSeconds float64
|
ExpiresInSeconds int64
|
||||||
GroupInfo IncomingGroupInfo
|
GroupInfo IncomingGroupInfo `json:"group"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncomingGroupInfo is information about a particular group
|
// IncomingGroupInfo is information about a particular group
|
164
signald/client-protocol/v0/structs.go
Normal file
164
signald/client-protocol/v0/structs.go
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
package v0
|
||||||
|
|
||||||
|
// DO NOT EDIT: this file is automatically generated by ./tools/generator in this repo
|
||||||
|
|
||||||
|
type Request struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AnswerMessage struct {
|
||||||
|
ID int64 `json:"id,omitempty"`
|
||||||
|
Opaque string `json:"opaque,omitempty"`
|
||||||
|
Sdp string `json:"sdp,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusyMessage struct {
|
||||||
|
ID int64 `json:"id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConfigurationMessage struct {
|
||||||
|
LinkPreviews *Optional `json:"linkPreviews,omitempty"`
|
||||||
|
ReadReceipts *Optional `json:"readReceipts,omitempty"`
|
||||||
|
TypingIndicators *Optional `json:"typingIndicators,omitempty"`
|
||||||
|
UnidentifiedDeliveryIndicators *Optional `json:"unidentifiedDeliveryIndicators,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type HangupMessage struct {
|
||||||
|
DeviceId int32 `json:"deviceId,omitempty"`
|
||||||
|
ID int64 `json:"id,omitempty"`
|
||||||
|
Legacy bool `json:"legacy,omitempty"`
|
||||||
|
Type *Type `json:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IceUpdateMessage struct {
|
||||||
|
ID int64 `json:"id,omitempty"`
|
||||||
|
Opaque string `json:"opaque,omitempty"`
|
||||||
|
Sdp string `json:"sdp,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonAccount struct {
|
||||||
|
DeviceId int32 `json:"deviceId,omitempty"`
|
||||||
|
Filename string `json:"filename,omitempty"`
|
||||||
|
Has_keys bool `json:"has_keys,omitempty"`
|
||||||
|
Registered bool `json:"registered,omitempty"`
|
||||||
|
Subscribed bool `json:"subscribed,omitempty"`
|
||||||
|
Username string `json:"username,omitempty"`
|
||||||
|
UUID string `json:"uuid,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonAccountList struct {
|
||||||
|
Accounts []*JsonAccount `json:"accounts,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonAttachment struct {
|
||||||
|
Blurhash string `json:"blurhash,omitempty"`
|
||||||
|
Caption string `json:"caption,omitempty"`
|
||||||
|
ContentType string `json:"contentType,omitempty"`
|
||||||
|
CustomFilename string `json:"customFilename,omitempty"`
|
||||||
|
Digest string `json:"digest,omitempty"`
|
||||||
|
Filename string `json:"filename,omitempty"`
|
||||||
|
Height int32 `json:"height,omitempty"`
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
Key string `json:"key,omitempty"`
|
||||||
|
Size int32 `json:"size,omitempty"`
|
||||||
|
StoredFilename string `json:"storedFilename,omitempty"`
|
||||||
|
VoiceNote bool `json:"voiceNote,omitempty"`
|
||||||
|
Width int32 `json:"width,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonCallMessage struct {
|
||||||
|
AnswerMessage *AnswerMessage `json:"answerMessage,omitempty"`
|
||||||
|
BusyMessage *BusyMessage `json:"busyMessage,omitempty"`
|
||||||
|
DestinationDeviceId int32 `json:"destinationDeviceId,omitempty"`
|
||||||
|
HangupMessage *HangupMessage `json:"hangupMessage,omitempty"`
|
||||||
|
IceUpdateMessages []*IceUpdateMessage `json:"iceUpdateMessages,omitempty"`
|
||||||
|
IsMultiRing bool `json:"isMultiRing,omitempty"`
|
||||||
|
OfferMessage *OfferMessage `json:"offerMessage,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonPreview struct {
|
||||||
|
Attachment *JsonAttachment `json:"attachment,omitempty"`
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
|
Url string `json:"url,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonQuotedAttachment struct {
|
||||||
|
ContentType string `json:"contentType,omitempty"`
|
||||||
|
FileName string `json:"fileName,omitempty"`
|
||||||
|
Thumbnail *JsonAttachment `json:"thumbnail,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonReceiptMessage struct {
|
||||||
|
Timestamps []int64 `json:"timestamps,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
When int64 `json:"when,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonSticker struct {
|
||||||
|
Attachment *JsonAttachment `json:"attachment,omitempty"`
|
||||||
|
PackID string `json:"packID,omitempty"`
|
||||||
|
PackKey string `json:"packKey,omitempty"`
|
||||||
|
StickerID int32 `json:"stickerID,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonStickerPackOperationMessage struct {
|
||||||
|
PackID string `json:"packID,omitempty"`
|
||||||
|
PackKey string `json:"packKey,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonTypingMessage struct {
|
||||||
|
Action string `json:"action,omitempty"`
|
||||||
|
GroupId string `json:"groupId,omitempty"`
|
||||||
|
Timestamp int64 `json:"timestamp,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Mention struct {
|
||||||
|
Length int32 `json:"length,omitempty"`
|
||||||
|
Start int32 `json:"start,omitempty"`
|
||||||
|
UUID string `json:"uuid,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Name struct {
|
||||||
|
Display *Optional `json:"display,omitempty"`
|
||||||
|
Family *Optional `json:"family,omitempty"`
|
||||||
|
Given *Optional `json:"given,omitempty"`
|
||||||
|
Middle *Optional `json:"middle,omitempty"`
|
||||||
|
Prefix *Optional `json:"prefix,omitempty"`
|
||||||
|
Suffix *Optional `json:"suffix,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OfferMessage struct {
|
||||||
|
ID int64 `json:"id,omitempty"`
|
||||||
|
Opaque string `json:"opaque,omitempty"`
|
||||||
|
Sdp string `json:"sdp,omitempty"`
|
||||||
|
Type *Type `json:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Optional struct {
|
||||||
|
Present bool `json:"present,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RemoteDelete struct {
|
||||||
|
TargetSentTimestamp int64 `json:"targetSentTimestamp,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SharedContact struct {
|
||||||
|
Address *Optional `json:"address,omitempty"`
|
||||||
|
Avatar *Optional `json:"avatar,omitempty"`
|
||||||
|
Email *Optional `json:"email,omitempty"`
|
||||||
|
Name *Name `json:"name,omitempty"`
|
||||||
|
Organization *Optional `json:"organization,omitempty"`
|
||||||
|
Phone *Optional `json:"phone,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Success struct {
|
||||||
|
Duration int64 `json:"duration,omitempty"`
|
||||||
|
NeedsSync bool `json:"needsSync,omitempty"`
|
||||||
|
Unidentified bool `json:"unidentified,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Type struct {
|
||||||
|
}
|
121
signald/client-protocol/v1/requests.go
Normal file
121
signald/client-protocol/v1/requests.go
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
package v1
|
||||||
|
|
||||||
|
// DO NOT EDIT: this file is automatically generated by ./tools/generator in this repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
|
"gitlab.com/signald/signald-go/signald"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Submit: react to a previous message
|
||||||
|
func (r *ReactRequest) Submit(conn *signald.Signald) (response SendResponse, err error) {
|
||||||
|
r.Version = "v1"
|
||||||
|
r.Type = "react"
|
||||||
|
if r.ID == "" {
|
||||||
|
r.ID = generateID()
|
||||||
|
}
|
||||||
|
|
||||||
|
err = conn.RawRequest(r)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("signald-go: error submitting request to signald")
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
responseChannel := conn.GetResponseListener(r.ID)
|
||||||
|
defer conn.CloseResponseListener(r.ID)
|
||||||
|
|
||||||
|
rawResponse := <-responseChannel
|
||||||
|
if rawResponse.Error != nil {
|
||||||
|
err = fmt.Errorf("signald error: %s", string(rawResponse.Error))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(rawResponse.Data, &response)
|
||||||
|
if err != nil {
|
||||||
|
rawResponseJson, _ := rawResponse.Data.MarshalJSON()
|
||||||
|
log.Println("signald-go: error unmarshalling response from signald of type", rawResponse.Type, string(rawResponseJson))
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SendRequest) Submit(conn *signald.Signald) (response SendResponse, err error) {
|
||||||
|
r.Version = "v1"
|
||||||
|
r.Type = "send"
|
||||||
|
if r.ID == "" {
|
||||||
|
r.ID = generateID()
|
||||||
|
}
|
||||||
|
|
||||||
|
err = conn.RawRequest(r)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("signald-go: error submitting request to signald")
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
responseChannel := conn.GetResponseListener(r.ID)
|
||||||
|
defer conn.CloseResponseListener(r.ID)
|
||||||
|
|
||||||
|
rawResponse := <-responseChannel
|
||||||
|
if rawResponse.Error != nil {
|
||||||
|
err = fmt.Errorf("signald error: %s", string(rawResponse.Error))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(rawResponse.Data, &response)
|
||||||
|
if err != nil {
|
||||||
|
rawResponseJson, _ := rawResponse.Data.MarshalJSON()
|
||||||
|
log.Println("signald-go: error unmarshalling response from signald of type", rawResponse.Type, string(rawResponseJson))
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *VersionRequest) Submit(conn *signald.Signald) (response JsonVersionMessage, err error) {
|
||||||
|
r.Version = "v1"
|
||||||
|
r.Type = "version"
|
||||||
|
if r.ID == "" {
|
||||||
|
r.ID = generateID()
|
||||||
|
}
|
||||||
|
|
||||||
|
err = conn.RawRequest(r)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("signald-go: error submitting request to signald")
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
responseChannel := conn.GetResponseListener(r.ID)
|
||||||
|
defer conn.CloseResponseListener(r.ID)
|
||||||
|
|
||||||
|
rawResponse := <-responseChannel
|
||||||
|
if rawResponse.Error != nil {
|
||||||
|
err = fmt.Errorf("signald error: %s", string(rawResponse.Error))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(rawResponse.Data, &response)
|
||||||
|
if err != nil {
|
||||||
|
rawResponseJson, _ := rawResponse.Data.MarshalJSON()
|
||||||
|
log.Println("signald-go: error unmarshalling response from signald of type", rawResponse.Type, string(rawResponseJson))
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const idsize = 10
|
||||||
|
|
||||||
|
var charset = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
|
||||||
|
|
||||||
|
func generateID() string {
|
||||||
|
id := make([]rune, idsize)
|
||||||
|
for i := range id {
|
||||||
|
id[i] = charset[rand.Intn(len(charset))]
|
||||||
|
}
|
||||||
|
return string(id)
|
||||||
|
}
|
199
signald/client-protocol/v1/structs.go
Normal file
199
signald/client-protocol/v1/structs.go
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
package v1
|
||||||
|
|
||||||
|
// DO NOT EDIT: this file is automatically generated by ./tools/generator in this repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gitlab.com/signald/signald-go/signald/client-protocol/v0"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Request struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonAddress struct {
|
||||||
|
Number string `json:"number,omitempty"` // An e164 phone number, starting with +. Currently the only available user-facing Signal identifier.
|
||||||
|
Relay string `json:"relay,omitempty"`
|
||||||
|
UUID string `json:"uuid,omitempty"` // A UUID, the unique identifier for a particular Signal account.
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonBlockedListMessage struct {
|
||||||
|
Addresses []*JsonAddress `json:"addresses,omitempty"`
|
||||||
|
GroupIds []string `json:"groupIds,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonDataMessage struct {
|
||||||
|
Attachments []*v0.JsonAttachment `json:"attachments,omitempty"` // files attached to the incoming message
|
||||||
|
Body string `json:"body,omitempty"` // the text body of the incoming message.
|
||||||
|
Contacts []*v0.SharedContact `json:"contacts,omitempty"` // if the incoming message has a shared contact, the contact's information will be here
|
||||||
|
EndSession bool `json:"endSession,omitempty"`
|
||||||
|
ExpiresInSeconds int32 `json:"expiresInSeconds,omitempty"` // the expiry timer on the incoming message. Clients should delete records of the message within this number of seconds
|
||||||
|
Group *JsonGroupInfo `json:"group,omitempty"` // if the incoming message was sent to a v1 group, information about that group will be here
|
||||||
|
GroupV2 *JsonGroupV2Info `json:"groupV2,omitempty"` // is the incoming message was sent to a v2 group, basic identifying information about that group will be here. For full information, use list_groups
|
||||||
|
Previews []*v0.JsonPreview `json:"previews,omitempty"` // if the incoming message has a link preview, information about that preview will be here
|
||||||
|
ProfileKeyUpdate bool `json:"profileKeyUpdate,omitempty"`
|
||||||
|
Quote *JsonQuote `json:"quote,omitempty"` // if the incoming message is a quote or reply to another message, this will contain information about that message
|
||||||
|
Reaction *JsonReaction `json:"reaction,omitempty"` // if the message adds or removes a reaction to another message, this will indicate what change is being made
|
||||||
|
RemoteDelete *v0.RemoteDelete `json:"remoteDelete,omitempty"` // if the inbound message is deleting a previously sent message, indicates which message should be deleted
|
||||||
|
Sticker *v0.JsonSticker `json:"sticker,omitempty"` // if the incoming message is a sticker, information about the sicker will be here
|
||||||
|
Timestamp int64 `json:"timestamp,omitempty"` // the (unix) timestamp that the message was sent at, according to the sender's device. This is used to uniquely identify this message for things like reactions and quotes.
|
||||||
|
ViewOnce bool `json:"viewOnce,omitempty"` // indicates the message is a view once message. View once messages typically include no body and a single image attachment. Official Signal clients will prevent the user from saving the image, and once the user has viewed the image once they will destroy the image.
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonGroupInfo struct {
|
||||||
|
AvatarId int64 `json:"avatarId,omitempty"`
|
||||||
|
GroupId string `json:"groupId,omitempty"`
|
||||||
|
Members []*JsonAddress `json:"members,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonGroupV2Info struct {
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
InviteLinkPassword string `json:"inviteLinkPassword,omitempty"`
|
||||||
|
MasterKey string `json:"masterKey,omitempty"`
|
||||||
|
Members []*JsonAddress `json:"members,omitempty"`
|
||||||
|
PendingMembers []*JsonAddress `json:"pendingMembers,omitempty"`
|
||||||
|
RequestingMembers []*JsonAddress `json:"requestingMembers,omitempty"`
|
||||||
|
Revision int32 `json:"revision,omitempty"`
|
||||||
|
Timer int32 `json:"timer,omitempty"`
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonMention struct {
|
||||||
|
Length int32 `json:"length,omitempty"`
|
||||||
|
Start int32 `json:"start,omitempty"`
|
||||||
|
UUID string `json:"uuid,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonMessageEnvelope struct {
|
||||||
|
CallMessage *v0.JsonCallMessage `json:"callMessage,omitempty"`
|
||||||
|
DataMessage *JsonDataMessage `json:"dataMessage,omitempty"`
|
||||||
|
HasContent bool `json:"hasContent,omitempty"`
|
||||||
|
HasLegacyMessage bool `json:"hasLegacyMessage,omitempty"`
|
||||||
|
IsUnidentifiedSender bool `json:"isUnidentifiedSender,omitempty"`
|
||||||
|
Receipt *v0.JsonReceiptMessage `json:"receipt,omitempty"`
|
||||||
|
Relay string `json:"relay,omitempty"`
|
||||||
|
ServerDeliveredTimestamp int64 `json:"serverDeliveredTimestamp,omitempty"`
|
||||||
|
ServerTimestamp int64 `json:"serverTimestamp,omitempty"`
|
||||||
|
Source *JsonAddress `json:"source,omitempty"`
|
||||||
|
SourceDevice int32 `json:"sourceDevice,omitempty"`
|
||||||
|
SyncMessage *JsonSyncMessage `json:"syncMessage,omitempty"`
|
||||||
|
Timestamp int64 `json:"timestamp,omitempty"`
|
||||||
|
TimestampISO string `json:"timestampISO,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
Typing *v0.JsonTypingMessage `json:"typing,omitempty"`
|
||||||
|
Username string `json:"username,omitempty"`
|
||||||
|
UUID string `json:"uuid,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonMessageRequestResponseMessage struct {
|
||||||
|
GroupId string `json:"groupId,omitempty"`
|
||||||
|
Person *JsonAddress `json:"person,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// JsonQuote: A quote is a reply to a previous message. ID is the sent time of the message being replied to
|
||||||
|
type JsonQuote struct {
|
||||||
|
Attachments []*v0.JsonQuotedAttachment `json:"attachments,omitempty"`
|
||||||
|
Author *JsonAddress `json:"author,omitempty"`
|
||||||
|
ID int64 `json:"id,omitempty"`
|
||||||
|
Mentions []*v0.Mention `json:"mentions,omitempty"`
|
||||||
|
Text string `json:"text,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonReaction struct {
|
||||||
|
Emoji string `json:"emoji,omitempty"` // the emoji to react with
|
||||||
|
Remove bool `json:"remove,omitempty"` // set to true to remove the reaction. requires emoji be set to previously reacted emoji
|
||||||
|
TargetAuthor *JsonAddress `json:"targetAuthor,omitempty"` // the author of the message being reacted to
|
||||||
|
TargetSentTimestamp int64 `json:"targetSentTimestamp,omitempty"` // the client timestamp of the message being reacted to
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonReadMessage struct {
|
||||||
|
Sender *JsonAddress `json:"sender,omitempty"`
|
||||||
|
Timestamp int64 `json:"timestamp,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonSendMessageResult struct {
|
||||||
|
Address *JsonAddress `json:"address,omitempty"`
|
||||||
|
IdentityFailure string `json:"identityFailure,omitempty"`
|
||||||
|
NetworkFailure bool `json:"networkFailure,omitempty"`
|
||||||
|
Success *v0.Success `json:"success,omitempty"`
|
||||||
|
UnregisteredFailure bool `json:"unregisteredFailure,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonSentTranscriptMessage struct {
|
||||||
|
Destination *JsonAddress `json:"destination,omitempty"`
|
||||||
|
ExpirationStartTimestamp int64 `json:"expirationStartTimestamp,omitempty"`
|
||||||
|
IsRecipientUpdate bool `json:"isRecipientUpdate,omitempty"`
|
||||||
|
Message *JsonDataMessage `json:"message,omitempty"`
|
||||||
|
Timestamp int64 `json:"timestamp,omitempty"`
|
||||||
|
UnidentifiedStatus map[string]string `json:"unidentifiedStatus,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonSyncMessage struct {
|
||||||
|
BlockedList *JsonBlockedListMessage `json:"blockedList,omitempty"`
|
||||||
|
Configuration *v0.ConfigurationMessage `json:"configuration,omitempty"`
|
||||||
|
Contacts *v0.JsonAttachment `json:"contacts,omitempty"`
|
||||||
|
ContactsComplete bool `json:"contactsComplete,omitempty"`
|
||||||
|
FetchType string `json:"fetchType,omitempty"`
|
||||||
|
Groups *v0.JsonAttachment `json:"groups,omitempty"`
|
||||||
|
MessageRequestResponse *JsonMessageRequestResponseMessage `json:"messageRequestResponse,omitempty"`
|
||||||
|
ReadMessages []*JsonReadMessage `json:"readMessages,omitempty"`
|
||||||
|
Request string `json:"request,omitempty"`
|
||||||
|
Sent *JsonSentTranscriptMessage `json:"sent,omitempty"`
|
||||||
|
StickerPackOperations []*v0.JsonStickerPackOperationMessage `json:"stickerPackOperations,omitempty"`
|
||||||
|
Verified *JsonVerifiedMessage `json:"verified,omitempty"`
|
||||||
|
ViewOnceOpen *JsonViewOnceOpenMessage `json:"viewOnceOpen,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonVerifiedMessage struct {
|
||||||
|
Destination *JsonAddress `json:"destination,omitempty"`
|
||||||
|
IdentityKey string `json:"identityKey,omitempty"`
|
||||||
|
Timestamp int64 `json:"timestamp,omitempty"`
|
||||||
|
Verified string `json:"verified,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonVersionMessage struct {
|
||||||
|
Branch string `json:"branch,omitempty"`
|
||||||
|
Commit string `json:"commit,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Version string `json:"version,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonViewOnceOpenMessage struct {
|
||||||
|
Sender *JsonAddress `json:"sender,omitempty"`
|
||||||
|
Timestamp int64 `json:"timestamp,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReactRequest: react to a previous message
|
||||||
|
type ReactRequest struct {
|
||||||
|
Request
|
||||||
|
Reaction *JsonReaction `json:"reaction,omitempty"`
|
||||||
|
RecipientAddress *JsonAddress `json:"recipientAddress,omitempty"`
|
||||||
|
RecipientGroupID string `json:"recipientGroupId,omitempty"`
|
||||||
|
Timestamp int64 `json:"timestamp,omitempty"`
|
||||||
|
Username string `json:"username,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SendRequest struct {
|
||||||
|
Request
|
||||||
|
Attachments []*v0.JsonAttachment `json:"attachments,omitempty"`
|
||||||
|
Mentions []*JsonMention `json:"mentions,omitempty"`
|
||||||
|
MessageBody string `json:"messageBody,omitempty"`
|
||||||
|
Quote *JsonQuote `json:"quote,omitempty"`
|
||||||
|
RecipientAddress *JsonAddress `json:"recipientAddress,omitempty"`
|
||||||
|
RecipientGroupID string `json:"recipientGroupId,omitempty"`
|
||||||
|
Timestamp int64 `json:"timestamp,omitempty"`
|
||||||
|
Username string `json:"username,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SendResponse struct {
|
||||||
|
Results []*JsonSendMessageResult `json:"results,omitempty"`
|
||||||
|
Timestamp int64 `json:"timestamp,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type VersionRequest struct {
|
||||||
|
Request
|
||||||
|
}
|
|
@ -1,44 +0,0 @@
|
||||||
package v1
|
|
||||||
|
|
||||||
// JsonAddress is a signal user's contact information. a phone number, UUID or both
|
|
||||||
type JsonAddress struct {
|
|
||||||
UUID string `json:"uuid,omitempty"`
|
|
||||||
Number string `json:"number"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type JsonMessageRequestResponseMessage struct {
|
|
||||||
Person JsonAddress `json:"person"`
|
|
||||||
GroupID string `json:"groupId"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type JsonReaction struct {
|
|
||||||
Emoji string `json:"emoji"`
|
|
||||||
Remove bool `json:"remove"`
|
|
||||||
TargetAuthor JsonAddress `json:"targetAuthor"`
|
|
||||||
TargetSentTimestamp uint64 `json:"targetSentTimestamp"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type JsonReadMessage struct {
|
|
||||||
Sender JsonAddress `json:"sender"`
|
|
||||||
Timestamp uint64 `json:"timestamp"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type JsonSendMessageResult struct {
|
|
||||||
Address JsonAddress `json:"address"`
|
|
||||||
Success Success `json:"success"`
|
|
||||||
NetworkFailure bool `json:"networkFailure"`
|
|
||||||
UnregisteredFailure bool `json:"unregisteredFailure"`
|
|
||||||
IdentityFailure string `json:"identityFailure"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Success struct {
|
|
||||||
Unidentified bool `json:"unidentified"`
|
|
||||||
NeedsSync bool `json:"needsSync"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RequestValidationFailure struct {
|
|
||||||
ValidationResults []string `json:"validationResults"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
}
|
|
32
signald/client-protocol/v1alpha1/requests.go
Normal file
32
signald/client-protocol/v1alpha1/requests.go
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
// DO NOT EDIT: this file is automatically generated by ./tools/generator in this repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
|
"gitlab.com/signald/signald-go/signald"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *ProtocolRequest) Submit(conn *signald.Signald) error {
|
||||||
|
r.Version = "v1alpha1"
|
||||||
|
r.Type = "protocol"
|
||||||
|
if r.ID == "" {
|
||||||
|
r.ID = generateID()
|
||||||
|
}
|
||||||
|
|
||||||
|
return conn.RawRequest(r)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const idsize = 10
|
||||||
|
|
||||||
|
var charset = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
|
||||||
|
|
||||||
|
func generateID() string {
|
||||||
|
id := make([]rune, idsize)
|
||||||
|
for i := range id {
|
||||||
|
id[i] = charset[rand.Intn(len(charset))]
|
||||||
|
}
|
||||||
|
return string(id)
|
||||||
|
}
|
13
signald/client-protocol/v1alpha1/structs.go
Normal file
13
signald/client-protocol/v1alpha1/structs.go
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
// DO NOT EDIT: this file is automatically generated by ./tools/generator in this repo
|
||||||
|
|
||||||
|
type Request struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProtocolRequest struct {
|
||||||
|
Request
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright © 2018 Finn Herzfeld <finn@janky.solutions>
|
// Copyright © 2020 Finn Herzfeld <finn@janky.solutions>
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -16,17 +16,39 @@
|
||||||
package signald
|
package signald
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"gitlab.com/signald/signald-go/signald/client-protocol/v0"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
debugSignaldIO, _ = strconv.ParseBool(os.Getenv("DEBUG_SIGNALD_IO"))
|
||||||
)
|
)
|
||||||
|
|
||||||
// Signald is a connection to a signald instance.
|
// Signald is a connection to a signald instance.
|
||||||
type Signald struct {
|
type Signald struct {
|
||||||
socket net.Conn
|
socket net.Conn
|
||||||
|
listeners map[string]chan BasicResponse
|
||||||
SocketPath string
|
SocketPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BasicResponse struct {
|
||||||
|
ID string
|
||||||
|
Type string
|
||||||
|
Error json.RawMessage
|
||||||
|
Data json.RawMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
type UnexpectedError struct {
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
// Connect connects to the signad socket
|
// Connect connects to the signad socket
|
||||||
func (s *Signald) Connect() error {
|
func (s *Signald) Connect() error {
|
||||||
if s.SocketPath == "" {
|
if s.SocketPath == "" {
|
||||||
|
@ -37,32 +59,86 @@ func (s *Signald) Connect() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.socket = socket
|
s.socket = socket
|
||||||
log.Print("Connected to signald socket ", socket.RemoteAddr().String())
|
log.Println("signald-go: Connected to signald socket ", socket.RemoteAddr().String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listen listens for events from signald
|
// Listen listens for events from signald
|
||||||
func (s *Signald) Listen(c chan Response) {
|
func (s *Signald) Listen(c chan v0.LegacyResponse) {
|
||||||
// we create a decoder that reads directly from the socket
|
|
||||||
d := json.NewDecoder(s.socket)
|
|
||||||
|
|
||||||
var msg Response
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if err := d.Decode(&msg); err != nil {
|
msg, err := s.readNext()
|
||||||
log.Println("error decoding message from signald:", err)
|
if err == io.EOF {
|
||||||
|
log.Println("signald-go: socket disconnected!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg.Type == "unexpected_error" {
|
||||||
|
var errorResponse UnexpectedError
|
||||||
|
if err := json.Unmarshal(msg.Data, &errorResponse); err != nil {
|
||||||
|
log.Println("signald-go: Error unmarshaling error response:", err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Println("signald-go: Unexpected error", errorResponse.Message)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if subscribers, ok := s.listeners[msg.ID]; ok {
|
||||||
|
subscribers <- msg
|
||||||
|
}
|
||||||
|
|
||||||
|
if c != nil {
|
||||||
|
legacyResponse := v0.LegacyResponse{
|
||||||
|
ID: msg.ID,
|
||||||
|
Type: msg.Type,
|
||||||
|
}
|
||||||
|
_ = json.Unmarshal(msg.Data, &legacyResponse.Data)
|
||||||
|
c <- legacyResponse
|
||||||
}
|
}
|
||||||
c <- msg
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendRequest sends a request to signald. Mostly used interally.
|
func (s *Signald) RawRequest(request interface{}) error {
|
||||||
func (s *Signald) SendRequest(request Request) error {
|
if debugSignaldIO {
|
||||||
b, err := json.Marshal(request)
|
buffer := bytes.Buffer{}
|
||||||
if err != nil {
|
if err := json.NewEncoder(&buffer).Encode(request); err == nil {
|
||||||
return err
|
log.Println("[to signald]", buffer.String())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log.Print("Sending ", string(b))
|
return json.NewEncoder(s.socket).Encode(request)
|
||||||
e := json.NewEncoder(s.socket)
|
}
|
||||||
return e.Encode(request)
|
|
||||||
|
func (s *Signald) GetResponseListener(requestid string) chan BasicResponse {
|
||||||
|
if s.listeners == nil {
|
||||||
|
s.listeners = map[string]chan BasicResponse{}
|
||||||
|
}
|
||||||
|
c, ok := s.listeners[requestid]
|
||||||
|
if !ok {
|
||||||
|
c = make(chan BasicResponse)
|
||||||
|
s.listeners[requestid] = c
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Signald) CloseResponseListener(requestid string) {
|
||||||
|
listener, ok := s.listeners[requestid]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
close(listener)
|
||||||
|
delete(s.listeners, requestid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Signald) readNext() (b BasicResponse, err error) {
|
||||||
|
if debugSignaldIO {
|
||||||
|
buffer := bytes.Buffer{}
|
||||||
|
err = json.NewDecoder(io.TeeReader(s.socket, &buffer)).Decode(&b)
|
||||||
|
log.Println("[from signald]", buffer.String())
|
||||||
|
} else {
|
||||||
|
err = json.NewDecoder(s.socket).Decode(&b)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Println("signald-go: error decoding message from signald:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
179
tools/generator/main.go
Normal file
179
tools/generator/main.go
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Protocol struct {
|
||||||
|
Types map[string]map[string]*Type
|
||||||
|
Actions map[string]map[string]*Action
|
||||||
|
}
|
||||||
|
|
||||||
|
type Type struct {
|
||||||
|
Fields map[string]*DataType
|
||||||
|
Request bool `json:"-"`
|
||||||
|
Doc string
|
||||||
|
}
|
||||||
|
|
||||||
|
type DataType struct {
|
||||||
|
List bool
|
||||||
|
Type string
|
||||||
|
Version string
|
||||||
|
FieldName string
|
||||||
|
Doc string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Action struct {
|
||||||
|
FnName string
|
||||||
|
Request string
|
||||||
|
Response string
|
||||||
|
Doc string
|
||||||
|
}
|
||||||
|
|
||||||
|
type StructsTemplateInput struct {
|
||||||
|
Types map[string]*Type
|
||||||
|
Version string
|
||||||
|
ImportVersions []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ActionsTemplateInput struct {
|
||||||
|
Actions map[string]*Action
|
||||||
|
Version string
|
||||||
|
Responses bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var typeMap = map[string]string{
|
||||||
|
"int": "int32",
|
||||||
|
"Integer": "int32",
|
||||||
|
"Boolean": "bool",
|
||||||
|
"long": "int64",
|
||||||
|
"Long": "int64",
|
||||||
|
"UUID": "string",
|
||||||
|
"boolean": "bool",
|
||||||
|
"String": "string",
|
||||||
|
"Map": "map[string]string", // TODO: make signald print the actual key and value types
|
||||||
|
}
|
||||||
|
|
||||||
|
var fieldNameMap = map[string]string{
|
||||||
|
"id": "ID",
|
||||||
|
"recipientGroupId": "RecipientGroupID",
|
||||||
|
"uuid": "UUID",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DataType) fixForVersion(field, version string) {
|
||||||
|
response, ok := typeMap[d.Type]
|
||||||
|
if ok {
|
||||||
|
if d.Type == "byte" && d.List {
|
||||||
|
d.List = false
|
||||||
|
}
|
||||||
|
d.Type = response
|
||||||
|
} else {
|
||||||
|
if d.Version == version || d.Version == "" {
|
||||||
|
d.Type = fmt.Sprintf("*%s", d.Type)
|
||||||
|
} else {
|
||||||
|
d.Type = fmt.Sprintf("*%s.%s", d.Version, d.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldName, ok := fieldNameMap[field]
|
||||||
|
if ok {
|
||||||
|
d.FieldName = fieldName
|
||||||
|
} else {
|
||||||
|
d.FieldName = strings.Title(field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var response Protocol
|
||||||
|
err := json.NewDecoder(os.Stdin).Decode(&response)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err, "\nError parsing stdin")
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl, err := template.ParseGlob("tools/generator/*.tmpl")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err, "\nError parsing templates from tools/generator/*.tmpl")
|
||||||
|
}
|
||||||
|
|
||||||
|
for version, actions := range response.Actions {
|
||||||
|
inputs := ActionsTemplateInput{Version: version, Responses: false}
|
||||||
|
for action, a := range actions {
|
||||||
|
actions[action].FnName = strings.Title(action)
|
||||||
|
if a.Request != "" {
|
||||||
|
response.Types[version][a.Request].Request = true
|
||||||
|
}
|
||||||
|
if a.Response != "" {
|
||||||
|
inputs.Responses = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputs.Actions = actions
|
||||||
|
outputDir := fmt.Sprintf("signald/client-protocol/%s", version)
|
||||||
|
err = os.MkdirAll(outputDir, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Error creating", outputDir, err)
|
||||||
|
}
|
||||||
|
outputFilename := fmt.Sprintf("%s/%s", outputDir, "requests.go")
|
||||||
|
log.Println("Opening", outputFilename)
|
||||||
|
f, err := os.Create(outputFilename)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err, "\nfailed to open output file ", outputFilename)
|
||||||
|
}
|
||||||
|
err = tmpl.ExecuteTemplate(f, "requests.go.tmpl", inputs)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err, "\nfailed to render template")
|
||||||
|
}
|
||||||
|
err = exec.Command("gofmt", "-w", outputFilename).Run()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err, " error running gofmt on ", outputFilename)
|
||||||
|
}
|
||||||
|
fmt.Println(outputFilename)
|
||||||
|
}
|
||||||
|
|
||||||
|
for version, types := range response.Types {
|
||||||
|
inputs := StructsTemplateInput{Version: version}
|
||||||
|
for typeName, t := range types {
|
||||||
|
for fieldName, field := range t.Fields {
|
||||||
|
types[typeName].Fields[fieldName].fixForVersion(fieldName, version)
|
||||||
|
if field.Version != "" && field.Version != version {
|
||||||
|
found := false
|
||||||
|
for _, v := range inputs.ImportVersions {
|
||||||
|
if v == field.Version {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
inputs.ImportVersions = append(inputs.ImportVersions, field.Version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputs.Types = types
|
||||||
|
outputDir := fmt.Sprintf("signald/client-protocol/%s", version)
|
||||||
|
err = os.MkdirAll(outputDir, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Error creating", outputDir, err)
|
||||||
|
}
|
||||||
|
outputFilename := fmt.Sprintf("%s/%s", outputDir, "structs.go")
|
||||||
|
log.Println("Opening", outputFilename)
|
||||||
|
f, err := os.Create(outputFilename)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err, "\nfailed to open output file ", outputFilename)
|
||||||
|
}
|
||||||
|
err = tmpl.ExecuteTemplate(f, "structs.go.tmpl", inputs)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err, "\nfailed to render template")
|
||||||
|
}
|
||||||
|
err = exec.Command("gofmt", "-w", outputFilename).Run()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err, " error running gofmt on ", outputFilename)
|
||||||
|
}
|
||||||
|
fmt.Println(outputFilename)
|
||||||
|
}
|
||||||
|
}
|
67
tools/generator/requests.go.tmpl
Normal file
67
tools/generator/requests.go.tmpl
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
package {{.Version}}
|
||||||
|
|
||||||
|
// DO NOT EDIT: this file is automatically generated by ./tools/generator in this repo
|
||||||
|
|
||||||
|
import ({{if .Responses}}
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"{{end}}
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
|
"gitlab.com/signald/signald-go/signald"
|
||||||
|
)
|
||||||
|
|
||||||
|
{{range $type, $action := .Actions}}
|
||||||
|
{{if ne $action.Request ""}}
|
||||||
|
{{if ne $action.Doc ""}}// Submit: {{$action.Doc}}{{end}}
|
||||||
|
func (r *{{$action.Request}}) Submit(conn *signald.Signald) ({{if ne $action.Response ""}}response {{$action.Response}}, err {{end}}error) {
|
||||||
|
r.Version = "{{$.Version}}"
|
||||||
|
{{else}}
|
||||||
|
{{if ne $action.Doc ""}}// {{$action.FnName}}: {{$action.Doc}}{{end}}
|
||||||
|
func {{$action.FnName}}(conn *signald.Signald) ({{if ne $action.Response ""}}response {{$action.Response}}, {{end}}err error) {
|
||||||
|
r := Request{Version: "{{.Version}}"}
|
||||||
|
{{end}} r.Type = "{{$type}}"
|
||||||
|
if(r.ID == "") {
|
||||||
|
r.ID = generateID()
|
||||||
|
}
|
||||||
|
|
||||||
|
{{if ne $action.Response ""}}
|
||||||
|
err = conn.RawRequest(r)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("signald-go: error submitting request to signald")
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
responseChannel := conn.GetResponseListener(r.ID)
|
||||||
|
defer conn.CloseResponseListener(r.ID)
|
||||||
|
|
||||||
|
rawResponse := <- responseChannel
|
||||||
|
if rawResponse.Error != nil {
|
||||||
|
err = fmt.Errorf("signald error: %s", string(rawResponse.Error))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(rawResponse.Data, &response)
|
||||||
|
if err != nil {
|
||||||
|
rawResponseJson, _ := rawResponse.Data.MarshalJSON()
|
||||||
|
log.Println("signald-go: error unmarshalling response from signald of type", rawResponse.Type, string(rawResponseJson))
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
{{else}}
|
||||||
|
return conn.RawRequest(r)
|
||||||
|
{{end}}
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
|
||||||
|
const idsize = 10
|
||||||
|
var charset = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
|
||||||
|
|
||||||
|
func generateID() string {
|
||||||
|
id := make([]rune, idsize)
|
||||||
|
for i := range id {
|
||||||
|
id[i]= charset[rand.Intn(len(charset))]
|
||||||
|
}
|
||||||
|
return string(id)
|
||||||
|
}
|
21
tools/generator/structs.go.tmpl
Normal file
21
tools/generator/structs.go.tmpl
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package {{.Version}}
|
||||||
|
|
||||||
|
// DO NOT EDIT: this file is automatically generated by ./tools/generator in this repo
|
||||||
|
{{if gt (.ImportVersions | len) 0}}
|
||||||
|
import (
|
||||||
|
{{range $version := .ImportVersions}}
|
||||||
|
"gitlab.com/signald/signald-go/signald/client-protocol/{{$version}}"{{end}}
|
||||||
|
)
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
type Request struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
{{ range $structName, $type := .Types }}{{if ne $type.Doc ""}}// {{$structName}}: {{$type.Doc}}{{end}}
|
||||||
|
type {{ $structName }} struct {
|
||||||
|
{{if $type.Request}} Request{{end}}
|
||||||
|
{{ range $fieldName, $field := $type.Fields }}{{ $field.FieldName }} {{if $field.List}}[]{{end}}{{ $field.Type }} `json:"{{$fieldName}},omitempty"`{{if ne $field.Doc ""}} // {{$field.Doc}}{{end}}
|
||||||
|
{{ end }}}
|
||||||
|
{{ end }}
|
Loading…
Reference in a new issue