Skip to content
Merged
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
6 changes: 6 additions & 0 deletions astrbot/core/config/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ class ChatProviderTemplate(TypedDict):
"telegram_command_register": True,
"telegram_command_auto_refresh": True,
"telegram_command_register_interval": 300,
"telegram_polling_restart_delay": 5.0,
},
"Discord": {
"id": "discord",
Expand Down Expand Up @@ -686,6 +687,11 @@ class ChatProviderTemplate(TypedDict):
"type": "int",
"hint": "Telegram 命令自动刷新间隔,单位为秒。",
},
"telegram_polling_restart_delay": {
"description": "Telegram 轮询重启延迟",
"type": "float",
"hint": "当轮询意外结束尝试自动重启时的延迟时间,理论上越短恢复越快,但过短(<0.1s)可能导致死循环针对 API 服务器的请求阻断。单位为秒。默认为 5s。",
},
"id": {
"description": "机器人名称",
"type": "string",
Expand Down
62 changes: 59 additions & 3 deletions astrbot/core/platform/sources/telegram/tg_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from telegram import BotCommand, Update
from telegram.constants import ChatType
from telegram.error import InvalidToken, Unauthorized
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Replace removed Telegram exception class

telegram.error.Unauthorized was removed in python-telegram-bot 20+ (renamed to Forbidden), but this commit adds from telegram.error import InvalidToken, Unauthorized. With this repo’s declared dependency python-telegram-bot>=22.6 (pyproject.toml), importing tg_adapter.py will raise ImportError, so the Telegram platform adapter cannot load at all. Use Forbidden (and update the corresponding except tuple) to keep startup compatible with supported versions.

Useful? React with 👍 / 👎.

from telegram.ext import ApplicationBuilder, ContextTypes, ExtBot, filters
from telegram.ext import MessageHandler as TelegramMessageHandler

Expand Down Expand Up @@ -93,6 +94,26 @@ def __init__(
logger.debug(f"Telegram base url: {self.client.base_url}")

self.scheduler = AsyncIOScheduler()
self._terminating = False
raw_delay = self.config.get("telegram_polling_restart_delay", 5.0)
try:
delay = float(raw_delay)
except (TypeError, ValueError):
logger.warning(
"Invalid 'telegram_polling_restart_delay' value %r in config, "
"falling back to default 5.0s",
raw_delay,
)
delay = 5.0

if delay < 0.1:
logger.warning(
"Configured 'telegram_polling_restart_delay' (%s) is too small; "
"enforcing minimum of 0.1s to avoid tight restart loops",
delay,
)
delay = 0.1
self._polling_restart_delay = delay

# Media group handling
# Cache structure: {media_group_id: {"created_at": datetime, "items": [(update, context), ...]}}
Expand Down Expand Up @@ -145,9 +166,43 @@ async def run(self) -> None:
logger.error("Telegram Updater is not initialized. Cannot start polling.")
return

queue = self.application.updater.start_polling()
logger.info("Telegram Platform Adapter is running.")
await queue
while not self._terminating:
try:
logger.info("Starting Telegram polling...")
await self.application.updater.start_polling(
error_callback=self._on_polling_error
)
logger.info("Telegram Platform Adapter is running.")
while self.application.updater.running and not self._terminating: # noqa: ASYNC110
await asyncio.sleep(1)

if not self._terminating:
logger.warning(
"Telegram polling loop exited unexpectedly, "
f"retrying in {self._polling_restart_delay}s."
)
except asyncio.CancelledError:
raise
except (Unauthorized, InvalidToken) as e:
logger.error(
f"Telegram token is invalid or unauthorized: {e}. Polling stopped."
)
break
except Exception as e:
logger.exception(
"Telegram polling crashed with exception: "
f"{type(e).__name__}: {e!s}. "
f"Retrying in {self._polling_restart_delay}s.",
)
Comment thread
SXP-Simon marked this conversation as resolved.

if not self._terminating:
await asyncio.sleep(self._polling_restart_delay)

def _on_polling_error(self, error: Exception) -> None:
logger.error(
f"Telegram polling request failed: {type(error).__name__}: {error!s}",
exc_info=error,
)

async def register_commands(self) -> None:
"""收集所有注册的指令并注册到 Telegram"""
Expand Down Expand Up @@ -567,6 +622,7 @@ def get_client(self) -> ExtBot:

async def terminate(self) -> None:
try:
self._terminating = True
if self.scheduler.running:
self.scheduler.shutdown()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,10 @@
"description": "Telegram Command Auto Refresh Interval",
"hint": "Telegram command auto-refresh interval in seconds."
},
"telegram_polling_restart_delay": {
"description": "Telegram Polling Restart Delay",
"hint": "Waiting time in seconds when the polling loop needs to restart after unexpected exits. Defaults to 5s."
},
"telegram_token": {
"description": "Bot Token",
"hint": "If you are in mainland China, set a proxy or change api_base in Other Settings."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,10 @@
"description": "Telegram 命令自动刷新间隔",
"hint": "Telegram 命令自动刷新间隔,单位为秒。"
},
"telegram_polling_restart_delay": {
"description": "Telegram 轮询重启延迟",
"hint": "当轮询意外结束尝试自动重启时的延迟时间,单位为秒。默认为 5s。"
},
"telegram_token": {
"description": "Bot Token",
"hint": "如果你的网络环境为中国大陆,请在 `其他配置` 处设置代理或更改 api_base。"
Expand Down
Loading