Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/developer51709/Noxie/llms.txt

Use this file to discover all available pages before exploring further.

Discord Components V2 (CV2) is the layout system introduced in discord.py 2.3+ that allows bots to send rich, structured messages using components like Container, TextDisplay, MediaGallery, and Separator — all wrapped in a LayoutView. Noxie uses CV2 exclusively for all user-facing output: hunt results, inventory lists, profiles, donation flows, and error messages. Every response is a purposefully composed container with an accent color, structured text sections, and a mood banner image at the bottom. The CV2 engine in utils/cv2_helpers.py provides the shared primitives that make this consistent across every cog.

Low-Level Primitives

These three helpers are the atomic building blocks used inside every container builder. They are prefixed with _ to signal internal use, but cogs import and use them directly.
def _make_file(path: str, filename: str) -> discord.File
def _media(attachment_name: str) -> discord.ui.MediaGallery
def _sep(visible: bool = False) -> discord.ui.Separator
FunctionPurpose
_make_file(path, filename)Wraps a file path in a discord.File with the given attachment filename. All image files passed to a container must be registered this way so Discord can serve them as attachment://filename.
_media(attachment_name)Creates a one-image discord.ui.MediaGallery that references attachment://{attachment_name}. Used to render both creature artwork (top of container) and mood banners (bottom of container).
_sep(visible=False)Creates a discord.ui.Separator. When visible=False the separator acts as invisible padding between sections. When visible=True it renders as a visible dividing line.

RARITY_COLORS

RARITY_COLORS is a module-level constant imported by cogs/hunt.py and used to set the accent_color on hunt and creature containers, giving each rarity tier a distinct color strip on the left edge of the card.
RARITY_COLORS: dict[str, int] = {
    "common":    0x829882,
    "uncommon":  0x4CAF50,
    "rare":      0x4A90E2,
    "epic":      0x9B59B6,
    "legendary": 0xFFD700,
    "mythic":    0xFF6BF6,
}
RarityHexAppearance
common#829882Muted sage green
uncommon#4CAF50Vivid green
rare#4A90E2Steel blue
epic#9B59B6Deep purple
legendary#FFD700Gold
mythic#FF6BF6Neon pink

build_face_reaction_container()

The generic face/mood reaction container. Used by main.py error handlers, cooldown responses, guild join greetings, and any cog that needs a simple mood-keyed message without a full feature-specific layout.
def build_face_reaction_container(
    message: str,
    banner_path: Optional[str] = None,
    color: int = 0x7930A7,
) -> tuple[list, list[discord.File]]
Parameters
ParameterTypeDescription
messagestrThe text content rendered in a TextDisplay. Supports Discord markdown (bold, italics, headings).
banner_pathOptional[str]Absolute path to a mood banner JPEG. If None, no image is appended. Retrieve via face_manager.get_face_for_event().
colorintAccent color as a hex integer for the container’s left-edge stripe. Defaults to Noxie’s signature purple 0x7930A7.
Returns tuple[list, list[discord.File]] — a components list containing one discord.ui.Container, and a files list with zero or one discord.File for the banner image. Layout: TextDisplay(message) → invisible separator → MediaGallery("face.jpeg") (if banner provided).

send_cv2()

The unified send dispatcher. All cogs call this single function instead of branching on the target type themselves. It wraps the components list in a discord.ui.LayoutView (which sets the CV2 message flag automatically) and routes the send to the correct discord.py API surface.
async def send_cv2(
    target,  # ctx, channel, or interaction
    components: list,
    files: list[discord.File],
    ephemeral: bool = False,
) -> None
Parameters
ParameterTypeDescription
targetcommands.Context | discord.Interaction | discord.abc.MessageableThe destination to send to.
componentslistTop-level CV2 components, typically a single discord.ui.Container.
fileslist[discord.File]Attachment files referenced inside the components. Pass an empty list if the container has no images.
ephemeralboolWhen True and target is an Interaction, sends an ephemeral response visible only to the invoking user. Has no effect on ctx or channel targets.
Dispatch logic:
  1. Builds a discord.ui.LayoutView and adds each component via view.add_item().
  2. If files is empty, passes discord.utils.MISSING to avoid sending an empty files=[] parameter.
  3. If target is a discord.Interaction:
    • If the interaction has already been responded to (e.g. after a defer()), calls target.followup.send().
    • Otherwise calls target.response.send_message().
  4. If target has a send attribute (any commands.Context or Messageable), calls target.send().
  5. Raises TypeError for any unrecognized target type.
