Skip to content

Commit 5e58291

Browse files
Merge pull request #36 from iloveicedgreentea/develop
Large refactor, automatic restarts, webui, API
2 parents c322add + a7f3e00 commit 5e58291

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+3438
-2408
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: Bug report
3-
about: Create a report to help us improve
3+
about: Create a bug report
44
title: ''
55
labels: bug
66
assignees: iloveicedgreentea
@@ -20,12 +20,17 @@ Steps to reproduce the behavior:
2020
**Expected behavior**
2121
A clear and concise description of what you expected to happen.
2222

23+
**Configuration**
24+
Navigate to `(your-server-ip):9999/config` and paste the output here
25+
2326
**Debug logs**
24-
Run the program with LOG_LEVEL=debug and send me the entire log output from start to finish
27+
Run the program with LOG_LEVEL=debug and send me the entire log output while you trigger the bug, if possible.
28+
29+
Get logs from the `(your-server-ip):9999/logs` endpoint
2530

26-
**Desktop (please complete the following information):**
31+
**Info (please complete the following information):**
2732
- OS: [Windows, Unraid, etc]
28-
- Version [e.g. 22]
33+
- Version [e.g. 1.2]
2934
- Deployment method: [Docker, binary]
3035

3136
**Additional context**

.github/ISSUE_TEMPLATE/config.yml

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
blank_issues_enabled: false

.github/ISSUE_TEMPLATE/feature_request.md

+3-6
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,16 @@
22
name: Feature request
33
about: Suggest an idea for this project
44
title: ''
5-
labels: ''
6-
assignees: ''
5+
labels: 'feature'
6+
assignees: 'iloveicedgreentea'
77

88
---
99

1010
**Is your feature request related to a problem? Please describe.**
11-
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
11+
A clear and concise description of what the problem is. Ex. I'm frustrated when [...]
1212

1313
**Describe the solution you'd like**
1414
A clear and concise description of what you want to happen.
1515

16-
**Describe alternatives you've considered**
17-
A clear and concise description of any alternative solutions or features you've considered.
18-
1916
**Additional context**
2017
Add any other context or screenshots about the feature request here.

.github/workflows/docker-publish.yml

+9-8
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ on:
1212
tags: ["v*.*.*"]
1313
pull_request:
1414
branches: ["master", "develop", "clip_support"]
15-
1615

1716
env:
1817
# Use docker.io for Docker Hub if empty
@@ -32,16 +31,18 @@ jobs:
3231

3332
steps:
3433
- name: Checkout repository
35-
uses: actions/checkout@v3
34+
uses: actions/checkout@v4
3635
# Workaround: https://github.com/docker/build-push-action/issues/461
3736
- name: Setup Docker buildx
38-
uses: docker/[email protected]
37+
uses: docker/[email protected]
38+
39+
# TODO: run tests
3940

4041
# Login against a Docker registry except on PR
4142
# https://github.com/docker/login-action
4243
- name: Log into registry ${{ env.REGISTRY }}
43-
if: github.event_name != 'pull_request'
44-
uses: docker/login-action@v2.2.0
44+
if: ${{ github.event_name == 'pull_request' && github.head_ref == 'develop' }}
45+
uses: docker/login-action@v3.0.0
4546
with:
4647
registry: ${{ env.REGISTRY }}
4748
username: ${{ github.actor }}
@@ -51,19 +52,19 @@ jobs:
5152
# https://github.com/docker/metadata-action
5253
- name: Extract Docker metadata
5354
id: meta
54-
uses: docker/metadata-action@v4.6.0
55+
uses: docker/metadata-action@v5.0.0
5556
with:
5657
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
5758

5859
# Build and push Docker image with Buildx (don't push on PR)
5960
# https://github.com/docker/build-push-action
6061
- name: Build and push Docker image
6162
id: build-and-push
62-
uses: docker/build-push-action@v4.1.1
63+
uses: docker/build-push-action@v5.0.0
6364
with:
6465
context: .
6566
# platforms: linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7
66-
push: ${{ github.event_name != 'pull_request' }}
67+
push: ${{ github.event_name == 'pull_request' && github.head_ref == 'develop' }}
6768
tags: ${{ steps.meta.outputs.tags }}
6869
# cache-from: type=gha
6970
# cache-to: type=gha,mode=max

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
build
22
.DS_Store
3-
config.json
3+
*config.json
44
media.*.priv*
5+
docker/data
56

67
# Binaries for programs and plugins
78
*.exe

Contributing.MD

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Contributing Rules
2+
3+
## Pull Requests
4+
Pull requests *will not be accepted*. If you have a change you want to make, create an issue and I will look at it.
5+
6+
## Feature Requests
7+
All feature requests must follow the template.
8+
9+
## Issues
10+
Issues should be used for bug reports. Please follow the template when creating an issue.
11+
12+
## Support
13+
Use the Discussions tab for support.

