feat: added logs & refactored webhooks

This commit is contained in:
Forden 2020-08-05 16:03:13 +03:00
parent e57c92bd4a
commit ea907d0bf2
7 changed files with 122 additions and 25 deletions

60
bot.py
View File

@ -1,42 +1,52 @@
from aiogram import Bot, Dispatcher, types
from typing import List
from aiogram import Bot, Dispatcher
from aiogram.contrib.fsm_storage.redis import RedisStorage2
from aiogram.types import ParseMode
from aiohttp import web
from loguru import logger
import filters
import handlers
import middlewares
from data import config
bot = Bot(token=config.BOT_TOKEN, parse_mode=types.ParseMode.HTML)
storage = RedisStorage2(**config.aiogram_redis)
dp = Dispatcher(bot, storage=storage)
# noinspection PyUnusedLocal
async def on_startup(web_app: web.Application):
filters.setup(dp)
async def on_startup(app: web.Application):
import middlewares, filters
import handlers
middlewares.setup(dp)
filters.setup(dp)
handlers.errors.setup(dp)
handlers.user.setup(dp)
await dp.bot.delete_webhook()
logger.info('Configure Webhook URL to: {url}', url=config.WEBHOOK_URL)
await dp.bot.set_webhook(config.WEBHOOK_URL)
async def execute(req: web.Request) -> web.Response:
upds = [types.Update(**(await req.json()))]
Bot.set_current(dp.bot)
Dispatcher.set_current(dp)
try:
await dp.process_updates(upds)
except Exception as e:
logger.error(e)
finally:
return web.Response()
async def on_shutdown(app: web.Application):
app_bot: Bot = app['bot']
await app_bot.close()
async def init() -> web.Application:
from utils.misc import logging
import web_handlers
logging.setup()
app = web.Application()
subapps: List[str, web.Application] = [
('/health/', web_handlers.health_app),
('/tg/webhooks', web_handlers.tg_updates_app),
]
for prefix, subapp in subapps:
subapp['bot'] = bot
subapp['dp'] = dp
app.add_subapp(prefix, subapp)
app.on_startup.append(on_startup)
app.on_shutdown.append(on_shutdown)
return app
if __name__ == '__main__':
app = web.Application()
app.on_startup.append(on_startup)
app.add_routes([web.post(config.WEBHOOK_PATH, execute)])
web.run_app(app, port=5151, host='localhost')
bot = Bot(config.BOT_TOKEN, parse_mode=ParseMode.HTML, validate_token=True)
storage = RedisStorage2(**config.aiogram_redis)
dp = Dispatcher(bot, storage=storage)
web.run_app(init())

View File

@ -1,8 +1,12 @@
from pathlib import Path
BOT_TOKEN = ''
BASE_URL = 'https://example.com' # Webhook domain
WEBHOOK_PATH = f'/webhook/bot/{BOT_TOKEN}'
WEBHOOK_URL = f'{BASE_URL}{WEBHOOK_PATH}'
LOGS_BASE_PATH = str(Path(__file__).parent.parent / 'logs')
admins = []
ip = {

View File

@ -3,3 +3,4 @@ aiogram==2.9.2
aiohttp==3.6.2
aioredis==1.3.1
loguru==0.5.1
aiohttp_healthcheck==1.3.1

30
utils/misc/logging.py Normal file
View File

@ -0,0 +1,30 @@
import logging
import sys
from loguru import logger
from data import config
class InterceptHandler(logging.Handler):
LEVELS_MAP = {
logging.CRITICAL: "CRITICAL",
logging.ERROR: "ERROR",
logging.WARNING: "WARNING",
logging.INFO: "INFO",
logging.DEBUG: "DEBUG",
}
def _get_level(self, record):
return self.LEVELS_MAP.get(record.levelno, record.levelno)
def emit(self, record):
logger_opt = logger.opt(depth=6, exception=record.exc_info)
logger_opt.log(self._get_level(record), record.getMessage())
# noinspection PyArgumentList
def setup():
logger.add(sys.stderr, format="{time} {level} {message}", filter="my_module", level="INFO")
logger.add(config.LOGS_BASE_PATH + "/file_{time}.log")
logging.basicConfig(handlers=[InterceptHandler()], level=logging.INFO)

2
web_handlers/__init__.py Normal file
View File

@ -0,0 +1,2 @@
from .health import health_app
from .tg_updates import tg_updates_app

29
web_handlers/health.py Normal file
View File

@ -0,0 +1,29 @@
from typing import Tuple
from aiogram import Bot
from aiohttp import web
from aiohttp_healthcheck import HealthCheck
from loguru import logger
async def health_check() -> Tuple[bool, str]:
return True, 'Server alive'
async def check_webhook() -> Tuple[bool, str]:
from data import config
bot: Bot = health_app['bot']
webhook = await bot.get_webhook_info()
if webhook.url and webhook.url == config.WEBHOOK_URL:
return True, f'Webhook configured. Pending updates count {webhook.pending_update_count}'
else:
logger.error('Configured wrong webhook URL {webhook}', webhook=webhook.url)
return False, 'Configured invalid webhook URL'
health_app = web.Application()
health = HealthCheck()
health.add_check(health_check)
health.add_check(check_webhook)
health_app.add_routes([web.get('/check', health)])

View File

@ -0,0 +1,21 @@
from aiogram import Bot, Dispatcher, types
from aiohttp import web
from loguru import logger
tg_updates_app = web.Application()
async def execute(req: web.Request) -> web.Response:
upds = [types.Update(**(await req.json()))]
Bot.set_current(req.app['bot'])
Dispatcher.set_current(req.app['dp'])
try:
await req.app['dp'].process_updates(upds)
except Exception as e:
logger.error(e)
finally:
return web.Response()
tg_updates_app.add_routes([web.post('/{token}', execute)])