This commit is contained in:
2025-12-16 22:43:03 +07:00
parent 696dc714c4
commit 895e296f44
4 changed files with 66 additions and 18 deletions

View File

@@ -22,7 +22,8 @@ class TelegramNotifier:
self,
chat_id: int,
text: str,
parse_mode: str = "HTML"
parse_mode: str = "HTML",
reply_markup: dict | None = None
) -> bool:
"""Send a message to a Telegram chat."""
if not self.bot_token:
@@ -31,13 +32,17 @@ class TelegramNotifier:
try:
async with httpx.AsyncClient() as client:
payload = {
"chat_id": chat_id,
"text": text,
"parse_mode": parse_mode
}
if reply_markup:
payload["reply_markup"] = reply_markup
response = await client.post(
f"{self.api_url}/sendMessage",
json={
"chat_id": chat_id,
"text": text,
"parse_mode": parse_mode
},
json=payload,
timeout=10.0
)
if response.status_code == 200:
@@ -53,7 +58,8 @@ class TelegramNotifier:
self,
db: AsyncSession,
user_id: int,
message: str
message: str,
reply_markup: dict | None = None
) -> bool:
"""Send notification to a user by user_id."""
result = await db.execute(
@@ -61,10 +67,16 @@ class TelegramNotifier:
)
user = result.scalar_one_or_none()
if not user or not user.telegram_id:
if not user:
logger.warning(f"[Notify] User {user_id} not found")
return False
return await self.send_message(user.telegram_id, message)
if not user.telegram_id:
logger.warning(f"[Notify] User {user_id} ({user.nickname}) has no telegram_id")
return False
logger.info(f"[Notify] Sending to user {user.nickname} (telegram_id={user.telegram_id})")
return await self.send_message(user.telegram_id, message, reply_markup=reply_markup)
async def notify_marathon_participants(
self,
@@ -171,16 +183,41 @@ class TelegramNotifier:
db: AsyncSession,
user_id: int,
marathon_title: str,
challenge_title: str
challenge_title: str,
assignment_id: int
) -> bool:
"""Notify user about dispute raised on their assignment."""
message = (
f"⚠️ <b>На твоё задание подан спор</b>\n\n"
f"Марафон: {marathon_title}\n"
f"Задание: {challenge_title}\n\n"
f"Зайди на сайт, чтобы ответить на спор."
)
return await self.notify_user(db, user_id, message)
logger.info(f"[Dispute] Sending notification to user_id={user_id} for assignment_id={assignment_id}")
dispute_url = f"{settings.FRONTEND_URL}/assignments/{assignment_id}"
logger.info(f"[Dispute] URL: {dispute_url}")
# Telegram requires HTTPS for inline keyboard URLs
use_inline_button = dispute_url.startswith("https://")
if use_inline_button:
message = (
f"⚠️ <b>На твоё задание подан спор</b>\n\n"
f"Марафон: {marathon_title}\n"
f"Задание: {challenge_title}"
)
reply_markup = {
"inline_keyboard": [[
{"text": "Открыть спор", "url": dispute_url}
]]
}
else:
message = (
f"⚠️ <b>На твоё задание подан спор</b>\n\n"
f"Марафон: {marathon_title}\n"
f"Задание: {challenge_title}\n\n"
f"🔗 {dispute_url}"
)
reply_markup = None
result = await self.notify_user(db, user_id, message, reply_markup=reply_markup)
logger.info(f"[Dispute] Notification result: {result}")
return result
async def notify_dispute_resolved(
self,