Compare commits

...

25 Commits

Author SHA1 Message Date
Qemlokriu 1329932262 REmoved all the options that are related to the webserver plugin. As it will be in its own file once it actually works. Also make the e in Essentials capital as when you clone the repo it has big E instead of e as in the conf file before. 2 years ago
supopur a77926b1e2 Merged dev into here 2 years ago
supopur 17c727d225 Intents all as +rep didnt work with Essentials i will make this a conf option 2 years ago
Qemlokriu 35646be4f8 Update 'README.md' 2 years ago
supopur 919bd48ecf Added some stuff to pipstuff.txt and did some things i forgot... 2 years ago
supopur 14f9e571da added some usefull commands tha cli api seems to be pretty solid i dont know about registering cli commands at runtime havent tested yet or from another cog... 2 years ago
supopur c639176828 I made a very buggy version of the api. Also i droped the load and unload feature from the api i might bring it back. But now it was just too useless and broken. 2 years ago
supopur 6b3cd255bb Merge branch 'main' of http://192.168.50.7:3000/git/mee2 2 years ago
supopur dac8c6516f Last commit before doing a major update 2 years ago
Qemlokriu 7bc1c459f1 fixed the port as cf is wierd af 2 years ago
Qemlokriu a38ad186e7 Update 'README.md' 2 years ago
supopur 0097d0557c Fixed minor bugs 2 years ago
supopur bad8460276 forgot the await 2 years ago
supopur ae563158b7 Made sure that there is ctx.defer() so we no longer get Unknown interaction errors. 2 years ago
supopur 91a75ff9c8 Introducing the brand new API capable of not a lot at this time. But i am expanding it rn. 2 years ago
supopur 9ba31e8284 Merge branch 'main' of http://192.168.50.7:3000/git/mee2 2 years ago
supopur 2561a3c157 I started to implement a API mainly for cogs so they can comunicate with eachother. Also this will reduce the lines of code in cogs. Also it is handy for saving to the main log and writing to the config as it will reduce the chance of corruption of file. 2 years ago
supopur 0bd4c0cc43 Cleaned the repo a lil 2 years ago
Qemlokriu ae4843f4b8 Add 'README.md' 2 years ago
supopur abfdd75dd0 I just forgot to import some module silly me. Also i forgot to move the static and templates folders 2 years ago
supopur 3bb0511ef9 I just forgot to import some module silly me 2 years ago
supopur 6d8c1c066a Made web ui into a cog it doesnt work yet but it doesnt throw errors. All pages are 404. Tho the web responds to get calls wich is good 2 years ago
supopur 63d82f5785 cogs now work. Also i added logging and some try catch thingies. I will convert the web interface into a cog the next commit or atleast i hope 2 years ago
supopur 19207cd26b Ok nvm im so stupid now the token is safe in a env variable. I will do some docs in a while. It will be hosted on Gitea 2 years ago
supopur 4a8c4950e0 No more leaking my token 2 years ago

19
.gitignore vendored

@ -0,0 +1,19 @@
# Ignore Python cache files
__pycache__/
*.pyc
*.pyo
*.pyd
# Ignore other non-needed Python files
*.pyc
*.pyo
*.egg-info/
dist/
# Ignore the meetoo async file and build directory
meetoo.async
build/
# Ignore the cogs directory
cogs/

