Ejemplo n.º 1
0
class CustomCommands(commands.Cog, name='CustomCommands'):
    def __init__(self, bot):
        self.bot = bot
        self.db = bot.mdb['custom_commands']

    async def cog_check(self, ctx):
        return ctx.guild is not None

    async def run_custom_commands(self, ctx):
        if ctx.guild is None:
            return

        cc = await self.db.find_one({'guild_id': ctx.guild_id, 'name': ctx.invoked_with})
        if cc is None:
            return
        cc = CustomCommand.from_dict(cc)
        return await ctx.send(cc.content)

    @commands.group(name='cc', invoke_without_command=True)
    async def cc_base(self, ctx):
        """
        Base command for CustomCommand commands. Will list any custom commands for this server.
        Any of these commands require the "DM" or "Dragonspeaker" role.
        """
        aliases = await self.db.find({'guild_id': ctx.guild.id}).to_list(None)
        source = CommandMenu(data=[CustomCommand.from_dict(a) for a in aliases], ctx=ctx)
        cc_list = menus.MenuPages(source=source, clear_reactions_after=True)
        await cc_list.start(ctx)

    @cc_base.command(name='create')
    @commands.check_any(commands.has_any_role(BOT_MODS), is_owner())
    async def cc_create(self, ctx, name: str, *, content: str):
        """
        Create a new Custom Command.
        """
        try:
            new_cc = await CustomCommand.new(self.bot,
                                             owner_id=ctx.author.id,
                                             guild_id=ctx.guild_id,
                                             name=name,
                                             content=content)
        except InvalidArgument as e:
            return await ctx.send(f'Encountered an error while creating the command:\n{str(e)}')
        return await ctx.send(f'Created new command with name `{new_cc.name}`')

    @cc_base.command(name='delete')
    @commands.check_any(commands.has_any_role(BOT_MODS), is_owner())
    async def cc_delete(self, ctx, name: str):
        """
        Deletes a Custom Counter. The name must be an existing CC.
        """
        cc_dict = await self.db.find_one({'guild_id': ctx.guild_id, 'name': name})
        if cc_dict is None:
            return await ctx.send(f'No CC with name `{name}` found.')
        await self.db.delete_one({'guild_id': ctx.guild_id, 'name': name})
        return await ctx.send(f'Deleted CC with name `{name}` from the server.')
Ejemplo n.º 2
0
 async def help(self, ctx):
     if commands.has_any_role(FONDATEUR):
         await ctx.send(self.generateur_help(ctx, COG_FONDATEUR))
     if commands.has_any_role(ADMIN):
         await ctx.send(self.generateur_help(ctx, COG_ADMIN))
     if commands.has_any_role(PROFESSEUR):
         await ctx.send(self.generateur_help(ctx, COG_PROFESSEUR))
     await ctx.send(self.generateur_help(ctx, COG_GENERALE))
     await ctx.send(self.generateur_help(ctx, COG_FICHE))
     await ctx.send(HELP)
Ejemplo n.º 3
0
    def add_slash_command(self,
                          cmd: typing.Callable,
                          roles: typing.Optional[typing.Sequence] = None,
                          channels: typing.Optional[typing.Sequence] = None,
                          options: typing.Optional[typing.Sequence] = None,
                          **kwargs) -> None:
        async def wrapper(ctx: SlashContext, cmd=cmd, **kwargs):
            return await cmd(ctx, **kwargs)

        def check_channels(channels: typing.Sequence):
            def predicate(ctx: SlashContext):
                print(f"channels: {channels}")
                if channels is None: return True
                for channel in channels:
                    name = self.config['channels'].get(channel, channel)
                    if ctx.channel.name == name:
                        return True
                return False

            return commands.check(predicate)

        cmd = check_channels(channels)(wrapper)

        if roles is not None:
            cmd = commands.has_any_role(*roles)(cmd)

        # have to set a dummy list to prevent
        # discord_slash from probing our cmd's args
        if options is None:
            options = []

        return self.slash.add_slash_command(cmd,
                                            guild_ids=self.guild_ids,
                                            options=options,
                                            **kwargs)
Ejemplo n.º 4
0
class BotControl(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    # @commands.Cog.listener()
    # async def on_ready(self):
    #     pass

    # from TLE bot.
    @commands.command(brief="Check if bot is still alive.")
    async def ping(self, ctx):
        """Replies to a ping."""
        start = time.perf_counter()
        message = await ctx.send('<:pingreee:665243570655199246>')
        end = time.perf_counter()
        duration = (end - start) * 1000
        await message.edit(
            content=
            f'<:pingreee:665243570655199246>\nREST API latency: {int(duration)}ms\n'
            f'Gateway API latency: {int(self.bot.latency * 1000)}ms')

    @commands.command(brief="Kill bot. ")
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role('Admin', 'Mod VNOI'))
    async def kill(self, ctx):
        """Kill bot"""
        await ctx.send("Dying")
        exit(0)

    @commands.command(brief='Restart bot')
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role('Admin', 'Mod VNOI'))
    async def restart(self, ctx):
        await ctx.send('Restarting...')
        os.execv(sys.executable, [sys.executable] + sys.argv)

    @commands.command(brief='Get database')
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role('Admin', 'Mod VNOI'))
    async def db(self, ctx):
        await ctx.send(
            file=discord.File('database/potd.db', filename='potd.db'))
Ejemplo n.º 5
0
class Handle(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command(brief="Set nick codeforces cho người khác",
                      usage="@user codeforces_handle")
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role('Admin', 'Mod VNOI'))
    async def set(self, ctx, member: discord.Member, handle):
        """
        Dùng command này để set nick codeforces cho người khác
        """
        discord_id = member.id
        TaggingDb.TaggingDb.add_handle(discord_id, handle)
        if os.path.exists('database/save/' + str(discord_id) + '.json'):
            os.remove('database/save/' + str(discord_id) + '.json')

        if os.path.exists('database/save/info_' + str(discord_id) + '.json'):
            os.remove('database/save/info_' + str(discord_id) + '.json')

        await ctx.send(SET_HANDLE_SUCCESS.format(discord_id, handle))

    @commands.command(brief="Tự set nick codeforces",
                      usage="codeforces_handle")
    async def identify(self, ctx, handle):
        """
        Dùng command này để set nick codeforces:
        Ví dụ account codeforces của mình là leduykhongngu thì mình dùng:
        ;identify leduykhongngu
        """
        if ctx.guild is None:
            await ctx.send(
                "Lệnh này chỉ được dùng ở server discord của VNOI, không được dùng trong tin nhắn"
            )
            return
        discord_id = ctx.author.id
        TaggingDb.TaggingDb.add_handle(discord_id, handle)
        await ctx.send(SET_HANDLE_SUCCESS.format(discord_id, handle))
Ejemplo n.º 6
0
mjs_only = commands.check_any(
    commands.check(lambda ctx: ctx.message.webhook_id),
    commands.has_role(config.Role.get_raw("mj"))  # nom du rôle
)

#: Décorateur pour commandes d'IA (:func:`discord.ext.commands.check`) :
#: commande exécutable par un :attr:`MJ <.config.Role.mj>`, un
#: :attr:`Rédacteur <.config.Role.redacteur>` ou un webhook (tâche planifiée)
mjs_et_redacteurs = commands.check_any(
    mjs_only, commands.has_role(config.Role.get_raw("redacteur")))

#: Décorateur pour commande (:func:`discord.ext.commands.check`) :
#: commande exécutable uniquement par un joueur,
#: :attr:`vivant <.config.Role.joueur_en_vie>` ou
#: :attr:`mort <.config.Role.joueur_mort>`.
joueurs_only = commands.has_any_role(config.Role.get_raw("joueur_en_vie"),
                                     config.Role.get_raw("joueur_mort"))

#: Décorateur pour commande (:func:`discord.ext.commands.check`) :
#: commande exécutable uniquement par un
#: :attr:`joueur vivant <.config.Role.joueur_en_vie>`
vivants_only = commands.has_role(config.Role.get_raw("joueur_en_vie"))


