Connectecting to inspircd

This commit is contained in:
adator
2025-09-03 22:01:52 +02:00
parent e79c15188e
commit 6b7fd16a44
13 changed files with 585 additions and 82 deletions

2
.gitignore vendored
View File

@@ -5,5 +5,7 @@ db/
logs/ logs/
__pycache__/ __pycache__/
configuration.json configuration.json
configuration_inspircd.json
configuration_unreal6.json
*.log *.log
test.py test.py

View File

@@ -683,14 +683,13 @@ class Base:
return False return False
def decode_ip(self, ip_b64encoded: str) -> Optional[str]: def decode_ip(self, ip_b64encoded: str) -> Optional[str]:
binary_ip = b64decode(ip_b64encoded)
try: try:
binary_ip = b64decode(ip_b64encoded)
decoded_ip = ipaddress.ip_address(binary_ip) decoded_ip = ipaddress.ip_address(binary_ip)
return decoded_ip.exploded return decoded_ip.exploded
except ValueError as ve: except ValueError as ve:
self.logs.critical(f'This remote ip is not valid : {ve}') self.logs.critical(f'This remote ip ({ip_b64encoded}) is not valid : {ve}')
return None return None
def encode_ip(self, remote_ip_address: str) -> Optional[str]: def encode_ip(self, remote_ip_address: str) -> Optional[str]:

View File

@@ -1,19 +0,0 @@
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','inspircd'], ircInstance: 'Irc'):
self.Protocol = None
match protocol:
case 'unreal6':
self.Protocol: Unrealircd6 = Unrealircd6(ircInstance)
case 'inspircd':
self.Protocol: Inspircd = Inspircd(ircInstance)
case _:
self.Protocol: Unrealircd6 = Unrealircd6(ircInstance)

View File

@@ -0,0 +1,28 @@
from typing import TYPE_CHECKING, Optional
from .unreal6 import Unrealircd6
from .inspircd import Inspircd
from .interface import IProtocol
if TYPE_CHECKING:
from core.irc import Irc
class ProtocolFactorty:
def __init__(self, uplink: 'Irc'):
self.__Config = uplink.Config
self.__uplink = uplink
def get(self) -> Optional[IProtocol]:
protocol = self.__Config.SERVEUR_PROTOCOL
match protocol:
case 'unreal6':
self.__uplink.Logs.debug(f"[PROTOCOL] {protocol} has been loaded")
return Unrealircd6(self.__uplink)
case 'inspircd':
self.__uplink.Logs.debug(f"[PROTOCOL] {protocol} has been loaded")
return Inspircd(self.__uplink)
case _:
self.__uplink.Logs.critical(f"[PROTOCOL ERROR] This protocol name ({protocol} is not valid!)")
raise Exception("Unknown protocol!")

View File

