/ Automatisierung2.0.0.py
Automatisierung2.0.0.py
   1  #!/usr/bin/python3.8
   2  #import the libraries:
   3  import asyncio,discord,random,requests,mctools,time,logging,json
   4  from datetime import datetime
   5  from bs4 import BeautifulSoup as bs4
   6  from datetime import datetime
   7  from discord.ext import commands, tasks
   8  from discord.utils import get
   9  
  10  format = logging.Formatter('%(name)s @ [%(asctime)s] - %(message)s', datefmt='%m/%d/%Y %I:%M %p')
  11  logger = logging.getLogger('The Butler')
  12  file = logging.FileHandler(filename='./ERRORS.log',mode='a')
  13  file.setFormatter(format)
  14  logger.addHandler(file)
  15  
  16  DATAPATH = './data.json'
  17  
  18  #WORKING ON
  19  #Theoretically optimizing the throne room loop - Not a pressing issue though
  20  
  21  """
  22  Functions verified to work as expected:
  23  getJSONfile
  24  writeJSONFile
  25  ReactionCheck
  26  serverCheck
  27  Loops verified to work as expected:
  28  StatusChangeLoop
  29  """
  30  
  31  #Bot Token:
  32  TOKEN = ""
  33  #Guild name:
  34  GUILD = "Bot test server"
  35  #Rcon setup stuff:
  36  #ANYTHING WITH A 2 AFTER IT REFERS TO THE SECONDARY SERVER
  37  """
  38  RCONPORT = '25575'
  39  PINGPORT='25565'  #Same port the server is hosted on
  40  RCONPORT2= '25579'
  41  PINGPORT2='25578' #Same port the secondary server is hosted on
  42  RCONPASS = 'Spghtt'
  43  RCONHOST = '192.168.29.39'
  44  """
  45  #SQL_DB = 'db.sqlite3'
  46  
  47  #Enable events:
  48  intents = discord.Intents.all()
  49  #Create a function to do things:
  50  prefixes = ['$']
  51  bot = commands.Bot(command_prefix = prefixes, intents = intents)
  52  
  53  #Global variables needed across functions:
  54  global ThroneRoomActive, Guild
  55  ThroneRoomActive = False
  56  RoleHeigherarchy = ["Citizenry","Good Lad","Count","Duke","Regent","Head Regent","King"]
  57  RoleHeigherarchy2 = ["Citizenry","Good Lady","Countess","Duchess","Regent","Head Regent","King"]
  58  GoodLadCheck = ['Good Lad','Good Lady','Count','Countess','Duke','Duchess','Regent','Head Regent','King']
  59  CountCheck = ['Count','Countess','Duke','Duchess','Regent','Head Regent','King']
  60  DukeCheck =['Duke','Duchess','Regent','Head Regent','King']
  61  RegentCheck = ['Regent','Head Regent','King']
  62  
  63  #Default responces:
  64  #Timeout:
  65  TIMEOUTR=['Mate, you timed out','Try typing like lightning next time buckaroo','My grandma can type faster than you and she\'s dead','Type faster...Please...']
  66  BADCOMMANDR=["Bruh, that aint a valid command", "Try that command again buckaroo",'My guy...You failed your one task of entering a valid command',\
  67              'Dont worry, that might not be a valid command but I\'m sure your next one will be', 'If you spent as much time on entering the right command as I do on these messages you might get them correct']
  68  
  69  def getJSONFile():
  70      with open(DATAPATH,'r') as F:
  71          temp = json.load(F)
  72      return temp
  73  
  74  def writeJSONFile(new):
  75      with open(DATAPATH,'w') as F:
  76          F.write(json.dumps(new,indent=2))
  77  
  78  def opCommand(Command,User,server):
  79      textData = ''
  80      jsonData = getJSONFile()
  81      if server == 'main':
  82          rconClient = mctools.mclient.RCONClient(host=jsonData['RCON']['ip'],port=jsonData['RCON']['main']['rconport'],format_method=1,timeout=60)
  83          rconClient.authenticate(jsonData['RCON']['password'])
  84          textData = rconClient.command(Command)
  85          textData = textData.replace('','')
  86          rconClient.stop()
  87      elif server == 'secondary':
  88          rconClient = mctools.mclient.RCONClient(host=jsonData['RCON']['ip'],port=jsonData['RCON']['secondary']['rconport'],format_method=1,timeout=60)
  89          rconClient.authenticate(jsonData['RCON']['password'])
  90          textData = rconClient.command(Command)
  91          textData = textData.replace('','')
  92          rconClient.stop()
  93      jsonData['RCONLogs'].append({'user':str(User.display_name),'date':str(datetime()),'command':str(Command),'return':str(textData)})
  94      writeJSONFile(jsonData)
  95      return textData
  96  
  97  def ReactionCheck(Message,left,right):
  98      def check(reaction, user):
  99          if reaction.message.id != Message.id or user == bot.user:
 100              return False
 101          if left and reaction.emoji == "⏪":
 102              return True
 103          if right and reaction.emoji == "⏩":
 104              return True
 105          return False
 106      return check
 107  
 108  async def serverCheck(ctx):
 109      embed = discord.Embed(color=discord.Color.dark_gold(),description='Which server would you like to run it on?')
 110      embed.add_field(name='Standard',value='The standard minecraft server')
 111      embed.add_field(name='Event',value='Minecraft server that minigames are run on')
 112      embed.set_footer(text='[1/2] is what you should put in the chat')
 113      message = await ctx.channel.send(embed=embed)
 114      try:
 115          response = await bot.wait_for("message",check=lambda i: i.author == ctx.message.author,timeout=60)
 116          await message.delete()
 117          await response.delete()
 118      except asyncio.TimeoutError:
 119          temp=await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description=random.choice(TIMEOUTR)))
 120          await message.delete()
 121          await temp.delete(delay=15)
 122          return 'FAIL'
 123      else:
 124          if response.content == '1':
 125              return 'main'
 126          elif response.content == '2':
 127              return 'secondary'
 128          else:
 129              temp=await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description=random.choice(BADCOMMANDR)))
 130              return 'FAIL'
 131  
 132  async def statUpdate(Port,cleared,server,event,message=None):
 133      try:
 134          ping = mctools.PINGClient(host=jsonData['RCON']['ip'],port=int(Port))
 135          stats = ping.get_stats()
 136          ping.stop()
 137      except:
 138          if server == 'main':
 139              embed = discord.Embed(color=discord.Color.dark_gold(),title='Main server')
 140          elif server == 'secondary':
 141              embed = discord.Embed(color=discord.Color.dark_gold(),title='Minigame server')
 142          embed.add_field(name='Server IP',value=('OFFLINE'),inline=False)
 143          embed.add_field(name='Status',value='OFFLINE')
 144          embed.add_field(name='Minecraft Version',value='OFFLINE')
 145          embed.add_field(name='Server TPS',value='OFFLINE',inline=False)
 146          embed.add_field(name='Server Uptime',value='OFFLINE',inline=False)
 147          embed.add_field(name='Player Stats',value='OFFLINE',inline=False)
 148          embed.add_field(name='Players Online',value='OFFLINE',inline=False)
 149          embed.add_field(name='Upcoming event',value='\u200b'+event)
 150          embed.add_field(name='Next Scheduled Restart',value='OFFLINE',inline=False)
 151          message = await importantChannels['serverstats'].send(embed=embed)
 152          return
 153      serverVersion=stats['version']['name']
 154      maxP=stats['players']['max']
 155      onlineCountP=stats['players']['online']
 156      pList = ''
 157      try:
 158          for index,i in enumerate(stats['players']['sample']):
 159              if index < len(stats['players']['sample'])-1:
 160                  temp = i[0].replace('\x1b','')
 161                  temp = temp.replace('[0m','')
 162                  pList += (temp+', ')
 163              else:
 164                  temp = i[0].replace('\x1b','')
 165                  temp = temp.replace('[0m','')
 166                  pList += (temp)
 167      except Exception as E:
 168          pList='NONE'
 169      jsonData=getJSONFile()
 170      if server == 'main':
 171          rconClient = mctools.mclient.RCONClient(host=jsonData['RCON']['ip'],port=jsonData['RCON']['main']['rconport'],format_method=1,timeout=60)
 172      else:
 173          rconClient = mctools.mclient.RCONClient(host=jsonData['RCON']['ip'],port=jsonData['RCON']['secondary']['rconport'],format_method=1,timeout=60)
 174      rconClient.authenticate(jsonData['RCON']['password'])
 175      tpsData = rconClient.command('tps')
 176      tpsData = tpsData.replace('','')
 177      daysData = rconClient.command('time query day')
 178      daysData = daysData.replace('','')
 179      rconClient.stop()
 180  
 181      tps = 0
 182      for i,char in enumerate(tpsData):
 183          if char == '*':
 184              tps += int(tpsData[i+1:i+3])
 185      tps = tps/3
 186      
 187      for i,char in enumerate(daysData):
 188          if i != len(daysData)-1:
 189              if char + daysData[i+1] == 's ':
 190                  days = daysData[i+2:]
 191                  break
 192  
 193      #formatting output for the standard server:
 194      if server == 'main':
 195          embed = discord.Embed(color=discord.Color.dark_gold(),title='Main server')
 196      elif server == 'secondary':
 197          embed = discord.Embed(color=discord.Color.dark_gold(),title='Minigame server')
 198      jsonData = getJSONFile()
 199      embed.add_field(name='Server IP',value=(jsonData['RCON']['ip']+':'),inline=False)
 200      embed.add_field(name='Status',value='Online')
 201      embed.add_field(name='Minecraft Version',value='\u200b'+str(serverVersion),inline=False)
 202      embed.add_field(name='Server TPS',value='\u200b'+str(tps),inline=False)
 203      embed.add_field(name='Server Uptime',value='\u200b'+(str(days)+' days'),inline=False)
 204      embed.add_field(name='Player Stats',value='\u200b'+(str(onlineCountP)+'/'+str(maxP)),inline=False)
 205      embed.add_field(name='Players Online',value='\u200b'+pList,inline=False)
 206      embed.add_field(name='Upcoming event',value='\u200b'+event)
 207      embed.add_field(name='Next Scheduled Restart',value='Wednesday night at midnight',inline=False)
 208  
 209      if cleared:
 210          await message.edit(embed=embed)
 211      else:
 212          message = await importantChannels['serverstats'].send(embed=embed)
 213      return message.id
 214  
 215  #Once the bot has fully come online run this function before everything else:
 216  @bot.event
 217  async def on_ready():
 218      global Guild, importantChannels, CITIZENRY,ThroneRoomActive
 219      Guild = get(bot.guilds, name = GUILD)
 220  
 221      for Role in Guild.roles:
 222          if Role.name == RoleHeigherarchy[0]:
 223              CITIZENRY = Role
 224  
 225      jsonData = getJSONFile()
 226      TH = Guild.get_channel(int(jsonData['channels']['throne-room']))
 227      AN = Guild.get_channel(int(jsonData['channels']['announcements']))
 228      AB = Guild.get_channel(int(jsonData['channels']['admin-bots']))
 229      SS = Guild.get_channel(int(jsonData['channels']['stats']))
 230      SR = Guild.get_channel(int(jsonData['channels']['rules']))
 231      importantChannels = dict(throneroom=TH,announcements=AN,adminbots=AB,serverstats=SS,serverrules=SR)
 232  
 233      #Update the loops that run in the background with no user input
 234      if jsonData['throne-room']['active'] == 'True':
 235          """ThroneRoomLoop.change_interval(seconds = TimeLeft)"""
 236          ThroneRoomActive = True
 237          ThroneRoomLoop.start(True,jsonData['throne-room']['time-left'])
 238      else:
 239          ThroneRoomActive = False
 240      StatusChangeLoop.start()
 241      await UpdateThroneRoomFile()
 242      #serverStats.start()
 243  
 244  #Change statuses of the bot:
 245  @tasks.loop(hours = 5)
 246  async def StatusChangeLoop():
 247      Options = ["I spent way too much time on this","I should get a life","Why do I do all the grunt work?","Pedro for president 2024!",\
 248                  "Minecraft","Can I earn money doing this?","Earth is fine, people are dumb",\
 249                  "Everyone should be able to do one card trick, tell two jokes, and recite three poems, in case they are ever trapped in an elevator",\
 250                  "Bruh","When a bird hits your window have you ever wondered if God is playing angry birds with you?",\
 251                  "When I’m on my death bed, I want my final words to be “I left one million dollars in the…",\
 252                  "My study period = 15 minutes. My break time = 3 hours","Never make eye contact while eating a banana",\
 253                  "C.L.A.S.S- come late and start sleeping","My biggest concern in life is actually how my online friends can be informed of my death!",\
 254                  "How do you know what it’s like to be stupid if you’ve never been smart?","I hate fake people. You know what I’m talking about. Mannequins.",\
 255                  "Everything is 10x funnier when you are not supposed to laugh.","It may look like I’m deep in thought, but 99% of the time I’m just thinking about what food to eat later.",\
 256                  "\"Focusing\" on school work","That awkward moment when you realize that dora, who is 5, has more freedom than you.",\
 257                  "That awkward when your eyes assumed “moment” was written after \"awkward\"","Never gonna let you down","Never gonna run around",\
 258                  "https://www.youtube.com/watch?v=dQw4w9WgXcQ","I lost the game","Dont forget to like and subscribe!","Imagine putting in effort",\
 259                  "I put the most effort into these quotes","If you have more status ideas, DM helaugheth#5815","Psst, is anyone watching these?",\
 260                  "There are 10 types of people, those who understand binary and those who dont","I should focus on college homework","There are 13 lines of quotes for me to choose from.",\
 261                  "Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn","#SupportC'thulu","#LearnParsletoung","I'm adding these during class","lol",\
 262                  "XD","Bro this releaves so much boredom","Shoot, I should do homework","College classes are BORING","All around me are familiar faces...",\
 263                  "What is this...\"Fish showcommands\" thing?","Yar dar dar and a hody hody do","https://www.youtube.com/watch?v=Q04Lkw91Gts"]
 264  
 265      Status = random.choice(Options)
 266      await bot.change_presence(activity = discord.Game(name = Status))
 267  
 268  #updates the Throne room file with information about it
 269  @tasks.loop(hours = 1)
 270  async def UpdateThroneRoomFile(new_m_data = None):
 271      if ThroneRoomActive:
 272          CurrentTime = int(datetime.now().timestamp())
 273          if ThroneRoomLoop.next_iteration != None:
 274              LoopTime = int(ThroneRoomLoop.next_iteration.timestamp())
 275              TimeLeft = str(LoopTime - CurrentTime)
 276          else:
 277              TimeLeft = 'None'
 278              LoopTime = 'None'
 279      else:
 280          TimeLeft = 'None'
 281          LoopTime = 'None'
 282      jsonData = getJSONFile()
 283          
 284      jsonData['throne-room']['active'] = str(ThroneRoomActive)
 285      jsonData['throne-room']['time-left'] = str(TimeLeft)
 286      if new_m_data != None:
 287          jsonData['throne-room']['messages'].append(new_m_data)
 288      writeJSONFile(jsonData)
 289  
 290  #Main throne room loop:
 291  @tasks.loop(hours = 196)
 292  async def ThroneRoomLoop(RebootedUp,timeLeft=None):
 293      global ThroneRoomActive
 294      Active = False
 295  
 296      """
 297      RebootedUp - Server was rebooted while the throne room was running. Just needs to make sure perms are given and make an anouncement to admins
 298      """
 299      if RebootedUp:
 300          await importantChannels['throneroom'].set_permissions(CITIZENRY, view_channel = True)
 301          await importantChannels['adminbots'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description="Server restarted, resuming the "+importantChannels['throneroom'].mention+" loop. Citizenry has been given access. No announcements made."))
 302          Active = True
 303          timeLeft = datetime.fromtimestamp(int(timeLeft))
 304          t = (datetime.now()-timeLeft).total_seconds()
 305          ThroneRoomLoop.change_interval(seconds=t)
 306      else:
 307          Active = True
 308          if ThroneRoomLoop.current_loop == 0:
 309              Active = True
 310          elif (ThroneRoomLoop.current_loop % 2) == 0:
 311              Active = True
 312          else:
 313              Active = False
 314                  
 315          if Active:
 316              await importantChannels['throneroom'].purge()
 317              await importantChannels['throneroom'].set_permissions(CITIZENRY, view_channel = True)
 318              temp = ""
 319              temp2 = ""
 320              for role in Guild.roles:
 321                  if role.name == RoleHeigherarchy[1]:
 322                      temp = role.mention
 323                  elif role.name == RoleHeigherarchy2[1]:
 324                      temp2 == role.mention
 325                      break
 326              await importantChannels['throneroom'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description=("Use the command `Fish title` to automatically request the rank higher than you are currently at. You must have the"+temp+"/"+temp2+"rank to request higher ranks. You can use `Fish Title help` to get more help.")))
 327              Temp = await importantChannels['announcements'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description=(importantChannels['throneroom'].mention + " is now open all yall!")))
 328              await Temp.delete(delay = 346500)
 329          else:
 330              await importantChannels['throneroom'].set_permissions(CITIZENRY, view_channel = False)
 331              Temp = await importantChannels['announcements'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description=("I just closed the "+importantChannels['throneroom'].mention+" so voting will be held and results will be announced somewhat soon, depends on how active members are.")))
 332              Temp.delete(delay=30000)
 333              for member in  Guild.members:
 334                  Cleared = False #Citizenry check
 335                  Cleared2 = True #Check so that they do NOT have Good Lad/Lady
 336                  for role in member.roles:
 337                      if role.name == RoleHeigherarchy[0]:
 338                          Cleared = True
 339                      if role.name == RoleHeigherarchy[1] or role.name == RoleHeigherarchy2[1]:
 340                          Cleared2 = False
 341                                      
 342                  if Cleared and Cleared2:
 343                      for i in Guild.roles:
 344                          if i.name == RoleHeigherarchy[0]:
 345                              lad = i
 346                          elif i.name == RoleHeigherarchy2[0]:
 347                              lady = i
 348                              break
 349                      Message = await importantChannels['throneroom'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description=("Grant " + member.mention + " the "+lad.mention+"/"+lady.mention+" role?")))
 350                      UpdateThroneRoomFile({"messageID":str(Message.id),"role":str(CITIZENRY.id),'discordID':str(Message.author.id)})
 351  
 352              jsonData = getJSONFile()
 353              for i in jsonData['throne-room']['messages']:
 354                  message = await importantChannels['throneroom'].fetch_message(int(i['messageID']))
 355                  await message.add_reaction("👍")
 356                  await message.add_reaction("👎")
 357  
 358      ThroneRoomActive = Active
 359  
 360  #Update server stats for people to be able to see
 361  #@tasks.loop(minutes=5)
 362  async def serverStats():
 363      jsonData = getJSONFile()
 364      main_message = None
 365      secondary_message = None
 366      if type(jsonData['stats']['main']['messageID']) == type('temp'):
 367          main_message = await importantChannels['serverstats'].fetch_message(int(jsonData['stats']['main']['messageID']))
 368      if type(jsonData['stats']['secondary']['messageID']) == type('temp'):
 369          secondary_message = await importantChannels['serverstats'].fetch_message(int(jsonData['stats']['secondary']['messageID']))
 370  
 371      secondary_event = jsonData['stats']['secondary']['event']
 372      main_event = jsonData['stats']['main']['event']
 373      await statUpdate(jsonData['RCON']['main']['mainport'],True,'main',main_event,main_message)
 374      await statUpdate(jsonData['RCON']['secondary']['mainport'],True,'secondary',secondary_event,secondary_message)
 375  
 376  @bot.command(help='Duke level command')
 377  @commands.has_any_role(*DukeCheck)
 378  async def removelink(ctx):
 379      ToDelete = []
 380      await ctx.message.delete()
 381      ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="Ping the discord user to force an unlink, *or* you can just slap the minecraft username in")))
 382      try:
 383          response = await bot.wait_for("message",check=lambda i: i.author == ctx.message.author,timeout=60)
 384          ToDelete.append(response)
 385      except asyncio.TimeoutError:
 386          ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description=random.choice(TIMEOUTR))))
 387      else:
 388          jsonData = getJSONFile()
 389          discordUsed = False
 390          if len(response.raw_mentions) > 0:
 391              discordUsed = True
 392          found = False
 393          for i in jsonData['registry']:
 394              if discordUsed:
 395                  if response.raw_mentions[0] == int(i['discordID']):
 396                      soup = bs4(requests.get("https://mcuuid.net/?q="+str(i['uuid'])).text,features="html.parser")
 397                      username = soup.find("input",attrs={"id":"results_username"})["value"]
 398                      user=Guild.get_member(response.raw_mentions[0])
 399                      ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description=(user.mention+' is linked to '+username+\
 400                          '. Please confirm admin unlinkage and that the requestor has correctly inputted their username [yes/no] THIS CANNOT BE UNDONE'))))
 401                  found = True
 402                  break
 403              else:
 404                  soup = bs4(requests.get("https://mcuuid.net/?q="+str(response.content)).text,features="html.parser")
 405                  username=response.content
 406                  user=Guild.get_member(int(i['discordID']))
 407                  ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description=(response.content+' is linked to '+user.mention+\
 408                          '. Please confirm admin unlinkage and that the requestor has correctly inputted their username [yes/no] THIS CANNOT BE UNDONE'))))
 409                  found = True
 410                  break
 411          if not found:
 412              if not discordUsed:
 413                  ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description='I couldn\'t find anyone linked up that Minecraft account, try again using the Discord ping mate')))
 414              else:
 415                  ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description='I couldn\'t find anyone linked up that Discord account, try again using the Minecraft username mate')))
 416          else:
 417              try:
 418                  response2 = await bot.wait_for("message",check=lambda i: i.author == ctx.message.author,timeout=60)
 419                  ToDelete.append(response)
 420              except asyncio.TimeoutError:
 421                  ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description=random.choice(TIMEOUTR))))
 422              else:
 423                  if response2.content.lower() == 'yes' or response2.content.lower() == 'y':
 424                      jsonData['registry'].remove(i)
 425                      writeJSONFile(jsonData)
 426                      await importantChannels['adminbots'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description=(str(ctx.message.author.mention)+' has forcefully removed the link between '+user.mention+' and '+username)))
 427                      textData = opCommand('whitelist remove '+username, user, 'main')  
 428                      textData += '    ' + opCommand('whitelist remove '+username, user, 'secondary')
 429                      jsonData.remove(i)
 430                      writeJSONFile(jsonData) 
 431                      await importantChannels['adminbots'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description='\u200b'+textData))
 432                  
 433                  elif response2.content.lower() == 'no' or response2.content.lower() == 'n':
 434                      ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description='Right-o then')))
 435                  else:
 436                      ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description=random.choice(BADCOMMANDR))))
 437      """for i in ToDelete:
 438          await i.delete(delay = 30)"""
 439  
 440  @bot.command(help='Regent level command')
 441  @commands.has_any_role(*RegentCheck)
 442  async def errors(ctx):
 443      file = discord.File(fp='./ERRORS.log', filename="ERRORS.log")
 444      await importantChannels['adminbots'].send(file=file)
 445  
 446  #help= says it all. They must have the Good Lad role to do this though
 447  @bot.command(help = "Request 1 title higher than you currently have.")
 448  @commands.has_any_role(*GoodLadCheck)
 449  async def title(ctx):
 450      Message = ctx.message
 451      await Message.delete()
 452      ToDelete = []
 453      jsonData = getJSONFile()
 454      for i in jsonData['throne-room']['messages']:
 455          if int(i['discordID']) == Message.author.id:
 456              m = await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description='Hey now mate...You already requested a title, can\' be requesting two now can you. How would that be fair eh?'))
 457              await m.delete(delay=30)
 458              return
 459  
 460      if ctx.channel == importantChannels['throneroom'] and ThroneRoomActive:
 461          User = Message.author
 462          RoleChosen = False
 463          TitleList = Guild.roles
 464          RequestedTitle = 'TEMP'
 465          CurrentTitle = 'TEMP'
 466  
 467          for role in User.roles:
 468              if role.name == RoleHeigherarchy[1]:
 469                  CurrentTitle = {"Role":role,"Rank":1,"H":1}
 470              elif role.name == RoleHeigherarchy[2]:
 471                  CurrentTitle = {"Role":role,"Rank":2,"H":1}
 472              elif role.name == RoleHeigherarchy2[2]:
 473                  CurrentTitle = {"Role":role,"Rank":2,"H":2}
 474  
 475              elif role.name == RoleHeigherarchy[3]:
 476                  CurrentTitle = {"Role":role,"Rank":3,"H":1}
 477              elif role.name == RoleHeigherarchy2[3]:
 478                  CurrentTitle = {"Role":role,"Rank":3,"H":2}
 479  
 480              elif role.name == RoleHeigherarchy[4] or role.name == RoleHeigherarchy2[4]:
 481                  CurrentTitle = {"Role":role,"Rank":4,"H":1}
 482              elif role.name == RoleHeigherarchy[5] or role.name == RoleHeigherarchy2[5]:
 483                  CurrentTitle = {"Role":role,"Rank":5,"H":1}
 484              elif role.name == RoleHeigherarchy[6]:
 485                  CurrentTitle = {"Role":role,"Rank":6,"H":1}
 486          for Title in TitleList[1:]:
 487              if Title == CurrentTitle["Role"]:
 488                  if CurrentTitle["Rank"] < 4:
 489                      if CurrentTitle["H"] == 1:
 490                          RequestedTitle = RoleHeigherarchy[CurrentTitle["Rank"] + 1]
 491                          RoleChosen = True
 492                      else:
 493                          RequestedTitle = RoleHeigherarchy2[CurrentTitle["Rank"] + 1]
 494                          RoleChosen = True
 495  
 496                  elif CurrentTitle["Rank"] == 4:
 497                      ToDelete.append(await ctx.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="That title is granted by the King (*cough cough* favoratism *cough cough*")))
 498                      RoleChosen = False
 499  
 500                  elif CurrentTitle["Rank"] == 5:
 501                      ToDelete.append(await ctx.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="When the King ~~dies~~ leaves you are given his title. So dont get too ambitious or he might take special notice of that...")))
 502                      RoleChosen = False
 503  
 504                  elif CurrentTitle["Rank"] == 6:
 505                      ToDelete.append(await ctx.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="You're already top of the ship mate. You cant request any higher. I mean you could by adding higher roles but then I'd start calling you an Egyptian or something")))
 506          
 507              if RoleChosen:
 508                  if Title.name == RequestedTitle:
 509                      NewMessage = await ctx.send(embed = discord.Embed(color=discord.Color.dark_gold(),description=User.mention + " Requests the title of: " + str(Title.name)))
 510                      await UpdateThroneRoomFile({"messageID":str(NewMessage.id),"role":str(Title.id),'discordID':str(Message.author.id)})
 511      else:
 512          ToDelete.append(await ctx.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="Incorrect channel. Message has been deleted. Please only use this command in the"+importantChannels['throneroom'].mention)))
 513  
 514      for i in ToDelete:
 515          await i.delete(delay=10)
 516  
 517  #Run a minecraft command from discord
 518  @bot.command(help = "Regent level command")
 519  @commands.has_any_role(*RegentCheck)
 520  async def mccommand(ctx):
 521      await ctx.message.delete()
 522      ToDelete = []
 523      ToDelete.append(await ctx.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="Enter the command to run on the server").set_footer(text="THIS WILL BE RAN WITH OP PRIVLAGES - DO NOT USE THE `/` I ADD IT")))
 524      try:
 525          response = await bot.wait_for("message",check=lambda i: i.author == ctx.message.author,timeout=90)
 526          ToDelete.append(response)
 527      except Exception as E:
 528          await importantChannels['adminbots'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description=("ERROR RUNNING A MC-COMMAND. ERROR: "+str(E))))
 529      else:
 530          if response.content.startswith('/'):
 531              ToDelete.append(await ctx.send(embed = discord.Embed(color=discord.Color.dark_gold(),description='HEY! I said no inputting the `/` I will take care of it...I gotchu this time...Try not to in the future, I know it\'s weird though')))
 532              response.content = response.content[1:]
 533  
 534          server = await serverCheck(ctx)
 535          if server != 'FAIL':
 536              
 537              textData = opCommand(response.content, ctx.message.author, server)
 538              embed = discord.Embed(color=discord.Color.dark_gold())
 539              embed.add_field(name='Data returned',value=('\u200b'+textData))
 540              ToDelete.append(await importantChannels['adminbots'].send(embed=embed))
 541              await importantChannels['adminbots'].send(embed=discord.Embed(color=discord.Color.dark_gold(),description=(str(ctx.message.author)+' ran the command: '+str(response.content)+' @ '+str(time.asctime()))))
 542  
 543      for i in ToDelete:
 544          await i.delete(delay=20)    
 545  
 546  #The throne room loop
 547  @bot.command(help = "Regent level command")
 548  @commands.has_any_role(*RegentCheck)
 549  async def loop(ctx, arg):
 550      global ThroneRoomActive
 551      await ctx.message.delete()
 552      ToDelete = []
 553      if arg == "start":
 554          if ThroneRoomLoop.is_running():
 555              if  ThroneRoomActive:
 556                  ToDelete.append(await importantChannels['adminbots'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description=("The "+importantChannels['throneroom'].mention+" loop is already running. "+importantChannels['throneroom'].mention+" is currently open and will close on: " + str(ThroneRoomLoop.next_iteration)))))
 557              else:
 558                  ToDelete.append(await importantChannels['adminbots'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description=("The "+importantChannels['throneroom'].mention+" loop is already running. "+importantChannels['throneroom'].mention+" is currently closed and will open on: " + str(ThroneRoomLoop.next_iteration)))))
 559          else:
 560              ToDelete.append(await importantChannels['adminbots'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description=("The "+importantChannels['throneroom'].mention+" loop has been started"))))
 561              await ThroneRoomLoop.start(False)
 562  
 563      elif arg == "stop":
 564          if not ThroneRoomLoop.is_running():
 565              ToDelete.append(await importantChannels['adminbots'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description=("The "+importantChannels['throneroom'].mention+" loop is not running."))))
 566          else:
 567              ToDelete.append(await importantChannels['adminbots'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description=("The "+importantChannels['throneroom'].mention+" loop has been stopped."))))
 568              ToDelete.append(await importantChannels['announcements'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description=(importantChannels['throneroom'].mention + " has closed. Voting will be held and results will be announced soon."))))
 569              ThroneRoomLoop.cancel()
 570              await importantChannels['throneroom'].set_permissions(CITIZENRY, view_channel = False)
 571              for member in  Guild.members:
 572                  Cleared = False #Citizenry check
 573                  Cleared2 = True #Check so that they do NOT have Good Lad/Lady
 574                  for role in member.roles:
 575                      if role.name == RoleHeigherarchy[0]:
 576                          Cleared = True
 577                      if role.name == RoleHeigherarchy[1] or role.name == RoleHeigherarchy2[1]:
 578                          Cleared2 = False
 579                                      
 580                  if Cleared and Cleared2:
 581                      for i in Guild.roles:
 582                          print(i.name,RoleHeigherarchy[0],RoleHeigherarchy2[0])
 583                          if i.name == RoleHeigherarchy[0]:
 584                              lad = i
 585                          elif i.name == RoleHeigherarchy2[0]:
 586                              lady = i
 587                              break
 588                      Message = await importantChannels['throneroom'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description=("Grant " + member.mention + " the "+lad.mention+"/"+lady.mention+" role?")))
 589                      await UpdateThroneRoomFile({"messageID":str(Message.id),"role":str(CITIZENRY.id),'discordID':str(Message.author.id)})
 590  
 591              jsonData = getJSONFile()
 592              
 593              for i in jsonData['throne-room']['messages']:
 594                  message = await importantChannels['throneroom'].fetch_message(i['messageID'])
 595                  await message.add_reaction("👍")
 596                  await message.add_reaction("👎")
 597  
 598      elif arg == "status":
 599          if not ThroneRoomLoop.is_running():
 600              ToDelete.append(await importantChannels['adminbots'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description=("The "+importantChannels['throneroom'].mention+" loop is not running at the moment"))))
 601          else:
 602              ToDelete.append(await importantChannels['adminbots'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description=(importantChannels['throneroom'].mention+" is currently running status will change in: " + str(ThroneRoomLoop.next_iteration)))))
 603  
 604      elif arg == "help":
 605          Help = discord.Embed(color=discord.Color.dark_gold())
 606          Help.add_field(name = "BOT PREFIX", value = "Fish")
 607          Help.add_field(name = "Loop Commands", value = "`start` | `stop` | `status`")
 608          Help.add_field(name = "start", value = "Starts the throne room loop EX: `Fish loop start`")
 609          Help.add_field(name = "stop", value = "Stops the throne room loop EX: `Fish loop stop`")
 610          Help.add_field(name = "status", value = "Check the status of the Throne Room. EX: `Fish loop status`")
 611          ToDelete.append(await ctx.send(embed = Help))
 612  
 613      for i in ToDelete:
 614          await i.delete(delay=20) 
 615  
 616  #Display the ServerFile
 617  @bot.command(help = "Regent level command")
 618  @commands.has_any_role(*RegentCheck)
 619  async def serverfile(ctx):
 620      await ctx.message.delete()
 621  
 622      server = await serverCheck()
 623      if server == 'FAIL':
 624          return
 625      jsonData = getJSONFile()
 626  
 627      with open(jsonData['serverfiles'][server]['properties']) as F:
 628          ServerFile = F.readlines()
 629      Book=[]
 630      Sheet = []
 631      title=""
 632      data=""
 633      await importantChannels['adminbots'].trigger_typing()
 634      for Place, line in enumerate(ServerFile):
 635          for i, letter in enumerate(line):
 636              if letter == "=":
 637                  title = line[:i]
 638                  if line[i+1:] == "\n":
 639                      data = "NO DATA"
 640                      break
 641                  else:
 642                      data = line[i+1:len(line)-1]
 643                      break
 644  
 645          if Place % 9 == 0 and Place != 0:
 646              if Place == 9:
 647                  Sheet.pop(0)
 648                  Sheet.pop(0)
 649              Book.append(Sheet)
 650              Sheet = []
 651          else:
 652              Sheet.append({"title":title,"data":data})
 653      Page = 0
 654      Forward = "⏩"
 655      Back = "⏪"
 656  
 657      EmbedData = discord.Embed(color=discord.Color.dark_gold())
 658      for i in Book[Page]:
 659          EmbedData.add_field(name = i["title"],value = '\u200b'+i["data"])
 660  
 661      file = discord.File(fp=jsonData['serverfiles'][server]['properties'], filename="server.propterties")
 662      await importantChannels['adminbots'].send(file=file)
 663  
 664      Message = await importantChannels['adminbots'].send(embed=EmbedData)
 665  
 666      while True:
 667          EmbedData = discord.Embed(color=discord.Color.dark_gold())
 668          for i in Book[Page]:
 669              EmbedData.add_field(name = i["title"],value = '\u200b'+i["data"])
 670          EmbedData.set_footer(text = "The whitelist option MUST be done through commands in-game. Spigot has an issue where it will dump the contents of the whitelist file when it's edited manually. No idea why it does so. Further details can be located at: https://minecraft.gamepedia.com/Server.properties")
 671  
 672          await Message.edit(embed=EmbedData)
 673  
 674          left = Page != 0
 675          right = Page != len(Book) - 1
 676  
 677          if left:
 678              await Message.add_reaction(Back)
 679          if right:
 680              await Message.add_reaction(Forward)
 681          try:
 682              Reaction = await bot.wait_for("reaction_add",check = ReactionCheck(Message,left,right),timeout=200)
 683          except asyncio.TimeoutError:
 684              await Message.delete()
 685              return
 686          else:
 687              if str(Reaction[0]) == Back:
 688                  Page -= 1
 689                  await Message.remove_reaction(emoji=Back,member=ctx.message.author)
 690                  if Page == 0:
 691                      await Message.remove_reaction(emoji=Back,member=bot.user)
 692              elif str(Reaction[0]) == Forward:
 693                  Page += 1
 694                  await Message.remove_reaction(emoji=Forward,member=ctx.message.author)
 695                  if Page == len(Book) - 1:
 696                      await Message.remove_reaction(emoji=Forward,member=bot.user)
 697  
 698  #Show default commands available to everyone below a Count
 699  @bot.command(help = "Shows available commands")
 700  async def showcommands(ctx):
 701      Help = discord.Embed(color=discord.Color.dark_gold())
 702      Help.add_field(name = "COMMANDS", value = "`title` | `link` | `userinfo`",inline=False)
 703      Help.add_field(name = "title", value = "Only available when the Throne Room is available and if you have the Good Lad/Lady Title. EX: `Fish title`",inline=False)
 704      Help.add_field(name = "link", value = "Link your discord account to your minecraft account. EX: `Fish link` then follow the prompts",inline=False)
 705      Help.add_field(name = "unlink", value = "UnLink the minecraft account linked to your discord account. EX: `Fish unlink` then follow prompts",inline=False)
 706      Help.add_field(name = "userinfo", value = "Show skin and name history of a player and what discord account they're linked to. EX: `Fish userinfo` then follow the prompts",inline=False)
 707      #Help.add_field(name = "prank", value = "Allows those who have linked their discord and minecraft accounts to prank each other. EX: `Fish prank` then follow the prompts",inline=False)
 708      Help.set_footer(text="BOT PREFIX: `Fish`")
 709      i = await ctx.send(embed = Help)
 710      await i.delete(delay=60)
 711  
 712  #Clear a bunch of messages from a channel
 713  @bot.command(help = "Count/Countess level command")
 714  @commands.has_any_role(*CountCheck)
 715  async def clear(ctx,arg):
 716      if arg == "help":
 717          await ctx.message.delete()
 718          await ctx.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="Clear an amount of messages from a channel. `EX: Fish clear 6`"))
 719      else:
 720          await ctx.channel.purge(limit=int(arg) + 1)
 721  
 722  #Link minecraft and discord accounts
 723  @bot.command(help="Link discord to minecraft account")
 724  async def link(ctx):
 725      ToDelete=[]
 726      await ctx.message.delete()
 727      jsonData = getJSONFile()
 728      for i in jsonData['registry']:
 729          if i['discordID'] == str(ctx.message.author.id):
 730              soup = bs4(requests.get("https://mcuuid.net/?q="+str(i['uuid'])).text,features="html.parser")
 731              username = soup.find("input",attrs={"id":"results_username"})["value"]
 732              temp = await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="Mate, you're already linked to a minecraft account... You're linked to an account with the name: "+username+'. You can unlink accounts by running the command `unlink` and following further prompts'))
 733              await temp.delete(delay=30)
 734              return
 735  
 736      #ToDelete.append(await ctx.channel.send("You input your minecraft username and then I can link it to your discord account so then it will be updated frequently and other users can check who minecraft users are if they dont know who it is on discord. It also helps with keeping the player registry up to date, this replaces it actually."))
 737      ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="Input your username here and I'll begin the linking process:")))
 738      try:
 739          response = await bot.wait_for("message",check=lambda i: i.author == ctx.message.author,timeout=60)
 740          ToDelete.append(response)
 741      except asyncio.TimeoutError:
 742          ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description=random.choice(TIMEOUTR))))
 743      else:
 744          details = discord.Embed(color=discord.Color.dark_gold())
 745          soup = bs4(requests.get("https://mcuuid.net/?q="+str(response.content)).text,features="html.parser")
 746          Username = soup.find("input",attrs={"id":"results_username"})["value"]
 747          uuid = soup.find("input",attrs={"id":"results_id"})["value"]
 748          Skin = soup.find("img",attrs={"id":"results_avatar_body"})["src"]
 749          Face = soup.find("img",attrs={"class":"results_avatar mx-auto"})["src"]
 750          details.set_thumbnail(url=Face)
 751          details.set_image(url=Skin)
 752          details.add_field(name="Username",value='\u200b'+Username,inline=False)
 753          details.set_footer(text="Please confirm if this is you [yes/no]")
 754          ToDelete.append(await ctx.channel.send(embed = details))
 755          try:
 756              response = await bot.wait_for("message", check = lambda i: i.author == ctx.message.author,timeout=60)
 757              ToDelete.append(response)
 758          except asyncio.TimeoutError:
 759              ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description=random.choice(TIMEOUTR))))
 760          else:
 761              found = False
 762              if response.content.lower() == "no":
 763                  ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="Right-o then")))
 764              elif response.content.lower() == "yes":
 765                  jsonData = getJSONFile()
 766                  for i in jsonData['registry']:
 767                      if i['uuid'] == uuid:
 768                          found = True
 769                          if i['discordID'] != str(ctx.message.author.id):
 770                              await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="Hey now...That minecraft account {Username: "+Username+"} is already linked to someone...You cant be doing that now. It's linked to: "+Guild.get_member(int(i['discordID'])).mention),header=(Guild.get_member(ctx.message.author.id)+" tried to link to a already existing account"))
 771                              break 
 772                          else:
 773                              ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="You must have a bad memory my guy. You're already linked to that account so you already did that...I guess good job?")))
 774                              break
 775                      elif i['discordID'] == str(ctx.message.author.id):
 776                          found = True
 777                          soup = bs4(requests.get("https://mcuuid.net/?q="+str(i['uuid'])).text,features="html.parser")
 778                          Username = soup.find("input",attrs={"id":"results_username"})["value"]
 779                          ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="Mate, you're already linked to a minecraft account... You're linked to an account with the name: "+Username)))
 780                          break
 781                      if i == jsonData['registry'][-1]:
 782                          found = True
 783                          jsonData['registry'].append({'uuid':uuid,'discordID':str(ctx.message.author.id)})
 784                          writeJSONFile(jsonData)
 785  
 786                          ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="Accounts linked. Good job mate. You've earned a donut")))
 787                          with open('./donut.png', 'rb') as f:
 788                              donut = discord.File(f,"./donut.png")
 789                          await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description=(str(ctx.message.author.mention)+' has linked his discord to the mincraft account: '+str())))
 790                          ToDelete.append(await ctx.channel.send(file=donut))
 791  
 792                          textData = opCommand(('whitelist add '+Username),ctx.message.author,'main')
 793                          temp = opCommand(('whitelist add '+Username),ctx.message.author,'secondary')
 794                          textData += '   ' +temp
 795                          await importantChannels['adminbots'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description='\u200b'+textData))
 796                          break
 797  
 798                  if not found:
 799                      jsonData['registry'].append({'uuid':uuid,'discordID':str(ctx.message.author.id)})
 800                      writeJSONFile(jsonData)
 801                      
 802                      ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="Accounts linked. Good job mate. You've earned a donut")))
 803                      with open('./donut.png', 'rb') as f:
 804                          donut = discord.File(f,"donut.png")
 805                      ToDelete.append(await ctx.channel.send(file=donut))
 806                      await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description=(str(ctx.message.author.mention)+' has linked his discord to the mincraft account: '+str(Username))))
 807  
 808                      textData = opCommand(('whitelist add '+Username),ctx.message.author,'main')
 809                      temp = opCommand(('whitelist add '+Username),ctx.message.author,'secondary')
 810                      textData += '   ' +temp
 811                      await importantChannels['adminbots'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description='\u200b'+textData))
 812                  
 813              else:
 814                  ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="My guy, that aint the responce I was looking for...Try again from the beginning. A simple yes/no will do")))
 815      for i in ToDelete:
 816          await i.delete(delay=30)
 817  
 818  #Unlink minecraft and discord accounts
 819  @bot.command(help="Unlink discord and minecraft account")
 820  async def unlink(ctx):
 821      ToDelete=[]
 822      await ctx.message.delete()
 823      found = False
 824      jsonData = getJSONFile()
 825      for i in jsonData['registry']:
 826          if i['discordID'] == str(ctx.message.author.id):
 827              found = True
 828              details = discord.Embed(color=discord.Color.dark_gold())
 829              soup = bs4(requests.get("https://mcuuid.net/?q="+str(i['uuid'])).text,features="html.parser")
 830              Username = soup.find("input",attrs={"id":"results_username"})["value"]
 831              Skin = soup.find("img",attrs={"id":"results_avatar_body"})["src"]
 832              Face = soup.find("img",attrs={"class":"results_avatar mx-auto"})["src"]
 833              details.set_thumbnail(url=Face)
 834              details.set_image(url=Skin)
 835              details.add_field(name="Username",value='\u200b'+Username,inline=False)
 836              details.set_footer(text="This is the account you're linked to. Confirm unlinkage? [yes/no]")
 837              ToDelete.append(await ctx.channel.send(embed = details))
 838              try:
 839                  response = await bot.wait_for("message",check=lambda i: i.author == ctx.message.author,timeout=60)
 840                  ToDelete.append(response)
 841              except asyncio.TimeoutError:
 842                  ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description=random.choice(TIMEOUTR))))
 843              else:
 844                  if response.content.lower() == "yes":
 845                      ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description="Deleting account linkage I s'pose")))
 846  
 847                      textData = opCommand(('whitelist remove '+Username),ctx.message.author,'main')
 848                      temp = opCommand(('whitelist remove '+Username),ctx.message.author,'secondary')
 849                      textData += '   ' +temp
 850  
 851                      jsonData['registry'].remove(i)
 852                      writeJSONFile(jsonData)
 853                      
 854                      await importantChannels['adminbots'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description='\u200b'+textData))
 855                  elif response.content.lower() == "no":
 856                      ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description="Right-o then"))) 
 857                  else:
 858                      ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="My guy, that aint the responce I was looking for...Try again from the beginning")))
 859              
 860      if not found:
 861          ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description="You aint linked to an account yet mate. You gotta link before you can unlink...No donut for you")))
 862  
 863      for i in ToDelete:
 864          await i.delete(delay=15)
 865  
 866  #Display low level info about a user
 867  @bot.command(help="Queury the registry database for information about a specific player")
 868  async def userinfo(ctx):
 869      ToDelete = []
 870      await ctx.message.delete()
 871      options = discord.Embed(color=discord.Color.dark_gold(),description="Enter a minecraft username to get some information about who that Minecraft account is linked to here on Discord. Just enter the username")
 872      ToDelete.append(await ctx.channel.send(embed=options))
 873      try:
 874          response = await bot.wait_for("message",check = lambda i: i.author == ctx.message.author,timeout=60)
 875          ToDelete.append(response)
 876      except asyncio.TimeoutError:
 877          ToDelete.append(await ctx.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description=random.choice(TIMEOUTR))))
 878      else:
 879          try:
 880              soup = bs4(requests.get("https://mcuuid.net/?q="+str(response.content)).content,features="html.parser")
 881              details = discord.Embed(color=discord.Color.dark_gold())
 882              Username = soup.find("input",attrs={"id":"results_username"})["value"]
 883              uuid = soup.find("input",attrs={"id":"results_id"})["value"]
 884              Skin = soup.find("img",attrs={"id":"results_avatar_body"})["src"]
 885              Face = soup.find("img",attrs={"class":"results_avatar mx-auto"})["src"]
 886              details.set_thumbnail(url=Face)
 887              details.set_image(url=Skin)
 888              details.add_field(name="Minecraft Username",value='\u200b'+Username,inline=False)
 889              #details.add_field(name="Username",value=Username,inline=False)
 890              jsonData = getJSONFile()
 891              for i in jsonData['registry']:
 892                  if i['uuid'] == str(uuid):
 893                      DiscordUser = Guild.get_member(int(i['discordID']))
 894                      details.add_field(name="Discord Account:",value='\u200b'+DiscordUser.mention,inline=False)
 895                      break
 896  
 897              ToDelete.append(await ctx.channel.send(embed = details))
 898              for i in ToDelete:
 899                  await i.delete(delay=10)
 900  
 901          except Exception as E:
 902              i = await ctx.channel.send(embed=discord.Embed(colord=discord.Color.dark_gold(),description="There was an error finding that user, they most likely have not linked their accounts yet."))
 903              await i.delete(delay=10)
 904  
 905  #Display the registry of the server       
 906  @bot.command(help="Duke/Duchess level command")
 907  @commands.has_any_role(*DukeCheck)
 908  async def registry(ctx):
 909      await ctx.message.delete()
 910      jsonData = getJSONFile()
 911  
 912      details = discord.Embed(color=discord.Color.dark_gold(),title="Registry of the server")
 913      page = []
 914      book = []
 915  
 916      for i in jsonData['registry']:
 917          soup = bs4(requests.get("https://mcuuid.net/?q="+str(i['uuid'])).content,features="html.parser")
 918          mcName = soup.find("input",attrs={"id":"results_username"})["value"]
 919          disName = Guild.get_member(int(i['discordID'])).mention
 920          if len(page) % 9 == 0 and len(page) != 0:
 921              book.append(page)
 922              page = []
 923          else:
 924              page.append({"header":mcName,"value":disName})
 925  
 926      if len(book) == 0:
 927          book.append(page)
 928  
 929      Page = 0
 930      Forward = "⏩"
 931      Back = "⏪" 
 932  
 933      for i in book[Page]:
 934          details.add_field(name = i["header"],value = '\u200b'+i["value"])
 935      details.set_footer(text = "Run `Fish userinfo` to get extended details about a user. A Admin version of that command will be made eventually but I honestly am tired of tweaking this and it not working so who knows anymore")
 936  
 937      Message = await ctx.channel.send(embed=details)
 938      while True:
 939          EmbedData = discord.Embed(color=discord.Color.dark_gold())
 940          for i in book[Page]:
 941              EmbedData.add_field(name = i["header"],value = '\u200b'+i["value"])
 942          EmbedData.set_footer(text = "Run `Fish userinfo [username]` to get extended details about a user. A Admin version of that command will be made eventually but I honestly am tired of tweaking this and it not working so who knows anymore")
 943  
 944          await Message.edit(embed=EmbedData)
 945  
 946          left = Page != 0
 947          right = Page != len(book) - 1
 948  
 949          if left:
 950              await Message.add_reaction(Back)
 951          if right:
 952              await Message.add_reaction(Forward)
 953          try:
 954              Reaction = await bot.wait_for("reaction_add",check = ReactionCheck(Message,left,right),timeout=200)
 955          except asyncio.TimeoutError:
 956              await Message.delete()
 957              return
 958          else:
 959              if str(Reaction[0]) == Back:
 960                  Page -= 1
 961                  await Message.remove_reaction(emoji=Back,member=ctx.message.author)
 962                  if Page == 0:
 963                      await Message.remove_reaction(emoji=Back,member=bot.user)
 964              elif str(Reaction[0]) == Forward:
 965                  Page += 1
 966                  await Message.remove_reaction(emoji=Forward,member=ctx.message.author)
 967                  if Page == len(book) - 1:
 968                      await Message.remove_reaction(emoji=Forward,member=bot.user)
 969  
 970  #Admin help
 971  @bot.command(help = "Duke/Duchess level command")
 972  @commands.has_any_role(*CountCheck)
 973  async def adminhelp(ctx):
 974      Help = discord.Embed(color=discord.Color.dark_gold())
 975      Help.add_field(name = "BOT PREFIX", value = "Fish")
 976      Help.add_field(name = "FURTHER HELP", value = "Run the command with `help` after to get help. EX: `Fish clear help` - NOT FULLY IMPLIMENTED YET")
 977      Help.add_field(name = "loop", value = "Has 3 sub-commands: Restart, Start and Stop. They will each do that to the Throne Room loop. EX: Fish loop start/stop/restart")
 978      Help.add_field(name = "clear", value = "Will clear an amount of messages from a given channel if you have the correct rank. EX: `Fish clear 23`")
 979      Help.add_field(name = "serverfile", value = "List the properties of the *server.properties* file the Minecraft server is using. EX: `Fish serverfile`")
 980      Help.add_field(name = "mccommand", value = "Run a minecraft command from here in discord. Will be run with OP. EX: `Fish mccommand` then follow the prompts")
 981      Help.add_field(name = 'prunecheck',value = 'Check what users would have roles revoked if I were to prune them')
 982      Help.add_field(name = 'errors',value='Posts the Error logs from the bot')
 983      await ctx.channel.send(embed = Help)
 984  
 985  @bot.command(help='Regent level command')
 986  @commands.has_any_role(*RegentCheck)
 987  async def changechannel(ctx):
 988      global importantChannels
 989      ToDelete = []
 990      await ctx.message.delete()
 991      embed = discord.Embed(color=discord.Color.dark_gold(),title='Which channel function are we working on today eh mate?')
 992      embed.add_field(name='1',value='Admin bots')
 993      embed.add_field(name='2',value='Throne room')
 994      embed.add_field(name='3',value='Announcements')
 995      embed.add_field(name='4',value='Server stats')
 996      embed.add_field(name='5',value='Server rules')
 997      embed.description='Just type out the number. I\'ll getcha more instructions ;)'
 998      embedMessage = await ctx.channel.send(embed=embed)
 999      ToDelete.append(embedMessage)
