Open souvenp opened 3 months ago
照着作者的写法写了个简单的监听,碰到了几个离谱的事情,群组的id居然有时候带-100有时候不带,私有群组需要先设置公开群组再设置回来再和bot交互才能通过消息链接点进去。 *这里消息如果有各种格式md,html可能无法匹配 /start 成为主人 /listen 群组或频道链接 单个字符串或逗号隔开字符串(或逻辑)或空格隔开的字符串(且逻辑):监听消息 /to 群组或者频道的链接:转发目标,机器人需要在那个里面,有时候需要重新拉进去 /unlisten 链接:解除该链接监听 /close 解除所有监听 /id 链接:获取id
import logging
from telethon import TelegramClient, events
import os, asyncio
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
logger = logging.getLogger(__name__)
api_id = 'xx'
api_hash = 'xx'
bot_token = 'xx'
phone_number = '+xxx'
# 初始化 TelegramClient
client = TelegramClient(f'session_name', api_id, api_hash)
bot = TelegramClient('bot', api_id, api_hash)
# 要监听的群组列表和对应的过滤条件
listen_targets = {}
default_group_id = xxxx # 默认群组ID
owner_id = None # 用于保存 owner 的 ID
# 下载并转发媒体文件
async def download_and_forward_media(event, target_chat_id, message_text):
media = event.message.media
if media:
file_path = await event.message.download_media()
await bot.send_file(target_chat_id, file_path, caption=message_text)
os.remove(file_path)
else:
await bot.send_message(target_chat_id, message_text)
# 监听并处理群组消息
@client.on(events.NewMessage())
async def message_handler(event):
chat_id = event.chat_id
message_text = event.text
# 获取 chat_id 的后八位
chat_id_suffix = str(chat_id)[-8:]
# 匹配 listen_targets 中的 chat_id 后八位
matched_filter = None
for target_chat_id, filters in listen_targets.items():
if str(target_chat_id)[-8:] == chat_id_suffix:
matched_filter = filters
break
if not matched_filter:
return
# 简单过滤逻辑
if matched_filter:
for filter_item in matched_filter:
if ',' in filter_item:
or_conditions = filter_item.split(',')
if not any(cond in message_text for cond in or_conditions):
return
elif ' ' in filter_item:
and_conditions = filter_item.split()
if not all(cond in message_text for cond in and_conditions):
return
else:
if filter_item not in message_text:
return
# 构建消息文本
if str(event.chat_id).startswith('-100'):
chat_id_suffix = str(abs(event.chat_id))[3:]
else:
chat_id_suffix = str(abs(event.chat_id))
message_link = f"https://t.me/c/{chat_id_suffix}/{event.id}"
message_text = f"{message_text}\n\n[FROM {event.chat.title}]({message_link})"
# 转发媒体文件或文本消息
await download_and_forward_media(event, default_group_id, message_text)
# 机器人命令处理 - /start
@bot.on(events.NewMessage(pattern='/start'))
async def start(event):
global owner_id
if owner_id is None:
# 第一次调用 /start 命令的用户将被设置为主人
owner_id = event.sender_id
await event.respond(f'Welcome, you are now the bot owner. Your ID is {owner_id}.')
elif event.sender_id == owner_id:
# 如果当前用户已经是主人
await event.respond('Bot is running and you are the owner..')
else:
# 如果用户不是主人,拒绝权限
await event.respond('Sorry, you are not the bot owner and cannot use this command.')
# 机器人命令处理 - /listen
@bot.on(events.NewMessage(pattern='/listen (.+)'))
async def set_listen(event):
if event.sender_id != owner_id:
await event.respond("You're not authorized to use this command.")
return
try:
args = event.pattern_match.group(1).split(' ', 1)
link = args[0]
filters = args[1].split() if len(args) > 1 else []
entity = await client.get_entity(link)
if str(entity.id).startswith('-100'):
normalized_chat_id = str(entity.id)
else:
normalized_chat_id = str('-100' + str(abs(entity.id)))
listen_targets[normalized_chat_id] = filters
await event.respond(f"Listening to {entity.title} with filters: {filters}")
except Exception as e:
await event.respond(f"Failed to set listen: {str(e)}")
# 机器人命令处理 - /id
@bot.on(events.NewMessage(pattern='/id ?(.+)?'))
async def get_id(event):
if event.sender_id != owner_id:
await event.respond("You're not authorized to use this command.")
return
try:
if event.is_private:
await event.respond(f"Your ID: {event.sender_id}")
elif event.is_group or event.is_channel:
await event.respond(f"Chat ID: {event.chat_id}")
if event.pattern_match.group(1):
link = event.pattern_match.group(1)
entity = await client.get_entity(link)
await event.respond(f"ID for {link}: {entity.id}")
except Exception as e:
await event.respond(f"Failed to retrieve ID: {str(e)}")
# 机器人命令处理 - /to
@bot.on(events.NewMessage(pattern='/to ?(.+)?'))
async def set_forward_target(event):
global default_group_id
if event.sender_id != owner_id:
await event.respond("You're not authorized to use this command.")
return
try:
if event.pattern_match.group(1):
link = event.pattern_match.group(1)
entity = await client.get_entity(link)
default_group_id = entity.id
await event.respond(f"Messages will now be forwarded to {entity.title}.")
elif event.is_group or event.is_channel:
default_group_id = event.chat_id
await event.respond(f"Messages will now be forwarded to this chat.")
except Exception as e:
await event.respond(f"Failed to set forward target: {str(e)}")
# 机器人命令处理 - /unlisten
@bot.on(events.NewMessage(pattern='/unlisten (.+)'))
async def unlisten(event):
if event.sender_id != owner_id:
await event.respond("You're not authorized to use this command.")
return
try:
link = event.pattern_match.group(1)
entity = await client.get_entity(link)
if str(entity.id).startswith('-100'):
normalized_chat_id = str(entity.id)
else:
normalized_chat_id = str('-100' + str(abs(entity.id)))
if normalized_chat_id in listen_targets:
del listen_targets[normalized_chat_id]
await event.respond(f"Stopped listening to {entity.title}.")
else:
await event.respond(f"Not listening to {entity.title}.")
except Exception as e:
await event.respond(f"Failed to unlisten: {str(e)}")
# 机器人命令处理 - /close
@bot.on(events.NewMessage(pattern='/close'))
async def close(event):
if event.sender_id != owner_id:
await event.respond("You're not authorized to use this command.")
return
try:
listen_targets.clear()
await event.respond("Stopped listening to all targets.")
except Exception as e:
await event.respond(f"Failed to clear listen targets: {str(e)}")
# 运行客户端
if __name__ == "__main__":
cache.expire()
client.start(phone=phone_number)
bot.start(bot_token=bot_token)
client.run_until_disconnected()
以及转发完整消息,包括非文本的内容 if event.message.media: file_path = await event.message.download_media() await bot.send_file(receiver, file_path, caption=message_str, link_preview=True, parse_mode='markdown') os.remove(file_path) else: await bot.send_message(receiver, message_str, link_preview=True, parse_mode='markdown')