@@ -1,6 +1,7 @@
from re import match, findall from re import match, findall
from datetime import datetime from datetime import datetime
from typing import TYPE_CHECKING import sys
from typing import TYPE_CHECKING, Optional
from ssl import SSLEOFError, SSLError from ssl import SSLEOFError, SSLError
if TYPE_CHECKING: if TYPE_CHECKING:
@@ -17,8 +18,32 @@ class Inspircd:
self.__Utils = ircInstance.Loader.Utils self.__Utils = ircInstance.Loader.Utils
self.__Logs = ircInstance.Loader.Logs self.__Logs = ircInstance.Loader.Logs
self.known_protocol: set[str] = {'SJOIN', 'UID', 'MD', 'QUIT', 'SQUIT',
'EOS', 'PRIVMSG', 'MODE', 'UMODE2',
'VERSION', 'REPUTATION', 'SVS2MODE',
'SLOG', 'NICK', 'PART', 'PONG', 'SASL', 'PING',
'PROTOCTL', 'SERVER', 'SMOD', 'TKL', 'NETINFO',
'006', '007', '018'}
self.__Logs.info(f"** Loading protocol [{__name__}]") self.__Logs.info(f"** Loading protocol [{__name__}]")
def get_ircd_protocol_poisition(self, cmd: list[str]) -> tuple[int, Optional[str]]:
"""Get the position of known commands
Args:
cmd (list[str]): The server response
Returns:
tuple[int, Optional[str]]: The position and the command.
"""
for index, token in enumerate(cmd):
if token.upper() in self.known_protocol:
return index, token.upper()
self.__Logs.debug(f"[IRCD LOGS] You need to handle this response: {cmd}")
return (-1, None)
def send2socket(self, message: str, print_log: bool = True) -> None: def send2socket(self, message: str, print_log: bool = True) -> None:
"""Envoit les commandes à envoyer au serveur. """Envoit les commandes à envoyer au serveur.
@@ -45,6 +70,8 @@ class Inspircd:
self.__Logs.error(f"SSLError: {se} - {message}") self.__Logs.error(f"SSLError: {se} - {message}")
except OSError as oe: except OSError as oe:
self.__Logs.error(f"OSError: {oe} - {message}") self.__Logs.error(f"OSError: {oe} - {message}")
if oe.errno == 10053:
sys.exit(oe)
except AttributeError as ae: except AttributeError as ae:
self.__Logs.critical(f"Attribute Error: {ae}") self.__Logs.critical(f"Attribute Error: {ae}")
@@ -175,7 +202,8 @@ class Inspircd:
self.__Logs.error(f"The channel [{channel}] is not valid") self.__Logs.error(f"The channel [{channel}] is not valid")
return None return None
self.send2socket(f":{self.__Config.SERVEUR_ID} SJOIN {self.__Utils.get_unixtime()} {channel} + :{self.__Config.SERVICE_ID}") # self.send2socket(f":{self.__Config.SERVEUR_ID} SJOIN {self.__Utils.get_unixtime()} {channel} + :{self.__Config.SERVICE_ID}")
self.send2socket(f":{self.__Config.SERVICE_ID} FJOIN {channel} 68")
# Add defender to the channel uids list # Add defender to the channel uids list
self.__Irc.Channel.insert(self.__Irc.Loader.Definition.MChannel(name=channel, uids=[self.__Config.SERVICE_ID])) self.__Irc.Channel.insert(self.__Irc.Loader.Definition.MChannel(name=channel, uids=[self.__Config.SERVICE_ID]))
@@ -481,32 +509,29 @@ class Inspircd:
def on_uid(self, serverMsg: list[str]) -> None: def on_uid(self, serverMsg: list[str]) -> None:
"""Handle uid message coming from the server """Handle uid message coming from the server
[:<sid>] UID <uid> <ts> <nick> <real-host> <displayed-host> <real-user> <displayed-user> <ip> <signon> <modes> [<mode-parameters>]+ :<real>
[':97K', 'UID', '97KAAAAAB', '1756928055', 'adator_', '172.18.128.1', '172.18.128.1', '...', '...', '172.18.128.1', '1756928055', '+', ':...']
Args: Args:
serverMsg (list[str]): Original server message 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: try:
isWebirc = True if 'webirc' in serverMsg[0] else False isWebirc = True if 'webirc' in serverMsg[0] else False
isWebsocket = True if 'websocket' in serverMsg[0] else False isWebsocket = True if 'websocket' in serverMsg[0] else False
uid = str(serverMsg[8]) uid = str(serverMsg[2])
nickname = str(serverMsg[3]) nickname = str(serverMsg[4])
username = str(serverMsg[6]) username = str(serverMsg[7])
hostname = str(serverMsg[7]) hostname = str(serverMsg[5])
umodes = str(serverMsg[10]) umodes = str(serverMsg[11])
vhost = str(serverMsg[11]) vhost = str(serverMsg[6])
if not 'S' in umodes: if not 'S' in umodes:
remote_ip = self.__Base.decode_ip(str(serverMsg[13])) remote_ip = self.__Base.decode_ip(str(serverMsg[9]))
else: else:
remote_ip = '127.0.0.1' remote_ip = '127.0.0.1'
# extract realname # extract realname
realname = ' '.join(serverMsg[14:]).lstrip(':') realname = ' '.join(serverMsg[12:]).lstrip(':')
# Extract Geoip information # Extract Geoip information
pattern = r'^.*geoip=cc=(\S{2}).*$' pattern = r'^.*geoip=cc=(\S{2}).*$'
@@ -540,7 +565,7 @@ class Inspircd:
except IndexError as ie: except IndexError as ie:
self.__Logs.error(f"{__name__} - Index Error: {ie}") self.__Logs.error(f"{__name__} - Index Error: {ie}")
except Exception as err: except Exception as err:
self.__Logs.error(f"{__name__} - General Error: {err}") self.__Logs.error(f"{__name__} - General Error: {err}", exc_info=True)
def on_server_ping(self, serverMsg: list[str]) -> None: def on_server_ping(self, serverMsg: list[str]) -> None:
"""Send a PONG message to the server """Send a PONG message to the server
@@ -560,6 +585,17 @@ class Inspircd:
except Exception as err: except Exception as err:
self.__Logs.error(f"{__name__} - General Error: {err}") self.__Logs.error(f"{__name__} - General Error: {err}")
def on_server(self, serverMsg: list[str]) -> None:
"""_summary_
Args:
serverMsg (list[str]): _description_
"""
try:
...
except Exception as err:
self.__Logs.error(f'General Error: {err}')
def on_version(self, serverMsg: list[str]) -> None: def on_version(self, serverMsg: list[str]) -> None:
"""Sending Server Version to the server """Sending Server Version to the server

