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.
- aiogram_tool-1.2.2/.github/workflows/main.yml +66 -0
- aiogram_tool-1.2.2/.github/workflows/release.yml +60 -0
- aiogram_tool-1.2.2/.gitignore +5 -0
- aiogram_tool-1.2.2/.pre-commit-config.yaml +7 -0
- aiogram_tool-1.2.2/.python-version +1 -0
- aiogram_tool-1.2.2/CONTRIBUTING.md +213 -0
- aiogram_tool-1.2.2/LICENSE.md +21 -0
- aiogram_tool-1.2.2/PKG-INFO +235 -0
- aiogram_tool-1.2.2/README.md +220 -0
- aiogram_tool-1.2.2/aiogram_tool/__init__.py +0 -0
- aiogram_tool-1.2.2/aiogram_tool/storage/__init__.py +15 -0
- aiogram_tool-1.2.2/aiogram_tool/storage/base.py +20 -0
- aiogram_tool-1.2.2/aiogram_tool/storage/impl/__init__.py +0 -0
- aiogram_tool-1.2.2/aiogram_tool/storage/impl/file.py +72 -0
- aiogram_tool-1.2.2/aiogram_tool/storage/impl/memory.py +33 -0
- aiogram_tool-1.2.2/aiogram_tool/storage/impl/redis.py +39 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/__init__.py +0 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/callback_data/__init__.py +4 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/callback_data/answer.py +10 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/callback_data/filter.py +120 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/__init__.py +16 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/components/__init__.py +0 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/components/exit.py +4 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/components/filter.py +63 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/components/inner_middleware.py +54 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/components/outer_middleware.py +27 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/depend.py +20 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/storage/__init__.py +0 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/storage/memory.py +29 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/tool.py +72 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/types/__init__.py +0 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/types/enums.py +15 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/types/exceptions.py +25 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/types/schema.py +19 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/utils/__init__.py +0 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/utils/inspect.py +56 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/utils/registry_manager.py +64 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/utils/resolver.py +163 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/utils/scope_registry.py +42 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/depend/utils/stack_manager.py +35 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/limit/__init__.py +5 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/limit/answer.py +20 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/limit/filter.py +82 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/limit/rate_limit/__init__.py +9 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/limit/rate_limit/base.py +36 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/limit/rate_limit/fixed_window.py +70 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/limit/rate_limit/sliding_window.py +79 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/limit/rate_limit/token_bucket.py +102 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/limit/schema.py +24 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/limit/tool.py +21 -0
- aiogram_tool-1.2.2/aiogram_tool/tools/setup.py +25 -0
- aiogram_tool-1.2.2/aiogram_tool/types.py +1 -0
- aiogram_tool-1.2.2/docs/en/callback_data.md +217 -0
- aiogram_tool-1.2.2/docs/en/depend.md +397 -0
- aiogram_tool-1.2.2/docs/en/limit.md +371 -0
- aiogram_tool-1.2.2/docs/ru/callback_data.md +219 -0
- aiogram_tool-1.2.2/docs/ru/depend.md +397 -0
- aiogram_tool-1.2.2/docs/ru/limit.md +370 -0
- aiogram_tool-1.2.2/examples/callback_data/basic.py +68 -0
- aiogram_tool-1.2.2/examples/callback_data/custom_expired_answer.py +72 -0
- aiogram_tool-1.2.2/examples/callback_data/redis_storage.py +68 -0
- aiogram_tool-1.2.2/examples/depend/classes.py +63 -0
- aiogram_tool-1.2.2/examples/depend/filter_and_exit.py +46 -0
- aiogram_tool-1.2.2/examples/depend/override.py +41 -0
- aiogram_tool-1.2.2/examples/depend/scopes.py +62 -0
- aiogram_tool-1.2.2/examples/depend/subdepends.py +45 -0
- aiogram_tool-1.2.2/examples/limit/advanced.py +66 -0
- aiogram_tool-1.2.2/examples/limit/basic.py +37 -0
- aiogram_tool-1.2.2/examples/limit/limit_algorithms.py +67 -0
- aiogram_tool-1.2.2/pyproject.toml +57 -0
- aiogram_tool-1.2.2/pytest.ini +5 -0
- aiogram_tool-1.2.2/tests/__init__.py +0 -0
- aiogram_tool-1.2.2/tests/callback_data/__init__.py +0 -0
- aiogram_tool-1.2.2/tests/callback_data/conftest.py +20 -0
- aiogram_tool-1.2.2/tests/callback_data/test_filter.py +118 -0
- aiogram_tool-1.2.2/tests/callback_data/test_pack.py +27 -0
- aiogram_tool-1.2.2/tests/callback_data/test_unique_id.py +13 -0
- aiogram_tool-1.2.2/tests/callback_data/test_with_handler.py +86 -0
- aiogram_tool-1.2.2/tests/conftest.py +69 -0
- aiogram_tool-1.2.2/tests/depend/__init__.py +0 -0
- aiogram_tool-1.2.2/tests/depend/conftest.py +64 -0
- aiogram_tool-1.2.2/tests/depend/test_classes.py +52 -0
- aiogram_tool-1.2.2/tests/depend/test_exit.py +35 -0
- aiogram_tool-1.2.2/tests/depend/test_filter.py +56 -0
- aiogram_tool-1.2.2/tests/depend/test_from.py +39 -0
- aiogram_tool-1.2.2/tests/depend/test_generator.py +107 -0
- aiogram_tool-1.2.2/tests/depend/test_lambda.py +25 -0
- aiogram_tool-1.2.2/tests/depend/test_middleware_data.py +73 -0
- aiogram_tool-1.2.2/tests/depend/test_override.py +46 -0
- aiogram_tool-1.2.2/tests/depend/test_scopes.py +264 -0
- aiogram_tool-1.2.2/tests/depend/test_setup.py +118 -0
- aiogram_tool-1.2.2/tests/depend/test_singleton_lock.py +46 -0
- aiogram_tool-1.2.2/tests/depend/test_subdepend.py +35 -0
- aiogram_tool-1.2.2/tests/limit/__init__.py +0 -0
- aiogram_tool-1.2.2/tests/limit/conftest.py +35 -0
- aiogram_tool-1.2.2/tests/limit/test_rate_limits.py +254 -0
- aiogram_tool-1.2.2/tests/limit/test_setup.py +14 -0
- aiogram_tool-1.2.2/tests/storage/__init__.py +0 -0
- aiogram_tool-1.2.2/tests/storage/test_storages.py +33 -0
- 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 @@
|
|
|
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).
|