コード例 #1
0
ファイル: Bugs.py プロジェクト: e-a-h/That-Sky-Bot
 async def channels(self, ctx):
     # TODO: allow guild admins to use this, restricted to single guild
     embed = Embed(
         timestamp=ctx.message.created_at,
         color=0x50f3d7,
         title='Bug Reporting Channels')
     guild_row = Guild.get_or_none(serverid=ctx.guild.id)
     guild_channels = []
     non_guild_channels = dict()
     for row in BugReportingPlatform.select():
         for channel_row in row.bug_channels:
             channel = self.bot.get_channel(channel_row.channelid)
             if not channel:
                 channel_row.delete_instance()
                 continue
             description = f"{row.platform}/{row.branch}: {channel.mention}"
             if channel_row.guild == guild_row:
                 guild_channels.append(description)
             else:
                 # TODO: get guild names and add to description
                 if channel_row.guild.serverid not in non_guild_channels:
                     non_guild_channels[channel_row.guild.serverid] = []
                 non_guild_channels[channel_row.guild.serverid].append(description)
     if guild_channels:
         embed.add_field(name=f'`{ctx.guild.name}` server', value="\n".join(guild_channels))
     for guild_id, channel_list in non_guild_channels.items():
         guild = self.bot.get_guild(guild_id)
         server_name = self.bot.get_guild(guild_id).name or f"[{guild_id}][MISSING GUILD]"
         embed.add_field(name=f'`{server_name}` server', value="\n".join(channel_list))
     if not guild_channels and not non_guild_channels:
         await ctx.send("There are no configured bug reporting channels")
     else:
         await ctx.send(embed=embed)
コード例 #2
0
ファイル: Bugs.py プロジェクト: e-a-h/That-Sky-Bot
            async def send_report():
                # save report in the database
                br = BugReport.create(reporter=user.id, platform=platform, deviceinfo=deviceinfo,
                                      platform_version=platform_version, branch=branch, app_version=app_version,
                                      app_build=app_build, title=title, steps=steps, expected=expected, actual=actual,
                                      additional=additional_text)
                for url in attachment_links:
                    Attachments.create(report=br, url=url)

                # send report
                channel_name = f"{platform}_{branch}".lower()

                report_id_saved = False
                attachment_id_saved = False
                user_reported_channels = list()
                all_reported_channels = list()
                selected_platform = BugReportingPlatform.get(platform=platform, branch=branch)

                for row in BugReportingChannel.select().where(BugReportingChannel.platform == selected_platform):
                    report_channel = self.bot.get_channel(row.channelid)
                    message = await report_channel.send(
                        content=Lang.get_locale_string("bugs/report_header", ctx, id=br.id, user=user.mention),
                        embed=report)
                    attachment = None
                    if len(attachment_links) != 0:
                        key = "attachment_info" if len(attachment_links) == 1 else "attachment_info_plural"
                        attachment = await report_channel.send(
                            Lang.get_locale_string(f"bugs/{key}", ctx, id=br.id, links="\n".join(attachment_links)))

                    if report_channel.guild.id == Configuration.get_var('guild_id'):
                        # Only save report and attachment IDs for posts in the official server
                        if not report_id_saved and not attachment_id_saved:
                            if attachment is not None:
                                br.attachment_message_id = attachment.id
                                attachment_id_saved = True
                            br.message_id = message.id
                            report_id_saved = True
                            br.save()
                            user_reported_channels.append(report_channel.mention)
                    else:
                        # guild is not the official server. if author is member, include user_reported_channels
                        this_guild = self.bot.get_guild(report_channel.guild.id)
                        if this_guild.get_member(user.id) is not None:
                            user_reported_channels.append(report_channel.mention)

                    all_reported_channels.append(report_channel)

                channels_mentions = []
                channels_ids = set()
                if not all_reported_channels:
                    await Logging.bot_log(f"no report channels for bug report #{br.id}")

                for report_channel in all_reported_channels:
                    channels_mentions.append(report_channel.mention)
                    channels_ids.add(report_channel.id)
                await channel.send(
                    Lang.get_locale_string("bugs/report_confirmation", ctx, channel_info=', '.join(channels_mentions)))
                await self.send_bug_info(*channels_ids)
