# plugins
import discord
import youtube_dl
from discord.ext import commands, tasks
from itertools import cycle
import random
import asyncio
import requests
import json
import os
import itertools
import sys
import traceback
from async_timeout import timeout
from functools import partial
from youtube_dl import YoutubeDL
from discord import FFmpegPCMAudio
from discord.ext.commands.cooldowns import BucketType


# status
#The Words/Sentence You Put in there it will say Playing That Word

status = cycle(['Put As Many As You want'])

Token = "Put In your Token"

#Trolling
#Shitpost
# ShitPost File

#Just Add More link to it if you wanna add more

LinkOSHITPOSTO = ('https://www.youtube.com/watch?v=-w0zMX9868o&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_',
                  'https://www.youtube.com/watch?v=SPO9M9thekA&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=12',
                  'https://www.youtube.com/watch?v=2yDwDKy1YtM&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=13',
                  'https://www.youtube.com/watch?v=rLXGTEZVxz8&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=14',
                  'https://www.youtube.com/watch?v=D70adBEEv-s&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=15',
                  'https://www.youtube.com/watch?v=vOvMzg2XiUA&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=16',
                  'https://www.youtube.com/watch?v=Qkm7Pfxgwc8&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=17',
                  'https://www.youtube.com/watch?v=lp8C0GJ8xXU&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=18',
                  'https://www.youtube.com/watch?v=6_RpKl4DpzU&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=19',
                  'https://www.youtube.com/watch?v=M2Sti6FvpCM&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=20',
                  'https://www.youtube.com/watch?v=K82eddpJ0SI&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=21',
                  'https://www.youtube.com/watch?v=InX9sTsMMPo&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=22',
                  'https://www.youtube.com/watch?v=kaBmFLLYD2A&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=23',
                  'https://www.youtube.com/watch?v=B6zV4fcktc4&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=24',
                  'https://www.youtube.com/watch?v=_Kex149LzQI&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=25',
                  'https://www.youtube.com/watch?v=h9cvQxllZjk&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=28',
                  'https://www.youtube.com/watch?v=etH_NGhkhbU&list=PL7i3LZxVlNlz_ALLo0Jyir0GG7VR6ZDQ_&index=30',
                  'https://youtu.be/BP9uI4rFVHU',
                  'https://www.youtube.com/watch?v=3kAOE73OhwI',
                  'https://www.youtube.com/watch?v=Q6OsskkeCmc',
                  'https://cdn.discordapp.com/attachments/695082176659587144/815298932506230794/video0_36.mp4',
                  'https://cdn.discordapp.com/attachments/695082176659587144/815246273341947944/video0.mp4',
                  'https://cdn.discordapp.com/attachments/695082176659587144/815246256405348403/video0.mov',
                  'https://cdn.discordapp.com/attachments/695082176659587144/815412631476764702/video0_40.mp4')



#You Can Get Your Token by going to the discord developer portal

#Link
'https://discord.com/developers/docs/intro'

client = discord.Client()

client = commands.Bot(command_prefix='!', case_insensitive=True)
client.remove_command("!Help")


#Owner Check

#If You Have Developer Mode on RightClick On your self then copy ID If you don't no worry's
#There is a command called !MyID use that and put that id in the section

def Is_it_Owner(ctx):
    return ctx.author.id == Put Your ID

 
#To see a minehut Server Status
@client.command(name='MineHut')
async def MineHut(ctx, arg):

    r = requests.get('https://api.minehut.com/server/' + arg + '?byName=true')
    json_data = r.json()

    description = json_data["server"]["motd"]
    online = str(json_data["server"]["online"])
    playerCount = str(json_data["server"]["playerCount"])

    embed = discord.Embed(
        title=arg + " Server Info",
        description='Description: ' + description + '\nOnline: ' + online + '\nPlayers: ' + playerCount,
        color=discord.Color.dark_green()
    )
    embed.set_thumbnail(
        url="https://i1.wp.com/www.craftycreations.net/wp-content/uploads/2019/08/Grass-Block-e1566147655539.png?fit=500%2C500&ssl=1")

    await ctx.send(embed=embed)


#Clearing Message
@client.command(name='Clear')
@commands.has_permissions(manage_messages=True)
async def clear(ctx, *, amount: int):
    await ctx.channel.purge(limit=amount)
    await ctx.channel.send(f"Removed {amount} messages")


@clear.error
async def clear_error(ctx, error):
    print(error)
    if isinstance(error, commands.MissingRequiredArgument):
        await ctx.send('''You Forget to mention the number of messages to delete''')


