Compare commits

..

No commits in common. "96edec466e40ca682bb37b6e2408b8334b3fe84b" and "0c00cea0704d934e5e67329382edbdfbb28f32f0" have entirely different histories.

13 changed files with 973 additions and 11 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
.env
.gitignore
karma.db
proxies.db
proxy_lists/
session.txt
socks5.txt
venv/

View File

@ -1,9 +0,0 @@
MIT License
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,3 +1,80 @@
# FunguyBot
# Matrix Bot
Bot for the Matrix protocol/network using simplematrixbotlib
Matrix Bot is a Python-based chat bot designed to work with Matrix, an open network for secure, decentralized communication. This bot is built using the `simplematrixbotlib` library and provides various commands and functionalities for interacting with Matrix rooms.
## Features
- Modular architecture: Commands are implemented as separate plugins, making it easy to add or modify functionality.
- Command handling: The bot listens for specific commands prefixed with `!` and responds accordingly.
- Plugin system: Each command is implemented as a separate plugin module, allowing for easy customization and extension.
- Extensible: Users can add new commands by creating additional plugin modules.
## Installation
1. Clone the repository:
`git clone https://github.com/example/matrix-bot.git`
2. Install dependencies:
`pip install -r requirements.txt`
3. Set up environment variables:
Create a `.env` file in the root directory of the bot and add the following variables:
```
MATRIX_URL="https://matrix.org" (or another homeserver)
MATRIX_USER=""
MATRIX_PASS=""
```
4. Run the bot:
1. `python funguy.py`, or
2. `chmod +x funguy.py`
`./bot.py`
## Usage
To use the bot, invite it to a Matrix room and interact with it by sending commands prefixed with `!`. For example:
- `!date`: Display the current date and time.
- `!fortune`: Get a random fortune message.
- `!proxy`: Retrieve and test random SOCKS5 and HTTP proxies.
- `!isup <domain/ip>`: Check if the specified domain or IP address is reachable.
- `!karma <user>`: View or modify karma points for a user.
For a complete list of available commands and their descriptions, use the `!commands` command.
# 🍄 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 Bot Credits 🌟
🧙‍♂️ Creator & Developer: Hash Borgir (HB): Hash Borgir, with a background in computer science and cybersecurity, is the author of 🍄Funguy Bot🍄.

64
funguy.py Executable file
View File

@ -0,0 +1,64 @@
#!/usr/bin/env python
# bot.py
import os
import logging
import importlib
import simplematrixbotlib as botlib
from dotenv import load_dotenv
import time
# 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
logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', level=logging.INFO)
# Load plugins
PLUGINS_DIR = "plugins"
PLUGINS = {}
def load_plugins():
for plugin_file in os.listdir(PLUGINS_DIR):
if plugin_file.endswith(".py"):
plugin_name = os.path.splitext(plugin_file)[0]
try:
module = importlib.import_module(f"{PLUGINS_DIR}.{plugin_name}")
PLUGINS[plugin_name] = module
logging.info(f"Loaded plugin: {plugin_name}")
except Exception as e:
logging.error(f"Error loading plugin {plugin_name}: {e}")
def reload_plugins():
global PLUGINS
PLUGINS = {}
load_plugins()
load_plugins()
@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:
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)
bot.run()

326
hcbot.py Executable file
View File

@ -0,0 +1,326 @@
#!/usr/bin/env python
import subprocess
import sqlite3
import time
import os
import random
import socket
from urllib.parse import urlparse
import datetime
import simplematrixbotlib as botlib
import requests
from pytube import YouTube
import logging
import inspect
MATRIX_URL = "https://matrix.org"
MATRIX_USER = "@hcbot:matrix.org"
MATRIX_PASS = "W4iy$nt^qp~&$K~$w@@jEhnT"
creds = botlib.Creds(MATRIX_URL, MATRIX_USER, MATRIX_PASS)
bot = botlib.Bot(creds)
PREFIX = '!'
# Setup logging
logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', level=logging.INFO)
# Database setup
conn = sqlite3.connect('karma.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS karma
(username TEXT PRIMARY KEY, points INTEGER)''')
conn.commit()
conn.close()
async def ping_proxy(proxy):
"""
Ping a proxy server to check its availability.
Args:
proxy (str): The proxy server address in the format 'ip:port'.
Returns:
float or str: The ping time in milliseconds if the proxy is up, or 'N/A' if it's down.
"""
ip, port = proxy.split(':')
start_time = time.time()
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
result = sock.connect_ex((ip, int(port)))
if result == 0:
return round((time.time() - start_time) * 1000, 2)
except Exception as e:
logging.error(f"Error pinging proxy {proxy}: {e}")
return "N/A"
@bot.listener.on_message_event
async def commands(room, message):
"""
Command to display the list of available commands and their descriptions.
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 = """
**Available Commands:**
**!fortune**
Returns a random fortune message.
**!date**
Displays the current date and time.
**!proxy**
Retrieves and tests random SOCKS5 and HTTP proxies.
**!isup <domain/ip>**
Checks if the specified domain or IP address is reachable.
**!karma <user>**
Retrieves the karma points for the specified user.
**!karma <user> up**
Increases the karma points for the specified user by 1.
**!karma <user> down**
Decreases the karma points for the specified user by 1.
"""
await bot.api.send_markdown_message(room.room_id, commands_message)
logging.info("Sent commands documentation to the room")
@bot.listener.on_message_event
async def fortune(room, message):
"""
Command to get a random fortune.
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("fortune"):
logging.info("Received !fortune command")
fortune_output = subprocess.run(['/usr/games/fortune'], capture_output=True).stdout.decode('UTF-8')
await bot.api.send_text_message(room.room_id, fortune_output)
logging.info("Sent fortune to the room")
@bot.listener.on_message_event
async def date(room, message):
"""
Command to get the current date and time.
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")
@bot.listener.on_message_event
async def proxy(room, message):
"""
Command to get random SOCKS5 and HTTP proxies.
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("proxy"):
logging.info("Received !proxy command")
socks5_proxies = requests.get('https://raw.githubusercontent.com/TheSpeedX/SOCKS-List/master/socks5.txt').text.splitlines()
http_proxies = requests.get('https://raw.githubusercontent.com/TheSpeedX/SOCKS-List/master/http.txt').text.splitlines()
random_socks5_proxy = random.choice(socks5_proxies)
random_http_proxy = random.choice(http_proxies)
socks5_ping = await ping_proxy(random_socks5_proxy)
http_ping = await ping_proxy(random_http_proxy)
await bot.api.send_text_message(room.room_id, f"Random SOCKS5 Proxy: {random_socks5_proxy} - Ping time: {socks5_ping} ms")
await bot.api.send_text_message(room.room_id, f"Random HTTP Proxy: {random_http_proxy} - Ping time: {http_ping} ms")
logging.info("Sent proxies to the room")
@bot.listener.on_message_event
async def isup(room, message):
"""
Command to check if a website or server is up.
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("isup"):
logging.info("Received !isup command")
args = match.args()
if len(args) != 1:
await bot.api.send_text_message(room.room_id, "Usage: !isup <ipv4/ipv6/domain>")
logging.info("Sent usage message to the room")
return
target = args[0]
try:
response = os.system(f"ping -c 1 {target}")
if response == 0:
await bot.api.send_text_message(room.room_id, f"{target} is up")
else:
await bot.api.send_text_message(room.room_id, f"{target} is down")
logging.info(f"Sent status of {target} to the room")
except Exception as e:
await bot.api.send_text_message(room.room_id, f"Error: {e}")
logging.error(f"Error occurred while checking {target}: {e}")
@bot.listener.on_message_event
async def karma(room, message):
"""
Command to manage karma points for users.
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("karma"):
logging.info("Received !karma command")
args = match.args()
sender = str(message.sender)
if len(args) == 0:
# Query sender's own karma
conn = sqlite3.connect('karma.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS karma
(username TEXT PRIMARY KEY, points INTEGER)''')
c.execute('''INSERT OR IGNORE INTO karma (username, points) VALUES (?, ?)''', (sender, 0))
c.execute('''SELECT points FROM karma WHERE username = ?''', (sender,))
points = c.fetchone()[0]
conn.close()
await bot.api.send_text_message(room.room_id, f"{sender}'s karma points: {points}")
logging.info(f"Sent {sender}'s karma points ({points}) to the room")
elif len(args) == 1:
username = args[0]
if username == sender:
await bot.api.send_text_message(room.room_id, "You cannot modify your own karma.")
logging.info("Sent self-modification warning message to the room")
return
conn = sqlite3.connect('karma.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS karma
(username TEXT PRIMARY KEY, points INTEGER)''')
c.execute('''INSERT OR IGNORE INTO karma (username, points) VALUES (?, ?)''', (username, 0))
c.execute('''SELECT points FROM karma WHERE username = ?''', (username,))
points = c.fetchone()[0]
conn.close()
await bot.api.send_text_message(room.room_id, f"{username}'s karma points: {points}")
logging.info(f"Sent {username}'s karma points ({points}) to the room")
elif len(args) == 2:
username, action = args
if action not in ['up', 'down']:
await bot.api.send_text_message(room.room_id, "Invalid action. Use 'up' or 'down'.")
logging.info("Sent invalid action message to the room")
return
if username == sender:
await bot.api.send_text_message(room.room_id, "You cannot modify your own karma.")
logging.info("Sent self-modification warning message to the room")
return
conn = sqlite3.connect('karma.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS karma
(username TEXT PRIMARY KEY, points INTEGER)''')
if action == 'up':
c.execute('''UPDATE karma SET points = points + 1 WHERE username = ?''', (username,))
else:
c.execute('''UPDATE karma SET points = points - 1 WHERE username = ?''', (username,))
conn.commit()
c.execute('''SELECT points FROM karma WHERE username = ?''', (username,))
points = c.fetchone()[0]
conn.close()
await bot.api.send_text_message(room.room_id, f"{username}'s karma points: {points}")
logging.info(f"Sent {username}'s karma points ({points}) to the room")
else:
await bot.api.send_text_message(room.room_id, "Usage: !karma [username] [up/down]")
logging.info("Sent usage message to the room")
import re
@bot.listener.on_message_event
async def youtube(room, message):
"""
Command to fetch 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)
if match.is_not_from_this_bot() and re.search(r'youtube\.com/watch\?v=', message.body):
logging.info("YouTube link detected")
video_id_match = re.search(r'youtube\.com/watch\?v=([^\s]+)', message.body)
if video_id_match:
video_id = video_id_match.group(1)
youtube_url = f"https://www.youtube.com/watch?v={video_id}"
logging.info(f"Fetching information for YouTube video: {youtube_url}")
try:
video = YouTube(youtube_url)
title = video.title
description = video.description
length = video.length
views = video.views
author = video.author
info_message = f"""Title: {title} | Length: {length} seconds | Views: {views} | Description: {description}"""
await bot.api.send_markdown_message(room.room_id, info_message)
logging.info("Sent YouTube video information to the room")
except Exception as e:
logging.error(f"Error fetching YouTube video information: {str(e)}")
await bot.api.send_text_message(room.room_id, "Error fetching YouTube video information.")
bot.run()

70
plugins/commands.py Normal file
View File

@ -0,0 +1,70 @@
# 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 Bot Credits 🌟
🧙 Creator & Developer: Hash Borgir (HB)
🎓 Academic Achievements:
- Bachelor of Computer Science (2004)
- Bachelor of Science, Cybersecurity & Information Assurance (2023)
- Master of Science, Cybersecurity & Information Assurance (ongoing)
🔐 Certifications:
- A+, Net+, Sec+, CySA+, Pentest+, Project+, ECES, ITILv4, SSCP, CCSP, MCP, MCSE
💼 Professional Profile:
- Website: [Hash Security](https://www.hashsecurity.net)
Hash Borgir, with a rich background in computer science and cybersecurity, is the author of 🍄Funguy Bot🍄.
"""
await bot.api.send_markdown_message(room.room_id, commands_message)
logging.info("Sent commands documentation to the room")

