acescripters

dual.py

Nov 12th, 2025
484
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 18.95 KB | Source Code | 0 0
  1. #!/usr/bin/env python3
  2. # dual.py - Complete Dual Bot dengan Semua Methods
  3. import socket
  4. import time
  5. import threading
  6. import random
  7. from config import SERVER, PORT, CHANNELS
  8. from waktu import TimeAnnouncer
  9. from ctcp import RealPingMonitor
  10. from events import EventHandler
  11. from prompt import irc_prompt, debug_prompt, status_prompt
  12. from api import api_manager
  13. from focus import autofocus
  14.  
  15. class DualBot:
  16.     def __init__(self):
  17.         self.master_sock = None
  18.         self.client_sock = None
  19.         self.running = True
  20.         self.joined_channels = set()
  21.  
  22.         # Initialize modules
  23.         self.events = EventHandler()
  24.         self.ping_monitor = RealPingMonitor()
  25.         self.time_announcer = None
  26.  
  27.         print(debug_prompt("Dual Bot dengan Focus System Initialized"))
  28.  
  29.     def should_respond_to_message(self, nick, target, message, is_master=True):
  30.         """Simple wrapper untuk focus system"""
  31.         bot_name = "www" if is_master else "deep"
  32.  
  33.         # Ignore bots
  34.         if nick in ["www", "deep"]:
  35.             return False
  36.  
  37.         # GUNA AUTO-FOCUS SYSTEM dari focus.py
  38.         return autofocus.should_respond(nick, message, bot_name)
  39.  
  40.     def send_message_delayed(self, target, message, is_master=True):
  41.         """Delay 1.5-2.5s"""
  42.         bot_name = "www" if is_master else "deep"
  43.  
  44.         # Random delay
  45.         delay_time = random.uniform(1.5, 2.5)
  46.         print(f"⏳ {bot_name} delay: {delay_time:.1f}s")
  47.         time.sleep(delay_time)
  48.  
  49.         # Send message
  50.         print(f"🎯 {bot_name} sending: '{message}'")
  51.  
  52.         if is_master:
  53.             self.events.send_message(target, message, is_master=True)
  54.         else:
  55.             self.events.send_message(target, message, is_master=False)
  56.  
  57.     def connect_master(self):
  58.         """Connect master bot"""
  59.         try:
  60.             print(f"🔌 Connecting master to {SERVER}:{PORT}...")
  61.             self.master_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  62.             self.master_sock.settimeout(30)
  63.             self.master_sock.connect((SERVER, PORT))
  64.             self.master_sock.settimeout(None)
  65.             print("✅ Master socket connected!")
  66.  
  67.             self.master_sock.send(f"NICK www\r\n".encode())
  68.             self.master_sock.send(f"USER www 0 * :Master Bot\r\n".encode())
  69.             print("📤 Master registration sent")
  70.  
  71.             self.events.master_sock = self.master_sock
  72.             return True
  73.  
  74.         except Exception as e:
  75.             print(f"❌ Master connection failed: {e}")
  76.             return False
  77.  
  78.     def connect_client(self):
  79.         """Connect client bot"""
  80.         try:
  81.             print(f"🔌 Connecting client to {SERVER}:{PORT}...")
  82.             self.client_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  83.             self.client_sock.settimeout(30)
  84.             self.client_sock.connect((SERVER, PORT))
  85.             self.client_sock.settimeout(None)
  86.             print("✅ Client socket connected!")
  87.  
  88.             self.client_sock.send(f"NICK deep\r\n".encode())
  89.             self.client_sock.send(f"USER deep 0 * :AI Assistant\r\n".encode())
  90.             print("📤 Client registration sent")
  91.  
  92.             self.events.client_sock = self.client_sock
  93.             return True
  94.  
  95.         except Exception as e:
  96.             print(f"❌ Client connection failed: {e}")
  97.             return False
  98.  
  99.     def identify_bots(self):
  100.         """Identify both bots to NickServ menggunakan config yang betul"""
  101.         try:
  102.             from config import BOTS
  103.  
  104.             # Cara yang betul untuk identify
  105.             master_nick = BOTS['www']['nick']
  106.             master_pass = BOTS['www']['password']
  107.             client_nick = BOTS['deep']['nick']
  108.             client_pass = BOTS['deep']['password']
  109.  
  110.             # Format yang betul: "IDENTIFY <password>" BUKAN "IDENTIFY <nick> <password>"
  111.             self.master_sock.send(f"PRIVMSG NickServ :IDENTIFY {master_pass}\r\n".encode())
  112.             time.sleep(1)
  113.             self.client_sock.send(f"PRIVMSG NickServ :IDENTIFY {client_pass}\r\n".encode())
  114.             time.sleep(2)
  115.             print(status_prompt("AUTH", "Identification commands sent"))
  116.         except Exception as e:
  117.             print(debug_prompt(f"Identification failed: {e}"))
  118.  
  119.     def join_channels(self):
  120.         """Join semua channels"""
  121.         try:
  122.             for channel in CHANNELS:
  123.                 if not channel.startswith('#'):
  124.                     channel = '#' + channel
  125.  
  126.                 self.master_sock.send(f"JOIN {channel}\r\n".encode())
  127.                 self.client_sock.send(f"JOIN {channel}\r\n".encode())
  128.                 self.joined_channels.add(channel)
  129.                 time.sleep(0.5)
  130.  
  131.             print(status_prompt("CHANNEL", f"Joined {len(CHANNELS)} channels"))
  132.         except Exception as e:
  133.             print(debug_prompt(f"Channel join failed: {e}"))
  134.  
  135.     def rejoin_channel(self, channel):
  136.         """Auto-rejoin channel apabila kena kick"""
  137.         try:
  138.             if channel in self.joined_channels:
  139.                 print(debug_prompt(f"Rejoining channel {channel}..."))
  140.                 self.master_sock.send(f"JOIN {channel}\r\n".encode())
  141.                 self.client_sock.send(f"JOIN {channel}\r\n".encode())
  142.                 time.sleep(1)
  143.                 print(status_prompt("CHANNEL", f"Rejoined {channel}"))
  144.         except Exception as e:
  145.             print(debug_prompt(f"Rejoin failed: {e}"))
  146.  
  147.     def _server_ping_timer(self):
  148.         """Send PING to server every 60 seconds"""
  149.         while self.running:
  150.             try:
  151.                 time.sleep(60)
  152.  
  153.                 if self.master_sock:
  154.                     self.master_sock.send(b'PING :keepalive_60s\r\n')
  155.                     print("🔁 MASTER SERVER PING SENT (60s)")
  156.                 if self.client_sock:
  157.                     self.client_sock.send(b'PING :keepalive_60s\r\n')  
  158.                     print("🔁 CLIENT SERVER PING SENT (60s)")
  159.  
  160.             except Exception as e:
  161.                 print(f"❌ Server ping error: {e}")
  162.  
  163.     def on_connect_actions(self):
  164.         """Execute actions on connect"""
  165.         try:
  166.             self.master_sock.send(b'PRIVMSG www :\x01PING connect_test\x01\r\n')
  167.             self.client_sock.send(b'PRIVMSG deep :\x01PING connect_test\x01\r\n')
  168.             print("🔁 CTCP self-ping on connect")
  169.         except:
  170.             pass
  171.  
  172.     def handle_master_message(self, line):
  173.         """Handle incoming messages untuk master bot"""
  174.         print(f"🔍 MASTER IN: {line}")
  175.  
  176.         # STANDARD IRC SERVER PING RESPONSE
  177.         if line.startswith('PING '):
  178.             ping_data = line.split('PING ')[1]
  179.             pong_msg = f"PONG {ping_data}\r\n"
  180.             self.master_sock.send(pong_msg.encode())
  181.             print(f"🔁 MASTER SERVER PONG: {pong_msg.strip()}")
  182.             return
  183.  
  184.         # STANDARD IRC PING (format lain)
  185.         if line.startswith(':') and ' PING ' in line:
  186.             ping_data = line.split(' PING ')[1]
  187.             self.ping_monitor.log_master_ping(ping_data)
  188.             pong_msg = f"PONG {ping_data}\r\n"
  189.             self.master_sock.send(pong_msg.encode())
  190.             self.ping_monitor.log_master_pong()
  191.             print(f"🔁 MASTER PONG SENT: {pong_msg.strip()}")
  192.             return
  193.  
  194.         # CTCP PING HANDLING
  195.         if '\x01PING' in line and 'PRIVMSG' in line:
  196.             print(f"🔁 MASTER CTCP PING: {line}")
  197.             try:
  198.                 nick = line.split('!')[0][1:]
  199.                 ping_data = line.split('\x01PING ')[1].split('\x01')[0]
  200.                 ctcp_reply = f"NOTICE {nick} :\x01PING {ping_data}\x01\r\n"
  201.                 self.master_sock.send(ctcp_reply.encode())
  202.                 print(f"🔁 MASTER CTCP PONG to {nick}: {ping_data}")
  203.             except Exception as e:
  204.                 print(f"❌ MASTER CTCP error: {e}")
  205.             return
  206.  
  207.         if 'KICK' in line:
  208.             try:
  209.                 parts = line.split(' ')
  210.                 channel = parts[2]
  211.                 kicked_nick = parts[3]
  212.                 if kicked_nick in ['www', 'deep']:
  213.                     print(debug_prompt(f"Bot was kicked from {channel}"))
  214.                     self.rejoin_channel(channel)
  215.             except Exception as e:
  216.                 print(debug_prompt(f"Kick handling error: {e}"))
  217.             return
  218.  
  219.         # 🆕 FIXED: PRIVMSG HANDLING - INI PERLU DI LUAR DARI if 'KICK' block!
  220.         if 'PRIVMSG' in line:
  221.             try:
  222.                 parts = line.split(' ', 3)
  223.                 if len(parts) >= 4:
  224.                     nick = parts[0][1:].split('!')[0]
  225.                     target = parts[2]
  226.                     message = parts[3][1:]
  227.  
  228.                     print(f"🎯 MASTER processing PRIVMSG from {nick}: {message}")
  229.  
  230.                     # GUNA AUTO-FOCUS SYSTEM
  231.                     should_respond = self.should_respond_to_message(nick, target, message, is_master=True)
  232.  
  233.                     if not should_respond:
  234.                         print(f"🛑 MASTER: Skip {nick} (no focus/mention)")
  235.                         return
  236.  
  237.                     print(f"✅ MASTER: Processing message from {nick}")
  238.  
  239.                     # Display dengan prompt system
  240.                     prompt = irc_prompt.get_prompt("www", target)
  241.                     print(f"{prompt}{nick}: {message}")
  242.  
  243.                     # Handle ACTION (/me) messages
  244.                     if message.startswith('\x01ACTION ') and message.endswith('\x01'):
  245.                         action_text = message[8:-1]
  246.                         response = self.events.handle_action(nick, target, action_text, is_master=True)
  247.                         if response:
  248.                             self.send_message_delayed(target, response, is_master=True)
  249.                             irc_prompt.log_interaction("www", nick, message, response)
  250.  
  251.                     # Handle normal PRIVMSG
  252.                     else:
  253.                         response = self.events.handle_privmsg(nick, target, message, is_master=True)
  254.                         print(f"🔧 DEBUG: Response = {response}")
  255.  
  256.                         if response:
  257.                             self.send_message_delayed(target, response, is_master=True)
  258.                             irc_prompt.log_interaction("www", nick, message, response)
  259.  
  260.             except Exception as e:
  261.                 print(debug_prompt(f"Master message error: {e}"))
  262.  
  263.         elif 'NOTICE' in line:
  264.             try:
  265.                 parts = line.split(' ', 3)
  266.                 if len(parts) >= 4:
  267.                     nick = parts[0][1:].split('!')[0]
  268.                     notice_text = parts[3][1:]
  269.  
  270.                     prompt = irc_prompt.get_prompt("www", "NOTICE")
  271.                     print(f"{prompt}From {nick}: {notice_text}")
  272.  
  273.                     response = self.events.handle_notice(nick, notice_text, is_master=True)
  274.                     if response:
  275.                         self.send_message_delayed(nick, response, is_master=True)
  276.             except Exception as e:
  277.                 print(debug_prompt(f"Master notice error: {e}"))
  278.  
  279.     def handle_client_message(self, line):
  280.         """Handle incoming messages untuk client bot"""
  281.         print(f"🔍 CLIENT IN: {line}")
  282.  
  283.         # STANDARD IRC SERVER PING RESPONSE
  284.         if line.startswith('PING '):
  285.             ping_data = line.split('PING ')[1]
  286.             pong_msg = f"PONG {ping_data}\r\n"
  287.             self.client_sock.send(pong_msg.encode())
  288.             print(f"🔁 CLIENT SERVER PONG: {pong_msg.strip()}")
  289.             return
  290.  
  291.         # STANDARD IRC PING (format lain)
  292.         if line.startswith(':') and ' PING ' in line:
  293.             ping_data = line.split(' PING ')[1]
  294.             self.ping_monitor.log_client_ping(ping_data)
  295.             pong_msg = f"PONG {ping_data}\r\n"
  296.             self.client_sock.send(pong_msg.encode())
  297.             self.ping_monitor.log_client_pong()
  298.             print(f"🔁 CLIENT PONG SENT: {pong_msg.strip()}")
  299.             return
  300.  
  301.         # CTCP PING HANDLING
  302.         if '\x01PING' in line and 'PRIVMSG' in line:
  303.             print(f"🔁 CLIENT CTCP PING: {line}")
  304.             try:
  305.                 nick = line.split('!')[0][1:]
  306.                 ping_data = line.split('\x01PING ')[1].split('\x01')[0]
  307.                 ctcp_reply = f"NOTICE {nick} :\x01PING {ping_data}\x01\r\n"
  308.                 self.client_sock.send(ctcp_reply.encode())
  309.                 print(f"🔁 CLIENT CTCP PONG to {nick}: {ping_data}")
  310.             except Exception as e:
  311.                 print(f"❌ CLIENT CTCP error: {e}")
  312.             return
  313.  
  314.         if 'KICK' in line:
  315.             try:
  316.                 parts = line.split(' ')
  317.                 channel = parts[2]
  318.                 kicked_nick = parts[3]
  319.                 if kicked_nick in ['www', 'deep']:
  320.                     print(debug_prompt(f"Bot was kicked from {channel}"))
  321.                     self.rejoin_channel(channel)
  322.             except Exception as e:
  323.                 print(debug_prompt(f"Kick handling error: {e}"))
  324.             return
  325.  
  326.         if 'PRIVMSG' in line:
  327.             try:
  328.                 parts = line.split(' ', 3)
  329.                 if len(parts) >= 4:
  330.                     nick = parts[0][1:].split('!')[0]
  331.                     target = parts[2]
  332.                     message = parts[3][1:]
  333.  
  334.                     print(f"🎯 CLIENT processing PRIVMSG from {nick}: {message}")
  335.  
  336.                     # GUNA AUTO-FOCUS SYSTEM
  337.                     should_respond = self.should_respond_to_message(nick, target, message, is_master=False)
  338.  
  339.                     if not should_respond:
  340.                         print(f"🛑 CLIENT: Skip {nick} (no focus/mention)")
  341.                         return
  342.  
  343.                     print(f"✅ CLIENT: Processing message from {nick}")
  344.  
  345.                     # Display dengan prompt system
  346.                     prompt = irc_prompt.get_prompt("deep", target)
  347.                     print(f"{prompt}{nick}: {message}")
  348.  
  349.                     # Handle ACTION (/me) messages
  350.                     if message.startswith('\x01ACTION ') and message.endswith('\x01'):
  351.                         action_text = message[8:-1]
  352.                         response = self.events.handle_action(nick, target, action_text, is_master=False)
  353.                         if response:
  354.                             self.send_message_delayed(target, response, is_master=False)
  355.                             irc_prompt.log_interaction("deep", nick, message, response)
  356.  
  357.                     # Handle normal PRIVMSG
  358.                     else:
  359.                         response = self.events.handle_privmsg(nick, target, message, is_master=False)
  360.                         print(f"🔧 DEBUG: Response = {response}")
  361.  
  362.                         if response:
  363.                             self.send_message_delayed(target, response, is_master=False)
  364.                             irc_prompt.log_interaction("deep", nick, message, response)
  365.  
  366.             except Exception as e:
  367.                 print(debug_prompt(f"Client message error: {e}"))
  368.  
  369.         elif 'NOTICE' in line:
  370.             try:
  371.                 parts = line.split(' ', 3)
  372.                 if len(parts) >= 4:
  373.                     nick = parts[0][1:].split('!')[0]
  374.                     notice_text = parts[3][1:]
  375.  
  376.                     prompt = irc_prompt.get_prompt("deep", "NOTICE")
  377.                     print(f"{prompt}From {nick}: {notice_text}")
  378.  
  379.                     response = self.events.handle_notice(nick, notice_text, is_master=False)
  380.                     if response:
  381.                         self.send_message_delayed(nick, response, is_master=False)
  382.             except Exception as e:
  383.                 print(debug_prompt(f"Client notice error: {e}"))
  384.  
  385.     def master_loop(self):
  386.         """Main loop untuk master bot"""
  387.         buffer = ""
  388.         while self.running and self.master_sock:
  389.             try:
  390.                 data = self.master_sock.recv(1024).decode('utf-8', errors='ignore')
  391.                 if not data:
  392.                     break
  393.  
  394.                 buffer += data
  395.                 lines = buffer.split('\r\n')
  396.                 buffer = lines.pop()
  397.  
  398.                 for line in lines:
  399.                     line = line.strip()
  400.                     if line:
  401.                         self.handle_master_message(line)
  402.  
  403.             except Exception as e:
  404.                 print(debug_prompt(f"Master loop error: {e}"))
  405.                 break
  406.  
  407.     def client_loop(self):
  408.         """Main loop untuk client bot"""
  409.         buffer = ""
  410.         while self.running and self.client_sock:
  411.             try:
  412.                 data = self.client_sock.recv(1024).decode('utf-8', errors='ignore')
  413.                 if not data:
  414.                     break
  415.  
  416.                 buffer += data
  417.                 lines = buffer.split('\r\n')
  418.                 buffer = lines.pop()
  419.  
  420.                 for line in lines:
  421.                     line = line.strip()
  422.                     if line:
  423.                         self.handle_client_message(line)
  424.  
  425.             except Exception as e:
  426.                 print(debug_prompt(f"Client loop error: {e}"))
  427.                 break
  428.  
  429.     def start(self):
  430.         """Start dual bot system"""
  431.         try:
  432.             print(debug_prompt("Starting Dual Bot..."))
  433.  
  434.             if not self.connect_master():
  435.                 print(debug_prompt("Master connection failed"))
  436.                 return False
  437.  
  438.             if not self.connect_client():
  439.                 print(debug_prompt("Client connection failed"))
  440.                 return False
  441.  
  442.             self.on_connect_actions()
  443.             time.sleep(3)
  444.             self.identify_bots()
  445.             self.join_channels()
  446.  
  447.             print(status_prompt("SYSTEM", "Dual Bot System READY!"))
  448.  
  449.             # Start background modules
  450.             self.time_announcer = TimeAnnouncer(self.master_sock, CHANNELS)
  451.             ping_thread = self.ping_monitor.start()
  452.             time_thread = self.time_announcer.start()
  453.  
  454.             # SERVER PING TIMER (60s)
  455.             server_ping_thread = threading.Thread(target=self._server_ping_timer, daemon=True)
  456.             server_ping_thread.start()
  457.  
  458.             # Start bot loops
  459.             master_thread = threading.Thread(target=self.master_loop, daemon=True)
  460.             client_thread = threading.Thread(target=self.client_loop, daemon=True)
  461.  
  462.             master_thread.start()
  463.             client_thread.start()
  464.  
  465.             while self.running and master_thread.is_alive() and client_thread.is_alive():
  466.                 time.sleep(5)
  467.  
  468.             return True
  469.  
  470.         except Exception as e:
  471.             print(debug_prompt(f"Bot startup failed: {e}"))
  472.             return False
  473.  
  474.     def is_running(self):
  475.         return self.running
  476.  
  477.     def stop(self):
  478.         self.running = False
  479.         try:
  480.             if self.master_sock:
  481.                 self.master_sock.close()
  482.             if self.client_sock:
  483.                 self.client_sock.close()
  484.             self.ping_monitor.stop()
  485.             print(status_prompt("SYSTEM", "Dual Bot stopped"))
  486.         except Exception as e:
  487.             print(debug_prompt(f"Stop error: {e}"))
  488.  
  489. if __name__ == "__main__":
  490.     bot = DualBot()
  491.     bot.start()
Advertisement
Add Comment
Please, Sign In to add comment