Testing configuration changes/updates

This commit is contained in:
Hash Borgir 2024-02-13 22:39:17 -07:00
parent aa7e76e653
commit 2277dd1b90
17 changed files with 525 additions and 20 deletions

11
funguy.conf Normal file
View File

@ -0,0 +1,11 @@
[simplematrixbotlib.config]
timeout = 65536
join_on_invite = true
encryption_enabled = false
emoji_verify = false
ignore_unverified_devices = true
store_path = "./store/"
allowlist = []
blocklist = []
admin_user = "@hashborgir:mozilla.org"
prefix = "!!"

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python
# bot.py
# funguy.py
import os
import logging
@ -8,26 +8,12 @@ import simplematrixbotlib as botlib
from dotenv import load_dotenv
import time
import sys
# Load environment variables from .env file
load_dotenv()
# Bot configuration settings
MATRIX_URL = os.getenv("MATRIX_URL")
MATRIX_USER = os.getenv("MATRIX_USER")
MATRIX_PASS = os.getenv("MATRIX_PASS")
ADMIN_USER = "@hashborgir:mozilla.org"
PREFIX = '!'
creds = botlib.Creds(MATRIX_URL, MATRIX_USER, MATRIX_PASS)
bot = botlib.Bot(creds)
from plugins.config import FunguyConfig
# Setup logging
logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', level=logging.INFO)
# Load plugins
# Load plugins (defined before plugin load/reload functions)
PLUGINS_DIR = "plugins"
PLUGINS = {}
@ -51,19 +37,53 @@ def reload_plugins():
del sys.modules[plugin_name]
load_plugins()
def rehash_config(config):
del config
config = FunguyConfig()
# Load environment variables from .env file
load_dotenv()
# Load plugins
load_plugins()
# Bot configuration settings
MATRIX_URL = os.getenv("MATRIX_URL")
MATRIX_USER = os.getenv("MATRIX_USER")
MATRIX_PASS = os.getenv("MATRIX_PASS")
# Get credentials from env
creds = botlib.Creds(MATRIX_URL, MATRIX_USER, MATRIX_PASS)
# Bot configuration
config = FunguyConfig()
bot = botlib.Bot(creds, config)
PREFIX = config.prefix
@bot.listener.on_message_event
async def handle_commands(room, message):
match = botlib.MessageMatch(room, message, bot, PREFIX)
if match.is_not_from_this_bot() and match.prefix() and match.command("reload"):
if str(message.sender) == ADMIN_USER:
if str(message.sender) == config.admin_user:
reload_plugins()
await bot.api.send_text_message(room.room_id, "Plugins reloaded successfully")
else:
await bot.api.send_text_message(room.room_id, "You are not authorized to reload plugins.")
for plugin_name, plugin_module in PLUGINS.items():
await plugin_module.handle_command(room, message, bot, PREFIX)
await plugin_module.handle_command(room, message, bot, PREFIX, config)
if match.is_not_from_this_bot() and match.prefix() and match.command("rehash"):
if str(message.sender) == config.admin_user:
rehash_config(config)
await bot.api.send_text_message(room.room_id, "Config rehashed")
else:
await bot.api.send_text_message(room.room_id, "You are not authorized to reload plugins.")
bot.run()

130
plugins/config.py Normal file
View File

