1
0

types.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. package server
  2. import (
  3. "heckel.io/ntfy/util"
  4. "net/http"
  5. "time"
  6. )
  7. // List of possible events
  8. const (
  9. openEvent = "open"
  10. keepaliveEvent = "keepalive"
  11. messageEvent = "message"
  12. pollRequestEvent = "poll_request"
  13. )
  14. const (
  15. messageIDLength = 10
  16. )
  17. // message represents a message published to a topic
  18. type message struct {
  19. ID string `json:"id"` // Random message ID
  20. Time int64 `json:"time"` // Unix time in seconds
  21. Event string `json:"event"` // One of the above
  22. Topic string `json:"topic"`
  23. Priority int `json:"priority,omitempty"`
  24. Tags []string `json:"tags,omitempty"`
  25. Click string `json:"click,omitempty"`
  26. Attachment *attachment `json:"attachment,omitempty"`
  27. Title string `json:"title,omitempty"`
  28. Message string `json:"message,omitempty"`
  29. Encoding string `json:"encoding,omitempty"` // empty for raw UTF-8, or "base64" for encoded bytes
  30. }
  31. type attachment struct {
  32. Name string `json:"name"`
  33. Type string `json:"type,omitempty"`
  34. Size int64 `json:"size,omitempty"`
  35. Expires int64 `json:"expires,omitempty"`
  36. URL string `json:"url"`
  37. Owner string `json:"-"` // IP address of uploader, used for rate limiting
  38. }
  39. // messageEncoder is a function that knows how to encode a message
  40. type messageEncoder func(msg *message) (string, error)
  41. // newMessage creates a new message with the current timestamp
  42. func newMessage(event, topic, msg string) *message {
  43. return &message{
  44. ID: util.RandomString(messageIDLength),
  45. Time: time.Now().Unix(),
  46. Event: event,
  47. Topic: topic,
  48. Priority: 0,
  49. Tags: nil,
  50. Title: "",
  51. Message: msg,
  52. }
  53. }
  54. // newOpenMessage is a convenience method to create an open message
  55. func newOpenMessage(topic string) *message {
  56. return newMessage(openEvent, topic, "")
  57. }
  58. // newKeepaliveMessage is a convenience method to create a keepalive message
  59. func newKeepaliveMessage(topic string) *message {
  60. return newMessage(keepaliveEvent, topic, "")
  61. }
  62. // newDefaultMessage is a convenience method to create a notification message
  63. func newDefaultMessage(topic, msg string) *message {
  64. return newMessage(messageEvent, topic, msg)
  65. }
  66. type sinceTime time.Time
  67. func (t sinceTime) IsAll() bool {
  68. return t == sinceAllMessages
  69. }
  70. func (t sinceTime) IsNone() bool {
  71. return t == sinceNoMessages
  72. }
  73. func (t sinceTime) Time() time.Time {
  74. return time.Time(t)
  75. }
  76. var (
  77. sinceAllMessages = sinceTime(time.Unix(0, 0))
  78. sinceNoMessages = sinceTime(time.Unix(1, 0))
  79. )
  80. type queryFilter struct {
  81. Message string
  82. Title string
  83. Tags []string
  84. Priority []int
  85. }
  86. func parseQueryFilters(r *http.Request) (*queryFilter, error) {
  87. messageFilter := readParam(r, "x-message", "message", "m")
  88. titleFilter := readParam(r, "x-title", "title", "t")
  89. tagsFilter := util.SplitNoEmpty(readParam(r, "x-tags", "tags", "tag", "ta"), ",")
  90. priorityFilter := make([]int, 0)
  91. for _, p := range util.SplitNoEmpty(readParam(r, "x-priority", "priority", "prio", "p"), ",") {
  92. priority, err := util.ParsePriority(p)
  93. if err != nil {
  94. return nil, err
  95. }
  96. priorityFilter = append(priorityFilter, priority)
  97. }
  98. return &queryFilter{
  99. Message: messageFilter,
  100. Title: titleFilter,
  101. Tags: tagsFilter,
  102. Priority: priorityFilter,
  103. }, nil
  104. }
  105. func (q *queryFilter) Pass(msg *message) bool {
  106. if msg.Event != messageEvent {
  107. return true // filters only apply to messages
  108. }
  109. if q.Message != "" && msg.Message != q.Message {
  110. return false
  111. }
  112. if q.Title != "" && msg.Title != q.Title {
  113. return false
  114. }
  115. messagePriority := msg.Priority
  116. if messagePriority == 0 {
  117. messagePriority = 3 // For query filters, default priority (3) is the same as "not set" (0)
  118. }
  119. if len(q.Priority) > 0 && !util.InIntList(q.Priority, messagePriority) {
  120. return false
  121. }
  122. if len(q.Tags) > 0 && !util.InStringListAll(msg.Tags, q.Tags) {
  123. return false
  124. }
  125. return true
  126. }