Compare commits
No commits in common. "2c813674e2d0ec3b7e2894dccb39196146239eb6" and "9aed9c78e38a16fc60da4ebb0b673b748344323c" have entirely different histories.
2c813674e2
...
9aed9c78e3
20 changed files with 272 additions and 199 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
||||||
[submodule "aur"]
|
|
||||||
path = aur
|
|
||||||
url = ssh://aur@aur.archlinux.org/sanic.git
|
|
1
aur
1
aur
|
@ -1 +0,0 @@
|
||||||
Subproject commit 8e38dfb90aa5b09a7ac6c762a4f5cc19a94b8b1d
|
|
53
aur/PKGBUILD
Normal file
53
aur/PKGBUILD
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# Maintainer: Ricardo Band <email@ricardo.band>
|
||||||
|
|
||||||
|
pkgname=sanic
|
||||||
|
pkgver=0.0.1
|
||||||
|
pkgrel=1
|
||||||
|
pkgdesc="chaos music control inspired by relaxx player"
|
||||||
|
arch=('any')
|
||||||
|
url=https://git.berlin.ccc.de/cccb/sanic
|
||||||
|
license=('custom:MIT')
|
||||||
|
makedepends=('go')
|
||||||
|
source=("$pkgname.service"
|
||||||
|
"$pkgname.sysusers"
|
||||||
|
"$pkgname.tmpfiles"
|
||||||
|
"$url/archive/v$pkgver.tar.gz")
|
||||||
|
sha256sums=("1337deadbeef"
|
||||||
|
"1337deadbeef"
|
||||||
|
"1337deadbeef"
|
||||||
|
"1337deadbeef")
|
||||||
|
|
||||||
|
prepare() {
|
||||||
|
cd "$pkgname-$pkgver"
|
||||||
|
|
||||||
|
mkdir -p build/
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
cd "$pkgname-$pkgver"
|
||||||
|
|
||||||
|
export CGO_CPPFLAGS="$CPPFLAGS"
|
||||||
|
export CGO_CFLAGS="$CFLAGS"
|
||||||
|
export CGO_CXXFLAGS="$CXXFLAGS"
|
||||||
|
export CGO_LDFLAGS="$LDFLAGS"
|
||||||
|
export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw"
|
||||||
|
|
||||||
|
go build -o build/ .
|
||||||
|
}
|
||||||
|
|
||||||
|
check() {
|
||||||
|
cd "$pkgname-$pkgver"
|
||||||
|
|
||||||
|
go test ./...
|
||||||
|
}
|
||||||
|
|
||||||
|
package() {
|
||||||
|
cd "$pkgname-$pkgver"
|
||||||
|
|
||||||
|
install -Dm644 "LICENSE" "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
|
||||||
|
install -Dm755 build/$pkgname "$pkgdir"/usr/bin/$pkgname
|
||||||
|
install -Dm644 "../$pkgname.service" "$pkgdir/usr/lib/systemd/system/$pkgname.service"
|
||||||
|
install -Dm644 "../$pkgname.sysusers" "$pkgdir/usr/lib/sysusers.d/$pkgname.conf"
|
||||||
|
install -Dm644 "../$pkgname.tmpfiles" "$pkgdir/usr/lib/tmpfiles.d/$pkgname.conf"
|
||||||
|
}
|
||||||
|
|
28
aur/sanic.service
Normal file
28
aur/sanic.service
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
[Unit]
|
||||||
|
Description=chaos music control
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=sanic
|
||||||
|
Group=sanic
|
||||||
|
ExecStart=/usr/bin/sanic
|
||||||
|
Restart=always
|
||||||
|
# security
|
||||||
|
NoNewPrivileges=true
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=yes
|
||||||
|
StateDirectory=sanic
|
||||||
|
StateDirectoryMode=0750
|
||||||
|
ConfigurationDirectory=sanic
|
||||||
|
ConfigurationDirectoryMode=0750
|
||||||
|
PrivateTmp=true
|
||||||
|
ProtectKernelTunables=true
|
||||||
|
ProtectKernelModules=true
|
||||||
|
ProtectKernelLogs=true
|
||||||
|
ProtectControlGroups=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
3
aur/sanic.sysusers
Normal file
3
aur/sanic.sysusers
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
u sanic - "chaos music control" /run/sanic /usr/bin/nologin
|
||||||
|
g sanic - -
|
||||||
|
|
3
aur/sanic.tmpfiles
Normal file
3
aur/sanic.tmpfiles
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
d /etc/sanic 0750 sanic sanic
|
||||||
|
d /run/sanic 0750 sanic sanic
|
||||||
|
|
114
flake.nix
114
flake.nix
|
@ -37,7 +37,119 @@
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
packages.default = sanic;
|
packages.default = sanic;
|
||||||
nixosModules.default = import ./option.nix;
|
nixosModules.default = { config, lib, pkgs, options, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.services.sanic;
|
||||||
|
configFile = pkgs.writeText "config.ini" (pkgs.lib.generators.toINI {} cfg);
|
||||||
|
execCommand = "${cfg.package}/bin/sanic -c '${configFile}'";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services.sanic = {
|
||||||
|
enable = lib.mkEnableOption "Enables the sanic systemd service.";
|
||||||
|
package = lib.mkOption {
|
||||||
|
description = "Package to use.";
|
||||||
|
type = lib.types.package;
|
||||||
|
default = sanic;
|
||||||
|
};
|
||||||
|
ui = lib.mkOption {
|
||||||
|
description = "Setting for HTTP(S) UI.";
|
||||||
|
example = lib.literalExpression ''
|
||||||
|
{
|
||||||
|
host = "[::1]";
|
||||||
|
port = 8443;
|
||||||
|
tls = true;
|
||||||
|
certificate = "${config.security.acme.certs."sanic.example.com".directory}/fullchain.pem";
|
||||||
|
key = "${config.security.acme.certs."sanic.example.com".directory}/key.pem";
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
default = {
|
||||||
|
host = "[::1]";
|
||||||
|
port = 80;
|
||||||
|
tls = false;
|
||||||
|
};
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
host = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "[::1]";
|
||||||
|
description = "Host to bind to.";
|
||||||
|
};
|
||||||
|
port = lib.mkOption {
|
||||||
|
type = lib.types.port;
|
||||||
|
default = 8080;
|
||||||
|
description = "Port to listen on.";
|
||||||
|
};
|
||||||
|
tls = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enables HTTPS.";
|
||||||
|
};
|
||||||
|
certificate = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.path;
|
||||||
|
default = null;
|
||||||
|
description = "Path to TLS certificate for HTTPS.";
|
||||||
|
};
|
||||||
|
key = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.path;
|
||||||
|
default = null;
|
||||||
|
description = "Path to TLS key for HTTPS.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
backend = lib.mkOption {
|
||||||
|
description = "Configure MPD backend.";
|
||||||
|
example = lib.literalExpression ''
|
||||||
|
{
|
||||||
|
host = "localhost";
|
||||||
|
port = 6600;
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
default = {
|
||||||
|
host = "localhost";
|
||||||
|
port = 6600;
|
||||||
|
};
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
host = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "localhost";
|
||||||
|
description = "Hostname or IP of MPD instance.";
|
||||||
|
};
|
||||||
|
port = lib.mkOption {
|
||||||
|
type = lib.types.port;
|
||||||
|
default = 6600;
|
||||||
|
description = "Port of MPD instance.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
systemd.services."sanic" = {
|
||||||
|
description = "sanic - chaos music control";
|
||||||
|
wants = [ "network-online.target" ];
|
||||||
|
after = [ "network-online.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Restart = "always";
|
||||||
|
RestartSec = 30;
|
||||||
|
ExecStart = execCommand;
|
||||||
|
User = "sanic";
|
||||||
|
Group = "sanic";
|
||||||
|
AmbientCapabilities = lib.mkIf (cfg.ui.port < 1000) [ "CAP_NET_BIND_SERVICE" ];
|
||||||
|
CapabilityBoundingSet = lib.mkIf (cfg.ui.port < 1000) [ "CAP_NET_BIND_SERVICE" ];
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#meta = {
|
||||||
|
# maintainers = with lib.maintainers; [ xengi ];
|
||||||
|
# doc = ./default.xml;
|
||||||
|
#};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -6,7 +6,6 @@ require (
|
||||||
github.com/fhs/gompd/v2 v2.3.0
|
github.com/fhs/gompd/v2 v2.3.0
|
||||||
github.com/labstack/echo-contrib v0.17.1
|
github.com/labstack/echo-contrib v0.17.1
|
||||||
github.com/labstack/echo/v4 v4.12.0
|
github.com/labstack/echo/v4 v4.12.0
|
||||||
github.com/tdewolff/minify/v2 v2.24.0
|
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,12 +21,11 @@ require (
|
||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.55.0 // indirect
|
github.com/prometheus/common v0.55.0 // indirect
|
||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
github.com/tdewolff/parse/v2 v2.8.3 // indirect
|
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||||
golang.org/x/crypto v0.26.0 // indirect
|
golang.org/x/crypto v0.26.0 // indirect
|
||||||
golang.org/x/net v0.28.0 // indirect
|
golang.org/x/net v0.28.0 // indirect
|
||||||
golang.org/x/sys v0.30.0 // indirect
|
golang.org/x/sys v0.23.0 // indirect
|
||||||
golang.org/x/text v0.17.0 // indirect
|
golang.org/x/text v0.17.0 // indirect
|
||||||
golang.org/x/time v0.6.0 // indirect
|
golang.org/x/time v0.6.0 // indirect
|
||||||
google.golang.org/protobuf v1.34.2 // indirect
|
google.golang.org/protobuf v1.34.2 // indirect
|
||||||
|
|
10
go.sum
10
go.sum
|
@ -35,12 +35,6 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg
|
||||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/tdewolff/minify/v2 v2.24.0 h1:m6j8VXvgUtmkavubzHbaNTXi9tw3hjIMZbdc57SRdvI=
|
|
||||||
github.com/tdewolff/minify/v2 v2.24.0/go.mod h1:uqtSu3w0+anqk4ofcsuLPZ8tV8yAZL1r/ILWYYl2j3c=
|
|
||||||
github.com/tdewolff/parse/v2 v2.8.3 h1:5VbvtJ83cfb289A1HzRA9sf02iT8YyUwN84ezjkdY1I=
|
|
||||||
github.com/tdewolff/parse/v2 v2.8.3/go.mod h1:Hwlni2tiVNKyzR1o6nUs4FOF07URA+JLBLd6dlIXYqo=
|
|
||||||
github.com/tdewolff/test v1.0.11 h1:FdLbwQVHxqG16SlkGveC0JVyrJN62COWTRyUFzfbtBE=
|
|
||||||
github.com/tdewolff/test v1.0.11/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
|
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||||
|
@ -51,8 +45,8 @@ golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
|
||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||||
|
|
13
mpd.go
13
mpd.go
|
@ -1,13 +1,12 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"github.com/fhs/gompd/v2/mpd"
|
||||||
"strconv"
|
"github.com/labstack/echo/v4"
|
||||||
"time"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
"github.com/fhs/gompd/v2/mpd"
|
"time"
|
||||||
"github.com/labstack/echo/v4"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MPD API calls
|
// MPD API calls
|
||||||
|
|
114
option.nix
114
option.nix
|
@ -1,114 +0,0 @@
|
||||||
{ config, lib, pkgs, options, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
cfg = config.services.sanic;
|
|
||||||
configFile = pkgs.writeText "config.ini" (pkgs.lib.generators.toINI {} cfg);
|
|
||||||
execCommand = "${cfg.package}/bin/sanic -c '${configFile}'";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.services.sanic = {
|
|
||||||
enable = lib.mkEnableOption "Enables the sanic systemd service.";
|
|
||||||
package = lib.mkOption {
|
|
||||||
description = "Package to use.";
|
|
||||||
type = lib.types.package;
|
|
||||||
default = sanic;
|
|
||||||
};
|
|
||||||
ui = lib.mkOption {
|
|
||||||
description = "Setting for HTTP(S) UI.";
|
|
||||||
example = lib.literalExpression ''
|
|
||||||
{
|
|
||||||
host = "[::1]";
|
|
||||||
port = 8443;
|
|
||||||
tls = true;
|
|
||||||
certificate = "${config.security.acme.certs."sanic.example.com".directory}/fullchain.pem";
|
|
||||||
key = "${config.security.acme.certs."sanic.example.com".directory}/key.pem";
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
default = {
|
|
||||||
host = "[::1]";
|
|
||||||
port = 80;
|
|
||||||
tls = false;
|
|
||||||
};
|
|
||||||
type = lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
host = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "[::1]";
|
|
||||||
description = "Host to bind to.";
|
|
||||||
};
|
|
||||||
port = lib.mkOption {
|
|
||||||
type = lib.types.port;
|
|
||||||
default = 8080;
|
|
||||||
description = "Port to listen on.";
|
|
||||||
};
|
|
||||||
tls = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = false;
|
|
||||||
description = "Enables HTTPS.";
|
|
||||||
};
|
|
||||||
certificate = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.path;
|
|
||||||
default = null;
|
|
||||||
description = "Path to TLS certificate for HTTPS.";
|
|
||||||
};
|
|
||||||
key = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.path;
|
|
||||||
default = null;
|
|
||||||
description = "Path to TLS key for HTTPS.";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
backend = lib.mkOption {
|
|
||||||
description = "Configure MPD backend.";
|
|
||||||
example = lib.literalExpression ''
|
|
||||||
{
|
|
||||||
host = "localhost";
|
|
||||||
port = 6600;
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
default = {
|
|
||||||
host = "localhost";
|
|
||||||
port = 6600;
|
|
||||||
};
|
|
||||||
type = lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
host = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "localhost";
|
|
||||||
description = "Hostname or IP of MPD instance.";
|
|
||||||
};
|
|
||||||
port = lib.mkOption {
|
|
||||||
type = lib.types.port;
|
|
||||||
default = 6600;
|
|
||||||
description = "Port of MPD instance.";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
systemd.services."sanic" = {
|
|
||||||
description = "sanic - chaos music control";
|
|
||||||
wants = [ "network-online.target" ];
|
|
||||||
after = [ "network-online.target" ];
|
|
||||||
serviceConfig = {
|
|
||||||
Restart = "always";
|
|
||||||
RestartSec = 30;
|
|
||||||
ExecStart = execCommand;
|
|
||||||
User = "sanic";
|
|
||||||
Group = "sanic";
|
|
||||||
AmbientCapabilities = lib.mkIf (cfg.ui.port < 1000) [ "CAP_NET_BIND_SERVICE" ];
|
|
||||||
CapabilityBoundingSet = lib.mkIf (cfg.ui.port < 1000) [ "CAP_NET_BIND_SERVICE" ];
|
|
||||||
NoNewPrivileges = true;
|
|
||||||
};
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#meta = {
|
|
||||||
# maintainers = with lib.maintainers; [ xengi ];
|
|
||||||
# doc = ./default.xml;
|
|
||||||
#};
|
|
||||||
}
|
|
|
@ -26,3 +26,4 @@ TimeoutStartSec=900
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target default.target
|
WantedBy=multi-user.target default.target
|
||||||
|
|
||||||
|
|
27
server.go
27
server.go
|
@ -1,29 +1,24 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"fmt"
|
||||||
"fmt"
|
"github.com/labstack/echo-contrib/echoprometheus"
|
||||||
"net/http"
|
"github.com/labstack/echo/v4"
|
||||||
"os"
|
"github.com/labstack/echo/v4/middleware"
|
||||||
"os/exec"
|
"gopkg.in/ini.v1"
|
||||||
|
"net/http"
|
||||||
"github.com/labstack/echo-contrib/echoprometheus"
|
"os"
|
||||||
"github.com/labstack/echo/v4"
|
"os/exec"
|
||||||
"github.com/labstack/echo/v4/middleware"
|
|
||||||
"gopkg.in/ini.v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed static/*
|
// Config holds the configuration for the mpd connection and for the web server.
|
||||||
var staticFS embed.FS
|
|
||||||
|
|
||||||
// Config holds the configuration for the mpd backend connection and for the web server.
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
BACKEND struct {
|
MPD struct {
|
||||||
Hostname string `ini:"hostname"`
|
Hostname string `ini:"hostname"`
|
||||||
Port int `ini:"port"`
|
Port int `ini:"port"`
|
||||||
Username string `ini:"username"`
|
Username string `ini:"username"`
|
||||||
Password string `ini:"password"`
|
Password string `ini:"password"`
|
||||||
} `ini:"backend"`
|
} `ini:"mpd"`
|
||||||
UI struct {
|
UI struct {
|
||||||
Hostname string `ini:"hostname"`
|
Hostname string `ini:"hostname"`
|
||||||
Port int `ini:"port"`
|
Port int `ini:"port"`
|
||||||
|
|
30
services.nix
Normal file
30
services.nix
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{ self, ...}: {config, lib, pkgs, ...}:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.sanic;
|
||||||
|
format = pkgs.formats.ini { };
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services.sanic = {
|
||||||
|
enable = mkEnableOption (lib.mdDoc "sanic");
|
||||||
|
settings = mkOption {
|
||||||
|
type = format.type;
|
||||||
|
default = { };
|
||||||
|
description = lib.mkDoc ''
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
systemd.services.sanic = {
|
||||||
|
description = "chaos music control";
|
||||||
|
wantedBy = [ "multi-user.target" "default.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
DynamicUser = true;
|
||||||
|
ExecStart = "${self.packages.${pkgs.system}.default}/bin/sanic";
|
||||||
|
Restart = "on-failure";
|
||||||
|
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
15
sse.go
15
sse.go
|
@ -1,14 +1,13 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"github.com/fhs/gompd/v2/mpd"
|
||||||
"time"
|
"github.com/labstack/echo/v4"
|
||||||
|
"io"
|
||||||
"github.com/fhs/gompd/v2/mpd"
|
"time"
|
||||||
"github.com/labstack/echo/v4"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Event represents Server-Sent Event.
|
// Event represents Server-Sent Event.
|
||||||
|
|
|
@ -1,38 +1,11 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en" xmlns="http://www.w3.org/1999/html">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<meta name="robots" content="noindex, nofollow">
|
|
||||||
<meta name="application-name" content="Sanic">
|
|
||||||
|
|
||||||
<!-- seo data -->
|
|
||||||
<meta name="description" lang="en" content="chaos music control inspired by relaxx player">
|
|
||||||
<meta name="keywords" lang="en" content="music, playlist, mpd, ui">
|
|
||||||
<meta name="author" content="XenGi">
|
|
||||||
<link rel="canonical" href="https://gitlab.com/XenGi/sanic">
|
|
||||||
|
|
||||||
<!-- social media -->
|
|
||||||
<meta property="og:title" content="Sanic">
|
|
||||||
<meta property="og:description" content="chaos music control inspired by relaxx player">
|
|
||||||
<meta property="og:url" content="https://gitlab.com/XenGi/sanic">
|
|
||||||
<meta property="og:image" content="https://gitlab.com/XenGi/sanic/-/raw/main/static/img/sanic-logo.webp?ref_type=heads&inline=false">
|
|
||||||
<meta property="og:image:alt" content="Crappy picture of sonic the hedgehog">
|
|
||||||
<meta name="twitter:title" content="Sanic">
|
|
||||||
<meta name="twitter:description" content="chaos music control inspired by relaxx player">
|
|
||||||
<meta name="twitter:url" content="https://gitlab.com/XenGi/sanic">
|
|
||||||
<meta name="twitter:image:src" content="https://gitlab.com/XenGi/sanic/-/raw/main/static/img/sanic-logo.webp?ref_type=heads&inline=false">
|
|
||||||
<meta name="twitter:image:alt" content="Crappy picture of sonic the hedgehog">
|
|
||||||
|
|
||||||
<!-- icons and color -->
|
|
||||||
<meta name="theme-color" content="#000000">
|
|
||||||
<meta name="theme-scheme" content="dark">
|
|
||||||
<link rel="shortcut icon" href="/favicon.ico">
|
|
||||||
|
|
||||||
<title>Sanic</title>
|
<title>Sanic</title>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
<link rel="stylesheet" href="css/style.css">
|
<link rel="stylesheet" href="treeview.css">
|
||||||
<link rel="stylesheet" href="css/treeview.css">
|
<link rel="icon" href="favicon.ico" sizes="16x16 32x32 48x48 64x64" type="image/png">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
@ -44,7 +17,7 @@
|
||||||
<input type="text" id="control-playlist-name" name="playlist-name" autofocus>
|
<input type="text" id="control-playlist-name" name="playlist-name" autofocus>
|
||||||
<button>Save</button>
|
<button>Save</button>
|
||||||
</form>
|
</form>
|
||||||
</dialog><!--/#save-playlist-->
|
</dialog>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div id="nav">
|
<div id="nav">
|
||||||
|
@ -63,7 +36,7 @@
|
||||||
<div class="spaced">
|
<div class="spaced">
|
||||||
<label for="control-progress"></label>
|
<label for="control-progress"></label>
|
||||||
<input type="range" id="control-progress" name="progress" min="0" step="1" />
|
<input type="range" id="control-progress" name="progress" min="0" step="1" />
|
||||||
</div><!--/.spaced-->
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="spaced">
|
<div class="spaced">
|
||||||
|
@ -90,20 +63,20 @@
|
||||||
<!--<input type="text" id="control-track" name="track" disabled="disabled" />-->
|
<!--<input type="text" id="control-track" name="track" disabled="disabled" />-->
|
||||||
<div class="marquee" id="control-track" data-songid="">
|
<div class="marquee" id="control-track" data-songid="">
|
||||||
<span></span>
|
<span></span>
|
||||||
</div><!--/#control-track /.marquee-->
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="control-time">Time:</label>
|
<label for="control-time">Time:</label>
|
||||||
<input type="text" id="control-time" name="time" value="00:00:00/00:00:00" disabled="disabled" />
|
<input type="text" id="control-time" name="time" value="00:00:00/00:00:00" disabled="disabled" />
|
||||||
</div>
|
</div>
|
||||||
</div><!--/.wide-->
|
</div>
|
||||||
<div id="sanic-logo">
|
<div id="sanic-logo">
|
||||||
<div><!-- TODO: try to remove this div -->
|
<div><!-- TODO: try to remove this div -->
|
||||||
<img alt="sanic logo" src="img/sanic-logo.webp" />
|
<img alt="sanic logo" src="img/sanic-logo.webp" />
|
||||||
Sanic © 2023
|
Sanic © 2023
|
||||||
</div>
|
</div>
|
||||||
</div><!--/#sanic-logo-->
|
</div><!--/#sanic-logo-->
|
||||||
</div><!--/#nav-->
|
</div>
|
||||||
<div id="queue">
|
<div id="queue">
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -206,7 +179,7 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul><!--/#tree-->
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
actions
|
actions
|
||||||
|
|
|
@ -157,6 +157,7 @@ dialog_save_playlist_close.addEventListener("click", () => {
|
||||||
dialog_save_playlist.close()
|
dialog_save_playlist.close()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Add API calls to controls
|
// Add API calls to controls
|
||||||
|
|
||||||
control_search_submit.addEventListener("click", event => {
|
control_search_submit.addEventListener("click", event => {
|
||||||
|
@ -214,6 +215,8 @@ control_delete_playlist.addEventListener("click", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add API calls to controls
|
||||||
|
|
||||||
control_update_db.addEventListener("click", (event) => {
|
control_update_db.addEventListener("click", (event) => {
|
||||||
console.log("Issuing database update");
|
console.log("Issuing database update");
|
||||||
fetch(`${API_URL}/update_db`).then(async r => {
|
fetch(`${API_URL}/update_db`).then(async r => {
|
Loading…
Add table
Add a link
Reference in a new issue