View File

@@ -0,0 +1,447 @@
from abc import ABC, abstractmethod
from typing import Optional, TYPE_CHECKING
if TYPE_CHECKING:
from core.classes.sasl import Sasl
from core.definition import MClient, MSasl
class IProtocol(ABC):
@abstractmethod
def get_ircd_protocol_poisition(self, cmd: list[str]) -> tuple[int, Optional[str]]:
"""Get the position of known commands
Args:
cmd (list[str]): The server response
Returns:
tuple[int, Optional[str]]: The position and the command.
"""
@abstractmethod
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.
"""
@abstractmethod
def send_priv_msg(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.
"""
@abstractmethod
def send_notice(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
"""
@abstractmethod
def send_link(self) -> None:
"""Créer le link et envoyer les informations nécessaires pour la
connexion au serveur.
"""
@abstractmethod
def send_gline(self, nickname: str, hostname: str, set_by: str, expire_timestamp: int, set_at_timestamp: int, reason: str) -> None:
"""_summary_
Args:
nickname (str): _description_
hostname (str): _description_
set_by (str): _description_
expire_timestamp (int): _description_
set_at_timestamp (int): _description_
reason (str): _description_
"""
@abstractmethod
def send_set_nick(self, newnickname: str) -> None:
"""Change nickname of the server
\n This method will also update the User object
Args:
newnickname (str): New nickname of the server
"""
@abstractmethod
def send_squit(self, server_id: str, server_link: str, reason: str) -> None:
"""_summary_
Args:
server_id (str): _description_
server_link (str): _description_
reason (str): _description_
"""
@abstractmethod
def send_ungline(self, nickname:str, hostname: str) -> None:
"""_summary_
Args:
nickname (str): _description_
hostname (str): _description_
"""
@abstractmethod
def send_kline(self, nickname: str, hostname: str, set_by: str, expire_timestamp: int, set_at_timestamp: int, reason: str) -> None:
"""_summary_
Args:
nickname (str): _description_
hostname (str): _description_
set_by (str): _description_
expire_timestamp (int): _description_
set_at_timestamp (int): _description_
reason (str): _description_
"""
@abstractmethod
def send_unkline(self, nickname:str, hostname: str) -> None:
"""_summary_
Args:
nickname (str): _description_
hostname (str): _description_
"""
@abstractmethod
def send_sjoin(self, channel: str) -> None:
"""Server will join a channel with pre defined umodes
Args:
channel (str): Channel to join
"""
@abstractmethod
def send_sapart(self, nick_to_sapart: str, channel_name: str) -> None:
"""_summary_
Args:
from_nick (str): _description_
nick_to (str): _description_
channel_name (str): _description_
"""
@abstractmethod
def send_sajoin(self, nick_to_sajoin: str, channel_name: str) -> None:
"""_summary_
Args:
nick_to_sajoin (str): _description_
channel_name (str): _description_
"""
@abstractmethod
def send_svspart(self, nick_to_part: str, channels: list[str], reason: str) -> None:
"""_summary_
Args:
nick_to_part (str): _description_
channels (list[str]): _description_
reason (str): _description_
"""
@abstractmethod
def send_svsjoin(self, nick_to_part: str, channels: list[str], keys: list[str]) -> None:
"""_summary_
Args:
nick_to_part (str): _description_
channels (list[str]): _description_
keys (list[str]): _description_
"""
@abstractmethod
def send_svsmode(self, nickname: str, user_mode: str) -> None:
"""_summary_
Args:
nickname (str): _description_
user_mode (str): _description_
"""
@abstractmethod
def send_svs2mode(self, nickname: str, user_mode: str) -> None:
"""_summary_
Args:
nickname (str): _description_
user_mode (str): _description_
"""
@abstractmethod
def send_svslogin(self, client_uid: str, user_account: str) -> None:
"""Log a client into his account.
Args:
client_uid (str): Client UID
user_account (str): The account of the user
"""
@abstractmethod
def send_svslogout(self, client_obj: 'MClient') -> None:
"""Logout a client from his account
Args:
client_uid (str): The Client UID
"""
@abstractmethod
def send_quit(self, uid: str, reason: str, print_log: True) -> None:
"""Send quit message
- Delete uid from User object
- Delete uid from Reputation object
Args:
uidornickname (str): The UID or the Nickname
reason (str): The reason for the quit
"""
@abstractmethod
def send_uid(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
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.
"""
@abstractmethod
def send_join_chan(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.
"""
@abstractmethod
def send_part_chan(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.
"""
@abstractmethod
def send_mode_chan(self, channel_name: str, channel_mode: str) -> None:
"""_summary_
Args:
channel_name (str): _description_
channel_mode (str): _description_
"""
@abstractmethod
def send_raw(self, raw_command: str) -> None:
"""_summary_
Args:
raw_command (str): _description_
"""
#####################
# HANDLE EVENTS #
#####################
@abstractmethod
def on_svs2mode(self, serverMsg: list[str]) -> None:
"""Handle svs2mode coming from a server
>>> [':00BAAAAAG', 'SVS2MODE', '001U01R03', '-r']
Args:
serverMsg (list[str]): Original server message
"""
@abstractmethod
def on_mode(self, serverMsg: list[str]) -> None:
"""Handle mode coming from a server
Args:
serverMsg (list[str]): Original server message
"""
@abstractmethod
def on_umode2(self, serverMsg: list[str]) -> None:
"""Handle umode2 coming from a server
>>> [':adator_', 'UMODE2', '-i']
Args:
serverMsg (list[str]): Original server message
"""
@abstractmethod
def on_quit(self, serverMsg: list[str]) -> None:
"""Handle quit coming from a server
Args:
serverMsg (list[str]): Original server message
"""
@abstractmethod
def on_squit(self, serverMsg: list[str]) -> None:
"""Handle squit coming from a server
Args:
serverMsg (list[str]): Original server message
"""
@abstractmethod
def on_protoctl(self, serverMsg: list[str]) -> None:
"""Handle protoctl coming from a server
Args:
serverMsg (list[str]): Original server message
"""
@abstractmethod
def on_nick(self, serverMsg: list[str]) -> None:
"""Handle nick coming from a server
new nickname
Args:
serverMsg (list[str]): Original server message
"""
@abstractmethod
def on_sjoin(self, serverMsg: list[str]) -> None:
"""Handle sjoin coming from a server
Args:
serverMsg (list[str]): Original server message
"""
@abstractmethod
def on_part(self, serverMsg: list[str]) -> None:
"""Handle part coming from a server
Args:
serverMsg (list[str]): Original server message
"""
@abstractmethod
def on_eos(self, serverMsg: list[str]) -> None:
"""Handle EOS coming from a server
Args:
serverMsg (list[str]): Original server message
"""
@abstractmethod
def on_reputation(self, serverMsg: list[str]) -> None:
"""Handle REPUTATION coming from a server
Args:
serverMsg (list[str]): Original server message
"""
@abstractmethod
def on_uid(self, serverMsg: list[str]) -> None:
"""Handle uid message coming from the server
Args:
serverMsg (list[str]): Original server message
"""
@abstractmethod
def on_privmsg(self, serverMsg: list[str]) -> None:
"""Handle PRIVMSG message coming from the server
Args:
serverMsg (list[str]): Original server message
"""
@abstractmethod
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
"""
@abstractmethod
def on_server(self, serverMsg: list[str]) -> None:
"""_summary_
Args:
serverMsg (list[str]): _description_
"""
@abstractmethod
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
"""
@abstractmethod
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
"""
@abstractmethod
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
"""
@abstractmethod
def on_version_msg(self, serverMsg: list[str]) -> None:
"""Handle version coming from the server
\n ex. /version Defender
Args:
serverMsg (list[str]): Original message from the server
"""
@abstractmethod
def on_smod(self, serverMsg: list[str]) -> None:
"""Handle SMOD message coming from the server
Args:
serverMsg (list[str]): Original server message
"""
@abstractmethod
def on_sasl(self, serverMsg: list[str], psasl: 'Sasl') -> Optional['MSasl']:
"""Handle SASL coming from a server
Args:
serverMsg (list[str]): Original server message
psasl (Sasl): The SASL process object
"""
@abstractmethod
def on_md(self, serverMsg: list[str]) -> None:
"""Handle MD responses
[':001', 'MD', 'client', '001MYIZ03', 'certfp', ':d1235648...']
Args:
serverMsg (list[str]): The server reply
"""

View File

@@ -4,6 +4,7 @@ from datetime import datetime
from typing import TYPE_CHECKING, Optional from typing import TYPE_CHECKING, Optional
from ssl import SSLEOFError, SSLError from ssl import SSLEOFError, SSLError
from core.classes.protocols.interface import IProtocol
from core.utils import tr from core.utils import tr
if TYPE_CHECKING: if TYPE_CHECKING:
@@ -11,7 +12,7 @@ if TYPE_CHECKING:
from core.classes.sasl import Sasl from core.classes.sasl import Sasl
from core.definition import MClient, MSasl from core.definition import MClient, MSasl
class Unrealircd6: class Unrealircd6(IProtocol):
def __init__(self, ircInstance: 'Irc'): def __init__(self, ircInstance: 'Irc'):
self.name = 'UnrealIRCD-6' self.name = 'UnrealIRCD-6'
@@ -200,6 +201,7 @@ class Unrealircd6:
self.send2socket(f":{server_id} PROTOCTL SID={server_id}") self.send2socket(f":{server_id} PROTOCTL SID={server_id}")
self.send2socket(f":{server_id} PROTOCTL BOOTED={unixtime}") self.send2socket(f":{server_id} PROTOCTL BOOTED={unixtime}")
self.send2socket(f":{server_id} SERVER {link} 1 :{info}") self.send2socket(f":{server_id} SERVER {link} 1 :{info}")
self.send2socket("EOS")
self.send2socket(f":{server_id} {nickname} :Reserved for services") self.send2socket(f":{server_id} {nickname} :Reserved for services")
self.send2socket(f":{server_id} UID {nickname} 1 {unixtime} {username} {host} {service_id} * {smodes} * * fwAAAQ== :{realname}") self.send2socket(f":{server_id} UID {nickname} 1 {unixtime} {username} {host} {service_id} * {smodes} * * fwAAAQ== :{realname}")
self.send_sjoin(chan) self.send_sjoin(chan)
@@ -1035,15 +1037,6 @@ class Unrealircd6:
) )
return None return None
# if not arg[0].lower() in self.__Irc.module_commands_list:
# self.__Logs.debug(f"This command {arg[0]} is not available")
# self.send_notice(
# nick_from=self.__Config.SERVICE_NICKNAME,
# nick_to=user_trigger,
# msg=f"This command [{self.__Config.COLORS.bold}{arg[0]}{self.__Config.COLORS.bold}] is not available"
# )
# return None
cmd_to_send = convert_to_string.replace(':','') cmd_to_send = convert_to_string.replace(':','')
self.__Base.log_cmd(user_trigger, cmd_to_send) self.__Base.log_cmd(user_trigger, cmd_to_send)
@@ -1106,7 +1099,6 @@ class Unrealircd6:
serverMsg (list[str]): List of str coming from the server serverMsg (list[str]): List of str coming from the server
""" """
try: try:
#
pong = str(serverMsg[1]).replace(':','') pong = str(serverMsg[1]).replace(':','')
self.send2socket(f"PONG :{pong}", print_log=False) self.send2socket(f"PONG :{pong}", print_log=False)
@@ -1115,6 +1107,11 @@ class Unrealircd6:
self.__Logs.error(f"{__name__} - General Error: {err}") self.__Logs.error(f"{__name__} - General Error: {err}")
def on_server(self, serverMsg: list[str]) -> None: def on_server(self, serverMsg: list[str]) -> None:
"""_summary_
Args:
serverMsg (list[str]): _description_
"""
try: try:
# ['SERVER', 'irc.local.org', '1', ':U6100-Fhn6OoE-001', 'Local', 'Server'] # ['SERVER', 'irc.local.org', '1', ':U6100-Fhn6OoE-001', 'Local', 'Server']
sCopy = serverMsg.copy() sCopy = serverMsg.copy()
@@ -1177,7 +1174,7 @@ class Unrealircd6:
Args: Args:
serverMsg (list[str]): List of str coming from the server 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'] # ['@unrealircd.org/...', ':001INC60B', 'PRIVMSG', '12ZAAAAAB', ':\x01PING', '762382207\x01']
# Réponse a un CTCP VERSION # Réponse a un CTCP VERSION
try: try:
@@ -1186,6 +1183,7 @@ class Unrealircd6:
arg = serverMsg[4].replace(':', '') arg = serverMsg[4].replace(':', '')
if nickname is None: if nickname is None:
self.__Logs.debug(serverMsg)
return None return None
if arg == '\x01PING': if arg == '\x01PING':
@@ -1199,6 +1197,7 @@ class Unrealircd6:
nick_to=nickname, nick_to=nickname,
msg=f"\x01PING {ping_response} secs\x01" msg=f"\x01PING {ping_response} secs\x01"
) )
self.__Logs.debug(serverMsg)
return None return None
except Exception as err: except Exception as err:

View File

@@ -3,7 +3,6 @@ import sys
import time import time
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import socket import socket
from core.classes.protocol import Protocol
if TYPE_CHECKING: if TYPE_CHECKING:
from core.irc import Irc from core.irc import Irc
@@ -15,9 +14,10 @@ REHASH_MODULES = [
'core.classes.config', 'core.classes.config',
'core.base', 'core.base',
'core.classes.commands', 'core.classes.commands',
'core.classes.protocols.interface',
'core.classes.protocols.factory',
'core.classes.protocols.unreal6', 'core.classes.protocols.unreal6',
'core.classes.protocols.inspircd', 'core.classes.protocols.inspircd'
'core.classes.protocol'
] ]
@@ -36,7 +36,7 @@ def restart_service(uplink: 'Irc', reason: str = "Restarting with no reason!") -
# Reload configuration # Reload configuration
uplink.Config = uplink.Loader.ConfModule.Configuration(uplink.Loader).get_config_model() uplink.Config = uplink.Loader.ConfModule.Configuration(uplink.Loader).get_config_model()
uplink.Base = uplink.Loader.BaseModule.Base(uplink.Loader) uplink.Base = uplink.Loader.BaseModule.Base(uplink.Loader)
uplink.Protocol = Protocol(uplink.Config.SERVEUR_PROTOCOL, uplink.ircObject).Protocol uplink.Protocol = uplink.Loader.PFactory.get()
uplink.Logs.debug(f'[{uplink.Config.SERVICE_NICKNAME} RESTART]: Reloading configuration!') uplink.Logs.debug(f'[{uplink.Config.SERVICE_NICKNAME} RESTART]: Reloading configuration!')
uplink.Protocol.send_squit(server_id=uplink.Config.SERVEUR_ID, server_link=uplink.Config.SERVEUR_LINK, reason="Defender Power off") uplink.Protocol.send_squit(server_id=uplink.Config.SERVEUR_ID, server_link=uplink.Config.SERVEUR_LINK, reason="Defender Power off")
@@ -106,7 +106,7 @@ def rehash_service(uplink: 'Irc', nickname: str) -> None:
uplink.Commands.DB_COMMANDS = uplink.Settings.get_cache('db_commands') uplink.Commands.DB_COMMANDS = uplink.Settings.get_cache('db_commands')
uplink.Base = uplink.Loader.BaseModule.Base(uplink.Loader) uplink.Base = uplink.Loader.BaseModule.Base(uplink.Loader)
uplink.Protocol = Protocol(uplink.Config.SERVEUR_PROTOCOL, uplink.ircObject).Protocol uplink.Protocol = uplink.Loader.PFactory.get()
# Reload Service modules # Reload Service modules
for module in uplink.ModuleUtils.model_get_loaded_modules().copy(): for module in uplink.ModuleUtils.model_get_loaded_modules().copy():

