Skip to content

Releases: shpaker/feedforbot

5.1.0

18 Apr 06:39

Choose a tag to compare

Added

  • py.typed marker (PEP 561) — downstream type checkers now pick up inline type annotations shipped with the package
  • PyPI classifiers populated in pyproject.toml (Python 3.10–3.14, topics, license, Typing :: Typed) — improves discoverability on pypi.org
  • Lint CI status badge in README

Changed

  • README feature list polished and restructured
  • tmfeed/ deploy artifacts renamed for clarity: config.ymlfeedforbot.config.yml, deploy.ymldeploy.playbook.yml; new feedforbot.compose.yml.j2 template; Justfile and deploy workflow updated to match
  • CI: build.yml consolidated into pypi.yml; lint matrix tweaks

Full Changelog: 5.0.0...5.1.0

5.0.0

17 Apr 20:53

Choose a tag to compare

Added

  • --healthcheck-host CLI option (defaults to 127.0.0.1) — previously bound to 0.0.0.0 unconditionally
  • HttpClientProtocol, ListenerProtocol, TransportProtocol are now context managers (__enter__/__exit__) with a required close() method — scheduler closes listener/transport (and their HTTP clients) cleanly on shutdown
  • Per-scheduler cache_limit config option — caps the number of entries kept in cache (keeps the N most recent by grabbed_at); unbounded when unset
  • --cache-dsn CLI flag (default file:) — cache backend is now configured on the command line via a URL-style DSN (file: persists at ~/.feedforbot/, file:///custom/path uses a custom directory, memory: is in-process). Designed to scale to future backends (e.g. redis://host:6379/0) without proliferating flags
  • RedisCache backend + redis://… / rediss://… / unix://… DSN schemes — shared cache suitable for multi-instance deployments and docker-compose setups. Ships with the cli extra (pip install feedforbot[cli]) and the GHCR Docker image. The redis package is an optional dependency — RedisCache(...) raises a clear ImportError when it isn't installed, so core installs (pip install feedforbot) stay minimal

Changed

  • Breaking: healthcheck endpoint now responds only at /health (previously matched every path) — Docker/Kubernetes probes configured against / must be updated
  • Breaking: YAML config is now a top-level list of listener+transport entries; the cache: and schedulers: wrapper keys have been removed. CLI positional argument renamed from CONFIGURATION to SCHEDULERS_FILE. Cache backend selection moved from cache.type in the YAML to the new --cache-dsn CLI flag.
  • Breaking: CacheProtocol redesigned around is_populated / known_ids / add(*articles) / trim(limit) (previously read / write / is_populated). FilesCache on-disk schema is now [{"id", "grabbed_at"}] (no title/url/text). Files written by earlier versions are detected on load, deleted, and treated as a first-run (no spam on upgrade). Custom cache implementations must be updated.

Fixed

  • FilesCache writes atomically (tempfile + os.replace) — no more corrupted cache on crash/power loss mid-write
  • FilesCache tolerates corrupt/invalid cache files — logs a warning, deletes the file and treats it as a first-run instead of propagating to Sentry
  • FilesCache no longer grows unbounded — use the new cache_limit scheduler option to cap retention
  • HttpClient.post raises HttpResponseError on non-JSON or non-object payloads (e.g. HTML error pages from Telegram API proxies) instead of leaking JSONDecodeError
  • Telegram default and custom templates now HTML-escape article fields (title/text/etc.) — prevents Telegram API rejecting messages with &, <, > in content
  • Config with empty schedulers: [] is now rejected at parse time instead of crashing with ValueError in ThreadPoolExecutor
  • RSSListener skips individual malformed feed entries (missing summary/title) with a warning instead of failing the whole tick
  • Telegram bot token masking now covers error-path log lines (http_error:) — token could previously leak via str(exc) when httpx included the URL in connection errors
  • HTTP 429 flood-wait responses are now retried after the Retry-After delay (capped by max_retry_after, default 60s) instead of failing the send immediately — Telegram rate-limit bursts self-heal
  • CLI graceful shutdown: shutdown_start / shutdown_complete are logged on SIGTERM/SIGINT, CancelledError is no longer reported as a crash, a second signal forces an immediate loop.stop() escape hatch, and Windows (no POSIX signals) falls back to KeyboardInterrupt without raising

Full Changelog: 4.0.0...5.0.0

4.0.0

15 Apr 14:37

Choose a tag to compare

Changed

  • Migrated from Poetry to uv
  • Python >=3.10 with CI matrix (3.10–3.14)
  • Structured logging throughout core modules
  • Domain layer made synchronous (async only in Scheduler)
  • Cache merges articles instead of overwriting
  • HTTP client with persistent connections and exponential backoff retries
  • Jinja2 sandbox rendering (SSTI mitigation)
  • Telegram Bot API token redacted from logs/tracebacks
  • New articles sorted chronologically before sending
  • All GitHub Actions pinned to commit SHAs

Added

  • Healthcheck endpoint (--healthcheck-port)
  • JSON Schema for YAML config
  • HTTP request timeouts (30s total, 10s connect)
  • Correlation ID per scheduler tick for log tracing
  • Docker images published to GHCR
  • Comprehensive test suite
  • GitHub Actions deploy workflow for tmfeed

Fixed

  • Scheduler silently dying on unhandled tick exceptions
  • TelegramBotTransport silently ignoring API errors
  • ArticleModel.__eq__ raising AttributeError on non-model types
  • RSSListener crashing on <img> tags without src
  • Cache diff performance, race conditions, and datetime serialization
  • Docker image tag strategy and GHCR metadata

4.0.0rc7

15 Apr 13:36

Choose a tag to compare

4.0.0rc7 Pre-release
Pre-release

Fixed

  • Scheduler silently dying on unhandled tick exceptions_tick now catches Exception broadly, logs the full traceback, reports to Sentry, and continues to the next cron tick. Previously, any error other than ListenerReceiveError (cache I/O, parsing, validation) would kill the scheduler coroutine, silently swallowed by asyncio.gather(return_exceptions=True). The container stayed healthy via healthcheck but no feeds were polled.
  • Crashed scheduler tasks are now logged at ERROR level when asyncio.gather exits.

Added

  • flake8-bandit (S) rules enabled in ruff, with per-file-ignores for test assertions.
  • Deployment configs for tmfeed.

4.0.0rc6

15 Apr 11:06

Choose a tag to compare

4.0.0rc6 Pre-release
Pre-release

Pre-release candidate 6 for v4.0.0

4.0.0rc5

15 Apr 09:59

Choose a tag to compare

4.0.0rc5 Pre-release
Pre-release

RC5: labels via --label at build time, provenance: false

3.3.5

29 Dec 08:50

Choose a tag to compare

bump requirements

3.3.4

23 Nov 10:17

Choose a tag to compare

What's Changed

  • Bump dependencies versions

3.3.3

20 Feb 13:51

Choose a tag to compare

Full Changelog: 3.3.2...3.3.3

3.3.2

16 Feb 20:35

Choose a tag to compare

Full Changelog: 3.3.1...3.3.2