fix: cap Action/Actor embed values before wrapping in backticks (no unbalanced markup)

_cap_field truncated the already-backtick-wrapped ('`{action}`') string past 1024 chars,
cutting off the closing backtick so an over-limit field rendered as an unbalanced inline-code
span. it now caps the inner value with reserve=2 (for the two backticks) and wraps after, so
the field stays <=1024 and the backticks are always balanced.

Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
2026-07-06 17:17:06 -04:00
parent 4db2a79e0a
commit 02c17c7e8b
+10 -7
View File
@@ -161,10 +161,12 @@ class DPYLogger:
return channel return channel
@staticmethod @staticmethod
def _cap_field(value: str) -> str: def _cap_field(value: str, reserve: int = 0) -> str:
"""cap an embed field value to discord's 1024-char limit, truncating with an ellipsis""" """cap a value to discord's 1024-char field limit (less `reserve` chars for any wrapping
if len(value) > DISCORD_FIELD_VALUE_LIMIT: the caller adds around it, e.g. backticks), truncating with an ellipsis"""
return value[:DISCORD_FIELD_VALUE_LIMIT - 3] + "..." limit = DISCORD_FIELD_VALUE_LIMIT - reserve
if len(value) > limit:
return value[:limit - 3] + "..."
return value return value
def build_embed(self, level, action, actor, details): def build_embed(self, level, action, actor, details):
@@ -178,11 +180,12 @@ class DPYLogger:
if self._embed_builder is not None: if self._embed_builder is not None:
return self._embed_builder(self, level, action, actor, details) return self._embed_builder(self, level, action, actor, details)
em = discord.Embed(color=self.colors[level]) em = discord.Embed(color=self.colors[level])
# discord 400s an empty or >1024-char field value; substitute + cap on every field # discord 400s an empty or >1024-char field value; cap then wrap so the closing
# backtick is never truncated off (cap the inner value, accounting for the 2 backticks)
if action is not None and str(action) != "": if action is not None and str(action) != "":
em.add_field(name="Action", value=self._cap_field(f"`{action}`"), inline=True) em.add_field(name="Action", value=f"`{self._cap_field(str(action), reserve=2)}`", inline=True)
if actor is not None and str(actor) != "": if actor is not None and str(actor) != "":
em.add_field(name="Actor", value=self._cap_field(f"`{actor}`"), inline=True) em.add_field(name="Actor", value=f"`{self._cap_field(str(actor), reserve=2)}`", inline=True)
log_value = str(details) if details is not None and str(details) != "" else "(no message)" log_value = str(details) if details is not None and str(details) != "" else "(no message)"
em.add_field(name="Log", value=self._cap_field(log_value), inline=False) em.add_field(name="Log", value=self._cap_field(log_value), inline=False)
em.timestamp = datetime.now(self.timezone) em.timestamp = datetime.now(self.timezone)