From a7de16f7ad765f6e008d535797bf8922df085dbc Mon Sep 17 00:00:00 2001 From: adator <85586985+adator85@users.noreply.github.com> Date: Tue, 17 Sep 2024 00:14:53 +0200 Subject: [PATCH] V5.2.4 multiple changes related to clones --- core/Model.py | 1 + core/base.py | 4 ++-- core/connection.py | 37 +++++++++++++++++++++---------------- core/loadConf.py | 4 ++++ mods/mod_clone.py | 17 ++++++++++------- version.json | 2 +- 6 files changed, 39 insertions(+), 26 deletions(-) diff --git a/core/Model.py b/core/Model.py index e9b5671..18016fc 100644 --- a/core/Model.py +++ b/core/Model.py @@ -414,6 +414,7 @@ class Clones: nickname: str username: str realname: str + vhost: str = None connected: bool = False UID_CLONE_DB: list[CloneModel] = [] diff --git a/core/base.py b/core/base.py index 808e9b6..922ab74 100644 --- a/core/base.py +++ b/core/base.py @@ -429,7 +429,7 @@ class Base: except AssertionError as ae: self.logs.error(f'Assertion Error -> {ae}') - def create_thread(self, func:object, func_args: tuple = (), run_once:bool = False) -> None: + def create_thread(self, func:object, func_args: tuple = (), run_once:bool = False, daemon: bool = True) -> None: """Create a new thread and store it into running_threads variable Args: @@ -445,7 +445,7 @@ class Base: if thread.getName() == func_name: return None - th = threading.Thread(target=func, args=func_args, name=str(func_name), daemon=True) + th = threading.Thread(target=func, args=func_args, name=str(func_name), daemon=daemon) th.start() self.running_threads.append(th) diff --git a/core/connection.py b/core/connection.py index 94a71d9..6fbd559 100644 --- a/core/connection.py +++ b/core/connection.py @@ -15,7 +15,7 @@ class Connection: self.nickname = nickname self.username = username self.realname = realname - self.chanlog = '#clones' + self.clone_chanlog = self.Config.SALON_CLONES self.channels:list[str] = channels self.CHARSET = ['utf-8', 'iso-8859-1'] self.Clones = CloneObject @@ -62,7 +62,7 @@ class Connection: self.Base.logs.critical(f"AttributeError __create_socket: {ae} - {soc.fileno()}") return False - def send2socket(self, send_message:str) -> None: + def send2socket(self, send_message:str, disconnect: bool = False) -> None: """Envoit les commandes à envoyer au serveur. Args: @@ -70,9 +70,8 @@ class Connection: """ try: with self.Base.lock: - # print(f">{str(send_message)}") self.IrcSocket.send(f"{send_message}\r\n".encode(self.CHARSET[0])) - self.Base.logs.debug(f'{send_message}') + self.Base.logs.debug(f'<<{self.currentCloneObject.nickname}>>: {send_message}') except UnicodeDecodeError: self.Base.logs.error(f'Decode Error try iso-8859-1 - message: {send_message}') @@ -114,7 +113,6 @@ class Connection: def connect(self): try: - while self.signal: try: # 4072 max what the socket can grab @@ -132,6 +130,7 @@ class Connection: data = data_in_bytes.splitlines(True) if not data: + # If no data then quit the loop break self.parser(data) @@ -145,10 +144,6 @@ class Connection: self.Base.logs.error(f"OSError __connect_to_irc: {oe} - {data}") self.signal = False - self.IrcSocket.shutdown(socket.SHUT_RDWR) - self.IrcSocket.close() - self.Base.logs.info("--> Clone Disconnected ...") - except AssertionError as ae: self.Base.logs.error(f'Assertion error : {ae}') except ValueError as ve: @@ -159,12 +154,17 @@ class Connection: self.Base.logs.critical(f"{atte}") except Exception as e: self.Base.logs.error(f"Exception: {e}") + finally: + self.IrcSocket.shutdown(socket.SHUT_WR) + self.IrcSocket.shutdown(socket.SHUT_RD) + self.Base.logs.info(f"<<{self.currentCloneObject.nickname}>> Clone Disconnected ...") + # self.IrcSocket.close() def parser(self, cmd:list[bytes]): try: + for data in cmd: response = data.decode(self.CHARSET[0]).split() - self.signal = self.currentCloneObject.alive current_clone_nickname = self.currentCloneObject.nickname # print(response) @@ -176,7 +176,8 @@ class Connection: case 'ERROR': error_value = str(response[1]).replace(':','') if error_value == 'Closing': - self.signal = False + self.Base.logs.info(f"<<{self.currentCloneObject.nickname}>> {response} ...") + # self.signal = False match response[1]: case '376': @@ -184,17 +185,22 @@ class Connection: self.currentCloneObject.connected = True for channel in self.channels: self.send2socket(f"JOIN {channel}") + + self.send2socket(f"JOIN {self.clone_chanlog}") + return None case '422': # Missing MOTD self.currentCloneObject.connected = True for channel in self.channels: self.send2socket(f"JOIN {channel}") + + self.send2socket(f"JOIN {self.clone_chanlog}") return None case 'PRIVMSG': - self.Base.logs.debug(response) - self.Base.logs.debug(f'{self.currentCloneObject.nickname} - {self.currentCloneObject.alive}') + self.Base.logs.debug(f'<<{self.currentCloneObject.nickname}>> Response: {response}') + self.Base.logs.debug(f'<<{self.currentCloneObject.nickname}>> Alive: {self.currentCloneObject.alive}') fullname = str(response[0]).replace(':', '') nickname = fullname.split('!')[0].replace(':','') @@ -203,14 +209,13 @@ class Connection: for i in range(3, len(response)): message.append(response[i]) final_message = ' '.join(message) - self.send2socket(f"PRIVMSG {self.chanlog} :{fullname} => {final_message[1:]}") + self.send2socket(f"PRIVMSG {self.clone_chanlog} :{fullname} => {final_message[1:]}") if nickname == self.Config.SERVICE_NICKNAME: command = str(response[3]).replace(':','') if command == 'KILL': - self.send2socket(f'QUIT :Thanks and goodbye') - self.signal = self.currentCloneObject.alive + self.send2socket(f'QUIT :Thanks and goodbye', disconnect=True) if command == 'JOIN': channel_to_join = str(response[4]) diff --git a/core/loadConf.py b/core/loadConf.py index e6b676d..d43d1b2 100644 --- a/core/loadConf.py +++ b/core/loadConf.py @@ -82,6 +82,9 @@ class ConfigDataModel: SALON_LIBERER: str """Channel where the nickname will be released""" + SALON_CLONES: str + """Channel to host clones""" + API_TIMEOUT: int """Default api timeout in second""" @@ -184,6 +187,7 @@ class Config: SALON_JAIL=import_config["SALON_JAIL"], SALON_JAIL_MODES=import_config["SALON_JAIL_MODES"], SALON_LIBERER=import_config["SALON_LIBERER"], + SALON_CLONES=import_config["SALON_CLONES"], API_TIMEOUT=import_config["API_TIMEOUT"], PORTS_TO_SCAN=import_config["PORTS_TO_SCAN"], WHITELISTED_IP=import_config["WHITELISTED_IP"], diff --git a/mods/mod_clone.py b/mods/mod_clone.py index 2cd75ad..410eb11 100644 --- a/mods/mod_clone.py +++ b/mods/mod_clone.py @@ -126,6 +126,9 @@ class Clone(): fake = faker.Faker('en_GB') for clone in self.Clone.UID_CLONE_DB: + if not clone.vhost is None: + continue + rand_1 = fake.random_elements(['A','B','C','D','E','F','0','1','2','3','4','5','6','7','8','9'], unique=True, length=8) rand_2 = fake.random_elements(['A','B','C','D','E','F','0','1','2','3','4','5','6','7','8','9'], unique=True, length=8) rand_3 = fake.random_elements(['A','B','C','D','E','F','0','1','2','3','4','5','6','7','8','9'], unique=True, length=8) @@ -137,6 +140,7 @@ class Clone(): if clone.connected: self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} CHGHOST {clone.nickname} {rand_ip}') found = True + clone.vhost = rand_ip break def thread_create_clones(self, nickname: str, username: str, realname: str, channels: list, server_port: int, ssl: bool) -> None: @@ -146,16 +150,16 @@ class Clone(): return None def thread_join_channels(self, channel_name: str, wait: float, clone_name:str = None): - + self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Clones start to join {channel_name} with {wait} secondes frequency') if clone_name is None: for clone in self.Clone.UID_CLONE_DB: - self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone.nickname} :JOIN {channel_name}') time.sleep(wait) + self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone.nickname} :JOIN {channel_name}') else: for clone in self.Clone.UID_CLONE_DB: if clone_name == clone.nickname: - self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone.nickname} :JOIN {channel_name}') time.sleep(wait) + self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone.nickname} :JOIN {channel_name}') def generate_names(self) -> tuple[str, str, str]: try: @@ -237,14 +241,13 @@ class Clone(): nickname, username, realname = self.generate_names() self.Base.create_thread( self.thread_create_clones, - (nickname, username, realname, ['#clones'], 6697, True) + (nickname, username, realname, [], 6697, True) ) self.Base.create_thread( - self.thread_change_hostname, - run_once=True + self.thread_change_hostname ) - + self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :{str(number_of_clones)} clones joined the network') except Exception as err: diff --git a/version.json b/version.json index 1137156..cc238b3 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "5.2.3" + "version": "5.2.4" } \ No newline at end of file