Skip to content

Commit

Permalink
Add sync request via pybotx
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivan Kudinov committed Jun 18, 2024
1 parent ccee9ea commit f2184e2
Show file tree
Hide file tree
Showing 8 changed files with 229 additions and 267 deletions.
67 changes: 19 additions & 48 deletions backend/app/api/endpoints/botx.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,74 +8,45 @@
Bot,
BotXMethodCallbackNotFoundError,
UnknownBotAccountError,
UnsupportedBotAPIVersionError,
UnverifiedRequestError,
build_bot_disabled_response,
build_command_accepted_response,
build_unverified_request_response,
)
from pybotx.constants import BOT_API_VERSION

from app.api.dependencies.bot import bot_dependency
from app.api.exceptions.botx import handle_exceptions
from app.logger import logger
from app.settings import settings


router = APIRouter()


@router.post("/command")
@handle_exceptions
async def command_handler(request: Request, bot: Bot = bot_dependency) -> JSONResponse:
"""Receive commands from users. Max timeout - 5 seconds."""
try: # noqa: WPS225
bot.async_execute_raw_bot_command(
await request.json(),
request_headers=request.headers,
)
except ValueError:
error_label = "Bot command validation error"

if settings.DEBUG:
logger.exception(error_label)
else:
logger.warning(error_label)

return JSONResponse(
build_bot_disabled_response(error_label),
status_code=HTTPStatus.SERVICE_UNAVAILABLE,
)
except UnknownBotAccountError as exc:
error_label = f"No credentials for bot {exc.bot_id}"
logger.warning(error_label)

return JSONResponse(
build_bot_disabled_response(error_label),
status_code=HTTPStatus.SERVICE_UNAVAILABLE,
)
except UnsupportedBotAPIVersionError as exc:
error_label = (
f"Unsupported Bot API version: `{exc.version}`. "
f"Set protocol version to `{BOT_API_VERSION}` in Admin panel."
)
logger.warning(error_label)

return JSONResponse(
build_bot_disabled_response(error_label),
status_code=HTTPStatus.SERVICE_UNAVAILABLE,
)
except UnverifiedRequestError as exc:
logger.warning(f"UnverifiedRequestError: {exc.args[0]}")
return JSONResponse(
content=build_unverified_request_response(
status_message=exc.args[0],
),
status_code=HTTPStatus.UNAUTHORIZED,
)

bot.async_execute_raw_bot_command(
await request.json(),
request_headers=request.headers,
)
return JSONResponse(
build_command_accepted_response(), status_code=HTTPStatus.ACCEPTED
)


@router.post("/smartapps/request")
@handle_exceptions
async def sync_smartapp_event_handler(
request: Request, bot: Bot = bot_dependency
) -> JSONResponse:
response = await bot.sync_execute_raw_smartapp_event(
await request.json(),
request_headers=request.headers,
)
return JSONResponse(response.jsonable_dict(), status_code=HTTPStatus.OK)


@router.get("/status")
async def status_handler(request: Request, bot: Bot = bot_dependency) -> JSONResponse:
"""Show bot status and commands list."""
Expand Down
Empty file.
66 changes: 66 additions & 0 deletions backend/app/api/exceptions/botx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""Handlers for BotX request exceptions."""

from functools import wraps
from http import HTTPStatus
from typing import Any, Callable

from fastapi.responses import JSONResponse
from pybotx import (
UnknownBotAccountError,
UnsupportedBotAPIVersionError,
UnverifiedRequestError,
build_bot_disabled_response,
build_unverified_request_response,
)
from pybotx.constants import BOT_API_VERSION

from app.logger import logger
from app.settings import settings


def handle_exceptions(func: Callable) -> Callable: # noqa: WPS212
@wraps(func)
async def wrapper(*args: Any, **kwargs: Any) -> JSONResponse:
try: # noqa: WPS225
return await func(*args, **kwargs)
except ValueError:
error_label = "Bot command validation error"

if settings.DEBUG:
logger.exception(error_label)
else:
logger.warning(error_label)

return JSONResponse(
build_bot_disabled_response(error_label),
status_code=HTTPStatus.SERVICE_UNAVAILABLE,
)
except UnknownBotAccountError as exc:
error_label = f"No credentials for bot {exc.bot_id}"
logger.warning(error_label)

return JSONResponse(
build_bot_disabled_response(error_label),
status_code=HTTPStatus.SERVICE_UNAVAILABLE,
)
except UnsupportedBotAPIVersionError as exc:
error_label = (
f"Unsupported Bot API version: `{exc.version}`. "
f"Set protocol version to `{BOT_API_VERSION}` in Admin panel."
)
logger.warning(error_label)

return JSONResponse(
build_bot_disabled_response(error_label),
status_code=HTTPStatus.SERVICE_UNAVAILABLE,
)
except UnverifiedRequestError as exc:
logger.warning(f"UnverifiedRequestError: {exc.args[0]}")
return JSONResponse(
content=build_unverified_request_response(
status_message=exc.args[0],
),
status_code=HTTPStatus.UNAUTHORIZED,
)

return wrapper
9 changes: 9 additions & 0 deletions backend/app/bot/commands/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
IncomingMessage,
SmartAppEvent,
StatusRecipient,
SyncSmartAppEventResponsePayload,
)

from app.bot.smartapp import smartapp
from app.resources import strings

collector = HandlerCollector()
Expand Down Expand Up @@ -49,6 +51,13 @@ async def help_handler(message: IncomingMessage, bot: Bot) -> None:
await bot.answer_message(answer_body)


@collector.sync_smartapp_event
async def handle_sync_smartapp_event(
event: SmartAppEvent, bot: Bot
) -> SyncSmartAppEventResponsePayload:
return await smartapp.handle_sync_smartapp_event(event, bot)


@collector.command("/_debug:git-commit-sha", visible=False)
async def git_commit_sha(message: IncomingMessage, bot: Bot) -> None:
"""Show git commit SHA."""
Expand Down
Loading

0 comments on commit f2184e2

Please sign in to comment.