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 }