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
|
package generic
import (
"fmt"
"net/url"
"github.com/nicholas-fedor/shoutrrr/pkg/format"
"github.com/nicholas-fedor/shoutrrr/pkg/services/standard"
"github.com/nicholas-fedor/shoutrrr/pkg/types"
)
// Scheme identifies this service in configuration URLs.
const (
Scheme = "generic"
DefaultWebhookScheme = "https"
)
// Config holds settings for the generic notification service.
type Config struct {
standard.EnumlessConfig
webhookURL *url.URL
headers map[string]string
extraData map[string]string
ContentType string `default:"application/json" desc:"The value of the Content-Type header" key:"contenttype"`
DisableTLS bool `default:"No" key:"disabletls"`
Template string ` desc:"The template used for creating the request payload" key:"template" optional:""`
Title string `default:"" key:"title"`
TitleKey string `default:"title" desc:"The key that will be used for the title value" key:"titlekey"`
MessageKey string `default:"message" desc:"The key that will be used for the message value" key:"messagekey"`
RequestMethod string `default:"POST" key:"method"`
}
// DefaultConfig creates a new Config with default values and its associated PropKeyResolver.
func DefaultConfig() (*Config, format.PropKeyResolver) {
config := &Config{}
pkr := format.NewPropKeyResolver(config)
_ = pkr.SetDefaultProps(config)
return config, pkr
}
// ConfigFromWebhookURL constructs a Config from a parsed webhook URL.
func ConfigFromWebhookURL(webhookURL url.URL) (*Config, format.PropKeyResolver, error) {
config, pkr := DefaultConfig()
webhookQuery := webhookURL.Query()
headers, extraData := stripCustomQueryValues(webhookQuery)
escapedQuery := url.Values{}
for key, values := range webhookQuery {
if len(values) > 0 {
escapedQuery.Set(format.EscapeKey(key), values[0])
}
}
_, err := format.SetConfigPropsFromQuery(&pkr, escapedQuery)
if err != nil {
return nil, pkr, fmt.Errorf("setting config properties from query: %w", err)
}
webhookURL.RawQuery = webhookQuery.Encode()
config.webhookURL = &webhookURL
config.headers = headers
config.extraData = extraData
config.DisableTLS = webhookURL.Scheme == "http"
return config, pkr, nil
}
// WebhookURL returns the configured webhook URL, adjusted for TLS settings.
func (config *Config) WebhookURL() *url.URL {
webhookURL := *config.webhookURL
webhookURL.Scheme = DefaultWebhookScheme
if config.DisableTLS {
webhookURL.Scheme = "http" // Truncate to "http" if TLS is disabled
}
return &webhookURL
}
// GetURL generates a URL from the current configuration values.
func (config *Config) GetURL() *url.URL {
resolver := format.NewPropKeyResolver(config)
return config.getURL(&resolver)
}
// SetURL updates the configuration from a service URL.
func (config *Config) SetURL(serviceURL *url.URL) error {
resolver := format.NewPropKeyResolver(config)
return config.setURL(&resolver, serviceURL)
}
func (config *Config) getURL(resolver types.ConfigQueryResolver) *url.URL {
serviceURL := *config.webhookURL
webhookQuery := config.webhookURL.Query()
serviceQuery := format.BuildQueryWithCustomFields(resolver, webhookQuery)
appendCustomQueryValues(serviceQuery, config.headers, config.extraData)
serviceURL.RawQuery = serviceQuery.Encode()
serviceURL.Scheme = Scheme
return &serviceURL
}
func (config *Config) setURL(resolver types.ConfigQueryResolver, serviceURL *url.URL) error {
webhookURL := *serviceURL
serviceQuery := serviceURL.Query()
headers, extraData := stripCustomQueryValues(serviceQuery)
customQuery, err := format.SetConfigPropsFromQuery(resolver, serviceQuery)
if err != nil {
return fmt.Errorf("setting config properties from service URL query: %w", err)
}
webhookURL.RawQuery = customQuery.Encode()
config.webhookURL = &webhookURL
config.headers = headers
config.extraData = extraData
return nil
}
|