1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
package ntfy
import (
"errors"
"fmt"
"net/url"
"strings"
"github.com/nicholas-fedor/shoutrrr/pkg/format"
"github.com/nicholas-fedor/shoutrrr/pkg/types"
)
// Scheme is the identifying part of this service's configuration URL.
const (
Scheme = "ntfy"
)
// ErrTopicRequired indicates that the topic is missing from the config URL.
var ErrTopicRequired = errors.New("topic is required")
// Config holds the configuration for the Ntfy service.
type Config struct {
Title string `default:"" desc:"Message title" key:"title"`
Host string `default:"ntfy.sh" desc:"Server hostname and port" url:"host"`
Topic string ` desc:"Target topic name" url:"path" required:""`
Password string ` desc:"Auth password" url:"password" optional:""`
Username string ` desc:"Auth username" url:"user" optional:""`
Scheme string `default:"https" desc:"Server protocol, http or https" key:"scheme"`
Tags []string ` desc:"List of tags that may or not map to emojis" key:"tags" optional:""`
Priority priority `default:"default" desc:"Message priority with 1=min, 3=default and 5=max" key:"priority"`
Actions []string ` desc:"Custom user action buttons for notifications, see https://docs.ntfy.sh/publish/#action-buttons" key:"actions" optional:"" sep:";"`
Click string ` desc:"Website opened when notification is clicked" key:"click" optional:""`
Attach string ` desc:"URL of an attachment, see attach via URL" key:"attach" optional:""`
Filename string ` desc:"File name of the attachment" key:"filename" optional:""`
Delay string ` desc:"Timestamp or duration for delayed delivery, see https://docs.ntfy.sh/publish/#scheduled-delivery" key:"delay,at,in" optional:""`
Email string ` desc:"E-mail address for e-mail notifications" key:"email" optional:""`
Icon string ` desc:"URL to use as notification icon" key:"icon" optional:""`
Cache bool `default:"yes" desc:"Cache messages" key:"cache"`
Firebase bool `default:"yes" desc:"Send to firebase" key:"firebase"`
DisableTLSVerification bool `default:"no" desc:"Disable TLS certificate verification" key:"disabletls"`
}
// Enums returns the fields that use an EnumFormatter for their values.
func (*Config) Enums() map[string]types.EnumFormatter {
return map[string]types.EnumFormatter{
"Priority": Priority.Enum,
}
}
// GetURL returns a URL representation of the Config's current field values.
func (config *Config) GetURL() *url.URL {
resolver := format.NewPropKeyResolver(config)
return config.getURL(&resolver)
}
// SetURL updates the Config from a URL representation of its field values.
func (config *Config) SetURL(url *url.URL) error {
resolver := format.NewPropKeyResolver(config)
return config.setURL(&resolver, url)
}
// GetAPIURL constructs the API URL for the Ntfy service based on the configuration.
func (config *Config) GetAPIURL() string {
path := config.Topic
if !strings.HasPrefix(config.Topic, "/") {
path = "/" + path
}
apiURL := url.URL{
Scheme: config.Scheme,
Host: config.Host,
Path: path,
}
return apiURL.String()
}
// getURL constructs a URL from the Config's fields using the provided resolver.
func (config *Config) getURL(resolver types.ConfigQueryResolver) *url.URL {
path := config.Topic
if !strings.HasPrefix(config.Topic, "/") {
path = "/" + path
}
result := &url.URL{
Host: config.Host,
Scheme: Scheme,
ForceQuery: true,
Path: path,
RawQuery: format.BuildQuery(resolver),
}
if config.Username != "" {
if config.Password != "" {
result.User = url.UserPassword(config.Username, config.Password)
} else {
result.User = url.User(config.Username)
}
}
return result
}
// setURL updates the Config from a URL using the provided resolver.
func (config *Config) setURL(resolver types.ConfigQueryResolver, url *url.URL) error {
if url.User != nil {
password, _ := url.User.Password()
config.Password = password
config.Username = url.User.Username()
} else {
config.Password = ""
config.Username = ""
}
config.Host = url.Host
config.Topic = strings.TrimPrefix(url.Path, "/")
url.RawQuery = strings.ReplaceAll(url.RawQuery, ";", "%3b")
for key, vals := range url.Query() {
if err := resolver.Set(key, vals[0]); err != nil {
return fmt.Errorf("setting query parameter %q to %q: %w", key, vals[0], err)
}
}
if url.String() != "ntfy://dummy@dummy.com" {
if config.Topic == "" {
return ErrTopicRequired
}
}
return nil
}
// QueryFields returns the list of query parameter names for the Config struct.
func (config *Config) QueryFields() []string {
return format.GetConfigQueryResolver(config).QueryFields()
}
|