{"id":13824952,"url":"https://github.com/Electronic-Mango/rss-reader-telegram-bot","last_synced_at":"2025-07-08T20:32:34.210Z","repository":{"id":47424837,"uuid":"512534544","full_name":"Electronic-Mango/rss-reader-telegram-bot","owner":"Electronic-Mango","description":"A simple RSS reader Telegram bot.","archived":false,"fork":false,"pushed_at":"2025-07-02T17:53:02.000Z","size":329,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-02T18:43:07.075Z","etag":null,"topics":["docker","docker-container","docker-image","rss","telegram","telegram-bot"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Electronic-Mango.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-07-10T20:37:42.000Z","updated_at":"2025-07-02T17:53:06.000Z","dependencies_parsed_at":"2023-11-13T12:26:51.801Z","dependency_job_id":"5812b2bf-1652-47ae-9399-74e78bfcd6f0","html_url":"https://github.com/Electronic-Mango/rss-reader-telegram-bot","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Electronic-Mango/rss-reader-telegram-bot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Electronic-Mango%2Frss-reader-telegram-bot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Electronic-Mango%2Frss-reader-telegram-bot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Electronic-Mango%2Frss-reader-telegram-bot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Electronic-Mango%2Frss-reader-telegram-bot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Electronic-Mango","download_url":"https://codeload.github.com/Electronic-Mango/rss-reader-telegram-bot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Electronic-Mango%2Frss-reader-telegram-bot/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264343772,"owners_count":23593788,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-container","docker-image","rss","telegram","telegram-bot"],"created_at":"2024-08-04T09:01:12.558Z","updated_at":"2025-07-08T20:32:33.779Z","avatar_url":"https://github.com/Electronic-Mango.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# RSS reader Telegram bot\n\n[![CodeQL](https://github.com/Electronic-Mango/rss-reader-telegram-bot/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/Electronic-Mango/rss-reader-telegram-bot/actions/workflows/codeql-analysis.yml)\n[![flake8 and pytest](https://github.com/Electronic-Mango/rss-reader-telegram-bot/actions/workflows/flake8-pytest-verification.yml/badge.svg)](https://github.com/Electronic-Mango/rss-reader-telegram-bot/actions/workflows/flake8-pytest-verification.yml)\n[![black](https://github.com/Electronic-Mango/rss-reader-telegram-bot/actions/workflows/black-formatting-verification.yml/badge.svg)](https://github.com/Electronic-Mango/rss-reader-telegram-bot/actions/workflows/black-formatting-verification.yml)\n\nA simple Telegram bot sending updates for RSS feeds, build with [`python-telegram-bot`](https://github.com/python-telegram-bot/python-telegram-bot)!\n\n\n## Table of contents\n - [Requirements](#requirements)\n - [Configuration](#configuration)\n   - [Bot parameters](#bot-parameters)\n   - [Restricting access to bot commands](#restricting-access-to-bot-commands)\n   - [Persistence](#persistence)\n   - [Supplying RSS feed links](#supplying-rss-feed-links)\n   - [Storing chat data](#storing-chat-data)\n   - [Quiet hours](#quiet-hours)\n   - [Randomness when checking for updates](#randomness-when-checking-for-updates)\n   - [Docker](#docker)\n - [Running the bot](#running-the-bot)\n - [Commands](#commands)\n - [Other details](#other-details)\n   - [Deciding which feeds are valid](#deciding-which-feeds-are-valid)\n   - [Checking for updates](#checking-for-updates)\n   - [Randomness in delays and checking for updates](#randomness-in-delays-and-checking-for-updates)\n   - [Sending updates and message formatting](#sending-updates-and-message-formatting)\n   - [Detecting when user blocks the bot and clearing chat data](#detecting-when-user-blocks-the-bot-and-clearing-chat-data)\n\n\n## Requirements\n\nThis bot was built with `Python 3.12` and [`python-telegram-bot`](https://github.com/python-telegram-bot/python-telegram-bot).\nFull list of Python requirements is in the `requirements.txt` file, you can use it to install all of them.\n\n\n## Configuration\n\n### Bot parameters\nConfiguration parameters for the bot are stored in a configuration YAML file.\nDefault parameters are stored in `settings.yml` file in the project root.\nDetailed description of each parameter is described there.\n\nAlmost all fields are filled with sensible defaults, except the Telegram bot token.\nValues from the default file can be overwritten by a custom YAML file, which path can be supplied by `CUSTOM_SETTINGS_PATH` environment variable.\nOnly specific parameters can be configured in the custom file.\nAll parameters missing from custom YAML will be taken from default YAML instead.\n\nThis way you can provide your own Telegram bot token without modifying project files.\nThis can be especially useful when running the bot in a Docker container.\n\nMost basic custom YAML can contain only Telegram bot token:\n\n```yaml\ntelegram:\n  token: your-telegram-bot-token\n```\n\n\n### Restricting access to bot commands\nBot can be restricted to allow only specific users to execute bot commands via `telegram` - `allowed_usernames` value in configuration YAML.\nWhen the list is left empty everyone will be able to access the bot.\n\nYou can specify multiple users, as the value in YAML is a list.\n\n\n### Persistence\n\nBot uses pickled file for storing persistence data between restarts.\nBy default `persistence` file in the project root is used.\nIts path can be tweaked via configuration YAML.\n\nAll conversation-style commands are persistent.\nThis means, that their state should be preserved after bot has been restarted, you can just continue the conversation afterward.\n\nWhen deploying the bot via Docker I'd recommend changing the path to persistence pickled file into a mounted volume.\nOtherwise, it will be stored directly in the container, and it will be removed with it.\n\n\n### Supplying RSS feed links\n\nBot doesn't allow users to directly specify an RSS link to follow, instead it stores all available links in a YAML configuration file and allows users to pick one of types defined there.\n\nThis might not be the best approach, however it was most suitable for my use case, as it simplified the process of subscribing to RSS feeds.\n\nThere's a template `feed_links.yml` file which contains examples of how to define RSS links for the bot.\nYou can either modify this file directly, or supply your own file by either modifying the `rss` - `feeds_yaml_filename` parameter in configuration YAML.\n\nOnly feed names (or types) will be displayed to users, links themselves are not.\n\nAdditionally, since RSS links are not stored together with subscription data, you can change the RSS links without the need of re-adding all your subscriptions.\nJust make sure, that feed type stays the same.\n\nHere's a basic set of configuration parameters for an RSS feed in YAML:\n\n```yaml\n# RSS type name displayed to the user\nFeed name 1:\n  # RSS feed link. Notice {source_pattern} substring, it will be replaced with whatever source you input when adding a subscription.\n  url: http://feedlink1.com/{source_pattern}/rss\n  # Configure whether updates will contain RSS entry title.\n  # Case-sensitive, optional, defaults to \"false\".\n  show_title: true\n  # Configure whether updates will contain RSS entry description.\n  # Case-sensitive, optional, defaults to \"false\".\n  show_description: true\n  # List of strings which will be trimmed out of both title and description.\n  # Filters are case-sensitive. Whole field is optional and defaults to an empty string.\n  filters:\n    - some string\n    - some other string\n  # String format used when creating update text to identify where the update comes from.\n  # Elements \"{name}\" and \"{type}\" are replaced by specific feed name and feed type\n  # (in this case \"Feed name 1\"). Both are optional.\n  # This string is also converted to inline URL pointing to actual update.\n  # Final string will be appended to the end of update description.\n  # This string can contain basic HTML format tags. List of supported tags by Telegram bots:\n  # https://core.telegram.org/bots/api#html-style\n  # The field is optional, if absent a default text format is used:\n  # \"By \u003cb\u003e{name}\u003c/b\u003e on {type}\"\n  sender_text_format: Posted by \u003cb\u003e{name}\u003c/b\u003e in \u003ci\u003e{type}\u003c/i\u003e!\n```\n\nOut of all parameters only `url` is required, others are optional.\n\n\n### Storing chat data\nBot uses a separate MongoDB to store chat data.\nDB configuration is stored in `database` section of configuration YAML.\nDB host and port can be configured via `host` and `port` parameters.\nParameters `name` and `collection_name` specify names of DB and collection where all the data will be stored.\n\nAll data is stored within a single collection, for simplicity, so the latter parameters don't matter much.\n\nEach document contains information about a single subscription and stores:\n - **chat ID** - ID of a chat where subscription was made\n - **feed type** - as specified by YAML with feed links\n - **feed name** - specific source from the link, like followed Reddit user\n - **latest read feed entry ID** - used to determine which feed entries were already send to the user\n\nRSS links are not stored, when the bot is checking for updates it uses the link from YAML file and stored feed type.\nThis means, that you can change feed links without the need of re-adding all your subscriptions.\nJust make sure, that feed type stays the same.\n\n\n### Quiet hours\nYou can configure hours when bot won't check for RSS updates via `quiet_hours` parameter in configuration YAML in `telegram` - `updates` section.\nAdd whatever hours you don't want updates in 24h format.\nFor example these values will stop the bot from checking for updates from 11PM to 8AM:\n\n```yml\ntelegram:\n  updates:\n    quiet_hours: [23, 0, 1, 2, 3, 4, 5, 6, 7]\n```\n\nJust don't pad the values with `0`, as they will be then treated as strings, rather than ints.\n\n\n### Randomness when checking for updates\nYou can configure additional delay when checking for updates on two levels - main job checking for all updates and between individual feeds.\n\nParameters related to updates, delays and randomness are in `telegram` - `updates` section of configuration YAML.\n\nDelay in the main loop checking for all updates can be added via `lookup_interval_randomness` parameter.\nMain job still triggers every `lookup_interval`, however it will only trigger a new delayed job which will check for all updates.\nThis job is scheduled after `0` to `lookup_interval_randomness` seconds.\n\nAdditional random delay when checking for individual feeds can be configured via `lookup_feed_delay_randomness` parameter.\nIt is an additional delay to `lookup_feed_delay` between `0` and configured value.\n\nSetting parameters to `0` will disable their respective randomness.\n\n\n### Docker\n\nThere's a Dockerfile in the repo, which will build a Docker image with for the bot using `python:3.12-alpine` as base.\nYou can set all configuration parameters using environment variables for Docker container, rather than modifying project files before building.\n\nKeep in mind, that running the bot in a Docker container might require changing DB IP address (as the default one is `localhost`) and possibly RSS feed links if you're using a self-hosted RSS feed, like [`RSS-Bridge`](https://github.com/RSS-Bridge/rss-bridge) or [`RSSHub`](https://github.com/DIYgod/RSSHub).\n\nWhen supplying configuration parameters, you can add a custom configuration YAML to a mounted volume and point to it via `CUSTOM_SETTINGS_PATH` environment variable in the container.\nThis way configuration YAML with your bot token isn't inserted directly in the container.\nAlso, you can provide custom configuration without modifying project files.\n\nYou can in a similar way supply feed links.\n\nWhen deploying the bot via Docker I'd also recommend changing the path to persistence pickled file into a mounted volume.\nOtherwise, it will be stored directly in the container, and it will be removed with it.\nYou can do that either by modifying `telegram` - `persistence_file` value in configuration YAML.\n\nYou can also check out my repository\n[RSS reader Telegram bot Docker deployment](https://github.com/Electronic-Mango/rss-reader-telegram-bot-docker-deployment)\nfor an example of how you can deploy this bot via Docker Compose.\n\n\n## Running the bot\n\nRunning the bot is quite simple:\n\n1. Create a Telegram bot via [BotFather](https://core.telegram.org/bots#6-botfather)\n2. Set up `MongoDB`, I use a [MongoDB Docker container](https://hub.docker.com/_/mongo)\n3. Configure DB-related parameters in the bot, default ones assume the DB is running locally\n4. Configure Telegram bot token parameters\n5. Supply RSS feed links\n6. Run the `main.py` file, or use a Docker container\n\n\n## Commands\n\n * `/help` - print help information with all commands\n * `/start` - the same as `/help`\n * `/hello` - say hello to the bot\n * `/add` - adds subscription for a given feed\n * `/subscriptions` - list and manage your subscriptions\n * `/removeall` - remove all subscriptions\n * `/unpinall` - unpin all videos, useful if bot is configured to pin all sent video messages, **only messages pinned by the bot automatically are affected**\n * `/cancel` - cancel the current operation, currently used only when adding new subscriptions\n\n\n## Other details\n\n### Deciding which feeds are valid\n\nBot will assume that a given feed link (for a specific source, not a general one) is valid if it passes two conditions:\n\n1. HTTP response code is either 200 or 301\n2. feed has any entries already\n\nThe second one means, that you can't subscribe to feeds which do exist, but don't have any entries yet.\nIt does, however, allow for a much better validation of links, since some RSS feeds will always respond with code 200, even if the feed is not valid.\nIt's not a perfect solution, but it works for my use case.\n\n\n### Checking for updates\n\nBot check for updates for all subscriptions in a regular intervals, configured by the configuration YAML parameter `telegram` - `updates` - `lookup_interval`.\n\nBy default, it will check for updates every hour.\n\nA different parameter `lookup_feed_delay` configures the delay between checking each feed.\nThis should prevent the bot from stopping responding to commands when it's checking for updates, since it might take a while.\n\nYou should check how long checking for each update takes in your case and modify the `lookup_feed_delay` accordingly, so the bot has the time to respond to commands in the meantime.\nAt the same time it shouldn't be so big, that last checks are done when next iteration of checking for updates starts.\n\n\n### Randomness in delays and checking for updates\n\nRandomness can be added to checking for updates on two levels:\n1. Main job triggering check for each feed via `lookup_interval_randomness`\n2. Between individual feeds via `lookup_feed_delay_randomness`\n\nMain job still triggers every exactly `lookup_interval` seconds.\nHowever, only responsibility of this job is triggering delayed checks.\nThese delayed checks will happen after between `0` and `lookup_interval_randomness` seconds.\n\nDelay between checking each feed is `lookup_feed_delay` plus a random value between `0` and `lookup_feed_delay_randomness`.\nSo minimum amount of seconds between checking for each feed is `lookup_feed_delay` and maximum is `lookup_feed_delay + lookup_feed_delay_randomness`.\n\nHowever, the main job isn't taking into account any of the additional delays and randomness, it still triggers every `lookup_interval`, triggering delayed job every `0` to `lookup_interval_randomness` seconds, etc.\n\nSo minimum amount of seconds between triggering checking for updates is `lookup_interval - lookup_interval_randomness` and maximum is `lookup_interval + lookup_interval_randomness`.\nThis, however, doesn't take into account neither `lookup_feed_delay` nor `lookup_feed_delay_randomness`.\n\n\n### Sending updates and message formatting\n\nEach RSS feed entry will be sent in a separate message.\nIf an entry contains more than 10 images/videos the update will be split into more messages, since Telegram only allows up to 10 images/videos per message. Only the final message will contain the caption.\n\nEach message will contain the RSS feed source and type, RSS entry title, summary and link.\n\nBot assumes that RSS entry summary (or description) will be in HTML format.\nBot will send only raw text from summary, without any tags.\n\n\n### Detecting when user blocks the bot and clearing chat data\n\nBot doesn't have any active way of checking that a user deleted their conversation with the bot and stopped it.\nAfter this happens the bot will still check for updates.\nWhen an update is meant to be sent, it will cause a `Forbidden` exception.\nBot will recognize this exception as a situation where this user stopped the conversation and will delete all their data from DB.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FElectronic-Mango%2Frss-reader-telegram-bot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FElectronic-Mango%2Frss-reader-telegram-bot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FElectronic-Mango%2Frss-reader-telegram-bot/lists"}