def private(callback):
    """Décorateur : commande utilisable dans son chan privé uniquement.

    Lors d'une invocation de la commande décorée hors d'un channel privé
    (commençant par :attr:`config.private_chan_prefix`), supprime le
    message d'invocation et exécute la commande dans le channel privé
    de l'invoqueur.
Ejemplo n.º 7
0
class Misc(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.Cog.listener()
    async def on_message(self, message):
        if message.content.lower() == '!role furaime':
            await message.add_reaction('👀')

        if self.bot.user in message.mentions:
            emoji = discord.utils.get(self.bot.emojis, name='SahasrahBot')
            if emoji:
                await asyncio.sleep(random.random()*5)
                await message.add_reaction(emoji)

        if discord.utils.get(message.role_mentions, id=524738280630124574):
            async with message.channel.typing():
                await asyncio.sleep((random.random()*30)+30)
                if random.choice([True, False]):
                    await message.channel.send(f'@{message.author.mention}')

    @commands.command(aliases=['joineddate'])
    @commands.check_any(
        commands.has_any_role(523276397679083520, 307883683526868992),
        commands.has_permissions(administrator=True),
        commands.has_permissions(manage_guild=True),
        checks.has_any_channel_id(608008164356653066)
    )
    async def memberinfo(self, ctx, member: discord.Member = None):
        if member is None:
            member = ctx.author
        embed = discord.Embed(
            title=f"Member info for {member.name}#{member.discriminator}",
            color=member.color
        )
        embed.add_field(name='Created at',
                        value=member.created_at, inline=False)
        embed.add_field(name='Joined at', value=member.joined_at, inline=False)
        embed.add_field(name="Discord ID", value=member.id, inline=False)
        embed.set_thumbnail(url=member.avatar_url)
        await ctx.send(embed=embed)

    @commands.command()
    async def prng(self, ctx):
        await ctx.send("PRNG is RNG!  It is random!  Humans tend to identify patterns where they do not exist.\n\nIf you're a Linux nerd check this out: https://www.2uo.de/myths-about-urandom/")

    @commands.command(hidden=True)
    async def pedestalgoal(self, ctx):
        await ctx.send("> If it takes 2 hours its because GT is required, which really isn't a thing anymore in pedestal goal games\n-Synack")

    @commands.command(
        aliases=['crc32'],
        brief="Posts instructions on how to verify your ROM is correct.",
        help="Posts instructions on how to verify your ROM is correct, or how to get the permalink to your randomized game."
    )
    async def rom(self, ctx):
        await ctx.send(
            "If you need help verifying your legally-dumped Japanese version 1.0 A Link to the Past Game file needed to run ALttPR, use this tool: <http://alttp.mymm1.com/game/checkcrc/>\n"
            "It can also help get the permalink page URL which has access to the Spoiler Log depending on the settings that were chosen. Not all games that are generated have access to the Spoiler Log.\n\n"
            "For legal reasons, we cannot provide help with finding this ROM online.  Please do not ask here for assistance with this.\n"
            "See <#543572578787393556> for details."
        )

    @commands.command(hidden=True)
    async def trpegs(self, ctx):
        await ctx.send(discord.utils.get(ctx.bot.emojis, name='RIPLink'))

    @commands.command(hidden=True, aliases=['8ball'])
    async def eightball(self, ctx):
      msg = random.choice([
        "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.",
        "Signs point to yes.",
        "Reply hazy, try again.",
        "Ask again later.",
        "Better not tell you now.",
        "Cannot predict now.",
        "Concentrate and ask again.",
        "Don't count on it.",
        "My reply is no.",
        "My sources say no.",
        "Outlook not so good.",
        "Very doubtful.",
      ])
      await ctx.send(msg)


    @commands.command(
        brief="Retrieves a holy image.",
        help="Retrieves a holy image from http://alttp.mymm1.com/holyimage/",
        aliases=['holy']
    )
    async def holyimage(self, ctx, slug=None, game='z3r'):
        holyimage = await holy(slug=slug, game=game)

        embed = discord.Embed(
            title=holyimage.image.get('title'),
            description=html2markdown.convert(
                holyimage.image['desc']) if 'desc' in holyimage.image else None,
            color=discord.Colour.from_rgb(0xFF, 0xAF, 0x00)
        )

        if 'url' in holyimage.image:
            url = urljoin('http://alttp.mymm1.com/holyimage/',
                          holyimage.image['url'])
            if holyimage.image.get('mode', '') == 'redirect':
                embed.add_field(name='Link', value=url, inline=False)
            else:
                embed.set_thumbnail(url=url)

        embed.add_field(name="Source", value=holyimage.link)

        if 'credit' in holyimage.image:
            embed.set_footer(text=f"Created by {holyimage.image['credit']}")

        await ctx.send(embed=embed)

    @commands.command(
        brief="Retrieves the next ALTTPR SG daily race.",
        help="Retrieves the next ALTTPR SG daily race.",
    )
    @commands.cooldown(rate=1, per=900, type=commands.BucketType.channel)
    async def sgdaily(self, ctx, get_next=1):
        sg_schedule = await speedgaming.get_upcoming_episodes_by_event('alttprdaily', hours_past=0, hours_future=192)
        if len(sg_schedule) == 0:
            await ctx.send("There are no currently SpeedGaming ALTTPR Daily Races scheduled within the next 8 days.")
            return
        
        if get_next == 1:
            embed = discord.Embed(
                title=sg_schedule[0]['event']['name'],
                description=f"**Mode:** {'*TBD*' if sg_schedule[0]['match1']['title'] == '' else sg_schedule[0]['match1']['title']}\n[Full Schedule](http://speedgaming.org/alttprdaily)"
            )
        else:
            embed = discord.Embed(
                title="ALTTP Randomizer SG Daily Schedule",
                description="[Full Schedule](http://speedgaming.org/alttprdaily)"
            )

        for episode in sg_schedule[0:get_next]:
            when = dateutil.parser.parse(episode['when'])
            when_central = when.astimezone(pytz.timezone(
                'US/Eastern')).strftime('%m-%d %I:%M %p')
            when_europe = when.astimezone(pytz.timezone(
                'Europe/Berlin')).strftime('%m-%d %I:%M %p')
            difference = when - datetime.datetime.now(when.tzinfo)

            if get_next == 1:
                embed.add_field(
                    name='Time', value=f"**US:** {when_central} Eastern\n**EU:** {when_europe} CET/CEST\n\n{round(difference / datetime.timedelta(hours=1), 1)} hours from now", inline=False)
                broadcast_channels = [a['name']
                                    for a in episode['channels'] if not a['name'] == 'No Stream']
                if broadcast_channels:
                    embed.add_field(name="Twitch Channels", value=', '.join(
                        [f"[{a}](https://twitch.tv/{a})" for a in broadcast_channels]), inline=False)
            else:
                embed.add_field(
                    name='TBD' if episode['match1']['title'] == '' else episode['match1']['title'],
                    value=(
                        f"**US:** {when_central} Eastern\n"
                        f"**EU:** {when_europe} CET/CEST\n\n"
                    ),
                    inline=False
                )
        embed.set_footer()

        embed.set_thumbnail(
            url='https://pbs.twimg.com/profile_images/1185422684190105600/3jiXIf5Y_400x400.jpg')
        await ctx.send(embed=embed)
Ejemplo n.º 8
0
Archivo: misc.py Proyecto: satoqz/egg
class Misc(Cog):
    """A cog containing miscellaneous commands."""
    def __init__(self, bot: utils.Bot):
        self.bot = bot

        with open("./assets/json/colors_lower.json", "r",
                  encoding="utf-8") as f:
            self.colors = json.load(f)

    @commands.command()
    async def nether(self, ctx: Context, *, query: str):
        """Gets an image from https://ceapa.cool/nether."""
        async with ctx.typing():
            quoted = parse.quote(query)
            async with self.bot.session.get(
                    f"https://ceapa.cool/nether/?obj={quoted}") as resp:
                image = await resp.read()
                ext = imghdr.what(None, h=image)
                if not ext:
                    embed = discord.Embed(color=EGG_COLOR,
                                          timestamp=ctx.message.created_at)
                    embed.set_author(name="No images found.",
                                     icon_url=ctx.me.avatar_url)
                    return await ctx.send(embed=embed)

                ext = ext.lower().replace("jpeg", "jpg")
                await ctx.send(file=discord.File(
                    BytesIO(image),
                    filename=f"nether_{query.replace(' ', '_')}.{ext}"))

    @commands.command()
    async def melon(self, ctx: Context, *, query: str):
        """Gets an image from https://ceapa.cool/melon."""
        async with ctx.typing():
            quoted = parse.quote(query)
            async with self.bot.session.get(
                    f"https://ceapa.cool/melon/?txt={quoted}") as resp:
                image = await resp.read()
                ext = imghdr.what(None, h=image).lower().replace("jpeg", "jpg")
                await ctx.send(file=discord.File(
                    BytesIO(image),
                    filename=f"melon_{query.replace(' ', '_')}.{ext}"))

    @commands.command()
    async def cumrat(self, ctx: Context, *, text: str):
        """Makes a "Cum rat says:" image."""
        if len(text) > 100:
            embed = discord.Embed(color=EGG_COLOR,
                                  timestamp=ctx.message.created_at)
            embed.set_author(name="Text must be 100 characters or less.",
                             icon_url=ctx.me.avatar_url)
            return await ctx.send(embed=embed)

        async with ctx.typing():
            image = await self.bot.loop.run_in_executor(
                None, self.create_cumrat, text)
            await ctx.send(file=discord.File(image, filename=f"cumrat.png"))

    @staticmethod
    def create_cumrat(text: str):
        """Takes the provided text and applies it onto the cum rat template."""
        text = textwrap.fill(re.sub(r"[^\w\s]+", "", text),
                             25,
                             break_long_words=True)
        font = ImageFont.truetype("./assets/fonts/angeltears.ttf", size=150)

        image = Image.open("./assets/images/cumrat.png")
        draw = ImageDraw.Draw(image)
        buffer = BytesIO()

        draw.multiline_text((50, 175),
                            text,
                            fill="#000F55",
                            font=font,
                            spacing=0)

        image.save(buffer, "png")
        buffer.seek(0)

        return buffer

    @commands.command()
    async def roblox(self, ctx: Context):
        """Shows how many members are playing Roblox."""
        players = []
        desc = []

        for member in ctx.guild.members:
            if member.activity and member.activity.name:
                if member.activity.name.lower().startswith("roblox"):
                    players.append(str(member))

        amount = len(players)

        for _ in range(10):
            try:
                player = players.pop(0)
                desc.append(player)
            except IndexError:
                break

        if players:
            desc.append(f"...and {len(players)} more \N{FLUSHED FACE}")

        embed = discord.Embed(description="\n".join(desc),
                              color=EGG_COLOR,
                              timestamp=ctx.message.created_at)
        embed.set_author(
            name=f"{amount} {utils.plural('member', amount)} "
            f"{'are' if amount != 1 else 'is'} currently playing Roblox.",
            icon_url=ctx.me.avatar_url)
        await ctx.send(embed=embed)

    @commands.command(aliases=["ud", "urbandictionary", "urb"])
    async def urban(self, ctx, term: str, *, index: str = None):
        """Gets a definition from Urban Dicrionary."""
        if index is None:
            index = 0
        else:
            maybe_index = index.split()[-1]
            if maybe_index.isdigit():
                if int(maybe_index) < 1:
                    embed = discord.Embed(color=EGG_COLOR,
                                          timestamp=ctx.message.created_at)
                    embed.set_author(name="Invalid index.",
                                     icon_url=ctx.me.avatar_url)
                    await ctx.send(embed=embed)
                else:
                    term += f" {' '.join(index.split()[:-1])}"
                    index = int(maybe_index) - 1
            else:
                term += f" {index}"
                index = 0

        async with aiohttp.ClientSession() as session:
            url = f"http://api.urbandictionary.com/v0/define?term={html.escape(term)}"
            async with session.get(url.replace(" ", "%20")) as response:
                resp = await response.json()

        try:
            item = resp["list"][index]
        except IndexError:
            embed = discord.Embed(color=EGG_COLOR,
                                  timestamp=ctx.message.created_at)
            embed.set_author(name="No definitions found.",
                             icon_url=ctx.me.avatar_url)
            return await ctx.send(embed=embed)

        def convert_to_url(match):
            term = match.group(0).strip('[]')
            url = f"https://www.urbandictionary.com/define.php?term={term}".replace(
                " ", "%20")
            return f"[{match.group(0).strip('[]')}]({url})"

        definition = re.sub(r"\[[^\]]*\]", convert_to_url, item["definition"])
        example = re.sub(r"\[[^\]]*\]", convert_to_url, item["example"])
        written_on = datetime.strptime(item["written_on"][:10],
                                       "%Y-%m-%d").strftime("%B %d, %Y")

        embed = discord.Embed(title=f"**__{item['word']}__**",
                              description=f"{definition}\n\n_{example}_",
                              color=EGG_COLOR,
                              url=item["permalink"])
        embed.set_author(name="Urban Dictionary",
                         icon_url=ctx.me.avatar_url,
                         url="https://www.urbandictionary.com/")
        embed.set_footer(
            text=f"\N{SPEAKING HEAD IN SILHOUETTE}: {item['author']} | "
            f"\N{THUMBS UP SIGN}/\N{THUMBS DOWN SIGN}: "
            f"{item['thumbs_up']}/{item['thumbs_down']} | {written_on}")

        try:
            await ctx.send(embed=embed)
        except discord.HTTPException:
            embed = discord.Embed(color=EGG_COLOR,
                                  timestamp=ctx.message.created_at)
            embed.set_author(name="Definition over 2048 characters.",
                             icon_url=ctx.me.avatar_url)
            embed.add_field(name="Link to definition", value=item["permalink"])
            await ctx.send(embed=embed)

    @commands.group(invoke_without_command=True)
    @commands.check_any(
        commands.check(lambda ctx: ctx.channel.id == 527938405951078407),
        commands.has_any_role("@moderator", "@admin", "@owner"))
    async def main2(self, ctx: Context):
        """Gives a role with permissions to send messages in Main 2.
           The role is automatically removed after 10 minutes of inactivity in the channel.
        """
        if await self.bot.db.fetchone(
                "SELECT * FROM main2_blacklist WHERE id = ?", ctx.author.id):
            embed = discord.Embed(color=EGG_COLOR,
                                  timestamp=ctx.message.created_at)
            embed.set_author(name="You're blacklisted from this command.",
                             icon_url=ctx.me.avatar_url)
            return await ctx.send(embed=embed)

        role = ctx.guild.get_role(723223787130191953)

        if role in ctx.author.roles:
            return

        embed = discord.Embed(
            description="You can now send messages in <#704713087772524565>.",
            color=EGG_COLOR,
            timestamp=ctx.message.created_at)
        embed.set_author(name="Role added.", icon_url=ctx.me.avatar_url)

        await ctx.author.add_roles(role)
        await ctx.send(embed=embed)

        def message_check(message: discord.Message):
            return message.author == ctx.author and message.channel.id == 704713087772524565

        def role_check(before: discord.Member, after: discord.Member):
            return role in before.roles and role not in after.roles

        while True:
            futures = [
                self.bot.wait_for("message", check=message_check),
                self.bot.wait_for("member_update", check=role_check)
            ]
            done, pending = await asyncio.wait(
                futures, timeout=600.0, return_when=asyncio.FIRST_COMPLETED)

            for future in pending:
                future.cancel()

            if not done:
                break

            result = done.pop().result()
            if isinstance(result, discord.Message):
                continue

            break

        await ctx.author.remove_roles(role)

    @main2.command()
    @commands.has_any_role("@moderator", "@admin", "@owner")
    async def block(self, ctx: Context, *, member: discord.Member):
        if role := discord.utils.get(member.roles, name="Main 2"):
            await member.remove_roles(role)

        _id = member.id
        await self.bot.db.execute(
            "INSERT OR IGNORE INTO main2_blacklist (id) VALUES (?)", _id)

        await ctx.message.add_reaction("\N{FLUSHED FACE}")
