1
0
Fork 0
mirror of https://github.com/binwiederhier/ntfy.git synced 2024-12-22 17:52:30 +01:00

feat: add subscribe param

This commit is contained in:
Hunter Kehoe 2024-11-04 21:33:35 -07:00
parent 630f2957de
commit 9241b0550c
7 changed files with 48 additions and 5 deletions

View file

@ -1378,6 +1378,7 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
**Features:** **Features:**
* Add username/password auth to email publishing ([#1164](https://github.com/binwiederhier/ntfy/pull/1164), thanks to [@bishtawi](https://github.com/bishtawi)) * Add username/password auth to email publishing ([#1164](https://github.com/binwiederhier/ntfy/pull/1164), thanks to [@bishtawi](https://github.com/bishtawi))
* Add `latest` subscription param for grabbing just the most recent message (thanks to [@wunter8](https://github.com/wunter8))
**Bug fixes + maintenance:** **Bug fixes + maintenance:**

View file

@ -257,6 +257,14 @@ curl -s "ntfy.sh/mytopic/json?since=1645970742"
curl -s "ntfy.sh/mytopic/json?since=nFS3knfcQ1xe" curl -s "ntfy.sh/mytopic/json?since=nFS3knfcQ1xe"
``` ```
### Fetch latest message
If you only want the most recent message sent to a topic and do not have a message ID or timestamp to use with
`since=`, you can use `since=latest` to grab the most recent message from the cache for a particular topic.
```
curl -s "ntfy.sh/mytopic/json?poll=1&since=latest"
```
### Fetch scheduled messages ### Fetch scheduled messages
Messages that are [scheduled to be delivered](../publish.md#scheduled-delivery) at a later date are not typically Messages that are [scheduled to be delivered](../publish.md#scheduled-delivery) at a later date are not typically
returned when subscribing via the API, which makes sense, because after all, the messages have technically not been returned when subscribing via the API, which makes sense, because after all, the messages have technically not been

View file

@ -99,6 +99,13 @@ const (
WHERE topic = ? AND (id > ? OR published = 0) WHERE topic = ? AND (id > ? OR published = 0)
ORDER BY time, id ORDER BY time, id
` `
selectMessagesLatestQuery = `
SELECT mid, time, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding
FROM messages
WHERE topic = ? AND published = 1
ORDER BY time DESC, id DESC
LIMIT 1
`
selectMessagesDueQuery = ` selectMessagesDueQuery = `
SELECT mid, time, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding SELECT mid, time, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding
FROM messages FROM messages
@ -416,6 +423,8 @@ func (c *messageCache) addMessages(ms []*message) error {
func (c *messageCache) Messages(topic string, since sinceMarker, scheduled bool) ([]*message, error) { func (c *messageCache) Messages(topic string, since sinceMarker, scheduled bool) ([]*message, error) {
if since.IsNone() { if since.IsNone() {
return make([]*message, 0), nil return make([]*message, 0), nil
} else if since.IsLatest() {
return c.messagesLatest(topic)
} else if since.IsID() { } else if since.IsID() {
return c.messagesSinceID(topic, since, scheduled) return c.messagesSinceID(topic, since, scheduled)
} }
@ -462,6 +471,14 @@ func (c *messageCache) messagesSinceID(topic string, since sinceMarker, schedule
return readMessages(rows) return readMessages(rows)
} }
func (c *messageCache) messagesLatest(topic string) ([]*message, error) {
rows, err := c.db.Query(selectMessagesLatestQuery, topic)
if err != nil {
return nil, err
}
return readMessages(rows)
}
func (c *messageCache) MessagesDue() ([]*message, error) { func (c *messageCache) MessagesDue() ([]*message, error) {
rows, err := c.db.Query(selectMessagesDueQuery, time.Now().Unix()) rows, err := c.db.Query(selectMessagesDueQuery, time.Now().Unix())
if err != nil { if err != nil {

View file

@ -66,6 +66,11 @@ func testCacheMessages(t *testing.T, c *messageCache) {
require.Equal(t, 1, len(messages)) require.Equal(t, 1, len(messages))
require.Equal(t, "my other message", messages[0].Message) require.Equal(t, "my other message", messages[0].Message)
// mytopic: latest
messages, _ = c.Messages("mytopic", sinceLatestMessage, false)
require.Equal(t, 1, len(messages))
require.Equal(t, "my other message", messages[0].Message)
// example: count // example: count
counts, err = c.MessageCounts() counts, err = c.MessageCounts()
require.Nil(t, err) require.Nil(t, err)

View file

@ -1556,8 +1556,8 @@ func (s *Server) sendOldMessages(topics []*topic, since sinceMarker, scheduled b
// parseSince returns a timestamp identifying the time span from which cached messages should be received. // parseSince returns a timestamp identifying the time span from which cached messages should be received.
// //
// Values in the "since=..." parameter can be either a unix timestamp or a duration (e.g. 12h), or // Values in the "since=..." parameter can be either a unix timestamp or a duration (e.g. 12h),
// "all" for all messages. // "all" for all messages, or "latest" for the most recent message for a topic
func parseSince(r *http.Request, poll bool) (sinceMarker, error) { func parseSince(r *http.Request, poll bool) (sinceMarker, error) {
since := readParam(r, "x-since", "since", "si") since := readParam(r, "x-since", "since", "si")
@ -1569,6 +1569,8 @@ func parseSince(r *http.Request, poll bool) (sinceMarker, error) {
return sinceNoMessages, nil return sinceNoMessages, nil
} else if since == "all" { } else if since == "all" {
return sinceAllMessages, nil return sinceAllMessages, nil
} else if since == "latest" {
return sinceLatestMessage, nil
} else if since == "none" { } else if since == "none" {
return sinceNoMessages, nil return sinceNoMessages, nil
} }

View file

@ -594,6 +594,11 @@ func TestServer_PublishAndPollSince(t *testing.T) {
require.Equal(t, 1, len(messages)) require.Equal(t, 1, len(messages))
require.Equal(t, "test 2", messages[0].Message) require.Equal(t, "test 2", messages[0].Message)
response = request(t, s, "GET", "/mytopic/json?poll=1&since=latest", "", nil)
messages = toMessages(t, response.Body.String())
require.Equal(t, 1, len(messages))
require.Equal(t, "test 2", messages[0].Message)
response = request(t, s, "GET", "/mytopic/json?poll=1&since=INVALID", "", nil) response = request(t, s, "GET", "/mytopic/json?poll=1&since=INVALID", "", nil)
require.Equal(t, 40008, toHTTPError(t, response.Body.String()).Code) require.Equal(t, 40008, toHTTPError(t, response.Body.String()).Code)
} }

View file

@ -169,8 +169,12 @@ func (t sinceMarker) IsNone() bool {
return t == sinceNoMessages return t == sinceNoMessages
} }
func (t sinceMarker) IsLatest() bool {
return t == sinceLatestMessage
}
func (t sinceMarker) IsID() bool { func (t sinceMarker) IsID() bool {
return t.id != "" return t.id != "" && t.id != "latest"
} }
func (t sinceMarker) Time() time.Time { func (t sinceMarker) Time() time.Time {
@ -182,8 +186,9 @@ func (t sinceMarker) ID() string {
} }
var ( var (
sinceAllMessages = sinceMarker{time.Unix(0, 0), ""} sinceAllMessages = sinceMarker{time.Unix(0, 0), ""}
sinceNoMessages = sinceMarker{time.Unix(1, 0), ""} sinceNoMessages = sinceMarker{time.Unix(1, 0), ""}
sinceLatestMessage = sinceMarker{time.Unix(0, 0), "latest"}
) )
type queryFilter struct { type queryFilter struct {