Compare commits
6 Commits
aa7e76e653
...
58fa16663e
Author | SHA1 | Date | |
---|---|---|---|
58fa16663e | |||
911f8dd47a | |||
|
b10178452b | ||
|
5f5c9d2a0c | ||
|
bb331092d0 | ||
|
2277dd1b90 |
@ -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 🍄
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
From 7b3421cf893ef8ea36978ae1343f7c8d5d353412 Mon Sep 17 00:00:00 2001
|
From 7b3421cf893ef8ea36978ae1343f7c8d5d353412 Mon Sep 17 00:00:00 2001
|
||||||
From: Hash Borgir <atirjavid@gmail.com>
|
From: Hash Borgir <hash@stoned.io>
|
||||||
Date: Tue, 13 Feb 2024 15:48:35 -0700
|
Date: Tue, 13 Feb 2024 15:48:35 -0700
|
||||||
Subject: [PATCH] api.py patch
|
Subject: [PATCH] api.py patch
|
||||||
|
|
||||||
|
12
funguy.conf
Normal file
12
funguy.conf
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[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 = "!"
|
||||||
|
config_file = "funguy.conf"
|
58
funguy.py
58
funguy.py
@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# bot.py
|
# funguy.py
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
@ -8,26 +8,12 @@ import simplematrixbotlib as botlib
|
|||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
import time
|
import time
|
||||||
import sys
|
import sys
|
||||||
|
from plugins.config import FunguyConfig
|
||||||
# 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)
|
|
||||||
|
|
||||||
# Setup logging
|
# Setup logging
|
||||||
logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', level=logging.INFO)
|
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_DIR = "plugins"
|
||||||
PLUGINS = {}
|
PLUGINS = {}
|
||||||
|
|
||||||
@ -51,19 +37,51 @@ def reload_plugins():
|
|||||||
del sys.modules[plugin_name]
|
del sys.modules[plugin_name]
|
||||||
load_plugins()
|
load_plugins()
|
||||||
|
|
||||||
|
def rehash_config(config):
|
||||||
|
del config
|
||||||
|
config = FunguyConfig()
|
||||||
|
|
||||||
|
|
||||||
|
# Load environment variables from .env file
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
# Load plugins
|
||||||
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)
|
||||||
|
|
||||||
@bot.listener.on_message_event
|
@bot.listener.on_message_event
|
||||||
async def handle_commands(room, message):
|
async def handle_commands(room, message):
|
||||||
match = botlib.MessageMatch(room, message, bot, PREFIX)
|
match = botlib.MessageMatch(room, message, bot, config.prefix)
|
||||||
if match.is_not_from_this_bot() and match.prefix() and match.command("reload"):
|
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()
|
reload_plugins()
|
||||||
await bot.api.send_text_message(room.room_id, "Plugins reloaded successfully")
|
await bot.api.send_text_message(room.room_id, "Plugins reloaded successfully")
|
||||||
else:
|
else:
|
||||||
await bot.api.send_text_message(room.room_id, "You are not authorized to reload plugins.")
|
await bot.api.send_text_message(room.room_id, "You are not authorized to reload plugins.")
|
||||||
|
|
||||||
for plugin_name, plugin_module in PLUGINS.items():
|
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, config.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()
|
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"
|
@ -1,11 +1,15 @@
|
|||||||
|
"""
|
||||||
|
This plugin provides a command to interact with the music knowledge A.I.
|
||||||
|
"""
|
||||||
# plugins/ai-music.py
|
# plugins/ai-music.py
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import requests
|
import requests
|
||||||
import json
|
import json
|
||||||
import simplematrixbotlib as botlib
|
import simplematrixbotlib as botlib
|
||||||
|
import re
|
||||||
|
|
||||||
async def handle_command(room, message, bot, PREFIX):
|
async def handle_command(room, message, bot, prefix, config):
|
||||||
"""
|
"""
|
||||||
Function to handle the !music command.
|
Function to handle the !music command.
|
||||||
|
|
||||||
@ -18,7 +22,7 @@ async def handle_command(room, message, bot, PREFIX):
|
|||||||
Returns:
|
Returns:
|
||||||
None
|
None
|
||||||
"""
|
"""
|
||||||
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("music"):
|
if match.is_not_from_this_bot() and match.prefix() and match.command("music"):
|
||||||
logging.info("Received !music command")
|
logging.info("Received !music command")
|
||||||
args = match.args()
|
args = match.args()
|
||||||
@ -52,6 +56,12 @@ async def handle_command(room, message, bot, PREFIX):
|
|||||||
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 = 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>"
|
||||||
|
await bot.api.send_markdown_message(room.room_id, new_text)
|
||||||
|
else:
|
||||||
await bot.api.send_markdown_message(room.room_id, new_text)
|
await bot.api.send_markdown_message(room.room_id, new_text)
|
||||||
logging.info("Sent generated text to the room")
|
logging.info("Sent generated text to the room")
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
|
"""
|
||||||
|
This plugin provides a command to interact with the LLM for Tech/IT/Security/Selfhosting/Programming etc.
|
||||||
|
"""
|
||||||
|
|
||||||
# plugins/ai-tech.py
|
# plugins/ai-tech.py
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import requests
|
import requests
|
||||||
import json
|
import json
|
||||||
import simplematrixbotlib as botlib
|
import simplematrixbotlib as botlib
|
||||||
|
import re
|
||||||
|
|
||||||
async def handle_command(room, message, bot, PREFIX):
|
async def handle_command(room, message, bot, prefix, config):
|
||||||
"""
|
"""
|
||||||
Function to handle the !funguy command.
|
Function to handle the !funguy command.
|
||||||
|
|
||||||
@ -13,12 +18,12 @@ async def handle_command(room, message, bot, PREFIX):
|
|||||||
room (Room): The Matrix room where the command was invoked.
|
room (Room): The Matrix room where the command was invoked.
|
||||||
message (RoomMessage): The message object containing the command.
|
message (RoomMessage): The message object containing the command.
|
||||||
bot (Bot): The bot object.
|
bot (Bot): The bot object.
|
||||||
PREFIX (str): The command prefix.
|
prefix (str): The command prefix.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
None
|
None
|
||||||
"""
|
"""
|
||||||
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("funguy"):
|
if match.is_not_from_this_bot() and match.prefix() and match.command("funguy"):
|
||||||
logging.info("Received !funguy command")
|
logging.info("Received !funguy command")
|
||||||
args = match.args()
|
args = match.args()
|
||||||
@ -36,7 +41,7 @@ async def handle_command(room, message, bot, PREFIX):
|
|||||||
}
|
}
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"prompt": "<s>[INST]You are Funguy, a language model deployed as a chatbot for a community chat room hosted on Matrix. The chat room focuses on discussions related to self-hosting, system administration, cybersecurity, homelab setups, programming, coding, and general IT/tech topics. Your role is to assist users within the community by providing helpful responses and guidance on various technical matters. It's essential to keep your replies concise and relevant, addressing users' queries effectively while maintaining a friendly and approachable demeanor. Remember to prioritize clarity and brevity in your interactions to ensure a positive user experience within the chat room environment. You are ChatGPT, an AI language model designed to serve as a chatbot within a vibrant and diverse community chat room hosted on the Matrix platform. This chat room acts as a hub for enthusiasts and professionals alike, engaging in discussions spanning a wide array of technical topics, including self-hosting, system administration, cybersecurity, homelab setups, programming, coding, and general IT/tech inquiries. Your primary objective is to act as a reliable and knowledgeable assistant, offering assistance, guidance, and solutions to the community members as they navigate through their technical challenges and endeavors.Given the broad spectrum of topics discussed within the community, it's crucial for you to possess a comprehensive understanding of various domains within the realm of technology. As such, your knowledge should encompass not only the fundamentals of programming languages, software development methodologies, and system administration principles but also extend to cybersecurity best practices, networking protocols, cloud computing, database management, and beyond. Your role as a chatbot is multifaceted and dynamic. You'll be tasked with responding to a wide range of queries, ranging from beginner-level inquiries seeking clarification on basic concepts to advanced discussions requiring nuanced insights and problem-solving skills. Whether it's troubleshooting code errors, configuring network settings, securing server environments, optimizing database performance, or recommending suitable homelab hardware, your goal is to provide accurate, actionable, and helpful responses tailored to the needs of the community members. In addition to offering direct assistance, you should also strive to foster a collaborative and supportive atmosphere within the chat room. Encourage knowledge sharing, facilitate discussions, and celebrate the achievements of community members as they tackle technical challenges and embark on learning journeys. By promoting a culture of learning and collaboration, you'll contribute to the growth and cohesion of the community, empowering individuals to expand their skill sets and achieve their goals within the realm of technology. As you engage with users within the chat room, prioritize brevity and clarity in your responses. While it's essential to provide comprehensive and accurate information, it's equally important to convey it in a concise and easily understandable manner. Avoid overly technical jargon or convoluted explanations that may confuse or overwhelm community members, opting instead for straightforward explanations and practical solutions whenever possible. Remember, your ultimate objective is to be a trusted ally and resource for the members of the community as they navigate the ever-evolving landscape of technology. By leveraging your expertise, empathy, and problem-solving abilities, you'll play a vital role in facilitating knowledge exchange, fostering collaboration, and empowering individuals to succeed in their technical endeavors. As you embark on this journey as a chatbot within the Matrix community, embrace the opportunity to make a meaningful and positive impact, one helpful interaction at a time."+prompt+"[/INST]",
|
"prompt": "<s>[INST]You are FunguyGPT, a language model deployed as a chatbot for a community chat room hosted on Matrix. The chat room focuses on discussions related to self-hosting, system administration, cybersecurity, homelab setups, programming, coding, and general IT/tech topics. Your role is to assist users within the community by providing helpful responses and guidance on various technical matters. It's essential to keep your replies concise and relevant, addressing users' queries effectively while maintaining a friendly and approachable demeanor. Remember to prioritize clarity and brevity in your interactions to ensure a positive user experience within the chat room environment. You are FunguyGPT, an AI language model designed to serve as a chatbot within a vibrant and diverse community chat room hosted on the Matrix platform. This chat room acts as a hub for enthusiasts and professionals alike, engaging in discussions spanning a wide array of technical topics, including self-hosting, system administration, cybersecurity, homelab setups, programming, coding, and general IT/tech inquiries. Your primary objective is to act as a reliable and knowledgeable assistant, offering assistance, guidance, and solutions to the community members as they navigate through their technical challenges and endeavors.Given the broad spectrum of topics discussed within the community, it's crucial for you to possess a comprehensive understanding of various domains within the realm of technology. As such, your knowledge should encompass not only the fundamentals of programming languages, software development methodologies, and system administration principles but also extend to cybersecurity best practices, networking protocols, cloud computing, database management, and beyond. Your role as a chatbot is multifaceted and dynamic. You'll be tasked with responding to a wide range of queries, ranging from beginner-level inquiries seeking clarification on basic concepts to advanced discussions requiring nuanced insights and problem-solving skills. Whether it's troubleshooting code errors, configuring network settings, securing server environments, optimizing database performance, or recommending suitable homelab hardware, your goal is to provide accurate, actionable, and helpful responses tailored to the needs of the community members. In addition to offering direct assistance, you should also strive to foster a collaborative and supportive atmosphere within the chat room. Encourage knowledge sharing, facilitate discussions, and celebrate the achievements of community members as they tackle technical challenges and embark on learning journeys. By promoting a culture of learning and collaboration, you'll contribute to the growth and cohesion of the community, empowering individuals to expand their skill sets and achieve their goals within the realm of technology. As you engage with users within the chat room, prioritize brevity and clarity in your responses. While it's essential to provide comprehensive and accurate information, it's equally important to convey it in a concise and easily understandable manner. Avoid overly technical jargon or convoluted explanations that may confuse or overwhelm community members, opting instead for straightforward explanations and practical solutions whenever possible. Remember, your ultimate objective is to be a trusted ally and resource for the members of the community as they navigate the ever-evolving landscape of technology. By leveraging your expertise, empathy, and problem-solving abilities, you'll play a vital role in facilitating knowledge exchange, fostering collaboration, and empowering individuals to succeed in their technical endeavors. As you embark on this journey as a chatbot within the Matrix community, embrace the opportunity to make a meaningful and positive impact, one helpful interaction at a time. You will format the reply using minimal html instead of markdown. Do not use markdown formatting. Here is the prompt: "+prompt+"[/INST]",
|
||||||
"max_tokens": 1024,
|
"max_tokens": 1024,
|
||||||
"temperature": 1.31,
|
"temperature": 1.31,
|
||||||
"top_p": 0.14,
|
"top_p": 0.14,
|
||||||
@ -52,8 +57,14 @@ async def handle_command(room, message, bot, PREFIX):
|
|||||||
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 = 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>"
|
||||||
await bot.api.send_markdown_message(room.room_id, new_text)
|
await bot.api.send_markdown_message(room.room_id, new_text)
|
||||||
logging.info("Sent generated text to the room")
|
else:
|
||||||
|
await bot.api.send_markdown_message(room.room_id, new_text)
|
||||||
|
logging.info(f"Sent generated text to the room: {new_text}")
|
||||||
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}")
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
# plugins/commands.py
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import simplematrixbotlib as botlib
|
|
||||||
|
|
||||||
async def handle_command(room, message, bot, PREFIX):
|
|
||||||
"""
|
|
||||||
Function to handle the !commands 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("commands"):
|
|
||||||
logging.info("Fetching commands documentation")
|
|
||||||
commands_message = """
|
|
||||||
# 🍄 Funguy Bot Commands 🍄
|
|
||||||
|
|
||||||
🃏 **!fortune**
|
|
||||||
Returns a random fortune message.
|
|
||||||
Executes the `/usr/games/fortune` utility and sends the output as a message to the chat room.
|
|
||||||
|
|
||||||
⏰ **!date**
|
|
||||||
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.
|
|
||||||
|
|
||||||
💻 **!proxy**
|
|
||||||
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.
|
|
||||||
|
|
||||||
📶 **!isup [domain/ip]**
|
|
||||||
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.
|
|
||||||
|
|
||||||
☯ **!karma [user]**
|
|
||||||
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.
|
|
||||||
|
|
||||||
⇧ **!karma [user] up**
|
|
||||||
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.
|
|
||||||
|
|
||||||
⇩ **!karma [user] down**
|
|
||||||
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.
|
|
||||||
|
|
||||||
📄 **!funguy [prompt]
|
|
||||||
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: **TheBloke_Mistral-7B-Instruct-v0.2-GPTQ**
|
|
||||||
|
|
||||||
🎝 **!music [prompt]**
|
|
||||||
Your music expert! Try it out.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 🌟 Funguy Bot Credits 🌟
|
|
||||||
|
|
||||||
🧙♂️ Creator & Developer:
|
|
||||||
- Hash Borgir is the author of 🍄Funguy Bot🍄. (@hashborgir:mozilla.org)
|
|
||||||
|
|
||||||
# Join our Matrix Room:
|
|
||||||
|
|
||||||
[Self-hosting | Security | Sysadmin | Homelab | Programming](https://chat.mozilla.org/#/room/#selfhosting:mozilla.org)
|
|
||||||
"""
|
|
||||||
await bot.api.send_markdown_message(room.room_id, commands_message)
|
|
||||||
logging.info("Sent commands documentation to the room")
|
|
144
plugins/config.py
Normal file
144
plugins/config.py
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
# 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(f"Loaded configuration from {config_file}")
|
||||||
|
|
||||||
|
_admin_user: str = ""
|
||||||
|
_prefix: str = ""
|
||||||
|
_config_file: 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
|
||||||
|
|
||||||
|
@property
|
||||||
|
def config_file(self):
|
||||||
|
return self._config_file
|
||||||
|
|
||||||
|
@config_file.setter
|
||||||
|
def config_file(self, value):
|
||||||
|
self._config_file = 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(f"Loaded configuration from {config_file}")
|
||||||
|
|
||||||
|
|
||||||
|
# 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(f"Saved configuration to {config_file}")
|
||||||
|
|
||||||
|
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("saveconf"):
|
||||||
|
config.save_config(config.config_file)
|
||||||
|
await bot.api.send_text_message(room.room_id, "Configuration saved")
|
||||||
|
|
||||||
|
elif match.is_not_from_this_bot() and match.prefix() and match.command("loadconf"):
|
||||||
|
config.load_config(config.config_file)
|
||||||
|
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")
|
||||||
|
|
@ -1,10 +1,14 @@
|
|||||||
|
"""
|
||||||
|
This plugin provides a command to get the current date
|
||||||
|
"""
|
||||||
|
|
||||||
# plugins/date.py
|
# plugins/date.py
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import simplematrixbotlib as botlib
|
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.
|
Function to handle the !date command.
|
||||||
|
|
||||||
@ -15,7 +19,7 @@ async def handle_command(room, message, bot, PREFIX):
|
|||||||
Returns:
|
Returns:
|
||||||
None
|
None
|
||||||
"""
|
"""
|
||||||
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("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()
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
|
"""
|
||||||
|
This plugin provides a command to get a random fortune message.
|
||||||
|
"""
|
||||||
# plugins/fortune.py
|
# plugins/fortune.py
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import logging
|
import logging
|
||||||
import simplematrixbotlib as botlib
|
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 !fortune command.
|
Function to handle the !fortune command.
|
||||||
|
|
||||||
@ -15,7 +18,7 @@ async def handle_command(room, message, bot, PREFIX):
|
|||||||
Returns:
|
Returns:
|
||||||
None
|
None
|
||||||
"""
|
"""
|
||||||
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("fortune"):
|
if match.is_not_from_this_bot() and match.prefix() and match.command("fortune"):
|
||||||
logging.info("Received !fortune command")
|
logging.info("Received !fortune command")
|
||||||
fortune_output = "🃏 " + subprocess.run(['/usr/games/fortune'], capture_output=True).stdout.decode('UTF-8')
|
fortune_output = "🃏 " + subprocess.run(['/usr/games/fortune'], capture_output=True).stdout.decode('UTF-8')
|
||||||
|
71
plugins/help.py
Normal file
71
plugins/help.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
"""
|
||||||
|
This plugin provides a command to display the list of available commands and their descriptions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# plugins/help.py
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import simplematrixbotlib as botlib
|
||||||
|
|
||||||
|
async def handle_command(room, message, bot, prefix, config):
|
||||||
|
"""
|
||||||
|
Function to handle the !help 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("help"):
|
||||||
|
logging.info("Fetching command help documentation")
|
||||||
|
commands_message = """<details><summary><strong>🍄Funguy Bot Commands🍄<br>⤵︎Click Here To See Help Text⤵︎</strong></summary>
|
||||||
|
<br>
|
||||||
|
<br>🃏 **!fortune**
|
||||||
|
<br>Returns a random fortune message.
|
||||||
|
<br>Executes the `/usr/games/fortune` utility and sends the output as a message to the chat room.
|
||||||
|
<br>
|
||||||
|
<br>⏰ **!date**
|
||||||
|
<br>Displays the current date and time.
|
||||||
|
<br>Fetches the current date and time using Python's `datetime` module and sends it in a formatted message to the chat room.
|
||||||
|
<br>
|
||||||
|
<br>💻 **!proxy**
|
||||||
|
<br>Retrieves a tested/working random SOCKS5 proxy.
|
||||||
|
<br>Fetches a list of SOCKS5 proxies, tests their availability, and sends the first working proxy to the chat room.
|
||||||
|
<br>
|
||||||
|
<br>📶 **!isup [domain/ip]**
|
||||||
|
<br>Checks if the specified domain or IP address is reachable.
|
||||||
|
<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.
|
||||||
|
<br>
|
||||||
|
<br>☯ **!karma [user]**
|
||||||
|
<br>Retrieves the karma points for the specified user.
|
||||||
|
<br>Retrieves the karma points for the specified user from a database and sends them as a message to the chat room.
|
||||||
|
<br>
|
||||||
|
<br>⇧ **!karma [user] up**
|
||||||
|
<br>Increases the karma points for the specified user by 1.
|
||||||
|
<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.
|
||||||
|
<br>
|
||||||
|
<br>⇩ **!karma [user] down**
|
||||||
|
<br>Decreases the karma points for the specified user by 1.
|
||||||
|
<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.
|
||||||
|
<br>
|
||||||
|
<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.
|
||||||
|
<br>(Currently loaded model: **TheBloke_Mistral-7B-Instruct-v0.2-GPTQ**
|
||||||
|
<br>
|
||||||
|
<br>🎝 **!music [prompt]**
|
||||||
|
<br>Your music expert! Try it out.
|
||||||
|
<br> 🌟 Funguy Bot Credits 🌟
|
||||||
|
<br>
|
||||||
|
<br>🧙♂️ Creator & Developer:
|
||||||
|
<br> Hash Borgir is the author of 🍄Funguy Bot🍄. (@hashborgir:mozilla.org)
|
||||||
|
<br>
|
||||||
|
<br> Join our Matrix Room:
|
||||||
|
<br>
|
||||||
|
<br>[Self-hosting | Security | Sysadmin | Homelab | Programming](https://matrix.to/#/#selfhosting:mozilla.org)
|
||||||
|
<br>
|
||||||
|
<br></details>"""
|
||||||
|
await bot.api.send_markdown_message(room.room_id, commands_message)
|
||||||
|
logging.info("Sent help documentation to the room")
|
@ -1,3 +1,7 @@
|
|||||||
|
"""
|
||||||
|
This plugin provides a command to check if a website or server is up.
|
||||||
|
"""
|
||||||
|
|
||||||
# plugins/isup.py
|
# plugins/isup.py
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
@ -39,7 +43,7 @@ async def check_https(domain):
|
|||||||
except aiohttp.ClientError:
|
except aiohttp.ClientError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async def handle_command(room, message, bot, PREFIX):
|
async def handle_command(room, message, bot, prefix, config):
|
||||||
"""
|
"""
|
||||||
Function to handle the !isup command.
|
Function to handle the !isup command.
|
||||||
|
|
||||||
@ -50,7 +54,7 @@ async def handle_command(room, message, bot, PREFIX):
|
|||||||
Returns:
|
Returns:
|
||||||
None
|
None
|
||||||
"""
|
"""
|
||||||
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("isup"):
|
if match.is_not_from_this_bot() and match.prefix() and match.command("isup"):
|
||||||
logging.info("Received !isup command")
|
logging.info("Received !isup command")
|
||||||
args = match.args()
|
args = match.args()
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
|
"""
|
||||||
|
This plugin provides a command to manage karma points for users.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
# plugins/karma.py
|
# plugins/karma.py
|
||||||
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import logging
|
import logging
|
||||||
import simplematrixbotlib as botlib
|
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 !karma command.
|
Function to handle the !karma command.
|
||||||
|
|
||||||
@ -15,7 +20,7 @@ async def handle_command(room, message, bot, PREFIX):
|
|||||||
Returns:
|
Returns:
|
||||||
None
|
None
|
||||||
"""
|
"""
|
||||||
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("karma"):
|
if match.is_not_from_this_bot() and match.prefix() and match.command("karma"):
|
||||||
logging.info("Received !karma command")
|
logging.info("Received !karma command")
|
||||||
args = match.args()
|
args = match.args()
|
||||||
|
38
plugins/loadplugin.py
Normal file
38
plugins/loadplugin.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# plugins/load_plugin.py
|
||||||
|
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
import importlib
|
||||||
|
import simplematrixbotlib as botlib
|
||||||
|
|
||||||
|
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) == config.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.")
|
58
plugins/plugins.py
Normal file
58
plugins/plugins.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
"""
|
||||||
|
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, config):
|
||||||
|
"""
|
||||||
|
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, "<details><summary><strong>🔌Plugins List🔌<br>⤵︎Click Here to Expand⤵︎</strong></summary><br>")
|
||||||
|
|
||||||
|
plugins_message = "<br><br>".join(plugin_descriptions)
|
||||||
|
plugins_message += "</details>"
|
||||||
|
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"<strong>[{plugin_name}.py]:</strong> {description}")
|
||||||
|
|
||||||
|
# Sort the plugin descriptions alphabetically by plugin name
|
||||||
|
plugin_descriptions.sort()
|
||||||
|
|
||||||
|
return plugin_descriptions
|
@ -1,3 +1,7 @@
|
|||||||
|
"""
|
||||||
|
This plugin provides a command to get random SOCKS5 proxies.
|
||||||
|
"""
|
||||||
|
|
||||||
# plugins/proxy.py
|
# plugins/proxy.py
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@ -68,7 +72,7 @@ async def download_proxy_list():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
async def handle_command(room, message, bot, PREFIX):
|
async def handle_command(room, message, bot, prefix, config):
|
||||||
"""
|
"""
|
||||||
Function to handle the !proxy command.
|
Function to handle the !proxy command.
|
||||||
|
|
||||||
@ -79,7 +83,7 @@ async def handle_command(room, message, bot, PREFIX):
|
|||||||
Returns:
|
Returns:
|
||||||
None
|
None
|
||||||
"""
|
"""
|
||||||
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("proxy"):
|
if match.is_not_from_this_bot() and match.prefix() and match.command("proxy"):
|
||||||
logging.info("Received !proxy command")
|
logging.info("Received !proxy command")
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
"""
|
||||||
|
This plugin provides a command to fetch YouTube video information from links.
|
||||||
|
"""
|
||||||
|
|
||||||
# plugins/youtube.py
|
# plugins/youtube.py
|
||||||
|
|
||||||
import re
|
import re
|
||||||
@ -10,7 +14,7 @@ def seconds_to_minutes_seconds(seconds):
|
|||||||
seconds %= 60
|
seconds %= 60
|
||||||
return f"{minutes:02d}:{seconds:02d}"
|
return f"{minutes:02d}:{seconds:02d}"
|
||||||
|
|
||||||
async def handle_command(room, message, bot, PREFIX):
|
async def handle_command(room, message, bot, prefix, config):
|
||||||
"""
|
"""
|
||||||
Function to handle YouTube video information from links.
|
Function to handle YouTube video information from links.
|
||||||
|
|
||||||
@ -21,7 +25,7 @@ async def handle_command(room, message, bot, PREFIX):
|
|||||||
Returns:
|
Returns:
|
||||||
None
|
None
|
||||||
"""
|
"""
|
||||||
match = botlib.MessageMatch(room, message, bot)
|
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")
|
||||||
video_id_match = re.search(r'youtube\.com/watch\?v=([^\s]+)', message.body)
|
video_id_match = re.search(r'youtube\.com/watch\?v=([^\s]+)', message.body)
|
38
plugins/youtube-search.py
Normal file
38
plugins/youtube-search.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# plugins/youtube_search.py
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import simplematrixbotlib as botlib
|
||||||
|
from youtube_search import YoutubeSearch
|
||||||
|
|
||||||
|
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("yt"):
|
||||||
|
args = match.args()
|
||||||
|
if len(args) < 1:
|
||||||
|
await bot.api.send_text_message(room.room_id, "Usage: !yt <search terms>")
|
||||||
|
else:
|
||||||
|
search_terms = " ".join(args)
|
||||||
|
logging.info(f"Performing YouTube search for: {search_terms}")
|
||||||
|
results = YoutubeSearch(search_terms, max_results=3).to_dict()
|
||||||
|
if results:
|
||||||
|
output = generate_output(results)
|
||||||
|
await send_collapsible_message(room, bot, output)
|
||||||
|
else:
|
||||||
|
await bot.api.send_text_message(room.room_id, "No results found.")
|
||||||
|
|
||||||
|
def generate_output(results):
|
||||||
|
output = ""
|
||||||
|
for video in results:
|
||||||
|
output += f'<a href="https://www.youtube.com/watch?v={video["id"]}">'
|
||||||
|
output += f'<img src="{video["thumbnails"][0]}"></img><br>'
|
||||||
|
output += f'<strong>{video["title"]}</strong><br>'
|
||||||
|
output += f'Length: {video["duration"]} | Views: {video["views"]}<br>'
|
||||||
|
if video["long_desc"]:
|
||||||
|
output += f'Description: {video["long_desc"]}<br>'
|
||||||
|
output += "</a><br>"
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
async def send_collapsible_message(room, bot, content):
|
||||||
|
message = f'<details><summary><strong>🍄Funguy ▶YouTube Search🍄<br>⤵︎Click Here To See Results⤵︎</strong></summary>{content}</details>'
|
||||||
|
await bot.api.send_markdown_message(room.room_id, message)
|
Loading…
Reference in New Issue
Block a user