aiogram-tool 1.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. aiogram_tool-1.2.2/.github/workflows/main.yml +66 -0
  2. aiogram_tool-1.2.2/.github/workflows/release.yml +60 -0
  3. aiogram_tool-1.2.2/.gitignore +5 -0
  4. aiogram_tool-1.2.2/.pre-commit-config.yaml +7 -0
  5. aiogram_tool-1.2.2/.python-version +1 -0
  6. aiogram_tool-1.2.2/CONTRIBUTING.md +213 -0
  7. aiogram_tool-1.2.2/LICENSE.md +21 -0
  8. aiogram_tool-1.2.2/PKG-INFO +235 -0
  9. aiogram_tool-1.2.2/README.md +220 -0
  10. aiogram_tool-1.2.2/aiogram_tool/__init__.py +0 -0
  11. aiogram_tool-1.2.2/aiogram_tool/storage/__init__.py +15 -0
  12. aiogram_tool-1.2.2/aiogram_tool/storage/base.py +20 -0
  13. aiogram_tool-1.2.2/aiogram_tool/storage/impl/__init__.py +0 -0
  14. aiogram_tool-1.2.2/aiogram_tool/storage/impl/file.py +72 -0
  15. aiogram_tool-1.2.2/aiogram_tool/storage/impl/memory.py +33 -0
  16. aiogram_tool-1.2.2/aiogram_tool/storage/impl/redis.py +39 -0
  17. aiogram_tool-1.2.2/aiogram_tool/tools/__init__.py +0 -0
  18. aiogram_tool-1.2.2/aiogram_tool/tools/callback_data/__init__.py +4 -0
  19. aiogram_tool-1.2.2/aiogram_tool/tools/callback_data/answer.py +10 -0
  20. aiogram_tool-1.2.2/aiogram_tool/tools/callback_data/filter.py +120 -0
  21. aiogram_tool-1.2.2/aiogram_tool/tools/depend/__init__.py +16 -0
  22. aiogram_tool-1.2.2/aiogram_tool/tools/depend/components/__init__.py +0 -0
  23. aiogram_tool-1.2.2/aiogram_tool/tools/depend/components/exit.py +4 -0
  24. aiogram_tool-1.2.2/aiogram_tool/tools/depend/components/filter.py +63 -0
  25. aiogram_tool-1.2.2/aiogram_tool/tools/depend/components/inner_middleware.py +54 -0
  26. aiogram_tool-1.2.2/aiogram_tool/tools/depend/components/outer_middleware.py +27 -0
  27. aiogram_tool-1.2.2/aiogram_tool/tools/depend/depend.py +20 -0
  28. aiogram_tool-1.2.2/aiogram_tool/tools/depend/storage/__init__.py +0 -0
  29. aiogram_tool-1.2.2/aiogram_tool/tools/depend/storage/memory.py +29 -0
  30. aiogram_tool-1.2.2/aiogram_tool/tools/depend/tool.py +72 -0
  31. aiogram_tool-1.2.2/aiogram_tool/tools/depend/types/__init__.py +0 -0
  32. aiogram_tool-1.2.2/aiogram_tool/tools/depend/types/enums.py +15 -0
  33. aiogram_tool-1.2.2/aiogram_tool/tools/depend/types/exceptions.py +25 -0
  34. aiogram_tool-1.2.2/aiogram_tool/tools/depend/types/schema.py +19 -0
  35. aiogram_tool-1.2.2/aiogram_tool/tools/depend/utils/__init__.py +0 -0
  36. aiogram_tool-1.2.2/aiogram_tool/tools/depend/utils/inspect.py +56 -0
  37. aiogram_tool-1.2.2/aiogram_tool/tools/depend/utils/registry_manager.py +64 -0
  38. aiogram_tool-1.2.2/aiogram_tool/tools/depend/utils/resolver.py +163 -0
  39. aiogram_tool-1.2.2/aiogram_tool/tools/depend/utils/scope_registry.py +42 -0
  40. aiogram_tool-1.2.2/aiogram_tool/tools/depend/utils/stack_manager.py +35 -0
  41. aiogram_tool-1.2.2/aiogram_tool/tools/limit/__init__.py +5 -0
  42. aiogram_tool-1.2.2/aiogram_tool/tools/limit/answer.py +20 -0
  43. aiogram_tool-1.2.2/aiogram_tool/tools/limit/filter.py +82 -0
  44. aiogram_tool-1.2.2/aiogram_tool/tools/limit/rate_limit/__init__.py +9 -0
  45. aiogram_tool-1.2.2/aiogram_tool/tools/limit/rate_limit/base.py +36 -0
  46. aiogram_tool-1.2.2/aiogram_tool/tools/limit/rate_limit/fixed_window.py +70 -0
  47. aiogram_tool-1.2.2/aiogram_tool/tools/limit/rate_limit/sliding_window.py +79 -0
  48. aiogram_tool-1.2.2/aiogram_tool/tools/limit/rate_limit/token_bucket.py +102 -0
  49. aiogram_tool-1.2.2/aiogram_tool/tools/limit/schema.py +24 -0
  50. aiogram_tool-1.2.2/aiogram_tool/tools/limit/tool.py +21 -0
  51. aiogram_tool-1.2.2/aiogram_tool/tools/setup.py +25 -0
  52. aiogram_tool-1.2.2/aiogram_tool/types.py +1 -0
  53. aiogram_tool-1.2.2/docs/en/callback_data.md +217 -0
  54. aiogram_tool-1.2.2/docs/en/depend.md +397 -0
  55. aiogram_tool-1.2.2/docs/en/limit.md +371 -0
  56. aiogram_tool-1.2.2/docs/ru/callback_data.md +219 -0
  57. aiogram_tool-1.2.2/docs/ru/depend.md +397 -0
  58. aiogram_tool-1.2.2/docs/ru/limit.md +370 -0
  59. aiogram_tool-1.2.2/examples/callback_data/basic.py +68 -0
  60. aiogram_tool-1.2.2/examples/callback_data/custom_expired_answer.py +72 -0
  61. aiogram_tool-1.2.2/examples/callback_data/redis_storage.py +68 -0
  62. aiogram_tool-1.2.2/examples/depend/classes.py +63 -0
  63. aiogram_tool-1.2.2/examples/depend/filter_and_exit.py +46 -0
  64. aiogram_tool-1.2.2/examples/depend/override.py +41 -0
  65. aiogram_tool-1.2.2/examples/depend/scopes.py +62 -0
  66. aiogram_tool-1.2.2/examples/depend/subdepends.py +45 -0
  67. aiogram_tool-1.2.2/examples/limit/advanced.py +66 -0
  68. aiogram_tool-1.2.2/examples/limit/basic.py +37 -0
  69. aiogram_tool-1.2.2/examples/limit/limit_algorithms.py +67 -0
  70. aiogram_tool-1.2.2/pyproject.toml +57 -0
  71. aiogram_tool-1.2.2/pytest.ini +5 -0
  72. aiogram_tool-1.2.2/tests/__init__.py +0 -0
  73. aiogram_tool-1.2.2/tests/callback_data/__init__.py +0 -0
  74. aiogram_tool-1.2.2/tests/callback_data/conftest.py +20 -0
  75. aiogram_tool-1.2.2/tests/callback_data/test_filter.py +118 -0
  76. aiogram_tool-1.2.2/tests/callback_data/test_pack.py +27 -0
  77. aiogram_tool-1.2.2/tests/callback_data/test_unique_id.py +13 -0
  78. aiogram_tool-1.2.2/tests/callback_data/test_with_handler.py +86 -0
  79. aiogram_tool-1.2.2/tests/conftest.py +69 -0
  80. aiogram_tool-1.2.2/tests/depend/__init__.py +0 -0
  81. aiogram_tool-1.2.2/tests/depend/conftest.py +64 -0
  82. aiogram_tool-1.2.2/tests/depend/test_classes.py +52 -0
  83. aiogram_tool-1.2.2/tests/depend/test_exit.py +35 -0
  84. aiogram_tool-1.2.2/tests/depend/test_filter.py +56 -0
  85. aiogram_tool-1.2.2/tests/depend/test_from.py +39 -0
  86. aiogram_tool-1.2.2/tests/depend/test_generator.py +107 -0
  87. aiogram_tool-1.2.2/tests/depend/test_lambda.py +25 -0
  88. aiogram_tool-1.2.2/tests/depend/test_middleware_data.py +73 -0
  89. aiogram_tool-1.2.2/tests/depend/test_override.py +46 -0
  90. aiogram_tool-1.2.2/tests/depend/test_scopes.py +264 -0
  91. aiogram_tool-1.2.2/tests/depend/test_setup.py +118 -0
  92. aiogram_tool-1.2.2/tests/depend/test_singleton_lock.py +46 -0
  93. aiogram_tool-1.2.2/tests/depend/test_subdepend.py +35 -0
  94. aiogram_tool-1.2.2/tests/limit/__init__.py +0 -0
  95. aiogram_tool-1.2.2/tests/limit/conftest.py +35 -0
  96. aiogram_tool-1.2.2/tests/limit/test_rate_limits.py +254 -0
  97. aiogram_tool-1.2.2/tests/limit/test_setup.py +14 -0
  98. aiogram_tool-1.2.2/tests/storage/__init__.py +0 -0
  99. aiogram_tool-1.2.2/tests/storage/test_storages.py +33 -0
  100. aiogram_tool-1.2.2/uv.lock +1113 -0
