aiogram-webhook 0.2.0__tar.gz → 1.1.0__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_webhook-0.2.0 → aiogram_webhook-1.1.0}/PKG-INFO +147 -44
- {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0}/README.md +129 -27
- {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0}/pyproject.toml +10 -59
- {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/__init__.py +2 -2
- {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/adapters/aiohttp.py +9 -2
- {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/adapters/base.py +22 -4
- {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/adapters/fastapi.py +6 -3
- aiogram_webhook-1.1.0/src/aiogram_webhook/config.py +19 -0
- {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/engines/base.py +59 -36
- aiogram_webhook-1.1.0/src/aiogram_webhook/engines/simple.py +101 -0
- aiogram_webhook-1.1.0/src/aiogram_webhook/engines/token.py +125 -0
- aiogram_webhook-1.1.0/src/aiogram_webhook/routing/__init__.py +6 -0
- {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/routing/base.py +12 -7
- aiogram_webhook-1.1.0/src/aiogram_webhook/routing/path.py +28 -0
- aiogram_webhook-1.1.0/src/aiogram_webhook/routing/query.py +18 -0
- aiogram_webhook-1.1.0/src/aiogram_webhook/routing/static.py +12 -0
- {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/security/__init__.py +2 -2
- {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/security/checks/check.py +7 -4
- aiogram_webhook-1.1.0/src/aiogram_webhook/security/checks/ip.py +88 -0
- {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/security/secret_token.py +8 -0
- {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/security/security.py +12 -5
- aiogram_webhook-0.2.0/.github/dependabot.yml +0 -11
- aiogram_webhook-0.2.0/.github/workflows/release.yml +0 -54
- aiogram_webhook-0.2.0/.github/workflows/tests.yml +0 -39
- aiogram_webhook-0.2.0/.gitignore +0 -207
- aiogram_webhook-0.2.0/CHANGELOG.md +0 -55
- aiogram_webhook-0.2.0/LICENSE +0 -21
- aiogram_webhook-0.2.0/aiogram_webhook/engines/simple.py +0 -99
- aiogram_webhook-0.2.0/aiogram_webhook/engines/token.py +0 -93
- aiogram_webhook-0.2.0/aiogram_webhook/routing/__init__.py +0 -5
- aiogram_webhook-0.2.0/aiogram_webhook/routing/path.py +0 -28
- aiogram_webhook-0.2.0/aiogram_webhook/routing/query.py +0 -35
- aiogram_webhook-0.2.0/aiogram_webhook/security/checks/ip.py +0 -67
- aiogram_webhook-0.2.0/tests/__init__.py +0 -0
- aiogram_webhook-0.2.0/tests/conftest.py +0 -40
- aiogram_webhook-0.2.0/tests/test_routing.py +0 -55
- aiogram_webhook-0.2.0/tests/test_security.py +0 -87
- {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/adapters/__init__.py +0 -0
- {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/engines/__init__.py +0 -0
- {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/security/checks/__init__.py +0 -0
|
@@ -1,35 +1,36 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: aiogram-webhook
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: A python library for integrating webhook support with multiple web frameworks in aiogram. Organizes bot operation via webhooks for both single and multi-bot setups.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Project-URL: Issues, https://github.com/m-xim/aiogram-webhook/issues
|
|
8
|
-
Project-URL: Documentation, https://github.com/m-xim/aiogram-webhook#readme
|
|
5
|
+
Keywords: aiogram,telegram,webhook,fastapi,aiohttp,multibot
|
|
6
|
+
Author: m-xim
|
|
9
7
|
Author-email: m-xim <i@m-xim.ru>
|
|
10
8
|
License: MIT
|
|
11
|
-
License-File: LICENSE
|
|
12
|
-
Keywords: aiogram,aiohttp,fastapi,multibot,telegram,webhook
|
|
13
|
-
Classifier: Operating System :: OS Independent
|
|
14
9
|
Classifier: Programming Language :: Python :: 3
|
|
15
10
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
13
|
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
15
|
Classifier: Topic :: Software Development :: Libraries
|
|
20
|
-
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
21
17
|
Requires-Dist: aiogram>=3.14.0
|
|
22
18
|
Requires-Dist: yarl>=1.17.0
|
|
19
|
+
Requires-Dist: aiohttp>=3.9.0 ; extra == 'aiohttp'
|
|
20
|
+
Requires-Dist: ruff ; extra == 'dev'
|
|
21
|
+
Requires-Dist: ty ; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest ; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest-asyncio ; extra == 'dev'
|
|
24
|
+
Requires-Dist: httpx ; extra == 'dev'
|
|
25
|
+
Requires-Dist: fastapi>=0.128.0 ; extra == 'fastapi'
|
|
26
|
+
Requires-Python: >=3.10
|
|
27
|
+
Project-URL: Homepage, https://github.com/m-xim/aiogram-webhook
|
|
28
|
+
Project-URL: Repository, https://github.com/m-xim/aiogram-webhook
|
|
29
|
+
Project-URL: Issues, https://github.com/m-xim/aiogram-webhook/issues
|
|
30
|
+
Project-URL: Documentation, https://github.com/m-xim/aiogram-webhook#readme
|
|
23
31
|
Provides-Extra: aiohttp
|
|
24
|
-
Requires-Dist: aiohttp>=3.9.0; extra == 'aiohttp'
|
|
25
32
|
Provides-Extra: dev
|
|
26
|
-
Requires-Dist: httpx; extra == 'dev'
|
|
27
|
-
Requires-Dist: pytest; extra == 'dev'
|
|
28
|
-
Requires-Dist: pytest-asyncio; extra == 'dev'
|
|
29
|
-
Requires-Dist: ruff; extra == 'dev'
|
|
30
|
-
Requires-Dist: ty; extra == 'dev'
|
|
31
33
|
Provides-Extra: fastapi
|
|
32
|
-
Requires-Dist: fastapi>=0.128.0; extra == 'fastapi'
|
|
33
34
|
Description-Content-Type: text/markdown
|
|
34
35
|
|
|
35
36
|
# aiogram-webhook
|
|
@@ -74,37 +75,42 @@ from fastapi import FastAPI
|
|
|
74
75
|
from aiogram import Bot, Dispatcher, Router
|
|
75
76
|
from aiogram.filters import CommandStart
|
|
76
77
|
from aiogram.types import Message
|
|
77
|
-
from aiogram_webhook import SimpleEngine, FastApiWebAdapter
|
|
78
|
-
from aiogram_webhook.routing import
|
|
78
|
+
from aiogram_webhook import SimpleEngine, FastApiWebAdapter, WebhookConfig
|
|
79
|
+
from aiogram_webhook.routing import StaticRouting
|
|
79
80
|
|
|
80
81
|
router = Router()
|
|
81
82
|
|
|
83
|
+
|
|
82
84
|
@router.message(CommandStart())
|
|
83
85
|
async def start(message: Message):
|
|
84
86
|
await message.answer("OK")
|
|
85
87
|
|
|
88
|
+
|
|
86
89
|
dispatcher = Dispatcher()
|
|
87
90
|
dispatcher.include_router(router)
|
|
88
91
|
bot = Bot("BOT_TOKEN")
|
|
89
92
|
|
|
90
|
-
|
|
93
|
+
|
|
94
|
+
engine = SimpleEngine(
|
|
91
95
|
dispatcher,
|
|
92
96
|
bot,
|
|
93
97
|
web_adapter=FastApiWebAdapter(),
|
|
94
|
-
routing=
|
|
98
|
+
routing=StaticRouting(url="https://example.com/webhook"),
|
|
99
|
+
webhook_config=WebhookConfig(allowed_updates=["message", "callback_query"], drop_pending_updates=True),
|
|
95
100
|
# security=Security(...)
|
|
96
101
|
)
|
|
97
102
|
|
|
103
|
+
|
|
98
104
|
@asynccontextmanager
|
|
99
105
|
async def lifespan(app: FastAPI):
|
|
100
106
|
engine.register(app)
|
|
101
|
-
await engine.set_webhook(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
)
|
|
105
|
-
await engine.on_startup()
|
|
107
|
+
await engine.set_webhook() # Uses webhook_config defaults
|
|
108
|
+
# Or override specific params:
|
|
109
|
+
# await engine.set_webhook(max_connections=100)
|
|
110
|
+
await engine.on_startup(app)
|
|
106
111
|
yield
|
|
107
|
-
await engine.on_shutdown()
|
|
112
|
+
await engine.on_shutdown(app)
|
|
113
|
+
|
|
108
114
|
|
|
109
115
|
app = FastAPI(lifespan=lifespan)
|
|
110
116
|
```
|
|
@@ -114,25 +120,33 @@ app = FastAPI(lifespan=lifespan)
|
|
|
114
120
|
from aiogram import Bot, Dispatcher, Router
|
|
115
121
|
from aiogram.filters import CommandStart
|
|
116
122
|
from aiogram.types import Message
|
|
117
|
-
from aiogram_webhook import SimpleEngine,
|
|
118
|
-
from aiogram_webhook.routing import
|
|
123
|
+
from aiogram_webhook import SimpleEngine, AiohttpWebAdapter, WebhookConfig
|
|
124
|
+
from aiogram_webhook.routing import StaticRouting
|
|
119
125
|
from aiohttp import web
|
|
120
126
|
|
|
121
127
|
router = Router()
|
|
122
128
|
|
|
129
|
+
|
|
123
130
|
@router.message(CommandStart())
|
|
124
131
|
async def start(message: Message):
|
|
125
132
|
await message.answer("OK")
|
|
126
133
|
|
|
134
|
+
|
|
135
|
+
async def on_startup(bot: Bot, webhook_engine: SimpleEngine) -> None:
|
|
136
|
+
await webhook_engine.set_webhook()
|
|
137
|
+
|
|
138
|
+
|
|
127
139
|
dispatcher = Dispatcher()
|
|
128
140
|
dispatcher.include_router(router)
|
|
141
|
+
dispatcher.startup.register(on_startup)
|
|
129
142
|
bot = Bot("BOT_TOKEN")
|
|
130
143
|
|
|
131
|
-
engine = SimpleEngine(
|
|
144
|
+
engine = SimpleEngine(
|
|
132
145
|
dispatcher,
|
|
133
146
|
bot,
|
|
134
|
-
web_adapter=
|
|
135
|
-
routing=
|
|
147
|
+
web_adapter=AiohttpWebAdapter(),
|
|
148
|
+
routing=StaticRouting(url="https://example.com/webhook"),
|
|
149
|
+
webhook_config=WebhookConfig(allowed_updates=["message", "callback_query"]),
|
|
136
150
|
# security=Security(...)
|
|
137
151
|
)
|
|
138
152
|
app = web.Application()
|
|
@@ -151,21 +165,23 @@ Used for serving a single Telegram bot. Suitable for most standard scenarios whe
|
|
|
151
165
|
|
|
152
166
|
- Connects aiogram `Dispatcher` and `Bot` to the selected web framework (FastAPI, aiohttp, etc.)
|
|
153
167
|
- Handles webhook requests for a single bot
|
|
154
|
-
- Requires explicit dispatcher, bot, web_adapter, and routing (security
|
|
168
|
+
- Requires explicit dispatcher, bot, web_adapter, and routing (security and webhook_config are optional)
|
|
155
169
|
|
|
156
170
|
**Example:**
|
|
157
171
|
```python
|
|
158
172
|
from aiogram import Bot, Dispatcher
|
|
159
|
-
from aiogram_webhook import SimpleEngine, FastApiWebAdapter
|
|
160
|
-
from aiogram_webhook.routing import
|
|
173
|
+
from aiogram_webhook import SimpleEngine, FastApiWebAdapter, WebhookConfig
|
|
174
|
+
from aiogram_webhook.routing import StaticRouting
|
|
161
175
|
|
|
162
176
|
bot = Bot("BOT_TOKEN")
|
|
163
177
|
dispatcher = Dispatcher()
|
|
178
|
+
|
|
164
179
|
engine = SimpleEngine(
|
|
165
180
|
dispatcher,
|
|
166
181
|
bot,
|
|
167
182
|
web_adapter=FastApiWebAdapter(),
|
|
168
|
-
routing=
|
|
183
|
+
routing=StaticRouting(url="https://example.com/webhook"),
|
|
184
|
+
webhook_config=WebhookConfig(allowed_updates=["message", "callback_query"], drop_pending_updates=True),
|
|
169
185
|
# security=Security(...)
|
|
170
186
|
)
|
|
171
187
|
```
|
|
@@ -176,7 +192,7 @@ Allows you to serve multiple Telegram bots in a single application. Useful if yo
|
|
|
176
192
|
|
|
177
193
|
- Allows serving multiple bots via a single endpoint
|
|
178
194
|
- Uses the bot token for request routing
|
|
179
|
-
- Requires dispatcher, web_adapter, routing, bot_settings (
|
|
195
|
+
- Requires dispatcher, web_adapter, routing, bot_settings (optional), webhook_config (optional), and security (optional)
|
|
180
196
|
|
|
181
197
|
**Example:**
|
|
182
198
|
|
|
@@ -185,11 +201,12 @@ from aiogram import Dispatcher, Router
|
|
|
185
201
|
from aiogram.client.default import DefaultBotProperties
|
|
186
202
|
from aiogram.types import Message
|
|
187
203
|
from aiogram.filters import Command, CommandObject
|
|
188
|
-
from aiogram_webhook import TokenEngine, FastApiWebAdapter
|
|
204
|
+
from aiogram_webhook import TokenEngine, FastApiWebAdapter, WebhookConfig
|
|
189
205
|
from aiogram_webhook.routing import PathRouting
|
|
190
206
|
|
|
191
207
|
router = Router()
|
|
192
208
|
|
|
209
|
+
|
|
193
210
|
@router.message(Command("addbot"))
|
|
194
211
|
async def add_bot_handler(message: Message, command: CommandObject, webhook_engine: TokenEngine):
|
|
195
212
|
token = command.args
|
|
@@ -199,14 +216,17 @@ async def add_bot_handler(message: Message, command: CommandObject, webhook_engi
|
|
|
199
216
|
new_bot = await webhook_engine.set_webhook(token)
|
|
200
217
|
await message.answer(f"Bot #{new_bot.id} started!")
|
|
201
218
|
|
|
219
|
+
|
|
202
220
|
dispatcher = Dispatcher()
|
|
203
221
|
dispatcher.include_router(router)
|
|
204
222
|
|
|
223
|
+
|
|
205
224
|
engine = TokenEngine(
|
|
206
225
|
dispatcher,
|
|
207
226
|
web_adapter=FastApiWebAdapter(),
|
|
208
|
-
routing=PathRouting(url="/webhook/{bot_token}"
|
|
227
|
+
routing=PathRouting(url="https://example.com/webhook/{bot_token}"),
|
|
209
228
|
bot_settings={"default": DefaultBotProperties(parse_mode="HTML")},
|
|
229
|
+
webhook_config=WebhookConfig(allowed_updates=["message", "callback_query"]),
|
|
210
230
|
# security=Security(...)
|
|
211
231
|
)
|
|
212
232
|
```
|
|
@@ -233,9 +253,74 @@ Adapters connect the engine to your web framework.
|
|
|
233
253
|
|
|
234
254
|
## 🛣️ Routing
|
|
235
255
|
|
|
236
|
-
-
|
|
237
|
-
|
|
238
|
-
|
|
256
|
+
aiogram-webhook provides several routing strategies to determine webhook URLs and extract bot tokens from requests:
|
|
257
|
+
|
|
258
|
+
### BaseRouting (Abstract)
|
|
259
|
+
Base class for all routing strategies. Defines the webhook URL template and provides the interface for extracting information from requests.
|
|
260
|
+
|
|
261
|
+
### StaticRouting (Single-bot)
|
|
262
|
+
Used with **SimpleEngine** for static webhook URLs without token extraction.
|
|
263
|
+
- Returns the webhook URL as-is
|
|
264
|
+
- No parameter extraction needed
|
|
265
|
+
- Example: `https://example.com/webhook`
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
from aiogram_webhook.routing import StaticRouting
|
|
269
|
+
|
|
270
|
+
routing = StaticRouting(url="https://example.com/webhook")
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### TokenRouting (Multi-bot, Abstract)
|
|
274
|
+
Base class for token-based routing strategies. Used with **TokenEngine** to serve multiple bots.
|
|
275
|
+
- Requires a URL template with a parameter placeholder (e.g. `{bot_token}`)
|
|
276
|
+
- Extracts bot token from incoming requests
|
|
277
|
+
- Automatically formats webhook URL using the bot token
|
|
278
|
+
|
|
279
|
+
### PathRouting (Multi-bot)
|
|
280
|
+
Extracts bot token from the URL path parameter.
|
|
281
|
+
- Parameter is read from the path segment
|
|
282
|
+
- Example: `https://example.com/webhook/123:ABC` → token extracted from path
|
|
283
|
+
- Default parameter name: `"bot_token"`
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
from aiogram_webhook.routing import PathRouting
|
|
287
|
+
|
|
288
|
+
# Using default parameter name "bot_token"
|
|
289
|
+
routing = PathRouting(url="https://example.com/webhook/{bot_token}")
|
|
290
|
+
|
|
291
|
+
# Or with custom parameter name
|
|
292
|
+
routing = PathRouting(url="https://example.com/webhook/{token}", param="token")
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### QueryRouting (Multi-bot)
|
|
296
|
+
Extracts bot token from URL query parameters.
|
|
297
|
+
- Parameter is read from the query string
|
|
298
|
+
- Example: `https://example.com/webhook?token=123:ABC` → token extracted from query
|
|
299
|
+
- Default parameter name: `"bot_token"`
|
|
300
|
+
|
|
301
|
+
```python
|
|
302
|
+
from aiogram_webhook.routing import QueryRouting
|
|
303
|
+
|
|
304
|
+
# Using default parameter name "bot_token"
|
|
305
|
+
routing = QueryRouting(url="https://example.com/webhook")
|
|
306
|
+
|
|
307
|
+
# Or with custom parameter name
|
|
308
|
+
routing = QueryRouting(url="https://example.com/webhook", param="token")
|
|
309
|
+
|
|
310
|
+
# Or with other parameters
|
|
311
|
+
routing = QueryRouting(url="https://example.com/webhook?other=value")
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Custom Routing
|
|
315
|
+
You can implement your own routing by inheriting from `BaseRouting` or `TokenRouting` and implementing the `webhook_point()` method (and `extract_token()` if using token-based routing).
|
|
316
|
+
|
|
317
|
+
See [routing examples](/src/aiogram_webhook/routing) for implementation details.
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## ⚙️ Webhook Configuration
|
|
322
|
+
|
|
323
|
+
`WebhookConfig` allows you to set default parameters for the Telegram [`setWebhook`](https://core.telegram.org/bots/api#setwebhook) API call. All parameters are optional and can be overridden when calling `engine.set_webhook()`.
|
|
239
324
|
|
|
240
325
|
---
|
|
241
326
|
|
|
@@ -247,8 +332,8 @@ aiogram-webhook provides a flexible and extensible security system for processin
|
|
|
247
332
|
from aiogram_webhook.security import Security, StaticSecretToken, IPCheck
|
|
248
333
|
|
|
249
334
|
security = Security(
|
|
250
|
-
IPCheck(),
|
|
251
|
-
secret_token=StaticSecretToken("YOUR_SECRET_TOKEN")
|
|
335
|
+
IPCheck(), # and other checks...
|
|
336
|
+
secret_token=StaticSecretToken("YOUR_SECRET_TOKEN"),
|
|
252
337
|
)
|
|
253
338
|
```
|
|
254
339
|
|
|
@@ -284,6 +369,24 @@ You can implement your own class based on the `SecretToken` protocol. For exampl
|
|
|
284
369
|
|
|
285
370
|
You can combine as many addresses and networks as needed. The check supports both IPv4 and IPv6.
|
|
286
371
|
|
|
372
|
+
**Features:**
|
|
373
|
+
- Automatic detection of client IP from direct connection or `X-Forwarded-For` header (for reverse proxy scenarios)
|
|
374
|
+
- Works seamlessly with load balancers and reverse proxies
|
|
375
|
+
|
|
376
|
+
**Example:**
|
|
377
|
+
```python
|
|
378
|
+
from aiogram_webhook.security import Security, IPCheck
|
|
379
|
+
|
|
380
|
+
# Use default Telegram IP networks
|
|
381
|
+
security = Security(IPCheck())
|
|
382
|
+
|
|
383
|
+
# Add custom addresses/networks
|
|
384
|
+
security = Security(IPCheck("192.168.1.0/24", "10.0.0.1"))
|
|
385
|
+
|
|
386
|
+
# Disable default Telegram networks and use only custom ones
|
|
387
|
+
security = Security(IPCheck("192.168.1.0/24", include_default=False))
|
|
388
|
+
```
|
|
389
|
+
|
|
287
390
|
### Using a custom check
|
|
288
391
|
You can create your own security check by implementing the `SecurityCheck` protocol. This allows you to define custom logic for validating incoming requests based on your specific requirements.
|
|
289
392
|
See [checks examples](/src/aiogram_webhook/security/checks) for more details.
|
|
@@ -40,37 +40,42 @@ from fastapi import FastAPI
|
|
|
40
40
|
from aiogram import Bot, Dispatcher, Router
|
|
41
41
|
from aiogram.filters import CommandStart
|
|
42
42
|
from aiogram.types import Message
|
|
43
|
-
from aiogram_webhook import SimpleEngine, FastApiWebAdapter
|
|
44
|
-
from aiogram_webhook.routing import
|
|
43
|
+
from aiogram_webhook import SimpleEngine, FastApiWebAdapter, WebhookConfig
|
|
44
|
+
from aiogram_webhook.routing import StaticRouting
|
|
45
45
|
|
|
46
46
|
router = Router()
|
|
47
47
|
|
|
48
|
+
|
|
48
49
|
@router.message(CommandStart())
|
|
49
50
|
async def start(message: Message):
|
|
50
51
|
await message.answer("OK")
|
|
51
52
|
|
|
53
|
+
|
|
52
54
|
dispatcher = Dispatcher()
|
|
53
55
|
dispatcher.include_router(router)
|
|
54
56
|
bot = Bot("BOT_TOKEN")
|
|
55
57
|
|
|
56
|
-
|
|
58
|
+
|
|
59
|
+
engine = SimpleEngine(
|
|
57
60
|
dispatcher,
|
|
58
61
|
bot,
|
|
59
62
|
web_adapter=FastApiWebAdapter(),
|
|
60
|
-
routing=
|
|
63
|
+
routing=StaticRouting(url="https://example.com/webhook"),
|
|
64
|
+
webhook_config=WebhookConfig(allowed_updates=["message", "callback_query"], drop_pending_updates=True),
|
|
61
65
|
# security=Security(...)
|
|
62
66
|
)
|
|
63
67
|
|
|
68
|
+
|
|
64
69
|
@asynccontextmanager
|
|
65
70
|
async def lifespan(app: FastAPI):
|
|
66
71
|
engine.register(app)
|
|
67
|
-
await engine.set_webhook(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
)
|
|
71
|
-
await engine.on_startup()
|
|
72
|
+
await engine.set_webhook() # Uses webhook_config defaults
|
|
73
|
+
# Or override specific params:
|
|
74
|
+
# await engine.set_webhook(max_connections=100)
|
|
75
|
+
await engine.on_startup(app)
|
|
72
76
|
yield
|
|
73
|
-
await engine.on_shutdown()
|
|
77
|
+
await engine.on_shutdown(app)
|
|
78
|
+
|
|
74
79
|
|
|
75
80
|
app = FastAPI(lifespan=lifespan)
|
|
76
81
|
```
|
|
@@ -80,25 +85,33 @@ app = FastAPI(lifespan=lifespan)
|
|
|
80
85
|
from aiogram import Bot, Dispatcher, Router
|
|
81
86
|
from aiogram.filters import CommandStart
|
|
82
87
|
from aiogram.types import Message
|
|
83
|
-
from aiogram_webhook import SimpleEngine,
|
|
84
|
-
from aiogram_webhook.routing import
|
|
88
|
+
from aiogram_webhook import SimpleEngine, AiohttpWebAdapter, WebhookConfig
|
|
89
|
+
from aiogram_webhook.routing import StaticRouting
|
|
85
90
|
from aiohttp import web
|
|
86
91
|
|
|
87
92
|
router = Router()
|
|
88
93
|
|
|
94
|
+
|
|
89
95
|
@router.message(CommandStart())
|
|
90
96
|
async def start(message: Message):
|
|
91
97
|
await message.answer("OK")
|
|
92
98
|
|
|
99
|
+
|
|
100
|
+
async def on_startup(bot: Bot, webhook_engine: SimpleEngine) -> None:
|
|
101
|
+
await webhook_engine.set_webhook()
|
|
102
|
+
|
|
103
|
+
|
|
93
104
|
dispatcher = Dispatcher()
|
|
94
105
|
dispatcher.include_router(router)
|
|
106
|
+
dispatcher.startup.register(on_startup)
|
|
95
107
|
bot = Bot("BOT_TOKEN")
|
|
96
108
|
|
|
97
|
-
engine = SimpleEngine(
|
|
109
|
+
engine = SimpleEngine(
|
|
98
110
|
dispatcher,
|
|
99
111
|
bot,
|
|
100
|
-
web_adapter=
|
|
101
|
-
routing=
|
|
112
|
+
web_adapter=AiohttpWebAdapter(),
|
|
113
|
+
routing=StaticRouting(url="https://example.com/webhook"),
|
|
114
|
+
webhook_config=WebhookConfig(allowed_updates=["message", "callback_query"]),
|
|
102
115
|
# security=Security(...)
|
|
103
116
|
)
|
|
104
117
|
app = web.Application()
|
|
@@ -117,21 +130,23 @@ Used for serving a single Telegram bot. Suitable for most standard scenarios whe
|
|
|
117
130
|
|
|
118
131
|
- Connects aiogram `Dispatcher` and `Bot` to the selected web framework (FastAPI, aiohttp, etc.)
|
|
119
132
|
- Handles webhook requests for a single bot
|
|
120
|
-
- Requires explicit dispatcher, bot, web_adapter, and routing (security
|
|
133
|
+
- Requires explicit dispatcher, bot, web_adapter, and routing (security and webhook_config are optional)
|
|
121
134
|
|
|
122
135
|
**Example:**
|
|
123
136
|
```python
|
|
124
137
|
from aiogram import Bot, Dispatcher
|
|
125
|
-
from aiogram_webhook import SimpleEngine, FastApiWebAdapter
|
|
126
|
-
from aiogram_webhook.routing import
|
|
138
|
+
from aiogram_webhook import SimpleEngine, FastApiWebAdapter, WebhookConfig
|
|
139
|
+
from aiogram_webhook.routing import StaticRouting
|
|
127
140
|
|
|
128
141
|
bot = Bot("BOT_TOKEN")
|
|
129
142
|
dispatcher = Dispatcher()
|
|
143
|
+
|
|
130
144
|
engine = SimpleEngine(
|
|
131
145
|
dispatcher,
|
|
132
146
|
bot,
|
|
133
147
|
web_adapter=FastApiWebAdapter(),
|
|
134
|
-
routing=
|
|
148
|
+
routing=StaticRouting(url="https://example.com/webhook"),
|
|
149
|
+
webhook_config=WebhookConfig(allowed_updates=["message", "callback_query"], drop_pending_updates=True),
|
|
135
150
|
# security=Security(...)
|
|
136
151
|
)
|
|
137
152
|
```
|
|
@@ -142,7 +157,7 @@ Allows you to serve multiple Telegram bots in a single application. Useful if yo
|
|
|
142
157
|
|
|
143
158
|
- Allows serving multiple bots via a single endpoint
|
|
144
159
|
- Uses the bot token for request routing
|
|
145
|
-
- Requires dispatcher, web_adapter, routing, bot_settings (
|
|
160
|
+
- Requires dispatcher, web_adapter, routing, bot_settings (optional), webhook_config (optional), and security (optional)
|
|
146
161
|
|
|
147
162
|
**Example:**
|
|
148
163
|
|
|
@@ -151,11 +166,12 @@ from aiogram import Dispatcher, Router
|
|
|
151
166
|
from aiogram.client.default import DefaultBotProperties
|
|
152
167
|
from aiogram.types import Message
|
|
153
168
|
from aiogram.filters import Command, CommandObject
|
|
154
|
-
from aiogram_webhook import TokenEngine, FastApiWebAdapter
|
|
169
|
+
from aiogram_webhook import TokenEngine, FastApiWebAdapter, WebhookConfig
|
|
155
170
|
from aiogram_webhook.routing import PathRouting
|
|
156
171
|
|
|
157
172
|
router = Router()
|
|
158
173
|
|
|
174
|
+
|
|
159
175
|
@router.message(Command("addbot"))
|
|
160
176
|
async def add_bot_handler(message: Message, command: CommandObject, webhook_engine: TokenEngine):
|
|
161
177
|
token = command.args
|
|
@@ -165,14 +181,17 @@ async def add_bot_handler(message: Message, command: CommandObject, webhook_engi
|
|
|
165
181
|
new_bot = await webhook_engine.set_webhook(token)
|
|
166
182
|
await message.answer(f"Bot #{new_bot.id} started!")
|
|
167
183
|
|
|
184
|
+
|
|
168
185
|
dispatcher = Dispatcher()
|
|
169
186
|
dispatcher.include_router(router)
|
|
170
187
|
|
|
188
|
+
|
|
171
189
|
engine = TokenEngine(
|
|
172
190
|
dispatcher,
|
|
173
191
|
web_adapter=FastApiWebAdapter(),
|
|
174
|
-
routing=PathRouting(url="/webhook/{bot_token}"
|
|
192
|
+
routing=PathRouting(url="https://example.com/webhook/{bot_token}"),
|
|
175
193
|
bot_settings={"default": DefaultBotProperties(parse_mode="HTML")},
|
|
194
|
+
webhook_config=WebhookConfig(allowed_updates=["message", "callback_query"]),
|
|
176
195
|
# security=Security(...)
|
|
177
196
|
)
|
|
178
197
|
```
|
|
@@ -199,9 +218,74 @@ Adapters connect the engine to your web framework.
|
|
|
199
218
|
|
|
200
219
|
## 🛣️ Routing
|
|
201
220
|
|
|
202
|
-
-
|
|
203
|
-
|
|
204
|
-
|
|
221
|
+
aiogram-webhook provides several routing strategies to determine webhook URLs and extract bot tokens from requests:
|
|
222
|
+
|
|
223
|
+
### BaseRouting (Abstract)
|
|
224
|
+
Base class for all routing strategies. Defines the webhook URL template and provides the interface for extracting information from requests.
|
|
225
|
+
|
|
226
|
+
### StaticRouting (Single-bot)
|
|
227
|
+
Used with **SimpleEngine** for static webhook URLs without token extraction.
|
|
228
|
+
- Returns the webhook URL as-is
|
|
229
|
+
- No parameter extraction needed
|
|
230
|
+
- Example: `https://example.com/webhook`
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
from aiogram_webhook.routing import StaticRouting
|
|
234
|
+
|
|
235
|
+
routing = StaticRouting(url="https://example.com/webhook")
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### TokenRouting (Multi-bot, Abstract)
|
|
239
|
+
Base class for token-based routing strategies. Used with **TokenEngine** to serve multiple bots.
|
|
240
|
+
- Requires a URL template with a parameter placeholder (e.g. `{bot_token}`)
|
|
241
|
+
- Extracts bot token from incoming requests
|
|
242
|
+
- Automatically formats webhook URL using the bot token
|
|
243
|
+
|
|
244
|
+
### PathRouting (Multi-bot)
|
|
245
|
+
Extracts bot token from the URL path parameter.
|
|
246
|
+
- Parameter is read from the path segment
|
|
247
|
+
- Example: `https://example.com/webhook/123:ABC` → token extracted from path
|
|
248
|
+
- Default parameter name: `"bot_token"`
|
|
249
|
+
|
|
250
|
+
```python
|
|
251
|
+
from aiogram_webhook.routing import PathRouting
|
|
252
|
+
|
|
253
|
+
# Using default parameter name "bot_token"
|
|
254
|
+
routing = PathRouting(url="https://example.com/webhook/{bot_token}")
|
|
255
|
+
|
|
256
|
+
# Or with custom parameter name
|
|
257
|
+
routing = PathRouting(url="https://example.com/webhook/{token}", param="token")
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### QueryRouting (Multi-bot)
|
|
261
|
+
Extracts bot token from URL query parameters.
|
|
262
|
+
- Parameter is read from the query string
|
|
263
|
+
- Example: `https://example.com/webhook?token=123:ABC` → token extracted from query
|
|
264
|
+
- Default parameter name: `"bot_token"`
|
|
265
|
+
|
|
266
|
+
```python
|
|
267
|
+
from aiogram_webhook.routing import QueryRouting
|
|
268
|
+
|
|
269
|
+
# Using default parameter name "bot_token"
|
|
270
|
+
routing = QueryRouting(url="https://example.com/webhook")
|
|
271
|
+
|
|
272
|
+
# Or with custom parameter name
|
|
273
|
+
routing = QueryRouting(url="https://example.com/webhook", param="token")
|
|
274
|
+
|
|
275
|
+
# Or with other parameters
|
|
276
|
+
routing = QueryRouting(url="https://example.com/webhook?other=value")
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Custom Routing
|
|
280
|
+
You can implement your own routing by inheriting from `BaseRouting` or `TokenRouting` and implementing the `webhook_point()` method (and `extract_token()` if using token-based routing).
|
|
281
|
+
|
|
282
|
+
See [routing examples](/src/aiogram_webhook/routing) for implementation details.
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## ⚙️ Webhook Configuration
|
|
287
|
+
|
|
288
|
+
`WebhookConfig` allows you to set default parameters for the Telegram [`setWebhook`](https://core.telegram.org/bots/api#setwebhook) API call. All parameters are optional and can be overridden when calling `engine.set_webhook()`.
|
|
205
289
|
|
|
206
290
|
---
|
|
207
291
|
|
|
@@ -213,8 +297,8 @@ aiogram-webhook provides a flexible and extensible security system for processin
|
|
|
213
297
|
from aiogram_webhook.security import Security, StaticSecretToken, IPCheck
|
|
214
298
|
|
|
215
299
|
security = Security(
|
|
216
|
-
IPCheck(),
|
|
217
|
-
secret_token=StaticSecretToken("YOUR_SECRET_TOKEN")
|
|
300
|
+
IPCheck(), # and other checks...
|
|
301
|
+
secret_token=StaticSecretToken("YOUR_SECRET_TOKEN"),
|
|
218
302
|
)
|
|
219
303
|
```
|
|
220
304
|
|
|
@@ -250,6 +334,24 @@ You can implement your own class based on the `SecretToken` protocol. For exampl
|
|
|
250
334
|
|
|
251
335
|
You can combine as many addresses and networks as needed. The check supports both IPv4 and IPv6.
|
|
252
336
|
|
|
337
|
+
**Features:**
|
|
338
|
+
- Automatic detection of client IP from direct connection or `X-Forwarded-For` header (for reverse proxy scenarios)
|
|
339
|
+
- Works seamlessly with load balancers and reverse proxies
|
|
340
|
+
|
|
341
|
+
**Example:**
|
|
342
|
+
```python
|
|
343
|
+
from aiogram_webhook.security import Security, IPCheck
|
|
344
|
+
|
|
345
|
+
# Use default Telegram IP networks
|
|
346
|
+
security = Security(IPCheck())
|
|
347
|
+
|
|
348
|
+
# Add custom addresses/networks
|
|
349
|
+
security = Security(IPCheck("192.168.1.0/24", "10.0.0.1"))
|
|
350
|
+
|
|
351
|
+
# Disable default Telegram networks and use only custom ones
|
|
352
|
+
security = Security(IPCheck("192.168.1.0/24", include_default=False))
|
|
353
|
+
```
|
|
354
|
+
|
|
253
355
|
### Using a custom check
|
|
254
356
|
You can create your own security check by implementing the `SecurityCheck` protocol. This allows you to define custom logic for validating incoming requests based on your specific requirements.
|
|
255
357
|
See [checks examples](/src/aiogram_webhook/security/checks) for more details.
|