This commit is contained in:
adator
2024-11-11 23:38:05 +01:00
parent bd9713006a
commit 44da01945c
7 changed files with 290 additions and 192 deletions

View File

@@ -194,14 +194,19 @@ class Base:
file_hanlder = logging.FileHandler(f'logs{self.Config.OS_SEP}defender.log',encoding='UTF-8')
file_hanlder.setLevel(self.Config.DEBUG_LEVEL)
stdout_handler = logging.StreamHandler()
stdout_handler.setLevel(50)
# Define log format
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(filename)s - %(lineno)d - %(funcName)s - %(message)s')
# Apply log format
file_hanlder.setFormatter(formatter)
stdout_handler.setFormatter(formatter)
# Add handler to logs
self.logs.addHandler(file_hanlder)
self.logs.addHandler(stdout_handler)
# Apply the filter
self.logs.addFilter(self.replace_filter)
@@ -217,8 +222,8 @@ class Base:
filter: list[str] = ['PING', f":{self.Config.SERVICE_PREFIX}auth"]
# record.msg = record.getMessage().replace("PING", "[REDACTED]")
if self.Settings.CONSOLE:
print(record.getMessage())
# if self.Settings.CONSOLE:
# print(record.getMessage())
for f in filter:
if f in record.getMessage():

View File

@@ -1184,6 +1184,10 @@ class Irc:
case 'auth':
# ['auth', 'adator', 'password']
if len(cmd) != 3:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} {command.upper()} [nickname] [password]")
return None
current_command = cmd[0]
user_to_log = self.User.get_nickname(cmd[1])
password = cmd[2]
@@ -1241,25 +1245,30 @@ class Irc:
case 'editaccess':
# .editaccess [USER] [PASSWORD] [LEVEL]
try:
user_to_edit = cmd[1]
user_new_level = int(cmd[3])
user_password = self.Base.crypt_password(cmd[2])
if len(cmd) < 4 or len(cmd) > 4:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"{self.Config.SERVICE_PREFIX}editaccess [USER] [NEWPASSWORD] [NEWLEVEL]")
if len(cmd) < 3:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"Right command : /msg {dnickname} editaccess [nickname] [NEWPASSWORD] [NEWLEVEL]")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"level: from 1 to 4")
return None
user_to_edit = cmd[1]
user_password = self.Base.crypt_password(cmd[2])
get_admin = self.Admin.get_Admin(fromuser)
if get_admin is None:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f" This user {fromuser} has no Admin access")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"This user {fromuser} has no Admin access")
return None
current_user = self.User.get_nickname(fromuser)
current_uid = self.User.get_uid(fromuser)
current_user_level = get_admin.level
user_new_level = int(cmd[3]) if len(cmd) == 4 else get_admin.level
if current_user == fromuser:
user_new_level = get_admin.level
if user_new_level > 5:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f" Maximum authorized level is 5")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg="Maximum authorized level is 5")
return None
# Rechercher le user dans la base de données.
@@ -1271,7 +1280,7 @@ class Irc:
if not isUserExist is None:
if current_user_level < int(isUserExist[1]):
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f" You are not allowed to edit this access")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg="You are not allowed to edit this access")
return None
if current_user_level == int(isUserExist[1]) and current_user != user_to_edit:

View File

@@ -1,5 +1,4 @@
from core.classes import user, admin, channel, clone, reputation, settings
import utils
import core.definition as df
import core.base as baseModule
import core.classes.config as confModule
@@ -15,8 +14,6 @@ class Loader:
self.BaseModule: baseModule = baseModule
self.Utils: utils
# Load Classes
self.Settings: settings = settings.Settings()

View File

