cleaning old folder

This commit is contained in:
Shadow15510 2023-06-11 14:30:46 +02:00
parent afa3e1859f
commit de1ab039be
7 changed files with 0 additions and 456 deletions

View File

@ -1,130 +0,0 @@
from functools import wraps
import logging
from irc_bot_api.secrets import USER, PASSWORD
from irc_bot_api.irc import IRC
from irc_bot_api.v5 import V5
PREFIX = ""
def command(name, event=None):
"""Decorate a function and return a Command instance."""
def decorator(func):
desc = name
if func.__doc__:
desc = func.__doc__
return Command(
name=name,
desc=desc,
func=func,
event=event
)
return decorator
class Command:
def __init__(self, name, desc, func, event=None):
self.name = name
self.desc = desc
self.func = func
if not event:
self.event = lambda m: m.text.startswith(PREFIX + name)
else:
self.event = event
self.cmnd_pack = None
def __call__(self, msg):
return self.func(self.cmnd_pack, msg)
class CommandsPack:
def __init__(self, bot):
self.bot = bot
class Bot:
"""Run the connexion between IRC's server and V5 one.
Attributes
----------
irc : IRC, public
IRC wrapper which handle communication with IRC server.
v5 : V5, public
V5 wrapper which handle communication with V5 server.
channels : list, public
The channels the bot will listen.
Methods
-------
start : NoneType, public
Runs the bot and connects it to IRC and V5 servers.
"""
def __init__(self, irc_params: tuple, v5_params: tuple, channels: list, prefix: str=""):
"""Initialize the Bot instance.
Parameters
----------
irc_params : tuple
Contains the IRC server informations (host, port)
v5_params : tuple
Contains the V5 server informations (host, port)
channels : list
Contains the names of the channels on which the bot will connect.
prefix : str, optionnal
The prefix on which the bot will react.
"""
global PREFIX
PREFIX = prefix
self.irc = IRC(*irc_params)
self.v5 = V5(v5_params, self.irc)
self.channels = channels
def start(self):
"""Starts the bot and connect it to the given IRC and V5 servers."""
# Start IRC
self.irc.start(USER, PASSWORD)
# Join channels
for channel in self.channels:
self.irc.join(channel)
# Start V5 hadndler
self.v5.start()
# Run IRC
self.irc.run()
def add_help(self):
help_callback = Command(
"aide",
"Affiche la liste des commandes disponibles.",
help_cmnd
)
help_callback.cmnd_pack = self
self.irc.callbacks.append(help_callback)
def add_commands_pack(self, commands_pack):
"""Add a package of commands to the bot.
Parameters
----------
commands_pack : CommandsPack
A commands pack which contains command's instances.
"""
cmnd_pack = commands_pack(self)
for cmnd_name in dir(commands_pack):
if not cmnd_name.startswith("__") and not cmnd_name.endswith("__"):
cmnd = getattr(commands_pack, cmnd_name)
cmnd.cmnd_pack = cmnd_pack
self.irc.callbacks.append(cmnd)
def help_cmnd(bot, msg):
"""Documentation des fonctions disponibles."""
bot.irc.send(msg.to, f"Aide des commandes")
for cmnd in bot.irc.callbacks:
bot.irc.send(msg.to, f" {cmnd.name} : {cmnd.desc}")

View File