1000      try:
1001          update = await bot.wait_for('message',check=lambda i: i.author==ctx.message.author,timeout=60)
1002      except asyncio.TimeoutError:
1003          ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description=random.choice(TIMEOUTR))))
1004      else:
1005          await update.delete()
1006          if int(update.content) == 1:
1007              embed = discord.Embed(color=discord.Color.dark_gold(),description=('Mention the channel to replace '+importantChannels['adminbots'].mention+' with'))
1008          elif int(update.content) == 2:
1009              embed = discord.Embed(color=discord.Color.dark_gold(),description=('Mention the channel to replace '+importantChannels['throneroom'].mention+' with'))
1010          elif int(update.content) == 3:
1011              embed = discord.Embed(color=discord.Color.dark_gold(),description=('Mention the channel to replace '+importantChannels['announcements'].mention+' with'))
1012          elif int(update.content) == 4:
1013              embed = discord.Embed(color=discord.Color.dark_gold(),description=('Mention the channel to replace '+importantChannels['serverstats'].mention+' with'))
1014          elif int(update.content) == 5:
1015              embed = discord.Embed(color=discord.Color.dark_gold(),description=('Mention the channel to replace '+importantChannels['serverrules'].mention+' with'))
1016  
1017          await embedMessage.edit(embed=embed)
1018          try:
1019              newChannel = await bot.wait_for('message',check=lambda i: i.author==ctx.message.author,timeout=60)
1020              ToDelete.append(newChannel)
1021          except asyncio.TimeoutError:
1022              ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description=random.choice(TIMEOUTR))))
1023              return
1024          else:
1025              jsonData = getJSONFile()
1026              if update.content == '1':
1027                  importantChannels['adminbots'] = Guild.get_channel(newChannel.raw_channel_mentions[0])
1028                  jsonData['channels']['admin-bots'] = importantChannels['adminbots'].id
1029                  ToDelete.append(await importantChannels['adminbots'].send(embed=discord.Embed(color=discord.Color.dark_gold(),description='New channel')))
1030              elif update.content == '2':
1031                  importantChannels['throneroom'] = Guild.get_channel(newChannel.raw_channel_mentions[0])
1032                  jsonData['channels']['throne-room'] = importantChannels['throneroom'].id
1033                  ToDelete.append(await importantChannels['throneroom'].send(embed=discord.Embed(color=discord.Color.dark_gold(),description='New channel')))
1034              elif update.content == '3':
1035                  importantChannels['announcements'] = Guild.get_channel(newChannel.raw_channel_mentions[0])
1036                  jsonData['channels']['admin-bots'] = importantChannels['adminbots'].id
1037                  ToDelete.append(await importantChannels['announcements'].send(embed=discord.Embed(color=discord.Color.dark_gold(),description='New channel')))
1038              elif update.content == '4':
1039                  importantChannels['serverstats'] = Guild.get_channel(newChannel.raw_channel_mentions[0])
1040                  jsonData['channels']['stats'] = importantChannels['stats'].id
1041                  ToDelete.append(await importantChannels['serverstats'].send(embed=discord.Embed(color=discord.Color.dark_gold(),description='New channel')))
1042              elif update.content == '5':
1043                  importantChannels['serverrules'] = Guild.get_channel(newChannel.raw_channel_mentions[0])
1044                  jsonData['channels']['rules'] = importantChannels['serverrules'].id
1045                  ToDelete.append(await importantChannels['serverrules'].send(embed=discord.Embed(color=discord.Color.dark_gold(),description='New channel')))
1046              writeJSONFile(jsonData)
1047              ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description='It has been done. Good job, you got past 3 steps in the process, 2 role checks, and 30 lines of code to get this done')))
1048      
1049      for i in ToDelete:
1050          await i.delete(delay=20)
1051  
1052  @bot.command(help='Prank minecraft players')
1053  async def prank(ctx):
1054      def linkCheck(User):
1055          jsonData = getJSONFile()
1056          for i in jsonData['registry']:
1057              if i['discordID'] == User.id:
1058                  return True
1059          return False
1060      
1061      server = await serverCheck(ctx)
1062      jsonData = getJSONFile()
1063      if server == 'main':
1064          p = jsonData['RCON']['main']['mainport']
1065      else:
1066          p = jsonData['RCON']['secondary']['mainport']
1067      ping = mctools.PINGClient(host=jsonData['RCON']['ip'],port=int(p))
1068      stats = ping.get_stats()
1069      pList = ''
1070      try:
1071          for index,i in enumerate(stats['players']['sample']):
1072              if index < len(stats['players']['sample'])-1:
1073                  temp = i[0].replace('\x1b','')
1074                  temp = temp.replace('[0m','')
1075                  
1076                  pList += (temp+', ')
1077              else:
1078                  temp = i[0].replace('\x1b','')
1079                  temp = temp.replace('[0m','')
1080                  pList += (temp)
1081      except Exception as E:
1082          pList='No one online...Sorry'
1083  
1084      ToDelete=[]
1085      if linkCheck(ctx.message.author):
1086          await ctx.message.delete()
1087          commands = ['execute at PLAYER run playsound entity.creeper.primed master PLAYER ~ ~ ~ 1',\
1088                      'execute at PLAYER run playsound entity.enderman.scream master PLAYER ~ ~ ~ 1',\
1089                      'execute at PLAYER run particle minecraft:elder_guardian'] 
1090            
1091          temp = discord.Embed(color=discord.Color.dark_gold(),description='Give me the minecraft username of who you would like to prank')
1092          temp.set_footer(text=('Available players: '+pList))
1093          ToDelete.append(await ctx.channel.send(embed=temp))
1094  
1095          try:
1096              prankee = await bot.wait_for('message',check = lambda i: i.author == ctx.message.author,timeout=60)
1097              ToDelete.append(prankee)
1098          except asyncio.TimeoutError:
1099              ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description=random.choice(TIMEOUTR))))
1100          else:
1101              options = discord.Embed(color=discord.Color.dark_gold(),title=('Please respond with the according number to what you would like to do to '+prankee.content))
1102              options.add_field(name='1',value='Create a hissing creeper sound at the player')
1103              options.add_field(name='2',value='Create a Enderman scream sound at the player')
1104              options.add_field(name='3',value='Create the visual effect of an Elder Guardian cursing the player')
1105              options.set_footer(text='[1/2/3] is what you should put in the chat')
1106              ToDelete.append(await ctx.channel.send(embed = options))
1107              try:
1108                  toRun = await bot.wait_for('message',check = lambda i: i.author == ctx.message.author,timeout=60)
1109                  ToDelete.append(toRun)
1110              except asyncio.TimeoutError:
1111                  ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description=random.choice(TIMEOUTR))))
1112              else:
1113                  c = commands[int(toRun.content)].replace('PLAYER',str(prankee.content))
1114                  textData = opCommand(c,ctx.message.author,server)
1115  
1116                  embed = discord.Embed(color=discord.Color.dark_gold())
1117                  embed.add_field(name='Server response',value=('\u200b'+textData))
1118                  embed.set_footer(text='If no value given, the player was either not online or you misspelled their username')
1119                  ToDelete.append(await ctx.channel.send(embed=embed))
1120      else:
1121          ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description='Mate...You gotta link your accounts before you can prank other players...`Fish link` is the command for that')))
1122  
1123      for i in ToDelete:
1124          await i.delete(delay=15)
1125  
1126  @bot.command(help='Duke/Duchess level command')
1127  @commands.has_any_role(*DukeCheck)
1128  async def event(ctx):
1129      ToDelete=[]
1130      await ctx.message.delete()
1131      server = await serverCheck(ctx)
1132      ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description='Please give me the message to list as the upcoming event for the server')))
1133      try:
1134          event = await bot.wait_for("message",check=lambda i: i.author == ctx.message.author,timeout=60)
1135          ToDelete.append(event)
1136      except asyncio.TimeoutError:
1137          ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description=random.choice(TIMEOUTR))))
1138      else:
1139          jsonData = getJSONFile()
1140          if server == 'main':
1141              jsonData['stats']['main']['event'] = event.content
1142          elif server == 'server':
1143              jsonData['stats']['secondary']['event'] = event.content
1144          writeJSONFile(jsonData)
1145          
1146          ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description='It is done...Farewhell. The event will show up soonish, the message updates every few minutes')))
1147  
1148      for i in ToDelete:
1149          await i.delete(delay=15)
1150  
1151  @bot.command(help='Regent level command')
1152  @commands.has_any_role(*RegentCheck)
1153  async def prunecheck(ctx):
1154      await ctx.message.delete()
1155      ToDelete = []
1156      temp=discord.Embed(color=discord.Color.dark_gold(),description='How long should I check back in the databases?')
1157      temp.set_footer(text='You need to put a integer or I\'ll be sad')
1158      temp=await ctx.channel.send(embed=temp)
1159      ToDelete.append(temp)
1160      response = (await bot.wait_for('message',check=lambda i: i.author == ctx.message.author,timeout=60))
1161      ToDelete.append(response)
1162      days=int(response.content)
1163      prunedInt = str(await Guild.estimate_pruned_members(days=30,roles=Guild.roles))
1164      ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description='Amount of innactive members in the last '+str(days)+' days: '+prunedInt)))
1165      ToDelete.append(await ctx.channel.send('https://tenor.com/view/hacker-sombra-overwatch-hacking-gif-7952445'))
1166      memberList = []
1167      for i in Guild.members:
1168          ID = i.id
1169          found = False
1170          for channel in Guild.text_channels:
1171              for message in await channel.history().flatten():
1172                  if message.author.id == ID and int(message.created_at.strftime('%s')) > int(time.time() - days*24*60*60):
1173                      memberList.append(i)
1174                      found = not found
1175                      break
1176              if found:
1177                  break
1178      
1179      purgedMembers = ''
1180      for i in Guild.members:
1181          if i not in memberList:
1182              purgedMembers += str(i.mention)+' '
1183  
1184      embed = discord.Embed(color=discord.Color.dark_gold(),title='Users that would be effected by removing all heigherachical roles',description=purgedMembers)
1185      await ctx.channel.send(embed=embed)
1186  
1187      for i in ToDelete:
1188          await i.delete(delay = 20)
1189      
1190  #Just for voting in the throne room
1191  async def on_raw_reaction_add(payload):
1192      """def RoleGetter(Member,RoleNeeded):
1193          Cleared = False
1194          for role in Member.roles:
1195              if role.name == RoleNeeded:
1196                  Cleared = True
1197              elif role.name == RoleHeigherarchy[6]:
1198                  Cleared = True
1199          return Cleared"""
1200  
1201      User = Guild.get_member(payload.member.id)
1202      if (payload.channel_id == importantChannels['throneroom'].id):
1203          jsonData = getJSONFile()
1204          for i in jsonData['throne-room']['messages']:
1205              message = await importantChannels['throneroom'].fetch_message(i['messageID'])
1206              requestedMale = message.mentions[0]
1207              requestedFemale = message.mentions[0]
1208              if not (requestedMale in User.roles or requestedFemale in User.roles):
1209                  await message.remove_reaction(payload.emoji,payload.member)
1210  
1211  #Respond to "E" 
1212  @bot.listen("on_message")
1213  async def Responder(message):
1214      if message.content == "E":  
1215          Message2 = await message.channel.send(embed = discord.Embed(color=discord.Color.dark_gold(),description="Oh?"))
1216          await message.delete(delay = 5)
1217          await Message2.delete(delay = 5)
1218      if bot.user.mentioned_in(message):
1219          await message.channel.send('https://tenor.com/view/summoned-gif-21949657')
1220      for i in message.author.roles:
1221          if i.name == RoleHeigherarchy[-1]:
1222              temp = await message.channel.send('https://tenor.com/view/roger-that-copy-that-yes-sir-yes-maam-ok-gif-18243692')
1223              await temp.delete(delay=5)
1224              break
1225  
1226  @bot.event
1227  async def on_member_remove(member):
1228      jsonData = getJSONFile()
1229      for i in jsonData['registry']:
1230          if i['discordID'] == member.id:
1231              soup = bs4(requests.get("https://mcuuid.net/?q="+str(i['uuid'])),features="html.parser")
1232              Username = soup.find("input",attrs={"id":"results_username"})["value"]
1233              textData = opCommand('whitelist remove '+Username, member, 'main')  
1234              textData += '    ' + opCommand('whitelist remove '+Username, member, 'secondary')
1235              jsonData.remove(i)
1236              writeJSONFile(jsonData) 
1237              await importantChannels['adminbots'].send(embed = discord.Embed(color=discord.Color.dark_gold(),description='\u200b'+textData))
1238  
1239  @bot.event
1240  async def on_member_join(member):
1241      sysChannel = Guild.system_channel
1242      await sysChannel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description=(str(member.mention) + ' Please read the ' + importantChannels['serverrules'].mention + ' and a member of the Duchy will be with you soon to get you your roles and verify with you you read the ' + importantChannels['serverrules'].mention)))
1243      for role in Guild.roles:
1244          if role.name == RoleHeigherarchy[3]:
1245              r1 = role
1246          elif role.name == RoleHeigherarchy2[3]:
1247              r2 = role
1248      await importantChannels['adminbots'].send(text=(str(member.mention)+' is in need of roles and whatnot that I have been told I cant do ~~* cough cough * Vasco * cough cough *~~. Please see to it '+str(r1.mention)+'/'+str(r2.mention)))
1249  
1250  #Handle errors
1251  """@bot.event
1252  async def on_command_error(ctx, error):
1253      ToDelete = [ctx.message]
1254      if isinstance(error, discord.ext.commands.CommandNotFound):
1255          ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description=random.choice(BADCOMMANDR))))
1256      elif isinstance(error,discord.ext.commands.errors.CommandOnCooldown):
1257          choices = ['My guy, try slowing your yee haws down for a minute','Holdup there cowboy, that\'s on a there cooldown','I dont know bout you, but I think you\'re running that command too often',\
1258              'Just...Just stop that...You\'re too fast there mate']
1259          ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description=random.choice(choices))))
1260      elif isinstance(error,discord.ext.commands.MissingAnyRole):
1261          choices=['Hey there cowboy...You dont have access to that command','Dont go tryin that now, you might catch attention of the big bad mods',\
1262              'I see you dont have your papers...No access for you kiddo','INTRUDER - INTRUDER - INTRUDER - THEY DONT HAVE THE ROLES NEEDED','Come back when you have the correct role for that']
1263          ToDelete.append(await ctx.channel.send(embed=discord.Embed(color=discord.Color.dark_gold(),description=random.choice(choices))))
1264      elif isinstance(error,discord.ext.commands.NoPrivateMessage):
1265          choices = ['I told you to STTTOOOOOPPPPP running commands through DMs!','No you','I lost the game',\
1266              'I\'m normally never going to let you down, but this time I\'m going to have to give you up','Tryin to bypass the system I see','Go away']
1267          await ctx.author.send(embed=discord.Embed(color=discord.Color.dark_gold(),description=random.choice(choices)))
1268          logger.info(str(ctx.author)+' is DMing me this: '+str(ctx.message.content))
1269      else:
1270          await importantChannels['adminbots'].send(embed=discord.Embed(color=discord.Color.dark_gold(),description='Error found. Check the ERRORS.log file'))
1271          logger.error(error)
1272      for i in ToDelete:
1273          await i.delete(delay=30)"""
1274  
1275  bot.run(TOKEN)