Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to refresh Plex Live TV Guide after the channels.json file is updated #40

Draft
wants to merge 18 commits into
base: master
Choose a base branch
from
Draft
4 changes: 2 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"os"
"strconv"

"github.com/duncanleo/plex-dvr-hls/config"
"github.com/duncanleo/plex-dvr-hls/routes"
"plex-dvr-hls/config"
"plex-dvr-hls/routes"
"github.com/gin-gonic/gin"
)

Expand Down
12 changes: 11 additions & 1 deletion config.example.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
{
"name": "Amazing Tuner",
"encoder_profile": "cpu",
"tuner_count": 3
"tuner_count": 3,
"plex_servers": [
{
"endpoint": "http://your-plex-server-1:32400",
"token": "your-plex-token-1"
},
{
"endpoint": "http://your-plex-server-2:32400",
"token": "your-plex-token-2"
}
]
}
143 changes: 74 additions & 69 deletions config/channels.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package config

import (
"encoding/json"
"errors"
"log"
"os"
"errors"
"sync"

"github.com/fsnotify/fsnotify"
"github.com/fsnotify/fsnotify"
m3uparser "github.com/pawanpaudel93/go-m3u-parser/m3uparser"
)

Expand All @@ -24,8 +24,8 @@ type Channel struct {
DisableTranscode bool `json:"disableTranscode"`

// UserAgent is a custom UA string that will be used by FFMPEG to make requests to the stream URL.
UserAgent *string `json:"userAgent,omitempty"`
Icon *string `json:"icon,omitempty"`
UserAgent *string `json:"userAgent,omitempty"`
Icon *string `json:"icon,omitempty"`
}

var (
Expand All @@ -34,18 +34,18 @@ var (
)

func LoadChannelsFromPl(location string) error {
var userAgent = os.Getenv("UA")
if len(userAgent) == 0 {
userAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
var userAgent = os.Getenv("UA")
if len(userAgent) == 0 {
userAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}
parser := m3uparser.M3uParser{UserAgent: userAgent, Timeout: 60}
parser.ParseM3u(location,true,true)
parser.ParseM3u(location, true, true)
streams := parser.GetStreamsSlice()
if len(streams) > 0 {
for _, st := range streams {
for _, st := range streams {
ch := Channel{Name: st["title"].(string), URL: st["url"].(string), UserAgent: &userAgent}
Channels = append(Channels,ch)
}
Channels = append(Channels, ch)
}
if len(Channels) > 0 {
return nil
}
Expand All @@ -54,76 +54,81 @@ func LoadChannelsFromPl(location string) error {
}

func WatchChannelsFile() {
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()

err = watcher.Add("channels.json")
if err != nil {
log.Fatal(err)
}

for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
if event.Has(fsnotify.Write) {
log.Println("Detected change in channels.json, reloading channels")
err := LoadChannels()
if err != nil {
log.Printf("Error reloading channels: %s\n", err)
}
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Printf("Watcher error: %s\n", err)
}
}
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()

err = watcher.Add("channels.json")
if err != nil {
log.Fatal(err)
}

for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
if event.Has(fsnotify.Write) {
log.Println("Detected change in channels.json, reloading channels")
err := LoadChannels()
if err != nil {
log.Printf("Error reloading channels: %s\n", err)
}

err = RefreshPlexLiveTVGuide()
if err != nil {
log.Printf("Error refreshing Plex LiveTV Guide: %s\n", err)
}
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Printf("Watcher error: %s\n", err)
}
}
}

func LoadChannels() error {
file, err := os.Open("channels.json")
if err != nil {
return err
}
defer file.Close()

var channels []Channel
decoder := json.NewDecoder(file)
err = decoder.Decode(&channels)
if err != nil {
return err
}

mu.Lock()
Channels = channels
mu.Unlock()

log.Println("Channels reloaded successfully")
return nil
file, err := os.Open("channels.json")
if err != nil {
return err
}
defer file.Close()

var channels []Channel
decoder := json.NewDecoder(file)
err = decoder.Decode(&channels)
if err != nil {
return err
}

mu.Lock()
Channels = channels
mu.Unlock()

log.Println("Channels reloaded successfully")
return nil
}

func init() {
var playlist = os.Getenv("PLAYLIST")
var playlist = os.Getenv("PLAYLIST")
if len(playlist) > 0 {
err := LoadChannelsFromPl(playlist)
if err == nil {
err := LoadChannelsFromPl(playlist)
if err == nil {
return
} else {
log.Printf("Provided m3u playlist error: %s\n",err)
log.Printf("Provided m3u playlist error: %s\n", err)
}
}

err := LoadChannels()
if err != nil {
log.Fatal(err)
}
if err != nil {
log.Fatal(err)
}

go WatchChannelsFile()
go WatchChannelsFile()
}
33 changes: 33 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package config

import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
)

Expand All @@ -15,10 +17,16 @@ const (
EncoderProfileOMX EncoderProfile = "omx"
)

type PlexServer struct {
Endpoint string `json:"endpoint"`
Token string `json:"token"`
}

type Config struct {
Name string `json:"name"`
EncoderProfile *EncoderProfile `json:"encoder_profile"`
TunerCount *int `json:"tuner_count"`
PlexServers []PlexServer `json:"plex_servers"`
}

func (c Config) GetEncoderProfile() EncoderProfile {
Expand All @@ -42,6 +50,31 @@ var (
Cfg Config
)

func RefreshPlexLiveTVGuide() error {
for _, server := range Cfg.PlexServers {
url := server.Endpoint + "/livetv/dvrs/29/reloadGuide?X-Plex-Token=" + server.Token
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: is the ID 29 hardcoded? I think it may change (e.g. if the DVR is removed and re-added).


req, err := http.NewRequest("POST", url, nil)
if err != nil {
return err
}

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to refresh Plex LiveTV Guide for server %s, status code: %d", server.Endpoint, resp.StatusCode)
}

log.Printf("Plex LiveTV Guide refreshed successfully for server %s", server.Endpoint)
}
return nil
}

func init() {
file, err := os.Open("config.json")
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module github.com/duncanleo/plex-dvr-hls
module plex-dvr-hls

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This change isn't compliant with Go module naming conventions:

The Go standard library uses package paths that do not contain a dot in the first path element, and the go command does not attempt to resolve such paths from network servers.

The non-absolute naming system appears to be suitable for local sub-packages (e.g. config) but not the root package.

go 1.23.3

Expand Down
2 changes: 1 addition & 1 deletion routes/discover.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"net/http"
"time"

"github.com/duncanleo/plex-dvr-hls/config"
"plex-dvr-hls/config"
"github.com/gin-gonic/gin"
)

Expand Down
2 changes: 1 addition & 1 deletion routes/lineup.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"fmt"
"net/http"

"github.com/duncanleo/plex-dvr-hls/config"
"plex-dvr-hls/config"
"github.com/gin-gonic/gin"
)

Expand Down
2 changes: 1 addition & 1 deletion routes/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"strconv"
"strings"

"github.com/duncanleo/plex-dvr-hls/config"
"plex-dvr-hls/config"
"github.com/gin-gonic/gin"
)

Expand Down
9 changes: 5 additions & 4 deletions routes/xmltv.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import (
"text/template"
"time"

"github.com/duncanleo/plex-dvr-hls/config"
"plex-dvr-hls/config"

"github.com/gin-gonic/gin"
)

type ChannelSimplified struct {
ID int
Name string
Icon *string
ID int
Name string
Icon *string
}

type Programme struct {
Expand Down
Loading