@@ -0,0 +1,66 @@
1
+ name: Run Tests
2
+
3
+ on:
4
+ push:
5
+ branches: ["master", "feature"]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ name: Python ${{ matrix.python-version }} on ${{ matrix.os }}
11
+ runs-on: ${{ matrix.os }}
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ os: [ubuntu-latest]
16
+ python-version: ['3.11', '3.12']
17
+
18
+ services:
19
+ redis:
20
+ image: redis:7-alpine
21
+ ports:
22
+ - 6379:6379
23
+ options: >-
24
+ --health-cmd "redis-cli ping"
25
+ --health-interval 10s
26
+ --health-timeout 5s
27
+ --health-retries 5
28
+
29
+ steps:
30
+ - name: Checkout code
31
+ uses: actions/checkout@v5
32
+
33
+ - name: Install uv
34
+ uses: astral-sh/setup-uv@v10.0.1
35
+ with:
36
+ enable-cache: true
37
+ python-version: ${{ matrix.python-version }}
38
+
39
+ - name: Install dependencies
40
+ run: uv sync --all-extras --dev
41
+
42
+ - name: Run tests with pytest
43
+ run: uv run pytest
44
+
45
+ lint:
46
+ name: Ruff linter
47
+ runs-on: ubuntu-latest
48
+
49
+ steps:
50
+ - name: Checkout code
51
+ uses: actions/checkout@v5
52
+
53
+ - name: Install uv
54
+ uses: astral-sh/setup-uv@v10.0.1
55
+ with:
56
+ enable-cache: true
57
+ python-version: "3.12"
58
+
59
+ - name: Install dependencies
60
+ run: uv sync --locked
61
+
62
+ - name: Check lint
63
+ run: uv run ruff check
64
+
65
+ - name: Check format
66
+ run: uv run ruff format --check
@@ -0,0 +1,60 @@
1
+ name: Publish release to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v[0-9]+.[0-9]+.[0-9]+"
7
+ - "v[0-9]+.[0-9]+.[0-9]+rc[0-9]+"
8
+ - "v[0-9]+.[0-9]+.[0-9]+[ab][0-9]+"
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ steps:
18
+ - name: Checkout
19
+ uses: actions/checkout@v5
20
+ with:
21
+ persist-credentials: false
22
+
23
+ - name: Install uv
24
+ uses: astral-sh/setup-uv@v10.0.1
25
+ with:
26
+ enable-cache: false
27
+
28
+ - name: Build
29
+ run: uv build
30
+
31
+ - name: Upload distributions
32
+ uses: actions/upload-artifact@v4
33
+ with:
34
+ name: dist
35
+ path: dist/
36
+
37
+ publish:
38
+ needs: build
39
+ runs-on: ubuntu-latest
40
+
41
+ environment:
42
+ name: pypi
43
+
44
+ permissions:
45
+ id-token: write
46
+
47
+ steps:
48
+ - name: Install uv
49
+ uses: astral-sh/setup-uv@v10.0.1
50
+ with:
51
+ enable-cache: false
52
+
53
+ - name: Download distributions
54
+ uses: actions/download-artifact@v4
55
+ with:
56
+ name: dist
57
+ path: dist/
58
+
59
+ - name: Publish to PyPI
60
+ run: uv publish
@@ -0,0 +1,5 @@
1
+ __pycache__/
2
+ .venv/
3
+ dist/
4
+ *_test.py
5
+ .pytest_cache/
@@ -0,0 +1,7 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.16.2
4
+ hooks:
5
+ - id: ruff-check
6
+ args: [--fix]
7
+ - id: ruff-format
@@ -0,0 +1 @@
1
+ 3.11
@@ -0,0 +1,213 @@
1
+ # Contributing to aiogram_tool
2
+
3
+ First off, thank you for considering contributing to **aiogram_tool**! 🎉
4
+ It's people like you that make this project a great toolkit for the [aiogram 3.x](https://github.com/aiogram/aiogram) community.
5
+
6
+ This document describes how to set up your development environment, run tests, follow the project's code style, and submit changes.
7
+
8
+ ## Table of Contents
9
+
10
+ - [Ways to Contribute](#ways-to-contribute)
11
+ - [Reporting Bugs](#reporting-bugs)
12
+ - [Suggesting Enhancements](#suggesting-enhancements)
13
+ - [Development Setup](#development-setup)
14
+ - [Project Structure](#project-structure)
15
+ - [Running Tests](#running-tests)
16
+ - [Code Style & Linting](#code-style--linting)
17
+ - [Making Changes](#making-changes)
18
+ - [Pull Request Guidelines](#pull-request-guidelines)
19
+ - [Commit Messages](#commit-messages)
20
+ - [Documentation](#documentation)
21
+ - [License](#license)
22
+
23
+ ## Ways to Contribute
24
+
25
+ You can help the project in many ways:
26
+
27
+ - 🐛 Report bugs
28
+ - 💡 Suggest new features or improvements
29
+ - 📖 Improve or translate documentation (`docs/en/`, `docs/ru/`)
30
+ - ✍️ Write or improve examples in `examples/`
31
+ - 🧪 Add tests or increase test coverage
32
+ - 🔧 Fix issues and submit pull requests
33
+
34
+ ## Reporting Bugs
35
+
36
+ Before opening a bug report, please [search existing issues](https://github.com/shayzi3/aiotool/issues) to avoid duplicates.
37
+
38
+ When creating a bug report, include:
39
+
40
+ - A clear, descriptive title
41
+ - Your Python version, aiogram version, and `aiogram_tool` version
42
+ - Steps to reproduce the problem (a minimal code example is best)
43
+ - Expected behavior vs. actual behavior
44
+ - Full traceback, if applicable
45
+
46
+ ## Suggesting Enhancements
47
+
48
+ Feature requests are welcome! Please open an issue and describe:
49
+
50
+ - The problem you're trying to solve
51
+ - Your proposed solution or API design
52
+ - Any alternatives you've considered
53
+ - Whether it fits the scope of the project (tools and utilities for aiogram 3.x)
54
+
55
+ ## Development Setup
56
+
57
+ ### Prerequisites
58
+
59
+ - **Python 3.11+**
60
+ - [**uv**](https://docs.astral.sh/uv/) — the package manager used by this project
61
+ - **Git**
62
+ - **Redis** (optional, but recommended — some tests use a Redis backend)
63
+
64
+ ### Getting Started
65
+
66
+ 1. Fork the repository and clone your fork:
67
+
68
+ ```bash
69
+ git clone https://github.com/<your-username>/aiotool.git
70
+ cd aiotool
71
+ ```
72
+
73
+ 2. Install dependencies (including dev tools):
74
+
75
+ ```bash
76
+ uv sync --all-extras --dev
77
+ ```
78
+
79
+ 3. Install the pre-commit hooks:
80
+
81
+ ```bash
82
+ uv run pre-commit install
83
+ ```
84
+
85
+ This ensures `ruff check --fix` and `ruff format` run automatically before each commit.
86
+
87
+ ## Project Structure
88
+
89
+ ```
90
+ aiogram_tool/
91
+ ├── aiogram_tool/ # Main package source code
92
+ │ ├── types.py # Shared type definitions
93
+ │ ├── storage/ # Storage backends (Memory, Redis, File)
94
+ │ └── tools/ # Tools (depend, limit, callback_data, setup)
95
+ ├── docs/ # Documentation (en/ and ru/)
96
+ ├── examples/ # Ready-to-run usage examples
97
+ ├── tests/ # Test suite (pytest)
98
+ ├── pyproject.toml # Project metadata and tool configuration
99
+ └── .pre-commit-config.yaml
100
+ ```
101
+
102
+ ## Running Tests
103
+
104
+ The test suite uses [pytest](https://docs.pytest.org/) with `pytest-asyncio` (asyncio mode is set to `auto`).
105
+
106
+ ```bash
107
+ uv run pytest
108
+ ```
109
+
110
+ Notes:
111
+
112
+ - Some tests require a **Redis** instance available at `localhost:6379`. In CI, a Redis 7 service container is started automatically. Locally, you can run one with Docker:
113
+
114
+ ```bash
115
+ docker run -d -p 6379:6379 redis:7-alpine
116
+ ```
117
+
118
+ - To run a specific test module or directory:
119
+
120
+ ```bash
121
+ uv run pytest tests/limit/
122
+ ```
123
+
124
+ When adding new features, please add corresponding tests under `tests/`, mirroring the package structure.
125
+
126
+ ## Code Style & Linting
127
+
128
+ This project uses [**ruff**](https://docs.astral.sh/ruff/) for both linting and formatting.
129
+
130
+ Configuration highlights (see `pyproject.toml`):
131
+
132
+ - Line length: **88**
133
+ - Target version: **Python 3.11**
134
+ - Quote style: **double quotes**
135
+ - Enabled rule sets: `E4`, `E7`, `E9`, `F`, `I` (isort), `B` (bugbear), `UP` (pyupgrade)
136
+
137
+ Run the linter and formatter manually:
138
+
139
+ ```bash
140
+ uv run ruff check --fix
141
+ uv run ruff format
142
+ ```
143
+
144
+ Or verify without modifying files (as CI does):
145
+
146
+ ```bash
147
+ uv run ruff check
148
+ uv run ruff format --check
149
+ ```
150
+
151
+ CI runs both a **test job** (Python 3.11 and 3.12) and a **lint job**, so please make sure both pass locally before opening a pull request.
152
+
153
+ ## Making Changes
154
+
155
+ 1. Create a new branch for your work:
156
+
157
+ ```bash
158
+ git checkout -b feature/my-feature
159
+ # or
160
+ git checkout -b fix/issue-123
161
+ ```
162
+
163
+ 2. Make your changes.
164
+ 3. Add or update tests for your changes.
165
+ 4. Update documentation (`docs/en/` and `docs/ru/`) and, if relevant, add an example in `examples/`.
166
+ 5. Run the linter, formatter, and tests:
167
+
168
+ ```bash
169
+ uv run ruff check
170
+ uv run ruff format --check
171
+ uv run pytest
172
+ ```
173
+
174
+ 6. Commit your changes (pre-commit hooks will run automatically) and push your branch.
175
+ 7. Open a pull request against the `master` branch.
176
+
177
+ ## Pull Request Guidelines
178
+
179
+ - Keep pull requests focused — one feature or fix per PR.
180
+ - Describe **what** you changed and **why**.
181
+ - Reference related issues (e.g., `Fixes #123`).
182
+ - Make sure all CI checks pass.
183
+ - New public APIs should be documented and covered by tests.
184
+ - Follow the existing code style and project structure.
185
+
186
+ ## Commit Messages
187
+
188
+ Write clear, concise commit messages. We recommend the [Conventional Commits](https://www.conventionalcommits.org/) style:
189
+
190
+ ```
191
+ feat: add token bucket rate limit option
192
+ fix: handle empty callback data in LongCallbackData
193
+ docs: update rate limiter documentation
194
+ test: add tests for Redis storage backend
195
+ refactor: simplify dependency resolution logic
196
+ ```
197
+
198
+ ## Documentation
199
+
200
+ Documentation lives in `docs/` and is available in two languages:
201
+
202
+ - `docs/en/` — English
203
+ - `docs/ru/` — Russian
204
+
205
+ If you add or change a feature, please update the documentation in **both** languages when possible. Runnable examples belong in `examples/`, organized by tool.
206
+
207
+ ## License
208
+
209
+ By contributing to `aiogram_tool`, you agree that your contributions will be licensed under the same license as the project — see [LICENSE.md](LICENSE.md).
210
+
211
+ ---
212
+
213
+ Thank you again for contributing! 💙
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Dyadchenko Vladislav Sergeevich
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,235 @@
1
+ Metadata-Version: 2.5
2
+ Name: aiogram-tool
3
+ Version: 1.2.2
4
+ Summary: Tools which doing work with aiogram simple
5
+ Project-URL: Repository, https://github.com/shayzi3/aiogram_tool
6
+ Project-URL: Contributing, https://github.com/shayzi3/aiogram_tool/blob/master/CONTRIBUTING.md
7
+ Author-email: Vlad_shayzi1 <tecnomega@mail.ru>
8
+ License-Expression: MIT
9
+ License-File: LICENSE.md
10
+ Keywords: DI,aiogram,callback,cooldown,data,delay,dependency-injection,depends,limit,long,rate,throttling
11
+ Requires-Python: >=3.11
12
+ Requires-Dist: aiogram==3.29.1
13
+ Requires-Dist: redis>=8.0.0
14
+ Description-Content-Type: text/markdown
15
+
16
+ # aiogram_tool
17
+
18
+ A collection of powerful tools and utilities for [aiogram 3.x](https://github.com/aiogram/aiogram) — dependency injection, rate limiting, and long callback data support.
19
+
20
+ ## ✨ Features
21
+
22
+ - **Dependency Injection** — inject dependencies into handlers with `Depends()`, similar to FastAPI. Supports classes, functions, scopes (`SINGLETON`, `REQUEST`, `TRANSIENT`), nested dependencies, and more.
23
+ - **Rate Limiter** — limit how often handlers can be called. Three built-in algorithms: Fixed Window, Sliding Window, and Token Bucket. Works per-user or globally.
24
+ - **Long Callback Data** — bypass Telegram's 64-byte `callback_data` limit. Pack large payloads into inline keyboard buttons transparently.
25
+ - **Pluggable Storage** — Memory, Redis, and File storage backends for persisting rate-limit and callback data state.
26
+
27
+ ## 📦 Installation
28
+
29
+ Requires **Python 3.11+** and **aiogram 3.x**.
30
+
31
+ ### pip
32
+
33
+ ```bash
34
+ pip install aiogram_tool
35
+ ```
36
+
37
+ ### Poetry
38
+
39
+ ```bash
40
+ poetry add aiogram_tool
41
+ ```
42
+
43
+ ### uv
44
+
45
+ ```bash
46
+ uv add aiogram_tool
47
+ ```
48
+
49
+ ## 🚀 Quick Start
50
+
51
+ Register tools on your dispatcher with `aiogram_tool_setup`:
52
+
53
+ ```python
54
+ from aiogram import Bot, Dispatcher
55
+ from aiogram_tool.tools.setup import aiogram_tool_setup
56
+ from aiogram_tool.tools.depend import DependTool
57
+ from aiogram_tool.tools.limit import RateLimitTool
58
+
59
+ bot = Bot("YOUR_TOKEN_HERE")
60
+ dp = Dispatcher()
61
+
62
+ aiogram_tool_setup(dp, [DependTool(), RateLimitTool()])
63
+
64
+ await dp.start_polling(bot)
65
+ ```
66
+
67
+ ## 🧰 Tools
68
+
69
+ ### Dependency Injection
70
+
71
+ Inject dependencies into handlers via default argument values — no middleware boilerplate required.
72
+
73
+ ```python
74
+ from aiogram_tool.tools.setup import aiogram_tool_setup
75
+ from aiogram_tool.tools.depend import Depends, DependTool, ScopeRegistry, Scope
76
+
77
+ scope_registry = ScopeRegistry()
78
+
79
+
80
+ class CounterService:
81
+ def __init__(self) -> None:
82
+ self.count = 0
83
+
84
+ async def __call__(self, context) -> dict:
85
+ self.count += 1
86
+ return {"current_count": self.count}
87
+
88
+
89
+ counter = CounterService()
90
+ scope_registry.register(counter, Scope.REQUEST)
91
+
92
+ # Pass the registry to the tool during setup
93
+ aiogram_tool_setup(dp, [DependTool(scope_registry=scope_registry)])
94
+
95
+
96
+ @dp.message(CommandStart())
97
+ async def start_handler(message: Message, stats: dict = Depends(counter)):
98
+ await message.answer(f"Pressed: {stats['current_count']} times")
99
+ ```
100
+
101
+ Highlights:
102
+
103
+ - Works with functions, class-functors, and `__init__` methods
104
+ - Scopes: `SINGLETON`, `REQUEST`, `TRANSIENT` (via `ScopeRegistry`)
105
+ - Nested dependencies (`subdepends`), `From` extractor, `DependFilter`, and `DependExit`
106
+
107
+ 📖 Full documentation: [EN](docs/en/depend.md) | [RU](docs/ru/depend.md)
108
+
109
+ ### Rate Limiter
110
+
111
+ Limit handler calls with three built-in algorithms:
112
+
113
+ ```python
114
+ from datetime import timedelta
115
+ from aiogram_tool.tools.limit import RateLimitTool, RateLimitFilter
116
+ from aiogram_tool.tools.limit.rate_limit import SlidingWindowRateLimit
117
+
118
+
119
+ @dp.message(
120
+ Command("ping"),
121
+ # 3 requests per 10 seconds per user
122
+ RateLimitFilter(
123
+ rate_limit=SlidingWindowRateLimit(
124
+ requests=3,
125
+ time=timedelta(seconds=10),
126
+ )
127
+ ),
128
+ )
129
+ async def ping_handler(message: Message):
130
+ await message.answer("Pong!")
131
+ ```
132
+
133
+ Available algorithms:
134
+
135
+ | Algorithm | Description |
136
+ |---|---|
137
+ | `FixedWindowRateLimit` | N requests per fixed time window |
138
+ | `SlidingWindowRateLimit` | More accurate; prevents bursts at window edges |
139
+ | `TokenBucketRateLimit` | Bucket of tokens that refills over time |
140
+
141
+ Extras:
142
+
143
+ - `all_users=True` — apply the limit globally instead of per-user
144
+ - `key="..."` — custom rate-limit key
145
+ - Custom `RateLimitAnswer` — control the response when the limit is exceeded
146
+ - Redis storage — share limits across bot restarts and multiple instances
147
+
148
+ 📖 Full documentation: [EN](docs/en/limit.md) | [RU](docs/ru/limit.md)
149
+
150
+ ### Long Callback Data
151
+
152
+ Telegram limits `callback_data` to **64 bytes**. `LongCallbackData` automatically stores oversized payloads and restores them when the callback arrives — with the same familiar aiogram API.
153
+
154
+ ```python
155
+ from aiogram import Bot, Dispatcher, F
156
+ from aiogram.filters import CommandStart
157
+ from aiogram.types import (
158
+ CallbackQuery,
159
+ InlineKeyboardButton,
160
+ InlineKeyboardMarkup,
161
+ Message,
162
+ )
163
+ from aiogram_tool.tools.callback_data import LongCallbackData
164
+
165
+ bot = Bot("YOUR_TOKEN_HERE")
166
+ dp = Dispatcher()
167
+
168
+
169
+ class MyData(LongCallbackData, prefix="mydata"):
170
+ mode: str
171
+ payload: str
172
+
173
+
174
+ @dp.message(CommandStart())
175
+ async def start_handler(message: Message):
176
+ # Short data is packed as usual; long data is stored transparently
177
+ short_cb = await MyData(mode="short", payload="Hello!").pack_long()
178
+ long_cb = await MyData(mode="long", payload="A" * 200).pack_long()
179
+
180
+ await message.answer(
181
+ "Choose an action:",
182
+ reply_markup=InlineKeyboardMarkup(
183
+ inline_keyboard=[
184
+ [InlineKeyboardButton(text="Short data", callback_data=short_cb)],
185
+ [InlineKeyboardButton(text="Long data", callback_data=long_cb)],
186
+ ]
187
+ ),
188
+ )
189
+
190
+
191
+ # Filter exactly like standard aiogram CallbackData
192
+ @dp.callback_query(MyData.filter(F.mode == "long"))
193
+ async def handler(query: CallbackQuery, callback_data: MyData):
194
+ # Original data is fully available despite the 64-byte limit
195
+ await query.answer(text=f"Received: {callback_data.payload}")
196
+ ```
197
+
198
+ By default data is kept in in-memory storage. Use Redis to persist it across restarts:
199
+
200
+ ```python
201
+ from redis.asyncio import Redis as AsyncRedis
202
+ from aiogram_tool.storage import AsyncRedisLockStorage
203
+
204
+
205
+ class PersistentData(LongCallbackData, prefix="redis"):
206
+ _storage = AsyncRedisLockStorage(redis=AsyncRedis(), expire=3600)
207
+ user_id: int
208
+ big_context: str
209
+ ```
210
+
211
+ 📖 Full documentation: [EN](docs/en/callback_data.md) | [RU](docs/ru/callback_data.md)
212
+
213
+ ## 💾 Storage Backends
214
+
215
+ | Storage | Persistence | Lock support |
216
+ |---|---|---|
217
+ | `MemoryStorage` / `MemoryLockStorage` | In-memory | ✅ |
218
+ | `AsyncRedisStorage` / `AsyncRedisLockStorage` | Redis (survives restarts) | ✅ |
219
+ | `FileStorage` / `FileLockStorage` | Local files | ✅ |
220
+
221
+ ## 📁 Examples
222
+
223
+ Ready-to-run examples are available in the [`examples/`](examples/) directory:
224
+
225
+ - [Dependency Injection](examples/depend/) — classes, scopes, overrides, sub-dependencies
226
+ - [Rate Limiting](examples/limit/) — basic usage, algorithms, advanced configuration
227
+ - [Callback Data](examples/callback_data/) — basic usage, custom answers, Redis storage
228
+
229
+ ## 🤝 Contributing
230
+
231
+ Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
232
+
233
+ ## 📄 License
234
+
235
+ This project is licensed under the terms of the [LICENSE.md](LICENSE.md).