diff --git a/client/client.yml b/client/client.yml
index 0a38a9b..2fbe17a 100644
--- a/client/client.yml
+++ b/client/client.yml
@@ -5,14 +5,25 @@
#
# default-host: https://ntfy.sh
-# Subscriptions to topics and their actions. This option is only used by the "ntfy subscribe --from-config"
-# command.
+# Subscriptions to topics and their actions. This option is primarily used by the systemd service,
+# or if you cann "ntfy subscribe --from-config" directly.
#
-# Here's a (hopefully self-explanatory) example:
-# subscribe:
-# - topic: mytopic
-# command: /usr/local/bin/mytopic-triggered.sh
-# - topic: myserver.com/anothertopic
-# command: 'echo "$message"'
+# Example:
+# subscribe:
+# - topic: mytopic
+# command: /usr/local/bin/mytopic-triggered.sh
+# - topic: myserver.com/anothertopic
+# command: 'echo "$message"'
+#
+# Variables:
+# Variable Aliases Description
+# --------------- --------------- -----------------------------------
+# $NTFY_ID $id Unique message ID
+# $NTFY_TIME $time Unix timestamp of the message delivery
+# $NTFY_TOPIC $topic Topic name
+# $NTFY_MESSAGE $message, $m Message body
+# $NTFY_TITLE $title, $t Message title
+# $NTFY_PRIORITY $priority, $p Message priority (1=min, 5=max)
+# $NTFY_TAGS $tags, $ta Message tags (comma separated list)
#
# subscribe:
diff --git a/client/config.go b/client/config.go
index 76fcc1f..8c19611 100644
--- a/client/config.go
+++ b/client/config.go
@@ -7,12 +7,12 @@ const (
// Config is the config struct for a Client
type Config struct {
- DefaultHost string
+ DefaultHost string `yaml:"default-host"`
Subscribe []struct {
- Topic string
- Command string
+ Topic string `yaml:"topic"`
+ Command string `yaml:"command"`
// If []map[string]string TODO This would be cool
- }
+ } `yaml:"subscribe"`
}
// NewConfig creates a new Config struct for a Client
diff --git a/cmd/subscribe.go b/cmd/subscribe.go
index 8d61477..a45b9c2 100644
--- a/cmd/subscribe.go
+++ b/cmd/subscribe.go
@@ -20,11 +20,6 @@ var cmdSubscribe = &cli.Command{
Usage: "Subscribe to one or more topics on a ntfy server",
UsageText: "ntfy subscribe [OPTIONS..] [TOPIC]",
Action: execSubscribe,
- OnUsageError: func(context *cli.Context, err error, isSubcommand bool) error {
- println("ee")
- return nil
- },
-
Flags: []cli.Flag{
&cli.StringFlag{Name: "config", Aliases: []string{"c"}, Usage: "client config file"},
&cli.StringFlag{Name: "since", Aliases: []string{"s"}, Usage: "return events since `SINCE` (Unix timestamp, or all)"},
@@ -109,26 +104,26 @@ func execSubscribe(c *cli.Context) error {
// Execute poll or subscribe
if poll {
- return execPoll(c, cl, conf, topic, command, options...)
+ return doPoll(c, cl, conf, topic, command, options...)
}
- return execSubscribeInternal(c, cl, conf, topic, command, options...)
+ return doSubscribe(c, cl, conf, topic, command, options...)
}
-func execPoll(c *cli.Context, cl *client.Client, conf *client.Config, topic, command string, options ...client.SubscribeOption) error {
+func doPoll(c *cli.Context, cl *client.Client, conf *client.Config, topic, command string, options ...client.SubscribeOption) error {
for _, s := range conf.Subscribe { // may be nil
- if err := execPollSingle(c, cl, s.Topic, s.Command, options...); err != nil {
+ if err := doPollSingle(c, cl, s.Topic, s.Command, options...); err != nil {
return err
}
}
if topic != "" {
- if err := execPollSingle(c, cl, topic, command, options...); err != nil {
+ if err := doPollSingle(c, cl, topic, command, options...); err != nil {
return err
}
}
return nil
}
-func execPollSingle(c *cli.Context, cl *client.Client, topic, command string, options ...client.SubscribeOption) error {
+func doPollSingle(c *cli.Context, cl *client.Client, topic, command string, options ...client.SubscribeOption) error {
messages, err := cl.Poll(topic, options...)
if err != nil {
return err
@@ -139,7 +134,7 @@ func execPollSingle(c *cli.Context, cl *client.Client, topic, command string, op
return nil
}
-func execSubscribeInternal(c *cli.Context, cl *client.Client, conf *client.Config, topic, command string, options ...client.SubscribeOption) error {
+func doSubscribe(c *cli.Context, cl *client.Client, conf *client.Config, topic, command string, options ...client.SubscribeOption) error {
commands := make(map[string]string)
for _, s := range conf.Subscribe { // May be nil
topicURL := cl.Subscribe(s.Topic, options...)
diff --git a/docs/static/img/cli-subscribe-video-3.webm b/docs/static/img/cli-subscribe-video-3.webm
new file mode 100644
index 0000000..8a07f41
Binary files /dev/null and b/docs/static/img/cli-subscribe-video-3.webm differ
diff --git a/docs/subscribe/cli.md b/docs/subscribe/cli.md
index 334611f..29416c3 100644
--- a/docs/subscribe/cli.md
+++ b/docs/subscribe/cli.md
@@ -5,10 +5,10 @@ to topics via the ntfy CLI. The CLI is included in the same `ntfy` binary that c
!!! info
The **ntfy CLI is not required to send or receive messages**. You can instead [send messages with curl](../publish.md),
and even use it to [subscribe to topics](api.md). It may be a little more convenient to use the ntfy CLI than writing
- your own script. Or it may not be. It all depends on the use case. 😀
+ your own script. It all depends on the use case. 😀
## Install + configure
-To install the ntfy CLI, simply follow the steps outlined on the [install page](../install.md). The ntfy server and
+To install the ntfy CLI, simply **follow the steps outlined on the [install page](../install.md)**. The ntfy server and
client are the same binary, so it's all very convenient. After installing, you can (optionally) configure the client
by creating `~/.config/ntfy/client.yml` (for the non-root user), or `/etc/ntfy/client.yml` (for the root user). You
can find a [skeleton config](https://github.com/binwiederhier/ntfy/blob/main/client/client.yml) on GitHub.
@@ -23,7 +23,7 @@ you may want to edit the `default-host` option:
default-host: https://ntfy.myhost.com
```
-## Publish using the ntfy CLI
+## Publish messages
You can send messages with the ntfy CLI using the `ntfy publish` command (or any of its aliases `pub`, `send` or
`trigger`). There are a lot of examples on the page about [publishing messages](../publish.md), but here are a few
quick ones:
@@ -56,20 +56,23 @@ quick ones:
ntfy pub mywebhook
```
-## Subscribe using the ntfy CLI
+## Subscribe to topics
You can subscribe to topics using `ntfy subscribe`. Depending on how it is called, this command
will either print or execute a command for every arriving message. There are a few different ways
in which the command can be run:
-### Stream messages and print JSON
-If run like this `ntfy subscribe TOPIC`, the command prints the JSON representation of every incoming
-message. This is useful when you have a command that wants to stream-read incoming JSON messages.
-Unless `--poll` is passed, this command stays open forever.
+### Stream messages as JSON
+```
+ntfy subscribe TOPIC
+```
+If you run the command like this, it prints the JSON representation of every incoming message. This is useful
+when you have a command that wants to stream-read incoming JSON messages. Unless `--poll` is passed, this command
+stays open forever.
```
$ ntfy sub mytopic
{"id":"nZ8PjH5oox","time":1639971913,"event":"message","topic":"mytopic","message":"hi there"}
-{"id":"sekSLWTujn","time":1639972063,"event":"message","topic":"mytopic","tags":["warning","skull"],"message":"Oh no, something went wrong"}
+{"id":"sekSLWTujn","time":1639972063,"event":"message","topic":"mytopic",priority:5,"message":"Oh no!"}
```
@@ -77,15 +80,28 @@ $ ntfy sub mytopic
Subscribe in JSON mode
-### Execute a command for every incoming message
-If run like this `ntfy subscribe TOPIC COMMAND`, a COMMAND is executed for every incoming messages.
-The message fields are passed to the command as environment variables and can be used in scripts:
+### Run command for every message
+```
+ntfy subscribe TOPIC COMMAND
+```
+If you run it like this, a COMMAND is executed for every incoming messages. Here are a few
+examples:
+
+```
+ntfy sub mytopic 'notify-send "$m"'
+ntfy sub topic1 /my/script.sh
+ntfy sub topic1 'echo "Message $m was received. Its title was $t and it had priority $p'
+```
Execute command on incoming messages
+The message fields are passed to the command as environment variables and can be used in scripts. Note that since
+these are environment variables, you typically don't have to worry about quoting too much, as long as you enclose them
+in double-quotes, you should be fine:
+
| Variable | Aliases | Description |
|---|---|---
| `$NTFY_ID` | `$id` | Unique message ID |
@@ -96,32 +112,78 @@ The message fields are passed to the command as environment variables and can be
| `$NTFY_PRIORITY` | `$priority`, `$p` | Message priority (1=min, 5=max) |
| `$NTFY_TAGS` | `$tags`, `$ta` | Message tags (comma separated list) |
- Examples:
- ntfy sub mytopic 'notify-send "$m"' # Execute command for incoming messages
- ntfy sub topic1 /my/script.sh # Execute script for incoming messages
-
-### Using a config file
+### Subscribing to multiple topics
+```
ntfy subscribe --from-config
-Service mode (used in ntfy-client.service). This reads the config file (/etc/ntfy/client.yml
-or ~/.config/ntfy/client.yml) and sets up subscriptions for every topic in the "subscribe:"
-block (see config file).
+```
+To subscribe to multiple topics at once, and run different commands for each one, you can use `ntfy subscribe --from-config`,
+which will read the `subscribe` config from the config file. Please also check out the [ntfy-client systemd service](#using-the-systemd-service).
- Examples:
- ntfy sub --from-config # Read topics from config file
- ntfy sub --config=/my/client.yml --from-config # Read topics from alternate config file
+Here's an example config file that subscribes to three different topics, executing a different command for each of them:
-The default config file for all client commands is /etc/ntfy/client.yml (if root user),
-or ~/.config/ntfy/client.yml for all other users.
+=== "~/.config/ntfy/client.yml"
+ ```yaml
+ subscribe:
+ - topic: echo-this
+ command: 'echo "Message received: $message"'
+ - topic: get-temp
+ command: |
+ temp="$(sensors | awk '/Package/ { print $4 }')"
+ ntfy publish --quiet temp "$temp";
+ echo "CPU temp is $temp; published to topic 'temp'"
+ - topic: alerts
+ command: notify-send "$m"
+ - topic: calc
+ command: 'gnome-calculator 2>/dev/null &'
+ ```
+In this example, when `ntfy subscribe --from-config` is executed:
+
+* Messages to topic `echo-this` will be simply echoed to standard out
+* Messages to topic `get-temp` will publish the CPU core temperature to topic `temp`
+* Messages to topic `alerts` will be displayed as desktop notification using `notify-send`
+* And messages to topic `calc` will open the gnome calculator 😀 (*because, why not*)
+
+I hope this shows how powerful this command is. Here's a short video that demonstrates the above example:
+
+
+
+ Execute all the things
+
### Using the systemd service
+You can use the `ntfy-client` systemd service (see [ntfy-client.service](https://github.com/binwiederhier/ntfy/blob/main/client/ntfy-client.service))
+to subscribe to multiple topics just like in the example above. The service is automatically installed (but not started)
+if you install the deb/rpm package. To configure it, simply edit `/etc/ntfy/client.yml` and run `sudo systemctl restart ntfy-client`.
+
+!!! info
+ The `ntfy-client.service` runs as user `ntfy`, meaning that typical Linux permission restrictions apply. See below
+ for how to fix this.
+
+If it runs on your personal desktop machine, you may want to override the service user/group (`User=` and `Group=`), and
+adjust the `DISPLAY` and DBUS environment variables. This will allow you to run commands in your X session as the primary
+machine user.
+
+You can either manually override these systemd service entries with `sudo systemctl edit ntfy-client`, and add this
+(assuming your user is `pheckel`):
+
+=== "/etc/systemd/system/ntfy-client.service.d/override.conf"
+ ```
+ [Service]
+ User=pheckel
+ Group=pheckel
+ Environment="DISPLAY=:0" "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus"
+ ```
+Or you can run the following script that creates this override config for you:
```
+sudo sh -c 'cat > /etc/systemd/system/ntfy-client.service.d/override.conf' <