@@ -1,10 +1,12 @@
from typing import TYPE_CHECKING
from dataclasses import dataclass, fields
from typing import Union, TYPE_CHECKING
from dataclasses import dataclass
from core.classes import user
if TYPE_CHECKING:
from core.irc import Irc
class Command():
class Command:
@dataclass
class ModConfModel:
@@ -20,6 +22,9 @@ class Command():
# Add Irc Object to the module (Mandatory)
self.Irc = ircInstance
# Add Loader Object to the module (Mandatory)
self.Loader = ircInstance.Loader
# Add Protocol object to the module (Mandatory)
self.Protocol = ircInstance.Protocol
@@ -42,12 +47,12 @@ class Command():
self.commands_level = {
1: ['join', 'part','owner', 'deowner', 'protect', 'deprotect', 'op',
'deop', 'halfop', 'dehalfop', 'voice','devoice', 'topic'],
2: ['opall', 'deopall', 'devoiceall', 'voiceall', 'ban',
'unban','kick', 'kickban', 'umode', 'mode', 'get_mode', 'svsjoin', 'svspart', 'svsnick',
2: ['opall', 'deopall', 'devoiceall', 'voiceall', 'ban', 'automode',
'unban', 'kick', 'kickban', 'umode',
'mode', 'get_mode', 'svsjoin', 'svspart', 'svsnick',
'wallops', 'globops','gnotice','whois', 'names', 'invite', 'inviteme',
'sajoin', 'sapart',
'kill', 'gline', 'ungline', 'kline', 'unkline', 'shun', 'unshun',
'glinelist', 'shunlist', 'klinelist'],
'sajoin', 'sapart', 'kill', 'gline', 'ungline', 'kline',
'unkline', 'shun', 'unshun', 'glinelist', 'shunlist', 'klinelist'],
3: ['map']
}
@@ -74,7 +79,7 @@ class Command():
return None
def __set_commands(self, commands:dict[int, list[str]]) -> None:
def __set_commands(self, commands: dict[int, list[str]]) -> None:
"""### Rajoute les commandes du module au programme principal
Args:
@@ -82,7 +87,7 @@ class Command():
"""
for level, com in commands.items():
for c in commands[level]:
if not c in self.Irc.commands:
if c not in self.Irc.commands:
self.Irc.commands_level[level].append(c)
self.Irc.commands.append(c)
@@ -98,14 +103,17 @@ class Command():
None: Aucun retour n'es attendu
"""
table_logs = '''CREATE TABLE IF NOT EXISTS test_logs (
table_automode = '''CREATE TABLE IF NOT EXISTS command_automode (
id INTEGER PRIMARY KEY AUTOINCREMENT,
datetime TEXT,
server_msg TEXT
created_on TEXT,
updated_on TEXT,
nickname TEXT,
channel TEXT,
mode TEXT
)
'''
# self.Base.db_execute_query(table_logs)
self.Base.db_execute_query(table_automode)
return None
def __load_module_configuration(self) -> None:
@@ -136,107 +144,203 @@ class Command():
return None
def cmd(self, data: list) -> None:
def cmd(self, data: list[str]) -> None:
try:
# service_id = self.Config.SERVICE_ID
dnickname = self.Config.SERVICE_NICKNAME
# dchanlog = self.Config.SERVICE_CHANLOG
red = self.Config.COLORS.red
green = self.Config.COLORS.green
bold = self.Config.COLORS.bold
nogc = self.Config.COLORS.nogc
cmd = list(data).copy()
service_id = self.Config.SERVICE_ID
dnickname = self.Config.SERVICE_NICKNAME
dchanlog = self.Config.SERVICE_CHANLOG
red = self.Config.COLORS.red
green = self.Config.COLORS.green
bold = self.Config.COLORS.bold
nogc = self.Config.COLORS.nogc
cmd = list(data).copy()
if len(cmd) < 2:
return None
if len(cmd) < 2:
return None
match cmd[1]:
# [':irc.deb.biz.st', '403', 'Dev-PyDefender', '#Z', ':No', 'such', 'channel']
case '403' | '401':
try:
message = ' '.join(cmd[3:])
self.Protocol.send_notice(
nick_from=dnickname,
nick_to=self.user_to_notice,
msg=f"[{red}ERROR MSG{nogc}] {message}"
)
self.Logs.error(f"{cmd[1]} - {message}")
except KeyError as ke:
self.Logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
match cmd[1]:
# [':irc.deb.biz.st', '403', 'Dev-PyDefender', '#Z', ':No', 'such', 'channel']
case '403' | '401':
try:
message = ' '.join(cmd[3:])
self.Protocol.send_notice(
nick_from=dnickname,
nick_to=self.user_to_notice,
msg=f"[{red}ERROR MSG{nogc}] {message}"
)
self.Logs.error(f"{cmd[1]} - {message}")
except KeyError as ke:
self.Logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case '006' | '018':
try:
# [':irc.deb.biz.st', '006', 'Dev-PyDefender', ':`-services.deb.biz.st', '------', '|', 'Users:', '9', '(47.37%)', '[00B]']
# [':irc.deb.biz.st', '018', 'Dev-PyDefender', ':4', 'servers', 'and', '19', 'users,', 'average', '4.75', 'users', 'per', 'server']
message = ' '.join(cmd[3:])
self.Protocol.send_notice(
nick_from=dnickname,
nick_to=self.user_to_notice,
msg=f"[{green}SERVER MSG{nogc}] {message}"
)
except KeyError as ke:
self.Logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case '006' | '018':
try:
# [':irc.deb.biz.st', '006', 'Dev-PyDefender', ':`-services.deb.biz.st', '------', '|', 'Users:', '9', '(47.37%)', '[00B]']
# [':irc.deb.biz.st', '018', 'Dev-PyDefender', ':4', 'servers', 'and', '19', 'users,', 'average', '4.75', 'users', 'per', 'server']
message = ' '.join(cmd[3:])
self.Protocol.send_notice(
nick_from=dnickname,
nick_to=self.user_to_notice,
msg=f"[{green}SERVER MSG{nogc}] {message}"
)
except KeyError as ke:
self.Logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case '219':
try:
# [':irc.deb.biz.st', '219', 'Dev-PyDefender', 's', ':End', 'of', '/STATS', 'report']
if not self.show_219:
# If there is a result in 223 then stop here
self.show_219 = True
return None
case '219':
try:
# [':irc.deb.biz.st', '219', 'Dev-PyDefender', 's', ':End', 'of', '/STATS', 'report']
if not self.show_219:
# If there is a result in 223 then stop here
self.show_219 = True
return None
type_of_stats = str(cmd[3])
type_of_stats = str(cmd[3])
match type_of_stats:
case 's':
self.Protocol.send_notice(nick_from=dnickname,nick_to=self.user_to_notice, msg="No shun")
case 'G':
self.Protocol.send_notice(nick_from=dnickname,nick_to=self.user_to_notice, msg="No gline")
case 'k':
self.Protocol.send_notice(nick_from=dnickname,nick_to=self.user_to_notice, msg="No kline")
match type_of_stats:
case 's':
self.Protocol.send_notice(nick_from=dnickname,nick_to=self.user_to_notice, msg="No shun")
case 'G':
self.Protocol.send_notice(nick_from=dnickname,nick_to=self.user_to_notice, msg="No gline")
case 'k':
self.Protocol.send_notice(nick_from=dnickname,nick_to=self.user_to_notice, msg="No kline")
except KeyError as ke:
self.Logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
except KeyError as ke:
self.Logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case '223':
try:
# [':irc.deb.biz.st', '223', 'Dev-PyDefender', 'G', '*@162.142.125.217', '67624', '18776', 'irc.deb.biz.st', ':Proxy/Drone', 'detected.', 'Check', 'https://dronebl.org/lookup?ip=162.142.125.217', 'for', 'details.']
self.show_219 = False
host = str(cmd[4])
author = str(cmd[7])
reason = ' '.join(cmd[8:])
case '223':
try:
# [':irc.deb.biz.st', '223', 'Dev-PyDefender', 'G', '*@162.142.125.217', '67624', '18776', 'irc.deb.biz.st', ':Proxy/Drone', 'detected.', 'Check', 'https://dronebl.org/lookup?ip=162.142.125.217', 'for', 'details.']
self.show_219 = False
host = str(cmd[4])
author = str(cmd[7])
reason = ' '.join(cmd[8:])
self.Protocol.send_notice(nick_from=dnickname,nick_to=self.user_to_notice,
msg=f"{bold}Author{nogc}: {author} - {bold}Host{nogc}: {host} - {bold}Reason{nogc}: {reason}"
)
self.Protocol.send_notice(nick_from=dnickname,nick_to=self.user_to_notice,
msg=f"{bold}Author{nogc}: {author} - {bold}Host{nogc}: {host} - {bold}Reason{nogc}: {reason}"
)
except KeyError as ke:
self.Logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
except KeyError as ke:
self.Logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case _:
pass
case _:
pass
if len(cmd) < 3:
return None
return None
match cmd[2]:
def _hcmds(self, user: str, channel: any, cmd: list, fullcmd: list = []) -> None:
case 'SJOIN':
# ['@msgid=yldTlbwAGbzCGUcCIHi3ku;time=2024-11-11T17:56:24.297Z', ':001', 'SJOIN', '1728815963', '#znc', ':001LQ0L0C']
# Check if the user has an automode
try:
if len(cmd) < 6:
return None
user_uid = self.User.clean_uid(cmd[5])
userObj = self.User.get_User(user_uid)
channel_name = cmd[4] if self.Channel.Is_Channel(cmd[4]) else None
if userObj is None:
return None
if 'r' not in userObj.umodes:
return None
db_data = {"nickname": userObj.nickname, "channel": channel_name}
db_query = self.Base.db_execute_query("SELECT id, mode FROM command_automode WHERE nickname = :nickname AND channel = :channel", db_data)
db_result = db_query.fetchone()
if db_result is not None:
id, mode = db_result
self.Protocol.send2socket(f":{self.Config.SERVICE_ID} MODE {channel_name} {mode} {userObj.nickname}")
except KeyError as ke:
self.Logs.error(f"Key Error: {err}")
except Exception as err:
self.Logs.error(f"General Error: {err}")
def _hcmds(self, uidornickname: str, channel_name: Union[str, None], cmd: list, fullcmd: list = []) -> None:
command = str(cmd[0]).lower()
dnickname = self.Config.SERVICE_NICKNAME
service_id = self.Config.SERVICE_ID
dchanlog = self.Config.SERVICE_CHANLOG
self.user_to_notice = user
fromuser = user
fromchannel = channel
self.user_to_notice = uidornickname
fromuser = uidornickname
fromchannel = channel_name
match command:
case "automode":
# automode nickname +/-mode #channel
# automode adator +o #channel
try:
allowed_modes = ['q','a','o','h','v']
userObj = self.User.get_User(str(cmd[1]))
if len(cmd) != 4:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} {command.upper()} [nickname] [+/-mode] [#channel]")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"AutoModes available: {' / '.join(allowed_modes)}")
return None
mode = str(cmd[2])
flag_found: bool = False
if mode.startswith( ('+', '-') ):
flag_found = True
if not flag_found:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg="You must provide the flag mode + or -")
return None
mode = str(cmd[2])
chan = cmd[3] if self.Channel.Is_Channel(cmd[3]) else None
if mode.lstrip('+-') not in allowed_modes:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"You should use one of those modes {' / '.join(allowed_modes)}")
return None
if chan is None:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"You should use one of those modes {' / '.join(allowed_modes)}")
return None
db_data: dict[str, str] = {"nickname": userObj.nickname, "channel": chan}
db_query = self.Base.db_execute_query(query="SELECT id FROM command_automode WHERE nickname = :nickname and channel = :channel", params=db_data)
db_result = db_query.fetchone()
if db_result is not None:
db_data = {"updated_on": self.Base.get_datetime(), "nickname": userObj.nickname, "channel": chan, "mode": mode}
db_result = self.Base.db_execute_query(query="UPDATE command_automode SET mode = :mode, updated_on = :updated_on WHERE nickname = :nickname and channel = :channel",
params=db_data)
if db_result.rowcount > 0:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"Automode {mode} edited for {userObj.nickname} in {chan}")
return None
# Instert a new automode
db_data = {"created_on": self.Base.get_datetime(), "updated_on": self.Base.get_datetime(), "nickname": userObj.nickname, "channel": chan, "mode": mode}
db_query = self.Base.db_execute_query(
query="INSERT INTO command_automode (created_on, updated_on, nickname, channel, mode) VALUES (:created_on, :updated_on, :nickname, :channel, :mode)",
params=db_data
)
if db_query.rowcount > 0:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"Automode {mode} applied to {userObj.nickname} in {chan}")
self.Protocol.send2socket(f":{service_id} MODE {chan} {mode} {userObj.nickname}")
except KeyError:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} {command.upper()} [nickname] [+/-mode] [#channel]")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"AutoModes available: {' / '.join(allowed_modes)}")
except Exception as err:
self.Logs.error(f"General Error: {err}")
case 'deopall':
try:
@@ -696,7 +800,7 @@ class Command():
chan = str(cmd[1])
if not self.Channel.Is_Channel(chan):
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"The channel must start with #")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg="The channel must start with #")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} TOPIC #channel THE_TOPIC_MESSAGE")
return None
@@ -705,7 +809,7 @@ class Command():
if topic_msg:
self.Protocol.send2socket(f':{dnickname} TOPIC {chan} :{topic_msg}')
else:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"You need to specify the topic")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg="You need to specify the topic")
except KeyError as ke:
self.Logs.error(ke)
@@ -723,7 +827,7 @@ class Command():
if wallops_msg:
self.Protocol.send2socket(f':{dnickname} WALLOPS {wallops_msg} ({dnickname})')
else:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"You need to specify the wallops message")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg="You need to specify the wallops message")
except KeyError as ke:
self.Logs.error(ke)
@@ -741,7 +845,7 @@ class Command():
if globops_msg:
self.Protocol.send2socket(f':{dnickname} GLOBOPS {globops_msg} ({dnickname})')
else:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"You need to specify the globops message")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg="You need to specify the globops message")
except KeyError as ke:
self.Logs.error(ke)
@@ -759,7 +863,7 @@ class Command():
if gnotice_msg:
self.Protocol.send_notice(nick_from=dnickname, nick_to='$*.*', msg=f"[{self.Config.COLORS.red}GLOBAL NOTICE{self.Config.COLORS.nogc}] {gnotice_msg}")
else:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"You need to specify the global notice message")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg="You need to specify the global notice message")
except KeyError as ke:
self.Logs.error(ke)
@@ -776,7 +880,7 @@ class Command():
nickname = str(cmd[1])
if self.User.get_nickname(nickname) is None:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"Nickname not found !")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg="Nickname not found !")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} {str(cmd[0]).upper()} NICKNAME")
return None
@@ -796,7 +900,7 @@ class Command():
chan = str(cmd[1])
if not self.Channel.Is_Channel(chan):
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"The channel must start with #")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg="The channel must start with #")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} {str(cmd[0]).upper()} #channel")
return None
@@ -817,12 +921,12 @@ class Command():
chan = str(cmd[2])
if not self.Channel.Is_Channel(chan):
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"The channel must start with #")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg="The channel must start with #")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} {str(cmd[0]).upper()} NICKNAME #CHANNEL")
return None
if self.User.get_nickname(nickname) is None:
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"Nickname not found !")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg="Nickname not found !")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"/msg {dnickname} {str(cmd[0]).upper()} NICKNAME #CHANNEL")
return None
@@ -906,8 +1010,10 @@ class Command():
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'get_mode':
self.Protocol.send2socket(f'MODE {channel}')
try:
self.Protocol.send2socket(f'MODE {fromchannel}')
except Exception as err:
self.Logs.error(f"General Error {err}")
case 'svsjoin':
try:
@@ -927,7 +1033,7 @@ class Command():
case 'svspart':
try:
# .svspart nickname #channel
# svspart nickname #channel
nickname = str(cmd[1])
channel = str(cmd[2])
if len(cmd) != 3:

View File

@@ -4,10 +4,9 @@ import time
import re
import psutil
import requests
from dataclasses import dataclass, fields, field
from dataclasses import dataclass
from datetime import datetime
from typing import Union, TYPE_CHECKING
from sys import exit
import core.definition as df
# Le module crée devra réspecter quelques conditions
@@ -141,7 +140,9 @@ class Defender():
self.Base.create_thread(func=self.thread_local_scan)
self.Base.create_thread(func=self.thread_psutil_scan)
self.Base.create_thread(func=self.thread_reputation_timer)
self.Base.create_thread(func=self.thread_autolimit)
if self.ModConfig.autolimit == 1:
self.Base.create_thread(func=self.thread_autolimit)
if self.ModConfig.reputation == 1:
self.Protocol.sjoin(self.Config.SALON_JAIL)
@@ -149,7 +150,7 @@ class Defender():
return None
def __set_commands(self, commands:dict[int, list[str]]) -> None:
def __set_commands(self, commands: dict[int, list[str]]) -> None:
"""### Rajoute les commandes du module au programme principal
Args:
@@ -157,7 +158,7 @@ class Defender():
"""
for level, com in commands.items():
for c in commands[level]:
if not c in self.Irc.commands:
if c not in self.Irc.commands:
self.Irc.commands_level[level].append(c)
self.Irc.commands.append(c)
@@ -173,31 +174,15 @@ class Defender():
None: Aucun retour n'es attendu
"""
table_channel = '''CREATE TABLE IF NOT EXISTS def_channels (
id INTEGER PRIMARY KEY AUTOINCREMENT,
datetime TEXT,
channel TEXT
)
'''
# table_autoop = '''CREATE TABLE IF NOT EXISTS defender_autoop (
# id INTEGER PRIMARY KEY AUTOINCREMENT,
# datetime TEXT,
# nickname TEXT,
# channel TEXT
# )
# '''
table_config = '''CREATE TABLE IF NOT EXISTS def_config (
id INTEGER PRIMARY KEY AUTOINCREMENT,
datetime TEXT,
parameter TEXT,
value TEXT
)
'''
table_trusted = '''CREATE TABLE IF NOT EXISTS def_trusted (
id INTEGER PRIMARY KEY AUTOINCREMENT,
datetime TEXT,
user TEXT,
host TEXT,
vhost TEXT
)
'''
# self.Base.db_execute_query(table_channel)
# self.Base.db_execute_query(table_autoop)
# self.Base.db_execute_query(table_config)
# self.Base.db_execute_query(table_trusted)
return None
@@ -255,7 +240,7 @@ class Defender():
exec_query = self.Base.db_execute_query(query, {"user": nickname})
response = exec_query.fetchone()
if not response is None:
if response is not None:
q_insert = "INSERT INTO def_trusted (datetime, user, host, vhost) VALUES (?, ?, ?, ?)"
mes_donnees = {'datetime': self.Base.get_datetime(), 'user': nickname, 'host': '*', 'vhost': '*'}
exec_query = self.Base.db_execute_query(q_insert, mes_donnees)
@@ -301,7 +286,8 @@ class Defender():
# Convertir la date enregistrée dans UID_DB en un objet {datetime}
connected_time_string = get_user.connexion_datetime
if type(connected_time_string) == datetime:
if isinstance(connected_time_string, datetime):
connected_time = connected_time_string
else:
connected_time = datetime.strptime(connected_time_string, "%Y-%m-%d %H:%M:%S.%f")
@@ -386,7 +372,6 @@ class Defender():
service_id = self.Config.SERVICE_ID
dchanlog = self.Config.SERVICE_CHANLOG
color_red = self.Config.COLORS.red
color_black = self.Config.COLORS.black
nogc = self.Config.COLORS.nogc
salon_jail = self.Config.SALON_JAIL
@@ -480,7 +465,7 @@ class Defender():
unixtime = self.Base.get_unixtime()
get_diff_secondes = 0
if not get_detected_uid in self.flood_system:
if get_detected_uid not in self.flood_system:
self.flood_system[get_detected_uid] = {
'nbr_msg': 0,
'first_msg_time': unixtime
@@ -694,7 +679,7 @@ class Defender():
# Formatted output
decodedResponse = json.loads(response.text)
if not 'data' in decodedResponse:
if 'data' not in decodedResponse:
return None
result = {
@@ -707,7 +692,6 @@ class Defender():
service_id = self.Config.SERVICE_ID
service_chanlog = self.Config.SERVICE_CHANLOG
color_red = self.Config.COLORS.red
color_black = self.Config.COLORS.black
nogc = self.Config.COLORS.nogc
# pseudo!ident@host
@@ -780,7 +764,6 @@ class Defender():
service_id = self.Config.SERVICE_ID
service_chanlog = self.Config.SERVICE_CHANLOG
color_red = self.Config.COLORS.red
color_black = self.Config.COLORS.black
nogc = self.Config.COLORS.nogc
url = f'https://freeipapi.com/api/json/{remote_ip}'
@@ -797,7 +780,7 @@ class Defender():
status_code = response.status_code
if status_code == 429:
self.Logs.warning(f'Too Many Requests - The rate limit for the API has been exceeded.')
self.Logs.warning('Too Many Requests - The rate limit for the API has been exceeded.')
return None
elif status_code != 200:
self.Logs.warning(f'status code = {str(status_code)}')
@@ -873,10 +856,9 @@ class Defender():
service_id = self.Config.SERVICE_ID
service_chanlog = self.Config.SERVICE_CHANLOG
color_red = self.Config.COLORS.red
color_black = self.Config.COLORS.black
nogc = self.Config.COLORS.nogc
url = f"https://developers18334.cloudfilt.com/"
url = "https://developers18334.cloudfilt.com/"
data = {
'ip': remote_ip,
@@ -941,7 +923,7 @@ class Defender():
def thread_autolimit(self) -> None:
if self.ModConfig.autolimit == 0:
self.Logs.debug(f"autolimit deactivated ... canceling the thread")
self.Logs.debug("autolimit deactivated ... canceling the thread")
return None
while self.Irc.autolimit_started:
@@ -958,7 +940,7 @@ class Defender():
while self.autolimit_isRunning:
if self.ModConfig.autolimit == 0:
self.Logs.debug(f"autolimit deactivated ... stopping the current thread")
self.Logs.debug("autolimit deactivated ... stopping the current thread")
break
for chan in self.Channel.UID_CHANNEL_DB:
@@ -967,14 +949,14 @@ class Defender():
self.Protocol.send2socket(f":{self.Config.SERVICE_ID} MODE {chan.name} +l {len(chan.uids) + self.ModConfig.autolimit_amount}")
chan_copy["uids_count"] = len(chan.uids)
if not chan.name in chan_list:
if chan.name not in chan_list:
chan_list.append(chan.name)
chanObj_copy.append({"name": chan.name, "uids_count": 0})
# Verifier si un salon a été vidé
current_chan_in_list = [d.name for d in self.Channel.UID_CHANNEL_DB]
for c in chan_list:
if not c in current_chan_in_list:
if c not in current_chan_in_list:
chan_list.remove(c)
# Si c'est la premiere execution
@@ -1059,12 +1041,12 @@ class Defender():
_User = self.User.get_User(str(cmd[7]))
# If user is not service or IrcOp then scan them
if not re.match(fr'^.*[S|o?].*$', _User.umodes):
self.abuseipdb_UserModel.append(_User) if self.ModConfig.abuseipdb_scan == 1 and not _User.remote_ip in self.Config.WHITELISTED_IP else None
self.freeipapi_UserModel.append(_User) if self.ModConfig.freeipapi_scan == 1 and not _User.remote_ip in self.Config.WHITELISTED_IP else None
self.cloudfilt_UserModel.append(_User) if self.ModConfig.cloudfilt_scan == 1 and not _User.remote_ip in self.Config.WHITELISTED_IP else None
self.psutil_UserModel.append(_User) if self.ModConfig.psutil_scan == 1 and not _User.remote_ip in self.Config.WHITELISTED_IP else None
self.localscan_UserModel.append(_User) if self.ModConfig.local_scan == 1 and not _User.remote_ip in self.Config.WHITELISTED_IP else None
if not re.match(r'^.*[S|o?].*$', _User.umodes):
self.abuseipdb_UserModel.append(_User) if self.ModConfig.abuseipdb_scan == 1 and _User.remote_ip not in self.Config.WHITELISTED_IP else None
self.freeipapi_UserModel.append(_User) if self.ModConfig.freeipapi_scan == 1 and _User.remote_ip not in self.Config.WHITELISTED_IP else None
self.cloudfilt_UserModel.append(_User) if self.ModConfig.cloudfilt_scan == 1 and _User.remote_ip not in self.Config.WHITELISTED_IP else None
self.psutil_UserModel.append(_User) if self.ModConfig.psutil_scan == 1 and _User.remote_ip not in self.Config.WHITELISTED_IP else None
self.localscan_UserModel.append(_User) if self.ModConfig.local_scan == 1 and _User.remote_ip not in self.Config.WHITELISTED_IP else None
if _User is None:
self.Logs.critical(f'This UID: [{cmd[7]}] is not available please check why')
@@ -1075,9 +1057,9 @@ class Defender():
if self.Config.DEFENDER_INIT == 0:
# Si le user n'es pas un service ni un IrcOP
if not re.match(fr'^.*[S|o?].*$', _User.umodes):
if not re.match(r'^.*[S|o?].*$', _User.umodes):
if reputation_flag == 1 and _User.score_connexion <= reputation_seuil:
currentDateTime = self.Base.get_datetime()
# currentDateTime = self.Base.get_datetime()
self.Reputation.insert(
self.Loader.Definition.MReputation(
**_User.__dict__,
@@ -1107,7 +1089,7 @@ class Defender():
self.Protocol.send2socket(f":{service_id} MODE {parsed_chan} +b ~security-group:unknown-users")
self.Protocol.send2socket(f":{service_id} MODE {parsed_chan} +eee ~security-group:webirc-users ~security-group:known-users ~security-group:websocket-users")
if not get_reputation is None:
if get_reputation is not None:
isWebirc = get_reputation.isWebirc
if not isWebirc:
@@ -1187,7 +1169,7 @@ class Defender():
get_user_reputation = self.Reputation.get_Reputation(final_UID)
if not get_user_reputation is None:
if get_user_reputation is not None:
final_nickname = get_user_reputation.nickname
for chan in self.Channel.UID_CHANNEL_DB:
if chan.name != jail_salon and ban_all_chan == 1:
@@ -1522,7 +1504,7 @@ class Defender():
except ValueError as ve:
self.Logs.warning(f'{ve}')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f" La valeur devrait etre un entier >= 0")
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=" La valeur devrait etre un entier >= 0")
case 'proxy_scan':
@@ -1729,14 +1711,14 @@ class Defender():
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' reputation_after_release ==> {self.ModConfig.reputation_score_after_release}')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' reputation_ban_all_chan ==> {self.ModConfig.reputation_ban_all_chan}')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' reputation_timer ==> {self.ModConfig.reputation_timer}')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' [Proxy_scan]')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=' [Proxy_scan]')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' {color_green if self.ModConfig.local_scan == 1 else color_red}local_scan{nogc} ==> {self.ModConfig.local_scan}')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' {color_green if self.ModConfig.psutil_scan == 1 else color_red}psutil_scan{nogc} ==> {self.ModConfig.psutil_scan}')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' {color_green if self.ModConfig.abuseipdb_scan == 1 else color_red}abuseipdb_scan{nogc} ==> {self.ModConfig.abuseipdb_scan}')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' {color_green if self.ModConfig.freeipapi_scan == 1 else color_red}freeipapi_scan{nogc} ==> {self.ModConfig.freeipapi_scan}')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' {color_green if self.ModConfig.cloudfilt_scan == 1 else color_red}cloudfilt_scan{nogc} ==> {self.ModConfig.cloudfilt_scan}')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' [{color_green if self.ModConfig.flood == 1 else color_red}Flood{nogc}] ==> {self.ModConfig.flood}')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' flood_action ==> Coming soon')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=' flood_action ==> Coming soon')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' flood_message ==> {self.ModConfig.flood_message}')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' flood_time ==> {self.ModConfig.flood_time}')
self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f' flood_timer ==> {self.ModConfig.flood_timer}')
@@ -1748,7 +1730,7 @@ class Defender():
nickoruid = cmd[1]
UserObject = self.User.get_User(nickoruid)
if not UserObject is None:
if UserObject is not None:
channels: list = []
for chan in self.Channel.UID_CHANNEL_DB:
for uid_in_chan in chan.uids:
@@ -1784,10 +1766,10 @@ class Defender():
if activation == 'on':
for chan in self.Channel.UID_CHANNEL_DB:
if not chan.name in channel_to_dont_quit:
if chan.name not in channel_to_dont_quit:
self.Protocol.send_join_chan(uidornickname=dnickname, channel=chan.name)
if activation == 'off':
for chan in self.Channel.UID_CHANNEL_DB:
if not chan.name in channel_to_dont_quit:
if chan.name not in channel_to_dont_quit:
self.Protocol.part(uidornickname=dnickname, channel=chan.name)
self.join_saved_channels()

