Exemplo n.º 1
0
    async def reasons(self, ctx: Context, karma: clean_content):
        karma_stripped = karma.lstrip("@")

        # Get the karma from the database
        karma_item = (db_session.query(KarmaModel).filter(
            func.lower(KarmaModel.name) == func.lower(karma_stripped)).first())

        if karma_item:
            # Set the karma item's name to be the same as in the database
            karma_stripped = karma_item.name
            # Get all of the changes that have some reason
            karma_changes = (db_session.query(KarmaChange).filter(
                KarmaChange.karma_id == karma_item.id,
                KarmaChange.reason is not None,
            ).all())
            # Flatten the reasons into a single list and sort it alphabetically
            reasons = sorted(
                (r for r in (change.reason
                             for change in karma_changes) if r is not None),
                key=str.casefold,
            )

            # If there's at least one reason
            if reasons:
                reasons_plural = pluralise(reasons, "reason")

                bullet_points = "\n".join(f" • {reason}\n"
                                          for reason in reasons)
                result = f'The {reasons_plural} for "{karma_stripped}" are as follows:\n\n{bullet_points}'
            else:
                result = f"There are no reasons down for that karma topic! :frowning:"

            file = None
            fp = None
            if len(result) > 2000:
                # Create a new temporary file that isn't deleted until we say
                with tempfile.NamedTemporaryFile(delete=False) as fp:
                    fp.write(result.encode("utf8"))

                # Wait for the file to close before accessing it (Windows NT limitation)
                file = File(fp.name, filename=f"{karma_stripped}.txt")
                result = f'There are too many reasons for "{karma_stripped}" to fit in a Discord message!'

            await ctx.send(result, file=file)

            # Delete temporary file (if any) after message is sent
            if fp:
                os.remove(fp.name)
        else:
            # The item hasn't been karma'd
            result = f"\"{karma_stripped}\" hasn't been karma'd yet. :cry:"
            await ctx.send(result)
Exemplo n.º 2
0
    async def reasons(self, ctx: Context, karma: clean_content):
        karma_stripped = karma.lstrip("@")

        # Get the karma from the database
        karma_item = (
            db_session.query(KarmaModel)
            .filter(func.lower(KarmaModel.name) == func.lower(karma_stripped))
            .first()
        )

        if karma_item:
            # Get all of the changes that have some reason
            karma_changes = (
                db_session.query(KarmaChange)
                .filter(
                    KarmaChange.karma_id == karma_item.id, KarmaChange.reasons != []
                )
                .all()
            )
            # Flatten the reasons into a single list and sort it alphabetically
            reasons = [
                reason
                for sublist in [change.reasons for change in karma_changes]
                for reason in sublist
            ]
            reasons = sorted(reasons, key=str.lower)

            # If there's at least one reason
            if reasons:
                # Handle the plurality of reason(s)
                plural = ""
                if len(reasons) > 1:
                    plural = "s"

                result = (
                    f'The reason{plural} for "{karma_stripped}" are as follows:\n\n'
                )
                for reason in reasons:
                    result += f" • {reason}\n"
            else:
                result = f"There are no reasons down for that karma topic! :frowning:"

            await ctx.send(result)
        else:
            # The item hasn't been karma'd
            result = f"\"{karma_stripped}\" hasn't been karma'd yet. :cry:"
            await ctx.send(result)
Exemplo n.º 3
0
    async def info(self, ctx: Context, karma: clean_content):
        await ctx.trigger_typing()
        t_start = current_milli_time()
        # Strip any leading @s and get the item from the DB
        karma_stripped = karma.lstrip("@")
        karma_item = (db_session.query(KarmaModel).filter(
            func.lower(KarmaModel.name) == func.lower(karma_stripped)).first())

        # If the item doesn't exist then raise an error
        if not karma_item:
            raise KarmaError(
                message=f"\"{karma_stripped}\" hasn't been karma'd yet. :cry:")

        # Get the changes and plot the graph
        filename, path = await plot_karma({karma_stripped: karma_item.changes})

        # Get the user with the most karma
        # I'd use a group_by sql statement here but it seems to not terminate
        all_changes = (db_session.query(KarmaChange).filter(
            KarmaChange.karma_id == karma_item.id).order_by(
                KarmaChange.created_at.asc()).all())
        user_changes = defaultdict(list)
        for change in all_changes:
            user_changes[change.user].append(change)

        most_karma = max(user_changes.items(), key=lambda item: len(item[1]))

        # Calculate the approval rating of the karma
        approval = 100 * ((karma_item.pluses - karma_item.minuses) /
                          (karma_item.pluses + karma_item.minuses))
        mins_per_karma = (all_changes[-1].local_time -
                          all_changes[0].local_time).total_seconds() / (
                              60 * len(all_changes))
        time_taken = (current_milli_time() - t_start) / 1000

        # Attach the file as an image for dev purposes
        if CONFIG.DEBUG:
            # Attach the file as an image for dev purposes
            plot_image = open(path, mode="rb")
            plot = File(plot_image)
            await ctx.send(
                f'Here\'s the karma trend for "{karma_stripped}" over time',
                file=plot)
        else:
            # Construct the embed
            generated_at = datetime.strftime(
                utc.localize(datetime.utcnow()).astimezone(
                    timezone("Europe/London")),
                "%H:%M %d %b %Y",
            )
            embed_colour = Color.from_rgb(61, 83, 255)
            embed_title = f'Statistics for "{karma_stripped}"'
            embed_description = f'"{karma_stripped}" has been karma\'d {len(all_changes)} {pluralise(all_changes, "time")} by {len(user_changes.keys())} {pluralise(user_changes.keys(), "user")}.'

            embed = Embed(title=embed_title,
                          description=embed_description,
                          color=embed_colour)
            embed.add_field(
                name="Most karma'd",
                value=
                f'"{karma_stripped}" has been karma\'d the most by <@{most_karma[0].user_uid}> with a total of {len(most_karma[1])} {pluralise(most_karma[1], "change")}.',
            )
            embed.add_field(
                name="Approval rating",
                value=
                f'The approval rating of "{karma_stripped}" is {approval:.1f}% ({karma_item.pluses} positive to {karma_item.minuses} negative karma and {karma_item.neutrals} neutral karma).',
            )
            embed.add_field(
                name="Karma timeline",
                value=
                f'"{karma_stripped}" was first karma\'d on {datetime.strftime(all_changes[0].local_time, "%d %b %Y at %H:%M")} and has been karma\'d approximately every {mins_per_karma:.1f} minutes.',
            )
            embed.set_footer(
                text=
                f"Statistics generated at {generated_at} in {time_taken:.3f} seconds."
            )
            embed.set_image(url="{host}/{filename}".format(
                host=CONFIG.FIG_HOST_URL, filename=filename))

            display_name = get_name_string(ctx.message)
            await ctx.send(f"Here you go, {display_name}! :page_facing_up:",
                           embed=embed)