34 Commits

Author SHA1 Message Date
adator
4d0087623c Merge pull request #49 from adator85/dev
unsubscribe before unload
2024-09-22 23:54:22 +02:00
adator
dc20f5ec3c Merge pull request #48 from adator85/dev
Dev
2024-09-22 23:20:37 +02:00
adator
110cae3b84 Merge pull request #47 from adator85/dev
Update the way to clean exceptions and bans
2024-09-22 16:45:54 +02:00
adator
857cbfc85d Merge pull request #46 from adator85/dev
Send the ready msg to channel log
2024-09-22 16:33:49 +02:00
adator
3518589e9c Merge pull request #45 from adator85/dev
Fix ConfModel error
2024-09-22 16:31:35 +02:00
adator
e14c97de03 Merge pull request #44 from adator85/dev
V5.3.0
2024-09-22 16:20:45 +02:00
adator
69360be3ad Merge pull request #43 from adator85/dev
Update info command
2024-09-21 20:28:29 +02:00
adator
bfa90c6bd5 Merge pull request #42 from adator85/dev
V5.2.9
2024-09-21 20:22:42 +02:00
adator
5c8378a0e7 Merge pull request #41 from adator85/dev
V5.2.9
2024-09-21 16:43:14 +02:00
adator
e3b212ea88 Merge pull request #40 from adator85/dev
finetune clone connection
2024-09-20 23:13:33 +02:00
adator
0c2a350d38 Merge pull request #39 from adator85/dev
Dev
2024-09-20 21:12:59 +02:00
adator
1cea8d0601 Merge pull request #38 from adator85/dev
V5.2.1
2024-09-15 03:09:22 +02:00
adator
652b400d5e Merge pull request #37 from adator85/dev
update mode clone
2024-09-15 02:50:27 +02:00
adator
2f8b965b59 Merge pull request #36 from adator85/dev
Dev
2024-09-15 02:04:32 +02:00
adator
3c043cefd8 Merge pull request #35 from adator85/dev
V5.1.8
2024-09-08 00:42:57 +02:00
adator
59a75cecd8 Merge pull request #34 from adator85/dev
V5.1.7
2024-09-03 00:21:32 +02:00
adator
71053437a7 Merge pull request #33 from adator85/dev
V5.1.6
2024-09-01 22:15:54 +02:00
adator
7796d05206 Merge pull request #32 from adator85/dev
Update vote kick commands
2024-09-01 18:55:57 +02:00
adator
5f2567f9e5 Merge pull request #31 from adator85/dev
mod_command update
2024-09-01 17:30:05 +02:00
adator
aaa1dd9a1a Merge pull request #30 from adator85/dev
adding Say command for clones
2024-09-01 16:40:25 +02:00
adator
a02f2f9a26 Merge pull request #29 from adator85/dev
update mod_clone module
2024-09-01 15:54:50 +02:00
adator
d73adb6f0b Merge pull request #28 from adator85/dev
update readme
2024-09-01 15:35:59 +02:00
adator
b812e64992 Merge pull request #27 from adator85/dev
Dev
2024-09-01 15:24:18 +02:00
adator
9bd1f68df2 Merge pull request #26 from adator85/dev
Dev
2024-09-01 14:59:38 +02:00
adator
f44b08bf36 Merge pull request #25 from adator85/dev
fix Installation
2024-08-29 01:36:38 +02:00
adator
1a19e1613a Merge pull request #24 from adator85/dev
Fix Bug installation
2024-08-29 01:31:19 +02:00
adator
cdc15b7b47 Merge pull request #23 from adator85/dev
Dev
2024-08-29 01:16:55 +02:00
adator
31fe9f62ec Merge pull request #22 from adator85/dev
Dev
2024-08-24 01:39:11 +02:00
adator
f0853e3afb Merge pull request #21 from adator85/dev
New Installation file created for unix system
2024-08-22 01:02:00 +02:00
adator
6dade09257 Merge pull request #20 from adator85/dev
README Update
2024-08-21 00:50:31 +02:00
adator
9533b010b2 Merge pull request #19 from adator85/dev
V5.0.4 - Delete a user when a user has been kicked
2024-08-20 02:24:37 +02:00
adator
824db73590 Merge pull request #18 from adator85/dev
Delete channel mode information
2024-08-20 02:14:31 +02:00
adator
96bf4b6f80 Merge pull request #17 from adator85/dev
Fix channel update
2024-08-20 02:08:09 +02:00
adator
922336363e Merge pull request #16 from adator85/dev
Dev
2024-08-20 01:56:04 +02:00
13 changed files with 402 additions and 1163 deletions

View File

@@ -32,34 +32,30 @@ Il permet aux opérateurs de gérer efficacement un canal, tout en offrant aux u
- Système d'exploitation Linux (Windows non supporté) - Système d'exploitation Linux (Windows non supporté)
- Un server UnrealIRCD corréctement configuré - Un server UnrealIRCD corréctement configuré
- Python version 3.10 ou supérieure - Python version 3.10 ou supérieure
```bash
# Bash Bash:
$ git clone https://github.com/adator85/IRC_DEFENDER_MODULES.git $ git clone https://github.com/adator85/IRC_DEFENDER_MODULES.git
# Renommer le fichier exemple_configuration.json en configuration.json - Renommer le fichier exemple_configuration.json en configuration.json
# Configurer le fichier configuration.json - Configurer le fichier configuration.json
$ python3 main.py $ python3 main.py
```
Si votre configuration est bonne, votre service est censé etre connecté a votre réseau IRC Si votre configuration est bonne, votre service est censé etre connecté a votre réseau IRC
Pour Les prochains lancement de defender vous devez utiliser la commande suivante: Pour Les prochains lancement de defender vous devez utiliser la commande suivante:
```bash Bash:
# Bash $ systemctl --user [start | stop | restart | status] defender
$ systemctl --user [start | stop | restart | status] defender
``` # Installation manuelle:
# Installation manuelle: Bash:
```bash $ git clone https://github.com/adator85/IRC_DEFENDER_MODULES.git
# Bash $ cd IRC_DEFENDER_MODULES
$ git clone https://github.com/adator85/IRC_DEFENDER_MODULES.git $ python3 -m venv .pyenv
$ cd IRC_DEFENDER_MODULES $ source .pyenv/bin/activate
$ python3 -m venv .pyenv (pyenv)$ pip install sqlalchemy, psutil, requests, faker
$ source .pyenv/bin/activate - Créer un service nommé "defender.service" pour votre service et placer le dans "/PATH/TO/USER/.config/systemd/user/"
(pyenv)$ pip install sqlalchemy, psutil, requests, faker, unrealircd_rpc_py - Si le dossier n'existe pas il faut les créer
$ sudo systemctl --user start defender
# Créer un service nommé "defender.service"
# pour votre service et placer le dans "/PATH/TO/USER/.config/systemd/user/"
# Si le dossier n'existe pas il faut les créer
$ sudo systemctl --user start defender
```
# Configuration # Configuration
``` ```
SERVEUR (Serveur) SERVEUR (Serveur)

View File

