Beispiel #1
0
    async def lock(self, ctx: commands.Context, report_id: int):
        """Locks a report.
        
        This command only works from inside of the queue channel and does not support already approved/denied reports."""

        if ctx.guild.me.guild_permissions.manage_messages:
            await ctx.message.delete()

        if ctx.channel.id != self.bot.config["channels"]["approval"]:
            return await ctx.failure(
                "This command can only be used in the approval queue.",
                delete_after=15)

        if not ctx.can_use("CAN_UNLOCK"):
            return await ctx.failure("You're not allowed to lock reports.",
                                     delete_after=15)

        report = await Report.from_db(self.bot, report_id)
        if report is None:
            return await ctx.failure("No report was found with your query.",
                                     delete_after=15)

        if report.locked:
            return await ctx.failure("This report is already locked.",
                                     delete_after=15)

        if report.stance != 0:
            return await ctx.failure("This report has already been moved.",
                                     delete_after=15)

        async with self.bot.postgres.acquire() as con:
            query = """UPDATE bug_reports
                       SET locked = $1
                       WHERE id = $2;"""

            await con.execute(query, True, report.id)

        if await report.approval_message is None:
            return await ctx.failure(
                "The approval queue message no longer exists, please contact an Administrator.",
                delete_after=15)

        if report.reporter is None:
            return await ctx.failure(
                "The user that made this report no longer exists, please contact an Administrator.",
                delete_after=15)

        if report.board is None:
            return await ctx.failure(
                "The board for this report no longer exists, please contact an Administrator.",
                delete_after=15)

        report.locked = True

        msg = await report.approval_message
        await msg.edit(content=f"From: {report.board.mention}",
                       embed=make_embed(self.bot, report))

        await ctx.success(f"You have locked report **#{report_id}**.",
                          delete_after=15)
Beispiel #2
0
    async def can_use(self,
                      ctx: commands.Context) -> bool:
        """Injects a function used to determine whether or not a user can run the specified command.
        
        Each command must have a required_perm parameter that matches one of the possible configs."""

        def _(perm: str):
            roles = [r for r in self.bot.config["roles"].items() if perm in r[1]]
    
            for role, actions in roles:
                if role == "everyone" and perm in actions:
                    return True

                if role in (r.id for r in ctx.author.roles) and perm in actions:
                    return True

        ctx.can_use = _
        return True
Beispiel #3
0
    async def approve(self, ctx: commands.Context, report_id: int, *,
                      info: str):
        """Approves a report that is currently in the queue.
        
        This command only works from inside of the queue channel and does not support already approved/denied reports."""

        if ctx.guild.me.guild_permissions.manage_messages:
            await ctx.message.delete()

        if ctx.channel.id != self.bot.config["channels"]["approval"]:
            return

        if not ctx.can_use("CAN_APPROVE"):
            return await ctx.failure("You're not allowed to approve reports.",
                                     delete_after=15)

        report = await Report.from_db(self.bot, report_id)
        if report is None:
            return await ctx.failure("No report was found with your query.",
                                     delete_after=15)

        if report.reporter == ctx.author:
            return await ctx.failure("You can't approve your own report.",
                                     delete_after=15)

        if report.locked:
            return await ctx.failure("This report has been locked by admins.",
                                     delete_after=15)

        if report.stance != 0:
            return await ctx.failure("This report has already been moved.",
                                     delete_after=15)

        stance = report.get_stance(ctx.author.id)

        if stance is not None:
            if stance.type == -1:
                report.denies.remove(stance)

            else:
                report.approves.remove(stance)

        report.approves.append(Stance(1, ctx.author, info))

        async with self.bot.postgres.acquire() as con:
            query = """UPDATE bug_reports
                       SET approves = $1,
                       denies = $2,
                       stance = $3
                       WHERE id = $4;"""

            await con.execute(
                query, str(report.approves), str(report.denies),
                1 if len(report.approves) >= self.bot.config["stances_needed"]
                else 0, report.id)

        if await report.approval_message is None:
            return await ctx.failure(
                "The approval queue message no longer exists, please contact an Administrator.",
                delete_after=15)

        if report.reporter is None:
            return await ctx.failure(
                "The user that made this report no longer exists, please contact an Administrator.",
                delete_after=15)

        if report.board is None:
            return await ctx.failure(
                "The board for this report no longer exists, please contact an Administrator.",
                delete_after=15)

        if len(report.approves) < self.bot.config["stances_needed"]:
            msg = await report.approval_message
            await msg.edit(content=f"From: {report.board.mention}",
                           embed=make_embed(self.bot, report))

        else:
            self.bot.dispatch("report_approve", ctx, report)

        if stance is not None:
            return await ctx.success(
                f"You have changed your stance on report **#{report_id}**.",
                delete_after=15)

        await ctx.success(f"You have approved report **#{report_id}**.",
                          delete_after=15)
