/Give card command should let you add multiple at once #359

Open
opened 2024-09-15 12:57:14 +01:00 by Vylpes · 5 comments
Owner

User story

As a whitelisted bot admin, I want to grant multiple copies of a card in one /give card invocation so I can correct inventories faster when the bot breaks.

Current behaviour

  • /give card accepts a single required cardnumber and user; each run adds one copy to inventory (src/commands/give.ts).
  • Command remains restricted to BOT_ADMINS, with existing sync/safe-mode checks unchanged.
  • /give currency is unchanged by this issue.

Acceptance criteria

  • GIVEN I am a whitelisted admin and drops are allowed
    WHEN I run /give card with a target user, a valid card number, and an optional quantity (default 1)
    THEN that many copies are added to the user's inventory in a single command execution
    AND the bot replies with the card name, amount added, and the new inventory total.

  • GIVEN I omit quantity
    WHEN I run /give card
    THEN behaviour matches today (exactly one copy is granted).

  • GIVEN I am not whitelisted, or drops are blocked (sync/safe mode), or the card number is invalid
    WHEN I run /give card
    THEN behaviour matches today's error handling (no inventory changes).

  • GIVEN quantity is less than 1
    WHEN I run /give card
    THEN the command is rejected and no inventory changes are made.

Subtasks

  • Add optional quantity number option to /give card (setMinValue(1), default 1)
  • Apply quantity via Inventory.AddQuantity / constructor initial quantity
  • Update reply to include card name, amount added, and new total
  • Add unit tests for default-1, explicit quantity, and existing guards

Notes

  • Scope is quantity of one card, not multiple card numbers in one invocation (confirmed).
  • Mirror optional-quantity UX from /sacrifice and /effects buy.
  • /give currency out of scope.
## User story As a whitelisted bot admin, I want to grant **multiple copies of a card** in one `/give card` invocation so I can correct inventories faster when the bot breaks. ## Current behaviour - `/give card` accepts a single required `cardnumber` and `user`; each run adds **one** copy to inventory (`src/commands/give.ts`). - Command remains restricted to `BOT_ADMINS`, with existing sync/safe-mode checks unchanged. - `/give currency` is unchanged by this issue. ## Acceptance criteria - **GIVEN** I am a whitelisted admin and drops are allowed **WHEN** I run `/give card` with a target user, a valid card number, and an optional `quantity` (default **1**) **THEN** that many copies are added to the user's inventory in a **single** command execution **AND** the bot replies with the card name, amount added, and the new inventory total. - **GIVEN** I omit `quantity` **WHEN** I run `/give card` **THEN** behaviour matches today (exactly one copy is granted). - **GIVEN** I am not whitelisted, or drops are blocked (sync/safe mode), or the card number is invalid **WHEN** I run `/give card` **THEN** behaviour matches today's error handling (no inventory changes). - **GIVEN** `quantity` is less than 1 **WHEN** I run `/give card` **THEN** the command is rejected and no inventory changes are made. ## Subtasks - [ ] Add optional `quantity` number option to `/give card` (`setMinValue(1)`, default 1) - [ ] Apply quantity via `Inventory.AddQuantity` / constructor initial quantity - [ ] Update reply to include card name, amount added, and new total - [ ] Add unit tests for default-1, explicit quantity, and existing guards ## Notes - Scope is **quantity of one card**, not multiple card numbers in one invocation (confirmed). - Mirror optional-quantity UX from `/sacrifice` and `/effects buy`. - `/give currency` out of scope.
Vylpes added this to the 0.11.0 milestone 2026-09-16 18:30:12 +01:00
Vylpes self-assigned this 2026-09-16 18:30:13 +01:00
Vylpes removed their assignment 2026-09-16 18:30:17 +01:00
Member

Planning — needs/criteria

Reviewed src/commands/give.ts: /give card currently takes one cardnumber and always increments quantity by 1.

