Skip to content

Commit 2edbd2e

Browse files
Merge pull request #54 from iloveicedgreentea/develop
Actual Jellyfin support and misc fixes
2 parents 46b6e6b + 6223b71 commit 2edbd2e

21 files changed

+853
-493
lines changed

.github/workflows/docker-publish.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
uses: docker/[email protected]
2727

2828
- name: Log into registry ${{ env.REGISTRY }}
29-
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
29+
# if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') || github.event_name == 'pull_request'}}
3030
uses: docker/[email protected]
3131
with:
3232
registry: ${{ env.REGISTRY }}
@@ -43,5 +43,5 @@ jobs:
4343
uses: docker/[email protected]
4444
with:
4545
context: .
46-
push: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
46+
push: true
4747
tags: ${{ steps.meta.outputs.tags }}

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM golang:1.21 as build
1+
FROM golang:1.22 as build
22

33
WORKDIR /go/src/app
44
COPY . .

Dockerfile.dev

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
FROM golang:1.22 as build
2+
3+
WORKDIR /go/src/app
4+
COPY . .
5+
RUN go mod download
6+
WORKDIR /go/src/app/cmd
7+
8+
RUN CGO_ENABLED=0 go build -o /go/bin/app
9+
10+
FROM alpine:20231219
11+
12+
RUN apk add supervisor
13+
COPY docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
14+
COPY docker/watch.py /watch.py
15+
16+
COPY --from=build /go/bin/app /
17+
COPY --from=build /go/src/app/web /web
18+
EXPOSE 9999
19+
20+
# CMD ["/app"]
21+
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ build:
55
test:
66
./test.sh
77
docker-build:
8-
docker buildx build --load --tag gowatchit-local .
8+
docker buildx build --platform linux/amd64 --load --tag gowatchit-local . -f ./Dockerfile.dev
99
docker-push:
1010
docker buildx build --push --platform linux/amd64 --tag ghcr.io/iloveicedgreentea/gowatchit:test .
1111
docker-run:
12-
LOG_FILE=false LOG_LEVEL=debug docker-compose up
12+
LOG_FILE=false LOG_LEVEL=debug docker-compose -f docker-compose-test.yml up
1313
run: build
1414
LOG_FILE=false LOG_LEVEL=debug ./build/server

changelog.txt

+4-2
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,7 @@ Modify UUID filter to accept comma for multiple
4040
* fix cache on resume
4141
* various speedups
4242
* remove listen port config
43-
* improve search by using tmdb
44-
* add author name to mqtt topic and logs
43+
* improve search by filtering tmdb
44+
* add author name to mqtt topic and logs
45+
* add option to skip TMDB for jellyfin, seems to be necessary because their metadata is super unreliable
46+
* Implement start/stop support for jellyfin

