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
| Function | Purpose |
|---|
_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,
}
| Rarity | Hex | Appearance |
|---|
common | #829882 | Muted sage green |
uncommon | #4CAF50 | Vivid green |
rare | #4A90E2 | Steel blue |
epic | #9B59B6 | Deep purple |
legendary | #FFD700 | Gold |
mythic | #FF6BF6 | Neon 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
| Parameter | Type | Description |
|---|
message | str | The text content rendered in a TextDisplay. Supports Discord markdown (bold, italics, headings). |
banner_path | Optional[str] | Absolute path to a mood banner JPEG. If None, no image is appended. Retrieve via face_manager.get_face_for_event(). |
color | int | Accent 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
| Parameter | Type | Description |
|---|
target | commands.Context | discord.Interaction | discord.abc.Messageable | The destination to send to. |
components | list | Top-level CV2 components, typically a single discord.ui.Container. |
files | list[discord.File] | Attachment files referenced inside the components. Pass an empty list if the container has no images. |
ephemeral | bool | When 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:
- Builds a
discord.ui.LayoutView and adds each component via view.add_item().
- If
files is empty, passes discord.utils.MISSING to avoid sending an empty files=[] parameter.
- 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().
- If
target has a send attribute (any commands.Context or Messageable), calls target.send().
- 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.
| Function | Module | Purpose |
|---|
build_hunt_container() | cogs/hunt.py | Hunt result card: creature artwork (top), name/description, rarity/mood/vibe/power stats, currency rewards, personality line, mood banner (bottom) |
build_inventory_container() | cogs/hunt.py | Paged creature collection list with count per species, no mood banner |
build_creature_container() | cogs/hunt.py | Single creature detail card with artwork, stats, and creature-native mood banner at bottom |
build_mood_pulse_container() | cogs/profile.py | Profile card showing vibe status, hunt streak, total hunts, Glow Shards, Vibe Coins, badges, and mood banner |
build_donate_start_container() | cogs/donate.py | Donation payment instructions card sent in DMs: crypto address, exact amount, payment ID, and excited mood banner |
build_donate_confirm_container() | cogs/donate.py | Donation 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.py | Donation failure card sent in DMs: failure reason and dizzy mood banner |
build_help_container() | cogs/help.py | Help 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.