Philipp Heckel %!s(int64=4) %!d(string=hai) anos
pai
achega
a1f513f6a5
Modificáronse 9 ficheiros con 138 adicións e 65 borrados
  1. 30 9
      client/client.go
  2. 26 32
      client/options.go
  3. 1 1
      cmd/app.go
  4. 1 1
      cmd/publish.go
  5. 37 10
      cmd/subscribe.go
  6. 25 0
      docs/deprecations.md
  7. 11 9
      docs/install.md
  8. 3 0
      docs/subscribe/cli.md
  9. 4 3
      mkdocs.yml

+ 30 - 9
client/client.go

@@ -34,12 +34,12 @@ type Message struct {
 	Event    string
 	Time     int64
 	Topic    string
+	BaseURL  string
+	TopicURL string
 	Message  string
 	Title    string
 	Priority int
 	Tags     []string
-	BaseURL  string
-	TopicURL string
 	Raw      string
 }
 
@@ -73,7 +73,23 @@ func (c *Client) Publish(topicURL, message string, options ...PublishOption) err
 	return err
 }
 
-func (c *Client) Subscribe(topicURL string) {
+func (c *Client) Poll(topicURL string, options ...SubscribeOption) ([]*Message, error) {
+	ctx := context.Background()
+	messages := make([]*Message, 0)
+	msgChan := make(chan *Message)
+	errChan := make(chan error)
+	go func() {
+		err := performSubscribeRequest(ctx, msgChan, topicURL, options...)
+		close(msgChan)
+		errChan <- err
+	}()
+	for m := range msgChan {
+		messages = append(messages, m)
+	}
+	return messages, <-errChan
+}
+
+func (c *Client) Subscribe(topicURL string, options ...SubscribeOption) {
 	c.mu.Lock()
 	defer c.mu.Unlock()
 	if _, ok := c.subscriptions[topicURL]; ok {
@@ -81,7 +97,7 @@ func (c *Client) Subscribe(topicURL string) {
 	}
 	ctx, cancel := context.WithCancel(context.Background())
 	c.subscriptions[topicURL] = &subscription{cancel}
-	go handleConnectionLoop(ctx, c.Messages, topicURL)
+	go handleSubscribeConnLoop(ctx, c.Messages, topicURL, options...)
 }
 
 func (c *Client) Unsubscribe(topicURL string) {
@@ -95,25 +111,30 @@ func (c *Client) Unsubscribe(topicURL string) {
 	return
 }
 
-func handleConnectionLoop(ctx context.Context, msgChan chan *Message, topicURL string) {
+func handleSubscribeConnLoop(ctx context.Context, msgChan chan *Message, topicURL string, options ...SubscribeOption) {
 	for {
-		if err := handleConnection(ctx, msgChan, topicURL); err != nil {
-			log.Printf("connection to %s failed: %s", topicURL, err.Error())
+		if err := performSubscribeRequest(ctx, msgChan, topicURL, options...); err != nil {
+			log.Printf("Connection to %s failed: %s", topicURL, err.Error())
 		}
 		select {
 		case <-ctx.Done():
-			log.Printf("connection to %s exited", topicURL)
+			log.Printf("Connection to %s exited", topicURL)
 			return
 		case <-time.After(5 * time.Second):
 		}
 	}
 }
 
-func handleConnection(ctx context.Context, msgChan chan *Message, topicURL string) error {
+func performSubscribeRequest(ctx context.Context, msgChan chan *Message, topicURL string, options ...SubscribeOption) error {
 	req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/json", topicURL), nil)
 	if err != nil {
 		return err
 	}
+	for _, option := range options {
+		if err := option(req); err != nil {
+			return err
+		}
+	}
 	resp, err := http.DefaultClient.Do(req)
 	if err != nil {
 		return err

+ 26 - 32
client/options.go

@@ -4,42 +4,24 @@ import (
 	"net/http"
 )
 
-type PublishOption func(r *http.Request) error
+type RequestOption func(r *http.Request) error
+type PublishOption = RequestOption
+type SubscribeOption = RequestOption
 
 func WithTitle(title string) PublishOption {
-	return func(r *http.Request) error {
-		if title != "" {
-			r.Header.Set("X-Title", title)
-		}
-		return nil
-	}
+	return WithHeader("X-Title", title)
 }
 
 func WithPriority(priority string) PublishOption {
-	return func(r *http.Request) error {
-		if priority != "" {
-			r.Header.Set("X-Priority", priority)
-		}
-		return nil
-	}
+	return WithHeader("X-Priority", priority)
 }
 
 func WithTags(tags string) PublishOption {
-	return func(r *http.Request) error {
-		if tags != "" {
-			r.Header.Set("X-Tags", tags)
-		}
-		return nil
-	}
+	return WithHeader("X-Tags", tags)
 }
 
 func WithDelay(delay string) PublishOption {
-	return func(r *http.Request) error {
-		if delay != "" {
-			r.Header.Set("X-Delay", delay)
-		}
-		return nil
-	}
+	return WithHeader("X-Delay", delay)
 }
 
 func WithNoCache() PublishOption {
@@ -50,20 +32,32 @@ func WithNoFirebase() PublishOption {
 	return WithHeader("X-Firebase", "no")
 }
 
-func WithHeader(header, value string) PublishOption {
+func WithSince(since string) SubscribeOption {
+	return WithQueryParam("since", since)
+}
+
+func WithPoll() SubscribeOption {
+	return WithQueryParam("poll", "1")
+}
+
+func WithScheduled() SubscribeOption {
+	return WithQueryParam("scheduled", "1")
+}
+
+func WithHeader(header, value string) RequestOption {
 	return func(r *http.Request) error {
-		r.Header.Set(header, value)
+		if value != "" {
+			r.Header.Set(header, value)
+		}
 		return nil
 	}
 }
 
-type SubscribeOption func(r *http.Request) error
-
-func WithSince(since string) PublishOption {
+func WithQueryParam(param, value string) RequestOption {
 	return func(r *http.Request) error {
-		if since != "" {
+		if value != "" {
 			q := r.URL.Query()
-			q.Add("since", since)
+			q.Add(param, value)
 			r.URL.RawQuery = q.Encode()
 		}
 		return nil

+ 1 - 1
cmd/app.go

@@ -36,7 +36,7 @@ func New() *cli.App {
 
 func execMainApp(c *cli.Context) error {
 	log.Printf("\x1b[1;33mDeprecation notice: Please run the server using 'ntfy serve'; see 'ntfy -h' for help.\x1b[0m")
-	log.Printf("\x1b[1;33mThis way of running the server will be removed Feb 2022.\x1b[0m")
+	log.Printf("\x1b[1;33mThis way of running the server will be removed March 2022. See https://ntfy.sh/docs/deprecations/ for details.\x1b[0m")
 	return execServe(c)
 }
 

+ 1 - 1
cmd/publish.go

@@ -9,7 +9,7 @@ import (
 
 var cmdPublish = &cli.Command{
 	Name:      "publish",
-	Aliases:   []string{"pub", "send"},
+	Aliases:   []string{"pub", "send", "push"},
 	Usage:     "Send message via a ntfy server",
 	UsageText: "ntfy send [OPTIONS..] TOPIC MESSAGE",
 	Action:    execPublish,

+ 37 - 10
cmd/subscribe.go

@@ -21,6 +21,8 @@ var cmdSubscribe = &cli.Command{
 	Flags: []cli.Flag{
 		&cli.StringFlag{Name: "exec", Aliases: []string{"e"}, Usage: "execute command for each message event"},
 		&cli.StringFlag{Name: "since", Aliases: []string{"s"}, Usage: "return events since (Unix timestamp, or all)"},
+		&cli.BoolFlag{Name: "poll", Aliases: []string{"p"}, Usage: "return events and exit, do not listen for new events"},
+		&cli.BoolFlag{Name: "scheduled", Aliases: []string{"sched", "S"}, Usage: "also return scheduled/delayed events"},
 	},
 	Description: `(THIS COMMAND IS INCUBATING. IT MAY CHANGE WITHOUT NOTICE.)
 
@@ -45,7 +47,8 @@ are passed to the command as environment variables:
 Examples:
   ntfy subscribe mytopic                       # Prints JSON for incoming messages to stdout
   ntfy sub home.lan/backups alerts             # Subscribe to two different topics
-  ntfy sub --exec='notify-send "$m"' mytopic   # Execute command for incoming messages'  
+  ntfy sub --exec='notify-send "$m"' mytopic   # Execute command for incoming messages
+  ntfy sub --exec=/my/script topic1 topic2     # Subscribe to two topics and execute command for each message
 `,
 }
 
@@ -56,11 +59,37 @@ func execSubscribe(c *cli.Context) error {
 	log.Printf("\x1b[1;33mThis command is incubating. The interface may change without notice.\x1b[0m")
 	cl := client.DefaultClient
 	command := c.String("exec")
-	for _, topic := range c.Args().Slice() {
-		cl.Subscribe(expandTopicURL(topic))
+	since := c.String("since")
+	poll := c.Bool("poll")
+	scheduled := c.Bool("scheduled")
+	topics := c.Args().Slice()
+	var options []client.SubscribeOption
+	if since != "" {
+		options = append(options, client.WithSince(since))
 	}
-	for m := range cl.Messages {
-		_ = dispatchMessage(c, command, m)
+	if poll {
+		options = append(options, client.WithPoll())
+	}
+	if scheduled {
+		options = append(options, client.WithScheduled())
+	}
+	if poll {
+		for _, topic := range topics {
+			messages, err := cl.Poll(expandTopicURL(topic), options...)
+			if err != nil {
+				return err
+			}
+			for _, m := range messages {
+				_ = dispatchMessage(c, command, m)
+			}
+		}
+	} else {
+		for _, topic := range topics {
+			cl.Subscribe(expandTopicURL(topic), options...)
+		}
+		for m := range cl.Messages {
+			_ = dispatchMessage(c, command, m)
+		}
 	}
 	return nil
 }
@@ -77,11 +106,9 @@ func execCommand(c *cli.Context, command string, m *client.Message) error {
 	if m.Event == client.OpenEvent {
 		log.Printf("[%s] Connection opened, subscribed to topic", collapseTopicURL(m.TopicURL))
 	} else if m.Event == client.MessageEvent {
-		go func() {
-			if err := runCommandInternal(c, command, m); err != nil {
-				log.Printf("[%s] Command failed: %s", collapseTopicURL(m.TopicURL), err.Error())
-			}
-		}()
+		if err := runCommandInternal(c, command, m); err != nil {
+			log.Printf("[%s] Command failed: %s", collapseTopicURL(m.TopicURL), err.Error())
+		}
 	}
 	return nil
 }

+ 25 - 0
docs/deprecations.md

@@ -0,0 +1,25 @@
+# Deprecation notices
+This page is used to list deprecation notices for ntfy. Deprecated commands and options will be 
+**removed after ~3 months** from the time they were deprecated.
+
+## Active deprecations
+
+### Running server via `ntfy` (instead of `ntfy serve`)
+> since 2021-12-17
+
+As more commands are added to the `ntfy` CLI tool, using just `ntfy` to run the server is not practical
+anymore. Please use `ntfy serve` instead. This also applies to Docker images, as they can also execute more than
+just the server.
+
+=== "Before"
+    ```
+    $ ntfy
+    2021/12/17 08:16:01 Listening on :80/http
+    ```
+
+=== "After"
+    ```
+    $ ntfy serve
+    2021/12/17 08:16:01 Listening on :80/http
+    ```
+

+ 11 - 9
docs/install.md

@@ -12,7 +12,7 @@ We support amd64, armv7 and arm64.
 
 1. Install ntfy using one of the methods described below
 2. Then (optionally) edit `/etc/ntfy/config.yml` (see [configuration](config.md))
-3. Then just run it with `ntfy` (or `systemctl start ntfy` when using the deb/rpm).
+3. Then just run it with `ntfy serve` (or `systemctl start ntfy` when using the deb/rpm).
 
 ## Binaries and packages
 Please check out the [releases page](https://github.com/binwiederhier/ntfy/releases) for binaries and
@@ -22,21 +22,21 @@ deb/rpm packages.
     ```bash
     wget https://github.com/binwiederhier/ntfy/releases/download/v1.7.0/ntfy_1.7.0_linux_x86_64.tar.gz
     sudo tar -C /usr/bin -zxf ntfy_*.tar.gz ntfy
-    sudo ./ntfy
+    sudo ./ntfy serve
     ```
 
 === "armv7/armhf"
     ```bash
     wget https://github.com/binwiederhier/ntfy/releases/download/v1.7.0/ntfy_1.7.0_linux_armv7.tar.gz
     sudo tar -C /usr/bin -zxf ntfy_*.tar.gz ntfy
-    sudo ./ntfy
+    sudo ./ntfy serve
     ```
 
 === "arm64"
     ```bash
     wget https://github.com/binwiederhier/ntfy/releases/download/v1.7.0/ntfy_1.7.0_linux_arm64.tar.gz
     sudo tar -C /usr/bin -zxf ntfy_*.tar.gz ntfy
-    sudo ./ntfy
+    sudo ./ntfy serve
     ```
 
 ## Debian/Ubuntu repository
@@ -132,12 +132,12 @@ The [ntfy image](https://hub.docker.com/r/binwiederhier/ntfy) is available for a
 straight forward to use.
 
 The server exposes its web UI and the API on port 80, so you need to expose that in Docker. To use the persistent 
-[message cache](config.md#message-cache), you also need to map a volume to `/var/cache/ntfy`. To change other settings, you should map `/etc/ntfy`,
-so you can edit `/etc/ntfy/config.yml`.
+[message cache](config.md#message-cache), you also need to map a volume to `/var/cache/ntfy`. To change other settings, 
+you should map `/etc/ntfy`, so you can edit `/etc/ntfy/config.yml`.
 
 Basic usage (no cache or additional config):
 ```
-docker run -p 80:80 -it binwiederhier/ntfy
+docker run -p 80:80 -it binwiederhier/ntfy serve
 ```
 
 With persistent cache (configured as command line arguments):
@@ -147,7 +147,8 @@ docker run \
   -p 80:80 \
   -it \
   binwiederhier/ntfy \
-    --cache-file /var/cache/ntfy/cache.db
+    --cache-file /var/cache/ntfy/cache.db \
+    serve
 ```
 
 With other config options (configured via `/etc/ntfy/config.yml`, see [configuration](config.md) for details):
@@ -156,7 +157,8 @@ docker run \
   -v /etc/ntfy:/etc/ntfy \
   -p 80:80 \
   -it \
-  binwiederhier/ntfy
+  binwiederhier/ntfy \
+  serve
 ```
 
 ## Go

+ 3 - 0
docs/subscribe/cli.md

@@ -0,0 +1,3 @@
+# Subscribe via CLI
+
+XXXXXXXXXxxx

+ 4 - 3
mkdocs.yml

@@ -1,11 +1,11 @@
 site_dir: server/docs
 site_name: ntfy
 site_url: https://ntfy.sh
-site_description: simple HTTP-based pub-sub
+site_description: Send push notifications to your phone via PUT/POST
 copyright: Made with ❤️ by Philipp C. Heckel
 repo_name: binwiederhier/ntfy
 repo_url: https://github.com/binwiederhier/ntfy
-edit_uri: edit/main/docs/
+edit_uri: blob/main/docs/
 
 theme:
   name: material
@@ -31,7 +31,6 @@ theme:
     - search.highlight
     - search.share
     - navigation.sections
-    # - navigation.instant
     - toc.integrate
     - content.tabs.link
 extra:
@@ -75,6 +74,7 @@ nav:
 - "Subscribing":
   - "From your phone": subscribe/phone.md
   - "From the Web UI": subscribe/web.md
+  - "Using the CLI": subscribe/cli.md
   - "Using the API": subscribe/api.md
 - "Self-hosting":
   - "Installation": install.md
@@ -83,6 +83,7 @@ nav:
   - "FAQs": faq.md
   - "Examples": examples.md
   - "Emojis 🥳 🎉": emojis.md
+  - "Deprecation notices": deprecations.md
   - "Development": develop.md
   - "Privacy policy": privacy.md