wip2
This commit is contained in:
@@ -54,8 +54,10 @@ type Playlist struct {
|
||||
CheckedAt int64 `json:"checkedAt"` // Время проверки в формате UNIX timestamp
|
||||
}
|
||||
|
||||
// tmpChannel хранит временные данные о канале, который обрабатывается в Parse
|
||||
var tmpChannel = Channel{}
|
||||
var (
|
||||
attrRegex = regexp.MustCompile(`(?U)([a-z-]+)="(.*)"`)
|
||||
titleRegex = regexp.MustCompile(`['"]?\s*,\s*(.+)`)
|
||||
)
|
||||
|
||||
// MakeFromFile создаёт экземпляр плейлиста из файла
|
||||
func MakeFromFile(filepath string) (Playlist, error) {
|
||||
@@ -98,8 +100,7 @@ func MakeFromUrl(url string) (Playlist, error) {
|
||||
// parseAttributes парсит атрибуты тегов #EXT*
|
||||
func parseAttributes(line string) map[string]string {
|
||||
result := make(map[string]string)
|
||||
regex := regexp.MustCompile(`(?U)([a-z-]+)="(.*)"`)
|
||||
regexMatches := regex.FindAllStringSubmatch(line, -1)
|
||||
regexMatches := attrRegex.FindAllStringSubmatch(line, -1)
|
||||
for _, match := range regexMatches {
|
||||
result[match[1]] = match[2]
|
||||
}
|
||||
@@ -110,8 +111,7 @@ func parseAttributes(line string) map[string]string {
|
||||
func parseTitle(line string) string {
|
||||
// сначала пытаемся по-доброму: в строке есть тег, могут быть атрибуты,
|
||||
// есть запятая-разделитель, после неё -- название канала (с запятыми или без)
|
||||
regex := regexp.MustCompile(`['"]?\s*,\s*(.+)`)
|
||||
regexMatches := regex.FindAllStringSubmatch(line, -1)
|
||||
regexMatches := titleRegex.FindAllStringSubmatch(line, -1)
|
||||
if len(regexMatches) > 0 && len(regexMatches[0]) >= 2 {
|
||||
return strings.TrimSpace(regexMatches[0][1])
|
||||
}
|
||||
@@ -159,6 +159,7 @@ func (pls *Playlist) ReadFromFs() error {
|
||||
// Parse разбирает плейлист
|
||||
func (pls *Playlist) Parse() Playlist {
|
||||
isChannel := false
|
||||
tmpChannel := Channel{}
|
||||
pls.Attributes = make(map[string]string)
|
||||
pls.Channels = make(map[string]Channel)
|
||||
pls.Groups = make(map[string]Group)
|
||||
|
||||
63
app/playlist/playlist_test.go
Normal file
63
app/playlist/playlist_test.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package playlist
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseAttributes(t *testing.T) {
|
||||
line := `#EXTINF:-1 tvg-id="test" group-title="News",Channel Name`
|
||||
attrs := parseAttributes(line)
|
||||
if attrs["tvg-id"] != "test" {
|
||||
t.Errorf("tvg-id = %q, want %q", attrs["tvg-id"], "test")
|
||||
}
|
||||
if attrs["group-title"] != "News" {
|
||||
t.Errorf("group-title = %q, want %q", attrs["group-title"], "News")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseTitle(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{`#EXTINF:-1,Channel Name`, "Channel Name"},
|
||||
{`#EXTINF:-1 tvg-id="x",Another Channel`, "Another Channel"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.expected, func(t *testing.T) {
|
||||
got := parseTitle(tt.input)
|
||||
if got != tt.expected {
|
||||
t.Errorf("parseTitle(%q) = %q, want %q", tt.input, got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlaylistParse(t *testing.T) {
|
||||
content := `#EXTM3U
|
||||
#EXTINF:-1 tvg-id="1" group-title="News",First Channel
|
||||
http://example.com/1
|
||||
#EXTINF:-1 tvg-id="2",Second Channel
|
||||
http://example.com/2
|
||||
`
|
||||
pls := Playlist{Content: content}
|
||||
result := pls.Parse()
|
||||
|
||||
if len(result.Channels) != 2 {
|
||||
t.Errorf("channels count = %d, want 2", len(result.Channels))
|
||||
}
|
||||
|
||||
if len(result.Groups) != 1 {
|
||||
t.Errorf("groups count = %d, want 1", len(result.Groups))
|
||||
}
|
||||
|
||||
for _, ch := range result.Channels {
|
||||
if ch.URL == "" {
|
||||
t.Error("channel URL is empty")
|
||||
}
|
||||
if ch.Title == "" {
|
||||
t.Error("channel Title is empty")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user