Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
041b32e1df
|
|||
|
e98d923ce5
|
|||
|
01ddf25ed5
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,5 +9,6 @@ output/
|
|||||||
*.m3u8
|
*.m3u8
|
||||||
*.json
|
*.json
|
||||||
*.ini
|
*.ini
|
||||||
|
iptvc
|
||||||
|
|
||||||
!/**/*.gitkeep
|
!/**/*.gitkeep
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
const VERSION = "1.0.3"
|
const VERSION = "1.0.4"
|
||||||
|
|
||||||
// Arguments описывает аргументы командной строки
|
// Arguments описывает аргументы командной строки
|
||||||
type Arguments struct {
|
type Arguments struct {
|
||||||
|
|||||||
@@ -217,7 +217,6 @@ func CheckChannels(pls playlist.Playlist) playlist.Playlist {
|
|||||||
|
|
||||||
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||||
req, err := http.NewRequest("GET", tvChannel.URL, nil)
|
req, err := http.NewRequest("GET", tvChannel.URL, nil)
|
||||||
tvChannel.CheckedAt = time.Now().Unix()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
data := errorData{tvChannel: tvChannel, err: err}
|
data := errorData{tvChannel: tvChannel, err: err}
|
||||||
chError <- data
|
chError <- data
|
||||||
@@ -226,7 +225,9 @@ func CheckChannels(pls playlist.Playlist) playlist.Playlist {
|
|||||||
|
|
||||||
//TODO user-agent
|
//TODO user-agent
|
||||||
req.Header.Set("User-Agent", "Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer")
|
req.Header.Set("User-Agent", "Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer")
|
||||||
|
req.Header.Add("Range", "bytes=0-1023") // 1 Kb, but sometimes servers ignore it
|
||||||
resp, err := httpClient.Do(req)
|
resp, err := httpClient.Do(req)
|
||||||
|
tvChannel.CheckedAt = time.Now().Unix()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
data := errorData{tvChannel: tvChannel, err: err}
|
data := errorData{tvChannel: tvChannel, err: err}
|
||||||
chError <- data
|
chError <- data
|
||||||
@@ -236,7 +237,8 @@ func CheckChannels(pls playlist.Playlist) playlist.Playlist {
|
|||||||
tvChannel.Status = resp.StatusCode
|
tvChannel.Status = resp.StatusCode
|
||||||
tvChannel.IsOnline = tvChannel.Status < http.StatusBadRequest
|
tvChannel.IsOnline = tvChannel.Status < http.StatusBadRequest
|
||||||
tvChannel.ContentType = resp.Header.Get("Content-Type")
|
tvChannel.ContentType = resp.Header.Get("Content-Type")
|
||||||
bodyBytes, _ := io.ReadAll(resp.Body)
|
chunk := io.LimitReader(resp.Body, 1024) // just for sure
|
||||||
|
bodyBytes, _ := io.ReadAll(chunk)
|
||||||
bodyString := string(bodyBytes)
|
bodyString := string(bodyBytes)
|
||||||
_ = resp.Body.Close()
|
_ = resp.Body.Close()
|
||||||
contentType := http.DetectContentType(bodyBytes)
|
contentType := http.DetectContentType(bodyBytes)
|
||||||
@@ -246,7 +248,9 @@ func CheckChannels(pls playlist.Playlist) playlist.Playlist {
|
|||||||
|
|
||||||
isContentCorrect := isContentBinary ||
|
isContentCorrect := isContentBinary ||
|
||||||
strings.Contains(bodyString, "#EXTM3U") ||
|
strings.Contains(bodyString, "#EXTM3U") ||
|
||||||
strings.Contains(bodyString, "<SegmentTemplate")
|
strings.Contains(bodyString, "<MPD ") ||
|
||||||
|
strings.Contains(bodyString, "<SegmentTemplate ") ||
|
||||||
|
strings.Contains(bodyString, "<AdaptationSet ")
|
||||||
|
|
||||||
if tvChannel.Status >= http.StatusBadRequest || !isContentCorrect {
|
if tvChannel.Status >= http.StatusBadRequest || !isContentCorrect {
|
||||||
tvChannel.Error = bodyString
|
tvChannel.Error = bodyString
|
||||||
@@ -254,12 +258,6 @@ func CheckChannels(pls playlist.Playlist) playlist.Playlist {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if isContentBinary {
|
|
||||||
tvChannel.Content = "binary"
|
|
||||||
} else {
|
|
||||||
tvChannel.Content = bodyString
|
|
||||||
}
|
|
||||||
|
|
||||||
chOnline <- tvChannel
|
chOnline <- tvChannel
|
||||||
return
|
return
|
||||||
}(tvChannel)
|
}(tvChannel)
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ type Channel struct {
|
|||||||
Status int `json:"status"` // Код статуса HTTP
|
Status int `json:"status"` // Код статуса HTTP
|
||||||
IsOnline bool `json:"isOnline"` // Признак доступности канала (при Status < 400)
|
IsOnline bool `json:"isOnline"` // Признак доступности канала (при Status < 400)
|
||||||
Error string `json:"error"` // Текст ошибки (при Status >= 400)
|
Error string `json:"error"` // Текст ошибки (при Status >= 400)
|
||||||
Content string `json:"content"` // Тело ответа (формат m3u, либо маскированные бинарные данные, либо пусто)
|
|
||||||
ContentType string `json:"contentType"` // MIME-тип тела ответа
|
ContentType string `json:"contentType"` // MIME-тип тела ответа
|
||||||
Tags []string `json:"tags"` // Список тегов канала
|
Tags []string `json:"tags"` // Список тегов канала
|
||||||
CheckedAt int64 `json:"checkedAt"` // Время проверки в формате UNIX timestamp
|
CheckedAt int64 `json:"checkedAt"` // Время проверки в формате UNIX timestamp
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
// TagBlock описывает объект с набором тегов, который подходит для каналов по регулярному выражению
|
// TagBlock описывает объект с набором тегов, который подходит для каналов по регулярному выражению
|
||||||
type TagBlock struct {
|
type TagBlock struct {
|
||||||
TvgId string `json:"tvg-id"`
|
TvgId string `json:"tvg-id"`
|
||||||
|
TvgName string `json:"tvg-name"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Tags []string `json:"tags"`
|
Tags []string `json:"tags"`
|
||||||
}
|
}
|
||||||
@@ -42,6 +43,18 @@ func (block *TagBlock) GetTags(ch playlist.Channel) []string {
|
|||||||
if checkString == "" {
|
if checkString == "" {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
} else if block.TvgName != "" {
|
||||||
|
regex, err = regexp.Compile(block.TvgName)
|
||||||
|
if err != nil {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
if _, ok := ch.Attributes["tvg-name"]; !ok {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
checkString = ch.Attributes["tvg-name"]
|
||||||
|
if checkString == "" {
|
||||||
|
return result
|
||||||
|
}
|
||||||
} else if block.Title != "" {
|
} else if block.Title != "" {
|
||||||
regex, err = regexp.Compile(block.Title)
|
regex, err = regexp.Compile(block.Title)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user