View File

@@ -57,6 +57,7 @@ class Jsonrpc():
# Insert module commands into the core one (Mandatory)
self.__set_commands(self.commands_level)
logging.getLogger('websockets').setLevel(logging.WARNING)
logging.getLogger('unrealircd-rpc-py').setLevel(logging.CRITICAL)
# Create you own tables (Mandatory)
# self.__create_tables()
@@ -65,13 +66,6 @@ class Jsonrpc():
self.__load_module_configuration()
# End of mandatory methods you can start your customization #
# self.UnrealIrcdRpcLive: Live = Live(
# req_method='unixsocket',
# path_to_socket_file=self.Config.JSONRPC_PATH_TO_SOCKET_FILE,
# callback_object_instance=self,
# callback_method_name='callback_sent_to_irc'
# )
self.UnrealIrcdRpcLive: Live = Live(
req_method='websocket',
url=self.Config.JSONRPC_URL,
@@ -235,6 +229,11 @@ class Jsonrpc():
match option:
case 'on':
# for logger_name, logger in logging.root.manager.loggerDict.items():
# if isinstance(logger, logging.Logger):
# self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f"{logger_name} - {logger.level}")
for thread in self.Base.running_threads:
if thread.getName() == 'thread_start_jsonrpc':
if thread.is_alive():

View File

@@ -1,9 +1,9 @@
{
"version": "6.0.0",
"version": "6.0.1",
"requests": "2.32.3",
"psutil": "6.0.0",
"unrealircd_rpc_py": "1.0.6",
"unrealircd_rpc_py": "1.0.7",
"sqlalchemy": "2.0.35",
"faker": "30.1.0"
}