@ -0,0 +1,35 @@
# Mee2
Mee2 is a fully customizable, open-source Discord bot with a web interface to control it. It supports plugins and is heavily customizable. Mee2 is forever free and licensed under GNU V3.
## Status
Mee2 is still actively maintained, but it's not yet ready for public use. Pull requests are welcome. You can find the latest version on our Gitea repo: https://git.nazev.eu:8443/
## Features
- Web interface to control the bot
- Plugins support
- Highly customizable
- Fully open-source
- Forever free
## Plugins
The official plugins can be downloaded at [our gitea repo](https://git.nazev.eu:8443/MEE2_Official_plugins).
The installation might be diffrent on every plugin so be sure to check README.md of the plugin. But in general here are the install steps of a normal plugin:
To install a plugin download the git repo and extract the zip. There should be a folder with the name of the plugin. Drag that folder over to {meetooroot}/cogs and open {meetooroot}/config.toml and under section [bot] you should see cogs=[] add the following to the [] brackets"cogs.{pluginname}.{pluginname}".
## Contributing
We welcome contributions to Mee2! To contribute, please clone the repository and make your changes. Then, open a pull request on our Gitea repo.
## Discord
Join our Discord server to get support, ask questions, or contribute to Mee2 development: https://discord.gg/dVVVSM4z
## License
Mee2 is licensed under the GNU V3 license. See LICENSE.md for details.

@ -1,21 +1,3 @@
#The config is auto generated in the web interface do not change unless you know what you are doing.
[webserver]
#set to false if you dont have a certificate
usessl = true
port = "5000"
#DO NOT USE IN PRODUCTION. Do not even use flask it is recomended to use a production ready wsgi server such as gunicorn
debug = true
#Leave it like this if you dont know what your doing.
ip = "0.0.0.0"
crt = "certs/certificate.crt"
key = "certs/private.key"
[bot] [bot]
cogs=["cogs.Essentials.commands"]
guild_ids=["823188238260633600"]
[commands]
hello=false
stop=false

@ -1 +0,0 @@
token="MTAwNDgwODA4OTgzNDM3MzIzMA.GeCLNB.JmmGESI2peVqyaaPFlFJUEVG-6SI7LGh3x-Ysc"

@ -1,65 +1,346 @@
import discord, flask, os, quart, sys, toml, time, datetime import discord, os, sys, toml, time, datetime, logging, threading, asyncio, readline, importlib
from quart import render_template
from quart.helpers import make_response
from discord.ext import commands
from discord.ext import commands
with open("config.toml", "r") as f: with open("config.toml", "r") as f:
config = toml.load(f) config = toml.load(f)
with open("creds.toml", "r") as f: try:
creds = toml.load(f) os.remove("main.log")
except: pass
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler = logging.FileHandler('main.log')
handler.setFormatter(formatter)
logger = logging.getLogger('')
logger.addHandler(handler)
logger.setLevel(logging.INFO)
#logging.basicConfig(filename='main.log', encoding='utf-8', level=logging.DEBUG)
#logging.getLogger().addHandler(logging.StreamHandler())
def log(level, log):
if level == "inf":
logger.info(log)
elif level == "wrn":
logger.warning(log)
elif level == "dbg":
logger.debug(log)
elif level == "err":
logger.error(log)
log("inf", "Logging utility set up.")
try:
token = os.environ.get('MEETOO_TOKEN')
except:
log("err", 'Error no token is present type: export MEETOO_TOKEN="[Your token here]" into your terminall NOW!')
if token == "":
log("err", 'Error no token is present type: export MEETOO_TOKEN="[Your token here]" into your terminall NOW!')
log("dbg", f"Token is: {token}")
start_time = time.time() start_time = time.time()
print(creds)
intents = discord.Intents.default()
intents.members = True
bot = commands.Bot(command_prefix='!', intents=intents)
bot = commands.Bot(command_prefix='!', intents=discord.Intents.all())
logger.debug("Loaded the client.")
#Api used mainly for plugins so getting uptime, loading, unloading, reloading plugins, getting status of plugins, get plugin info, stopping the bot, getting bot name and tag, getting cpm/commands per minute, get if there is web plugin, if there is web plugin register api, get if plugin supports web and so on..
class API:
#Returns config.tomls content in a array.
def get_config(self):
return self.config
#Dumps all the toml data from self.config and stores it inside toml.config
def save_config(self):
try:
with open("config.toml", w) as f:
self.log("inf", "Saving the configuration file...")
toml.dump(self.config, f)
self.log("inf", "Config was saved to config.toml")
#aok
return 0
#In case file doesnt exist
except Exception as e:
self.log("err", f"Failed to save to config.toml. {e}")
return 1
#Connect the main .log file to the api so plugins can log to latest.log w/o risking corrupting the file. Absolutly useless as you can do: self.bot.api.logger("inf", "Hello w/o some useless function")
def log(self, status, log):
self.logger(str(status), str(log))
#Get the uptime of the root of the bot
def uptime(self):
uptime = time.time() - self.start_time
return uptime
def __init__(self, config, bot, log, token):
self.start_time = time.time()
self.config = config
self.bot = bot
self.logger = log
self.token = token
self.guild_ids = config["bot"]["guild_ids"]
#This is the most basic interface CLI wich is basically a comand line that appears when you launch the app it will have commands like stop, help, commands, cogs, load, unload and so on..
class CLI:
def register_command(self, command, function, description):
self.api.logger("inf", f"Trying to register {command} into the CLI commands...")
if command in self.cli_cmds:
self.api.logger("wrn", f"The command {command} already exists.")
return 1
if not callable(function):
self.api.logger("err", f"Unable to register {command} as the passed function is not callable.")
return 1
try:
command = str(command)
description = str(description)
except:
self.api.logger("err", f"Passed cli name or description is not convertable to string.")
return 1
dictionary = {"description": description, "function": function}
try:
self.cli_cmds[command] = dictionary
except:
return 1
else:
self.api.logger("inf", f"CLI Command: {command} registered.")
return 0
def remove_command(self, command):
self.api.logger("inf", f"Trying to remove {command} from the CLI commands...")
if command in self.cli_cmds:
self.cli_cmds[command] = None
self.api.logger("inf", f"Command {command} removed.")
return 0
else:
self.api.logger("wrn", f"Command {command} could not be removed as it doesnt exist.")
return 1
def handle_input(self, user_input):
# Split the user input into command and arguments
parts = user_input.strip().split()
if not parts:
return
command_name = parts[0]
args = parts[1:]
# Find the command
command = self.cli_cmds.get(command_name)
if not command:
# Suggest commands based on input
suggestions = [cmd_name for cmd_name in self.cli_cmds
if cmd_name.startswith(command_name)]
if suggestions:
print(f"Unknown command '{command_name}'. Did you mean one of these?")
for suggestion in suggestions:
print(f" - {suggestion}")
else:
print(f"Unknown command '{command_name}'")
return
# Execute the command
function = command["function"]
try:
function(self, *args)
except TypeError as e:
print(f"Invalid arguments: {e}")
def run(self):
# Start the CLI loop
while True:
try:
user_input = input(self.prompt)
except KeyboardInterrupt:
# Handle CTRL+C
break
except EOFError:
# Handle CTRL+D
break
else:
self.handle_input(user_input)
#Init of the class where all the values inside self are defined. Takes a loaded api as a arg
def __init__(self, api):
self.api = api
self.cli_cmds = {}
self.prompt = "mee2> "
@bot.event @bot.event
async def on_ready(): async def on_ready():
print(f"We have logged in as {bot.user}") log("inf", f"We have logged in as {bot.user}")
@bot.slash_command(guild_ids=["823188238260633600"])
async def hello(ctx):
await ctx.respond("Hello!")
@bot.slash_command(guild_ids=["823188238260633600"]) @bot.slash_command(guild_ids=config["bot"]["guild_ids"])
async def stop(ctx): async def stop(ctx):
await ctx.defer()
if ctx.author.guild_permissions.administrator: if ctx.author.guild_permissions.administrator:
print("Terminating the bot...") print("Terminating the bot...")
await ctx.respond("https://media4.giphy.com/media/CC5MVO9Jx4RqMQRfvT/giphy.gif") try:
await ctx.respond("https://media4.giphy.com/media/CC5MVO9Jx4RqMQRfvT/giphy.gif")
except:
pass
sys.exit("Terminated.") sys.exit("Terminated.")
else: else:
await ctx.respond("https://media.tenor.com/Iv6oKRuAhVEAAAAC/hal9000-im-sorry-dave.gif") await ctx.respond("https://media.tenor.com/Iv6oKRuAhVEAAAAC/hal9000-im-sorry-dave.gif")
#webserver
app = quart.Quart(__name__)
#The index.
@app.route('/', methods=['GET'])
async def index():
return await render_template('index.html')
@app.route('/configuration', methods=['GET'])
async def configuration():
return await render_template('configuration.html')
@app.route('/dashboard', methods=['GET'])
async def dashboard():
return await render_template('dashboard.html')
@app.route('/plugins', methods=['GET'])
async def plugins():
return await render_template('plugins.html')
@app.route('/stop', methods=['GET'])
async def stop():
sys.exit("Web terminated.")
if __name__ == "__main__":
api = API(config, bot, log, token)
cli = CLI(api)
bot.api = api
#CLI commands:
#help
def cli_help(self, page=1):
page_size = 10
start_index = (page - 1) * page_size
end_index = start_index + page_size
commands = list(self.cli_cmds.keys())[start_index:end_index]
if not commands:
print("No commands found for this page.")
return 1
msg = f"Commands (page {page}):\n"
for command in commands:
msg += f" {command}: {self.cli_cmds[command]['description']}\n"
print(msg)
return 0
cli.register_command("help", cli_help, "Shows this page.")
#uptime
def cli_uptime(self):
uptime = self.api.uptime()
uptime = str(datetime.timedelta(seconds=uptime)).split(".")[0]
print(f"The uptime of the bot is {uptime} HH:MM:SS.")
cli.register_command("uptime", cli_uptime, "Shows the uptime of the bot in seconds.")
#info
def cli_info(self):
print(f"You are running version 0.1.0 - Dev. Created by supopur under the GNUv3 license. Git repo: https://git.nazev.eu:8443/supopur/mee2 Our discord link: https://discord.gg/dVVVSM4z")
cli.register_command("info", cli_info, "Shows the info about the bot.")
#shutdown
def cli_sd(self):
print("Shutting down the bot. You still must do CTRL+C to exit this terminal!!")
try:
sys.exit("Terminated from the cli..")
except: pass
cli.register_command("stop", cli_sd, "Terminates the bot.")
def cli_clear(self):
os.system('cls' if os.name == 'nt' else 'clear')
cli.register_command("clear", cli_clear, "Clears the terminal output")
#load
def cli_load(self, cog):
try:
cog = str(cog)
except:
print("Unable to convert the cog name to string.")
return 1
print(f"Trying to load {cog}...")
try:
cog_module = importlib.import_module(cog)
class_name = cog.split(".")[1]
print(class_name)
cog_class = getattr(cog_module,class_name)
cog_instance = cog_class(self.api.bot)
self.api.bot.add_cog(cog_instance)
except Exception as e:
print(f"ERR: Failed to load {cog} becouse: {e}")
else:
print(f"Loaded {cog} successfully")
cli.register_command("load", cli_load, "Loads a cog takes a cog name as a arg example: load cogs.example")
#unload
def cli_unload(self, cog):
try:
cog = str(cog)
except:
print("Unable to convert the cog name to string.")
return 1
print(f"Trying to loadd {cog}...")
try:
cog = cog.split(".")[1]
self.api.bot.unload_extension(cog)
except Exception as e:
print(f"ERR Unable to unload {cog} due to: {e}")
else:
print(f"Loaded {cog} successfully")
cli.register_command("unload", cli_unload, "Unloads a cog takes a cog name as a arg example: unload cogs.example")
#start Starts the bot itself.
def cli_start(self):
print("Starting the bot...")
try:
self.api.bot.run(self.api.token)
except Exception as e:
print(e)
return 1
else:
print("Bot started.")
return 0
#cli.register_command("start", cli_start, "Starts the bot.")
bot.loop.create_task(app.run_task('0.0.0.0', 5000)) for x in config["bot"]["cogs"]:
log("inf", f"Loading {x}...")
try:
bot.load_extension(x)
except Exception as e:
log("wrn", f"Extension {x} failed to load due to: {e}")
else:
log("inf", f"{x} Loaded.")
log("inf", "Loading all cogs completed.")
# Create a thread to run the CLI
cli_thread = threading.Thread(target=cli.run)
cli_thread.start()
bot.run(creds["token"]) #uncomment this to enable autostartup
bot.run(token)

@ -2,3 +2,4 @@ py-cord
pytoml pytoml
flask flask
quart quart
readline

@ -1,88 +0,0 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #2c3e50;
color: #fff;
}
.logo {
width: 25;
height: 25;
}
header {
background-color: #3e4982;
color: #fff;
padding: 20px;
text-align: center;
}
header h1 {
margin: 0;
}
.container {
display: flex;
}
table {
font-family: Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 100%;
}
table td,
#status th {
border: 1px solid #ddd;
padding: 8px;
}
table tr:nth-child(even) {
background-color: #1c567d;
}
table tr:hover {
background-color: #2980b9;
}
table th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
background-color: #04AA6D;
color: white;
}
nav {
background-color: #34495e;
width: 200px;
padding: 20px;
text-align: center;
}
nav ul {
list-style: none;
margin: 0;
padding: 0;
}
nav li a {
color: #fff;
text-decoration: none;
padding: 10px 0;
display: block;
}
nav li a:hover {
background-color: #2980b9;
}
.selected {
background-color: #2980b9;
}
main {
padding: 20px;
flex-grow: 1;
}