@@ -1,21 +1,8 @@
import os import time, threading, os, random, socket, hashlib, ipaddress, logging, requests, json, re, ast
import re
import json
import time
import random
import socket
import hashlib
import logging
import threading
import ipaddress
import ast
import requests
from dataclasses import fields from dataclasses import fields
from typing import Union, Literal from typing import Union, Literal
from base64 import b64decode, b64encode from base64 import b64decode, b64encode
from datetime import datetime, timedelta, timezone from datetime import datetime
from sqlalchemy import create_engine, Engine, Connection, CursorResult from sqlalchemy import create_engine, Engine, Connection, CursorResult
from sqlalchemy.sql import text from sqlalchemy.sql import text
from core.loadConf import ConfigDataModel from core.loadConf import ConfigDataModel
@@ -48,6 +35,7 @@ class Base:
with open(version_filename, 'r') as version_data: with open(version_filename, 'r') as version_data:
current_version:dict[str, str] = json.load(version_data) current_version:dict[str, str] = json.load(version_data)
# self.DEFENDER_VERSION = current_version["version"]
self.Config.current_version = current_version['version'] self.Config.current_version = current_version['version']
return None return None
@@ -80,14 +68,6 @@ class Base:
self.logs.warning(f'Github not available to fetch latest version') self.logs.warning(f'Github not available to fetch latest version')
def check_for_new_version(self, online:bool) -> bool: def check_for_new_version(self, online:bool) -> bool:
"""Check if there is a new version available
Args:
online (bool): True if you want to get the version from github (main branch)
Returns:
bool: True if there is a new version available
"""
try: try:
self.logs.debug(f'Checking for a new service version') self.logs.debug(f'Checking for a new service version')
@@ -126,11 +106,7 @@ class Base:
Cette fonction retourne un UNIXTIME de type 12365456 Cette fonction retourne un UNIXTIME de type 12365456
Return: Current time in seconds since the Epoch (int) Return: Current time in seconds since the Epoch (int)
""" """
cet_offset = timezone(timedelta(hours=2))
now_cet = datetime.now(cet_offset)
unixtime_cet = int(now_cet.timestamp())
unixtime = int( time.time() ) unixtime = int( time.time() )
return unixtime return unixtime
def get_datetime(self) -> str: def get_datetime(self) -> str:
@@ -236,19 +212,6 @@ class Base:
return False return False
def db_update_module(self, user_cmd: str, module_name: str) -> None:
"""Modifie la date et le user qui a rechargé le module
Args:
user_cmd (str): le user qui a rechargé le module
module_name (str): le module a rechargé
"""
update_cmd_query = f"UPDATE {self.Config.table_module} SET datetime = :datetime, user = :user WHERE module_name = :module_name"
mes_donnees = {'datetime': self.get_datetime(), 'user': user_cmd, 'module_name': module_name}
self.db_execute_query(update_cmd_query, mes_donnees)
return False
def db_delete_module(self, module_name:str) -> None: def db_delete_module(self, module_name:str) -> None:
"""Supprime les modules de la base de données """Supprime les modules de la base de données
@@ -611,7 +574,7 @@ class Base:
) )
''' '''
table_core_channel = f'''CREATE TABLE IF NOT EXISTS {self.Config.table_channel} ( table_core_channel = '''CREATE TABLE IF NOT EXISTS core_channel (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
datetime TEXT, datetime TEXT,
module_name TEXT, module_name TEXT,

View File

@@ -2,10 +2,10 @@ import socket
import ssl import ssl
import traceback import traceback
from ssl import SSLSocket from ssl import SSLSocket
from typing import Union
from core.loadConf import Config from core.loadConf import Config
from core.Model import Clones from core.Model import Clones
from core.base import Base from core.base import Base
from typing import Union
class Connection: class Connection:

View File

@@ -1,9 +1,8 @@
import os
import json
from sys import exit, prefix
from dataclasses import dataclass from dataclasses import dataclass
from subprocess import check_call, run, CalledProcessError, PIPE, check_output from subprocess import check_call, run, CalledProcessError, PIPE
from platform import python_version, python_version_tuple from platform import python_version, python_version_tuple
from sys import exit
import os
class Install: class Install:
@@ -25,23 +24,13 @@ class Install:
venv_pip_executable: str venv_pip_executable: str
venv_python_executable: str venv_python_executable: str
@dataclass
class Package:
name: str = None
version: str = None
DB_PACKAGES: list[Package] = []
def __init__(self) -> None: def __init__(self) -> None:
self.set_configuration() self.set_configuration()
if self.skip_install: if self.skip_install:
self.check_packages_version()
return None return None
self.check_packages_version()
# Sinon tester les dependances python et les installer avec pip # Sinon tester les dependances python et les installer avec pip
if self.do_install(): if self.do_install():
@@ -86,13 +75,11 @@ class Install:
if not os.path.exists(os.path.join(self.config.defender_install_folder, 'core', 'configuration.json')): if not os.path.exists(os.path.join(self.config.defender_install_folder, 'core', '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 (configuration.json) doesn't exist /!\\")
# Exclude Windows OS from the installation # Exclude Windows OS from the installation
if os.name == 'nt': if os.name == 'nt':
# If windows, modify pip and python virtual environment executable #print('/!\\ Skip installation /!\\')
self.config.venv_pip_executable = f'{os.path.join(defender_install_folder, venv_folder, "Scripts")}{os.sep}pip.exe'
self.config.venv_python_executable = f'{os.path.join(defender_install_folder, venv_folder, "Scripts")}{os.sep}python.exe'
self.skip_install = True self.skip_install = True
return False return False
@@ -104,7 +91,7 @@ class Install:
def is_root(self) -> bool: def is_root(self) -> bool:
if os.geteuid() != 0: if os.geteuid() != 0:
print('> User without privileges ==> OK') print('User without privileges ==> PASS')
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 /!\\')
@@ -136,75 +123,6 @@ class Install:
print(f"Try to install dependencies ...") print(f"Try to install dependencies ...")
exit(5) exit(5)
def get_packages_version_from_json(self) -> None:
"""This will create Package model with package names and required version
"""
try:
version_filename = f'.{os.sep}version.json'
with open(version_filename, 'r') as version_data:
package_info:dict[str, str] = json.load(version_data)
for name, version in package_info.items():
if name == 'version':
continue
self.DB_PACKAGES.append(
self.Package(name=name, version=version)
)
return None
except FileNotFoundError as fe:
print(f"File not found: {fe}")
except Exception as err:
print(f"General Error: {err}")
def check_packages_version(self) -> bool:
try:
newVersion = False
self.get_packages_version_from_json()
if not self.config.venv_folder in prefix:
print(f"You are probably running a new installation or you are not using your virtual env {self.config.venv_folder}")
return newVersion
print(f"> Checking for dependencies versions ==> WAIT")
for package in self.DB_PACKAGES:
newVersion = False
required_version = package.version
installed_version = None
output = check_output([self.config.venv_pip_executable, 'show', package.name])
for line in output.decode().splitlines():
if line.startswith('Version:'):
installed_version = line.split(':')[1].strip()
break
required_major, required_minor, required_patch = required_version.split('.')
installed_major, installed_minor, installed_patch = installed_version.split('.')
if required_major > installed_major:
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}')
newVersion = True
if newVersion:
self.run_subprocess([self.config.venv_pip_executable, 'install', '--upgrade', package.name])
print(f"> Dependencies versions ==> OK")
return newVersion
except CalledProcessError:
print(f"/!\\ Package {package.name} not installed /!\\")
except Exception as err:
print(f"General Error: {err}")
def check_python_version(self) -> bool: def check_python_version(self) -> bool:
"""Test si la version de python est autorisée ou non """Test si la version de python est autorisée ou non

View File

@@ -1,17 +1,10 @@
import sys import ssl, re, importlib, sys, time, threading, socket, traceback
import socket
import threading
import ssl
import re
import importlib
import time
import traceback
from ssl import SSLSocket from ssl import SSLSocket
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Union from typing import Union, Literal
from core.loadConf import Config from core.loadConf import Config
from core.base import Base
from core.Model import User, Admin, Channel, Clones from core.Model import User, Admin, Channel, Clones
from core.base import Base
class Irc: class Irc:
@@ -95,15 +88,13 @@ class Irc:
return None return None
except ssl.SSLEOFError as soe: except ssl.SSLEOFError as soe:
self.Base.logs.critical(f"SSLEOFError: {soe} - {soc.fileno()}") self.Base.logs.critical(f"SSLEOFError __create_socket: {soe} - {soc.fileno()}")
except ssl.SSLError as se: except ssl.SSLError as se:
self.Base.logs.critical(f"SSLError: {se} - {soc.fileno()}") self.Base.logs.critical(f"SSLError __create_socket: {se} - {soc.fileno()}")
except OSError as oe: except OSError as oe:
self.Base.logs.critical(f"OSError: {oe} - {soc.fileno()}") self.Base.logs.critical(f"OSError __create_socket: {oe} - {soc.fileno()}")
if 'connection refused' in str(oe).lower():
sys.exit(oe)
except AttributeError as ae: except AttributeError as ae:
self.Base.logs.critical(f"AttributeError: {ae} - {soc.fileno()}") self.Base.logs.critical(f"AttributeError __create_socket: {ae} - {soc.fileno()}")
def __ssl_context(self) -> ssl.SSLContext: def __ssl_context(self) -> ssl.SSLContext:
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
@@ -313,7 +304,7 @@ class Irc:
def send_response(self, responses:list[bytes]) -> None: def send_response(self, responses:list[bytes]) -> None:
try: try:
# print(responses) # print(data)
for data in responses: for data in responses:
response = data.decode(self.CHARSET[0]).split() response = data.decode(self.CHARSET[0]).split()
self.cmd(response) self.cmd(response)
@@ -490,8 +481,7 @@ class Irc:
self.Base.db_record_module(fromuser, module_name) self.Base.db_record_module(fromuser, module_name)
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Module {module_name} chargé") self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Module {module_name} chargé")
# self.Base.logs.info(self.loaded_classes) self.Base.logs.info(self.loaded_classes)
self.Base.logs.info(f"Module {class_name} has been loaded")
return True return True
except ModuleNotFoundError as moduleNotFound: except ModuleNotFoundError as moduleNotFound:
@@ -502,89 +492,6 @@ class Irc:
self.Base.logs.error(f"Something went wrong with a module you want to load : {e}") self.Base.logs.error(f"Something went wrong with a module you want to load : {e}")
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.COLORS.red}ERROR{self.Config.COLORS.black} ]: {e}") self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.COLORS.red}ERROR{self.Config.COLORS.black} ]: {e}")
def unload_module(self, mod_name: str) -> bool:
"""Unload a module
Args:
mod_name (str): Module name ex mod_defender
Returns:
bool: True if success
"""
try:
module_name = mod_name.lower() # Le nom du module. exemple: mod_defender
class_name = module_name.split('_')[1].capitalize() # Nom de la class. exemple: Defender
if class_name in self.loaded_classes:
self.loaded_classes[class_name].unload()
for level, command in self.loaded_classes[class_name].commands_level.items():
# Supprimer la commande de la variable commands
for c in self.loaded_classes[class_name].commands_level[level]:
self.commands.remove(c)
self.commands_level[level].remove(c)
del self.loaded_classes[class_name]
# Supprimer le module de la base de données
self.Base.db_delete_module(module_name)
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Module {module_name} supprimé")
return True
except Exception as err:
self.Base.logs.error(f"General Error: {err}")
return False
def reload_module(self, from_user: str, mod_name: str) -> bool:
try:
module_name = mod_name.lower() # ==> mod_defender
class_name = module_name.split('_')[1].capitalize() # ==> Defender
if 'mods.' + module_name in sys.modules:
self.Base.logs.info('Unload the module ...')
self.loaded_classes[class_name].unload()
self.Base.logs.info('Module Already Loaded ... reloading the module ...')
the_module = sys.modules['mods.' + module_name]
importlib.reload(the_module)
# Supprimer la class déja instancier
if class_name in self.loaded_classes:
# Supprimer les commandes déclarer dans la classe
for level, command in self.loaded_classes[class_name].commands_level.items():
# Supprimer la commande de la variable commands
for c in self.loaded_classes[class_name].commands_level[level]:
self.commands.remove(c)
self.commands_level[level].remove(c)
del self.loaded_classes[class_name]
my_class = getattr(the_module, class_name, None)
new_instance = my_class(self.ircObject)
self.loaded_classes[class_name] = new_instance
self.Base.db_update_module(from_user, mod_name)
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Module {module_name} rechargé")
return False
else:
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Module {module_name} n'est pas chargé !")
except TypeError as te:
self.Base.logs.error(f"A TypeError raised: {te}")
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :A TypeError raised: {te}")
self.Base.db_delete_module(module_name)
except AttributeError as ae:
self.Base.logs.error(f"Missing Attribute: {ae}")
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Missing Attribute: {ae}")
self.Base.db_delete_module(module_name)
except KeyError as ke:
self.Base.logs.error(f"Key Error: {ke}")
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Key Error: {ke}")
self.Base.db_delete_module(module_name)
except Exception as e:
self.Base.logs.error(f"Something went wrong with a module you want to reload: {e}")
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Something went wrong with the module: {e}")
self.Base.db_delete_module(module_name)
def insert_db_admin(self, uid:str, level:int) -> None: def insert_db_admin(self, uid:str, level:int) -> None:
if self.User.get_User(uid) is None: if self.User.get_User(uid) is None:
@@ -882,13 +789,6 @@ class Irc:
self.sendPrivMsg(msg=f'[{self.Config.COLORS.green}INFORMATION{self.Config.COLORS.nogc}] >> Defender is ready', channel=self.Config.SERVICE_CHANLOG) self.sendPrivMsg(msg=f'[{self.Config.COLORS.green}INFORMATION{self.Config.COLORS.nogc}] >> Defender is ready', channel=self.Config.SERVICE_CHANLOG)
self.INIT = 0 self.INIT = 0
# Send EOF to other modules
for classe_name, classe_object in self.loaded_classes.items():
classe_object.cmd(original_response)
# Stop here When EOS
return None
case _: case _:
pass pass
@@ -1063,8 +963,7 @@ class Irc:
arg.remove(f':{self.Config.SERVICE_PREFIX}') arg.remove(f':{self.Config.SERVICE_PREFIX}')
if not arg[0].lower() in self.commands: if not arg[0].lower() in self.commands:
self.Base.logs.debug(f"This command {arg[0]} is not available") self.Base.logs.debug(f"This command {arg[0]} is not available")
self.sendNotice(f"This command [{self.Config.COLORS.bold}{arg[0]}{self.Config.COLORS.bold}] is not available", user_trigger) return False
return None
cmd_to_send = convert_to_string.replace(':','') cmd_to_send = convert_to_string.replace(':','')
self.Base.log_cmd(user_trigger, cmd_to_send) self.Base.log_cmd(user_trigger, cmd_to_send)
@@ -1098,9 +997,7 @@ class Irc:
recieved_unixtime = int(arg[1].replace('\x01','')) recieved_unixtime = int(arg[1].replace('\x01',''))
current_unixtime = self.Base.get_unixtime() current_unixtime = self.Base.get_unixtime()
ping_response = current_unixtime - recieved_unixtime ping_response = current_unixtime - recieved_unixtime
self.send2socket(f':{dnickname} NOTICE {user_trigger} :\x01PING {str(ping_response)} secs\x01')
self.send2socket(f'PONG :{recieved_unixtime}')
self.send2socket(f':{dnickname} NOTICE {user_trigger} :\x01PING {ping_response} secs\x01')
return False return False
if not arg[0].lower() in self.commands: if not arg[0].lower() in self.commands:
@@ -1388,6 +1285,7 @@ class Irc:
case 'help': case 'help':
help = ''
count_level_definition = 0 count_level_definition = 0
get_admin = self.Admin.get_Admin(uid) get_admin = self.Admin.get_Admin(uid)
if not get_admin is None: if not get_admin is None:
@@ -1402,42 +1300,93 @@ class Irc:
if int(user_level) >= int(count_level_definition): if int(user_level) >= int(count_level_definition):
self.send2socket(f':{dnickname} NOTICE {fromuser} : ***************** {self.Config.COLORS.nogc}[ {self.Config.COLORS.green}LEVEL {str(levDef)} {self.Config.COLORS.nogc}] *****************') self.send2socket(f':{dnickname} NOTICE {fromuser} : ***************** {self.Config.COLORS.nogc}[ {self.Config.COLORS.green}LEVEL {str(levDef)} {self.Config.COLORS.nogc}] *****************')
count_commands = 0
help = ''
for comm in self.commands_level[count_level_definition]:
batch = 7 help += f"{comm.upper()}"
for i in range(0, len(self.commands_level[count_level_definition]), batch): if int(count_commands) < len(self.commands_level[count_level_definition])-1:
groupe = self.commands_level[count_level_definition][i:i + batch] # Extraire le groupe help += ' | '
batch_commands = ' | '.join(groupe) count_commands += 1
self.send2socket(f':{dnickname} NOTICE {fromuser} : {batch_commands}')
self.send2socket(f':{dnickname} NOTICE {fromuser} : ') self.send2socket(f':{dnickname} NOTICE {fromuser} : {help}')
count_level_definition += 1 count_level_definition += 1
self.send2socket(f':{dnickname} NOTICE {fromuser} : ***************** FIN DES COMMANDES *****************') self.send2socket(f':{dnickname} NOTICE {fromuser} : ***************** FIN DES COMMANDES *****************')
case 'load': case 'load':
try:
# Load a module ex: .load mod_defender self.load_module(fromuser, str(cmd[1]))
mod_name = str(cmd[1])
self.load_module(fromuser, mod_name)
except KeyError as ke:
self.Base.logs.error(f"Key Error: {ke} - list recieved: {cmd}")
except Exception as err:
self.Base.logs.error(f"General Error: {ke} - list recieved: {cmd}")
case 'unload': case 'unload':
# unload mod_defender # unload mod_dktmb
try: try:
module_name = str(cmd[1]).lower() # Le nom du module. exemple: mod_defender module_name = str(cmd[1]).lower() # Le nom du module. exemple: mod_defender
self.unload_module(module_name) class_name = module_name.split('_')[1].capitalize() # Nom de la class. exemple: Defender
except Exception as err:
self.Base.logs.error(f"General Error: {err}") if class_name in self.loaded_classes:
self.loaded_classes[class_name].unload()
for level, command in self.loaded_classes[class_name].commands_level.items():
# Supprimer la commande de la variable commands
for c in self.loaded_classes[class_name].commands_level[level]:
self.commands.remove(c)
self.commands_level[level].remove(c)
del self.loaded_classes[class_name]
# Supprimer le module de la base de données
self.Base.db_delete_module(module_name)
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Module {module_name} supprimé")
except:
self.Base.logs.error(f"Something went wrong with a module you want to load")
case 'reload': case 'reload':
# reload mod_defender # reload mod_dktmb
try: try:
module_name = str(cmd[1]).lower() # ==> mod_defender module_name = str(cmd[1]).lower() # ==> mod_defender
self.reload_module(from_user=fromuser, mod_name=module_name) class_name = module_name.split('_')[1].capitalize() # ==> Defender
if 'mods.' + module_name in sys.modules:
self.Base.logs.info('Unload the module ...')
self.loaded_classes[class_name].unload()
self.Base.logs.info('Module Already Loaded ... reloading the module ...')
the_module = sys.modules['mods.' + module_name]
importlib.reload(the_module)
# Supprimer la class déja instancier
if class_name in self.loaded_classes:
# Supprimer les commandes déclarer dans la classe
for level, command in self.loaded_classes[class_name].commands_level.items():
# Supprimer la commande de la variable commands
for c in self.loaded_classes[class_name].commands_level[level]:
self.commands.remove(c)
self.commands_level[level].remove(c)
del self.loaded_classes[class_name]
my_class = getattr(the_module, class_name, None)
new_instance = my_class(self.ircObject)
self.loaded_classes[class_name] = new_instance
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Module {module_name} rechargé")
return False
else:
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Module {module_name} n'est pas chargé !")
except TypeError as te:
self.Base.logs.error(f"A TypeError raised: {te}")
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :A TypeError raised: {te}")
self.Base.db_delete_module(module_name)
except AttributeError as ae:
self.Base.logs.error(f"Missing Attribute: {ae}")
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Missing Attribute: {ae}")
self.Base.db_delete_module(module_name)
except KeyError as ke:
self.Base.logs.error(f"Key Error: {ke}")
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Key Error: {ke}")
self.Base.db_delete_module(module_name)
except Exception as e: except Exception as e:
self.Base.logs.error(f"Something went wrong with a module you want to reload: {e}") self.Base.logs.error(f"Something went wrong with a module you want to reload: {e}")
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Something went wrong with the module: {e}") self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Something went wrong with the module: {e}")
@@ -1488,24 +1437,24 @@ class Irc:
self.Base.logs.debug(self.loaded_classes) self.Base.logs.debug(self.loaded_classes)
all_modules = self.Base.get_all_modules() all_modules = self.Base.get_all_modules()
loaded = False
results = self.Base.db_execute_query(f'SELECT datetime, user, module_name FROM {self.Config.table_module}') results = self.Base.db_execute_query(f'SELECT module_name FROM {self.Config.table_module}')
results = results.fetchall() results = results.fetchall()
found = False
for module in all_modules: for module in all_modules:
for loaded_mod in results: for loaded_mod in results:
if module == loaded_mod[2]: if module == loaded_mod[0]:
loaded_datetime = loaded_mod[0] found = True
loaded_user = loaded_mod[1]
loaded = True
if loaded: if found:
self.send2socket(f":{dnickname} NOTICE {fromuser} :{module} - {self.Config.COLORS.green}Loaded{self.Config.COLORS.nogc} by {loaded_user} on {loaded_datetime}") self.send2socket(f":{dnickname} NOTICE {fromuser} :{module} - {self.Config.COLORS.green}Loaded{self.Config.COLORS.nogc}")
loaded = False
else: else:
self.send2socket(f":{dnickname} NOTICE {fromuser} :{module} - {self.Config.COLORS.red}Not Loaded{self.Config.COLORS.nogc}") self.send2socket(f":{dnickname} NOTICE {fromuser} :{module} - {self.Config.COLORS.red}Not Loaded{self.Config.COLORS.nogc}")
found = False
case 'show_timers': case 'show_timers':
if self.Base.running_timers: if self.Base.running_timers:

