Files
WorldCraft_Discord_Bot/cogs/playerlink.py
2020-10-10 15:13:48 +02:00

138 lines
5.4 KiB
Python

import discord
from discord.ext import commands
import random
import string
import socket
import asyncio
import threading
from data import constants
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
def send_chat(discordname, minecraftname, code):
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 3333 # 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(discordname, minecraftname, code), encoding="ascii"))
data = s.recv(1024)
data_string = data.decode("utf-8").strip('\n')
if data_string == "PlayerError":
raise PlayerError()
return True
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
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)
if isinstance(error, WrongCodeError):
embed.add_field(name="Error", value=f"The code is wrong!", inline=False)
embed.colour = discord.Colour.red()
elif (timer.ended):
embed.add_field(name="Timer", value=f"The code is expired!", inline=False)
embed.colour = discord.Colour.red()
elif (success == True):
embed.add_field(name="Success", value=f"The link was successfull!", inline=False)
embed.colour = discord.Colour.green()
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 update_timer(timer, message):
while (not timer.ended):
await asyncio.sleep(1)
timer.update()
# 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)))
try:
send_chat(ctx.author.name, arg, code)
#message_send_time =
timer = Timer()
message = await ctx.send(embed=create_embed(ctx.author, arg, timer))
# Start timer in background
task = asyncio.create_task(update_timer(timer, message))
# Wait for the code response
msg = await self.client.wait_for('message', check=check)
if msg.content == code:
await ctx.author.add_roles(self.get_linked_role())
timer.ended = True
await message.edit(embed=create_embed(ctx.author, arg, timer, success=True))
else:
# this stops the timer task
task.cancel()
timer.ended = True
await message.edit(embed=create_embed(ctx.author, arg, timer, WrongCodeError()))
except PlayerError:
await ctx.send("Player '" + arg + "' not found")
#except:
# await ctx.send("Something went wrong")
@commands.command(name="Unlink")
async def unlink(self, ctx):
await ctx.author.remove_roles(self.get_linked_role())
await ctx.send("Unlinked your account")
class Timer():
def __init__(self):
self.minutes = 2
self.seconds = 0
self.ended = False
def update(self):
if (self.minutes > 0 and self.seconds == 0):
self.minutes -= 1
self.seconds = 59
elif (self.seconds > 0):
self.seconds -= 1
if (self.minutes == 0 and self.seconds == 0):
self.ended = True
def setup(client):
client.add_cog(PlayerLink(client))