@ -1,88 +0,0 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #2c3e50;
color: #fff;
}
.logo {
width: 25;
height: 25;
}
header {
background-color: #3e4982;
color: #fff;
padding: 20px;
text-align: center;
}
header h1 {
margin: 0;
}
.container {
display: flex;
}
table {
font-family: Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 100%;
}
table td,
#status th {
border: 1px solid #ddd;
padding: 8px;
}
table tr:nth-child(even) {
background-color: #1c567d;
}
table tr:hover {
background-color: #2980b9;
}
table th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
background-color: #04AA6D;
color: white;
}
nav {
background-color: #34495e;
width: 200px;
padding: 20px;
text-align: center;
}
nav ul {
list-style: none;
margin: 0;
padding: 0;
}
nav li a {
color: #fff;
text-decoration: none;
padding: 10px 0;
display: block;
}
nav li a:hover {
background-color: #2980b9;
}
.selected {
background-color: #2980b9;
}
main {
padding: 20px;
flex-grow: 1;
}

@ -1,61 +0,0 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #2c3e50;
color: #fff;
}
.selected {
background-color: #2980b9;
}
.logo {
width: 25;
height: 25;
}
header {
background-color: #3e4982;
color: #fff;
padding: 20px;
text-align: center;
}
header h1 {
margin: 0;
}
.container {
display: flex;
}
nav {
background-color: #34495e;
width: 200px;
padding: 20px;
text-align: center;
}
nav ul {
list-style: none;
margin: 0;
padding: 0;
}
nav li a {
color: #fff;
text-decoration: none;
padding: 10px 0;
display: block;
}
nav li a:hover {
background-color: #2980b9;
}
main {
padding: 20px;
flex-grow: 1;
}