View File

@@ -1,5 +1,4 @@
import sys import json, sys
import json
from os import sep from os import sep
from typing import Union, Literal from typing import Union, Literal
from dataclasses import dataclass, field from dataclasses import dataclass, field
@@ -17,7 +16,7 @@ class ColorModel:
red: str = "\x0304" red: str = "\x0304"
yellow: str = "\x0306" yellow: str = "\x0306"
bold: str = "\x02" bold: str = "\x02"
nogc: str = "\x03" nogc: str = "\x03"
@dataclass @dataclass
class ConfigDataModel: class ConfigDataModel:
@@ -86,19 +85,10 @@ class ConfigDataModel:
"""The password of the admin of the service""" """The password of the admin of the service"""
JSONRPC_URL: str JSONRPC_URL: str
"""The RPC url, if local https://127.0.0.1:PORT/api should be fine"""
JSONRPC_PATH_TO_SOCKET_FILE: str JSONRPC_PATH_TO_SOCKET_FILE: str
"""The full path of the socket file (/PATH/TO/YOUR/UNREALIRCD/SOCKET/FILE.socket)"""
JSONRPC_METHOD: str JSONRPC_METHOD: str
"""3 methods are available; requests/socket/unixsocket"""
JSONRPC_USER: str JSONRPC_USER: str
"""The RPC User defined in your unrealircd.conf"""
JSONRPC_PASSWORD: str JSONRPC_PASSWORD: str
"""The RPC Password defined in your unrealircd.conf"""
SALON_JAIL: str SALON_JAIL: str
"""The JAIL channel (ex. #jail)""" """The JAIL channel (ex. #jail)"""