async def send_cv2(target, components, files, ephemeral=False):
    view = discord.ui.LayoutView()
    for item in components:
        view.add_item(item)

    send_files = files if files else discord.utils.MISSING

    if isinstance(target, discord.Interaction):
        if target.response.is_done():
            await target.followup.send(view=view, files=send_files, ephemeral=ephemeral)
        else:
            await target.response.send_message(view=view, files=send_files, ephemeral=ephemeral)
    elif hasattr(target, "send"):
        await target.send(view=view, files=send_files)
    else:
        raise TypeError(f"Cannot send CV2 to target of type {type(target)}")
When a slash command calls await interaction.response.defer() before doing async work (such as polling an API), the subsequent send_cv2() call will automatically route to followup.send() because response.is_done() will be True.

Cog-Specific Container Builders

Each feature cog defines its own container builder functions that import the low-level primitives from cv2_helpers.py. These builders are not in cv2_helpers.py itself — they live in their cog modules so that layout changes stay co-located with the commands that use them.
FunctionModulePurpose
build_hunt_container()cogs/hunt.pyHunt result card: creature artwork (top), name/description, rarity/mood/vibe/power stats, currency rewards, personality line, mood banner (bottom)
build_inventory_container()cogs/hunt.pyPaged creature collection list with count per species, no mood banner
build_creature_container()cogs/hunt.pySingle creature detail card with artwork, stats, and creature-native mood banner at bottom
build_mood_pulse_container()cogs/profile.pyProfile card showing vibe status, hunt streak, total hunts, Glow Shards, Vibe Coins, badges, and mood banner
build_donate_start_container()cogs/donate.pyDonation payment instructions card sent in DMs: crypto address, exact amount, payment ID, and excited mood banner
build_donate_confirm_container()cogs/donate.pyDonation success card sent in DMs: amount, rewards granted, optional new-donor badge note, personality line, and love mood banner
build_donate_failed_container()cogs/donate.pyDonation failure card sent in DMs: failure reason and dizzy mood banner
build_help_container()cogs/help.pyHelp command overview card listing all commands with descriptions

Standard Container Layout Pattern

Every Noxie container follows the same visual grammar, applied consistently so users build an intuitive recognition of the card structure:
┌─────────────────────────────────────────┐  ← accent_color stripe
│  [MediaGallery]  ← creature art / hero   │
│  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ (invisible sep) │
│  [TextDisplay]   ← title / description   │
│  ───────────────────────── (visible sep) │
│  [TextDisplay]   ← stat block            │
│  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ (invisible sep) │
│  [TextDisplay]   ← rewards / balance     │
│  ───────────────────────── (visible sep) │
│  [TextDisplay]   ← personality line      │
│  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ (invisible sep) │
│  [MediaGallery]  ← mood banner           │
└─────────────────────────────────────────┘
  • Optional art/media at top — creature artwork or a hero image, separated from the text below by an invisible separator.
  • Title and description — a TextDisplay with a markdown heading (##) and flavor text.
  • Visible separator — a clear visual break before structured data.
  • Stat/data block — bold key–value pairs using **Key** — value formatting.
  • Invisible separator — padding before reward or secondary data.
  • Rewards or secondary info — currency amounts, totals, or badge notes.
  • Visible separator — break before the personality/footer line.
  • Personality line — an italicized quote from the personality engine.
  • Invisible separator — breathing room before the banner.
  • Mood banner at bottom — a JPEG face image matched to the event/rarity, always the last item.
All container builder functions return tuple[list, list[discord.File]] — a components list and a files list. Always pass both return values to send_cv2(). If the container has no images the files list will be empty, and send_cv2() will handle that correctly by passing discord.utils.MISSING for the files parameter.

Build docs developers (and LLMs) love