mirror of
https://github.com/iio612/DEFENDER.git
synced 2026-02-13 19:24:23 +00:00
@@ -53,7 +53,7 @@ Pour Les prochains lancement de defender vous devez utiliser la commande suivant
|
|||||||
$ cd IRC_DEFENDER_MODULES
|
$ cd IRC_DEFENDER_MODULES
|
||||||
$ python3 -m venv .pyenv
|
$ python3 -m venv .pyenv
|
||||||
$ source .pyenv/bin/activate
|
$ source .pyenv/bin/activate
|
||||||
(pyenv)$ pip install sqlalchemy, psutil, requests, faker, unrealircd_rpc_py
|
(pyenv)$ pip install sqlalchemy, psutil, requests, faker, unrealircd_rpc_py, pyyaml
|
||||||
|
|
||||||
# Créer un service nommé "defender.service"
|
# Créer un service nommé "defender.service"
|
||||||
# pour votre service et placer le dans "/PATH/TO/USER/.config/systemd/user/"
|
# pour votre service et placer le dans "/PATH/TO/USER/.config/systemd/user/"
|
||||||
|
|||||||
27
core/base.py
27
core/base.py
@@ -296,13 +296,14 @@ class Base:
|
|||||||
'password': password,
|
'password': password,
|
||||||
'hostname': '*',
|
'hostname': '*',
|
||||||
'vhost': '*',
|
'vhost': '*',
|
||||||
|
'language': 'EN',
|
||||||
'level': 5
|
'level': 5
|
||||||
}
|
}
|
||||||
self.db_execute_query(f"""
|
self.db_execute_query(f"""
|
||||||
INSERT INTO {self.Config.TABLE_ADMIN}
|
INSERT INTO {self.Config.TABLE_ADMIN}
|
||||||
(createdOn, user, password, hostname, vhost, level)
|
(createdOn, user, password, hostname, vhost, language, level)
|
||||||
VALUES
|
VALUES
|
||||||
(:createdOn, :user, :password, :hostname, :vhost, :level)"""
|
(:createdOn, :user, :password, :hostname, :vhost, :language, :level)"""
|
||||||
, mes_donnees)
|
, mes_donnees)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
@@ -564,6 +565,9 @@ class Base:
|
|||||||
self.db_execute_query(table_core_channel)
|
self.db_execute_query(table_core_channel)
|
||||||
self.db_execute_query(table_core_config)
|
self.db_execute_query(table_core_config)
|
||||||
|
|
||||||
|
# Patch database
|
||||||
|
self.db_patch(self.Config.TABLE_ADMIN, "language", "TEXT")
|
||||||
|
|
||||||
if self.install:
|
if self.install:
|
||||||
self.Loader.ModuleUtils.db_register_module('mod_command', 'sys', True)
|
self.Loader.ModuleUtils.db_register_module('mod_command', 'sys', True)
|
||||||
self.Loader.ModuleUtils.db_register_module('mod_defender', 'sys', True)
|
self.Loader.ModuleUtils.db_register_module('mod_defender', 'sys', True)
|
||||||
@@ -584,6 +588,25 @@ class Base:
|
|||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def db_is_column_exist(self, table_name: str, column_name: str) -> bool:
|
||||||
|
q = self.db_execute_query(f"PRAGMA table_info({table_name})")
|
||||||
|
existing_columns = [col[1] for col in q.fetchall()]
|
||||||
|
|
||||||
|
if column_name in existing_columns:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def db_patch(self, table_name: str, column_name: str, column_type: str) -> bool:
|
||||||
|
if not self.db_is_column_exist(table_name, column_name):
|
||||||
|
patch = f"ALTER TABLE {self.Config.TABLE_ADMIN} ADD COLUMN {column_name} {column_type}"
|
||||||
|
self.db_execute_query(patch)
|
||||||
|
self.logs.debug(f"The patch has been applied")
|
||||||
|
self.logs.debug(f"Table name: {table_name}, Column name: {column_name}, Column type: {column_type}")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def db_close(self) -> None:
|
def db_close(self) -> None:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ class Admin:
|
|||||||
|
|
||||||
def __init__(self, loader: 'Loader') -> None:
|
def __init__(self, loader: 'Loader') -> None:
|
||||||
self.Logs = loader.Logs
|
self.Logs = loader.Logs
|
||||||
|
self.Base = loader.Base
|
||||||
|
self.Setting = loader.Settings
|
||||||
|
self.Config = loader.Config
|
||||||
|
self.User = loader.User
|
||||||
|
self.Definition = loader.Definition
|
||||||
|
|
||||||
def insert(self, new_admin: MAdmin) -> bool:
|
def insert(self, new_admin: MAdmin) -> bool:
|
||||||
"""Insert a new admin object model
|
"""Insert a new admin object model
|
||||||
@@ -153,3 +158,46 @@ class Admin:
|
|||||||
return record.nickname
|
return record.nickname
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_language(self, uidornickname: str) -> Optional[str]:
|
||||||
|
"""Get the language of the admin
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uidornickname (str): The user ID or the Nickname of the admin
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Optional[str]: The language selected by the admin.
|
||||||
|
"""
|
||||||
|
admin = self.get_admin(uidornickname)
|
||||||
|
|
||||||
|
if admin is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return admin.language
|
||||||
|
|
||||||
|
def db_auth_admin_via_fingerprint(self, fp: str, uidornickname: str) -> bool:
|
||||||
|
"""Check the fingerprint
|
||||||
|
|
||||||
|
Args:
|
||||||
|
fp (str): The unique fingerprint of the user
|
||||||
|
uidornickname (str): The UID or the Nickname of the user
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if found
|
||||||
|
"""
|
||||||
|
query = f"SELECT user, level, language FROM {self.Config.TABLE_ADMIN} WHERE fingerprint = :fp"
|
||||||
|
data = {'fp': fp}
|
||||||
|
exe = self.Base.db_execute_query(query, data)
|
||||||
|
result = exe.fetchone()
|
||||||
|
if result:
|
||||||
|
account = result[0]
|
||||||
|
level = result[1]
|
||||||
|
language = result[2]
|
||||||
|
user_obj = self.User.get_user(uidornickname)
|
||||||
|
if user_obj:
|
||||||
|
admin_obj = self.Definition.MAdmin(**user_obj.to_dict(),account=account, level=level, language=language)
|
||||||
|
if self.insert(admin_obj):
|
||||||
|
self.Setting.current_admin = admin_obj
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|||||||
@@ -211,15 +211,6 @@ class Channel:
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_channel_asdict(self, channel_name: str) -> Optional[dict[str, Any]]:
|
|
||||||
|
|
||||||
channel_obj: Optional['MChannel'] = self.get_channel(channel_name)
|
|
||||||
|
|
||||||
if channel_obj is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return channel_obj.to_dict()
|
|
||||||
|
|
||||||
def is_valid_channel(self, channel_to_check: str) -> bool:
|
def is_valid_channel(self, channel_to_check: str) -> bool:
|
||||||
"""Check if the string has the # caractere and return True if this is a valid channel
|
"""Check if the string has the # caractere and return True if this is a valid channel
|
||||||
|
|
||||||
@@ -276,7 +267,7 @@ class Channel:
|
|||||||
mes_donnees = {'datetime': self.Utils.get_sdatetime(), 'channel_name': channel_name, 'module_name': module_name}
|
mes_donnees = {'datetime': self.Utils.get_sdatetime(), 'channel_name': channel_name, 'module_name': module_name}
|
||||||
insert = self.Base.db_execute_query(f"INSERT INTO {core_table} (datetime, channel_name, module_name) VALUES (:datetime, :channel_name, :module_name)", mes_donnees)
|
insert = self.Base.db_execute_query(f"INSERT INTO {core_table} (datetime, channel_name, module_name) VALUES (:datetime, :channel_name, :module_name)", mes_donnees)
|
||||||
if insert.rowcount:
|
if insert.rowcount:
|
||||||
self.Logs.debug(f'New channel added: channel={channel_name} / module_name={module_name}')
|
self.Logs.debug(f'Channel added to DB: channel={channel_name} / module_name={module_name}')
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
@@ -286,7 +277,7 @@ class Channel:
|
|||||||
response = self.Base.db_execute_query(f"DELETE FROM {core_table} WHERE channel_name = :channel_name AND module_name = :module_name", mes_donnes)
|
response = self.Base.db_execute_query(f"DELETE FROM {core_table} WHERE channel_name = :channel_name AND module_name = :module_name", mes_donnes)
|
||||||
|
|
||||||
if response.rowcount > 0:
|
if response.rowcount > 0:
|
||||||
self.Logs.debug(f'Channel deleted: channel={channel_name} / module: {module_name}')
|
self.Logs.debug(f'Channel deleted from DB: channel={channel_name} / module: {module_name}')
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ class Command:
|
|||||||
def __init__(self, loader: 'Loader'):
|
def __init__(self, loader: 'Loader'):
|
||||||
self.Loader = loader
|
self.Loader = loader
|
||||||
self.Base = loader.Base
|
self.Base = loader.Base
|
||||||
|
self.Logs = loader.Logs
|
||||||
|
|
||||||
def build(self, new_command_obj: MCommand) -> bool:
|
def build(self, new_command_obj: MCommand) -> bool:
|
||||||
|
|
||||||
@@ -45,6 +46,27 @@ class Command:
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def drop_command_by_module(self, module_name: str) -> bool:
|
||||||
|
"""Drop all command by module
|
||||||
|
|
||||||
|
Args:
|
||||||
|
module_name (str): The module name
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True
|
||||||
|
"""
|
||||||
|
tmp_model: list[MCommand] = []
|
||||||
|
|
||||||
|
for command in self.DB_COMMANDS:
|
||||||
|
if command.module_name.lower() == module_name.lower():
|
||||||
|
tmp_model.append(command)
|
||||||
|
|
||||||
|
for c in tmp_model:
|
||||||
|
self.DB_COMMANDS.remove(c)
|
||||||
|
|
||||||
|
self.Logs.debug(f"[COMMAND] Drop command for module {module_name}")
|
||||||
|
return True
|
||||||
|
|
||||||
def get_ordered_commands(self) -> list[MCommand]:
|
def get_ordered_commands(self) -> list[MCommand]:
|
||||||
return sorted(self.DB_COMMANDS, key=lambda c: (c.command_level, c.module_name))
|
return sorted(self.DB_COMMANDS, key=lambda c: (c.command_level, c.module_name))
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ 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.utils import tr
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.irc import Irc
|
from core.irc import Irc
|
||||||
from core.classes.sasl import Sasl
|
from core.classes.sasl import Sasl
|
||||||
@@ -25,7 +27,7 @@ class Unrealircd6:
|
|||||||
self.known_protocol: set[str] = {'SJOIN', 'UID', 'MD', 'QUIT', 'SQUIT',
|
self.known_protocol: set[str] = {'SJOIN', 'UID', 'MD', 'QUIT', 'SQUIT',
|
||||||
'EOS', 'PRIVMSG', 'MODE', 'UMODE2',
|
'EOS', 'PRIVMSG', 'MODE', 'UMODE2',
|
||||||
'VERSION', 'REPUTATION', 'SVS2MODE',
|
'VERSION', 'REPUTATION', 'SVS2MODE',
|
||||||
'SLOG', 'NICK', 'PART', 'PONG', 'SASL',
|
'SLOG', 'NICK', 'PART', 'PONG', 'SASL', 'PING',
|
||||||
'PROTOCTL', 'SERVER', 'SMOD', 'TKL', 'NETINFO',
|
'PROTOCTL', 'SERVER', 'SMOD', 'TKL', 'NETINFO',
|
||||||
'006', '007', '018'}
|
'006', '007', '018'}
|
||||||
|
|
||||||
@@ -567,6 +569,7 @@ class Unrealircd6:
|
|||||||
|
|
||||||
def on_svs2mode(self, serverMsg: list[str]) -> None:
|
def on_svs2mode(self, serverMsg: list[str]) -> None:
|
||||||
"""Handle svs2mode coming from a server
|
"""Handle svs2mode coming from a server
|
||||||
|
>>> [':00BAAAAAG', 'SVS2MODE', '001U01R03', '-r']
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
serverMsg (list[str]): Original server message
|
serverMsg (list[str]): Original server message
|
||||||
@@ -604,6 +607,7 @@ class Unrealircd6:
|
|||||||
|
|
||||||
def on_umode2(self, serverMsg: list[str]) -> None:
|
def on_umode2(self, serverMsg: list[str]) -> None:
|
||||||
"""Handle umode2 coming from a server
|
"""Handle umode2 coming from a server
|
||||||
|
>>> [':adator_', 'UMODE2', '-i']
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
serverMsg (list[str]): Original server message
|
serverMsg (list[str]): Original server message
|
||||||
@@ -860,7 +864,7 @@ class Unrealircd6:
|
|||||||
# Initialisation terminé aprés le premier PING
|
# Initialisation terminé aprés le premier PING
|
||||||
self.send_priv_msg(
|
self.send_priv_msg(
|
||||||
nick_from=self.__Config.SERVICE_NICKNAME,
|
nick_from=self.__Config.SERVICE_NICKNAME,
|
||||||
msg=f"[{self.__Config.COLORS.green}INFORMATION{self.__Config.COLORS.nogc}] >> Defender is ready",
|
msg=tr("[ %sINFORMATION%s ] >> %s is ready!", self.__Config.COLORS.green, self.__Config.COLORS.nogc, self.__Config.SERVICE_NICKNAME),
|
||||||
channel=self.__Config.SERVICE_CHANLOG
|
channel=self.__Config.SERVICE_CHANLOG
|
||||||
)
|
)
|
||||||
self.__Config.DEFENDER_INIT = 0
|
self.__Config.DEFENDER_INIT = 0
|
||||||
@@ -946,6 +950,11 @@ class Unrealircd6:
|
|||||||
fp_match = match(pattern, serverMsg[0])
|
fp_match = match(pattern, serverMsg[0])
|
||||||
fingerprint = fp_match.group(1) if fp_match else None
|
fingerprint = fp_match.group(1) if fp_match else None
|
||||||
|
|
||||||
|
# Extract tls_cipher information
|
||||||
|
pattern = r'^.*tls_cipher=([^;]+).*$'
|
||||||
|
tlsc_match = match(pattern, serverMsg[0])
|
||||||
|
tls_cipher = tlsc_match.group(1) if tlsc_match else None
|
||||||
|
|
||||||
if geoip_match:
|
if geoip_match:
|
||||||
geoip = geoip_match.group(1)
|
geoip = geoip_match.group(1)
|
||||||
else:
|
else:
|
||||||
@@ -963,6 +972,7 @@ class Unrealircd6:
|
|||||||
umodes=umodes,
|
umodes=umodes,
|
||||||
vhost=vhost,
|
vhost=vhost,
|
||||||
fingerprint=fingerprint,
|
fingerprint=fingerprint,
|
||||||
|
tls_cipher=tls_cipher,
|
||||||
isWebirc=isWebirc,
|
isWebirc=isWebirc,
|
||||||
isWebsocket=isWebsocket,
|
isWebsocket=isWebsocket,
|
||||||
remote_ip=remote_ip,
|
remote_ip=remote_ip,
|
||||||
@@ -971,6 +981,21 @@ class Unrealircd6:
|
|||||||
connexion_datetime=datetime.now()
|
connexion_datetime=datetime.now()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Auto Auth admin via fingerprint
|
||||||
|
dnickname = self.__Config.SERVICE_NICKNAME
|
||||||
|
dchanlog = self.__Config.SERVICE_CHANLOG
|
||||||
|
GREEN = self.__Config.COLORS.green
|
||||||
|
NOGC = self.__Config.COLORS.nogc
|
||||||
|
|
||||||
|
if self.__Irc.Admin.db_auth_admin_via_fingerprint(fingerprint, uid):
|
||||||
|
admin = self.__Irc.Admin.get_admin(uid)
|
||||||
|
account = admin.account if admin else ''
|
||||||
|
self.send_priv_msg(nick_from=dnickname,
|
||||||
|
msg=tr("[ %sSASL AUTO AUTH%s ] - %s (%s) is now connected successfuly to %s", GREEN, NOGC, nickname, account, dnickname),
|
||||||
|
channel=dchanlog)
|
||||||
|
self.send_notice(nick_from=dnickname, nick_to=nickname, msg=tr("Successfuly connected to %s", dnickname))
|
||||||
|
|
||||||
return None
|
return None
|
||||||
except IndexError as ie:
|
except IndexError as ie:
|
||||||
self.__Logs.error(f"{__name__} - Index Error: {ie}")
|
self.__Logs.error(f"{__name__} - Index Error: {ie}")
|
||||||
@@ -1302,3 +1327,33 @@ class Unrealircd6:
|
|||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
self.__Logs.error(f'General Error: {err}', exc_info=True)
|
self.__Logs.error(f'General Error: {err}', exc_info=True)
|
||||||
|
|
||||||
|
def on_md(self, serverMsg: list[str]) -> None:
|
||||||
|
"""Handle MD responses
|
||||||
|
[':001', 'MD', 'client', '001MYIZ03', 'certfp', ':d1235648...']
|
||||||
|
Args:
|
||||||
|
serverMsg (list[str]): The server reply
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
scopy = serverMsg.copy()
|
||||||
|
available_vars = ['creationtime', 'certfp', 'tls_cipher']
|
||||||
|
|
||||||
|
uid = str(scopy[3])
|
||||||
|
var = str(scopy[4]).lower()
|
||||||
|
value = str(scopy[5]).replace(':', '')
|
||||||
|
|
||||||
|
user_obj = self.__Irc.User.get_user(uid)
|
||||||
|
if user_obj is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
match var:
|
||||||
|
case 'certfp':
|
||||||
|
user_obj.fingerprint = value
|
||||||
|
case 'tls_cipher':
|
||||||
|
user_obj.tls_cipher = value
|
||||||
|
case _:
|
||||||
|
return None
|
||||||
|
|
||||||
|
...
|
||||||
|
except Exception as e:
|
||||||
|
self.__Logs.error(f"General Error: {e}")
|
||||||
@@ -69,7 +69,7 @@ def rehash_service(uplink: 'Irc', nickname: str) -> None:
|
|||||||
msg=f'[REHASH] Module [{mod}] reloaded',
|
msg=f'[REHASH] Module [{mod}] reloaded',
|
||||||
channel=uplink.Config.SERVICE_CHANLOG
|
channel=uplink.Config.SERVICE_CHANLOG
|
||||||
)
|
)
|
||||||
|
uplink.Utils = sys.modules['core.utils']
|
||||||
uplink.Config = uplink.Loader.ConfModule.Configuration(uplink.Loader).get_config_model()
|
uplink.Config = uplink.Loader.ConfModule.Configuration(uplink.Loader).get_config_model()
|
||||||
uplink.Config.HSID = config_model_bakcup.HSID
|
uplink.Config.HSID = config_model_bakcup.HSID
|
||||||
uplink.Config.DEFENDER_INIT = config_model_bakcup.DEFENDER_INIT
|
uplink.Config.DEFENDER_INIT = config_model_bakcup.DEFENDER_INIT
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
'''This class should never be reloaded.
|
'''This class should never be reloaded.
|
||||||
'''
|
'''
|
||||||
|
from logging import Logger
|
||||||
from threading import Timer, Thread, RLock
|
from threading import Timer, Thread, RLock
|
||||||
from socket import socket
|
from socket import socket
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional, TYPE_CHECKING
|
||||||
from core.definition import MSModule
|
from core.definition import MSModule, MAdmin
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from core.classes.user import User
|
||||||
|
from core.classes.admin import Admin
|
||||||
|
|
||||||
class Settings:
|
class Settings:
|
||||||
"""This Class will never be reloaded.
|
"""This Class will never be reloaded.
|
||||||
@@ -11,24 +16,38 @@ class Settings:
|
|||||||
the whole life of the app
|
the whole life of the app
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RUNNING_TIMERS: list[Timer] = []
|
RUNNING_TIMERS: list[Timer] = []
|
||||||
RUNNING_THREADS: list[Thread] = []
|
RUNNING_THREADS: list[Thread] = []
|
||||||
RUNNING_SOCKETS: list[socket] = []
|
RUNNING_SOCKETS: list[socket] = []
|
||||||
PERIODIC_FUNC: dict[object] = {}
|
PERIODIC_FUNC: dict[object] = {}
|
||||||
LOCK: RLock = RLock()
|
LOCK: RLock = RLock()
|
||||||
|
|
||||||
CONSOLE: bool = False
|
CONSOLE: bool = False
|
||||||
|
|
||||||
MAIN_SERVER_HOSTNAME: str = None
|
MAIN_SERVER_HOSTNAME: str = None
|
||||||
PROTOCTL_USER_MODES: list[str] = []
|
PROTOCTL_USER_MODES: list[str] = []
|
||||||
PROTOCTL_PREFIX: list[str] = []
|
PROTOCTL_PREFIX: list[str] = []
|
||||||
|
|
||||||
SMOD_MODULES: list[MSModule] = []
|
SMOD_MODULES: list[MSModule] = []
|
||||||
"""List contains all Server modules"""
|
"""List contains all Server modules"""
|
||||||
|
|
||||||
__CACHE: dict[str, Any] = {}
|
__CACHE: dict[str, Any] = {}
|
||||||
"""Use set_cache or get_cache instead"""
|
"""Use set_cache or get_cache instead"""
|
||||||
|
|
||||||
|
__TRANSLATION: dict[str, list[list[str]]] = dict()
|
||||||
|
"""Translation Varibale"""
|
||||||
|
|
||||||
|
__LANG: str = "EN"
|
||||||
|
|
||||||
|
__INSTANCE_OF_USER_UTILS: Optional['User'] = None
|
||||||
|
"""Instance of the User Utils class"""
|
||||||
|
|
||||||
|
__CURRENT_ADMIN: Optional['MAdmin'] = None
|
||||||
|
"""The Current Admin Object Model"""
|
||||||
|
|
||||||
|
__LOGGER: Optional[Logger] = None
|
||||||
|
"""Instance of the logger"""
|
||||||
|
|
||||||
def set_cache(self, key: str, value_to_cache: Any):
|
def set_cache(self, key: str, value_to_cache: Any):
|
||||||
"""When you want to store a variable
|
"""When you want to store a variable
|
||||||
|
|
||||||
@@ -57,3 +76,45 @@ class Settings:
|
|||||||
|
|
||||||
def show_cache(self) -> dict[str, Any]:
|
def show_cache(self) -> dict[str, Any]:
|
||||||
return self.__CACHE.copy()
|
return self.__CACHE.copy()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def global_translation(self) -> dict[str, list[list[str]]]:
|
||||||
|
return self.__TRANSLATION
|
||||||
|
|
||||||
|
@global_translation.setter
|
||||||
|
def global_translation(self, translation_var: dict) -> None:
|
||||||
|
self.__TRANSLATION = translation_var
|
||||||
|
|
||||||
|
@property
|
||||||
|
def global_lang(self) -> str:
|
||||||
|
return self.__LANG
|
||||||
|
|
||||||
|
@global_lang.setter
|
||||||
|
def global_lang(self, lang: str) -> None:
|
||||||
|
self.__LANG = lang
|
||||||
|
|
||||||
|
@property
|
||||||
|
def global_user(self) -> 'User':
|
||||||
|
return self.__INSTANCE_OF_USER_UTILS
|
||||||
|
|
||||||
|
@global_user.setter
|
||||||
|
def global_user(self, user_utils_instance: 'User') -> None:
|
||||||
|
self.__INSTANCE_OF_USER_UTILS = user_utils_instance
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_admin(self) -> MAdmin:
|
||||||
|
return self.__CURRENT_ADMIN
|
||||||
|
|
||||||
|
@current_admin.setter
|
||||||
|
def current_admin(self, current_admin: MAdmin) -> None:
|
||||||
|
self.__CURRENT_ADMIN = current_admin
|
||||||
|
|
||||||
|
@property
|
||||||
|
def global_logger(self) -> Logger:
|
||||||
|
return self.__LOGGER
|
||||||
|
|
||||||
|
@global_logger.setter
|
||||||
|
def global_logger(self, logger: Logger) -> None:
|
||||||
|
self.__LOGGER = logger
|
||||||
|
|
||||||
|
global_settings = Settings()
|
||||||
92
core/classes/translation.py
Normal file
92
core/classes/translation.py
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
import yaml
|
||||||
|
import yaml.scanner
|
||||||
|
from os import sep
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from core.loader import Loader
|
||||||
|
|
||||||
|
|
||||||
|
class Translation:
|
||||||
|
|
||||||
|
def __init__(self, loader: 'Loader') -> None:
|
||||||
|
self.Logs = loader.Logs
|
||||||
|
self.Settings = loader.Settings
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_translation(self) -> dict[str, list[list[str]]]:
|
||||||
|
try:
|
||||||
|
translation: dict[str, list[list[str]]] = dict()
|
||||||
|
sfs: dict[str, list[list[str]]] = {}
|
||||||
|
|
||||||
|
module_translation_directory = Path("mods")
|
||||||
|
core_translation_directory = Path("core")
|
||||||
|
sfs_core = self.get_subfolders_name(core_translation_directory.__str__())
|
||||||
|
sfs_module = self.get_subfolders_name(module_translation_directory.__str__())
|
||||||
|
|
||||||
|
# Combine the 2 dict
|
||||||
|
for d in (sfs_core, sfs_module):
|
||||||
|
for k, v in d.items():
|
||||||
|
sfs.setdefault(k, []).extend(v)
|
||||||
|
|
||||||
|
loaded_files: list[str] = []
|
||||||
|
|
||||||
|
for module, filenames in sfs.items():
|
||||||
|
translation[module] = []
|
||||||
|
for filename in filenames:
|
||||||
|
with open(f"{filename}", "r", encoding="utf-8") as fyaml:
|
||||||
|
data: dict[str, list[dict[str, str]]] = yaml.safe_load(fyaml)
|
||||||
|
|
||||||
|
if not isinstance(data, dict):
|
||||||
|
continue
|
||||||
|
|
||||||
|
for key, list_trad in data.items():
|
||||||
|
for vlist in list_trad:
|
||||||
|
translation[module].append([vlist["orig"], vlist["trad"]])
|
||||||
|
|
||||||
|
loaded_files.append(f"{filename}")
|
||||||
|
|
||||||
|
return translation
|
||||||
|
|
||||||
|
except yaml.scanner.ScannerError as se:
|
||||||
|
self.Logs.error(f"[!] {se} [!]")
|
||||||
|
return {}
|
||||||
|
except yaml.YAMLError as ye:
|
||||||
|
if hasattr(ye, 'problem_mark'):
|
||||||
|
mark = ye.problem_mark
|
||||||
|
self.Logs.error(f"Error YAML: {ye.with_traceback(None)}")
|
||||||
|
self.Logs.error("Error position: (%s:%s)" % (mark.line+1, mark.column+1))
|
||||||
|
return {}
|
||||||
|
except yaml.error.MarkedYAMLError as me:
|
||||||
|
self.Logs.error(f"[!] {me} [!]")
|
||||||
|
return {}
|
||||||
|
except Exception as err:
|
||||||
|
self.Logs.error(f'General Error: {err}', exc_info=True)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
finally:
|
||||||
|
self.Logs.debug("Translation files loaded")
|
||||||
|
for f in loaded_files:
|
||||||
|
self.Logs.debug(f" - {f}")
|
||||||
|
|
||||||
|
def get_subfolders_name(self, directory: str) -> dict[str, list[str]]:
|
||||||
|
try:
|
||||||
|
translation_information: dict[str, list[str]] = dict()
|
||||||
|
main_directory = Path(directory)
|
||||||
|
|
||||||
|
# Init the dictionnary
|
||||||
|
for subfolder in main_directory.rglob(f'*language{sep}*{sep}*.yaml'):
|
||||||
|
if subfolder.name != '__pycache__':
|
||||||
|
translation_information[subfolder.parent.name.lower()] = []
|
||||||
|
|
||||||
|
|
||||||
|
for subfolder in main_directory.rglob(f'*language{sep}*{sep}*.yaml'):
|
||||||
|
if subfolder.name != '__pycache__':
|
||||||
|
translation_information[subfolder.parent.name.lower()].append(subfolder)
|
||||||
|
|
||||||
|
return translation_information
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
self.Logs.error(f'General Error: {err}')
|
||||||
|
return {}
|
||||||
@@ -10,10 +10,15 @@ class User:
|
|||||||
|
|
||||||
UID_DB: list['MUser'] = []
|
UID_DB: list['MUser'] = []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def get_current_user(self) -> 'MUser':
|
||||||
|
return self.current_user
|
||||||
|
|
||||||
def __init__(self, loader: 'Loader'):
|
def __init__(self, loader: 'Loader'):
|
||||||
|
|
||||||
self.Logs = loader.Logs
|
self.Logs = loader.Logs
|
||||||
self.Base = loader.Base
|
self.Base = loader.Base
|
||||||
|
self.current_user: Optional['MUser'] = None
|
||||||
|
|
||||||
def insert(self, new_user: 'MUser') -> bool:
|
def insert(self, new_user: 'MUser') -> bool:
|
||||||
"""Insert a new User object
|
"""Insert a new User object
|
||||||
@@ -126,8 +131,10 @@ class User:
|
|||||||
"""
|
"""
|
||||||
for record in self.UID_DB:
|
for record in self.UID_DB:
|
||||||
if record.uid == uidornickname:
|
if record.uid == uidornickname:
|
||||||
|
self.current_user = record
|
||||||
return record
|
return record
|
||||||
elif record.nickname == uidornickname:
|
elif record.nickname == uidornickname:
|
||||||
|
self.current_user = record
|
||||||
return record
|
return record
|
||||||
|
|
||||||
return None
|
return None
|
||||||
@@ -147,6 +154,7 @@ class User:
|
|||||||
if user_obj is None:
|
if user_obj is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
self.current_user = user_obj
|
||||||
return user_obj.uid
|
return user_obj.uid
|
||||||
|
|
||||||
def get_nickname(self, uidornickname:str) -> Optional[str]:
|
def get_nickname(self, uidornickname:str) -> Optional[str]:
|
||||||
@@ -163,6 +171,7 @@ class User:
|
|||||||
if user_obj is None:
|
if user_obj is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
self.current_user = user_obj
|
||||||
return user_obj.nickname
|
return user_obj.nickname
|
||||||
|
|
||||||
def get_user_asdict(self, uidornickname: str) -> Optional[dict[str, Any]]:
|
def get_user_asdict(self, uidornickname: str) -> Optional[dict[str, Any]]:
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ class MClient(MainModel):
|
|||||||
umodes: str = None
|
umodes: str = None
|
||||||
vhost: str = None
|
vhost: str = None
|
||||||
fingerprint: str = None
|
fingerprint: str = None
|
||||||
|
tls_cipher: str = None
|
||||||
isWebirc: bool = False
|
isWebirc: bool = False
|
||||||
isWebsocket: bool = False
|
isWebsocket: bool = False
|
||||||
remote_ip: str = None
|
remote_ip: str = None
|
||||||
@@ -50,6 +51,7 @@ class MUser(MainModel):
|
|||||||
umodes: str = None
|
umodes: str = None
|
||||||
vhost: str = None
|
vhost: str = None
|
||||||
fingerprint: str = None
|
fingerprint: str = None
|
||||||
|
tls_cipher: str = None
|
||||||
isWebirc: bool = False
|
isWebirc: bool = False
|
||||||
isWebsocket: bool = False
|
isWebsocket: bool = False
|
||||||
remote_ip: str = None
|
remote_ip: str = None
|
||||||
@@ -70,12 +72,14 @@ class MAdmin(MainModel):
|
|||||||
umodes: str = None
|
umodes: str = None
|
||||||
vhost: str = None
|
vhost: str = None
|
||||||
fingerprint: str = None
|
fingerprint: str = None
|
||||||
|
tls_cipher: str = None
|
||||||
isWebirc: bool = False
|
isWebirc: bool = False
|
||||||
isWebsocket: bool = False
|
isWebsocket: bool = False
|
||||||
remote_ip: str = None
|
remote_ip: str = None
|
||||||
score_connexion: int = 0
|
score_connexion: int = 0
|
||||||
geoip: str = None
|
geoip: str = None
|
||||||
connexion_datetime: datetime = field(default=datetime.now())
|
connexion_datetime: datetime = field(default=datetime.now())
|
||||||
|
language: str = "EN"
|
||||||
level: int = 0
|
level: int = 0
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -191,6 +195,9 @@ class MConfig(MainModel):
|
|||||||
SERVICE_ID: str = field(init=False)
|
SERVICE_ID: str = field(init=False)
|
||||||
"""The service unique ID"""
|
"""The service unique ID"""
|
||||||
|
|
||||||
|
LANG: str = "EN"
|
||||||
|
"""The default language of Defender. default: EN"""
|
||||||
|
|
||||||
OWNER: str = "admin"
|
OWNER: str = "admin"
|
||||||
"""The nickname of the admin of the service"""
|
"""The nickname of the admin of the service"""
|
||||||
|
|
||||||
@@ -359,5 +366,6 @@ class MSasl(MainModel):
|
|||||||
username: Optional[str] = None
|
username: Optional[str] = None
|
||||||
password: Optional[str] = None
|
password: Optional[str] = None
|
||||||
fingerprint: Optional[str] = None
|
fingerprint: Optional[str] = None
|
||||||
|
language: str = "EN"
|
||||||
auth_success: bool = False
|
auth_success: bool = False
|
||||||
level: int = 0
|
level: int = 0
|
||||||
@@ -16,12 +16,12 @@ class Install:
|
|||||||
service_cmd_daemon_reload: list
|
service_cmd_daemon_reload: list
|
||||||
defender_main_executable: str
|
defender_main_executable: str
|
||||||
python_min_version: str
|
python_min_version: str
|
||||||
python_current_version_tuple: tuple[str, str, str]
|
python_current_version_tuple: tuple[int, int, int]
|
||||||
python_current_version: str
|
python_current_version: tuple[int, int, int]
|
||||||
defender_install_folder: str
|
defender_install_folder: str
|
||||||
venv_folder: str
|
venv_folder: str
|
||||||
venv_cmd_installation: list
|
venv_cmd_installation: list
|
||||||
venv_cmd_requirements: list
|
venv_cmd_requirements: list[str]
|
||||||
venv_pip_executable: str
|
venv_pip_executable: str
|
||||||
venv_python_executable: str
|
venv_python_executable: str
|
||||||
|
|
||||||
@@ -70,24 +70,24 @@ class Install:
|
|||||||
service_cmd_executable=['systemctl', '--user', 'start', 'defender'],
|
service_cmd_executable=['systemctl', '--user', 'start', 'defender'],
|
||||||
service_cmd_daemon_reload=['systemctl', '--user', 'daemon-reload'],
|
service_cmd_daemon_reload=['systemctl', '--user', 'daemon-reload'],
|
||||||
defender_main_executable=defender_main_executable,
|
defender_main_executable=defender_main_executable,
|
||||||
python_min_version='3.10',
|
python_min_version=(3, 10, 0),
|
||||||
python_current_version_tuple=python_version_tuple(),
|
python_current_version_tuple=tuple(map(int, python_version_tuple())),
|
||||||
python_current_version=python_version(),
|
python_current_version=python_version(),
|
||||||
defender_install_folder=defender_install_folder,
|
defender_install_folder=defender_install_folder,
|
||||||
venv_folder=venv_folder,
|
venv_folder=venv_folder,
|
||||||
venv_cmd_installation=['python3', '-m', 'venv', venv_folder],
|
venv_cmd_installation=['python3', '-m', 'venv', venv_folder],
|
||||||
venv_cmd_requirements=['sqlalchemy','psutil','requests','faker','unrealircd_rpc_py'],
|
venv_cmd_requirements=['sqlalchemy','psutil','requests','faker','pyyaml','unrealircd_rpc_py'],
|
||||||
venv_pip_executable=f'{os.path.join(defender_install_folder, venv_folder, "bin")}{os.sep}pip',
|
venv_pip_executable=f'{os.path.join(defender_install_folder, venv_folder, "bin")}{os.sep}pip',
|
||||||
venv_python_executable=f'{os.path.join(defender_install_folder, venv_folder, "bin")}{os.sep}python'
|
venv_python_executable=f'{os.path.join(defender_install_folder, venv_folder, "bin")}{os.sep}python'
|
||||||
)
|
)
|
||||||
|
|
||||||
if not self.check_python_version():
|
if not self.check_python_version():
|
||||||
# If the Python version is not good then Exit
|
# If the Python version is not good then Exit
|
||||||
exit("/!\\ Python version error /!\\")
|
exit("[!] Python version error [!]")
|
||||||
|
|
||||||
if not os.path.exists(os.path.join(self.config.defender_install_folder, 'config', 'configuration.json')):
|
if not os.path.exists(os.path.join(self.config.defender_install_folder, 'config', 'configuration.json')):
|
||||||
# If configuration file do not exist
|
# If configuration file do not exist
|
||||||
exit("/!\\ Configuration file (core/configuration.json) doesn't exist! please create it /!\\")
|
exit("[!] Configuration file (core/configuration.json) doesn't exist! please create it [!]")
|
||||||
|
|
||||||
# Exclude Windows OS from the installation
|
# Exclude Windows OS from the installation
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
@@ -98,7 +98,7 @@ class Install:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
if self.is_root():
|
if self.is_root():
|
||||||
exit(f'/!\\ I highly not recommend running Defender as root /!\\')
|
exit(f'[!] I highly not recommend running Defender as root [!]')
|
||||||
self.skip_install = True
|
self.skip_install = True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ class Install:
|
|||||||
print('> User without privileges ==> OK')
|
print('> User without privileges ==> OK')
|
||||||
return False
|
return False
|
||||||
elif os.geteuid() == 0:
|
elif os.geteuid() == 0:
|
||||||
print('/!\\ Do not use root to install Defender /!\\')
|
print('[!] Do not use root to install Defender [!]')
|
||||||
exit("Do not use root to install Defender")
|
exit("Do not use root to install Defender")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -117,13 +117,13 @@ class Install:
|
|||||||
full_service_file_path = os.path.join(self.config.unix_systemd_folder, self.config.service_file_name)
|
full_service_file_path = os.path.join(self.config.unix_systemd_folder, self.config.service_file_name)
|
||||||
|
|
||||||
if not os.path.exists(full_service_file_path):
|
if not os.path.exists(full_service_file_path):
|
||||||
print(f'/!\\ Service file does not exist /!\\')
|
print(f'[!] Service file does not exist [!]')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Check if virtual env exist
|
# Check if virtual env exist
|
||||||
if not os.path.exists(f'{os.path.join(self.config.defender_install_folder, self.config.venv_folder)}'):
|
if not os.path.exists(f'{os.path.join(self.config.defender_install_folder, self.config.venv_folder)}'):
|
||||||
self.run_subprocess(self.config.venv_cmd_installation)
|
self.run_subprocess(self.config.venv_cmd_installation)
|
||||||
print(f'/!\\ Virtual env does not exist run the install /!\\')
|
print(f'[!] Virtual env does not exist run the install [!]')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def run_subprocess(self, command:list) -> None:
|
def run_subprocess(self, command:list) -> None:
|
||||||
@@ -173,25 +173,19 @@ class Install:
|
|||||||
print(f"> Checking for dependencies versions ==> WAIT")
|
print(f"> Checking for dependencies versions ==> WAIT")
|
||||||
for package in self.DB_PACKAGES:
|
for package in self.DB_PACKAGES:
|
||||||
newVersion = False
|
newVersion = False
|
||||||
required_version = package.version
|
_required_version = package.version
|
||||||
installed_version = None
|
_installed_version: str = None
|
||||||
|
|
||||||
output = check_output([self.config.venv_pip_executable, 'show', package.name])
|
output = check_output([self.config.venv_pip_executable, 'show', package.name])
|
||||||
for line in output.decode().splitlines():
|
for line in output.decode().splitlines():
|
||||||
if line.startswith('Version:'):
|
if line.startswith('Version:'):
|
||||||
installed_version = line.split(':')[1].strip()
|
_installed_version = line.split(':')[1].strip()
|
||||||
break
|
break
|
||||||
|
|
||||||
required_major, required_minor, required_patch = required_version.split('.')
|
required_version = tuple(map(int, _required_version.split('.')))
|
||||||
installed_major, installed_minor, installed_patch = installed_version.split('.')
|
installed_version = tuple(map(int, _installed_version.split('.')))
|
||||||
|
|
||||||
if required_major > installed_major:
|
if required_version > installed_version:
|
||||||
print(f'> New version of {package.name} is available {installed_version} ==> {required_version}')
|
|
||||||
newVersion = True
|
|
||||||
elif required_major == installed_major and required_minor > installed_minor:
|
|
||||||
print(f'> New version of {package.name} is available {installed_version} ==> {required_version}')
|
|
||||||
newVersion = True
|
|
||||||
elif required_major == installed_major and required_minor == installed_minor and required_patch > installed_patch:
|
|
||||||
print(f'> New version of {package.name} is available {installed_version} ==> {required_version}')
|
print(f'> New version of {package.name} is available {installed_version} ==> {required_version}')
|
||||||
newVersion = True
|
newVersion = True
|
||||||
|
|
||||||
@@ -202,7 +196,7 @@ class Install:
|
|||||||
return newVersion
|
return newVersion
|
||||||
|
|
||||||
except CalledProcessError:
|
except CalledProcessError:
|
||||||
print(f"/!\\ Package {package.name} not installed /!\\")
|
print(f"[!] Package {package.name} not installed [!]")
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"General Error: {err}")
|
print(f"General Error: {err}")
|
||||||
|
|
||||||
@@ -212,23 +206,11 @@ class Install:
|
|||||||
Returns:
|
Returns:
|
||||||
bool: True si la version de python est autorisé sinon False
|
bool: True si la version de python est autorisé sinon False
|
||||||
"""
|
"""
|
||||||
# Current system version
|
if self.config.python_current_version_tuple < self.config.python_min_version:
|
||||||
sys_major, sys_minor, sys_patch = self.config.python_current_version_tuple
|
|
||||||
|
|
||||||
# min python version required
|
|
||||||
python_required_version = self.config.python_min_version.split('.')
|
|
||||||
min_major, min_minor = tuple((python_required_version[0], python_required_version[1]))
|
|
||||||
|
|
||||||
if int(sys_major) < int(min_major):
|
|
||||||
print(f"## Your python version must be greather than or equal to {self.config.python_min_version} ##")
|
|
||||||
return False
|
|
||||||
|
|
||||||
elif (int(sys_major) <= int(min_major)) and (int(sys_minor) < int(min_minor)):
|
|
||||||
print(f"## Your python version must be greather than or equal to {self.config.python_min_version} ##")
|
print(f"## Your python version must be greather than or equal to {self.config.python_min_version} ##")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
print(f"> Version of python : {self.config.python_current_version} ==> OK")
|
print(f"> Version of python : {self.config.python_current_version} ==> OK")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def check_package(self, package_name) -> bool:
|
def check_package(self, package_name) -> bool:
|
||||||
@@ -255,6 +237,7 @@ class Install:
|
|||||||
do_install = True
|
do_install = True
|
||||||
|
|
||||||
for module in self.config.venv_cmd_requirements:
|
for module in self.config.venv_cmd_requirements:
|
||||||
|
module = module.replace('pyyaml', 'yaml')
|
||||||
if not self.check_package(module):
|
if not self.check_package(module):
|
||||||
do_install = True
|
do_install = True
|
||||||
|
|
||||||
@@ -284,7 +267,7 @@ class Install:
|
|||||||
full_service_file_path = os.path.join(self.config.unix_systemd_folder, self.config.service_file_name)
|
full_service_file_path = os.path.join(self.config.unix_systemd_folder, self.config.service_file_name)
|
||||||
|
|
||||||
if os.path.exists(full_service_file_path):
|
if os.path.exists(full_service_file_path):
|
||||||
print(f'/!\\ Service file already exist /!\\')
|
print(f'[!] Service file already exist [!]')
|
||||||
self.run_subprocess(self.config.service_cmd_executable)
|
self.run_subprocess(self.config.service_cmd_executable)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
74
core/irc.py
74
core/irc.py
@@ -9,7 +9,7 @@ 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.loader import Loader
|
||||||
from core.classes.protocol import Protocol
|
from core.classes.protocol import Protocol
|
||||||
from core.classes.commands import Command
|
from core.utils import tr
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.definition import MSasl
|
from core.definition import MSasl
|
||||||
@@ -313,15 +313,15 @@ class Irc:
|
|||||||
def db_get_admin_info(*, username: Optional[str] = None, password: Optional[str] = None, fingerprint: Optional[str] = None) -> Optional[dict[str, Any]]:
|
def db_get_admin_info(*, username: Optional[str] = None, password: Optional[str] = None, fingerprint: Optional[str] = None) -> Optional[dict[str, Any]]:
|
||||||
if fingerprint:
|
if fingerprint:
|
||||||
mes_donnees = {'fingerprint': fingerprint}
|
mes_donnees = {'fingerprint': fingerprint}
|
||||||
query = f"SELECT user, level FROM {self.Config.TABLE_ADMIN} WHERE fingerprint = :fingerprint"
|
query = f"SELECT user, level, language FROM {self.Config.TABLE_ADMIN} WHERE fingerprint = :fingerprint"
|
||||||
else:
|
else:
|
||||||
mes_donnees = {'user': username, 'password': self.Utils.hash_password(password)}
|
mes_donnees = {'user': username, 'password': self.Utils.hash_password(password)}
|
||||||
query = f"SELECT user, level FROM {self.Config.TABLE_ADMIN} WHERE user = :user AND password = :password"
|
query = f"SELECT user, level, language FROM {self.Config.TABLE_ADMIN} WHERE user = :user AND password = :password"
|
||||||
|
|
||||||
result = self.Base.db_execute_query(query, mes_donnees)
|
result = self.Base.db_execute_query(query, mes_donnees)
|
||||||
user_from_db = result.fetchone()
|
user_from_db = result.fetchone()
|
||||||
if user_from_db:
|
if user_from_db:
|
||||||
return {'user': user_from_db[0], 'level': user_from_db[1]}
|
return {'user': user_from_db[0], 'level': user_from_db[1], 'language': user_from_db[2]}
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -331,6 +331,7 @@ class Irc:
|
|||||||
if admin_info is not None:
|
if admin_info is not None:
|
||||||
s.auth_success = True
|
s.auth_success = True
|
||||||
s.level = admin_info.get('level', 0)
|
s.level = admin_info.get('level', 0)
|
||||||
|
s.language = admin_info.get('language', 'EN')
|
||||||
self.Protocol.send2socket(f":{self.Config.SERVEUR_LINK} SASL {self.Settings.MAIN_SERVER_HOSTNAME} {s.client_uid} D S")
|
self.Protocol.send2socket(f":{self.Config.SERVEUR_LINK} SASL {self.Settings.MAIN_SERVER_HOSTNAME} {s.client_uid} D S")
|
||||||
self.Protocol.send2socket(f":{self.Config.SERVEUR_LINK} 903 {s.username} :SASL authentication successful")
|
self.Protocol.send2socket(f":{self.Config.SERVEUR_LINK} 903 {s.username} :SASL authentication successful")
|
||||||
else:
|
else:
|
||||||
@@ -345,6 +346,7 @@ class Irc:
|
|||||||
s.auth_success = True
|
s.auth_success = True
|
||||||
s.level = admin_info.get('level', 0)
|
s.level = admin_info.get('level', 0)
|
||||||
s.username = admin_info.get('user', None)
|
s.username = admin_info.get('user', None)
|
||||||
|
s.language = admin_info.get('language', 'EN')
|
||||||
self.Protocol.send2socket(f":{self.Config.SERVEUR_LINK} SASL {self.Settings.MAIN_SERVER_HOSTNAME} {s.client_uid} D S")
|
self.Protocol.send2socket(f":{self.Config.SERVEUR_LINK} SASL {self.Settings.MAIN_SERVER_HOSTNAME} {s.client_uid} D S")
|
||||||
self.Protocol.send2socket(f":{self.Config.SERVEUR_LINK} 903 {s.username} :SASL authentication successful")
|
self.Protocol.send2socket(f":{self.Config.SERVEUR_LINK} 903 {s.username} :SASL authentication successful")
|
||||||
else:
|
else:
|
||||||
@@ -380,14 +382,16 @@ class Irc:
|
|||||||
time.sleep(beat)
|
time.sleep(beat)
|
||||||
self.Base.execute_periodic_action()
|
self.Base.execute_periodic_action()
|
||||||
|
|
||||||
def insert_db_admin(self, uid: str, account: str, level: int) -> None:
|
def insert_db_admin(self, uid: str, account: str, level: int, language: str) -> None:
|
||||||
user_obj = self.User.get_user(uid)
|
user_obj = self.User.get_user(uid)
|
||||||
|
|
||||||
if user_obj is None:
|
if user_obj is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
self.Admin.insert(
|
self.Admin.insert(
|
||||||
self.Loader.Definition.MAdmin(
|
self.Loader.Definition.MAdmin(
|
||||||
**user_obj.to_dict(),
|
**user_obj.to_dict(),
|
||||||
|
language=language,
|
||||||
account=account,
|
account=account,
|
||||||
level=int(level)
|
level=int(level)
|
||||||
)
|
)
|
||||||
@@ -476,13 +480,17 @@ class Irc:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
original_response: list[str] = data.copy()
|
original_response: list[str] = data.copy()
|
||||||
|
RED = self.Config.COLORS.red
|
||||||
|
GREEN = self.Config.COLORS.green
|
||||||
|
NOGC = self.Config.COLORS.nogc
|
||||||
|
|
||||||
if len(original_response) < 2:
|
if len(original_response) < 2:
|
||||||
self.Logs.warning(f'Size ({str(len(original_response))}) - {original_response}')
|
self.Logs.warning(f'Size ({str(len(original_response))}) - {original_response}')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
self.Logs.debug(f">> {self.Utils.hide_sensitive_data(original_response)}")
|
self.Logs.debug(f">> {self.Utils.hide_sensitive_data(original_response)}")
|
||||||
parsed_protocol = self.Protocol.parse_server_msg(original_response.copy())
|
# parsed_protocol = self.Protocol.parse_server_msg(original_response.copy())
|
||||||
|
pos, parsed_protocol = self.Protocol.get_ircd_protocol_poisition(cmd=original_response)
|
||||||
match parsed_protocol:
|
match parsed_protocol:
|
||||||
|
|
||||||
case 'PING':
|
case 'PING':
|
||||||
@@ -512,16 +520,16 @@ class Irc:
|
|||||||
sasl_obj = self.Sasl.get_sasl_obj(uid)
|
sasl_obj = self.Sasl.get_sasl_obj(uid)
|
||||||
if sasl_obj:
|
if sasl_obj:
|
||||||
if sasl_obj.auth_success:
|
if sasl_obj.auth_success:
|
||||||
self.insert_db_admin(sasl_obj.client_uid, sasl_obj.username, sasl_obj.level)
|
self.insert_db_admin(sasl_obj.client_uid, sasl_obj.username, sasl_obj.level, sasl_obj.language)
|
||||||
self.Protocol.send_priv_msg(nick_from=dnickname,
|
self.Protocol.send_priv_msg(nick_from=dnickname,
|
||||||
msg=f"[ {self.Config.COLORS.green}SASL AUTH{self.Config.COLORS.nogc} ] - {nickname} ({sasl_obj.username}) est désormais connecté a {dnickname}",
|
msg=tr("[ %sSASL AUTH%s ] - %s (%s) is now connected successfuly to %s", GREEN, NOGC, nickname, sasl_obj.username, dnickname),
|
||||||
channel=dchanlog)
|
channel=dchanlog)
|
||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=nickname, msg=f"Connexion a {dnickname} réussie!")
|
self.Protocol.send_notice(nick_from=dnickname, nick_to=nickname, msg=tr("Successfuly connected to %s", dnickname))
|
||||||
else:
|
else:
|
||||||
self.Protocol.send_priv_msg(nick_from=dnickname,
|
self.Protocol.send_priv_msg(nick_from=dnickname,
|
||||||
msg=f"[ {self.Config.COLORS.red}SASL AUTH{self.Config.COLORS.nogc} ] - {nickname} a tapé un mauvais mot de pass pour le username ({sasl_obj.username})",
|
msg=tr("[ %sSASL AUTH%s ] - %s provided a wrong password for this username %s", RED, NOGC, nickname, sasl_obj.username),
|
||||||
channel=dchanlog)
|
channel=dchanlog)
|
||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=nickname, msg=f"Mot de passe incorrecte")
|
self.Protocol.send_notice(nick_from=dnickname, nick_to=nickname, msg=tr("Wrong password!"))
|
||||||
|
|
||||||
# Delete sasl object!
|
# Delete sasl object!
|
||||||
self.Sasl.delete_sasl_client(uid)
|
self.Sasl.delete_sasl_client(uid)
|
||||||
@@ -537,7 +545,6 @@ class Irc:
|
|||||||
self.Protocol.on_protoctl(serverMsg=original_response)
|
self.Protocol.on_protoctl(serverMsg=original_response)
|
||||||
|
|
||||||
case 'SVS2MODE':
|
case 'SVS2MODE':
|
||||||
# >> [':00BAAAAAG', 'SVS2MODE', '001U01R03', '-r']
|
|
||||||
self.Protocol.on_svs2mode(serverMsg=original_response)
|
self.Protocol.on_svs2mode(serverMsg=original_response)
|
||||||
|
|
||||||
case 'SQUIT':
|
case 'SQUIT':
|
||||||
@@ -550,7 +557,6 @@ class Irc:
|
|||||||
self.Protocol.on_version_msg(serverMsg=original_response)
|
self.Protocol.on_version_msg(serverMsg=original_response)
|
||||||
|
|
||||||
case 'UMODE2':
|
case 'UMODE2':
|
||||||
# [':adator_', 'UMODE2', '-i']
|
|
||||||
self.Protocol.on_umode2(serverMsg=original_response)
|
self.Protocol.on_umode2(serverMsg=original_response)
|
||||||
|
|
||||||
case 'NICK':
|
case 'NICK':
|
||||||
@@ -566,15 +572,15 @@ class Irc:
|
|||||||
sasl_response = self.Protocol.on_sasl(original_response, self.Sasl)
|
sasl_response = self.Protocol.on_sasl(original_response, self.Sasl)
|
||||||
self.on_sasl_authentication_process(sasl_response)
|
self.on_sasl_authentication_process(sasl_response)
|
||||||
|
|
||||||
case 'SLOG': # TODO
|
case 'MD':
|
||||||
self.Logs.debug(f"[!] TO HANDLE: {parsed_protocol}")
|
self.Protocol.on_md(serverMsg=original_response)
|
||||||
|
|
||||||
case 'MD': # TODO
|
|
||||||
self.Logs.debug(f"[!] TO HANDLE: {parsed_protocol}")
|
|
||||||
|
|
||||||
case 'PRIVMSG':
|
case 'PRIVMSG':
|
||||||
self.Protocol.on_privmsg(serverMsg=original_response)
|
self.Protocol.on_privmsg(serverMsg=original_response)
|
||||||
|
|
||||||
|
case 'SLOG': # TODO
|
||||||
|
self.Logs.debug(f"[!] TO HANDLE: {parsed_protocol}")
|
||||||
|
|
||||||
case 'PONG': # TODO
|
case 'PONG': # TODO
|
||||||
self.Logs.debug(f"[!] TO HANDLE: {parsed_protocol}")
|
self.Logs.debug(f"[!] TO HANDLE: {parsed_protocol}")
|
||||||
|
|
||||||
@@ -619,7 +625,8 @@ class Irc:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
fromuser = self.User.get_nickname(user) # Nickname qui a lancé la commande
|
fromuser = self.User.get_nickname(user) # Nickname qui a lancé la commande
|
||||||
uid = self.User.get_uid(fromuser) # Récuperer le uid de l'utilisateur
|
uid = self.User.get_uid(user) # Récuperer le uid de l'utilisateur
|
||||||
|
self.Settings.current_admin = self.Admin.get_admin(user) # set Current admin if any.
|
||||||
|
|
||||||
RED = self.Config.COLORS.red
|
RED = self.Config.COLORS.red
|
||||||
GREEN = self.Config.COLORS.green
|
GREEN = self.Config.COLORS.green
|
||||||
@@ -646,9 +653,9 @@ class Irc:
|
|||||||
|
|
||||||
case 'notallowed':
|
case 'notallowed':
|
||||||
try:
|
try:
|
||||||
current_command = cmd[0]
|
current_command = str(cmd[0])
|
||||||
self.Protocol.send_priv_msg(
|
self.Protocol.send_priv_msg(
|
||||||
msg=f'[ {RED}{current_command}{NOGC} ] - Accès Refusé à {self.User.get_nickname(fromuser)}',
|
msg=tr('[ %s%s%s ] - Access denied to %s', RED, current_command.upper(), NOGC, fromuser),
|
||||||
nick_from=dnickname,
|
nick_from=dnickname,
|
||||||
channel=dchanlog
|
channel=dchanlog
|
||||||
)
|
)
|
||||||
@@ -656,7 +663,7 @@ class Irc:
|
|||||||
self.Protocol.send_notice(
|
self.Protocol.send_notice(
|
||||||
nick_from=dnickname,
|
nick_from=dnickname,
|
||||||
nick_to=fromuser,
|
nick_to=fromuser,
|
||||||
msg=f'Accès Refusé'
|
msg=tr('Access denied!')
|
||||||
)
|
)
|
||||||
|
|
||||||
except IndexError as ie:
|
except IndexError as ie:
|
||||||
@@ -664,12 +671,12 @@ class Irc:
|
|||||||
|
|
||||||
case 'deauth':
|
case 'deauth':
|
||||||
|
|
||||||
current_command = cmd[0]
|
current_command = str(cmd[0]).upper()
|
||||||
uid_to_deauth = self.User.get_uid(fromuser)
|
uid_to_deauth = self.User.get_uid(fromuser)
|
||||||
self.delete_db_admin(uid_to_deauth)
|
self.delete_db_admin(uid_to_deauth)
|
||||||
|
|
||||||
self.Protocol.send_priv_msg(
|
self.Protocol.send_priv_msg(
|
||||||
msg=f"[ {RED}{str(current_command).upper()}{NOGC} ] - {self.User.get_nickname(fromuser)} est désormais déconnecter de {dnickname}",
|
msg=tr("[ %s%s%s ] - %s has been disconnected from %s", RED, current_command, NOGC, fromuser, dnickname),
|
||||||
nick_from=dnickname,
|
nick_from=dnickname,
|
||||||
channel=dchanlog
|
channel=dchanlog
|
||||||
)
|
)
|
||||||
@@ -688,7 +695,7 @@ class Irc:
|
|||||||
self.Protocol.send_notice(
|
self.Protocol.send_notice(
|
||||||
nick_from=dnickname,
|
nick_from=dnickname,
|
||||||
nick_to=fromuser,
|
nick_to=fromuser,
|
||||||
msg=f"You can't use this command anymore ! Please use [{self.Config.SERVICE_PREFIX}auth] instead"
|
msg=tr("You can't use this command anymore ! Please use [%sauth] instead", self.Config.SERVICE_PREFIX)
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -733,7 +740,7 @@ class Irc:
|
|||||||
|
|
||||||
if cmd_owner == config_owner and cmd_password == config_password:
|
if cmd_owner == config_owner and cmd_password == config_password:
|
||||||
self.Base.db_create_first_admin()
|
self.Base.db_create_first_admin()
|
||||||
self.insert_db_admin(current_uid, cmd_owner, 5)
|
self.insert_db_admin(current_uid, cmd_owner, 5, self.Config.LANG)
|
||||||
self.Protocol.send_priv_msg(
|
self.Protocol.send_priv_msg(
|
||||||
msg=f"[ {self.Config.COLORS.green}{str(current_command).upper()} ]{self.Config.COLORS.black} - {self.User.get_nickname(fromuser)} est désormais connecté a {dnickname}",
|
msg=f"[ {self.Config.COLORS.green}{str(current_command).upper()} ]{self.Config.COLORS.black} - {self.User.get_nickname(fromuser)} est désormais connecté a {dnickname}",
|
||||||
nick_from=dnickname,
|
nick_from=dnickname,
|
||||||
@@ -784,14 +791,15 @@ class Irc:
|
|||||||
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)}
|
||||||
query = f"SELECT id, user, level FROM {self.Config.TABLE_ADMIN} WHERE user = :user AND password = :password"
|
query = f"SELECT id, user, level, language FROM {self.Config.TABLE_ADMIN} WHERE user = :user AND password = :password"
|
||||||
result = self.Base.db_execute_query(query, mes_donnees)
|
result = self.Base.db_execute_query(query, mes_donnees)
|
||||||
user_from_db = result.fetchone()
|
user_from_db = result.fetchone()
|
||||||
|
|
||||||
if user_from_db:
|
if user_from_db:
|
||||||
account = user_from_db[1]
|
account = str(user_from_db[1])
|
||||||
level = user_from_db[2]
|
level = int(user_from_db[2])
|
||||||
self.insert_db_admin(current_client.uid, account, level)
|
language = str(user_from_db[3])
|
||||||
|
self.insert_db_admin(current_client.uid, account, level, language)
|
||||||
self.Protocol.send_priv_msg(nick_from=dnickname,
|
self.Protocol.send_priv_msg(nick_from=dnickname,
|
||||||
msg=f"[ {GREEN}{str(current_command).upper()}{NOGC} ] - {current_client.nickname} ({account}) est désormais connecté a {dnickname}",
|
msg=f"[ {GREEN}{str(current_command).upper()}{NOGC} ] - {current_client.nickname} ({account}) est désormais connecté a {dnickname}",
|
||||||
channel=dchanlog)
|
channel=dchanlog)
|
||||||
@@ -1189,14 +1197,14 @@ class Irc:
|
|||||||
self.Protocol.send_notice(
|
self.Protocol.send_notice(
|
||||||
nick_from=dnickname,
|
nick_from=dnickname,
|
||||||
nick_to=fromuser,
|
nick_to=fromuser,
|
||||||
msg=f"{module} - {GREEN}Loaded{NOGC} by {loaded_user} on {loaded_datetime}"
|
msg=tr('%s - %sLoaded%s by %s on %s', module, GREEN, NOGC, loaded_user, loaded_datetime)
|
||||||
)
|
)
|
||||||
loaded = False
|
loaded = False
|
||||||
else:
|
else:
|
||||||
self.Protocol.send_notice(
|
self.Protocol.send_notice(
|
||||||
nick_from=dnickname,
|
nick_from=dnickname,
|
||||||
nick_to=fromuser,
|
nick_to=fromuser,
|
||||||
msg=f"{module} - {RED}Not Loaded{NOGC}"
|
msg=tr('%s - %sNot Loaded%s', module, GREEN, NOGC)
|
||||||
)
|
)
|
||||||
|
|
||||||
case 'show_timers':
|
case 'show_timers':
|
||||||
@@ -1266,7 +1274,7 @@ class Irc:
|
|||||||
self.Protocol.send_notice(
|
self.Protocol.send_notice(
|
||||||
nick_from=dnickname,
|
nick_from=dnickname,
|
||||||
nick_to=fromuser,
|
nick_to=fromuser,
|
||||||
msg=f"UID : {db_admin.uid} - Nickname: {db_admin.nickname} - Account: {db_admin.account} - Level: {db_admin.level} - Connection: {db_admin.connexion_datetime}"
|
msg=f"UID : {db_admin.uid} - Nickname: {db_admin.nickname} - Account: {db_admin.account} - Level: {db_admin.level} - Language: {db_admin.language} - Connection: {db_admin.connexion_datetime}"
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
13
core/language/fr/core-fr.yaml
Normal file
13
core/language/fr/core-fr.yaml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
traduction:
|
||||||
|
# Message help
|
||||||
|
- orig: "Access denied!"
|
||||||
|
trad: "Accès refusé."
|
||||||
|
- orig: "%s - %sLoaded%s by %s on %s"
|
||||||
|
trad: "%s - %sChargé%s par %s le %s"
|
||||||
|
- orig: "%s - %sNot Loaded%s"
|
||||||
|
trad: "%s - %sNon chargé%s"
|
||||||
|
- orig: "Successfuly connected to %s"
|
||||||
|
trad: "Connecter a %s avec succés"
|
||||||
|
- orig: "[ %sINFORMATION%s ] >> %s is ready!"
|
||||||
|
trad: "[ %sINFORMATION%s ] >> %s est prêt!"
|
||||||
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
from logging import Logger
|
from logging import Logger
|
||||||
from core.classes import user, admin, client, channel, reputation, settings, sasl
|
from core.classes.settings import global_settings
|
||||||
|
from core.classes import translation, user, admin, client, channel, reputation, settings, sasl
|
||||||
import core.logs as logs
|
import core.logs as logs
|
||||||
import core.definition as df
|
import core.definition as df
|
||||||
import core.utils as utils
|
import core.utils as utils
|
||||||
@@ -13,43 +14,53 @@ class Loader:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
# Load Main Modules
|
# Load Main Modules
|
||||||
self.Definition: df = df
|
self.Definition: df = df
|
||||||
|
|
||||||
self.ConfModule: conf_mod = conf_mod
|
self.ConfModule: conf_mod = conf_mod
|
||||||
|
|
||||||
self.BaseModule: base_mod = base_mod
|
self.BaseModule: base_mod = base_mod
|
||||||
|
|
||||||
self.CommandModule: commands_mod = commands_mod
|
self.CommandModule: commands_mod = commands_mod
|
||||||
|
|
||||||
self.LoggingModule: logs = logs
|
self.LoggingModule: logs = logs
|
||||||
|
|
||||||
self.Utils: utils = utils
|
self.Utils: utils = utils
|
||||||
|
|
||||||
# Load Classes
|
# Load Classes
|
||||||
self.ServiceLogging: logs.ServiceLogging = self.LoggingModule.ServiceLogging()
|
self.Settings: settings.Settings = global_settings
|
||||||
|
|
||||||
self.Logs: Logger = self.ServiceLogging.get_logger()
|
self.ServiceLogging: logs.ServiceLogging = self.LoggingModule.ServiceLogging()
|
||||||
|
|
||||||
self.Settings: settings.Settings = settings.Settings()
|
self.Logs: Logger = self.ServiceLogging.get_logger()
|
||||||
|
|
||||||
self.Config: df.MConfig = self.ConfModule.Configuration(self).get_config_model()
|
self.Config: df.MConfig = self.ConfModule.Configuration(self).get_config_model()
|
||||||
|
|
||||||
self.Base: base_mod.Base = self.BaseModule.Base(self)
|
self.Settings.global_lang = self.Config.LANG if self.Config.LANG else "EN"
|
||||||
|
|
||||||
self.User: user.User = user.User(self)
|
self.Settings.global_logger = self.Logs
|
||||||
|
|
||||||
self.Client: client.Client = client.Client(self)
|
self.Translation: translation.Translation = translation.Translation(self)
|
||||||
|
|
||||||
self.Admin: admin.Admin = admin.Admin(self)
|
self.Settings.global_translation = self.Translation.get_translation()
|
||||||
|
|
||||||
self.Channel: channel.Channel = channel.Channel(self)
|
self.Base: base_mod.Base = self.BaseModule.Base(self)
|
||||||
|
|
||||||
self.Reputation: reputation.Reputation = reputation.Reputation(self)
|
self.User: user.User = user.User(self)
|
||||||
|
|
||||||
self.Commands: commands_mod.Command = commands_mod.Command(self)
|
self.Settings.global_user = self.User
|
||||||
|
|
||||||
self.ModuleUtils: module_mod.Module = module_mod.Module(self)
|
self.Client: client.Client = client.Client(self)
|
||||||
|
|
||||||
self.Sasl: sasl.Sasl = sasl.Sasl(self)
|
self.Admin: admin.Admin = admin.Admin(self)
|
||||||
|
|
||||||
self.Logs.debug("LOADER Success!")
|
self.Channel: channel.Channel = channel.Channel(self)
|
||||||
|
|
||||||
|
self.Reputation: reputation.Reputation = reputation.Reputation(self)
|
||||||
|
|
||||||
|
self.Commands: commands_mod.Command = commands_mod.Command(self)
|
||||||
|
|
||||||
|
self.ModuleUtils: module_mod.Module = module_mod.Module(self)
|
||||||
|
|
||||||
|
self.Sasl: sasl.Sasl = sasl.Sasl(self)
|
||||||
|
|
||||||
|
self.Logs.debug(self.Utils.tr("Loader %s success", __name__))
|
||||||
|
|||||||
@@ -13,10 +13,56 @@ from datetime import datetime, timedelta, timezone
|
|||||||
from time import time
|
from time import time
|
||||||
from random import choice
|
from random import choice
|
||||||
from hashlib import md5, sha3_512
|
from hashlib import md5, sha3_512
|
||||||
|
from core.classes.settings import global_settings
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.irc import Irc
|
from core.irc import Irc
|
||||||
|
|
||||||
|
def tr(message: str, *args) -> str:
|
||||||
|
"""Translation Engine system
|
||||||
|
```python
|
||||||
|
example:
|
||||||
|
_('Hello my firstname is %s and my lastname is %s', firstname, lastname)
|
||||||
|
```
|
||||||
|
Args:
|
||||||
|
message (str): The message to translate
|
||||||
|
*args (any) : Whatever the variable you want to pass
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The translated message
|
||||||
|
"""
|
||||||
|
count_args = len(args) # Count number of args sent
|
||||||
|
count_placeholder = message.count('%s') # Count number of placeholder in the message
|
||||||
|
is_args_available = True if args else False
|
||||||
|
g = global_settings
|
||||||
|
try:
|
||||||
|
# Access to user object ==> global_instance.get_user_option
|
||||||
|
client_language = g.current_admin.language if g.current_admin else g.global_lang
|
||||||
|
|
||||||
|
if count_args != count_placeholder:
|
||||||
|
g.global_logger.error(f"Translation: Original message: {message} | Args: {count_args} - Placeholder: {count_placeholder}")
|
||||||
|
return message
|
||||||
|
|
||||||
|
if g.global_lang is None:
|
||||||
|
return message % args if is_args_available else message
|
||||||
|
|
||||||
|
if client_language.lower() == 'en':
|
||||||
|
return message % args if is_args_available else message
|
||||||
|
|
||||||
|
for trads in g.global_translation[client_language.lower()]:
|
||||||
|
if sub(r"\s+", "", message) == sub(r"\s+", "", trads[0]):
|
||||||
|
return trads[1] % args if is_args_available else trads[1]
|
||||||
|
|
||||||
|
return message % args if is_args_available else message
|
||||||
|
|
||||||
|
except KeyError as ke:
|
||||||
|
g.global_logger.error(f"Key Error: {ke}")
|
||||||
|
return message % args if is_args_available else message
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
global_settings.global_logger.error(f"General Error: {err} / {message}")
|
||||||
|
return message
|
||||||
|
|
||||||
def convert_to_int(value: Any) -> Optional[int]:
|
def convert_to_int(value: Any) -> Optional[int]:
|
||||||
"""Convert a value to int
|
"""Convert a value to int
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from core import installation
|
|||||||
# Requierements : #
|
# Requierements : #
|
||||||
# Python3.10 or higher #
|
# Python3.10 or higher #
|
||||||
# SQLAlchemy, requests, psutil #
|
# SQLAlchemy, requests, psutil #
|
||||||
# unrealircd-rpc-py #
|
# unrealircd-rpc-py, pyyaml #
|
||||||
# UnrealIRCD 6.2.2 or higher #
|
# UnrealIRCD 6.2.2 or higher #
|
||||||
#############################################
|
#############################################
|
||||||
|
|
||||||
|
|||||||
4
mods/clone/language/es/clone-es_1.yaml
Normal file
4
mods/clone/language/es/clone-es_1.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
traduction:
|
||||||
|
# Message help
|
||||||
|
- orig: "Hi my name is clone-es"
|
||||||
|
trad: "Hola mi name is clone-es"
|
||||||
6
mods/clone/language/fr/clone-fr_1.yaml
Normal file
6
mods/clone/language/fr/clone-fr_1.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
traduction:
|
||||||
|
# Message help
|
||||||
|
- orig: "You are now logged in"
|
||||||
|
trad: "Vous étes désomais identifier"
|
||||||
|
- orig: "NSUser ==> nsuid: %s | cuid: %s | Account: %s | Nickname: %s | email: %s"
|
||||||
|
trad: "NSUser ==> nsuid: %s | cuid: %s | Compte: %s | Pseudo: %s | email: %s"
|
||||||
0
mods/clone/language/fr/clone-fr_2.yaml
Normal file
0
mods/clone/language/fr/clone-fr_2.yaml
Normal file
@@ -131,6 +131,8 @@ class Clone:
|
|||||||
self.Protocol.send2socket(f":{self.Config.SERVICE_NICKNAME} MODE {self.Config.CLONE_CHANNEL} -k {self.Config.CLONE_CHANNEL_PASSWORD}")
|
self.Protocol.send2socket(f":{self.Config.SERVICE_NICKNAME} MODE {self.Config.CLONE_CHANNEL} -k {self.Config.CLONE_CHANNEL_PASSWORD}")
|
||||||
self.Protocol.send_part_chan(self.Config.SERVICE_NICKNAME, self.Config.CLONE_CHANNEL)
|
self.Protocol.send_part_chan(self.Config.SERVICE_NICKNAME, self.Config.CLONE_CHANNEL)
|
||||||
|
|
||||||
|
self.Irc.Commands.drop_command_by_module(self.module_name)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def cmd(self, data:list) -> None:
|
def cmd(self, data:list) -> None:
|
||||||
@@ -200,7 +202,7 @@ class Clone:
|
|||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
self.Logs.error(f'{err}')
|
self.Logs.error(f'{err}')
|
||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} clone connect [number of clone you want to connect] [Group]")
|
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} clone connect [number of clone you want to connect] [Group] [freq]")
|
||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"Exemple /msg {dnickname} clone connect 6 Ambiance")
|
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"Exemple /msg {dnickname} clone connect 6 Ambiance")
|
||||||
|
|
||||||
case 'kill':
|
case 'kill':
|
||||||
@@ -230,8 +232,7 @@ class Clone:
|
|||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
self.Logs.error(f'{err}')
|
self.Logs.error(f'{err}')
|
||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} clone kill all")
|
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} clone kill [all | group name | nickname]")
|
||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} clone kill clone_nickname")
|
|
||||||
|
|
||||||
case 'join':
|
case 'join':
|
||||||
try:
|
try:
|
||||||
@@ -260,8 +261,7 @@ class Clone:
|
|||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
self.Logs.error(f'{err}')
|
self.Logs.error(f'{err}')
|
||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} clone join all #channel")
|
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} clone join [all | group name | nickname] #channel")
|
||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} clone join clone_nickname #channel")
|
|
||||||
|
|
||||||
case 'part':
|
case 'part':
|
||||||
try:
|
try:
|
||||||
@@ -291,8 +291,7 @@ class Clone:
|
|||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
self.Logs.error(f'{err}')
|
self.Logs.error(f'{err}')
|
||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} clone part all #channel")
|
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} clone part [all | group name | nickname] #channel")
|
||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} clone part clone_nickname #channel")
|
|
||||||
|
|
||||||
case 'list':
|
case 'list':
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ class Command:
|
|||||||
self.Base.db_update_core_config(self.module_name, self.ModConfig, param_key, param_value)
|
self.Base.db_update_core_config(self.module_name, self.ModConfig, param_key, param_value)
|
||||||
|
|
||||||
def unload(self) -> None:
|
def unload(self) -> None:
|
||||||
|
self.Irc.Commands.drop_command_by_module(self.module_name)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def cmd(self, data: list[str]) -> None:
|
def cmd(self, data: list[str]) -> None:
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import traceback
|
from typing import TYPE_CHECKING
|
||||||
import mods.defender.schemas as schemas
|
import mods.defender.schemas as schemas
|
||||||
import mods.defender.utils as utils
|
import mods.defender.utils as utils
|
||||||
import mods.defender.threads as thds
|
import mods.defender.threads as thds
|
||||||
from typing import TYPE_CHECKING
|
from core.utils import tr
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.irc import Irc
|
from core.irc import Irc
|
||||||
@@ -202,6 +202,8 @@ class Defender:
|
|||||||
self.reputationTimer_isRunning:bool = False
|
self.reputationTimer_isRunning:bool = False
|
||||||
self.autolimit_isRunning: bool = False
|
self.autolimit_isRunning: bool = False
|
||||||
|
|
||||||
|
self.Irc.Commands.drop_command_by_module(self.module_name)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def insert_db_trusted(self, uid: str, nickname:str) -> None:
|
def insert_db_trusted(self, uid: str, nickname:str) -> None:
|
||||||
@@ -320,8 +322,7 @@ class Defender:
|
|||||||
except IndexError as ie:
|
except IndexError as ie:
|
||||||
self.Logs.error(f"{ie} / {cmd} / length {str(len(cmd))}")
|
self.Logs.error(f"{ie} / {cmd} / length {str(len(cmd))}")
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
self.Logs.error(f"General Error: {err}")
|
self.Logs.error(f"General Error: {err}", exc_info=True)
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
def hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None:
|
def hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None:
|
||||||
|
|
||||||
@@ -948,7 +949,7 @@ class Defender:
|
|||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' WebWebsocket : {UserObject.isWebsocket}')
|
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' WebWebsocket : {UserObject.isWebsocket}')
|
||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' REPUTATION : {UserObject.score_connexion}')
|
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' REPUTATION : {UserObject.score_connexion}')
|
||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' MODES : {UserObject.umodes}')
|
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' MODES : {UserObject.umodes}')
|
||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' CHANNELS : {channels}')
|
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' CHANNELS : {", ".join(channels)}')
|
||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' CONNECTION TIME : {UserObject.connexion_datetime}')
|
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' CONNECTION TIME : {UserObject.connexion_datetime}')
|
||||||
else:
|
else:
|
||||||
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"This user {nickoruid} doesn't exist")
|
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"This user {nickoruid} doesn't exist")
|
||||||
|
|||||||
@@ -220,6 +220,7 @@ class Jsonrpc():
|
|||||||
)
|
)
|
||||||
self.Base.create_thread(func=self.Threads.thread_unsubscribe, func_args=(self, ), run_once=True)
|
self.Base.create_thread(func=self.Threads.thread_unsubscribe, func_args=(self, ), run_once=True)
|
||||||
self.update_configuration('jsonrpc', 0)
|
self.update_configuration('jsonrpc', 0)
|
||||||
|
self.Irc.Commands.drop_command_by_module(self.module_name)
|
||||||
self.Logs.debug(f"Unloading {self.module_name}")
|
self.Logs.debug(f"Unloading {self.module_name}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class Test():
|
|||||||
self.Base.db_update_core_config(self.module_name, self.ModConfig, param_key, param_value)
|
self.Base.db_update_core_config(self.module_name, self.ModConfig, param_key, param_value)
|
||||||
|
|
||||||
def unload(self) -> None:
|
def unload(self) -> None:
|
||||||
|
self.Irc.Commands.drop_command_by_module(self.module_name)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def cmd(self, data:list) -> None:
|
def cmd(self, data:list) -> None:
|
||||||
|
|||||||
@@ -126,6 +126,8 @@ class Votekick:
|
|||||||
self.VoteKickManager.VOTE_CHANNEL_DB = []
|
self.VoteKickManager.VOTE_CHANNEL_DB = []
|
||||||
self.Logs.debug(f'Delete memory DB VOTE_CHANNEL_DB: {self.VoteKickManager.VOTE_CHANNEL_DB}')
|
self.Logs.debug(f'Delete memory DB VOTE_CHANNEL_DB: {self.VoteKickManager.VOTE_CHANNEL_DB}')
|
||||||
|
|
||||||
|
self.Irc.Commands.drop_command_by_module(self.module_name)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
except UnboundLocalError as ne:
|
except UnboundLocalError as ne:
|
||||||
self.Logs.error(f'{ne}')
|
self.Logs.error(f'{ne}')
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
{
|
{
|
||||||
"version": "6.2.2",
|
"version": "6.2.5",
|
||||||
|
|
||||||
"requests": "2.32.3",
|
"requests": "2.32.3",
|
||||||
"psutil": "6.0.0",
|
"psutil": "6.0.0",
|
||||||
"unrealircd_rpc_py": "2.0.5",
|
"unrealircd_rpc_py": "2.0.5",
|
||||||
"sqlalchemy": "2.0.35",
|
"sqlalchemy": "2.0.35",
|
||||||
"faker": "30.1.0"
|
"faker": "30.1.0",
|
||||||
|
"pyyaml": "6.0.2"
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user