View File

@@ -60,7 +60,6 @@ class Clone():
self.Base.db_query_channel(action='add', module_name=self.module_name, channel_name=self.Config.CLONE_CHANNEL) self.Base.db_query_channel(action='add', module_name=self.module_name, channel_name=self.Config.CLONE_CHANNEL)
self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} JOIN {self.Config.CLONE_CHANNEL}") self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} JOIN {self.Config.CLONE_CHANNEL}")
self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} SAMODE {self.Config.CLONE_CHANNEL} +o {self.Config.SERVICE_NICKNAME}")
self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} MODE {self.Config.CLONE_CHANNEL} +nts") self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} MODE {self.Config.CLONE_CHANNEL} +nts")
self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} MODE {self.Config.CLONE_CHANNEL} +k {self.Config.CLONE_CHANNEL_PASSWORD}") self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} MODE {self.Config.CLONE_CHANNEL} +k {self.Config.CLONE_CHANNEL_PASSWORD}")
@@ -127,8 +126,6 @@ class Clone():
self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone} :KILL') self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone} :KILL')
self.Base.db_query_channel(action='del', module_name=self.module_name, channel_name=self.Config.CLONE_CHANNEL) self.Base.db_query_channel(action='del', module_name=self.module_name, channel_name=self.Config.CLONE_CHANNEL)
self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} MODE {self.Config.CLONE_CHANNEL} -nts")
self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} MODE {self.Config.CLONE_CHANNEL} -k {self.Config.CLONE_CHANNEL_PASSWORD}")
self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} PART {self.Config.CLONE_CHANNEL}") self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} PART {self.Config.CLONE_CHANNEL}")
return None return None
@@ -150,7 +147,7 @@ class Clone():
del clone_to_kill del clone_to_kill
# If no more clones then stop this thread # If LIST empty then stop this thread
if not self.Clone.UID_CLONE_DB: if not self.Clone.UID_CLONE_DB:
break break

View File