@ -0,0 +1,130 @@
# plugins/config.py
import os
import logging
import simplematrixbotlib as botlib
from dataclasses import dataclass
@dataclass
class FunguyConfig(botlib.Config):
"""
Custom configuration class for the Funguy bot.
Extends the base Config class to provide additional configuration options.
Args:
config_file (str): Path to the configuration file.
"""
def __init__(self, config_file="funguy.conf"):
super().__init__()
# Load configuration from file
self.load_toml(config_file)
logging.info("Loaded configuration from funguy.conf")
_admin_user: str = ""
_prefix: str = ""
# Define getters and setters for custom configuration options
@property
def admin_user(self):
return self._admin_user
@admin_user.setter
def admin_user(self, value):
self._admin_user = value
@property
def prefix(self):
return self._prefix
@prefix.setter
def prefix(self, value):
self._prefix = value
# Method to load configuration from file
def load_config(self, config_file):
"""
Load configuration options from a TOML file.
Args:
config_file (str): Path to the configuration file.
Returns:
None
"""
self.__init__()
logging.info("Loaded configuration from funguy.conf")
# Method to save configuration to file
def save_config(self, config_file):
"""
Save configuration options to a TOML file.
Args:
config_file (str): Path to the configuration file.
Returns:
None
"""
self.save_toml(config_file)
logging.info("Saved configuration to funguy.conf")
async def handle_command(room, message, bot, PREFIX, config):
"""
Function to handle commands related to bot configuration.
Args:
room (Room): The Matrix room where the command was invoked.
message (RoomMessage): The message object containing the command.
bot (Bot): The bot instance.
PREFIX (str): The bot command prefix.
config (FunguyConfig): The bot configuration instance.
Returns:
None
"""
match = botlib.MessageMatch(room, message, bot, PREFIX)
if match.is_not_from_this_bot() and match.prefix() and match.command("set"):
args = match.args()
if len(args) != 2:
await bot.api.send_text_message(room.room_id, "Usage: !set <config_option> <value>")
return
option, value = args
if option == "admin_user":
config.admin_user = value
await bot.api.send_text_message(room.room_id, f"Admin user set to {value}")
elif option == "prefix":
config.prefix = value
await bot.api.send_text_message(room.room_id, f"Prefix set to {value}")
else:
await bot.api.send_text_message(room.room_id, "Invalid configuration option")
elif match.is_not_from_this_bot() and match.prefix() and match.command("get"):
args = match.args()
if len(args) != 1:
await bot.api.send_text_message(room.room_id, "Usage: !get <config_option>")
return
option = args[0]
if option == "admin_user":
await bot.api.send_text_message(room.room_id, f"Admin user: {config.admin_user}")
elif option == "prefix":
await bot.api.send_text_message(room.room_id, f"Prefix: {config.prefix}")
else:
await bot.api.send_text_message(room.room_id, "Invalid configuration option")
elif match.is_not_from_this_bot() and match.prefix() and match.command("save"):
config.save_config("funguy.conf")
config.load_config("funguy.conf")
await bot.api.send_text_message(room.room_id, "Configuration saved & reloaded")
elif match.is_not_from_this_bot() and match.prefix() and match.command("show"):
admin_user = config.admin_user
prefix = config.prefix
await bot.api.send_text_message(room.room_id, f"Admin user: {admin_user}, Prefix: {prefix}")
elif match.is_not_from_this_bot() and match.prefix() and match.command("reset"):
config.admin_user = ""
config.prefix = "!"
await bot.api.send_text_message(room.room_id, "Configuration reset")

View File