@ -1,66 +0,0 @@
const form = document.querySelector("form");
const tokenInput = form.querySelector("#token");
const nameInput = form.querySelector("#name");
const statusSelect = form.querySelector("#status");
// set the token input as password field
tokenInput.setAttribute("type", "password");
// function to get the config values from the server
const getConfigValues = async () => {
try {
const tokenResponse = await fetch('/api/token');
const tokenValue = await tokenResponse.text();
tokenInput.value = tokenValue;
const nameResponse = await fetch('/api/name');
const nameValue = await nameResponse.text();
nameInput.value = nameValue;
const statusResponse = await fetch('/api/status');
const statusValue = await statusResponse.text();
statusSelect.value = statusValue;
} catch (error) {
console.error(error);
}
}
getConfigValues();
form.addEventListener("submit", async (event) => {
event.preventDefault();
const token = tokenInput.value;
const name = nameInput.value;
const status = statusSelect.value;
try {
// send POST request to /api/token endpoint with token as the body
if (token !== '') {
await fetch('/api/token', {
method: 'POST',
body: token
});
}
// send POST request to /api/name endpoint with name as the body
if (name !== '') {
await fetch('/api/name', {
method: 'POST',
body: name
});
}
// send POST request to /api/status endpoint with status as the body
if (status !== '') {
await fetch('/api/status', {
method: 'POST',
body: status
});
}
} catch (error) {
console.error(error);
}
});

