feat: chat language display, disabled EntitySelect items, dev scripts
Chat language: - Added language_code field to TelegramChat model + migration - Saved from message.from.language_code on webhook/polling - Displayed as badge on bot chat cards and target receiver items - Resolved from DB in target API response (works for existing receivers) - Shown in chat picker dropdown (desc includes language) EntitySelect improvements: - Tracker-target link selector shows all targets, already-linked ones appear disabled with "Already linked" hint - Receiver chat picker shows already-added chats as disabled Dev scripts: - scripts/restart-backend.sh and restart-frontend.sh - Updated .claude/docs/dev-servers.md to reference scripts
This commit is contained in:
@@ -7,7 +7,8 @@ from ..database.models import TelegramChat
|
||||
|
||||
|
||||
async def save_chat_from_webhook(
|
||||
session: AsyncSession, bot_id: int, chat_data: dict
|
||||
session: AsyncSession, bot_id: int, chat_data: dict,
|
||||
language_code: str = "",
|
||||
) -> None:
|
||||
"""Save or update a chat entry from an incoming webhook message.
|
||||
|
||||
@@ -32,6 +33,8 @@ async def save_chat_from_webhook(
|
||||
if existing:
|
||||
existing.title = title
|
||||
existing.username = chat_data.get("username", existing.username)
|
||||
if language_code:
|
||||
existing.language_code = language_code
|
||||
session.add(existing)
|
||||
else:
|
||||
session.add(TelegramChat(
|
||||
@@ -40,4 +43,5 @@ async def save_chat_from_webhook(
|
||||
title=title,
|
||||
chat_type=chat_data.get("type", "private"),
|
||||
username=chat_data.get("username", ""),
|
||||
language_code=language_code,
|
||||
))
|
||||
|
||||
@@ -17,7 +17,7 @@ import aiohttp
|
||||
from sqlmodel import select
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
|
||||
from notify_bridge_core.notifications.telegram.media import TELEGRAM_API_BASE_URL
|
||||
from notify_bridge_core.notifications.telegram.client import TelegramClient
|
||||
|
||||
from ..database.engine import get_engine
|
||||
from ..database.models import CommandTracker, CommandTrackerListener, TelegramBot
|
||||
@@ -150,25 +150,16 @@ async def _poll_bot(bot_id: int) -> None:
|
||||
bot_obj = bot
|
||||
|
||||
offset = _last_update_id.get(bot_id, 0)
|
||||
params: dict[str, Any] = {
|
||||
"timeout": 0,
|
||||
"limit": 50,
|
||||
"allowed_updates": '["message"]',
|
||||
}
|
||||
if offset:
|
||||
params["offset"] = offset + 1
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession() as http:
|
||||
async with http.get(
|
||||
f"{TELEGRAM_API_BASE_URL}{bot_token}/getUpdates",
|
||||
params=params,
|
||||
timeout=aiohttp.ClientTimeout(total=10),
|
||||
) as resp:
|
||||
data = await resp.json()
|
||||
if not data.get("ok"):
|
||||
return
|
||||
updates = data.get("result", [])
|
||||
client = TelegramClient(http, bot_token)
|
||||
result = await client.get_updates(
|
||||
offset=offset + 1 if offset else None, limit=50,
|
||||
)
|
||||
if not result.get("success"):
|
||||
return
|
||||
updates = result.get("result", [])
|
||||
except Exception as e:
|
||||
_LOGGER.debug("Polling error for bot %d: %s", bot_id, e)
|
||||
return
|
||||
@@ -190,6 +181,8 @@ async def _poll_bot(bot_id: int) -> None:
|
||||
chat_info = message.get("chat", {})
|
||||
chat_id = str(chat_info.get("id", ""))
|
||||
text = message.get("text", "")
|
||||
from_user = message.get("from", {})
|
||||
msg_language = from_user.get("language_code", "")
|
||||
|
||||
if not chat_id:
|
||||
continue
|
||||
@@ -197,7 +190,7 @@ async def _poll_bot(bot_id: int) -> None:
|
||||
# Auto-persist chat (fresh session per save)
|
||||
try:
|
||||
async with AsyncSession(engine) as save_session:
|
||||
await save_chat_from_webhook(save_session, bot_obj.id, chat_info)
|
||||
await save_chat_from_webhook(save_session, bot_obj.id, chat_info, language_code=msg_language)
|
||||
await save_session.commit()
|
||||
except Exception:
|
||||
_LOGGER.debug("Failed to auto-save chat %s", chat_id, exc_info=True)
|
||||
@@ -205,13 +198,13 @@ async def _poll_bot(bot_id: int) -> None:
|
||||
# Dispatch commands
|
||||
if text and text.startswith("/"):
|
||||
try:
|
||||
language_code = message.get("from", {}).get("language_code", "")
|
||||
cmd_response = await handle_command(bot_obj, chat_id, text, language_code=language_code)
|
||||
message_id = message.get("message_id")
|
||||
cmd_response = await handle_command(bot_obj, chat_id, text, language_code=msg_language)
|
||||
if cmd_response is not None:
|
||||
if isinstance(cmd_response, list):
|
||||
await send_media_group(bot_token, chat_id, cmd_response)
|
||||
await send_media_group(bot_token, chat_id, cmd_response, reply_to_message_id=message_id)
|
||||
else:
|
||||
await send_reply(bot_token, chat_id, cmd_response)
|
||||
await send_reply(bot_token, chat_id, cmd_response, reply_to_message_id=message_id)
|
||||
except Exception:
|
||||
_LOGGER.error("Error handling command from bot %d", bot_id, exc_info=True)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user