Bunch of cleanup

This commit is contained in:
Benjamin Morgan 2026-01-04 18:18:57 -07:00
parent dee736bd54
commit 65a504c882
4 changed files with 282 additions and 246 deletions

View file

@ -11,4 +11,4 @@ RUN apt update && apt install sqlite3
RUN pip install --upgrade pip && pip install -r requirements.txt
ENTRYPOINT [ "/app/entrypoint.sh" ]
CMD [ "python3", "mstbot.py" ]
CMD [ "python3", "-u", "mstbot.py" ]

View file

@ -1,2 +1,24 @@
![Static Badge](https://img.shields.io/badge/Bot-Invite-5865F2?style=for-the-badge&logo=discord&link=https%3A%2F%2Fdiscord.com%2Foauth2%2Fauthorize%3Fclient_id%3D911009295947165747%26permissions%3D3088%26response_type%3Dcode%26redirect_uri%3Dhttps%253A%252F%252Fwww.benrmorgan.com%252Fportfolio%252Fminecraft-server-tools-bot%26integration_type%3D0%26scope%3Dmessages.read%2Bbot)
# MinecraftStatus
Minecraft Status discord bot
Minecraft Status discord bot that adds status banners to your guild's sidebar. See below for example.
![Server Status Banners](image.png)
### Commands
```
Admin:
announce Turns on player join announcements
cleanup Removes querier and status channels
noannounce Turns off player join announcements
nohours Turns off total player hour display
setup Sets up new Minecraft server querier
showhours Turns on total player hour display
Other:
help Shows this message
lastquery Shows last query time
players Lists online players
status Shows server status
Type $help command for more info on a command.
You can also type $help category for more info on a category.
```

491
mstbot.py
View file

@ -1,9 +1,10 @@
# TODO: Change hours column to boolean, drop times table, make it a column in servers
# TODO: prevent sql injection
# TODO: in readme, add badge for guild count, total player count
# TODO: make dev bot for testing
# TODO: handle wait=301 rate limits more cleanly
# TODO: annotate return types everywhere
# TODO: split cogs into separate files, add utils file, remove globals
# TODO: wrap all SQL queries with a func to determine if server has been set up or not. If fetchone returns None, log helpful message to run $setup.
# TODO: save invite link to README and show query port enable instructions
# TODO: https://discord.com/oauth2/authorize?client_id=911009295947165747&permissions=3088&response_type=code&redirect_uri=https%3A%2F%2Fwww.benrmorgan.com%2Fportfolio%2Fminecraft-server-tools-bot&integration_type=0&scope=messages.read+bot
# TODO: Feature: allow discord users to associate their mc usernames, change server nickname?
# TODO: Feature: allow other users to query playtime by username, default to their own. This and above require new columns in names table.
@ -13,6 +14,7 @@ import re
import socket
import unicodedata
from contextlib import contextmanager
from datetime import datetime, timezone
from typing import Union, List
@ -31,10 +33,11 @@ servers = []
@bot.event
async def on_ready():
print(f'Logged in as {bot.user}')
mydb, cursor = connect()
cursor.execute("SELECT id, ip, announce_joins, announce_joins_id FROM servers")
rows = cursor.fetchall()
with sqlite_conn() as conn:
rows = conn.execute(
"SELECT id, ip, announce_joins, announce_joins_id FROM servers"
).fetchall()
for row in rows:
if get_server_by_id(row[0]) is None:
@ -51,14 +54,13 @@ async def on_ready():
@bot.event
async def on_command_error(ctx: commands.Context, error: commands.CommandError):
command = ctx.message.content.split()[0][1:] # Extract command name
prefix = ctx.prefix
if isinstance(error, commands.CommandNotFound):
await safe_send(ctx, f'Command "{command}" does not exist. Use `{ctx.prefix}help` for available commands.')
await safe_send(f'Command "{command}" does not exist. Use `{ctx.prefix}help` for available commands.', ctx)
elif isinstance(error, commands.MissingRequiredArgument):
await log(ctx, f'Command "{command}" is missing required arguments. Use `{ctx.prefix}help {command}` for details.')
elif isinstance(error, commands.MissingPermissions):
await safe_send(ctx, f'You lack permissions: {", ".join(error.missing_perms)}.')
await safe_send(f'You lack permissions: {", ".join(error.missing_perms)}.', ctx)
elif isinstance(error, commands.CommandInvokeError) and isinstance(error.original, socket.gaierror):
await log(ctx, "Could not connect, is the server down?")
else:
@ -87,16 +89,16 @@ class Admin(commands.Cog):
except ConnectionRefusedError:
await log(ctx, "Setup query failed, server down?")
else:
mydb, cursor = connect()
with sqlite_conn() as conn:
conn.execute("""
INSERT INTO servers (id, ip, port)
VALUES (?, ?, ?)
ON CONFLICT(id) DO UPDATE SET
ip = excluded.ip,
port = excluded.port
""", (ctx.guild.id, val_ip, val_port))
cursor.execute(f"INSERT INTO servers (id, ip, port) VALUES({str(ctx.guild.id)}, \"{val_ip}\", {str(port)}) ON CONFLICT(id) DO UPDATE SET ip=\"{val_ip}\", port={str(port)}")
setMCNames(ctx.guild.id, cursor, names)
cursor.execute(f"INSERT INTO times (id) VALUES({ctx.guild.id}) ON CONFLICT(id) DO UPDATE SET id=id;")
mydb.commit()
mydb.close()
setMCNames(ctx.guild.id, conn, names)
if annChanID is None:
await setAnn(ctx, False)
@ -129,34 +131,12 @@ class Admin(commands.Cog):
@commands.command(brief="Turns on total player hour display", description="Turns on total player hour display.")
@commands.has_permissions(administrator=True)
async def showhours(self, ctx: discord.ext.commands.context.Context):
await setHours(ctx, True)
await setShowHours(ctx, True)
@commands.command(brief="Turns off total player hour display", description="Turns off total player hour display.")
@commands.has_permissions(administrator=True)
async def nohours(self, ctx: discord.ext.commands.context.Context):
await setHours(ctx, False)
# @commands.command()
# async def notif(ctx: discord.ext.commands.context.Context, kind: Union[str, None] = None):
# if kind is None:
# await safe_send(ctx, "The notification options are: \n1. joins")
# else:
# name = ""
# if kind.lower() == "joins":
# name = "Status Joins"
#
# if name != "":
# await addrole(ctx, name)
# await log(ctx, "Gave", name, "role to", ctx.message.author.name)
#
#
# async def addrole(ctx: discord.ext.commands.context.Context, name: str):
# member = ctx.message.author
# role = get(member.guild.roles, name=name)
# if role is None:
# role = await member.guild.create_role(name=name)
#
# await member.add_roles(role)
await setShowHours(ctx, False)
class Other(commands.Cog):
@ -167,33 +147,29 @@ class Other(commands.Cog):
@commands.command(brief="Shows server status", description="Shows server status.")
async def status(self, ctx: discord.ext.commands.context.Context):
mydb, cursor = connect()
ip, port = getMCIP(ctx.guild.id, cursor)
mc = JavaServer(ip, port)
with sqlite_conn() as conn:
ip, port = getMCIP(ctx.guild.id, conn)
mc = JavaServer(ip, port)
if mc is None:
await safe_send("There is no server query set up. Run the `setup` command to get started.", ctx=ctx)
else:
players, max, _, motd = await getStatus(mc)
if mc is None:
await safe_send("There is no server query set up. Run the `setup` command to get started.", ctx=ctx)
else:
players, max, _, motd = await getStatus(mc)
seconds = getPersonSeconds(ctx.guild.id, conn)
seconds = seconds % (24 * 3600)
hour = seconds // 3600
seconds %= 3600
minutes = seconds // 60
seconds %= 60
seconds = getPersonSeconds(ctx.guild.id, cursor)
seconds = seconds % (24 * 3600)
hour = seconds // 3600
seconds %= 3600
minutes = seconds // 60
seconds %= 60
await safe_send("Status:\n " + ip + "\n " + motd.to_plain() + "\n\n Players: " + str(players) + "/" + str(max) + "\n Total Player Time: " + "%d:%02d:%02d" % (hour, minutes, seconds), ctx=ctx, format="```")
mydb.close()
await safe_send("Status:\n " + ip + "\n " + motd.to_plain() + "\n\n Players: " + str(players) + "/" + str(max) + "\n Total Player Time: " + "%d:%02d:%02d" % (hour, minutes, seconds), ctx=ctx, format="```")
@commands.command(brief="Lists online players", description="Lists online players.")
async def players(self, ctx: discord.ext.commands.context.Context):
mydb, cursor = connect()
ip, port = getMCIP(ctx.guild.id, cursor)
mc = JavaServer(ip, port)
mydb.close()
with sqlite_conn() as conn:
ip, port = getMCIP(ctx.guild.id, conn)
mc = JavaServer(ip, port)
if mc is None:
await safe_send("There is no server query set up. Run the `setup` command to get started.", ctx=ctx)
@ -209,11 +185,10 @@ class Other(commands.Cog):
@commands.command(brief="Shows last query time", description="Shows last query time. Useful for debugging server connection issues.")
async def lastquery(self, ctx: discord.ext.commands.context.Context):
mydb, cursor = connect()
ip, port = getMCIP(ctx.guild.id, cursor)
mc = JavaServer(ip, port)
last = getMCQueryTime(ctx.guild.id, cursor)
mydb.close()
with sqlite_conn() as conn:
ip, port = getMCIP(ctx.guild.id, conn)
mc = JavaServer(ip, port)
last = getMCQueryTime(ctx.guild.id, conn)
if mc is None:
await safe_send("There is no server query set up. Run the `setup` command to get started.", ctx=ctx)
@ -236,15 +211,20 @@ async def setAnn(ctx: discord.ext.commands.context.Context, ann: bool, cid: Unio
await log(ctx, "Channel", str(cid), "does not exist.")
return
mydb, cursor = connect()
ip, _ = getMCIP(ctx.guild.id, cursor)
with sqlite_conn() as conn:
ip, _ = getMCIP(ctx.guild.id, conn)
cursor.execute(
"UPDATE servers SET announce_joins=" + str((0, 1)[ann]) + ", announce_joins_id=" + ("NULL", str(cid))[
ann] + " WHERE id=" + str(ctx.guild.id))
mydb.commit()
mydb.close()
conn.execute("""
UPDATE servers
SET
announce_joins = ?,
announce_joins_id = ?
WHERE id = ?
""", (
ann,
cid if ann else None,
ctx.guild.id
))
await log(ctx, (
"Not announcing when a player joins " + ip + ".",
@ -252,20 +232,23 @@ async def setAnn(ctx: discord.ext.commands.context.Context, ann: bool, cid: Unio
ann])
async def setHours(ctx: discord.ext.commands.context.Context, hours: bool):
mydb, cursor = connect()
ip, _ = getMCIP(ctx.guild.id, cursor)
async def setShowHours(ctx: discord.ext.commands.context.Context, show_hours: bool):
with sqlite_conn() as conn:
ip, _ = getMCIP(ctx.guild.id, conn)
cursor.execute(
f"UPDATE servers SET hours={str((0, 1)[hours])} WHERE id={str(ctx.guild.id)}")
mydb.commit()
mydb.close()
conn.execute("""
UPDATE servers
SET show_hours = ?
WHERE id = ?
""", (
show_hours,
ctx.guild.id
))
await log(ctx, (
"Not displaying total player hours for " + ip + ".",
"Displaying total player hours for " + ip + ".")[
hours] + " Please wait a moment for channel updates to take effect.")
show_hours] + " Please wait a moment for channel updates to take effect.")
async def log(ctx: commands.Context, *msg: str):
@ -349,77 +332,110 @@ async def getStatus(serv: JavaServer):
return p, m, n, d
def connect():
mydb = sqlite3.connect('/data/mstbot.db')
cursor = mydb.cursor()
return mydb, cursor
@contextmanager
def sqlite_conn():
conn = sqlite3.connect('/data/mstbot.db')
try:
# per-connection PRAGMAs
conn.execute("PRAGMA foreign_keys = ON")
conn.execute("PRAGMA busy_timeout = 5000")
yield conn
conn.commit()
except Exception:
conn.rollback()
raise
finally:
# run on close
conn.execute("PRAGMA optimize")
conn.close()
def getMCIP(sid: int, cursor: sqlite3.Cursor):
cursor.execute("SELECT ip, port FROM servers WHERE id=" + str(sid))
row = cursor.fetchone()
def getMCIP(sid: int, conn: sqlite3.Connection):
row = conn.execute(
"SELECT ip, port FROM servers WHERE id = ?",
(sid,)
).fetchone()
ip = row[0]
port = row[1]
return ip, port
def getMCNames(sid: int, cursor: sqlite3.Cursor):
cursor.execute("SELECT name FROM names WHERE id=" + str(sid))
rows = cursor.fetchall()
def getMCNames(sid: int, conn: sqlite3.Connection):
rows = conn.execute(
"SELECT name FROM names WHERE id = ?",
(sid,)
).fetchall()
return [row[0] for row in rows]
def getMCQueryTime(sid: int, cursor: sqlite3.Cursor):
cursor.execute("SELECT last_query FROM servers WHERE id=" + str(sid))
tstr = cursor.fetchone()[0]
def getMCQueryTime(sid: int, conn: sqlite3.Connection):
tstr = conn.execute(
"SELECT last_query FROM servers WHERE id = ?",
(sid,)
).fetchone()[0]
if tstr is None:
return tstr
return datetime.strptime(tstr, '%Y-%m-%d %H:%M:%S')
def getPersonSeconds(sid: int, cursor: sqlite3.Cursor):
cursor.execute("SELECT time FROM times WHERE id=" + str(sid))
tstr = cursor.fetchone()[0]
def getPersonSeconds(sid: int, conn: sqlite3.Connection):
cols = conn.execute(
f"SELECT SUM(seconds) FROM times WHERE id = ? GROUP BY id",
(sid,)
).fetchone()
if cols is not None:
return cols[0]
return int(tstr)
return 0
def getShowHours(sid: int, cursor: sqlite3.Cursor):
cursor.execute("SELECT hours FROM servers WHERE id=" + str(sid))
tstr = cursor.fetchone()[0]
def getShowHours(sid: int, conn: sqlite3.Connection):
show_hours = conn.execute(
"SELECT show_hours FROM servers WHERE id = ?",
(sid,)
).fetchone()[0]
return bool(tstr)
return show_hours
def getMCJoinAnnounce(sid: int, cursor: sqlite3.Cursor):
cursor.execute("SELECT announce_joins, announce_joins_id FROM servers WHERE id=" + str(sid))
row = cursor.fetchone()
def getMCJoinAnnounce(sid: int, conn: sqlite3.Connection):
row = conn.execute(
"SELECT announce_joins, announce_joins_id FROM servers WHERE id = ?",
(sid,)
).fetchone()
ann = row[0]
cid = row[1]
return ann, cid
def setMCNames(sid: int, cursor: sqlite3.Cursor, names: List[str]):
cursor.execute("DELETE FROM names WHERE id=" + str(sid))
def setMCNames(sid: int, conn: sqlite3.Connection, names: List[str]):
conn.execute("DELETE FROM names WHERE id = ?", (sid,))
if len(names) > 0:
qStr = ""
for name in names:
qStr += "(" + str(sid) + ",\"" + name + "\"),"
if names:
rows = [(sid, name) for name in names]
conn.executemany("INSERT INTO names (id, name) VALUES (?, ?)", rows)
qStr = qStr[:-1] + ";"
cursor.execute("INSERT INTO names (id, name) VALUES " + qStr)
def setMCQueryTime(sid: int, conn: sqlite3.Connection, dt: datetime):
conn.execute("""
UPDATE servers
SET last_query = ?
WHERE id = ?
""", (
dt.strftime('%Y-%m-%d %H:%M:%S'),
sid
))
def setMCQueryTime(sid: int, cursor: sqlite3.Cursor, dt: datetime):
cursor.execute("UPDATE servers SET last_query=\"" + dt.strftime('%Y-%m-%d %H:%M:%S') + "\" WHERE id=" + str(sid))
def incrementPersonSeconds(sid: int, cursor: sqlite3.Cursor, seconds: int):
cursor.execute(f"UPDATE times SET time=time+{seconds} WHERE id={str(sid)};")
def incrementPersonSeconds(sid: int, user: str, conn: sqlite3.Connection, seconds: float):
conn.execute("""
INSERT INTO times (id, name, seconds)
VALUES (?, ?, ?)
ON CONFLICT(id, name) DO UPDATE SET
seconds = times.seconds + excluded.seconds
""", (sid, user, seconds))
async def do_bot_cleanup(sid: int, ctx: Union[discord.ext.commands.context.Context, None] = None):
if sid in servers:
@ -440,16 +456,13 @@ async def do_bot_cleanup(sid: int, ctx: Union[discord.ext.commands.context.Conte
except discord.errors.Forbidden:
print(currServ.name, "Error: I don't have permission to delete channels.")
mydb, cursor = connect()
ip, port = getMCIP(sid, cursor)
mc = JavaServer(ip, port)
with sqlite_conn() as conn:
ip, port = getMCIP(sid, conn)
mc = JavaServer(ip, port)
cursor.execute("DELETE FROM servers WHERE id=" + str(sid))
cursor.execute("DELETE FROM names WHERE id=" + str(sid))
cursor.execute("DELETE FROM times WHERE id=" + str(sid))
mydb.commit()
mydb.close()
conn.execute("DELETE FROM servers WHERE id = ?", (sid,))
conn.execute("DELETE FROM names WHERE id = ?", (sid,))
conn.execute("DELETE FROM times WHERE id = ?", (sid,))
if ctx is None:
print("Cleaned up", sid, ".")
@ -496,120 +509,82 @@ async def status_task(sid: int):
print(get_server_by_id(sid).name, "is not querying. Ending task.")
return
mydb, cursor = connect()
ip, port = getMCIP(sid, cursor)
mc = JavaServer(ip, port)
currServ = get_server_by_id(sid)
wait = 10
with sqlite_conn() as conn:
ip, port = getMCIP(sid, conn)
mc = JavaServer(ip, port)
currServ = get_server_by_id(sid)
wait = 10
if not ip == "" and currServ is not None:
try:
oldNames = getMCNames(sid, cursor)
players, max, names, _ = await getStatus(mc)
lastTime = getMCQueryTime(sid, cursor)
lastSeconds = getPersonSeconds(sid, cursor)
if not ip == "" and currServ is not None:
try:
oldNames = getMCNames(sid, conn)
players, max, names, _ = await getStatus(mc)
lastTime = getMCQueryTime(sid, conn)
lastSeconds = getPersonSeconds(sid, conn)
currTime = datetime.now(timezone.utc)
if lastTime is None:
lastTime = currTime
else:
lastTime = lastTime.replace(tzinfo=timezone.utc)
currTime = datetime.now(timezone.utc)
if lastTime is None:
lastTime = currTime
else:
lastTime = lastTime.replace(tzinfo=timezone.utc)
print(currServ.name, "Query:", ip, str(players) + "/" + str(max), datetime.now(timezone.utc).strftime("%H:%M:%S"),
str(currTime - lastTime))
deltaSeconds = (currTime - lastTime).total_seconds()
setMCNames(sid, cursor, names)
setMCQueryTime(sid, cursor, currTime)
if not first_iter:
incrementPersonSeconds(sid, cursor, len(names) * (currTime - lastTime).total_seconds())
print(currServ.name, "Query:", ip, str(players) + "/" + str(max), datetime.now(timezone.utc).strftime("%H:%M:%S"),
str(deltaSeconds))
announceJoin, annChanId = getMCJoinAnnounce(sid, cursor)
annRole = None
setMCNames(sid, conn, names)
setMCQueryTime(sid, conn, currTime)
if not first_iter:
for name in names:
incrementPersonSeconds(sid, name, conn, deltaSeconds)
if announceJoin and annChanId is not None:
jNames = list(set(names) - set(oldNames))
for name in jNames:
aChannels = find_channels(serv=currServ, chanid=int(annChanId))
announceJoin, annChanId = getMCJoinAnnounce(sid, conn)
annRole = None
if len(aChannels) > 0:
if annRole is None:
await safe_send(name + " joined the game!", chan=aChannels[0])
else:
await safe_send("<@&" + str(annRole.id) + "> " + name + " joined the game!",
chan=aChannels[0])
if announceJoin and annChanId is not None:
jNames = list(set(names) - set(oldNames))
for name in jNames:
aChannels = find_channels(serv=currServ, chanid=int(annChanId))
print(currServ.name, "Announced player(s) join.")
if len(aChannels) > 0:
if annRole is None:
await safe_send(name + " joined the game!", chan=aChannels[0])
else:
await safe_send("<@&" + str(annRole.id) + "> " + name + " joined the game!",
chan=aChannels[0])
except asyncio.exceptions.TimeoutError:
print(currServ.name, "Timeout, server lagging?")
players = -1
lastSeconds = -1
print(currServ.name, "Announced player(s) join.")
except (ConnectionRefusedError, socket.gaierror):
print(currServ.name, "Cannot connect to server, down?")
players = -1
lastSeconds = -1
except asyncio.exceptions.TimeoutError:
print(currServ.name, "Timeout, server lagging?")
players = -1
lastSeconds = -1
iChannels = find_channels(serv=currServ, channame="IP: ", channamesearch="in", chantype=discord.ChannelType.voice)
pChannels = find_channels(serv=currServ, channame="Players: ", channamesearch="in",
chantype=discord.ChannelType.voice)
tChannels = find_channels(serv=currServ, channame="Player Hrs: ", channamesearch="in",
chantype=discord.ChannelType.voice)
except (ConnectionRefusedError, socket.gaierror):
print(currServ.name, "Cannot connect to server, down?")
players = -1
lastSeconds = -1
overwrites = {
currServ.default_role: discord.PermissionOverwrite(connect=False, view_channel=True),
currServ.me: discord.PermissionOverwrite(connect=True, view_channel=True, manage_channels=True)
}
iChannels = find_channels(serv=currServ, channame="IP: ", channamesearch="in", chantype=discord.ChannelType.voice)
pChannels = find_channels(serv=currServ, channame="Players: ", channamesearch="in",
chantype=discord.ChannelType.voice)
tChannels = find_channels(serv=currServ, channame="Player Hrs: ", channamesearch="in",
chantype=discord.ChannelType.voice)
if len(iChannels) > 0:
lastIPName = iChannels[0].name
overwrites = {
currServ.default_role: discord.PermissionOverwrite(connect=False, view_channel=True),
currServ.me: discord.PermissionOverwrite(connect=True, view_channel=True, manage_channels=True)
}
ipStr = "IP: " + ip
if lastIPName != ipStr:
try:
print(currServ.name, "Update: Ip changed!")
await iChannels[0].edit(name=ipStr)
wait = 301
except discord.errors.Forbidden:
print(currServ.name,
"Error: I don't have permission to edit channels. Try deleting the channels I create. Then, run the `setup` command again.")
await do_bot_cleanup(sid)
return
else:
await currServ.create_voice_channel("IP: " + ip, overwrites=overwrites)
if len(iChannels) > 0:
lastIPName = iChannels[0].name
if len(pChannels) > 0:
lastPName = pChannels[0].name
if players == -1:
pStr = lastPName
else:
pStr = "Players: " + str(players) + "/" + str(max)
if lastPName != pStr:
try:
print(currServ.name, "Update: Players changed!")
await pChannels[0].edit(name=pStr)
wait = 301
except discord.errors.Forbidden:
print(currServ.name,
"Error: I don't have permission to edit channels. Try deleting the channels I create. Then, run the `setup` command again.")
await do_bot_cleanup(sid)
return
else:
await currServ.create_voice_channel(f"Players: {str(players)}/{str(max)}",
overwrites=overwrites)
do_show_hours = getShowHours(sid, cursor)
if do_show_hours and not first_iter and lastSeconds != -1:
tStr = "Player Hrs: " + str(round((lastSeconds + len(names) * (currTime - lastTime).total_seconds())/3600))
if len(tChannels) > 0:
lastTName = tChannels[0].name
if lastTName != tStr:
ipStr = "IP: " + ip
if lastIPName != ipStr:
try:
print(currServ.name, "Update: Time changed!")
await tChannels[0].edit(name=tStr)
print(currServ.name, "Update: Ip changed!")
await iChannels[0].edit(name=ipStr)
wait = 301
except discord.errors.Forbidden:
print(currServ.name,
@ -617,15 +592,53 @@ async def status_task(sid: int):
await do_bot_cleanup(sid)
return
else:
await currServ.create_voice_channel(tStr,
overwrites=overwrites)
elif not do_show_hours:
if len(tChannels) > 0:
for channel in tChannels:
await channel.delete()
await currServ.create_voice_channel("IP: " + ip, overwrites=overwrites)
mydb.commit()
mydb.close()
if len(pChannels) > 0:
lastPName = pChannels[0].name
if players == -1:
pStr = lastPName
else:
pStr = "Players: " + str(players) + "/" + str(max)
if lastPName != pStr:
try:
print(currServ.name, "Update: Players changed!")
await pChannels[0].edit(name=pStr)
wait = 301
except discord.errors.Forbidden:
print(currServ.name,
"Error: I don't have permission to edit channels. Try deleting the channels I create. Then, run the `setup` command again.")
await do_bot_cleanup(sid)
return
else:
await currServ.create_voice_channel(f"Players: {str(players)}/{str(max)}",
overwrites=overwrites)
do_show_hours = getShowHours(sid, conn)
if do_show_hours and not first_iter and lastSeconds != -1:
tStr = "Player Hrs: " + str(round(getPersonSeconds(sid, conn)/3600))
if len(tChannels) > 0:
lastTName = tChannels[0].name
if lastTName != tStr:
try:
print(currServ.name, "Update: Time changed!")
await tChannels[0].edit(name=tStr)
wait = 301
except discord.errors.Forbidden:
print(currServ.name,
"Error: I don't have permission to edit channels. Try deleting the channels I create. Then, run the `setup` command again.")
await do_bot_cleanup(sid)
return
else:
await currServ.create_voice_channel(tStr,
overwrites=overwrites)
elif not do_show_hours:
if len(tChannels) > 0:
for channel in tChannels:
await channel.delete()
await asyncio.sleep(wait)
first_iter = False

View file

@ -1,3 +1,4 @@
PRAGMA journal_mode = WAL;
CREATE TABLE names (id INTEGER NOT NULL, name TEXT NOT NULL, UNIQUE (id, name));
CREATE TABLE times (id INTEGER NOT NULL PRIMARY KEY, time NOT NULL DEFAULT 0) WITHOUT ROWID;
CREATE TABLE servers (id INTEGER PRIMARY KEY, ip TEXT NOT NULL, port INTEGER NOT NULL DEFAULT 25565, last_query TIMESTAMP, hours REAL NOT NULL DEFAULT 0, announce_joins BOOLEAN NOT NULL DEFAULT FALSE, announce_joins_id INTEGER) WITHOUT ROWID;
CREATE TABLE times (id INTEGER NOT NULL, name TEXT NOT NULL, seconds REAL NOT NULL DEFAULT 0, UNIQUE (id, name));
CREATE TABLE servers (id INTEGER PRIMARY KEY, ip TEXT NOT NULL, port INTEGER NOT NULL DEFAULT 25565, last_query TIMESTAMP, show_hours BOOLEAN NOT NULL DEFAULT FALSE, announce_joins BOOLEAN NOT NULL DEFAULT FALSE, announce_joins_id INTEGER) WITHOUT ROWID;