-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
549 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
FROM golang:1.16.2 as builder | ||
|
||
ENV GO111MODULE=on \ | ||
CGO_ENABLED=0 \ | ||
GOOS=linux \ | ||
GOARCH=amd64 | ||
|
||
WORKDIR /app | ||
|
||
COPY go.mod . | ||
#COPY go.sum . | ||
RUN go mod download | ||
|
||
COPY . /app | ||
RUN go build -o binary . | ||
|
||
FROM alpine:latest | ||
|
||
RUN addgroup -S app && adduser -S app -G app | ||
|
||
WORKDIR /app | ||
COPY --from=builder /app/binary . | ||
|
||
USER app | ||
ENTRYPOINT ["./binary"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
#/bin/sh | ||
docker build . -t xmltv-exporter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"net/http" | ||
"path" | ||
"strings" | ||
"time" | ||
"xmltv-exporter/xmltv" | ||
) | ||
|
||
func ServeEpg() { | ||
|
||
http.HandleFunc("/channels-norway.xml", ChannelListHandler) | ||
http.HandleFunc("/", ChannelHandler) | ||
|
||
if err := http.ListenAndServe(":8080", nil); err != nil { | ||
log.Fatal(err) | ||
} | ||
} | ||
|
||
func ChannelListHandler(w http.ResponseWriter, r *http.Request) { | ||
if !isValid(w, r) { | ||
return | ||
} | ||
|
||
bytes, err := xmltv.GetChannelList() | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
_, _ = w.Write(bytes) | ||
} | ||
|
||
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) | ||
return | ||
} | ||
|
||
date, err := date(r) | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusBadRequest) | ||
return | ||
} | ||
|
||
bytes, err := xmltv.GetSchedule(channelId, date) | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusNotFound) | ||
return | ||
} | ||
|
||
_, _ = w.Write(bytes) | ||
} | ||
|
||
/** | ||
Finds channelId from Path | ||
Example input: zebrahd.tv2.no_2021-03-16.xml.gz | ||
*/ | ||
func channelId(r *http.Request) (string, error) { | ||
filename := path.Base(r.URL.Path) | ||
parts := strings.Split(filename, "_") | ||
|
||
if len(parts) == 0 { | ||
return "", fmt.Errorf("channel name could not be found from input '%s'", filename) | ||
} | ||
return parts[0], nil | ||
} | ||
|
||
/** | ||
Finds time.Time from Path | ||
Example input: zebrahd.tv2.no_2021-03-16.xml.gz | ||
*/ | ||
func date(r *http.Request) (time.Time, error) { | ||
filename := path.Base(r.URL.Path) | ||
parts := strings.Split(filename, "_") | ||
|
||
if len(parts) <= 1 { | ||
return time.Time{}, fmt.Errorf("date could not be found from input '%s'", filename) | ||
} | ||
|
||
parts2 := strings.Split(parts[1], ".") | ||
|
||
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package cmd | ||
|
||
import ( | ||
"log" | ||
"time" | ||
"xmltv-exporter/tv2" | ||
"xmltv-exporter/xmltv" | ||
) | ||
|
||
func MapEgp() { | ||
today := time.Now() | ||
futureOneWeek := time.Now().Add(time.Hour * 24 * 3) | ||
|
||
var t = today | ||
for t.Before(futureOneWeek) { | ||
channels := tv2.FetchEpg(today) | ||
xmltv.UpdateAvailableChannels(channels) | ||
|
||
// TODO make this more efficient | ||
for _, channel := range channels { | ||
xmltv.BuildCache(t, channel) | ||
} | ||
|
||
t = t.Add(time.Hour * 24) | ||
log.Printf("date: %s", t) | ||
} | ||
log.Println("Epg cache refreshed") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module xmltv-exporter | ||
|
||
go 1.16 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package main | ||
|
||
import "xmltv-exporter/cmd" | ||
|
||
func main() { | ||
cmd.MapEgp() | ||
cmd.ServeEpg() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package tv2 | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"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" | ||
) | ||
|
||
func FetchEpg(date time.Time) []Channel { | ||
day := date.Day() | ||
month := date.Month() | ||
year := date.Year() | ||
|
||
datePath := fmt.Sprintf("%d/%d/%d", year, int(month), day) | ||
|
||
client := &http.Client{} | ||
req, err := http.NewRequest(http.MethodGet, rootUrl+datePath, nil) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
|
||
req.Header.Set("User-Agent", userAgent) | ||
|
||
resp, err := client.Do(req) | ||
if err != nil { | ||
log.Fatalf("unable to get data: %s", err) | ||
} | ||
if resp.StatusCode != 200 { | ||
log.Printf("got unhappy statuscode: %d", resp.StatusCode) | ||
} | ||
|
||
defer resp.Body.Close() | ||
body, err := ioutil.ReadAll(resp.Body) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
|
||
r := &Response{} | ||
err = json.Unmarshal(body, r) | ||
if err != nil { | ||
log.Fatalf("unable to decode data: %s", err) | ||
} | ||
|
||
return r.Channels | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package tv2 | ||
|
||
import ( | ||
"time" | ||
) | ||
|
||
type Response struct { | ||
Date string `json:"date"` | ||
Channels []Channel `json:"channel"` | ||
} | ||
|
||
type Channel struct { | ||
Id int `json:"id"` | ||
Name string `json:"name"` | ||
ShortName string `json:"shortName"` | ||
Category string `json:"category"` | ||
Score int `json:"score"` | ||
Tv2Id int `json:"tv2id"` | ||
Programs []Program `json:"program"` | ||
} | ||
|
||
type Program struct { | ||
Id int `json:"id"` | ||
SeriesId string `json:"srsid"` | ||
ProgramId string `json:"programId"` | ||
House string `json:"house"` | ||
Title string `json:"title"` | ||
Start time.Time `json:"start"` | ||
Stop time.Time `json:"stop"` | ||
Episode int `json:"epnr"` | ||
EpisodeTotal int `json:"eptot"` | ||
Season int `json:"season"` | ||
SeriesSynopsis string `json:"srsyn"` | ||
EpisodeSynopsis string `json:"epsyn"` | ||
|
||
Nationality string `json:"natio"` | ||
Genre string `json:"genre"` | ||
ProductionYear int `json:"pyear"` | ||
|
||
IsReplay bool `json:"isrepl"` | ||
IsLive bool `json:"islive"` | ||
IsMovie bool `json:"ismov"` | ||
IsSyn bool `json:"issyn"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package xmltv | ||
|
||
var xmlChannelIdMap = map[int]string{ | ||
1005: "tv2.no", | ||
1152: "zebra.tv2.no", | ||
1969: "livsstil.tv2.no", | ||
1147: "news.tv2.no", | ||
1153: "sport1.tv2.no", | ||
1154: "sport2.tv2.no", | ||
1148: "sportpremium.tv2.no", | ||
1000: "nrk1.nrk.no", | ||
1001: "nrk2.nrk.no", | ||
1112: "nrk3.nrk.no", | ||
1041: "tv3.no", | ||
1169: "v4.no", | ||
1162: "tvnorge.no", | ||
1101: "max.no", | ||
1092: "fem.no", | ||
1176: "vox.no", | ||
1132: "svt1.svt.se", | ||
1134: "svt2.svt.se", | ||
1156: "tv4.se", | ||
1078: "dr1.dr.dk", | ||
1079: "dr2.dr.dk", | ||
1083: "tv2.dk", | ||
1175: "tv6.no", | ||
1093: "foxtv.no", | ||
1050: "bbcworld.no", | ||
1046: "bbcentertainment.no", | ||
1048: "bbcknowledge.no", | ||
1044: "animalplanet.discovery.eu", | ||
1072: "hd.discovery.no", | ||
1073: "discovery.no", | ||
1080: "science.discovery.no", | ||
1085: "world.discovery.no", | ||
1094: "historytv.no", | ||
1105: "natgeo.no", | ||
1108: "wild.natgeo.no", | ||
1138: "travelchannel.no", | ||
1082: "tlc.discovery.no", | ||
1088: "eurosport.discovery.no", | ||
1089: "eurosport2.discovery.no", | ||
1081: "dsf.de", // tysk sportskanal lol | ||
1091: "extremesports.com", | ||
1057: "first.cmore.no", | ||
1059: "series.cmore.no", | ||
1058: "hits.cmore.no", | ||
1054: "stars.cmore.no", | ||
1055: "emotion.cmore.no", | ||
1060: "sf.cmore.no", | ||
1062: "tennis.cmore.no", | ||
1065: "hockey.cmore.no", | ||
1140: "film.viasat.no", | ||
9999: "action.film.viasat.no", | ||
1141: "classic.film.viasat.no", | ||
1142: "drama.film.viasat.no", | ||
1143: "family.film.viasat.no", | ||
1144: "comedy.film.viasat.no", | ||
1174: "plus.viasport.no", | ||
1170: "1.viasport.no", | ||
1173: "2.viasport.no", | ||
1172: "3.viasport.no", | ||
1166: "golf.viasat.no", | ||
1167: "history.viasat.no", | ||
1165: "explore.viasat.no", | ||
1168: "nature.viasat.no", | ||
1103: "mtv.no", | ||
1163: "vh1.no", | ||
1164: "classic.vh1.no", | ||
1113: "super.nrk.no", | ||
1074: "disneychannel.no", | ||
1077: "xd.disneychannel.no", // finnes ikke lengre | ||
1075: "junior.disneychannel.no", | ||
1110: "nickelodeon.no", | ||
1051: "boomerang.no", | ||
1067: "cartoonnetwork.no", | ||
1043: "aljazeera.eu", | ||
1071: "cnn.eu", | ||
1069: "cnbc.eu", | ||
1129: "skynews.eu", | ||
1042: "3sat.de", | ||
1084: "dw.de", | ||
1178: "rai1.de", | ||
1124: "rtl.de", | ||
1158: "tv5.eu", | ||
} |
Oops, something went wrong.