Système de Notifications Contextuelles
Le module de notifications de MoviePilot utilise une architecture modulaire pour générer des messages adaptatifs via le moteur de templates Jinja2. La classe GenerateurContexteNotification assemble automatiquement des métadonnées telles que le titre du média, la saison et la note moyenne dans un format cohérent.
def preparer_details_medias(self, infos_media: InfosMedia):
if not infos_media:
return
saison_formatee = f"S{infos_media.saison:02d}" if infos_media.saison else None
self._contexte.update({
"titre": infos_media.titre,
"titre_anglais": infos_media.titre_anglais,
"annee": infos_media.annee,
"saison": infos_media.saison,
"saison_formatee": saison_formatee,
"note_moyenne": infos_media.note_moyenne,
"affiche": infos_media.obtenir_image_affiche(),
"synopsis": infos_media.synopsis
})
Pour éviter les interruptions intempestives, une file d'attente basée sur des plages horaires est implémentée. La classe GestionnaireFileNotifications vérifie si l'heure actuelle correspond à une fenêtre de diffusion autorisée.
def est_dans_plage_horaire(self, heure_courante: datetime) -> bool:
if not self.periodes_planifiees:
return True
minutes_actuelles = heure_courante.hour * 60 + heure_courante.minute
for plage in self.periodes_planifiees:
debut_h, debut_m, fin_h, fin_m = plage
debut_minutes = debut_h * 60 + debut_m
fin_minutes = fin_h * 60 + fin_m
if debut_minutes <= fin_minutes and debut_minutes <= minutes_actuelles <= fin_minutes:
return True
if debut_minutes > fin_minutes and (minutes_actuelles >= debut_minutes or minutes_actuelles <= fin_minutes):
return True
return False
Mécanisme de Suivi de Progression Visuel
Pour les tâches longues comme le téléchargement ou le transfert de fichiers, la classe AssistantProgression fournit des mises à jour multi-dimensionnelles via une interface publique. Elle permet de combiner un pourcentage d'avancement, un texte descriptif et des données supplémentaires.
def mettre_a_jour(self, valeur: Union[float, int] = None, texte: Optional[str] = None, donnees: dict = None):
tache_actuelle = self._progression.get(self._cle)
if not tache_actuelle or not tache_actuelle.get('active'):
return
if valeur:
tache_actuelle['valeur'] = valeur
if texte:
tache_actuelle['texte'] = texte
if donnees:
tache_actuelle['donnees'].update(donnees)
self._progression[self._cle] = tache_actuelle
Le cycle de vie d'une tâche est géré automatiquement, avec des transitions d'état claires pour indiquer le démarrage, les phases intermédiaires et la fin.
progression = AssistantProgression(CleProgression.TELECHARGEMENT)
progression.demarrer()
progression.mettre_a_jour(40, "Téléchargement des fichiers sources en cours")
progression.mettre_a_jour(80, "Vérification de l'intégrité des données")
progression.terminer()
Interfaces de Configuration Intelligentes
La classe ParametresSysteme assure une gestion robuste des entrées utilisateur en appliquant des conversions de type automatiques et des validatiosn. Par exemple, les valeurs booléennes sont interprétées à partir de chaînes comme "oui" ou "non".
@staticmethod
def convertisseur_type_generique(valeur: Any, type_attendu: Type, defaut: Any):
try:
if type_attendu is bool:
if isinstance(valeur, str):
return valeur.lower() in ["vrai", "oui", "1", "actif"]
return bool(valeur)
elif type_attendu is int:
return int(valeur)
except (ValueError, TypeError):
logger.avertissement(f"Échec de conversion de la valeur, utilisation de la valeur par défaut : {defaut}")
return defaut
Lorsqu'une entrée est incorrecte, le système corrige automatiquement et fournit des suggestions. Pour le token d'API, par exemple, un nouveau jeton est généré si la longueur est insuffisante.
@staticmethod
def valider_token_api(valeur: Any, valeur_originale: Any) -> Tuple[Any, bool]:
valeur = valeur.strip() if isinstance(valeur, str) else None
if not valeur or len(valeur) < 16:
nouveau_token = secrets.token_urlsafe(16)
logger.info(f"Token API manquant ou trop court, génération d'un nouveau jeton : {nouveau_token}")
return nouveau_token, True
return valeur, False