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.contrib.fsm_storage.redis import RedisStorage2
from aiogram.types import ParseMode
from aiohttp import web from aiohttp import web
from loguru import logger from loguru import logger
import filters
import handlers
import middlewares
from data import config 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 # noinspection PyUnusedLocal
async def on_startup(web_app: web.Application): async def on_startup(app: web.Application):
filters.setup(dp) import middlewares, filters
import handlers
middlewares.setup(dp) middlewares.setup(dp)
filters.setup(dp)
handlers.errors.setup(dp) handlers.errors.setup(dp)
handlers.user.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) await dp.bot.set_webhook(config.WEBHOOK_URL)
async def execute(req: web.Request) -> web.Response: async def on_shutdown(app: web.Application):
upds = [types.Update(**(await req.json()))] app_bot: Bot = app['bot']
Bot.set_current(dp.bot) await app_bot.close()
Dispatcher.set_current(dp)
try:
await dp.process_updates(upds) async def init() -> web.Application:
except Exception as e: from utils.misc import logging
logger.error(e) import web_handlers
finally: logging.setup()
return web.Response() 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__': if __name__ == '__main__':
app = web.Application() bot = Bot(config.BOT_TOKEN, parse_mode=ParseMode.HTML, validate_token=True)
app.on_startup.append(on_startup) storage = RedisStorage2(**config.aiogram_redis)
app.add_routes([web.post(config.WEBHOOK_PATH, execute)]) dp = Dispatcher(bot, storage=storage)
web.run_app(app, port=5151, host='localhost')
web.run_app(init())

View File

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

View File

@ -3,3 +3,4 @@ aiogram==2.9.2
aiohttp==3.6.2 aiohttp==3.6.2
aioredis==1.3.1 aioredis==1.3.1
loguru==0.5.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)])