From d51cc101851deabc456fd9bfc290a9ac99805df3 Mon Sep 17 00:00:00 2001 From: Sjur Fredriksen Date: Tue, 18 Apr 2023 19:50:45 +0200 Subject: [PATCH] some love --- .github/workflows/build.yml | 2 +- .github/workflows/release.yml | 2 +- .gitignore | 1 + Dockerfile | 2 +- Makefile | 13 +++++ README.md | 5 +- build.sh | 2 +- cmd/server.go | 70 ++++++++++++++------------- cmd/transform.go | 7 +-- go.mod | 18 +++++-- go.sum | 47 ++++++++++-------- {xmltv => internal/tv2}/channelmap.go | 4 +- {tv2 => internal/tv2}/client.go | 8 ++- {tv2 => internal/tv2}/types.go | 0 {xmltv => internal/xmltv}/types.go | 0 {xmltv => internal/xmltv}/xmltv.go | 28 ++++++----- main.go | 12 +++-- run.sh | 2 +- tools.go | 10 ++++ 19 files changed, 144 insertions(+), 89 deletions(-) create mode 100644 .gitignore create mode 100644 Makefile rename {xmltv => internal/tv2}/channelmap.go (97%) rename {tv2 => internal/tv2}/client.go (91%) rename {tv2 => internal/tv2}/types.go (100%) rename {xmltv => internal/xmltv}/types.go (100%) rename {xmltv => internal/xmltv}/xmltv.go (90%) create mode 100644 tools.go diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 774bb86..5f66474 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: 1.18.4 + go-version: 1.20.3 - name: Build run: go build -v ./... diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3241e11..5e9f57f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,6 +21,6 @@ jobs: - uses: wangyoucao577/go-release-action@v1.37 with: github_token: ${{ secrets.GITHUB_TOKEN }} - goversion: "https://dl.google.com/go/go1.18.4.linux-amd64.tar.gz" + goversion: "https://dl.google.com/go/go1.20.3.linux-amd64.tar.gz" goos: ${{ matrix.goos }} goarch: ${{ matrix.goarch }} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..485dee6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea diff --git a/Dockerfile b/Dockerfile index e84eab2..832afa0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18.4 as builder +FROM golang:1.20.3 as builder ENV GO111MODULE=on \ CGO_ENABLED=0 \ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f067f0d --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ + +.PHONY: build +build: + docker build . -t xmltv:development + +.PHONY: fmt +fmt: + go run mvdan.cc/gofumpt -w ./ + +.PHONY: fmt +check: + go run honnef.co/go/tools/cmd/staticcheck ./... + go run golang.org/x/vuln/cmd/govulncheck -v ./... diff --git a/README.md b/README.md index ecf827d..e65c4f9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -# xmltv-exporter - +# xmltv Maps EPG data from TV2 to XMLTV and serves it @@ -8,4 +7,4 @@ Demo app can be found at https://xmltv.sjurtf.net Complete list of channels can be found at https://xmltv.sjurtf.net/channels-norway.xml ## Dockerhub -Images can be found at https://hub.docker.com/repository/docker/sjurtf/xmltv-exporter \ No newline at end of file +Images can be found at https://hub.docker.com/repository/docker/sjurtf/xmltv \ No newline at end of file diff --git a/build.sh b/build.sh index cacad27..faec705 100755 --- a/build.sh +++ b/build.sh @@ -1,2 +1,2 @@ #!/bin/sh -docker build . -t xmltv-exporter:development +docker build . -t xmltv:development diff --git a/cmd/server.go b/cmd/server.go index 36cd071..f4f5015 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -7,28 +7,47 @@ import ( "path" "strings" "time" - "xmltv-exporter/xmltv" + + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" + + "xmltv/internal/xmltv" ) -func ServeEpg(port string) { +type Server struct { + producer xmltv.Producer + router chi.Router +} - http.HandleFunc("/channels-norway.xml", ChannelListHandler) - http.HandleFunc("/", ChannelHandler) +func (s *Server) Start() { + s.initRouter() + s.listen() +} - if port == "" { - port = "8080" - } +func (s *Server) initRouter() { + router := chi.NewRouter() - if err := http.ListenAndServe(":"+port, nil); err != nil { - log.Fatal(err) - } + router.Use(middleware.RequestID) + router.Use(middleware.RealIP) + router.Use(middleware.Logger) + router.Use(middleware.Recoverer) + + router.Route("/", func(r chi.Router) { + r.Get("/channels-norway.xml", ChannelListHandler) + r.Get("/{channelId}_{month}-{day}-{year}.xml.gz", ChannelHandler) + }) + + s.router = router } -func ChannelListHandler(w http.ResponseWriter, r *http.Request) { - if !isValid(w, r) { - return +func (s *Server) listen() { + err := http.ListenAndServe(":8080", s.router) + if err != nil { + log.Fatalf("unable to listen: %s", err.Error()) } +} +func ChannelListHandler(w http.ResponseWriter, r *http.Request) { bytes, err := xmltv.GetChannelList() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) @@ -39,10 +58,6 @@ func ChannelListHandler(w http.ResponseWriter, r *http.Request) { } func ChannelHandler(w http.ResponseWriter, r *http.Request) { - if !isValid(w, r) { - return - } - channelId, err := channelId(r) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) @@ -64,7 +79,8 @@ func ChannelHandler(w http.ResponseWriter, r *http.Request) { _, _ = w.Write(bytes) } -/** +/* +* Finds channelId from Path Example input: zebrahd.tv2.no_2021-03-16.xml.gz */ @@ -78,7 +94,8 @@ func channelId(r *http.Request) (string, error) { return parts[0], nil } -/** +/* +* Finds time.Time from Path Example input: zebrahd.tv2.no_2021-03-16.xml.gz */ @@ -95,22 +112,7 @@ func date(r *http.Request) (time.Time, error) { date, err := time.Parse("2006-01-02", parts2[0]) if err != nil { return time.Time{}, fmt.Errorf("date could not be parsed: '%s'", err) - } return date, nil } - -func isValid(w http.ResponseWriter, r *http.Request) bool { - if r.Method != http.MethodGet { - http.Error(w, "Method is not supported", http.StatusMethodNotAllowed) - return false - } - - if len(r.URL.Path) <= 1 { - http.Error(w, "Not found", http.StatusNotFound) - return false - } - - return true -} diff --git a/cmd/transform.go b/cmd/transform.go index 07cb6c3..6926f21 100644 --- a/cmd/transform.go +++ b/cmd/transform.go @@ -3,8 +3,9 @@ package cmd import ( "log" "time" - "xmltv-exporter/tv2" - "xmltv-exporter/xmltv" + + "xmltv/internal/tv2" + "xmltv/internal/xmltv" ) func RefreshWeek() { @@ -20,7 +21,7 @@ func RefreshToday() { } func refresh(start time.Time, days int) { - var t = start + t := start end := time.Now().Add(time.Hour * time.Duration(24*days)) for t.Before(end) { diff --git a/go.mod b/go.mod index 2dfa7dd..9b5ccbb 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,22 @@ -module xmltv-exporter +module xmltv -go 1.17 +go 1.20 -require github.com/go-co-op/gocron v1.19.0 +require ( + github.com/go-co-op/gocron v1.19.0 + golang.org/x/vuln v0.0.0-20230418010118-28ba02ac73db + honnef.co/go/tools v0.4.3 + mvdan.cc/gofumpt v0.5.0 +) require ( + github.com/BurntSushi/toml v1.2.1 // indirect + github.com/go-chi/chi/v5 v5.0.8 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect + golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a // indirect + golang.org/x/mod v0.10.0 // indirect golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.7.0 // indirect + golang.org/x/tools v0.8.0 // indirect ) diff --git a/go.sum b/go.sum index 690cbd4..75447b9 100644 --- a/go.sum +++ b/go.sum @@ -1,30 +1,39 @@ -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= +github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-co-op/gocron v1.19.0 h1:XlPLqNnxnKblmCRLdfcWV1UgbukQaU54QdNeR1jtgak= github.com/go-co-op/gocron v1.19.0/go.mod h1:UqVyvM90I1q/R1qGEX6cBORI6WArLuEgYlbncLMvzRM= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a h1:Jw5wfR+h9mnIYH+OtGT2im5wV1YGGDora5vTv/aa5bE= +golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y= +golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= +golang.org/x/vuln v0.0.0-20230418010118-28ba02ac73db h1:tLxfII6jPR3mfwEMkyOakawu+Lldo9hIA7vliXnDZYg= +golang.org/x/vuln v0.0.0-20230418010118-28ba02ac73db/go.mod h1:64LpnL2PuSMzFYeCmJjYiRbroOUG9aCZYznINnF5PHE= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.4.3 h1:o/n5/K5gXqk8Gozvs2cnL0F2S1/g1vcGCAx2vETjITw= +honnef.co/go/tools v0.4.3/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA= +mvdan.cc/gofumpt v0.5.0 h1:0EQ+Z56k8tXjj/6TQD25BFNKQXpCvT0rnansIc7Ug5E= +mvdan.cc/gofumpt v0.5.0/go.mod h1:HBeVDtMKRZpXyxFciAirzdKklDlGu8aAy1wEbH5Y9js= +mvdan.cc/unparam v0.0.0-20230312165513-e84e2d14e3b8 h1:VuJo4Mt0EVPychre4fNlDWDuE5AjXtPJpRUWqZDQhaI= diff --git a/xmltv/channelmap.go b/internal/tv2/channelmap.go similarity index 97% rename from xmltv/channelmap.go rename to internal/tv2/channelmap.go index bcd4569..1bcf077 100644 --- a/xmltv/channelmap.go +++ b/internal/tv2/channelmap.go @@ -1,6 +1,6 @@ -package xmltv +package tv2 -var xmlChannelIdMap = map[int]string{ +var XmlChannelIdMap = map[int]string{ 1005: "tv2.no", 1152: "zebra.tv2.no", 1969: "livsstil.tv2.no", diff --git a/tv2/client.go b/internal/tv2/client.go similarity index 91% rename from tv2/client.go rename to internal/tv2/client.go index 4394aa9..7fb8969 100644 --- a/tv2/client.go +++ b/internal/tv2/client.go @@ -3,15 +3,13 @@ package tv2 import ( "encoding/json" "fmt" - "io/ioutil" + "io" "log" "net/http" "time" ) -// // https://rest.tv2.no/epg-dw-rest/epg/program/2021/03/15/ -// const ( rootUrl = "https://rest.tv2.no/epg-dw-rest/epg/program/" userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:86.0) Gecko/20100101 Firefox/86.0" @@ -36,12 +34,12 @@ func FetchEpg(date time.Time) []Channel { if err != nil { log.Fatalf("unable to get data: %s", err) } - if resp.StatusCode != 200 { + if resp.StatusCode != http.StatusOK { log.Printf("got unhappy statuscode: %d", resp.StatusCode) } defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { log.Fatalln(err) } diff --git a/tv2/types.go b/internal/tv2/types.go similarity index 100% rename from tv2/types.go rename to internal/tv2/types.go diff --git a/xmltv/types.go b/internal/xmltv/types.go similarity index 100% rename from xmltv/types.go rename to internal/xmltv/types.go diff --git a/xmltv/xmltv.go b/internal/xmltv/xmltv.go similarity index 90% rename from xmltv/xmltv.go rename to internal/xmltv/xmltv.go index 12d7d3a..607df2a 100644 --- a/xmltv/xmltv.go +++ b/internal/xmltv/xmltv.go @@ -5,7 +5,8 @@ import ( "fmt" "log" "time" - "xmltv-exporter/tv2" + + "xmltv/internal/tv2" ) const ( @@ -16,9 +17,13 @@ const ( defaultGeneratorUrl = "https://xmltv.sjurtf.net/" ) -var channelCache map[int]tv2.Channel -var channelGuideMap map[string]map[string][]tv2.Program -var generatorUrl string +type Producer struct{} + +var ( + channelCache map[int]tv2.Channel + channelGuideMap map[string]map[string][]tv2.Program + generatorUrl string +) func Init(url string) { generatorUrl = defaultGeneratorUrl @@ -40,7 +45,7 @@ func BuildCache(date time.Time, channel tv2.Channel) { channelGuideMap[dateKey] = make(map[string][]tv2.Program) } - xmlChannelId := xmlChannelIdMap[channel.Id] + xmlChannelId := tv2.XmlChannelIdMap[channel.Id] if xmlChannelId == "" { log.Printf("channel %s with id %d is not mapped", channel.Name, channel.Id) } @@ -63,14 +68,14 @@ func GetChannelList() ([]byte, error) { } channel := Channel{ - Id: xmlChannelIdMap[c.Id], + Id: tv2.XmlChannelIdMap[c.Id], Name: name, BaseUrl: generatorUrl, } channels = append(channels, channel) } - log.Printf("fetched available channels. Num channels %d", len(channels)) + log.Printf("Fetched %d channels from channel cahce", len(channels)) return marshall(channels, programs) } @@ -108,10 +113,11 @@ func getProgramsForChannel(channelId string, date time.Time) []Programme { } if !p.IsMovie { episodeNums = []EpisodeNum{episode} - subtitles = []CommonElement{{ - Lang: "nb", - Value: formatEpisodeHuman(p.Season, p.Episode), - }, + subtitles = []CommonElement{ + { + Lang: "nb", + Value: formatEpisodeHuman(p.Season, p.Episode), + }, } } diff --git a/main.go b/main.go index 7373cff..0a5d7eb 100644 --- a/main.go +++ b/main.go @@ -1,11 +1,14 @@ package main import ( - "github.com/go-co-op/gocron" "os" "time" - "xmltv-exporter/cmd" - "xmltv-exporter/xmltv" + + "xmltv/internal/xmltv" + + "github.com/go-co-op/gocron" + + "xmltv/cmd" ) func main() { @@ -18,5 +21,6 @@ func main() { cmd.RefreshToday() cmd.RefreshWeek() - cmd.ServeEpg(os.Getenv("XMLTV_PORT")) + server := cmd.Server{} + server.Start() } diff --git a/run.sh b/run.sh index f4edf86..d37d303 100755 --- a/run.sh +++ b/run.sh @@ -3,4 +3,4 @@ docker run -it --rm \ -p 8080:8080 \ -e 'XMLTV_PORT=8080' \ -e 'XMLTV_DOMAIN=http://host.docker.internal:8080/' \ - xmltv-exporter:development \ No newline at end of file + xmltv:development \ No newline at end of file diff --git a/tools.go b/tools.go new file mode 100644 index 0000000..6b3ce05 --- /dev/null +++ b/tools.go @@ -0,0 +1,10 @@ +//go:build tools +// +build tools + +package tools + +import ( + _ "golang.org/x/vuln/cmd/govulncheck" + _ "honnef.co/go/tools/cmd/staticcheck" + _ "mvdan.cc/gofumpt" +)