import os import asyncio from telethon import TelegramClient, events from telethon.tl.types import Channel, Chat, User from telethon.tl.functions.channels import GetParticipantRequest from telethon.errors import ChannelInvalidError, ChannelPrivateError # تحميل المتغيرات من البيئة def load_config(): """تحميل الإعدادات من ملف .env""" from dotenv import load_dotenv load_dotenv() # تحميل القيم من ملف .env api_id = os.getenv('API_ID') api_hash = os.getenv('API_HASH') bot_token = os.getenv('BOT_TOKEN') # إذا لم تكن القيم موجودة، نطلب من المستخدم إدخالها if not api_id: api_id = input("🔑 أدخل API_ID: ") os.environ['API_ID'] = api_id if not api_hash: api_hash = input("🔑 أدخل API_HASH: ") os.environ['API_HASH'] = api_hash if not bot_token: bot_token = input("🔑 أدخل BOT_TOKEN: ") os.environ['BOT_TOKEN'] = bot_token try: return int(api_id), api_hash, bot_token except ValueError: print("❌ خطأ: API_ID يجب أن يكون رقماً صحيحاً") exit(1) # تحميل الإعدادات api_id, api_hash, bot_token = load_config() print(f"✅ تم تحميل الإعدادات:") print(f" API_ID: {api_id}") print(f" API_HASH: {api_hash}") print(f" BOT_TOKEN: {bot_token}") # إنشاء العميل client = TelegramClient('forward_bot_session', api_id, api_hash).start(bot_token=bot_token) # قائمة لحفظ القنوات/المجموعات التي البوت مشرف فيها admin_channels = [] async def get_admin_channels(): """الحصول على جميع القنوات والمجموعات التي يكون البوت مشرفاً فيها""" global admin_channels # إذا كانت القائمة محفوظة بالفعل، نعيدها if admin_channels: return admin_channels admin_chats = [] try: # بدلاً من iter_dialogs، سنستخدم طريقة بديلة للبوتات # البوتات يمكنها فقط رؤية الدردشات التي تمت إضافتها إليها # جلب الدردشات التي البوت عضو فيها (هذه تعمل مع البوتات) async for dialog in client.iter_dialogs(): if isinstance(dialog.entity, User): continue try: # التحقق إذا كان البوت مشرفاً في هذه الدردشة if isinstance(dialog.entity, (Channel, Chat)): try: participant = await client(GetParticipantRequest( dialog.entity, await client.get_input_entity('me') )) if hasattr(participant.participant, 'admin_rights'): if participant.participant.admin_rights.post_messages: admin_chats.append(dialog.entity.id) print(f"✅ البوت مشرف في: {dialog.name} (ID: {dialog.entity.id})") elif hasattr(participant.participant, 'rank'): # بعض أنواع المشرفين admin_chats.append(dialog.entity.id) print(f"✅ البوت مشرف في: {dialog.name} (ID: {dialog.entity.id})") except (ChannelInvalidError, ChannelPrivateError, ValueError): continue except Exception as e: # إذا فشل التحقق، قد يكون البوت مشرفاً لكن مع صلاحيات محدودة continue except Exception as e: continue except Exception as e: print(f"❌ خطأ في جلب الدردشات: {e}") # نستخدم طريقة بديلة: تخزين القنوات يدوياً عند إضافة البوت كمساعد print("⚠️ يمكنك إضافة القنوات يدوياً عن طريق إرسال /add_channel") admin_channels = admin_chats return admin_chats @client.on(events.NewMessage(incoming=True, func=lambda e: e.is_private)) async def handle_private_message(event): """معالجة الرسائل الخاصة الواردة""" try: message_text = event.message.text sender_id = event.sender_id print(f"📩 رسالة جديدة من {sender_id}: {message_text}") # التحقق من الأوامر الخاصة if message_text.startswith('/'): if message_text.startswith('/add_channel'): # إضافة قناة يدوياً if event.message.reply_to_msg_id: replied_msg = await event.get_reply_message() if replied_msg.forward_from_chat: chat_id = replied_msg.forward_from_chat.id if chat_id not in admin_channels: admin_channels.append(chat_id) await event.reply(f"✅ تمت إضافة القناة {chat_id} إلى القائمة") else: await event.reply("⚠️ هذه القناة مضافة بالفعل") return await event.reply("⚠️ للاستخدام: رد على رسالة من القناة بأمر /add_channel") return elif message_text.startswith('/list_channels'): # عرض القنوات المضافة if admin_channels: response = "📋 القنوات/المجموعات المضافة:\n" for i, chat_id in enumerate(admin_channels, 1): response += f"{i}. {chat_id}\n" await event.reply(response) else: await event.reply("❌ لا توجد قنوات مضافة بعد") return elif message_text.startswith('/clear_channels'): # مسح القنوات admin_channels.clear() await event.reply("✅ تم مسح جميع القنوات من القائمة") return # الحصول على القنوات/المجموعات التي البوت مشرف فيها admin_chats = await get_admin_channels() if not admin_chats: print("❌ البوت ليس مشرفاً في أي قناة أو مجموعة") await event.reply("⚠️ أنا لست مشرفاً في أي قناة أو مجموعة حالياً.\n\nاستخدم /add_channel لإضافة قنوات يدوياً") return # إعادة توجيه الرسالة إلى جميع القنوات/المجموعات success_count = 0 for chat_id in admin_chats: try: await client.forward_messages(chat_id, event.message) print(f"✅ تم إعادة التوجيه إلى الدردشة: {chat_id}") success_count += 1 except Exception as e: print(f"❌ فشل الإرسال إلى {chat_id}: {e}") # إزالة القناة من القائمة إذا فشل الإرسال if chat_id in admin_channels: admin_channels.remove(chat_id) # إرسال تقرير للمستخدم await event.reply(f"✅ تم إعادة توجيه رسالتك إلى {success_count} من {len(admin_chats)} قناة/مجموعة") except Exception as e: print(f"❌ خطأ في معالجة الرسالة: {e}") await event.reply("⚠️ عذراً، حدث خطأ أثناء معالجة رسالتك.") async def main(): """الدالة الرئيسية لتشغيل البوت""" print("🔍 جاري البحث عن القنوات والمجموعات التي البوت مشرف فيها...") admin_chats = await get_admin_channels() if admin_chats: print(f"✅ البوت مشرف في {len(admin_chats)} قناة/مجموعة") else: print("❌ البوت ليس مشرفاً في أي قناة أو مجموعة") print("💡 يمكنك إضافة قنوات يدوياً باستخدام الأمر /add_channel") print("🤖 البوت يعمل الآن ويستمع للرسائل...") print("📋 الأوامر المتاحة:") print(" /add_channel - إضافة قناة يدوياً (الرد على رسالة من القناة)") print(" /list_channels - عرض القنوات المضافة") print(" /clear_channels - مسح جميع القنوات") # تشغيل البوت with client: client.loop.run_until_complete(main()) client.run_until_disconnected()