Contributing.md

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Contributing Rules
2+
3+
## Pull Requests
4+
Pull requests *will not be accepted*. If you have a change you want to make, create an issue and I will look at it.
5+
6+
## Feature Requests
7+
All feature requests must follow the template.
8+
9+
## Issues
10+
Issues should be used for bug reports. Please follow the template when creating an issue.
11+
12+
## Support
13+
Use the Discussions tab for support.

Dockerfile

+10-3
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,21 @@ FROM golang:1.21 as build
22

33
WORKDIR /go/src/app
44
COPY . .
5-
65
RUN go mod download
6+
WORKDIR /go/src/app/cmd
77
RUN go vet -v
88

99
RUN CGO_ENABLED=0 go build -o /go/bin/app
1010

11-
FROM gcr.io/distroless/static-debian11
11+
FROM alpine:20230901
1212

13+
RUN apk add supervisor
14+
COPY docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
15+
COPY docker/watch.py /watch.py
1316

1417
COPY --from=build /go/bin/app /
15-
CMD ["/app"]
18+
COPY --from=build /go/src/app/web /web
19+
EXPOSE 9999
20+
21+
# CMD ["/app"]
22+
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

Makefile

+18-11
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
1-
.PHONY: build test run
2-
1+
.PHONY: build test run docker-run docker-build
2+
SHELL := /bin/bash
33
build:
4-
go build -o ./build/server
4+
cd cmd && go build -o ../build/server
55

66
test:
7-
@go vet
8-
@unset LOG_LEVEL && cd handlers && go test
9-
@unset LOG_LEVEL && cd homeassistant && go test
10-
@unset LOG_LEVEL && cd plex && go test
11-
@unset LOG_LEVEL && cd mqtt && go test
12-
@unset LOG_LEVEL && cd ezbeq && go test
13-
7+
# @go vet
8+
@unset LOG_LEVEL && cd internal/config && go test -v
9+
@unset LOG_LEVEL && cd internal/handlers && go test -v
10+
@unset LOG_LEVEL && cd internal/homeassistant && go test -v
11+
@unset LOG_LEVEL && cd internal/denon && go test -v
12+
@unset LOG_LEVEL && cd internal/plex && go test -v
13+
@unset LOG_LEVEL && cd internal/mqtt && go test -v
14+
@unset LOG_LEVEL && cd internal/ezbeq && go test -v
15+
docker-build:
16+
docker buildx build --load --tag plex-webhook-automation-local .
17+
docker-push:
18+
docker buildx build --push --platform linux/amd64 --tag ghcr.io/iloveicedgreentea/plex-webhook-automation:test .
19+
docker-run:
20+
docker run -p 9999:9999 -e LOG_LEVEL=debug -v $(shell pwd)/docker/data:/data plex-webhook-automation-local
1421
run: build
15-
@./build/server
22+
LOG_FILE=false LOG_LEVEL=debug ./build/server

