{"id":24542766,"url":"https://github.com/brokenpip3/lotb","last_synced_at":"2026-05-24T19:04:03.913Z","repository":{"id":273016047,"uuid":"903854865","full_name":"brokenpip3/lotb","owner":"brokenpip3","description":"LOTB: a plugin based bot for telegram","archived":false,"fork":false,"pushed_at":"2025-06-02T22:38:23.000Z","size":2491,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-09T00:41:04.589Z","etag":null,"topics":["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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brokenpip3.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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}},"created_at":"2024-12-15T18:16:05.000Z","updated_at":"2025-04-25T15:05:32.000Z","dependencies_parsed_at":"2025-02-03T23:25:16.919Z","dependency_job_id":"ced3feb6-f02a-4482-b8c6-c791cdc7e177","html_url":"https://github.com/brokenpip3/lotb","commit_stats":null,"previous_names":["brokenpip3/lotb"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/brokenpip3/lotb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brokenpip3%2Flotb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brokenpip3%2Flotb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brokenpip3%2Flotb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brokenpip3%2Flotb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brokenpip3","download_url":"https://codeload.github.com/brokenpip3/lotb/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brokenpip3%2Flotb/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260126251,"owners_count":22962610,"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":["telegram","telegram-bot"],"created_at":"2025-01-22T19:17:47.725Z","updated_at":"2025-12-26T14:24:38.837Z","avatar_url":"https://github.com/brokenpip3.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Lotb\n\n[![Coverage badge](https://img.shields.io/badge/dynamic/json?color=brightgreen\u0026label=coverage\u0026query=%24.message\u0026url=https%3A%2F%2Fraw.githubusercontent.com%2Fbrokenpip3%2Flotb%2Fpython-coverage-comment-action-data%2Fendpoint.json)](https://htmlpreview.github.io/?https://github.com/brokenpip3/lotb/blob/python-coverage-comment-action-data/htmlcov/index.html)\n![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/brokenpip3/lotb/ci.yaml)\n\n[![built with nix](https://builtwithnix.org/badge.svg)](https://builtwithnix.org)\n\n![logo](logo.png)\n\n*One bot to rule them all, one bot to find them, one bot to bring them all and in the darkness run them.* 💍\n\n## Why❓\n\u003cdetails\u003e\n\u003csummary\u003e\n\u003c/summary\u003e\nSeveral years ago telegram introduced the Bot API, and since then, I have used it to automate tasks and send notifications to my groups.\n\nWhile the `python-telegram-bot` library has been my go-to choice, I often found myself reinventing the wheel for each bot I created or used from others' projects.\nI also had to update all my bots whenever telegram introduced new features or changed its implementation.\n\nTo eliminate this pain and save time, I decided to develop a more dry approach for my bots.\nThis system is plugin-based and it shares a common core logic, making it easier to define new bots with just a few lines of code.\n\u003c/details\u003e\n\n### Features ✨\n\n* Plugins based: you can enable or disable plugins either at runtime or in the config\n* Each plugin has its own config entry and entry in the config can be overridden by the env var (useful for secrets)\n* Built-in helper methods to:\n  * create, register and run bot commands\n  * intercept messages based on a regex and run a callback\n  * use sqlite to store data\n  * reply to messages or quoted messages\n  * support for internal logs\n  * schedule tasks for your plugin using the job queue scheduler\n  * support for job queue scheduler so you can schedule tasks for your plugin\n  * auth: define a list of users or authorize specific groups to interact with the bot\n  * create llm completions using litellm\n* Great test coverage (\u003e 80%) ✅\n\n### How to use it? 📦\n\n* Clone this repo (will probably be published on pypi in the future)\n* Install the dependencies with poetry\n* Create a new bot on telegram and get the token\n* Create a config file, see [config.example.toml](./config.example.toml), the base is something like this:\n```toml\n[core]\ndatabase = \"lotb.db\" # path to the sqlite database\nadmins = [''] # list of telegram user ids that can interact with the bot\ndebug = \"false\" # set to true to enable debug logs\n```\n\n* Run the bot\n\n```bash\npoetry install\npoetry run lotb --config config.toml\n```\n\n### Docker 🐳\n\nYou can also run the bot using docker, the registry is `ghcr.io/brokenpip3/lotb`, just create a config file and mount it in the container:\n\n```bash\ndocker run -v $(pwd)/config.toml:/config.toml ghcr.io/brokenpip3/lotb:0.0.1 --config /config.toml\n```\n\nor you can also find a docker-compose example in the [docker-compose-example.yaml](./docker-compose-example.yaml) file.\n\n## Plugins 🔌\n\nBy default, the bot will load all the plugins in the `lotb/plugins` directory.\nYou can disable a plugin by removing it from the `plugins` list in the config file.\nYou can also make the bot load a plugin from a different directory by passing another path\nto the `core.plugins_additional_directory` key in the config file.\n\n### Available plugins\n\nBe aware that these are the plugins that I wrote for my own use, and they may or may not be useful for you.\n\n* [Welcome](./lotb/plugins/welcome.py): Just an example plugin that will reply to a welcome message\n* [RSSfeed](./lotb/plugins/rssfeed.py): A plugin that will fetch a list of rss feeds and send the new entries every X minutes:\n  ```toml\n  [plugins.rssfeed]\n  enabled = true # enable or disable the plugin\n  chatid = \"\" # the chat id where the bot will send the messages\n  interval = \"30\" # the interval in seconds\n  feeds = [\n      {name = \"mullvad\", url = \"https://mullvad.net/en/blog/feed/atom/\"},\n  ] # list of feeds\n  ```\n* [Prometheus_alerts](./lotb/plugins/prometheus_alerts.py): A plugin that will fetch and send the alerts from a prometheus server:\n  ```toml\n  [plugins.prometheus_alerts]\n  enabled = true # enable or disable the plugin\n  chatid = \"\" # the chat id where the bot will send the messages\n  alertmanager_url = \"https://my.prometheus.server\" # the url of the prometheus server\n  alert_interval = 1 # the interval in minutes\n  ```\n* [Readwise](./lotb/plugins/readwise.py): A plugin that will let you add the quoted url in your Readwise reader account:\n  ```toml\n  [plugins.readwise]\n  enabled = true # enable or disable the plugin\n  token = \"your_token\" # can be also set as env var: LOTB_PLUGINS_READWISE_TOKEN\n  ```\n* [Notes](./lotb/plugins/notes.py): A plugin that will let you save notes in sqlite and retrieve them later:\n  ```toml\n  [plugins.notes]\n  enabled = true # enable or disable the plugin\n  ```\n* [Memo](./lotb/plugins/memo.py): A plugin that will let you save memos based on regex or the first word and save it in separate files.\n  For each category, the plugin will save the memo in a different file automatically by starting the message with the category name,\n  for instance: `todo: buy milk` will save the memo in the todo file:\n  ```toml\n  [plugins.memo]\n  generic = \"path/to/generic/memo\" # path to the generic memo file\n  todo = \"path/to/todo\" # path to the todo memo file\n  book = \"\" # path to the book memo file\n  series = \"\" # path to the series memo file\n  film = \"\" # path to the film memo file\n  ```\n* [Image](./lotb/plugins/image.py): A plugin that will let you save images/gifs/stickers ids in sqlite and call it in a group chat with\n  `name.\u003ctype\u003e` (img,gif,stk) or search for images with `/image search term` using Unsplash. If no term is provided, the plugin will return the list of images saved in the database:\n  ```toml\n  [plugins.image]\n  accesskey = \"your_access_key\" # optional: can be also set as env var: LOTB_PLUGINS_IMAGE_ACCESSKEY\n  secretkey = \"your_secret_key\" # optional: can be also set as env var: LOTB_PLUGINS_IMAGE_SECRETKEY\n  ```\n* [SocialFix](./lotb/plugins/socialfix.py): A simple plugin that will fix twitter, instagram and reddit links to show the preview in telegram:\n  ```toml\n  [plugins.socialfix]\n  enabled = true # enable or disable the plugin\n  instagram = true # enable or disable the instagram fix\n  twitter = true # enable or disable the twitter fix\n  reddit = true # enable or disable the reddit fix\n  ```\n* [Quote](./lotb/plugins/quote.py): A plugin that will let you save quotes in sqlite and retrieve them later. If no quoted message is provided,\n  the plugin will return a random quote from the database:\n  ```toml\n  [plugins.quote]\n  enabled = true # enable or disable the plugin\n  ```\n* [remindme](./lotb/plugins/remindme.py): A plugin that will let you set reminders for a specific message like the reddit bot.\n  The plugin will send a message to the chat after the specified time (s,m,h,d,w,M,y) with the original quoted message.\n  ```toml\n  [plugins.remindme]\n  enabled = true # enable or disable the plugin\n  ```\n* [llm](./lotb/plugins/llm.py): A unified plugin that provides LLM capabilities with two modes:\n\n  **Simple Mode (default):** A basic chat assistant that keeps conversation history per user. Uses [litellm](https://github.com/BerriAI/litellm) so you can use any supported model.\n  Interact with `/llm \u003cquery\u003e` or use a friendly trigger name (for instance: \"Dino, what is borrowing in Rust?\").\n\n  **Assistant Mode:** Extends simple mode with MCP (Model Context Protocol) support, allowing the LLM to access tools and resources from [streamable http](https://modelcontextprotocol.io/docs/concepts/transports#streamable-http) servers.\n  The assistant can call tools, read resources, and provide rich contextual responses. Enable with `assistant = true`.\n\n  ```toml\n  [plugins.llm]\n  enabled = true # enable or disable the plugin\n  model = \"deepseek/deepseek-chat\"\n  apikey = \"your_api_key\" # can be also set as env var: LOTB_PLUGINS_LLM_APIKEY\n  friendlyname = \"Dino\" # optional: set a friendly name to trigger the plugin without /llm command\n  maxhistory = 3 # optional: number of messages to keep in history, default 3\n  assistant = false # optional: enable MCP tool/resource capabilities, default false\n\n  # Only used when assistant = true\n  [[plugins.llm.mcpservers]]\n  name = \"task\"\n  url = \"http://localhost:8125\"\n  auth_value = \"your-secret-token-here\"\n\n  [[plugins.llm.mcpservers]]\n  name = \"calendar\"\n  url = \"http://localhost:8126\"\n  auth_value = \"your-secret-token-here\"\n  ```\n\n  When in assistant mode, additional commands are available:\n  - `/llm tools` - show available MCP tools and resources\n  - `/llm status` - show plugin status and configuration\n  - `/llm help` - show help message\n\n\n### How to add a plugin? What helper methods are available?\n\nCheck [CONTRIBUTING.md](./CONTRIBUTING.md)\n\n## Credits 🙏\n\n* Thanks to the [`python-telegram-bot`](https://github.com/python-telegram-bot/python-telegram-bot) dev team for the great library\n* Thanks DALL-E for the great logo\n* This repo has been initialized with:\n\n```bash\nnix flake init -t github:brokenpip3/my-flake-templates#python-poetry\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrokenpip3%2Flotb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrokenpip3%2Flotb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrokenpip3%2Flotb/lists"}