@@ -35,14 +35,9 @@ class Command():
# Create module commands (Mandatory) # Create module commands (Mandatory)
self.commands_level = { self.commands_level = {
1: ['join', 'part'], 1: ['join', 'part'],
2: ['owner', 'deowner', 'protect', 'deprotect', 'op', 'deop', 'halfop', 'dehalfop', 'voice', 2: ['owner', 'deowner', 'op', 'deop', 'halfop', 'dehalfop', 'voice',
'devoice', 'opall', 'deopall', 'devoiceall', 'voiceall', 'ban', 'devoice', 'opall', 'deopall', 'devoiceall', 'voiceall', 'ban',
'unban','kick', 'kickban', 'umode', 'mode', 'svsjoin', 'svspart', 'svsnick', 'topic', 'unban','kick', 'kickban', 'umode', 'svsjoin', 'svspart', 'svsnick']
'wallops', 'globops','gnotice','whois', 'names', 'invite', 'inviteme',
'sajoin', 'sapart',
'kill', 'gline', 'ungline', 'kline', 'unkline', 'shun', 'unshun',
'glinelist', 'shunlist', 'klinelist'],
3: ['map']
} }
# Init the module # Init the module
@@ -63,9 +58,6 @@ class Command():
self.__load_module_configuration() self.__load_module_configuration()
# End of mandatory methods you can start your customization # # End of mandatory methods you can start your customization #
self.user_to_notice: str = ''
self.show_219: bool = True
return None return None
def __set_commands(self, commands:dict[int, list[str]]) -> None: def __set_commands(self, commands:dict[int, list[str]]) -> None:
@@ -99,7 +91,7 @@ class Command():
) )
''' '''
# self.Base.db_execute_query(table_logs) self.Base.db_execute_query(table_logs)
return None return None
def __load_module_configuration(self) -> None: def __load_module_configuration(self) -> None:
@@ -130,81 +122,45 @@ class Command():
return None return None
def add_defender_channel(self, channel:str) -> bool:
"""Cette fonction ajoute les salons de join de Defender
Args:
channel (str): le salon à enregistrer.
"""
mes_donnees = {'channel': channel}
response = self.Base.db_execute_query("SELECT id FROM def_channels WHERE channel = :channel", mes_donnees)
isChannelExist = response.fetchone()
if isChannelExist is None:
mes_donnees = {'datetime': self.Base.get_datetime(), 'channel': channel}
insert = self.Base.db_execute_query(f"INSERT INTO def_channels (datetime, channel) VALUES (:datetime, :channel)", mes_donnees)
if insert.rowcount >=0:
return True
else:
return False
else:
return False
def delete_defender_channel(self, channel:str) -> bool:
"""Cette fonction supprime les salons de join de Defender
Args:
channel (str): le salon à enregistrer.
"""
mes_donnes = {'channel': channel}
response = self.Base.db_execute_query("DELETE FROM def_channels WHERE channel = :channel", mes_donnes)
affected_row = response.rowcount
if affected_row > 0:
return True
else:
return False
def cmd(self, data:list) -> None: def cmd(self, data:list) -> None:
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
match cmd[1]:
# [':irc.deb.biz.st', '403', 'Dev-PyDefender', '#Z', ':No', 'such', 'channel']
case '403' | '401':
try:
message = ' '.join(cmd[3:])
self.Irc.send2socket(f":{dnickname} NOTICE {self.user_to_notice} :[{red}ERROR MSG{nogc}] {message}")
self.Base.logs.error(f"{cmd[1]} - {message}")
except KeyError as ke:
self.Base.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.Irc.send2socket(f":{dnickname} NOTICE {self.user_to_notice} : [{green}SERVER MSG{nogc}] {message}")
except KeyError as ke:
self.Base.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
type_of_stats = str(cmd[3])
match type_of_stats:
case 's':
self.Irc.send2socket(f":{dnickname} NOTICE {self.user_to_notice} : No shun")
case 'G':
self.Irc.send2socket(f":{dnickname} NOTICE {self.user_to_notice} : No gline")
case 'k':
self.Irc.send2socket(f":{dnickname} NOTICE {self.user_to_notice} : No kline")
except KeyError as ke:
self.Base.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:])
self.Irc.send2socket(f":{dnickname} NOTICE {self.user_to_notice} : {bold}Author{nogc}: {author} - {bold}Host{nogc}: {host} - {bold}Reason{nogc}: {reason}")
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
return None return None
def _hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None: def _hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None:
@@ -213,7 +169,6 @@ class Command():
dnickname = self.Config.SERVICE_NICKNAME dnickname = self.Config.SERVICE_NICKNAME
service_id = self.Config.SERVICE_ID service_id = self.Config.SERVICE_ID
dchanlog = self.Config.SERVICE_CHANLOG dchanlog = self.Config.SERVICE_CHANLOG
self.user_to_notice = user
fromuser = user fromuser = user
fromchannel = channel fromchannel = channel
@@ -391,60 +346,6 @@ class Command():
except Exception as err: except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}') self.Logs.warning(f'Unknown Error: {str(err)}')
case 'protect':
# /mode #channel +a user
# .protect #channel user
try:
if fromchannel is None:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Right command : /msg {dnickname} {command.upper()} [#SALON] [NICKNAME]')
return False
if len(cmd) == 1:
self.Irc.send2socket(f":{service_id} MODE {fromchannel} +a {fromuser}")
return True
# deowner nickname
if len(cmd) == 2:
nickname = cmd[1]
self.Irc.send2socket(f":{service_id} MODE {fromchannel} +a {nickname}")
return True
nickname = cmd[2]
self.Irc.send2socket(f":{service_id} MODE {fromchannel} +a {nickname}")
except IndexError as e:
self.Logs.warning(f'_hcmd DEOWNER: {str(e)}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Right command : /msg {dnickname} {command.upper()} [#SALON] [NICKNAME]')
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'deprotect':
# /mode #channel -a user
# .deprotect #channel user
try:
if fromchannel is None:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Right command : /msg {dnickname} {command.upper()} [#SALON] [NICKNAME]')
return False
if len(cmd) == 1:
self.Irc.send2socket(f":{service_id} MODE {fromchannel} -a {fromuser}")
return True
# deowner nickname
if len(cmd) == 2:
nickname = cmd[1]
self.Irc.send2socket(f":{service_id} MODE {fromchannel} -a {nickname}")
return True
nickname = cmd[2]
self.Irc.send2socket(f":{service_id} MODE {fromchannel} -a {nickname}")
except IndexError as e:
self.Logs.warning(f'_hcmd DEOWNER: {str(e)}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Right command : /msg {dnickname} {command.upper()} [#SALON] [NICKNAME]')
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'halfop': case 'halfop':
# /mode #channel +h user # /mode #channel +h user
# .halfop #channel user # .halfop #channel user
@@ -558,7 +459,7 @@ class Command():
try: try:
sentchannel = str(cmd[1]) if self.Base.Is_Channel(cmd[1]) else None sentchannel = str(cmd[1]) if self.Base.Is_Channel(cmd[1]) else None
if sentchannel is None: if sentchannel is None:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Right command : /msg {dnickname} {command.upper()} [#SALON] [NICKNAME]') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Right command : /msg {dnickname} ban [#SALON] [NICKNAME]')
return False return False
nickname = cmd[2] nickname = cmd[2]
@@ -567,7 +468,7 @@ class Command():
self.Logs.debug(f'{fromuser} has banned {nickname} from {sentchannel}') self.Logs.debug(f'{fromuser} has banned {nickname} from {sentchannel}')
except IndexError as e: except IndexError as e:
self.Logs.warning(f'_hcmd BAN: {str(e)}') self.Logs.warning(f'_hcmd BAN: {str(e)}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Right command : /msg {dnickname} {command.upper()} [#SALON] [NICKNAME]') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Right command : /msg {dnickname} ban [#SALON] [NICKNAME]')
except Exception as err: except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}') self.Logs.warning(f'Unknown Error: {str(err)}')
@@ -676,174 +577,6 @@ class Command():
except Exception as err: except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}') self.Logs.warning(f'Unknown Error: {str(err)}')
case 'topic':
try:
if len(cmd) == 1:
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :/msg {dnickname} TOPIC #channel THE_TOPIC_MESSAGE")
return None
chan = str(cmd[1])
if not self.Base.Is_Channel(chan):
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :The channel must start with #")
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :/msg {dnickname} TOPIC #channel THE_TOPIC_MESSAGE")
return None
topic_msg = ' '.join(cmd[2:]).strip()
if topic_msg:
self.Irc.send2socket(f':{dnickname} TOPIC {chan} :{topic_msg}')
else:
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :You need to specify the topic")
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'wallops':
try:
if len(cmd) == 1:
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :/msg {dnickname} WALLOPS THE_WALLOPS_MESSAGE")
return None
wallops_msg = ' '.join(cmd[1:]).strip()
if wallops_msg:
self.Irc.send2socket(f':{dnickname} WALLOPS {wallops_msg} ({dnickname})')
else:
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :You need to specify the wallops message")
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'globops':
try:
if len(cmd) == 1:
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :/msg {dnickname} GLOBOPS THE_GLOBOPS_MESSAGE")
return None
globops_msg = ' '.join(cmd[1:]).strip()
if globops_msg:
self.Irc.send2socket(f':{dnickname} GLOBOPS {globops_msg} ({dnickname})')
else:
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :You need to specify the globops message")
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'gnotice':
try:
if len(cmd) == 1:
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :/msg {dnickname} {str(cmd[0]).upper()} THE_GLOBAL_NOTICE_MESSAGE")
return None
gnotice_msg = ' '.join(cmd[1:]).strip()
if gnotice_msg:
self.Irc.send2socket(f':{dnickname} NOTICE $*.* :[{self.Config.COLORS.red}GLOBAL NOTICE{self.Config.COLORS.nogc}] {gnotice_msg}')
else:
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :You need to specify the global notice message")
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'whois':
try:
self.user_to_notice = fromuser
if len(cmd) == 1:
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :/msg {dnickname} {str(cmd[0]).upper()} NICKNAME")
return None
nickname = str(cmd[1])
if self.User.get_nickname(nickname) is None:
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :Nickname not found !")
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :/msg {dnickname} {str(cmd[0]).upper()} NICKNAME")
return None
self.Irc.send2socket(f':{dnickname} WHOIS {nickname}')
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'names':
try:
if len(cmd) == 1:
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :/msg {dnickname} {str(cmd[0]).upper()} #CHANNEL")
return None
chan = str(cmd[1])
if not self.Base.Is_Channel(chan):
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :The channel must start with #")
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :/msg {dnickname} {str(cmd[0]).upper()} #channel")
return None
self.Irc.send2socket(f':{dnickname} NAMES {chan}')
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'invite':
try:
if len(cmd) < 3:
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :/msg {dnickname} {str(cmd[0]).upper()} #CHANNEL NICKNAME")
return None
chan = str(cmd[1])
nickname = str(cmd[2])
if not self.Base.Is_Channel(chan):
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :The channel must start with #")
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :/msg {dnickname} {str(cmd[0]).upper()} #channel nickname")
return None
if self.User.get_nickname(nickname) is None:
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :Nickname not found !")
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :/msg {dnickname} {str(cmd[0]).upper()} #channel NICKNAME")
return None
self.Irc.send2socket(f':{dnickname} INVITE {nickname} {chan}')
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'inviteme':
try:
if len(cmd) == 0:
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} :/msg {dnickname} {str(cmd[0]).upper()}")
return None
self.Irc.send2socket(f':{dnickname} INVITE {fromuser} {self.Config.SERVICE_CHANLOG}')
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'map':
try:
self.user_to_notice = fromuser
self.Irc.send2socket(f':{dnickname} MAP')
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'umode': case 'umode':
try: try:
# .umode nickname +mode # .umode nickname +mode
@@ -856,39 +589,6 @@ class Command():
except Exception as err: except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}') self.Logs.warning(f'Unknown Error: {str(err)}')
case 'mode':
# .mode #channel +/-mode
# .mode +/-mode
try:
if len(cmd) < 2:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Right command : /msg {dnickname} {command.upper()} [#CHANNEL] [+/-]mode')
return None
if fromchannel is None:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Right command : /msg {dnickname} {command.upper()} [#CHANNEL] [+/-]mode')
return None
if len(cmd) == 2:
channel_mode = cmd[1]
if self.Base.Is_Channel(fromchannel):
self.Irc.send2socket(f":{dnickname} MODE {fromchannel} {channel_mode}")
else:
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} : Right command : Channel [{fromchannel}] is not correct should start with #")
return None
if len(cmd) == 3:
provided_channel = cmd[1]
channel_mode = cmd[2]
self.Irc.send2socket(f":{service_id} MODE {provided_channel} {channel_mode}")
return None
except IndexError as e:
self.Logs.warning(f'_hcmd OP: {str(e)}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Right command : /msg {dnickname} {command.upper()} [#CHANNEL] [+/-]mode')
except Exception as err:
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'svsjoin': case 'svsjoin':
try: try:
# .svsjoin nickname #channel # .svsjoin nickname #channel
@@ -921,38 +621,6 @@ class Command():
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} SVSPART nickname #channel') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} SVSPART nickname #channel')
self.Logs.warning(f'Unknown Error: {str(err)}') self.Logs.warning(f'Unknown Error: {str(err)}')
case 'sajoin':
try:
# .sajoin nickname #channel
nickname = str(cmd[1])
channel = str(cmd[2])
if len(cmd) < 3:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname #channel')
return None
self.Irc.send2socket(f':{self.Config.SERVEUR_ID} SAJOIN {nickname} {channel}')
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname #channel')
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'sapart':
try:
# .sapart nickname #channel
nickname = str(cmd[1])
channel = str(cmd[2])
if len(cmd) < 3:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname #channel')
return None
self.Irc.send2socket(f':{self.Config.SERVEUR_ID} SAPART {nickname} {channel}')
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname #channel')
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'svsnick': case 'svsnick':
try: try:
# .svsnick nickname newnickname # .svsnick nickname newnickname
@@ -965,203 +633,12 @@ class Command():
return None return None
if len(cmd) != 3: if len(cmd) != 3:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname newnickname') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} SVSNICK nickname newnickname')
return None return None
self.Irc.send2socket(f':{self.Config.SERVEUR_ID} SVSNICK {nickname} {newnickname} {unixtime}') self.Irc.send2socket(f':{self.Config.SERVEUR_ID} SVSNICK {nickname} {newnickname} {unixtime}')
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname newnickname')
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'kill':
try:
# 'kill', 'gline', 'ungline', 'shun', 'unshun'
# .kill nickname reason
if len(cmd) < 3:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname reason')
return None
nickname = str(cmd[1])
kill_reason = ' '.join(cmd[2:])
self.Irc.send2socket(f":{service_id} KILL {nickname} {kill_reason} ({self.Config.COLORS.red}{dnickname}{self.Config.COLORS.nogc})")
except KeyError as ke: except KeyError as ke:
self.Base.logs.error(ke) self.Base.logs.error(ke)
except Exception as err: except Exception as err:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} SVSNICK nickname newnickname') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} SVSNICK nickname newnickname')
self.Logs.warning(f'Unknown Error: {str(err)}') self.Logs.warning(f'Unknown Error: {str(err)}')
case 'gline':
try:
# TKL + G user host set_by expire_timestamp set_at_timestamp :reason
# .gline [nickname] [host] [reason]
if len(cmd) < 4:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname host reason')
return None
nickname = str(cmd[1])
hostname = str(cmd[2])
set_at_timestamp = self.Base.get_unixtime()
expire_time = (60 * 60 * 24) + set_at_timestamp
gline_reason = ' '.join(cmd[3:])
if nickname == '*' and hostname == '*':
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : You want to close the server ? i would recommand ./unrealircd stop :)')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname host reason')
return None
self.Irc.send2socket(f":{self.Config.SERVEUR_ID} TKL + G {nickname} {hostname} {dnickname} {expire_time} {set_at_timestamp} :{gline_reason}")
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname host reason')
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'ungline':
try:
# 'shun', 'unshun'
# TKL + G user host set_by expire_timestamp set_at_timestamp :reason
# .ungline nickname host
if len(cmd) < 2:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname hostname')
return None
nickname = str(cmd[1])
hostname = str(cmd[2])
self.Irc.send2socket(f":{self.Config.SERVEUR_ID} TKL - G {nickname} {hostname} {dnickname}")
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname hostname')
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'kline':
try:
# TKL + k user host set_by expire_timestamp set_at_timestamp :reason
# .gline [nickname] [host] [reason]
if len(cmd) < 4:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname host reason')
return None
nickname = str(cmd[1])
hostname = str(cmd[2])
set_at_timestamp = self.Base.get_unixtime()
expire_time = (60 * 60 * 24) + set_at_timestamp
gline_reason = ' '.join(cmd[3:])
if nickname == '*' and hostname == '*':
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : You want to close the server ? i would recommand ./unrealircd stop :)')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname host reason')
return None
self.Irc.send2socket(f":{self.Config.SERVEUR_ID} TKL + k {nickname} {hostname} {dnickname} {expire_time} {set_at_timestamp} :{gline_reason}")
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname host reason')
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'unkline':
try:
# 'shun', 'unshun'
# TKL + G user host set_by expire_timestamp set_at_timestamp :reason
# .ungline nickname host
if len(cmd) < 2:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname hostname')
return None
nickname = str(cmd[1])
hostname = str(cmd[2])
self.Irc.send2socket(f":{self.Config.SERVEUR_ID} TKL - k {nickname} {hostname} {dnickname}")
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname hostname')
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'shun':
try:
# TKL + G user host set_by expire_timestamp set_at_timestamp :reason
# .shun [nickname] [host] [reason]
if len(cmd) < 4:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname host reason')
return None
nickname = str(cmd[1])
hostname = str(cmd[2])
set_at_timestamp = self.Base.get_unixtime()
expire_time = (60 * 60 * 24) + set_at_timestamp
shun_reason = ' '.join(cmd[3:])
if nickname == '*' and hostname == '*':
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : You want to close the server ? i would recommand ./unrealircd stop :)')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname host reason')
return None
self.Irc.send2socket(f":{self.Config.SERVEUR_ID} TKL + s {nickname} {hostname} {dnickname} {expire_time} {set_at_timestamp} :{shun_reason}")
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname host reason')
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'unshun':
try:
# 'shun', 'unshun'
# TKL + G user host set_by expire_timestamp set_at_timestamp :reason
# .unshun nickname host
if len(cmd) < 2:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname hostname')
return None
nickname = str(cmd[1])
hostname = str(cmd[2])
self.Irc.send2socket(f":{self.Config.SERVEUR_ID} TKL - s {nickname} {hostname} {dnickname}")
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()} nickname hostname')
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'glinelist':
try:
self.user_to_notice = fromuser
self.Irc.send2socket(f":{self.Config.SERVICE_ID} STATS G")
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()}')
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'shunlist':
try:
self.user_to_notice = fromuser
self.Irc.send2socket(f":{self.Config.SERVICE_ID} STATS s")
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()}')
self.Logs.warning(f'Unknown Error: {str(err)}')
case 'klinelist':
try:
self.user_to_notice = fromuser
self.Irc.send2socket(f":{self.Config.SERVICE_ID} STATS k")
except KeyError as ke:
self.Base.logs.error(ke)
except Exception as err:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : /msg {dnickname} {command.upper()}')
self.Logs.warning(f'Unknown Error: {str(err)}')

