{ lib, original, callPackage, dotnetCorePackages, fetchFromGitHub, buildDotnetModule, gnused, jprm, unzip, }: let capitalize = upper: str: let length = builtins.stringLength str; head = builtins.substring 0 1 str; tail = builtins.substring 1 length str; in "${upper head}${tail}"; jellyfin = original.overrideAttrs ( final: prev: assert !prev ? "plugin"; { passthru.plugin = base: args: let meta = from: { inherit (from) license homepage description; }; helper = { inherit base; name = builtins.baseNameOf info.base; self = info; owner = "jellyfin"; hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; rev = "v${info.version}"; description = "${info.name} plugin for jellyfin"; homepage = original.meta.homepage; license = original.meta.license; override = assert false; null; overrideAttrs = assert false; null; overrideDerivation = assert false; null; mkPlugin = info: result: buildDotnetModule result; inherit jellyfin; }; defaults = { pname = "jellyfin-plugin-${info.name}"; nugetDeps = let options = builtins.filter builtins.pathExists [ "${info.base}/deps.json" ]; in assert options != [ ]; builtins.head options; pluginLibraries = lib.attrsets.foldlAttrs ( acc: name: value: acc ++ lib.optional (value == "directory") name ) [ ] (builtins.readDir ("${info.src}/src")); dotnet-sdk = dotnetCorePackages.sdk_8_0; dotnet-runtime = dotnetCorePackages.aspnetcore_8_0; dontDotnetBuild = true; dontDotnetInstall = true; project = "Jellyfin.Plugin.${capitalize lib.strings.toUpper info.name}"; prePatch = '' sed --sandbox --separate \ -e 's:\(PackageReference Include="Jellyfin\..*" Version="\)[^"]\+":\1${info.jellyfin.version}":' \ -e 's:<\(enerateDocumentationFile\|TreatWarningsAsErrors\)>true:<\1>false:' \ -i ${ lib.strings.escapeShellArgs (builtins.map (lib: "src/${lib}/${lib}.csproj") info.pluginLibraries) } success=true for x in ${ lib.strings.escapeShellArgs (builtins.map (lib: "src/${lib}/${lib}.csproj") info.pluginLibraries) } do diff -q $src/$x $x 2>/dev/null || continue printf >&2 'no change: %s\n' $x success=false done $success || exit 1 ''; projectFile = "src/${info.project}/${info.project}.csproj"; src = fetchFromGitHub { owner = info.owner; repo = "jellyfin-plugin-${info.name}"; inherit (info) rev hash; }; nativeBuildInputs = [ gnused jprm unzip ]; patches = lib.optional (builtins.pathExists "${info.base}.patch") "${info.base}.patch" ++ lib.optionals (builtins.pathExists info.base) ( lib.attrsets.foldlAttrs ( acc: name: type: acc ++ lib.optional (type == "regular" && lib.strings.hasSuffix ".patch" name) "${info.base}/${name}" ) [ ] (builtins.readDir info.base) ); outputs = [ "out" "zip" ]; postInstall = let dlls = builtins.map (name: "${name}.dll") info.pluginLibraries; in '' tmp_output_dir="$(mktemp -d)" jprm plugin build . --output="''${tmp_output_dir}" --version="${info.version}" --dotnet-configuration="''${dotnetBuildType-Release}" mv "''${tmp_output_dir}/${info.name}_${info.version}.zip" $zip mkdir -p $out unzip $zip -d $out success=true for file in $out/*; do case "''${file##*/}" in meta.json) ;; ${builtins.concatStringsSep "|" (builtins.map lib.strings.escapeShellArg dlls)}) ;; *) printf 'unknown file: %s\n' ''${file@Q} success=false ;; esac done for file in meta.json ${lib.strings.escapeShellArgs dlls} do [[ -f "$out/$file" ]] && continue printf 'missing file: %s\n' ''${file@Q} success=false done $success || exit 42 ''; meta = meta original.meta // meta info; }; info = helper // defaults // callPackage base ({ inherit info; } // args); result = lib.attrsets.removeAttrs info (builtins.attrNames helper); in info.mkPlugin info result; } ); in jellyfin