import time
import os
import platform
import re
import asyncio
import inspect
import textwrap
from datetime import datetime, timedelta
from collections import Counter
import aiohttp
import discord
from discord.ext import commands
from PIL import Image, ImageDraw, ImageFont

#Stolen from https://github.com/Rapptz/RoboDanny/blob/b513a32dfbd4fdbd910f7f56d88d1d012ab44826/cogs/meta.py
class TimeParser:
    def __init__(self, argument):
        compiled = re.compile(r"(?:(?P<hours>[0-9]{1,5})h)?(?:(?P<minutes>[0-9]{1,5})m)?(?:(?P<seconds>[0-9]{1,5})s)?$")
        self.original = argument
        try:
            self.seconds = int(argument)
        except ValueError as e:
            match = compiled.match(argument)
            if match is None or not match.group(0):
                raise commands.BadArgument('Falsche Zeit angegeben, gültig sind z.B. `4h`, `3m` oder `2s`') from e

            self.seconds = 0
            hours = match.group('hours')
            if hours is not None:
                self.seconds += int(hours) * 3600
            minutes = match.group('minutes')
            if minutes is not None:
                self.seconds += int(minutes) * 60
            seconds = match.group('seconds')
            if seconds is not None:
                self.seconds += int(seconds)

        if self.seconds <= 0:
            raise commands.BadArgument('Zu wenig Zeit angegeben, gültig sind z.B. `4h`, `3m` oder `2s`')

        if self.seconds > 604800: # 7 days
            raise commands.BadArgument('7 Tage sind ne lange Zeit, denkste du nicht auch?')
    
    async def cog_command_error(self, ctx, error):
        print('Error in {0.command.qualified_name}: {1}'.format(ctx, error))

    @staticmethod
    def human_timedelta(dt):
        now = datetime.utcnow()
        delta = now - dt
        hours, remainder = divmod(int(delta.total_seconds()), 3600)
        minutes, seconds = divmod(remainder, 60)
        days, hours = divmod(hours, 24)
        years, days = divmod(days, 365)

        if days:
            if hours:
                return '%s und %s' % (Plural(Tag=days), Plural(Stunde=hours))
            return Plural(day=days)

        if hours:
            if minutes:
                return '%s und %s' % (Plural(Stunde=hours), Plural(Minute=minutes))
            return Plural(hour=hours)

        if minutes:
            if seconds:
                return '%s und %s' % (Plural(Minute=minutes), Plural(Sekunde=seconds))
            return Plural(Minute=minutes)
        return Plural(Sekunde=seconds)

class Plural:
    def __init__(self, **attr):
        iterator = attr.items()
        self.name, self.value = next(iter(iterator))

    def __str__(self):
        v = self.value
        if v > 1:
            return '%s %sn' % (v, self.name)
        return '%s %s' % (v, self.name)

