From 622fa73725caa1f11ae184e70b406b207875ef9d Mon Sep 17 00:00:00 2001
From: Sefa Eyeoglu <contact@scrumplex.net>
Date: Thu, 11 May 2023 14:03:54 +0200
Subject: [PATCH] beets: add mpdIntegration (#3755)

Allow configuration of mpdstats and mpdupdate plugins for Beets using
Home Manager.

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
---
 .github/CODEOWNERS                            |  3 +-
 modules/programs/beets.nix                    | 55 +++++++++++++++++--
 tests/default.nix                             |  1 +
 tests/modules/programs/beets/default.nix      |  5 ++
 .../programs/beets/mpdstats-expected.service  | 10 ++++
 .../programs/beets/mpdstats-expected.yaml     |  5 ++
 .../beets/mpdstats-external-expected.service  |  8 +++
 .../beets/mpdstats-external-expected.yaml     |  5 ++
 .../programs/beets/mpdstats-external.nix      | 29 ++++++++++
 tests/modules/programs/beets/mpdstats.nix     | 31 +++++++++++
 .../programs/beets/mpdupdate-expected.yaml    |  5 ++
 tests/modules/programs/beets/mpdupdate.nix    | 20 +++++++
 12 files changed, 170 insertions(+), 7 deletions(-)
 create mode 100644 tests/modules/programs/beets/default.nix
 create mode 100644 tests/modules/programs/beets/mpdstats-expected.service
 create mode 100644 tests/modules/programs/beets/mpdstats-expected.yaml
 create mode 100644 tests/modules/programs/beets/mpdstats-external-expected.service
 create mode 100644 tests/modules/programs/beets/mpdstats-external-expected.yaml
 create mode 100644 tests/modules/programs/beets/mpdstats-external.nix
 create mode 100644 tests/modules/programs/beets/mpdstats.nix
 create mode 100644 tests/modules/programs/beets/mpdupdate-expected.yaml
 create mode 100644 tests/modules/programs/beets/mpdupdate.nix

diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index d84819190..50e538e47 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -84,7 +84,8 @@ Makefile                                              @thiagokokada
 
 /modules/programs/bat.nix                             @marsam
 
-/modules/programs/beets.nix                           @rycee
+/modules/programs/beets.nix                           @rycee @Scrumplex
+/tests/modules/programs/beets                         @Scrumplex
 
 /modules/programs/bottom.nix                          @polykernel
 /tests/modules/programs/bottom                        @polykernel
diff --git a/modules/programs/beets.nix b/modules/programs/beets.nix
index fa959669c..f8399a483 100644
--- a/modules/programs/beets.nix
+++ b/modules/programs/beets.nix
@@ -9,7 +9,7 @@ let
   yamlFormat = pkgs.formats.yaml { };
 
 in {
-  meta.maintainers = [ maintainers.rycee ];
+  meta.maintainers = with maintainers; [ rycee Scrumplex ];
 
   options = {
     programs.beets = {
@@ -48,13 +48,56 @@ in {
           <filename>$XDG_CONFIG_HOME/beets/config.yaml</filename>
         '';
       };
+
+      mpdIntegration = {
+        enableStats = mkEnableOption "mpdstats plugin and service";
+        enableUpdate = mkEnableOption "mpdupdate plugin";
+        host = mkOption {
+          type = types.str;
+          default = "localhost";
+          description = "Host mpdstats will connect to";
+          example = "10.0.0.42";
+        };
+        port = mkOption {
+          type = types.port;
+          default = config.services.mpd.network.port;
+          defaultText = literalExpression "config.services.mpd.network.port";
+          description = "Port mpdstats will connect to";
+          example = 6601;
+        };
+      };
     };
   };
 
-  config = mkIf cfg.enable {
-    home.packages = [ cfg.package ];
+  config = mkMerge [
+    (mkIf cfg.enable {
+      home.packages = [ cfg.package ];
 
-    xdg.configFile."beets/config.yaml".source =
-      yamlFormat.generate "beets-config" cfg.settings;
-  };
+      xdg.configFile."beets/config.yaml".source =
+        yamlFormat.generate "beets-config" cfg.settings;
+    })
+    (mkIf (cfg.mpdIntegration.enableStats || cfg.mpdIntegration.enableUpdate) {
+      programs.beets.settings.mpd = {
+        host = cfg.mpdIntegration.host;
+        port = cfg.mpdIntegration.port;
+      };
+    })
+    (mkIf cfg.mpdIntegration.enableStats {
+      programs.beets.settings.plugins = [ "mpdstats" ];
+    })
+    (mkIf cfg.mpdIntegration.enableUpdate {
+      programs.beets.settings.plugins = [ "mpdupdate" ];
+    })
+    (mkIf (cfg.enable && cfg.mpdIntegration.enableStats) {
+      systemd.user.services."beets-mpdstats" = {
+        Unit = {
+          Description = "Beets MPDStats daemon";
+          After = optional config.services.mpd.enable "mpd.service";
+          Requires = optional config.services.mpd.enable "mpd.service";
+        };
+        Service.ExecStart = "${cfg.package}/bin/beet mpdstats";
+        Install.WantedBy = [ "default.target" ];
+      };
+    })
+  ];
 }
diff --git a/tests/default.nix b/tests/default.nix
index b7a3c4322..979626880 100644
--- a/tests/default.nix
+++ b/tests/default.nix
@@ -152,6 +152,7 @@ import nmt {
     ./modules/misc/xsession
     ./modules/programs/abook
     ./modules/programs/autorandr
+    ./modules/programs/beets  # One test relies on services.mpd
     ./modules/programs/borgmatic
     ./modules/programs/firefox
     ./modules/programs/foot
diff --git a/tests/modules/programs/beets/default.nix b/tests/modules/programs/beets/default.nix
new file mode 100644
index 000000000..93bf207c6
--- /dev/null
+++ b/tests/modules/programs/beets/default.nix
@@ -0,0 +1,5 @@
+{
+  beets-mpdstats = ./mpdstats.nix;
+  beets-mpdstats-external = ./mpdstats-external.nix;
+  beets-mpdupdate = ./mpdupdate.nix;
+}
diff --git a/tests/modules/programs/beets/mpdstats-expected.service b/tests/modules/programs/beets/mpdstats-expected.service
new file mode 100644
index 000000000..3f1dbf63b
--- /dev/null
+++ b/tests/modules/programs/beets/mpdstats-expected.service
@@ -0,0 +1,10 @@
+[Install]
+WantedBy=default.target
+
+[Service]
+ExecStart=@beets@/bin/beet mpdstats
+
+[Unit]
+After=mpd.service
+Description=Beets MPDStats daemon
+Requires=mpd.service
diff --git a/tests/modules/programs/beets/mpdstats-expected.yaml b/tests/modules/programs/beets/mpdstats-expected.yaml
new file mode 100644
index 000000000..4f3e6b0a9
--- /dev/null
+++ b/tests/modules/programs/beets/mpdstats-expected.yaml
@@ -0,0 +1,5 @@
+mpd:
+  host: localhost
+  port: 4242
+plugins:
+- mpdstats
diff --git a/tests/modules/programs/beets/mpdstats-external-expected.service b/tests/modules/programs/beets/mpdstats-external-expected.service
new file mode 100644
index 000000000..85efc1f50
--- /dev/null
+++ b/tests/modules/programs/beets/mpdstats-external-expected.service
@@ -0,0 +1,8 @@
+[Install]
+WantedBy=default.target
+
+[Service]
+ExecStart=@beets@/bin/beet mpdstats
+
+[Unit]
+Description=Beets MPDStats daemon
diff --git a/tests/modules/programs/beets/mpdstats-external-expected.yaml b/tests/modules/programs/beets/mpdstats-external-expected.yaml
new file mode 100644
index 000000000..ce4784df8
--- /dev/null
+++ b/tests/modules/programs/beets/mpdstats-external-expected.yaml
@@ -0,0 +1,5 @@
+mpd:
+  host: 10.0.0.42
+  port: 6601
+plugins:
+- mpdstats
diff --git a/tests/modules/programs/beets/mpdstats-external.nix b/tests/modules/programs/beets/mpdstats-external.nix
new file mode 100644
index 000000000..f7e6d5b16
--- /dev/null
+++ b/tests/modules/programs/beets/mpdstats-external.nix
@@ -0,0 +1,29 @@
+{ config, lib, pkgs, ... }:
+
+{
+  config = {
+    home.stateVersion = "23.05";
+
+    programs.beets = {
+      enable = true;
+      package = config.lib.test.mkStubPackage { outPath = "@beets@"; };
+      mpdIntegration = {
+        enableStats = true;
+        host = "10.0.0.42";
+        port = 6601;
+      };
+    };
+
+    nmt.script = ''
+      assertFileExists home-files/.config/beets/config.yaml
+      assertFileContent \
+        home-files/.config/beets/config.yaml \
+        ${./mpdstats-external-expected.yaml}
+
+      assertFileExists home-files/.config/systemd/user/beets-mpdstats.service
+      assertFileContent \
+        home-files/.config/systemd/user/beets-mpdstats.service \
+        ${./mpdstats-external-expected.service}
+    '';
+  };
+}
diff --git a/tests/modules/programs/beets/mpdstats.nix b/tests/modules/programs/beets/mpdstats.nix
new file mode 100644
index 000000000..b4fba4a41
--- /dev/null
+++ b/tests/modules/programs/beets/mpdstats.nix
@@ -0,0 +1,31 @@
+{ config, lib, pkgs, ... }:
+
+{
+  config = {
+    home.stateVersion = "23.05";
+
+    services.mpd = {
+      enable = true;
+      musicDirectory = "/my/music/dir";
+      network.port = 4242;
+    };
+
+    programs.beets = {
+      enable = true;
+      package = config.lib.test.mkStubPackage { outPath = "@beets@"; };
+      mpdIntegration.enableStats = true;
+    };
+
+    nmt.script = ''
+      assertFileExists home-files/.config/beets/config.yaml
+      assertFileContent \
+        home-files/.config/beets/config.yaml \
+        ${./mpdstats-expected.yaml}
+
+      assertFileExists home-files/.config/systemd/user/beets-mpdstats.service
+      assertFileContent \
+        home-files/.config/systemd/user/beets-mpdstats.service \
+        ${./mpdstats-expected.service}
+    '';
+  };
+}
diff --git a/tests/modules/programs/beets/mpdupdate-expected.yaml b/tests/modules/programs/beets/mpdupdate-expected.yaml
new file mode 100644
index 000000000..1f998bd9a
--- /dev/null
+++ b/tests/modules/programs/beets/mpdupdate-expected.yaml
@@ -0,0 +1,5 @@
+mpd:
+  host: localhost
+  port: 6600
+plugins:
+- mpdupdate
diff --git a/tests/modules/programs/beets/mpdupdate.nix b/tests/modules/programs/beets/mpdupdate.nix
new file mode 100644
index 000000000..3516ae205
--- /dev/null
+++ b/tests/modules/programs/beets/mpdupdate.nix
@@ -0,0 +1,20 @@
+{ config, lib, pkgs, ... }:
+
+{
+  config = {
+    home.stateVersion = "23.05";
+
+    programs.beets = {
+      enable = true;
+      package = config.lib.test.mkStubPackage { outPath = "@beets@"; };
+      mpdIntegration.enableUpdate = true;
+    };
+
+    nmt.script = ''
+      assertFileExists home-files/.config/beets/config.yaml
+      assertFileContent \
+        home-files/.config/beets/config.yaml \
+        ${./mpdupdate-expected.yaml}
+    '';
+  };
+}