@ -1,88 +0,0 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #2c3e50;
color: #fff;
}
.logo {
width: 25;
height: 25;
}
header {
background-color: #3e4982;
color: #fff;
padding: 20px;
text-align: center;
}
header h1 {
margin: 0;
}
.container {
display: flex;
}
table {
font-family: Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 100%;
}
table td,
#status th {
border: 1px solid #ddd;
padding: 8px;
}
table tr:nth-child(even) {
background-color: #1c567d;
}
table tr:hover {
background-color: #2980b9;
}
table th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
background-color: #04AA6D;
color: white;
}
nav {
background-color: #34495e;
width: 200px;
padding: 20px;
text-align: center;
}
nav ul {
list-style: none;
margin: 0;
padding: 0;
}
nav li a {
color: #fff;
text-decoration: none;
padding: 10px 0;
display: block;
}
nav li a:hover {
background-color: #2980b9;
}
.selected {
background-color: #2980b9;
}
main {
padding: 20px;
flex-grow: 1;
}

@ -1,47 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>MEE2 Configuration</title>
<link href="{{ url_for('static', filename='configuration.css') }}" rel="stylesheet" type="text/css" />
<script src="{{ url_for('static', filename='js/configuration.js') }}"></script>
<link rel="icon" type="image/x-icon" href="https://cdn.discordapp.com/app-icons/1004808089834373230/e30029e50ec03472f1fe236a43d38684.png?size=512">
</head>
<body>
<header>
<h1>MEE2 Configuration</h1>
</header>
<div class="container">
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/dashboard">Dashboard</a></li>
<li><a href="#" class="selected">Configuration</a></li>
<li><a href="/logs">Logs</a></li>
<li><a href="/support">Support</a></li>
</ul>
</nav>
<main>
<form>
<label for="token">Token:</label>
<input type="password" id="token" name="token">
<br>
<label for="name">Bot Name:</label>
<input type="text" id="name" name="name">
<br>
<label for="status">Status:</label>
<select id="status" name="status">
<option value="online">Online</option>
<option value="idle">Idle</option>
<option value="dnd">Do Not Disturb</option>
<option value="invisible">Invisible</option>
</select>
<br>
<input type="submit" value="Save Changes">
</form>
</main>
</div>
</body>
</html>