api/handlers.go

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package api
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"path/filepath"
8+
9+
"github.com/gin-gonic/gin"
10+
"github.com/iloveicedgreentea/go-plex/internal/config"
11+
"github.com/iloveicedgreentea/go-plex/internal/logger"
12+
)
13+
14+
var log = logger.GetLogger()
15+
16+
func GenConfigPaths() (string, string) {
17+
ex, err := os.Executable()
18+
if err != nil {
19+
log.Error(err)
20+
}
21+
22+
exPath := filepath.Dir(ex)
23+
configPath1 := "/data/config.json" // docker
24+
configPath2 := filepath.Join(exPath, "../config.json") // Fallback path (for local)
25+
26+
log.Debugf("Config paths: %s, %s", configPath1, configPath2)
27+
28+
return configPath1, configPath2
29+
}
30+
31+
// GetConfigPath returns the path to the config file
32+
func GetConfigPath() (string, error) {
33+
configPath1, configPath2 := GenConfigPaths()
34+
35+
if _, err := os.Stat(configPath1); err == nil {
36+
return configPath1, nil
37+
} else if _, err := os.Stat(configPath2); err == nil {
38+
return configPath2, nil
39+
}
40+
return "", os.ErrNotExist
41+
}
42+
43+
// ConfigExists checks if the config exists for the API
44+
func ConfigExists(c *gin.Context) {
45+
configPath, err := GetConfigPath()
46+
if err != nil {
47+
c.JSON(500, gin.H{"exists": false})
48+
return
49+
}
50+
_, err = os.Stat(configPath)
51+
c.JSON(200, gin.H{"exists": err == nil})
52+
}
53+
54+
// Route for getting logs
55+
func GetLogs(c *gin.Context) {
56+
logFile, err := os.ReadFile("/data/application.log")
57+
if err != nil {
58+
c.JSON(500, gin.H{"error": "unable to read log file: " + err.Error()})
59+
return
60+
}
61+
c.Data(200, "text/plain", logFile)
62+
}
63+
64+
// GetConfig returns the config for the API
65+
func GetConfig(c *gin.Context) {
66+
path, err := GetConfigPath()
67+
// if not found, create it
68+
if err != nil {
69+
log.Debugf("Didn't get config: %v", err)
70+
err = CreateConfig(c)
71+
if err != nil {
72+
log.Debugf("Didn't create config: %v", err)
73+
c.JSON(500, gin.H{"error": "unable to create config"})
74+
return
75+
}
76+
}
77+
data, err := os.ReadFile(path)
78+
if err != nil {
79+
log.Debugf("Didn't read config: %v", err)
80+
c.JSON(500, gin.H{"error": "unable to read config"})
81+
return
82+
}
83+
c.Data(200, "application/json", data)
84+
}
85+
86+
// CreateConfig creates a new config file
87+
func CreateConfig(c *gin.Context) error {
88+
log.Debug("Creating new config")
89+
configPath1, configPath2 := GenConfigPaths()
90+
91+
// try to create config in the first path
92+
file, err := os.Create(configPath1)
93+
if err != nil {
94+
log.Debugf("Unable to create config in %s: %v", configPath1, err)
95+
// try to create config in the second path
96+
file, err = os.Create(configPath2)
97+
if err != nil {
98+
// if we can't create it in either path, return the error
99+
log.Errorf("Unable to create config in %s: %v", configPath2, err)
100+
return fmt.Errorf("unable to create config in %s or %s", configPath1, configPath2)
101+
}
102+
}
103+
defer file.Close()
104+
105+
log.Debug("Successfully created config file")
106+
return nil
107+
}
108+
109+
// SaveConfig saves the config for the API
110+
func SaveConfig(c *gin.Context) {
111+
var jsonData map[string]interface{}
112+
113+
if err := c.ShouldBindJSON(&jsonData); err != nil {
114+
c.JSON(400, gin.H{"error": err.Error()})
115+
fmt.Println(c.Request.Body)
116+
return
117+
}
118+
119+
path, err := GetConfigPath()
120+
if err != nil {
121+
log.Error("unable to get config")
122+
c.JSON(500, gin.H{"error": "unable to get config"})
123+
return
124+
}
125+
126+
// Loop through the incoming JSON map to set keys in Viper
127+
for key, value := range jsonData {
128+
switch v := value.(type) {
129+
case map[string]interface{}:
130+
for subKey, subValue := range v {
131+
config.Set(fmt.Sprintf("%s.%s", key, subKey), subValue)
132+
}
133+
default:
134+
config.Set(key, value)
135+
}
136+
}
137+
138+
// Use your SaveConfigFile function to save the updated configuration
139+
if err := config.SaveConfigFile(path); err != nil {
140+
log.Error("unable to save config")
141+
c.JSON(500, gin.H{"error": "Unable to save config"})
142+
return
143+
}
144+
145+
c.JSON(200, gin.H{"message": "Config saved successfully"})
146+
}

api/routes.go

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package api
2+
3+
import (
4+
"github.com/gin-gonic/gin"
5+
)
6+
7+
// RegisterRoutes registers the routes for the API contained in handlers.go
8+
func RegisterRoutes(router *gin.Engine) {
9+
router.GET("/config", GetConfig)
10+
router.POST("/config", SaveConfig)
11+
router.GET("/logs", GetLogs)
12+
}

changelog.txt

+22-1
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,25 @@ use both denon and plex to compare codecs, make sure they are playing whats expe
1212
Add support for detecting HDMI sync using madvr Envy. It will detect when media is synced and continue playing.
1313
This prevents a black screen but stuff is playing which is annoying
1414
It also makes the denon codec detection more accurate
15-
New config homeAssistant.envyName
15+
New config homeAssistant.envyName
16+
17+
18+
9-10-23
19+
Web UI flow for configuring server
20+
New MQTT automations:
21+
* "topicbeqcurrentprofile": -> which current profile is loaded
22+
* "topicminidspmutestatus": -> true/false if minidsp(s) muted
23+
* "topicplayingstatus": -> true/false if the tool is playing
24+
Some functionality changes, check the readme
25+
HDMI Sync automation in testing
26+
*Breaking changes* All config fields are lowercase now
27+
28+
10-9-23
29+
Modify UUID filter to accept comma for multiple
30+
31+
12-sometime-23
32+
* Breaking change - volume must now be mounted to /data
33+
* log to a file
34+
* add /logs endpoint
35+
* add prelim jellyfin support
36+
* new name/logo

0 commit comments

Comments
 (0)