mirror of
https://github.com/AsamK/signal-cli
synced 2025-09-02 04:20:38 +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