-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun_web_app.py
More file actions
185 lines (156 loc) · 5.52 KB
/
run_web_app.py
File metadata and controls
185 lines (156 loc) · 5.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
import asyncio
from aiohttp import web
from aiogram import Bot, Dispatcher
from aiogram.types import Update
from src.confredis import rediska
from src.app.customer import customer_r, customer_fallback
from src.app.courier import courier_r, courier_fallback, payment_r
from src.app.admin import admin_r, admin_fallback
from src.app.partner import partner_r, partner_fallback
from src.tasks.worker import main_worker
from src.middlewares import (
CustomerOuterMiddleware,
CourierOuterMiddleware,
AdminOuterMiddleware,
AgentOuterMiddleware,
)
from src.config import (
customer_bot,
courier_bot,
admin_bot,
partner_bot,
customer_dp,
courier_dp,
admin_dp,
partner_dp,
log,
customer_bot_secret,
courier_bot_secret,
admin_bot_secret,
partner_bot_secret,
)
app = web.Application()
def setup_dispatchers():
"""Инициализация диспетчеров (синхронная часть)"""
# Customer
customer_dp["bot"] = customer_bot
customer_dp["redis"] = rediska
customer_dp.message.middleware(CustomerOuterMiddleware(rediska))
customer_dp.callback_query.middleware(CustomerOuterMiddleware(rediska))
customer_dp.include_routers(customer_r, customer_fallback)
# Courier
courier_dp["bot"] = courier_bot
courier_dp["redis"] = rediska
courier_dp.message.middleware(CourierOuterMiddleware(rediska))
courier_dp.callback_query.middleware(CourierOuterMiddleware(rediska))
courier_dp.include_routers(courier_r, payment_r, courier_fallback)
# Admin
admin_dp["bot"] = admin_bot
admin_dp["redis"] = rediska
admin_dp.message.middleware(AdminOuterMiddleware(rediska))
admin_dp.callback_query.middleware(AdminOuterMiddleware(rediska))
admin_dp.include_routers(admin_r, admin_fallback)
# Partner
partner_dp["bot"] = partner_bot
partner_dp["redis"] = rediska
partner_dp.message.middleware(AgentOuterMiddleware(rediska))
partner_dp.callback_query.middleware(AgentOuterMiddleware(rediska))
partner_dp.include_routers(partner_r, partner_fallback)
async def handle_webhook(request: web.Request):
bot_name = request.path.strip("/")
try:
update = Update.model_validate(await request.json())
log.debug(f"Update for {bot_name}: {update}")
if bot_name == "customer":
await customer_dp.feed_update(
customer_bot,
update,
)
elif bot_name == "courier":
await courier_dp.feed_update(
courier_bot,
update,
)
elif bot_name == "admin":
await admin_dp.feed_update(
admin_bot,
update,
)
elif bot_name == "partner":
await partner_dp.feed_update(
partner_bot,
update,
)
else:
return web.Response(status=404)
return web.Response(status=200)
except Exception as e:
log.error(f"Error handling update: {e}")
return web.Response(status=500)
import os
async def set_webhooks():
"""
Установка вебхуков для всех ботов.
Можно отключить через переменную окружения: DISABLE_WEBHOOKS=true
"""
if os.getenv("DISABLE_WEBHOOKS", "").lower() == "true":
log.warning("Webhook setup is disabled via DISABLE_WEBHOOKS env variable")
return
webhooks = [
(customer_bot, "customer", customer_bot_secret),
(courier_bot, "courier", courier_bot_secret),
(admin_bot, "admin", admin_bot_secret),
(partner_bot, "partner", partner_bot_secret),
]
for bot, name, secret in webhooks:
url = f"https://{name}.raketago.ru/{name}"
try:
await bot.set_webhook(
url,
secret_token=secret,
drop_pending_updates=True,
)
log.info(f"✅ Webhook установлен для бота {name} -> {url}")
except Exception as e:
log.error(f"❌ Не удалось установить webhook для бота {name}: {e}")
async def start_server():
"""Запуск веб-сервера"""
app.router.add_post("/customer", handle_webhook)
app.router.add_post("/courier", handle_webhook)
app.router.add_post("/admin", handle_webhook)
app.router.add_post("/partner", handle_webhook)
runner = web.AppRunner(app)
await runner.setup()
site = web.TCPSite(runner, "0.0.0.0", 80)
await site.start()
log.info("Server started at http://0.0.0.0:80")
return runner
async def main():
# Инициализация
setup_dispatchers() # Синхронная настройка диспетчеров
await set_webhooks()
# Запуск сервера
runner = await start_server()
# Запуск воркера в фоне
worker_task = asyncio.create_task(main_worker())
try:
# Основной цикл
while True:
await asyncio.sleep(3600)
except (KeyboardInterrupt, SystemExit):
log.info("Shutting down...")
finally:
# Корректное завершение
worker_task.cancel()
try:
await worker_task
except asyncio.CancelledError:
pass
await runner.cleanup()
await rediska.redis.aclose()
log.info("All resources released")
if __name__ == "__main__":
try:
asyncio.run(main())
except Exception as e:
log.critical(f"Fatal error: {e}")