树莓派1 B+运行Telethon下载脚本时遭遇RPCError 406: UPDATE_APP_TO_LOGIN错误的解决求助
树莓派1 B+运行Telethon下载脚本时遭遇RPCError 406: UPDATE_APP_TO_LOGIN错误的解决求助
问题背景
我在树莓派1 B+(Bookworm系统)上运行下面的Telethon下载脚本时遇到了RPCError 406: UPDATE_APP_TO_LOGIN错误,而相同的脚本在Oracle服务器上已经稳定运行了好几个月,Telethon也是最新版本,请问该怎么解决这个问题?
运行的脚本代码
import asyncio from telethon import TelegramClient, events from telethon.errors import SessionPasswordNeededError import logging import json import requests import os from urllib.parse import unquote from pathlib import Path logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) class TelegramDownloader: def __init__(self, api_id, api_hash, phone_number): self.api_id = api_id self.api_hash = api_hash self.phone_number = phone_number self.client = TelegramClient(f'session_{phone_number}', api_id, api_hash) self.download_queue = asyncio.Queue() self.download_path = "/media/pi/MRX/Download" self.is_downloading = False async def connect(self): await self.client.start() if not await self.client.is_user_authorized(): try: await self.client.send_code_request(self.phone_number) code = input('Enter the code: ') await self.client.sign_in(self.phone_number, code) except SessionPasswordNeededError: password = input('Two-step verification is enabled. Please enter your password: ') await self.client.sign_in(password=password) async def download_file(self, url, event): try: filename = unquote(url.split('/')[-1].split('?')[0]) filepath = os.path.join(self.download_path, filename) await event.respond(f"⬇️ Downloading: {filename}") response = requests.get(url, stream=True) total_size = int(response.headers.get('content-length', 0)) with open(filepath, 'wb') as f: for chunk in response.iter_content(chunk_size=8192): if chunk: f.write(chunk) await event.respond(f"✅ Download completed: {filename}") logger.info(f"Downloaded {filename}") except Exception as e: await event.respond(f"❌ Download failed: {filename}\nError: {str(e)}") logger.error(f"Error downloading {filename}: {str(e)}") async def process_download_queue(self): while True: url, event = await self.download_queue.get() self.is_downloading = True await self.download_file(url, event) self.is_downloading = False self.download_queue.task_done() async def monitor_channel(self, channel_id): await self.connect() # Start download queue processor asyncio.create_task(self.process_download_queue()) @self.client.on(events.NewMessage(chats=[channel_id])) async def handler(event): try: message = event.message.text if message and "example.com" in message: # Add download to queue await self.download_queue.put((message, event)) if not self.is_downloading: logger.info("Download added to queue") else: await event.respond("⏳ Download queued - will start after current download completes") except Exception as e: logger.error(f"Error processing message: {str(e)}") logger.info(f"Started monitoring channel {channel_id} for download links") await self.client.run_until_disconnected() def read_credentials(): try: with open("credentials.json", "r") as file: creds = json.load(file) return creds["api_id"], creds["api_hash"], creds["phone_number"] except FileNotFoundError: logger.error("Credentials file not found.") return None, None, None def write_credentials(api_id, api_hash, phone_number): creds = { "api_id": api_id, "api_hash": api_hash, "phone_number": phone_number } with open("credentials.json", "w") as file: json.dump(creds, file, indent=4) async def main(): api_id, api_hash, phone_number = read_credentials() if api_id is None or api_hash is None or phone_number is None: api_id = input("Enter your API ID: ") api_hash = input("Enter your API Hash: ") phone_number = input("Enter your phone number: ") write_credentials(api_id, api_hash, phone_number) downloader = TelegramDownloader(api_id, api_hash, phone_number) # Create download directory if it doesn't exist os.makedirs(downloader.download_path, exist_ok=True) # Monitor the specific group group_id = "https://t.me/+IgOxAHTrv8UzMGU9" await downloader.monitor_channel(group_id) if __name__ == "__main__": asyncio.run(main())
错误日志
pi@raspberrypi:~/telegram_forwarder $ sudo python3 linkdownloader.py 2025-02-04 23:02:03,276 - telethon.network.mtprotosender - INFO - Connecting to 149.154.167.51:443/TcpFull... 2025-02-04 23:02:08,398 - telethon.network.mtprotosender - INFO - Connection to 149.154.167.51:443/TcpFull complete! Please enter your phone (or bot token): ********** 2025-02-04 23:03:21,912 - telethon.client.users - INFO - Phone migrated to 5 2025-02-04 23:03:22,181 - telethon.client.telegrambaseclient - INFO - Reconnecting to new data center 5 2025-02-04 23:03:22,494 - telethon.network.mtprotosender - INFO - Disconnecting from 149.154.167.51:443/TcpFull... 2025-02-04 23:03:22,508 - telethon.network.mtprotosender - INFO - Disconnection from 149.154.167.51:443/TcpFull complete! 2025-02-04 23:03:22,518 - telethon.network.mtprotosender - INFO - Connecting to 91.108.56.128:443/TcpFull... 2025-02-04 23:03:26,847 - telethon.network.mtprotosender - INFO - Connection to 91.108.56.128:443/TcpFull complete! Traceback (most recent call last): File "/home/pi/telegram_forwarder/linkdownloader.py", line 125, in asyncio.run(main()) File "/usr/lib/python3.11/asyncio/runners.py", line 190, in run return runner.run(main) ^^^^^^^^^^^^^^^^ File "/usr/lib/python3.11/asyncio/runners.py", line 118, in run return self._loop.run_until_complete(task) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete return future.result() ^^^^^^^^^^^^^^^ File "/home/pi/telegram_forwarder/linkdownloader.py", line 122, in main await downloader.monitor_channel(group_id) File "/home/pi/telegram_forwarder/linkdownloader.py", line 66, in monitor_channel await self.connect() File "/home/pi/telegram_forwarder/linkdownloader.py", line 25, in connect await self.client.start() File "/usr/lib/python3/dist-packages/telethon/client/auth.py", line 190, in _start await self.send_code_request(phone, force_sms=force_sms) File "/usr/lib/python3/dist-packages/telethon/client/auth.py", line 519, in send_code_request result = await self(functions.auth.SendCodeRequest( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/telethon/client/users.py", line 30, in __call__ return await self._call(self._sender, request, ordered=ordered) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/telethon/client/users.py", line 84, in _call result = await future ^^^^^^^^^^^^ telethon.errors.rpcbaseerrors.AuthKeyError: RPCError 406: UPDATE_APP_TO_LOGIN (caused by SendCodeRequest) pi@raspberrypi:~/telegram_forwarder $
可能的解决方法
这个错误是Telegram服务器认定当前客户端版本过时,要求更新后才能登录,结合树莓派的硬件特性,试试下面几个方案:
自定义客户端标识参数
修改TelegramClient的初始化代码,添加更贴近官方APP的设备和版本信息,避免被判定为过时客户端:self.client = TelegramClient( f'session_{phone_number}', api_id, api_hash, device_model='Raspberry Pi 1 B+', system_version='Debian Bookworm', app_version='4.16.0' # 可以参考Telegram官方APP的最新版本号填写 )删除旧会话文件重新登录
树莓派上可能存在损坏或过期的会话文件,删除当前目录下的session_你的手机号.session文件,然后重新运行脚本,从头完成登录流程。更新系统和依赖库
树莓派1硬件较老,部分依赖库版本可能过低,执行以下命令更新系统和Python包:sudo apt update && sudo apt upgrade -y pip3 install --upgrade telethon requests尝试使用代理连接
如果树莓派的公网IP被Telegram服务器限制,可以尝试添加MTProxy代理(需要有可用的代理服务),修改客户端初始化代码:from telethon import connection # 替换成你的代理信息 self.client = TelegramClient( f'session_{phone_number}', api_id, api_hash, connection=connection.ConnectionTcpMTProxyRandomizedIntermediate, proxy=('你的代理地址', 代理端口, '代理密钥') )确认账号状态
先在手机端登录你的Telegram账号,检查是否有异常提示(比如账号验证、登录限制等),确保账号处于正常状态后再尝试运行脚本。
备注:内容来源于stack exchange,提问作者Savad




