This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

superconfig / 2configs / services / radio / default.nix
12 kB 351 lines
1{ self, config, pkgs, lib, ... }: 2 3let 4 name = "radio"; 5 6 music_dir = "/var/music"; 7 8 skip_track = pkgs.writers.writeBashBin "skip_track" '' 9 set -eu 10 11 # TODO come up with new rating, without moving files 12 # current_track=$(${pkgs.curl}/bin/curl -fSs http://localhost:8002/current | ${pkgs.jq}/bin/jq -r .filename) 13 # track_infos=$(${print_current}/bin/print_current) 14 # skip_count=$(${pkgs.attr}/bin/getfattr -n user.skip_count --only-values "$current_track" || echo 0) 15 # if [[ "$current_track" =~ .*/the_playlist/music/.* ]] && [ "$skip_count" -le 2 ]; then 16 # skip_count=$((skip_count+1)) 17 # ${pkgs.attr}/bin/setfattr -n user.skip_count -v "$skip_count" "$current_track" 18 # echo skipping: "$track_infos" skip_count: "$skip_count" 19 # else 20 # mkdir -p "$music_dir"/the_playlist/.graveyard/ 21 # mv "$current_track" "$music_dir"/the_playlist/.graveyard/ 22 # echo killing: "$track_infos" 23 # fi 24 ${pkgs.curl}/bin/curl -fSs -X POST http://localhost:8002/skip | 25 ${pkgs.jq}/bin/jq -r '.filename' 26 ''; 27 28 good_track = pkgs.writeBashBin "good_track" '' 29 set -eu 30 31 current_track=$(${pkgs.curl}/bin/curl -fSs http://localhost:8002/current | ${pkgs.jq}/bin/jq -r .filename) 32 track_infos=$(${print_current}/bin/print_current) 33 # TODO come up with new rating, without moving files 34 # if [[ "$current_track" =~ .*/the_playlist/music/.* ]]; then 35 # ${pkgs.attr}/bin/setfattr -n user.skip_count -v 0 "$current_track" 36 # else 37 # mv "$current_track" "$music_dir"/the_playlist/music/ || : 38 # fi 39 echo good: "$track_infos" 40 ''; 41 42 print_current = pkgs.writeDashBin "print_current" '' 43 file=$(${pkgs.curl}/bin/curl -fSs http://localhost:8002/current | 44 ${pkgs.jq}/bin/jq -r '.filename' | 45 ${pkgs.gnused}/bin/sed 's,^${music_dir},,' 46 ) 47 link=$(${pkgs.curl}/bin/curl http://localhost:8002/current | 48 ${pkgs.jq}/bin/jq -r '.filename' | 49 ${pkgs.gnused}/bin/sed 's@.*\(.\{11\}\)\.ogg@https://youtu.be/\1@' 50 ) 51 echo "$file": "$link" 52 ''; 53 54 set_irc_topic = pkgs.writeDash "set_irc_topic" '' 55 ${pkgs.curl}/bin/curl -fsS --unix-socket /home/radio/reaktor.sock http://z/ \ 56 -H content-type:application/json \ 57 -d "$(${pkgs.jq}/bin/jq -n \ 58 --arg text "$1" '{ 59 command:"TOPIC", 60 params:["#the_playlist",$text] 61 }' 62 )" 63 ''; 64 65 write_to_irc = pkgs.writeDash "write_to_irc" '' 66 ${pkgs.curl}/bin/curl -fsSv --unix-socket /home/radio/reaktor.sock http://z/ \ 67 -H content-type:application/json \ 68 -d "$(${pkgs.jq}/bin/jq -n \ 69 --arg text "$1" '{ 70 command:"PRIVMSG", 71 params:["#the_playlist",$text] 72 }' 73 )" 74 ''; 75 76in { 77 imports = [ 78 ./news.nix 79 ./weather.nix 80 self.inputs.stockholm.nixosModules.acl 81 self.inputs.stockholm.nixosModules.reaktor2 82 ]; 83 84 users.users = { 85 "${name}" = rec { 86 inherit name; 87 createHome = true; 88 group = name; 89 uid = pkgs.stockholm.lib.genid_uint31 name; 90 description = "radio manager"; 91 home = "/home/${name}"; 92 useDefaultShell = true; 93 openssh.authorizedKeys.keys = with config.krebs.users; [ 94 lass.pubkey 95 ]; 96 packages = [ 97 good_track 98 skip_track 99 print_current 100 ]; 101 }; 102 }; 103 104 users.groups = { 105 "radio" = {}; 106 }; 107 108 systemd.services.radio_watcher = { 109 wantedBy = [ "multi-user.target" ]; 110 after = [ "radio.service" ]; 111 serviceConfig = { 112 ExecStart = pkgs.writers.writeDash "radio_watcher" '' 113 set -efux 114 while :; do 115 ${pkgs.curl}/bin/curl -Ss http://localhost:8000/radio.ogg -o /dev/null 116 ${pkgs.systemd}/bin/systemctl restart radio 117 sleep 60 118 done 119 ''; 120 Restart = "on-failure"; 121 }; 122 }; 123 124 services.liquidsoap.streams.radio = ./radio.liq; 125 systemd.services.radio = { 126 environment = { 127 RADIO_PORT = "8002"; 128 HOOK_TRACK_CHANGE = pkgs.writers.writeDash "on_change" '' 129 set -xefu 130 LIMIT=1000 #how many tracks to keep in the history 131 HISTORY_FILE=/var/lib/radio/recent 132 133 listeners=$(${pkgs.curl}/bin/curl -fSs http://localhost:8000/status-json.xsl | 134 ${pkgs.jq}/bin/jq '[.icestats.source[].listeners] | add' || echo 0) 135 echo "$(${pkgs.coreutils}/bin/date -Is)" "$filename" | ${pkgs.coreutils}/bin/tee -a "$HISTORY_FILE" 136 echo "$(${pkgs.coreutils}/bin/tail -$LIMIT "$HISTORY_FILE")" > "$HISTORY_FILE" 137 ${set_irc_topic} "playing: $filename listeners: $listeners" 138 ''; 139 MUSIC = "${music_dir}/the_playlist"; 140 ICECAST_HOST = "localhost"; 141 }; 142 path = [ 143 pkgs.yt-dlp 144 pkgs.bubblewrap 145 ]; 146 serviceConfig.User = lib.mkForce "radio"; 147 }; 148 149 nixpkgs.config.packageOverrides = opkgs: { 150 liquidsoap = opkgs.liquidsoap.override { 151 runtimePackages = with opkgs; [ bubblewrap curl ffmpeg yt-dlp ]; 152 }; 153 icecast = opkgs.icecast.overrideAttrs (old: rec { 154 version = "2.5-beta3"; 155 156 src = pkgs.fetchurl { 157 url = "http://downloads.xiph.org/releases/icecast/icecast-${version}.tar.gz"; 158 sha256 = "sha256-4FDokoA9zBDYj8RAO/kuTHaZ6jZYBLSJZiX/IYFaCW8="; 159 }; 160 161 buildInputs = old.buildInputs ++ [ pkgs.pkg-config ]; 162 }); 163 }; 164 services.icecast = { 165 enable = true; 166 hostname = "radio.lassul.us"; 167 admin.password = "hackme"; 168 extraConf = '' 169 <authentication> 170 <source-password>hackme</source-password> 171 <admin-user>admin</admin-user> 172 <admin-password>hackme</admin-password> 173 </authentication> 174 <logging> 175 <accesslog>-</accesslog> 176 <errorlog>-</errorlog> 177 <loglevel>3</loglevel> 178 </logging> 179 ''; 180 }; 181 182 krebs.iptables = { 183 tables = { 184 filter.INPUT.rules = [ 185 { predicate = "-p tcp --dport 8000"; target = "ACCEPT"; } 186 { predicate = "-i retiolum -p tcp --dport 8001"; target = "ACCEPT"; } 187 { predicate = "-i retiolum -p tcp --dport 8002"; target = "ACCEPT"; } 188 ]; 189 }; 190 }; 191 192 # allow reaktor2 to modify files 193 systemd.services."reaktor2-the_playlist".serviceConfig.DynamicUser = lib.mkForce false; 194 systemd.services."reaktor2-the_playlist".serviceConfig.Group = lib.mkForce "radio"; 195 196 krebs.reaktor2.the_playlist = { 197 hostname = "irc.hackint.org"; 198 port = "6697"; 199 useTLS = true; 200 nick = "the_playlist"; 201 username = "radio"; 202 API.listen = "unix:/home/radio/reaktor.sock"; 203 plugins = [ 204 { 205 plugin = "register"; 206 config = { 207 channels = [ 208 "#the_playlist" 209 "#krebs" 210 ]; 211 }; 212 } 213 { 214 plugin = "system"; 215 config = { 216 workdir = config.krebs.reaktor2.the_playlist.stateDir; 217 hooks.PRIVMSG = [ 218 { 219 activate = "match"; 220 pattern = "^(?:.*\\s)?\\s*the_playlist:\\s*([0-9A-Za-z._][0-9A-Za-z._-]*)(?:\\s+(.*\\S))?\\s*$"; 221 command = 1; 222 arguments = [2]; 223 commands = { 224 skip.filename = "${skip_track}/bin/skip_track"; 225 next.filename = "${skip_track}/bin/skip_track"; 226 bad.filename = "${skip_track}/bin/skip_track"; 227 228 good.filename = "${good_track}/bin/good_track"; 229 nice.filename = "${good_track}/bin/good_track"; 230 like.filename = "${good_track}/bin/good_track"; 231 232 current.filename = "${print_current}/bin/print_current"; 233 wish.filename = pkgs.writeDash "wish" '' 234 echo "youtube-dl:$1" | ${pkgs.curl}/bin/curl -fSs http://localhost:8002/wish -d @- > /dev/null 235 ''; 236 wishlist.filename = pkgs.writeDash "wishlist" '' 237 ${pkgs.curl}/bin/curl -fSs http://localhost:8002/wish | ${pkgs.jq}/bin/jq -r '.[]' 238 ''; 239 suggest.filename = pkgs.writeDash "suggest" '' 240 echo "$@" >> playlist_suggest 241 ''; 242 }; 243 } 244 ]; 245 }; 246 } 247 ]; 248 }; 249 250 krebs.htgen.radio = { 251 port = 8001; 252 user = { 253 name = "radio"; 254 }; 255 scriptFile = pkgs.writeDash "radio" '' 256 case "$Method $Request_URI" in 257 "POST /skip") 258 printf 'HTTP/1.1 200 OK\r\n' 259 printf 'Connection: close\r\n' 260 printf '\r\n' 261 msg=$(${skip_track}/bin/skip_track) 262 ${write_to_irc} "$msg" 263 echo "$msg" 264 exit 265 ;; 266 "POST /good") 267 printf 'HTTP/1.1 200 OK\r\n' 268 printf 'Connection: close\r\n' 269 printf '\r\n' 270 msg=$(${good_track}/bin/good_track) 271 ${write_to_irc} "$msg" 272 echo "$msg" 273 exit 274 ;; 275 esac 276 ''; 277 }; 278 279 networking.firewall.allowedTCPPorts = [ 80 ]; 280 services.nginx = { 281 enable = true; 282 virtualHosts."radio.r" = { 283 locations."/".extraConfig = '' 284 # https://github.com/aswild/icecast-notes#core-nginx-config 285 proxy_pass http://localhost:8000; 286 # Disable request size limit, very important for uploading large files 287 client_max_body_size 0; 288 289 # Enable support `Transfer-Encoding: chunked` 290 chunked_transfer_encoding on; 291 292 # Disable request and response buffering, minimize latency to/from Icecast 293 proxy_buffering off; 294 proxy_request_buffering off; 295 296 # Icecast needs HTTP/1.1, not 1.0 or 2 297 proxy_http_version 1.1; 298 299 # Forward all original request headers 300 proxy_pass_request_headers on; 301 302 # Set some standard reverse proxy headers. Icecast server currently ignores these, 303 # but may support them in a future version so that access logs are more useful. 304 proxy_set_header Host $host; 305 proxy_set_header X-Real-IP $remote_addr; 306 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 307 proxy_set_header X-Forwarded-Proto $scheme; 308 309 # get source ip for weather reports 310 proxy_set_header user-agent "$http_user_agent; client-ip=$remote_addr"; 311 ''; 312 locations."= /recent".extraConfig = '' 313 default_type "text/plain"; 314 alias /var/lib/radio/recent; 315 ''; 316 locations."= /current".extraConfig = '' 317 proxy_pass http://localhost:8002; 318 ''; 319 locations."= /skip".extraConfig = '' 320 proxy_pass http://localhost:8001; 321 ''; 322 locations."= /good".extraConfig = '' 323 proxy_pass http://localhost:8001; 324 ''; 325 locations."= /radio.sh".alias = pkgs.writeScript "radio.sh" '' 326 #!/bin/sh 327 trap 'exit 0' EXIT 328 while sleep 1; do 329 mpv \ 330 --cache-secs=0 --demuxer-readahead-secs=0 --untimed --cache-pause=no \ 331 'http://radio.lassul.us/radio.ogg' 332 done 333 ''; 334 locations."= /controls".extraConfig = '' 335 default_type "text/html"; 336 alias ${./controls.html}; 337 ''; 338 extraConfig = '' 339 add_header 'Access-Control-Allow-Origin' '*'; 340 add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; 341 ''; 342 }; 343 }; 344 services.syncthing.declarative.folders."/home/lass/tmp/the_playlist" = { 345 path = lib.mkForce "/var/music/the_playlist"; 346 devices = [ "mors" "phone" "prism" "omo" "radio" ]; 347 }; 348 krebs.acl."/var/music/the_playlist"."u:lass:X".parents = true; 349 krebs.acl."/var/music/the_playlist"."u:lass:rwX" = {}; 350 krebs.acl."/var/music/the_playlist"."u:radio:rwX" = {}; 351}