-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Summary
Add a crafting order board to the WoW module. An admin slash command posts a persistent board embed in a chosen channel. The board's available profession roles are set at creation time. Craftable items are fetched from the Blizzard Game Data API, filtered to only those requiring the in-game Crafting Order System (BOP items, not tradeable on the Auction House), and cached locally alongside their item IDs and icon URLs. A dedicated admin command refreshes the cache on demand. Each crafting order is tracked as its own embed — including the item's icon — with interactive buttons for status transitions, and includes a fallback thread for DM-gated communication.
Feature Description
1. Board Setup — /wow craftingorder create
An admin-only slash command that creates the order board in a target channel.
| Parameter | Type | Description |
|---|---|---|
channel |
TextChannel |
Channel where the board embed is posted |
description |
str |
Body text shown in the board embed |
roles |
str |
Space- or comma-separated role mentions — one per craftable profession |
The command stores the channel, board message ID, and configured role list in the database. It then posts a persistent embed in the target channel containing a Create Crafting Order button.
2. Recipe Cache — /wow craftingorder recipe-sync
An admin-only slash command that fetches craftable item data from the Blizzard Game Data API, filters to crafting-order-eligible items only, and stores the result locally. Because recipes change only on major content patches, this is intentionally manual.
Fetch and filter sequence (via blizzapi.RetailClient):
professions_index()— enumerate all profession IDsprofession(professionId)— retrieve skill tiers; select only the current expansion skill tierprofession_skill_tier(professionId, skillTierId)— retrieve the full recipe list for that tier- For each recipe:
recipe(recipeId)— retrieve the crafted item ID - For each crafted item:
item(itemId)— inspect the binding type field - Filter: keep only items where binding type is BOP (Bind on Pickup — requires the Crafting Order System; not tradeable on the Auction House)
- For each kept item:
item_media(itemId)— fetch the icon URL using the existingget_asset_url(response, "icon")helper fromutils/blizzard.py
Stored per recipe:
| Column | Source | Purpose |
|---|---|---|
profession_id |
Step 2 | Links recipe to profession |
recipe_id |
Step 3 | Original recipe identifier |
item_id |
Step 4 | Enables icon refresh and external links (e.g. Wowhead) |
item_name |
Step 4/5 | Shown in the Select menu and order embed |
icon_url |
Step 7 | Displayed as thumbnail in the order embed |
last_synced |
Sync time | Shown in the sync command's confirmation response |
Implementation note: The exact response field path for binding type (expected:
preview_item.binding.type, values"BOP"/"BOE") must be confirmed against a live Blizzard API response during implementation, asblizzapiis a schema-free HTTP wrapper.
Rate limiting:
blizzapidoes not auto-retry on 429 — every response must be checked via the existingcheck_rate_limit()inutils/blizzard.py. Add a small delay between item/media lookups and report a user-friendly error if rate-limited mid-sync.
3. Order Creation Flow
Because Discord modals only support text inputs (no dropdowns), item and profession selection happen as separate steps before the modal opens:
Step 1 — Profession select (ephemeral Select menu)
Options populated from the roles configured at board creation; labels are the role names.
Step 2 — Item select (ephemeral Select menu)
Options populated from the cached BOP item names for the chosen profession.
- Discord
Selectmenus support a maximum of 25 options; if the filtered list exceeds 25, show the first 25 alphabetically - Always appends "Other (specify below)" as the final option
- Skipped entirely if no cache exists for the profession
Step 3 — Modal
Item Name— pre-filled with the selected item name; empty when "Other" or no cacheAdditional Notes— free text (optional)
4. Order Embed
After submission, a new embed is posted in the board channel. If the item was selected from the dropdown and an icon_url is cached, it is displayed as the embed thumbnail — following the same pattern used by achievements and mounts elsewhere in the WoW module (embed.set_thumbnail(url=icon_url)).
| Field | Value |
|---|---|
| Item Name | As submitted / selected |
| Profession | Role name + role mention (e.g. Blacksmithing @Blacksmith) |
| Additional Notes | As submitted |
| Posted by | Mention of the order creator |
| Status | Open / In Progress (@CrafterName) / Completed |
| (Thumbnail) | Item icon from cached icon_url, if available |
5. Order Buttons & Transitions
| Button | Who can use it | Action |
|---|---|---|
| Accept | Members with the order's profession role | Sets status → In Progress (@Crafter) |
| Drop | Active crafter or Admins | Sets status → Open; clears crafter mention |
| Complete | Active crafter or Admins | Sets status → Completed; DMs creator; deletes embed |
| Cancel | Order creator or Admins | Sets status → Completed; deletes embed (see DM rules) |
| Ask Question | Anyone | Opens a modal with a Message field; creates a thread; pings creator |
DM rules for Complete/Cancel:
- Complete — DM to creator:
"Your crafting order has been completed!" - Cancel by creator — no DM
- Cancel by Admin — DM to creator:
"Your crafting order has been cancelled!" - DM failure fallback — creates thread if absent, posts message there and pings creator
6. State Machine
Open
└─[Accept]──► In Progress
├─[Drop]────► Open
└─[Complete]► Completed (embed deleted)
Open / In Progress
└─[Cancel]──► Completed (embed deleted)
Acceptance Criteria
-
/wow craftingorder createis guild-only and restricted to Admins - Command accepts
channel,description, androlesparameters - Board embed is posted in the target channel and survives bot restarts
-
/wow craftingorder recipe-syncfetches profession recipe data from the Blizzard API - Sync filters to current expansion skill tier only
- Sync filters to BOP items only (not tradeable on AH; require Crafting Order System)
- Sync stores
item_id,item_name, andicon_urlper recipe entry - Sync stores a
last_syncedtimestamp and reports it in the confirmation response - Sync handles 429 rate limits gracefully using the existing
check_rate_limit()helper - Profession select menu is populated from the roles configured at board creation
- Item select menu is shown after profession selection if cached BOP data exists; skipped otherwise
- Item select always includes an "Other (specify below)" fallback option
- If filtered item count exceeds 25, show first 25 alphabetically plus "Other"
- Modal pre-fills Item Name when a specific item was selected; empty for "Other"/no-cache
- Order embed displays all required fields including profession role mention
- Order embed shows the item icon as thumbnail when
icon_urlis available - Status transitions enforce correct role/permission gating
- Order embed is deleted after Completed or Cancelled
- DMs are sent per the rules above; DM failure triggers thread fallback
- Thread is created on "Ask Question"; creator is pinged inside it
Technical Notes
- Store board config (channel ID, message ID, role IDs), recipe cache (per recipe:
profession_id,recipe_id,item_id,item_name,icon_url,last_synced), and order metadata (includingicon_urlsnapshot) in the database — new tables, no migration needed per project convention - Snapshot
icon_urlonto the order row at creation time so the embed can be reconstructed after restarts without a DB join on the cache - Use
discord.ui.Viewwithtimeout=Noneand persistentcustom_ids (e.g.crafting:accept:<order_id>) on order buttons; re-register on startup - Ephemeral Step 1/2 select views are short-lived — pass selected state into the modal via hidden
TextInputwith presetdefault, or store temporarily server-side keyed byuser_id - Implement DM fallback before deleting the embed so the thread exists when needed
🤖 Generated with Claude Code