To finish acceptance criteria, please confirm:

  1. What should “multiple at once” mean?

    • A quantity option on one card number (e.g. give 5× card #123), and/or
    • Several card numbers in one slash command (e.g. #123, #456, #789 to the same user), and/or
    • Something else?
  2. If multiple card numbers are supported, what is the maximum per invocation (Discord option limits may apply)?

  3. Partial failure: if one card number is invalid, should the command fail entirely with no inventory changes, or apply the valid cards and report which failed?

  4. Reply format: is a single summary message listing each card name, amount added, and new inventory total acceptable?

Once you reply, I’ll lock the criteria and move the ticket to needs/estimate.

### Planning — needs/criteria Reviewed `src/commands/give.ts`: `/give card` currently takes one `cardnumber` and always increments quantity by **1**. To finish acceptance criteria, please confirm: 1. **What should “multiple at once” mean?** - A **quantity** option on one card number (e.g. give 5× card `#123`), and/or - **Several card numbers** in one slash command (e.g. `#123`, `#456`, `#789` to the same user), and/or - Something else? 2. **If multiple card numbers are supported**, what is the **maximum** per invocation (Discord option limits may apply)? 3. **Partial failure**: if one card number is invalid, should the command **fail entirely** with no inventory changes, or **apply the valid cards** and report which failed? 4. **Reply format**: is a single summary message listing each card name, amount added, and new inventory total acceptable? Once you reply, I’ll lock the criteria and move the ticket to **needs/estimate**.
Smithy-bot removed their assignment 2026-09-22 12:09:13 +01:00
Author
Owner

@Smithy-bot wrote in #359 (comment):

Planning — needs/criteria

Reviewed src/commands/give.ts: /give card currently takes one cardnumber and always increments quantity by 1.

To finish acceptance criteria, please confirm:

1. **What should “multiple at once” mean?**
   
   * A **quantity** option on one card number (e.g. give 5× card `#123`), and/or
   * **Several card numbers** in one slash command (e.g. `#123`, `#456`, `#789` to the same user), and/or
   * Something else?

2. **If multiple card numbers are supported**, what is the **maximum** per invocation (Discord option limits may apply)?

3. **Partial failure**: if one card number is invalid, should the command **fail entirely** with no inventory changes, or **apply the valid cards** and report which failed?

4. **Reply format**: is a single summary message listing each card name, amount added, and new inventory total acceptable?

Once you reply, I’ll lock the criteria and move the ticket to needs/estimate.

  1. A quantity
  2. N/A
  3. N/A
  4. Card name, amount added, new total
@Smithy-bot wrote in https://git.vylpes.xyz/External/card-drop/issues/359#issuecomment-21887: > ### [](#planning-needs-criteria)Planning — needs/criteria > > Reviewed `src/commands/give.ts`: `/give card` currently takes one `cardnumber` and always increments quantity by **1**. > > To finish acceptance criteria, please confirm: > > 1. **What should “multiple at once” mean?** > > * A **quantity** option on one card number (e.g. give 5× card `#123`), and/or > * **Several card numbers** in one slash command (e.g. `#123`, `#456`, `#789` to the same user), and/or > * Something else? > > 2. **If multiple card numbers are supported**, what is the **maximum** per invocation (Discord option limits may apply)? > > 3. **Partial failure**: if one card number is invalid, should the command **fail entirely** with no inventory changes, or **apply the valid cards** and report which failed? > > 4. **Reply format**: is a single summary message listing each card name, amount added, and new inventory total acceptable? > > > Once you reply, I’ll lock the criteria and move the ticket to **needs/estimate**. 1. A quantity 2. N/A 3. N/A 4. Card name, amount added, new total
Vylpes removed their assignment 2026-10-04 18:15:32 +01:00
Member

Planning — criteria locked

Confirmed from owner reply:

  1. Scope: optional quantity on one card (not multiple card numbers)
  2. Max card IDs: N/A
  3. Partial failure: N/A
  4. Reply: card name, amount added, new inventory total

Implementation plan

File: src/commands/give.ts only for behaviour; add tests/commands/give.test.ts.

  1. Slash option — on card subcommand, add optional number option quantity with .setMinValue(1) and description like sacrifice/effects (The amount to give (default 1)).
  2. Parse — const quantity = Number(interaction.options.get("quantity")?.value ?? 1); reject if < 1 (belt-and-braces if Discord client skips min).
  3. Grant — after successful card lookup:
    • no row → new Inventory(userId, cardId, quantity)
    • exists → inventory.AddQuantity(quantity) (align with claim/multidrop; replace SetQuantity(+1))
  4. Reply — e.g. Card {name} x{quantity} given to {username}, they now have {Quantity}.
  5. Unchanged — BOT_ADMINS, sync/AllowDrops, safemode, invalid-card errors, /give currency.
  6. Tests — mirror tests/commands/drop.test.ts mocks: default quantity 1, explicit quantity N, non-admin / sync / safemode / missing card (no save).

Moved to needs/estimate.

### Planning — criteria locked Confirmed from owner reply: 1. **Scope**: optional `quantity` on one card (not multiple card numbers) 2. **Max card IDs**: N/A 3. **Partial failure**: N/A 4. **Reply**: card name, amount added, new inventory total #### Implementation plan **File:** `src/commands/give.ts` only for behaviour; add `tests/commands/give.test.ts`. 1. **Slash option** — on `card` subcommand, add optional number option `quantity` with `.setMinValue(1)` and description like sacrifice/effects (`The amount to give (default 1)`). 2. **Parse** — `const quantity = Number(interaction.options.get("quantity")?.value ?? 1)`; reject if `< 1` (belt-and-braces if Discord client skips min). 3. **Grant** — after successful card lookup: - no row → `new Inventory(userId, cardId, quantity)` - exists → `inventory.AddQuantity(quantity)` (align with claim/multidrop; replace `SetQuantity(+1)`) 4. **Reply** — e.g. `Card {name} x{quantity} given to {username}, they now have {Quantity}`. 5. **Unchanged** — `BOT_ADMINS`, sync/`AllowDrops`, safemode, invalid-card errors, `/give currency`. 6. **Tests** — mirror `tests/commands/drop.test.ts` mocks: default quantity 1, explicit quantity N, non-admin / sync / safemode / missing card (no save). Moved to **needs/estimate**.
Member

Planning — needs/estimate

Story points: 3

Factor Notes
Scope One subcommand path in give.ts, optional quantity option, reply text
Patterns Mirrors /sacrifice and /effects buy quantity UX; inventory via AddQuantity / constructor
Tests New or extended give command tests (default 1, explicit N, existing guard paths)
Risk Low — no schema/migration; admin-only command with existing guards

Rationale: slightly more than a 1-point tweak because of test coverage and touching inventory grant logic, but well-bounded and no cross-cutting changes.

Moving to needs/tests.

### Planning — needs/estimate **Story points: 3** | Factor | Notes | |--------|--------| | Scope | One subcommand path in `give.ts`, optional `quantity` option, reply text | | Patterns | Mirrors `/sacrifice` and `/effects buy` quantity UX; inventory via `AddQuantity` / constructor | | Tests | New or extended `give` command tests (default 1, explicit N, existing guard paths) | | Risk | Low — no schema/migration; admin-only command with existing guards | Rationale: slightly more than a 1-point tweak because of test coverage and touching inventory grant logic, but well-bounded and no cross-cutting changes. Moving to **needs/tests**.
Member

Planning — needs/tests → needs/approval

QA scripts mapped to the acceptance criteria in the issue description. Run on a branch with the implementation merged or deployed to stage; unit-test rows can run locally via yarn test.

Preconditions

  • Test user in BOT_ADMINS and a non-admin user for guard checks.
  • Known valid card number and a user with zero and non-zero existing inventory for that card.
  • Ability to run yarn test (target tests/commands/give.test.ts or equivalent).
  • Optional: stage Discord bot with sync/safe-mode toggles for manual admin checks.

AC1 — Grant multiple copies in one invocation (default quantity behaviour when set)

ID Steps Expected
T1.1 As admin with drops allowed, /give card with user, valid cardnumber, quantity = 5 User inventory for that card increases by 5 in a single DB save / command execution
T1.2 Note bot reply Includes card name, amount added (5), and new inventory total for that card
T1.3 Repeat with user who had 0 copies before New Inventory row created with quantity 5
T1.4 Repeat with user who had N copies before Final quantity = N + 5

AC2 — Omit quantity → exactly one copy (unchanged from today)

ID Steps Expected
T2.1 /give card with user and cardnumber, no quantity option Inventory increases by 1
T2.2 Reply content Card name, amount added 1, new total
T2.3 Compare behaviour to pre-change baseline on same inputs No functional regression when quantity omitted

AC3 — Existing guards unchanged (no inventory changes on failure)

ID Steps Expected
T3.1 Non-admin runs /give card (any quantity) Same error as today; no inventory change
T3.2 Admin while sync / drops disallowed (AllowDrops false) Same error as today; no inventory change
T3.3 Admin in safe mode (if applicable to give) Same error as today; no inventory change
T3.4 Admin with invalid cardnumber Same error as today; no inventory change
T3.5 For each failure case above, attempt with quantity > 1 Still no inventory change

AC4 — quantity less than 1 rejected

ID Steps Expected
T4.1 Unit / integration test: quantity = 0 (if reachable past Discord min) Command rejected; no inventory change
T4.2 Unit test: negative quantity (mocked option) Rejected; no inventory change
T4.3 Discord UI: quantity option has setMinValue(1) User cannot submit 0 or negative via slash UI

Unit tests (subtasks)

ID Steps Expected
U1 yarn test — give command suite Green
U2 Test: default quantity (omit option) +1 inventory, expected reply shape
U3 Test: explicit quantity = N +N inventory, reply shows N and new total
U4 Tests: non-admin, sync blocked, safemode, missing card No save / no quantity change (mirror drop.test.ts patterns)
U5 CI / Forgejo Actions test job on PR Passes

Regression / scope

ID Steps Expected
R1 /give currency subcommand Unchanged
R2 Other give paths / inventory commands Unchanged unless explicitly sharing code

Sign-off checklist

  • T1–T4, U1–U5, and R1 pass.
  • Reply format matches: card name, amount added, new total.

Moving to needs/approval for your review before implementation. @Vylpes

## Planning — needs/tests → needs/approval QA scripts mapped to the acceptance criteria in the issue description. Run on a branch with the implementation merged or deployed to **stage**; unit-test rows can run locally via `yarn test`. ### Preconditions - Test user in `BOT_ADMINS` and a non-admin user for guard checks. - Known valid card number and a user with **zero** and **non-zero** existing inventory for that card. - Ability to run `yarn test` (target `tests/commands/give.test.ts` or equivalent). - Optional: stage Discord bot with sync/safe-mode toggles for manual admin checks. --- ### AC1 — Grant multiple copies in one invocation (default quantity behaviour when set) | ID | Steps | Expected | |----|--------|----------| | T1.1 | As admin with drops allowed, `/give card` with `user`, valid `cardnumber`, `quantity` = **5** | User inventory for that card increases by **5** in a **single** DB save / command execution | | T1.2 | Note bot reply | Includes **card name**, **amount added** (5), and **new inventory total** for that card | | T1.3 | Repeat with user who had **0** copies before | New `Inventory` row created with quantity **5** | | T1.4 | Repeat with user who had **N** copies before | Final quantity = **N + 5** | --- ### AC2 — Omit `quantity` → exactly one copy (unchanged from today) | ID | Steps | Expected | |----|--------|----------| | T2.1 | `/give card` with `user` and `cardnumber`, **no** `quantity` option | Inventory increases by **1** | | T2.2 | Reply content | Card name, amount added **1**, new total | | T2.3 | Compare behaviour to pre-change baseline on same inputs | No functional regression when quantity omitted | --- ### AC3 — Existing guards unchanged (no inventory changes on failure) | ID | Steps | Expected | |----|--------|----------| | T3.1 | Non-admin runs `/give card` (any quantity) | Same error as today; **no** inventory change | | T3.2 | Admin while sync / drops disallowed (`AllowDrops` false) | Same error as today; **no** inventory change | | T3.3 | Admin in safe mode (if applicable to give) | Same error as today; **no** inventory change | | T3.4 | Admin with **invalid** `cardnumber` | Same error as today; **no** inventory change | | T3.5 | For each failure case above, attempt with `quantity` > 1 | Still **no** inventory change | --- ### AC4 — `quantity` less than 1 rejected | ID | Steps | Expected | |----|--------|----------| | T4.1 | Unit / integration test: `quantity` = **0** (if reachable past Discord min) | Command rejected; **no** inventory change | | T4.2 | Unit test: negative quantity (mocked option) | Rejected; **no** inventory change | | T4.3 | Discord UI: `quantity` option has `setMinValue(1)` | User cannot submit 0 or negative via slash UI | --- ### Unit tests (subtasks) | ID | Steps | Expected | |----|--------|----------| | U1 | `yarn test` — give command suite | Green | | U2 | Test: default quantity (omit option) | +1 inventory, expected reply shape | | U3 | Test: explicit `quantity` = N | +N inventory, reply shows N and new total | | U4 | Tests: non-admin, sync blocked, safemode, missing card | No `save` / no quantity change (mirror `drop.test.ts` patterns) | | U5 | CI / Forgejo Actions test job on PR | Passes | --- ### Regression / scope | ID | Steps | Expected | |----|--------|----------| | R1 | `/give currency` subcommand | Unchanged | | R2 | Other give paths / inventory commands | Unchanged unless explicitly sharing code | --- ### Sign-off checklist - [ ] T1–T4, U1–U5, and R1 pass. - [ ] Reply format matches: card name, amount added, new total. Moving to **needs/approval** for your review before implementation. @Vylpes
Smithy-bot removed their assignment 2026-10-18 12:03:39 +01:00
Smithy-bot stopped working 2026-10-18 12:03:39 +01:00
21 seconds
Vylpes removed their assignment 2026-10-18 13:30:44 +01:00
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Total time spent: 21 seconds
Smithy-bot
21 seconds
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
External/card-drop#359
No description provided.