class utility(commands.Cog):
    '''Allgemeine/nützliche Befehle welche nirgendwo sonst reinpassen'''

    def __init__(self, bot):
        self.bot = bot

    async def cog_command_error(self, ctx, error):
        print('Error in {0.command.qualified_name}: {1}'.format(ctx, error))

    @staticmethod
    def _newImage(width, height, color):
        return Image.new("L", (width, height), color)

    @staticmethod
    def _getRoles(roles):
        string = ''
        for role in roles[::-1]:
            if not role.is_default():
                string += f'{role.mention}, '
        if string == '':
            return 'None'
        else:
            return string[:-2]

    @staticmethod
    def _getEmojis(emojis):
        string = ''
        for emoji in emojis:
            string += str(emoji)
        if string == '':
            return 'None'
        else:
            return string[:1000] #The maximum allowed charcter amount for embed fields

    @commands.command(aliases=['uptime', 'up'])
    async def status(self, ctx):
        '''Infos über den Bot'''
        timeUp = time.time() - self.bot.startTime
        hours = timeUp / 3600
        minutes = (timeUp / 60) % 60
        seconds = timeUp % 60

        admin = self.bot.AppInfo.owner
        users = 0
        channel = 0
        if len(self.bot.commands_used.items()):
            commandsChart = sorted(self.bot.commands_used.items(), key=lambda t: t[1], reverse=False)
            topCommand = commandsChart.pop()
            commandsInfo = '{} (Top-Command: {} x {})'.format(sum(self.bot.commands_used.values()), topCommand[1], topCommand[0])
        else:
            commandsInfo = str(sum(self.bot.commands_used.values()))
        for guild in self.bot.guilds:
            users += len(guild.members)
            channel += len(guild.channels)

        embed = discord.Embed(color=ctx.me.top_role.colour)
        embed.set_footer(text='Dieser Bot ist Open-Source auf GitHub: https://github.com/Der-Eddy/discord_bot')
        embed.set_thumbnail(url=ctx.me.avatar_url)
        embed.add_field(name='Admin', value=admin, inline=False)
        embed.add_field(name='Uptime', value='{0:.0f} Stunden, {1:.0f} Minuten und {2:.0f} Sekunden\n'.format(hours, minutes, seconds), inline=False)
        embed.add_field(name='Beobachtete Benutzer', value=users, inline=True)
        embed.add_field(name='Beobachtete Server', value=len(self.bot.guilds), inline=True)
        embed.add_field(name='Beobachtete Channel', value=channel, inline=True)
        embed.add_field(name='Ausgeführte Commands', value=commandsInfo, inline=True)
        embed.add_field(name='Bot Version', value=self.bot.botVersion, inline=True)
        embed.add_field(name='Discord.py Version', value=discord.__version__, inline=True)
        embed.add_field(name='Python Version', value=platform.python_version(), inline=True)
        # embed.add_field(name='Speicher Auslastung', value=f'{round(memory_usage(-1)[0], 3)} MB', inline=True)
        embed.add_field(name='Betriebssystem', value=f'{platform.system()} {platform.release()} {platform.version()}', inline=False)
        await ctx.send('**:information_source:** Informationen über diesen Bot:', embed=embed)

    @commands.command()
    async def ping(self, ctx):
        '''Misst die Response Time'''
        ping = ctx.message
        pong = await ctx.send('**:ping_pong:** Pong!')
        delta = pong.created_at - ping.created_at
        delta = int(delta.total_seconds() * 1000)
        await pong.edit(content=f':ping_pong: Pong! ({delta} ms)\n*Discord WebSocket Latenz: {round(self.bot.latency, 5)} ms*')

    # @commands.command()
    # @commands.cooldown(1, 2, commands.cooldowns.BucketType.guild)
    # async def github(self, ctx):
    #     '''In progress'''
    #     url = 'https://api.github.com/repos/Der-Eddy/discord_bot/stats/commit_activity'
    #     async with aiohttp.get(url) as r:
    #         if r.status == 200:
    #             content = await r.json()
    #             commitCount = 0
    #             for week in content:
    #                 commitCount += week['total']
    #
    #             embed = discord.Embed(title='GitHub Repo Stats', type='rich', color=0xf1c40f) #Golden
    #             embed.set_thumbnail(url='https://assets-cdn.github.com/images/modules/logos_page/GitHub-Mark.png')
    #             embed.add_field(name='Commits', value=commitCount, inline=True)
    #             embed.add_field(name='Link', value='https://github.com/Der-Eddy/discord_bot')
    #             await ctx.send(embed=embed)
    #         else:
    #             await ctx.send(':x: Konnte nicht aufs GitHub API zugreifen\nhttps://github.com/Der-Eddy/discord_bot')

    @commands.command(aliases=['info'])
    async def about(self, ctx):
        '''Info über mich'''
        msg = 'Shinobu Oshino gehört wohl zu den mysteriösesten Charakteren in Bakemonogatari. Sie war bis vorletzten Frühling ein hochangesehener, adeliger, skrupelloser Vampir, der weit über 500 Jahre alt ist. Gnadenlos griff sie Menschen an und massakrierte sie nach Belieben. Auch Koyomi Araragi wurde von ihr attackiert und schwer verwundet. Nur durch das Eingreifen des Exorzisten Meme Oshino konnte Kiss-shot Acerola-orion Heart-under-blade, wie sie damals bekannt war, bezwungen werden. Dabei verlor sie jedoch all ihre Erinnerungen und wurde von einer attraktiven, erwachsenen Frau in einen unschuldigen Mädchenkörper verwandelt.\n\n'
        msg += 'Seitdem lebt sie zusammen mit Meme in einem verlassenen Gebäude und wurde von ihm aufgenommen. Er gab ihr auch ihren Namen Shinobu. Das Vampirblut in ihr verlangt immer noch nach Opfern und da sich Koyomi in gewisser Art und Weise schuldig fühlt, stellt er sich regelmäßig als Nahrungsquelle für Shinobu zur Verfügung.\n\n'
        msg += 'Quelle: http://www.anisearch.de/character/6598,shinobu-oshino/\n\n'

        embed = discord.Embed(color=ctx.me.top_role.colour)
        embed.set_footer(text='Dieser Bot ist außerdem free, Open-Source, in Python und mit Hilfe von discord.py geschrieben! https://github.com/Der-Eddy/discord_bot\n')
        embed.set_thumbnail(url=ctx.me.avatar_url)
        embed.add_field(name='**:information_source: Shinobu Oshino (500 Jahre alt)**', value=msg, inline=False)
        await ctx.send(embed=embed)

    @commands.command(aliases=['archive'])
    @commands.cooldown(1, 60, commands.cooldowns.BucketType.channel)
    async def log(self, ctx, *limit: int):
        '''Archiviert den Log des derzeitigen Channels und läd diesen als Attachment hoch

        Beispiel:
        -----------

        :log 100
        '''
        if not limit:
            limit = 10
        else:
            limit = limit[0]
        logFile = f'{ctx.channel}.log'
        counter = 0
        with open(logFile, 'w', encoding='UTF-8') as f:
            f.write(f'Archivierte Nachrichten vom Channel: {ctx.channel} am {ctx.message.created_at.strftime("%d.%m.%Y %H:%M:%S")}\n')
            async for message in ctx.channel.history(limit=limit, before=ctx.message):
                try:
                    attachment = '[Angehängte Datei: {}]'.format(message.attachments[0].url)
                except IndexError:
                    attachment = ''
                f.write('{} {!s:20s}: {} {}\r\n'.format(message.created_at.strftime('%d.%m.%Y %H:%M:%S'), message.author, message.clean_content, attachment))
                counter += 1
        msg = f':ok: {counter} Nachrichten wurden archiviert!'
        f = discord.File(logFile)
        await ctx.send(file=f, content=msg)
        os.remove(logFile)

    @log.error
    async def log_error(self, error, ctx):
        if isinstance(error, commands.errors.CommandOnCooldown):
            seconds = str(error)[34:]
            await ctx.send(f':alarm_clock: Cooldown! Versuche es in {seconds} erneut')

    @commands.command()
    async def invite(self, ctx):
        '''Erstellt einen Invite Link für den derzeitigen Channel'''
        invite = await ctx.channel.create_invite(unique=False)
        msg = f'Invite Link für **#{ctx.channel.name}** auf Server **{ctx.guild.name}**:\n`{invite}`'
        await ctx.send(msg)

    @commands.command()
    async def whois(self, ctx, member: discord.Member=None):
        '''Gibt Informationen über einen Benutzer aus

        Beispiel:
        -----------

        :whois @Der-Eddy#6508
        '''
        if member == None:
            member = ctx.author

        if member.top_role.is_default():
            topRole = 'everyone' #to prevent @everyone spam
            topRoleColour = '#000000'
        else:
            topRole = member.top_role
            topRoleColour = member.top_role.colour

        if member is not None:
            embed = discord.Embed(color=member.top_role.colour)
            embed.set_footer(text=f'UserID: {member.id}')
            embed.set_thumbnail(url=member.avatar_url)
            if member.name != member.display_name:
                fullName = f'{member} ({member.display_name})'
            else:
                fullName = member
            embed.add_field(name=member.name, value=fullName, inline=False)
            embed.add_field(name='Discord beigetreten am', value='{}\n(Tage seitdem: {})'.format(member.created_at.strftime('%d.%m.%Y'), (datetime.now()-member.created_at).days), inline=True)
            embed.add_field(name='Server beigetreten am', value='{}\n(Tage seitdem: {})'.format(member.joined_at.strftime('%d.%m.%Y'), (datetime.now()-member.joined_at).days), inline=True)
            embed.add_field(name='Avatar Link', value=member.avatar_url, inline=False)
            embed.add_field(name='Rollen', value=self._getRoles(member.roles), inline=True)
            embed.add_field(name='Rollenfarbe', value='{} ({})'.format(topRoleColour, topRole), inline=True)
            embed.add_field(name='Status', value=member.status, inline=True)
            await ctx.send(embed=embed)
        else:
            msg = ':no_entry: Du hast keinen Benutzer angegeben!'
            await ctx.send(msg)

    @commands.command(aliases=['e'])
    async def emoji(self, ctx, emojiname: str):
        '''Gibt eine vergrößerte Version eines angegebenen Emojis zurück

        Beispiel:
        -----------

        :emoji Emilia
        '''
        emoji = discord.utils.find(lambda e: e.name.lower() == emojiname.lower(), self.bot.emojis)
        if emoji:
            tempEmojiFile = 'tempEmoji.png'
            async with aiohttp.ClientSession() as cs:
                async with cs.get(emoji.url) as img:
                    with open(tempEmojiFile, 'wb') as f:
                        f.write(await img.read())
                f = discord.File(tempEmojiFile)
                await ctx.send(file=f)
                os.remove(tempEmojiFile)
        else:
            await ctx.send(':x: Konnte das angegebene Emoji leider nicht finden :(')

    @commands.command(aliases=['emotes'])
    async def emojis(self, ctx):
        '''Gibt alle Emojis aus auf welche der Bot Zugriff hat'''
        msg = ''
        for emoji in self.bot.emojis:
            if len(msg) + len(str(emoji)) > 1000:
                await ctx.send(msg)
                msg = ''
            msg += str(emoji)
        await ctx.send(msg)

    @commands.command(pass_context=True, aliases=['serverinfo', 'guild', 'membercount'])
    async def server(self, ctx):
        '''Gibt Informationen über die derzeitge Discord Guild aus'''
        emojis = self._getEmojis(ctx.guild.emojis)
        #print(emojis)
        roles = self._getRoles(ctx.guild.roles)
        embed = discord.Embed(color=0xf1c40f) #Golden
        embed.set_thumbnail(url=ctx.guild.icon_url)
        embed.set_footer(text='Es können evtl. Emojis fehlen')
        embed.add_field(name='Name', value=ctx.guild.name, inline=True)
        embed.add_field(name='ID', value=ctx.guild.id, inline=True)
        embed.add_field(name='Besitzer', value=ctx.guild.owner, inline=True)
        embed.add_field(name='Region', value=ctx.guild.region, inline=True)
        embed.add_field(name='Mitglieder', value=ctx.guild.member_count, inline=True)
        embed.add_field(name='Erstellt am', value=ctx.guild.created_at.strftime('%d.%m.%Y'), inline=True)
        if ctx.guild.system_channel:
            embed.add_field(name='Standard Channel', value=f'#{ctx.guild.system_channel}', inline=True)
        embed.add_field(name='AFK Voice Timeout', value=f'{int(ctx.guild.afk_timeout / 60)} min', inline=True)
        embed.add_field(name='Guild Shard', value=ctx.guild.shard_id, inline=True)
        embed.add_field(name='Rollen', value=roles, inline=True)
        embed.add_field(name='Custom Emojis', value=emojis, inline=True)
        await ctx.send(embed=embed)

    #Shameful copied from https://github.com/Rapptz/RoboDanny/blob/b513a32dfbd4fdbd910f7f56d88d1d012ab44826/cogs/meta.py
    @commands.command(aliases=['reminder'])
    @commands.cooldown(1, 30, commands.cooldowns.BucketType.user)
    async def timer(self, ctx, time : TimeParser, *, message=''):
        '''Setzt einen Timer und benachrichtigt einen dann

        Beispiel:
        -----------

        :timer 13m Pizza

        :timer 2h Stream startet
        '''
        reminder = None
        completed = None
        message = message.replace('@everyone', '@\u200beveryone').replace('@here', '@\u200bhere')

        if not message:
            reminder = ':timer: Ok {0.mention}, Ich stelle einen Timer auf {1}.'
            completed = ':alarm_clock: Ding Ding Ding {0.mention}! Dein Timer ist abgelaufen.'
        else:
            reminder = ':timer: Ok {0.mention}, Ich stelle einen Timer für `{2}` auf {1}.'
            completed = ':alarm_clock: Ding Ding Ding {0.mention}! Dein Timer für `{1}` ist abgelaufen.'

        human_time = datetime.utcnow() - timedelta(seconds=time.seconds)
        human_time = TimeParser.human_timedelta(human_time)
        await ctx.send(reminder.format(ctx.author, human_time, message))
        await asyncio.sleep(time.seconds)
        await ctx.send(completed.format(ctx.author, message, human_time))

    @timer.error
    async def timer_error(self, ctx, error):
        if isinstance(error, commands.BadArgument):
            await ctx.send(str(error))
        elif isinstance(error, commands.errors.CommandOnCooldown):
            seconds = str(error)[34:]
            await ctx.send(f':alarm_clock: Cooldown! Versuche es in {seconds} erneut')

    #Stolen from https://github.com/Rapptz/RoboDanny/blob/b513a32dfbd4fdbd910f7f56d88d1d012ab44826/cogs/meta.py
    @commands.command()
    async def source(self, ctx, *, command: str = None):
        '''Zeigt den Quellcode für einen Befehl auf GitHub an

        Beispiel:
        -----------

        :source kawaii
        '''
        source_url = 'https://github.com/Der-Eddy/discord_bot'
        if command is None:
            await ctx.send(source_url)
            return

        obj = self.bot.get_command(command.replace('.', ' '))
        if obj is None:
            return await ctx.send(':x: Konnte den Befehl nicht finden')

        # since we found the command we're looking for, presumably anyway, let's
        # try to access the code itself
        src = obj.callback.__code__
        lines, firstlineno = inspect.getsourcelines(src)
        sourcecode = inspect.getsource(src).replace('```', '')
        if not obj.callback.__module__.startswith('discord'):
            # not a built-in command
            location = os.path.relpath(src.co_filename).replace('\\', '/')
        else:
            location = obj.callback.__module__.replace('.', '/') + '.py'
            source_url = 'https://github.com/Rapptz/discord.py'

        if len(sourcecode) > 1900:
            final_url = '{}/blob/master/{}#L{}-L{}'.format(source_url, location, firstlineno, firstlineno + len(lines) - 1)
        else:
            final_url = '<{}/blob/master/{}#L{}-L{}>\n```Python\n{}```'.format(source_url, location, firstlineno, firstlineno + len(lines) - 1, sourcecode)

        await ctx.send(final_url)

    @commands.command(hidden=True)
    async def roleUsers(self, ctx, *roleName: str):
        '''Listet alle Benutzer einer Rolle auf'''
        roleName = ' '.join(roleName)
        role = discord.utils.get(ctx.guild.roles, name=roleName)
        msg = ''
        for member in ctx.guild.members:
            if role in member.roles:
                msg += f'{member.id} | {member}\n'

        if msg == '':
            await ctx.send(':x: Konnte keinen Benutzer mit dieser Rolle finden!')
        else:
            await ctx.send(msg)

    @commands.command()
    async def games(self, ctx, *scope):
        '''Zeigt welche Spiele wie oft auf dem Server gerade gespielt werden'''
        games = Counter()
        for member in ctx.guild.members:
            if member.game != None:
                games[member.game] += 1
        msg = ':chart: Spiele die derzeit auf diesem Server gespielt werden\n'
        msg += '```js\n'
        msg += '{!s:40s}: {!s:>3s}\n'.format('Name', 'Anzahl')
        chart = sorted(games.items(), key=lambda t: t[1], reverse=True)
        for index, (name, amount) in enumerate(chart):
            if len(msg) < 1950:
                msg += '{!s:40s}: {!s:>3s}\n'.format(name, amount)
            else:
                amount = len(chart) - index
                msg += f'+ {amount} andere'
                break
        msg += '```'
        await ctx.send(msg)

    @commands.command()
    async def spoiler(self, ctx, *, text: str):
        '''Erstellt ein GIF Bild welches beim Hover einen Spoiler Text anzeigt'''
        #https://github.com/flapjax/FlapJack-Cogs/blob/master/spoiler/spoiler.py
        content = '**' + ctx.author.display_name + '** hat einen Text gespoilert:'
        try:
            await ctx.message.delete()
        except discord.errors.Forbidden:
            content += '\n*(Bitte lösche deinen eigenen Beitrag)*'

        lineLength = 60
        margin = (5, 5)
        fontFile = "font/Ubuntu-R.ttf"
        fontSize = 18
        fontColor = 150
        bgColor = 20
        font = ImageFont.truetype(fontFile, fontSize)

        textLines = []
        for line in text.splitlines():
            textLines.extend(textwrap.wrap(line, lineLength, replace_whitespace=False))

        title = 'SPOILER! Hover zum lesen'
        width = font.getsize(title)[0] + 50
        height = 0

        for line in textLines:
            size = font.getsize(line)
            width = max(width, size[0])
            height += size[1] + 2

        width += margin[0]*2
        height += margin[1]*2

        textFull = '\n'.join(textLines)

        spoilIMG = [self._newImage(width, height, bgColor) for _ in range(2)]
        spoilText = [title, textFull]

        for img, txt in zip(spoilIMG, spoilText):
            canvas = ImageDraw.Draw(img)
            canvas.multiline_text(margin, txt, font=font, fill=fontColor, spacing=4)

        path = f'tmp\\{ctx.message.id}.gif'

        spoilIMG[0].save(path, format='GIF', save_all=True, append_images=[spoilIMG[1]], duration=[0, 0xFFFF], loop=0)
        f = discord.File(path)
        await ctx.send(file=f, content=content)

        os.remove(path)

    # @commands.command(aliases=['rank', 'role', 'roles'], enabled=False)
    # async def ranks(self, ctx, *rankName: str):
    #     '''Auflistung aller Ränge oder beitritt eines bestimmten Ranges

    #     Beispiel:
    #     -----------

    #     :rank

    #     :rank Python
    #     '''
    #     codingLoungeID = 161637499939192832
    #     wshbrID = 247830763649761282
    #     codingRankList = ['HTML + CSS', 'Javascript', 'C++ / C', '.NET', 'PHP', 'NSFW',
    #                 'Java', 'Gourmet', 'Assembler', 'Python', 'Math', 'AutoIt',
    #                 'Member', 'Clash', 'Books', 'Chess', 'Free Games', 'macOS', 'Linux', 'Windows', 'Rust']
    #     wshbrRankList = ['Chuunin', 'Genin']
    #     if ctx.guild.id == codingLoungeID:
    #         rankList = codingRankList
    #     elif ctx.guild.id == wshbrID:
    #         rankList = wshbrRankList

    #     if len(rankName) == 0 and ctx.guild.id not in [codingLoungeID, wshbrID] or ''.join(rankName) == 'all':
    #         rolesList = '`'
    #         for roleServer in ctx.guild.roles:
    #             if not roleServer.is_default():
    #                 count = 0
    #                 for member in ctx.guild.members:
    #                     if roleServer in member.roles:
    #                         count += 1
    #                 rolesList += f'{roleServer.name:30}{count} Members\n'
    #         embed = discord.Embed(color=0xf1c40f) #Golden
    #         embed.set_thumbnail(url=ctx.guild.icon_url)
    #         embed.add_field(name='Ranks', value=rolesList + '`', inline=True)
    #         await ctx.send(embed=embed)
    #     elif len(rankName) == 0 and ctx.guild.id in [codingLoungeID, wshbrID]:
    #         rolesList = '`'
    #         for role in rankList:
    #             count = 0
    #             roleServer = discord.utils.get(ctx.guild.roles, name=role)
    #             for member in ctx.guild.members:
    #                 if roleServer in member.roles:
    #                     count += 1
    #             rolesList += f'{role:20}{count} Members\n'
    #         embed = discord.Embed(color=0x3498db) #Blue
    #         embed.set_thumbnail(url=ctx.guild.icon_url)
    #         embed.set_footer(text='Use the ":rank RANKNAME" command to join a rank')
    #         embed.add_field(name='Ranks', value=rolesList + '`', inline=True)
    #         await ctx.send(embed=embed)
    #     elif ctx.guild.id not in [codingLoungeID, wshbrID]:
    #         await ctx.send(':x: This command only works on the Coding Lounge Server!')
    #     elif ctx.guild.id in [codingLoungeID, wshbrID]:
    #         synonyms = []
    #         synonyms.append(['html / css', 'HTML + CSS'])
    #         synonyms.append(['html + css', 'HTML + CSS'])
    #         synonyms.append(['html', 'HTML + CSS'])
    #         synonyms.append(['css', 'HTML + CSS'])
    #         synonyms.append(['javascript', 'Javascript'])
    #         synonyms.append(['js', 'Javascript'])
    #         synonyms.append(['c / c++', 'C++ / C'])
    #         synonyms.append(['c++', 'C++ / C'])
    #         synonyms.append(['c', 'C++ / C'])
    #         synonyms.append(['c#', '.NET'])
    #         synonyms.append(['.net', '.NET'])
    #         synonyms.append(['vs', '.NET'])
    #         synonyms.append(['php', 'PHP'])
    #         synonyms.append(['nsfw', 'NSFW'])
    #         synonyms.append(['porn', 'NSFW'])
    #         synonyms.append(['java', 'Java'])
    #         synonyms.append(['gourmet', 'Gourmet'])
    #         synonyms.append(['assembler', 'Assembler'])
    #         synonyms.append(['asm', 'Assembler'])
    #         synonyms.append(['python', 'Python'])
    #         synonyms.append(['math', 'Math'])
    #         synonyms.append(['autoit', 'AutoIt'])
    #         synonyms.append(['clash', 'Clash'])
    #         synonyms.append(['chess', 'Chess'])
    #         synonyms.append(['books', 'Books'])
    #         synonyms.append(['free games', 'Free Games'])
    #         synonyms.append(['free game', 'Free Games'])
    #         synonyms.append(['genin', 'Genin'])
    #         synonyms.append(['chuunin', 'Chuunin'])
    #         synonyms.append(['linux', 'Linux'])
    #         synonyms.append(['macos', 'macOS'])
    #         synonyms.append(['mac', 'macOS'])
    #         synonyms.append(['osx', 'macOS'])
    #         synonyms.append(['windows', 'Windows'])
    #         synonyms.append(['rust', 'Rust'])

    #         synonyms_dict = dict(synonyms)

    #         try:
    #             rankName = synonyms_dict[' '.join(rankName).lower()]
    #         except KeyError:
    #             rankName = ' '.join(rankName)

    #         if not rankName in rankList:
    #             await ctx.send(':x: Couldn\'t find that rank! Use `:ranks` to list all available ranks')
    #             return

    #         rank = discord.utils.get(ctx.guild.roles, name=rankName)
    #         if rank in ctx.message.author.roles:
    #             try:
    #                 await ctx.author.remove_roles(rank)
    #             except:
    #                 pass
    #             await ctx.send(f':negative_squared_cross_mark: Rank **{rank}** removed from **{ctx.author.mention}**')
    #         else:
    #             try:
    #                 await ctx.author.add_roles(rank)
    #             except:
    #                 pass
    #             await ctx.send(f':white_check_mark: Rank **{rank}** added to **{ctx.author.mention}**')

    @commands.command(aliases=['vote', 'addvotes', 'votes'])
    async def addvote(self, ctx, votecount = 'bool'):
        '''Fügt Emotes als Reactions hinzu für Abstimmungen/Umfragen'''
        if votecount.lower() == 'bool':
            emote_list = ['✅', '❌']
        elif votecount in ['2', '3', '4', '5', '6', '7', '8', '9', '10']:
            #emotes = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟']
            #for whatever reason, the above won't work
            emotes = ['1\u20e3', '2\u20e3', '3\u20e3', '4\u20e3', '5\u20e3', '6\u20e3', '7\u20e3', '8\u20e3', '9\u20e3', '\U0001f51f']
            emote_list = []
            for i in range (0, int(votecount)):
                emote_list.append(emotes[i])
        else:
            ctx.say(':x: Bitte gib eine Zahl zwischen 2 und 10 an')

        message = await ctx.channel.history(limit=1, before=ctx.message).flatten()
        try:
            await ctx.message.delete()
        except:
            pass

        for emote in emote_list:
            await message[0].add_reaction(emote)


    # This command needs to be at the end due to it's name
    @commands.command()
    async def commands(self, ctx):
        '''Zeigt an wie oft welcher Command benutzt wurde seit dem letzten Startup'''
        msg = ':chart: Liste der ausgeführten Befehle (seit letztem Startup)\n'
        msg += 'Insgesamt: {}\n'.format(sum(self.bot.commands_used.values()))
        msg += '```js\n'
        msg += '{!s:15s}: {!s:>4s}\n'.format('Name', 'Anzahl')
        chart = sorted(self.bot.commands_used.items(), key=lambda t: t[1], reverse=True)
        for name, amount in chart:
            msg += '{!s:15s}: {!s:>4s}\n'.format(name, amount)
        msg += '```'
        await ctx.send(msg)

def setup(bot):
    bot.add_cog(utility(bot))