at 23.11-pre 6.6 kB view raw
1{ config, lib, options, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.mpdscribble; 7 mpdCfg = config.services.mpd; 8 mpdOpt = options.services.mpd; 9 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 }; 16 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 ''; 24 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. 29 30 ## mpdscribble - an audioscrobbler for the Music Player Daemon. 31 ## http://mpd.wikia.com/wiki/Client:mpdscribble 32 33 # HTTP proxy URL. 34 ${optionalString (cfg.proxy != null) "proxy = ${cfg.proxy}"} 35 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 = - 41 42 # How verbose mpdscribble's logging should be. Default is 1. 43 verbose = ${toString cfg.verbose} 44 45 # How often should mpdscribble save the journal file? [seconds] 46 journal_interval = ${toString cfg.journalInterval} 47 48 # The host running MPD, possibly protected by a password 49 # ([PASSWORD@]HOSTNAME). 50 host = ${(optionalString (cfg.passwordFile != null) "{{MPD_PASSWORD}}@") + cfg.host} 51 52 # The port that the MPD listens on and mpdscribble should try to 53 # connect to. 54 port = ${toString cfg.port} 55 56 ${endpoints} 57 ''; 58 59 cfgFile = "/run/mpdscribble/mpdscribble.conf"; 60 61 replaceSecret = secretFile: placeholder: targetFile: 62 optionalString (secretFile != null) '' 63 ${pkgs.replace-secret}/bin/replace-secret '${placeholder}' '${secretFile}' '${targetFile}' ''; 64 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 ''; 72 73 localMpd = (cfg.host == "localhost" || cfg.host == "127.0.0.1"); 74 75in { 76 ###### interface 77 78 options.services.mpdscribble = { 79 80 enable = mkEnableOption (lib.mdDoc "mpdscribble"); 81 82 proxy = mkOption { 83 default = null; 84 type = types.nullOr types.str; 85 description = lib.mdDoc '' 86 HTTP proxy URL. 87 ''; 88 }; 89 90 verbose = mkOption { 91 default = 1; 92 type = types.int; 93 description = lib.mdDoc '' 94 Log level for the mpdscribble daemon. 95 ''; 96 }; 97 98 journalInterval = mkOption { 99 default = 600; 100 example = 60; 101 type = types.int; 102 description = lib.mdDoc '' 103 How often should mpdscribble save the journal file? [seconds] 104 ''; 105 }; 106 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 = lib.mdDoc '' 119 Host for the mpdscribble daemon to search for a mpd daemon on. 120 ''; 121 }; 122 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 = lib.mdDoc '' 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 }; 142 143 port = mkOption { 144 default = mpdCfg.network.port; 145 defaultText = literalExpression "config.${mpdOpt.network.port}"; 146 type = types.port; 147 description = lib.mdDoc '' 148 Port for the mpdscribble daemon to search for a mpd daemon on. 149 ''; 150 }; 151 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 = 160 lib.mdDoc "The url endpoint where the scrobble API is listening."; 161 }; 162 username = mkOption { 163 type = types.str; 164 description = lib.mdDoc '' 165 Username for the scrobble service. 166 ''; 167 }; 168 passwordFile = mkOption { 169 type = types.nullOr types.str; 170 description = 171 lib.mdDoc "File containing the password, either as MD5SUM or cleartext."; 172 }; 173 }; 174 }; 175 in types.attrsOf (types.submodule endpoint)); 176 default = { }; 177 example = { 178 "last.fm" = { 179 username = "foo"; 180 passwordFile = "/run/secrets/lastfm_password"; 181 }; 182 }; 183 description = lib.mdDoc '' 184 Endpoints to scrobble to. 185 If the endpoint is one of "${ 186 concatStringsSep "\", \"" (attrNames endpointUrls) 187 }" the url is set automatically. 188 ''; 189 }; 190 191 }; 192 193 ###### implementation 194 195 config = mkIf cfg.enable { 196 systemd.services.mpdscribble = { 197 after = [ "network.target" ] ++ (optional localMpd "mpd.service"); 198 description = "mpdscribble mpd scrobble client"; 199 wantedBy = [ "multi-user.target" ]; 200 serviceConfig = { 201 DynamicUser = true; 202 StateDirectory = "mpdscribble"; 203 RuntimeDirectory = "mpdscribble"; 204 RuntimeDirectoryMode = "700"; 205 # TODO use LoadCredential= instead of running preStart with full privileges? 206 ExecStartPre = "+${preStart}"; 207 ExecStart = 208 "${pkgs.mpdscribble}/bin/mpdscribble --no-daemon --conf ${cfgFile}"; 209 }; 210 }; 211 }; 212 213}