Welcome plugin added. Refactored funguy.py a bit.

This commit is contained in:
2026-04-30 01:07:29 -05:00
parent 0ae04c8656
commit 868b2b7e32
2 changed files with 143 additions and 0 deletions
+24
View File
@@ -90,6 +90,22 @@ class FunguyBot:
except Exception as e: except Exception as e:
logging.error(f"Error loading plugin {plugin_name}: {e}") # Logging error if plugin loading fails logging.error(f"Error loading plugin {plugin_name}: {e}") # Logging error if plugin loading fails
def setup_plugins(self):
"""
Method to call setup(bot) on any plugin that defines it.
This must be called AFTER self.bot is created (i.e. inside run()), so
that plugins which register custom event listeners (e.g. on_custom_event
for RoomMemberEvent) receive a valid bot instance.
"""
for plugin_name, plugin_module in self.PLUGINS.items():
if hasattr(plugin_module, "setup") and callable(plugin_module.setup):
try:
plugin_module.setup(self.bot)
logging.info(f"Setup called for plugin: {plugin_name}")
except Exception as e:
logging.error(f"Error during setup of plugin {plugin_name}: {e}")
def reload_plugins(self): def reload_plugins(self):
""" """
Method to reload all plugins. Method to reload all plugins.
@@ -100,6 +116,9 @@ class FunguyBot:
if plugin_name.startswith(self.PLUGINS_DIR + "."): if plugin_name.startswith(self.PLUGINS_DIR + "."):
del sys.modules[plugin_name] # Deleting plugin module from system modules del sys.modules[plugin_name] # Deleting plugin module from system modules
self.load_plugins() # Reloading plugins self.load_plugins() # Reloading plugins
# Re-run setup for any plugin that needs it (bot already exists at this point)
if self.bot is not None:
self.setup_plugins()
def load_config(self): def load_config(self):
""" """
@@ -223,6 +242,11 @@ class FunguyBot:
creds = botlib.Creds(MATRIX_URL, MATRIX_USER, MATRIX_PASS) # Creating credentials object creds = botlib.Creds(MATRIX_URL, MATRIX_USER, MATRIX_PASS) # Creating credentials object
self.bot = botlib.Bot(creds, self.config) # Creating bot instance self.bot = botlib.Bot(creds, self.config) # Creating bot instance
# Call setup() on any plugin that defines it, now that self.bot exists.
# This is what registers custom event listeners such as the join-event
# listener in the welcome plugin.
self.setup_plugins()
# Defining listener for message events # Defining listener for message events
@self.bot.listener.on_message_event @self.bot.listener.on_message_event
async def wrapper_handle_commands(room, message): async def wrapper_handle_commands(room, message):
+119
View File
@@ -0,0 +1,119 @@
"""
Plugin for welcoming new users to the room.
Features:
* Automatically greets users when they join the target room.
* !welcome command manually trigger the welcome message for yourself.
Restricted to room: !NXdVjDXPxXowPkrJJY:matrix.org
"""
import logging
import simplematrixbotlib as botlib
import nio
# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------
ALLOWED_ROOM_ID = "!NXdVjDXPxXowPkrJJY:matrix.org"
# ---------------------------------------------------------------------------
# Internal helpers
# ---------------------------------------------------------------------------
def _build_welcome_message(display_name: str) -> str:
"""Return the Markdown welcome message for a given display name."""
return (
f"Welcome to the room, **{display_name}**! 🎉\n\n"
"We're glad to have you here in "
"**Selfhosting | Security | Sysadmin | Homelab | Programming**!\n\n"
"To help us get to know you better:\n"
"• 🔧 **What do you selfhost?** Got any cool services running?\n"
"• 🔐 **Are you into cybersecurity?** What areas interest you most?\n"
"• 💻 **What programming languages do you use?**\n"
"• 🏠 **Tell us about your homelab setup!**\n\n"
"Feel free to introduce yourself and jump into the conversation! 🍄"
)
# ---------------------------------------------------------------------------
# Plugin setup - called by funguy.py's run() after the bot object is created
# ---------------------------------------------------------------------------
def setup(bot):
"""
Register the member-join listener.
funguy.py must call plugin_module.setup(self.bot) for each loaded plugin
(after self.bot is created) for this listener to fire. See the note in
funguy.py's run() method.
"""
@bot.listener.on_custom_event(nio.RoomMemberEvent)
async def _on_member_event(room, event):
logging.debug(
"RoomMemberEvent received: room=%s, sender=%s, membership=%s",
room.room_id, event.sender, event.membership,
)
# Only the configured room
if room.room_id != ALLOWED_ROOM_ID:
return
# Only on actual join (not invite / leave / ban)
if event.membership != "join":
return
# Ignore the bot itself
if event.sender == bot.async_client.user_id:
logging.debug("Ignoring bot's own join event")
return
# Derive a friendly display name from the Matrix ID (@name:server → name)
display_name = event.sender.split(":")[0].lstrip("@")
logging.info(
"User %s joined room %s sending welcome", event.sender, room.room_id
)
try:
await bot.api.send_markdown_message(
room.room_id, _build_welcome_message(display_name)
)
logging.info("Welcome message sent successfully to %s", display_name)
except Exception as exc:
logging.error("Failed to send welcome message: %s", exc)
logging.info("Join listener registered for room %s", ALLOWED_ROOM_ID)
# ---------------------------------------------------------------------------
# Plugin entry point - called by FunguyBot for every message event
# ---------------------------------------------------------------------------
async def handle_command(room, message, bot, prefix, config):
"""Handle the !welcome command."""
match = botlib.MessageMatch(room, message, bot, prefix)
if not (
match.is_not_from_this_bot()
and match.prefix()
and match.command("welcome")
):
return
if room.room_id != ALLOWED_ROOM_ID:
await bot.api.send_text_message(
room.room_id,
"The !welcome command only works in the designated room.",
)
return
sender = str(message.sender)
display_name = sender.split(":")[0].lstrip("@")
await bot.api.send_markdown_message(
room.room_id, _build_welcome_message(display_name)
)
logging.info("Sent manual !welcome to %s", sender)