Files
WorldCraft_Discord_Bot/cogs/playerlink.py
2020-11-19 12:11:11 +01:00

190 lines
7.7 KiB
Python
Executable File

import discord
from discord.ext import commands
import random
import string
import socket
import asyncio
import threading
from functions.timer import Timer
from data import constants
from functions.emoji_check import *
import re
from data.DatabaseConnection import *
# 25216 --> uuid server
# 25224 --> send chat server
def get_random_string(length):
# Random string with the combination of lower and upper case
letters = string.ascii_letters + "0123456789"
result_str = ''.join(random.choice(letters) for i in range(length))
return result_str
class PlayerError(Exception):
pass
class WrongCodeError(Exception):
pass
class TimerExpiredError(Exception):
pass
def get_player_uuid(minecraftname):
HOST = '192.168.1.214' # The server's hostname or IP address
PORT = 25216 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.send(bytes("{}\n".format(minecraftname), encoding="ascii"))
data = s.recv(1024)
data_string = data.decode("utf-8").strip('\n')
if data_string == "PlayerError":
raise PlayerError()
return data_string
def send_chat(discordname, minecraftname, code):
HOST = '192.168.1.214' # The server's hostname or IP address
PORT = 25224 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.send(bytes("{}\t{}\t{}\n".format(deEmojify(discordname), minecraftname, code), encoding="ascii"))
data = s.recv(1024)
data_string = data.decode("utf-8").strip('\n')
if data_string == "PlayerError":
raise PlayerError()
return data_string
class PlayerLink(commands.Cog):
def __init__(self, client):
self.client = client
def get_linked_role(self):
return discord.utils.get(self.client.get_guild(constants.WorldCraft).roles, id=constants.roleLinked)
@commands.command(name="Link")
async def link(self, ctx, arg):
channelid = ctx.channel.id
authorid = ctx.author.id
if channelid == constants.DiscordLinkerID:
dbLinker = PlayerDBLinker()
if dbLinker.discordidused(authorid):
await ctx.send(f"{ctx.author.mention}, your account is already linked!")
dbLinker.close()
return
code = get_random_string(8)
def check(message: discord.Message):
return message.channel.id == channelid and message.author.id == authorid
# creates the embed for the link message
def create_embed(discord_author, minecraftname, timer, error=None, success=False):
embed = discord.Embed(title="WorldCraft Linker")
embed.add_field(name="How to:", value= "A code has been sent to your minecraft chat in the WorldCraft server.\nSend the code in this channel.")
embed.add_field(name="Minecraft Name:", value=f"{minecraftname}", inline=False)
embed.add_field(name="Discord Name:", value=f"{discord_author.mention}", inline=False)
# use dictionary and set color string before the message: example => r(ed):message
if isinstance(error, WrongCodeError):
embed.add_field(name="Error", value=f"The code is wrong!", inline=False)
embed.colour = discord.Colour.red()
elif isinstance(error, TimerExpiredError):
embed.colour = discord.Colour.red()
embed.add_field(name="Timer", value=f"The timer expired!", inline=False)
elif (success == True):
embed.add_field(name="Success", value=f"The link was successfull!", inline=False)
embed.colour = discord.Colour.green()
elif (timer.ended):
embed.add_field(name="Timer", value=f"The code is expired!", inline=False)
embed.colour = discord.Colour.red()
elif (timer.minutes == 2):
embed.add_field(name="Timer", value=f"The code will expire in { str(timer.minutes)} minutes", inline=False)
embed.colour = discord.Colour.orange()
elif (timer.minutes < 2):
embed.add_field(name="Timer", value=f"The code will expire in less than { str(timer.minutes + 1)} {'minutes' if timer.minutes + 1 > 1 else 'minute'}", inline=False)
embed.colour = discord.Colour.orange()
else:
embed.add_field(name="Timer", value=f"The code will expire in {str(timer.minutes).zfill(2)}:{str(timer.seconds).zfill(2)}", inline=False)
embed.colour = discord.Colour.orange()
return embed
async def send_timer_messages(timer, message):
while (not timer.ended):
# maybe create a task from this because this takes some time -> timer not accurate
if ((timer.minutes < 2 and timer.seconds == 59) or (timer.minutes == 0 and timer.seconds == 0)):
asyncio.create_task(message.edit(embed=create_embed(ctx.author, arg, timer)))
await asyncio.sleep(1)
message = None
try:
uuid = get_player_uuid(arg)
send_chat(ctx.author.name, arg, code)
#message_send_time =
timer = Timer(2, 0)
timer.start()
message = await ctx.send(embed=create_embed(ctx.author, arg, timer))
task = asyncio.create_task(send_timer_messages(timer, message))
# Wait for the code response
msg = await self.client.wait_for('message', check=check, timeout=120)
if msg.content == code:
dbLinker = PlayerDBLinker()
try:
dbLinker.linkPlayer(uuid, authorid)
await ctx.author.add_roles(self.get_linked_role())
timer.stop()
await message.edit(embed=create_embed(ctx.author, arg, timer, success=True))
except SQLInsertError:
await message.edit(embed=create_embed(ctx.author, arg, timer))
finally:
dbLinker.close()
else:
# this stops the timer task
timer.stop()
await message.edit(embed=create_embed(ctx.author, arg, timer, WrongCodeError()))
except PlayerError:
await ctx.send("Player '" + arg + "' not found")
except asyncio.TimeoutError:
if message != None:
await message.edit(embed=create_embed(ctx.author, arg, timer, TimerExpiredError()))
# except:
# await ctx.send("Something went wrong")
@commands.command(name="Unlink")
async def unlink(self, ctx):
authorid = ctx.author.id
channelid = ctx.channel.id
if channelid == constants.DiscordLinkerID:
dbLinker = PlayerDBLinker()
try:
dbLinker.unlinkPlayer(authorid)
await ctx.author.remove_roles(self.get_linked_role())
await ctx.send(f"{ctx.author.mention}, unlinked your account")
except UnLinkError:
await ctx.send("The unlink was unsuccessfull")
except WrongMinecraftName:
await ctx.send("Wrong minecraft name!")
except PlayerNotLinked:
await ctx.send("Player not linked!")
finally:
dbLinker.close()
def setup(client):
client.add_cog(PlayerLink(client))