Update EPG model and parsing mechanisms

This commit revises the EPG model's struct tag to include mapstructure along with json. It also includes an implementation switch from goquery and otto to mapstructure for data parsing. This removes dependencies on PuerkitoBio/goquery and robertkrimen/otto. The commit also includes some minor code refactors for the more efficient handling of EPG data along with a version bump to 0.0.3.
This commit is contained in:
Senis 2024-01-05 23:25:33 +08:00
parent 8b3020e086
commit fe53df21b7
No known key found for this signature in database
9 changed files with 72 additions and 103 deletions

View File

@ -4,6 +4,7 @@ RUN go env -w GOPROXY=https://goproxy.cn,direct
WORKDIR /build
COPY . .
RUN go mod tidy
RUN go mod download
RUN go build -ldflags="-s -w" -trimpath -v -o /app/main main.go

View File

@ -1,33 +1,16 @@
package channel
import (
"bytes"
"regexp"
"strconv"
"strings"
"github.com/PuerkitoBio/goquery"
"github.com/mitchellh/mapstructure"
)
func BytesToChannels(resp []byte) ([]Channel, error) {
doc, err := goquery.NewDocumentFromReader(bytes.NewBuffer(resp))
if err != nil {
return nil, err
}
var data []string
re := regexp.MustCompile(`\((.*?)\)`) // filter strings in ()
re1 := regexp.MustCompile(`'([^']*)'`) // filter strings in ''
// use the goquery document...
_ = doc.Find("script:contains(ChannelName)").Each(func(i int, selection *goquery.Selection) {
matches := re.FindStringSubmatch(selection.Text())
if len(matches) > 1 {
matches2 := re1.FindAllStringSubmatch(matches[1], -1)
data = append(data, matches2[1][1]) // 用1而非0作为索引
}
})
re := regexp.MustCompile(`(?s)ChannelID="\d*".*?ChannelFECPort="\d*"`)
data := re.FindAllString(string(resp), -1)
var channelMaps []map[string]any
re2 := regexp.MustCompile(`画中画|单音轨`)
@ -36,7 +19,8 @@ func BytesToChannels(resp []byte) ([]Channel, error) {
continue
}
res := strings.Split(data[i], ",")
d := data[i]
res := strings.Split(d, ",")
kvMap := make(map[string]any)
for ii := range res {
kvs := strings.SplitN(res[ii], "=", 2)

View File

@ -1,87 +1,87 @@
package epg
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"regexp"
"time"
"github.com/PuerkitoBio/goquery"
"github.com/robertkrimen/otto"
"github.com/mitchellh/mapstructure"
)
func byteToEpg(resp []byte) ([]Epg, error) {
doc, err := goquery.NewDocumentFromReader(bytes.NewReader(resp))
if err != nil {
func BytesToAllEPGs(resp []byte) ([]Epg, error) {
re := regexp.MustCompile(`(?s)\[.*]`)
b := re.FindSubmatch(resp)
if b == nil {
return nil, errors.New("not found valid data")
}
var es []any
if err := json.Unmarshal(b[0], &es); err != nil {
return nil, err
}
vm := otto.New()
if err := vm.Set("parent", map[string]any{}); err != nil {
return nil, err
if len(es) != 2 {
return nil, errors.New("the length of data must equal 2")
}
if _, err := vm.Run(doc.Find("script").Text()); err != nil {
return nil, err
}
objParent, _ := vm.Object("parent")
obj, _ := objParent.Get("jsonBackLookStr")
ex, _ := obj.Export()
val, ok := ex.([]any)
if !ok {
return nil, fmt.Errorf("invalid type of object")
}
if len(val) < 2 {
return nil, errors.New("invalid length of object")
}
es := val[1]
bb, _ := json.Marshal(es)
var data [][]Epg
if err := json.Unmarshal(bb, &data); err != nil {
if err := mapstructure.Decode(es[1], &data); err != nil {
return nil, err
}
var epgs []Epg
for i := range data {
epgsDay := data[i]
for ii := range epgsDay {
epgs = append(epgs, epgsDay[ii])
e := data[i]
for ii := range e {
epgs = append(epgs, e[ii])
}
}
return epgs, nil
}
func GetEPGs(resp []byte) ([]Epg, error) {
epgs, err := byteToEpg(resp)
func BytesToValidEPGs(resp []byte) ([]Epg, error) {
allEPGs, err := BytesToAllEPGs(resp)
if err != nil {
return nil, err
}
var validEpgs []Epg
var epgs []Epg
tz := time.FixedZone("CST", 3600*8)
for i := range epgs {
endTime, err := time.ParseInLocation("20060102150405", epgs[i].EndTimeFormat, tz) // time format: 20231228001700
for i := range allEPGs {
epg, err := filterEPGs(&allEPGs[i], tz)
if err != nil {
continue
}
beginTime, err := time.ParseInLocation("20060102150405", epgs[i].BeginTimeFormat, tz) // time format: 20231228001700
if err != nil {
continue
}
if beginTime.Sub(endTime) > 0 {
endTime = beginTime
}
if time.Since(endTime) < time.Hour {
validEpgs = append(validEpgs, epgs[i])
}
epgs = append(epgs, *epg)
}
return validEpgs, nil
return epgs, nil
}
func filterEPGs(e *Epg, tz *time.Location) (*Epg, error) {
// time format: 20231228001700
endTime, err := time.ParseInLocation("20060102150405", e.EndTimeFormat, tz)
if err != nil {
return nil, err
}
beginTime, err := time.ParseInLocation("20060102150405", e.BeginTimeFormat, tz)
if err != nil {
return nil, err
}
if beginTime.Sub(endTime) > 0 {
endTime = beginTime
}
if time.Since(endTime) > time.Hour {
return nil, fmt.Errorf("not a valid EPG: %s [%s] -> %s", e.ChannelId, e.ProgramName, e.EndTimeFormat)
}
return e, nil
}

View File

@ -15,19 +15,21 @@ func TestGetEpg(t *testing.T) {
if err != nil {
t.Error(err)
}
es, err := byteToEpg(resp)
es, err := BytesToAllEPGs(resp)
if err != nil {
t.Error(err)
}
for i := range es {
t.Log(es[i])
}
t.Logf("Total EPGs: %d", len(es))
validEs, err := GetEPGs(resp)
validEs, err := BytesToValidEPGs(resp)
if err != nil {
t.Error(err)
}
for i := range validEs {
t.Log(validEs[i])
}
t.Logf("Valid EPGs: %d", len(validEs))
}

View File

@ -1,13 +1,13 @@
package epg
type Epg struct {
BeginTimeFormat string `json:"beginTimeFormat"`
ChannelId string `json:"channelId"`
ContentId string `json:"contentId"`
EndTime string `json:"endTime"`
EndTimeFormat string `json:"endTimeFormat"`
Index string `json:"index"`
IsPlayable string `json:"isPlayable"`
ProgramName string `json:"programName"`
StartTime string `json:"startTime"`
BeginTimeFormat string `json:"beginTimeFormat" mapstructure:"beginTimeFormat"`
ChannelId string `json:"channelId" mapstructure:"channelId"`
ContentId string `json:"contentId" mapstructure:"contentId"`
EndTime string `json:"endTime" mapstructure:"endTime"`
EndTimeFormat string `json:"endTimeFormat" mapstructure:"endTimeFormat"`
Index string `json:"index" mapstructure:"index"`
IsPlayable string `json:"isPlayable" mapstructure:"isPlayable"`
ProgramName string `json:"programName" mapstructure:"programName"`
StartTime string `json:"startTime" mapstructure:"startTime"`
}

View File

@ -6,7 +6,7 @@ import (
const (
appName = "iptvChannel"
version = "0.0.2"
version = "0.0.3"
desc = "(github.com/thank243/iptvChannel)"
)

View File

@ -121,15 +121,13 @@ func (c *Controller) fetchEPGs() error {
logger.Error(err)
return
}
epgs, err := epg.GetEPGs(resp)
epgs, err := epg.BytesToValidEPGs(resp)
if err != nil {
logger.Error(err)
return
}
if len(epgs) > 0 {
for i := range epgs {
es <- epgs[i]
}
for i := range epgs {
es <- epgs[i]
}
}(i)
}

6
go.mod
View File

@ -3,23 +3,20 @@ module github.com/thank243/iptvChannel
go 1.21
require (
github.com/PuerkitoBio/goquery v1.8.1
github.com/beevik/etree v1.3.0
github.com/go-resty/resty/v2 v2.11.0
github.com/labstack/echo/v4 v4.11.4
github.com/labstack/gommon v0.4.2
github.com/mitchellh/mapstructure v1.5.0
github.com/robertkrimen/otto v0.3.0
github.com/robfig/cron/v3 v3.0.1
github.com/sirupsen/logrus v1.9.3
github.com/spf13/viper v1.18.2
)
require (
github.com/andybalholm/cascadia v1.3.1 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
@ -42,6 +39,5 @@ require (
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

12
go.sum
View File

@ -1,7 +1,3 @@
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
github.com/beevik/etree v1.3.0 h1:hQTc+pylzIKDb23yYprodCWWTt+ojFfUZyzU09a/hmU=
github.com/beevik/etree v1.3.0/go.mod h1:aiPf89g/1k3AShMVAzriilpcE4R/Vuor90y83zVZWFc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -42,8 +38,6 @@ github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdU
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robertkrimen/otto v0.3.0 h1:5RI+8860NSxvXywDY9ddF5HcPw0puRsd8EgbXV0oqRE=
github.com/robertkrimen/otto v0.3.0/go.mod h1:uW9yN1CYflmUQYvAMS0m+ZiNo3dMzRUDQJX0jWbzgxw=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
@ -95,10 +89,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
@ -108,7 +100,6 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -127,7 +118,6 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
@ -147,8 +137,6 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=