@notidotbot/noti-api-client 1.6.15 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.APIAdminFishing = void 0;
4
+ // Data.
5
+ /**
6
+ * Dev-only backend for the Fishing minigame admin dashboard.
7
+ *
8
+ * Every method here requires a developer account — the routes check the caller against the developer
9
+ * list and return 403 otherwise, so these are not merely "admin" in the guild-owner sense.
10
+ *
11
+ * Endpoints live under `/admin/minigames/fishing/*`. The `minigames` segment is deliberate: Fishing is
12
+ * the first minigame, not the only one, so a second game slots in beside it rather than replacing it.
13
+ */
14
+ class APIAdminFishing {
15
+ web;
16
+ constructor(web) {
17
+ this.web = web;
18
+ }
19
+ // ── Health & rollout ──────────────────────────────────────────────────────
20
+ /** Rollout state, active kill switches, pending flush backlog and Redis memory. */
21
+ async getHealth({ auth }) {
22
+ return await this.web.request({
23
+ method: 'GET', auth,
24
+ endpoint: this.web.qp('/admin/minigames/fishing/health'),
25
+ });
26
+ }
27
+ async getRollout({ auth }) {
28
+ return await this.web.request({
29
+ method: 'GET', auth,
30
+ endpoint: this.web.qp('/admin/minigames/fishing/rollout'),
31
+ });
32
+ }
33
+ /** Add or remove guilds from the beta allowlist. This is what starts a beta cohort. */
34
+ async setRolloutAllowlist({ auth, action, guildIds }) {
35
+ return await this.web.request({
36
+ method: 'PATCH', auth, body: { action, guildIds },
37
+ endpoint: this.web.qp('/admin/minigames/fishing/rollout/allowlist'),
38
+ });
39
+ }
40
+ /**
41
+ * Set the percentage dial.
42
+ *
43
+ * **0 is the fleet-wide kill switch** — the fastest way to stop fishing everywhere without a
44
+ * deploy. It stops ingestion only; the flush keeps draining so nobody's unflushed progress is lost.
45
+ */
46
+ async setRolloutPercent({ auth, percent }) {
47
+ return await this.web.request({
48
+ method: 'PATCH', auth, body: { percent },
49
+ endpoint: this.web.qp('/admin/minigames/fishing/rollout/percent'),
50
+ });
51
+ }
52
+ // ── Kill switches ─────────────────────────────────────────────────────────
53
+ async getKills({ auth }) {
54
+ return await this.web.request({
55
+ method: 'GET', auth,
56
+ endpoint: this.web.qp('/admin/minigames/fishing/kills'),
57
+ });
58
+ }
59
+ /**
60
+ * Throw or clear a kill switch.
61
+ *
62
+ * `scope` is either a subsystem (`cast`, `sell`, `boss`, …) or a single target (`guild:<id>` /
63
+ * `user:<id>`). A kill stops INGESTION only — the flush keeps draining, so throwing a switch mid
64
+ * incident does not destroy a window of every active player's progress.
65
+ */
66
+ async setKill({ auth, scope, on, reason }) {
67
+ return await this.web.request({
68
+ method: 'PATCH', auth, body: { on, reason },
69
+ endpoint: this.web.qp('/admin/minigames/fishing/kills/' + scope),
70
+ });
71
+ }
72
+ // ── Economy dials ─────────────────────────────────────────────────────────
73
+ /** Every dial with its current value and its permitted bounds. */
74
+ async getDials({ auth }) {
75
+ return await this.web.request({
76
+ method: 'GET', auth,
77
+ endpoint: this.web.qp('/admin/minigames/fishing/dials'),
78
+ });
79
+ }
80
+ /**
81
+ * Set a dial, or pass `value: null` to reset it to its seeded default.
82
+ *
83
+ * Out-of-range values are **rejected with a 400, not clamped** — an operator who typed 500 should
84
+ * learn it did not take rather than quietly getting 3.
85
+ */
86
+ async setDial({ auth, dial, value, reason }) {
87
+ return await this.web.request({
88
+ method: 'PATCH', auth, body: { value, reason },
89
+ endpoint: this.web.qp('/admin/minigames/fishing/dials/' + dial),
90
+ });
91
+ }
92
+ // ── Content ───────────────────────────────────────────────────────────────
93
+ /** The editable content tables, plus the currently effective content version. */
94
+ async getContentTables({ auth }) {
95
+ return await this.web.request({
96
+ method: 'GET', auth,
97
+ endpoint: this.web.qp('/admin/minigames/fishing/content'),
98
+ });
99
+ }
100
+ async listContent({ auth, table, limit }) {
101
+ return await this.web.request({
102
+ method: 'GET', auth,
103
+ endpoint: this.web.qp('/admin/minigames/fishing/content/' + table, { limit }),
104
+ });
105
+ }
106
+ /**
107
+ * Create or update one content row (upsert — one verb, not two).
108
+ *
109
+ * For `dateDerived` tables the change does **not** apply today: `effectiveFrom` in the response is
110
+ * the next 00:00 UTC. Daily demand, the shop rotation and the quest board are a date-seeded shuffle
111
+ * over the content list, so editing it mid-day would reshuffle a day players already acted on.
112
+ */
113
+ async upsertContent({ auth, table, id, data, reason }) {
114
+ return await this.web.request({
115
+ method: 'PUT', auth, body: { ...data, reason },
116
+ endpoint: this.web.qp(`/admin/minigames/fishing/content/${table}/${id}`),
117
+ });
118
+ }
119
+ /**
120
+ * Disable a content row. **Nothing is hard-deleted** — player rows store content ids (claimed sets,
121
+ * caught species, owned items), so removing a row would orphan them.
122
+ */
123
+ async disableContent({ auth, table, id }) {
124
+ return await this.web.request({
125
+ method: 'DELETE', auth,
126
+ endpoint: this.web.qp(`/admin/minigames/fishing/content/${table}/${id}`),
127
+ });
128
+ }
129
+ // ── Player & guild operations ─────────────────────────────────────────────
130
+ /** Global progression, plus per-guild wallet/inventory/ledger when `guildId` is supplied. */
131
+ async getPlayer({ auth, userId, guildId }) {
132
+ return await this.web.request({
133
+ method: 'GET', auth,
134
+ endpoint: this.web.qp('/admin/minigames/fishing/players/' + userId, { guildId }),
135
+ });
136
+ }
137
+ async getGuild({ auth, guildId }) {
138
+ return await this.web.request({
139
+ method: 'GET', auth,
140
+ endpoint: this.web.qp('/admin/minigames/fishing/guilds/' + guildId),
141
+ });
142
+ }
143
+ /**
144
+ * Grant (positive delta) or revoke (negative delta) coins.
145
+ *
146
+ * A revoke **clamps at zero**. A negative balance silently blocks every future purchase with no
147
+ * explanation the player can act on, and support would have to undo it by hand.
148
+ */
149
+ async adjustPlayerCoins({ auth, userId, guildId, delta, reason }) {
150
+ return await this.web.request({
151
+ method: 'PATCH', auth, body: { guildId, delta, reason },
152
+ endpoint: this.web.qp(`/admin/minigames/fishing/players/${userId}/coins`),
153
+ });
154
+ }
155
+ /**
156
+ * Reset a player's server stats, their global progression, a guild's dock, or a guild's economy.
157
+ *
158
+ * `claimedSets` and `claimedMilestones` are **preserved unless `alsoClearClaims` is set**. They
159
+ * record what a player was already *paid* for — clearing them makes every milestone and collection
160
+ * pay out a second time as the counters climb back, so "please reset me" becomes a faucet. Setting
161
+ * the flag is audited as its own action. A dock reset likewise preserves `prestige`.
162
+ */
163
+ async resetTarget({ auth, scope, userId, guildId, alsoClearClaims, reason }) {
164
+ return await this.web.request({
165
+ method: 'POST', auth, body: { scope, userId, guildId, alsoClearClaims, reason },
166
+ endpoint: this.web.qp('/admin/minigames/fishing/reset'),
167
+ });
168
+ }
169
+ /**
170
+ * Subtract what a range of flush batches awarded, clamped at zero.
171
+ *
172
+ * This is **not** an undo — deltas are not invertible once superseded (earn 500, buy a 500-coin
173
+ * rod, undo, and the balance goes negative while they keep the rod). It reads what those batches
174
+ * actually applied and reverses that much.
175
+ *
176
+ * **Dry-run unless `apply` is true.** Each subtraction is idempotent per player per range, so a
177
+ * retried apply cannot double-charge.
178
+ */
179
+ async compensateBatches({ auth, fromBatchId, toBatchId, apply, reason }) {
180
+ return await this.web.request({
181
+ method: 'POST', auth, body: { fromBatchId, toBatchId, apply, reason },
182
+ endpoint: this.web.qp('/admin/minigames/fishing/compensate'),
183
+ });
184
+ }
185
+ // ── Audit & abuse ─────────────────────────────────────────────────────────
186
+ /** Who ran what, with before → after. Distinct from the coin ledger, which is where coins came from. */
187
+ async getAudit({ auth, limit }) {
188
+ return await this.web.request({
189
+ method: 'GET', auth,
190
+ endpoint: this.web.qp('/admin/minigames/fishing/audit', { limit }),
191
+ });
192
+ }
193
+ /**
194
+ * Abuse review queue.
195
+ *
196
+ * A queue of things for a HUMAN to look at, never a list of confirmed cheats. Detection runs
197
+ * against an economy with no live data, so its false positives are disproportionately legitimate
198
+ * heavy players — the most engaged users in the feature. Nothing here bans, and there is
199
+ * deliberately no bulk action: confirmed abuse is actioned through `resetTarget`,
200
+ * `adjustPlayerCoins` or `setKill`, each of which writes an audit row.
201
+ *
202
+ * Defaults to PENDING flags, ordered most-severe-first.
203
+ */
204
+ async getAbuseQueue({ auth, status, severity, kind, userId, guildId, limit, offset }) {
205
+ return await this.web.request({
206
+ method: 'GET', auth,
207
+ endpoint: this.web.qp('/admin/minigames/fishing/abuse', { status, severity, kind, userId, guildId, limit, offset }),
208
+ });
209
+ }
210
+ /**
211
+ * Mark a flag reviewed, or reopen one.
212
+ *
213
+ * Pass `reviewed: false` to reopen — a reviewer who dismisses the wrong row otherwise has no way
214
+ * back, because the queue's day-grained dedupe key stops the same condition re-raising it.
215
+ *
216
+ * Reviewing is also what makes retention work: reviewed flags age out after 30 days, unreviewed
217
+ * ones after 90.
218
+ */
219
+ async updateAbuseFlag({ auth, flagId, reviewed, reason }) {
220
+ return await this.web.request({
221
+ method: 'PATCH', auth, body: { reviewed, reason },
222
+ endpoint: this.web.qp('/admin/minigames/fishing/abuse/' + flagId),
223
+ });
224
+ }
225
+ }
226
+ exports.APIAdminFishing = APIAdminFishing;
@@ -0,0 +1,188 @@
1
+ import { CancelOutWebResponses } from '../types';
2
+ import { WebDataManager } from '../core/manager';
3
+ /**
4
+ * Per-guild fishing customization (Premium) and the server-listing link.
5
+ *
6
+ * Every method here requires the caller to administer the guild AND the guild to hold the right
7
+ * entitlement — both enforced server-side, not merely hidden in the dashboard:
8
+ *
9
+ * `FishingCustomization` (Premium) — names, rarity table, catch message, shop items, listing
10
+ * `FishingWebhooks` (Premium Plus) — the webhook identity, matching every other webhook feature
11
+ *
12
+ * A Premium (non-Plus) guild gets a 403 from `setWebhook` despite passing every other check.
13
+ *
14
+ * **Customization never affects gameplay rates in a way that moves leaderboard standing.** Premium buys
15
+ * names, prices, messages and identity — the rarity table is the only thing touching the roll, and it
16
+ * is clamped to 0.5x–2x of the defaults, cannot reach `mythic`, and cannot zero a tier.
17
+ */
18
+ export declare class APIGuildFishing {
19
+ private web;
20
+ constructor(web: WebDataManager);
21
+ /** The guild's full customization, including a member-facing summary of its rarity weighting. */
22
+ getCustomization({ auth, guildId }: GuildFishingFunctionsInput['getCustomization']): Promise<import("../types").WebResponse<GuildFishingCustomization>>;
23
+ /**
24
+ * Reweight the guild's rarity table, or pass `weights: null` to clear the override.
25
+ *
26
+ * **Rejects rather than clamps.** Out-of-band weights, `mythic`, and zeroing all return a 400 with
27
+ * per-field `issues` — an owner who typed 100 should learn it did not take, not quietly receive 2.
28
+ */
29
+ setRarityTable({ auth, guildId, weights }: GuildFishingFunctionsInput['setRarityTable']): Promise<import("../types").WebResponse<GuildFishingRarityTable>>;
30
+ /**
31
+ * Rename species and/or rarity tiers for this guild.
32
+ *
33
+ * Display only — the catalogue itself stays global, so the codex, collections and the public API
34
+ * remain coherent across every server. A rename changes what a server *calls* a fish, never which
35
+ * fish exist.
36
+ */
37
+ setNames({ auth, guildId, species, rarities }: GuildFishingFunctionsInput['setNames']): Promise<import("../types").WebResponse<GuildFishingNames>>;
38
+ /** Custom catch line, appended to the catch card. `null` or `''` clears it. */
39
+ setCatchMessage({ auth, guildId, message }: GuildFishingFunctionsInput['setCatchMessage']): Promise<import("../types").WebResponse<{
40
+ message?: string;
41
+ cleared?: boolean;
42
+ }>>;
43
+ /**
44
+ * Reskin and reprice a built-in shop item.
45
+ *
46
+ * NAME AND PRICE ONLY — the effect, item type and stock scope always come from the built-in item.
47
+ * There is deliberately no way to supply an effect, and the price is clamped to 0.5x–2x the
48
+ * default (a free item cannot be repriced at all).
49
+ */
50
+ setShopItem({ auth, guildId, baseItemId, name, priceCoins }: GuildFishingFunctionsInput['setShopItem']): Promise<import("../types").WebResponse<GuildFishingShopItem>>;
51
+ /** Hide a custom shop item. Disables rather than deletes — players may already own it. */
52
+ disableShopItem({ auth, guildId, baseItemId }: GuildFishingFunctionsInput['disableShopItem']): Promise<import("../types").WebResponse<{
53
+ baseItemId: string;
54
+ disabled: true;
55
+ }>>;
56
+ /**
57
+ * Link the guild's server listing and issue a webhook secret.
58
+ *
59
+ * **top.gg only.** No other listing site exposes a verifiable per-user server-vote webhook —
60
+ * discords.com lists bots only, and neither Discadia nor DISBOARD publishes a contract. Any other
61
+ * `site` returns a 400 saying so.
62
+ *
63
+ * The response carries the URL and secret to paste into the listing. Note the secret is held by the
64
+ * owner, so this is a perk an owner can self-award; it is contained because voters receive
65
+ * **per-server coins only** — never XP, items or global progression.
66
+ */
67
+ linkListing({ auth, guildId, site }: GuildFishingFunctionsInput['linkListing']): Promise<import("../types").WebResponse<GuildFishingListing>>;
68
+ unlinkListing({ auth, guildId }: GuildFishingFunctionsInput['unlinkListing']): Promise<import("../types").WebResponse<{
69
+ unlinked: true;
70
+ }>>;
71
+ /** Webhook identity for fishing messages. **Premium Plus only** — Premium alone gets a 403. */
72
+ setWebhook({ auth, guildId, enabled, username, avatarUrl }: GuildFishingFunctionsInput['setWebhook']): Promise<import("../types").WebResponse<GuildFishingWebhook>>;
73
+ }
74
+ export type GuildFishingFunctionsInput = {
75
+ 'getCustomization': {
76
+ auth: string;
77
+ guildId: string;
78
+ };
79
+ 'setRarityTable': {
80
+ auth: string;
81
+ guildId: string;
82
+ weights: Record<string, number> | null;
83
+ };
84
+ 'setNames': {
85
+ auth: string;
86
+ guildId: string;
87
+ species?: Record<string, string> | null;
88
+ rarities?: Record<string, string> | null;
89
+ };
90
+ 'setCatchMessage': {
91
+ auth: string;
92
+ guildId: string;
93
+ message: string | null;
94
+ };
95
+ 'setShopItem': {
96
+ auth: string;
97
+ guildId: string;
98
+ baseItemId: string;
99
+ name?: string | null;
100
+ priceCoins?: number | null;
101
+ };
102
+ 'disableShopItem': {
103
+ auth: string;
104
+ guildId: string;
105
+ baseItemId: string;
106
+ };
107
+ 'linkListing': {
108
+ auth: string;
109
+ guildId: string;
110
+ site?: 'topgg';
111
+ };
112
+ 'unlinkListing': {
113
+ auth: string;
114
+ guildId: string;
115
+ };
116
+ 'setWebhook': {
117
+ auth: string;
118
+ guildId: string;
119
+ enabled?: boolean;
120
+ username?: string;
121
+ avatarUrl?: string;
122
+ };
123
+ };
124
+ export type GuildFishingGetReturnTypes = {
125
+ 'getCustomizationRaw': Awaited<ReturnType<APIGuildFishing['getCustomization']>>;
126
+ 'getCustomizationSuccess': CancelOutWebResponses<Awaited<ReturnType<APIGuildFishing['getCustomization']>>>;
127
+ 'setRarityTableRaw': Awaited<ReturnType<APIGuildFishing['setRarityTable']>>;
128
+ 'setRarityTableSuccess': CancelOutWebResponses<Awaited<ReturnType<APIGuildFishing['setRarityTable']>>>;
129
+ 'setNamesRaw': Awaited<ReturnType<APIGuildFishing['setNames']>>;
130
+ 'setNamesSuccess': CancelOutWebResponses<Awaited<ReturnType<APIGuildFishing['setNames']>>>;
131
+ 'setCatchMessageRaw': Awaited<ReturnType<APIGuildFishing['setCatchMessage']>>;
132
+ 'setCatchMessageSuccess': CancelOutWebResponses<Awaited<ReturnType<APIGuildFishing['setCatchMessage']>>>;
133
+ 'setShopItemRaw': Awaited<ReturnType<APIGuildFishing['setShopItem']>>;
134
+ 'setShopItemSuccess': CancelOutWebResponses<Awaited<ReturnType<APIGuildFishing['setShopItem']>>>;
135
+ 'disableShopItemRaw': Awaited<ReturnType<APIGuildFishing['disableShopItem']>>;
136
+ 'disableShopItemSuccess': CancelOutWebResponses<Awaited<ReturnType<APIGuildFishing['disableShopItem']>>>;
137
+ 'linkListingRaw': Awaited<ReturnType<APIGuildFishing['linkListing']>>;
138
+ 'linkListingSuccess': CancelOutWebResponses<Awaited<ReturnType<APIGuildFishing['linkListing']>>>;
139
+ 'unlinkListingRaw': Awaited<ReturnType<APIGuildFishing['unlinkListing']>>;
140
+ 'unlinkListingSuccess': CancelOutWebResponses<Awaited<ReturnType<APIGuildFishing['unlinkListing']>>>;
141
+ 'setWebhookRaw': Awaited<ReturnType<APIGuildFishing['setWebhook']>>;
142
+ 'setWebhookSuccess': CancelOutWebResponses<Awaited<ReturnType<APIGuildFishing['setWebhook']>>>;
143
+ };
144
+ /** A rarity weighting expressed as a multiplier against the default — "2x rare" reads, "0.0412" does not. */
145
+ export type GuildFishingWeighting = {
146
+ rarity: string;
147
+ multiplier: number;
148
+ };
149
+ export type GuildFishingShopItem = {
150
+ baseItemId: string;
151
+ name: string | null;
152
+ priceCoins: number | null;
153
+ enabled?: boolean;
154
+ };
155
+ export type GuildFishingCustomization = {
156
+ customRarityTable: Record<string, number> | null;
157
+ customSpeciesNames: Record<string, string> | null;
158
+ customRarityNames: Record<string, string> | null;
159
+ customCatchMessage: string | null;
160
+ webhookEnabled: boolean;
161
+ webhookUsername: string | null;
162
+ webhookAvatarUrl: string | null;
163
+ shopItems: GuildFishingShopItem[];
164
+ /** Shown to members — reweighting changes the game people are playing, so it is not invisible. */
165
+ weighting: GuildFishingWeighting[];
166
+ };
167
+ export type GuildFishingRarityTable = {
168
+ weights?: Record<string, number>;
169
+ weighting?: GuildFishingWeighting[];
170
+ cleared?: boolean;
171
+ };
172
+ export type GuildFishingNames = {
173
+ customSpeciesNames?: Record<string, string> | null;
174
+ customRarityNames?: Record<string, string> | null;
175
+ };
176
+ export type GuildFishingListing = {
177
+ site: 'topgg';
178
+ /** Paste into the listing's webhook settings alongside `webhookUrl`. */
179
+ secret: string;
180
+ webhookUrl: string;
181
+ instructions: string;
182
+ note: string;
183
+ };
184
+ export type GuildFishingWebhook = {
185
+ webhookEnabled?: boolean;
186
+ webhookUsername?: string | null;
187
+ webhookAvatarUrl?: string | null;
188
+ };
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.APIGuildFishing = void 0;
4
+ // Data.
5
+ /**
6
+ * Per-guild fishing customization (Premium) and the server-listing link.
7
+ *
8
+ * Every method here requires the caller to administer the guild AND the guild to hold the right
9
+ * entitlement — both enforced server-side, not merely hidden in the dashboard:
10
+ *
11
+ * `FishingCustomization` (Premium) — names, rarity table, catch message, shop items, listing
12
+ * `FishingWebhooks` (Premium Plus) — the webhook identity, matching every other webhook feature
13
+ *
14
+ * A Premium (non-Plus) guild gets a 403 from `setWebhook` despite passing every other check.
15
+ *
16
+ * **Customization never affects gameplay rates in a way that moves leaderboard standing.** Premium buys
17
+ * names, prices, messages and identity — the rarity table is the only thing touching the roll, and it
18
+ * is clamped to 0.5x–2x of the defaults, cannot reach `mythic`, and cannot zero a tier.
19
+ */
20
+ class APIGuildFishing {
21
+ web;
22
+ constructor(web) {
23
+ this.web = web;
24
+ }
25
+ /** The guild's full customization, including a member-facing summary of its rarity weighting. */
26
+ async getCustomization({ auth, guildId }) {
27
+ return await this.web.request({
28
+ method: 'GET', auth,
29
+ endpoint: this.web.qp(`/data/fishing/${guildId}/customization`),
30
+ });
31
+ }
32
+ /**
33
+ * Reweight the guild's rarity table, or pass `weights: null` to clear the override.
34
+ *
35
+ * **Rejects rather than clamps.** Out-of-band weights, `mythic`, and zeroing all return a 400 with
36
+ * per-field `issues` — an owner who typed 100 should learn it did not take, not quietly receive 2.
37
+ */
38
+ async setRarityTable({ auth, guildId, weights }) {
39
+ return await this.web.request({
40
+ method: 'PATCH', auth, body: { weights },
41
+ endpoint: this.web.qp(`/data/fishing/${guildId}/rarity-table`),
42
+ });
43
+ }
44
+ /**
45
+ * Rename species and/or rarity tiers for this guild.
46
+ *
47
+ * Display only — the catalogue itself stays global, so the codex, collections and the public API
48
+ * remain coherent across every server. A rename changes what a server *calls* a fish, never which
49
+ * fish exist.
50
+ */
51
+ async setNames({ auth, guildId, species, rarities }) {
52
+ return await this.web.request({
53
+ method: 'PATCH', auth, body: { species, rarities },
54
+ endpoint: this.web.qp(`/data/fishing/${guildId}/names`),
55
+ });
56
+ }
57
+ /** Custom catch line, appended to the catch card. `null` or `''` clears it. */
58
+ async setCatchMessage({ auth, guildId, message }) {
59
+ return await this.web.request({
60
+ method: 'PATCH', auth, body: { message },
61
+ endpoint: this.web.qp(`/data/fishing/${guildId}/catch-message`),
62
+ });
63
+ }
64
+ /**
65
+ * Reskin and reprice a built-in shop item.
66
+ *
67
+ * NAME AND PRICE ONLY — the effect, item type and stock scope always come from the built-in item.
68
+ * There is deliberately no way to supply an effect, and the price is clamped to 0.5x–2x the
69
+ * default (a free item cannot be repriced at all).
70
+ */
71
+ async setShopItem({ auth, guildId, baseItemId, name, priceCoins }) {
72
+ return await this.web.request({
73
+ method: 'PUT', auth, body: { name, priceCoins },
74
+ endpoint: this.web.qp(`/data/fishing/${guildId}/shop-items/${baseItemId}`),
75
+ });
76
+ }
77
+ /** Hide a custom shop item. Disables rather than deletes — players may already own it. */
78
+ async disableShopItem({ auth, guildId, baseItemId }) {
79
+ return await this.web.request({
80
+ method: 'DELETE', auth,
81
+ endpoint: this.web.qp(`/data/fishing/${guildId}/shop-items/${baseItemId}`),
82
+ });
83
+ }
84
+ /**
85
+ * Link the guild's server listing and issue a webhook secret.
86
+ *
87
+ * **top.gg only.** No other listing site exposes a verifiable per-user server-vote webhook —
88
+ * discords.com lists bots only, and neither Discadia nor DISBOARD publishes a contract. Any other
89
+ * `site` returns a 400 saying so.
90
+ *
91
+ * The response carries the URL and secret to paste into the listing. Note the secret is held by the
92
+ * owner, so this is a perk an owner can self-award; it is contained because voters receive
93
+ * **per-server coins only** — never XP, items or global progression.
94
+ */
95
+ async linkListing({ auth, guildId, site }) {
96
+ return await this.web.request({
97
+ method: 'PUT', auth, body: { site: site ?? 'topgg' },
98
+ endpoint: this.web.qp(`/data/fishing/${guildId}/listing`),
99
+ });
100
+ }
101
+ async unlinkListing({ auth, guildId }) {
102
+ return await this.web.request({
103
+ method: 'DELETE', auth,
104
+ endpoint: this.web.qp(`/data/fishing/${guildId}/listing`),
105
+ });
106
+ }
107
+ /** Webhook identity for fishing messages. **Premium Plus only** — Premium alone gets a 403. */
108
+ async setWebhook({ auth, guildId, enabled, username, avatarUrl }) {
109
+ return await this.web.request({
110
+ method: 'PATCH', auth, body: { enabled, username, avatarUrl },
111
+ endpoint: this.web.qp(`/data/fishing/${guildId}/webhook`),
112
+ });
113
+ }
114
+ }
115
+ exports.APIGuildFishing = APIGuildFishing;