@ -1,54 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>MEE2 Dashboard</title>
<link href="{{ url_for('static', filename='dashboard.css') }}" rel="stylesheet" type="text/css" />
<link rel="icon" type="image/x-icon" href="https://cdn.discordapp.com/app-icons/1004808089834373230/e30029e50ec03472f1fe236a43d38684.png?size=512">
</head>
<body>
<header>
<h1>MEE2 - Admin Dashboard</h1>
</header>
<div class="container">
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="#" class="selected">Dashboard</a></li>
<li><a href="/plugins">Plugins</a></li>
<li><a href="/configuration">Configuration</a></li>
<li><a href="/logs">Logs</a></li>
<li><a href="/support">Support</a></li>
</ul>
</nav>
<main>
<p>This is the admin dashboard. Here you can see important thing like the uptime, hits per minute, cogs status etc..</p>
<table id="status">
<tr>
<th>Module</th>
<th>Status</th>
<th>Module link</th>
</tr>
<tr>
<td>Uptime</td>
<td>1 Year</td>
<td><a href="/api/uptime">/api/uptime</a></td>
</tr>
<tr>
<td>Hits Per Minute</td>
<td>10</td>
<td><a href="/api/hpm">/api/hpm</a></td>
</tr>
<tr>
<td>Plugin - Fivem</td>
<td>Online</td>
<td><a href="/plugins/fivem">/plugins/fivem</a></td>
</tr>
</table>
</main>
</div>
</body>
</html>