View File

@@ -7,12 +7,12 @@ from ssl import SSLSocket
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import TYPE_CHECKING, Any, Optional, Union from typing import TYPE_CHECKING, Any, Optional, Union
from core.classes import rehash from core.classes import rehash
from core.loader import Loader from core.classes.protocols.interface import IProtocol
from core.classes.protocol import Protocol
from core.utils import tr from core.utils import tr
if TYPE_CHECKING: if TYPE_CHECKING:
from core.definition import MSasl from core.definition import MSasl
from core.loader import Loader
class Irc: class Irc:
_instance = None _instance = None
@@ -24,7 +24,7 @@ class Irc:
return cls._instance return cls._instance
def __init__(self, loader: Loader) -> 'Irc': def __init__(self, loader: 'Loader'):
# Loader class # Loader class
self.Loader = loader self.Loader = loader
@@ -135,7 +135,7 @@ class Irc:
############################################## ##############################################
# CONNEXION IRC # # CONNEXION IRC #
############################################## ##############################################
def init_irc(self, ircInstance: 'Irc') -> None: def init_irc(self) -> None:
"""Create a socket and connect to irc server """Create a socket and connect to irc server
Args: Args:
@@ -143,8 +143,8 @@ class Irc:
""" """
try: try:
self.init_service_user() self.init_service_user()
self.Utils.create_socket(ircInstance) self.Utils.create_socket(self)
self.__connect_to_irc(ircInstance) self.__connect_to_irc()
except AssertionError as ae: except AssertionError as ae:
self.Logs.critical(f'Assertion error: {ae}') self.Logs.critical(f'Assertion error: {ae}')
@@ -161,23 +161,20 @@ class Irc:
)) ))
return None return None
def __connect_to_irc(self, ircInstance: 'Irc') -> None: def __connect_to_irc(self) -> None:
try: try:
self.init_service_user() self.init_service_user()
self.ircObject = ircInstance # créer une copie de l'instance Irc self.Protocol: 'IProtocol' = self.Loader.PFactory.get()
self.Protocol = Protocol(
protocol=self.Config.SERVEUR_PROTOCOL,
ircInstance=self.ircObject
).Protocol
self.Protocol.send_link() # Etablir le link en fonction du protocol choisi self.Protocol.send_link() # Etablir le link en fonction du protocol choisi
self.signal = True # Une variable pour initier la boucle infinie self.signal = True # Une variable pour initier la boucle infinie
self.join_saved_channels() # Join existing channels self.join_saved_channels() # Join existing channels
self.ModuleUtils.db_load_all_existing_modules(self) time.sleep(3)
# self.ModuleUtils.db_load_all_existing_modules(self)
while self.signal: while self.signal:
try: try:
if self.Config.DEFENDER_RESTART == 1: if self.Config.DEFENDER_RESTART == 1:
rehash.restart_service(self.ircObject) rehash.restart_service(self)
# 4072 max what the socket can grab # 4072 max what the socket can grab
buffer_size = self.IrcSocket.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF) buffer_size = self.IrcSocket.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)
@@ -202,9 +199,11 @@ class Irc:
self.Logs.error(f"SSLEOFError __connect_to_irc: {soe} - {data}") self.Logs.error(f"SSLEOFError __connect_to_irc: {soe} - {data}")
except ssl.SSLError as se: except ssl.SSLError as se:
self.Logs.error(f"SSLError __connect_to_irc: {se} - {data}") self.Logs.error(f"SSLError __connect_to_irc: {se} - {data}")
sys.exit(1) sys.exit(-1)
except OSError as oe: except OSError as oe:
self.Logs.error(f"SSLError __connect_to_irc: {oe} - {data}") self.Logs.error(f"SSLError __connect_to_irc: {oe} {oe.errno}")
if oe.errno == 10053:
sys.exit(-1)
except (socket.error, ConnectionResetError): except (socket.error, ConnectionResetError):
self.Logs.debug("Connexion reset") self.Logs.debug("Connexion reset")
@@ -790,8 +789,9 @@ class Irc:
if admin_obj: if admin_obj:
self.Protocol.send_priv_msg(nick_from=dnickname, self.Protocol.send_priv_msg(nick_from=dnickname,
msg=f"[ {GREEN}{str(current_command).upper()}{NOGC} ] - You are already connected to {dnickname}", msg=f"[ {GREEN}{str(current_command).upper()}{NOGC} ] - {fromuser} is already connected to {dnickname}",
channel=dchanlog) channel=dchanlog)
self.Protocol.send_notice(dnickname, fromuser, tr("You are already connected to %s", dnickname))
return None return None
mes_donnees = {'user': user_to_log, 'password': self.Loader.Utils.hash_password(password)} mes_donnees = {'user': user_to_log, 'password': self.Loader.Utils.hash_password(password)}
@@ -1179,7 +1179,7 @@ class Irc:
self.Config.DEFENDER_INIT = 1 # set init to 1 saying that the service will be re initiated self.Config.DEFENDER_INIT = 1 # set init to 1 saying that the service will be re initiated
case 'rehash': case 'rehash':
rehash.rehash_service(self.ircObject, fromuser) rehash.rehash_service(self, fromuser)
return None return None
case 'show_modules': case 'show_modules':

