mirror of
https://github.com/AsamK/signal-cli
synced 2025-09-02 12:30:39 +00:00
Create signal-cli-api.go
An interface for `signal-cli daemon --socket ...` to separate command responses from incoming messages. This also solved a problem I had with using the `--tcp` option inside a LXC container, since signal-cli binds to 127.0.0.1 and I needed access from outside the container.
This commit is contained in:
parent
15630356e1
commit
8506e7db53
1 changed files with 99 additions and 0 deletions
99
client-golang/signal-cli-api.go
Normal file
99
client-golang/signal-cli-api.go
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/**
|
||||||
|
Accept commands on TCP socket and send to signal-cli daemon on UNIX socket.
|
||||||
|
Immediate responses are returned via the TCP socket, and other incoming
|
||||||
|
messages are logged to stdout.
|
||||||
|
|
||||||
|
With this program running as a service, we can follow incoming messages with:
|
||||||
|
journalctl -fu signal-cli-api --no-tail
|
||||||
|
**/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
unixSocketPath := "/tmp/signal-cli/socket"
|
||||||
|
unixConn, err := net.Dial("unix", unixSocketPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer unixConn.Close()
|
||||||
|
|
||||||
|
tcpPort := "5780"
|
||||||
|
tcpListener, err := net.Listen("tcp", ":"+tcpPort)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer tcpListener.Close()
|
||||||
|
|
||||||
|
responses := make(chan string)
|
||||||
|
|
||||||
|
// Read messages from the UNIX socket
|
||||||
|
go func() {
|
||||||
|
scanner := bufio.NewScanner(unixConn)
|
||||||
|
for scanner.Scan() {
|
||||||
|
resp := scanner.Text()
|
||||||
|
if isCommandResponse(resp) {
|
||||||
|
responses <- resp
|
||||||
|
} else {
|
||||||
|
log.Println(resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
// Wait for TCP connection
|
||||||
|
tcpConn, err := tcpListener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read command
|
||||||
|
cmd, err := bufio.NewReader(tcpConn).ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
tcpConn.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write command to UNIX socket
|
||||||
|
fmt.Fprint(unixConn, cmd)
|
||||||
|
|
||||||
|
// Read responses
|
||||||
|
select {
|
||||||
|
case msg := <-responses:
|
||||||
|
fmt.Fprintln(tcpConn, msg)
|
||||||
|
case <-time.After(2 * time.Second):
|
||||||
|
fmt.Fprint(tcpConn, "Timed out")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close TCP connection
|
||||||
|
tcpConn.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if signal-cli json-rpc message is a command response.
|
||||||
|
Command response & error formats:
|
||||||
|
{"jsonrpc":"2.0","result":{...},"id":1678829060000}
|
||||||
|
{"jsonrpc":"2.0","result":[...],"id":1678829060000}
|
||||||
|
{"jsonrpc":"2.0","error":{...},"id":1678829060000}
|
||||||
|
|
||||||
|
Incoming message format:
|
||||||
|
{"jsonrpc":"2.0","method":"receive","params":{...}}
|
||||||
|
|
||||||
|
This assumes signal-cli doesn't change jsonrpc format or version.
|
||||||
|
It would be more robust to parse the JSON, but shouldn't be needed.
|
||||||
|
**/
|
||||||
|
func isCommandResponse(resp string) bool {
|
||||||
|
return len(resp) >= 26 && resp[:26] != "{\"jsonrpc\":\"2.0\",\"method\":"
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue