Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/notify admins new users #19

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions backend/src/medsyncapp/tgbot/handlers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Import all routers and add them to routers_list."""
from .bookings import profile_router
from .new_users import new_users_router
from .start import start_router
from .test_results import test_results_router
from .web_app import web_app_router
Expand All @@ -8,6 +9,7 @@
start_router,
profile_router,
test_results_router,
new_users_router,
web_app_router,
]

Expand Down
13 changes: 13 additions & 0 deletions backend/src/medsyncapp/tgbot/handlers/new_users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from aiogram import Router, types, Bot
from aiogram.filters import JOIN_TRANSITION, ChatMemberUpdatedFilter

from medsyncapp.tgbot.config import Config
from medsyncapp.tgbot.services.broadcaster import broadcast
from medsyncapp.tgbot.services.log_new_user import track_user_join_text

new_users_router = Router()


@new_users_router.my_chat_member(ChatMemberUpdatedFilter(JOIN_TRANSITION))
async def new_user(cmu: types.ChatMemberUpdated, config: Config, bot: Bot):
await broadcast(bot, config.tg_bot.admin_ids, track_user_join_text(cmu.from_user))
7 changes: 7 additions & 0 deletions backend/src/medsyncapp/tgbot/services/log_new_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from aiogram import types


def track_user_join_text(from_user: types.User):
user_username = f"@{from_user.username}" if from_user.username else ""
user_mention = from_user.mention_html(from_user.full_name)
return f"{user_mention} {user_username} joined the bot"
87 changes: 61 additions & 26 deletions backend/src/medsyncapp/webhook/routers/booking.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import json
import logging
from contextlib import suppress

import sqlalchemy.exc
Expand All @@ -13,6 +12,8 @@
validate_telegram_data,
bot,
parse_init_data,
track_user_booked_text,
config,
)
from .diagnostics import diagnostics_router
from .doctors import doctor_router
Expand Down Expand Up @@ -44,16 +45,14 @@ async def book_slot_endpoint(
):
book_repo = repo.doctors if item_type == "doctor" else repo.diagnostics

user_info = parsed_data.get('user')
user_info = parsed_data.get("user")
if user_info:
user_id = json.loads(user_info).get('id')
user_id = json.loads(user_info).get("id")
else:
user_id = None

try:
booking_id = await book_repo.book_slot(
payload, user_id=user_id
)
booking_id = await book_repo.book_slot(payload, user_id=user_id)
except sqlalchemy.exc.IntegrityError as e:
await repo.session.rollback()
if "bookings_user_id_fkey" in str(e) and payload.get("user_id"):
Expand All @@ -63,7 +62,9 @@ async def book_slot_endpoint(
+ " "
+ payload.get("user_surname", ""),
)
booking_id = await book_repo.book_slot(payload, user_id=parsed_data.get("user_id"))
booking_id = await book_repo.book_slot(
payload, user_id=parsed_data.get("user_id")
)
else:
raise HTTPException(status_code=400, detail="Invalid payload") from e

Expand All @@ -80,22 +81,63 @@ async def book_slot(request: Request, repo: RequestsRepo = Depends(get_repo)):
parsed_data = parse_init_data(init_data)
result = await book_slot_endpoint(data, "doctor", repo, parsed_data)

await notify_booking(
init_data=init_data,
repo=repo,
result=result,
parsed_data=parsed_data,
)

return result


async def log_notify_admins(
username: str, user_id: int, first_name: str, last_name: str
):
for admin_id in config.tg_bot.admin_ids:
with suppress():
await bot.send_message(
chat_id=admin_id,
text=track_user_booked_text(
username=username,
user_id=user_id,
first_name=first_name,
last_name=last_name,
),
parse_mode="HTML",
)


async def notify_booking(
init_data: str,
repo: RequestsRepo,
result: dict,
parsed_data: dict = None,
):
if init_data:
user_info = parsed_data.get("user")
if user_info:
user_id = json.loads(user_info).get("id")
user_info = json.loads(user_info)
user_id = user_info.get("id")
username = user_info.get("username")
first_name = user_info.get("first_name")
last_name = user_info.get("last_name")
notification = await get_booking_notification_text(
repo, result["booking_id"]
)
await log_notify_admins(
username=username,
user_id=user_id,
first_name=first_name,
last_name=last_name,
)
with suppress():
notification = await get_booking_notification_text(
repo, result["booking_id"]
)
await bot.send_message(
chat_id=user_id,
text=notification,
parse_mode="HTML",
)

return result


@diagnostics_router.post("/book_slot")
async def book_slot(request: Request, repo: RequestsRepo = Depends(get_repo)):
Expand All @@ -112,18 +154,11 @@ async def book_slot(request: Request, repo: RequestsRepo = Depends(get_repo)):
result["booking_id"], diagnostic_id=data["diagnostic_id"]
)

if init_data:
user_info = parsed_data.get("user")
if user_info:
user_id = json.loads(user_info).get("id")
with suppress():
notification = await get_booking_notification_text(
repo, result["booking_id"]
)
await bot.send_message(
chat_id=user_id,
text=notification,
parse_mode="HTML",
)
await notify_booking(
init_data=init_data,
repo=repo,
result=result,
parsed_data=parsed_data,
)

return result
9 changes: 7 additions & 2 deletions backend/src/medsyncapp/webhook/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import time
from urllib.parse import unquote, parse_qsl

from aiogram import Bot
from aiogram import Bot, types

from medsyncapp.infrastructure.database.repo.requests import RequestsRepo
from medsyncapp.infrastructure.database.setup import create_session_pool, create_engine
Expand Down Expand Up @@ -54,5 +54,10 @@ def validate_telegram_data(init_data: str) -> bool:
if computed_hash != received_hash:
return False


return True


def track_user_booked_text(username: str, user_id: int, first_name: str, last_name: str):
user_username = f"@{username}" if username else ""
user_mention = f"<a href='tg://user?id={user_id}'>{first_name} {last_name}</a>"
return f"{user_mention} {user_username} booked a slot"