View File

@@ -8,6 +8,8 @@ import core.base as base_mod
import core.module as module_mod import core.module as module_mod
import core.classes.commands as commands_mod import core.classes.commands as commands_mod
import core.classes.config as conf_mod import core.classes.config as conf_mod
import core.irc as irc
import core.classes.protocols.factory as factory
class Loader: class Loader:
@@ -63,4 +65,8 @@ class Loader:
self.Sasl: sasl.Sasl = sasl.Sasl(self) self.Sasl: sasl.Sasl = sasl.Sasl(self)
self.Irc: irc.Irc = irc.Irc(self)
self.PFactory: factory.ProtocolFactorty = factory.ProtocolFactorty(self.Irc)
self.Logs.debug(self.Utils.tr("Loader %s success", __name__)) self.Logs.debug(self.Utils.tr("Loader %s success", __name__))

View File

@@ -15,7 +15,7 @@ class ServiceLogging:
self.SERVER_PREFIX = None self.SERVER_PREFIX = None
self.LOGGING_CONSOLE = True self.LOGGING_CONSOLE = True
self.LOG_FILTERS: list[str] = ['PING', f":{self.SERVER_PREFIX}auth", "['PASS'"] self.LOG_FILTERS: list[str] = ["PING", f":{self.SERVER_PREFIX}auth", "['PASS'"]
self.file_handler = None self.file_handler = None
self.stdout_handler = None self.stdout_handler = None

