-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathchannels.go
129 lines (112 loc) · 2.95 KB
/
channels.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
120
121
122
123
124
125
126
127
128
129
package config
import (
"encoding/json"
"log"
"os"
"errors"
"sync"
"github.com/fsnotify/fsnotify"
m3uparser "github.com/pawanpaudel93/go-m3u-parser/m3uparser"
)
type ProxyConfig struct {
Host string `json:"host"`
Username string `json:"username"`
Password string `json:"password"`
}
type Channel struct {
Name string `json:"name"`
URL string `json:"url"`
ProxyConfig *ProxyConfig `json:"proxy"`
DisableTranscode bool `json:"disableTranscode"`
// UserAgent is a custom UA string that will be used by FFMPEG to make requests to the stream URL.
UserAgent *string `json:"userAgent,omitempty"`
Icon *string `json:"icon,omitempty"`
}
var (
Channels []Channel
mu sync.Mutex
)
func LoadChannelsFromPl(location string) error {
var userAgent = os.Getenv("UA")
if len(userAgent) == 0 {
userAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}
parser := m3uparser.M3uParser{UserAgent: userAgent, Timeout: 60}
parser.ParseM3u(location,true,true)
streams := parser.GetStreamsSlice()
if len(streams) > 0 {
for _, st := range streams {
ch := Channel{Name: st["title"].(string), URL: st["url"].(string), UserAgent: &userAgent}
Channels = append(Channels,ch)
}
if len(Channels) > 0 {
return nil
}
}
return errors.New("No streams in playlist")
}
func WatchChannelsFile() {
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()
err = watcher.Add("channels.json")
if err != nil {
log.Fatal(err)
}
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
if event.Has(fsnotify.Write) {
log.Println("Detected change in channels.json, reloading channels")
err := LoadChannels()
if err != nil {
log.Printf("Error reloading channels: %s\n", err)
}
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Printf("Watcher error: %s\n", err)
}
}
}
func LoadChannels() error {
file, err := os.Open("channels.json")
if err != nil {
return err
}
defer file.Close()
var channels []Channel
decoder := json.NewDecoder(file)
err = decoder.Decode(&channels)
if err != nil {
return err
}
mu.Lock()
Channels = channels
mu.Unlock()
log.Println("Channels reloaded successfully")
return nil
}
func init() {
var playlist = os.Getenv("PLAYLIST")
if len(playlist) > 0 {
err := LoadChannelsFromPl(playlist)
if err == nil {
return
} else {
log.Printf("Provided m3u playlist error: %s\n",err)
}
}
err := LoadChannels()
if err != nil {
log.Fatal(err)
}
go WatchChannelsFile()
}