Ejemplo n.º 9
0
class Handle(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command(brief="Set nick codeforces để dùng bot.",
    usage="nick codeforces của bạn.")
    async def identify(self, ctx, handle): 
        """
        Dùng command này để set nick codeforces.
        Bot sẽ yêu cầu bạn nộp một code bị dịch lỗi tới bài nào đó trong vòng 60s.
        Nếu nick codeforces mình là `leduykhongngu` thì mình dùng:
        ;voj identify leduykhongngu
        """
        discord_id = ctx.author.id
        tmp = RankingDb.RankingDb.get_handle(discord_id)
        if tmp is not None:
            await ctx.send('Ông identify lần 2 làm cái gì. Có nick {0} chưa đủ à'.format(tmp))
            return
        subs = await codeforces_api.get_user_status(handle)
        problem = random.choice(codeforces_api.problems)
        await ctx.send(f'<@{str(ctx.author.id)}>, Hãy nộp một submission bị DỊCH LỖI tới bài <https://codeforces.com/problemset/problem/{problem[0]}/{problem[1]}> trong 60 giây')
        for i in range(6):
            await asyncio.sleep(10)
            subs = await codeforces_api.get_user_status(handle)
            if any(sub == problem[2] for sub in subs):
                x = RankingDb.RankingDb.set_handle(discord_id, handle)
                if x != 0:
                    await ctx.send('Lỗi, nick {0} đã được set cho user <@{1}>. Gọi @Cá nóc cắn cáp nếu cần giúp đỡ'.format(handle, x))
                else:
                    await ctx.send(SET_HANDLE_SUCCESS.format(discord_id, handle))
                return
        await ctx.send(f'<@{str(ctx.author.id)}>, thử lại pls. Dùng `;voj help identify` nếu cần giúp đỡ.')

    @commands.command(brief='Set Codeforces handle of a user')
    @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI'))
    async def set(self, ctx, member: discord.Member, handle):
        # message = (
        #     "Vẫn đang được dev, xin quay lại sau ...\n"
        #     "~~Vì lý do đặc biệt nên xem xét dùng các command sau:\n"
        #     "- Nếu user chưa identify bao giờ -> ;voj set_new @member handle\n"
        #     "- Nếu user muốn đổi acc codeforces -> ;voj change @member new_handle\n"
        #     "- Nếu user dùng acc discord mới -> ;voj ~~"
        # )
        # await ctx.send(message)
        # return
        # await ctx.send("Cẩn thận khi dùng cái này, nên hú Thức cho chắc.")
        if RankingDb.RankingDb.set_handle(member.id, handle) == 0:
            await ctx.send(SET_HANDLE_SUCCESS.format(member.id, handle))
        else:
            await ctx.send("Failed ?? :D ??")

    @commands.command(brief='Lấy nick của user tương ứng')
    async def get(self, ctx, member: discord.Member):
        """
        Lấy codeforces nick của user discord tương ứng.
        Nếu mình muốn lấy nick codeforces của Cá Nóc Cắn Cáp, thì dùng:
        ;voj get @cá nóc cắn cáp (tag vào)
        """
        handle = RankingDb.RankingDb.get_handle(member.id)
        if handle is None:
            await ctx.send(f'Không tìm thấy nick của {member.mention} trong dữ liệu. Xin hãy dùng command ;voj identify nick_cf')
            return
        await ctx.send(SET_HANDLE_SUCCESS.format(member.id, handle))
Ejemplo n.º 10
0
 def predicate(ctx):
     return commands.has_any_role(Roles.IF1A, Roles.IF1B, Roles.IB1A,
                                  Roles.IB1B, Roles.IB1C, Roles.IB1D)
Ejemplo n.º 11
0
    - ctx: discord.Context object

    Returns:
    - isDM: str"""
    # If message guild is None, we are in DMs
    if ctx.guild is None:
        return True
    return False


# region mod commands


# This decorator adds the command to the command list
@bot.command()
@commands.check_any(commands.has_any_role(*config.elevated_roles),
                    commands.is_owner())
# The function name is the name of the command, unless specified.
async def ban(ctx,
              musr: typing.Union[discord.Member, str] = None,
              *,
              reason: str = f"No reason supplied; {config.botname}"):
    # Check if the musr object was properly parsed as a User object
    if isinstance(musr, discord.Member):
        # ignore if self
        if ctx.author == musr:
            return

        # Fail if user is invincible
        if len([r for r in musr.roles if r.id in config.invincibleroles]) > 0:
            return await ctx.send("_🚫 You can't ban invincible users_")
Ejemplo n.º 12
0
    @disq.command(
        name="time",
        aliases=["t"],
        description=
        "Check how long until you or a user is re-eligible for giveaways.")
    async def disq_time(self, ctx, user: discord.Member = None):
        # This should return a timedelta? iunno lol
        if user is None:
            ctx.bot.disq(ctx.author)
        ctx.bot.disq(user)

    # Giveaway
    @commands.group(name="giveaway", aliases=["give", "g"])
    @commands.check_any(commands.has_guild_permissions(manage_messages=True),
                        commands.has_any_role())
    async def give(self, ctx):
        """All giveaway-related commands."""
        if not ctx.invoked_subcommand:
            await ctx.send_help(self.give)

    @give.command(name="start", aliases=["s"])
    async def give_start(self, ctx,
                         channel: typing.Optional[discord.TextChannel], *,
                         giveaway_data):
        """
        Starts a giveaway on a given channel.

        giveaway_data should have the following data:
        - Ending time
        - Platform data w/ giveaway row (Optional),
Ejemplo n.º 13
0
class POTD(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.Cog.listener()
    async def on_ready(self):
        self.POTD_dis = self.bot.get_channel(int(_POTD_DISCUSSION_CHANNEL))
        self.POTD_post = self.bot.get_channel(int(_POTD_POST))
        self.POTD_sug = self.bot.get_channel(int(_POTD_SUGGESTION))
    
    @commands.Cog.listener()
    async def on_message(self, message):
        if str(message.channel.id) != str(_POTD_SUGGESTION):
            return
        if message.author.bot:
            return
        note = message.content
        pattern = r"https?:\/\/\S+"
        links = re.findall(pattern, note)
        if len(links) == 0:
            return
        if len(links) > 1:
            await message.channel.send("Ít bài thôi, không prof đau ruột thừa mất.")
            return
        link = links[0]
        author = message.author.id
        if potd_database.PotdDB.add_potd(link, note, author):
            for x in message.guild.emojis:
                if x.name == 'dab':
                    await message.add_reaction(x)
        else:
            await message.channel.send('Ông đừng tưởng tôi không biết ông đạo bài nhé. Gửi bài khác đê.')

    @commands.command(brief="Lấy role SOTD sau khi hoàn thành bài")
    async def gimme(self, ctx):
        if potd_database.PotdDB.today_potd() is None:
            await ctx.send("Hôm nay làm gì có Problem of the day, ông định lừa ai?")
            return

        sotd = None
        for role in ctx.guild.roles:
            if role.name == _SOLVER_OF_THE_DAY:
                sotd = role

        if sotd is None:
            await ctx.send(f'Sever đã có role `{_SOLVER_OF_THE_DAY}` đâu mà cho')
            return

        for role in ctx.author.roles:
            if role.name == _SOLVER_OF_THE_DAY:
                await ctx.send('Xin 1 lần thôi xin gì xin lắm!!!!')
                return
    
        await ctx.author.add_roles(sotd)
        for x in ctx.guild.emojis:
            if x.name == 'dab':
                await ctx.message.add_reaction(x)

    async def clear_role(self, ctx):
        sotd = None
        for role in ctx.guild.roles:
            if role.name == _SOLVER_OF_THE_DAY:
                sotd = role
        if sotd is None:
            return
        cnt_AC = 0
        for member in sotd.members:
            await member.remove_roles(sotd)
            cnt_AC += 1
        print("Cleared role SOTD")
        return cnt_AC
    
    async def post_new_problem(self, ctx):
        potd = potd_database.PotdDB.get_potd()
        if potd is None:
            await ctx.send(f"Trong queue hết bài rồi, các bạn vào suggest đi <:sadness:662197924918329365>")
            return
        link = potd[0]
        note = potd[1]
        author = potd[2]
        author = ctx.guild.get_member(int(author))
        if author is None:
            author = ctx.author
        color = discord_common._SUCCESS_BLUE_
        today = datetime.today().strftime('%d-%m-%Y')
        embed = discord.Embed(title=f"Problem of the day {today}", description= note, url=link, color=color)
        embed.set_author(name=author.display_name, icon_url=author.avatar_url)
        embed.set_thumbnail(url="https://cdn.discordapp.com/avatars/669671624793915402/8c8e467d1ce25a0474279d076a33529a.jpg?size=1024")
        await self.POTD_post.send(embed=embed)
        return potd

    @commands.command(brief="Renew potd")
    @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI'))
    async def renew(self, ctx):
        #clear role SOTD
        current_potd = potd_database.PotdDB.today_potd()
        if current_potd is not None:
            cnt_AC = await self.clear_role(ctx)
            await ctx.send(f"Có {cnt_AC} người đã AC potd")
            link, note, author = current_potd
            potd_database.PotdDB.move_problem('potd_using', 'potd_used', link, note, author)
        #get new problem
        new_potd = await self.post_new_problem(ctx)
        if new_potd is not None:
            link, note, author = new_potd
            potd_database.PotdDB.move_problem('potd_queue', 'potd_using', link, note, author)
Ejemplo n.º 14
0
 def predicate(ctx):
     return commands.has_any_role(ServerRoles.ALL_GROUPS)
Ejemplo n.º 15
0
                await payload.member.send("Your reaction is recorded")
                await message.remove_reaction(reaction.emoji, payload.member)
                await c.execute(
                    "INSERT INTO reactions (user_id,message_id) VALUES (?,?)",
                    (member, payload.message_id))
                await c.execute("SELECT * FROM reactions")
                z = await c.fetchall()
                print(z)
                await conn.commit()
            elif users != None:
                await payload.member.send("You can't vote again")
                await message.remove_reaction(reaction.emoji, payload.member)


@commands.command()
@commands.check_any(commands.has_any_role("Mod", "BookKeeper"), is_suv())
async def save(self, ctx):
    for attachment in ctx.message.attachments:
        print("hello")
        if any(attachment.filename.lower().endswith(image)
               for image in image_types):
            for attachment in ctx.message.attachments:
                await attachment.save(attachment.filename)
                await ctx.send(f"Saved {attachment.filename}")


@save.error
async def save_error(self, ctx, error):
    if isinstance(error, commands.MissingAnyRole):
        await ctx.send("You don't have the role to run the command")
Ejemplo n.º 16
0
class reaction(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command(name='create poll', aliases=['cp'])
    @commands.check_any(commands.has_any_role("Mod", "BookKeeper"), is_suv())
    async def create_poll(self, ctx, question, *options):
        conn = await aiosqlite.connect('test.db')
        c = await conn.cursor()

        member = ctx.message.author
        member_name = member.name
        member_avatar = member.avatar_url
        print(member_name)

        embed = discord.Embed(colour=discord.Colour.green(), title=question)

        embed.set_author(name=member_name, icon_url=member_avatar)

        fields = [("Options", "\n".join([
            f"{alphabets[idx]} {option}" for idx, option in enumerate(options)
        ]), False), ("Instructions", "React slowly and on one option.", False)]

        for name, value, inline in fields:
            embed.add_field(name=name, value=value, inline=inline)

        sent_message = await ctx.send(embed=embed)

        for emote in alphabets[:len(options)]:
            await sent_message.add_reaction(emote)

        message_id = sent_message.id

        await c.execute("INSERT INTO reactions (message_id) VALUES ( ?)",
                        (message_id))
        await conn.commit()
        await c.execute("SELECT * FROM reactions")
        b = await c.fetchone()
        print("Command", b)

    @create_poll.error
    async def create_poll_error(self, ctx, error):
        if isinstance(error, commands.MissingAnyRole):
            await ctx.send("You don't have the role to run the command")

    @commands.Cog.listener()
    async def on_raw_reaction_add(self, payload):
        conn = await aiosqlite.connect('test.db')
        c = await conn.cursor()
        member = payload.user_id
        await c.execute(
            "SELECT user_id FROM reactions WHERE user_id = ? AND message_id = ?",
            (member, payload.message_id))
        users = await c.fetchone()
        print("User", users)

        await c.execute("SELECT message_id FROM reactions")

        message = await self.bot.get_channel(payload.channel_id
                                             ).fetch_message(payload.message_id
                                                             )

        for reaction in message.reactions:

            if (not payload.member.bot and users == None
                    and payload.member in await reaction.users().flatten()):

                await payload.member.send("Your reaction is recorded")
                await message.remove_reaction(reaction.emoji, payload.member)
                await c.execute(
                    "INSERT INTO reactions (user_id,message_id) VALUES (?,?)",
                    (member, payload.message_id))
                await c.execute("SELECT * FROM reactions")
                z = await c.fetchall()
                print(z)
                await conn.commit()
            elif users != None:
                await payload.member.send("You can't vote again")
                await message.remove_reaction(reaction.emoji, payload.member)
Ejemplo n.º 17
0
class Music(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.music_queue = defaultdict(list)

    @commands.command()
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role(*voice_channel_moderator_roles))
    async def summon(self, ctx):
        """Joins a voice channel"""
        logger.info(f"Summoned! author:'{ctx.author}'")

    @commands.command()
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role(*voice_channel_moderator_roles))
    async def play(self, ctx, *, song):
        """Play a song or playlist"""
        logger.info(
            f"play command - song:'{song}' author:'{ctx.author}' guild:'{ctx.guild}'"
        )

        music_queue = self.music_queue[ctx.guild.id]

        await self.queue_song(ctx, song)

        if len(music_queue) > 0 and not ctx.voice_client.is_playing():
            await self.play_music(ctx)

    @commands.command()
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role(*voice_channel_moderator_roles))
    async def skip(self, ctx):
        """Skip to next song"""
        logger.info(f"skip command - author:{ctx.author}")

        if ctx.voice_client:
            ctx.voice_client.stop()
            #await self.play_music(ctx)

    @commands.command()
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role(*voice_channel_moderator_roles))
    async def queue(self, ctx):
        """List songs in the queue"""
        logger.info(f"queue command - author:'{ctx.author}'")

        music_queue = self.music_queue[ctx.guild.id]

        if len(music_queue) > 0:
            embed = discord.Embed(title=f"Song queue")
            text = ""
            for (n, (player, _)) in enumerate(music_queue):
                text += f"{n+1}. **{player.title}**\n"

            embed.description = text
            await ctx.send(embed=embed)
        else:
            await ctx.send(f":shrug: Queue is empty")

    @commands.command()
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role(*voice_channel_moderator_roles))
    async def volume(self, ctx, volume: int):
        """Changes the player's volume"""
        logger.info(
            f"volume command - volume:'{volume}' author:'{ctx.author}'")

        if ctx.voice_client is None:
            return await ctx.send("Not connected to a voice channel.")

        volume = max(0, min(volume, 100))

        ctx.voice_client.source.volume = volume / 100
        await ctx.send(f"Changed volume to {volume}%")

    @commands.command()
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role(*voice_channel_moderator_roles))
    async def pause(self, ctx):
        """Pause or resume music"""
        logger.info(f"stop command - author:'{ctx.author}'")

        if ctx.voice_client is not None:
            if ctx.voice_client.is_paused():
                ctx.voice_client.resume()
                await ctx.send(f":arrow_forward: Resuming the music")
            elif ctx.voice_client.is_playing():
                ctx.voice_client.pause()
                await ctx.send(f":pause_button: Pausing the music")

    @commands.command()
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role(*voice_channel_moderator_roles))
    async def stop(self, ctx):
        """Stops and disconnects the bot from voice"""
        logger.info(f"stop command - author:'{ctx.author}'")

        music_queue = self.music_queue[ctx.guild.id]
        if ctx.voice_client is not None:
            await ctx.voice_client.disconnect()

        music_queue.clear()

    @commands.command()
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role(*voice_channel_moderator_roles))
    async def solo(self, ctx):
        """Soloooooooo"""
        logger.info(f"solo command - author:'{ctx.author}'")

        music_queue = self.music_queue[ctx.guild.id]

        await self.queue_song(ctx, solo)

        if len(music_queue) > 0 and not ctx.voice_client.is_playing():
            await self.play_music(ctx)

    @commands.Cog.listener()
    async def on_voice_state_update(self, member: discord.Member,
                                    before: discord.VoiceState,
                                    after: discord.VoiceState):
        if member.id == self.bot.user.id:
            return

        voice = member.guild.voice_client
        if voice is None:
            return

        logger.info(
            f"voice update voice:{voice} member:{member} before:{before.channel} after:{after.channel}"
        )

        channel = voice.channel
        if len(channel.members
               ) == 1 and channel.members[0].id == self.bot.user.id:
            logger.info(f"channel empty, wait 20s - channel:{channel}")
            await asyncio.sleep(20)
            if len(channel.members
                   ) == 1 and channel.members[0].id == self.bot.user.id:
                logger.info(f"disconnecting from {channel}")
                music_queue = self.music_queue[channel.guild.id]
                await voice.disconnect()
                music_queue.clear()

    async def queue_song(self, ctx, song):
        async with ctx.typing():
            songs = await YTDLSource.from_url(song, loop=self.bot.loop)
            if len(songs) == 0:
                await ctx.send(
                    f":shrug: Couldn't find **{song}** -- requested by {ctx.author.mention}"
                )
            else:
                text = ""
                music_queue = self.music_queue[ctx.guild.id]
                for song in songs:
                    logger.info(f"adding song {song.title}")

                    text += f":musical_note: Added **{song.title}** to the queue\n"
                    music_queue.append((song, ctx.author.mention))

                if len(music_queue) >= 1:
                    await ctx.send(embed=discord.Embed(description=text))

    async def play_music(self, ctx):
        music_queue = self.music_queue[ctx.guild.id]
        if len(music_queue) > 0:
            (song, author) = music_queue.pop(0)
            await ctx.send(embed=discord.Embed(
                description=
                f":arrow_forward: Playing **{song.title}** -- requested by {author}"
            ))
            loop = self.bot.loop
            ctx.voice_client.play(
                song,
                after=lambda e: wrap_await(
                    play_next(ctx, ctx.voice_client, music_queue, loop), loop))

    @play.before_invoke
    @solo.before_invoke
    @skip.before_invoke
    @summon.before_invoke
    async def ensure_voice(self, ctx):
        logger.info("ensuring voice connection")
        if ctx.author.voice:
            logger.info(f"connecting to {ctx.author.voice.channel.name}")
            if ctx.voice_client is None:
                await ctx.author.voice.channel.connect()
            else:
                await ctx.voice_client.move_to(ctx.author.voice.channel)
        else:
            await ctx.send("You are not connected to a voice channel.")
            raise commands.CommandError(
                "Author not connected to a voice channel.")
