updated to include a automatic restart script
This commit is contained in:
parent
4b6be075c1
commit
621e51c7cd
14
Dockerfile
14
Dockerfile
@ -1,16 +1,22 @@
|
||||
FROM --platform=$BUILDPLATFORM debian:bullseye-slim as build
|
||||
FROM --platform=$BUILDPLATFORM golang:1-bullseye as build
|
||||
|
||||
ENV SPOTIFYD_VERSION=v0.3.5
|
||||
ENV URL=https://github.com/Spotifyd/spotifyd/releases/download/${SPOTIFYD_VERSION}/spotifyd-linux-armhf-full.tar.gz
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -yqq --no-install-recommends ca-certificates wget
|
||||
apt-get install -yqq --no-install-recommends ca-certificates wget
|
||||
|
||||
RUN wget ${URL} -O - | tar -xz && chmod +x /spotifyd
|
||||
WORKDIR /
|
||||
|
||||
RUN wget ${URL} -O - | tar -xz && chmod +x spotifyd
|
||||
|
||||
COPY main.go /main.go
|
||||
RUN GOARCH=arm go build -o /runner /main.go
|
||||
|
||||
FROM --platform=$TARGETPLATFORM debian:bullseye-slim
|
||||
|
||||
COPY --from=build /spotifyd /app/spotifyd
|
||||
COPY --from=build /runner /app/runner
|
||||
COPY start.sh /app/start.sh
|
||||
|
||||
RUN apt-get update && \
|
||||
@ -22,4 +28,4 @@ RUN apt-get update && \
|
||||
USER spotifyd
|
||||
WORKDIR /app
|
||||
|
||||
ENTRYPOINT [ "/app/start.sh" ]
|
||||
ENTRYPOINT [ "/app/runner" ]
|
||||
|
@ -22,7 +22,7 @@ Following variables are available. See the [spotifyd doc](https://spotifyd.githu
|
||||
|
||||
`PASSWORD` Required. Spotify password.
|
||||
|
||||
`DEVICE` Name of the device. Default: "Spotifyd"
|
||||
`DEVICE_NAME` Name of the device. Default: "Spotifyd"
|
||||
|
||||
`VOLUME_NORMALISATION` If set to true, enables volume normalisation between songs.
|
||||
|
||||
|
2
build.sh
2
build.sh
@ -1,3 +1,3 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
docker buildx build --platform linux/arm/v7 . -t djeeberjr/spotifyd --push
|
||||
docker buildx build --platform linux/arm/v7 . -t djeeberjr/spotifyd $@
|
||||
|
@ -9,4 +9,4 @@ services:
|
||||
environment:
|
||||
- USERNAME=myUsername
|
||||
- PASSWORD=myPassword
|
||||
- DEVICE=Spotifyd
|
||||
- DEVICE_NAME=Spotifyd
|
||||
|
155
main.go
Normal file
155
main.go
Normal file
@ -0,0 +1,155 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
)
|
||||
|
||||
type headerTransport struct {
|
||||
baseTransport http.RoundTripper
|
||||
headers map[string]string
|
||||
}
|
||||
|
||||
func (t *headerTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
for key, value := range t.headers {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
|
||||
return t.baseTransport.RoundTrip(req)
|
||||
}
|
||||
|
||||
type DevicesResponse struct {
|
||||
Devices []struct {
|
||||
ID string `json:"id"`
|
||||
IsActive bool `json:"is_active"`
|
||||
IsPrivateSession bool `json:"is_private_session"`
|
||||
IsRestricted bool `json:"is_restricted"`
|
||||
Name string `json:"name"`
|
||||
SupportsVolume bool `json:"supports_volume"`
|
||||
Type string `json:"type"`
|
||||
VolumePercent int `json:"volume_percent"`
|
||||
} `json:"devices"`
|
||||
}
|
||||
|
||||
var API_URL string
|
||||
var API_KEY string
|
||||
var DEVICE_NAME string
|
||||
var MAX_FAILED = 5
|
||||
var CHECK_INTERVAL = 5 * time.Second
|
||||
|
||||
func main() {
|
||||
API_URL = os.Getenv("API_URL")
|
||||
API_KEY = os.Getenv("API_KEY")
|
||||
DEVICE_NAME = os.Getenv("DEVICE_NAME")
|
||||
|
||||
if API_URL == "" {
|
||||
fmt.Println("API_URL not set")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if API_KEY == "" {
|
||||
fmt.Println("API_KEY not set")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if DEVICE_NAME == "" {
|
||||
fmt.Println("DEVICE_NAME not set")
|
||||
fmt.Println("Using default: Spotifyd")
|
||||
DEVICE_NAME = "Spotifyd"
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Transport: &headerTransport{
|
||||
baseTransport: http.DefaultTransport,
|
||||
headers: map[string]string{
|
||||
"X-API-KEY": API_KEY,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
runLoop(client)
|
||||
}
|
||||
|
||||
func runLoop(client *http.Client) {
|
||||
proc := runSpotifyd()
|
||||
|
||||
go func() {
|
||||
defer func() {
|
||||
fmt.Println("Killing spotifyd")
|
||||
proc.Process.Kill()
|
||||
}()
|
||||
|
||||
failedCheck := 0
|
||||
for {
|
||||
time.Sleep(CHECK_INTERVAL)
|
||||
devices, err := getDevices(client)
|
||||
if err != nil {
|
||||
fmt.Println("Error getting devices: " + err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
if containsDevice(devices, DEVICE_NAME) {
|
||||
failedCheck = 0
|
||||
continue
|
||||
}
|
||||
|
||||
failedCheck++
|
||||
fmt.Printf("Can't find device %s. Failed check %d of %d \n", DEVICE_NAME, failedCheck, MAX_FAILED)
|
||||
|
||||
if failedCheck >= MAX_FAILED {
|
||||
return // kill handled by defer
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
proc.Run()
|
||||
}
|
||||
|
||||
func containsDevice(response *DevicesResponse, deviceName string) bool {
|
||||
for _, device := range response.Devices {
|
||||
if device.Name == DEVICE_NAME {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getDevices(client *http.Client) (*DevicesResponse, error) {
|
||||
// https://developer.spotify.com/documentation/web-api/reference/get-a-users-available-devices
|
||||
resp, err := client.Get(API_URL + "/me/player/devices")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, errors.New("Not OK. Got " + resp.Status + " instead")
|
||||
}
|
||||
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var devicesResponse DevicesResponse
|
||||
err = json.Unmarshal(data, &devicesResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &devicesResponse, nil
|
||||
}
|
||||
|
||||
func runSpotifyd() *exec.Cmd {
|
||||
proc := exec.Command("/app/start.sh")
|
||||
|
||||
proc.Stdout = os.Stdout
|
||||
proc.Stderr = os.Stderr
|
||||
|
||||
return proc
|
||||
}
|
2
start.sh
2
start.sh
@ -32,4 +32,4 @@ if [ -n "$EXTRA_ARGS" ]; then
|
||||
ARGS="${ARGS} ${EXTRA_ARGS}"
|
||||
fi
|
||||
|
||||
/app/spotifyd --no-daemon --username "$USERNAME" --password "$PASSWORD" --device-name "${DEVICE:=Spotifyd}" $ARGS
|
||||
/app/spotifyd --no-daemon --username "$USERNAME" --password "$PASSWORD" --device-name "${DEVICE_NAME:=Spotifyd}" $ARGS
|
||||
|
Loading…
Reference in New Issue
Block a user