View File

@@ -36,7 +36,7 @@ def tr(message: str, *args) -> str:
is_args_available = True if args else False is_args_available = True if args else False
g = global_settings g = global_settings
try: try:
# Access to user object ==> global_instance.get_user_option # Access to admin object
client_language = g.current_admin.language if g.current_admin else g.global_lang client_language = g.current_admin.language if g.current_admin else g.global_lang
if count_args != count_placeholder: if count_args != count_placeholder:
@@ -56,7 +56,7 @@ def tr(message: str, *args) -> str:
return message % args if is_args_available else message return message % args if is_args_available else message
except KeyError as ke: except KeyError as ke:
g.global_logger.error(f"Key Error: {ke}") g.global_logger.error(f"KeyError: {ke}")
return message % args if is_args_available else message return message % args if is_args_available else message
except Exception as err: except Exception as err:
@@ -143,6 +143,8 @@ def create_socket(uplink: 'Irc') -> None:
uplink.Logs.critical(f"[OS Error]: {oe}") uplink.Logs.critical(f"[OS Error]: {oe}")
if 'connection refused' in str(oe).lower(): if 'connection refused' in str(oe).lower():
sys.exit(oe) sys.exit(oe)
if oe.errno == 10053:
sys.exit(oe)
except AttributeError as ae: except AttributeError as ae:
uplink.Logs.critical(f"AttributeError: {ae}") uplink.Logs.critical(f"AttributeError: {ae}")
@@ -241,4 +243,4 @@ def hide_sensitive_data(srvmsg: list[str]) -> list[str]:
return srv_msg return srv_msg
except ValueError: except ValueError:
return srvmsg return srvmsg

View File

@@ -11,14 +11,17 @@ from core import installation
try: try:
installation.Install() # installation.Install()
from core.loader import Loader from core.loader import Loader
from core.irc import Irc loader = Loader()
ircInstance = Irc(Loader()) loader.Irc.init_irc()
ircInstance.init_irc(ircInstance) # from core.irc import Irc
# ircInstance = Irc(Loader())
# ircInstance.init_irc(ircInstance)
except AssertionError as ae: except AssertionError as ae:
print(f'Assertion Error -> {ae}') print(f'Assertion Error -> {ae}')
except KeyboardInterrupt as k: except KeyboardInterrupt as k:
ircInstance.Base.execute_periodic_action() # ircInstance.Base.execute_periodic_action()
...