vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / audio / mpdscribble.nix
blob3c7270a3a4a4cf9cc42f223c305e172789ed23b7
1 { config, lib, options, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.services.mpdscribble;
7   mpdCfg = config.services.mpd;
8   mpdOpt = options.services.mpd;
10   endpointUrls = {
11     "last.fm" = "http://post.audioscrobbler.com";
12     "libre.fm" = "http://turtle.libre.fm";
13     "jamendo" = "http://postaudioscrobbler.jamendo.com";
14     "listenbrainz" = "http://proxy.listenbrainz.org";
15   };
17   mkSection = secname: secCfg: ''
18     [${secname}]
19     url      = ${secCfg.url}
20     username = ${secCfg.username}
21     password = {{${secname}_PASSWORD}}
22     journal  = /var/lib/mpdscribble/${secname}.journal
23   '';
25   endpoints = concatStringsSep "\n" (mapAttrsToList mkSection cfg.endpoints);
26   cfgTemplate = pkgs.writeText "mpdscribble.conf" ''
27     ## This file was automatically genenrated by NixOS and will be overwritten.
28     ## Do not edit. Edit your NixOS configuration instead.
30     ## mpdscribble - an audioscrobbler for the Music Player Daemon.
31     ## http://mpd.wikia.com/wiki/Client:mpdscribble
33     # HTTP proxy URL.
34     ${optionalString (cfg.proxy != null) "proxy = ${cfg.proxy}"}
36     # The location of the mpdscribble log file.  The special value
37     # "syslog" makes mpdscribble use the local syslog daemon.  On most
38     # systems, log messages will appear in /var/log/daemon.log then.
39     # "-" means log to stderr (the current terminal).
40     log = -
42     # How verbose mpdscribble's logging should be.  Default is 1.
43     verbose = ${toString cfg.verbose}
45     # How often should mpdscribble save the journal file? [seconds]
46     journal_interval = ${toString cfg.journalInterval}
48     # The host running MPD, possibly protected by a password
49     # ([PASSWORD@]HOSTNAME).
50     host = ${(optionalString (cfg.passwordFile != null) "{{MPD_PASSWORD}}@") + cfg.host}
52     # The port that the MPD listens on and mpdscribble should try to
53     # connect to.
54     port = ${toString cfg.port}
56     ${endpoints}
57   '';
59   cfgFile = "/run/mpdscribble/mpdscribble.conf";
61   replaceSecret = secretFile: placeholder: targetFile:
62     optionalString (secretFile != null) ''
63       ${pkgs.replace-secret}/bin/replace-secret '${placeholder}' '${secretFile}' '${targetFile}' '';
65   preStart = pkgs.writeShellScript "mpdscribble-pre-start" ''
66     cp -f "${cfgTemplate}" "${cfgFile}"
67     ${replaceSecret cfg.passwordFile "{{MPD_PASSWORD}}" cfgFile}
68     ${concatStringsSep "\n" (mapAttrsToList (secname: cfg:
69       replaceSecret cfg.passwordFile "{{${secname}_PASSWORD}}" cfgFile)
70       cfg.endpoints)}
71   '';
73   localMpd = (cfg.host == "localhost" || cfg.host == "127.0.0.1");
75 in {
76   ###### interface
78   options.services.mpdscribble = {
80     enable = mkEnableOption "mpdscribble, an MPD client which submits info about tracks being played to Last.fm (formerly AudioScrobbler)";
82     proxy = mkOption {
83       default = null;
84       type = types.nullOr types.str;
85       description = ''
86         HTTP proxy URL.
87       '';
88     };
90     verbose = mkOption {
91       default = 1;
92       type = types.int;
93       description = ''
94         Log level for the mpdscribble daemon.
95       '';
96     };
98     journalInterval = mkOption {
99       default = 600;
100       example = 60;
101       type = types.int;
102       description = ''
103         How often should mpdscribble save the journal file? [seconds]
104       '';
105     };
107     host = mkOption {
108       default = (if mpdCfg.network.listenAddress != "any" then
109         mpdCfg.network.listenAddress
110       else
111         "localhost");
112       defaultText = literalExpression ''
113         if config.${mpdOpt.network.listenAddress} != "any"
114         then config.${mpdOpt.network.listenAddress}
115         else "localhost"
116       '';
117       type = types.str;
118       description = ''
119         Host for the mpdscribble daemon to search for a mpd daemon on.
120       '';
121     };
123     passwordFile = mkOption {
124       default = if localMpd then
125         (findFirst
126           (c: any (x: x == "read") c.permissions)
127           { passwordFile = null; }
128           mpdCfg.credentials).passwordFile
129       else
130         null;
131       defaultText = literalMD ''
132         The first password file with read access configured for MPD when using a local instance,
133         otherwise `null`.
134       '';
135       type = types.nullOr types.str;
136       description = ''
137         File containing the password for the mpd daemon.
138         If there is a local mpd configured using {option}`services.mpd.credentials`
139         the default is automatically set to a matching passwordFile of the local mpd.
140       '';
141     };
143     port = mkOption {
144       default = mpdCfg.network.port;
145       defaultText = literalExpression "config.${mpdOpt.network.port}";
146       type = types.port;
147       description = ''
148         Port for the mpdscribble daemon to search for a mpd daemon on.
149       '';
150     };
152     endpoints = mkOption {
153       type = (let
154         endpoint = { name, ... }: {
155           options = {
156             url = mkOption {
157               type = types.str;
158               default = endpointUrls.${name} or "";
159               description = "The url endpoint where the scrobble API is listening.";
160             };
161             username = mkOption {
162               type = types.str;
163               description = ''
164                 Username for the scrobble service.
165               '';
166             };
167             passwordFile = mkOption {
168               type = types.nullOr types.str;
169               description = "File containing the password, either as MD5SUM or cleartext.";
170             };
171           };
172         };
173       in types.attrsOf (types.submodule endpoint));
174       default = { };
175       example = {
176         "last.fm" = {
177           username = "foo";
178           passwordFile = "/run/secrets/lastfm_password";
179         };
180       };
181       description = ''
182         Endpoints to scrobble to.
183         If the endpoint is one of "${
184           concatStringsSep "\", \"" (attrNames endpointUrls)
185         }" the url is set automatically.
186       '';
187     };
189   };
191   ###### implementation
193   config = mkIf cfg.enable {
194     systemd.services.mpdscribble = {
195       after = [ "network.target" ] ++ (optional localMpd "mpd.service");
196       description = "mpdscribble mpd scrobble client";
197       wantedBy = [ "multi-user.target" ];
198       serviceConfig = {
199         DynamicUser = true;
200         StateDirectory = "mpdscribble";
201         RuntimeDirectory = "mpdscribble";
202         RuntimeDirectoryMode = "700";
203         # TODO use LoadCredential= instead of running preStart with full privileges?
204         ExecStartPre = "+${preStart}";
205         ExecStart =
206           "${pkgs.mpdscribble}/bin/mpdscribble --no-daemon --conf ${cfgFile}";
207       };
208     };
209   };