Hootrix / keyword_alert_bot

telegram keyword alert bot ⏰
https://t.me/keyword_alert_bot
GNU General Public License v3.0
265 stars 62 forks source link

[FEATURE] 是否可以增加推送到群组频道而不是机器人私聊里面 #102

Open souvenp opened 3 months ago

souvenp commented 3 months ago

以及转发完整消息,包括非文本的内容 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')

souvenp commented 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()