Application Flask pour nettoyer automatiquement les watchlists Plex d'un serveur multi-utilisateurs. Synchronise les collections du serveur avec les watchlists de tous les utilisateurs, et gère un système de consensus par notes pour les demandes de suppression.
Surveille une ou plusieurs collections Plex. Lorsqu'un média est ajouté à ces collections, il est automatiquement retiré de la watchlist de tous les utilisateurs enregistrés.
Idéal en complément de Maintainerr : les médias placés dans une collection de sortie ("Leaving soon") par Maintainerr sont nettoyés des watchlists sans avoir besoin de list exclusions.
Un système collaboratif pour gérer les suppressions :
- Note 0.5★ (= 1/10) → Le média est ajouté à la collection
WEBHOOK_COLLECTION(demande de suppression) - Note ≥ 1★ (= ≥ 2/10) → Le média est protégé : s'il est dans
WEBHOOK_COLLECTION, il en est retiré. Les autres utilisateurs ne peuvent plus le faire supprimer.
Le consensus vérifie tous les comptes enregistrés avant de décider — une seule note ≥ 1★ sauve un média.
Chaque décision de consensus (suppression ou maintien) est envoyée à un webhook Discord configurable.
Chaque utilisateur s'autorise simplement en ouvrant http://<server>:5000 dans son navigateur — pas besoin de partager ses identifiants. Le flow utilise l'authentification Plex PIN / OAuth native.
L'endpoint /webhook reçoit les événements de notation de Plex en temps réel et déclenche la vérification de consensus immédiatement (sans attendre le cron).
| Variable | Requis | Défaut | Description |
|---|---|---|---|
PLEX_URL |
✅ | http://localhost:32400 |
URL de ton serveur Plex |
ADMIN_USERNAME |
✅ | — | Nom d'utilisateur Plex de l'admin (pour les opérations serveur) |
COLLECTIONS |
❌ | (vide) | Liste de collections à monitorer (séparées par des virgules). Quand un média y est ajouté → retiré des watchlists |
WEBHOOK_COLLECTION |
❌ | Demande de suppression |
Collection cible pour les médias notés 0.5★ |
DISCORD_WEBHOOK_URL |
❌ | (vide) | URL du webhook Discord pour les notifications |
CRON_SCHEDULE |
❌ | 0 */1 * * * |
Expression cron pour la sync automatique (par défaut : chaque heure) |
RUN_SYNC_AT_STARTUP |
❌ | false |
Lancer une sync au démarrage (true / false) |
TOKEN_TTL_HOURS |
❌ | 24 |
Durée de vie du cache du token admin (heures) |
APP_NAME |
❌ | Plex Watchlist Cleaner |
Nom affiché lors de l'authentification Plex |
services:
plex-watchlist-cleaner:
image: ghcr.io/chwps/plex-watchlist-cleaner:latest
container_name: plex-watchlist-cleaner
restart: unless-stopped
environment:
PLEX_URL: "http://plex:32400"
ADMIN_USERNAME: "ton_compte_admin"
COLLECTIONS: "Leaving soon,Cleaned"
WEBHOOK_COLLECTION: "Demande de suppression"
DISCORD_WEBHOOK_URL: "https://discord.com/api/webhooks/..."
CRON_SCHEDULE: "0 */1 * * *"
RUN_SYNC_AT_STARTUP: "true"
volumes:
- ./data:/data
ports:
- "5000:5000"Chaque utilisateur ouvre http://<serveur>:5000 dans son navigateur :
- Cliquer sur "Choisir un compte Plex"
- Se connecter à son compte Plex et autoriser l'application
- Le token est sauvegardé automatiquement dans
/data/user_tokens.json - Fermer la fenêtre — c'est tout !
Dans ton serveur Plex : Réglages → Web & XML → Ajouter un nouveau webhook
- URL :
http://plex-watchlist-cleaner:5000/webhook - Événement : cocher
media.rate
Les notes sont traitées en temps réel dès qu'un utilisateur note un média.
La sync s'exécute automatiquement selon le cron configuré. Tu peux aussi la déclencher manuellement :
curl -X POST http://localhost:5000/run_sync| Note Plex | Valeur API | Effet |
|---|---|---|
| 0.5★ | 1.0 |
Demande de suppression → ajout à WEBHOOK_COLLECTION |
| 1.0★ | 2.0 |
Protection → retrait de WEBHOOK_COLLECTION |
| ≥ 1.0★ | ≥ 2.0 |
Protection |
Règle de consensus : si un média a au moins une note ≥ 1★, il est protégé et ne peut plus être supprimé par un 0.5★.
┌─────────────────────┐
│ Interface Web │ :5000 ┌──────────────────────────┐
│ (OAuth PIN) │ ◄──────────│ Plex Web │
│ │ │ (authentification) │
├─────────────────────┤ └──────────────────────────┘
│ Flask App │
│ │ ┌──────────────────────────┐
│ / (onboarding) │ │ │
│ /login + /callback │ │ Plex Server │
│ │ ◄─────► │ (Collections, Ratings) │
│ /run_sync │ │ │
│ /webhook │ ◄─────► │ │
├─────────────────────┤ └──────────────────────────┘
│ │
│ sync_collections │ ┌──────────────────────────┐
│ _once() │ ──────► │ Discord Webhook │
│ │ │ (notifications) │
├─────────────────────┤ └──────────────────────────┘
│ │
│ Cron (entrypoint) │
└─────────────────────┘
data/
├── user_tokens.json # Tokens OAuth de chaque utilisateur
├── plex_token.json # Cache du token admin
├── plex_watchlist_state.json # État des collections déjà traitées
└── client_id.txt # ID client Plex (généré automatiquement)
Build & push automatique sur GitHub Container Registry via GitHub Actions :
- Branche
main→ taglatest - Branche
dev→ tagdev
- Ajout d'un nouvel utilisateur : si tu ajoutes un utilisateur après la première sync, il est recommandé de supprimer le fichier
data/plex_watchlist_state.jsonpour qu'il hérite du nettoyage des médias déjà présents dans les collections monitorées. - Le compte admin doit aussi passer par l'onboarding web pour fournir son token (il sera utilisé pour les opérations serveur : lecture des collections, modifications, etc.).