View File

@@ -1,12 +1,7 @@
import socket
import json
import time
import re
import psutil
import requests
from dataclasses import dataclass, fields, field from dataclasses import dataclass, fields, field
from datetime import datetime from datetime import datetime
from typing import Union from typing import Union
import re, socket, psutil, requests, json, time
from sys import exit from sys import exit
from core.irc import Irc from core.irc import Irc
from core.Model import User from core.Model import User
@@ -111,6 +106,9 @@ class Defender():
self.__load_module_configuration() self.__load_module_configuration()
# End of mandatory methods you can start your customization # # End of mandatory methods you can start your customization #
# # Rejoindre les salons
# self.join_saved_channels()
self.timeout = self.Config.API_TIMEOUT self.timeout = self.Config.API_TIMEOUT
# Listes qui vont contenir les ip a scanner avec les différentes API # Listes qui vont contenir les ip a scanner avec les différentes API
@@ -147,8 +145,7 @@ class Defender():
self.Base.create_thread(func=self.thread_reputation_timer) self.Base.create_thread(func=self.thread_reputation_timer)
if self.ModConfig.reputation == 1: if self.ModConfig.reputation == 1:
self.Irc.send2socket(f":{self.Config.SERVEUR_ID} SJOIN {self.Base.get_unixtime()} {self.Config.SALON_JAIL} + :{self.Config.SERVICE_NICKNAME}") self.Irc.send2socket(f":{self.Config.SERVICE_ID} SAMODE {self.Config.SALON_JAIL} +{self.Config.SERVICE_UMODES} {self.Config.SERVICE_NICKNAME}")
self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} SAMODE {self.Config.SALON_JAIL} +o {self.Config.SERVICE_NICKNAME}")
return None return None
@@ -247,6 +244,40 @@ class Defender():
self.reputationTimer_isRunning:bool = False self.reputationTimer_isRunning:bool = False
return None return None
def add_defender_channel(self, channel:str) -> bool:
"""Cette fonction ajoute les salons de join de Defender
Args:
channel (str): le salon à enregistrer.
"""
mes_donnees = {'channel': channel}
response = self.Base.db_execute_query("SELECT id FROM def_channels WHERE channel = :channel", mes_donnees)
isChannelExist = response.fetchone()
if isChannelExist is None:
mes_donnees = {'datetime': self.Base.get_datetime(), 'channel': channel}
insert = self.Base.db_execute_query(f"INSERT INTO def_channels (datetime, channel) VALUES (:datetime, :channel)", mes_donnees)
return True
else:
return False
def delete_defender_channel(self, channel:str) -> bool:
"""Cette fonction supprime les salons de join de Defender
Args:
channel (str): le salon à enregistrer.
"""
mes_donnes = {'channel': channel}
response = self.Base.db_execute_query("DELETE FROM def_channels WHERE channel = :channel", mes_donnes)
affected_row = response.rowcount
if affected_row > 0:
return True
else:
return False
def reputation_insert(self, reputationModel: ReputationModel) -> bool: def reputation_insert(self, reputationModel: ReputationModel) -> bool:
response = False response = False
@@ -336,7 +367,7 @@ class Defender():
def join_saved_channels(self) -> None: def join_saved_channels(self) -> None:
result = self.Base.db_execute_query(f"SELECT distinct channel_name FROM {self.Config.table_channel}") result = self.Base.db_execute_query("SELECT id, channel FROM def_channels")
channels = result.fetchall() channels = result.fetchall()
jail_chan = self.Config.SALON_JAIL jail_chan = self.Config.SALON_JAIL
jail_chan_mode = self.Config.SALON_JAIL_MODES jail_chan_mode = self.Config.SALON_JAIL_MODES
@@ -347,7 +378,7 @@ class Defender():
unixtime = self.Base.get_unixtime() unixtime = self.Base.get_unixtime()
for channel in channels: for channel in channels:
chan = channel[0] id, chan = channel
self.Irc.send2socket(f":{self.Config.SERVEUR_ID} SJOIN {unixtime} {chan} + :{self.Config.SERVICE_ID}") self.Irc.send2socket(f":{self.Config.SERVEUR_ID} SJOIN {unixtime} {chan} + :{self.Config.SERVICE_ID}")
if chan == jail_chan: if chan == jail_chan:
self.Irc.send2socket(f":{service_id} SAMODE {jail_chan} +{dumodes} {dnickname}") self.Irc.send2socket(f":{service_id} SAMODE {jail_chan} +{dumodes} {dnickname}")
@@ -964,206 +995,190 @@ class Defender():
self.Logs.error(f"Thread_cloudfilt_scan Error : {ve}") self.Logs.error(f"Thread_cloudfilt_scan Error : {ve}")
def cmd(self, data: list) -> None: def cmd(self, data: list) -> None:
try:
service_id = self.Config.SERVICE_ID # Defender serveur id
cmd = list(data).copy()
match cmd[1]: service_id = self.Config.SERVICE_ID # Defender serveur id
cmd = list(data).copy()
case 'REPUTATION': if len(cmd) < 2:
# :001 REPUTATION 91.168.141.239 118 return None
try:
self.reputation_first_connexion['ip'] = cmd[2]
self.reputation_first_connexion['score'] = cmd[3]
if str(cmd[3]).find('*') != -1:
# If the reputation changed, we do not need to scan the IP
return None
if not self.Base.is_valid_ip(cmd[2]): match cmd[1]:
return None
# Possibilité de déclancher les bans a ce niveau. case 'EOS':
except IndexError as ie: if self.Irc.INIT == 0:
self.Logs.error(f'cmd reputation: index error: {ie}') self.Irc.send2socket(f":{service_id} SAMODE {self.Config.SALON_JAIL} +{self.Config.SERVICE_UMODES} {self.Config.SERVICE_NICKNAME}")
if len(cmd) < 3: case 'REPUTATION':
return None # :001 REPUTATION 91.168.141.239 118
try:
match cmd[2]: self.reputation_first_connexion['ip'] = cmd[2]
self.reputation_first_connexion['score'] = cmd[3]
case 'MODE': if str(cmd[3]).find('*') != -1:
# ['...', ':001XSCU0Q', 'MODE', '#jail', '+b', '~security-group:unknown-users'] # If the reputation changed, we do not need to scan the IP
channel = str(cmd[3])
mode = str(cmd[4])
group_to_check = str(cmd[5:])
group_to_unban = '~security-group:unknown-users'
if self.Config.SALON_JAIL == channel:
if mode == '+b' and group_to_unban in group_to_check:
self.Irc.send2socket(f":{service_id} MODE {self.Config.SALON_JAIL} -b ~security-group:unknown-users")
self.Irc.send2socket(f":{service_id} MODE {self.Config.SALON_JAIL} -eee ~security-group:webirc-users ~security-group:known-users ~security-group:websocket-users")
case 'PRIVMSG':
cmd.pop(0)
user_trigger = str(cmd[0]).replace(':','')
channel = cmd[2]
find_nickname = self.User.get_nickname(user_trigger)
self.flood(find_nickname, channel)
case 'UID':
# If Init then do nothing
if self.Irc.INIT == 1:
return None return None
# Supprimer la premiere valeur et finir le code normalement if not self.Base.is_valid_ip(cmd[2]):
cmd.pop(0) return None
# Get User information # Possibilité de déclancher les bans a ce niveau.
_User = self.User.get_User(str(cmd[7])) except IndexError as ie:
self.Logs.error(f'cmd reputation: index error: {ie}')
# If user is not service or IrcOp then scan them match cmd[2]:
case 'PRIVMSG':
cmd.pop(0)
user_trigger = str(cmd[0]).replace(':','')
channel = cmd[2]
find_nickname = self.User.get_nickname(user_trigger)
self.flood(find_nickname, channel)
case 'UID':
# If Init then do nothing
if self.Irc.INIT == 1:
return None
# Supprimer la premiere valeur et finir le code normalement
cmd.pop(0)
# Get User information
_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 _User is None:
self.Logs.critical(f'This UID: [{cmd[7]}] is not available please check why')
return None
reputation_flag = self.ModConfig.reputation
reputation_seuil = self.ModConfig.reputation_seuil
if self.Irc.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(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 if reputation_flag == 1 and _User.score_connexion <= reputation_seuil:
self.freeipapi_UserModel.append(_User) if self.ModConfig.freeipapi_scan == 1 and not _User.remote_ip in self.Config.WHITELISTED_IP else None currentDateTime = self.Base.get_datetime()
self.cloudfilt_UserModel.append(_User) if self.ModConfig.cloudfilt_scan == 1 and not _User.remote_ip in self.Config.WHITELISTED_IP else None self.reputation_insert(
self.psutil_UserModel.append(_User) if self.ModConfig.psutil_scan == 1 and not _User.remote_ip in self.Config.WHITELISTED_IP else None self.ReputationModel(
self.localscan_UserModel.append(_User) if self.ModConfig.local_scan == 1 and not _User.remote_ip in self.Config.WHITELISTED_IP else None uid=_User.uid, nickname=_User.nickname, username=_User.username, realname=_User.realname,
hostname=_User.hostname, umodes=_User.umodes, vhost=_User.vhost, ip=_User.remote_ip, score=_User.score_connexion,
if _User is None: secret_code=self.Base.get_random(8), isWebirc=_User.isWebirc, isWebsocket=_User.isWebsocket, connected_datetime=currentDateTime,
self.Logs.critical(f'This UID: [{cmd[7]}] is not available please check why') updated_datetime=currentDateTime
return None
reputation_flag = self.ModConfig.reputation
reputation_seuil = self.ModConfig.reputation_seuil
if self.Irc.INIT == 0:
# Si le user n'es pas un service ni un IrcOP
if not re.match(fr'^.*[S|o?].*$', _User.umodes):
if reputation_flag == 1 and _User.score_connexion <= reputation_seuil:
currentDateTime = self.Base.get_datetime()
self.reputation_insert(
self.ReputationModel(
uid=_User.uid, nickname=_User.nickname, username=_User.username, realname=_User.realname,
hostname=_User.hostname, umodes=_User.umodes, vhost=_User.vhost, ip=_User.remote_ip, score=_User.score_connexion,
secret_code=self.Base.get_random(8), isWebirc=_User.isWebirc, isWebsocket=_User.isWebsocket, connected_datetime=currentDateTime,
updated_datetime=currentDateTime
)
) )
# self.Irc.send2socket(f":{service_id} WHOIS {nickname}") )
if self.reputation_check(_User.uid): # self.Irc.send2socket(f":{service_id} WHOIS {nickname}")
if reputation_flag == 1 and _User.score_connexion <= reputation_seuil: if self.reputation_check(_User.uid):
self.system_reputation(_User.uid) if reputation_flag == 1 and _User.score_connexion <= reputation_seuil:
self.Logs.info('Démarrer le systeme de reputation') self.system_reputation(_User.uid)
self.Logs.info('Démarrer le systeme de reputation')
case 'SJOIN': case 'SJOIN':
# ['@msgid=F9B7JeHL5pj9nN57cJ5pEr;time=2023-12-28T20:47:24.305Z', ':001', 'SJOIN', '1702138958', '#welcome', ':0015L1AHL'] # ['@msgid=F9B7JeHL5pj9nN57cJ5pEr;time=2023-12-28T20:47:24.305Z', ':001', 'SJOIN', '1702138958', '#welcome', ':0015L1AHL']
try: try:
cmd.pop(0)
parsed_chan = cmd[3]
if self.ModConfig.reputation == 1:
parsed_UID = cmd[4]
pattern = fr'^:[@|%|\+|~|\*]*'
parsed_UID = re.sub(pattern, '', parsed_UID)
get_reputation = self.reputation_get_Reputation(parsed_UID)
if parsed_chan != self.Config.SALON_JAIL:
self.Irc.send2socket(f":{service_id} MODE {parsed_chan} +b ~security-group:unknown-users")
self.Irc.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:
isWebirc = get_reputation.isWebirc
if not isWebirc:
if parsed_chan != self.Config.SALON_JAIL:
self.Irc.send2socket(f":{service_id} SAPART {get_reputation.nickname} {parsed_chan}")
if self.ModConfig.reputation_ban_all_chan == 1 and not isWebirc:
if parsed_chan != self.Config.SALON_JAIL:
self.Irc.send2socket(f":{service_id} MODE {parsed_chan} +b {get_reputation.nickname}!*@*")
self.Irc.send2socket(f":{service_id} KICK {parsed_chan} {get_reputation.nickname}")
self.Logs.debug(f'SJOIN parsed_uid : {parsed_UID}')
except KeyError as ke:
self.Logs.error(f"key error SJOIN : {ke}")
case 'SLOG':
# self.Base.scan_ports(cmd[7])
cmd.pop(0) cmd.pop(0)
parsed_chan = cmd[3]
if not self.Base.is_valid_ip(cmd[7]): if self.ModConfig.reputation == 1:
return None parsed_UID = cmd[4]
pattern = fr'^:[@|%|\+|~|\*]*'
parsed_UID = re.sub(pattern, '', parsed_UID)
# if self.ModConfig.local_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP: get_reputation = self.reputation_get_Reputation(parsed_UID)
# self.localscan_remote_ip.append(cmd[7])
# if self.ModConfig.psutil_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP: self.Irc.send2socket(f":{service_id} MODE {parsed_chan} +b ~security-group:unknown-users")
# self.psutil_remote_ip.append(cmd[7]) self.Irc.send2socket(f":{service_id} MODE {parsed_chan} +eee ~security-group:webirc-users ~security-group:known-users ~security-group:websocket-users")
# if self.ModConfig.abuseipdb_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP: if not get_reputation is None:
# self.abuseipdb_remote_ip.append(cmd[7]) isWebirc = get_reputation.isWebirc
# if self.ModConfig.freeipapi_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP: if not isWebirc:
# self.freeipapi_remote_ip.append(cmd[7]) if parsed_chan != self.Config.SALON_JAIL:
self.Irc.send2socket(f":{service_id} SAPART {get_reputation.nickname} {parsed_chan}")
# if self.ModConfig.cloudfilt_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP: if self.ModConfig.reputation_ban_all_chan == 1 and not isWebirc:
# self.cloudfilt_remote_ip.append(cmd[7]) if parsed_chan != self.Config.SALON_JAIL:
self.Irc.send2socket(f":{service_id} MODE {parsed_chan} +b {get_reputation.nickname}!*@*")
self.Irc.send2socket(f":{service_id} KICK {parsed_chan} {get_reputation.nickname}")
case 'NICK': self.Logs.debug(f'SJOIN parsed_uid : {parsed_UID}')
# :0010BS24L NICK [NEWNICK] 1697917711 except KeyError as ke:
# Changement de nickname self.Logs.error(f"key error SJOIN : {ke}")
try:
cmd.pop(0)
uid = str(cmd[0]).replace(':','')
get_Reputation = self.reputation_get_Reputation(uid)
jail_salon = self.Config.SALON_JAIL
service_id = self.Config.SERVICE_ID
if get_Reputation is None: case 'SLOG':
self.Logs.debug(f'This UID: {uid} is not listed in the reputation dataclass') # self.Base.scan_ports(cmd[7])
return None cmd.pop(0)
# Update the new nickname if not self.Base.is_valid_ip(cmd[7]):
oldnick = get_Reputation.nickname return None
newnickname = cmd[2]
get_Reputation.nickname = newnickname
# If ban in all channel is ON then unban old nickname an ban the new nickname # if self.ModConfig.local_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP:
if self.ModConfig.reputation_ban_all_chan == 1: # self.localscan_remote_ip.append(cmd[7])
for chan in self.Channel.UID_CHANNEL_DB:
if chan.name != jail_salon:
self.Irc.send2socket(f":{service_id} MODE {chan.name} -b {oldnick}!*@*")
self.Irc.send2socket(f":{service_id} MODE {chan.name} +b {newnickname}!*@*")
except KeyError as ke: # if self.ModConfig.psutil_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP:
self.Logs.error(f'cmd - NICK - KeyError: {ke}') # self.psutil_remote_ip.append(cmd[7])
case 'QUIT': # if self.ModConfig.abuseipdb_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP:
# :001N1WD7L QUIT :Quit: free_znc_1 # self.abuseipdb_remote_ip.append(cmd[7])
# if self.ModConfig.freeipapi_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP:
# self.freeipapi_remote_ip.append(cmd[7])
# if self.ModConfig.cloudfilt_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP:
# self.cloudfilt_remote_ip.append(cmd[7])
case 'NICK':
# :0010BS24L NICK [NEWNICK] 1697917711
# Changement de nickname
try:
cmd.pop(0) cmd.pop(0)
ban_all_chan = self.Base.int_if_possible(self.ModConfig.reputation_ban_all_chan) uid = str(cmd[0]).replace(':','')
user_id = str(cmd[0]).replace(':','') get_Reputation = self.reputation_get_Reputation(uid)
final_UID = user_id
jail_salon = self.Config.SALON_JAIL jail_salon = self.Config.SALON_JAIL
service_id = self.Config.SERVICE_ID service_id = self.Config.SERVICE_ID
get_user_reputation = self.reputation_get_Reputation(final_UID) if get_Reputation is None:
self.Logs.debug(f'This UID: {uid} is not listed in the reputation dataclass')
return None
if not get_user_reputation is None: # Update the new nickname
final_nickname = get_user_reputation.nickname oldnick = get_Reputation.nickname
newnickname = cmd[2]
get_Reputation.nickname = newnickname
# If ban in all channel is ON then unban old nickname an ban the new nickname
if self.ModConfig.reputation_ban_all_chan == 1:
for chan in self.Channel.UID_CHANNEL_DB: for chan in self.Channel.UID_CHANNEL_DB:
if chan.name != jail_salon and ban_all_chan == 1: if chan.name != jail_salon:
self.Irc.send2socket(f":{service_id} MODE {chan.name} -b {final_nickname}!*@*") self.Irc.send2socket(f":{service_id} MODE {chan.name} -b {oldnick}!*@*")
self.reputation_delete(final_UID) self.Irc.send2socket(f":{service_id} MODE {chan.name} +b {newnickname}!*@*")
except KeyError as ke: except KeyError as ke:
self.Logs.error(f"{ke} / {cmd} / length {str(len(cmd))}") self.Logs.error(f'cmd - NICK - KeyError: {ke}')
except IndexError as ie:
self.Logs.error(f"{ie} / {cmd} / length {str(len(cmd))}") case 'QUIT':
except Exception as err: # :001N1WD7L QUIT :Quit: free_znc_1
self.Logs.error(f"General Error: {err}") cmd.pop(0)
ban_all_chan = self.Base.int_if_possible(self.ModConfig.reputation_ban_all_chan)
user_id = str(cmd[0]).replace(':','')
final_UID = user_id
jail_salon = self.Config.SALON_JAIL
service_id = self.Config.SERVICE_ID
get_user_reputation = self.reputation_get_Reputation(final_UID)
if not get_user_reputation is 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:
self.Irc.send2socket(f":{service_id} MODE {chan.name} -b {final_nickname}!*@*")
self.reputation_delete(final_UID)
def _hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None: def _hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None:

View File

@@ -10,7 +10,8 @@ class Jsonrpc():
class ModConfModel: class ModConfModel:
"""The Model containing the module parameters """The Model containing the module parameters
""" """
jsonrpc: int = 0 param_exemple1: str
param_exemple2: int
def __init__(self, ircInstance:Irc) -> None: def __init__(self, ircInstance:Irc) -> None:
@@ -58,41 +59,16 @@ class Jsonrpc():
self.__load_module_configuration() self.__load_module_configuration()
# End of mandatory methods you can start your customization # # End of mandatory methods you can start your customization #
# self.UnrealIrcdRpcLive: Live = Live( self.UnrealIrcdRpcLive: Live = None
# 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,
username=self.Config.JSONRPC_USER,
password=self.Config.JSONRPC_PASSWORD,
callback_object_instance=self,
callback_method_name='callback_sent_to_irc',
debug_level=10
)
self.Rpc: Loader = Loader( self.Rpc: Loader = Loader(
req_method=self.Config.JSONRPC_METHOD, req_method=self.Config.JSONRPC_METHOD,
url=self.Config.JSONRPC_URL, url=self.Config.JSONRPC_URL,
username=self.Config.JSONRPC_USER, username=self.Config.JSONRPC_USER,
password=self.Config.JSONRPC_PASSWORD password=self.Config.JSONRPC_PASSWORD
) )
self.subscribed = False
if self.Rpc.Error.code != 0: if self.Rpc.Error.code != 0:
self.Irc.sendPrivMsg(f"[{self.Config.COLORS.red}ERROR{self.Config.COLORS.nogc}] {self.Rpc.Error.message}", self.Config.SERVICE_CHANLOG) self.Irc.sendPrivMsg(f"[{self.Config.COLORS.red}ERROR{self.Config.COLORS.nogc}] {self.Rpc.Error.message}", self.Config.SERVICE_CHANLOG)
if self.UnrealIrcdRpcLive.Error.code != 0:
self.Irc.sendPrivMsg(f"[{self.Config.COLORS.red}ERROR{self.Config.COLORS.nogc}] {self.UnrealIrcdRpcLive.Error.message}", self.Config.SERVICE_CHANLOG)
if self.ModConfig.jsonrpc == 1:
self.Base.create_thread(self.thread_start_jsonrpc, run_once=True)
return None return None
def __set_commands(self, commands:dict[int, list[str]]) -> None: def __set_commands(self, commands:dict[int, list[str]]) -> None:
@@ -133,30 +109,17 @@ class Jsonrpc():
dnickname = self.Config.SERVICE_NICKNAME dnickname = self.Config.SERVICE_NICKNAME
dchanlog = self.Config.SERVICE_CHANLOG dchanlog = self.Config.SERVICE_CHANLOG
green = self.Config.COLORS.green
nogc = self.Config.COLORS.nogc
bold = self.Config.COLORS.bold
red = self.Config.COLORS.red
if json_response.result == True: self.Irc.sendPrivMsg(msg=json_response, channel=dchanlog)
self.Irc.sendPrivMsg(msg=f"[{bold}{green}JSONRPC{nogc}{bold}] Event activated", channel=dchanlog)
return None
level = json_response.result.level
subsystem = json_response.result.subsystem
event_id = json_response.result.event_id
log_source = json_response.result.log_source
msg = json_response.result.msg
build_msg = f"{green}{log_source}{nogc}: [{bold}{level}{bold}] {subsystem}.{event_id} - {msg}"
self.Irc.sendPrivMsg(msg=build_msg, channel=dchanlog)
def thread_start_jsonrpc(self): def thread_start_jsonrpc(self):
self.UnrealIrcdRpcLive = Live(path_to_socket_file=self.Config.JSONRPC_PATH_TO_SOCKET_FILE,
callback_object_instance=self,
callback_method_name='callback_sent_to_irc'
)
if self.UnrealIrcdRpcLive.Error.code == 0: if self.UnrealIrcdRpcLive.Error.code == 0:
self.UnrealIrcdRpcLive.subscribe(["all"]) self.UnrealIrcdRpcLive.subscribe()
self.subscribed = True
else: else:
self.Irc.sendPrivMsg(f"[{self.Config.COLORS.red}ERROR{self.Config.COLORS.nogc}] {self.UnrealIrcdRpcLive.Error.message}", self.Config.SERVICE_CHANLOG) self.Irc.sendPrivMsg(f"[{self.Config.COLORS.red}ERROR{self.Config.COLORS.nogc}] {self.UnrealIrcdRpcLive.Error.message}", self.Config.SERVICE_CHANLOG)
@@ -165,10 +128,10 @@ class Jsonrpc():
""" """
try: try:
# Build the default configuration model (Mandatory) # Build the default configuration model (Mandatory)
self.ModConfig = self.ModConfModel(jsonrpc=0) self.ModConfig = self.ModConfModel(param_exemple1='param value 1', param_exemple2=1)
# Sync the configuration with core configuration (Mandatory) # Sync the configuration with core configuration (Mandatory)
self.Base.db_sync_core_config(self.module_name, self.ModConfig) #self.Base.db_sync_core_config(self.module_name, self.ModConfig)
return None return None
@@ -185,8 +148,7 @@ class Jsonrpc():
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:
if self.UnrealIrcdRpcLive.Error.code != -1: self.UnrealIrcdRpcLive.unsubscribe()
self.UnrealIrcdRpcLive.unsubscribe()
return None return None
def cmd(self, data:list) -> None: def cmd(self, data:list) -> None:
@@ -197,7 +159,6 @@ class Jsonrpc():
command = str(cmd[0]).lower() command = str(cmd[0]).lower()
dnickname = self.Config.SERVICE_NICKNAME dnickname = self.Config.SERVICE_NICKNAME
dchannel = self.Config.SERVICE_CHANLOG
fromuser = user fromuser = user
fromchannel = str(channel) if not channel is None else None fromchannel = str(channel) if not channel is None else None
@@ -214,19 +175,10 @@ class Jsonrpc():
match option: match option:
case 'on': case 'on':
for thread in self.Base.running_threads:
if thread.getName() == 'thread_start_jsonrpc':
if thread.is_alive():
self.Irc.sendPrivMsg(f"Thread {thread.getName()} is running", dchannel)
else:
self.Irc.sendPrivMsg(f"Thread {thread.getName()} is not running, wait untill the process will be cleaned up", dchannel)
self.Base.create_thread(self.thread_start_jsonrpc, run_once=True) self.Base.create_thread(self.thread_start_jsonrpc, run_once=True)
self.__update_configuration('jsonrpc', 1)
case 'off': case 'off':
self.UnrealIrcdRpcLive.unsubscribe() self.UnrealIrcdRpcLive.unsubscribe()
self.__update_configuration('jsonrpc', 0)
except IndexError as ie: except IndexError as ie:
self.Logs.error(ie) self.Logs.error(ie)
@@ -246,39 +198,36 @@ class Jsonrpc():
if uid_to_get is None: if uid_to_get is None:
return None return None
rpc = self.Rpc rpc = Loader(
req_method=self.Config.JSONRPC_METHOD,
url=self.Config.JSONRPC_URL,
username=self.Config.JSONRPC_USER,
password=self.Config.JSONRPC_PASSWORD
)
UserInfo = rpc.User.get(uid_to_get) UserInfo = rpc.User.get(uid_to_get)
if rpc.Error.code != 0: if rpc.Error.code != 0:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :{rpc.Error.message}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :{rpc.Error.message}')
return None return None
chan_list = []
for chan in UserInfo.user.channels:
chan_list.append(chan.name)
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :UID : {UserInfo.id}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :UID : {UserInfo.id}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :NICKNAME : {UserInfo.name}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :NICKNAME : {UserInfo.name}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :USERNAME : {UserInfo.user.username}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :USERNAME : {UserInfo.username}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :REALNAME : {UserInfo.user.realname}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :REALNAME : {UserInfo.realname}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :MODES : {UserInfo.user.modes}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :CHANNELS : {UserInfo.channels}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :CHANNELS : {chan_list}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :SECURITY GROUP : {UserInfo.security_groups}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :SECURITY GROUP : {UserInfo.user.security_groups}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :REPUTATION : {UserInfo.reputation}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :REPUTATION : {UserInfo.user.reputation}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :IP : {UserInfo.ip}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :IP : {UserInfo.ip}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :COUNTRY CODE : {UserInfo.geoip.country_code}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :COUNTRY CODE : {UserInfo.country_code}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :ASN : {UserInfo.geoip.asn}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :ASN : {UserInfo.asn}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :ASNAME : {UserInfo.geoip.asname}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :ASNAME : {UserInfo.asname}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :CLOAKED HOST : {UserInfo.user.cloakedhost}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :CLOAKED HOST : {UserInfo.cloakedhost}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :HOSTNAME : {UserInfo.hostname}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :HOSTNAME : {UserInfo.hostname}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :VHOST : {UserInfo.user.vhost}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :VHOST : {UserInfo.vhost}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :CLIENT PORT : {UserInfo.client_port}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :CLIENT PORT : {UserInfo.client_port}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :SERVER PORT : {UserInfo.server_port}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :SERVER PORT : {UserInfo.server_port}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :CERTFP : {UserInfo.tls.certfp}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :CIPHER : {UserInfo.tls.cipher}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :IDLE SINCE : {UserInfo.idle_since}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :IDLE SINCE : {UserInfo.idle_since}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :CONNECTED SINCE : {UserInfo.connected_since}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :CONNECTED SINCE : {UserInfo.connected_since}')

View File

@@ -124,16 +124,8 @@ class Test():
return None return None
def cmd(self, data:list) -> None: def cmd(self, data:list) -> None:
try:
cmd = list(data).copy()
return None return None
except KeyError as ke:
self.Base.logs.error(f"Key Error: {ke}")
except IndexError as ie:
self.Base.logs.error(f"{ie} / {cmd} / length {str(len(cmd))}")
except Exception as err:
self.Base.logs.error(f"General Error: {err}")
def _hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None: def _hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None:

View File

@@ -242,16 +242,15 @@ class Votekick():
return None return None
def cmd(self, data:list) -> None: def cmd(self, data:list) -> None:
try: cmd = list(data).copy()
cmd = list(data).copy()
return None
except KeyError as ke: match cmd[2]:
self.Base.logs.error(f"Key Error: {ke}") case 'SJOIN':
except IndexError as ie: pass
self.Base.logs.error(f"{ie} / {cmd} / length {str(len(cmd))}") case _:
except Exception as err: pass
self.Base.logs.error(f"General Error: {err}")
return None
def _hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None: def _hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None:
# cmd is the command starting from the user command # cmd is the command starting from the user command

View File

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