183 lines
3.9 KiB
Go
Executable File
183 lines
3.9 KiB
Go
Executable File
package m3u
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"net/url"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
// MakeInterfaceFromM3U :
|
|
func MakeInterfaceFromM3U(byteStream []byte) (allChannels []interface{}, err error) {
|
|
|
|
var content = string(byteStream)
|
|
var channelName string
|
|
var uuids []string
|
|
|
|
var parseMetaData = func(channel string) (stream map[string]string) {
|
|
|
|
stream = make(map[string]string)
|
|
var exceptForParameter = `[a-z-A-Z=]*(".*?")`
|
|
var exceptForChannelName = `,([^\n]*|,[^\r]*)`
|
|
|
|
var lines = strings.Split(strings.Replace(channel, "\r\n", "\n", -1), "\n")
|
|
|
|
// Zeilen mit # und leerer Zeilen entfernen
|
|
for i := len(lines) - 1; i >= 0; i-- {
|
|
|
|
if len(lines[i]) == 0 || lines[i][0:1] == "#" {
|
|
lines = append(lines[:i], lines[i+1:]...)
|
|
}
|
|
|
|
}
|
|
|
|
if len(lines) >= 2 {
|
|
|
|
for _, line := range lines {
|
|
|
|
_, err := url.ParseRequestURI(line)
|
|
|
|
switch err {
|
|
|
|
case nil:
|
|
stream["url"] = strings.Trim(line, "\r\n")
|
|
|
|
default:
|
|
|
|
var value string
|
|
// Alle Parameter parsen
|
|
var p = regexp.MustCompile(exceptForParameter)
|
|
var streamParameter = p.FindAllString(line, -1)
|
|
|
|
for _, p := range streamParameter {
|
|
|
|
line = strings.Replace(line, p, "", 1)
|
|
|
|
p = strings.Replace(p, `"`, "", -1)
|
|
var parameter = strings.SplitN(p, "=", 2)
|
|
|
|
if len(parameter) == 2 {
|
|
|
|
// TVG Key als Kleinbuchstaben speichern
|
|
switch strings.Contains(parameter[0], "tvg") {
|
|
|
|
case true:
|
|
stream[strings.ToLower(parameter[0])] = parameter[1]
|
|
case false:
|
|
stream[parameter[0]] = parameter[1]
|
|
|
|
}
|
|
|
|
// URL's nicht an die Filterfunktion übergeben
|
|
if !strings.Contains(parameter[1], "://") && len(parameter[1]) > 0 {
|
|
value = value + parameter[1] + " "
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Kanalnamen parsen
|
|
n := regexp.MustCompile(exceptForChannelName)
|
|
var name = n.FindAllString(line, 1)
|
|
|
|
if len(name) > 0 {
|
|
channelName = name[0]
|
|
channelName = strings.Replace(channelName, `,`, "", 1)
|
|
channelName = strings.TrimRight(channelName, "\r\n")
|
|
channelName = strings.TrimRight(channelName, " ")
|
|
}
|
|
|
|
if len(channelName) == 0 {
|
|
|
|
if v, ok := stream["tvg-name"]; ok {
|
|
channelName = v
|
|
}
|
|
|
|
}
|
|
|
|
channelName = strings.TrimRight(channelName, " ")
|
|
|
|
// Kanäle ohne Namen werden augelassen
|
|
if len(channelName) == 0 {
|
|
return
|
|
}
|
|
|
|
stream["name"] = channelName
|
|
value = value + channelName
|
|
|
|
stream["_values"] = value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Nach eindeutiger ID im Stream suchen
|
|
for key, value := range stream {
|
|
|
|
if !strings.Contains(strings.ToLower(key), "tvg-id") {
|
|
|
|
if strings.Contains(strings.ToLower(key), "id") {
|
|
|
|
if indexOfString(value, uuids) != -1 {
|
|
log.Println(fmt.Sprintf("Channel: %s - %s = %s ", stream["name"], key, value))
|
|
break
|
|
}
|
|
|
|
uuids = append(uuids, value)
|
|
|
|
stream["_uuid.key"] = key
|
|
stream["_uuid.value"] = value
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
//fmt.Println(content)
|
|
|
|
if strings.Contains(content, "#EXTM3U") {
|
|
|
|
var channels = strings.Split(content, "#EXTINF")
|
|
|
|
channels = append(channels[:0], channels[1:]...)
|
|
|
|
for _, channel := range channels {
|
|
|
|
var stream = parseMetaData(channel)
|
|
|
|
if len(stream) > 0 && stream != nil {
|
|
allChannels = append(allChannels, stream)
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
err = errors.New("No valid m3u file")
|
|
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func indexOfString(element string, data []string) int {
|
|
|
|
for k, v := range data {
|
|
if element == v {
|
|
return k
|
|
}
|
|
}
|
|
|
|
return -1
|
|
}
|