# Ping
@client.command(name='Ping')
async def Ping(context):
    embed = discord.Embed(
        title="BotsPing",
        color=discord.Color.blue()
    )
    embed.add_field(name="Ping: ", value=f'{round(client.latency * 1000)}ms')
    await context.message.channel.send(embed=embed)


#Poll
@client.command(name='poll')
async def poll(ctx, *, message):
    embed = discord.Embed(
        title='Poll',
        description=f'{message}',
        color=discord.Color.blue()
    )
    msg = await ctx.message.channel.send(embed=embed)
    await msg.add_reaction('👍')
    await msg.add_reaction('\N{THUMBS DOWN SIGN}')


# Kick
@client.command(name='Kick', pass_context=True)
@commands.has_permissions(kick_members=True)
async def Kick(context, member: discord.Member):
    embed = discord.Embed(
        title='Kicked',
        timestamp=context.message.created_at,
        color=discord.Color.blue()
    )
    embed.add_field(name='You Have Kicked', value=f'user: {member}')
    await member.kick()
    await context.send(embed=embed)


#Kick Error
@Kick.error
async def Kick_error(ctx, error):
    print(error)
    if isinstance(error, commands.MissingRequiredArgument):
        await ctx.send("You Forgot To Mention the User")


# Ban
@client.command(name='Ban', pass_context=True)
@commands.has_permissions(kick_members=True)
async def Ban(context, member: discord.Member, *, reason=None):
    embed = discord.Embed(
        title='Banned',
        timestamp=context.message.created_at,
        color=discord.Color.blue()
    )
    embed.add_field(name='User', value=member.display_name, inline=False)
    embed.add_field(name='Reason', value=reason, inline=False)
    await context.send(embed=embed)

    #Not Really Needed
    # await member.ban(reason=reason)


#Ban Error
@Ban.error
async def Ban_error(ctx, error):
    print(error)
    if isinstance(error, commands.MissingRequiredArgument):
        await ctx.send('''You Forgot To Mention/Ping the User Or Put A reasoning for the Ban
        exp: !Ban @User "Reason"''')


# Server Info
@client.command()
async def server(ctx):
    name = str(ctx.guild.name)
    description = str(ctx.guild.description)

    owner = str(ctx.guild.owner)
    id = str(ctx.guild.id)
    region = str(ctx.guild.region)
    memberCount = str(ctx.guild.member_count)

    icon = str(ctx.guild.icon_url)

    embed = discord.Embed(
        title=name + " Server Information",
        description=description,
        color=discord.Color.blue()
    )
    embed.set_thumbnail(url=icon)
    embed.add_field(name="Owner", value=owner, inline=True)
    embed.add_field(name="Server ID", value=id, inline=True)
    embed.add_field(name="Region", value=region, inline=True)
    embed.add_field(name="Member Count", value=memberCount, inline=True)

    await ctx.send(embed=embed)


#TicTacToe Game
player1 = ""
player2 = ""
turn = ""
gameOver = True

board = []

winningConditions = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6]
]


# T-T-T
@client.command()
async def tictactoe(ctx, p1: discord.Member, p2: discord.Member):
    global count
    global player1
    global player2
    global turn
    global gameOver

    if gameOver:
        global board

        board = [":white_large_square:", ":white_large_square:", ":white_large_square:",
                 ":white_large_square:", ":white_large_square:", ":white_large_square:",
                 ":white_large_square:", ":white_large_square:", ":white_large_square:"]

        turn = ""
        gameOver = False
        count = 0

        player1 = p1
        player2 = p2

        # print the board
        line = ""
        for x in range(len(board)):
            if x == 2 or x == 5 or x == 8:
                line += " " + board[x]
                await ctx.send(line)
                line = ""
            else:
                line += " " + board[x]

        # determine who goes first
        num = random.randint(1, 2)
        if num == 1:
            turn = player1
            await ctx.send("It is <@" + str(player1.id) + ">'s turn.")
            await ctx.send("To Play Do exp: !place 5 ")
        elif num == 2:
            turn = player2
            await ctx.send("It is <@" + str(player2.id) + ">'s turn.")
            await ctx.send("To Play Do exp: !place 5 ")
    else:
        await ctx.send("A game is already in progress! Finish it before starting a new one.")


