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:
parent
630f2957de
commit
9241b0550c
7 changed files with 48 additions and 5 deletions
|
@ -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:**
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue