Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python3
- # dual.py - Complete Dual Bot dengan Semua Methods
- import socket
- import time
- import threading
- import random
- from config import SERVER, PORT, CHANNELS
- from waktu import TimeAnnouncer
- from ctcp import RealPingMonitor
- from events import EventHandler
- from prompt import irc_prompt, debug_prompt, status_prompt
- from api import api_manager
- from focus import autofocus
- class DualBot:
- def __init__(self):
- self.master_sock = None
- self.client_sock = None
- self.running = True
- self.joined_channels = set()
- # Initialize modules
- self.events = EventHandler()
- self.ping_monitor = RealPingMonitor()
- self.time_announcer = None
- print(debug_prompt("Dual Bot dengan Focus System Initialized"))
- def should_respond_to_message(self, nick, target, message, is_master=True):
- """Simple wrapper untuk focus system"""
- bot_name = "www" if is_master else "deep"
- # Ignore bots
- if nick in ["www", "deep"]:
- return False
- # GUNA AUTO-FOCUS SYSTEM dari focus.py
- return autofocus.should_respond(nick, message, bot_name)
- def send_message_delayed(self, target, message, is_master=True):
- """Delay 1.5-2.5s"""
- bot_name = "www" if is_master else "deep"
- # Random delay
- delay_time = random.uniform(1.5, 2.5)
- print(f"⏳ {bot_name} delay: {delay_time:.1f}s")
- time.sleep(delay_time)
- # Send message
- print(f"🎯 {bot_name} sending: '{message}'")
- if is_master:
- self.events.send_message(target, message, is_master=True)
- else:
- self.events.send_message(target, message, is_master=False)
- def connect_master(self):
- """Connect master bot"""
- try:
- print(f"🔌 Connecting master to {SERVER}:{PORT}...")
- self.master_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.master_sock.settimeout(30)
- self.master_sock.connect((SERVER, PORT))
- self.master_sock.settimeout(None)
- print("✅ Master socket connected!")
- self.master_sock.send(f"NICK www\r\n".encode())
- self.master_sock.send(f"USER www 0 * :Master Bot\r\n".encode())
- print("📤 Master registration sent")
- self.events.master_sock = self.master_sock
- return True
- except Exception as e:
- print(f"❌ Master connection failed: {e}")
- return False
- def connect_client(self):
- """Connect client bot"""
- try:
- print(f"🔌 Connecting client to {SERVER}:{PORT}...")
- self.client_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.client_sock.settimeout(30)
- self.client_sock.connect((SERVER, PORT))
- self.client_sock.settimeout(None)
- print("✅ Client socket connected!")
- self.client_sock.send(f"NICK deep\r\n".encode())
- self.client_sock.send(f"USER deep 0 * :AI Assistant\r\n".encode())
- print("📤 Client registration sent")
- self.events.client_sock = self.client_sock
- return True
- except Exception as e:
- print(f"❌ Client connection failed: {e}")
- return False
- def identify_bots(self):
- """Identify both bots to NickServ menggunakan config yang betul"""
- try:
- from config import BOTS
- # Cara yang betul untuk identify
- master_nick = BOTS['www']['nick']
- master_pass = BOTS['www']['password']
- client_nick = BOTS['deep']['nick']
- client_pass = BOTS['deep']['password']
- # Format yang betul: "IDENTIFY <password>" BUKAN "IDENTIFY <nick> <password>"
- self.master_sock.send(f"PRIVMSG NickServ :IDENTIFY {master_pass}\r\n".encode())
- time.sleep(1)
- self.client_sock.send(f"PRIVMSG NickServ :IDENTIFY {client_pass}\r\n".encode())
- time.sleep(2)
- print(status_prompt("AUTH", "Identification commands sent"))
- except Exception as e:
- print(debug_prompt(f"Identification failed: {e}"))
- def join_channels(self):
- """Join semua channels"""
- try:
- for channel in CHANNELS:
- if not channel.startswith('#'):
- channel = '#' + channel
- self.master_sock.send(f"JOIN {channel}\r\n".encode())
- self.client_sock.send(f"JOIN {channel}\r\n".encode())
- self.joined_channels.add(channel)
- time.sleep(0.5)
- print(status_prompt("CHANNEL", f"Joined {len(CHANNELS)} channels"))
- except Exception as e:
- print(debug_prompt(f"Channel join failed: {e}"))
- def rejoin_channel(self, channel):
- """Auto-rejoin channel apabila kena kick"""
- try:
- if channel in self.joined_channels:
- print(debug_prompt(f"Rejoining channel {channel}..."))
- self.master_sock.send(f"JOIN {channel}\r\n".encode())
- self.client_sock.send(f"JOIN {channel}\r\n".encode())
- time.sleep(1)
- print(status_prompt("CHANNEL", f"Rejoined {channel}"))
- except Exception as e:
- print(debug_prompt(f"Rejoin failed: {e}"))
- def _server_ping_timer(self):
- """Send PING to server every 60 seconds"""
- while self.running:
- try:
- time.sleep(60)
- if self.master_sock:
- self.master_sock.send(b'PING :keepalive_60s\r\n')
- print("🔁 MASTER SERVER PING SENT (60s)")
- if self.client_sock:
- self.client_sock.send(b'PING :keepalive_60s\r\n')
- print("🔁 CLIENT SERVER PING SENT (60s)")
- except Exception as e:
- print(f"❌ Server ping error: {e}")
- def on_connect_actions(self):
- """Execute actions on connect"""
- try:
- self.master_sock.send(b'PRIVMSG www :\x01PING connect_test\x01\r\n')
- self.client_sock.send(b'PRIVMSG deep :\x01PING connect_test\x01\r\n')
- print("🔁 CTCP self-ping on connect")
- except:
- pass
- def handle_master_message(self, line):
- """Handle incoming messages untuk master bot"""
- print(f"🔍 MASTER IN: {line}")
- # STANDARD IRC SERVER PING RESPONSE
- if line.startswith('PING '):
- ping_data = line.split('PING ')[1]
- pong_msg = f"PONG {ping_data}\r\n"
- self.master_sock.send(pong_msg.encode())
- print(f"🔁 MASTER SERVER PONG: {pong_msg.strip()}")
- return
- # STANDARD IRC PING (format lain)
- if line.startswith(':') and ' PING ' in line:
- ping_data = line.split(' PING ')[1]
- self.ping_monitor.log_master_ping(ping_data)
- pong_msg = f"PONG {ping_data}\r\n"
- self.master_sock.send(pong_msg.encode())
- self.ping_monitor.log_master_pong()
- print(f"🔁 MASTER PONG SENT: {pong_msg.strip()}")
- return
- # CTCP PING HANDLING
- if '\x01PING' in line and 'PRIVMSG' in line:
- print(f"🔁 MASTER CTCP PING: {line}")
- try:
- nick = line.split('!')[0][1:]
- ping_data = line.split('\x01PING ')[1].split('\x01')[0]
- ctcp_reply = f"NOTICE {nick} :\x01PING {ping_data}\x01\r\n"
- self.master_sock.send(ctcp_reply.encode())
- print(f"🔁 MASTER CTCP PONG to {nick}: {ping_data}")
- except Exception as e:
- print(f"❌ MASTER CTCP error: {e}")
- return
- if 'KICK' in line:
- try:
- parts = line.split(' ')
- channel = parts[2]
- kicked_nick = parts[3]
- if kicked_nick in ['www', 'deep']:
- print(debug_prompt(f"Bot was kicked from {channel}"))
- self.rejoin_channel(channel)
- except Exception as e:
- print(debug_prompt(f"Kick handling error: {e}"))
- return
- # 🆕 FIXED: PRIVMSG HANDLING - INI PERLU DI LUAR DARI if 'KICK' block!
- if 'PRIVMSG' in line:
- try:
- parts = line.split(' ', 3)
- if len(parts) >= 4:
- nick = parts[0][1:].split('!')[0]
- target = parts[2]
- message = parts[3][1:]
- print(f"🎯 MASTER processing PRIVMSG from {nick}: {message}")
- # GUNA AUTO-FOCUS SYSTEM
- should_respond = self.should_respond_to_message(nick, target, message, is_master=True)
- if not should_respond:
- print(f"🛑 MASTER: Skip {nick} (no focus/mention)")
- return
- print(f"✅ MASTER: Processing message from {nick}")
- # Display dengan prompt system
- prompt = irc_prompt.get_prompt("www", target)
- print(f"{prompt}{nick}: {message}")
- # Handle ACTION (/me) messages
- if message.startswith('\x01ACTION ') and message.endswith('\x01'):
- action_text = message[8:-1]
- response = self.events.handle_action(nick, target, action_text, is_master=True)
- if response:
- self.send_message_delayed(target, response, is_master=True)
- irc_prompt.log_interaction("www", nick, message, response)
- # Handle normal PRIVMSG
- else:
- response = self.events.handle_privmsg(nick, target, message, is_master=True)
- print(f"🔧 DEBUG: Response = {response}")
- if response:
- self.send_message_delayed(target, response, is_master=True)
- irc_prompt.log_interaction("www", nick, message, response)
- except Exception as e:
- print(debug_prompt(f"Master message error: {e}"))
- elif 'NOTICE' in line:
- try:
- parts = line.split(' ', 3)
- if len(parts) >= 4:
- nick = parts[0][1:].split('!')[0]
- notice_text = parts[3][1:]
- prompt = irc_prompt.get_prompt("www", "NOTICE")
- print(f"{prompt}From {nick}: {notice_text}")
- response = self.events.handle_notice(nick, notice_text, is_master=True)
- if response:
- self.send_message_delayed(nick, response, is_master=True)
- except Exception as e:
- print(debug_prompt(f"Master notice error: {e}"))
- def handle_client_message(self, line):
- """Handle incoming messages untuk client bot"""
- print(f"🔍 CLIENT IN: {line}")
- # STANDARD IRC SERVER PING RESPONSE
- if line.startswith('PING '):
- ping_data = line.split('PING ')[1]
- pong_msg = f"PONG {ping_data}\r\n"
- self.client_sock.send(pong_msg.encode())
- print(f"🔁 CLIENT SERVER PONG: {pong_msg.strip()}")
- return
- # STANDARD IRC PING (format lain)
- if line.startswith(':') and ' PING ' in line:
- ping_data = line.split(' PING ')[1]
- self.ping_monitor.log_client_ping(ping_data)
- pong_msg = f"PONG {ping_data}\r\n"
- self.client_sock.send(pong_msg.encode())
- self.ping_monitor.log_client_pong()
- print(f"🔁 CLIENT PONG SENT: {pong_msg.strip()}")
- return
- # CTCP PING HANDLING
- if '\x01PING' in line and 'PRIVMSG' in line:
- print(f"🔁 CLIENT CTCP PING: {line}")
- try:
- nick = line.split('!')[0][1:]
- ping_data = line.split('\x01PING ')[1].split('\x01')[0]
- ctcp_reply = f"NOTICE {nick} :\x01PING {ping_data}\x01\r\n"
- self.client_sock.send(ctcp_reply.encode())
- print(f"🔁 CLIENT CTCP PONG to {nick}: {ping_data}")
- except Exception as e:
- print(f"❌ CLIENT CTCP error: {e}")
- return
- if 'KICK' in line:
- try:
- parts = line.split(' ')
- channel = parts[2]
- kicked_nick = parts[3]
- if kicked_nick in ['www', 'deep']:
- print(debug_prompt(f"Bot was kicked from {channel}"))
- self.rejoin_channel(channel)
- except Exception as e:
- print(debug_prompt(f"Kick handling error: {e}"))
- return
- if 'PRIVMSG' in line:
- try:
- parts = line.split(' ', 3)
- if len(parts) >= 4:
- nick = parts[0][1:].split('!')[0]
- target = parts[2]
- message = parts[3][1:]
- print(f"🎯 CLIENT processing PRIVMSG from {nick}: {message}")
- # GUNA AUTO-FOCUS SYSTEM
- should_respond = self.should_respond_to_message(nick, target, message, is_master=False)
- if not should_respond:
- print(f"🛑 CLIENT: Skip {nick} (no focus/mention)")
- return
- print(f"✅ CLIENT: Processing message from {nick}")
- # Display dengan prompt system
- prompt = irc_prompt.get_prompt("deep", target)
- print(f"{prompt}{nick}: {message}")
- # Handle ACTION (/me) messages
- if message.startswith('\x01ACTION ') and message.endswith('\x01'):
- action_text = message[8:-1]
- response = self.events.handle_action(nick, target, action_text, is_master=False)
- if response:
- self.send_message_delayed(target, response, is_master=False)
- irc_prompt.log_interaction("deep", nick, message, response)
- # Handle normal PRIVMSG
- else:
- response = self.events.handle_privmsg(nick, target, message, is_master=False)
- print(f"🔧 DEBUG: Response = {response}")
- if response:
- self.send_message_delayed(target, response, is_master=False)
- irc_prompt.log_interaction("deep", nick, message, response)
- except Exception as e:
- print(debug_prompt(f"Client message error: {e}"))
- elif 'NOTICE' in line:
- try:
- parts = line.split(' ', 3)
- if len(parts) >= 4:
- nick = parts[0][1:].split('!')[0]
- notice_text = parts[3][1:]
- prompt = irc_prompt.get_prompt("deep", "NOTICE")
- print(f"{prompt}From {nick}: {notice_text}")
- response = self.events.handle_notice(nick, notice_text, is_master=False)
- if response:
- self.send_message_delayed(nick, response, is_master=False)
- except Exception as e:
- print(debug_prompt(f"Client notice error: {e}"))
- def master_loop(self):
- """Main loop untuk master bot"""
- buffer = ""
- while self.running and self.master_sock:
- try:
- data = self.master_sock.recv(1024).decode('utf-8', errors='ignore')
- if not data:
- break
- buffer += data
- lines = buffer.split('\r\n')
- buffer = lines.pop()
- for line in lines:
- line = line.strip()
- if line:
- self.handle_master_message(line)
- except Exception as e:
- print(debug_prompt(f"Master loop error: {e}"))
- break
- def client_loop(self):
- """Main loop untuk client bot"""
- buffer = ""
- while self.running and self.client_sock:
- try:
- data = self.client_sock.recv(1024).decode('utf-8', errors='ignore')
- if not data:
- break
- buffer += data
- lines = buffer.split('\r\n')
- buffer = lines.pop()
- for line in lines:
- line = line.strip()
- if line:
- self.handle_client_message(line)
- except Exception as e:
- print(debug_prompt(f"Client loop error: {e}"))
- break
- def start(self):
- """Start dual bot system"""
- try:
- print(debug_prompt("Starting Dual Bot..."))
- if not self.connect_master():
- print(debug_prompt("Master connection failed"))
- return False
- if not self.connect_client():
- print(debug_prompt("Client connection failed"))
- return False
- self.on_connect_actions()
- time.sleep(3)
- self.identify_bots()
- self.join_channels()
- print(status_prompt("SYSTEM", "Dual Bot System READY!"))
- # Start background modules
- self.time_announcer = TimeAnnouncer(self.master_sock, CHANNELS)
- ping_thread = self.ping_monitor.start()
- time_thread = self.time_announcer.start()
- # SERVER PING TIMER (60s)
- server_ping_thread = threading.Thread(target=self._server_ping_timer, daemon=True)
- server_ping_thread.start()
- # Start bot loops
- master_thread = threading.Thread(target=self.master_loop, daemon=True)
- client_thread = threading.Thread(target=self.client_loop, daemon=True)
- master_thread.start()
- client_thread.start()
- while self.running and master_thread.is_alive() and client_thread.is_alive():
- time.sleep(5)
- return True
- except Exception as e:
- print(debug_prompt(f"Bot startup failed: {e}"))
- return False
- def is_running(self):
- return self.running
- def stop(self):
- self.running = False
- try:
- if self.master_sock:
- self.master_sock.close()
- if self.client_sock:
- self.client_sock.close()
- self.ping_monitor.stop()
- print(status_prompt("SYSTEM", "Dual Bot stopped"))
- except Exception as e:
- print(debug_prompt(f"Stop error: {e}"))
- if __name__ == "__main__":
- bot = DualBot()
- bot.start()
Advertisement
Add Comment
Please, Sign In to add comment