@kevlid/discordmenus 0.1.2 → 0.1.3
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.
- package/index.d.ts +5 -0
- package/package.json +1 -1
- package/src/handle/component.js +14 -1
- package/src/index.js +4 -1
- package/src/menuInstance.js +3 -2
- package/src/utils/adapters.js +9 -1
- package/src/utils/formatKey.js +46 -1
package/index.d.ts
CHANGED
|
@@ -257,3 +257,8 @@ export declare function normalizeInteraction(
|
|
|
257
257
|
): DiscordInteraction;
|
|
258
258
|
export declare function fromEris(interaction: DiscordInteraction): DiscordInteraction;
|
|
259
259
|
export declare function fromDiscordJS(interaction: DiscordInteraction): DiscordInteraction;
|
|
260
|
+
|
|
261
|
+
/** Encode option/menu keys for custom IDs (uppercase → _lowercase, spaces → _). */
|
|
262
|
+
export declare function formatKey(key: string): string;
|
|
263
|
+
/** Restore original key before get/save callbacks (inverse of formatKey). */
|
|
264
|
+
export declare function decodeKey(encoded: string): string;
|
package/package.json
CHANGED
package/src/handle/component.js
CHANGED
|
@@ -365,7 +365,20 @@ async function handleComponent(interaction, menu, menu_key, renderMenu) {
|
|
|
365
365
|
const opt = menu.getOption(category, page, optionKey);
|
|
366
366
|
const maxSel = Number(opt?.maxValues);
|
|
367
367
|
const multi = Number.isFinite(maxSel) && maxSel > 1;
|
|
368
|
-
|
|
368
|
+
let saveValue = multi ? [...selected] : selected[0] ?? null;
|
|
369
|
+
if (
|
|
370
|
+
!multi &&
|
|
371
|
+
saveValue == null &&
|
|
372
|
+
opt?.type === OptionTypes.StringSelect &&
|
|
373
|
+
Number(opt.minValues ?? 1) >= 1 &&
|
|
374
|
+
Array.isArray(opt.choices) &&
|
|
375
|
+
opt.choices.length === 1
|
|
376
|
+
) {
|
|
377
|
+
const only = opt.choices[0]?.value;
|
|
378
|
+
if (only != null && only !== "") {
|
|
379
|
+
saveValue = only;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
369
382
|
await menu.save(optionKey, saveValue, { guildId, userId });
|
|
370
383
|
result = updateMessage(
|
|
371
384
|
await renderMenu(menu_key, { category, index: page, userId, guildId }),
|
package/src/index.js
CHANGED
|
@@ -4,6 +4,7 @@ const { OptionTypes } = require("./utils/types");
|
|
|
4
4
|
const { CustomIdPrefix, EphemeralMessageFlag } = require("./utils/constants");
|
|
5
5
|
const { MenuStorage, MemoryMenuStorage } = require("./utils/storage");
|
|
6
6
|
const { normalizeInteraction, fromEris, fromDiscordJS } = require("./utils/adapters");
|
|
7
|
+
const { formatKey, decodeKey } = require("./utils/formatKey");
|
|
7
8
|
|
|
8
9
|
module.exports = {
|
|
9
10
|
MenuManager,
|
|
@@ -16,4 +17,6 @@ module.exports = {
|
|
|
16
17
|
normalizeInteraction,
|
|
17
18
|
fromEris,
|
|
18
19
|
fromDiscordJS,
|
|
19
|
-
|
|
20
|
+
formatKey,
|
|
21
|
+
decodeKey,
|
|
22
|
+
};
|
package/src/menuInstance.js
CHANGED
|
@@ -6,6 +6,7 @@ const { OptionTypes } = require("./utils/types");
|
|
|
6
6
|
const { PageRenderOverhead, OptionRenderCost, MaxComponents, ComponentsV2MessageFlags } = require("./utils/constants");
|
|
7
7
|
const { validateComponents } = require("./utils/componentsValidate");
|
|
8
8
|
const { arrayClone, normalizeObjectListItems, objectListItemsNeedReshape } = require("./utils/helpers");
|
|
9
|
+
const { decodeKey } = require("./utils/formatKey");
|
|
9
10
|
|
|
10
11
|
class MenuInstance {
|
|
11
12
|
constructor(builder, options = {}) {
|
|
@@ -41,11 +42,11 @@ class MenuInstance {
|
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
async get(key, ctx = {}) {
|
|
44
|
-
return this.getData(key, ctx);
|
|
45
|
+
return this.getData(decodeKey(key), ctx);
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
async save(key, value, ctx = {}) {
|
|
48
|
-
return this.saveData(key, value, ctx);
|
|
49
|
+
return this.saveData(decodeKey(key), value, ctx);
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
ensureBuilt() {
|
package/src/utils/adapters.js
CHANGED
|
@@ -37,7 +37,15 @@ function normalizeInteraction(interaction) {
|
|
|
37
37
|
customId = source.id;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
// Prefer live interaction: toJSON() often omits or strips data.values for select menus,
|
|
41
|
+
// which breaks saves (especially single-value selects).
|
|
42
|
+
let values = interaction?.data?.values;
|
|
43
|
+
if (!Array.isArray(values) && interaction != null && typeof interaction.values !== "undefined") {
|
|
44
|
+
values = interaction.values;
|
|
45
|
+
}
|
|
46
|
+
if (!Array.isArray(values)) {
|
|
47
|
+
values = source.data?.values ?? source.values ?? [];
|
|
48
|
+
}
|
|
41
49
|
if (!Array.isArray(values)) {
|
|
42
50
|
values = [];
|
|
43
51
|
}
|
package/src/utils/formatKey.js
CHANGED
|
@@ -1 +1,46 @@
|
|
|
1
|
-
function formatKey(key) {
|
|
2
1
|
if (typeof key !== "string") throw new TypeError("Key must be a string");
|
|
3
2
|
return key.toLowerCase().replace(" ", "_");
|
|
4
3
|
formatKey
|
|
4
|
+
/**
|
|
5
|
+
* Encodes a key for custom IDs (Discord is case-insensitive in some paths; this keeps uniqueness).
|
|
6
|
+
* Each uppercase letter becomes "_" + its lowercase form (e.g. guildId → guild_id).
|
|
7
|
+
* Spaces become "_".
|
|
8
|
+
* Lowercase letters, digits, and underscores are kept as-is (underscores are not escaped).
|
|
9
|
+
*/
|
|
10
|
+
function formatKey(key) {
|
|
11
|
+
if (typeof key !== "string") throw new TypeError("Key must be a string");
|
|
12
|
+
const s = String(key).replace(/ /g, "_");
|
|
13
|
+
let out = "";
|
|
14
|
+
for (const c of s) {
|
|
15
|
+
if (c >= "A" && c <= "Z") {
|
|
16
|
+
out += "_" + c.toLowerCase();
|
|
17
|
+
} else {
|
|
18
|
+
out += c;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Reverses formatKey: "_" followed by a-z becomes A–Z. Literal "_" + letter in keys that were
|
|
26
|
+
* not produced by an uppercase letter may decode incorrectly; prefer camelCase/PascalCase keys.
|
|
27
|
+
*/
|
|
28
|
+
function decodeKey(encoded) {
|
|
29
|
+
if (typeof encoded !== "string") throw new TypeError("Key must be a string");
|
|
30
|
+
let out = "";
|
|
31
|
+
for (let i = 0; i < encoded.length; i++) {
|
|
32
|
+
const c = encoded[i];
|
|
33
|
+
if (c === "_" && i + 1 < encoded.length) {
|
|
34
|
+
const next = encoded[i + 1];
|
|
35
|
+
if (next >= "a" && next <= "z") {
|
|
36
|
+
out += next.toUpperCase();
|
|
37
|
+
i++;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
out += c;
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = {
|
|
47
|
+
formatKey,
|
|
48
|
+
decodeKey,
|
|
49
|
+
};
|