-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
116 lines (97 loc) · 3.59 KB
/
Copy pathmain.py
File metadata and controls
116 lines (97 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import asyncio
import os
import sys
import traceback
from pyrogram import Client
from config import ACCOUNTS, TARGETS_FILE, SOURCE_CHANNEL, MOCK_MODE
from account_manager import AccountManager
from dispatcher import Dispatcher
from monitor import Monitor
from logger import logger
def load_targets(filepath: str) -> list:
"""Load target usernames/phone numbers from file."""
if not os.path.exists(filepath):
logger.error(f"Targets file not found: {filepath}")
return []
targets = []
with open(filepath, "r", encoding="utf-8") as f:
for line in f:
# Strip all whitespace including \r and \n
line = line.strip()
if line and not line.startswith("#"):
# Convert numeric IDs (like -100xxx) to integers
if line.lstrip('-').isdigit():
targets.append(int(line))
else:
targets.append(line)
if not targets:
logger.error("No targets found in targets.txt!")
return []
logger.info(f"Loaded {len(targets)} targets from {filepath}")
for t in targets:
logger.info(f" Target: {t}")
return targets
async def main():
logger.info("=" * 55)
logger.info(" TELEGRAM BULK MESSENGER — Starting Up")
logger.info("=" * 55)
# 1. Load targets
targets = load_targets(TARGETS_FILE)
if not targets:
logger.error("No valid targets. Please add targets in the Admin Panel and restart.")
return
# 2. Initialize account manager (logs in all sender accounts)
account_manager = AccountManager()
await account_manager.initialize()
# 3. Set up dispatcher with the target list
dispatcher = Dispatcher(account_manager, targets)
# 4. Handle Mock vs Real Monitor
if MOCK_MODE:
logger.info("🛠️ MOCK MODE: Injecting a test message to start the demo...")
# Inject a fake message data
fake_message = {
"from_chat_id": 123456789,
"message_id": 1
}
await dispatcher.enqueue(fake_message)
try:
await dispatcher.run()
except (KeyboardInterrupt, asyncio.CancelledError):
pass
else:
# Real production mode
# Reuse the FIRST client already started by account_manager
# This avoids the "sqlite3.OperationalError: database is locked" error
monitor_client = account_manager.clients[0]
logger.info(f"Monitor client active. Watching: {SOURCE_CHANNEL}")
monitor = Monitor(monitor_client, dispatcher)
# Diagnostic: List all channels we can see
await monitor.list_channels()
# Start dispatcher in the background
dispatcher_task = asyncio.create_task(dispatcher.run())
try:
# idle() keeps the script running and listening for events
await monitor_client.idle()
except (KeyboardInterrupt, asyncio.CancelledError):
pass
finally:
dispatcher.stop()
await dispatcher_task
# 5. Shutdown
await account_manager.stop_all()
logger.info("Bot stopped cleanly.")
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
print("\nBot interrupted by user.")
except Exception as e:
print("\n" + "=" * 55)
print("❌ BOT CRASHED WITH ERROR:")
print("=" * 55)
traceback.print_exc()
print("=" * 55)
finally:
# KEEP THE WINDOW OPEN so the user can read the output
print("\n")
input("Press ENTER to close this window...")