@ -1,234 +0,0 @@
"""
irc (GLaDOS)
============
Description
-----------
Manage the IRC layer of GLaDOS.
"""
import logging
import re
import socket
import ssl
from functools import wraps
from queue import Queue
from threading import Thread
class IRC:
"""Manage connexion to an IRC server, authentication and callbacks.
Attributes
----------
connected : bool, public
If the bot is connected to an IRC server or not.
callbacks : list, public
List of the registred callbacks.
socket : ssl.SSLSocket, private
The IRC's socket.
inbox : Queue, private
Queue of the incomming messages.
handler : Thread, private
Methods
-------
start : NoneType, public
Starts the IRC layer and manage authentication.
run : NoneType, public
Mainloop, allows to handle public messages.
send : NoneType, public
Sends a message to a given channel.
receive : Message, public
Same as ``run`` for private messages.
join : NoneType, public
Allows to join a given channel.
on : function, public
Add a callback on a given message.
handle : NoneType, private
Handles the ping and store incoming messages into the inbox attribute.
send : NoneType, private
Send message to a target.
recv : str, private
Get the oldest incoming message and returns it.
waitfor : str, private
Wait for a raw message that matches the given condition.
"""
def __init__(self, host: str, port: int):
"""Initialize an IRC wrapper.
Parameters
----------
host : str
The adress of the IRC server.
port : int
The port of the IRC server.
"""
# Public attributes
self.connected = False # Simple lock
self.callbacks = []
# Private attributes
self.__socket = ssl.create_default_context().wrap_socket(
socket.create_connection((host, port)),
server_hostname=host
)
self.__inbox = Queue()
self.__handler = Thread(target=self.__handle)
# Public methods
def start(self, nick: str, password: str):
"""Start the IRC layer. Manage authentication as well.
Parameters
----------
nick : str
The username for login and nickname once connected.
password : str
The password for authentification.
"""
self.__handler.start()
self.__send(f"USER {nick} * * :{nick}")
self.__send(f"NICK {nick}")
self.__waitfor(lambda m: "NOTICE" in m and "/AUTH" in m)
self.__send(f"AUTH {nick}:{password}")
self.__waitfor(lambda m: "You are now logged in" in m)
self.connected = True
def run(self):
"""Handle new messages."""
while True:
message = self.receive()
logging.info("received %s", message)
if message is not None:
for callback in self.callbacks:
if callback.event(message):
logging.info("matched %s", callback.name)
callback(message)
def send(self, target: str, message: str):
"""Send a message to the specified target (channel or user).
Parameters
----------
target : str
The target of the message. It can be a channel or user (private message).
message : str
The content of the message to send.
"""
self.__send(f"PRIVMSG {target} :{message}")
def receive(self):
"""Receive a private message.
Returns
-------
msg : Message
The incoming processed private message.
"""
while True:
message = self.__inbox.get()
if " PRIVMSG " in message:
msg = Message(message)
if msg:
return msg
def join(self, channel: str):
"""Join a channel.
Parameters
----------
channel : str
The name of the channel to join.
"""
self.__send(f"JOIN {channel}")
logging.info("joined %s", channel)
# Private methods
def __handle(self):
"""Handle raw messages from irc and manage ping."""
while True:
# Get incoming messages
data = self.__socket.recv(4096).decode()
# Split multiple lines
for msg in data.split('\r\n'):
# Manage ping
if msg.startswith("PING"):
self.__send(msg.replace("PING", "PONG"))
# Or add a new message to inbox
elif len(msg):
self.__inbox.put(msg)
logging.debug("received %s", msg)
def __send(self, raw: str):
"""Wrap and encode raw message to send.
Parameters
----------
raw : str
The raw message to send.
"""
self.__socket.send(f"{raw}\r\n".encode())
def __waitfor(self, condition):
"""Wait for a raw message that matches the condition.
Parameters
----------
condition : function
``condition`` is a function that must taking a raw message in parameter and returns a
boolean.
Returns
-------
msg : str
The last message received that doesn't match the condition.
"""
msg = self.__inbox.get()
while not condition(msg):
msg = self.__inbox.get()
return msg
class Message:
"""Parse the raw message in three fields : author, the channel, and text.
Attributes
----------
pattern : re.Pattern, public
The message parsing pattern.
author : str, public
The message's author.
to : str, public
The message's origin (channel or DM).
text : str, public
The message's content.
"""
pattern = re.compile(
r"^:(?P<author>[\w.~|\-\[\]]+)(?:!(?P<host>\S+))? PRIVMSG (?P<to>\S+) :(?P<text>.+)"
)
def __init__(self, raw: str):
match = re.search(Message.pattern, raw)
if match:
self.author = match.group("author")
self.to = match.group("to")
self.text = match.group("text")
logging.debug("sucessfully parsed %s into %s", raw, self.__str__())
else:
self.author = ""
self.to = ""
self.text = ""
logging.warning("failed to parse %s into valid message", raw)
def __str__(self):
return f"{self.author} to {self.to}: {self.text}"

View File

@ -1,92 +0,0 @@
"""
v5 (GLaDOS)
===========
Description
-----------
Manage the V5 layer of GLaDOS.
"""
import logging
import socket
from threading import Thread
from functools import wraps
class V5:
"""Manage connexion beetween the bot and the V5 server, and manage callbacks.
Attributes
----------
irc : irc.IRC, public
An IRC instance.
sock : ssl.SSLSocket, private
The V5 socket.
handler : Thread, private
callbacks : list, private
List of the registred callbacks.
Methods
-------
start : NoneType, public
Start v5 handler.
on : function, public
Add a callback to the v5 handler.
handle : NoneType, private
Handle the incoming messages and callbacks.
"""
def __init__(self, v5_params: tuple, irc):
"""Initialize V5 handle.
Parameters
----------
v5 : tuple
The information on V5 server (host, port).
irc : irc.IRC
An initialized IRC instance.
"""
self.irc = irc
self.__sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
self.__sock.bind(v5_params)
self.__handler = Thread(target=self.__handle)
self.__callbacks = []
def start(self):
"""Start v5 handler."""
self.__handler.start()
logging.info("started")
def on(self, event):
"""Adds a callback to the v5 handler.
Parameters
----------
event : function
``event`` is a function taking in parameter a list of channels and a string, and return
``True`` if the callback should be executed.
"""
def callback(func):
@wraps(func)
def wrapper(channels, message):
func(channels, message)
self.__callbacks.append((event, wrapper))
return wrapper
return callback
def __handle(self):
"""Handle the incoming messages and callbacks."""
while True:
data, addr = self.__sock.recvfrom(4096)
data = data.decode()
logging.debug("received %s", data)
channels, message = data.split(":", 1)
channels = channels.split(" ")
for event, callback in self.__callbacks:
if event(channels, message):
logging.info("passed %s", event.__name__)
callback(channels, message)