# 🍄 Funguy Bot A modular, security-focused Matrix chat bot built with [`simplematrixbotlib`](https://simple-matrix-bot-lib.readthedocs.io/), written in Python. Features a plugin architecture, in-process cron scheduling, per-room plugin management, rate limiting, and a full suite of recon, encoding, and utility commands. > Written during recovery from cervical spinal surgery (CDA – Cervical Discectomy and Disc Arthroplasty). Expect bugs — please report them! --- ## 📋 Table of Contents - [Features](#-features) - [Requirements](#-requirements) - [Installation](#-installation) - [Configuration](#-configuration) - [Running the Bot](#-running-the-bot) - [Core Admin Commands](#-core-admin-commands) - [Plugin Reference](#-plugin-reference) - [Rate Limiting](#-rate-limiting) - [Security Notes](#-security-notes) - [Support](#-support) - [Credits](#-credits) --- ## ✨ Features - **Modular plugin system** – each command lives in its own `plugins/*.py` file; add or remove features without touching core code - **Runtime plugin management** – load, unload, enable, or disable plugins per-room with no restart required - **In-process cron scheduler** – schedule any bot command to fire automatically (APScheduler + SQLite, no system crontab needed) - **Rate limiting** – non-admin users are capped at 3 commands per 5-second window; admins are always exempt - **SSRF protection** – all outbound network plugins validate that targets resolve to public IPs only - **Admin/moderator access control** – a dedicated `admin_user` is set in config; moderation commands require power level ≥ 50 - **Live configuration** – settings can be changed at runtime with `!set`/`!saveconf` without restarting --- ## 📦 Requirements - Python 3.9+ - A Matrix homeserver account for the bot - `fortune` package installed on the host (`sudo apt install fortune`) if using `fortune.py` - `dict` / WordNet installed on the host (`sudo apt install dict dict-wn`) if using `dictionary.py` - Optional API keys for certain plugins (see [Configuration](#-configuration)) --- ## 🚀 Installation **1. Clone the repository** ```bash git clone https://gitlab.com/Eggzy/funguybot.git cd funguybot ``` **2. Create and activate a Python virtual environment** ```bash python3 -m venv venv source venv/bin/activate ``` **3. Install dependencies** ```bash pip3 install -r requirements.txt ``` **4. (Optional) Install Playwright for the Goodreads quote plugin (`quote.py`)** ```bash pip3 install playwright beautifulsoup4 lxml playwright install chromium ``` **5. Configure the bot** — create your `.env` and `funguy.conf` files (see [Configuration](#-configuration)) **6. Set up and start the systemd service** (see [Running the Bot](#-running-the-bot)) --- ## ⚙️ Configuration ### Environment Variables (`.env`) Create a `.env` file in the bot's root directory. Only the three Matrix variables are required; all API keys are optional. ```env # ── Required ────────────────────────────────────────────────────────── MATRIX_URL="https://matrix.org" # Your homeserver URL MATRIX_USER="@yourbot:matrix.org" # Bot's Matrix ID MATRIX_PASS="your_password" # Bot's password # ── Logging (optional, default: INFO) ───────────────────────────────── LOG_LEVEL=INFO # DEBUG | INFO | WARNING | ERROR | CRITICAL # ── Plugin API Keys (all optional) ──────────────────────────────────── OPENWEATHER_API_KEY= # weather.py SHODAN_KEY= # shodan.py DNSDUMPSTER_KEY= # dnsdumpster.py LASTFM_API_KEY= # lastfm.py YOUTUBE_API_KEY= # youtube-search.py INFERMATIC_API= # infermatic-text.py INFERMATIC_MODEL= # infermatic-text.py – model name string OMDB_API_KEY= # imdb.py GNEWS_API_KEY= # news.py # ── SMTP (optional, for notification plugins) ───────────────────────── SMTP_SERVER=mail.example.com SMTP_PORT=465 SMTP_USER=bot@example.com SMTP_PASSWORD=yourpassword ``` ### Bot Configuration (`funguy.conf`) Create `funguy.conf` in the bot's root directory. This is a TOML file consumed by `simplematrixbotlib` and the `config.py` plugin. ```toml [simplematrixbotlib.config] admin_user = "@youradmin:matrix.org" # Full Matrix ID of the admin prefix = "!" # Single-character command prefix join_on_invite = true encryption_enabled = false emoji_verify = false ignore_unverified_devices = true store_path = "./store/" # Pre-disable plugins per room (optional) [plugins.disabled] # "!yourroom:matrix.org" = ["pluginname1", "pluginname2"] ``` All writable options can also be changed live by the admin using `!set` (see [config.py](#configpy--live-configuration-admin-only)). --- ## 🤖 Running the Bot ### Systemd Service (Recommended) Create `/etc/systemd/system/funguybot.service`, replacing the `$variables` with your actual paths and user: ```ini [Unit] Description=Funguy Bot Service After=network.target [Service] Type=simple User=$user Group=$group WorkingDirectory=$working_directory ExecStart=$working_directory/start-funguy.sh Restart=on-failure StandardOutput=syslog StandardError=syslog SyslogIdentifier=funguybot [Install] WantedBy=multi-user.target ``` ```bash systemctl daemon-reload systemctl enable funguybot systemctl start funguybot ``` ### Direct Launch ```bash source venv/bin/activate python3 funguy.py ``` --- ## 🔑 Core Admin Commands These commands are handled by `funguy.py` itself and require `admin_user` privileges. | Command | Description | |---------|-------------| | `!reload` | Reload all plugins from disk (no restart needed) | | `!load ` | Dynamically load a single plugin by filename (without `.py`) | | `!unload ` | Dynamically unload a single plugin | | `!enable ` | Re-enable a plugin in the current room | | `!disable ` | Disable a plugin in the current room (persisted to `funguy.conf`) | | `!restart` | Gracefully stop the bot process (systemd will restart it automatically) | | `!rehash` | Reload `funguy.conf` and the disabled-plugin list without restarting | --- ## 🧩 Plugin Reference All commands use the prefix defined in `funguy.conf` (default `!`). Plugin filenames correspond to the names used with `!load` / `!unload` / `!disable` / `!enable`. --- ### 🛡️ admin.py – Room Moderation Full moderator toolkit with multi-word display name resolution. Requires power level ≥ 50 or `admin_user`. The bot automatically resolves multi-word display names and prompts with a numbered disambiguation list when names are ambiguous. | Command | Description | |---------|-------------| | `!kick [reason]` | Kick a user from the room | | `!ban [reason]` | Ban a user | | `!unban <@user:domain>` | Unban a user (full MXID required) | | `!invite ` | Invite a user to the room | | `!op [power_level]` | Promote a user (max 50 / moderator level) | | `!deop ` | Demote a user to power level 0 | | `!userinfo ` | Show display name and power level | | `!topic [new topic]` | View or set the room topic | | `!roomname [new name]` | View or set the room name | | `!avatar [mxc://…]` | View or set the room avatar (must be an `mxc://` URL) | | `!members` | List all joined members with power levels | | `!bans` | List all banned users | | `!modhelp` | Show moderator command reference | `!admin ` also works as an explicit parent command for all of the above. --- ### 📄 arxiv.py – arXiv Academic Search | Command | Description | |---------|-------------| | `!arxiv ` | Search papers with abstracts | | `!arxiv list ` | Search titles only (no abstracts) | | `!arxiv category ` | Browse recent papers by category | | `!arxiv recent [category]` | Papers from the last 7 days | | `!arxiv random` | Random paper | | `!arxiv ` | Fetch paper by arXiv ID (e.g. `2101.00101`) | **Categories:** `ai`, `ml`, `security`, `crypto`, `cv`, `nlp`, `math`, `physics`, `quantum`, `bio`, `software` --- ### ₿ bitcoin.py – Bitcoin Price ``` !btc ``` Fetches the latest BTC/USD price from `bitcointicker.co` (Bitstamp feed, 60-second intervals). No API key required. --- ### ⚙️ config.py – Live Configuration *(Admin Only)* Manage bot settings at runtime. Changes are in-memory until you run `!saveconf`. | Command | Description | |---------|-------------| | `!set