ops-jrz1/modules/musiclink.nix

137 lines
4.1 KiB
Nix

{ config, pkgs, lib, musiclink, ... }:
with lib;
let
cfg = config.services.musiclink;
musiclinkPkg = musiclink; # musiclink input passed via specialArgs is the package set? No, usually it's the flake itself if not mapped.
# But in flake.nix we did: musiclink = inputs.musiclink.packages.x86_64-linux.default;
# So `musiclink` here is the package.
in {
options.services.musiclink = {
enable = mkEnableOption "MusicLink bot with Matterbridge";
package = mkOption {
type = types.package;
default = musiclink;
description = "The MusicLink bot package";
};
matterbridge = {
enable = mkOption {
type = types.bool;
default = true;
description = "Enable bundled Matterbridge instance";
};
port = mkOption {
type = types.port;
default = 4242;
description = "Matterbridge API port";
};
slackChannel = mkOption {
type = types.str;
default = "music";
description = "Slack channel to bridge";
};
};
};
config = mkIf cfg.enable {
# -------------------------------------------------------------------------
# Matterbridge Service
# -------------------------------------------------------------------------
systemd.services.musiclink-matterbridge = mkIf cfg.matterbridge.enable {
description = "Matterbridge for MusicLink";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
DynamicUser = true;
StateDirectory = "musiclink-matterbridge";
WorkingDirectory = "/var/lib/musiclink-matterbridge";
# Secrets
LoadCredential = [
"slack-bot-token:/run/secrets/slack-bot-token"
"slack-app-token:/run/secrets/slack-app-token"
];
ExecStartPre = pkgs.writeShellScript "generate-matterbridge-config" ''
set -euo pipefail
SLACK_TOKEN=$(cat $CREDENTIALS_DIRECTORY/slack-bot-token)
SLACK_APP_TOKEN=$(cat $CREDENTIALS_DIRECTORY/slack-app-token)
cat > /var/lib/musiclink-matterbridge/matterbridge.toml <<EOF
[api.local]
BindAddress="127.0.0.1:${toString cfg.matterbridge.port}"
Token="musiclink-internal-token"
[[slack]]
[slack.my-slack]
Token="$SLACK_TOKEN"
AppToken="$SLACK_APP_TOKEN"
# Socket Mode is cleaner (no public ingress needed)
# If using Socket Mode, we usually need app-level token.
# Matterbridge supports it? It seems to use standard Slack API.
# Let's assume standard RTM or Events API if not specified.
# Wait, for standard Slack bot we need 'Token'. 'AppToken' is for Socket Mode.
[[gateway]]
name = "musiclink-gateway"
enable = true
[[gateway.inout]]
account = "api.local"
[[gateway.inout]]
account = "slack.my-slack"
channel = "${cfg.matterbridge.slackChannel}"
EOF
'';
ExecStart = "${pkgs.matterbridge}/bin/matterbridge -conf /var/lib/musiclink-matterbridge/matterbridge.toml";
Restart = "always";
RestartSec = "10s";
};
};
# -------------------------------------------------------------------------
# MusicLink Bot Service
# -------------------------------------------------------------------------
systemd.services.musiclink = {
description = "MusicLink Bot";
after = [ "musiclink-matterbridge.service" ];
wants = [ "musiclink-matterbridge.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
DynamicUser = true;
StateDirectory = "musiclink";
WorkingDirectory = "/var/lib/musiclink";
ExecStartPre = pkgs.writeShellScript "generate-musiclink-config" ''
cat > /var/lib/musiclink/config.toml <<EOF
[matterbridge]
url = "http://127.0.0.1:${toString cfg.matterbridge.port}/api/websocket"
token = "musiclink-internal-token"
gateway = "musiclink-gateway"
username = "MusicLink"
EOF
'';
ExecStart = "${cfg.package}/bin/musiclink";
Restart = "always";
RestartSec = "10s";
};
};
};
}