make goober export some env variables for cogs to use and add webserver
This commit is contained in:
parent
c72368010d
commit
b5c8895b4d
6 changed files with 429 additions and 8 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -3,4 +3,4 @@ __pycache__
|
||||||
current_version.txt
|
current_version.txt
|
||||||
MEMORY_LOADED
|
MEMORY_LOADED
|
||||||
memory.json
|
memory.json
|
||||||
markov_model.pkl
|
*.pkl
|
17
bot.py
17
bot.py
|
@ -173,7 +173,9 @@ def generate_sha256_of_current_file():
|
||||||
|
|
||||||
|
|
||||||
latest_version = "0.0.0"
|
latest_version = "0.0.0"
|
||||||
local_version = "0.14.8.1"
|
local_version = "0.14.8.2"
|
||||||
|
os.environ['gooberlocal_version'] = local_version
|
||||||
|
os.environ['gooberlatest_version'] = latest_version
|
||||||
|
|
||||||
def check_for_update():
|
def check_for_update():
|
||||||
if ALIVEPING == "false":
|
if ALIVEPING == "false":
|
||||||
|
@ -327,10 +329,13 @@ def ping_server():
|
||||||
response = requests.post(VERSION_URL+"/ping", json=payload)
|
response = requests.post(VERSION_URL+"/ping", json=payload)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
print(f"{GREEN}{get_translation(LOCALE, 'goober_ping_success').format(NAME=NAME)}{RESET}")
|
print(f"{GREEN}{get_translation(LOCALE, 'goober_ping_success').format(NAME=NAME)}{RESET}")
|
||||||
|
os.environ['gooberauthenticated'] = 'Yes'
|
||||||
else:
|
else:
|
||||||
print(f"{RED}{get_translation(LOCALE, 'goober_ping_fail')} {response.status_code}{RESET}")
|
print(f"{RED}{get_translation(LOCALE, 'goober_ping_fail')} {response.status_code}{RESET}")
|
||||||
|
os.environ['gooberauthenticated'] = 'No'
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{RED}{get_translation(LOCALE, 'goober_ping_fail2')} {str(e)}{RESET}")
|
print(f"{RED}{get_translation(LOCALE, 'goober_ping_fail2')} {str(e)}{RESET}")
|
||||||
|
os.environ['gooberauthenticated'] = 'No'
|
||||||
|
|
||||||
|
|
||||||
positive_gifs = os.getenv("POSITIVE_GIFS").split(',')
|
positive_gifs = os.getenv("POSITIVE_GIFS").split(',')
|
||||||
|
@ -434,6 +439,8 @@ async def talk(ctx, sentence_size: int = 5):
|
||||||
combined_message = f"{coherent_response}\n[jif]({gif_url})"
|
combined_message = f"{coherent_response}\n[jif]({gif_url})"
|
||||||
else:
|
else:
|
||||||
combined_message = coherent_response
|
combined_message = coherent_response
|
||||||
|
print(combined_message)
|
||||||
|
os.environ['gooberlatestgen'] = combined_message
|
||||||
await send_message(ctx, combined_message)
|
await send_message(ctx, combined_message)
|
||||||
else:
|
else:
|
||||||
await send_message(ctx, f"{get_translation(LOCALE, 'command_talk_generation_fail')}")
|
await send_message(ctx, f"{get_translation(LOCALE, 'command_talk_generation_fail')}")
|
||||||
|
@ -511,6 +518,14 @@ async def on_message(message):
|
||||||
# process any commands in the message
|
# process any commands in the message
|
||||||
await bot.process_commands(message)
|
await bot.process_commands(message)
|
||||||
|
|
||||||
|
@bot.event
|
||||||
|
async def on_interaction(interaction):
|
||||||
|
if interaction.type == discord.InteractionType.application_command:
|
||||||
|
if interaction.user.id in BLACKLISTED_USERS:
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"{get_translation(LOCALE, 'command_ran_s').format(interaction=interaction)}{interaction.data['name']}")
|
||||||
|
|
||||||
@bot.hybrid_command(description=f"{get_translation(LOCALE, 'command_desc_ping')}")
|
@bot.hybrid_command(description=f"{get_translation(LOCALE, 'command_desc_ping')}")
|
||||||
async def ping(ctx):
|
async def ping(ctx):
|
||||||
await ctx.defer()
|
await ctx.defer()
|
||||||
|
|
|
@ -1,18 +1,24 @@
|
||||||
# goobers custom commands
|
# goobers custom commands
|
||||||
[Hello World!](https://github.com/WhatDidYouExpect/goobercustomcommands/blob/main/customcommands/hello.py)
|
[Hello World!](https://github.com/WhatDidYouExpect/goober/blob/main/cogs/hello.py)
|
||||||
by expect
|
by expect
|
||||||
|
|
||||||
[WhoAmI (lists username and nickname)](https://github.com/WhatDidYouExpect/goober/blob/main/customcommands/whoami.py)
|
[WhoAmI (lists username and nickname)](https://github.com/WhatDidYouExpect/goober/blob/main/cogs/whoami.py)
|
||||||
by PowerPCFan
|
by PowerPCFan
|
||||||
|
|
||||||
[Cog Manager](https://github.com/WhatDidYouExpect/goober/blob/main/customcommands/cogmanager.py)
|
[Cog Manager](https://github.com/WhatDidYouExpect/goober/blob/main/cogs/cogmanager.py)
|
||||||
by expect
|
by expect
|
||||||
|
|
||||||
[TensorFlow integration](https://github.com/WhatDidYouExpect/goober/blob/main/customcommands/tf.py)
|
[TensorFlow integration](https://github.com/WhatDidYouExpect/goober/blob/main/cogs/tf.py)
|
||||||
by SuperSilly2 (requires Python 3.7 - 3.10, tensorflow-metal/tensorflow-gpu and tensorflow/tensorflow-macos)
|
by SuperSilly2 (requires Python 3.7 - 3.10, tensorflow-metal/tensorflow-gpu and tensorflow/tensorflow-macos)
|
||||||
|
|
||||||
[Web Scraper](https://raw.githubusercontent.com/WhatDidYouExpect/goober/refs/heads/main/customcommands/webscraper.py)
|
[Web Scraper](https://raw.githubusercontent.com/WhatDidYouExpect/goober/refs/heads/main/cogs/webscraper.py)
|
||||||
by expect (requires goober version 0.11.7.2 or higher)
|
by expect (requires goober version 0.11.7.2 or higher)
|
||||||
|
|
||||||
[Status Changer](https://raw.githubusercontent.com/WhatDidYouExpect/goober/refs/heads/main/customcommands/songchanger.py)
|
[Status Changer](https://raw.githubusercontent.com/WhatDidYouExpect/goober/refs/heads/main/cogs/songchanger.py)
|
||||||
|
by expect (requires goober version 0.11.8 or higher)
|
||||||
|
|
||||||
|
[Status Changer](https://raw.githubusercontent.com/WhatDidYouExpect/goober/refs/heads/main/cogs/songchanger.py)
|
||||||
|
by expect (requires goober version 0.11.8 or higher)
|
||||||
|
|
||||||
|
[webUI](https://raw.githubusercontent.com/WhatDidYouExpect/goober/refs/heads/main/cogs/webserver.py)
|
||||||
by expect (requires goober version 0.11.8 or higher)
|
by expect (requires goober version 0.11.8 or higher)
|
||||||
|
|
118
cogs/styles.css
Normal file
118
cogs/styles.css
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
|
||||||
|
.topnav {
|
||||||
|
background-color: rgb(95, 27, 27);
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 10px;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topnav a {
|
||||||
|
color: #f2f2f2;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topnav a:hover {
|
||||||
|
background-color: #ddd;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
color: white;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-title {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-container {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 20px auto;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
border-radius: 8px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balls {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
background-color: #2a2a2a;
|
||||||
|
padding: 15px;
|
||||||
|
margin: 10px 0;
|
||||||
|
border-radius: 5px;
|
||||||
|
border-left: 4px solid rgb(95, 27, 27);
|
||||||
|
}
|
||||||
|
|
||||||
|
.guild-list {
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
background-color: #2a2a2a;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guild-item {
|
||||||
|
padding: 5px 0;
|
||||||
|
border-bottom: 1px solid #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guild-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border-color: rgb(95, 27, 27);
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-container-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bot-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bot-avatar {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
border-radius: 0%;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color:black;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
281
cogs/webserver.py
Normal file
281
cogs/webserver.py
Normal file
|
@ -0,0 +1,281 @@
|
||||||
|
import discord
|
||||||
|
from discord.ext import commands, tasks
|
||||||
|
import asyncio
|
||||||
|
from aiohttp import web
|
||||||
|
import psutil
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
from datetime import datetime
|
||||||
|
import time
|
||||||
|
import aiohttp
|
||||||
|
from aiohttp import WSMsgType
|
||||||
|
|
||||||
|
class GooberWeb(commands.Cog):
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
self.app = web.Application()
|
||||||
|
self.runner = None
|
||||||
|
self.site = None
|
||||||
|
self.last_command = "No commands executed yet"
|
||||||
|
self.last_command_time = "Never"
|
||||||
|
self.start_time = time.time()
|
||||||
|
self.websockets = set()
|
||||||
|
|
||||||
|
self.app.add_routes([
|
||||||
|
web.get('/', self.handle_index),
|
||||||
|
web.get('/changesong', self.handle_changesong),
|
||||||
|
web.get('/stats', self.handle_stats),
|
||||||
|
web.get('/data', self.handle_json_data),
|
||||||
|
web.get('/ws', self.handle_websocket),
|
||||||
|
web.get('/styles.css', self.handle_css),
|
||||||
|
])
|
||||||
|
|
||||||
|
self.bot.loop.create_task(self.start_web_server())
|
||||||
|
self.update_clients.start()
|
||||||
|
|
||||||
|
async def start_web_server(self):
|
||||||
|
self.runner = web.AppRunner(self.app)
|
||||||
|
await self.runner.setup()
|
||||||
|
self.site = web.TCPSite(self.runner, '0.0.0.0', 8080)
|
||||||
|
await self.site.start()
|
||||||
|
print("Goober web server started on port 8080")
|
||||||
|
|
||||||
|
async def stop_web_server(self):
|
||||||
|
await self.site.stop()
|
||||||
|
await self.runner.cleanup()
|
||||||
|
print("Web server stopped")
|
||||||
|
|
||||||
|
def cog_unload(self):
|
||||||
|
self.update_clients.cancel()
|
||||||
|
self.bot.loop.create_task(self.stop_web_server())
|
||||||
|
|
||||||
|
@tasks.loop(seconds=5)
|
||||||
|
async def update_clients(self):
|
||||||
|
if not self.websockets:
|
||||||
|
return
|
||||||
|
|
||||||
|
stats = await self.get_bot_stats()
|
||||||
|
message = json.dumps(stats)
|
||||||
|
|
||||||
|
for ws in set(self.websockets):
|
||||||
|
try:
|
||||||
|
await ws.send_str(message)
|
||||||
|
except ConnectionResetError:
|
||||||
|
self.websockets.remove(ws)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error sending to websocket: {e}")
|
||||||
|
self.websockets.remove(ws)
|
||||||
|
|
||||||
|
async def handle_websocket(self, request):
|
||||||
|
ws = web.WebSocketResponse()
|
||||||
|
await ws.prepare(request)
|
||||||
|
self.websockets.add(ws)
|
||||||
|
|
||||||
|
try:
|
||||||
|
async for msg in ws:
|
||||||
|
if msg.type == WSMsgType.ERROR:
|
||||||
|
print(f"WebSocket error: {ws.exception()}")
|
||||||
|
finally:
|
||||||
|
self.websockets.remove(ws)
|
||||||
|
|
||||||
|
return ws
|
||||||
|
|
||||||
|
async def handle_css(self, request):
|
||||||
|
css_path = os.path.join(os.path.dirname(__file__), 'styles.css')
|
||||||
|
if os.path.exists(css_path):
|
||||||
|
return web.FileResponse(css_path)
|
||||||
|
return web.Response(text="CSS file not found", status=404)
|
||||||
|
|
||||||
|
@commands.Cog.listener()
|
||||||
|
async def on_message(self, message):
|
||||||
|
if message.author.bot:
|
||||||
|
return
|
||||||
|
|
||||||
|
ctx = await self.bot.get_context(message)
|
||||||
|
if ctx.valid and ctx.command:
|
||||||
|
self._update_command_stats(ctx.command.name, ctx.author)
|
||||||
|
|
||||||
|
@commands.Cog.listener()
|
||||||
|
async def on_app_command_completion(self, interaction, command):
|
||||||
|
self._update_command_stats(command.name, interaction.user)
|
||||||
|
|
||||||
|
def _update_command_stats(self, command_name, user):
|
||||||
|
self.last_command = f"{command_name} (by {user.name}#{user.discriminator})"
|
||||||
|
self.last_command_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
if self.websockets:
|
||||||
|
asyncio.create_task(self.update_clients())
|
||||||
|
|
||||||
|
async def get_bot_stats(self):
|
||||||
|
process = psutil.Process(os.getpid())
|
||||||
|
mem_info = process.memory_full_info()
|
||||||
|
cpu_percent = psutil.cpu_percent()
|
||||||
|
process_cpu = process.cpu_percent()
|
||||||
|
|
||||||
|
memory_json_size = "N/A"
|
||||||
|
if os.path.exists("memory.json"):
|
||||||
|
memory_json_size = f"{os.path.getsize('memory.json') / 1024:.2f} KB"
|
||||||
|
|
||||||
|
guilds = sorted(self.bot.guilds, key=lambda g: g.member_count, reverse=True)
|
||||||
|
guild_info = [f"{g.name} ({g.member_count} members)" for g in guilds]
|
||||||
|
|
||||||
|
uptime_seconds = int(time.time() - self.start_time)
|
||||||
|
uptime_str = f"{uptime_seconds // 86400}d {(uptime_seconds % 86400) // 3600}h {(uptime_seconds % 3600) // 60}m {uptime_seconds % 60}s"
|
||||||
|
|
||||||
|
return {
|
||||||
|
"ram_usage": f"{mem_info.rss / 1024 / 1024:.2f} MB",
|
||||||
|
"cpu_usage": f"{process_cpu}%",
|
||||||
|
"system_cpu": f"{cpu_percent}%",
|
||||||
|
"memory_json_size": memory_json_size,
|
||||||
|
"guild_count": len(guilds),
|
||||||
|
"guilds": guild_info,
|
||||||
|
"last_command": self.last_command,
|
||||||
|
"last_command_time": self.last_command_time,
|
||||||
|
"bot_uptime": uptime_str,
|
||||||
|
"latency": f"{self.bot.latency * 1000:.2f} ms",
|
||||||
|
"bot_name": self.bot.user.name,
|
||||||
|
"bot_avatar_url": str(self.bot.user.avatar.url) if self.bot.user.avatar else "",
|
||||||
|
"authenticated": os.getenv("gooberauthenticated"),
|
||||||
|
"lastmsg": os.getenv("gooberlatestgen")
|
||||||
|
}
|
||||||
|
|
||||||
|
async def handle_update(self, request):
|
||||||
|
if os.path.exists("goob/update.py"):
|
||||||
|
return web.FileResponse("goob/update.py")
|
||||||
|
return web.Response(text="Update file not found", status=404)
|
||||||
|
|
||||||
|
async def handle_changesong(self, request):
|
||||||
|
song = request.query.get('song', '')
|
||||||
|
if song:
|
||||||
|
await self.bot.change_presence(activity=discord.Activity(type=discord.ActivityType.listening, name=song))
|
||||||
|
return web.Response(text=f"Changed song to: {song}")
|
||||||
|
return web.Response(text="Please provide a song parameter", status=400)
|
||||||
|
|
||||||
|
async def handle_changes(self, request):
|
||||||
|
if os.path.exists("goob/changes.txt"):
|
||||||
|
return web.FileResponse("goob/changes.txt")
|
||||||
|
return web.Response(text="Changelog not found", status=404)
|
||||||
|
|
||||||
|
async def handle_index(self, request):
|
||||||
|
stats = await self.get_bot_stats()
|
||||||
|
|
||||||
|
html_content = f"""
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>goobs central</title>
|
||||||
|
<link rel="stylesheet" href="/styles.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="topnav">
|
||||||
|
<div class="stat-item" id="ram-usage">
|
||||||
|
<span class="stat-title">RAM:</span>
|
||||||
|
<span>{stats['ram_usage']}</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item" id="cpu-usage">
|
||||||
|
<span class="stat-title">CPU:</span>
|
||||||
|
<span>{stats['cpu_usage']}</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item" id="system-cpu">
|
||||||
|
<span class="stat-title">System CPU:</span>
|
||||||
|
<span>{stats['system_cpu']}</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item" id="latency">
|
||||||
|
<span class="stat-title">Latency:</span>
|
||||||
|
<span>{stats['latency']}</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item" id="json-size">
|
||||||
|
<span class="stat-title">JSON Size:</span>
|
||||||
|
<span>{stats['memory_json_size']}</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item" id="uptime">
|
||||||
|
<span class="stat-title">Uptime:</span>
|
||||||
|
<span>{stats['bot_uptime']}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="center">
|
||||||
|
<h2>
|
||||||
|
<div class="bot-info">
|
||||||
|
<img src="{stats['bot_avatar_url']}" alt="botvatar" class="bot-avatar" id="bot-avatar">
|
||||||
|
<span id="bot-name">{stats['bot_name']}</span>
|
||||||
|
</div>
|
||||||
|
</h2>
|
||||||
|
<hr>
|
||||||
|
<p>your stupid little goober that learns off other people's messages</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-container-row">
|
||||||
|
<div>
|
||||||
|
<div class="stat-title">Last Command</div>
|
||||||
|
<div id="last-command">{stats['last_command']}</div>
|
||||||
|
<div style="font-size: 0.9em; color: #999;" id="last-command-time">at {stats['last_command_time']}</div>
|
||||||
|
<br>
|
||||||
|
<div class="stat-title">Logged into goober central</div>
|
||||||
|
<div id="last-command">{stats['authenticated']}</div>
|
||||||
|
<br>
|
||||||
|
<div class="stat-title">Last generated message</div>
|
||||||
|
<div id="last-command">{stats['lastmsg']}</div>
|
||||||
|
<br>
|
||||||
|
<div class="stat-title">Change song</div>
|
||||||
|
<form action="/changesong" method="get">
|
||||||
|
<input type="text" name="song" placeholder="Enter song name..." style="background-color:black; color:white; solid #ccc;">
|
||||||
|
<button type="submit">
|
||||||
|
change song
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="balls">
|
||||||
|
<div class="stat-title">Servers (<span id="guild-count">{stats['guild_count']}</span>)</div>
|
||||||
|
<div id="guild-list">
|
||||||
|
{"".join(f'<div class="guild-item">{guild}</div>' for guild in stats['guilds'])}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
const ws = new WebSocket('ws://' + window.location.host + '/ws');
|
||||||
|
|
||||||
|
ws.onmessage = function(event) {{
|
||||||
|
const data = JSON.parse(event.data);
|
||||||
|
|
||||||
|
document.getElementById('ram-usage').innerHTML = `<span class="stat-title">RAM:</span> <span>${{data.ram_usage}}</span>`;
|
||||||
|
document.getElementById('cpu-usage').innerHTML = `<span class="stat-title">CPU:</span> <span>${{data.cpu_usage}}</span>`;
|
||||||
|
document.getElementById('system-cpu').innerHTML = `<span class="stat-title">System CPU:</span> <span>${{data.system_cpu}}</span>`;
|
||||||
|
document.getElementById('latency').innerHTML = `<span class="stat-title">Latency:</span> <span>${{data.latency}}</span>`;
|
||||||
|
document.getElementById('json-size').innerHTML = `<span class="stat-title">JSON Size:</span> <span>${{data.memory_json_size}}</span>`;
|
||||||
|
document.getElementById('uptime').innerHTML = `<span class="stat-title">Uptime:</span> <span>${{data.bot_uptime}}</span>`;
|
||||||
|
|
||||||
|
document.getElementById('bot-name').textContent = data.bot_name;
|
||||||
|
const botAvatar = document.getElementById('bot-avatar');
|
||||||
|
if (botAvatar.src !== data.bot_avatar_url) {{
|
||||||
|
botAvatar.src = data.bot_avatar_url;
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
document.getElementById('last-command').textContent = data.last_command;
|
||||||
|
document.getElementById('last-command-time').textContent = `at ${{data.last_command_time}}`;
|
||||||
|
|
||||||
|
document.getElementById('guild-count').textContent = data.guild_count;
|
||||||
|
document.getElementById('guild-list').innerHTML =
|
||||||
|
data.guilds.map(guild => `<div class="guild-item">${{guild}}</div>`).join('');
|
||||||
|
}};
|
||||||
|
|
||||||
|
ws.onclose = function() {{
|
||||||
|
console.log('WebSocket disconnected');
|
||||||
|
}};
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
|
return web.Response(text=html_content, content_type='text/html')
|
||||||
|
|
||||||
|
async def handle_stats(self, request):
|
||||||
|
return await self.handle_index(request)
|
||||||
|
|
||||||
|
async def handle_json_data(self, request):
|
||||||
|
stats = await self.get_bot_stats()
|
||||||
|
return web.json_response(stats)
|
||||||
|
|
||||||
|
async def setup(bot):
|
||||||
|
await bot.add_cog(GooberWeb(bot))
|
|
@ -57,6 +57,7 @@
|
||||||
"command_help_categories_admin": "Administration",
|
"command_help_categories_admin": "Administration",
|
||||||
"command_help_categories_custom": "Custom Commands",
|
"command_help_categories_custom": "Custom Commands",
|
||||||
"command_ran": "Info: {message.author.name} ran {message.content}",
|
"command_ran": "Info: {message.author.name} ran {message.content}",
|
||||||
|
"command_ran_s": "Info: {interaction.user} ran ",
|
||||||
"command_desc_ping": "ping",
|
"command_desc_ping": "ping",
|
||||||
"command_ping_embed_desc": "Bot Latency:",
|
"command_ping_embed_desc": "Bot Latency:",
|
||||||
"command_ping_footer": "Requested by",
|
"command_ping_footer": "Requested by",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue