2021-10-27 14:56:17 -04:00
|
|
|
package server
|
|
|
|
|
2021-10-29 13:58:14 -04:00
|
|
|
import (
|
2023-02-05 23:34:27 -05:00
|
|
|
"heckel.io/ntfy/log"
|
2022-12-25 11:41:38 -05:00
|
|
|
"heckel.io/ntfy/user"
|
2022-01-15 23:17:46 -05:00
|
|
|
"net/http"
|
2022-10-05 15:42:07 -05:00
|
|
|
"net/netip"
|
2021-10-29 13:58:14 -04:00
|
|
|
"time"
|
2022-10-05 15:42:07 -05:00
|
|
|
|
|
|
|
"heckel.io/ntfy/util"
|
2021-10-29 13:58:14 -04:00
|
|
|
)
|
2021-10-27 14:56:17 -04:00
|
|
|
|
|
|
|
// List of possible events
|
|
|
|
const (
|
2022-01-31 19:33:22 -05:00
|
|
|
openEvent = "open"
|
|
|
|
keepaliveEvent = "keepalive"
|
|
|
|
messageEvent = "message"
|
|
|
|
pollRequestEvent = "poll_request"
|
2021-10-29 13:58:14 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2022-02-26 15:57:10 -05:00
|
|
|
messageIDLength = 12
|
2021-10-27 14:56:17 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
// message represents a message published to a topic
|
|
|
|
type message struct {
|
2023-01-12 12:04:18 -05:00
|
|
|
ID string `json:"id"` // Random message ID
|
|
|
|
Time int64 `json:"time"` // Unix time in seconds
|
|
|
|
Expires int64 `json:"expires,omitempty"` // Unix time in seconds (not required for open/keepalive)
|
|
|
|
Event string `json:"event"` // One of the above
|
2022-01-02 23:56:12 +01:00
|
|
|
Topic string `json:"topic"`
|
2022-05-27 07:55:57 -04:00
|
|
|
Title string `json:"title,omitempty"`
|
|
|
|
Message string `json:"message,omitempty"`
|
2022-01-02 23:56:12 +01:00
|
|
|
Priority int `json:"priority,omitempty"`
|
|
|
|
Tags []string `json:"tags,omitempty"`
|
2022-01-05 00:25:49 +01:00
|
|
|
Click string `json:"click,omitempty"`
|
2022-09-11 16:31:39 -04:00
|
|
|
Icon string `json:"icon,omitempty"`
|
2022-04-19 09:14:32 -04:00
|
|
|
Actions []*action `json:"actions,omitempty"`
|
2022-01-05 00:25:49 +01:00
|
|
|
Attachment *attachment `json:"attachment,omitempty"`
|
2022-05-27 07:55:57 -04:00
|
|
|
PollID string `json:"poll_id,omitempty"`
|
2022-01-17 13:28:07 -05:00
|
|
|
Encoding string `json:"encoding,omitempty"` // empty for raw UTF-8, or "base64" for encoded bytes
|
2022-12-19 21:42:36 -05:00
|
|
|
Sender netip.Addr `json:"-"` // IP address of uploader, used for rate limiting
|
|
|
|
User string `json:"-"` // Username of the uploader, used to associated attachments
|
2022-01-02 23:56:12 +01:00
|
|
|
}
|
|
|
|
|
2023-02-05 23:34:27 -05:00
|
|
|
func (m *message) Context() log.Context {
|
2023-02-03 22:21:50 -05:00
|
|
|
fields := map[string]any{
|
2023-02-25 20:23:22 -05:00
|
|
|
"topic": m.Topic,
|
2023-02-03 22:21:50 -05:00
|
|
|
"message_id": m.ID,
|
|
|
|
"message_time": m.Time,
|
|
|
|
"message_event": m.Event,
|
|
|
|
"message_body_size": len(m.Message),
|
|
|
|
}
|
2023-02-07 22:10:51 -05:00
|
|
|
if m.Sender.IsValid() {
|
2023-02-03 22:21:50 -05:00
|
|
|
fields["message_sender"] = m.Sender.String()
|
|
|
|
}
|
|
|
|
if m.User != "" {
|
|
|
|
fields["message_user"] = m.User
|
|
|
|
}
|
|
|
|
return fields
|
|
|
|
}
|
|
|
|
|
2022-01-02 23:56:12 +01:00
|
|
|
type attachment struct {
|
2022-01-07 14:49:28 +01:00
|
|
|
Name string `json:"name"`
|
|
|
|
Type string `json:"type,omitempty"`
|
|
|
|
Size int64 `json:"size,omitempty"`
|
|
|
|
Expires int64 `json:"expires,omitempty"`
|
|
|
|
URL string `json:"url"`
|
2021-10-27 14:56:17 -04:00
|
|
|
}
|
|
|
|
|
2022-04-16 16:17:58 -04:00
|
|
|
type action struct {
|
2022-04-17 14:29:43 -04:00
|
|
|
ID string `json:"id"`
|
2022-04-22 23:07:35 -04:00
|
|
|
Action string `json:"action"` // "view", "broadcast", or "http"
|
|
|
|
Label string `json:"label"` // action button label
|
|
|
|
Clear bool `json:"clear"` // clear notification after successful execution
|
2022-04-19 09:14:32 -04:00
|
|
|
URL string `json:"url,omitempty"` // used in "view" and "http" actions
|
|
|
|
Method string `json:"method,omitempty"` // used in "http" action, default is POST (!)
|
|
|
|
Headers map[string]string `json:"headers,omitempty"` // used in "http" action
|
|
|
|
Body string `json:"body,omitempty"` // used in "http" action
|
2022-04-19 19:22:19 -04:00
|
|
|
Intent string `json:"intent,omitempty"` // used in "broadcast" action
|
2022-04-19 09:14:32 -04:00
|
|
|
Extras map[string]string `json:"extras,omitempty"` // used in "broadcast" action
|
2022-04-16 16:17:58 -04:00
|
|
|
}
|
|
|
|
|
2022-04-27 09:51:23 -04:00
|
|
|
func newAction() *action {
|
|
|
|
return &action{
|
|
|
|
Headers: make(map[string]string),
|
|
|
|
Extras: make(map[string]string),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-15 16:00:59 -04:00
|
|
|
// publishMessage is used as input when publishing as JSON
|
|
|
|
type publishMessage struct {
|
2022-03-16 14:16:54 -04:00
|
|
|
Topic string `json:"topic"`
|
|
|
|
Title string `json:"title"`
|
|
|
|
Message string `json:"message"`
|
|
|
|
Priority int `json:"priority"`
|
|
|
|
Tags []string `json:"tags"`
|
|
|
|
Click string `json:"click"`
|
2022-09-11 16:31:39 -04:00
|
|
|
Icon string `json:"icon"`
|
2022-04-16 16:17:58 -04:00
|
|
|
Actions []action `json:"actions"`
|
2022-03-16 14:16:54 -04:00
|
|
|
Attach string `json:"attach"`
|
|
|
|
Filename string `json:"filename"`
|
2022-03-29 15:40:26 -04:00
|
|
|
Email string `json:"email"`
|
2023-05-21 20:56:56 -04:00
|
|
|
Call string `json:"call"`
|
2022-03-29 15:40:26 -04:00
|
|
|
Delay string `json:"delay"`
|
2022-03-15 16:00:59 -04:00
|
|
|
}
|
|
|
|
|
2021-10-27 14:56:17 -04:00
|
|
|
// messageEncoder is a function that knows how to encode a message
|
|
|
|
type messageEncoder func(msg *message) (string, error)
|
|
|
|
|
|
|
|
// newMessage creates a new message with the current timestamp
|
2021-10-29 13:58:14 -04:00
|
|
|
func newMessage(event, topic, msg string) *message {
|
2021-10-27 14:56:17 -04:00
|
|
|
return &message{
|
2022-05-27 07:55:57 -04:00
|
|
|
ID: util.RandomString(messageIDLength),
|
|
|
|
Time: time.Now().Unix(),
|
|
|
|
Event: event,
|
|
|
|
Topic: topic,
|
|
|
|
Message: msg,
|
2021-10-27 14:56:17 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// newOpenMessage is a convenience method to create an open message
|
2021-10-29 13:58:14 -04:00
|
|
|
func newOpenMessage(topic string) *message {
|
|
|
|
return newMessage(openEvent, topic, "")
|
2021-10-27 14:56:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// newKeepaliveMessage is a convenience method to create a keepalive message
|
2021-10-29 13:58:14 -04:00
|
|
|
func newKeepaliveMessage(topic string) *message {
|
|
|
|
return newMessage(keepaliveEvent, topic, "")
|
2021-10-27 14:56:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// newDefaultMessage is a convenience method to create a notification message
|
2021-10-29 13:58:14 -04:00
|
|
|
func newDefaultMessage(topic, msg string) *message {
|
|
|
|
return newMessage(messageEvent, topic, msg)
|
2021-10-27 14:56:17 -04:00
|
|
|
}
|
2022-01-15 23:17:46 -05:00
|
|
|
|
2022-05-27 07:55:57 -04:00
|
|
|
// newPollRequestMessage is a convenience method to create a poll request message
|
|
|
|
func newPollRequestMessage(topic, pollID string) *message {
|
|
|
|
m := newMessage(pollRequestEvent, topic, newMessageBody)
|
|
|
|
m.PollID = pollID
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
2022-02-26 15:57:10 -05:00
|
|
|
func validMessageID(s string) bool {
|
|
|
|
return util.ValidRandomString(s, messageIDLength)
|
|
|
|
}
|
|
|
|
|
|
|
|
type sinceMarker struct {
|
|
|
|
time time.Time
|
|
|
|
id string
|
|
|
|
}
|
2022-01-15 23:17:46 -05:00
|
|
|
|
2022-02-26 15:57:10 -05:00
|
|
|
func newSinceTime(timestamp int64) sinceMarker {
|
|
|
|
return sinceMarker{time.Unix(timestamp, 0), ""}
|
|
|
|
}
|
|
|
|
|
|
|
|
func newSinceID(id string) sinceMarker {
|
|
|
|
return sinceMarker{time.Unix(0, 0), id}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t sinceMarker) IsAll() bool {
|
2022-01-15 23:17:46 -05:00
|
|
|
return t == sinceAllMessages
|
|
|
|
}
|
|
|
|
|
2022-02-26 15:57:10 -05:00
|
|
|
func (t sinceMarker) IsNone() bool {
|
2022-01-15 23:17:46 -05:00
|
|
|
return t == sinceNoMessages
|
|
|
|
}
|
|
|
|
|
2022-02-26 15:57:10 -05:00
|
|
|
func (t sinceMarker) IsID() bool {
|
|
|
|
return t.id != ""
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t sinceMarker) Time() time.Time {
|
|
|
|
return t.time
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t sinceMarker) ID() string {
|
|
|
|
return t.id
|
2022-01-15 23:17:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
2022-02-26 15:57:10 -05:00
|
|
|
sinceAllMessages = sinceMarker{time.Unix(0, 0), ""}
|
|
|
|
sinceNoMessages = sinceMarker{time.Unix(1, 0), ""}
|
2022-01-15 23:17:46 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
type queryFilter struct {
|
2022-05-26 18:52:55 -04:00
|
|
|
ID string
|
2022-01-15 23:17:46 -05:00
|
|
|
Message string
|
|
|
|
Title string
|
|
|
|
Tags []string
|
|
|
|
Priority []int
|
|
|
|
}
|
|
|
|
|
|
|
|
func parseQueryFilters(r *http.Request) (*queryFilter, error) {
|
2022-05-26 18:52:55 -04:00
|
|
|
idFilter := readParam(r, "x-id", "id")
|
2022-01-15 23:17:46 -05:00
|
|
|
messageFilter := readParam(r, "x-message", "message", "m")
|
|
|
|
titleFilter := readParam(r, "x-title", "title", "t")
|
|
|
|
tagsFilter := util.SplitNoEmpty(readParam(r, "x-tags", "tags", "tag", "ta"), ",")
|
|
|
|
priorityFilter := make([]int, 0)
|
|
|
|
for _, p := range util.SplitNoEmpty(readParam(r, "x-priority", "priority", "prio", "p"), ",") {
|
|
|
|
priority, err := util.ParsePriority(p)
|
|
|
|
if err != nil {
|
2022-07-01 09:28:42 -04:00
|
|
|
return nil, errHTTPBadRequestPriorityInvalid
|
2022-01-15 23:17:46 -05:00
|
|
|
}
|
|
|
|
priorityFilter = append(priorityFilter, priority)
|
|
|
|
}
|
|
|
|
return &queryFilter{
|
2022-05-26 18:52:55 -04:00
|
|
|
ID: idFilter,
|
2022-01-15 23:17:46 -05:00
|
|
|
Message: messageFilter,
|
|
|
|
Title: titleFilter,
|
|
|
|
Tags: tagsFilter,
|
|
|
|
Priority: priorityFilter,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (q *queryFilter) Pass(msg *message) bool {
|
|
|
|
if msg.Event != messageEvent {
|
|
|
|
return true // filters only apply to messages
|
2022-05-26 18:52:55 -04:00
|
|
|
} else if q.ID != "" && msg.ID != q.ID {
|
2022-01-15 23:17:46 -05:00
|
|
|
return false
|
2022-05-26 18:52:55 -04:00
|
|
|
} else if q.Message != "" && msg.Message != q.Message {
|
|
|
|
return false
|
|
|
|
} else if q.Title != "" && msg.Title != q.Title {
|
2022-01-15 23:17:46 -05:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
messagePriority := msg.Priority
|
|
|
|
if messagePriority == 0 {
|
|
|
|
messagePriority = 3 // For query filters, default priority (3) is the same as "not set" (0)
|
|
|
|
}
|
2022-10-01 15:50:48 -04:00
|
|
|
if len(q.Priority) > 0 && !util.Contains(q.Priority, messagePriority) {
|
2022-01-15 23:17:46 -05:00
|
|
|
return false
|
|
|
|
}
|
2022-10-01 15:50:48 -04:00
|
|
|
if len(q.Tags) > 0 && !util.ContainsAll(msg.Tags, q.Tags) {
|
2022-01-15 23:17:46 -05:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
2022-12-14 23:11:22 -05:00
|
|
|
|
2022-12-24 12:22:54 -05:00
|
|
|
type apiHealthResponse struct {
|
|
|
|
Healthy bool `json:"healthy"`
|
|
|
|
}
|
2022-12-24 12:26:56 -05:00
|
|
|
|
2023-04-20 22:04:11 -04:00
|
|
|
type apiStatsResponse struct {
|
|
|
|
Messages int64 `json:"messages"`
|
|
|
|
MessagesRate float64 `json:"messages_rate"` // Average number of messages per second
|
|
|
|
}
|
|
|
|
|
2023-05-13 22:07:54 -04:00
|
|
|
type apiUserAddRequest struct {
|
|
|
|
Username string `json:"username"`
|
|
|
|
Password string `json:"password"`
|
|
|
|
Tier string `json:"tier"`
|
|
|
|
// Do not add 'role' here. We don't want to add admins via the API.
|
|
|
|
}
|
|
|
|
|
2023-05-15 10:42:24 -04:00
|
|
|
type apiUserResponse struct {
|
|
|
|
Username string `json:"username"`
|
|
|
|
Role string `json:"role"`
|
|
|
|
Tier string `json:"tier,omitempty"`
|
|
|
|
Grants []*apiUserGrantResponse `json:"grants,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type apiUserGrantResponse struct {
|
|
|
|
Topic string `json:"topic"` // This may be a pattern
|
|
|
|
Permission string `json:"permission"`
|
|
|
|
}
|
|
|
|
|
2023-05-13 22:07:54 -04:00
|
|
|
type apiUserDeleteRequest struct {
|
|
|
|
Username string `json:"username"`
|
|
|
|
}
|
|
|
|
|
2023-05-13 14:39:31 -04:00
|
|
|
type apiAccessAllowRequest struct {
|
|
|
|
Username string `json:"username"`
|
2023-05-15 10:42:24 -04:00
|
|
|
Topic string `json:"topic"` // This may be a pattern
|
2023-05-13 14:39:31 -04:00
|
|
|
Permission string `json:"permission"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type apiAccessResetRequest struct {
|
|
|
|
Username string `json:"username"`
|
|
|
|
Topic string `json:"topic"`
|
|
|
|
}
|
|
|
|
|
2022-12-14 23:11:22 -05:00
|
|
|
type apiAccountCreateRequest struct {
|
|
|
|
Username string `json:"username"`
|
|
|
|
Password string `json:"password"`
|
|
|
|
}
|
|
|
|
|
2022-12-28 22:16:11 -05:00
|
|
|
type apiAccountPasswordChangeRequest struct {
|
2023-01-21 20:52:16 -05:00
|
|
|
Password string `json:"password"`
|
|
|
|
NewPassword string `json:"new_password"`
|
2022-12-28 22:16:11 -05:00
|
|
|
}
|
|
|
|
|
2023-01-23 10:58:39 -05:00
|
|
|
type apiAccountDeleteRequest struct {
|
|
|
|
Password string `json:"password"`
|
|
|
|
}
|
|
|
|
|
2023-01-27 23:10:59 -05:00
|
|
|
type apiAccountTokenIssueRequest struct {
|
|
|
|
Label *string `json:"label"`
|
|
|
|
Expires *int64 `json:"expires"` // Unix timestamp
|
|
|
|
}
|
|
|
|
|
|
|
|
type apiAccountTokenUpdateRequest struct {
|
|
|
|
Token string `json:"token"`
|
|
|
|
Label *string `json:"label"`
|
|
|
|
Expires *int64 `json:"expires"` // Unix timestamp
|
|
|
|
}
|
|
|
|
|
2022-12-14 23:11:22 -05:00
|
|
|
type apiAccountTokenResponse struct {
|
2023-01-28 20:29:06 -05:00
|
|
|
Token string `json:"token"`
|
|
|
|
Label string `json:"label,omitempty"`
|
|
|
|
LastAccess int64 `json:"last_access,omitempty"`
|
|
|
|
LastOrigin string `json:"last_origin,omitempty"`
|
|
|
|
Expires int64 `json:"expires,omitempty"` // Unix timestamp
|
2022-12-14 23:11:22 -05:00
|
|
|
}
|
|
|
|
|
2023-05-16 22:27:48 -04:00
|
|
|
type apiAccountPhoneNumberVerifyRequest struct {
|
|
|
|
Number string `json:"number"`
|
|
|
|
Channel string `json:"channel"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type apiAccountPhoneNumberAddRequest struct {
|
2023-05-11 13:50:10 -04:00
|
|
|
Number string `json:"number"`
|
2023-05-17 10:39:15 -04:00
|
|
|
Code string `json:"code"` // Only set when adding a phone number
|
2023-05-11 13:50:10 -04:00
|
|
|
}
|
|
|
|
|
2023-01-07 21:04:13 -05:00
|
|
|
type apiAccountTier struct {
|
2023-01-09 15:40:46 -05:00
|
|
|
Code string `json:"code"`
|
|
|
|
Name string `json:"name"`
|
2022-12-17 15:17:52 -05:00
|
|
|
}
|
|
|
|
|
2022-12-19 09:59:32 -05:00
|
|
|
type apiAccountLimits struct {
|
2023-01-25 10:05:54 -05:00
|
|
|
Basis string `json:"basis,omitempty"` // "ip" or "tier"
|
2023-01-07 09:34:02 -05:00
|
|
|
Messages int64 `json:"messages"`
|
|
|
|
MessagesExpiryDuration int64 `json:"messages_expiry_duration"`
|
|
|
|
Emails int64 `json:"emails"`
|
2023-05-07 11:59:15 -04:00
|
|
|
Calls int64 `json:"calls"`
|
2023-01-07 21:04:13 -05:00
|
|
|
Reservations int64 `json:"reservations"`
|
2023-01-07 09:34:02 -05:00
|
|
|
AttachmentTotalSize int64 `json:"attachment_total_size"`
|
|
|
|
AttachmentFileSize int64 `json:"attachment_file_size"`
|
|
|
|
AttachmentExpiryDuration int64 `json:"attachment_expiry_duration"`
|
2023-01-25 10:05:54 -05:00
|
|
|
AttachmentBandwidth int64 `json:"attachment_bandwidth"`
|
2022-12-19 09:59:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
type apiAccountStats struct {
|
2022-12-19 16:22:13 -05:00
|
|
|
Messages int64 `json:"messages"`
|
|
|
|
MessagesRemaining int64 `json:"messages_remaining"`
|
|
|
|
Emails int64 `json:"emails"`
|
|
|
|
EmailsRemaining int64 `json:"emails_remaining"`
|
2023-05-07 11:59:15 -04:00
|
|
|
Calls int64 `json:"calls"`
|
|
|
|
CallsRemaining int64 `json:"calls_remaining"`
|
2023-01-07 21:04:13 -05:00
|
|
|
Reservations int64 `json:"reservations"`
|
|
|
|
ReservationsRemaining int64 `json:"reservations_remaining"`
|
2022-12-19 16:22:13 -05:00
|
|
|
AttachmentTotalSize int64 `json:"attachment_total_size"`
|
|
|
|
AttachmentTotalSizeRemaining int64 `json:"attachment_total_size_remaining"`
|
2022-12-14 23:11:22 -05:00
|
|
|
}
|
|
|
|
|
2023-01-02 20:08:37 -05:00
|
|
|
type apiAccountReservation struct {
|
|
|
|
Topic string `json:"topic"`
|
|
|
|
Everyone string `json:"everyone"`
|
2023-01-01 15:21:43 -05:00
|
|
|
}
|
|
|
|
|
2023-01-15 23:29:46 -05:00
|
|
|
type apiAccountBilling struct {
|
|
|
|
Customer bool `json:"customer"`
|
|
|
|
Subscription bool `json:"subscription"`
|
|
|
|
Status string `json:"status,omitempty"`
|
2023-02-21 22:44:30 -05:00
|
|
|
Interval string `json:"interval,omitempty"`
|
2023-01-15 23:29:46 -05:00
|
|
|
PaidUntil int64 `json:"paid_until,omitempty"`
|
2023-01-16 10:35:12 -05:00
|
|
|
CancelAt int64 `json:"cancel_at,omitempty"`
|
2023-01-15 23:29:46 -05:00
|
|
|
}
|
|
|
|
|
2022-12-27 22:14:14 -05:00
|
|
|
type apiAccountResponse struct {
|
2023-05-12 21:47:41 -04:00
|
|
|
Username string `json:"username"`
|
|
|
|
Role string `json:"role,omitempty"`
|
|
|
|
SyncTopic string `json:"sync_topic,omitempty"`
|
|
|
|
Language string `json:"language,omitempty"`
|
|
|
|
Notification *user.NotificationPrefs `json:"notification,omitempty"`
|
|
|
|
Subscriptions []*user.Subscription `json:"subscriptions,omitempty"`
|
|
|
|
Reservations []*apiAccountReservation `json:"reservations,omitempty"`
|
|
|
|
Tokens []*apiAccountTokenResponse `json:"tokens,omitempty"`
|
|
|
|
PhoneNumbers []string `json:"phone_numbers,omitempty"`
|
|
|
|
Tier *apiAccountTier `json:"tier,omitempty"`
|
|
|
|
Limits *apiAccountLimits `json:"limits,omitempty"`
|
|
|
|
Stats *apiAccountStats `json:"stats,omitempty"`
|
|
|
|
Billing *apiAccountBilling `json:"billing,omitempty"`
|
2022-12-14 23:11:22 -05:00
|
|
|
}
|
2022-12-30 14:20:48 -05:00
|
|
|
|
2023-01-12 12:04:18 -05:00
|
|
|
type apiAccountReservationRequest struct {
|
2022-12-31 09:31:46 -05:00
|
|
|
Topic string `json:"topic"`
|
|
|
|
Everyone string `json:"everyone"`
|
2022-12-30 14:20:48 -05:00
|
|
|
}
|
2023-01-04 20:34:22 -05:00
|
|
|
|
|
|
|
type apiConfigResponse struct {
|
2023-01-10 22:51:51 -05:00
|
|
|
BaseURL string `json:"base_url"`
|
|
|
|
AppRoot string `json:"app_root"`
|
|
|
|
EnableLogin bool `json:"enable_login"`
|
|
|
|
EnableSignup bool `json:"enable_signup"`
|
|
|
|
EnablePayments bool `json:"enable_payments"`
|
2023-05-07 22:28:07 -04:00
|
|
|
EnableCalls bool `json:"enable_calls"`
|
2023-05-17 10:58:28 -04:00
|
|
|
EnableEmails bool `json:"enable_emails"`
|
2023-01-10 22:51:51 -05:00
|
|
|
EnableReservations bool `json:"enable_reservations"`
|
2023-02-28 14:38:31 -05:00
|
|
|
BillingContact string `json:"billing_contact"`
|
2023-01-10 22:51:51 -05:00
|
|
|
DisallowedTopics []string `json:"disallowed_topics"`
|
2023-01-04 20:34:22 -05:00
|
|
|
}
|
2023-01-14 06:43:44 -05:00
|
|
|
|
2023-02-21 22:44:30 -05:00
|
|
|
type apiAccountBillingPrices struct {
|
|
|
|
Month int64 `json:"month"`
|
|
|
|
Year int64 `json:"year"`
|
|
|
|
}
|
|
|
|
|
2023-01-17 10:09:37 -05:00
|
|
|
type apiAccountBillingTier struct {
|
2023-02-21 22:44:30 -05:00
|
|
|
Code string `json:"code,omitempty"`
|
|
|
|
Name string `json:"name,omitempty"`
|
|
|
|
Prices *apiAccountBillingPrices `json:"prices,omitempty"`
|
|
|
|
Limits *apiAccountLimits `json:"limits"`
|
2023-01-14 06:43:44 -05:00
|
|
|
}
|
|
|
|
|
2023-01-17 10:09:37 -05:00
|
|
|
type apiAccountBillingSubscriptionCreateResponse struct {
|
2023-01-14 06:43:44 -05:00
|
|
|
RedirectURL string `json:"redirect_url"`
|
|
|
|
}
|
|
|
|
|
2023-01-17 10:09:37 -05:00
|
|
|
type apiAccountBillingSubscriptionChangeRequest struct {
|
2023-02-21 22:44:30 -05:00
|
|
|
Tier string `json:"tier"`
|
|
|
|
Interval string `json:"interval"`
|
2023-01-17 10:09:37 -05:00
|
|
|
}
|
|
|
|
|
2023-01-14 06:43:44 -05:00
|
|
|
type apiAccountBillingPortalRedirectResponse struct {
|
|
|
|
RedirectURL string `json:"redirect_url"`
|
|
|
|
}
|
2023-01-16 16:35:37 -05:00
|
|
|
|
|
|
|
type apiAccountSyncTopicResponse struct {
|
|
|
|
Event string `json:"event"`
|
|
|
|
}
|
2023-01-17 10:09:37 -05:00
|
|
|
|
|
|
|
type apiSuccessResponse struct {
|
|
|
|
Success bool `json:"success"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func newSuccessResponse() *apiSuccessResponse {
|
|
|
|
return &apiSuccessResponse{
|
|
|
|
Success: true,
|
|
|
|
}
|
|
|
|
}
|
2023-01-18 15:50:06 -05:00
|
|
|
|
|
|
|
type apiStripeSubscriptionUpdatedEvent struct {
|
|
|
|
ID string `json:"id"`
|
|
|
|
Customer string `json:"customer"`
|
|
|
|
Status string `json:"status"`
|
|
|
|
CurrentPeriodEnd int64 `json:"current_period_end"`
|
|
|
|
CancelAt int64 `json:"cancel_at"`
|
|
|
|
Items *struct {
|
|
|
|
Data []*struct {
|
|
|
|
Price *struct {
|
2023-02-21 22:44:30 -05:00
|
|
|
ID string `json:"id"`
|
|
|
|
Recurring *struct {
|
|
|
|
Interval string `json:"interval"`
|
|
|
|
} `json:"recurring"`
|
2023-01-18 15:50:06 -05:00
|
|
|
} `json:"price"`
|
|
|
|
} `json:"data"`
|
|
|
|
} `json:"items"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type apiStripeSubscriptionDeletedEvent struct {
|
2023-01-22 22:21:30 -05:00
|
|
|
ID string `json:"id"`
|
2023-01-18 15:50:06 -05:00
|
|
|
Customer string `json:"customer"`
|
|
|
|
}
|