Files
tg_code/text/text1.py
Administrator 37e9d4038c gfregfregfr
2025-11-12 12:50:39 +08:00

313 lines
12 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
优化后的 Telegram 客户端代码
"""
import asyncio
from urllib.parse import unquote
from typing import Optional, Dict, Any
from loguru import logger
from telethon import TelegramClient, functions, events, client
from telethon.errors import (
NewSaltInvalidError,
NewSettingsInvalidError,
PasswordHashInvalidError,
FloodWaitError,
SessionPasswordNeededError
)
from telethon.tl import types
from telethon.tl.functions.account import GetAuthorizationsRequest, ResetAuthorizationRequest
from telethon.tl.functions.channels import JoinChannelRequest
from telethon.tl.functions.messages import RequestAppWebViewRequest, StartBotRequest
from telethon.tl.types import InputBotAppShortName
from models.tg_phone_devices import TgPhoneDevices
class OptimizedTelegramClient:
"""优化的 Telegram 客户端类"""
def __init__(self, server):
self.server = server
self.client = None
self.verification_answers = {
"年龄": "25",
"职业": "程序员",
"目的": "学习交流",
"来自": "中国",
"兴趣": "编程、阅读",
"名字": "张三"
}
async def create_client(self) -> TelegramClient:
"""创建并配置 Telegram 客户端"""
proxy = {
'proxy_type': self.server.proxy_type,
'addr': self.server.addr,
'port': int(self.server.port),
'username': self.server.user if self.server.user else "",
'password': self.server.pwd if self.server.pwd else ""
}
self.client = TelegramClient(
fr"C:\sessions\{self.server.phone}",
api_id=self.server.api_id,
api_hash=self.server.api_hash,
device_model=self.server.device_model,
system_version=self.server.system_version,
app_version=self.server.app_version,
system_lang_code=self.server.system_lang_code,
lang_code=self.server.lang_code,
proxy=proxy
)
return self.client
async def connect_and_auth(self) -> bool:
"""连接并验证客户端"""
try:
await self.client.connect()
if await self.client.is_user_authorized():
me = await self.client.get_me()
logger.info(f'账号 {self.server.phone} -- {me.username} 登录成功!')
return True
else:
logger.error(f'账号 {self.server.phone} 登录失败!')
return False
except Exception as e:
logger.error(f"连接失败: {e}")
return False
async def setup_verification_handler(self):
"""设置验证问题处理器"""
import re
@self.client.on(events.NewMessage)
async def handle_verification(event):
try:
message_text = event.message.text.strip()
logger.info(f"收到消息: {message_text}")
# ========== 1. 加法验证题处理 ==========
match = re.match(r"(\d+)\s*\+\s*(\d+)", message_text)
if match:
a, b = int(match.group(1)), int(match.group(2))
answer = str(a + b)
logger.info(f"检测到加法题: {a}+{b} 答案是 {answer}")
# 获取按钮并点击正确答案
if event.buttons:
for row in event.buttons:
for button in row:
if button.text.strip() == answer:
await asyncio.sleep(2) # 模拟人工延迟
await event.click(button)
logger.info(f"已点击正确答案按钮: {answer}")
return
# ========== 2. 关键字问答处理 ==========
lower_text = message_text.lower()
for keyword, answer in self.verification_answers.items():
if keyword in lower_text:
logger.info(f"检测到验证问题: {message_text}")
logger.info(f"自动回答: {answer}")
await asyncio.sleep(2)
await event.respond(answer)
logger.info("验证答案已发送")
return
# ========== 3. 泛化验证提示 ==========
if any(kw in message_text for kw in ['请回答', '请验证', '回答问题', '验证问题']):
logger.info("检测到需要回答验证问题")
except Exception as e:
logger.error(f"处理验证问题时出错: {e}")
async def join_channel(self, channel_name: str) -> bool:
"""加入频道/群组"""
try:
await self.client(JoinChannelRequest(channel_name))
logger.info(f"成功加入频道: {channel_name}")
return True
except FloodWaitError as e:
logger.warning(f"需要等待 {e.seconds} 秒后重试")
return False
except Exception as e:
logger.error(f"加入频道失败: {e}")
return False
async def check_bot_interaction(self, bot_username: str) -> bool:
"""检查是否与机器人有过交互"""
try:
async for dialog in self.client.iter_dialogs():
if dialog.is_user and dialog.entity.username == bot_username:
logger.info(f'已与机器人交互: @{bot_username}')
return True
try:
for username in dialog.entity.usernames:
if username.username == bot_username:
logger.info(f'已与机器人交互: @{bot_username}')
return True
except:
pass
logger.info(f'尚未与机器人交互: @{bot_username}')
return False
except Exception as e:
logger.error(f"检查机器人交互时出错: {e}")
return False
async def start_bot_with_invite(self, bot_name: str, invite_code: str) -> bool:
"""使用邀请码启动机器人"""
try:
result = await self.client(StartBotRequest(
bot=bot_name,
peer=bot_name,
start_param=invite_code
))
logger.info(f"成功启动机器人 {bot_name} 使用邀请码 {invite_code}")
return True
except Exception as e:
logger.error(f"启动机器人失败: {e}")
return False
async def get_webapp_data(self, bot_name: str, invite_code: Optional[str] = None) -> Optional[str]:
"""获取 WebApp 数据"""
try:
await self.client.get_input_entity(bot_name)
app_info = await self.client(RequestAppWebViewRequest(
'me',
InputBotAppShortName(await self.client.get_input_entity(bot_name), "app"),
platform="web",
start_param=invite_code if invite_code else None
))
tg_data = unquote(app_info.url.split('tgWebAppData=')[1].split('&tgWebAppVersion')[0])
logger.info(f"成功获取 WebApp 数据: {tg_data[:50]}...")
return tg_data
except Exception as e:
logger.error(f"获取 WebApp 数据失败: {e}")
return None
async def get_authorizations(self) -> list:
"""获取所有登录设备信息"""
try:
authorizations = await self.client(GetAuthorizationsRequest())
return authorizations.authorizations
except Exception as e:
logger.error(f"获取授权信息失败: {e}")
return []
async def kick_device(self, target_device_model: str) -> bool:
"""踢出指定设备"""
try:
authorizations = await self.get_authorizations()
for authorization in authorizations:
if authorization.device_model == target_device_model and not authorization.current:
await self.client(ResetAuthorizationRequest(hash=authorization.hash))
logger.info(f"已踢出设备: {authorization.device_model} (授权ID: {authorization.hash})")
return True
logger.warning(f"未找到设备: {target_device_model}")
return False
except Exception as e:
logger.error(f"踢出设备失败: {e}")
return False
async def click_confirm_button(self, chat_id: int = 777000, limit: int = 5) -> bool:
"""点击确认按钮"""
try:
messages = await self.client.get_messages(chat_id, limit=limit)
for message in messages:
if message.buttons:
for row in message.buttons:
for button in row:
if 'confirm' in button.text.lower():
await button.click()
logger.info(f"已点击消息 {message.id} 的 Confirm 按钮")
return True
logger.warning("未找到包含 Confirm 按钮的消息")
return False
except Exception as e:
logger.error(f"点击确认按钮失败: {e}")
return False
async def monitor_channel_messages(self, channel_name: str, duration: int = 60):
"""监控频道消息"""
try:
# 获取频道实体
entity = await self.get_channel_entity(channel_name)
if not entity:
logger.error(f"无法获取频道实体: {channel_name}")
return
logger.info(f"开始监控频道: {entity.title} (ID: {entity.id})")
# 设置消息处理器
await self.setup_verification_handler(entity.id)
# ✅ 使用 asyncio.wait_for 控制时间
try:
await asyncio.wait_for(self.client.run_until_disconnected(), timeout=duration)
except asyncio.TimeoutError:
logger.info(f"监控 {duration} 秒结束,主动断开连接")
await self.client.disconnect()
except Exception as e:
logger.error(f"监控频道消息时出错: {e}")
async def run_with_verification(self, channel_name: str, wait_time: int = 60):
"""运行客户端并处理验证"""
try:
# 加入频道
if not await self.join_channel(channel_name):
logger.error("加入频道失败")
return
# 监控频道消息
await self.monitor_channel_messages(channel_name, wait_time)
except Exception as e:
logger.error(f"运行过程中出错: {e}")
finally:
if self.client and self.client.is_connected():
await self.client.disconnect()
logger.info("客户端已断开连接")
async def main():
"""主函数"""
try:
# 获取设备信息
server, server_type = TgPhoneDevices().get_or_create(
phone="201285449831",
)
# 创建客户端
tg_client = OptimizedTelegramClient(server)
client = await tg_client.create_client()
# 连接并验证
if not await tg_client.connect_and_auth():
logger.error("客户端验证失败")
return
# 运行主要功能
await tg_client.run_with_verification('newmoneyai', wait_time=60)
except Exception as e:
logger.error(f"主函数执行失败: {e}")
if __name__ == '__main__':
asyncio.run(main())