28
plugins/date.py Normal file
View File

@ -0,0 +1,28 @@
# plugins/date.py
import datetime
import logging
import simplematrixbotlib as botlib
async def handle_command(room, message, bot, 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")

23
plugins/fortune.py Normal file
View File

@ -0,0 +1,23 @@
# plugins/fortune.py
import subprocess
import logging
import simplematrixbotlib as botlib
async def handle_command(room, message, bot, PREFIX):
"""
Function to handle the !fortune 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("fortune"):
logging.info("Received !fortune command")
fortune_output = "🃏 " + subprocess.run(['/usr/games/fortune'], capture_output=True).stdout.decode('UTF-8')
await bot.api.send_markdown_message(room.room_id, fortune_output)
logging.info("Sent fortune to the room")

83
plugins/isup.py Normal file
View File

@ -0,0 +1,83 @@
# plugins/isup.py
import logging
import aiohttp
import socket
import simplematrixbotlib as botlib
async def check_http(domain):
"""
Check if HTTP service is up for the given domain.
Args:
domain (str): The target domain.
Returns:
bool: True if HTTP service is up, False otherwise.
"""
try:
async with aiohttp.ClientSession() as session:
async with session.get(f"http://{domain}") as response:
return response.status == 200
except aiohttp.ClientError:
return False
async def check_https(domain):
"""
Check if HTTPS service is up for the given domain.
Args:
domain (str): The target domain.
Returns:
bool: True if HTTPS service is up, False otherwise.
"""
try:
async with aiohttp.ClientSession() as session:
async with session.get(f"https://{domain}") as response:
return response.status == 200
except aiohttp.ClientError:
return False
async def handle_command(room, message, bot, PREFIX):
"""
Function to handle the !isup 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("isup"):
logging.info("Received !isup command")
args = match.args()
if len(args) != 1:
await bot.api.send_markdown_message(room.room_id, "Usage: !isup <ipv4/ipv6/domain>")
logging.info("Sent usage message to the room")
return
target = args[0]
# DNS resolution
try:
ip_address = socket.gethostbyname(target)
logging.info(f"DNS resolution successful for {target}: {ip_address}")
await bot.api.send_markdown_message(room.room_id, f"✅ DNS resolution successful for **{target}**: **{ip_address}** (A record)")
except socket.gaierror:
logging.info(f"DNS resolution failed for {target}")
await bot.api.send_markdown_message(room.room_id, f"❌ DNS resolution failed for **{target}**")
return
# Check HTTP/HTTPS services
if await check_http(target):
await bot.api.send_markdown_message(room.room_id, f"🖧 **{target}** HTTP service is up")
logging.info(f"{target} HTTP service is up")
elif await check_https(target):
await bot.api.send_markdown_message(room.room_id, f"🖧 **{target}** HTTPS service is up")
logging.info(f"{target} HTTPS service is up")
else:
await bot.api.send_markdown_message(room.room_id, f"😕 **{target}** HTTP/HTTPS services are down")
logging.info(f"{target} HTTP/HTTPS services are down")

101
plugins/karma.py Normal file
View File

@ -0,0 +1,101 @@
# plugins/karma.py
import sqlite3
import logging
import simplematrixbotlib as botlib
async def handle_command(room, message, bot, PREFIX):
"""
Function to handle the !karma 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("karma"):
logging.info("Received !karma command")
args = match.args()
sender = str(message.sender)
if len(args) == 0:
# Query sender's own karma
conn = sqlite3.connect('karma.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS karma
(username TEXT PRIMARY KEY, points INTEGER)''')
c.execute('''INSERT OR IGNORE INTO karma (username, points) VALUES (?, ?)''', (sender, 0))
c.execute('''SELECT points FROM karma WHERE username = ?''', (sender,))
row = c.fetchone()
if row is not None:
points = row[0]
await bot.api.send_markdown_message(room.room_id, f"💗 {sender}'s karma points: {points}")
logging.info(f"Sent {sender}'s karma points ({points}) to the room")
else:
await bot.api.send_markdown_message(room.room_id, f"💗 {sender} does not have any karma points yet.")
logging.info(f"Sent message that {sender} does not have any karma points yet.")
conn.close()
elif len(args) == 1:
username = args[0]
if username == sender:
await bot.api.send_markdown_message(room.room_id, "❌ You cannot modify your own karma.")
logging.info("Sent self-modification warning message to the room")
return
conn = sqlite3.connect('karma.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS karma
(username TEXT PRIMARY KEY, points INTEGER)''')
c.execute('''INSERT OR IGNORE INTO karma (username, points) VALUES (?, ?)''', (username, 0))
c.execute('''SELECT points FROM karma WHERE username = ?''', (username,))
row = c.fetchone()
if row is not None:
points = row[0]
await bot.api.send_markdown_message(room.room_id, f"💗 {username}'s karma points: {points}")
logging.info(f"Sent {username}'s karma points ({points}) to the room")
else:
await bot.api.send_markdown_message(room.room_id, f"💗 {username} does not have any karma points yet.")
logging.info(f"Sent message that {username} does not have any karma points yet.")
conn.close()
elif len(args) == 2:
username, action = args
if action not in ['up', 'down']:
await bot.api.send_markdown_message(room.room_id, "❌ Invalid action. Use 'up' or 'down'.")
logging.info("Sent invalid action message to the room")
return
if username == sender:
await bot.api.send_markdown_message(room.room_id, "❌ You cannot modify your own karma.")
logging.info("Sent self-modification warning message to the room")
return
conn = sqlite3.connect('karma.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS karma
(username TEXT PRIMARY KEY, points INTEGER)''')
if action == 'up':
c.execute('''INSERT OR IGNORE INTO karma (username, points) VALUES (?, ?)''', (username, 0))
c.execute('''UPDATE karma SET points = points + 1 WHERE username = ?''', (username,))
else:
c.execute('''INSERT OR IGNORE INTO karma (username, points) VALUES (?, ?)''', (username, 0))
c.execute('''UPDATE karma SET points = points - 1 WHERE username = ?''', (username,))
conn.commit()
c.execute('''SELECT points FROM karma WHERE username = ?''', (username,))
row = c.fetchone()
if row is not None:
points = row[0]
await bot.api.send_markdown_message(room.room_id, f"💗 {username}'s karma points: {points}")
logging.info(f"Sent {username}'s karma points ({points}) to the room")
else:
await bot.api.send_markdown_message(room.room_id, f"💗 {username} does not have any karma points yet.")
logging.info(f"Sent message that {username} does not have any karma points yet.")
conn.close()
else:
await bot.api.send_markdown_message(room.room_id, "☯ Usage: !karma [username] [up/down]")
logging.info("Sent usage message to the room")

116
plugins/proxy.py Normal file
View File

@ -0,0 +1,116 @@
# plugins/proxy.py
import os
import logging
import random
import requests
import socket
import ssl
import time
from datetime import datetime, timedelta
import simplematrixbotlib as botlib
# Constants
SOCKS5_LIST_URL = 'https://raw.githubusercontent.com/TheSpeedX/SOCKS-List/master/socks5.txt'
MAX_TRIES = 5
PROXY_LIST_FILENAME = 'socks5.txt'
PROXY_LIST_EXPIRATION = timedelta(hours=8)
async def test_socks5_proxy(proxy):
"""
Test a SOCKS5 proxy by attempting a connection and sending a request through it.
Args:
proxy (str): The SOCKS5 proxy address in the format 'ip:port'.
Returns:
bool: True if the proxy is working, False otherwise.
float: The latency in milliseconds if the proxy is working, None otherwise.
"""
try:
ip, port = proxy.split(':')
start_time = time.time()
with socket.create_connection((ip, int(port)), timeout=5) as client:
client.sendall(b'\x05\x01\x00')
response = client.recv(2)
if response == b'\x05\x00':
latency = int(round((time.time() - start_time) * 1000, 0))
logging.info(f"Successful connection to SOCKS5 proxy {proxy}. Latency: {latency} ms")
return True, latency
else:
logging.info(f"Failed to connect to SOCKS5 proxy {proxy}: Connection refused")
return False, None
except Exception as e:
logging.error(f"Error testing SOCKS5 proxy {proxy}: {e}")
return False, None
async def download_proxy_list():
"""
Download the SOCKS5 proxy list file if it doesn't already exist or if it's expired.
Returns:
bool: True if the proxy list is downloaded or up-to-date, False otherwise.
"""
try:
if not os.path.exists(PROXY_LIST_FILENAME) or \
datetime.now() - datetime.fromtimestamp(os.path.getctime(PROXY_LIST_FILENAME)) > PROXY_LIST_EXPIRATION:
logging.info("Downloading SOCKS5 proxy list")
response = requests.get(SOCKS5_LIST_URL, timeout=5)
with open(PROXY_LIST_FILENAME, 'w') as f:
f.write(response.text)
logging.info("Proxy list downloaded successfully")
return True
else:
logging.info("Proxy list already exists and is up-to-date")
return True
except Exception as e:
logging.error(f"Error downloading proxy list: {e}")
return False
async def handle_command(room, message, bot, PREFIX):
"""
Function to handle the !proxy 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("proxy"):
logging.info("Received !proxy command")
# Download proxy list if needed
if not await download_proxy_list():
await bot.api.send_markdown_message(room.room_id, "Error downloading proxy list")
logging.error("Error downloading proxy list")
return
try:
# Read proxies from file
with open(PROXY_LIST_FILENAME, 'r') as f:
socks5_proxies = f.read().splitlines()
random.shuffle(socks5_proxies)
# Test proxies
socks5_proxy = None
for proxy in socks5_proxies[:MAX_TRIES]:
success, latency = await test_socks5_proxy(proxy)
if success:
socks5_proxy = proxy
break
# Send the first working anonymous proxy of each type to the Matrix room
if socks5_proxy:
await bot.api.send_markdown_message(room.room_id, f"✅ Anonymous SOCKS5 Proxy: **{socks5_proxy}** - Latency: **{latency} ms**")
logging.info(f"Sent SOCKS5 proxy {socks5_proxy} to the room")
else:
await bot.api.send_markdown_message(room.room_id, "❌ No working anonymous SOCKS5 proxy found")
logging.info("No working anonymous SOCKS5 proxy found")
except Exception as e:
logging.error(f"Error handling !proxy command: {e}")
await bot.api.send_markdown_message(room.room_id, "❌ Error handling !proxy command")

39
plugins/youtube.py Normal file
View File

@ -0,0 +1,39 @@
# plugins/youtube.py
import re
import logging
from pytube import YouTube
import simplematrixbotlib as botlib
async def handle_command(room, message, bot, PREFIX):
"""
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)
if match.is_not_from_this_bot() and re.search(r'youtube\.com/watch\?v=', message.body):
logging.info("YouTube link detected")
video_id_match = re.search(r'youtube\.com/watch\?v=([^\s]+)', message.body)
if video_id_match:
video_id = video_id_match.group(1)
youtube_url = f"https://www.youtube.com/watch?v={video_id}"
logging.info(f"Fetching information for YouTube video: {youtube_url}")
try:
video = YouTube(youtube_url)
title = video.title
description = video.description
length = video.length
views = video.views
author = video.author
info_message = f"""**🎬🎝 Title:** {title} | **Length**: {length} sec | **Views:** {views} | **Description:** {description}"""
await bot.api.send_markdown_message(room.room_id, info_message)
logging.info("Sent YouTube video information to the room")
except Exception as e:
logging.error(f"Error fetching YouTube video information: {str(e)}")
# await bot.api.send__message(room.room_id, "Error fetching YouTube video information.")

36
requirements.txt Normal file
View File

@ -0,0 +1,36 @@
aiofiles==23.2.1
aiohttp==3.9.3
aiohttp-socks==0.7.1
aiosignal==1.3.1
async-timeout==4.0.3
attrs==23.2.0
certifi==2024.2.2
cffi==1.16.0
charset-normalizer==3.3.2
cryptography==42.0.2
frozenlist==1.4.1
h11==0.14.0
h2==4.1.0
hpack==4.0.0
hyperframe==6.0.1
idna==3.6
jsonschema==4.21.1
jsonschema-specifications==2023.12.1
Markdown==3.5.2
matrix-nio==0.23.0
multidict==6.0.5
pillow==10.2.0
pycparser==2.21
pycryptodome==3.20.0
python-cryptography-fernet-wrapper==1.0.4
python-dotenv==1.0.1
python-socks==2.4.4
pytube==15.0.0
referencing==0.33.0
requests==2.31.0
rpds-py==0.17.1
simplematrixbotlib==2.10.3
toml==0.10.2
unpaddedbase64==2.1.0
urllib3==2.2.0
yarl==1.9.4