@ -1,10 +1,14 @@
"""
This plugin provides a command to get the current date
"""
# plugins/date.py
import datetime
import logging
import simplematrixbotlib as botlib
async def handle_command(room, message, bot, PREFIX):
async def handle_command(room, message, bot, PREFIX, config):
"""
Function to handle the !date command.

View File

@ -1,3 +1,6 @@
"""
This plugin provides a command to interact with the music knowledge A.I.
"""
# plugins/ai-music.py
import logging

View File

@ -1,3 +1,7 @@
"""
This plugin provides a command to interact with the LLM for Tech/IT/Security/Selfhosting/Programming etc.
"""
# plugins/ai-tech.py
import logging

View File

@ -1,3 +1,7 @@
"""
This plugin provides a command to display the list of available commands and their descriptions.
"""
# plugins/commands.py
import logging

131
plugins/disabled/config.py Normal file
View File

@ -0,0 +1,131 @@
# plugins/config.py
import os
import logging
import simplematrixbotlib as botlib
class FunguyConfig(botlib.Config):
"""
Custom configuration class for the Funguy bot.
Extends the base Config class to provide additional configuration options.
Args:
config_file (str): Path to the configuration file.
"""
def __init__(self, config_file):
super().__init__()
# Define custom configuration options here
self.admin_user = ""
self.prefix = "!"
# Load configuration from file
self.load_toml(config_file)
logging.info("Loaded configuration from funguy.conf")
# Define getters and setters for custom configuration options
@property
def admin_user(self):
return self._admin_user
@admin_user.setter
def admin_user(self, value):
self._admin_user = value
@property
def prefix(self):
return self._prefix
@prefix.setter
def prefix(self, value):
self._prefix = value
# Method to load configuration from file
def load_config(self, config_file):
"""
Load configuration options from a TOML file.
Args:
config_file (str): Path to the configuration file.
Returns:
None
"""
self.load_toml(config_file)
logging.info("Loaded configuration from funguy.conf")
# Method to save configuration to file
def save_config(self, config_file):
"""
Save configuration options to a TOML file.
Args:
config_file (str): Path to the configuration file.
Returns:
None
"""
self.save_toml(config_file)
logging.info("Saved configuration to funguy.conf")
async def handle_command(room, message, bot, PREFIX, config):
"""
Function to handle commands related to bot configuration.
Args:
room (Room): The Matrix room where the command was invoked.
message (RoomMessage): The message object containing the command.
bot (Bot): The bot instance.
PREFIX (str): The bot command prefix.
config (FunguyConfig): The bot configuration instance.
Returns:
None
"""
match = botlib.MessageMatch(room, message, bot, PREFIX)
if match.is_not_from_this_bot() and match.prefix() and match.command("set"):
args = match.args()
if len(args) != 2:
await bot.api.send_text_message(room.room_id, "Usage: !set <config_option> <value>")
return
option, value = args
if option == "admin_user":
config.admin_user = value
await bot.api.send_text_message(room.room_id, f"Admin user set to {value}")
elif option == "prefix":
config.prefix = value
await bot.api.send_text_message(room.room_id, f"Prefix set to {value}")
else:
await bot.api.send_text_message(room.room_id, "Invalid configuration option")
elif match.is_not_from_this_bot() and match.prefix() and match.command("get"):
args = match.args()
if len(args) != 1:
await bot.api.send_text_message(room.room_id, "Usage: !get <config_option>")
return
option = args[0]
if option == "admin_user":
await bot.api.send_text_message(room.room_id, f"Admin user: {config.admin_user}")
elif option == "prefix":
await bot.api.send_text_message(room.room_id, f"Prefix: {config.prefix}")
else:
await bot.api.send_text_message(room.room_id, "Invalid configuration option")
elif match.is_not_from_this_bot() and match.prefix() and match.command("save"):
config.save_config("funguy.conf")
await bot.api.send_text_message(room.room_id, "Configuration saved")
elif match.is_not_from_this_bot() and match.prefix() and match.command("load"):
config.load_config("funguy.conf")
await bot.api.send_text_message(room.room_id, "Configuration loaded")
elif match.is_not_from_this_bot() and match.prefix() and match.command("show"):
admin_user = config.admin_user
prefix = config.prefix
await bot.api.send_text_message(room.room_id, f"Admin user: {admin_user}, Prefix: {prefix}")
elif match.is_not_from_this_bot() and match.prefix() and match.command("reset"):
config.admin_user = ""
config.prefix = "!"
await bot.api.send_text_message(room.room_id, "Configuration reset")

33
plugins/disabled/date.py Normal file
View File

@ -0,0 +1,33 @@
"""
This plugin provides a command to get the current date
"""
# plugins/date.py
import datetime
import logging
import simplematrixbotlib as botlib
async def handle_command(room, message, bot, config):
PREFIX = config.prefix
"""
Function to handle the !date command.
Args:
room (Room): The Matrix room where the command was invoked.
message (RoomMessage): The message object containing the command.
Returns:
None
"""
match = botlib.MessageMatch(room, message, bot, PREFIX)
if match.is_not_from_this_bot() and match.prefix() and match.command("date"):
logging.info("Fetching current date and time")
current_datetime = datetime.datetime.now()
day_of_week = current_datetime.strftime("%A")
month = current_datetime.strftime("%B")
year = current_datetime.strftime("%Y")
time = current_datetime.strftime("%I:%M:%S %p")
date_message = f"📅 Today is **{day_of_week}** of **{month}** in **{year}**. The time is **⏰ {time}**"
await bot.api.send_markdown_message(room.room_id, date_message)
logging.info("Sent current date and time to the room")

View File

@ -1,3 +1,6 @@
"""
This plugin provides a command to get a random fortune message.
"""
# plugins/fortune.py
import subprocess

View File

@ -1,3 +1,7 @@
"""
This plugin provides a command to check if a website or server is up.
"""
# plugins/isup.py
import logging

View File

@ -1,3 +1,8 @@
"""
This plugin provides a command to manage karma points for users.
"""
# plugins/karma.py
import sqlite3

View File

@ -0,0 +1,47 @@
"""
This plugin provides a command to load individual plugins from local or remote sources
"""
# plugins/load_plugin.py
import os
import logging
import importlib
import simplematrixbotlib as botlib
# Bot configuration settings
ADMIN_USER = "@hashborgir:mozilla.org"
PLUGINS = {}
async def load_plugin(plugin_name):
try:
module = importlib.import_module(f"{plugin_name}")
PLUGINS[plugin_name] = module
logging.info(f"Loaded plugin: {plugin_name}")
return True
except ModuleNotFoundError:
logging.error(f"Plugin module '{plugin_name}' not found")
except Exception as e:
logging.error(f"Error loading plugin '{plugin_name}': {e}")
return False
async def handle_command(room, message, bot, PREFIX):
match = botlib.MessageMatch(room, message, bot, PREFIX)
if match.is_not_from_this_bot() and match.prefix() and match.command("load"):
if str(message.sender) == ADMIN_USER:
args = match.args()
if len(args) != 1:
await bot.api.send_text_message(room.room_id, "Usage: !load <plugin>")
else:
plugin_name = args[0]
if plugin_name not in PLUGINS:
success = await load_plugin(plugin_name)
if success:
await bot.api.send_text_message(room.room_id, f"Plugin '{plugin_name}' loaded successfully")
else:
await bot.api.send_text_message(room.room_id, f"Failed to load plugin '{plugin_name}'")
else:
await bot.api.send_text_message(room.room_id, f"Plugin '{plugin_name}' is already loaded")
else:
await bot.api.send_text_message(room.room_id, "You are not authorized to load plugins.")

View File

@ -0,0 +1,57 @@
"""
This plugin provides a command to list all loaded plugins along with their descriptions.
"""
# plugins/plugins.py
import os
import sys
import logging
import simplematrixbotlib as botlib
async def handle_command(room, message, bot, PREFIX):
"""
Function to handle the !plugins command.
Args:
room (Room): The Matrix room where the command was invoked.
message (RoomMessage): The message object containing the command.
Returns:
None
"""
match = botlib.MessageMatch(room, message, bot, PREFIX)
if match.is_not_from_this_bot() and match.prefix() and match.command("plugins"):
logging.info("Received !plugins command")
plugin_descriptions = get_plugin_descriptions()
# Prepend custom string before the output
plugin_descriptions.insert(0, "# Plugins List: \n\n")
plugins_message = "\n\n".join(plugin_descriptions)
await bot.api.send_markdown_message(room.room_id, plugins_message)
logging.info("Sent plugin list to the room")
def get_plugin_descriptions():
"""
Function to get descriptions of all loaded plugin modules.
Returns:
list: A list of plugin descriptions sorted alphabetically.
"""
plugin_descriptions = []
for module_name, module in sys.modules.items():
if module_name.startswith("plugins.") and hasattr(module, "__file__"):
plugin_path = module.__file__
plugin_name = os.path.basename(plugin_path).split(".")[0]
try:
description = module.__doc__.strip().split("\n")[0]
except AttributeError:
description = "No description available"
plugin_descriptions.append(f"**[{plugin_name}.py]:** {description}")
# Sort the plugin descriptions alphabetically by plugin name
plugin_descriptions.sort()
return plugin_descriptions

View File

@ -1,3 +1,7 @@
"""
This plugin provides a command to get random SOCKS5 proxies.
"""
# plugins/proxy.py
import os

View File

@ -1,3 +1,7 @@
"""
This plugin provides a command to fetch YouTube video information from links.
"""
# plugins/youtube.py
import re

41
plugins/load_plugin.py Normal file
View File

@ -0,0 +1,41 @@
# plugins/load_plugin.py
import os
import logging
import importlib
import simplematrixbotlib as botlib
# Bot configuration settings
ADMIN_USER = "@hashborgir:mozilla.org"
PLUGINS = {}
async def load_plugin(plugin_name):
try:
module = importlib.import_module(f"plugins.{plugin_name}")
PLUGINS[plugin_name] = module
logging.info(f"Loaded plugin: {plugin_name}")
return True
except Exception as e:
logging.error(f"Error loading plugin {plugin_name}: {e}")
return False
async def handle_command(room, message, bot, PREFIX, config):
match = botlib.MessageMatch(room, message, bot, PREFIX)
if match.is_not_from_this_bot() and match.prefix() and match.command("load"):
if str(message.sender) == ADMIN_USER:
args = match.args()
if len(args) != 1:
await bot.api.send_text_message(room.room_id, "Usage: !load <plugin>")
else:
plugin_name = args[0]
if plugin_name not in PLUGINS:
success = await load_plugin(plugin_name)
if success:
await bot.api.send_text_message(room.room_id, f"Plugin '{plugin_name}' loaded successfully")
else:
await bot.api.send_text_message(room.room_id, f"Error loading plugin '{plugin_name}'")
else:
await bot.api.send_text_message(room.room_id, f"Plugin '{plugin_name}' is already loaded")
else:
await bot.api.send_text_message(room.room_id, "You are not authorized to load plugins.")