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.

main
supopur 2 years ago
parent 0bd4c0cc43
commit 2561a3c157

@ -1,13 +0,0 @@
#The webserver plugin cofiguration file.
[webserver]
#This will specify the ip adress of the machine that the server is running on. I would recomend to change it as some pages might 404 if you dont.
ip=0.0.0.0
#The port to listen on.
port=5000
#Section related to security and .key, .crt file locations. Its really recomended to use ssl if you are exposing the web interface to the internet.
[SSL]
userssl=False
crt="certs/certificate.crt"
key="certs/private.key"

@ -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,39 +0,0 @@
import sys
import discord
from discord.ext import commands
import quart
import toml
import logging
from quart import render_template
from quart.helpers import make_response
class WebServer(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.app = quart.Quart(__name__)
with open("config.toml", "r") as f:
config = toml.load(f)
logging.info("Starting Quart server...")
bot.loop.create_task(self.app.run_task(config["webserver"]["ip"], config["webserver"]["port"]))
@self.app.route('/', methods=['GET'])
async def index():
return await render_template('index.html')
@self.app.route('/configuration', methods=['GET'])
async def configuration():
return await render_template('configuration.html')
@self.app.route('/dashboard', methods=['GET'])
async def dashboard():
return await render_template('dashboard.html')
@self.app.route('/plugins', methods=['GET'])
async def plugins():
return await render_template('plugins.html')
def setup(bot):
bot.add_cog(WebServer(bot))

@ -14,4 +14,4 @@ key = "/path/to/private.key"
[bot]
cogs=["cogs.example", "cogs.web.web"]
cogs=["cogs.example", "cogs.web.web", "cogs.sapi.sapi"]

@ -2,13 +2,6 @@ import discord, os, sys, toml, time, datetime, logging
from discord.ext import commands
with open("config.toml", "r") as f:
config = toml.load(f)
@ -53,6 +46,56 @@ bot = commands.Bot(command_prefix='!', intents=intents)
logging.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.
def log(self, status, log):
self.logger(str(status), str(log))
def load(self, extension):
self.logger("inf", f"Loading {extension}...")
extension = str(extension)
if extension.startswith("cogs."):
extension.replace("cogs.", "", 1)
try:
self.bot.load_extension(f"cogs.{extension}")
except Exception as e:
self.logger("wrn", f"Extension {extension} failed to load due to: {e}")
else:
self.config["bot"]["cogs"].append(f"cogs.{extension}")
self.save_config()
self.logger("inf", f"Extension {extension} loaded.")
def __init__(self, config, bot, log):
self.start_time = time.time()
self.config = config
self.bot = bot
self.logger = log
print(type(config["bot"]))
#Load all the extensions
for x in config["bot"]["cogs"]:
log("inf", f"Loading {x}...")
@ -81,5 +124,7 @@ async def stop(ctx):
else:
await ctx.respond("https://media.tenor.com/Iv6oKRuAhVEAAAAC/hal9000-im-sorry-dave.gif")
if __name__ == "__main__":
api = API(config, bot, log)
bot.run(token)
bot.run(token)

Loading…
Cancel
Save