Ejemplo n.º 18
0
class RankingCommand(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        username = os.getenv('CODEFORCES_USERNAME')
        password = os.getenv('CODEFORCES_PASSWORD')
        group_id = os.getenv('CODEFORCES_GROUP_ID')
        self.crawler = SubmissionCrawler.Crawler(username, password, group_id)
        self.rank_cache = []
        self.looper.start()
        self.index = 0

    @tasks.loop(minutes=10.0)
    async def looper(self):
        self.index += 1
        print("looping " + str(self.index))
        try:
            await self.crawl(None, 1, 162)
            await self.calculate_rank(None)
        except Exception as e:
            print(e)

    @commands.command(brief="Lấy thông tin các huy hiệu")
    async def badge(self, ctx):
        """
        Hiện phần trăm điểm yêu cầu để đạt được huy hiệu tương ứng.
        """
        style = table.Style('{:<}  {:<}  {:<}')
        t = table.Table(style)
        t += table.Header('Tên huy hiệu', '% yêu cầu', '% giới hạn')
        t += table.Line()
        for rank in badge.RATED_RANKS:
            title = rank.title
            low = max(0, rank.low)
            hi = min(100, rank.high)
            low = "{:.2f}%".format(low)
            hi = "{:.2f}%".format(hi)
            t += table.Data(title, low, hi)
        table_str = f'```\n{t}\n```'
        embed = discord_common.cf_color_embed(
            title="% điểm yêu cầu."
            "Tổng điểm hiện tại SUM_SCORE={:.2f}".format(badge.MAX_SCORE),
            description=table_str)
        await ctx.send(embed=embed)

    @commands.command(brief="Update badge info.")
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role('Admin', 'Mod VNOI'))
    async def update_badge(self, ctx, name, low, hi):
        try:
            for i in range(len(badge.RATED_RANKS)):
                if badge.RATED_RANKS[i].title == name:
                    rank = badge.RATED_RANKS[i]
                    #Rank = namedtuple('Rank', 'low high title title_abbr color_graph color_embed')
                    badge.RATED_RANKS[i] = badge.Rank(float(low), float(hi),
                                                      name, rank.title_abbr,
                                                      rank.color_graph,
                                                      rank.color_embed)
                    await ctx.send('Ok')
                    return
            else:
                await ctx.send('Badge {0} not found'.format(name))
        except Exception as e:
            print(e)
            await ctx.send(str(e))

    # from TLE bot: https://github.com/cheran-senthil/TLE/blob/97c9bff9800b3bbaefb72ec00faa57a4911d3a4b/tle/cogs/duel.py#L410

    @commands.command(brief="Hiện bảng xếp hạng")
    async def rank(self, ctx):
        """
        Hiện bảng xếp hạng.
        """
        if len(self.rank_cache) == 0:
            await self.calculate_rank(ctx)
        _PER_PAGE = 10

        def make_page(chunk, page_num):
            style = table.Style('{:>}  {:<}  {:<}')
            t = table.Table(style)
            t += table.Header('#', 'Handle', 'Point')
            t += table.Line()
            for index, (point, handle) in enumerate(chunk):
                point_str = '{:.3f}'.format(point)
                t += table.Data(_PER_PAGE * page_num + index, handle,
                                point_str)

            table_str = f'```yml\n{t}\n```'
            embed = discord.Embed(description=table_str)
            return 'Bảng xếp hạng VOJ', embed

        pages = [
            make_page(chunk, k) for k, chunk in enumerate(
                paginator.chunkify(self.rank_cache, _PER_PAGE))
        ]
        paginator.paginate(self.bot, ctx.channel, pages)

    @commands.command(brief="Calculate ranking and cache it.")
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role('Admin', 'Mod VNOI'))
    async def calculate_rank(self, ctx):
        start = time.perf_counter()
        message = ""
        if ctx != None:
            message = await ctx.send(
                '<:pingreee:665243570655199246> Calculating ...')
        # calculating
        problem_points = common.get_problem_points(force=True)
        badge.MAX_SCORE = 0
        # for p, point in problem_points.items():
        #     #remove scale
        #     badge.MAX_SCORE += point
        #     # badge.MAX_SCORE += 2
        user_data = RankingDb.RankingDb.get_data('user_data', limit=None)
        user_handles = {}
        for cf_id, handle, discord_id in user_data:
            if cf_id is None:
                continue
            user_handles[int(cf_id)] = handle

        user_points = {}
        solved_info = RankingDb.RankingDb.get_data('solved_info', limit=None)
        for user_id, problem_id, result, date in solved_info:
            handle = user_handles[int(user_id)]
            if handle not in user_points:
                user_points[handle] = 0
            if result == 'AC':
                result = 100
            result = float(result)
            #remove scale
            user_points[handle] += result * problem_points[int(
                problem_id)] / 100
            # user_points[handle] += result * 2 / 100
        self.rank_cache = []
        badge.MAX_SCORE = 0
        for handle, point in user_points.items():
            self.rank_cache.append((point, handle))
            badge.MAX_SCORE = max(badge.MAX_SCORE, point)
        self.rank_cache.sort(reverse=True)
        end = time.perf_counter()
        duration = (end - start) * 1000
        if ctx != None:
            await message.edit(
                content=f'Done. Calculation time: {int(duration)}ms.')

    @commands.command(brief="Test crawler")
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role('Admin', 'Mod VNOI'))
    async def exclude(self, ctx, contest_id):
        open('database/contest_id_whitelist.txt',
             'a').write(str(contest_id) + '\n')
        await ctx.send('ok')

    @commands.command(brief="Test crawler")
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role('Admin', 'Mod VNOI'))
    async def crawl(self, ctx, l, r):
        if self.crawler.login() == False:
            if ctx is not None:
                await ctx.send(
                    'Failed when log in to codeforces, please try later.')
            else:
                print('Failed when log in to codeforces, please try later.')
            return
        l = int(l)
        r = int(r)
        problems = self.crawler.get_new_submissions(l, r)
        if ctx is not None:
            await ctx.send('Found {0} submissions.'.format(len(problems)))
        else:
            print('Found {0} submissions.'.format(len(problems)))
        cnt = 0
        for p_info in problems:
            cnt += 1
            if cnt % 10 == 0:
                print(cnt)
            id, problem_name, short_link, handle, user_id, verdict, date = p_info
            RankingDb.RankingDb.handle_new_submission(problem_name, short_link,
                                                      verdict, user_id, handle,
                                                      date)
        RankingDb.RankingDb.conn.commit()