@ -1,34 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>MEE2 Index</title>
<link rel="icon" type="image/x-icon" href="https://cdn.discordapp.com/app-icons/1004808089834373230/e30029e50ec03472f1fe236a43d38684.png?size=512">
<link href="{{ url_for('static', filename='index.css') }}" rel="stylesheet" type="text/css" />
</head>
<body>
<header>
<h1>MEE2</h1>
</header>
<div class="container">
<nav>
<ul>
<li class="selected"><a href="#">Home</a></li>
<li><a href="/dashboard">Dashboard</a></li>
<li><a href="/plugins">Plugins</a></li>
<li><a href="/configuration">Configuration</a></li>
<li><a href="/logs">Logs</a></li>
<li><a href="/support">Support</a></li>
</ul>
</nav>
<main>
<h2>Welcome to the MEE2 index page.</h2>
<p>This bot is designed to help you with various tasks and make your life easier</p>
<p>Here you can find information about the bot's features, plugins, configuration, and support. All this info is public. If you want you can turn it off in the settings page.</p>
</main>
</div>
</body>
</html>

@ -1,54 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>MEE2 Plugins</title>
<link href="{{ url_for('static', filename='plugins.css') }}" rel="stylesheet" type="text/css" />
<link rel="icon" type="image/x-icon" href="https://cdn.discordapp.com/app-icons/1004808089834373230/e30029e50ec03472f1fe236a43d38684.png?size=512">
</head>
<body>
<header>
<h1>MEE2 - Plugins</h1>
</header>
<div class="container">
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/dashboard">Dashboard</a></li>
<li><a href="#" class="selected">Plugins</a></li>
<li><a href="/configuration">Configuration</a></li>
<li><a href="/logs">Logs</a></li>
<li><a href="/support">Support</a></li>
</ul>
</nav>
<main>
<p>This is the plugin page here you can disable/enable the individual cogs.</p>
<table id="status">
<tr>
<th>Plugin</th>
<th>Status</th>
<th>Plugin link</th>
</tr>
<tr>
<td>Uptime</td>
<td>1 Year</td>
<td><a href="/api/uptime">/api/uptime</a></td>
</tr>
<tr>
<td>Hits Per Minute</td>
<td>10</td>
<td><a href="/api/hpm">/api/hpm</a></td>
</tr>
<tr>
<td>Plugin - Fivem</td>
<td>Online</td>
<td><a href="/plugins/fivem">/plugins/fivem</a></td>
</tr>
</table>
</main>
</div>
</body>
</html>

@ -1,16 +0,0 @@
import requests
def get_player_description(user_id):
url = f"https://users.roblox.com/v1/users/{user_id}"
response = requests.get(url)
if response.status_code == 200:
player_data = response.json()
return player_data["description"]
else:
return None
user_id = 156719681 # Replace with the desired user ID
description = get_player_description(user_id)
print(f"Player description: \n{description}")
Loading…
Cancel
Save