@client.command()
async def place(ctx, pos: int):
    global turn
    global player1
    global player2
    global board
    global count
    global gameOver

    if not gameOver:
        mark = ""
        if turn == ctx.author:
            if turn == player1:
                mark = ":regional_indicator_x:"
            elif turn == player2:
                mark = ":o2:"
            if 0 < pos < 10 and board[pos - 1] == ":white_large_square:":
                board[pos - 1] = mark
                count += 1

                # print the board
                line = ""
                for x in range(len(board)):
                    if x == 2 or x == 5 or x == 8:
                        line += " " + board[x]
                        await ctx.send(line)
                        line = ""
                    else:
                        line += " " + board[x]

                checkWinner(winningConditions, mark)
                print(count)
                if gameOver == True:
                    await ctx.send(mark + " wins!")
                    await ctx.add_reaction(":confetti_ball: ")
                elif count >= 9:
                    gameOver = True
                    await ctx.send("It's a tie!")

                # switch turns
                if turn == player1:
                    turn = player2
                elif turn == player2:
                    turn = player1
            else:
                await ctx.send("Be sure to choose an integer between 1 and 9 (inclusive) and an unmarked tile.")
        else:
            await ctx.send("It is not your turn.")
    else:
        await ctx.send("Please start a new game using the !tictactoe command.")


def checkWinner(winningConditions, mark):
    global gameOver
    for condition in winningConditions:
        if board[condition[0]] == mark and board[condition[1]] == mark and board[condition[2]] == mark:
            gameOver = True


@tictactoe.error
async def tictactoe_error(ctx, error):
    print(error)
    if isinstance(error, commands.MissingRequiredArgument):
        await ctx.send("Please mention 2 players for this command.")
    elif isinstance(error, commands.BadArgument):
        await ctx.send("Please make sure to mention/ping players (ie. <@688534433879556134>).")


@place.error
async def place_error(ctx, error):
    if isinstance(error, commands.MissingRequiredArgument):
        await ctx.send("Please enter a position you would like to mark.")
    elif isinstance(error, commands.BadArgument):
        await ctx.send("Please make sure to enter an integer.")


#You Can Do Both Of this thing without this command but you would need to enable developer mode from your account setting

@client.command(name='av')
async def av(ctx, user: discord.Member):
    embed = discord.Embed(
        title=f'This is {user} Avatar!',
        timestamp=ctx.message.created_at,
        color=discord.Color.blue()
    )
    embed.set_image(url=user.avatar_url)
    await ctx.message.channel.send(embed=embed)