コード例 #3
0
ファイル: Reporting.py プロジェクト: e-a-h/That-Sky-Bot
        def get_platform(pl):
            platforms = dict()

            for row in BugReportingPlatform.select():
                platforms[row.platform.lower()] = row.platform

            pl = pl.lower()
            if pl in platforms:
                return [platforms[pl]]
            return ["Android", "iOS", "Switch"]
コード例 #4
0
ファイル: Reporting.py プロジェクト: e-a-h/That-Sky-Bot
        def get_branch(br):
            platforms = dict()
            branches = set()

            for row in BugReportingPlatform.select():
                branches.add(row.branch)
                if row.branch not in platforms:
                    platforms[row.branch] = set()
                platforms[row.branch].add(row.platform)

            br = br.lower().capitalize()
            if br in branches:
                return [br]
            return ["Beta", "Stable"]
コード例 #5
0
ファイル: Bugs.py プロジェクト: e-a-h/That-Sky-Bot
    async def add_channel(self, ctx, channel: TextChannel, platform, branch):
        try:
            guild_row = Guild.get(serverid=ctx.guild.id)
        except DoesNotExist:
            await ctx.send(f"I couldn't find a record for guild id {ctx.guild.id}... call a plumber!")
            return

        try:
            platform_row = BugReportingPlatform.get(platform=platform, branch=branch)
        except DoesNotExist:
            await ctx.send(f"I couldn't find a record for platform/branch `{platform}`/`{branch}`")
            return

        try:
            record, created = BugReportingChannel.get_or_create(guild=guild_row, platform=platform_row, channelid=channel.id)
        except IntegrityError:
            await ctx.send(f"channel{channel.mention} is already in used for bug reporting")
            return

        if created:
            await ctx.send(f"{channel.mention} will now be used to record `{platform}/{branch}` bug reports")
        else:
            await ctx.send(f"{channel.mention} was already configured for `{platform}/{branch}` bug reports")
コード例 #6
0
ファイル: Bugs.py プロジェクト: e-a-h/That-Sky-Bot
    async def platforms(self, ctx):
        platforms = dict()

        for row in BugReportingPlatform.select():
            if row.branch in platforms:
                if row.platform in platforms[row.branch]:
                    await self.bot.guild_log(ctx.guild.id, f"duplicate platform in db: {row.platform}/{row.branch}")
            if row.branch not in platforms:
                platforms[row.branch] = list()
            platforms[row.branch].append(row.platform)

        embed = Embed(
            timestamp=ctx.message.created_at,
            color=0x50f3d7,
            title='Bug Reporting Platforms')

        for branch, platforms in platforms.items():
            embed.add_field(name=branch, value='\n'.join(platforms), inline=False)

        if not platforms:
            await ctx.send("There are no bug reporting platforms in my database")
        else:
            await ctx.send(embed=embed)
