diff --git a/core/base.py b/core/base.py index 1f2ea70..c25e309 100644 --- a/core/base.py +++ b/core/base.py @@ -187,14 +187,26 @@ class Base: os.makedirs(logs_directory) # Init logs object - self.logs = logging - self.logs.basicConfig(level=self.Config.DEBUG_LEVEL, - filename=f'logs{self.Config.OS_SEP}defender.log', - encoding='UTF-8', - format='%(asctime)s - %(levelname)s - %(filename)s - %(lineno)d - %(funcName)s - %(message)s') + self.logs = logging.getLogger(self.Config.LOGGING_NAME) + self.logs.setLevel(self.Config.DEBUG_LEVEL) - logger = logging.getLogger() - logger.addFilter(self.replace_filter) + # Add Handlers + file_hanlder = logging.FileHandler(f'logs{self.Config.OS_SEP}defender.log',encoding='UTF-8') + file_hanlder.setLevel(self.Config.DEBUG_LEVEL) + + # Define log format + formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(filename)s - %(lineno)d - %(funcName)s - %(message)s') + + # Apply log format + file_hanlder.setFormatter(formatter) + + # Add handler to logs + self.logs.addHandler(file_hanlder) + + # Apply the filter + self.logs.addFilter(self.replace_filter) + + # self.logs.Logger('defender').addFilter(self.replace_filter) self.logs.info('#################### STARTING DEFENDER ####################') return None @@ -214,6 +226,21 @@ class Base: return response # Retourne True pour permettre l'affichage du message + def delete_logger(self, logger_name: str) -> None: + + # Récupérer le logger + logger = logging.getLogger(logger_name) + + # Retirer tous les gestionnaires du logger et les fermer + for handler in logger.handlers[:]: # Utiliser une copie de la liste + logger.removeHandler(handler) + handler.close() + + # Supprimer le logger du dictionnaire global + logging.Logger.manager.loggerDict.pop(logger_name, None) + + return None + def log_cmd(self, user_cmd:str, cmd:str) -> None: """Enregistre les commandes envoyées par les utilisateurs @@ -222,7 +249,7 @@ class Base: """ cmd_list = cmd.split() if len(cmd_list) == 3: - if cmd_list[0].replace('.', '') == 'auth': + if cmd_list[0].replace(self.Config.SERVICE_PREFIX, '') == 'auth': cmd_list[1] = '*******' cmd_list[2] = '*******' cmd = ' '.join(cmd_list) diff --git a/core/classes/channel.py b/core/classes/channel.py index 507d45f..94d8438 100644 --- a/core/classes/channel.py +++ b/core/classes/channel.py @@ -60,36 +60,30 @@ class Channel: return result - def delete(self, name: str) -> bool: + def delete(self, channel_name: str) -> bool: - result = False + chanObj = self.get_Channel(channel_name) - for record in self.UID_CHANNEL_DB: - if record.name == name: - # If the channel exist, then remove it and return True. - # As soon as the channel found, return True and stop the loop - self.UID_CHANNEL_DB.remove(record) - result = True - # self.Logs.debug(f'Channel ({record.name}) has been created') - return result + if chanObj is None: + return False - if not result: - self.Logs.critical(f'The Channel {name} was not deleted') + self.UID_CHANNEL_DB.remove(chanObj) - return result + return True - def delete_user_from_channel(self, chan_name: str, uid:str) -> bool: + def delete_user_from_channel(self, channel_name: str, uid:str) -> bool: try: result = False - chan_name = chan_name.lower() - for record in self.UID_CHANNEL_DB: - if record.name == chan_name: - for user_id in record.uids: - if self.Base.clean_uid(user_id) == uid: - record.uids.remove(user_id) - # self.Logs.debug(f'The UID {uid} has been removed, here is the new object: {record}') - result = True + chanObj = self.get_Channel(channel_name.lower()) + + if chanObj is None: + return result + + for userid in chanObj.uids: + if self.Base.clean_uid(userid) == self.Base.clean_uid(uid): + chanObj.uids.remove(userid) + result = True self.clean_channel() @@ -126,14 +120,13 @@ class Channel: except Exception as err: self.Logs.error(f'{err}') - def get_Channel(self, name: str) -> Union['MChannel', None]: + def get_Channel(self, channel_name: str) -> Union['MChannel', None]: Channel = None - for record in self.UID_CHANNEL_DB: - if record.name == name: - Channel = record - # self.Logs.debug(f'Search {name} -- result = {Channel}') + for record in self.UID_CHANNEL_DB: + if record.name == channel_name: + Channel = record return Channel @@ -169,9 +162,9 @@ class Channel: else: return True except TypeError as te: - self.logs.error(f'TypeError: [{channelToCheck}] - {te}') + self.Logs.error(f'TypeError: [{channelToCheck}] - {te}') except Exception as err: - self.logs.error(f'Error Not defined: {err}') + self.Logs.error(f'Error Not defined: {err}') def db_query_channel(self, action: Literal['add','del'], module_name: str, channel_name: str) -> bool: """You can add a channel or delete a channel. diff --git a/core/classes/protocol.py b/core/classes/protocol.py index ce6f939..536a396 100644 --- a/core/classes/protocol.py +++ b/core/classes/protocol.py @@ -1,15 +1,18 @@ from typing import Literal, TYPE_CHECKING from .protocols.unreal6 import Unrealircd6 +from .protocols.inspircd import Inspircd if TYPE_CHECKING: from core.irc import Irc class Protocol: - def __init__(self, protocol: Literal['unreal6'], ircInstance: 'Irc'): + def __init__(self, protocol: Literal['unreal6','inspircd'], ircInstance: 'Irc'): self.Protocol = None if protocol == 'unreal6': self.Protocol: Unrealircd6 = Unrealircd6(ircInstance) + elif protocol == 'inspircd': # InspIRCd + self.Protocol: Inspircd = Inspircd(ircInstance) else: self.Protocol = None \ No newline at end of file diff --git a/core/classes/protocols/inspircd.py b/core/classes/protocols/inspircd.py new file mode 100644 index 0000000..6b90471 --- /dev/null +++ b/core/classes/protocols/inspircd.py @@ -0,0 +1,672 @@ +from re import match, findall +from datetime import datetime +from typing import TYPE_CHECKING +from ssl import SSLEOFError, SSLError + +if TYPE_CHECKING: + from core.irc import Irc + +class Inspircd: + + def __init__(self, ircInstance: 'Irc'): + self.name = 'InspIRCd-4' + + self.__Irc = ircInstance + self.__Config = ircInstance.Config + self.__Base = ircInstance.Base + + def send2socket(self, message: str, print_log: bool = True) -> None: + """Envoit les commandes à envoyer au serveur. + + Args: + string (Str): contient la commande à envoyer au serveur. + """ + try: + with self.__Base.lock: + self.__Irc.IrcSocket.send(f"{message}\r\n".encode(self.__Config.SERVEUR_CHARSET[0])) + if print_log: + self.__Base.logs.debug(f'<< {message}') + + except UnicodeDecodeError as ude: + self.__Base.logs.error(f'Decode Error try iso-8859-1 - {ude} - {message}') + self.__Irc.IrcSocket.send(f"{message}\r\n".encode(self.__Config.SERVEUR_CHARSET[1],'replace')) + except UnicodeEncodeError as uee: + self.__Base.logs.error(f'Encode Error try iso-8859-1 - {uee} - {message}') + self.__Irc.IrcSocket.send(f"{message}\r\n".encode(self.__Config.SERVEUR_CHARSET[1],'replace')) + except AssertionError as ae: + self.__Base.logs.warning(f'Assertion Error {ae} - message: {message}') + except SSLEOFError as soe: + self.__Base.logs.error(f"SSLEOFError: {soe} - {message}") + except SSLError as se: + self.__Base.logs.error(f"SSLError: {se} - {message}") + except OSError as oe: + self.__Base.logs.error(f"OSError: {oe} - {message}") + except AttributeError as ae: + self.__Base.logs.critical(f"Attribute Error: {ae}") + + def sendPrivMsg(self, nick_from: str, msg: str, channel: str = None, nick_to: 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 + nick_from (str): The sender nickname + channel (str, optional): The receiver channel. Defaults to None. + nick_to (str, optional): The reciever nickname. Defaults to None. + """ + try: + batch_size = self.__Config.BATCH_SIZE + User_from = self.__Irc.User.get_User(nick_from) + User_to = self.__Irc.User.get_User(nick_to) if nick_to is None else None + + if User_from is None: + self.__Base.logs.error(f"The sender nickname [{nick_from}] do not exist") + return None + + 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":{User_from.uid} PRIVMSG {channel} :{batch}") + + if not nick_to is None: + for i in range(0, len(str(msg)), batch_size): + batch = str(msg)[i:i+batch_size] + self.send2socket(f":{nick_from} PRIVMSG {User_to.uid} :{batch}") + except Exception as err: + self.__Base.logs.error(f"General Error: {err}") + + def sendNotice(self, nick_from: str, nick_to: str, msg: str) -> None: + """Sending NOTICE by batches + + Args: + msg (str): The message to send to the server + nick_from (str): The sender Nickname + nick_to (str): The reciever nickname + """ + try: + batch_size = self.__Config.BATCH_SIZE + User_from = self.__Irc.User.get_User(nick_from) + User_to = self.__Irc.User.get_User(nick_to) + + if User_from is None or User_to is None: + self.__Base.logs.error(f"The sender [{nick_from}] or the Reciever [{nick_to}] do not exist") + return None + + for i in range(0, len(str(msg)), batch_size): + batch = str(msg)[i:i+batch_size] + self.send2socket(f":{User_from.uid} NOTICE {User_to.uid} :{batch}") + + except Exception as err: + self.__Base.logs.error(f"General Error: {err}") + + def link(self): + """Créer le link et envoyer les informations nécessaires pour la + connexion au serveur. + """ + + nickname = self.__Config.SERVICE_NICKNAME + username = self.__Config.SERVICE_USERNAME + realname = self.__Config.SERVICE_REALNAME + chan = self.__Config.SERVICE_CHANLOG + info = self.__Config.SERVICE_INFO + smodes = self.__Config.SERVICE_SMODES + cmodes = self.__Config.SERVICE_CMODES + umodes = self.__Config.SERVICE_UMODES + host = self.__Config.SERVICE_HOST + service_name = self.__Config.SERVICE_NAME + + password = self.__Config.SERVEUR_PASSWORD + link = self.__Config.SERVEUR_LINK + server_id = self.__Config.SERVEUR_ID + service_id = self.__Config.SERVICE_ID + + version = self.__Config.CURRENT_VERSION + unixtime = self.__Base.get_unixtime() + + self.send2socket(f":{server_id} PASS :{password}") + self.send2socket(f":{server_id} PROTOCTL SID NOQUIT NICKv2 SJOIN SJ3 NICKIP TKLEXT2 NEXTBANS CLK EXTSWHOIS MLOCK MTAGS") + # self.__Irc.send2socket(f":{sid} PROTOCTL NICKv2 VHP UMODE2 NICKIP SJOIN SJOIN2 SJ3 NOQUIT TKLEXT MLOCK SID MTAGS") + self.send2socket(f":{server_id} PROTOCTL EAUTH={link},,,{service_name}-v{version}") + self.send2socket(f":{server_id} PROTOCTL SID={server_id}") + self.send2socket(f":{server_id} SERVER {link} 1 :{info}") + self.send2socket(f":{server_id} {nickname} :Reserved for services") + #self.__Irc.send2socket(f":{sid} UID {nickname} 1 {unixtime} {username} {host} {service_id} * {smodes} * * * :{realname}") + self.send2socket(f":{server_id} UID {nickname} 1 {unixtime} {username} {host} {service_id} * {smodes} * * fwAAAQ== :{realname}") + # self.__Irc.send2socket(f":{server_id} SJOIN {unixtime} {chan} + :{service_id}") + self.sjoin(chan) + self.send2socket(f":{server_id} TKL + Q * {nickname} {host} 0 {unixtime} :Reserved for services") + + self.send2socket(f":{service_id} MODE {chan} {cmodes}") + self.send2socket(f":{service_id} MODE {chan} {umodes} {service_id}") + + self.__Base.logs.debug(f'>> {__name__} Link information sent to the server') + + def gline(self, nickname: str, hostname: str, set_by: str, expire_timestamp: int, set_at_timestamp: int, reason: str) -> None: + # TKL + G user host set_by expire_timestamp set_at_timestamp :reason + + self.send2socket(f":{self.__Config.SERVEUR_ID} TKL + G {nickname} {hostname} {set_by} {expire_timestamp} {set_at_timestamp} :{reason}") + + return None + + def set_nick(self, newnickname: str) -> None: + + self.send2socket(f":{self.__Config.SERVICE_NICKNAME} NICK {newnickname}") + return None + + def squit(self, server_id: str, server_link: str, reason: str) -> None: + + if not reason: + reason = 'Service Shutdown' + + self.send2socket(f":{server_id} SQUIT {server_link} :{reason}") + return None + + def ungline(self, nickname:str, hostname: str) -> None: + + self.send2socket(f":{self.__Config.SERVEUR_ID} TKL - G {nickname} {hostname} {self.__Config.SERVICE_NICKNAME}") + + return None + + def kline(self, nickname: str, hostname: str, set_by: str, expire_timestamp: int, set_at_timestamp: int, reason: str) -> None: + # TKL + k user host set_by expire_timestamp set_at_timestamp :reason + + self.send2socket(f":{self.__Config.SERVEUR_ID} TKL + k {nickname} {hostname} {set_by} {expire_timestamp} {set_at_timestamp} :{reason}") + + return None + + def sjoin(self, channel: str) -> None: + + if not self.__Irc.Channel.Is_Channel(channel): + self.__Base.logs.error(f"The channel [{channel}] is not valid") + return None + + self.send2socket(f":{self.__Config.SERVEUR_ID} SJOIN {self.__Base.get_unixtime()} {channel} + :{self.__Config.SERVICE_ID}") + + # Add defender to the channel uids list + self.__Irc.Channel.insert(self.__Irc.Loader.Definition.MChannel(name=channel, uids=[self.__Config.SERVICE_ID])) + return None + + def sendQuit(self, uid: str, reason: str, print_log: True) -> None: + """Send quit message + + Args: + uidornickname (str): The UID or the Nickname + reason (str): The reason for the quit + """ + userObj = self.__Irc.User.get_User(uidornickname=uid) + cloneObj = self.__Irc.Clone.get_Clone(uidornickname=uid) + reputationObj = self.__Irc.Reputation.get_Reputation(uidornickname=uid) + + if not userObj is None: + self.send2socket(f":{userObj.uid} QUIT :{reason}", print_log=print_log) + self.__Irc.User.delete(userObj.uid) + + if not cloneObj is None: + self.__Irc.Clone.delete(cloneObj.uid) + + if not reputationObj is None: + self.__Irc.Reputation.delete(reputationObj.uid) + + if not self.__Irc.Channel.delete_user_from_all_channel(uid): + self.__Base.logs.error(f"The UID [{uid}] has not been deleted from all channels") + + return None + + def sendUID(self, nickname:str, username: str, hostname: str, uid:str, umodes: str, vhost: str, remote_ip: str, realname: str, print_log: bool = True) -> None: + """Send UID to the server + + Args: + nickname (str): Nickname of the client + username (str): Username of the client + hostname (str): Hostname of the client you want to create + uid (str): UID of the client you want to create + umodes (str): umodes of the client you want to create + vhost (str): vhost of the client you want to create + remote_ip (str): remote_ip of the client you want to create + realname (str): realname of the client you want to create + print_log (bool, optional): print logs if true. Defaults to True. + """ + # {self.Config.SERVEUR_ID} UID + # {clone.nickname} 1 {self.Base.get_unixtime()} {clone.username} {clone.hostname} {clone.uid} * {clone.umodes} {clone.vhost} * {self.Base.encode_ip(clone.remote_ip)} :{clone.realname} + try: + unixtime = self.__Base.get_unixtime() + encoded_ip = self.__Base.encode_ip(remote_ip) + + # Create the user + self.__Irc.User.insert( + self.__Irc.Loader.Definition.MUser( + uid=uid, nickname=nickname, username=username, + realname=realname,hostname=hostname, umodes=umodes, + vhost=vhost, remote_ip=remote_ip + ) + ) + + uid_msg = f":{self.__Config.SERVEUR_ID} UID {nickname} 1 {unixtime} {username} {hostname} {uid} * {umodes} {vhost} * {encoded_ip} :{realname}" + + self.send2socket(uid_msg, print_log=print_log) + + return None + + except Exception as err: + self.__Base.logs.error(f"{__name__} - General Error: {err}") + + def sendChanJoin(self, uidornickname: str, channel: str, password: str = None, print_log: bool = True) -> None: + """Joining a channel + + Args: + uidornickname (str): UID or nickname that need to join + channel (str): channel to join + password (str, optional): The password of the channel to join. Default to None + print_log (bool, optional): Write logs. Defaults to True. + """ + + userObj = self.__Irc.User.get_User(uidornickname) + passwordChannel = password if not password is None else '' + + if userObj is None: + return None + + if not self.__Irc.Channel.Is_Channel(channel): + self.__Base.logs.error(f"The channel [{channel}] is not valid") + return None + + self.send2socket(f":{userObj.uid} JOIN {channel} {passwordChannel}", print_log=print_log) + + # Add defender to the channel uids list + self.__Irc.Channel.insert(self.__Irc.Loader.Definition.MChannel(name=channel, uids=[userObj.uid])) + return None + + def sendChanPart(self, uidornickname:str, channel: str, print_log: bool = True) -> None: + """Part from a channel + + Args: + uidornickname (str): UID or nickname that need to join + channel (str): channel to join + print_log (bool, optional): Write logs. Defaults to True. + """ + + userObj = self.__Irc.User.get_User(uidornickname) + + if userObj is None: + self.__Base.logs.error(f"The user [{uidornickname}] is not valid") + return None + + if not self.__Irc.Channel.Is_Channel(channel): + self.__Base.logs.error(f"The channel [{channel}] is not valid") + return None + + self.send2socket(f":{userObj.uid} PART {channel}", print_log=print_log) + + # Add defender to the channel uids list + self.__Irc.Channel.delete_user_from_channel(channel, userObj.uid) + return None + + def unkline(self, nickname:str, hostname: str) -> None: + + self.send2socket(f":{self.__Config.SERVEUR_ID} TKL - K {nickname} {hostname} {self.__Config.SERVICE_NICKNAME}") + + return None + + def on_umode2(self, serverMsg: list[str]) -> None: + """Handle umode2 coming from a server + + Args: + serverMsg (list[str]): Original server message + """ + try: + # [':adator_', 'UMODE2', '-iwx'] + + userObj = self.__Irc.User.get_User(str(serverMsg[0]).lstrip(':')) + userMode = serverMsg[2] + + if userObj is None: # If user is not created + return None + + # save previous user modes + old_umodes = userObj.umodes + + # TODO : User object should be able to update user modes + if self.__Irc.User.update_mode(userObj.uid, userMode): + return None + # self.__Base.logs.debug(f"Updating user mode for [{userObj.nickname}] [{old_umodes}] => [{userObj.umodes}]") + + return None + + except IndexError as ie: + self.__Base.logs.error(f"{__name__} - Index Error: {ie}") + except Exception as err: + self.__Base.logs.error(f"{__name__} - General Error: {err}") + + def on_quit(self, serverMsg: list[str]) -> None: + """Handle quit coming from a server + + Args: + serverMsg (list[str]): Original server message + """ + try: + # ['@unrealircd.org/userhost=...@192.168.1.10;unrealircd.org/userip=...@192.168.1.10;msgid=CssUrV08BzekYuq7BfvPHn;time=2024-11-02T15:03:33.182Z', ':001JKNY0N', 'QUIT', ':Quit:', '....'] + + uid_who_quit = str(serverMsg[1]).lstrip(':') + + self.__Irc.Channel.delete_user_from_all_channel(uid_who_quit) + self.__Irc.User.delete(uid_who_quit) + self.__Irc.Reputation.delete(uid_who_quit) + self.__Irc.Clone.delete(uid_who_quit) + + return None + + except IndexError as ie: + self.__Base.logs.error(f"{__name__} - Index Error: {ie}") + except Exception as err: + self.__Base.logs.error(f"{__name__} - General Error: {err}") + + def on_squit(self, serverMsg: list[str]) -> None: + """Handle squit coming from a server + + Args: + serverMsg (list[str]): Original server message + """ + # ['@msgid=QOEolbRxdhpVW5c8qLkbAU;time=2024-09-21T17:33:16.547Z', 'SQUIT', 'defender.deb.biz.st', ':Connection', 'closed'] + + server_hostname = serverMsg[2] + uid_to_delete = None + for s_user in self.__Irc.User.UID_DB: + if s_user.hostname == server_hostname and 'S' in s_user.umodes: + uid_to_delete = s_user.uid + + if uid_to_delete is None: + return None + + self.__Irc.User.delete(uid_to_delete) + self.__Irc.Channel.delete_user_from_all_channel(uid_to_delete) + + return None + + def on_protoctl(self, serverMsg: list[str]) -> None: + """Handle protoctl coming from a server + + Args: + serverMsg (list[str]): Original server message + """ + if len(serverMsg) > 5: + if '=' in serverMsg[5]: + serveur_hosting_id = str(serverMsg[5]).split('=') + self.__Config.HSID = serveur_hosting_id[1] + + return None + + def on_nick(self, serverMsg: list[str]) -> None: + """Handle nick coming from a server + new nickname + + Args: + serverMsg (list[str]): Original server message + """ + try: + # ['@unrealircd.org/geoip=FR;unrealircd.org/', ':001OOU2H3', 'NICK', 'WebIrc', '1703795844'] + # Changement de nickname + + uid = str(serverMsg[1]).lstrip(':') + newnickname = serverMsg[3] + self.__Irc.User.update(uid, newnickname) + + return None + + except IndexError as ie: + self.__Base.logs.error(f"{__name__} - Index Error: {ie}") + except Exception as err: + self.__Base.logs.error(f"{__name__} - General Error: {err}") + + def on_sjoin(self, serverMsg: list[str]) -> None: + """Handle sjoin coming from a server + + Args: + serverMsg (list[str]): Original server message + """ + try: + # ['@msgid=5sTwGdj349D82L96p749SY;time=2024-08-15T09:50:23.528Z', ':001', 'SJOIN', '1721564574', '#welcome', ':001JD94QH'] + # ['@msgid=bvceb6HthbLJapgGLXn1b0;time=2024-08-15T09:50:11.464Z', ':001', 'SJOIN', '1721564574', '#welcome', '+lnrt', '13', ':001CIVLQF', '+11ZAAAAAB', '001QGR10C', '*@0014UE10B', '001NL1O07', '001SWZR05', '001HB8G04', '@00BAAAAAJ', '0019M7101'] + # ['@msgid=SKUeuVzOrTShRDduq8VerX;time=2024-08-23T19:37:04.266Z', ':001', 'SJOIN', '1723993047', '#welcome', '+lnrt', '13', + # ':001T6VU3F', '001JGWB2K', '@11ZAAAAAB', + # '001F16WGR', '001X9YMGQ', '*+001DYPFGP', '@00BAAAAAJ', '001AAGOG9', '001FMFVG8', '001DAEEG7', + # '&~G:unknown-users', '"~G:websocket-users', '"~G:known-users', '"~G:webirc-users'] + serverMsg.pop(0) + channel = str(serverMsg[3]).lower() + len_cmd = len(serverMsg) + list_users:list = [] + occurence = 0 + start_boucle = 0 + + # Trouver le premier user + for i in range(len_cmd): + s: list = findall(fr':', serverMsg[i]) + if s: + occurence += 1 + if occurence == 2: + start_boucle = i + + # Boucle qui va ajouter l'ensemble des users (UID) + for i in range(start_boucle, len(serverMsg)): + parsed_UID = str(serverMsg[i]) + clean_uid = self.__Irc.User.clean_uid(parsed_UID) + if not clean_uid is None and len(clean_uid) == 9: + list_users.append(parsed_UID) + + if list_users: + self.__Irc.Channel.insert( + self.__Irc.Loader.Definition.MChannel( + name=channel, + uids=list_users + ) + ) + return None + + except IndexError as ie: + self.__Base.logs.error(f"{__name__} - Index Error: {ie}") + except Exception as err: + self.__Base.logs.error(f"{__name__} - General Error: {err}") + + def on_part(self, serverMsg: list[str]) -> None: + """Handle part coming from a server + + Args: + serverMsg (list[str]): Original server message + """ + try: + # ['@unrealircd.org/geoip=FR;unrealircd.org/userhost=50d6492c@80.214.73.44;unrealircd.org/userip=50d6492c@80.214.73.44;msgid=YSIPB9q4PcRu0EVfC9ci7y-/mZT0+Gj5FLiDSZshH5NCw;time=2024-08-15T15:35:53.772Z', + # ':001EPFBRD', 'PART', '#welcome', ':WEB', 'IRC', 'Paris'] + + uid = str(serverMsg[1]).lstrip(':') + channel = str(serverMsg[3]).lower() + self.__Irc.Channel.delete_user_from_channel(channel, uid) + + return None + + except IndexError as ie: + self.__Base.logs.error(f"{__name__} - Index Error: {ie}") + except Exception as err: + self.__Base.logs.error(f"{__name__} - General Error: {err}") + + def on_uid(self, serverMsg: list[str]) -> None: + """Handle uid message coming from the server + + Args: + serverMsg (list[str]): Original server message + """ + # ['@s2s-md/geoip=cc=GB|cd=United\\sKingdom|asn=16276|asname=OVH\\sSAS;s2s-md/tls_cipher=TLSv1.3-TLS_CHACHA20_POLY1305_SHA256;s2s-md/creationtime=1721564601', + # ':001', 'UID', 'albatros', '0', '1721564597', 'albatros', 'vps-91b2f28b.vps.ovh.net', + # '001HB8G04', '0', '+iwxz', 'Clk-A62F1D18.vps.ovh.net', 'Clk-A62F1D18.vps.ovh.net', 'MyZBwg==', ':...'] + try: + + isWebirc = True if 'webirc' in serverMsg[0] else False + isWebsocket = True if 'websocket' in serverMsg[0] else False + + uid = str(serverMsg[8]) + nickname = str(serverMsg[3]) + username = str(serverMsg[6]) + hostname = str(serverMsg[7]) + umodes = str(serverMsg[10]) + vhost = str(serverMsg[11]) + + if not 'S' in umodes: + remote_ip = self.__Base.decode_ip(str(serverMsg[13])) + else: + remote_ip = '127.0.0.1' + + # extract realname + realname = ' '.join(serverMsg[14:]).lstrip(':') + + # Extract Geoip information + pattern = r'^.*geoip=cc=(\S{2}).*$' + geoip_match = match(pattern, serverMsg[0]) + + if geoip_match: + geoip = geoip_match.group(1) + else: + geoip = None + + score_connexion = 0 + + self.__Irc.User.insert( + self.__Irc.Loader.Definition.MUser( + uid=uid, + nickname=nickname, + username=username, + realname=realname, + hostname=hostname, + umodes=umodes, + vhost=vhost, + isWebirc=isWebirc, + isWebsocket=isWebsocket, + remote_ip=remote_ip, + geoip=geoip, + score_connexion=score_connexion, + connexion_datetime=datetime.now() + ) + ) + return None + except IndexError as ie: + self.__Base.logs.error(f"{__name__} - Index Error: {ie}") + except Exception as err: + self.__Base.logs.error(f"{__name__} - General Error: {err}") + + def on_server_ping(self, serverMsg: list[str]) -> None: + """Send a PONG message to the server + + Args: + serverMsg (list[str]): List of str coming from the server + """ + try: + + pong = str(serverMsg[1]).replace(':','') + self.send2socket(f"PONG :{pong}", print_log=False) + + return None + except Exception as err: + self.__Base.logs.error(f"{__name__} - General Error: {err}") + + def on_version(self, serverMsg: list[str]) -> None: + """Sending Server Version to the server + + Args: + serverMsg (list[str]): List of str coming from the server + """ + # ['@unrealircd.org/userhost=StatServ@stats.deb.biz.st;draft/bot;bot;msgid=ehfAq3m2yjMjhgWEfi1UCS;time=2024-10-26T13:49:06.299Z', ':00BAAAAAI', 'PRIVMSG', '12ZAAAAAB', ':\x01VERSION\x01'] + # Réponse a un CTCP VERSION + try: + + nickname = self.__Irc.User.get_nickname(self.__Base.clean_uid(serverMsg[1])) + dnickname = self.__Config.SERVICE_NICKNAME + arg = serverMsg[4].replace(':', '') + + if nickname is None: + return None + + if arg == '\x01VERSION\x01': + self.send2socket(f':{dnickname} NOTICE {nickname} :\x01VERSION Service {self.__Config.SERVICE_NICKNAME} V{self.__Config.CURRENT_VERSION}\x01') + + return None + except Exception as err: + self.__Base.logs.error(f"{__name__} - General Error: {err}") + + def on_time(self, serverMsg: list[str]) -> None: + """Sending TIME answer to a requestor + + Args: + serverMsg (list[str]): List of str coming from the server + """ + # ['@unrealircd.org/userhost=StatServ@stats.deb.biz.st;draft/bot;bot;msgid=ehfAq3m2yjMjhgWEfi1UCS;time=2024-10-26T13:49:06.299Z', ':00BAAAAAI', 'PRIVMSG', '12ZAAAAAB', ':\x01TIME\x01'] + # Réponse a un CTCP VERSION + try: + + nickname = self.__Irc.User.get_nickname(self.__Base.clean_uid(serverMsg[1])) + dnickname = self.__Config.SERVICE_NICKNAME + arg = serverMsg[4].replace(':', '') + current_datetime = self.__Base.get_datetime() + + if nickname is None: + return None + + if arg == '\x01TIME\x01': + self.send2socket(f':{dnickname} NOTICE {nickname} :\x01TIME {current_datetime}\x01') + + return None + except Exception as err: + self.__Base.logs.error(f"{__name__} - General Error: {err}") + + def on_ping(self, serverMsg: list[str]) -> None: + """Sending a PING answer to requestor + + Args: + serverMsg (list[str]): List of str coming from the server + """ + # ['@unrealircd.org/userhost=StatServ@stats.deb.biz.st;draft/bot;bot;msgid=ehfAq3m2yjMjhgWEfi1UCS;time=2024-10-26T13:49:06.299Z', ':001INC60B', 'PRIVMSG', '12ZAAAAAB', ':\x01PING', '762382207\x01'] + # Réponse a un CTCP VERSION + try: + + nickname = self.__Irc.User.get_nickname(self.__Base.clean_uid(serverMsg[1])) + dnickname = self.__Config.SERVICE_NICKNAME + arg = serverMsg[4].replace(':', '') + + if nickname is None: + return None + + if arg == '\x01PING': + recieved_unixtime = int(serverMsg[5].replace('\x01','')) + current_unixtime = self.__Base.get_unixtime() + ping_response = current_unixtime - recieved_unixtime + + # self.__Irc.send2socket(f':{dnickname} NOTICE {nickname} :\x01PING {ping_response} secs\x01') + self.sendNotice( + nick_from=dnickname, + nick_to=nickname, + msg=f"\x01PING {ping_response} secs\x01" + ) + + return None + except Exception as err: + self.__Base.logs.error(f"{__name__} - General Error: {err}") + + def on_version_msg(self, serverMsg: list[str]) -> None: + """Handle version coming from the server + + Args: + serverMsg (list[str]): Original message from the server + """ + try: + # ['@label=0073', ':0014E7P06', 'VERSION', 'PyDefender'] + getUser = self.__Irc.User.get_User(self.__Irc.User.clean_uid(serverMsg[1])) + + if getUser is None: + return None + + response_351 = f"{self.__Config.SERVICE_NAME.capitalize()}-{self.__Config.CURRENT_VERSION} {self.__Config.SERVICE_HOST} {self.name}" + self.send2socket(f':{self.__Config.SERVICE_HOST} 351 {getUser.nickname} {response_351}') + + modules = self.__Base.get_all_modules() + response_005 = ' | '.join(modules) + self.send2socket(f':{self.__Config.SERVICE_HOST} 005 {getUser.nickname} {response_005} are supported by this server') + + return None + + except Exception as err: + self.__Base.logs.error(f"{__name__} - General Error: {err}") diff --git a/core/classes/protocols/unreal6.py b/core/classes/protocols/unreal6.py index 170bedd..f636aec 100644 --- a/core/classes/protocols/unreal6.py +++ b/core/classes/protocols/unreal6.py @@ -9,6 +9,8 @@ if TYPE_CHECKING: class Unrealircd6: def __init__(self, ircInstance: 'Irc'): + self.name = 'UnrealIRCD-6' + self.__Irc = ircInstance self.__Config = ircInstance.Config self.__Base = ircInstance.Base @@ -171,6 +173,12 @@ class Unrealircd6: return None + def unkline(self, nickname:str, hostname: str) -> None: + + self.send2socket(f":{self.__Config.SERVEUR_ID} TKL - K {nickname} {hostname} {self.__Config.SERVICE_NICKNAME}") + + return None + def sjoin(self, channel: str) -> None: if not self.__Irc.Channel.Is_Channel(channel): @@ -183,8 +191,36 @@ class Unrealircd6: self.__Irc.Channel.insert(self.__Irc.Loader.Definition.MChannel(name=channel, uids=[self.__Config.SERVICE_ID])) return None + def sendSapart(self, nick_to_sapart: str, channel_name: str) -> None: + """_summary_ + + Args: + from_nick (str): _description_ + nick_to (str): _description_ + channel_name (str): _description_ + """ + try: + + userObj = self.__Irc.User.get_User(uidornickname=nick_to_sapart) + chanObj = self.__Irc.Channel.get_Channel(channel_name) + service_uid = self.__Config.SERVICE_ID + + if userObj is None or chanObj is None: + return None + + self.send2socket(f":{service_uid} SAPART {userObj.nickname} {chanObj.name}") + self.__Irc.Channel.delete_user_from_channel(chanObj.name, userObj.uid) + + return None + + except Exception as err: + self.__Base.logs.error(f"{__name__} - General Error: {err}") + def sendQuit(self, uid: str, reason: str, print_log: True) -> None: """Send quit message + - Delete uid from User object + - Delete uid from Clone object + - Delete uid from Reputation object Args: uidornickname (str): The UID or the Nickname @@ -211,7 +247,7 @@ class Unrealircd6: def sendUID(self, nickname:str, username: str, hostname: str, uid:str, umodes: str, vhost: str, remote_ip: str, realname: str, print_log: bool = True) -> None: """Send UID to the server - + - Insert User to User Object Args: nickname (str): Nickname of the client username (str): Username of the client @@ -298,12 +334,6 @@ class Unrealircd6: self.__Irc.Channel.delete_user_from_channel(channel, userObj.uid) return None - def unkline(self, nickname:str, hostname: str) -> None: - - self.send2socket(f":{self.__Config.SERVEUR_ID} TKL - K {nickname} {hostname} {self.__Config.SERVICE_NICKNAME}") - - return None - def on_umode2(self, serverMsg: list[str]) -> None: """Handle umode2 coming from a server @@ -357,6 +387,41 @@ class Unrealircd6: except Exception as err: self.__Base.logs.error(f"{__name__} - General Error: {err}") + def on_squit(self, serverMsg: list[str]) -> None: + """Handle squit coming from a server + + Args: + serverMsg (list[str]): Original server message + """ + # ['@msgid=QOEolbRxdhpVW5c8qLkbAU;time=2024-09-21T17:33:16.547Z', 'SQUIT', 'defender.deb.biz.st', ':Connection', 'closed'] + + server_hostname = serverMsg[2] + uid_to_delete = None + for s_user in self.__Irc.User.UID_DB: + if s_user.hostname == server_hostname and 'S' in s_user.umodes: + uid_to_delete = s_user.uid + + if uid_to_delete is None: + return None + + self.__Irc.User.delete(uid_to_delete) + self.__Irc.Channel.delete_user_from_all_channel(uid_to_delete) + + return None + + def on_protoctl(self, serverMsg: list[str]) -> None: + """Handle protoctl coming from a server + + Args: + serverMsg (list[str]): Original server message + """ + if len(serverMsg) > 5: + if '=' in serverMsg[5]: + serveur_hosting_id = str(serverMsg[5]).split('=') + self.__Config.HSID = serveur_hosting_id[1] + + return None + def on_nick(self, serverMsg: list[str]) -> None: """Handle nick coming from a server new nickname @@ -366,7 +431,7 @@ class Unrealircd6: """ try: # ['@unrealircd.org/geoip=FR;unrealircd.org/', ':001OOU2H3', 'NICK', 'WebIrc', '1703795844'] - # Changement de nickname + # Changement de nickname uid = str(serverMsg[1]).lstrip(':') newnickname = serverMsg[3] @@ -610,11 +675,26 @@ class Unrealircd6: self.__Base.logs.error(f"{__name__} - General Error: {err}") def on_version_msg(self, serverMsg: list[str]) -> None: + """Handle version coming from the server - # ['@label=0073', ':0014E7P06', 'VERSION', 'PyDefender'] - getUser = self.__Irc.User.get_User(self.__Irc.User.clean_uid(serverMsg[1])) + Args: + serverMsg (list[str]): Original message from the server + """ + try: + # ['@label=0073', ':0014E7P06', 'VERSION', 'PyDefender'] + getUser = self.__Irc.User.get_User(self.__Irc.User.clean_uid(serverMsg[1])) + + if getUser is None: + return None + + response_351 = f"{self.__Config.SERVICE_NAME.capitalize()}-{self.__Config.CURRENT_VERSION} {self.__Config.SERVICE_HOST} {self.name}" + self.send2socket(f':{self.__Config.SERVICE_HOST} 351 {getUser.nickname} {response_351}') + + modules = self.__Base.get_all_modules() + response_005 = ' | '.join(modules) + self.send2socket(f':{self.__Config.SERVICE_HOST} 005 {getUser.nickname} {response_005} are supported by this server') - if getUser is None: return None - self.send2socket(f'{self.__Config.SERVEUR_ID} 351 {getUser.nickname} {self.__Config.CURRENT_VERSION} {self.__Config.SERVICE_NAME} *:') \ No newline at end of file + except Exception as err: + self.__Base.logs.error(f"{__name__} - General Error: {err}") diff --git a/core/classes/settings.py b/core/classes/settings.py index 1060ae9..ac3f4cf 100644 --- a/core/classes/settings.py +++ b/core/classes/settings.py @@ -9,4 +9,4 @@ class Settings: PERIODIC_FUNC: dict[object] = {} LOCK: RLock = RLock() - CONSOLE: bool = True + CONSOLE: bool = False diff --git a/core/definition.py b/core/definition.py index a31c25b..ac557b7 100644 --- a/core/definition.py +++ b/core/definition.py @@ -208,6 +208,9 @@ class MConfig: DEBUG_LEVEL:Literal[10, 20, 30, 40, 50] = 20 """Logs level: DEBUG 10 | INFO 20 | WARNING 30 | ERROR 40 | CRITICAL 50. (default: 20)""" + LOGGING_NAME: str = "defender" + """The name of the Logging instance""" + TABLE_ADMIN: str = "core_admin" """Admin table""" diff --git a/core/irc.py b/core/irc.py index 010ec66..9b4d606 100644 --- a/core/irc.py +++ b/core/irc.py @@ -49,6 +49,9 @@ class Irc: # Use Base Instance self.Base = self.Loader.Base + # Logger + self.Logs = self.Loader.Base.logs + # Get Settings. self.Settings = self.Base.Settings @@ -66,7 +69,7 @@ class Irc: # Use Reputation Instance self.Reputation = self.Loader.Reputation - + self.autolimit_started: bool = False """This variable is to make sure the thread is not running""" @@ -107,7 +110,7 @@ class Irc: self.__create_socket() self.__connect_to_irc(ircInstance) except AssertionError as ae: - self.Base.logs.critical(f'Assertion error: {ae}') + self.Logs.critical(f'Assertion error: {ae}') def init_service_user(self) -> None: @@ -135,34 +138,34 @@ class Irc: ssl_connexion.connect(connexion_information) self.IrcSocket:SSLSocket = ssl_connexion self.Config.SSL_VERSION = self.IrcSocket.version() - self.Base.logs.info(f"Connexion en mode SSL : Version = {self.Config.SSL_VERSION}") + self.Logs.info(f"Connexion en mode SSL : Version = {self.Config.SSL_VERSION}") else: soc.connect(connexion_information) self.IrcSocket:socket.socket = soc - self.Base.logs.info("Connexion en mode normal") + self.Logs.info("Connexion en mode normal") return None except ssl.SSLEOFError as soe: - self.Base.logs.critical(f"SSLEOFError: {soe} - {soc.fileno()}") + self.Logs.critical(f"SSLEOFError: {soe} - {soc.fileno()}") except ssl.SSLError as se: - self.Base.logs.critical(f"SSLError: {se} - {soc.fileno()}") + self.Logs.critical(f"SSLError: {se} - {soc.fileno()}") except OSError as oe: - self.Base.logs.critical(f"OSError: {oe} - {soc.fileno()}") + self.Logs.critical(f"OSError: {oe} - {soc.fileno()}") if 'connection refused' in str(oe).lower(): sys.exit(oe) if soc.fileno() == -1: sys.exit(soc.fileno()) except AttributeError as ae: - self.Base.logs.critical(f"AttributeError: {ae} - {soc.fileno()}") + self.Logs.critical(f"AttributeError: {ae} - {soc.fileno()}") def __ssl_context(self) -> ssl.SSLContext: ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE - self.Base.logs.debug(f'SSLContext initiated with verified mode {ctx.verify_mode}') + self.Logs.debug(f'SSLContext initiated with verified mode {ctx.verify_mode}') return ctx @@ -172,7 +175,7 @@ class Irc: self.init_service_user() self.ircObject = ircInstance # créer une copie de l'instance Irc self.Protocol = Protocol( - protocol=self.Config.SERVEUR_PROTOCOL, + protocol=self.Config.SERVEUR_PROTOCOL, ircInstance=self.ircObject ).Protocol self.Protocol.link() # Etablir le link en fonction du protocol choisi @@ -183,16 +186,16 @@ class Irc: while self.signal: try: if self.Config.DEFENDER_RESTART == 1: - self.Base.logs.debug('Restarting Defender ...') + self.Logs.debug('Restarting Defender ...') self.IrcSocket.shutdown(socket.SHUT_RDWR) self.IrcSocket.close() while self.IrcSocket.fileno() != -1: time.sleep(0.5) - self.Base.logs.warning('--> Waiting for socket to close ...') + self.Logs.warning('--> Waiting for socket to close ...') # Reload configuration - self.Base.logs.debug('Reloading configuration') + self.Logs.debug('Reloading configuration') self.Config = self.Loader.ConfModule.Configuration().ConfigObject self.Base = self.Loader.BaseModule.Base(self.Config, self.Settings) self.Protocol = Protocol(self.Config.SERVEUR_PROTOCOL, ircInstance).Protocol @@ -224,30 +227,30 @@ class Irc: self.send_response(data) except ssl.SSLEOFError as soe: - self.Base.logs.error(f"SSLEOFError __connect_to_irc: {soe} - {data}") + self.Logs.error(f"SSLEOFError __connect_to_irc: {soe} - {data}") except ssl.SSLError as se: - self.Base.logs.error(f"SSLError __connect_to_irc: {se} - {data}") + self.Logs.error(f"SSLError __connect_to_irc: {se} - {data}") except OSError as oe: - self.Base.logs.error(f"SSLError __connect_to_irc: {oe} - {data}") + self.Logs.error(f"SSLError __connect_to_irc: {oe} - {data}") except (socket.error, ConnectionResetError): print("Connexion reset") self.IrcSocket.shutdown(socket.SHUT_RDWR) self.IrcSocket.close() - self.Base.logs.info("--> Fermeture de Defender ...") + self.Logs.info("--> Fermeture de Defender ...") sys.exit(0) except AssertionError as ae: - self.Base.logs.error(f'AssertionError: {ae}') + self.Logs.error(f'AssertionError: {ae}') except ValueError as ve: - self.Base.logs.error(f'ValueError: {ve}') + self.Logs.error(f'ValueError: {ve}') except ssl.SSLEOFError as soe: - self.Base.logs.error(f"SSLEOFError: {soe}") + self.Logs.error(f"SSLEOFError: {soe}") except AttributeError as atte: - self.Base.logs.critical(f"AttributeError: {atte}") + self.Logs.critical(f"AttributeError: {atte}") except Exception as e: - self.Base.logs.critical(f"General Error: {e}") - self.Base.logs.critical(traceback.format_exc()) + self.Logs.critical(f"General Error: {e}") + self.Logs.critical(traceback.format_exc()) def __join_saved_channels(self) -> None: """## Joining saved channels""" @@ -262,67 +265,32 @@ class Irc: chan = chan_name[0] self.Protocol.sjoin(channel=chan) - def send2socket(self, send_message:str, print_log: bool = True) -> None: - """Envoit les commandes à envoyer au serveur. - - Args: - string (Str): contient la commande à envoyer au serveur. - """ - try: - with self.Base.lock: - self.IrcSocket.send(f"{send_message}\r\n".encode(self.CHARSET[0])) - if print_log: - self.Base.logs.debug(f'< {send_message}') - - except UnicodeDecodeError: - self.Base.logs.error(f'Decode Error try iso-8859-1 - message: {send_message}') - self.IrcSocket.send(f"{send_message}\r\n".encode(self.CHARSET[0],'replace')) - except UnicodeEncodeError: - self.Base.logs.error(f'Encode Error try iso-8859-1 - message: {send_message}') - self.IrcSocket.send(f"{send_message}\r\n".encode(self.CHARSET[0],'replace')) - except AssertionError as ae: - self.Base.logs.warning(f'Assertion Error {ae} - message: {send_message}') - except ssl.SSLEOFError as soe: - self.Base.logs.error(f"SSLEOFError: {soe} - {send_message}") - except ssl.SSLError as se: - self.Base.logs.error(f"SSLError: {se} - {send_message}") - 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 + # def send2socket(self, send_message:str, print_log: bool = True) -> None: + # """Envoit les commandes à envoyer au serveur. # Args: - # msg (str): The message to send to the server - # nickname (str): The reciever Nickname + # string (Str): contient la commande à envoyer au serveur. # """ - # batch_size = self.Config.BATCH_SIZE - # service_nickname = self.Config.SERVICE_NICKNAME + # try: + # with self.Base.lock: + # self.IrcSocket.send(f"{send_message}\r\n".encode(self.CHARSET[0])) + # if print_log: + # self.Logs.debug(f'< {send_message}') - # 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}") + # except UnicodeDecodeError: + # self.Logs.error(f'Decode Error try iso-8859-1 - message: {send_message}') + # self.IrcSocket.send(f"{send_message}\r\n".encode(self.CHARSET[0],'replace')) + # except UnicodeEncodeError: + # self.Logs.error(f'Encode Error try iso-8859-1 - message: {send_message}') + # self.IrcSocket.send(f"{send_message}\r\n".encode(self.CHARSET[0],'replace')) + # except AssertionError as ae: + # self.Logs.warning(f'Assertion Error {ae} - message: {send_message}') + # except ssl.SSLEOFError as soe: + # self.Logs.error(f"SSLEOFError: {soe} - {send_message}") + # except ssl.SSLError as se: + # self.Logs.error(f"SSLError: {se} - {send_message}") + # except OSError as oe: + # self.Logs.error(f"OSError: {oe} - {send_message}") def send_response(self, responses:list[bytes]) -> None: try: @@ -335,18 +303,18 @@ class Irc: for data in responses: response = data.decode(self.CHARSET[1],'replace').split() self.cmd(response) - self.Base.logs.error(f'UnicodeEncodeError: {ue}') - self.Base.logs.error(response) + self.Logs.error(f'UnicodeEncodeError: {ue}') + self.Logs.error(response) except UnicodeDecodeError as ud: for data in responses: response = data.decode(self.CHARSET[1],'replace').split() self.cmd(response) - self.Base.logs.error(f'UnicodeDecodeError: {ud}') - self.Base.logs.error(response) + self.Logs.error(f'UnicodeDecodeError: {ud}') + self.Logs.error(response) except AssertionError as ae: - self.Base.logs.error(f"Assertion error : {ae}") + self.Logs.error(f"Assertion error : {ae}") def unload(self) -> None: # This is only to reference the method @@ -405,7 +373,7 @@ class Irc: # 2. Executer la fonction try: if not class_name in self.loaded_classes: - self.Base.logs.error(f"La class [{class_name} n'existe pas !!]") + self.Logs.error(f"La class [{class_name} n'existe pas !!]") return False class_instance = self.loaded_classes[class_name] @@ -415,12 +383,12 @@ class Irc: self.Base.running_timers.append(t) - self.Base.logs.debug(f"Timer ID : {str(t.ident)} | Running Threads : {len(threading.enumerate())}") + self.Logs.debug(f"Timer ID : {str(t.ident)} | Running Threads : {len(threading.enumerate())}") except AssertionError as ae: - self.Base.logs.error(f'Assertion Error -> {ae}') + self.Logs.error(f'Assertion Error -> {ae}') except TypeError as te: - self.Base.logs.error(f"Type error -> {te}") + self.Logs.error(f"Type error -> {te}") def __create_tasks(self, obj: object, method_name: str, param:list) -> None: """#### Ajouter les méthodes a éxecuter dans un dictionnaire @@ -439,7 +407,7 @@ class Irc: 'param': param } - self.Base.logs.debug(f'Function to execute : {str(self.Base.periodic_func)}') + self.Logs.debug(f'Function to execute : {str(self.Base.periodic_func)}') self.send_ping_to_sereur() return None @@ -462,8 +430,8 @@ class Irc: # Si le module est déja chargé if 'mods.' + module_name in sys.modules: - self.Base.logs.info("Module déja chargé ...") - self.Base.logs.info('module name = ' + module_name) + self.Logs.info("Module déja chargé ...") + self.Logs.info('module name = ' + module_name) if class_name in self.loaded_classes: # Si le module existe dans la variable globale retourne False self.Protocol.sendPrivMsg( @@ -502,7 +470,7 @@ class Irc: msg=f"Module {module_name} ne contient pas de méthode cmd", channel=self.Config.SERVICE_CHANLOG ) - self.Base.logs.critical(f"The Module {module_name} has not been loaded because cmd method is not available") + self.Logs.critical(f"The Module {module_name} has not been loaded because cmd method is not available") self.Base.db_delete_module(module_name) return False @@ -512,31 +480,33 @@ class Irc: # Enregistrer le module dans la base de données if not init: self.Base.db_record_module(fromuser, module_name) + self.Protocol.sendPrivMsg( nick_from=self.Config.SERVICE_NICKNAME, msg=f"Module {module_name} chargé", channel=self.Config.SERVICE_CHANLOG ) - # self.Base.logs.info(self.loaded_classes) - self.Base.logs.info(f"Module {class_name} has been loaded") + self.Logs.info(f"Module {class_name} has been loaded") + return True except ModuleNotFoundError as moduleNotFound: - self.Base.logs.error(f"MODULE_NOT_FOUND: {moduleNotFound}") + self.Logs.error(f"MODULE_NOT_FOUND: {moduleNotFound}") self.Protocol.sendPrivMsg( nick_from=self.Config.SERVICE_NICKNAME, msg=f"[ {self.Config.COLORS.red}MODULE_NOT_FOUND{self.Config.COLORS.black} ]: {moduleNotFound}", channel=self.Config.SERVICE_CHANLOG ) 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}") + except Exception as err: + self.Logs.error(f"Something went wrong with a module you want to load : {err}") self.Protocol.sendPrivMsg( nick_from=self.Config.SERVICE_NICKNAME, - msg=f"[ {self.Config.COLORS.red}ERROR{self.Config.COLORS.black} ]: {e}", + msg=f"[ {self.Config.COLORS.red}ERROR{self.Config.COLORS.black} ]: {err}", channel=self.Config.SERVICE_CHANLOG ) + self.Base.db_delete_module(module_name) def unload_module(self, mod_name: str) -> bool: """Unload a module @@ -572,7 +542,7 @@ class Irc: return True except Exception as err: - self.Base.logs.error(f"General Error: {err}") + self.Logs.error(f"General Error: {err}") return False def reload_module(self, from_user: str, mod_name: str) -> bool: @@ -581,9 +551,9 @@ class Irc: class_name = module_name.split('_')[1].capitalize() # ==> Defender if 'mods.' + module_name in sys.modules: - self.Base.logs.info('Unload the module ...') + self.Logs.info('Unload the module ...') self.loaded_classes[class_name].unload() - self.Base.logs.info('Module Already Loaded ... reloading the module ...') + self.Logs.info('Module Already Loaded ... reloading the module ...') the_module = sys.modules['mods.' + module_name] importlib.reload(the_module) @@ -617,7 +587,7 @@ class Irc: ) except TypeError as te: - self.Base.logs.error(f"A TypeError raised: {te}") + self.Logs.error(f"A TypeError raised: {te}") self.Protocol.sendPrivMsg( nick_from=self.Config.SERVICE_NICKNAME, msg=f"A TypeError raised: {te}", @@ -625,7 +595,7 @@ class Irc: ) self.Base.db_delete_module(module_name) except AttributeError as ae: - self.Base.logs.error(f"Missing Attribute: {ae}") + self.Logs.error(f"Missing Attribute: {ae}") self.Protocol.sendPrivMsg( nick_from=self.Config.SERVICE_NICKNAME, msg=f"Missing Attribute: {ae}", @@ -633,7 +603,7 @@ class Irc: ) self.Base.db_delete_module(module_name) except KeyError as ke: - self.Base.logs.error(f"Key Error: {ke}") + self.Logs.error(f"Key Error: {ke}") self.Protocol.sendPrivMsg( nick_from=self.Config.SERVICE_NICKNAME, msg=f"Key Error: {ke}", @@ -641,7 +611,7 @@ class Irc: ) 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 reload: {e}") + self.Logs.error(f"Something went wrong with a module you want to reload: {e}") self.Protocol.sendPrivMsg( nick_from=self.Config.SERVICE_NICKNAME, msg=f"Something went wrong with the module: {e}", @@ -673,7 +643,7 @@ class Irc: return None if not self.Admin.delete(uid): - self.Base.logs.critical(f'UID: {uid} was not deleted') + self.Logs.critical(f'UID: {uid} was not deleted') return None @@ -682,7 +652,7 @@ class Irc: get_user = self.User.get_User(nickname) if get_user is None: response = f'This nickname {nickname} does not exist, it is not possible to create this user' - self.Base.logs.warning(response) + self.Logs.warning(response) return response nickname = get_user.nickname @@ -690,7 +660,7 @@ class Irc: if level > 4: response = "Impossible d'ajouter un niveau > 4" - self.Base.logs.warning(response) + self.Logs.warning(response) return response hostname = get_user.hostname @@ -711,12 +681,12 @@ class Irc: ''', mes_donnees) response = f"{nickname} ajouté en tant qu'administrateur de niveau {level}" self.Protocol.sendNotice(nick_from=self.Config.SERVICE_NICKNAME, nick_to=nickname, msg=response) - self.Base.logs.info(response) + self.Logs.info(response) return response else: response = f'{nickname} Existe déjà dans les users enregistrés' self.Protocol.sendNotice(nick_from=self.Config.SERVICE_NICKNAME, nick_to=nickname, msg=response) - self.Base.logs.info(response) + self.Logs.info(response) return response def is_cmd_allowed(self, nickname:str, cmd:str) -> bool: @@ -789,18 +759,18 @@ class Irc: interm_response.pop(0) if len(original_response) == 0 or len(original_response) == 1: - self.Base.logs.warning(f'Size ({str(len(original_response))}) - {original_response}') + self.Logs.warning(f'Size ({str(len(original_response))}) - {original_response}') return False if len(original_response) == 7: if original_response[2] == 'PRIVMSG' and original_response[4] == ':auth': data_copy = original_response.copy() data_copy[6] = '**********' - self.Base.logs.debug(f">> {data_copy}") + self.Logs.debug(f">> {data_copy}") else: - self.Base.logs.debug(f">> {original_response}") + self.Logs.debug(f">> {original_response}") else: - self.Base.logs.debug(f">> {original_response}") + self.Logs.debug(f">> {original_response}") match original_response[0]: @@ -814,12 +784,9 @@ class Irc: # 'PREFIX=(qaohv)~&@%+', 'SID=001', 'MLOCK', 'TS=1703793941', 'EXTSWHOIS'] # GET SERVER ID HOST - if len(original_response) > 5: - if '=' in original_response[5]: - serveur_hosting_id = str(original_response[5]).split('=') - self.HSID = serveur_hosting_id[1] - self.Config.HSID = serveur_hosting_id[1] - return False + self.Protocol.on_protoctl(serverMsg=original_response) + + return None case _: pass @@ -840,15 +807,8 @@ class Irc: self.Protocol.on_umode2(serverMsg=original_response) case 'SQUIT': - # ['@msgid=QOEolbRxdhpVW5c8qLkbAU;time=2024-09-21T17:33:16.547Z', 'SQUIT', 'defender.deb.biz.st', ':Connection', 'closed'] - server_hostname = interm_response[1] - uid_to_delete = '' - for s_user in self.User.UID_DB: - if s_user.hostname == server_hostname and 'S' in s_user.umodes: - uid_to_delete = s_user.uid - self.User.delete(uid_to_delete) - self.Channel.delete_user_from_all_channel(uid_to_delete) + self.Protocol.on_squit(serverMsg=original_response) case 'REPUTATION': # :001 REPUTATION 127.0.0.1 118 @@ -868,10 +828,10 @@ class Irc: # Possibilité de déclancher les bans a ce niveau. except IndexError as ie: - self.Base.logs.error(f'{ie}') + self.Logs.error(f'{ie}') except ValueError as ve: self.first_score = 0 - self.Base.logs.error(f'Impossible to convert first_score: {ve}') + self.Logs.error(f'Impossible to convert first_score: {ve}') case '320': #:irc.deb.biz.st 320 PyDefender IRCParis07 :is in security-groups: known-users,webirc-users,tls-and-known-users,tls-users @@ -908,16 +868,16 @@ class Irc: print(f"# VERSION : {version} ") print(f"################################################") - self.Base.logs.info(f"################### DEFENDER ###################") - self.Base.logs.info(f"# SERVICE CONNECTE ") - self.Base.logs.info(f"# SERVEUR : {self.Config.SERVEUR_IP} ") - self.Base.logs.info(f"# PORT : {self.Config.SERVEUR_PORT} ") - self.Base.logs.info(f"# SSL : {self.Config.SERVEUR_SSL} ") - self.Base.logs.info(f"# SSL VER : {self.Config.SSL_VERSION} ") - self.Base.logs.info(f"# NICKNAME : {self.Config.SERVICE_NICKNAME} ") - self.Base.logs.info(f"# CHANNEL : {self.Config.SERVICE_CHANLOG} ") - self.Base.logs.info(f"# VERSION : {version} ") - self.Base.logs.info(f"################################################") + self.Logs.info(f"################### DEFENDER ###################") + self.Logs.info(f"# SERVICE CONNECTE ") + self.Logs.info(f"# SERVEUR : {self.Config.SERVEUR_IP} ") + self.Logs.info(f"# PORT : {self.Config.SERVEUR_PORT} ") + self.Logs.info(f"# SSL : {self.Config.SERVEUR_SSL} ") + self.Logs.info(f"# SSL VER : {self.Config.SSL_VERSION} ") + self.Logs.info(f"# NICKNAME : {self.Config.SERVICE_NICKNAME} ") + self.Logs.info(f"# CHANNEL : {self.Config.SERVICE_CHANLOG} ") + self.Logs.info(f"# VERSION : {version} ") + self.Logs.info(f"################################################") if self.Base.check_for_new_version(False): self.Protocol.sendPrivMsg( @@ -950,7 +910,6 @@ class Irc: match original_response[2]: case 'VERSION': - self.Protocol.on_version_msg(original_response) case 'QUIT': @@ -978,7 +937,7 @@ class Irc: case 'PART': self.Protocol.on_part(serverMsg=original_response) - + case 'UID': try: self.Protocol.on_uid(serverMsg=original_response) @@ -987,7 +946,7 @@ class Irc: classe_object.cmd(original_response) except Exception as err: - self.Base.logs.error(f'General Error: {err}') + self.Logs.error(f'General Error: {err}') case 'PRIVMSG': try: @@ -1002,11 +961,11 @@ class Irc: if cmd[1] == 'PRIVMSG' and str(cmd[3]).replace(self.Config.SERVICE_PREFIX,'') == ':auth': cmd_copy = cmd.copy() cmd_copy[5] = '**********' - self.Base.logs.info(f'>> {cmd_copy}') + self.Logs.info(f'>> {cmd_copy}') else: - self.Base.logs.info(f'>> {cmd}') + self.Logs.info(f'>> {cmd}') else: - self.Base.logs.info(f'>> {cmd}') + self.Logs.info(f'>> {cmd}') pattern = fr'(:\{self.Config.SERVICE_PREFIX})(.*)$' hcmds = re.search(pattern, ' '.join(cmd)) # va matcher avec tout les caractéres aprés le . @@ -1017,7 +976,7 @@ class Irc: arg = convert_to_string.split() arg.remove(f':{self.Config.SERVICE_PREFIX}') if not arg[0].lower() in self.commands: - self.Base.logs.debug(f"This command {arg[0]} is not available") + self.Logs.debug(f"This command {arg[0]} is not available") self.Protocol.sendNotice( nick_from=self.Config.SERVICE_NICKNAME, nick_to=user_trigger, @@ -1057,7 +1016,7 @@ class Irc: return False if not arg[0].lower() in self.commands: - self.Base.logs.debug(f"This command {arg[0]} sent by {user_trigger} is not available") + self.Logs.debug(f"This command {arg[0]} sent by {user_trigger} is not available") return False cmd_to_send = convert_to_string.replace(':','') @@ -1070,7 +1029,7 @@ class Irc: self._hcmds(user_trigger, fromchannel, arg, cmd) except IndexError as io: - self.Base.logs.error(f'{io}') + self.Logs.error(f'{io}') case _: pass @@ -1081,10 +1040,10 @@ class Irc: classe_object.cmd(original_response) except IndexError as ie: - self.Base.logs.error(f"{ie} / {original_response} / length {str(len(original_response))}") + self.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()}") + self.Logs.error(f"General Error: {err}") + self.Logs.error(f"General Error: {traceback.format_exc()}") def _hcmds(self, user: str, channel: Union[str, None], cmd: list, fullcmd: list = []) -> None: """_summary_ @@ -1138,7 +1097,7 @@ class Irc: ) except IndexError as ie: - self.Base.logs.error(f'{ie}') + self.Logs.error(f'{ie}') case 'deauth': @@ -1171,7 +1130,7 @@ class Irc: return False if current_nickname is None: - self.Base.logs.critical(f"This nickname [{fromuser}] don't exist") + self.Logs.critical(f"This nickname [{fromuser}] don't exist") return False # Credentials sent from the user @@ -1183,7 +1142,7 @@ class Irc: config_password = self.Config.PASSWORD if current_nickname != cmd_owner: - self.Base.logs.critical(f"The current nickname [{fromuser}] is different than the nickname sent [{cmd_owner}] !") + self.Logs.critical(f"The current nickname [{fromuser}] is different than the nickname sent [{cmd_owner}] !") self.Protocol.sendNotice( nick_from=dnickname, nick_to=fromuser, @@ -1192,7 +1151,7 @@ class Irc: return False if current_nickname != config_owner: - self.Base.logs.critical(f"The current nickname [{current_nickname}] is different than the configuration owner [{config_owner}] !") + self.Logs.critical(f"The current nickname [{current_nickname}] is different than the configuration owner [{config_owner}] !") self.Protocol.sendNotice( nick_from=dnickname, nick_to=fromuser, @@ -1201,7 +1160,7 @@ class Irc: return False if cmd_owner != config_owner: - self.Base.logs.critical(f"The nickname sent [{cmd_owner}] is different than the configuration owner [{config_owner}] !") + self.Logs.critical(f"The nickname sent [{cmd_owner}] is different than the configuration owner [{config_owner}] !") self.Protocol.sendNotice( nick_from=dnickname, nick_to=fromuser, @@ -1283,13 +1242,13 @@ class Irc: response = self.create_defender_user(newnickname, newlevel, password) self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f"{response}") - self.Base.logs.info(response) + self.Logs.info(response) except IndexError as ie: - self.Base.logs.error(f'_hcmd addaccess: {ie}') + self.Logs.error(f'_hcmd addaccess: {ie}') self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} addaccess [nickname] [level] [password]") except TypeError as te: - self.Base.logs.error(f'_hcmd addaccess: out of index : {te}') + self.Logs.error(f'_hcmd addaccess: out of index : {te}') self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} addaccess [nickname] [level] [password]") case 'editaccess': @@ -1343,9 +1302,9 @@ class Irc: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" Impossible de modifier l'utilisateur {str(user_new_level)}") except TypeError as te: - self.Base.logs.error(f"Type error : {te}") + self.Logs.error(f"Type error : {te}") except ValueError as ve: - self.Base.logs.error(f"Value Error : {ve}") + self.Logs.error(f"Value Error : {ve}") self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" {self.Config.SERVICE_PREFIX}editaccess [USER] [NEWPASSWORD] [NEWLEVEL]") case 'delaccess': @@ -1355,7 +1314,7 @@ class Irc: if user_to_del != user_confirmation: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f"Les user ne sont pas les mêmes, tu dois confirmer le user que tu veux supprimer") - self.Base.logs.warning(f':{dnickname} NOTICE {fromuser} : Les user ne sont pas les mêmes, tu dois confirmer le user que tu veux supprimer') + self.Logs.warning(f':{dnickname} NOTICE {fromuser} : Les user ne sont pas les mêmes, tu dois confirmer le user que tu veux supprimer') return None if len(cmd) < 3: @@ -1382,7 +1341,7 @@ class Irc: level_user_to_del = info_user[1] if current_user_level <= level_user_to_del: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f"You are not allowed to delete this access") - self.Base.logs.warning(f':{dnickname} NOTICE {fromuser} : You are not allowed to delete this access') + self.Logs.warning(f':{dnickname} NOTICE {fromuser} : You are not allowed to delete this access') return None data_to_delete = {'user': user_to_del} @@ -1393,7 +1352,7 @@ class Irc: self.Admin.delete(user_to_del) else: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f"Impossible de supprimer l'utilisateur.") - self.Base.logs.warning(f":{dnickname} NOTICE {fromuser} : Impossible de supprimer l'utilisateur.") + self.Logs.warning(f":{dnickname} NOTICE {fromuser} : Impossible de supprimer l'utilisateur.") case 'help': @@ -1432,9 +1391,9 @@ class Irc: mod_name = str(cmd[1]) self.load_module(fromuser, mod_name) except KeyError as ke: - self.Base.logs.error(f"Key Error: {ke} - list recieved: {cmd}") + self.Logs.error(f"Key Error: {ke} - list recieved: {cmd}") except Exception as err: - self.Base.logs.error(f"General Error: {ke} - list recieved: {cmd}") + self.Logs.error(f"General Error: {ke} - list recieved: {cmd}") case 'unload': # unload mod_defender @@ -1442,7 +1401,7 @@ class Irc: module_name = str(cmd[1]).lower() # Le nom du module. exemple: mod_defender self.unload_module(module_name) except Exception as err: - self.Base.logs.error(f"General Error: {err}") + self.Logs.error(f"General Error: {err}") case 'reload': # reload mod_defender @@ -1450,7 +1409,7 @@ class Irc: module_name = str(cmd[1]).lower() # ==> mod_defender self.reload_module(from_user=fromuser, mod_name=module_name) except Exception as e: - self.Base.logs.error(f"Something went wrong with a module you want to reload: {e}") + self.Logs.error(f"Something went wrong with a module you want to reload: {e}") self.Protocol.sendPrivMsg( nick_from=dnickname, msg=f"Something went wrong with the module: {e}", @@ -1473,12 +1432,12 @@ class Irc: msg=f"Arrêt du service {dnickname}" ) self.Protocol.squit(server_id=self.Config.SERVEUR_ID, server_link=self.Config.SERVEUR_LINK, reason=final_reason) - self.Base.logs.info(f'Arrêt du server {dnickname}') + self.Logs.info(f'Arrêt du server {dnickname}') self.Config.DEFENDER_RESTART = 0 self.signal = False except IndexError as ie: - self.Base.logs.error(f'{ie}') + self.Logs.error(f'{ie}') case 'restart': reason = [] @@ -1499,7 +1458,7 @@ class Irc: self.Channel.UID_CHANNEL_DB.clear() # Clear Channel Object self.Protocol.squit(server_id=self.Config.SERVEUR_ID, server_link=self.Config.SERVEUR_LINK, reason=final_reason) - self.Base.logs.info(f'Redémarrage du server {dnickname}') + self.Logs.info(f'Redémarrage du server {dnickname}') self.loaded_classes.clear() self.Config.DEFENDER_RESTART = 1 # Set restart status to 1 saying that the service will restart self.Config.DEFENDER_INIT = 1 # set init to 1 saying that the service will be re initiated @@ -1554,6 +1513,7 @@ class Irc: self.Config.SERVEUR_ID = serveur_id self.Protocol.sendPrivMsg(nick_from=self.Config.SERVICE_NICKNAME, msg='You need to restart defender !', channel=self.Config.SERVICE_CHANLOG) + self.Base.delete_logger(self.Config.LOGGING_NAME) self.Base = self.Loader.BaseModule.Base(self.Config, self.Settings) importlib.reload(mod_unreal6) @@ -1572,7 +1532,7 @@ class Irc: case 'show_modules': - self.Base.logs.debug(self.loaded_classes) + self.Logs.debug(self.loaded_classes) all_modules = self.Base.get_all_modules() loaded = False diff --git a/mods/mod_clone.py b/mods/mod_clone.py index 4b78070..ba74390 100644 --- a/mods/mod_clone.py +++ b/mods/mod_clone.py @@ -305,14 +305,13 @@ class Clone(): ) except Exception as err: - self.Base.logs.error(f'General Error: {err}') + self.Logs.error(f'General Error: {err}') def _hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None: try: command = str(cmd[0]).lower() fromuser = user - print(command) dnickname = self.Config.SERVICE_NICKNAME # Defender nickname diff --git a/mods/mod_command.py b/mods/mod_command.py index 3198c0d..758d6b6 100644 --- a/mods/mod_command.py +++ b/mods/mod_command.py @@ -160,9 +160,9 @@ class Command(): nick_to=self.user_to_notice, msg=f"[{red}ERROR MSG{nogc}] {message}" ) - self.Base.logs.error(f"{cmd[1]} - {message}") + self.Logs.error(f"{cmd[1]} - {message}") except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Logs.warning(f'Unknown Error: {str(err)}') @@ -177,7 +177,7 @@ class Command(): msg=f"[{green}SERVER MSG{nogc}] {message}" ) except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Logs.warning(f'Unknown Error: {str(err)}') @@ -200,7 +200,7 @@ class Command(): self.Protocol.sendNotice(nick_from=dnickname,nick_to=self.user_to_notice, msg="No kline") except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Logs.warning(f'Unknown Error: {str(err)}') @@ -217,7 +217,7 @@ class Command(): ) except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Logs.warning(f'Unknown Error: {str(err)}') @@ -708,7 +708,7 @@ class Command(): self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f"You need to specify the topic") except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Logs.warning(f'Unknown Error: {str(err)}') @@ -726,7 +726,7 @@ class Command(): self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f"You need to specify the wallops message") except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Logs.warning(f'Unknown Error: {str(err)}') @@ -744,7 +744,7 @@ class Command(): self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f"You need to specify the globops message") except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Logs.warning(f'Unknown Error: {str(err)}') @@ -762,7 +762,7 @@ class Command(): self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f"You need to specify the global notice message") except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Logs.warning(f'Unknown Error: {str(err)}') @@ -783,7 +783,7 @@ class Command(): self.Protocol.send2socket(f':{dnickname} WHOIS {nickname}') except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Logs.warning(f'Unknown Error: {str(err)}') @@ -803,7 +803,7 @@ class Command(): self.Protocol.send2socket(f':{dnickname} NAMES {chan}') except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Logs.warning(f'Unknown Error: {str(err)}') @@ -829,7 +829,7 @@ class Command(): self.Protocol.send2socket(f':{dnickname} INVITE {nickname} {chan}') except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Logs.warning(f'Unknown Error: {str(err)}') @@ -842,7 +842,7 @@ class Command(): self.Protocol.send2socket(f':{dnickname} INVITE {fromuser} {self.Config.SERVICE_CHANLOG}') except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Logs.warning(f'Unknown Error: {str(err)}') @@ -852,7 +852,7 @@ class Command(): self.Protocol.send2socket(f':{dnickname} MAP') except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Logs.warning(f'Unknown Error: {str(err)}') @@ -868,7 +868,7 @@ class Command(): self.Protocol.send2socket(f':{dnickname} SVSMODE {nickname} {umode}') except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Logs.warning(f'Unknown Error: {str(err)}') @@ -920,7 +920,7 @@ class Command(): self.Protocol.send2socket(f':{self.Config.SERVEUR_ID} SVSJOIN {nickname} {channel}') except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" /msg {dnickname} SVSJOIN nickname #channel") self.Logs.warning(f'Unknown Error: {str(err)}') @@ -936,7 +936,7 @@ class Command(): self.Protocol.send2socket(f':{self.Config.SERVEUR_ID} SVSPART {nickname} {channel}') except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" /msg {dnickname} SVSPART nickname #channel") self.Logs.warning(f'Unknown Error: {str(err)}') @@ -952,7 +952,7 @@ class Command(): self.Protocol.send2socket(f':{self.Config.SERVEUR_ID} SAJOIN {nickname} {channel}') except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" /msg {dnickname} {command.upper()} nickname #channel") self.Logs.warning(f'Unknown Error: {str(err)}') @@ -968,7 +968,7 @@ class Command(): self.Protocol.send2socket(f':{self.Config.SERVEUR_ID} SAPART {nickname} {channel}') except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" /msg {dnickname} {command.upper()} nickname #channel") self.Logs.warning(f'Unknown Error: {str(err)}') @@ -991,7 +991,7 @@ class Command(): self.Protocol.send2socket(f':{self.Config.SERVEUR_ID} SVSNICK {nickname} {newnickname} {unixtime}') except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" /msg {dnickname} {command.upper()} nickname newnickname") self.Logs.warning(f'Unknown Error: {str(err)}') @@ -1009,7 +1009,7 @@ class Command(): self.Protocol.send2socket(f":{service_id} KILL {nickname} {kill_reason} ({self.Config.COLORS.red}{dnickname}{self.Config.COLORS.nogc})") except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" /msg {dnickname} SVSNICK nickname newnickname") self.Logs.warning(f'Unknown Error: {str(err)}') @@ -1036,7 +1036,7 @@ class Command(): self.Protocol.gline(nickname=nickname, hostname=hostname, set_by=dnickname, expire_timestamp=expire_time, set_at_timestamp=set_at_timestamp, reason=gline_reason) except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" /msg {dnickname} {command.upper()} nickname host reason") self.Logs.warning(f'Unknown Error: {str(err)}') @@ -1057,7 +1057,7 @@ class Command(): self.Protocol.ungline(nickname=nickname, hostname=hostname) except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" /msg {dnickname} {command.upper()} nickname hostname") self.Logs.warning(f'Unknown Error: {str(err)}') @@ -1084,7 +1084,7 @@ class Command(): self.Protocol.kline(nickname=nickname, hostname=hostname, set_by=dnickname, expire_timestamp=expire_time, set_at_timestamp=set_at_timestamp, reason=gline_reason) except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" /msg {dnickname} {command.upper()} nickname host reason") self.Logs.warning(f'Unknown Error: {str(err)}') @@ -1104,7 +1104,7 @@ class Command(): self.Protocol.unkline(nickname=nickname, hostname=hostname) except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" /msg {dnickname} {command.upper()} nickname hostname") self.Logs.warning(f'Unknown Error: {str(err)}') @@ -1131,7 +1131,7 @@ class Command(): self.Protocol.send2socket(f":{self.Config.SERVEUR_ID} TKL + s {nickname} {hostname} {dnickname} {expire_time} {set_at_timestamp} :{shun_reason}") except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" /msg {dnickname} {command.upper()} nickname host reason") self.Logs.warning(f'Unknown Error: {str(err)}') @@ -1151,7 +1151,7 @@ class Command(): self.Protocol.send2socket(f":{self.Config.SERVEUR_ID} TKL - s {nickname} {hostname} {dnickname}") except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" /msg {dnickname} {command.upper()} nickname hostname") self.Logs.warning(f'Unknown Error: {str(err)}') @@ -1162,7 +1162,7 @@ class Command(): self.Protocol.send2socket(f":{self.Config.SERVICE_ID} STATS G") except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" /msg {dnickname} {command.upper()}") self.Logs.warning(f'Unknown Error: {str(err)}') @@ -1173,7 +1173,7 @@ class Command(): self.Protocol.send2socket(f":{self.Config.SERVICE_ID} STATS s") except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" /msg {dnickname} {command.upper()}") self.Logs.warning(f'Unknown Error: {str(err)}') @@ -1184,7 +1184,7 @@ class Command(): self.Protocol.send2socket(f":{self.Config.SERVICE_ID} STATS k") except KeyError as ke: - self.Base.logs.error(ke) + self.Logs.error(ke) except Exception as err: self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg=f" /msg {dnickname} {command.upper()}") self.Logs.warning(f'Unknown Error: {str(err)}') diff --git a/mods/mod_defender.py b/mods/mod_defender.py index b1cf4b5..23ebd22 100644 --- a/mods/mod_defender.py +++ b/mods/mod_defender.py @@ -262,26 +262,28 @@ class Defender(): pass def join_saved_channels(self) -> None: + """_summary_ + """ + try: + result = self.Base.db_execute_query(f"SELECT distinct channel_name FROM {self.Config.TABLE_CHANNEL}") + channels = result.fetchall() + jail_chan = self.Config.SALON_JAIL + jail_chan_mode = self.Config.SALON_JAIL_MODES + service_id = self.Config.SERVICE_ID + dumodes = self.Config.SERVICE_UMODES + dnickname = self.Config.SERVICE_NICKNAME - result = self.Base.db_execute_query(f"SELECT distinct channel_name FROM {self.Config.TABLE_CHANNEL}") - channels = result.fetchall() - jail_chan = self.Config.SALON_JAIL - jail_chan_mode = self.Config.SALON_JAIL_MODES - service_id = self.Config.SERVICE_ID - dumodes = self.Config.SERVICE_UMODES - dnickname = self.Config.SERVICE_NICKNAME + for channel in channels: + chan = channel[0] + self.Protocol.sjoin(chan) + if chan == jail_chan: + self.Protocol.send2socket(f":{service_id} SAMODE {jail_chan} +{dumodes} {dnickname}") + self.Protocol.send2socket(f":{service_id} MODE {jail_chan} +{jail_chan_mode}") - unixtime = self.Base.get_unixtime() + return None - for channel in channels: - chan = channel[0] - # self.Irc.send2socket(f":{self.Config.SERVEUR_ID} SJOIN {unixtime} {chan} + :{self.Config.SERVICE_ID}") - self.Protocol.sjoin(chan) - if chan == jail_chan: - self.Protocol.send2socket(f":{service_id} SAMODE {jail_chan} +{dumodes} {dnickname}") - self.Protocol.send2socket(f":{service_id} MODE {jail_chan} +{jail_chan_mode}") - - return None + except Exception as err: + self.Logs.error(f"General Error: {err}") def get_user_uptime_in_minutes(self, uidornickname:str) -> float: """Retourne depuis quand l'utilisateur est connecté (en secondes ). @@ -313,7 +315,7 @@ class Defender(): return uptime_minutes - def system_reputation(self, uid:str)-> None: + def system_reputation(self, uid: str)-> None: # Reputation security # - Activation ou désactivation du système --> OK # - Le user sera en mesure de changer la limite de la réputation --> OK @@ -336,7 +338,7 @@ class Defender(): code = get_reputation.secret_code jailed_nickname = get_reputation.nickname - jailed_score = get_reputation.score + jailed_score = get_reputation.score_connexion color_red = self.Config.COLORS.red color_black = self.Config.COLORS.black @@ -370,7 +372,7 @@ class Defender(): # self.Base.create_timer(int(self.ModConfig.reputation_timer) * 60, self.system_reputation_timer) else: self.Logs.info(f"system_reputation : {jailed_nickname} à été supprimé du système de réputation car connecté via WebIrc ou il est dans la 'Trusted list'") - self.Repurtation.delete(uid) + self.Reputation.delete(uid) except IndexError as e: self.Logs.error(f"system_reputation : {str(e)}") @@ -397,14 +399,14 @@ class Defender(): for user in self.Reputation.UID_REPUTATION_DB: if not user.isWebirc: # Si il ne vient pas de WebIRC - if self.get_user_uptime_in_minutes(user.uid) >= reputation_timer and int(user.score) <= int(reputation_seuil): + if self.get_user_uptime_in_minutes(user.uid) >= reputation_timer and int(user.score_connexion) <= int(reputation_seuil): self.Protocol.sendPrivMsg( nick_from=service_id, msg=f":{service_id} PRIVMSG {dchanlog} :[{color_red} REPUTATION {nogc}] : Action sur {user.nickname} aprés {str(reputation_timer)} minutes d'inactivité", channel=dchanlog ) self.Protocol.send2socket(f":{service_id} KILL {user.nickname} After {str(reputation_timer)} minutes of inactivity you should reconnect and type the password code ") - self.Protocol.send2socket(f":{self.Config.SERVEUR_LINK} REPUTATION {user.ip} 0") + self.Protocol.send2socket(f":{self.Config.SERVEUR_LINK} REPUTATION {user.remote_ip} 0") self.Logs.info(f"Nickname: {user.nickname} KILLED after {str(reputation_timer)} minutes of inactivity") uid_to_clean.append(user.uid) @@ -432,7 +434,7 @@ class Defender(): return None except ValueError as ve: - self.Irc.Base.logs.error(f"thread_reputation_timer Error : {ve}") + self.Logs.error(f"thread_reputation_timer Error : {ve}") def _execute_flood_action(self, action:str, channel:str) -> None: """DO NOT EXECUTE THIS FUNCTION WITHOUT THREADING @@ -461,7 +463,7 @@ class Defender(): if self.ModConfig.flood == 0: return None - if not '#' in channel: + if not self.Channel.Is_Channel(channelToCheck=channel): return None flood_time = self.ModConfig.flood_time @@ -471,10 +473,10 @@ class Defender(): dnickname = self.Config.SERVICE_NICKNAME 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) - + unixtime = self.Base.get_unixtime() get_diff_secondes = 0 @@ -490,7 +492,7 @@ class Defender(): self.flood_system[get_detected_uid]['first_msg_time'] = unixtime self.flood_system[get_detected_uid]['nbr_msg'] = 0 get_diff_secondes = unixtime - self.flood_system[get_detected_uid]['first_msg_time'] - + elif self.flood_system[get_detected_uid]['nbr_msg'] > flood_message: self.Irc.Base.logs.info('system de flood detecté') self.Protocol.sendPrivMsg( @@ -1086,7 +1088,6 @@ class Defender(): # updated_datetime=currentDateTime ) ) - # self.Irc.send2socket(f":{service_id} WHOIS {nickname}") if self.Reputation.is_exist(_User.uid): if reputation_flag == 1 and _User.score_connexion <= reputation_seuil: self.system_reputation(_User.uid) @@ -1096,13 +1097,10 @@ class Defender(): # ['@msgid=F9B7JeHL5pj9nN57cJ5pEr;time=2023-12-28T20:47:24.305Z', ':001', 'SJOIN', '1702138958', '#welcome', ':0015L1AHL'] try: cmd.pop(0) - parsed_chan = cmd[3] + parsed_chan = cmd[3] if self.Channel.Is_Channel(cmd[3]) else None if self.ModConfig.reputation == 1: - parsed_UID = cmd[4] - pattern = fr'^:[@|%|\+|~|\*]*' - parsed_UID = re.sub(pattern, '', parsed_UID) - + parsed_UID = self.User.clean_uid(cmd[4]) get_reputation = self.Reputation.get_Reputation(parsed_UID) if parsed_chan != self.Config.SALON_JAIL: @@ -1122,6 +1120,7 @@ class Defender(): self.Protocol.send2socket(f":{service_id} KICK {parsed_chan} {get_reputation.nickname}") self.Logs.debug(f'SJOIN parsed_uid : {parsed_UID}') + except KeyError as ke: self.Logs.error(f"key error SJOIN : {ke}") diff --git a/mods/mod_test.py b/mods/mod_test.py index aaeed38..c27032e 100644 --- a/mods/mod_test.py +++ b/mods/mod_test.py @@ -141,11 +141,11 @@ class Test(): return None except KeyError as ke: - self.Base.logs.error(f"Key Error: {ke}") + self.Logs.error(f"Key Error: {ke}") except IndexError as ie: - self.Base.logs.error(f"{ie} / {cmd} / length {str(len(cmd))}") + self.Logs.error(f"{ie} / {cmd} / length {str(len(cmd))}") except Exception as err: - self.Base.logs.error(f"General Error: {err}") + self.Logs.error(f"General Error: {err}") def _hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None: @@ -159,11 +159,11 @@ class Test(): case 'test-command': try: - self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} : This is a notice to the sender ...") - self.Irc.send2socket(f":{dnickname} PRIVMSG {fromuser} : This is private message to the sender ...") + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser, msg="This is a notice to the sender ...") + self.Protocol.sendPrivMsg(nick_from=dnickname, msg=f"This is private message to the sender ...", nick_to=fromuser) if not fromchannel is None: - self.Irc.send2socket(f":{dnickname} PRIVMSG {fromchannel} : This is channel message to the sender ...") + self.Protocol.sendPrivMsg(nick_from=dnickname, msg=f"This is private message to the sender ...", channel=fromchannel) # How to update your module configuration self.__update_configuration('param_exemple2', 7) diff --git a/mods/mod_votekick.py b/mods/mod_votekick.py index a3806a2..9a871d4 100644 --- a/mods/mod_votekick.py +++ b/mods/mod_votekick.py @@ -34,6 +34,12 @@ class Votekick(): # Add Irc Object to the module self.Irc = ircInstance + # Add Loader Object to the module (Mandatory) + self.Loader = ircInstance.Loader + + # Add server protocol Object to the module (Mandatory) + self.Protocol = ircInstance.Protocol + # Add Global Configuration to the module self.Config = ircInstance.Config @@ -116,7 +122,7 @@ class Votekick(): def unload(self) -> None: try: for chan in self.VOTE_CHANNEL_DB: - self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} PART {chan.channel_name}") + self.Protocol.sendChanPart(uidornickname=self.Config.SERVICE_ID, channel=chan.channel_name) self.VOTE_CHANNEL_DB = [] self.Logs.debug(f'Delete memory DB VOTE_CHANNEL_DB: {self.VOTE_CHANNEL_DB}') @@ -126,8 +132,8 @@ class Votekick(): self.Logs.error(f'{ne}') except NameError as ue: self.Logs.error(f'{ue}') - except: - self.Logs.error('Error on the module') + except Exception as err: + self.Logs.error(f'General Error: {err}') def init_vote_system(self, channel: str) -> bool: @@ -206,8 +212,8 @@ class Votekick(): for channel in channels: id, chan = channel self.insert_vote_channel(self.VoteChannelModel(channel_name=chan, target_user='', voter_users=[], vote_for=0, vote_against=0)) - self.Irc.send2socket(f":{self.Config.SERVEUR_ID} SJOIN {unixtime} {chan} + :{self.Config.SERVICE_ID}") - self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} SAMODE {chan} +o {self.Config.SERVICE_NICKNAME}") + self.Protocol.sjoin(channel=chan) + self.Protocol.send2socket(f":{self.Config.SERVICE_NICKNAME} SAMODE {chan} +o {self.Config.SERVICE_NICKNAME}") return None @@ -232,15 +238,27 @@ 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.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.Protocol.sendPrivMsg( + nick_from=dnickname, + msg=f"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", + channel=channel + ) + self.Protocol.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.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') + self.Protocol.sendPrivMsg( + nick_from=dnickname, + msg=f"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", + channel=channel + ) # Init the system if self.init_vote_system(channel): - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :System vote re initiated') + self.Protocol.sendPrivMsg( + nick_from=dnickname, + msg="System vote re initiated", + channel=channel + ) return None @@ -250,11 +268,11 @@ class Votekick(): return None except KeyError as ke: - self.Base.logs.error(f"Key Error: {ke}") + self.Logs.error(f"Key Error: {ke}") except IndexError as ie: - self.Base.logs.error(f"{ie} / {cmd} / length {str(len(cmd))}") + self.Logs.error(f"{ie} / {cmd} / length {str(len(cmd))}") except Exception as err: - self.Base.logs.error(f"General Error: {err}") + self.Logs.error(f"General Error: {err}") def _hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None: # cmd is the command starting from the user command @@ -266,18 +284,19 @@ class Votekick(): fromchannel = channel match command: + case 'vote': option = str(cmd[1]).lower() if len(command) == 1: - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote activate #channel') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote deactivate #channel') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote +') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote -') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote cancel') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote status') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote submit nickname') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote verdict') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote activate #channel') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote deactivate #channel') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote +') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote -') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote cancel') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote status') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote submit nickname') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote verdict') match option: @@ -285,12 +304,12 @@ class Votekick(): try: # vote activate #channel if self.Admin.get_Admin(fromuser) is None: - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :Your are not allowed to execute this command') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' :Your are not allowed to execute this command') return None sentchannel = str(cmd[2]).lower() if self.Channel.Is_Channel(str(cmd[2]).lower()) else None if sentchannel is None: - self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :The correct command is {self.Config.SERVICE_PREFIX}{command} {option} #CHANNEL") + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f" The correct command is {self.Config.SERVICE_PREFIX}{command} {option} #CHANNEL") self.insert_vote_channel( self.VoteChannelModel( @@ -304,27 +323,30 @@ class Votekick(): self.Channel.db_query_channel('add', self.module_name, sentchannel) - self.Irc.send2socket(f":{dnickname} JOIN {sentchannel}") - self.Irc.send2socket(f":{dnickname} SAMODE {sentchannel} +o {dnickname}") - self.Irc.send2socket(f":{dnickname} PRIVMSG {sentchannel} :You can now use !submit to decide if he will stay or not on this channel ") + self.Protocol.sendChanJoin(uidornickname=dnickname, channel=sentchannel) + self.Protocol.send2socket(f":{dnickname} SAMODE {sentchannel} +o {dnickname}") + self.Protocol.sendPrivMsg(nick_from=dnickname, + msg="You can now use !submit to decide if he will stay or not on this channel ", + channel=sentchannel + ) except Exception as err: self.Logs.error(f'{err}') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} {command} {option} #channel') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :Exemple /msg {dnickname} {command} {option} #welcome') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} {command} {option} #channel') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' Exemple /msg {dnickname} {command} {option} #welcome') case 'deactivate': try: # vote deactivate #channel if self.Admin.get_Admin(fromuser) is None: - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :Your are not allowed to execute this command') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f" Your are not allowed to execute this command") return None sentchannel = str(cmd[2]).lower() if self.Channel.Is_Channel(str(cmd[2]).lower()) else None if sentchannel is None: - self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :The correct command is {self.Config.SERVICE_PREFIX}{command} {option} #CHANNEL") + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f" The correct command is {self.Config.SERVICE_PREFIX}{command} {option} #CHANNEL") - self.Irc.send2socket(f":{dnickname} SAMODE {sentchannel} -o {dnickname}") - self.Irc.send2socket(f":{dnickname} PART {sentchannel}") + self.Protocol.send2socket(f":{dnickname} SAMODE {sentchannel} -o {dnickname}") + self.Protocol.sendChanPart(uidornickname=dnickname, channel=sentchannel) for chan in self.VOTE_CHANNEL_DB: if chan.channel_name == sentchannel: @@ -334,8 +356,8 @@ class Votekick(): self.Logs.debug(f"The Channel {sentchannel} has been deactivated from the vote system") except Exception as err: self.Logs.error(f'{err}') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} {command} {option} #channel') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :Exemple /msg {dnickname} {command} {option} #welcome') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f" /msg {dnickname} {command} {option} #channel") + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f" Exemple /msg {dnickname} {command} {option} #welcome") case '+': try: @@ -344,15 +366,21 @@ class Votekick(): for chan in self.VOTE_CHANNEL_DB: if chan.channel_name == channel: if fromuser in chan.voter_users: - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :You already submitted a vote') + self.Protocol.sendPrivMsg(nick_from=dnickname, + msg="You already submitted a vote", + channel=channel + ) else: chan.vote_for += 1 chan.voter_users.append(fromuser) - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :Vote recorded, thank you') + self.Protocol.sendPrivMsg(nick_from=dnickname, + msg="Vote recorded, thank you", + channel=channel + ) except Exception as err: self.Logs.error(f'{err}') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} {command} {option}') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :Exemple /msg {dnickname} {command} {option}') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} {command} {option}') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' Exemple /msg {dnickname} {command} {option}') case '-': try: @@ -361,54 +389,65 @@ class Votekick(): for chan in self.VOTE_CHANNEL_DB: if chan.channel_name == channel: if fromuser in chan.voter_users: - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :You already submitted a vote') + self.Protocol.sendPrivMsg(nick_from=dnickname, + msg="You already submitted a vote", + channel=channel + ) else: chan.vote_against += 1 chan.voter_users.append(fromuser) - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :Vote recorded, thank you') + self.Protocol.sendPrivMsg(nick_from=dnickname, + msg="Vote recorded, thank you", + channel=channel + ) except Exception as err: self.Logs.error(f'{err}') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} {command} {option}') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :Exemple /msg {dnickname} {command} {option}') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} {command} {option}') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' Exemple /msg {dnickname} {command} {option}') case 'cancel': try: # vote cancel if self.Admin.get_Admin(fromuser) is None: - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :Your are not allowed to execute this command') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' Your are not allowed to execute this command') return None if channel is None: self.Logs.error(f"The channel is not known, defender can't cancel the vote") - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :You need to specify the channel => /msg {dnickname} vote_cancel #channel') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' You need to specify the channel => /msg {dnickname} vote_cancel #channel') for vote in self.VOTE_CHANNEL_DB: if vote.channel_name == channel: self.init_vote_system(channel) - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :Vote system re-initiated') + self.Protocol.sendPrivMsg(nick_from=dnickname, + msg="Vote system re-initiated", + channel=channel + ) except Exception as err: self.Logs.error(f'{err}') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} {command} {option}') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :Exemple /msg {dnickname} {command} {option}') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} {command} {option}') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' Exemple /msg {dnickname} {command} {option}') case 'status': try: # vote status for chan in self.VOTE_CHANNEL_DB: if chan.channel_name == channel: - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :Channel: {chan.channel_name} | Target: {self.User.get_nickname(chan.target_user)} | For: {chan.vote_for} | Against: {chan.vote_against} | Number of voters: {str(len(chan.voter_users))}') - + self.Protocol.sendPrivMsg(nick_from=dnickname, + msg=f"Channel: {chan.channel_name} | Target: {self.User.get_nickname(chan.target_user)} | For: {chan.vote_for} | Against: {chan.vote_against} | Number of voters: {str(len(chan.voter_users))}", + channel=channel + ) except Exception as err: self.Logs.error(f'{err}') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} {command} {option}') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :Exemple /msg {dnickname} {command} {option}') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} {command} {option}') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' Exemple /msg {dnickname} {command} {option}') case 'submit': try: # vote submit nickname if self.Admin.get_Admin(fromuser) is None: - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :Your are not allowed to execute this command') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' Your are not allowed to execute this command') return None nickname_submitted = cmd[2] @@ -421,18 +460,24 @@ class Votekick(): if vote.channel_name == channel: ongoing_user = self.User.get_nickname(vote.target_user) - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :There is an ongoing vote on {ongoing_user}') + self.Protocol.sendPrivMsg(nick_from=dnickname, + msg=f"There is an ongoing vote on {ongoing_user}", + channel=channel + ) return False # check if the user exist if user_submitted is None: - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :This nickname <{nickname_submitted}> do not exist') + self.Protocol.sendPrivMsg(nick_from=dnickname, + msg=f"This nickname <{nickname_submitted}> do not exist", + channel=channel + ) return False uid_cleaned = self.Base.clean_uid(uid_submitted) ChannelInfo = self.Channel.get_Channel(channel) if ChannelInfo is None: - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :This channel [{channel}] do not exist in the Channel Object') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' This channel [{channel}] do not exist in the Channel Object') return False clean_uids_in_channel: list = [] @@ -440,60 +485,83 @@ class Votekick(): clean_uids_in_channel.append(self.Base.clean_uid(uid)) if not uid_cleaned in clean_uids_in_channel: - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :This nickname <{nickname_submitted}> is not available in this channel') + self.Protocol.sendPrivMsg(nick_from=dnickname, + msg=f"This nickname <{nickname_submitted}> is not available in this channel", + channel=channel + ) return False # check if Ircop or Service or Bot pattern = fr'[o|B|S]' operator_user = re.findall(pattern, user_submitted.umodes) if operator_user: - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :You cant vote for this user ! he/she is protected') + self.Protocol.sendPrivMsg(nick_from=dnickname, + msg="You cant vote for this user ! he/she is protected", + channel=channel + ) return False for chan in self.VOTE_CHANNEL_DB: if chan.channel_name == channel: chan.target_user = self.User.get_uid(nickname_submitted) - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :{nickname_submitted} has been targeted for a vote') + self.Protocol.sendPrivMsg(nick_from=dnickname, + msg=f"{nickname_submitted} has been targeted for a vote", + channel=channel + ) self.Base.create_timer(60, self.timer_vote_verdict, (channel, )) - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :This vote will end after 60 secondes') + self.Protocol.sendPrivMsg(nick_from=dnickname, + msg="This vote will end after 60 secondes", + channel=channel + ) except Exception as err: self.Logs.error(f'{err}') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} {command} {option} nickname') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :Exemple /msg {dnickname} {command} {option} adator') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} {command} {option} nickname') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' Exemple /msg {dnickname} {command} {option} adator') case 'verdict': try: # vote verdict if self.Admin.get_Admin(fromuser) is None: - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :Your are not allowed to execute this command') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f'Your are not allowed to execute this command') return None for chan in self.VOTE_CHANNEL_DB: 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.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.Protocol.sendPrivMsg(nick_from=dnickname, + msg=f"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", + channel=channel + ) + self.Protocol.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.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') - + self.Protocol.sendPrivMsg( + nick_from=dnickname, + msg=f"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", + channel=channel + ) + # Init the system if self.init_vote_system(channel): - self.Irc.send2socket(f':{dnickname} PRIVMSG {channel} :System vote re initiated') + self.Protocol.sendPrivMsg( + nick_from=dnickname, + msg="System vote re initiated", + channel=channel + ) except Exception as err: self.Logs.error(f'{err}') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} {command} {option}') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :Exemple /msg {dnickname} {command} {option}') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} {command} {option}') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' Exemple /msg {dnickname} {command} {option}') case _: - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote activate #channel') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote deactivate #channel') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote +') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote -') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote cancel') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote status') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote submit nickname') - self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} vote verdict') \ No newline at end of file + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote activate #channel') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote deactivate #channel') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote +') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote -') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote cancel') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote status') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote submit nickname') + self.Protocol.sendNotice(nick_from=dnickname, nick_to=fromuser,msg=f' /msg {dnickname} vote verdict') \ No newline at end of file