Skip to content

Commit

Permalink
feat(services): migrate services to prop key resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
piksel committed Dec 20, 2020
1 parent 753fb2d commit 15960cf
Show file tree
Hide file tree
Showing 41 changed files with 360 additions and 531 deletions.
15 changes: 14 additions & 1 deletion cli/cmd/generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,20 @@ func Run(cmd *cobra.Command, _ []string) {
os.Exit(1)
}

generator, err := generators.NewGenerator(generatorName)
var generator types.Generator

var generatorFlag = cmd.Flags().Lookup("generator")

if !generatorFlag.Changed {
// try to use the service default generator if one exists
generator, _ = generators.NewGenerator(serviceSchema)
}

if generator != nil {
generatorName = serviceSchema
} else {
generator, err = generators.NewGenerator(generatorName)
}

if err != nil {
fmt.Printf("Error: %s\n", err)
Expand Down
3 changes: 2 additions & 1 deletion cli/cmd/verify/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ func Run(cmd *cobra.Command, _ []string) {
}

configMap, maxKeyLen := format.GetConfigMap(service)
for key, value := range configMap {
for key, _ := range configMap {
value := configMap[key]
pad := strings.Repeat(" ", maxKeyLen-len(key))
_, _ = fmt.Fprintf(color.Output, "%s%s: %s\n", pad, key, value)
}
Expand Down
5 changes: 3 additions & 2 deletions internal/testutils/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package testutils

import (
"github.com/containrrr/shoutrrr/pkg/format"
"net/url"

Ω "github.com/onsi/gomega"
Expand All @@ -10,7 +11,7 @@ import (

// TestConfigGetInvalidQueryValue tests whether the config returns an error when an invalid query value is requested
func TestConfigGetInvalidQueryValue(config types.ServiceConfig) {
value, err := config.Get("invalid query var")
value, err := format.GetConfigQueryResolver(config).Get("invalid query var")
Ω.ExpectWithOffset(1, value).To(Ω.BeEmpty())
Ω.ExpectWithOffset(1, err).To(Ω.HaveOccurred())
}
Expand All @@ -32,6 +33,6 @@ func TestConfigGetEnumsCount(config types.ServiceConfig, expectedCount int) {

// TestConfigGetFieldsCount tests whether the config.QueryFields return the expected amount of fields
func TestConfigGetFieldsCount(config types.ServiceConfig, expectedCount int) {
fields := config.QueryFields()
fields := format.GetConfigQueryResolver(config).QueryFields()
Ω.ExpectWithOffset(1, fields).To(Ω.HaveLen(expectedCount))
}
6 changes: 3 additions & 3 deletions pkg/format/format_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import (
)

// BuildQuery converts the fields of a config object to a delimited query string
func BuildQuery(c types.ServiceConfig) string {
func BuildQuery(cqr types.ConfigQueryResolver) string {
query := ""
fields := c.QueryFields()
format := "%s=%s"
fields := cqr.QueryFields()
for index, key := range fields {
value, _ := c.Get(key)
value, _ := cqr.Get(key)
if index == 1 {
format = "&%s=%s"
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/format/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func GetConfigMap(service types.Service) (map[string]string, int) {

formatter := formatter{
EnumFormatters: config.Enums(),
MaxDepth: 2,
MaxDepth: 10,
}
return formatter.formatStructMap(configType, config, 0)
}
Expand Down Expand Up @@ -95,7 +95,7 @@ func (fmtr *formatter) formatStructMap(structType reflect.Type, structItem inter
fmtr.Errors = append(fmtr.Errors, err)
}
} else if nextDepth < fmtr.MaxDepth {
value, valueLen = fmtr.getFieldValueString(values.Field(i), nextDepth)
value, valueLen = fmtr.getFieldValueString(values.FieldByName(field.Name), nextDepth)
}
} else {
// Since no values was supplied, let's substitute the value with the type
Expand Down
105 changes: 105 additions & 0 deletions pkg/format/prop_key_resolver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package format

import (
"errors"
"fmt"
"github.com/containrrr/shoutrrr/pkg/types"
"reflect"
"sort"
"strings"
)

// KeyPropConfig implements the ServiceConfig interface for services that uses key tags for query props
type PropKeyResolver struct {
confValue reflect.Value
keyFields map[string]FieldInfo
keys []string
}

// BindKeys is called to map config fields to it's tagged query keys
func NewPropKeyResolver(config types.ServiceConfig) PropKeyResolver {

_, fields := GetConfigFormat(config)
keyFields := make(map[string]FieldInfo, len(fields))
keys := make([]string, 0, len(fields))
for _, field := range fields {
key := strings.ToLower(field.Key)
if key != "" {
keys = append(keys, key)
keyFields[key] = field
}
}

sort.Strings(keys)

confValue := reflect.ValueOf(config)
if confValue.Kind() == reflect.Ptr {
confValue = confValue.Elem()
}

return PropKeyResolver{
keyFields: keyFields,
confValue: confValue,
keys: keys,
}
}

// QueryFields returns a list of tagged keys
func (pkr *PropKeyResolver) QueryFields() []string {
return pkr.keys
}

// Get returns the value of a config property tagged with the corresponding key
func (pkr *PropKeyResolver) Get(key string) (string, error) {
if field, found := pkr.keyFields[strings.ToLower(key)]; found {
return GetConfigFieldString(pkr.confValue, field)
}

return "", fmt.Errorf("%v is not a valid config key", key)
}

// Set sets the value of it's bound struct's property, tagged with the corresponding key
func (pkr *PropKeyResolver) Set(key string, value string) error {
return pkr.set(pkr.confValue, key, value)
}

// set sets the value of a target struct tagged with the corresponding key
func (c *PropKeyResolver) set(target reflect.Value, key string, value string) error {
if field, found := c.keyFields[strings.ToLower(key)]; found {
valid, err := SetConfigField(target, field, value)
if !valid && err == nil {
return errors.New("invalid value for type")
}
return err
}

return fmt.Errorf("%v is not a valid config key %v", key, c.keys)
}

// UpdateConfigFromParams mutates the provided config, updating the values from it's corresponding params
func (pkr *PropKeyResolver) UpdateConfigFromParams(config types.ServiceConfig, params *types.Params) error {
if params != nil {
for key, val := range *params {
if err := pkr.set(reflect.ValueOf(config), key, val); err != nil {
return err
}
}
}
return nil
}

func (pkr *PropKeyResolver) Bind(config types.ServiceConfig) PropKeyResolver {
bound := *pkr
bound.confValue = reflect.ValueOf(config)
return bound
}

func GetConfigQueryResolver(config types.ServiceConfig) types.ConfigQueryResolver {
var resolver types.ConfigQueryResolver
var ok bool
if resolver, ok = config.(types.ConfigQueryResolver); !ok {
pkr := NewPropKeyResolver(config)
resolver = &pkr
}
return resolver
}
1 change: 0 additions & 1 deletion pkg/services/discord/discord_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

// Config is the configuration needed to send discord notifications
type Config struct {
standard.QuerylessConfig
standard.EnumlessConfig
Channel string
Token string
Expand Down
1 change: 0 additions & 1 deletion pkg/services/gotify/gotify_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

// Config for use within the gotify plugin
type Config struct {
standard.QuerylessConfig
standard.EnumlessConfig
Token string
Host string
Expand Down
1 change: 0 additions & 1 deletion pkg/services/hangouts/hangouts_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

// Config for use within the Hangouts Chat plugin.
type Config struct {
standard.QuerylessConfig
standard.EnumlessConfig
URL *url.URL
}
Expand Down
18 changes: 14 additions & 4 deletions pkg/services/ifttt/ifttt.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ifttt
import (
"bytes"
"fmt"
"github.com/containrrr/shoutrrr/pkg/format"
"log"
"net/http"
"net/url"
Expand All @@ -19,13 +20,17 @@ const (
type Service struct {
standard.Standard
config *Config
pkr format.PropKeyResolver
}

// Initialize loads ServiceConfig from configURL and sets logger for this Service
func (service *Service) Initialize(configURL *url.URL, logger *log.Logger) error {
service.Logger.SetLogger(logger)
service.config = &Config{}
if err := service.config.SetURL(configURL); err != nil {
service.config = &Config{
UseMessageAsValue: 2,
}
service.pkr = format.NewPropKeyResolver(service.config)
if err := service.config.setURL(&service.pkr, configURL); err != nil {
return err
}

Expand All @@ -34,12 +39,17 @@ func (service *Service) Initialize(configURL *url.URL, logger *log.Logger) error

// Send a notification message to a IFTTT webhook
func (service *Service) Send(message string, params *types.Params) error {
payload, err := createJSONToSend(service.config, message, params)
config := service.config
if err := service.pkr.UpdateConfigFromParams(config, params); err != nil {
return err
}

payload, err := createJSONToSend(config, message, params)
fmt.Printf("%+v", payload)
if err != nil {
return err
}
for _, event := range service.config.Events {
for _, event := range config.Events {
apiURL := service.createAPIURLForEvent(event)
err := doSend(payload, apiURL)
if err != nil {
Expand Down
Loading

0 comments on commit 15960cf

Please sign in to comment.