From 4f1f49d96f8b381996c2ffef3cd856cde70d7105 Mon Sep 17 00:00:00 2001 From: Michael H Date: Mon, 2 Sep 2019 09:38:19 -0400 Subject: [PATCH] [Modlog] userinfo stops breaking with high numbers of roles on a user (#2971) * Fixes it, I guess * changelog * reluctant handling of what the people want here * mypy would have prevented this one --- changelog.d/mod/2910.bugfix.rst | 1 + redbot/cogs/mod/names.py | 39 +++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 changelog.d/mod/2910.bugfix.rst diff --git a/changelog.d/mod/2910.bugfix.rst b/changelog.d/mod/2910.bugfix.rst new file mode 100644 index 000000000..b27f55dcf --- /dev/null +++ b/changelog.d/mod/2910.bugfix.rst @@ -0,0 +1 @@ +userinfo doesn't break with absurd numbers of roles. \ No newline at end of file diff --git a/redbot/cogs/mod/names.py b/redbot/cogs/mod/names.py index 6c44bab1b..2b82f46b8 100644 --- a/redbot/cogs/mod/names.py +++ b/redbot/cogs/mod/names.py @@ -125,15 +125,46 @@ class ModInfo(MixinMeta): activity = _("Watching {}").format(user.activity.name) if roles: - roles = ", ".join([x.mention for x in roles]) + + role_str = ", ".join([x.mention for x in roles]) + # 400 BAD REQUEST (error code: 50035): Invalid Form Body + # In embed.fields.2.value: Must be 1024 or fewer in length. + if len(role_str) > 1024: + # Alternative string building time. + # This is not the most optimal, but if you're hitting this, you are losing more time + # to every single check running on users than the occasional user info invoke + # We don't start by building this way, since the number of times we hit this should be + # infintesimally small compared to when we don't across all uses of Red. + continuation_string = _( + "and {numeric_number} more roles not displayed due to embed limits." + ) + available_length = 1024 - len(continuation_string) # do not attempt to tweak, i18n + + role_chunks = [] + remaining_roles = 0 + + for r in roles: + chunk = f"{r.mention}, " + chunk_size = len(chunk) + + if chunk_size < available_length: + available_length -= chunk_size + role_chunks.append(chunk) + else: + remaining_roles += 1 + + role_chunks.append(continuation_string.format(numeric_number=remaining_roles)) + + role_str = "".join(role_chunks) + else: - roles = None + role_str = None data = discord.Embed(description=activity, colour=user.colour) data.add_field(name=_("Joined Discord on"), value=created_on) data.add_field(name=_("Joined this server on"), value=joined_on) - if roles is not None: - data.add_field(name=_("Roles"), value=roles, inline=False) + if role_str is not None: + data.add_field(name=_("Roles"), value=role_str, inline=False) if names: # May need sanitizing later, but mentions do not ping in embeds currently val = filter_invites(", ".join(names))