Compare commits
2 Commits
cc8761a304
...
e049cba3c4
| Author | SHA1 | Date | |
|---|---|---|---|
|
e049cba3c4
|
|||
|
d3ede84bd3
|
@@ -11,6 +11,9 @@
|
|||||||
service_configs.prowlarr.dataDir
|
service_configs.prowlarr.dataDir
|
||||||
])
|
])
|
||||||
(lib.vpnNamespaceOpenPort service_configs.ports.private.prowlarr.port "prowlarr")
|
(lib.vpnNamespaceOpenPort service_configs.ports.private.prowlarr.port "prowlarr")
|
||||||
|
(lib.serviceFilePerms "prowlarr" [
|
||||||
|
"Z ${service_configs.prowlarr.dataDir} 0700 prowlarr prowlarr"
|
||||||
|
])
|
||||||
];
|
];
|
||||||
|
|
||||||
services.prowlarr = {
|
services.prowlarr = {
|
||||||
@@ -19,6 +22,24 @@
|
|||||||
settings.server.port = service_configs.ports.private.prowlarr.port;
|
settings.server.port = service_configs.ports.private.prowlarr.port;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# The upstream prowlarr module uses DynamicUser=true which is incompatible
|
||||||
|
# with ZFS-backed persistent storage — the dynamic user can't access files
|
||||||
|
# on the ZFS mount. Override with a static user to match sonarr/radarr.
|
||||||
|
users.users.prowlarr = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = "prowlarr";
|
||||||
|
home = service_configs.prowlarr.dataDir;
|
||||||
|
};
|
||||||
|
users.groups.prowlarr = { };
|
||||||
|
|
||||||
|
systemd.services.prowlarr.serviceConfig = {
|
||||||
|
DynamicUser = lib.mkForce false;
|
||||||
|
User = "prowlarr";
|
||||||
|
Group = "prowlarr";
|
||||||
|
StateDirectory = lib.mkForce "";
|
||||||
|
ExecStart = lib.mkForce "${lib.getExe pkgs.prowlarr} -nobrowser -data=${service_configs.prowlarr.dataDir}";
|
||||||
|
};
|
||||||
|
|
||||||
services.caddy.virtualHosts."prowlarr.${service_configs.https.domain}".extraConfig = ''
|
services.caddy.virtualHosts."prowlarr.${service_configs.https.domain}".extraConfig = ''
|
||||||
import ${config.age.secrets.caddy_auth.path}
|
import ${config.age.secrets.caddy_auth.path}
|
||||||
reverse_proxy ${config.vpnNamespaces.wg.namespaceAddress}:${builtins.toString service_configs.ports.private.prowlarr.port}
|
reverse_proxy ${config.vpnNamespaces.wg.namespaceAddress}:${builtins.toString service_configs.ports.private.prowlarr.port}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
SONARR_URL = "http://localhost:${builtins.toString service_configs.ports.private.sonarr.port}";
|
SONARR_URL = "http://localhost:${builtins.toString service_configs.ports.private.sonarr.port}";
|
||||||
SONARR_CONFIG = "${service_configs.sonarr.dataDir}/config.xml";
|
SONARR_CONFIG = "${service_configs.sonarr.dataDir}/config.xml";
|
||||||
CATEGORIES = "tvshows,movies,anime";
|
CATEGORIES = "tvshows,movies,anime";
|
||||||
|
TAG_TORRENTS = "true";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -266,6 +266,51 @@ def print_section(torrents, show_status=False):
|
|||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
AUDIT_TAGS = {"audit:unmanaged", "audit:abandoned-safe", "audit:abandoned-review"}
|
||||||
|
|
||||||
|
|
||||||
|
def tag_torrents(qbit_client, qbit_torrents, all_known, all_abandoned):
|
||||||
|
log.info("Tagging torrents ...")
|
||||||
|
|
||||||
|
abandoned_by_hash = {t["hash"].upper(): t for t in all_abandoned}
|
||||||
|
|
||||||
|
all_hashes = []
|
||||||
|
for torrents in qbit_torrents.values():
|
||||||
|
all_hashes.extend(torrents.keys())
|
||||||
|
|
||||||
|
for h in all_hashes:
|
||||||
|
current_tags = set()
|
||||||
|
torrent_info = None
|
||||||
|
for torrents in qbit_torrents.values():
|
||||||
|
if h in torrents:
|
||||||
|
torrent_info = torrents[h]
|
||||||
|
break
|
||||||
|
if not torrent_info:
|
||||||
|
continue
|
||||||
|
|
||||||
|
existing_tags = {t.strip() for t in torrent_info.get("tags", "").split(",") if t.strip()}
|
||||||
|
existing_audit_tags = existing_tags & AUDIT_TAGS
|
||||||
|
|
||||||
|
if h in abandoned_by_hash:
|
||||||
|
status = abandoned_by_hash[h]["status"]
|
||||||
|
desired = "audit:abandoned-safe" if status == "SAFE" else "audit:abandoned-review"
|
||||||
|
elif h not in all_known:
|
||||||
|
desired = "audit:unmanaged"
|
||||||
|
else:
|
||||||
|
desired = None
|
||||||
|
|
||||||
|
tags_to_remove = existing_audit_tags - ({desired} if desired else set())
|
||||||
|
tags_to_add = ({desired} if desired else set()) - existing_audit_tags
|
||||||
|
|
||||||
|
low_hash = torrent_info["hash"]
|
||||||
|
for tag in tags_to_remove:
|
||||||
|
qbit_client.torrents_remove_tags(tags=tag, torrent_hashes=low_hash)
|
||||||
|
for tag in tags_to_add:
|
||||||
|
qbit_client.torrents_add_tags(tags=tag, torrent_hashes=low_hash)
|
||||||
|
|
||||||
|
log.info("Tagging complete")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
qbit_url = os.environ["QBITTORRENT_URL"]
|
qbit_url = os.environ["QBITTORRENT_URL"]
|
||||||
radarr_url = os.environ["RADARR_URL"]
|
radarr_url = os.environ["RADARR_URL"]
|
||||||
@@ -328,6 +373,10 @@ def main():
|
|||||||
)
|
)
|
||||||
print(f"SAFE TO RECLAIM: {gib(sum(t['size'] for t in safe))} GiB")
|
print(f"SAFE TO RECLAIM: {gib(sum(t['size'] for t in safe))} GiB")
|
||||||
|
|
||||||
|
# -- Tagging --
|
||||||
|
if os.environ.get("TAG_TORRENTS", "").lower() in ("1", "true", "yes"):
|
||||||
|
tag_torrents(qbit, qbit_torrents, all_known, all_abandoned)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user