-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathconfig.go
119 lines (94 loc) · 2.76 KB
/
config.go
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
package proxytv
import (
"fmt"
"os"
"regexp"
"time"
"github.com/creasty/defaults"
"gopkg.in/yaml.v3"
)
type Filter struct {
Value string `yaml:"filter"`
Type string `yaml:"type"`
regexp *regexp.Regexp // Compiled regular expression
}
// GetRegexp returns the compiled regular expression
func (f *Filter) GetRegexp() *regexp.Regexp {
return f.regexp
}
type Config struct {
LogLevel string `yaml:"logLevel,omitempty" default:"info"`
IPTVUrl string `yaml:"iptvUrl"`
EPGUrl string `yaml:"epgUrl"`
ListenAddress string `yaml:"listenAddress,omitempty" default:":6078"`
ServerAddress string `yaml:"serverAddress"`
UseFFMPEG bool
UseFFMPEGPtr *bool `yaml:"ffmpeg,omitempty" default:"true"`
MaxStreams int `yaml:"maxStreams,omitempty" default:"1"`
RefreshInterval time.Duration
RefreshIntervalStr string `yaml:"refreshInterval,omitempty" default:"12h"`
UserAgent string `yaml:"userAgent,omitempty" default:""`
Filters []*Filter `yaml:"filters"`
}
// LoadConfig reads a YAML config file from the given path and returns a Config pointer.
func LoadConfig(path string) (*Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
config := &Config{}
err = yaml.Unmarshal(data, config)
if err != nil {
return nil, err
}
if err = defaults.Set(config); err != nil {
return nil, err
}
config.UseFFMPEG = *config.UseFFMPEGPtr
config.RefreshInterval, err = time.ParseDuration(config.RefreshIntervalStr)
if err != nil {
return nil, fmt.Errorf("invalid refreshInterval: %w", err)
}
if config.IPTVUrl == "" {
return nil, fmt.Errorf("iptvUrl is required")
}
if config.EPGUrl == "" {
return nil, fmt.Errorf("epgUrl is required")
}
if config.ServerAddress == "" {
return nil, fmt.Errorf("serverAddress is required")
}
re := regexp.MustCompile(`^https?://`)
config.ServerAddress = re.ReplaceAllString(config.ServerAddress, "")
if err := validateFileOrURL(config.IPTVUrl); err != nil {
return nil, fmt.Errorf("invalid iptvUrl: %w", err)
}
if err := validateFileOrURL(config.EPGUrl); err != nil {
return nil, fmt.Errorf("invalid epgUrl: %w", err)
}
if err := config.compileFilterRegexps(); err != nil {
return nil, err
}
return config, nil
}
func (c *Config) compileFilterRegexps() error {
for i, filter := range c.Filters {
re, err := regexp.Compile(filter.Value)
if err != nil {
return fmt.Errorf("invalid regular expression in filter %d: %w", i, err)
}
c.Filters[i].regexp = re
}
return nil
}
func validateFileOrURL(input string) error {
// Check if it's a file
if _, err := os.Stat(input); err == nil {
return nil
}
// Check if it's a URL
if matched, _ := regexp.MatchString(`^https?://`, input); matched {
return nil
}
return fmt.Errorf("not a valid file path or URL")
}