From ff603ab2a4561b8d6ca764076620a5f2be4aad59 Mon Sep 17 00:00:00 2001 From: adator <85586985+adator85@users.noreply.github.com> Date: Sun, 22 Sep 2024 16:20:02 +0200 Subject: [PATCH] V5.3.0 --- README.md | 32 +++++-------- core/connection.py | 32 ++++++++++--- core/exemple_configuration.json | 40 +++++++--------- core/irc.py | 74 ++++++++++++++++++++++------- core/loadConf.py | 66 +++++++++++++------------- mods/mod_clone.py | 17 ++++++- mods/mod_defender.py | 84 ++++++++++++++++----------------- mods/mod_votekick.py | 8 ++-- version.json | 2 +- 9 files changed, 204 insertions(+), 151 deletions(-) diff --git a/README.md b/README.md index ec8e033..1166ff9 100644 --- a/README.md +++ b/README.md @@ -102,8 +102,6 @@ Pour Les prochains lancement de defender vous devez utiliser la commande suivant DEBUG (Debug) DEBUG_LEVEL: Niveau de verbosité des messages de debug (plus grand est le nombre, plus il y a d'informations). (default : 20) Pour une production - COULEURS (Couleurs) - CONFIG_COLOR: Dictionnaire contenant des codes de couleurs IRC pour un meilleur affichage des messages. ``` Modification de la configuration @@ -121,13 +119,13 @@ Pour Les prochains lancement de defender vous devez utiliser la commande suivant "SERVEUR_SSL": true, "SERVICE_NAME": "defender", - "SERVICE_NICKNAME": "Dev-PyDefender", + "SERVICE_NICKNAME": "PyDefender", "SERVICE_REALNAME": "Python Defender Security", - "SERVICE_USERNAME": "Dev-PyDefender", + "SERVICE_USERNAME": "PyDefender", "SERVICE_HOST": "HOST.DE.TON.DEFENDER", "OWNER": "TON_NICK_NAME", - "PASSWORD": "admin" + "PASSWORD": "TON_PASSWORD" } @@ -145,9 +143,9 @@ Pour Les prochains lancement de defender vous devez utiliser la commande suivant "SERVEUR_SSL": true, "SERVICE_NAME": "defender", - "SERVICE_NICKNAME": "Dev-PyDefender", + "SERVICE_NICKNAME": "PyDefender", "SERVICE_REALNAME": "Python Defender Security", - "SERVICE_USERNAME": "Dev-PyDefender", + "SERVICE_USERNAME": "PyDefender", "SERVICE_HOST": "HOST.DE.TON.DEFENDER", "SERVICE_INFO": "Network IRC Service", "SERVICE_CHANLOG": "#services", @@ -157,13 +155,16 @@ Pour Les prochains lancement de defender vous devez utiliser la commande suivant "SERVICE_PREFIX": "!", "OWNER": "TON_NICK_NAME", - "PASSWORD": "admin", + "PASSWORD": "TON_PASSWORD", "SALON_JAIL": "#jail", "SALON_JAIL_MODES": "sS", "SALON_LIBERER": "#welcome", - "SALON_CLONES": "#clones", + "CLONE_CHANNEL": "#clones", + "CLONE_CMODES": "+nts", + "CLONE_LOG_HOST_EXEMPT": ["HOST.TO.SKIP"], + "CLONE_CHANNEL_PASSWORD": "YOUR_CHANNEL_PASSWORD", "API_TIMEOUT": 2, @@ -171,18 +172,7 @@ Pour Les prochains lancement de defender vous devez utiliser la commande suivant "WHITELISTED_IP": ["127.0.0.1"], "GLINE_DURATION": "30", - "DEBUG_LEVEL": 10, - - "CONFIG_COLOR": { - "blanche": "\\u0003\\u0030", - "noire": "\\u0003\\u0031", - "bleue": "\\u0003\\u0020", - "verte": "\\u0003\\u0033", - "rouge": "\\u0003\\u0034", - "jaune": "\\u0003\\u0036", - "gras": "\\u0002", - "nogc": "\\u0002\\u0003" - } + "DEBUG_LEVEL": 20 } ``` diff --git a/core/connection.py b/core/connection.py index 6b9c281..4aca76c 100644 --- a/core/connection.py +++ b/core/connection.py @@ -1,4 +1,6 @@ -import socket, ssl +import socket +import ssl +import traceback from ssl import SSLSocket from core.loadConf import Config from core.Model import Clones @@ -15,7 +17,8 @@ class Connection: self.nickname = nickname self.username = username self.realname = realname - self.clone_chanlog = self.Config.SALON_CLONES + self.clone_chanlog = self.Config.CLONE_CHANNEL + self.clone_log_exempt = self.Config.CLONE_LOG_HOST_EXEMPT self.channels:list[str] = channels self.CHARSET = ['utf-8', 'iso-8859-1'] self.Clones = CloneObject @@ -157,6 +160,7 @@ class Connection: self.Base.logs.error(f"OS Error __connect_to_irc: {soe}") except AttributeError as atte: self.Base.logs.critical(f"{atte}") + self.Base.logs.critical(f"{traceback.format_exc()}") except Exception as e: self.Base.logs.error(f"Exception: {e}") @@ -190,9 +194,10 @@ class Connection: for channel in self.channels: self.send2socket(f"JOIN {channel}") - self.send2socket(f"JOIN {self.clone_chanlog}") + self.send2socket(f"JOIN {self.clone_chanlog} {self.Config.CLONE_CHANNEL_PASSWORD}") return None + case '422': # Missing MOTD self.currentCloneObject.connected = True @@ -200,7 +205,15 @@ class Connection: for channel in self.channels: self.send2socket(f"JOIN {channel}") - self.send2socket(f"JOIN {self.clone_chanlog}") + self.send2socket(f"JOIN {self.clone_chanlog} {self.Config.CLONE_CHANNEL_PASSWORD}") + return None + + case '433': + # Nickname already in use + self.currentCloneObject.connected = False + self.currentCloneObject.init = False + self.send2socket(f'QUIT :Thanks and goodbye') + self.Base.logs.warning(f"Nickname {self.currentCloneObject.nickname} already in use >> Clone should be disconnected") return None case 'PRIVMSG': @@ -214,13 +227,20 @@ class Connection: for i in range(3, len(response)): message.append(response[i]) final_message = ' '.join(message) - self.send2socket(f"PRIVMSG {self.clone_chanlog} :{fullname} => {final_message[1:]}") + + exampt = False + for log_exception in self.clone_log_exempt: + if log_exception in fullname: + exampt = True + + if not exampt: + 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', disconnect=True) + self.send2socket(f'QUIT :Thanks and goodbye') if command == 'JOIN': channel_to_join = str(response[4]) diff --git a/core/exemple_configuration.json b/core/exemple_configuration.json index 951edcf..05b77c6 100644 --- a/core/exemple_configuration.json +++ b/core/exemple_configuration.json @@ -1,48 +1,42 @@ { - "SERVEUR_IP": "0.0.0.0", - "SERVEUR_HOSTNAME": "your.host.name", - "SERVEUR_LINK": "your.link.to.server", + "SERVEUR_IP": "YOUR.SERVER.IP", + "SERVEUR_HOSTNAME": "YOUR.SERVER.HOST", + "SERVEUR_LINK": "LINK.DE.TON.SERVER", "SERVEUR_PORT": 7002, - "SERVEUR_PASSWORD": "link_password", + "SERVEUR_PASSWORD": "YOUR_LINK_PASSWORD", "SERVEUR_ID": "006", "SERVEUR_SSL": true, "SERVICE_NAME": "defender", - "SERVICE_NICKNAME": "BotNickname", - "SERVICE_REALNAME": "BotRealname", - "SERVICE_USERNAME": "BotUsername", - "SERVICE_HOST": "your.service.hostname", + "SERVICE_NICKNAME": "PyDefender", + "SERVICE_REALNAME": "Python Defender Security", + "SERVICE_USERNAME": "PyDefender", + "SERVICE_HOST": "HOST.DE.TON.DEFENDER", "SERVICE_INFO": "Network IRC Service", "SERVICE_CHANLOG": "#services", "SERVICE_SMODES": "+ioqBS", - "SERVICE_CMODES": "ntsO", + "SERVICE_CMODES": "ntsOP", "SERVICE_UMODES": "o", "SERVICE_PREFIX": "!", - "OWNER": "admin", - "PASSWORD": "password", + "OWNER": "TON_NICK_NAME", + "PASSWORD": "TON_PASSWORD", "SALON_JAIL": "#jail", "SALON_JAIL_MODES": "sS", "SALON_LIBERER": "#welcome", + "CLONE_CHANNEL": "#clones", + "CLONE_CMODES": "+nts", + "CLONE_LOG_HOST_EXEMPT": ["HOST.TO.SKIP"], + "CLONE_CHANNEL_PASSWORD": "YOUR_CHANNEL_PASSWORD", + "API_TIMEOUT": 2, "PORTS_TO_SCAN": [3028, 8080, 1080, 1085, 4145, 9050], "WHITELISTED_IP": ["127.0.0.1"], "GLINE_DURATION": "30", - "DEBUG_LEVEL": 20, - - "CONFIG_COLOR": { - "blanche": "\\u0003\\u0030", - "noire": "\\u0003\\u0031", - "bleue": "\\u0003\\u0020", - "verte": "\\u0003\\u0033", - "rouge": "\\u0003\\u0034", - "jaune": "\\u0003\\u0036", - "gras": "\\u0002", - "nogc": "\\u0002\\u0003" - } + "DEBUG_LEVEL": 20 } \ No newline at end of file diff --git a/core/irc.py b/core/irc.py index 45c0333..df478ca 100644 --- a/core/irc.py +++ b/core/irc.py @@ -175,8 +175,8 @@ class Irc: except AttributeError as atte: self.Base.logs.critical(f"AttributeError: {atte}") except Exception as e: - self.Base.logs.critical(f"Exception: {e}") - self.Base.logs.critical(traceback.print_exc()) + self.Base.logs.critical(f"General Error: {e}") + self.Base.logs.critical(traceback.format_exc()) def __link(self, writer:Union[socket.socket, SSLSocket]) -> None: """Créer le link et envoyer les informations nécessaires pour la @@ -222,7 +222,7 @@ class Irc: writer.send(f":{service_id} MODE {chan} +{cmodes}\r\n".encode(charset)) writer.send(f":{service_id} MODE {chan} +{umodes} {service_id}\r\n".encode(charset)) - self.Base.logs.debug('Link information sent to the server') + self.Base.logs.debug('>> Link information sent to the server') return None except AttributeError as ae: @@ -249,7 +249,6 @@ class Irc: """ 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}') @@ -268,6 +267,41 @@ class Irc: except OSError as oe: self.Base.logs.error(f"OSError: {oe} - {send_message}") + def sendNotice(self, msg:str, nickname: str) -> None: + """Sending NOTICE by batches + + Args: + msg (str): The message to send to the server + nickname (str): The reciever Nickname + """ + batch_size = self.Config.BATCH_SIZE + service_nickname = self.Config.SERVICE_NICKNAME + + for i in range(0, len(str(msg)), batch_size): + batch = str(msg)[i:i+batch_size] + self.send2socket(f":{service_nickname} NOTICE {nickname} :{batch}") + + def sendPrivMsg(self, msg: str, channel: str = None, nickname: str = None): + """Sending PRIVMSG to a channel or to a nickname by batches + could be either channel or nickname not both together + Args: + msg (str): The message to send + channel (str, optional): The receiver channel. Defaults to None. + nickname (str, optional): The reciever nickname. Defaults to None. + """ + batch_size = self.Config.BATCH_SIZE + service_nickname = self.Config.SERVICE_NICKNAME + + if not channel is None: + for i in range(0, len(str(msg)), batch_size): + batch = str(msg)[i:i+batch_size] + self.send2socket(f":{service_nickname} PRIVMSG {channel} :{batch}") + + if not nickname is None: + for i in range(0, len(str(msg)), batch_size): + batch = str(msg)[i:i+batch_size] + self.send2socket(f":{service_nickname} PRIVMSG {nickname} :{batch}") + def send_response(self, responses:list[bytes]) -> None: try: # print(data) @@ -452,11 +486,11 @@ class Irc: except ModuleNotFoundError as moduleNotFound: self.Base.logs.error(f"MODULE_NOT_FOUND: {moduleNotFound}") - self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.CONFIG_COLOR['rouge']}MODULE_NOT_FOUND{self.Config.CONFIG_COLOR['noire']} ]: {moduleNotFound}") + self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.COLORS.red}MODULE_NOT_FOUND{self.Config.COLORS.black} ]: {moduleNotFound}") self.Base.db_delete_module(module_name) except Exception as e: self.Base.logs.error(f"Something went wrong with a module you want to load : {e}") - self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.CONFIG_COLOR['rouge']}ERROR{self.Config.CONFIG_COLOR['noire']} ]: {e}") + self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.COLORS.red}ERROR{self.Config.COLORS.black} ]: {e}") def insert_db_admin(self, uid:str, level:int) -> None: @@ -752,6 +786,7 @@ class Irc: self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} : New Version available {version}") # Initialisation terminé aprés le premier PING + self.sendPrivMsg(msg=f'[{self.Config.COLORS.green}INFORMATION{self.Config.COLORS.nogc}] >> Defender is ready', channel='#devservices') self.INIT = 0 case _: @@ -991,6 +1026,9 @@ class Irc: except IndexError as ie: self.Base.logs.error(f"{ie} / {original_response} / length {str(len(original_response))}") + except Exception as err: + self.Base.logs.error(f"General Error: {err}") + self.Base.logs.error(f"General Error: {traceback.format_exc()}") def _hcmds(self, user: str, channel: Union[str, None], cmd: list, fullcmd: list = []) -> None: """_summary_ @@ -1031,7 +1069,7 @@ class Irc: case 'notallowed': try: current_command = cmd[0] - self.send2socket(f':{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR["rouge"]}{current_command}{self.Config.CONFIG_COLOR["noire"]} ] - Accès Refusé à {self.User.get_nickname(fromuser)}') + self.send2socket(f':{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.red}{current_command}{self.Config.COLORS.black} ] - Accès Refusé à {self.User.get_nickname(fromuser)}') self.send2socket(f':{dnickname} NOTICE {fromuser} : Accès Refusé') except IndexError as ie: self.Base.logs.error(f'{ie}') @@ -1041,7 +1079,7 @@ class Irc: current_command = cmd[0] uid_to_deauth = self.User.get_uid(fromuser) self.delete_db_admin(uid_to_deauth) - self.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['rouge']}{str(current_command).upper()} ]{self.Config.CONFIG_COLOR['noire']} - {self.User.get_nickname(fromuser)} est désormais déconnecter de {dnickname}") + self.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.red}{str(current_command).upper()} ]{self.Config.COLORS.black} - {self.User.get_nickname(fromuser)} est désormais déconnecter de {dnickname}") case 'firstauth': # firstauth OWNER_NICKNAME OWNER_PASSWORD @@ -1087,10 +1125,10 @@ class Irc: if cmd_owner == config_owner and cmd_password == config_password: self.Base.db_create_first_admin() self.insert_db_admin(current_uid, 5) - self.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}{str(current_command).upper()} ]{self.Config.CONFIG_COLOR['noire']} - {self.User.get_nickname(fromuser)} est désormais connecté a {dnickname}") + self.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}{str(current_command).upper()} ]{self.Config.COLORS.black} - {self.User.get_nickname(fromuser)} est désormais connecté a {dnickname}") self.send2socket(f":{self.Config.SERVICE_NICKNAME} NOTICE {fromuser} :Connexion a {dnickname} réussie!") else: - self.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['rouge']}{str(current_command).upper()} ]{self.Config.CONFIG_COLOR['noire']} - {self.User.get_nickname(fromuser)} a tapé un mauvais mot de pass") + self.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.red}{str(current_command).upper()} ]{self.Config.COLORS.black} - {self.User.get_nickname(fromuser)} a tapé un mauvais mot de pass") self.send2socket(f":{self.Config.SERVICE_NICKNAME} NOTICE {fromuser} :Mot de passe incorrecte") case 'auth': @@ -1113,10 +1151,10 @@ class Irc: if not user_from_db is None: uid_user = self.User.get_uid(user_to_log) self.insert_db_admin(uid_user, user_from_db[1]) - self.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}{str(current_command).upper()} ]{self.Config.CONFIG_COLOR['noire']} - {self.User.get_nickname(fromuser)} est désormais connecté a {dnickname}") + self.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}{str(current_command).upper()} ]{self.Config.COLORS.black} - {self.User.get_nickname(fromuser)} est désormais connecté a {dnickname}") self.send2socket(f":{self.Config.SERVICE_NICKNAME} NOTICE {fromuser} :Connexion a {dnickname} réussie!") else: - self.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['rouge']}{str(current_command).upper()} ]{self.Config.CONFIG_COLOR['noire']} - {self.User.get_nickname(fromuser)} a tapé un mauvais mot de pass") + self.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.red}{str(current_command).upper()} ]{self.Config.COLORS.black} - {self.User.get_nickname(fromuser)} a tapé un mauvais mot de pass") self.send2socket(f":{self.Config.SERVICE_NICKNAME} NOTICE {fromuser} :Mot de passe incorrecte") else: @@ -1255,13 +1293,13 @@ class Irc: else: user_level = 0 - self.send2socket(f':{dnickname} NOTICE {fromuser} : **************** LIST DES COMMANDES *****************') + self.send2socket(f':{dnickname} NOTICE {fromuser} : ***************** LISTE DES COMMANDES *****************') self.send2socket(f':{dnickname} NOTICE {fromuser} : ') for levDef in self.commands_level: - + if int(user_level) >= int(count_level_definition): - self.send2socket(f':{dnickname} NOTICE {fromuser} : **************** {self.Config.CONFIG_COLOR["noire"]}[ {self.Config.CONFIG_COLOR["verte"]}LEVEL {str(levDef)} {self.Config.CONFIG_COLOR["noire"]}] ****************') + self.send2socket(f':{dnickname} NOTICE {fromuser} : ***************** {self.Config.COLORS.nogc}[ {self.Config.COLORS.green}LEVEL {str(levDef)} {self.Config.COLORS.nogc}] *****************') count_commands = 0 help = '' for comm in self.commands_level[count_level_definition]: @@ -1275,7 +1313,7 @@ class Irc: count_level_definition += 1 - self.send2socket(f':{dnickname} NOTICE {fromuser} : **************** FIN DES COMMANDES *****************') + self.send2socket(f':{dnickname} NOTICE {fromuser} : ***************** FIN DES COMMANDES *****************') case 'load': @@ -1411,9 +1449,9 @@ class Irc: found = True if found: - self.send2socket(f":{dnickname} NOTICE {fromuser} :{module} - {self.Config.CONFIG_COLOR['verte']}Loaded{self.Config.CONFIG_COLOR['nogc']}") + self.send2socket(f":{dnickname} NOTICE {fromuser} :{module} - {self.Config.COLORS.green}Loaded{self.Config.COLORS.nogc}") else: - self.send2socket(f":{dnickname} NOTICE {fromuser} :{module} - {self.Config.CONFIG_COLOR['rouge']}Not Loaded{self.Config.CONFIG_COLOR['nogc']}") + self.send2socket(f":{dnickname} NOTICE {fromuser} :{module} - {self.Config.COLORS.red}Not Loaded{self.Config.COLORS.nogc}") found = False diff --git a/core/loadConf.py b/core/loadConf.py index a7b4a2d..94f3369 100644 --- a/core/loadConf.py +++ b/core/loadConf.py @@ -7,6 +7,17 @@ from dataclasses import dataclass, field # CONFIGURATION FILE # ########################################## +@dataclass +class ColorModel: + white: str = "\x0300" + black: str = "\x0301" + blue: str = "\x0302" + green: str = "\x0303" + red: str = "\x0304" + yellow: str = "\x0306" + bold: str = "\x02" + nogc: str = "\x03" + @dataclass class ConfigDataModel: @@ -82,8 +93,17 @@ class ConfigDataModel: SALON_LIBERER: str """Channel where the nickname will be released""" - SALON_CLONES: str - """Channel to host clones""" + CLONE_CHANNEL: str + """Channel where clones are hosted and will log PRIVMSG""" + + CLONE_CMODES: str + """Clone channel modes""" + + CLONE_LOG_HOST_EXEMPT: list[str] + """Hosts that clones will not log""" + + CLONE_CHANNEL_PASSWORD: str + """Clone password channel""" API_TIMEOUT: int """Default api timeout in second""" @@ -100,8 +120,6 @@ class ConfigDataModel: DEBUG_LEVEL:Literal[10, 20, 30, 40, 50] """Logs level: DEBUG 10 | INFO 20 | WARNING 30 | ERROR 40 | CRITICAL 50""" - CONFIG_COLOR: dict[str, str] - table_admin: str """Admin table""" @@ -132,6 +150,12 @@ class ConfigDataModel: db_path: str """The database path""" + COLORS: ColorModel = ColorModel() + """Available colors in Defender""" + + BATCH_SIZE: int = 400 + """The batch size used for privmsg and notice""" + def __post_init__(self): # Initialiser SERVICE_ID après la création de l'objet self.SERVICE_ID:str = f"{self.SERVEUR_ID}AAAAAB" @@ -150,34 +174,6 @@ class Config: with open(conf_filename, 'r') as configuration_data: configuration:dict[str, Union[str, int, list, dict]] = json.load(configuration_data) - config_dict = {"CONFIG_COLOR" : { - "blanche": "\x0300", - "noire": "\x0301", - "bleue": "\x0302", - "verte": "\x0303", - "rouge": "\x0304", - "jaune": "\x0306", - "gras": "\x02", - "nogc": "\x02\x03" - } - } - - missing_color = False - - if not "CONFIG_COLOR" in configuration: - missing_color = True - configuration_color = config_dict - else: - configuration_color = configuration["CONFIG_COLOR"] - - if missing_color: - for key, value in configuration_color.items(): - configuration_color['CONFIG_COLOR'][key] = str(value).encode('utf-8').decode('unicode_escape') - configuration['CONFIG_COLOR'] = configuration_color['CONFIG_COLOR'] - else: - for key, value in configuration['CONFIG_COLOR'].items(): - configuration['CONFIG_COLOR'][key] = str(value).encode('utf-8').decode('unicode_escape') - return configuration except FileNotFoundError as fe: @@ -215,13 +211,15 @@ class Config: SALON_JAIL=import_config["SALON_JAIL"] if "SALON_JAIL" in import_config else '#jail', SALON_JAIL_MODES=import_config["SALON_JAIL_MODES"] if "SALON_JAIL_MODES" in import_config else 'sS', SALON_LIBERER=import_config["SALON_LIBERER"] if "SALON_LIBERER" in import_config else '#welcome', - SALON_CLONES=import_config["SALON_CLONES"] if "SALON_CLONES" in import_config else '#clones', + CLONE_CHANNEL=import_config["CLONE_CHANNEL"] if "CLONE_CHANNEL" in import_config else '#clones', + CLONE_CMODES=import_config["CLONE_CMODES"] if "CLONE_CMODES" in import_config else '+nts', + CLONE_LOG_HOST_EXEMPT=import_config["CLONE_LOG_HOST_EXEMPT"] if "CLONE_LOG_HOST_EXEMPT" in import_config else [], + CLONE_CHANNEL_PASSWORD=import_config["CLONE_CHANNEL_PASSWORD"] if "CLONE_CHANNEL_PASSWORD" in import_config else "clone_Password_1234", API_TIMEOUT=import_config["API_TIMEOUT"] if "API_TIMEOUT" in import_config else 2, PORTS_TO_SCAN=import_config["PORTS_TO_SCAN"] if "PORTS_TO_SCAN" in import_config else [], WHITELISTED_IP=import_config["WHITELISTED_IP"] if "WHITELISTED_IP" in import_config else ['127.0.0.1'], GLINE_DURATION=import_config["GLINE_DURATION"] if "GLINE_DURATION" in import_config else '30', DEBUG_LEVEL=import_config["DEBUG_LEVEL"] if "DEBUG_LEVEL" in import_config else 20, - CONFIG_COLOR=import_config["CONFIG_COLOR"], table_admin='core_admin', table_commande='core_command', table_log='core_log', diff --git a/mods/mod_clone.py b/mods/mod_clone.py index a8a2129..6c3c8fb 100644 --- a/mods/mod_clone.py +++ b/mods/mod_clone.py @@ -58,6 +58,11 @@ class Clone(): # Load module configuration (Mandatory) self.__load_module_configuration() + self.Base.db_query_channel(action='add', module_name=self.module_name, channel_name=self.Config.CLONE_CHANNEL) + self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} JOIN {self.Config.CLONE_CHANNEL}") + self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} MODE {self.Config.CLONE_CHANNEL} +nts") + self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} MODE {self.Config.CLONE_CHANNEL} +k {self.Config.CLONE_CHANNEL_PASSWORD}") + def __set_commands(self, commands:dict[int, list[str]]) -> None: """### Rajoute les commandes du module au programme principal @@ -120,6 +125,8 @@ class Clone(): for clone in self.ModConfig.clone_nicknames: self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone} :KILL') + self.Base.db_query_channel(action='del', module_name=self.module_name, channel_name=self.Config.CLONE_CHANNEL) + self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} PART {self.Config.CLONE_CHANNEL}") return None def thread_clone_clean_up(self, wait: float): @@ -139,6 +146,11 @@ class Clone(): self.Logs.debug(f'<<{clone_nickname}>> object has been deleted') del clone_to_kill + + # If LIST empty then stop this thread + if not self.Clone.UID_CLONE_DB: + break + time.sleep(wait) def thread_change_hostname(self): @@ -166,7 +178,7 @@ class Clone(): break def thread_create_clones_with_interval(self, number_of_clones:int, channels: list, connection_interval: float): - + for i in range(number_of_clones): nickname, username, realname = self.generate_names() self.Base.create_thread( @@ -289,6 +301,7 @@ class Clone(): case 'connect': try: + # clone connect 5 number_of_clones = int(cmd[2]) connection_interval = int(cmd[3]) if len(cmd) == 4 else 0.5 self.Base.create_thread( @@ -350,7 +363,7 @@ class Clone(): clone_count = len(self.Clone.UID_CLONE_DB) self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :>> Number of connected clones: {clone_count}') for clone_name in self.Clone.UID_CLONE_DB: - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :>> Nickname: {clone_name.nickname} | Username: {clone_name.username} | Realname: {clone_name.realname} | Vhost: {clone_name.vhost} | Connected: {clone_name.connected}') + self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :>> Nickname: {clone_name.nickname} | Username: {clone_name.username} | Realname: {clone_name.realname} | Vhost: {clone_name.vhost} | Init: {clone_name.init} | Live: {clone_name.alive} | Connected: {clone_name.connected}') except Exception as err: self.Logs.error(f'{err}') diff --git a/mods/mod_defender.py b/mods/mod_defender.py index 9286d33..3dc5f2b 100644 --- a/mods/mod_defender.py +++ b/mods/mod_defender.py @@ -441,9 +441,9 @@ class Defender(): jailed_nickname = get_reputation.nickname jailed_score = get_reputation.score - color_red = self.Config.CONFIG_COLOR['rouge'] - color_black = self.Config.CONFIG_COLOR['noire'] - color_bold = self.Config.CONFIG_COLOR['gras'] + color_red = self.Config.COLORS.red + color_black = self.Config.COLORS.black + color_bold = self.Config.COLORS.bold service_id = self.Config.SERVICE_ID service_prefix = self.Config.SERVICE_PREFIX reputation_ban_all_chan = self.ModConfig.reputation_ban_all_chan @@ -478,8 +478,8 @@ class Defender(): ban_all_chan = self.ModConfig.reputation_ban_all_chan service_id = self.Config.SERVICE_ID dchanlog = self.Config.SERVICE_CHANLOG - color_red = self.Config.CONFIG_COLOR['rouge'] - color_black = self.Config.CONFIG_COLOR['noire'] + color_red = self.Config.COLORS.red + color_black = self.Config.COLORS.black salon_jail = self.Config.SALON_JAIL if reputation_flag == 0: @@ -559,8 +559,8 @@ class Defender(): flood_timer = self.ModConfig.flood_timer service_id = self.Config.SERVICE_ID dnickname = self.Config.SERVICE_NICKNAME - color_red = self.Config.CONFIG_COLOR['rouge'] - color_bold = self.Config.CONFIG_COLOR['gras'] + color_red = self.Config.COLORS.red + color_bold = self.Config.COLORS.bold get_detected_uid = self.User.get_uid(detected_user) get_detected_nickname = self.User.get_nickname(detected_user) @@ -634,7 +634,7 @@ class Defender(): connection = (remote_ip, self.Base.int_if_possible(port)) newSocket.connect(connection) - self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.CONFIG_COLOR['rouge']}PROXY_SCAN{self.Config.CONFIG_COLOR['noire']} ] {fullname} ({remote_ip}) : Port [{str(port)}] ouvert sur l'adresse ip [{remote_ip}]") + self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.COLORS.red}PROXY_SCAN{self.Config.COLORS.black} ] {fullname} ({remote_ip}) : Port [{str(port)}] ouvert sur l'adresse ip [{remote_ip}]") # print(f"=======> Le port {str(port)} est ouvert !!") self.Base.running_sockets.append(newSocket) # print(newSocket) @@ -697,7 +697,7 @@ class Defender(): self.Logs.info(f"Connexion of {fullname} ({remote_ip}) using ports : {str(matching_ports)}") if matching_ports: - self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.CONFIG_COLOR['rouge']}PSUTIL_SCAN{self.Config.CONFIG_COLOR['noire']} ] {fullname} ({remote_ip}) : is using ports {matching_ports}") + self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.COLORS.red}PSUTIL_SCAN{self.Config.COLORS.black} ] {fullname} ({remote_ip}) : is using ports {matching_ports}") return matching_ports @@ -777,8 +777,8 @@ class Defender(): service_id = self.Config.SERVICE_ID service_chanlog = self.Config.SERVICE_CHANLOG - color_red = self.Config.CONFIG_COLOR['rouge'] - color_black = self.Config.CONFIG_COLOR['noire'] + color_red = self.Config.COLORS.red + color_black = self.Config.COLORS.black # pseudo!ident@host fullname = f'{nickname}!{username}@{hostname}' @@ -845,8 +845,8 @@ class Defender(): service_id = self.Config.SERVICE_ID service_chanlog = self.Config.SERVICE_CHANLOG - color_red = self.Config.CONFIG_COLOR['rouge'] - color_black = self.Config.CONFIG_COLOR['noire'] + color_red = self.Config.COLORS.red + color_black = self.Config.COLORS.black url = f'https://freeipapi.com/api/json/{remote_ip}' @@ -933,8 +933,8 @@ class Defender(): service_id = self.Config.SERVICE_ID service_chanlog = self.Config.SERVICE_CHANLOG - color_red = self.Config.CONFIG_COLOR['rouge'] - color_black = self.Config.CONFIG_COLOR['noire'] + color_red = self.Config.COLORS.red + color_black = self.Config.COLORS.black url = f"https://developers18334.cloudfilt.com/" @@ -1233,8 +1233,8 @@ class Defender(): self.Logs.debug(f"IP de {jailed_nickname} : {jailed_IP}") link = self.Config.SERVEUR_LINK - color_green = self.Config.CONFIG_COLOR['verte'] - color_black = self.Config.CONFIG_COLOR['noire'] + color_green = self.Config.COLORS.green + color_black = self.Config.COLORS.black if release_code == get_reputation.secret_code: self.Irc.send2socket(f':{dnickname} PRIVMSG {jailed_salon} : Bon mot de passe. Allez du vent !') @@ -1278,13 +1278,13 @@ class Defender(): if activation == 'on': if self.ModConfig.reputation == 1: - self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}REPUTATION{self.Config.CONFIG_COLOR['noire']} ] : Already activated") + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}REPUTATION{self.Config.COLORS.black} ] : Already activated") return False # self.update_db_configuration('reputation', 1) self.__update_configuration(key, 1) - self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}REPUTATION{self.Config.CONFIG_COLOR['noire']} ] : Activated by {fromuser}") + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}REPUTATION{self.Config.COLORS.black} ] : Activated by {fromuser}") self.Irc.send2socket(f":{service_id} JOIN {jail_chan}") self.Irc.send2socket(f":{service_id} SAMODE {jail_chan} +{dumodes} {dnickname}") self.Irc.send2socket(f":{service_id} MODE {jail_chan} +{jail_chan_mode}") @@ -1300,12 +1300,12 @@ class Defender(): if activation == 'off': if self.ModConfig.reputation == 0: - self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}REPUTATION{self.Config.CONFIG_COLOR['noire']} ] : Already deactivated") + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}REPUTATION{self.Config.COLORS.black} ] : Already deactivated") return False self.__update_configuration(key, 0) - self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['rouge']}REPUTATION{self.Config.CONFIG_COLOR['noire']} ] : Deactivated by {fromuser}") + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.red}REPUTATION{self.Config.COLORS.black} ] : Deactivated by {fromuser}") self.Irc.send2socket(f":{service_id} SAMODE {jail_chan} -{dumodes} {dnickname}") self.Irc.send2socket(f":{service_id} MODE {jail_chan} -sS") self.Irc.send2socket(f":{service_id} PART {jail_chan}") @@ -1335,23 +1335,23 @@ class Defender(): if get_value == 'on': if self.ModConfig.reputation_ban_all_chan == 1: - self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['rouge']}BAN ON ALL CHANS{self.Config.CONFIG_COLOR['noire']} ] : Already activated") + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.red}BAN ON ALL CHANS{self.Config.COLORS.black} ] : Already activated") return False # self.update_db_configuration(key, 1) self.__update_configuration(key, 1) - self.Irc.send2socket(f':{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR["verte"]}BAN ON ALL CHANS{self.Config.CONFIG_COLOR["noire"]} ] : Activated by {fromuser}') + self.Irc.send2socket(f':{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}BAN ON ALL CHANS{self.Config.COLORS.black} ] : Activated by {fromuser}') elif get_value == 'off': if self.ModConfig.reputation_ban_all_chan == 0: - self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['rouge']}BAN ON ALL CHANS{self.Config.CONFIG_COLOR['noire']} ] : Already deactivated") + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.red}BAN ON ALL CHANS{self.Config.COLORS.black} ] : Already deactivated") return False # self.update_db_configuration(key, 0) self.__update_configuration(key, 0) - self.Irc.send2socket(f':{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR["verte"]}BAN ON ALL CHANS{self.Config.CONFIG_COLOR["noire"]} ] : Deactivated by {fromuser}') + self.Irc.send2socket(f':{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}BAN ON ALL CHANS{self.Config.COLORS.black} ] : Deactivated by {fromuser}') case 'limit': reputation_seuil = int(cmd[3]) @@ -1360,7 +1360,7 @@ class Defender(): # self.update_db_configuration(key, reputation_seuil) self.__update_configuration(key, reputation_seuil) - self.Irc.send2socket(f':{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR["verte"]}REPUTATION SEUIL{self.Config.CONFIG_COLOR["noire"]} ] : Limit set to {str(reputation_seuil)} by {fromuser}') + self.Irc.send2socket(f':{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}REPUTATION SEUIL{self.Config.COLORS.black} ] : Limit set to {str(reputation_seuil)} by {fromuser}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Reputation set to {reputation_seuil}') case 'timer': @@ -1368,7 +1368,7 @@ class Defender(): key = 'reputation_timer' self.__update_configuration(key, reputation_timer) - self.Irc.send2socket(f':{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR["verte"]}REPUTATION TIMER{self.Config.CONFIG_COLOR["noire"]} ] : Timer set to {str(reputation_timer)} minute(s) by {fromuser}') + self.Irc.send2socket(f':{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}REPUTATION TIMER{self.Config.COLORS.black} ] : Timer set to {str(reputation_timer)} minute(s) by {fromuser}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Reputation set to {reputation_timer}') case 'score_after_release': @@ -1376,7 +1376,7 @@ class Defender(): key = 'reputation_score_after_release' self.__update_configuration(key, reputation_score_after_release) - self.Irc.send2socket(f':{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR["verte"]}REPUTATION SCORE AFTER RELEASE{self.Config.CONFIG_COLOR["noire"]} ] : Reputation score after release set to {str(reputation_score_after_release)} by {fromuser}') + self.Irc.send2socket(f':{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}REPUTATION SCORE AFTER RELEASE{self.Config.COLORS.black} ] : Reputation score after release set to {str(reputation_score_after_release)} by {fromuser}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Reputation score after release set to {reputation_score_after_release}') case 'security_group': @@ -1384,7 +1384,7 @@ class Defender(): key = 'reputation_sg' self.__update_configuration(key, reputation_sg) - self.Irc.send2socket(f':{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR["verte"]}REPUTATION SECURITY-GROUP{self.Config.CONFIG_COLOR["noire"]} ] : Reputation Security-group set to {str(reputation_sg)} by {fromuser}') + self.Irc.send2socket(f':{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}REPUTATION SECURITY-GROUP{self.Config.COLORS.black} ] : Reputation Security-group set to {str(reputation_sg)} by {fromuser}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Reputation score after release set to {reputation_sg}') case _: @@ -1414,9 +1414,9 @@ class Defender(): # .proxy_scan set psutil_scan on/off --> Active les informations de connexion a la machine locale # .proxy_scan set abuseipdb_scan on/off --> Active le scan via l'api abuseipdb len_cmd = len(cmd) - color_green = self.Config.CONFIG_COLOR['verte'] - color_red = self.Config.CONFIG_COLOR['rouge'] - color_black = self.Config.CONFIG_COLOR['noire'] + color_green = self.Config.COLORS.green + color_red = self.Config.COLORS.red + color_black = self.Config.COLORS.black if len_cmd == 4: set_key = str(cmd[1]).lower() @@ -1548,21 +1548,21 @@ class Defender(): key = 'flood' if activation == 'on': if self.ModConfig.flood == 1: - self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}FLOOD{self.Config.CONFIG_COLOR['noire']} ] : Already activated") + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}FLOOD{self.Config.COLORS.black} ] : Already activated") return False self.__update_configuration(key, 1) - self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}FLOOD{self.Config.CONFIG_COLOR['noire']} ] : Activated by {fromuser}") + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}FLOOD{self.Config.COLORS.black} ] : Activated by {fromuser}") if activation == 'off': if self.ModConfig.flood == 0: - self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['rouge']}FLOOD{self.Config.CONFIG_COLOR['noire']} ] : Already Deactivated") + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.red}FLOOD{self.Config.COLORS.black} ] : Already Deactivated") return False self.__update_configuration(key, 0) - self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}FLOOD{self.Config.CONFIG_COLOR['noire']} ] : Deactivated by {fromuser}") + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}FLOOD{self.Config.COLORS.black} ] : Deactivated by {fromuser}") if len_cmd == 4: set_key = str(cmd[2]).lower() @@ -1574,21 +1574,21 @@ class Defender(): set_value = int(cmd[3]) self.__update_configuration(key, set_value) - self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}FLOOD{self.Config.CONFIG_COLOR['noire']} ] : Flood message set to {set_value} by {fromuser}") + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}FLOOD{self.Config.COLORS.black} ] : Flood message set to {set_value} by {fromuser}") case 'flood_time': key = 'flood_time' set_value = int(cmd[3]) self.__update_configuration(key, set_value) - self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}FLOOD{self.Config.CONFIG_COLOR['noire']} ] : Flood time set to {set_value} by {fromuser}") + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}FLOOD{self.Config.COLORS.black} ] : Flood time set to {set_value} by {fromuser}") case 'flood_timer': key = 'flood_timer' set_value = int(cmd[3]) self.__update_configuration(key, set_value) - self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}FLOOD{self.Config.CONFIG_COLOR['noire']} ] : Flood timer set to {set_value} by {fromuser}") + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.COLORS.green}FLOOD{self.Config.COLORS.black} ] : Flood timer set to {set_value} by {fromuser}") case _: pass @@ -1597,9 +1597,9 @@ class Defender(): self.Logs.error(f"{self.__class__.__name__} Value Error : {ve}") case 'status': - color_green = self.Config.CONFIG_COLOR['verte'] - color_red = self.Config.CONFIG_COLOR['rouge'] - color_black = self.Config.CONFIG_COLOR['noire'] + color_green = self.Config.COLORS.green + color_red = self.Config.COLORS.red + color_black = self.Config.COLORS.black try: self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : [{color_green if self.ModConfig.reputation == 1 else color_red}Reputation{color_black}] ==> {self.ModConfig.reputation}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : reputation_seuil ==> {self.ModConfig.reputation_seuil}') diff --git a/mods/mod_votekick.py b/mods/mod_votekick.py index 34b7093..61be294 100644 --- a/mods/mod_votekick.py +++ b/mods/mod_votekick.py @@ -229,11 +229,11 @@ class Votekick(): if chan.channel_name == channel: target_user = self.User.get_nickname(chan.target_user) if chan.vote_for > chan.vote_against: - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :User {self.Config.CONFIG_COLOR["gras"]}{target_user}{self.Config.CONFIG_COLOR["nogc"]} has {chan.vote_against} votes against and {chan.vote_for} votes for. For this reason, it\'ll be kicked from the channel') + self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :User {self.Config.COLORS.bold}{target_user}{self.Config.COLORS.nogc} has {chan.vote_against} votes against and {chan.vote_for} votes for. For this reason, it\'ll be kicked from the channel') self.Irc.send2socket(f":{dnickname} KICK {channel} {target_user} Following the vote, you are not welcome in {channel}") self.Channel.delete_user_from_channel(channel, self.User.get_uid(target_user)) elif chan.vote_for <= chan.vote_against: - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :User {self.Config.CONFIG_COLOR["gras"]}{target_user}{self.Config.CONFIG_COLOR["nogc"]} has {chan.vote_against} votes against and {chan.vote_for} votes for. For this reason, it\'ll remain in the channel') + self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :User {self.Config.COLORS.bold}{target_user}{self.Config.COLORS.nogc} has {chan.vote_against} votes against and {chan.vote_for} votes for. For this reason, it\'ll remain in the channel') # Init the system if self.init_vote_system(channel): @@ -471,10 +471,10 @@ class Votekick(): if chan.channel_name == channel: target_user = self.User.get_nickname(chan.target_user) if chan.vote_for > chan.vote_against: - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :User {self.Config.CONFIG_COLOR["gras"]}{target_user}{self.Config.CONFIG_COLOR["nogc"]} has {chan.vote_against} votes against and {chan.vote_for} votes for. For this reason, it\'ll be kicked from the channel') + self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :User {self.Config.COLORS.bold}{target_user}{self.Config.COLORS.nogc} has {chan.vote_against} votes against and {chan.vote_for} votes for. For this reason, it\'ll be kicked from the channel') self.Irc.send2socket(f":{dnickname} KICK {channel} {target_user} Following the vote, you are not welcome in {channel}") elif chan.vote_for <= chan.vote_against: - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :User {self.Config.CONFIG_COLOR["gras"]}{target_user}{self.Config.CONFIG_COLOR["nogc"]} has {chan.vote_against} votes against and {chan.vote_for} votes for. For this reason, it\'ll remain in the channel') + self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :User {self.Config.COLORS.bold}{target_user}{self.Config.COLORS.nogc} has {chan.vote_against} votes against and {chan.vote_for} votes for. For this reason, it\'ll remain in the channel') # Init the system if self.init_vote_system(channel): diff --git a/version.json b/version.json index cdc5ae6..21edfcd 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "5.2.9" + "version": "5.3.0" } \ No newline at end of file