raito


Nameraito JSON
Version 1.2.2 PyPI version JSON
download
home_pageNone
SummaryREPL, hot-reload, keyboards, pagination, and internal dev tools β€” all in one. That's Raito.
upload_time2025-07-10 20:47:28
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseNone
keywords aiogram aiogram3 bot devtools hot-reload keyboard pagination raito repl telegram
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <div align="center">
    <h1 id="header" align="center">πŸ”¦ Raito</h1>
    <p align="center">REPL, hot-reload, keyboards, pagination, and internal dev tools β€” all in one. That's Raito.</p>
</div>

<div align="center">
<img alt="GitHub License" src="https://img.shields.io/github/license/Aidenable/Raito?style=for-the-badge&labelColor=252622&link=https%3A%2F%2Fgithub.com%2FAidenable%2FRaito%2Fblob%2Fmain%2FLICENSE">
<img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/Aidenable/Raito?style=for-the-badge&labelColor=262422&color=F59937">
<img alt="PyPI - Version" src="https://img.shields.io/pypi/v/raito?style=for-the-badge&labelColor=222226&color=3760F5&link=https%3A%2F%2Fpypi.org%2Fproject%2Fraito%2F">
</div>

<div align="center">
<img alt="uv" src="https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fastral-sh%2Fuv%2Fmain%2Fassets%2Fbadge%2Fv0.json&style=flat-square&labelColor=232226&color=6341AC&link=https%3A%2F%2Fastral.sh%2Fuv">
<img alt="Ruff" src="https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fastral-sh%2Fruff%2Fmain%2Fassets%2Fbadge%2Fv2.json&style=flat-square&labelColor=232226&color=6341AC&link=https%3A%2F%2Fastral.sh%2Fruff">
<img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/raito?style=flat-square&labelColor=222426&color=19A4F3">
<img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Aidenable/Raito/ci.yml?style=flat-square&labelColor=232622">
</div>

---

## Highlights

- πŸ”₯ **Hot Reload** β€” automatic router loading and file watching for instant development cycles
- 🎭 **Role System** β€” `@raito.roles` with pre-configured roles (admin, mod, support, etc) and selector UI
- πŸ“š **Pagination** β€” easy pagination over text and media using inline buttons
- πŸ’¬ **FSM Toolkit** β€” interactive confirmations, questionnaires, and mockable message flow
- πŸš€ **CLI Generator** β€” `$ raito init` creates a ready-to-use bot template in seconds
- πŸ› οΈ **Command Registration** β€” automatic setup of bot commands with descriptions for each
- πŸ›‘οΈ **Rate Limiting** β€” apply global or per-command throttling via decorators or middleware
- πŸ’Ύ **Database Storages** β€” optional SQL support
- πŸ§ͺ **REPL** β€” execute async Python in context (`_msg`, `_user`, `_raito`)
- πŸ” **Params Parser** β€” extracts and validates command arguments
- πŸ“Š **Metrics** β€” inspect memory usage, uptime, and caching stats
- πŸ“ƒ **Logging** β€” view and filter runtime logs without leaving Telegram
- 🧰 **Debug Utils** β€” run shell commands, monitor jobs, inspect command states, and more


## Installation

```bash
pip install -U raito
```


## Quick Start

```python
import asyncio

from aiogram import Bot, Dispatcher
from raito import Raito


async def main() -> None:
    bot = Bot(token="TOKEN")
    dispatcher = Dispatcher()
    raito = Raito(dispatcher, "src/handlers")

    await raito.setup()
    await dispatcher.start_polling(bot)


if __name__ == "__main__":
    asyncio.run(main())
```

## Why Raito?

Raito speeds up your bot development by removing the boring parts β€” no more boilerplate, no more manual restarts, no more duplicated code across projects. \
Everything that used to slow you down is already solved.


## Showcases

#### πŸ“¦ Handling Commands

You can control access to commands using `@rt.roles`

The `@rt.description` decorator adds a description to each command β€” they will show up in the slash menu automatically.

For commands like `/ban 1234`, use `@rt.params` to extract and validate the arguments.

```python
@router.message(filters.Command("ban"))
@rt.roles(rt.Role.OWNER, rt.Role.ADMINISTRATOR, rt.Role.MODERATOR)
@rt.description("Ban a user")
@rt.params(user_id=int)
async def ban(message: types.Message, user_id: int, bot: Bot):
    await bot.ban_chat_member(chat_id=message.chat.id, user_id=user_id)
    await message.answer(text="βœ… User banned successfully!")
```

---

#### πŸ”₯ Hot-Reload & Router Management

Whenever you change a file with handlers, Raito automatically reloads it without restarting the bot.

