Changed: Final
This commit is contained in:
parent
3e616132d4
commit
8b1b6fdd54
BIN
bot/assets/death.png
Normal file
BIN
bot/assets/death.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.2 KiB |
BIN
bot/assets/end.png
Normal file
BIN
bot/assets/end.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
BIN
bot/assets/fight.png
Normal file
BIN
bot/assets/fight.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
BIN
bot/assets/init.png
Normal file
BIN
bot/assets/init.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.3 KiB |
BIN
bot/assets/safe.png
Normal file
BIN
bot/assets/safe.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
BIN
bot/bot.db
Normal file
BIN
bot/bot.db
Normal file
Binary file not shown.
@ -1,9 +1,11 @@
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from mcrcon import MCRcon
|
||||
import enum
|
||||
from transitions import Machine
|
||||
from cogs.spawner import containers
|
||||
from cogs.spawner import get_server
|
||||
import utils
|
||||
|
||||
color = discord.Color.from_rgb(181, 24, 60)
|
||||
|
||||
class Whitelist:
|
||||
"A workflow machine for managing Whitelist states"
|
||||
@ -11,25 +13,6 @@ class Whitelist:
|
||||
Off = None
|
||||
toggle = None
|
||||
|
||||
class RCON(MCRcon):
|
||||
def __init__(self, ip: str, secret: str, port: int = 31066):
|
||||
super().__init__(ip, secret, port)
|
||||
self.connect()
|
||||
|
||||
def whitelist(self):
|
||||
self.whitelist.toggle()
|
||||
cmds = "/whitelist {}".format(self.whitelist.current_state.id)
|
||||
print(cmds)
|
||||
|
||||
def sendcmd(self, cmds) -> None:
|
||||
if isinstance(cmds, str):
|
||||
return self.command(str)
|
||||
if isinstance(cmds, list):
|
||||
return [self.command(cmd) for cmd in cmds]
|
||||
|
||||
def __del__(self):
|
||||
self.disconnect()
|
||||
|
||||
class States(enum.Enum):
|
||||
NOTHING = 0
|
||||
INIT = 1
|
||||
@ -41,7 +24,6 @@ class States(enum.Enum):
|
||||
class Minecraft(commands.Cog):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
self.servers = dict()
|
||||
|
||||
transitions = [
|
||||
['init_game', States.NOTHING, States.INIT],
|
||||
@ -68,21 +50,12 @@ class Minecraft(commands.Cog):
|
||||
server_name: str
|
||||
Server on which the Session should be initialized
|
||||
"""
|
||||
server_name = server_name.title()
|
||||
|
||||
c = None
|
||||
for container in containers:
|
||||
if server_name == container.name:
|
||||
c = container
|
||||
break
|
||||
c = get_server(server_name)
|
||||
|
||||
if not c:
|
||||
await ctx.send("---The server doesn't run---")
|
||||
return
|
||||
|
||||
conn = RCON(str(c.ip), c.rcon_pass, c.rcon_port)
|
||||
self.servers[server_name] = conn
|
||||
|
||||
cmds = [
|
||||
"/effect give @a minecraft:resistance infinite 255 true",
|
||||
"/effect give @a minecraft:saturation infinite 4 true",
|
||||
@ -92,9 +65,29 @@ class Minecraft(commands.Cog):
|
||||
"/worldborder set 5",
|
||||
"/whitelist off"
|
||||
]
|
||||
c.rcon.rconnect()
|
||||
c.rcon.sendcmd(cmds)
|
||||
|
||||
conn.sendcmd(cmds)
|
||||
await ctx.send("init Border Wars Game")
|
||||
embed = discord.Embed(
|
||||
title=f"Border Wars @ {server_name.title()}",
|
||||
description='''
|
||||
Session initialized
|
||||
Get ready to get a good armorset.
|
||||
|
||||
**Explanation**
|
||||
This phase last as long as the moderator wants.
|
||||
Every player is immune to damage and can't die by hunger.
|
||||
Look out for a good direction to scout.
|
||||
|
||||
Happy Border Wars!
|
||||
''',
|
||||
color=color,
|
||||
timestamp=utils.now()
|
||||
)
|
||||
file = discord.File("../assets/init.png", filename="init.png")
|
||||
embed.set_thumbnail(url="attachment://init.png")
|
||||
|
||||
await ctx.send(file=file, embed=embed)
|
||||
|
||||
@commands.hybrid_command(name='safe')
|
||||
async def safe(self, ctx: commands.Context, server_name: str):
|
||||
@ -108,25 +101,12 @@ class Minecraft(commands.Cog):
|
||||
server_name: str
|
||||
Server on which the Session should be initialized
|
||||
"""
|
||||
server_name = server_name.title()
|
||||
c = get_server(server_name)
|
||||
|
||||
c = None
|
||||
for container in containers:
|
||||
if server_name == container.name:
|
||||
c = container
|
||||
break
|
||||
|
||||
if not c:
|
||||
await ctx.send("---The server doesn't run---")
|
||||
return
|
||||
|
||||
conn = self.servers.get(server_name)
|
||||
|
||||
if not conn:
|
||||
await ctx.send("---Border Wars Session not Initialized---")
|
||||
return
|
||||
|
||||
|
||||
|
||||
cmds = [
|
||||
'''/title @a subtitle ["",{"text":"bei ","color":"blue"},{"text":"BORDER WARS!","bold":true,"color":"red"}]''',
|
||||
'''/title @a title {"text":"Viel Glück!","bold":true,"color":"blue"}''',
|
||||
@ -137,9 +117,29 @@ class Minecraft(commands.Cog):
|
||||
"/effect clear @a"
|
||||
]
|
||||
|
||||
conn.sendcmd(cmds)
|
||||
await ctx.send("Switched to Safe Phase")
|
||||
|
||||
c.rcon.sendcmd(cmds)
|
||||
|
||||
embed = discord.Embed(
|
||||
title=f"Border Wars @ {server_name.title()}",
|
||||
description='''
|
||||
Switched to Safe Phase
|
||||
Hide from other players and scout for resources.
|
||||
|
||||
**Explanation**
|
||||
This phase lasts 30 minutes, after that the fighting phase begins.
|
||||
Every player who dies will keep there inventory.
|
||||
Get a good armorset and be ready to fight.
|
||||
|
||||
Happy Border Wars!
|
||||
''',
|
||||
color=color,
|
||||
timestamp=utils.now()
|
||||
)
|
||||
file = discord.File("../assets/safe.png", filename="safe.png")
|
||||
embed.set_thumbnail(url="attachment://safe.png")
|
||||
|
||||
await ctx.send(file=file, embed=embed)
|
||||
|
||||
@commands.hybrid_command(name='fight')
|
||||
async def fight(self, ctx: commands.Context, server_name: str):
|
||||
"""
|
||||
@ -152,25 +152,12 @@ class Minecraft(commands.Cog):
|
||||
server_name: str
|
||||
Server on which the Session should be initialized
|
||||
"""
|
||||
server_name = server_name.title()
|
||||
|
||||
c = None
|
||||
for container in containers:
|
||||
if server_name == container.name:
|
||||
c = container
|
||||
break
|
||||
c = get_server(server_name)
|
||||
|
||||
if not c:
|
||||
await ctx.send("---The server doesn't run---")
|
||||
return
|
||||
|
||||
conn = self.servers.get(server_name)
|
||||
|
||||
if not conn:
|
||||
await ctx.send("---Border Wars Session not Initialized---")
|
||||
return
|
||||
|
||||
|
||||
cmds = [
|
||||
'''/title @a subtitle {"text":"ÜBERLEBEN!","bold":true,"color":"red"}''',
|
||||
'''/title @a title {"text":"Möge der beste","color":"blue"}''',
|
||||
@ -179,8 +166,28 @@ class Minecraft(commands.Cog):
|
||||
"/gamerule keepInventory false"
|
||||
]
|
||||
|
||||
conn.sendcmd(cmds)
|
||||
await ctx.send("Switched to Fight Phase")
|
||||
c.rcon.sendcmd(cmds)
|
||||
|
||||
embed = discord.Embed(
|
||||
title=f"Border Wars @ {server_name.title()}",
|
||||
description='''
|
||||
Switched to Fight Phase
|
||||
Now the real fun begins.
|
||||
|
||||
**Explanation**
|
||||
This phase lasts 60 minutes, after that the game ends.
|
||||
Every player can die now and therefor will lose.
|
||||
Look out for other players.
|
||||
|
||||
Happy Border Wars!
|
||||
''',
|
||||
color=color,
|
||||
timestamp=utils.now()
|
||||
)
|
||||
file = discord.File("../assets/fight.png", filename="fight.png")
|
||||
embed.set_thumbnail(url="attachment://fight.png")
|
||||
|
||||
await ctx.send(file=file, embed=embed)
|
||||
|
||||
@commands.hybrid_command(name='death')
|
||||
async def death(self, ctx: commands.Context, server_name: str):
|
||||
@ -194,33 +201,40 @@ class Minecraft(commands.Cog):
|
||||
server_name: str
|
||||
Server on which the Session should be initialized
|
||||
"""
|
||||
server_name = server_name.title()
|
||||
c = get_server(server_name)
|
||||
|
||||
c = None
|
||||
for container in containers:
|
||||
if server_name == container.name:
|
||||
c = container
|
||||
break
|
||||
|
||||
if not c:
|
||||
await ctx.send("---The server doesn't run---")
|
||||
return
|
||||
|
||||
conn = self.servers.get(server_name)
|
||||
|
||||
if not conn:
|
||||
await ctx.send("---Border Wars Session not Initialized---")
|
||||
return
|
||||
|
||||
|
||||
cmds = [
|
||||
'''/title @a title ["",{"text":"Sudden ","color":"dark_blue"},{"text":"DEATH!","bold":true,"color":"red"}]''',
|
||||
"/playsound minecraft:entity.ender_dragon.growl ambient @a 0 64 0 80",
|
||||
"/worldborder set 5 600"
|
||||
]
|
||||
|
||||
conn.sendcmd(cmds)
|
||||
await ctx.send("Switched to Sudden Death Phase")
|
||||
c.rcon.sendcmd(cmds)
|
||||
|
||||
embed = discord.Embed(
|
||||
title=f"Border Wars @ {server_name.title()}",
|
||||
description='''
|
||||
Switched to Sudden Death
|
||||
Only one can be the Winner.
|
||||
|
||||
**Explanation**
|
||||
This phase lasts as long as only one player survives.
|
||||
The worldborder will now shrink 'till zero zero.
|
||||
Good Luck.
|
||||
|
||||
Happy Border Wars!
|
||||
''',
|
||||
color=color,
|
||||
timestamp=utils.now()
|
||||
)
|
||||
file = discord.File("../assets/death.png", filename="death.png")
|
||||
embed.set_thumbnail(url="attachment://death.png")
|
||||
|
||||
await ctx.send(file=file, embed=embed)
|
||||
|
||||
@commands.hybrid_command(name='end')
|
||||
async def end(self, ctx: commands.Context, server_name: str, playername: str):
|
||||
@ -236,24 +250,11 @@ class Minecraft(commands.Cog):
|
||||
playername: str
|
||||
Player which is announced as the Winner
|
||||
"""
|
||||
server_name = server_name.title()
|
||||
|
||||
c = None
|
||||
for container in containers:
|
||||
if server_name == container.name:
|
||||
c = container
|
||||
break
|
||||
c = get_server(server_name)
|
||||
|
||||
if not c:
|
||||
await ctx.send("---The server doesn't run---")
|
||||
return
|
||||
|
||||
conn = self.servers.get(server_name)
|
||||
|
||||
if not conn:
|
||||
await ctx.send("---Border Wars Session not Initialized---")
|
||||
return
|
||||
|
||||
|
||||
cmds = [
|
||||
"/worldborder center 0 0",
|
||||
@ -264,8 +265,20 @@ class Minecraft(commands.Cog):
|
||||
"/playsound minecraft:entity.ender_dragon_death ambient @a 0 64 0 80",
|
||||
]
|
||||
|
||||
conn.sendcmd(cmds)
|
||||
await ctx.send("Ended Border Wars Session")
|
||||
c.rcon.sendcmd(cmds)
|
||||
|
||||
embed = discord.Embed(
|
||||
title=f"Border Wars @ {server_name.title()}",
|
||||
description=f'''
|
||||
*Game Over*
|
||||
Congratulations **{playername}**.
|
||||
|
||||
Hope you had fun @ **Border Wars!**
|
||||
''',
|
||||
color=color,
|
||||
timestamp=utils.now()
|
||||
)
|
||||
file = discord.File("../assets/end.png", filename="end.png")
|
||||
embed.set_thumbnail(url="attachment://end.png")
|
||||
|
||||
|
||||
|
||||
await ctx.send(file=file, embed=embed)
|
||||
|
@ -4,35 +4,65 @@ import docker
|
||||
import random
|
||||
import socket
|
||||
from contextlib import closing
|
||||
from datetime import datetime
|
||||
import pytz
|
||||
from dataclasses import dataclass
|
||||
from ipaddress import IPv4Address
|
||||
import secrets
|
||||
from mcrcon import MCRcon
|
||||
import asyncio
|
||||
from models.users import *
|
||||
import utils
|
||||
|
||||
class RCON(MCRcon):
|
||||
def __init__(self, ip: str, secret: str, port: int):
|
||||
super().__init__(ip, secret, port)
|
||||
|
||||
def rconnect(self):
|
||||
self.connect()
|
||||
|
||||
def whitelist(self):
|
||||
pass
|
||||
|
||||
def sendcmd(self, cmds) -> None:
|
||||
if isinstance(cmds, str):
|
||||
return self.command(str)
|
||||
if isinstance(cmds, list):
|
||||
return [self.command(cmd) for cmd in cmds]
|
||||
|
||||
def __del__(self):
|
||||
self.disconnect()
|
||||
|
||||
@dataclass
|
||||
class Server:
|
||||
container: None
|
||||
name: str
|
||||
ip: IPv4Address
|
||||
rcon: RCON
|
||||
port: int
|
||||
players: int
|
||||
rcon_pass: str
|
||||
rcon_port: int
|
||||
|
||||
# Global List of all running Containers
|
||||
containers = list()
|
||||
def get_server(name):
|
||||
name = name.title()
|
||||
for container in containers:
|
||||
if container.name == name:
|
||||
return container
|
||||
return None
|
||||
|
||||
color = discord.Color.from_rgb(13, 183, 237)
|
||||
|
||||
def seed_generator():
|
||||
'''
|
||||
Generates a random minecraft seed
|
||||
'''
|
||||
seed = random.randrange(1_000_000_000, 100_000_000_000_000)
|
||||
if random.randrange(0,2) == 0:
|
||||
seed *= -1
|
||||
return str(seed)
|
||||
|
||||
def find_free_port():
|
||||
'''
|
||||
Returns the next available IPv4 Port
|
||||
'''
|
||||
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
|
||||
s.bind(('', 0))
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
@ -75,6 +105,13 @@ class Spawner(commands.Cog):
|
||||
enable_hardcore: bool
|
||||
Enables Hardcore Minecraft
|
||||
'''
|
||||
try:
|
||||
User.get(User.username == ctx.author.id)
|
||||
except:
|
||||
await ctx.send(f"{ctx.author.name} isn't registered!")
|
||||
return
|
||||
|
||||
# Send user a Waiting screen to avoid confusion
|
||||
embed = discord.Embed(
|
||||
title="Starting Server",
|
||||
description=f'''
|
||||
@ -83,17 +120,21 @@ class Spawner(commands.Cog):
|
||||
This could take up to **5 minutes**
|
||||
''',
|
||||
color=color,
|
||||
timestamp=datetime.now(pytz.timezone('Europe/Berlin'))
|
||||
timestamp=utils.now()
|
||||
)
|
||||
file = discord.File("../assets/clock.png", filename="clock.png")
|
||||
embed.set_thumbnail(url="attachment://clock.png")
|
||||
start = await ctx.send(file=file, embed=embed)
|
||||
|
||||
# Set up needed variables
|
||||
# Server Stuff
|
||||
port = find_free_port()
|
||||
server_name = server_name.title()
|
||||
# Rcon Stuff
|
||||
passwd = secrets.token_hex(32)
|
||||
rcon_port = find_free_port()
|
||||
|
||||
# Image Enviroment
|
||||
env = {
|
||||
"EULA": "true",
|
||||
"TYPE": "FABRIC",
|
||||
@ -120,7 +161,6 @@ class Spawner(commands.Cog):
|
||||
"MAX_MEMORY": "2G",
|
||||
"USE_AIKAR_FLAGS": "true",
|
||||
|
||||
#"MODS_FILE": "/extras/mods.txt",
|
||||
"OPS_FILE": "https://git.cyperpunk.de/Garde-Studios/Uno-MC/raw/branch/main/ops.json",
|
||||
"SYNC_SKIP_NEWER_IN_DESTINATION": "false",
|
||||
"MAX_PLAYERS": max_players,
|
||||
@ -138,6 +178,7 @@ class Spawner(commands.Cog):
|
||||
}
|
||||
|
||||
|
||||
# Decide between seed or world url if no ones given seed would be randomly generated
|
||||
if not seed and not world_url:
|
||||
seed = seed_generator()
|
||||
if seed:
|
||||
@ -145,6 +186,7 @@ class Spawner(commands.Cog):
|
||||
if world_url:
|
||||
env["WORLD"] = world_url
|
||||
|
||||
# setting up the container
|
||||
container = self.client.containers.run(
|
||||
image='itzg/minecraft-server:latest',
|
||||
environment=env,
|
||||
@ -157,14 +199,18 @@ class Spawner(commands.Cog):
|
||||
volumes={'mods.txt': {'bind': '/extras/mods.txt', 'mode': 'ro'}}
|
||||
)
|
||||
|
||||
# Connect Container to the appropiate network
|
||||
net = self.client.networks.get('bot_rcon')
|
||||
net.connect(container)
|
||||
|
||||
ip = self.client.containers.get(server_name).attrs['NetworkSettings']['Networks']['bot_rcon']['IPAddress']
|
||||
server = Server(container, server_name, IPv4Address(ip), port, max_players, passwd, rcon_port)
|
||||
# save container info
|
||||
ip = self.client.containers.get(server_name).attrs['NetworkSettings']['Networks']['bot_rcon']['IPAddress']
|
||||
rcon = RCON(ip, passwd, rcon_port)
|
||||
server = Server(container, server_name, rcon, port, max_players)
|
||||
|
||||
containers.append(server)
|
||||
|
||||
|
||||
# Send user the confirmation
|
||||
embed = discord.Embed(
|
||||
title="Success",
|
||||
description=f'''
|
||||
@ -174,7 +220,7 @@ class Spawner(commands.Cog):
|
||||
garde-studios.de:{port}
|
||||
''',
|
||||
color=color,
|
||||
timestamp=datetime.now(pytz.timezone('Europe/Berlin'))
|
||||
timestamp=utils.now()
|
||||
)
|
||||
file = discord.File("../assets/docker.png", filename="docker.png")
|
||||
embed.set_thumbnail(url="attachment://docker.png")
|
||||
@ -191,12 +237,17 @@ class Spawner(commands.Cog):
|
||||
ctx: commands.Context
|
||||
The context of the command invocation
|
||||
'''
|
||||
try:
|
||||
User.get(User.username == ctx.author.id)
|
||||
except:
|
||||
await ctx.send(f"{ctx.author.name} isn't registered!")
|
||||
return
|
||||
|
||||
embed = discord.Embed(
|
||||
title="Currently Running Servers",
|
||||
description="List of all currently running Minecraft Servers",
|
||||
color=color,
|
||||
timestamp=datetime.now(pytz.timezone('Europe/Berlin'))
|
||||
timestamp=utils.now()
|
||||
)
|
||||
|
||||
for container in containers:
|
||||
@ -223,6 +274,11 @@ class Spawner(commands.Cog):
|
||||
server_name: str
|
||||
Name of the server that should be removed
|
||||
'''
|
||||
try:
|
||||
User.get(User.username == ctx.author.id)
|
||||
except:
|
||||
await ctx.send(f"{ctx.author.name} isn't registered!")
|
||||
return
|
||||
|
||||
server_name = server_name.title()
|
||||
|
||||
@ -247,7 +303,7 @@ class Spawner(commands.Cog):
|
||||
title="Killed",
|
||||
description=f"{server_name} killed!",
|
||||
color=color,
|
||||
timestamp=datetime.now(pytz.timezone('Europe/Berlin'))
|
||||
timestamp=utils.now()
|
||||
)
|
||||
|
||||
file = discord.File("../assets/rip.png", filename="rip.png")
|
||||
|
@ -1,12 +1,165 @@
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import DeclarativeBase
|
||||
from models.users import *
|
||||
from mojang import API
|
||||
import utils
|
||||
|
||||
#engine = create_engine("sqlite://user.sqlite", echo=True)
|
||||
#connection = engine.connect()
|
||||
|
||||
class User(DeclarativeBase):
|
||||
pass
|
||||
color = discord.Color.from_rgb(79, 227, 119)
|
||||
|
||||
class UserManager(commands.Cog):
|
||||
pass
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
def gen_user_info(self, user_name: str, user_id: int):
|
||||
'''
|
||||
Generates user output Embed
|
||||
|
||||
Parameters
|
||||
----------
|
||||
user_name: str
|
||||
given user name
|
||||
user_id: int
|
||||
discord user id to access database info
|
||||
'''
|
||||
user = User.get(User.username == user_id)
|
||||
embed = discord.Embed(
|
||||
title=user_name if not user.is_admin else f'{user_name} (Admin)',
|
||||
description=f'''
|
||||
Name: {user.mc_name}
|
||||
UUID: {user.mc_uuid}
|
||||
Registered since {user.registration_date.strftime("%d.%m.%Y, %H:%M:%S")}
|
||||
''',
|
||||
color=color,
|
||||
timestamp=utils.now()
|
||||
)
|
||||
return embed
|
||||
|
||||
@commands.hybrid_command(name='info')
|
||||
async def info(self, ctx: commands.Context):
|
||||
'''
|
||||
Registers Users to internal Database
|
||||
and links there minecraft username to there discord account.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx: commands.Context
|
||||
The context of the command invocation
|
||||
'''
|
||||
try:
|
||||
user = User.get(User.username == ctx.author.id)
|
||||
await ctx.send(embed=self.gen_user_info(ctx.author.name, ctx.author.id))
|
||||
except:
|
||||
await ctx.send(f"{ctx.author.name} isn't registered")
|
||||
|
||||
@commands.hybrid_command(name='register')
|
||||
async def register(self, ctx: commands.Context, minecraft_name: str):
|
||||
'''
|
||||
Registers Users to internal Database
|
||||
and links there minecraft username to there discord account.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx: commands.Context
|
||||
The context of the command invocation
|
||||
minecraft_name: str
|
||||
The minecraft user name to link with
|
||||
'''
|
||||
# Get minecraft uuid
|
||||
api = API()
|
||||
uuid = api.get_uuid(minecraft_name)
|
||||
if not uuid:
|
||||
await ctx.send("Username doesn't exist")
|
||||
return
|
||||
|
||||
# build user
|
||||
try:
|
||||
user = User(
|
||||
username=ctx.author.id,
|
||||
mc_name=minecraft_name,
|
||||
mc_uuid=uuid,
|
||||
is_admin=False if not ctx.author.id == 418848241036165160 else True
|
||||
)
|
||||
user.save()
|
||||
except IntegrityError:
|
||||
await ctx.send("You're already registered")
|
||||
return
|
||||
|
||||
await ctx.send(embed=self.gen_user_info(ctx.author.name, ctx.author.id))
|
||||
|
||||
@commands.hybrid_command(name='delete')
|
||||
async def delete(self, ctx: commands.Context):
|
||||
'''
|
||||
Registers Users to internal Database
|
||||
and links there minecraft username to there discord account.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx: commands.Context
|
||||
The context of the command invocation
|
||||
'''
|
||||
try:
|
||||
user = User.get(User.username == ctx.author.id)
|
||||
user.delete_instance()
|
||||
await ctx.send(f"Purged {ctx.author.name} from database!")
|
||||
except:
|
||||
await ctx.send(f"{ctx.author.name} isn't registered!")
|
||||
|
||||
@commands.hybrid_command(name='op')
|
||||
async def op(self, ctx: commands.Context, member: discord.Member):
|
||||
'''
|
||||
Toggels if User is an Admin
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx: commands.Context
|
||||
The context of the command invocation
|
||||
'''
|
||||
user = User.get(User.username == ctx.author.id)
|
||||
if not user.is_admin:
|
||||
await ctx.send("You're not allowed to use this command")
|
||||
return
|
||||
|
||||
if member.id == 418848241036165160:
|
||||
await ctx.send(f"{member.name} is always an admin")
|
||||
return
|
||||
|
||||
user = User.get(User.username == member.id)
|
||||
user.is_admin = not user.is_admin
|
||||
user.save()
|
||||
await ctx.send(embed=self.gen_user_info(member.name, member.id))
|
||||
|
||||
|
||||
@commands.hybrid_command(name='all')
|
||||
async def all(self, ctx: commands.Context):
|
||||
'''
|
||||
Returns User info
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx: commands.Context
|
||||
The context of the command invocation
|
||||
'''
|
||||
try:
|
||||
user = User.get(User.username == ctx.author.id)
|
||||
if not user.is_admin:
|
||||
await ctx.send("You're not allowed to use this command")
|
||||
return
|
||||
except:
|
||||
await ctx.send(f"{ctx.author.name} isn't registered")
|
||||
return
|
||||
|
||||
|
||||
embed = discord.Embed(
|
||||
title="All Users",
|
||||
description="Registered Users in Database",
|
||||
color=color,
|
||||
timestamp=utils.now()
|
||||
)
|
||||
|
||||
rows = User.select()
|
||||
for row in rows:
|
||||
member = await ctx.guild.fetch_member(row.username)
|
||||
member = member if not row.is_admin else f'{member} (Admin)'
|
||||
reg_date = row.registration_date.strftime("%d.%m.%Y, %H:%M:%S")
|
||||
embed.add_field(name=member, value="{}\n{}\n{}\n".format(row.mc_name, row.mc_uuid, reg_date))
|
||||
await ctx.send(embed=embed)
|
||||
|
10
bot/models/base.py
Normal file
10
bot/models/base.py
Normal file
@ -0,0 +1,10 @@
|
||||
from peewee import *
|
||||
from playhouse.postgres_ext import *
|
||||
import os
|
||||
import datetime
|
||||
|
||||
db = SqliteDatabase('bot.db')
|
||||
|
||||
class BaseModel(Model):
|
||||
class Meta:
|
||||
database = db
|
13
bot/models/containers.py
Normal file
13
bot/models/containers.py
Normal file
@ -0,0 +1,13 @@
|
||||
from peewee import *
|
||||
from models.base import BaseModel
|
||||
import datetime
|
||||
|
||||
class Container(BaseModel):
|
||||
# Container
|
||||
name =
|
||||
# players =
|
||||
port =
|
||||
|
||||
# RCON
|
||||
rcon_port =
|
||||
rcon_pwd =
|
12
bot/models/users.py
Normal file
12
bot/models/users.py
Normal file
@ -0,0 +1,12 @@
|
||||
from peewee import *
|
||||
from models.base import BaseModel
|
||||
import datetime
|
||||
|
||||
class User(BaseModel):
|
||||
username = CharField(unique=True)
|
||||
mc_name = CharField(unique=True)
|
||||
mc_uuid = CharField(unique=True)
|
||||
is_admin = BooleanField(default=False)
|
||||
registration_date = DateTimeField(default=datetime.datetime.now())
|
||||
|
||||
User.create_table()
|
@ -11,13 +11,18 @@ docker==7.1.0
|
||||
frozenlist==1.4.1
|
||||
greenlet==3.1.1
|
||||
idna==3.10
|
||||
Jinja2==3.1.4
|
||||
MarkupSafe==3.0.1
|
||||
mcrcon==0.7.0
|
||||
mojang==1.1.0
|
||||
multidict==6.1.0
|
||||
peewee==3.17.7
|
||||
psycopg2-binary==2.9.9
|
||||
Pygments==2.18.0
|
||||
python-dotenv==1.0.1
|
||||
pytz==2024.2
|
||||
requests==2.32.3
|
||||
six==1.16.0
|
||||
SQLAlchemy==2.0.35
|
||||
transitions==0.9.2
|
||||
typing_extensions==4.12.2
|
||||
urllib3==2.2.3
|
||||
|
7
bot/utils.py
Normal file
7
bot/utils.py
Normal file
@ -0,0 +1,7 @@
|
||||
import datetime
|
||||
import pytz
|
||||
|
||||
now = lambda: datetime.datetime.now(pytz.timezone('Europe/Berlin'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(now())
|
Loading…
Reference in New Issue
Block a user