Compare commits
10 Commits
testing-co
...
25f9159155
Author | SHA1 | Date | |
---|---|---|---|
25f9159155 | |||
803acf514b | |||
542bb5d5cd | |||
5962eb53ad | |||
eb81f7aa67 | |||
c996168543 | |||
784409cef6 | |||
e9a853c31a | |||
669fd361d4 | |||
58fa16663e |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,5 +1,4 @@
|
|||||||
.env
|
.env
|
||||||
.gitignore
|
|
||||||
karma.db
|
karma.db
|
||||||
proxies.db
|
proxies.db
|
||||||
session.txt
|
session.txt
|
||||||
@@ -10,3 +9,4 @@ simplematrixbotlib*/
|
|||||||
chromedriver
|
chromedriver
|
||||||
store
|
store
|
||||||
funguybot.service
|
funguybot.service
|
||||||
|
stats.db
|
@@ -87,7 +87,7 @@ To use the bot, invite it to a Matrix room and interact with it by sending comma
|
|||||||
- `!karma <user>`: View or modify karma points for a user.
|
- `!karma <user>`: View or modify karma points for a user.
|
||||||
- `!funguy <prompt>` Talk to the Tech AI LLM
|
- `!funguy <prompt>` Talk to the Tech AI LLM
|
||||||
- `!music <prompt>` Talk to the music knowledge LLM
|
- `!music <prompt>` Talk to the music knowledge LLM
|
||||||
|
- `!yt <search terms>` Search Youtube
|
||||||
For a complete list of available commands and their descriptions, use the `!commands` command.
|
For a complete list of available commands and their descriptions, use the `!commands` command.
|
||||||
|
|
||||||
# 🍄 Funguy Bot Commands 🍄
|
# 🍄 Funguy Bot Commands 🍄
|
||||||
|
128
funguy.py
128
funguy.py
@@ -10,78 +10,86 @@ import time
|
|||||||
import sys
|
import sys
|
||||||
from plugins.config import FunguyConfig
|
from plugins.config import FunguyConfig
|
||||||
|
|
||||||
# Setup logging
|
class FunguyBot:
|
||||||
logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', level=logging.INFO)
|
|
||||||
|
|
||||||
# Load plugins (defined before plugin load/reload functions)
|
bot = None
|
||||||
PLUGINS_DIR = "plugins"
|
config = None
|
||||||
PLUGINS = {}
|
|
||||||
|
|
||||||
def load_plugins():
|
def __init__(self):
|
||||||
for plugin_file in os.listdir(PLUGINS_DIR):
|
self.PLUGINS_DIR = "plugins"
|
||||||
if plugin_file.endswith(".py"):
|
self.PLUGINS = {}
|
||||||
plugin_name = os.path.splitext(plugin_file)[0]
|
self.config = None
|
||||||
try:
|
self.bot = None
|
||||||
module = importlib.import_module(f"{PLUGINS_DIR}.{plugin_name}")
|
self.load_dotenv()
|
||||||
PLUGINS[plugin_name] = module
|
self.setup_logging()
|
||||||
logging.info(f"Loaded plugin: {plugin_name}")
|
self.load_plugins()
|
||||||
except Exception as e:
|
self.load_config()
|
||||||
logging.error(f"Error loading plugin {plugin_name}: {e}")
|
|
||||||
|
|
||||||
def reload_plugins():
|
def load_dotenv(self):
|
||||||
global PLUGINS
|
load_dotenv()
|
||||||
PLUGINS = {}
|
|
||||||
# Unload modules from sys.modules
|
|
||||||
for plugin_name in list(sys.modules.keys()):
|
|
||||||
if plugin_name.startswith(PLUGINS_DIR + "."):
|
|
||||||
del sys.modules[plugin_name]
|
|
||||||
load_plugins()
|
|
||||||
|
|
||||||
def rehash_config(config):
|
def setup_logging(self):
|
||||||
del config
|
logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', level=logging.INFO)
|
||||||
config = FunguyConfig()
|
logging.getLogger().setLevel(logging.INFO)
|
||||||
|
|
||||||
|
def load_plugins(self):
|
||||||
|
for plugin_file in os.listdir(self.PLUGINS_DIR):
|
||||||
|
if plugin_file.endswith(".py"):
|
||||||
|
plugin_name = os.path.splitext(plugin_file)[0]
|
||||||
|
try:
|
||||||
|
module = importlib.import_module(f"{self.PLUGINS_DIR}.{plugin_name}")
|
||||||
|
self.PLUGINS[plugin_name] = module
|
||||||
|
logging.info(f"Loaded plugin: {plugin_name}")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Error loading plugin {plugin_name}: {e}")
|
||||||
|
|
||||||
# Load environment variables from .env file
|
def reload_plugins(self):
|
||||||
load_dotenv()
|
self.PLUGINS = {}
|
||||||
|
# Unload modules from sys.modules
|
||||||
|
for plugin_name in list(sys.modules.keys()):
|
||||||
|
if plugin_name.startswith(self.PLUGINS_DIR + "."):
|
||||||
|
del sys.modules[plugin_name]
|
||||||
|
self.load_plugins()
|
||||||
|
|
||||||
# Load plugins
|
def load_config(self):
|
||||||
load_plugins()
|
self.config = FunguyConfig()
|
||||||
|
|
||||||
# Bot configuration settings
|
async def handle_commands(self, room, message):
|
||||||
MATRIX_URL = os.getenv("MATRIX_URL")
|
match = botlib.MessageMatch(room, message, self.bot, self.config.prefix)
|
||||||
MATRIX_USER = os.getenv("MATRIX_USER")
|
if match.is_not_from_this_bot() and match.prefix() and match.command("reload"):
|
||||||
MATRIX_PASS = os.getenv("MATRIX_PASS")
|
if str(message.sender) == self.config.admin_user:
|
||||||
|
self.reload_plugins()
|
||||||
|
await self.bot.api.send_text_message(room.room_id, "Plugins reloaded successfully")
|
||||||
|
else:
|
||||||
|
await self.bot.api.send_text_message(room.room_id, "You are not authorized to reload plugins.")
|
||||||
|
|
||||||
# Get credentials from env
|
for plugin_name, plugin_module in self.PLUGINS.items():
|
||||||
creds = botlib.Creds(MATRIX_URL, MATRIX_USER, MATRIX_PASS)
|
await plugin_module.handle_command(room, message, self.bot, self.config.prefix, self.config)
|
||||||
|
|
||||||
# Bot configuration
|
if match.is_not_from_this_bot() and match.prefix() and match.command("rehash"):
|
||||||
config = FunguyConfig()
|
if str(message.sender) == self.config.admin_user:
|
||||||
bot = botlib.Bot(creds, config)
|
self.rehash_config()
|
||||||
|
await self.bot.api.send_text_message(room.room_id, "Config rehashed")
|
||||||
|
else:
|
||||||
|
await self.bot.api.send_text_message(room.room_id, "You are not authorized to reload plugins.")
|
||||||
|
|
||||||
@bot.listener.on_message_event
|
def rehash_config(self):
|
||||||
async def handle_commands(room, message):
|
del self.config
|
||||||
match = botlib.MessageMatch(room, message, bot, config.prefix)
|
self.config = FunguyConfig()
|
||||||
if match.is_not_from_this_bot() and match.prefix() and match.command("reload"):
|
|
||||||
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():
|
def run(self):
|
||||||
await plugin_module.handle_command(room, message, bot, config.prefix, config)
|
MATRIX_URL = os.getenv("MATRIX_URL")
|
||||||
|
MATRIX_USER = os.getenv("MATRIX_USER")
|
||||||
|
MATRIX_PASS = os.getenv("MATRIX_PASS")
|
||||||
|
creds = botlib.Creds(MATRIX_URL, MATRIX_USER, MATRIX_PASS)
|
||||||
|
self.bot = botlib.Bot(creds, self.config)
|
||||||
|
|
||||||
|
@self.bot.listener.on_message_event
|
||||||
|
async def wrapper_handle_commands(room, message):
|
||||||
|
await self.handle_commands(room, message)
|
||||||
|
|
||||||
if match.is_not_from_this_bot() and match.prefix() and match.command("rehash"):
|
self.bot.run()
|
||||||
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.")
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
bot = FunguyBot()
|
||||||
|
bot.run()
|
||||||
bot.run()
|
|
||||||
|
4
g
Executable file
4
g
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
git add .;
|
||||||
|
git commit -a -m "$1";
|
||||||
|
git push -u origin "$2"
|
@@ -8,6 +8,7 @@ import requests
|
|||||||
import json
|
import json
|
||||||
import simplematrixbotlib as botlib
|
import simplematrixbotlib as botlib
|
||||||
import re
|
import re
|
||||||
|
import markdown2
|
||||||
|
|
||||||
async def handle_command(room, message, bot, prefix, config):
|
async def handle_command(room, message, bot, prefix, config):
|
||||||
"""
|
"""
|
||||||
@@ -56,9 +57,12 @@ async def handle_command(room, message, bot, prefix, config):
|
|||||||
response.raise_for_status() # Raise HTTPError for bad responses
|
response.raise_for_status() # Raise HTTPError for bad responses
|
||||||
payload = response.json()
|
payload = response.json()
|
||||||
new_text = payload['choices'][0]['text']
|
new_text = payload['choices'][0]['text']
|
||||||
if new_text.count('\n') > 1: # Check if new_text has more than one paragraph
|
new_text = markdown_to_html(new_text)
|
||||||
new_text = new_text.replace("\n", '<br>')
|
print(new_text)
|
||||||
new_text = re.sub(r"\*\*(.*?)\*\*", r"<strong>\1</strong>", new_text)
|
|
||||||
|
if new_text.count('<p>') > 1 or new_text.count('<li>') > 1: # Check if new_text has more than one paragraph
|
||||||
|
#new_text = new_text.replace("\n", '<br>')
|
||||||
|
#new_text = re.sub(r"\*\*(.*?)\*\*", r"<strong>\1</strong>", new_text)
|
||||||
new_text = "<details><summary><strong>🎵Funguy Music GPT🎵<br>⤵︎Click Here To See Funguy's Response⤵︎</strong></summary>" + new_text + "</details>"
|
new_text = "<details><summary><strong>🎵Funguy Music GPT🎵<br>⤵︎Click Here To See Funguy's Response⤵︎</strong></summary>" + new_text + "</details>"
|
||||||
await bot.api.send_markdown_message(room.room_id, new_text)
|
await bot.api.send_markdown_message(room.room_id, new_text)
|
||||||
else:
|
else:
|
||||||
@@ -67,3 +71,8 @@ async def handle_command(room, message, bot, prefix, config):
|
|||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
logging.error(f"HTTP request failed for '{prompt}': {e}")
|
logging.error(f"HTTP request failed for '{prompt}': {e}")
|
||||||
await bot.api.send_text_message(room.room_id, f"Error generating text: {e}")
|
await bot.api.send_text_message(room.room_id, f"Error generating text: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
def markdown_to_html(markdown_text):
|
||||||
|
html_content = markdown2.markdown(markdown_text)
|
||||||
|
return html_content
|
||||||
|
@@ -9,6 +9,7 @@ import requests
|
|||||||
import json
|
import json
|
||||||
import simplematrixbotlib as botlib
|
import simplematrixbotlib as botlib
|
||||||
import re
|
import re
|
||||||
|
import markdown2
|
||||||
|
|
||||||
async def handle_command(room, message, bot, prefix, config):
|
async def handle_command(room, message, bot, prefix, config):
|
||||||
"""
|
"""
|
||||||
@@ -57,9 +58,10 @@ async def handle_command(room, message, bot, prefix, config):
|
|||||||
response.raise_for_status() # Raise HTTPError for bad responses
|
response.raise_for_status() # Raise HTTPError for bad responses
|
||||||
payload = response.json()
|
payload = response.json()
|
||||||
new_text = payload['choices'][0]['text']
|
new_text = payload['choices'][0]['text']
|
||||||
if new_text.count('\n') > 2: # Check if new_text has more than one paragraph
|
new_text = markdown_to_html(new_text)
|
||||||
new_text = new_text.replace("\n", '<br>')
|
if new_text.count('<p>') > 2: # Check if new_text has more than one paragraph
|
||||||
new_text = re.sub(r"\*\*(.*?)\*\*", r"<strong>\1</strong>", new_text)
|
#new_text = new_text.replace("\n", '<br>')
|
||||||
|
#new_text = re.sub(r"\*\*(.*?)\*\*", r"<strong>\1</strong>", new_text)
|
||||||
new_text = "<details><summary><strong>🍄Funguy Tech GPT🍄<br>⤵︎Click Here To See Funguy's Response⤵︎</strong></summary>" + new_text + "</details>"
|
new_text = "<details><summary><strong>🍄Funguy Tech GPT🍄<br>⤵︎Click Here To See Funguy's Response⤵︎</strong></summary>" + new_text + "</details>"
|
||||||
await bot.api.send_markdown_message(room.room_id, new_text)
|
await bot.api.send_markdown_message(room.room_id, new_text)
|
||||||
else:
|
else:
|
||||||
@@ -68,3 +70,7 @@ async def handle_command(room, message, bot, prefix, config):
|
|||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
logging.error(f"HTTP request failed for '{prompt}': {e}")
|
logging.error(f"HTTP request failed for '{prompt}': {e}")
|
||||||
await bot.api.send_text_message(room.room_id, f"Error generating text: {e}")
|
await bot.api.send_text_message(room.room_id, f"Error generating text: {e}")
|
||||||
|
|
||||||
|
def markdown_to_html(markdown_text):
|
||||||
|
html_content = markdown2.markdown(markdown_text)
|
||||||
|
return html_content
|
||||||
|
@@ -1,3 +1,6 @@
|
|||||||
|
"""
|
||||||
|
Custom configuration class for the Funguy bot.
|
||||||
|
"""
|
||||||
# plugins/config.py
|
# plugins/config.py
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
@@ -23,10 +23,39 @@ async def handle_command(room, message, bot, prefix, config):
|
|||||||
if match.is_not_from_this_bot() and match.prefix() and match.command("date"):
|
if match.is_not_from_this_bot() and match.prefix() and match.command("date"):
|
||||||
logging.info("Fetching current date and time")
|
logging.info("Fetching current date and time")
|
||||||
current_datetime = datetime.datetime.now()
|
current_datetime = datetime.datetime.now()
|
||||||
|
|
||||||
|
# Extract individual date components
|
||||||
day_of_week = current_datetime.strftime("%A")
|
day_of_week = current_datetime.strftime("%A")
|
||||||
|
date_of_month = current_datetime.strftime("%d") # Day with leading zero
|
||||||
month = current_datetime.strftime("%B")
|
month = current_datetime.strftime("%B")
|
||||||
year = current_datetime.strftime("%Y")
|
year = current_datetime.strftime("%Y")
|
||||||
time = current_datetime.strftime("%I:%M:%S %p")
|
time = current_datetime.strftime("%I:%M:%S %p")
|
||||||
date_message = f"📅 Today is **{day_of_week}** of **{month}** in **{year}**. The time is **⏰ {time}**"
|
|
||||||
|
# Format date with ordinal suffix
|
||||||
|
date_with_ordinal = f"{date_of_month}{get_ordinal_suffix(date_of_month)}"
|
||||||
|
|
||||||
|
# Construct the message
|
||||||
|
date_message = f"Date: **{day_of_week}** the {date_with_ordinal}, **{month} {year}**. \nTime: **⏰ {time}**"
|
||||||
|
|
||||||
await bot.api.send_markdown_message(room.room_id, date_message)
|
await bot.api.send_markdown_message(room.room_id, date_message)
|
||||||
logging.info("Sent current date and time to the room")
|
logging.info("Sent current date and time to the room")
|
||||||
|
|
||||||
|
|
||||||
|
def get_ordinal_suffix(day_of_month):
|
||||||
|
"""
|
||||||
|
Helper function to get the ordinal suffix for a day number.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
day_of_month (str): The day number as a string (e.g., "1", "13")
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The ordinal suffix (e.g., "st", "th", "nd")
|
||||||
|
"""
|
||||||
|
if day_of_month.endswith("11") or day_of_month.endswith("12") or day_of_month.endswith("13"):
|
||||||
|
return "th"
|
||||||
|
elif day_of_month.endswith("1") or day_of_month.endswith("3"):
|
||||||
|
return "st"
|
||||||
|
elif day_of_month.endswith("2"):
|
||||||
|
return "nd"
|
||||||
|
else:
|
||||||
|
return "th"
|
||||||
|
@@ -21,51 +21,52 @@ async def handle_command(room, message, bot, prefix, config):
|
|||||||
match = botlib.MessageMatch(room, message, bot, prefix)
|
match = botlib.MessageMatch(room, message, bot, prefix)
|
||||||
if match.is_not_from_this_bot() and match.prefix() and match.command("help"):
|
if match.is_not_from_this_bot() and match.prefix() and match.command("help"):
|
||||||
logging.info("Fetching command help documentation")
|
logging.info("Fetching command help documentation")
|
||||||
commands_message = """<details><summary><strong>🍄Funguy Bot Commands🍄<br>⤵︎Click Here To See Help Text⤵︎</strong></summary>
|
commands_message = """
|
||||||
<br>
|
<details><summary><strong>🍄Funguy Bot Commands🍄<br>⤵︎Click Here To See Help Text⤵︎</strong></summary>
|
||||||
<br>🃏 **!fortune**
|
<p>
|
||||||
<br>Returns a random fortune message.
|
<details><summary>🃏 <strong>!fortune</strong></summary>
|
||||||
<br>Executes the `/usr/games/fortune` utility and sends the output as a message to the chat room.
|
<p>Returns a random fortune message. Executes the `/usr/games/fortune` utility and sends the output as a message to the chat room.</p>
|
||||||
<br>
|
</details>
|
||||||
<br>⏰ **!date**
|
|
||||||
<br>Displays the current date and time.
|
<details><summary>⏰ <strong>!date</strong></summary>
|
||||||
<br>Fetches the current date and time using Python's `datetime` module and sends it in a formatted message to the chat room.
|
<p>Displays the current date and time. Fetches the current date and time using Python's `datetime` module and sends it in a formatted message to the chat room.</p>
|
||||||
<br>
|
</details>
|
||||||
<br>💻 **!proxy**
|
|
||||||
<br>Retrieves a tested/working random SOCKS5 proxy.
|
<details><summary>💻 <strong>!proxy</strong></summary>
|
||||||
<br>Fetches a list of SOCKS5 proxies, tests their availability, and sends the first working proxy to the chat room.
|
<p>Retrieves a tested/working random SOCKS5 proxy. Fetches a list of SOCKS5 proxies, tests their availability, and sends the first working proxy to the chat room.</p>
|
||||||
<br>
|
</details>
|
||||||
<br>📶 **!isup [domain/ip]**
|
|
||||||
<br>Checks if the specified domain or IP address is reachable.
|
<details><summary>📶 <strong>!isup [domain/ip]</strong></summary>
|
||||||
<br>Checks if the specified domain or IP address is reachable by attempting to ping it. If DNS resolution is successful, it checks HTTP and HTTPS service availability by sending requests to the domain.
|
<p>Checks if the specified domain or IP address is reachable. Checks if the specified domain or IP address is reachable by attempting to ping it. If DNS resolution is successful, it checks HTTP and HTTPS service availability by sending requests to the domain.</p>
|
||||||
<br>
|
</details>
|
||||||
<br>☯ **!karma [user]**
|
|
||||||
<br>Retrieves the karma points for the specified user.
|
<details><summary>☯ <strong>!karma [user]</strong></summary>
|
||||||
<br>Retrieves the karma points for the specified user from a database and sends them as a message to the chat room.
|
<p>Retrieves the karma points for the specified user. Retrieves the karma points for the specified user from a database and sends them as a message to the chat room.</p>
|
||||||
<br>
|
</details>
|
||||||
<br>⇧ **!karma [user] up**
|
|
||||||
<br>Increases the karma points for the specified user by 1.
|
<details><summary>⇧ <strong>!karma [user] up</strong></summary>
|
||||||
<br>Increases the karma points for the specified user by 1 in the database and sends the updated points as a message to the chat room.
|
<p>Increases the karma points for the specified user by 1. Increases the karma points for the specified user by 1 in the database and sends the updated points as a message to the chat room.</p>
|
||||||
<br>
|
</details>
|
||||||
<br>⇩ **!karma [user] down**
|
|
||||||
<br>Decreases the karma points for the specified user by 1.
|
<details><summary>⇩ <strong>!karma [user] down</strong></summary>
|
||||||
<br>Decreases the karma points for the specified user by 1 in the database and sends the updated points as a message to the chat room.
|
<p>Decreases the karma points for the specified user by 1. Decreases the karma points for the specified user by 1 in the database and sends the updated points as a message to the chat room.</p>
|
||||||
<br>
|
</details>
|
||||||
<br>📄 **!funguy [prompt]
|
|
||||||
<br>An AI large language model designed to serve as a chatbot within a vibrant and diverse community chat room hosted on the Matrix platform.
|
<details><summary>📄 <strong>!funguy [prompt]</strong></summary>
|
||||||
<br>(Currently loaded model: **TheBloke_Mistral-7B-Instruct-v0.2-GPTQ**
|
<p>An AI large language model designed to serve as a chatbot within a vibrant and diverse community chat room hosted on the Matrix platform. (Currently loaded model: <strong>TheBloke_Mistral-7B-Instruct-v0.2-GPTQ</strong>)</p>
|
||||||
<br>
|
</details>
|
||||||
<br>🎝 **!music [prompt]**
|
|
||||||
<br>Your music expert! Try it out.
|
<details><summary>🎝 <strong>!music [prompt]</strong></summary>
|
||||||
<br> 🌟 Funguy Bot Credits 🌟
|
<p>Your music expert! Try it out.</p>
|
||||||
<br>
|
</details>
|
||||||
<br>🧙♂️ Creator & Developer:
|
|
||||||
<br> Hash Borgir is the author of 🍄Funguy Bot🍄. (@hashborgir:mozilla.org)
|
<details><summary>🌟 <strong>Funguy Bot Credits</strong> 🌟</summary>
|
||||||
<br>
|
<p>🧙♂️ Creator & Developer: Hash Borgir is the author of 🍄Funguy Bot🍄. (@hashborgir:mozilla.org)</p>
|
||||||
<br> Join our Matrix Room:
|
<p>Join our Matrix Room: [Self-hosting | Security | Sysadmin | Homelab | Programming](https://matrix.to/#/#selfhosting:mozilla.org)</p>
|
||||||
<br>
|
</details>
|
||||||
<br>[Self-hosting | Security | Sysadmin | Homelab | Programming](https://matrix.to/#/#selfhosting:mozilla.org)
|
</p>
|
||||||
<br>
|
</details>
|
||||||
<br></details>"""
|
"""
|
||||||
|
|
||||||
await bot.api.send_markdown_message(room.room_id, commands_message)
|
await bot.api.send_markdown_message(room.room_id, commands_message)
|
||||||
logging.info("Sent help documentation to the room")
|
logging.info("Sent help documentation to the room")
|
||||||
|
@@ -1,3 +1,6 @@
|
|||||||
|
"""
|
||||||
|
This plugin provides a command for the admin to load a plugin
|
||||||
|
"""
|
||||||
# plugins/load_plugin.py
|
# plugins/load_plugin.py
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
@@ -26,9 +26,9 @@ async def handle_command(room, message, bot, prefix, config):
|
|||||||
plugin_descriptions = get_plugin_descriptions()
|
plugin_descriptions = get_plugin_descriptions()
|
||||||
|
|
||||||
# Prepend custom string before the output
|
# Prepend custom string before the output
|
||||||
plugin_descriptions.insert(0, "<details><summary><strong>🔌Plugins List🔌<br>⤵︎Click Here to Expand⤵︎</strong></summary><br>")
|
plugin_descriptions.insert(0, "<details><summary><strong>🔌Plugins List🔌<br>⤵︎Click Here to Expand⤵︎</strong></summary>")
|
||||||
|
|
||||||
plugins_message = "<br><br>".join(plugin_descriptions)
|
plugins_message = "<br>".join(plugin_descriptions)
|
||||||
plugins_message += "</details>"
|
plugins_message += "</details>"
|
||||||
await bot.api.send_markdown_message(room.room_id, plugins_message)
|
await bot.api.send_markdown_message(room.room_id, plugins_message)
|
||||||
logging.info("Sent plugin list to the room")
|
logging.info("Sent plugin list to the room")
|
||||||
|
42
plugins/stable-diffusion.py
Normal file
42
plugins/stable-diffusion.py
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
"""
|
||||||
|
This plugin provides a command to generate images using self hosted Stable Diffusion and send to the room
|
||||||
|
"""
|
||||||
|
# plugins/stable-diffusion.py
|
||||||
|
import requests
|
||||||
|
import base64
|
||||||
|
from asyncio import Queue
|
||||||
|
import simplematrixbotlib as botlib
|
||||||
|
|
||||||
|
# Queue to store pending commands
|
||||||
|
command_queue = Queue()
|
||||||
|
|
||||||
|
async def process_command(room, message, bot, prefix, config):
|
||||||
|
match = botlib.MessageMatch(room, message, bot, prefix)
|
||||||
|
if match.prefix() and match.command("sd"):
|
||||||
|
if command_queue.empty():
|
||||||
|
await handle_command(room, message, bot, prefix, config)
|
||||||
|
else:
|
||||||
|
await command_queue.put((room, message, bot, prefix, config))
|
||||||
|
|
||||||
|
async def handle_command(room, message, bot, prefix, config):
|
||||||
|
match = botlib.MessageMatch(room, message, bot, prefix)
|
||||||
|
if match.prefix() and match.command("sd"):
|
||||||
|
prompt = message.body[len(prefix) + len("sd"):].strip() # Extract prompt from message body
|
||||||
|
payload = {
|
||||||
|
"prompt": prompt,
|
||||||
|
"steps": 16
|
||||||
|
}
|
||||||
|
url = "http://127.0.0.1:7860/sdapi/v1/txt2img"
|
||||||
|
try:
|
||||||
|
response = requests.post(url=url, json=payload)
|
||||||
|
r = response.json()
|
||||||
|
with open("/tmp/output.png", 'wb') as f:
|
||||||
|
f.write(base64.b64decode(r['images'][0]))
|
||||||
|
await bot.api.send_image_message(room_id=room.room_id, image_filepath="/tmp/output.png") # Corrected argument name
|
||||||
|
except Exception as e:
|
||||||
|
await bot.api.send_text_message(room.room_id, f"Error processing the command: {str(e)}")
|
||||||
|
finally:
|
||||||
|
if not command_queue.empty():
|
||||||
|
next_command = await command_queue.get()
|
||||||
|
await handle_command(*next_command)
|
||||||
|
|
@@ -6,25 +6,31 @@ This plugin provides a command to fetch YouTube video information from links.
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
import logging
|
import logging
|
||||||
from pytube import YouTube
|
from pytubefix import YouTube
|
||||||
import simplematrixbotlib as botlib
|
import simplematrixbotlib as botlib
|
||||||
|
import asyncio
|
||||||
|
|
||||||
def seconds_to_minutes_seconds(seconds):
|
def seconds_to_minutes_seconds(seconds):
|
||||||
minutes = seconds // 60
|
minutes = seconds // 60
|
||||||
seconds %= 60
|
seconds %= 60
|
||||||
return f"{minutes:02d}:{seconds:02d}"
|
return f"{minutes:02d}:{seconds:02d}"
|
||||||
|
|
||||||
|
async def fetch_youtube_info(youtube_url):
|
||||||
|
try:
|
||||||
|
video = YouTube(youtube_url)
|
||||||
|
title = video.title
|
||||||
|
description = video.description
|
||||||
|
length = seconds_to_minutes_seconds(video.length)
|
||||||
|
views = video.views
|
||||||
|
author = video.author
|
||||||
|
description_with_breaks = description.replace('\n', '<br>')
|
||||||
|
info_message = f"""<strong>🎬🎝 Title:</strong> {title} | <strong>Length</strong>: {length} minutes | <strong>Views</strong>: {views}\n<details><summary><strong>⤵︎Click Here For Description⤵︎</strong></summary>{description_with_breaks}</details>"""
|
||||||
|
return info_message
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Error fetching YouTube video information: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
async def handle_command(room, message, bot, prefix, config):
|
async def handle_command(room, message, bot, prefix, config):
|
||||||
"""
|
|
||||||
Function to handle YouTube video information from links.
|
|
||||||
|
|
||||||
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)
|
match = botlib.MessageMatch(room, message, bot, prefix)
|
||||||
if match.is_not_from_this_bot() and re.search(r'youtube\.com/watch\?v=', message.body):
|
if match.is_not_from_this_bot() and re.search(r'youtube\.com/watch\?v=', message.body):
|
||||||
logging.info("YouTube link detected")
|
logging.info("YouTube link detected")
|
||||||
@@ -33,16 +39,18 @@ async def handle_command(room, message, bot, prefix, config):
|
|||||||
video_id = video_id_match.group(1)
|
video_id = video_id_match.group(1)
|
||||||
youtube_url = f"https://www.youtube.com/watch?v={video_id}"
|
youtube_url = f"https://www.youtube.com/watch?v={video_id}"
|
||||||
logging.info(f"Fetching information for YouTube video: {youtube_url}")
|
logging.info(f"Fetching information for YouTube video: {youtube_url}")
|
||||||
try:
|
retry_count = 3
|
||||||
video = YouTube(youtube_url)
|
while retry_count > 0:
|
||||||
title = video.title
|
info_message = await fetch_youtube_info(youtube_url)
|
||||||
description = video.description
|
if info_message:
|
||||||
length = seconds_to_minutes_seconds(video.length)
|
await bot.api.send_markdown_message(room.room_id, info_message)
|
||||||
views = video.views
|
logging.info("Sent YouTube video information to the room")
|
||||||
author = video.author
|
break
|
||||||
info_message = f"""**🎬🎝 Title:** {title} | **Length**: {length} minutes| **Views:** {views} | **Description:** {description}"""
|
else:
|
||||||
await bot.api.send_markdown_message(room.room_id, info_message)
|
logging.info("Retrying...")
|
||||||
logging.info("Sent YouTube video information to the room")
|
retry_count -= 1
|
||||||
except Exception as e:
|
await asyncio.sleep(1) # wait for 1 second before retrying
|
||||||
logging.error(f"Error fetching YouTube video information: {str(e)}")
|
else:
|
||||||
# await bot.api.send__message(room.room_id, "Error fetching YouTube video information.")
|
logging.error("Failed to fetch YouTube video information after retries")
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,3 +1,6 @@
|
|||||||
|
"""
|
||||||
|
This plugin provides a command to search for YouTube videos in the room
|
||||||
|
"""
|
||||||
# plugins/youtube_search.py
|
# plugins/youtube_search.py
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
@@ -1,5 +1,8 @@
|
|||||||
python-dotenv
|
python-dotenv
|
||||||
requests
|
requests
|
||||||
pytube
|
pytubefix
|
||||||
duckduckgo_search
|
duckduckgo_search
|
||||||
nio
|
nio
|
||||||
|
markdown2
|
||||||
|
watchdog
|
||||||
|
emoji
|
||||||
|
Reference in New Issue
Block a user