Beispiel #4
0
    async def revoke(self, ctx: commands.Context, report_id: int):
        """Revokes your stance on a report that is currently in the queue.
        
        This command only works from inside of the queue channel and does not support already approved/denied reports."""

        if ctx.guild.me.guild_permissions.manage_messages:
            await ctx.message.delete()

        if ctx.channel.id != self.bot.config["channels"]["approval"]:
            return await ctx.failure(
                "This command can only be used in the approval queue.",
                delete_after=15)

        if not ctx.can_use("CAN_REVOKE"):
            return await ctx.failure(
                "You're not allowed to revoke your stance on reports.",
                delete_after=15)

        report = await Report.from_db(self.bot, report_id)
        if report is None:
            return await ctx.failure("No report was found with your query.",
                                     delete_after=15)

        if report.locked:
            return await ctx.failure("This report has been locked by admins.",
                                     delete_after=15)

        if report.stance != 0:
            return await ctx.failure("This report has already been moved.",
                                     delete_after=15)

        stance = report.get_stance(ctx.author)

        if stance is not None:
            if stance.type == 1:
                report.approves.remove(stance)

            else:
                report.denies.remove(stance)

        else:
            return await ctx.failure(
                "You haven't placed a stance on this report yet.",
                delete_after=15)

        async with self.bot.postgres.acquire() as con:
            query = """UPDATE bug_reports
                       SET approves = $1,
                       denies = $2
                       WHERE id = $3;"""

            await con.execute(query, str(report.approves), str(report.denies),
                              report.id)

        if await report.approval_message is None:
            return await ctx.failure(
                "The approval queue message no longer exists, please contact an Administrator.",
                delete_after=15)

        if report.reporter is None:
            return await ctx.failure(
                "The user that made this report no longer exists, please contact an Administrator.",
                delete_after=15)

        if report.board is None:
            return await ctx.failure(
                "The board for this report no longer exists, please contact an Administrator.",
                delete_after=15)

        msg = await report.approval_message
        await msg.edit(content=f"From: {report.board.mention}",
                       embed=make_embed(self.bot, report))

        await ctx.success(
            f"You have revoked your stance on report **#{report_id}**.",
            delete_after=15)
