M .build.yml => .build.yml +1 -1
@@ 3,7 3,7 @@ packages:
- golang
- curl
secrets:
- - 601f28e4-9b07-42e9-822e-de5a46dfb0c5
+ - eb5f916b-5731-47ca-9b06-526c25632d65
tasks:
- build-x86_64: |
cd xmpp-toolbox
M .gitignore => .gitignore +2 -1
@@ 2,4 2,5 @@ config.json
.vscode
xmpp-toolbox
go.sum
-.DS_Store>
\ No newline at end of file
+.DS_Store
+config.env<
\ No newline at end of file
A README.md => README.md +54 -0
@@ 0,0 1,54 @@
+XMPP Toolbox
+============
+
+[](https://builds.sr.ht/~michalr/xmpp-toolbox/.build.yml?)
+
+**Disclaimer**: I am pretty new to golang, so the code is probably of low quality. Please point out problems and my mistakes on the [mailing list](https://lists.sr.ht/~michalr/xmpp-toolbox). Thanks!
+
+Simple XMPP tool that has two purposes:
+
+ * Receives XMPP messages and prints their content to standard output in JSON format for further processing (for example using [jq](https://stedolan.github.io/jq/)),
+ * Reads data from standard input and sends them to a specified JID as chat messages.
+
+Both of those functionalities have to be explicitly enabled on the command line:
+
+```
+Usage of ./xmpp-toolbox:
+ -listen
+ If specified, will connect to XMPP and print incoming messages to the console
+ -recipent string
+ If specified, a messages from STDIN will be sent to provided JID
+
+```
+
+Exiting
+-------
+
+ * Program terminates immediately when neither `-listen` nor `-recipent` is used in the command line,
+ * SIGTERM causes the program to disconnect from the XMPP server and terminate,
+ * In case of `-recipent` command line option being used, program terminates when EOF is encountered on the standard input.
+
+Configuration
+-------------
+
+Program reads the server, JID and password from the following environment variables:
+
+ * `XMPP_SERVER`
+ * `XMPP_USERNAME`
+ * `XMPP_PASSWORD`
+
+There are multiple options where to go from there. My suggestion would be to create a file like the following and `source` it before executing the toolbox:
+
+```sh
+export XMPP_SERVER="server.tld"
+export XMPP_USERNAME="user@server.tld"
+export XMPP_PASSWORD="password"
+```
+
+Downloads
+---------
+
+Automatically built binaries:
+
+ * [x86_64](https://nc.fl9.eu/index.php/s/K375DQxxNGEE6YG)
+ * [arm5 (Raspberry Pi)](https://nc.fl9.eu/index.php/s/T5PAPzNRWa2Dk4J)
M go.mod => go.mod +5 -1
@@ 2,4 2,8 @@ module code.fl9.eu/xmpp-toolbox
go 1.13
-require gosrc.io/xmpp v0.3.0
+require (
+ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
+ gosrc.io/xmpp v0.4.0
+ nhooyr.io/websocket v1.7.4 // indirect
+)
M main.go => main.go +16 -8
@@ 25,10 25,10 @@ func listenToMessages(x XmppConnection) {
})
}
-func sendMessagesFromStdin(x XmppConnection, recipentJid *xmpp.Jid) {
+func sendMessagesFromStdin(s xmpp.Sender, x XmppConnection, recipentJid *string) {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
- x.Send(scanner.Text(), recipentJid)
+ x.Send(s, scanner.Text(), recipentJid)
}
x.Disconnect()
os.Exit(0)
@@ 41,27 41,35 @@ func main() {
var listen = flag.Bool("listen", false, "If specified, will connect to XMPP and print incoming messages to the console")
var messageRecipent = flag.String("recipent", "", "If specified, a messages from STDIN will be sent to provided JID")
- var recipentJid *xmpp.Jid = nil
+ var recipentJid *stanza.Jid = nil
var err error
+ optionChosen := false
flag.Parse()
if (len(*messageRecipent) > 0) {
- recipentJid, err = xmpp.NewJid(*messageRecipent)
+ recipentJid, err = stanza.NewJid(*messageRecipent)
if (err != nil) {
log.Fatalf("Invalid JID provided as recipent: %s", err)
}
+ optionChosen = true
}
- xmppConnection, err := CreateXMPPConnection(xmppServer, xmppUsername, xmppPassword)
+ xmppSender := make(chan xmpp.Sender)
+ xmppConnection, err := CreateXMPPConnection(xmppServer, xmppUsername, xmppPassword, xmppSender)
if (err != nil) {
- log.Fatalf("Could not connect to XMPP server: %s\n", err)
+ log.Fatalf("Could not create an XMPP connection: %s\n", err)
}
if (*listen) {
+ optionChosen = true
listenToMessages(xmppConnection)
}
+ if (!optionChosen) {
+ log.Fatal("No option chosen in the command line! Exiting")
+ }
+
xmppError := make(chan error)
go xmppConnection.Run(xmppError)
go func() {
@@ 70,12 78,12 @@ func main() {
}()
if (recipentJid != nil) {
- go sendMessagesFromStdin(xmppConnection, recipentJid)
+ go sendMessagesFromStdin(<- xmppSender, xmppConnection, messageRecipent)
}
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
- go func() {
+ func() {
<-c
xmppConnection.Disconnect()
os.Exit(0)
M xmpp.go => xmpp.go +8 -6
@@ 1,6 1,8 @@
package main
import (
+ "log"
+
"gosrc.io/xmpp"
"gosrc.io/xmpp/stanza"
)
@@ 23,15 25,15 @@ func (x XmppConnection) Run(c chan error) {
c <- x.cm.Run()
}
-func (x XmppConnection) Send(body string, to *xmpp.Jid) {
+func (x XmppConnection) Send(s xmpp.Sender, body string, to *string) {
msg := stanza.Message{
- Attrs: stanza.Attrs{Type: stanza.MessageTypeChat, To: to.Full()},
+ Attrs: stanza.Attrs{Type: stanza.MessageTypeChat, To: *to},
Body: body,
}
- x.client.Send(msg)
+ s.Send(msg)
}
-func CreateXMPPConnection(serverAddress string, jid string, password string) (XmppConnection, error) {
+func CreateXMPPConnection(serverAddress string, jid string, password string, sender chan<- xmpp.Sender) (XmppConnection, error) {
config := xmpp.Config{
TransportConfiguration: xmpp.TransportConfiguration{
Address: serverAddress,
@@ 44,14 46,14 @@ func CreateXMPPConnection(serverAddress string, jid string, password string) (Xm
router := xmpp.NewRouter()
- client, err := xmpp.NewClient(config, router)
+ client, err := xmpp.NewClient(config, router, func(e error){ log.Fatalf("Connection error: %s", e) })
if err != nil {
return XmppConnection{cm: nil, client: nil, router: nil}, err
}
// If you pass the client to a connection manager, it will handle the reconnect policy
// for you automatically.
- cm := xmpp.NewStreamManager(client, nil)
+ cm := xmpp.NewStreamManager(client, func(s xmpp.Sender){sender <- s})
retval := XmppConnection{
cm: cm,