Ejemplo n.º 19
0
class BotControl(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.start_time = time.time()

    # @commands.Cog.listener()
    # async def on_ready(self):
    #     pass

    # from TLE bot.
    @commands.command(brief="Check if bot is still alive.")
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role('Admin', 'Mod VNOI'))
    async def ping(self, ctx):
        """Replies to a ping."""
        start = time.perf_counter()
        message = await ctx.send('<:pingreee:665243570655199246>')
        end = time.perf_counter()
        duration = (end - start) * 1000
        await message.edit(
            content=
            f'<:pingreee:665243570655199246>\nREST API latency: {int(duration)}ms\n'
            f'Gateway API latency: {int(self.bot.latency * 1000)}ms')

    @commands.command(brief="Kill bot. ")
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role('Admin', 'Mod VNOI'))
    async def kill(self, ctx):
        """Kill bot"""
        await ctx.send("Dying")
        exit(0)

    @commands.command(brief='Restart bot')
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role('Admin', 'Mod VNOI'))
    async def restart(self, ctx):
        await ctx.send('Restarting...')
        os.execv(sys.executable, [sys.executable] + sys.argv)

    @commands.command(brief="Get database. ")
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role('Admin', 'Mod VNOI'))
    async def database(self, ctx):
        last_submission = open('database/last_submission.txt').read().strip()
        await ctx.send('Last submissions: {0}'.format(last_submission),
                       file=discord.File('database/ranking.db',
                                         filename='ranking.db'))

    @commands.command(brief="Update bot & restart")
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role('Admin', 'Mod VNOI'))
    async def update_restart(self, ctx):
        await self.update(ctx)
        await self.restart(ctx)

    @commands.command(brief='Get git information')
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role('Admin', 'Mod VNOI'))
    async def git(self, ctx):
        """Replies with git information."""
        await ctx.send('```yaml\n' + git_history() + '```')

    @commands.command(brief='Incorporates changes from the remote repository')
    @commands.check_any(commands.is_owner(),
                        commands.has_any_role('Admin', 'Mod VNOI'))
    async def update(self, ctx):
        mess = await ctx.send('Getting changes from the remote repository...')
        result = subprocess.run(
            ['git', 'pull', 'origin', 'dev'],
            stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
        await mess.edit(content='```\n' + result + '\n```')
Ejemplo n.º 20
0
class SheetApproval(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    async def sheet_from_emoji(self, payload) -> ToBeApproved:
        # Check the Guild
        guild_id = payload.guild_id
        if guild_id != self.bot.personal_server['server_id']:
            return None

        # Check the Roles
        member = payload.member
        if member is None:
            member = self.bot.get_guild(guild_id).get_member(payload.user_id)
            if member is None:
                return None
        if len([
                role for role in member.roles
                if role.name.lower() in APPROVAL_ROLES
        ]) == 0:
            return None

        # Check to see if it's an existing sheet
        result = await self.bot.mdb['to_approve'].find_one(
            {'message_id': payload.message_id})
        if result is None:
            return None
        # Get rid of object id
        result.pop('_id')

        sheet: ToBeApproved = ToBeApproved.from_dict(result)
        return sheet

    @commands.Cog.listener('on_raw_reaction_add')
    async def check_for_approval(self, payload):
        sheet: ToBeApproved = await self.sheet_from_emoji(payload)
        if sheet is None:
            return
        if len(sheet.approvals) >= 2:
            return

        guild = self.bot.get_guild(payload.guild_id)

        await sheet.add_approval(guild, payload.member, self.bot)
        await sheet.commit(self.bot.mdb['to_approve'])

    @commands.Cog.listener('on_raw_reaction_remove')
    async def check_for_deny(self, payload):
        sheet: ToBeApproved = await self.sheet_from_emoji(payload)
        if sheet is None:
            return

        guild = self.bot.get_guild(payload.guild_id)
        await sheet.remove_approval(guild, payload.user_id, self.bot)
        await sheet.commit(self.bot.mdb['to_approve'])

    @commands.command(name='sheet', aliases=['submit'])
    @is_personal_server()
    async def new_sheet(self, ctx, *, content: str):
        """
        Adds a sheet to be approved
        """
        embed = create_default_embed(ctx)
        embed.title = f'Sheet Approval - {ctx.author.display_name}'
        embed.description = content

        if '(url)' in content:
            return await ctx.author.send(
                'You must include your *actual* sheet URL in the command, not `(url)`'
            )

        # If not character-submission or FrogBot dev
        if (ctx.channel.id != self.bot.personal_server['sheet_channel']
            ) and not (ctx.guild.id == 755202524859859004):
            return await ctx.send(
                'This channel is not valid for submitting sheets.')

        msg = await ctx.send(embed=embed)

        new_sheet = ToBeApproved(message_id=msg.id,
                                 approvals=[],
                                 channel_id=ctx.channel.id,
                                 owner_id=ctx.author.id)
        await self.bot.mdb['to_approve'].insert_one(new_sheet.to_dict())

    @commands.command('cleanup_sheets')
    @is_personal_server()
    @commands.check_any(is_owner(), commands.has_any_role(*BOT_MODS))
    async def remove_sheets(self, ctx):
        """
        Removes deleted sheets from database. Run every once and a while.
        """
        db = self.bot.mdb['to_approve']

        embed = create_default_embed(ctx)
        embed.title = f'Pruning Old Sheets from Database.'
        all_sheets = await db.find().to_list(None)
        count = 0
        for sheet in all_sheets:
            sheet.pop('_id')
            sheet = ToBeApproved.from_dict(sheet)
            channel = ctx.guild.get_channel(sheet.channel_id)
            if channel is None:
                continue
            try:
                await channel.fetch_message(sheet.message_id)
            except discord.NotFound:
                count += 1
                await db.delete_one({'message_id': sheet.message_id})
        embed.description = f'Pruned {count} Sheet{"s" if count != 1 else ""} from the DB.'
        await ctx.send(embed=embed)
Ejemplo n.º 21
0
class Loot(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.timeFormats = [
            "%d/%m/%Y", "%d/%m/%y", "%m/%d", "%d-%m-%Y", "%d-%m-%y", "%m-%d"
        ]

    @commands.command(help="Adds a user to the loot tracking Database.")
    @commands.check_any(commands.has_any_role(*keys.LOOT_MODS), is_me())
    async def addUser(self, ctx, username: str):
        with self.createConnection() as conn:
            with conn.cursor() as cur:
                cur.execute(
                    "SELECT * FROM {0} WHERE username ILIKE %s".format(
                        keys.USERS_TABLE), (username, ))
                if (cur.fetchone() == None):
                    cur.execute(
                        "INSERT INTO {0} (username) VALUES(%s)".format(
                            keys.USERS_TABLE), (username, ))
                    await ctx.message.add_reaction('✅')
                else:
                    await ctx.send(
                        "User `{0}` already added to database.".format(
                            username))

    @commands.command(
        help=
        "Adds a drop.\n Timestamp should be of the format DD/MM or DD/MM/YY. If no year is specified, the current year will be assumed."
    )
    @commands.check_any(commands.has_any_role(*keys.LOOT_MODS), is_me())
    async def addLoot(self, ctx, username: str, timestamp: str, *, loot):
        with self.createConnection() as conn:
            with conn.cursor() as cur:

                ##table = "drops2" if ctx.channel.id == 718219865483116545 else "drops"
                table = keys.SECONDARY_MAPPINGS[
                    ctx.channel.
                    id] if ctx.channel.id in keys.SECONDARY_MAPPINGS else keys.MAIN_DB

                ##Validate username and exit if invalid
                ret = await self.__validateUsername(ctx, cur, username)
                if (ret):
                    return ()

                ##Validate timestamp, store in self.dTime, and exit if invalid
                ret = await self.__validateTimestamp(ctx, timestamp)
                if (ret):
                    return ()

                ##Validate loot and exit if invalid
                ret = await self.__validateLoot(ctx, cur, loot)
                if (ret):
                    return ()

                try:
                    cur.execute(
                        "INSERT INTO {0} (date, username, loot) VALUES(%s, %s, %s)"
                        .format(table), (self.dTime, username, loot))
                    await ctx.message.add_reaction('✅')
                except psycopg2.errors.UniqueViolation as e:
                    await ctx.send("Duplicate, unable to insert.")
                except Exception as e:
                    print("Error inserting: {0}".format(e))
                    await ctx.send(
                        "Unable to insert, contact Will if you think this is in error."
                    )

    @commands.command(
        help=
        "Deletes user and ALL associated drops from database. Use carefully.")
    @commands.check_any(commands.has_any_role(*keys.LOOT_MODS), is_me())
    async def deleteUser(self, ctx, username: str):
        with self.createConnection() as conn:
            with conn.cursor() as cur:

                ##Validate username and exit if invalid
                ret = await self.__validateUsername(ctx, cur, username)
                if (ret):
                    return ()

                r1 = cur.execute("DELETE FROM drops WHERE username ILIKE %s",
                                 (username, ))
                r2 = cur.execute(
                    "DELETE FROM {0} WHERE username ILIKE %s".format(
                        keys.USERS_TABLE), (username, ))
                r3 = cur.execute("DELETE FROM drops2 WHERE username ILIKE %s",
                                 (username, ))

                print(r1, r2)

                await ctx.message.add_reaction('✅')

    @commands.command(
        help="Deletes a specific drop from the database. Use carefully.")
    @commands.check_any(commands.has_any_role(*keys.LOOT_MODS), is_me())
    async def deleteLoot(self, ctx, username: str, timestamp: str, *, loot):
        with self.createConnection() as conn:
            with conn.cursor() as cur:

                table = keys.SECONDARY_MAPPINGS[
                    ctx.channel.
                    id] if ctx.channel.id in keys.SECONDARY_MAPPINGS else keys.MAIN_DB

                ##Validate username and exit if invalid
                ret = await self.__validateUsername(ctx, cur, username)
                if (ret):
                    return ()

                ##Validate timestamp, store in self.dTime, and exit if invalid
                ret = await self.__validateTimestamp(ctx, timestamp)
                if (ret):
                    return ()

                ##Validate loot and exit if invalid
                ret = await self.__validateLoot(ctx, cur, loot)
                if (ret):
                    return ()

                cur.execute(
                    "DELETE FROM {0} WHERE date = %s AND username ILIKE %s AND loot ILIKE %s"
                    .format(table), (self.dTime, username, loot))

                await ctx.message.add_reaction('✅')

    async def __validateLoot(self, ctx, cur, loot):
        cur.execute(
            "SELECT * FROM {0} WHERE loot ILIKE %s".format(
                keys.DROPS_TABLE_DB), (loot, ))
        if (cur.fetchone() == None):
            cur.execute(
                "SELECT *, similarity(loot, %s) FROM {0} ORDER BY 5 desc LIMIT 5;"
                .format(keys.DROPS_TABLE_DB), (loot, ))
            simList = "\n".join(["`{0[1]}`".format(x) for x in cur.fetchall()])
            await ctx.send(
                "Loot `{0}` not in database.\nDid you mean:\n{1}".format(
                    loot, simList))
            return (1)
        return (0)

    async def __validateUsername(self, ctx, cur, username):
        cur.execute(
            "SELECT * FROM {0} WHERE username ILIKE %s".format(
                keys.USERS_TABLE), (username, ))
        if (cur.fetchone() == None):
            cur.execute(
                "SELECT *, similarity(username, %s) FROM {0} ORDER BY 3 desc LIMIT 5;"
                .format(keys.USERS_TABLE), (username, ))
            simList = "\n".join(["`{0[1]}`".format(x) for x in cur.fetchall()])
            await ctx.send(
                "User `{0}` not in database.\nYou can add them with ```?addUser {0}```\nOr, did you mean:\n{1}"
                .format(username, simList))
            return (1)
        return (0)

    async def __validateTimestamp(self, ctx, timestamp):
        self.dTime = None
        for tFormat in self.timeFormats:
            try:
                self.dTime = time.strptime(timestamp, tFormat)
                break
            except:
                pass
        if (self.dTime == None):
            await ctx.send("Invalid time format specified. Try MM/DD")
            return (1)
        self.dTime = datetime.datetime(*self.dTime[:6])
        if (self.dTime.year == 1900):
            self.dTime = self.dTime.replace(year=datetime.datetime.now().year)
        if (self.dTime > datetime.datetime.now() + datetime.timedelta(days=1)):
            await ctx.send("Timestamp is in the future.")
            return (1)
        return (0)

    async def __validateRaid(self, ctx, cur, raid):
        cur.execute(
            "SELECT * FROM {0} WHERE raid ILIKE %s".format(
                keys.DROPS_TABLE_DB), (raid, ))
        if (cur.fetchone() == None):
            cur.execute(
                "SELECT DISTINCT (raid), similarity(raid, %s) FROM {0} ORDER BY similarity DESC LIMIT 5"
                .format(keys.DROPS_TABLE_DB), (raid, ))
            simList = "\n".join(["`{0[0]}`".format(x) for x in cur.fetchall()])
            await ctx.send(
                "Raid `{0}` not in database.\nDid you mean:\n{1}".format(
                    raid, simList))
            return (1)
        return (0)

    async def __validateBoss(self, ctx, cur, boss):
        cur.execute(
            "SELECT * FROM {0} WHERE boss ILIKE %s".format(
                keys.DROPS_TABLE_DB), (boss, ))
        if (cur.fetchone() == None):
            cur.execute(
                "SELECT DISTINCT (boss), similarity(boss, %s) FROM {0} ORDER BY similarity DESC LIMIT 5"
                .format(keys.DROPS_TABLE_DB), (boss, ))
            simList = "\n".join(["`{0[0]}`".format(x) for x in cur.fetchall()])
            await ctx.send(
                "Boss `{0}` not in database.\nDid you mean:\n{1}".format(
                    boss, simList))
            return (1)
        return (0)

    @commands.command(help="Exports entire database as a csv.")
    @commands.check_any(commands.has_any_role(*keys.LOOT_MODS), is_me())
    async def exportCSV(self, ctx):
        with self.createConnection() as conn:
            with conn.cursor() as cur:

                table = keys.SECONDARY_MAPPINGS[
                    ctx.channel.
                    id] if ctx.channel.id in keys.SECONDARY_MAPPINGS else keys.MAIN_DB

                cur.execute("SELECT * FROM {0}".format(table))
                drops = cur.fetchall()
                dropList = "username,date,loot\n" + "\n".join(
                    ["{0[2]},{0[1]},{0[3]}".format(x) for x in drops])

                f = discord.File(io.StringIO(dropList), filename="loot.csv")
                await ctx.send("Exported csv:", file=f)

    @commands.command(help="Displays the loot recieved by the given user.")
    @commands.check_any(commands.has_any_role(*USERS), is_me())
    async def loot(self, ctx, *, username):
        with self.createConnection() as conn:
            with conn.cursor() as cur:

                table = keys.SECONDARY_MAPPINGS[
                    ctx.channel.
                    id] if ctx.channel.id in keys.SECONDARY_MAPPINGS else keys.MAIN_DB

                ##Validate username and exit if invalid
                ret = await self.__validateUsername(ctx, cur, username)
                if (ret):
                    return ()

                cur.execute(
                    "SELECT * FROM {0} WHERE username ILIKE %s".format(table),
                    (username, ))
                drops = cur.fetchall()

                dropList = "\n\t".join(
                    ["`{0[3]}` - {0[1]}".format(x) for x in drops])
                outStr = "`{0}` has received drops:\n\t{1}".format(
                    username, dropList)

                ##if we can't attach the full log, send as an attachment.
                if (len(outStr) > 2000):
                    f = discord.File(io.StringIO("\n".join(
                        ["{0[3]} - {0[1]}".format(x) for x in drops])),
                                     filename="{0}_drops.txt".format(username))
                    await ctx.send(
                        "Drop Log for `{0}` exceeds the message length limit. Attaching as file."
                        .format(username),
                        file=f)
                else:
                    await ctx.send(outStr)

    @commands.command(help="Displays who has looted the given item.")
    @commands.check_any(commands.has_any_role(*USERS), is_me())
    async def looted(self, ctx, *, drop):
        with self.createConnection() as conn:
            with conn.cursor() as cur:

                table = keys.SECONDARY_MAPPINGS[
                    ctx.channel.
                    id] if ctx.channel.id in keys.SECONDARY_MAPPINGS else keys.MAIN_DB

                ##Validate loot and exit if invalid
                ret = await self.__validateLoot(ctx, cur, drop)
                if (ret):
                    return ()

                cur.execute(
                    "SELECT * FROM {0} WHERE loot ILIKE %s".format(table),
                    (drop, ))
                drops = cur.fetchall()

                dropList = "\n\t".join(
                    ["`{0[2]}` - {0[1]}".format(x) for x in drops])
                outStr = "All recipients of `{0}`:\n\t{1}".format(
                    drop, dropList)

                ##if we can't attach the full log, send as an attachment.
                if (len(outStr) > 2000):
                    f = discord.File(
                        io.StringIO("\n".join(
                            ["{0[2]} - {0[1]}".format(x) for x in drops])),
                        filename="{0}_drops.txt".format(drop).replace(
                            " ", "_"))
                    await ctx.send(
                        "Drop Log for `{0}` exceeds the message length limit. Attaching as file."
                        .format(drop),
                        file=f)
                else:
                    await ctx.send(outStr)

    @commands.command(help="Displays the sources for the given item.")
    @commands.check_any(commands.has_any_role(*USERS), is_me())
    async def sources(self, ctx, *, loot):
        with self.createConnection() as conn:
            with conn.cursor() as cur:

                ##Validate loot and exit if invalid
                ret = await self.__validateLoot(ctx, cur, loot)
                if (ret):
                    return ()

                cur.execute(
                    "SELECT * FROM {0} WHERE loot ILIKE %s".format(
                        keys.DROPS_TABLE_DB), (loot, ))
                sources = cur.fetchall()

                sourceList = "\n\t".join(
                    ["{0[2]} in {0[3]}".format(x) for x in sources])

                await ctx.send("`{0}` is available from:\n\t{1}".format(
                    loot, sourceList))

    @commands.command(help="Displays the bosses in the given raid.")
    @commands.check_any(commands.has_any_role(*USERS), is_me())
    async def raid(self, ctx, *, raid):
        with self.createConnection() as conn:
            with conn.cursor() as cur:

                ##Validate raod and exit if invalid
                ret = await self.__validateRaid(ctx, cur, raid)
                if (ret):
                    return ()

                cur.execute(
                    "SELECT DISTINCT (boss) FROM {0} WHERE raid ILIKE %s".
                    format(keys.DROPS_TABLE_DB), (raid, ))
                bosses = cur.fetchall()

                bossList = "\n\t".join(["`{0[0]}`".format(x) for x in bosses])

                await ctx.send(
                    "Bosses in raid `{0}` are:\n\t{1}\nYou can use `?boss <boss>` to view a boss' drops."
                    .format(raid, bossList))

    @commands.command(help="Displays the possible drops from the given boss.")
    @commands.check_any(commands.has_any_role(*USERS), is_me())
    async def boss(self, ctx, *, boss):
        with self.createConnection() as conn:
            with conn.cursor() as cur:

                ##Validate boss and exit if invalid
                ret = await self.__validateBoss(ctx, cur, boss)
                if (ret):
                    return ()

                cur.execute(
                    "SELECT loot FROM {0} WHERE boss ILIKE %s".format(
                        keys.DROPS_TABLE_DB), (boss, ))
                loot = cur.fetchall()

                lootList = "\n\t".join(["`{0[0]}`".format(x) for x in loot])

                await ctx.send("`{0}` can drop:\n\t{1}".format(boss, lootList))

    @commands.command(help="Displays all the loot on a given date.")
    @commands.check_any(commands.has_any_role(*USERS), is_me())
    async def lootDate(self, ctx, timestamp: str):
        with self.createConnection() as conn:
            with conn.cursor() as cur:

                table = keys.SECONDARY_MAPPINGS[
                    ctx.channel.
                    id] if ctx.channel.id in keys.SECONDARY_MAPPINGS else keys.MAIN_DB

                ##Validate timestamp, store in self.dTime, and exit if invalid
                ret = await self.__validateTimestamp(ctx, timestamp)
                if (ret):
                    return ()
                dateStr = self.dTime.strftime("%D")

                cur.execute(
                    "SELECT * FROM {0} WHERE date::date = %s".format(table),
                    (dateStr, ))

                drops = cur.fetchall()

                dropList = "\n\t".join(
                    ["`{0[3]}` - `{0[2]}`".format(x) for x in drops])
                outStr = "All items looted on `{0}`:\n\t{1}".format(
                    dateStr, dropList)

                ##if we can't attach the full log, send as an attachment.
                if (len(outStr) > 2000):
                    f = discord.File(
                        io.StringIO("\n".join(
                            ["{0[3]} - {0[2]}".format(x) for x in drops])),
                        filename="{0}_drops.txt".format(dateStr).replace(
                            "/", "-"))
                    await ctx.send(
                        "Drop Log for `{0}` exceeds the message length limit. Attaching as file."
                        .format(dateStr),
                        file=f)
                else:
                    await ctx.send(outStr)

    def createConnection(self):
        return (psycopg2.connect(dbname="loot",
                                 user=keys.PSQL_USERNAME,
                                 password=keys.PSQL_PASSWORD,
                                 host="192.168.1.20",
                                 port=5432))
Ejemplo n.º 22
0
        try:
            response = requests.get(
                "https://www.googleapis.com/customsearch/v1"
                f"?key={GOOGLE_API_KEY}&cx={pseid}&q={query}").json(
                )["items"][0]["link"]
        except KeyError:
            response = "No matches found."
    return response


@OMEGA.command(
    name="iq",
    help=
    "Takes a username, analyzes their post history to generate an estimate of their IQ",
)
@commands.check_any(commands.has_any_role("Regular", "Admin"),
                    commands.check(is_in_playground))
async def estimate_iq(ctx, *args):
    """Returns Omega's most accurate possible estimate of given username's IQ"""
    if len(args) >= 1:
        queried_username = args[0]
        queried_iq_estimate = random.randint(25, 100)
        requester_iq_estimate = queried_iq_estimate - random.randint(5, 30)
        requester_username = ctx.message.author
        response = (
            f"Based on post history, {queried_username} has an IQ of approximately "
            f"{queried_iq_estimate} (which is {queried_iq_estimate - requester_iq_estimate} points "
            f"higher than the estimated value of {requester_iq_estimate} for {requester_username})."
        )
    else:
        requester_iq_estimate = random.randint(5, 65)
Ejemplo n.º 23
0
 def predicate(ctx):
     return commands.has_any_role(Roles.INFORMATIK,
                                  Roles.WIRTSCHAFTSINFORMATIK,
                                  Roles.DATA_SCIENCE)
Ejemplo n.º 24
0
@list.error
async def list_error(ctx, error):
    message = 'Wot?'
    if isinstance(error, commands.MissingRequiredArgument):
        message = 'List confluences or essences.'
    elif isinstance(error, commands.CommandInvokeError):
        err = error.original
        if isinstance(err, KeyError):
            message = "Not found."
    await ctx.send(f'**ERROR**: `{message}`')

    print(error)

# TODO: add "new" command line "list"
@bot.command()
@commands.check_any(commands.has_any_role(*ADMIN_ROLES), commands.is_owner())
async def new(ctx, what, *args):
    what = what.lower()
    if what == 'essence':
        await new_essence(ctx, *args)
    elif what == 'combination':
        await new_combination(ctx, *args)
    else:
        raise commands.MissingRequiredArgument

async def new_essence(ctx, name, rarity='Unknown'):
    name, rarity = map(logic.form, [name, rarity])
    logic.add_essence(name, rarity)
    await ctx.send(f'Added new essence `{name} [{rarity}]`.')

Ejemplo n.º 25
0
class Modmail(commands.Cog, name="Modmail System"):
    def __init__(self, client):
        self.client = client
        self.IST = pytz.timezone('Asia/Kolkata')
        print("Caching Modmail Data...")
        self.active_channels_dict = {
            i['_id']: i["channel_id"]
            for i in self.client.sent_users.find()
        }
        self.ban_dict = {
            i['_id']: {
                'reason': i['reason'],
                'mod': i['mod']
            }
            for i in self.client.blacklisted_users.find()
        }
        with open("data.json") as f:
            data = json.load(f)
            f.close()
        self.category_id = data['category_id']
        self.server_id = data['guild_id']
        self.mod_role_id = data['mod_role_id']
        self.log_channel_id = data['log_channel_id']
        self.guild = self.client.get_guild(self.server_id)
        self.log_channel = discord.utils.get(self.guild.channels,
                                             id=data['log_channel_id'])
        self.msg = None
        print("Done")

    @commands.Cog.listener()
    async def on_ready(self):
        print(f"{self.__class__.__name__} loaded successfully.")

    @commands.Cog.listener()
    async def on_message(self, message):
        modmail_category = discord.utils.get(self.guild.categories,
                                             id=int(self.category_id))
        mod_role = discord.utils.get(self.guild.roles,
                                     id=int(self.mod_role_id))
        if message.author == self.client.user:
            return
        if not message.guild:
            if message.author not in self.guild.members:
                message_dm = await message.author.send(
                    "You are not in **Gallant Asia**. Join the server to use modmail and connect with the staffs.\n"
                    "Click on ✅ to get invite link.")
                await message_dm.add_reaction('✅')

                def check(reaction, user):
                    return user == message.author and str(
                        reaction.emoji) == '✅'

                try:
                    _, user_ = await self.client.wait_for('reaction_add',
                                                          check=check,
                                                          timeout=10.0)
                except asyncio.TimeoutError:
                    pass
                else:
                    await user_.send("https://discord.gg/NPFqwc9")
                return
            if message.author.id in self.ban_dict:
                await message.author.send(
                    f"You are banned from using Modmail.\n`Reason: {self.ban_dict[message.author.id]['reason']}`"
                )
                return
            if message.author.id not in self.active_channels_dict:
                overwrites = {
                    self.guild.default_role:
                    discord.PermissionOverwrite(read_messages=False),
                    self.guild.me:
                    discord.PermissionOverwrite(read_messages=True),
                    mod_role:
                    discord.PermissionOverwrite(read_messages=True)
                }
                channel = await self.guild.create_text_channel(
                    f"{message.author.name}",
                    overwrites=overwrites,
                    category=modmail_category)
                post = {'_id': message.author.id, "channel_id": channel.id}
                self.client.sent_users.insert_one(post)
                self.active_channels_dict[message.author.id] = channel.id
                self.msg = await self.log_channel.send(
                    content=channel.mention,
                    embed=discord.Embed(
                        title='New Thread',
                        description=
                        f"New thread created by {message.author.name}({message.author.name})\n"
                        f"Channel Created => {channel.mention}",
                        timestamp=datetime.now(self.IST),
                        color=discord.Color.gold()))
                files = [
                    await attachment.to_file()
                    for attachment in message.attachments
                ] if message.attachments != [] else None
                await message.author.send(
                    "Thank you for your message! You've opened up a new thread with our team of supportive moderators and admins."
                    "As long as the bot is online, messages you send here will be forwarded to the team.\n"
                    "If you've realised that you no longer need our help, reply with 'close' and we'll close your thread."
                )
                await channel.send(files=files,
                                   embed=discord.Embed(
                                       title='Reply with *reply',
                                       description=message.content,
                                       timestamp=datetime.now(self.IST),
                                       color=discord.Color.green()))
            else:
                channel = discord.utils.get(self.guild.channels,
                                            id=self.active_channels_dict.get(
                                                message.author.id))
                await self.log_channel.send(
                    content=channel.mention,
                    embed=discord.Embed(
                        title='New message',
                        description=
                        f" Message from {message.author.name}({message.author.name})\n",
                        timestamp=datetime.now(self.IST),
                        color=discord.Color.random()))
                await message.add_reaction("✅")
                await channel.send(
                    embed=discord.Embed(title='Reply with *reply or *r',
                                        description=message.content,
                                        timestamp=datetime.now(self.IST),
                                        color=discord.Color.green()))

    @commands.Cog.listener()
    async def on_member_remove(self, member):
        if member.id in self.active_channels_dict.keys():
            channel = discord.utils.get(
                self.guild.channels, id=self.active_channels_dict[member.id])
            try:
                self.client.sent_users.delete_one({'_id': member.id})
                del self.active_channels_dict[member.id]
            except KeyError:
                pass
            await member.send(
                'You left our server. Your thread has been closed.\n'
                'Hope to see you back soon.\n- Gallant Asia Management Team.')
            await channel.send(
                f"{member.name} has left the server. Thread has been closed.Channel will be deleted in 5 minutes."
            )
            await self.log_channel.send(
                content=channel.mention,
                embed=discord.Embed(
                    title='Thread closed!',
                    description=
                    f'Thread {channel.mention} has been closed due to {member.name} left the server.',
                    color=discord.Color.orange()))
            await asyncio.sleep(300.0)
            check = discord.utils.get(self.guild.channels, id=channel.id)
            if check is not None:
                await channel.delete()
                await self.log_channel.send(embed=discord.Embed(
                    title='Ticket deleted.',
                    description=f"{member.name}'s ticket has been deleted.",
                    color=discord.Color.red()))

    @commands.command(aliases=['r'])
    @commands.check_any(commands.has_permissions(administrator=True),
                        commands.has_any_role("Moderator", "Head Mod"))
    async def reply(self, ctx, *, message):
        if isinstance(ctx.channel, discord.DMChannel):
            return
        user = discord.utils.get(self.guild.members,
                                 id=self.get_key(ctx.channel.id))
        if user is not None:
            var = 'Community Lead' if ctx.author.top_role.name == '.' else ctx.author.top_role.name
            files = [
                await attachment.to_file()
                for attachment in ctx.message.attachments
            ] if ctx.message.attachments != [] else None
            await user.send(
                content=
                f"**({var}){ctx.author.name}#{ctx.author.discriminator}:** {message}",
                files=files)
            await ctx.message.add_reaction('✅')
            await self.log_channel.send(
                content=ctx.channel.mention,
                embed=discord.Embed(
                    description=
                    f'{ctx.author.name} replied to {ctx.channel.mention}',
                    timestamp=datetime.now(self.IST),
                    color=discord.Color.random()))
        else:
            await ctx.send(
                'Some error occurred. Maybe you are not using the command in a thread channel.'
            )

    @commands.command()
    @commands.check_any(commands.has_permissions(administrator=True),
                        commands.has_any_role("Moderator", "Head Mod"))
    async def close(self, ctx):
        if isinstance(ctx.channel, discord.DMChannel):
            return
        if ctx.channel.id in self.active_channels_dict.values():
            self.client.sent_users.delete_one(
                {'_id': self.get_key(ctx.channel.id)})
            user = discord.utils.get(self.guild.members,
                                     id=self.get_key(ctx.channel.id))
            try:
                del self.active_channels_dict[user.id]
            except KeyError:
                pass
            await user.send('Your thread has been closed.')
            await ctx.channel.send(
                'Thread marked as closed. Channel will be deleted in 5 minutes.'
            )
            await self.log_channel.send(
                content=ctx.channel.mention,
                embed=discord.Embed(
                    title='Thread closed!',
                    description=
                    f'Thread {ctx.channel.mention} has been marked as closed by {ctx.author.mention}',
                    color=discord.Color.orange()))
            await asyncio.sleep(300.0)
            check = discord.utils.get(self.guild.channels, id=ctx.channel.id)
            if check is not None:
                await ctx.channel.delete()
                await self.log_channel.send(embed=discord.Embed(
                    title='Ticket deleted.',
                    description=
                    f"{user.name}({user.mention})'s ticket has been deleted.",
                    color=discord.Color.red()))

    @commands.command()
    @commands.is_owner()
    async def delete(self, ctx, user_id):
        try:
            del self.active_channels_dict[user_id]
            self.client.sent_users.delete_one({"_id": user_id})
            await ctx.send("Deleted.")
        except KeyError:
            await ctx.send(f"{user_id} not found in local database.")

    @commands.command()
    @commands.has_permissions(administrator=True)
    async def list(self, ctx):
        text = ''
        for key, val in self.active_channels_dict.items():
            text += f"<@{key}> => <#{val}>\n"
        await ctx.send(text)

    def get_key(self, value):
        for key, val in self.active_channels_dict.items():
            if val == value:
                return key
        return None

    @commands.command(aliases=['bl', 'mban'])
    @commands.check_any(commands.has_permissions(administrator=True),
                        commands.has_role('Moderator'))
    async def blacklist(self, ctx, user: discord.Member, reason):
        self.ban_dict[user.id] = dict(
            reason=reason, mod=f'{ctx.author.name}#{ctx.author.discriminator}')
        post = {
            '_id': user.id,
            'reason': reason,
            'mod': f'{ctx.author.name}#{ctx.author.discriminator}'
        }
        self.client.blacklisted_users.insert_one(post)
        await ctx.send(
            discord.Embed(title=f'Banned {user.name}#{user.discriminator}',
                          description=f"**Reason**: {reason}",
                          color=discord.Color.red(),
                          timestamp=datetime.now(self.IST)).set_footer(
                              text=f"Mod - {ctx.author.name}"))

    @commands.command()
    @commands.check_any(commands.has_permissions(administrator=True),
                        commands.has_role('Moderator'))
    async def banlist(self, ctx):
        embed = discord.Embed(title="Banned users list!",
                              description='',
                              colour=ctx.author.color)
        for x, y in self.ban_dict.items():
            embed.description += f"<@{x}>\n**Reason**: {y['reason']}\nMod: {y['mod']}\n-----------------------------------------"
        await ctx.send(embed=embed)
Ejemplo n.º 26
0
class Misc(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.Cog.listener()
    async def on_message(self, message):
        if message.content.lower() == '!role furaime':
            await message.add_reaction('👀')
        if discord.utils.get(message.role_mentions, id=524738280630124574):
            if random.choice([True, False]):
                await asyncio.sleep((random.random() * 30) + 30)
                await message.channel.send(f'@{message.author.mention}')

    @commands.command(aliases=['joineddate'])
    @commands.check_any(
        commands.has_any_role(523276397679083520, 307883683526868992),
        commands.has_permissions(administrator=True),
        commands.has_permissions(manage_guild=True))
    async def memberinfo(self, ctx, member: discord.Member = None):
        if member is None:
            member = ctx.author
        embed = discord.Embed(
            title=f"Member info for {member.name}#{member.discriminator}",
            color=member.color)
        embed.add_field(name='Created at',
                        value=member.created_at,
                        inline=False)
        embed.add_field(name='Joined at', value=member.joined_at, inline=False)
        embed.add_field(name="Discord ID", value=member.id, inline=False)
        embed.set_thumbnail(url=member.avatar_url)
        await ctx.send(embed=embed)

    @commands.command()
    @commands.is_owner()
    async def throwerror(self, ctx):
        raise Exception('omg')

    @commands.command()
    async def prng(self, ctx):
        await ctx.send(
            "PRNG is RNG!  It is random!  Humans tend to identify patterns where they do not exist.\n\nIf you're a Linux nerd check this out: https://www.2uo.de/myths-about-urandom/"
        )

    @commands.command(hidden=True)
    async def pedestalgoal(self, ctx):
        await ctx.send(
            "> If it takes 2 hours its because GT is required, which really isn't a thing anymore in pedestal goal games\n-Synack"
        )

    @commands.command(
        aliases=['crc32'],
        brief="Posts instructions on how to verify your ROM is correct.",
        help=
        "Posts instructions on how to verify your ROM is correct, or how to get the permalink to your randomized game."
    )
    async def rom(self, ctx):
        await ctx.send(
            "If you need help verifying your legally-dumped Japanese version 1.0 A Link to the Past Game file needed to run ALttPR, use this tool: <http://alttp.mymm1.com/game/checkcrc/>\n"
            "It can also help get the permalink page URL which has access to the Spoiler Log depending on the settings that were chosen. Not all games that are generated have access to the Spoiler Log.\n\n"
            "For legal reasons, we cannot provide help with finding this ROM online.  Please do not ask here for assistance with this.\n"
            "See <#543572578787393556> for details.")

    @commands.command(hidden=True)
    async def trpegs(self, ctx):
        await ctx.send(discord.utils.get(ctx.bot.emojis, name='RIPLink'))

    @commands.command(
        brief="Retrieves a holy image.",
        help="Retrieves a holy image from http://alttp.mymm1.com/holyimage/",
        aliases=['holy'])
    async def holyimage(self, ctx, slug=None, game='z3r'):
        holyimage = await holy(slug=slug, game=game)

        embed = discord.Embed(
            title=holyimage.image.get('title'),
            description=html2markdown.convert(holyimage.image['desc'])
            if 'desc' in holyimage.image else None,
            color=discord.Colour.from_rgb(0xFF, 0xAF, 0x00))

        if 'url' in holyimage.image:
            url = urljoin('http://alttp.mymm1.com/holyimage/',
                          holyimage.image['url'])
            if holyimage.image.get('mode', '') == 'redirect':
                embed.add_field(name='Link', value=url, inline=False)
            else:
                embed.set_thumbnail(url=url)

        embed.add_field(name="Source", value=holyimage.link)

        if 'credit' in holyimage.image:
            embed.set_footer(text=f"Created by {holyimage.image['credit']}")

        await ctx.send(embed=embed)
Ejemplo n.º 27
0
 async def cog_check(self, ctx):
     '''Allow only moderators to invoke these commands'''
     return commands.has_any_role(*check_author())
Ejemplo n.º 28
0
def is_community_manager():
    return commands.has_any_role(*constants.COMMUNITY_MANAGER_ROLES)
Ejemplo n.º 29
0
class Topics(commands.Cog):
    """Get topics for discussion."""

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

        self.messages = None

    async def gen_topic(self):
        topic = await self.bot.db.get_random_topic()

        embed = Embed(
            description=topic["topic"],
            colour=0x87CEEB,
            timestamp=topic["created_at"],
        )

        user = self.bot.get_user(topic["author_id"])

        embed.set_footer(
            text=f"From: {user if user else 'unknown'} • ID: {topic['id']} • Created:"
        )

        return embed

    @commands.command(name="topic")
    @commands.cooldown(rate=1, per=60, type=commands.BucketType.channel)
    @in_channel(264417177094848512, 737760236013748295, 779479420481175554)
    async def get_topic(self, ctx: Context):
        """Get a topic to talk about."""

        embed = await self.gen_topic()

        msg = await ctx.reply(embed=embed)

        await msg.add_reaction("🔁")

        self.message = TopicMessage(msg)

    @commands.command(name="newtopic")
    @commands.cooldown(rate=1, per=600, type=commands.BucketType.member)
    @commands.check_any(commands.is_owner(), commands.has_any_role(339445127917338635, 337442104026595329))
    @in_channel(264417177094848512, 737760236013748295)
    async def new_topic(self, ctx: Context, *, topic: str):
        """Create a new topic."""

        if len(topic) > 200:
            return await ctx.reply("Topics must be 200 characters or less.")

        topic = await self.bot.db.create_topic(ctx.author.id, topic)

        await ctx.reply(f"Topic created! ID: {topic['id']}")

    @commands.command(name="importtopics")
    @commands.check_any(commands.is_owner(), commands.has_role(337442104026595329))
    async def import_topics(self, ctx: Context):
        """Import topics from a text file."""

        if not ctx.message.attachments:
            return await ctx.reply("You must attach a file for this.")

        async with ctx.typing():
            file = await self.bot.sess.get(ctx.message.attachments[0].url)
            file = await file.text()

            ids = []

            for line in file.split("\n"):
                if line:
                    topic = await self.bot.db.create_topic(ctx.author.id, line)
                    ids.append(topic['id'])

            await ctx.reply(f"Successfully inserted {len(ids)} topics")

    @commands.command(name="deltopic")
    @commands.check_any(commands.is_owner(), commands.has_role(337442104026595329))
    async def del_topic(self, ctx: Context, id: int):
        """Delete a topic."""

        await self.bot.db.delete_topic(id)

        await ctx.message.add_reaction("👌")

    @commands.command(name="topicinfo")
    @commands.check_any(commands.is_owner(), commands.has_role(337442104026595329))
    async def topic_info(self, ctx: Context, id: int):
        """Get information about a topic."""

        topic = await self.bot.db.get_topic_by_id(id)

        if not topic:
            return await ctx.reply("Not a valid topic.")

        await ctx.reply(f"ID: {topic['id']}\nCreated by: {ctx.guild.get_member(topic['author_id'])} ({topic['author_id']})\nData:```\n{topic['topic']}```")

    @commands.command(name="lstopics")
    @commands.check_any(commands.is_owner(), commands.has_role(337442104026595329))
    async def list_topics(self, ctx: Context):
        """List all topics."""

        topics = await self.bot.db.get_topics()

        data = "\n".join([f"{str(topic['id']).zfill(4)}: {topic['topic']}" for topic in topics])

        await ctx.reply(f"There are a total of {len(topics)} topics:", file=File(StringIO(data), filename="topics.txt"))

    @commands.Cog.listener()
    async def on_reaction_add(self, reaction: Reaction, member: Member):
        """Allows for refreshing the topic."""

        if not isinstance(member, Member):
            return

        if member == self.bot.user:
            return

        if not self.message:
            return

        if self.message.msg.id != reaction.message.id:
            return

        if self.message.time + 30 < time():
            return

        self.message.users.add(member.id)

        if len(self.message.users) >= 4:
            await self.message.msg.edit(embed=await self.gen_topic())
            self.message = None
Ejemplo n.º 30
0
def is_moderator():
    return commands.has_any_role(*constants.MODERATOR_ROLES)