You can also manage your routers manually using the `.rt load`, `.rt unload`, `.rt reload`, or `.rt routers` commands in the bot.

https://github.com/user-attachments/assets/c7ecfb7e-b709-4f92-9de3-efc4982cc926

---

#### 🎭 Roles

Use built-in roles to set different access levels for team members.

<p align="left">
  <img src=".github/assets/roles.png" alt="Roles" width="600">
</p>

---

#### πŸ“š Pagination

The simplest, most native and most effective pagination. Unlike many other libraries, it **does not use internal storage**. \
It is very user-friendly and fully customizable.

```python
@router.message(filters.Command("pagination"))
async def pagination(message: Message, raito: Raito, bot: Bot):
    if not message.from_user:
        return

    await raito.paginate(
        "button_list",
        chat_id=message.chat.id,
        bot=bot,
        from_user=message.from_user,
        limit=5,
    )


# mock data
BUTTONS = [
    InlineKeyboardButton(text=f"Button #{i}", callback_data=f"button:{i}")
    for i in range(10000)
]

@rt.on_pagination(router, "button_list")
async def on_pagination(query: CallbackQuery, paginator: InlinePaginator, offset: int, limit: int):
    content = BUTTONS[offset : offset + limit]
    await paginator.answer(text="Here is your buttons:", buttons=content)
```

---

#### ⌨️ Keyboards

Sometimes you want quick layouts. Sometimes β€” full control. You get both.

##### Static (layout-based)
```python
@rt.keyboard.static(inline=True)
def information():
    return [
        ("πŸ“„ Terms of Service", "tos"),
        [("ℹ️ About", "about"), ("βš™οΈ Website", "web")],
    ]
```

##### Dynamic (builder-based)
```python
@rt.keyboard.dynamic(1, 2, adjust=True, inline=False)
def start_menu(builder: ReplyKeyboardBuilder, app_url: str):
    builder.button(text="πŸ“± Open App", web_app=WebAppInfo(url=app_url))
    builder.button(text="πŸ’¬ Support")
    builder.button(text="πŸ“’ Channel")
```

## Contributing

Have an idea, found a bug, or want to improve something? \
Contributions are welcome! Feel free to open an issue or submit a pull request.


## Security

If you discover a security vulnerability, please report it responsibly. \
You can open a private GitHub issue or contact the maintainer directly.

There’s no bounty program β€” this is a solo open source project. \
Use in production at your own risk.

> For full details, check out the [Security Policy](SECURITY.md).


## Questions?

