106 lines
3.4 KiB
Nix
106 lines
3.4 KiB
Nix
{ pkgs, lib }:
|
|
let
|
|
pluginVersion = "18.0.0.0";
|
|
# GUID from the plugin's meta.json; addresses it on /Plugins/<guid>/Configuration.
|
|
pluginGuid = "71552a5a-5c5c-4350-a2ae-ebe451a30173";
|
|
|
|
package = pkgs.stdenvNoCC.mkDerivation {
|
|
pname = "jellyfin-plugin-webhook";
|
|
version = pluginVersion;
|
|
src = pkgs.fetchurl {
|
|
url = "https://repo.jellyfin.org/files/plugin/webhook/webhook_${pluginVersion}.zip";
|
|
hash = "sha256-LFFojiPnBGl9KJ0xVyPBnCmatcaeVbllRwRkz5Z3dqI=";
|
|
};
|
|
nativeBuildInputs = [ pkgs.unzip ];
|
|
unpackPhase = ''unzip "$src"'';
|
|
installPhase = ''
|
|
mkdir -p "$out"
|
|
cp *.dll meta.json "$out/"
|
|
'';
|
|
dontFixup = true; # managed .NET assemblies must not be patched
|
|
};
|
|
|
|
# Minimal Handlebars template, base64 encoded. The monitor only needs the POST;
|
|
# NotificationType is parsed for the debug log line.
|
|
# Decoded: {"NotificationType":"{{NotificationType}}"}
|
|
templateB64 = "eyJOb3RpZmljYXRpb25UeXBlIjoie3tOb3RpZmljYXRpb25UeXBlfX0ifQ==";
|
|
|
|
# Build a PluginConfiguration payload accepted by Jellyfin's JSON deserializer.
|
|
# Each webhook is `{ name, uri, notificationTypes }`.
|
|
mkConfigJson =
|
|
webhooks:
|
|
builtins.toJSON {
|
|
ServerUrl = "";
|
|
GenericOptions = map (w: {
|
|
NotificationTypes = w.notificationTypes;
|
|
WebhookName = w.name;
|
|
WebhookUri = w.uri;
|
|
EnableMovies = true;
|
|
EnableEpisodes = true;
|
|
EnableVideos = true;
|
|
EnableWebhook = true;
|
|
Template = templateB64;
|
|
Headers = [
|
|
{
|
|
Key = "Content-Type";
|
|
Value = "application/json";
|
|
}
|
|
];
|
|
}) webhooks;
|
|
};
|
|
|
|
# Oneshot that POSTs the plugin configuration. Retries past the window
|
|
# between Jellyfin API health and plugin registration.
|
|
mkConfigureScript =
|
|
{ jellyfinUrl, webhooks }:
|
|
pkgs.writeShellScript "jellyfin-webhook-configure" ''
|
|
set -euo pipefail
|
|
export PATH=${
|
|
lib.makeBinPath [
|
|
pkgs.coreutils
|
|
pkgs.curl
|
|
]
|
|
}
|
|
|
|
URL=${lib.escapeShellArg jellyfinUrl}
|
|
AUTH="Authorization: MediaBrowser Token=\"$(cat "$CREDENTIALS_DIRECTORY/jellyfin-api-key")\""
|
|
CONFIG=${lib.escapeShellArg (mkConfigJson webhooks)}
|
|
|
|
for _ in $(seq 1 120); do curl -sf -o /dev/null "$URL/health" && break; sleep 1; done
|
|
curl -sf -o /dev/null "$URL/health"
|
|
|
|
for _ in $(seq 1 60); do
|
|
if printf '%s' "$CONFIG" | curl -sf -X POST \
|
|
-H "$AUTH" -H "Content-Type: application/json" --data-binary @- \
|
|
"$URL/Plugins/${pluginGuid}/Configuration"; then
|
|
echo "Jellyfin webhook plugin configured"; exit 0
|
|
fi
|
|
sleep 1
|
|
done
|
|
echo "Failed to configure webhook plugin" >&2; exit 1
|
|
'';
|
|
|
|
# Materialise a writable copy of the plugin. Jellyfin rewrites meta.json at
|
|
# runtime, so a read-only nix-store symlink would EACCES.
|
|
mkInstallScript =
|
|
{ pluginsDir }:
|
|
pkgs.writeShellScript "jellyfin-webhook-install" ''
|
|
set -euo pipefail
|
|
export PATH=${lib.makeBinPath [ pkgs.coreutils ]}
|
|
dst=${lib.escapeShellArg "${pluginsDir}/Webhook_${pluginVersion}"}
|
|
mkdir -p ${lib.escapeShellArg pluginsDir}
|
|
rm -rf "$dst" && mkdir -p "$dst"
|
|
cp ${package}/*.dll ${package}/meta.json "$dst/"
|
|
chmod u+rw "$dst"/*
|
|
'';
|
|
in
|
|
{
|
|
inherit
|
|
package
|
|
pluginVersion
|
|
pluginGuid
|
|
mkConfigureScript
|
|
mkInstallScript
|
|
;
|
|
}
|