diff --git a/core/classes/channel.py b/core/classes/channel.py index 993f21d..608b051 100644 --- a/core/classes/channel.py +++ b/core/classes/channel.py @@ -2,6 +2,8 @@ from re import findall from typing import Union, Literal, TYPE_CHECKING from dataclasses import asdict +from core.classes import user + if TYPE_CHECKING: from core.definition import MChannel from core.base import Base @@ -31,6 +33,10 @@ class Channel: result = False exist = False + if not self.Is_Channel(newChan.name): + self.Logs.error(f"The channel {newChan.name} is not valid, channel must start with #") + return False + for record in self.UID_CHANNEL_DB: if record.name.lower() == newChan.name.lower(): # If the channel exist, update the user list and do not go further @@ -129,6 +135,29 @@ class Channel: except Exception as err: self.Logs.error(f'{err}') + def is_user_present_in_channel(self, channel_name: str, uid: str) -> bool: + """Check if a user is present in the channel + + Args: + channel_name (str): The channel to check + uid (str): The UID + + Returns: + bool: True if the user is present in the channel + """ + user_found = False + chan = self.get_Channel(channel_name=channel_name) + if chan is None: + return user_found + + clean_uid = self.Base.clean_uid(uid=uid) + for chan_uid in chan.uids: + if self.Base.clean_uid(chan_uid) == clean_uid: + user_found = True + break + + return user_found + def clean_channel(self) -> None: """Remove Channels if empty """ diff --git a/core/classes/protocols/unreal6.py b/core/classes/protocols/unreal6.py index dffd537..31de700 100644 --- a/core/classes/protocols/unreal6.py +++ b/core/classes/protocols/unreal6.py @@ -476,6 +476,17 @@ class Unrealircd6: except Exception as err: self.__Base.logs.error(f"{__name__} - General Error: {err}") + def on_mode(self, serverMsg: list[str]) -> None: + """Handle mode coming from a server + + Args: + serverMsg (list[str]): Original server message + """ + #['@msgid=d0ySx56Yd0nc35oHts2SkC-/J9mVUA1hfM6...', ':001', 'MODE', '#a', '+nt', '1723207536'] + #['@unrealircd.org/userhost=adator@localhost;...', ':001LQ0L0C', 'MODE', '#services', '-l'] + + return None + def on_umode2(self, serverMsg: list[str]) -> None: """Handle umode2 coming from a server @@ -622,8 +633,11 @@ class Unrealircd6: # ':001T6VU3F', '001JGWB2K', '@11ZAAAAAB', # '001F16WGR', '001X9YMGQ', '*+001DYPFGP', '@00BAAAAAJ', '001AAGOG9', '001FMFVG8', '001DAEEG7', # '&~G:unknown-users', '"~G:websocket-users', '"~G:known-users', '"~G:webirc-users'] + # [':00B', 'SJOIN', '1731872579', '#services', '+', ':00BAAAAAB'] serverMsg_copy = serverMsg.copy() - serverMsg_copy.pop(0) + if serverMsg_copy[0].startswith('@'): + serverMsg_copy.pop(0) + channel = str(serverMsg_copy[3]).lower() len_cmd = len(serverMsg_copy) list_users:list = [] diff --git a/core/irc.py b/core/irc.py index a94086c..6578d24 100644 --- a/core/irc.py +++ b/core/irc.py @@ -750,12 +750,12 @@ class Irc: case 'PING': self.Protocol.on_server_ping(serverMsg=original_response) - # print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") return None case 'SJOIN': self.Protocol.on_sjoin(serverMsg=original_response) - # print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") case 'EOS': # TODO hsid = str(original_response[0]).replace(':','') @@ -810,7 +810,7 @@ class Irc: classe_object.cmd(original_response) # Stop here When EOS - # print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") return None case 'UID': @@ -820,44 +820,44 @@ class Irc: for classe_name, classe_object in self.loaded_classes.items(): classe_object.cmd(original_response) - # print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") except Exception as err: self.Logs.error(f'General Error: {err}') case 'QUIT': self.Protocol.on_quit(serverMsg=original_response) - # print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") case 'PROTOCTL': self.Protocol.on_protoctl(serverMsg=original_response) - # print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") case 'SVS2MODE': # >> [':00BAAAAAG', 'SVS2MODE', '001U01R03', '-r'] self.Protocol.on_svs2mode(serverMsg=original_response) - # print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") case 'SQUIT': self.Protocol.on_squit(serverMsg=original_response) - # print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") case 'PART': self.Protocol.on_part(serverMsg=parsed_protocol) - # print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") case 'VERSION': self.Protocol.on_version_msg(serverMsg=original_response) - # print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") case 'UMODE2': # [':adator_', 'UMODE2', '-i'] self.Protocol.on_umode2(serverMsg=original_response) - # print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") case 'NICK': self.Protocol.on_nick(serverMsg=original_response) - # print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") case 'REPUTATION': # TODO # :001 REPUTATION 127.0.0.1 118 @@ -875,7 +875,7 @@ class Irc: else: self.first_score = int(original_response[3]) - # print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") # Possibilité de déclancher les bans a ce niveau. except IndexError as ie: self.Logs.error(f'{ie}') @@ -884,10 +884,10 @@ class Irc: self.Logs.error(f'Impossible to convert first_score: {ve}') case 'SLOG': # TODO - print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") case 'MD': # TODO - print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") case 'PRIVMSG': # TODO try: @@ -974,24 +974,23 @@ class Irc: self.Logs.error(f'{io}') case 'PONG': # TODO - print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") case 'MODE': # TODO - #['@msgid=d0ySx56Yd0nc35oHts2SkC-/J9mVUA1hfM6+Z4494xWUg;time=2024-08-09T12:45:36.651Z', - # ':001', 'MODE', '#a', '+nt', '1723207536'] - # [':adator_', 'UMODE2', '-i'] - print(f"** handle {parsed_protocol}") + #['@msgid=d0ySx56Yd0nc35oHts2SkC-/J9mVUA1hfM6...', ':001', 'MODE', '#a', '+nt', '1723207536'] + #['@unrealircd.org/userhost=adator@localhost;...', ':001LQ0L0C', 'MODE', '#services', '-l'] + self.Logs.debug(f"** handle {parsed_protocol}") case '320': # TODO #:irc.deb.biz.st 320 PyDefender IRCParis07 :is in security-groups: known-users,webirc-users,tls-and-known-users,tls-users - print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") case '318': # TODO #:irc.deb.biz.st 318 PyDefender IRCParis93 :End of /WHOIS list. - print(f"** handle {parsed_protocol}") + self.Logs.debug(f"** handle {parsed_protocol}") case None: - print(f"** TO BE HANDLE {original_response}") + self.Logs.debug(f"** TO BE HANDLE {original_response}") if len(original_response) == 7: if original_response[2] == 'PRIVMSG' and original_response[4] == ':auth': @@ -1003,10 +1002,11 @@ class Irc: else: self.Logs.debug(f">> {original_response}") - if original_response[2] != 'UID': - # Envoyer la commande aux classes dynamiquement chargées - for classe_name, classe_object in self.loaded_classes.items(): - classe_object.cmd(original_response) + if len(original_response) > 2: + if original_response[2] != 'UID': + # Envoyer la commande aux classes dynamiquement chargées + for classe_name, classe_object in self.loaded_classes.items(): + classe_object.cmd(original_response) except IndexError as ie: self.Logs.error(f"{ie} / {original_response} / length {str(len(original_response))}") diff --git a/mods/mod_command.py b/mods/mod_command.py index 867399a..5156fac 100644 --- a/mods/mod_command.py +++ b/mods/mod_command.py @@ -252,7 +252,7 @@ class Command: if userObj is None: return None - if 'r' not in userObj.umodes: + if 'r' not in userObj.umodes and 'o' not in userObj.umodes: return None db_data: dict[str, str] = {"nickname": userObj.nickname, "channel": channel_name} @@ -285,12 +285,13 @@ class Command: option: str = str(cmd[1]).lower() match option: case 'set': + allowed_modes: list[str] = self.Base.Settings.PROTOCTL_PREFIX # ['q','a','o','h','v'] + if len(cmd) < 5: self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} {command.upper()} [nickname] [+/-mode] [#channel]") self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"AutoModes available: {' / '.join(allowed_modes)}") return None - allowed_modes: list[str] = self.Base.Settings.PROTOCTL_PREFIX # ['q','a','o','h','v'] # userObj: MUser = self.User.get_User(str(cmd[2])) nickname = str(cmd[2]) mode = str(cmd[3]) @@ -342,7 +343,8 @@ class Command: if db_query.rowcount > 0: self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"Automode {mode} applied to {nickname} in {chan}") - self.Protocol.send2socket(f":{service_id} MODE {chan} {mode} {nickname}") + if self.Channel.is_user_present_in_channel(chan, self.User.get_uid(nickname)): + self.Protocol.send2socket(f":{service_id} MODE {chan} {mode} {nickname}") else: self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"AUTOMODE {mode} cannot be added to {nickname} in {chan} because it doesn't exist") diff --git a/version.json b/version.json index 30e9a11..4b47bd8 100644 --- a/version.json +++ b/version.json @@ -1,5 +1,5 @@ { - "version": "6.0.1", + "version": "6.0.3", "requests": "2.32.3", "psutil": "6.0.0",