@av.error
async def av_error(ctx, error):
    print(error)
    if isinstance(error, commands.MissingRequiredArgument):
        await ctx.send("You Didn't Ping/mention anyone"


@FindID.error
async def ID_error(ctx, error):
    print(error)
    if isinstance(error, commands.MissingRequiredArgument):
        await ctx.send("Please make sure to mention/ping players (ie. <@688534433879556134>).")


@Say.error
async def Say_error(ctx, error):
    print(error)
    if isinstance(error, commands.MissingRequiredArgument):
        await ctx.send("There Is Nothing to Say")
    elif isinstance(error, commands.BadArgument):
        BadArg = ["It Can Only Take One Word", "To Make it 1 Word remove all the Spaces in between the other words"]
        await ctx.send(random.choice(BadArg))


# 8ball
@client.command(name='8ball')
async def _8ball(ctx, *, question):
    responses = ['It is certain',
                 'It is decidedly so.',
                 'Without a doubt',
                 'Yes - definitely.',
                 'You may rely on it',
                 'As I see it, yes',
                 'Most Likely.',
                 'Outlook good.',
                 'Yes.',
                 'Maybe',
                 'Idk',
                 'No.',
                 'Can you not',
                 'Signs point to yes.',
                 'Reply hazy, try again.',
                 'Ask again later.',
                 'Better not tell you now.',
                 'My reply is no.',
                 'My sources say no.',
                 'Outlook not so good.',
                 'Very doubtful.']
    embed = discord.Embed(
        title="8ball",
        timestamp=ctx.message.created_at,
        color=discord.Color.blue()
    )
    embed.add_field(name=f'Question: {question}\nAnswer: {random.choice(responses)}',
                    value="*What's your luck* :crystal_ball:")
    await ctx.send(embed=embed)


@client.event
async def on_ready():
    ChangeStatus.start()
    print('We have logged in as {0.user}'
          .format(client))



# Status
#It Will Change Every 60 secounds

@tasks.loop(seconds=60)
async def ChangeStatus():
    await client.change_presence(status=discord.Status.online, activity=discord.Game(next(status)))


@client.command(name='Shitpost')
async def Shitpost(context):
    await context.message.channel.send(random.choice(LinkOSHITPOSTO))


@client.command(name='CreateSampleServer')
async def CreateSampleServer(ctx):
    WelcomeName = "∈👋∋⋮⌜welcome⌟"
    GoodByeName = "∈🛑∋⋮⌜goodbye⌟"
    GeneralName = "∈🌐∋⋮⌜general-chat⌟"
    ModMailName = "∈📩∋⋮⌜mod-mail⌟"
    MemeName = "∈❇∋⋮⌜meme-spam⌟"
    TestingChannelName = "∈💻∋⋮⌜Testing⌟"
    GamingName = "∈🎮∋⋮⌜games⌟⌟"
    Art = "∈🎨∋⋮⌜art⌟⌟"
    announcements = '∈⚠∋⋮⌜announcements⌟'

    guild = ctx.guild

    #sending msg
    SM = discord.Embed(
        title = '!CreateSampleServer',
        color=discord.Color.blue(),
        timestamp=ctx.message.created_at
    )
    SM.add_field(name='*Sample Server Has Been Created*',
                 value='''**If u use this command while those channels it will make duplicate of them**
                 **ModMail Channel is basically a way to talk to the mods without being in the server
                 just by doign**''')

    if ctx.author.guild_permissions.manage_channels:
        await guild.create_text_channel(name='{}'.format(announcements))
        await guild.create_text_channel(name='{}'.format(ModMailName))
        await guild.create_text_channel(name='{}'.format(WelcomeName))
        await guild.create_text_channel(name='{}'.format(GoodByeName))
        await guild.create_text_channel(name='{}'.format(GeneralName))
        await guild.create_text_channel(name='{}'.format(MemeName))
        await guild.create_text_channel(name='{}'.format(TestingChannelName))
        await guild.create_text_channel(name='{}'.format(GamingName))
        await guild.create_text_channel(name='{}'.format(Art))

        await ctx.send(embed=SM)


# Creating Channel
@client.command(name='createchannel')
async def createchannel(ctx, channelName):
    guild = ctx.guild

    embed = discord.Embed(
        title='You Have Created A Channel',
        color=discord.Color.blue(),
        description="{} has been successfully created.".format(channelName)
    )
    if ctx.author.guild_permissions.manage_channels:
        await guild.create_text_channel(name='{}'.format(channelName))
        await ctx.send(embed=embed)


# deleting
@client.command(name='deletechannel')
async def deletechannel(ctx, channel: discord.TextChannel):
    embed = discord.Embed(
        title='You Have Deleted A Channel',
        color=discord.Color.blue(),
        description=f'Channel: {channel} has been deleted'
    )
    if ctx.author.guild_permissions.manage_channels:
        await ctx.send(embed=embed)
        await channel.delete()


# member Joining
@client.event
async def on_member_join(member, ctx):
    embed = discord.Embed(
        title=f'Welcome {member.mention}!',
        color=discord.Color.blue()
    )
    embed.set_image(url=member.avatar_url)

    channelW = ctx.guild.get_channel("∈👋∋⋮⌜welcome⌟")

    await channelW.send(embed=embed)


# member leaving
@client.event
async def on_member_join(member, ctx):
    embed = discord.Embed(
        title=f'Bye {member.mention}!',
        color=discord.Color.blue()
    )
    embed.set_image(url=member.avatar_url)

    channelB = ctx.guild.get_channel("∈🛑∋⋮⌜goodbye⌟")

    await channelB.send(embed=embed)


@client.event
async def on_message(msg):
    # so it doesn't respond to it self
    if msg.author == client.user:
        return

    # Mod-Mail
    empty_array = []
    modmail_channel = discord.utils.get(client.get_all_channels(), name="∈📩∋⋮⌜mod-mail⌟")

    if msg.author == client.user:
        return
    if str(msg.channel.type) == "private":
        if msg.attachments != empty_array:
            files = msg.attachments
            await modmail_channel.send("[" + msg.author.display_name + "]")

            for file in files:
                await modmail_channel.send(file.url)
        else:
            await modmail_channel.send("[" + msg.author.display_name + "] " + msg.content)

    elif str(msg.channel) == "∈📩∋⋮⌜mod-mail⌟" and msg.content.startswith("<"):
        member_object = msg.mentions[0]
        if msg.attachments != empty_array:
            files = msg.attachments
            await member_object.send("[" + msg.author.display_name + "]")

            for file in files:
                await member_object.send(file.url)
        else:
            index = msg.content.index(" ")
            string = msg.content
            mod_message = string[index:]
            await member_object.send("[" + msg.author.display_name + "]" + mod_message)

    await client.process_commands(msg)


client.run(Token)