コード例 #7
0
ファイル: Bugs.py プロジェクト: e-a-h/That-Sky-Bot
    async def actual_bug_reporter(self, user, trigger_channel):
        # wrap everything so users can't get stuck in limbo
        m = self.bot.metrics
        active_question = None
        restarting = False
        try:
            channel = await user.create_dm()
            last_message = await trigger_channel.history(limit=1).flatten()
            last_message = last_message[0]
            ctx = await self.bot.get_context(last_message)

            # vars to store everything
            asking = True
            platform = ""
            branch = ""
            app_build = None
            additional = False
            additional_text = ""
            attachments = False
            attachment_links = []
            report = None

            # define all the parts we need as inner functions for easier sinfulness

            async def abort():
                nonlocal asking
                await user.send(Lang.get_locale_string("bugs/abort_report", ctx))
                asking = False
                m.reports_abort_count.inc()
                m.reports_exit_question.observe(active_question)
                await self.delete_progress(user.id)

            def set_platform(p):
                nonlocal platform
                platform = p

            def set_branch(b):
                nonlocal branch
                branch = b

            def add_additional():
                nonlocal additional
                additional = True

            def add_attachments():
                nonlocal attachments
                attachments = True

            def verify_version(v):
                if "latest" in v:
                    return Lang.get_locale_string("bugs/latest_not_allowed", ctx)
                # TODO: double check if we actually want to enforce this
                if len(Utils.NUMBER_MATCHER.findall(v)) == 0:
                    return Lang.get_locale_string("bugs/no_numbers", ctx)
                if len(v) > 20:
                    return Lang.get_locale_string("bugs/love_letter", ctx)
                return True

            def max_length(length):
                def real_check(text):
                    if len(text) > length:
                        return Lang.get_locale_string("bugs/text_too_long", ctx, max=length)
                    return True

                return real_check

            async def send_report():
                # save report in the database
                br = BugReport.create(reporter=user.id, platform=platform, deviceinfo=deviceinfo,
                                      platform_version=platform_version, branch=branch, app_version=app_version,
                                      app_build=app_build, title=title, steps=steps, expected=expected, actual=actual,
                                      additional=additional_text)
                for url in attachment_links:
                    Attachments.create(report=br, url=url)

                # send report
                channel_name = f"{platform}_{branch}".lower()

                report_id_saved = False
                attachment_id_saved = False
                user_reported_channels = list()
                all_reported_channels = list()
                selected_platform = BugReportingPlatform.get(platform=platform, branch=branch)

                for row in BugReportingChannel.select().where(BugReportingChannel.platform == selected_platform):
                    report_channel = self.bot.get_channel(row.channelid)
                    message = await report_channel.send(
                        content=Lang.get_locale_string("bugs/report_header", ctx, id=br.id, user=user.mention),
                        embed=report)
                    attachment = None
                    if len(attachment_links) != 0:
                        key = "attachment_info" if len(attachment_links) == 1 else "attachment_info_plural"
                        attachment = await report_channel.send(
                            Lang.get_locale_string(f"bugs/{key}", ctx, id=br.id, links="\n".join(attachment_links)))

                    if report_channel.guild.id == Configuration.get_var('guild_id'):
                        # Only save report and attachment IDs for posts in the official server
                        if not report_id_saved and not attachment_id_saved:
                            if attachment is not None:
                                br.attachment_message_id = attachment.id
                                attachment_id_saved = True
                            br.message_id = message.id
                            report_id_saved = True
                            br.save()
                            user_reported_channels.append(report_channel.mention)
                    else:
                        # guild is not the official server. if author is member, include user_reported_channels
                        this_guild = self.bot.get_guild(report_channel.guild.id)
                        if this_guild.get_member(user.id) is not None:
                            user_reported_channels.append(report_channel.mention)

                    all_reported_channels.append(report_channel)

                channels_mentions = []
                channels_ids = set()
                if not all_reported_channels:
                    await Logging.bot_log(f"no report channels for bug report #{br.id}")

                for report_channel in all_reported_channels:
                    channels_mentions.append(report_channel.mention)
                    channels_ids.add(report_channel.id)
                await channel.send(
                    Lang.get_locale_string("bugs/report_confirmation", ctx, channel_info=', '.join(channels_mentions)))
                await self.send_bug_info(*channels_ids)

            async def restart():
                nonlocal restarting
                restarting = True
                m.reports_restarted.inc()
                await self.delete_progress(user.id)
                self.bot.loop.create_task(self.report_bug(user, trigger_channel))

            # start global report timer and question timer
            report_start_time = question_start_time = time.time()
            m.reports_started.inc()

            def update_metrics():
                nonlocal active_question
                nonlocal question_start_time

                now = time.time()
                question_duration = now - question_start_time
                question_start_time = now

                # Record the time taken to answer the previous question
                gauge = getattr(m, f"reports_question_{active_question}_duration")
                gauge.set(question_duration)

                active_question = active_question + 1

            active_question = 0
            await Questions.ask(self.bot, channel, user, Lang.get_locale_string("bugs/question_ready", ctx),
                                [
                                    Questions.Option("YES", "Press this reaction to answer YES and begin a report"),
                                    Questions.Option("NO", "Press this reaction to answer NO", handler=abort),
                                ], show_embed=True, locale=ctx)
            update_metrics()

            if asking:
                # question 1: android or ios?
                platforms = set()
                options = []
                for platform_row in BugReportingPlatform.select():
                    platforms.add(platform_row.platform)
                for platform_name in platforms:
                    options.append(
                        Questions.Option(
                            platform_name.upper(),
                            platform_name,
                            set_platform,
                            [platform_name]))

                await Questions.ask(self.bot, channel, user, Lang.get_locale_string("bugs/question_platform", ctx),
                                    options, show_embed=True, locale=ctx)
                update_metrics()

                # question 2: android/ios version
                platform_version = await Questions.ask_text(self.bot, channel, user,
                                                            Lang.get_locale_string("bugs/question_platform_version",
                                                                                   ctx,
                                                                                   platform=platform),
                                                            validator=verify_version, locale=ctx)
                update_metrics()

                # question 3: hardware info
                device_info_platform = Lang.get_locale_string(f"bugs/device_info_{platform.lower()}", ctx)
                deviceinfo = await Questions.ask_text(self.bot, channel, user,
                                                      Lang.get_locale_string("bugs/question_device_info",
                                                                             ctx, platform=platform,
                                                                             device_info_help=device_info_platform,
                                                                             max=200),
                                                      validator=max_length(200), locale=ctx)
                update_metrics()

                # question 4: stable or beta?
                branches = set()
                for platform_row in BugReportingPlatform.select():
                    if platform_row.platform == platform:
                        branches.add(platform_row.branch)
                if len(branches) == 0:
                    branch = "NONE"
                elif len(branches) == 1:
                    branch = branches.pop()
                else:
                    options = []
                    for branch_name in branches:
                        branch_display_name = "Live" if branch_name.lower() == 'stable' else branch_name
                        options.append(
                            Questions.Option(
                                branch_name.upper(),
                                branch_display_name,
                                set_branch,
                                [branch_name]))
                    await Questions.ask(self.bot, channel, user, Lang.get_locale_string("bugs/question_app_branch", ctx),
                                        options, show_embed=True, locale=ctx)
                update_metrics()

                # question 5: sky app version
                app_version = await Questions.ask_text(
                    self.bot,
                    channel,
                    user,
                    Lang.get_locale_string(
                        "bugs/question_app_version", ctx,
                        version_help=Lang.get_locale_string("bugs/version_" + platform.lower())),
                    validator=verify_version, locale=ctx)
                update_metrics()

                # question 6: sky app build number
                app_build = await Questions.ask_text(
                    self.bot, channel, user, Lang.get_locale_string("bugs/question_app_build", ctx),
                    validator=verify_version, locale=ctx)
                update_metrics()

                # question 7: Title
                title = await Questions.ask_text(
                    self.bot, channel, user, Lang.get_locale_string("bugs/question_title", ctx, max=300),
                    validator=max_length(300), locale=ctx)
                update_metrics()

                # question 8: "actual" - defect behavior
                actual = await Questions.ask_text(
                    self.bot, channel, user, Lang.get_locale_string("bugs/question_actual", ctx, max=800),
                    validator=max_length(800), locale=ctx)
                update_metrics()

                # question 9: steps to reproduce
                steps = await Questions.ask_text(
                    self.bot, channel, user, Lang.get_locale_string("bugs/question_steps", ctx, max=800),
                    validator=max_length(800), locale=ctx)
                update_metrics()

                # question 10: expected behavior
                expected = await Questions.ask_text(
                    self.bot, channel, user,
                    Lang.get_locale_string("bugs/question_expected", ctx, max=800),
                    validator=max_length(800), locale=ctx)
                update_metrics()

                # question 11: attachments y/n
                await Questions.ask(
                    self.bot, channel, user, Lang.get_locale_string("bugs/question_attachments", ctx),
                    [
                        Questions.Option("YES",
                                         Lang.get_locale_string("bugs/attachments_yes", ctx),
                                         handler=add_attachments),
                        Questions.Option("NO", Lang.get_locale_string("bugs/skip_step", ctx))
                    ], show_embed=True, locale=ctx)
                update_metrics()

                if attachments:
                    # question 12: attachments
                    attachment_links = await Questions.ask_attachements(self.bot, channel, user, locale=ctx)
                # update metrics outside condition to keep count up-to-date and reflect skipped question as zero time
                update_metrics()

                # question 13: additional info y/n
                await Questions.ask(
                    self.bot, channel, user, Lang.get_locale_string("bugs/question_additional", ctx),
                    [
                        Questions.Option("YES",
                                         Lang.get_locale_string("bugs/additional_info_yes", ctx),
                                         handler=add_additional),
                        Questions.Option("NO", Lang.get_locale_string("bugs/skip_step", ctx))
                    ], show_embed=True, locale=ctx)
                update_metrics()

                if additional:
                    # question 14: additional info
                    additional_text = await Questions.ask_text(
                        self.bot, channel, user,
                        Lang.get_locale_string("bugs/question_additional_info", ctx),
                        validator=max_length(500), locale=ctx)
                # update metrics outside condition to keep count up-to-date and reflect skipped question as zero time
                update_metrics()

                # assemble the report and show to user for review
                report = Embed(timestamp=datetime.utcfromtimestamp(time.time()))
                report.set_author(name=f"{user} ({user.id})", icon_url=user.avatar_url_as(size=32))
                report.add_field(
                    name=Lang.get_locale_string("bugs/platform", ctx), value=f"{platform} {platform_version}")
                report.add_field(
                    name=Lang.get_locale_string("bugs/app_version", ctx), value=app_version)
                report.add_field(
                    name=Lang.get_locale_string("bugs/app_build", ctx), value=app_build)
                report.add_field(
                    name=Lang.get_locale_string("bugs/device_info", ctx), value=deviceinfo, inline=False)
                report.add_field(
                    name=Lang.get_locale_string("bugs/title", ctx), value=title, inline=False)
                report.add_field(
                    name=Lang.get_locale_string("bugs/description", ctx), value=actual, inline=False)
                report.add_field(
                    name=Lang.get_locale_string("bugs/steps_to_reproduce", ctx), value=steps, inline=False)
                report.add_field(
                    name=Lang.get_locale_string("bugs/expected", ctx), value=expected)
                if additional:
                    report.add_field(
                        name=Lang.get_locale_string("bugs/additional_info", ctx), value=additional_text, inline=False)

                await channel.send(
                    content=Lang.get_locale_string("bugs/report_header", ctx, id="##", user=user.mention), embed=report)
                if attachment_links:
                    attachment_message = ''
                    for a in attachment_links:
                        attachment_message += f"{a}\n"
                    await channel.send(attachment_message)

                review_time = 300
                await asyncio.sleep(1)

                # Question 15 - final review
                await Questions.ask(
                    self.bot, channel, user,
                    Lang.get_locale_string("bugs/question_ok", ctx, timeout=Questions.timeout_format(review_time)),
                    [
                        Questions.Option("YES", Lang.get_locale_string("bugs/send_report", ctx), send_report),
                        Questions.Option("NO", Lang.get_locale_string("bugs/mistake", ctx), restart)
                    ], show_embed=True, timeout=review_time, locale=ctx)
                update_metrics()
                report_duration = time.time() - report_start_time
                m.reports_duration.set(report_duration)
            else:
                return

        except Forbidden as ex:
            m.bot_cannot_dm_member.inc()
            await trigger_channel.send(
                Lang.get_locale_string("bugs/dm_unable", ctx, user=user.mention),
                delete_after=30)
        except asyncio.TimeoutError as ex:
            m.report_incomplete_count.inc()
            await channel.send(Lang.get_locale_string("bugs/report_timeout", ctx))
            if active_question is not None:
                m.reports_exit_question.observe(active_question)
        except CancelledError as ex:
            m.report_incomplete_count.inc()
            if active_question is not None:
                m.reports_exit_question.observe(active_question)
            if not restarting:
                raise ex
        except Exception as ex:
            await Utils.handle_exception("bug reporting", self.bot, ex)
            raise ex
        finally:
            self.bot.loop.create_task(self.delete_progress(user.id))
コード例 #8
0
ファイル: Bugs.py プロジェクト: e-a-h/That-Sky-Bot
 async def add_platform(self, ctx, platform, branch):
     row, create = BugReportingPlatform.get_or_create(platform=platform, branch=branch)
     if create:
         await ctx.send(f"Ok, I added `{platform}/{branch}` to my database")
     else:
         await ctx.send(f"That platform/branch combination is already in my database")