File: generic_config.go

package info (click to toggle)
golang-github-nicholas-fedor-shoutrrr 0.12.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,680 kB
  • sloc: sh: 74; makefile: 58
file content (154 lines) | stat: -rw-r--r-- 5,330 bytes parent folder | download
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
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
	// The webhook URL to send notifications to
	webhookURL *url.URL
	// Custom HTTP headers to include in requests
	headers map[string]string
	// Additional data to include in JSON payloads
	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) {
	// Initialize empty config
	config := &Config{}
	// Create property key resolver
	pkr := format.NewPropKeyResolver(config)
	// Set default properties from struct tags
	_ = pkr.SetDefaultProps(config)

	return config, pkr
}

// ConfigFromWebhookURL constructs a Config from a parsed webhook URL.
func ConfigFromWebhookURL(webhookURL url.URL) (*Config, format.PropKeyResolver, error) {
	// Get default config and resolver
	config, pkr := DefaultConfig()

	// Extract query parameters
	webhookQuery := webhookURL.Query()
	// Extract custom headers and extra data
	headers, extraData := stripCustomQueryValues(webhookQuery)

	// Set config properties from remaining query params
	_, err := format.SetConfigPropsFromQuery(&pkr, webhookQuery)
	if err != nil {
		return nil, pkr, fmt.Errorf("setting config properties from query: %w", err)
	}

	// Update URL with modified query
	webhookURL.RawQuery = webhookQuery.Encode()
	// Assign webhook URL
	config.webhookURL = &webhookURL
	// Assign extracted headers
	config.headers = headers
	// Assign extracted extra data
	config.extraData = extraData
	// Set TLS based on scheme
	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 {
	// Copy the URL to modify
	webhookURL := *config.webhookURL
	// Set default HTTPS scheme
	webhookURL.Scheme = DefaultWebhookScheme

	if config.DisableTLS {
		// Use HTTP if TLS is disabled
		webhookURL.Scheme = "http"
	}

	return &webhookURL
}

// GetURL generates a URL from the current configuration values.
func (config *Config) GetURL() *url.URL {
	// Create resolver for this config
	resolver := format.NewPropKeyResolver(config)

	// Generate URL using resolver
	return config.getURL(&resolver)
}

// SetURL updates the configuration from a service URL.
func (config *Config) SetURL(serviceURL *url.URL) error {
	// Create resolver for this config
	resolver := format.NewPropKeyResolver(config)

	// Parse and set URL
	return config.setURL(&resolver, serviceURL)
}

// getURL generates a service URL from the configuration using the provided resolver.
func (config *Config) getURL(resolver types.ConfigQueryResolver) *url.URL {
	// Copy webhook URL
	serviceURL := *config.webhookURL
	// Get existing query params
	webhookQuery := config.webhookURL.Query()
	// Build query with config fields
	serviceQuery := format.BuildQueryWithCustomFields(resolver, webhookQuery)
	// Add custom headers and extra data
	appendCustomQueryValues(serviceQuery, config.headers, config.extraData)
	// Encode the query
	serviceURL.RawQuery = serviceQuery.Encode()
	// Set service scheme
	serviceURL.Scheme = Scheme

	return &serviceURL
}

// setURL updates the configuration from a service URL using the provided resolver.
func (config *Config) setURL(resolver types.ConfigQueryResolver, serviceURL *url.URL) error {
	// Copy service URL
	webhookURL := *serviceURL
	// Extract query parameters
	serviceQuery := serviceURL.Query()
	// Extract custom headers and extra data
	headers, extraData := stripCustomQueryValues(serviceQuery)

	// Set config properties from query
	customQuery, err := format.SetConfigPropsFromQuery(resolver, serviceQuery)
	if err != nil {
		return fmt.Errorf("setting config properties from service URL query: %w", err)
	}

	// Update URL with remaining query
	webhookURL.RawQuery = customQuery.Encode()
	// Assign webhook URL
	config.webhookURL = &webhookURL
	// Assign extracted headers
	config.headers = headers
	// Assign extracted extra data
	config.extraData = extraData

	return nil
}