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.
Files changed (40) hide show
  1. {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0}/PKG-INFO +147 -44
  2. {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0}/README.md +129 -27
  3. {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0}/pyproject.toml +10 -59
  4. {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/__init__.py +2 -2
  5. {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/adapters/aiohttp.py +9 -2
  6. {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/adapters/base.py +22 -4
  7. {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/adapters/fastapi.py +6 -3
  8. aiogram_webhook-1.1.0/src/aiogram_webhook/config.py +19 -0
  9. {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/engines/base.py +59 -36
  10. aiogram_webhook-1.1.0/src/aiogram_webhook/engines/simple.py +101 -0
  11. aiogram_webhook-1.1.0/src/aiogram_webhook/engines/token.py +125 -0
  12. aiogram_webhook-1.1.0/src/aiogram_webhook/routing/__init__.py +6 -0
  13. {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/routing/base.py +12 -7
  14. aiogram_webhook-1.1.0/src/aiogram_webhook/routing/path.py +28 -0
  15. aiogram_webhook-1.1.0/src/aiogram_webhook/routing/query.py +18 -0
  16. aiogram_webhook-1.1.0/src/aiogram_webhook/routing/static.py +12 -0
  17. {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/security/__init__.py +2 -2
  18. {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/security/checks/check.py +7 -4
  19. aiogram_webhook-1.1.0/src/aiogram_webhook/security/checks/ip.py +88 -0
  20. {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/security/secret_token.py +8 -0
  21. {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/security/security.py +12 -5
  22. aiogram_webhook-0.2.0/.github/dependabot.yml +0 -11
  23. aiogram_webhook-0.2.0/.github/workflows/release.yml +0 -54
  24. aiogram_webhook-0.2.0/.github/workflows/tests.yml +0 -39
  25. aiogram_webhook-0.2.0/.gitignore +0 -207
  26. aiogram_webhook-0.2.0/CHANGELOG.md +0 -55
  27. aiogram_webhook-0.2.0/LICENSE +0 -21
  28. aiogram_webhook-0.2.0/aiogram_webhook/engines/simple.py +0 -99
  29. aiogram_webhook-0.2.0/aiogram_webhook/engines/token.py +0 -93
  30. aiogram_webhook-0.2.0/aiogram_webhook/routing/__init__.py +0 -5
  31. aiogram_webhook-0.2.0/aiogram_webhook/routing/path.py +0 -28
  32. aiogram_webhook-0.2.0/aiogram_webhook/routing/query.py +0 -35
  33. aiogram_webhook-0.2.0/aiogram_webhook/security/checks/ip.py +0 -67
  34. aiogram_webhook-0.2.0/tests/__init__.py +0 -0
  35. aiogram_webhook-0.2.0/tests/conftest.py +0 -40
  36. aiogram_webhook-0.2.0/tests/test_routing.py +0 -55
  37. aiogram_webhook-0.2.0/tests/test_security.py +0 -87
  38. {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/adapters/__init__.py +0 -0
  39. {aiogram_webhook-0.2.0 → aiogram_webhook-1.1.0/src}/aiogram_webhook/engines/__init__.py +0 -0
  40. {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.4
1
+ Metadata-Version: 2.3
2
2
  Name: aiogram-webhook
3
- Version: 0.2.0
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
- Project-URL: Homepage, https://github.com/m-xim/aiogram-webhook
6
- Project-URL: Repository, https://github.com/m-xim/aiogram-webhook
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
- Requires-Python: >=3.10
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 PathRouting
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
- engine = SimpleEngine( # or other engine
93
+
94
+ engine = SimpleEngine(
91
95
  dispatcher,
92
96
  bot,
93
97
  web_adapter=FastApiWebAdapter(),
94
- routing=PathRouting(url="/webhook"),
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
- drop_pending_updates=True,
103
- allowed_updates=("message", "callback_query"),
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, FastApiWebAdapter
118
- from aiogram_webhook.routing import PathRouting
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( # or other engine
144
+ engine = SimpleEngine(
132
145
  dispatcher,
133
146
  bot,
134
- web_adapter=FastApiWebAdapter(),
135
- routing=PathRouting(url="/webhook"),
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 is optional)
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 PathRouting
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=PathRouting(url="/webhook"),
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 (a dict with bot settings), security (optional)
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}", param="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
- - **PathRouting** static path or path with parameter (e.g. `/webhook/{bot_token}`)
237
- - **QueryRouting** — via query parameters (e.g. `/webhook?bot_token={bot_token}`)
238
- - **CustomRouting** — implement your own routing logic (see [routing examples](/src/aiogram_webhook/routing))
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(), # and other checks...
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 PathRouting
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
- engine = SimpleEngine( # or other engine
58
+
59
+ engine = SimpleEngine(
57
60
  dispatcher,
58
61
  bot,
59
62
  web_adapter=FastApiWebAdapter(),
60
- routing=PathRouting(url="/webhook"),
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
- drop_pending_updates=True,
69
- allowed_updates=("message", "callback_query"),
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, FastApiWebAdapter
84
- from aiogram_webhook.routing import PathRouting
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( # or other engine
109
+ engine = SimpleEngine(
98
110
  dispatcher,
99
111
  bot,
100
- web_adapter=FastApiWebAdapter(),
101
- routing=PathRouting(url="/webhook"),
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 is optional)
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 PathRouting
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=PathRouting(url="/webhook"),
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 (a dict with bot settings), security (optional)
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}", param="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
- - **PathRouting** static path or path with parameter (e.g. `/webhook/{bot_token}`)
203
- - **QueryRouting** — via query parameters (e.g. `/webhook?bot_token={bot_token}`)
204
- - **CustomRouting** — implement your own routing logic (see [routing examples](/src/aiogram_webhook/routing))
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(), # and other checks...
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.