cmd/main.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ func main() {
7676
r.GET("/health", handlers.ProcessHealthcheckWebhookGin)
7777

7878
// Add plex webhook handler
79-
// TODO: split out non plex specific stuff into a library
8079
r.POST("/plexwebhook", func(c *gin.Context) {
8180
handlers.ProcessWebhook(plexChan, c)
8281
})
@@ -92,11 +91,11 @@ func main() {
9291
r.POST("/save-config", api.SaveConfig)
9392
// TODO: add generic webhook endpoint, maybe mqtt?
9493

95-
// TODO implement signal checking, error chan, etc
9694
/*
9795
###############################
9896
block until workers get ready
9997
############################## */
98+
log.Info("Waiting for workers to be ready...")
10099
<-plexReady
101100
<-minidspReady
102101
<-jfReady

docker-compose-test.yml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
version: '3.8'
2+
3+
services:
4+
plex-webhook-automation:
5+
platform: linux/amd64
6+
image: gowatchit-local:latest
7+
ports:
8+
- '9999:9999'
9+
environment:
10+
SUPER_DEBUG: 'false'
11+
LOG_LEVEL: 'debug'
12+
volumes:
13+
- ./docker/data:/data
14+
- ./web:/web

internal/common/webhooks.go

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"github.com/iloveicedgreentea/go-plex/models"
99
)
1010

11-
// TODO: test this if not already
1211
func DecodeWebhook(payload []string) (models.PlexWebhookPayload, int, error) {
1312
var pwhPayload models.PlexWebhookPayload
1413

internal/ezbeq/ezbeq.go

+60-10
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ func (c *BeqClient) MuteCommand(status bool) error {
128128
func (c *BeqClient) MakeCommand(payload []byte) error {
129129
for _, v := range c.DeviceInfo {
130130
endpoint := fmt.Sprintf("/api/1/devices/%s", v.Name)
131-
log.Debugf("ezbeq: Using endpoint %s", endpoint)
132131
_, err := c.makeReq(endpoint, payload, http.MethodPatch)
133132
if err != nil {
134133
return err
@@ -171,7 +170,7 @@ func (c *BeqClient) makeReq(endpoint string, payload []byte, methodType string)
171170
// log.Debugf("Using url %s", req.URL)
172171
// log.Debugf("Headers from req %v", req.Header)
173172
// simple retry
174-
res, err := c.makeCallWithRetry(req, 5, endpoint)
173+
res, err := c.makeCallWithRetry(req, 20, endpoint)
175174

176175
return res, err
177176
}
@@ -188,13 +187,15 @@ func (c *BeqClient) makeCallWithRetry(req *http.Request, maxRetries int, endpoin
188187
res, err = c.HTTPClient.Do(req)
189188
if err != nil {
190189
log.Debugf("Error with request - Retrying %v", err)
190+
time.Sleep(time.Second * 2)
191191
continue
192192
}
193193
defer res.Body.Close()
194194

195195
resp, err = io.ReadAll(res.Body)
196196
if err != nil {
197197
log.Debugf("Reading body failed - Retrying %v", err)
198+
time.Sleep(time.Second * 2)
198199
continue
199200
}
200201

@@ -213,6 +214,7 @@ func (c *BeqClient) makeCallWithRetry(req *http.Request, maxRetries int, endpoin
213214
log.Debug(string(resp), status)
214215
log.Debug("Retrying request...")
215216
err = fmt.Errorf("error in response: %v", res.Status)
217+
time.Sleep(time.Second * 2)
216218
continue
217219
}
218220
}
@@ -260,15 +262,37 @@ func (c *BeqClient) searchCatalog(m *models.SearchRequest) (models.BeqCatalog, e
260262

261263
// search through results and find match
262264
for _, val := range payload {
263-
log.Debugf("Beq results: Title: %v -- Codec %v, ID: %v", val.Title, val.AudioTypes, val.ID)
265+
// if skipping TMDB, set the IDs to match
266+
if config.GetBool("jellyfin.skiptmdb") {
267+
if m.Title == "" {
268+
return models.BeqCatalog{}, errors.New("title is blank, can't skip TMDB")
269+
}
270+
log.Debug("Skipping TMDB for search")
271+
val.MovieDbID = m.TMDB
272+
if !strings.EqualFold(val.Title, m.Title) {
273+
log.Debugf("%s did not match with title %s", val.Title, m.Title)
274+
continue
275+
}
276+
log.Debugf("%s matched with title %s", val.Title, m.Title)
277+
}
278+
log.Debugf("Beq results: Title: %v // Codec %v, ID: %v", val.Title, val.AudioTypes, val.ID)
264279
// if we find a match, return it. Much easier to match on tmdb since plex provides it also
265-
if val.MovieDbID == m.TMDB && val.Year == m.Year && val.AudioTypes[0] == m.Codec {
280+
var audioMatch bool
281+
// rationale here is some BEQ entries have multiple audio types in one entry
282+
for _, v := range val.AudioTypes {
283+
if strings.EqualFold(v, m.Codec) {
284+
audioMatch = true
285+
break
286+
}
287+
}
288+
if val.MovieDbID == m.TMDB && val.Year == m.Year && audioMatch {
289+
log.Debugf("%s matched with codecs %v, checking further", val.Title, val.AudioTypes)
266290
// if it matches, check edition
267291
if checkEdition(val, m.Edition) {
268292
log.Infof("Found a match in catalog from author %s", val.Author)
269293
return val, nil
270294
} else {
271-
log.Error("Found a match but editions did not match entry. Not loading")
295+
log.Errorf("Found a potential match but editions did not match entry. Not loading")
272296
}
273297
}
274298
}
@@ -299,9 +323,6 @@ func (c *BeqClient) LoadBeqProfile(m *models.SearchRequest) error {
299323
return nil
300324
}
301325

302-
if m.TMDB == "" {
303-
return errors.New("tmdb is empty. Can't find a match")
304-
}
305326
log.Debugf("beq payload is %#v", m)
306327

307328
// if no devices provided, error
@@ -330,6 +351,37 @@ func (c *BeqClient) LoadBeqProfile(m *models.SearchRequest) error {
330351
return err
331352
}
332353
}
354+
// most metadata contains DD+5.1 or something but its actually DD+ Atmos, so try a few options
355+
} else if m.Codec == "DD+Atmos5.1Maybe" {
356+
m.Codec = "DD+ Atmos"
357+
catalog, err = c.searchCatalog(m)
358+
// else try DD+ 5.1
359+
if err != nil {
360+
m.Codec = "DD+ 5.1"
361+
catalog, err = c.searchCatalog(m)
362+
if err != nil {
363+
m.Codec = "DD+"
364+
catalog, err = c.searchCatalog(m)
365+
if err != nil {
366+
return err
367+
}
368+
}
369+
}
370+
} else if m.Codec == "DD+Atmos7.1Maybe" {
371+
m.Codec = "DD+ Atmos"
372+
catalog, err = c.searchCatalog(m)
373+
// else try DD+ 7.1
374+
if err != nil {
375+
m.Codec = "DD+ 7.1"
376+
catalog, err = c.searchCatalog(m)
377+
if err != nil {
378+
m.Codec = "DD+"
379+
catalog, err = c.searchCatalog(m)
380+
if err != nil {
381+
return err
382+
}
383+
}
384+
}
333385
} else {
334386
catalog, err = c.searchCatalog(m)
335387
if err != nil {
@@ -382,8 +434,6 @@ func (c *BeqClient) LoadBeqProfile(m *models.SearchRequest) error {
382434
// write payload to each device
383435
for _, v := range m.Devices {
384436
endpoint := fmt.Sprintf("/api/2/devices/%s", v)
385-
log.Debugf("json payload %v", string(jsonPayload))
386-
log.Debugf("using endpoint %s", endpoint)
387437
_, err = c.makeReq(endpoint, jsonPayload, http.MethodPatch)
388438
if err != nil {
389439
log.Debugf("json payload %v", string(jsonPayload))

internal/ezbeq/ezbeq_test.go

+34-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package ezbeq
22

33
import (
4-
// "strings"
4+
"strings"
55
"fmt"
66
"testing"
77

@@ -670,6 +670,35 @@ func TestLoadProfile(t *testing.T) {
670670
Devices: []string{"master", "master2"},
671671
Slots: []int{1},
672672
},
673+
// DD+Atmos5.1Maybe //underwater
674+
{
675+
TMDB: "443791",
676+
Year: 2020,
677+
Codec: "DD+Atmos5.1Maybe",
678+
SkipSearch: false,
679+
EntryID: "",
680+
MVAdjust: 0.0,
681+
DryrunMode: false,
682+
PreferredAuthor: "none",
683+
Edition: "",
684+
MediaType: "movie",
685+
Devices: []string{"master", "master2"},
686+
Slots: []int{1},
687+
},
688+
{
689+
TMDB: "804095",
690+
Year: 2022,
691+
Codec: "DD+Atmos7.1Maybe",
692+
SkipSearch: false,
693+
EntryID: "",
694+
MVAdjust: 0.0,
695+
DryrunMode: false,
696+
PreferredAuthor: "none",
697+
Edition: "",
698+
MediaType: "movie",
699+
Devices: []string{"master", "master2"},
700+
Slots: []int{1},
701+
},
673702
}
674703

675704
for _, tc := range tt {
@@ -682,3 +711,7 @@ func TestLoadProfile(t *testing.T) {
682711
}
683712

684713
}
714+
715+
func TestTitleCom(t *testing.T) {
716+
assert.True(t, strings.EqualFold("American Sniper", ""))
717+
}

0 commit comments

Comments
 (0)