Open an issue or start a discussion in the GitHub Discussions tab. \
You can also ping [@Aidenable](https://github.com/Aidenable) for feedback or ideas.

[![GO TOP](https://img.shields.io/badge/GO%20TOP-black?style=for-the-badge)](#header)

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "raito",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "aiogram, aiogram3, bot, devtools, hot-reload, keyboard, pagination, raito, repl, telegram",
    "author": null,
    "author_email": "Aiden <aidenthedev@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/9f/90/603682759bc1f065d6db60d439597d6c0d72b11abb443f24f40eb7e3f032/raito-1.2.2.tar.gz",
    "platform": null,
    "description": "<div align=\"center\">\n    <h1 id=\"header\" align=\"center\">\ud83d\udd26 Raito</h1>\n    <p align=\"center\">REPL, hot-reload, keyboards, pagination, and internal dev tools \u2014 all in one. That's Raito.</p>\n</div>\n\n<div align=\"center\">\n<img alt=\"GitHub License\" src=\"https://img.shields.io/github/license/Aidenable/Raito?style=for-the-badge&labelColor=252622&link=https%3A%2F%2Fgithub.com%2FAidenable%2FRaito%2Fblob%2Fmain%2FLICENSE\">\n<img alt=\"GitHub Repo stars\" src=\"https://img.shields.io/github/stars/Aidenable/Raito?style=for-the-badge&labelColor=262422&color=F59937\">\n<img alt=\"PyPI - Version\" src=\"https://img.shields.io/pypi/v/raito?style=for-the-badge&labelColor=222226&color=3760F5&link=https%3A%2F%2Fpypi.org%2Fproject%2Fraito%2F\">\n</div>\n\n<div align=\"center\">\n<img alt=\"uv\" src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fastral-sh%2Fuv%2Fmain%2Fassets%2Fbadge%2Fv0.json&style=flat-square&labelColor=232226&color=6341AC&link=https%3A%2F%2Fastral.sh%2Fuv\">\n<img alt=\"Ruff\" src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fastral-sh%2Fruff%2Fmain%2Fassets%2Fbadge%2Fv2.json&style=flat-square&labelColor=232226&color=6341AC&link=https%3A%2F%2Fastral.sh%2Fruff\">\n<img alt=\"PyPI - Python Version\" src=\"https://img.shields.io/pypi/pyversions/raito?style=flat-square&labelColor=222426&color=19A4F3\">\n<img alt=\"GitHub Actions Workflow Status\" src=\"https://img.shields.io/github/actions/workflow/status/Aidenable/Raito/ci.yml?style=flat-square&labelColor=232622\">\n</div>\n\n---\n\n## Highlights\n\n- \ud83d\udd25 **Hot Reload** \u2014 automatic router loading and file watching for instant development cycles\n- \ud83c\udfad **Role System** \u2014 `@raito.roles` with pre-configured roles (admin, mod, support, etc) and selector UI\n- \ud83d\udcda **Pagination** \u2014 easy pagination over text and media using inline buttons\n- \ud83d\udcac **FSM Toolkit** \u2014 interactive confirmations, questionnaires, and mockable message flow\n- \ud83d\ude80 **CLI Generator** \u2014 `$ raito init` creates a ready-to-use bot template in seconds\n- \ud83d\udee0\ufe0f **Command Registration** \u2014 automatic setup of bot commands with descriptions for each\n- \ud83d\udee1\ufe0f **Rate Limiting** \u2014 apply global or per-command throttling via decorators or middleware\n- \ud83d\udcbe **Database Storages** \u2014 optional SQL support\n- \ud83e\uddea **REPL** \u2014 execute async Python in context (`_msg`, `_user`, `_raito`)\n- \ud83d\udd0d **Params Parser** \u2014 extracts and validates command arguments\n- \ud83d\udcca **Metrics** \u2014 inspect memory usage, uptime, and caching stats\n- \ud83d\udcc3 **Logging** \u2014 view and filter runtime logs without leaving Telegram\n- \ud83e\uddf0 **Debug Utils** \u2014 run shell commands, monitor jobs, inspect command states, and more\n\n\n## Installation\n\n```bash\npip install -U raito\n```\n\n\n## Quick Start\n\n```python\nimport asyncio\n\nfrom aiogram import Bot, Dispatcher\nfrom raito import Raito\n\n\nasync def main() -> None:\n    bot = Bot(token=\"TOKEN\")\n    dispatcher = Dispatcher()\n    raito = Raito(dispatcher, \"src/handlers\")\n\n    await raito.setup()\n    await dispatcher.start_polling(bot)\n\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\n## Why Raito?\n\nRaito speeds up your bot development by removing the boring parts \u2014 no more boilerplate, no more manual restarts, no more duplicated code across projects. \\\nEverything that used to slow you down is already solved.\n\n\n## Showcases\n\n#### \ud83d\udce6 Handling Commands\n\nYou can control access to commands using `@rt.roles`\n\nThe `@rt.description` decorator adds a description to each command \u2014 they will show up in the slash menu automatically.\n\nFor commands like `/ban 1234`, use `@rt.params` to extract and validate the arguments.\n\n```python\n@router.message(filters.Command(\"ban\"))\n@rt.roles(rt.Role.OWNER, rt.Role.ADMINISTRATOR, rt.Role.MODERATOR)\n@rt.description(\"Ban a user\")\n@rt.params(user_id=int)\nasync def ban(message: types.Message, user_id: int, bot: Bot):\n    await bot.ban_chat_member(chat_id=message.chat.id, user_id=user_id)\n    await message.answer(text=\"\u2705 User banned successfully!\")\n```\n\n---\n\n#### \ud83d\udd25 Hot-Reload & Router Management\n\nWhenever you change a file with handlers, Raito automatically reloads it without restarting the bot.\n\nYou can also manage your routers manually using the `.rt load`, `.rt unload`, `.rt reload`, or `.rt routers` commands in the bot.\n\nhttps://github.com/user-attachments/assets/c7ecfb7e-b709-4f92-9de3-efc4982cc926\n\n---\n\n#### \ud83c\udfad Roles\n\nUse built-in roles to set different access levels for team members.\n\n<p align=\"left\">\n  <img src=\".github/assets/roles.png\" alt=\"Roles\" width=\"600\">\n</p>\n\n---\n\n#### \ud83d\udcda Pagination\n\nThe simplest, most native and most effective pagination. Unlike many other libraries, it **does not use internal storage**. \\\nIt is very user-friendly and fully customizable.\n\n```python\n@router.message(filters.Command(\"pagination\"))\nasync def pagination(message: Message, raito: Raito, bot: Bot):\n    if not message.from_user:\n        return\n\n    await raito.paginate(\n        \"button_list\",\n        chat_id=message.chat.id,\n        bot=bot,\n        from_user=message.from_user,\n        limit=5,\n    )\n\n\n# mock data\nBUTTONS = [\n    InlineKeyboardButton(text=f\"Button #{i}\", callback_data=f\"button:{i}\")\n    for i in range(10000)\n]\n\n@rt.on_pagination(router, \"button_list\")\nasync def on_pagination(query: CallbackQuery, paginator: InlinePaginator, offset: int, limit: int):\n    content = BUTTONS[offset : offset + limit]\n    await paginator.answer(text=\"Here is your buttons:\", buttons=content)\n```\n\n---\n\n#### \u2328\ufe0f Keyboards\n\nSometimes you want quick layouts. Sometimes \u2014 full control. You get both.\n\n##### Static (layout-based)\n```python\n@rt.keyboard.static(inline=True)\ndef information():\n    return [\n        (\"\ud83d\udcc4 Terms of Service\", \"tos\"),\n        [(\"\u2139\ufe0f About\", \"about\"), (\"\u2699\ufe0f Website\", \"web\")],\n    ]\n```\n\n##### Dynamic (builder-based)\n```python\n@rt.keyboard.dynamic(1, 2, adjust=True, inline=False)\ndef start_menu(builder: ReplyKeyboardBuilder, app_url: str):\n    builder.button(text=\"\ud83d\udcf1 Open App\", web_app=WebAppInfo(url=app_url))\n    builder.button(text=\"\ud83d\udcac Support\")\n    builder.button(text=\"\ud83d\udce2 Channel\")\n```\n\n## Contributing\n\nHave an idea, found a bug, or want to improve something? \\\nContributions are welcome! Feel free to open an issue or submit a pull request.\n\n\n## Security\n\nIf you discover a security vulnerability, please report it responsibly. \\\nYou can open a private GitHub issue or contact the maintainer directly.\n\nThere\u2019s no bounty program \u2014 this is a solo open source project. \\\nUse in production at your own risk.\n\n> For full details, check out the [Security Policy](SECURITY.md).\n\n\n## Questions?\n\nOpen an issue or start a discussion in the GitHub Discussions tab. \\\nYou can also ping [@Aidenable](https://github.com/Aidenable) for feedback or ideas.\n\n[![GO TOP](https://img.shields.io/badge/GO%20TOP-black?style=for-the-badge)](#header)\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "REPL, hot-reload, keyboards, pagination, and internal dev tools \u2014 all in one. That's Raito.",
    "version": "1.2.2",
    "project_urls": {
        "Documentation": "https://aidenable.github.io/raito",
        "Repository": "https://github.com/Aidenable/raito"
    },
    "split_keywords": [
        "aiogram",
        " aiogram3",
        " bot",
        " devtools",
        " hot-reload",
        " keyboard",
        " pagination",
        " raito",
        " repl",
        " telegram"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "903ae54519009aacc34c5d139037b93173ae04fecbd40ebffb781405d2de2602",
                "md5": "6bafdef7f99e3a6e9390031cb82dc729",
                "sha256": "6cdaf73bf3ff24c283c720c6d9fe98a166d47567ac15225a16df0ec00bc5f8ef"
            },
            "downloads": -1,
            "filename": "raito-1.2.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "6bafdef7f99e3a6e9390031cb82dc729",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 65233,
            "upload_time": "2025-07-10T20:47:27",
            "upload_time_iso_8601": "2025-07-10T20:47:27.212420Z",
            "url": "https://files.pythonhosted.org/packages/90/3a/e54519009aacc34c5d139037b93173ae04fecbd40ebffb781405d2de2602/raito-1.2.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "9f90603682759bc1f065d6db60d439597d6c0d72b11abb443f24f40eb7e3f032",
                "md5": "99a880af83af2be7e13dbc34ec65df34",
                "sha256": "f5c11350b99bddf093aa8bbd2edbf2ae4a055d23ae1bfceb49128de3e0892d4a"
            },
            "downloads": -1,
            "filename": "raito-1.2.2.tar.gz",
            "has_sig": false,
            "md5_digest": "99a880af83af2be7e13dbc34ec65df34",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 39089,
            "upload_time": "2025-07-10T20:47:28",
            "upload_time_iso_8601": "2025-07-10T20:47:28.586999Z",
            "url": "https://files.pythonhosted.org/packages/9f/90/603682759bc1f065d6db60d439597d6c0d72b11abb443f24f40eb7e3f032/raito-1.2.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-10 20:47:28",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Aidenable",
    "github_project": "raito",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "raito"
}
        
Elapsed time: 0.41747s