Beispiel #5
0
    async def submit(self, ctx: commands.Context, *, text: str):
        """Submits a bug report."""

        config = self.bot.config

        if ctx.guild.me.guild_permissions.manage_messages:
            await ctx.message.delete()

        if ctx.channel.id not in config["channels"]["boards"].keys():
            return await ctx.failure(
                "You must be in a bug board to use this command.",
                delete_after=15)

        if not ctx.can_use("CAN_REPORT"):
            return await ctx.failure("You're not allowed to submit reports.",
                                     delete_after=15)

        data = vars(parser.parse_args(text.split(" ")))

        # because of how we're parsing it in argparse, the values of each flag will be an iterable
        # of each word in the sentence, so we iterate through the dictionary and join the lists with " "
        # if the value is an iterable of some kind
        for k, v in data.items():
            if isinstance(v, (list, tuple)):
                data[k] = " ".join(v)

        if None in data.keys():
            return await ctx.failure(
                f"Your syntax seems incorrect! If you're having trouble, try using the tool over at: {config.tool}",
                delete_after=15)

        steps = data["steps"].split(" ~ ")

        queue = ctx.guild.get_channel(config["channels"]["approval"])
        if queue is None:
            return await ctx.failure(
                "The approval queue does not exist, please contact an Administrator.",
                delete_after=15)

        if not queue.permissions_for(ctx.guild.me).send_messages:
            return await ctx.failure(
                f"I'm missing permissions to send messages in {queue.mention}, please contact an Administrator.",
                delete_after=15)

        async with self.bot.postgres.acquire() as con:
            query = """INSERT INTO bug_reports (reporter_id, board_id, short_description, steps_to_reproduce, expected_result, actual_result, software_version, stance, created_at)
                       VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
                       
                       RETURNING id;"""

            id = await con.fetchval(query, ctx.author.id, ctx.channel.id,
                                    data["title"], str(steps),
                                    data["expected"], data["actual"],
                                    data["software"], 0, datetime.utcnow())

            message = await queue.send(f"From: {ctx.channel.mention}",
                                       embed=make_embed(
                                           self.bot,
                                           ctx.channel,
                                           id=id,
                                           reporter=ctx.author,
                                           short=data["title"],
                                           steps=steps,
                                           expected=data["expected"],
                                           actual=data["actual"],
                                           software=data["software"]))

            query = """UPDATE bug_reports
                       SET message_id = $1
                       WHERE id = $2;"""

            await con.execute(query, message.id, id)
Beispiel #6
0
    async def edit(self, ctx: commands.Context, report_id: int, section: str,
                   *, new_content: str):
        """Edits an existing bug report.
        
        This only works on reports currently in the approval queue."""

        if ctx.guild.me.guild_permissions.manage_messages:
            await ctx.message.delete()

        if not ctx.can_use("CAN_EDIT"):
            return await ctx.failure("You're not allowed to edit reports.",
                                     delete_after=15)

        report = await Report.from_db(self.bot, report_id)

        if report is None:
            return await ctx.failure("No report was found with your query.",
                                     delete_after=15)

        if report.reporter != ctx.author:
            return await ctx.failure("You did not make this report.",
                                     delete_after=15)

        if report.locked:
            return await ctx.failure("This report has been locked by admins.",
                                     delete_after=15)

        if report.stance != 0:
            return await ctx.failure("This report has already been moved.",
                                     delete_after=15)

        key = {
            "short": "short_description",
            "header": "short_description",
            "title": "short_description",
            "steps": "steps_to_reproduce",
            "str": "steps_to_reproduce",
            "body": "steps_to_reproduce",
            "expected": "expected_result",
            "actual": "actual_result",
            "software": "software_version",
            "sv": "software_version"
        }.get(section)

        if key is None:
            return await ctx.failure(
                "Check the section name you provided, it's incorrect.",
                delete_after=15)

        if key == "steps_to_reproduce":
            new_content = new_content.split(" ~ ")

        async with self.bot.postgres.acquire() as con:
            query = f"""UPDATE bug_reports
                        SET {key} = $1
                        WHERE id = $2;"""

            await con.execute(query, str(new_content), report_id)

        queue = ctx.guild.get_channel(self.bot.config["channels"]["approval"])
        if queue is None:
            return await ctx.failure(
                "The approval queue does not exist, please contact an Administrator.",
                delete_after=15)

        if not queue.permissions_for(ctx.guild.me).read_messages:
            return await ctx.failure(
                f"I'm missing permissions to read messages in {queue.mention}, please contact an Administrator.",
                delete_after=15)

        if await report.approval_message is None:
            return await ctx.failure(
                "The approval queue message no longer exists, please contact an Administrator.",
                delete_after=15)

        report.update(key, new_content)

        if report.board is None:
            return await ctx.failure(
                "The board for this report no longer exists, please contact an Administrator.",
                delete_after=15)

        msg = await report.approval_message
        await msg.edit(content=f"From: {report.board.mention}",
                       embed=make_embed(self.bot, report))

        await ctx.success(f"You've edited report **#{report_id}**.",
                          delete_after=15)