"""Étape de récupération non bloquante des articles RSS du collège.""" from __future__ import annotations from pronote_sync.models.blog import BlogArticle from pronote_sync.sources.blog.rss import BlogRSSClient from pronote_sync.sources.blog.state import BlogRSSState from pronote_sync.utils.redaction import redact_exception def fetch_blog_step(client: BlogRSSClient | None, state: BlogRSSState | None) -> list[BlogArticle]: """Récupère les articles RSS nouveaux en conservant l'état du client. :param client: Client RSS configuré, ou ``None`` lorsque le blog est désactivé. :param state: État de déduplication et de cache HTTP associé au run. :return: Nouveaux articles du blog. :rtype: list[BlogArticle] :raises RuntimeError: Si la récupération RSS injectée échoue. """ if client is None or state is None: return [] try: etag, last_modified = state.get_cache_headers() result = client.fetch_and_parse( known_guids=state.get_known_guids(), etag=etag, last_modified=last_modified ) if result.error is not None: raise RuntimeError(result.error) from None if not result.not_modified: state.add_guids(article.id for article in result.articles) state.update_cache_headers(result.etag, result.last_modified) return list(result.articles) except Exception as exc: raise RuntimeError(f"Récupération du blog échouée : {redact_exception(exc)}") from None