@helyx/module-reactionroles 1.0.11 → 1.0.14
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/CHANGELOG.md +20 -0
- package/dist/index.js +0 -320
- package/manifest.json +24 -3
- package/migrations/0001_reactionroles_foundation.sql +60 -0
- package/package.json +3 -3
- package/migrations/0002_cleanup_retry_order.sql +0 -6
- package/migrations/0003_persistent_reactions.sql +0 -37
- package/migrations/0004_entry_lookup_indexes.sql +0 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @helyx/module-reactionroles
|
|
2
2
|
|
|
3
|
+
## 1.0.14
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Remove the Reaction Roles command root now that the dashboard Panels workspace owns panel creation and management.
|
|
8
|
+
|
|
9
|
+
## 1.0.13
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Consolidate the module database migration history into a clean one-file baseline for the planned database rebuild.
|
|
14
|
+
|
|
15
|
+
## 1.0.12
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [26b4c3e]
|
|
20
|
+
- @helyx/module-manifest@0.7.0
|
|
21
|
+
- @helyx/sdk@0.8.0
|
|
22
|
+
|
|
3
23
|
## 1.0.11
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -90,98 +90,6 @@ export const reactionRolesModule = defineModule({
|
|
|
90
90
|
},
|
|
91
91
|
records: reactionRoleRecords,
|
|
92
92
|
interactions: {
|
|
93
|
-
commands: [
|
|
94
|
-
{
|
|
95
|
-
name: "reaction-role",
|
|
96
|
-
description: "Create and manage Helyx role panels.",
|
|
97
|
-
registration: "global",
|
|
98
|
-
contexts: ["guild"],
|
|
99
|
-
integrationTypes: ["guild_install"],
|
|
100
|
-
subcommands: [
|
|
101
|
-
{
|
|
102
|
-
name: "create",
|
|
103
|
-
description: "Open the guided Reaction Roles builder.",
|
|
104
|
-
permissionId: "reactionroles.create",
|
|
105
|
-
options: [
|
|
106
|
-
{
|
|
107
|
-
type: "channel",
|
|
108
|
-
name: "channel",
|
|
109
|
-
description: "Prefill the destination channel.",
|
|
110
|
-
channelTypes: ["guild_text", "guild_announcement"],
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
type: "string",
|
|
114
|
-
name: "style",
|
|
115
|
-
description: "Prefill the public message style.",
|
|
116
|
-
choices: [
|
|
117
|
-
{ name: "Text", value: "text" },
|
|
118
|
-
{ name: "Embed", value: "embed" },
|
|
119
|
-
],
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
type: "string",
|
|
123
|
-
name: "control",
|
|
124
|
-
description: "Prefill how members choose roles.",
|
|
125
|
-
choices: [
|
|
126
|
-
{ name: "Buttons", value: "buttons" },
|
|
127
|
-
{ name: "Dropdown", value: "dropdown" },
|
|
128
|
-
{ name: "Emoji reactions", value: "reactions" },
|
|
129
|
-
],
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
type: "boolean",
|
|
133
|
-
name: "one-role-only",
|
|
134
|
-
description: "Allow each member to hold only one role from this panel.",
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
type: "boolean",
|
|
138
|
-
name: "persistent-reactions",
|
|
139
|
-
description: "Keep member reactions visible and synchronised with roles.",
|
|
140
|
-
},
|
|
141
|
-
],
|
|
142
|
-
rateLimit: { scope: "user", limit: 5, windowSeconds: 60 },
|
|
143
|
-
execute: startCreate,
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
name: "edit",
|
|
147
|
-
description: "Edit an existing role panel.",
|
|
148
|
-
permissionId: "reactionroles.manage",
|
|
149
|
-
options: [
|
|
150
|
-
referenceOption(),
|
|
151
|
-
{
|
|
152
|
-
type: "boolean",
|
|
153
|
-
name: "persistent-reactions",
|
|
154
|
-
description: "Keep member reactions visible and synchronised with roles.",
|
|
155
|
-
},
|
|
156
|
-
],
|
|
157
|
-
autocomplete: autocompletePanelReference,
|
|
158
|
-
execute: startEdit,
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
name: "list",
|
|
162
|
-
description: "List the active and degraded role panels.",
|
|
163
|
-
permissionId: "reactionroles.manage",
|
|
164
|
-
execute: listPanels,
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
name: "repair",
|
|
168
|
-
description: "Revalidate and repair a role panel.",
|
|
169
|
-
permissionId: "reactionroles.manage",
|
|
170
|
-
options: [referenceOption()],
|
|
171
|
-
autocomplete: autocompletePanelReference,
|
|
172
|
-
execute: repairPanel,
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
name: "delete",
|
|
176
|
-
description: "Delete a role panel without changing member roles.",
|
|
177
|
-
permissionId: "reactionroles.delete",
|
|
178
|
-
options: [referenceOption()],
|
|
179
|
-
autocomplete: autocompletePanelReference,
|
|
180
|
-
execute: prepareDelete,
|
|
181
|
-
},
|
|
182
|
-
],
|
|
183
|
-
},
|
|
184
|
-
],
|
|
185
93
|
buttons: [
|
|
186
94
|
{
|
|
187
95
|
customId: COMPONENT_IDS.continueDraft,
|
|
@@ -427,43 +335,6 @@ export const reactionRolesModule = defineModule({
|
|
|
427
335
|
},
|
|
428
336
|
health: () => ({ status: healthStatus, message: healthMessage }),
|
|
429
337
|
});
|
|
430
|
-
async function startCreate(context) {
|
|
431
|
-
const guildId = requireGuild(context);
|
|
432
|
-
const channel = context.getChannelOption("channel");
|
|
433
|
-
const style = context.getStringOption("style");
|
|
434
|
-
const control = context.getStringOption("control");
|
|
435
|
-
const sessions = sessionService(context.services);
|
|
436
|
-
const nextState = {
|
|
437
|
-
mode: "create",
|
|
438
|
-
selectionMode: context.getBooleanOption("one-role-only") === true
|
|
439
|
-
? "one_only"
|
|
440
|
-
: "multiple",
|
|
441
|
-
persistentReactions: context.getBooleanOption("persistent-reactions") !== false,
|
|
442
|
-
...(channel ? { channelId: channel.id } : {}),
|
|
443
|
-
...(style ? { messageStyle: requiredStyle([style]) } : {}),
|
|
444
|
-
...(control ? { controlType: requiredControl([control]) } : {}),
|
|
445
|
-
};
|
|
446
|
-
const existing = await sessions.getFor(guildId, context.userId, PANEL_PURPOSE);
|
|
447
|
-
if (existing) {
|
|
448
|
-
await sessions.update({
|
|
449
|
-
sessionId: existing.sessionId,
|
|
450
|
-
state: { ...existing.state, pendingReplacement: nextState },
|
|
451
|
-
expectedVersion: existing.version,
|
|
452
|
-
expiresAt: expiresAt(),
|
|
453
|
-
});
|
|
454
|
-
await context.reply(existingDraftResponse());
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
457
|
-
await sessions.create({
|
|
458
|
-
guildId,
|
|
459
|
-
userId: context.userId,
|
|
460
|
-
purpose: PANEL_PURPOSE,
|
|
461
|
-
state: nextState,
|
|
462
|
-
expiresAt: expiresAt(),
|
|
463
|
-
replace: true,
|
|
464
|
-
});
|
|
465
|
-
await context.showModal(basicModal(defaultsFromSessionState(nextState)));
|
|
466
|
-
}
|
|
467
338
|
async function continueDraft(context) {
|
|
468
339
|
const guildId = requireGuild(context);
|
|
469
340
|
const session = await sessionService(context.services).getFor(guildId, context.userId, PANEL_PURPOSE);
|
|
@@ -520,108 +391,6 @@ async function keepDraft(context) {
|
|
|
520
391
|
},
|
|
521
392
|
});
|
|
522
393
|
}
|
|
523
|
-
async function startEdit(context) {
|
|
524
|
-
const guildId = requireGuild(context);
|
|
525
|
-
const panel = await findPanelReference(context.services, guildId, context.getStringOption("reference"));
|
|
526
|
-
const persistentReactions = context.getBooleanOption("persistent-reactions");
|
|
527
|
-
const draft = persistentReactions === null
|
|
528
|
-
? panel
|
|
529
|
-
: validatePanelDraft({ ...panel, persistentReactions });
|
|
530
|
-
await sessionService(context.services).create({
|
|
531
|
-
guildId,
|
|
532
|
-
userId: context.userId,
|
|
533
|
-
purpose: PANEL_PURPOSE,
|
|
534
|
-
state: {
|
|
535
|
-
mode: "edit",
|
|
536
|
-
panelId: panel.panelId,
|
|
537
|
-
expectedRevision: panel.revision,
|
|
538
|
-
draft: serializeDraft(draft),
|
|
539
|
-
},
|
|
540
|
-
expiresAt: expiresAt(),
|
|
541
|
-
replace: true,
|
|
542
|
-
});
|
|
543
|
-
await context.showModal(basicModal(draft, true));
|
|
544
|
-
}
|
|
545
|
-
async function listPanels(context) {
|
|
546
|
-
const guildId = requireGuild(context);
|
|
547
|
-
const result = await panels.repository(context.services).list({
|
|
548
|
-
guildId,
|
|
549
|
-
limit: 10,
|
|
550
|
-
});
|
|
551
|
-
await context.reply({
|
|
552
|
-
ephemeral: true,
|
|
553
|
-
componentsV2: {
|
|
554
|
-
text: [
|
|
555
|
-
{
|
|
556
|
-
content: result.panels.length === 0
|
|
557
|
-
? "No Reaction Roles panels have been created."
|
|
558
|
-
: result.panels
|
|
559
|
-
.map((panel) => `**${panel.title}** · \`${panel.panelId}\` · ${panel.status} · revision ${panel.revision}`)
|
|
560
|
-
.join("\n"),
|
|
561
|
-
},
|
|
562
|
-
],
|
|
563
|
-
},
|
|
564
|
-
allowedUserMentionIds: [],
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
|
-
async function repairPanel(context) {
|
|
568
|
-
const guildId = requireGuild(context);
|
|
569
|
-
await context.deferReply?.(true);
|
|
570
|
-
const panel = await findPanelReference(context.services, guildId, context.getStringOption("reference"));
|
|
571
|
-
const repaired = await panels.repair(interactionMutationContext(context, guildId), panel.panelId, panel.revision, false);
|
|
572
|
-
await context.reply({
|
|
573
|
-
ephemeral: true,
|
|
574
|
-
componentsV2: {
|
|
575
|
-
text: [
|
|
576
|
-
{
|
|
577
|
-
content: `Role panel **${repaired.title}** is active at revision ${repaired.revision}.`,
|
|
578
|
-
},
|
|
579
|
-
],
|
|
580
|
-
},
|
|
581
|
-
allowedUserMentionIds: [],
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
|
-
async function prepareDelete(context) {
|
|
585
|
-
const guildId = requireGuild(context);
|
|
586
|
-
const panel = await findPanelReference(context.services, guildId, context.getStringOption("reference"));
|
|
587
|
-
await sessionService(context.services).create({
|
|
588
|
-
guildId,
|
|
589
|
-
userId: context.userId,
|
|
590
|
-
purpose: PANEL_PURPOSE,
|
|
591
|
-
state: {
|
|
592
|
-
mode: "delete",
|
|
593
|
-
panelId: panel.panelId,
|
|
594
|
-
expectedRevision: panel.revision,
|
|
595
|
-
},
|
|
596
|
-
expiresAt: expiresAt(),
|
|
597
|
-
replace: true,
|
|
598
|
-
});
|
|
599
|
-
await context.reply({
|
|
600
|
-
ephemeral: true,
|
|
601
|
-
componentsV2: {
|
|
602
|
-
text: [
|
|
603
|
-
{
|
|
604
|
-
content: `Delete **${panel.title}**? Helyx will try to remove its panel message. Existing member roles will not change.`,
|
|
605
|
-
},
|
|
606
|
-
],
|
|
607
|
-
},
|
|
608
|
-
buttons: [
|
|
609
|
-
{
|
|
610
|
-
type: "button",
|
|
611
|
-
customId: COMPONENT_IDS.deleteConfirm,
|
|
612
|
-
label: "Delete role panel",
|
|
613
|
-
style: "danger",
|
|
614
|
-
},
|
|
615
|
-
{
|
|
616
|
-
type: "button",
|
|
617
|
-
customId: COMPONENT_IDS.cancel,
|
|
618
|
-
label: "Keep role panel",
|
|
619
|
-
style: "secondary",
|
|
620
|
-
},
|
|
621
|
-
],
|
|
622
|
-
allowedUserMentionIds: [],
|
|
623
|
-
});
|
|
624
|
-
}
|
|
625
394
|
async function saveBasicDraft(context) {
|
|
626
395
|
const guildId = requireGuild(context);
|
|
627
396
|
const sessions = sessionService(context.services);
|
|
@@ -1199,39 +968,6 @@ function basicModal(panel, editing = false) {
|
|
|
1199
968
|
],
|
|
1200
969
|
};
|
|
1201
970
|
}
|
|
1202
|
-
function existingDraftResponse() {
|
|
1203
|
-
return {
|
|
1204
|
-
ephemeral: true,
|
|
1205
|
-
componentsV2: {
|
|
1206
|
-
text: [
|
|
1207
|
-
{
|
|
1208
|
-
content: "You already have a Reaction Roles draft. Continue it or replace it with a new draft.",
|
|
1209
|
-
},
|
|
1210
|
-
],
|
|
1211
|
-
},
|
|
1212
|
-
buttons: [
|
|
1213
|
-
{
|
|
1214
|
-
type: "button",
|
|
1215
|
-
customId: COMPONENT_IDS.continueDraft,
|
|
1216
|
-
label: "Continue draft",
|
|
1217
|
-
style: "primary",
|
|
1218
|
-
},
|
|
1219
|
-
{
|
|
1220
|
-
type: "button",
|
|
1221
|
-
customId: COMPONENT_IDS.replaceDraft,
|
|
1222
|
-
label: "Replace draft",
|
|
1223
|
-
style: "danger",
|
|
1224
|
-
},
|
|
1225
|
-
{
|
|
1226
|
-
type: "button",
|
|
1227
|
-
customId: COMPONENT_IDS.keepDraft,
|
|
1228
|
-
label: "Cancel",
|
|
1229
|
-
style: "secondary",
|
|
1230
|
-
},
|
|
1231
|
-
],
|
|
1232
|
-
allowedUserMentionIds: [],
|
|
1233
|
-
};
|
|
1234
|
-
}
|
|
1235
971
|
function defaultsFromSessionState(state) {
|
|
1236
972
|
return {
|
|
1237
973
|
...(typeof state.channelId === "string"
|
|
@@ -1397,62 +1133,6 @@ function interactionMutationContext(context, guildId) {
|
|
|
1397
1133
|
addChannelMessageReaction: (channelId, messageId, emojiIdentifier) => context.addChannelMessageReaction(channelId, messageId, emojiIdentifier),
|
|
1398
1134
|
};
|
|
1399
1135
|
}
|
|
1400
|
-
async function findPanelReference(services, guildId, value) {
|
|
1401
|
-
const reference = value?.trim();
|
|
1402
|
-
if (!reference)
|
|
1403
|
-
throw new Error("Role panel reference is required");
|
|
1404
|
-
const panel = await panels.repository(services).findById(guildId, reference);
|
|
1405
|
-
if (!panel)
|
|
1406
|
-
throw new Error("Role panel was not found");
|
|
1407
|
-
return panel;
|
|
1408
|
-
}
|
|
1409
|
-
async function autocompletePanelReference(context) {
|
|
1410
|
-
if (!context.serverId || context.focusedOptionName !== "reference") {
|
|
1411
|
-
await context.respond([]);
|
|
1412
|
-
return;
|
|
1413
|
-
}
|
|
1414
|
-
const query = context.focusedValue.trim().normalize("NFKC").toLowerCase();
|
|
1415
|
-
const repository = panels.repository(context.services);
|
|
1416
|
-
const choices = [];
|
|
1417
|
-
let cursor;
|
|
1418
|
-
for (let pageNumber = 0; pageNumber < 5 && choices.length < 25; pageNumber += 1) {
|
|
1419
|
-
const page = await repository.listReferences({
|
|
1420
|
-
guildId: context.serverId,
|
|
1421
|
-
...(cursor ? { cursor } : {}),
|
|
1422
|
-
limit: query ? 100 : 25,
|
|
1423
|
-
});
|
|
1424
|
-
for (const panel of page.panels) {
|
|
1425
|
-
if (panel.status === "deleting")
|
|
1426
|
-
continue;
|
|
1427
|
-
const searchable = `${panel.title} ${panel.panelId} ${panel.status}`.toLowerCase();
|
|
1428
|
-
if (query && !searchable.includes(query))
|
|
1429
|
-
continue;
|
|
1430
|
-
const title = panel.title.replaceAll(/\s+/gu, " ").trim();
|
|
1431
|
-
const suffix = `${panel.status} · ${panel.panelId.slice(0, 8)}`;
|
|
1432
|
-
choices.push({
|
|
1433
|
-
name: `${title.slice(0, Math.max(1, 97 - suffix.length))} · ${suffix}`,
|
|
1434
|
-
value: panel.panelId,
|
|
1435
|
-
});
|
|
1436
|
-
if (choices.length === 25)
|
|
1437
|
-
break;
|
|
1438
|
-
}
|
|
1439
|
-
if (!query || !page.nextCursor)
|
|
1440
|
-
break;
|
|
1441
|
-
cursor = page.nextCursor;
|
|
1442
|
-
}
|
|
1443
|
-
await context.respond(choices);
|
|
1444
|
-
}
|
|
1445
|
-
function referenceOption() {
|
|
1446
|
-
return {
|
|
1447
|
-
type: "string",
|
|
1448
|
-
name: "reference",
|
|
1449
|
-
description: "Panel reference shown by /reaction-role list.",
|
|
1450
|
-
required: true,
|
|
1451
|
-
minLength: 1,
|
|
1452
|
-
maxLength: 100,
|
|
1453
|
-
autocomplete: true,
|
|
1454
|
-
};
|
|
1455
|
-
}
|
|
1456
1136
|
function sessionService(services) {
|
|
1457
1137
|
return services.get(HELYX_SERVICE_NAMES.sessions);
|
|
1458
1138
|
}
|
package/manifest.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"releaseStatus": "live",
|
|
4
4
|
"id": "helyx.reactionroles",
|
|
5
5
|
"name": "Reaction Roles",
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.14",
|
|
7
7
|
"description": "Let members select approved roles themselves.",
|
|
8
8
|
"entry": "./dist/index.js",
|
|
9
9
|
"framework": "^0.1.0",
|
|
@@ -283,10 +283,31 @@
|
|
|
283
283
|
}
|
|
284
284
|
]
|
|
285
285
|
}
|
|
286
|
-
]
|
|
286
|
+
],
|
|
287
|
+
"workspace": {
|
|
288
|
+
"type": "managed_resources_v1",
|
|
289
|
+
"settings": [
|
|
290
|
+
{
|
|
291
|
+
"resources": ["panels"],
|
|
292
|
+
"mode": "create-only"
|
|
293
|
+
}
|
|
294
|
+
],
|
|
295
|
+
"tabs": [
|
|
296
|
+
{
|
|
297
|
+
"id": "panels",
|
|
298
|
+
"label": "Panels",
|
|
299
|
+
"panels": [
|
|
300
|
+
{
|
|
301
|
+
"resources": ["panels"],
|
|
302
|
+
"mode": "list-only"
|
|
303
|
+
}
|
|
304
|
+
]
|
|
305
|
+
}
|
|
306
|
+
]
|
|
307
|
+
}
|
|
287
308
|
},
|
|
288
309
|
"contributions": {
|
|
289
|
-
"commands": [
|
|
310
|
+
"commands": [],
|
|
290
311
|
"events": [
|
|
291
312
|
"discord.channel-delete",
|
|
292
313
|
"discord.channel-update",
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
-- Baseline source: 0001_reactionroles_foundation.sql
|
|
2
|
+
|
|
1
3
|
CREATE TABLE IF NOT EXISTS reactionroles_panels (
|
|
2
4
|
panel_id text PRIMARY KEY,
|
|
3
5
|
guild_id text NOT NULL,
|
|
@@ -106,3 +108,61 @@ CREATE UNIQUE INDEX IF NOT EXISTS reactionroles_cleanup_message_reason_idx
|
|
|
106
108
|
message_id,
|
|
107
109
|
reason
|
|
108
110
|
);
|
|
111
|
+
|
|
112
|
+
-- Baseline source: 0002_cleanup_retry_order.sql
|
|
113
|
+
|
|
114
|
+
UPDATE reactionroles_message_cleanup
|
|
115
|
+
SET next_attempt_at = created_at
|
|
116
|
+
WHERE next_attempt_at IS NULL;
|
|
117
|
+
|
|
118
|
+
ALTER TABLE reactionroles_message_cleanup
|
|
119
|
+
ALTER COLUMN next_attempt_at SET NOT NULL;
|
|
120
|
+
|
|
121
|
+
-- Baseline source: 0003_persistent_reactions.sql
|
|
122
|
+
|
|
123
|
+
ALTER TABLE reactionroles_panels
|
|
124
|
+
ADD COLUMN IF NOT EXISTS persistent_reactions boolean NOT NULL DEFAULT true;
|
|
125
|
+
|
|
126
|
+
DO $$
|
|
127
|
+
DECLARE
|
|
128
|
+
constraint_name text;
|
|
129
|
+
BEGIN
|
|
130
|
+
FOR constraint_name IN
|
|
131
|
+
SELECT conname
|
|
132
|
+
FROM pg_constraint
|
|
133
|
+
WHERE conrelid = 'reactionroles_panels'::regclass
|
|
134
|
+
AND contype = 'c'
|
|
135
|
+
AND conname <> 'reactionroles_panels_reaction_selection_check'
|
|
136
|
+
AND pg_get_constraintdef(oid) LIKE '%control_type%reactions%selection_mode%'
|
|
137
|
+
LOOP
|
|
138
|
+
EXECUTE format(
|
|
139
|
+
'ALTER TABLE reactionroles_panels DROP CONSTRAINT %I',
|
|
140
|
+
constraint_name
|
|
141
|
+
);
|
|
142
|
+
END LOOP;
|
|
143
|
+
|
|
144
|
+
IF NOT EXISTS (
|
|
145
|
+
SELECT 1
|
|
146
|
+
FROM pg_constraint
|
|
147
|
+
WHERE conrelid = 'reactionroles_panels'::regclass
|
|
148
|
+
AND conname = 'reactionroles_panels_reaction_selection_check'
|
|
149
|
+
) THEN
|
|
150
|
+
ALTER TABLE reactionroles_panels
|
|
151
|
+
ADD CONSTRAINT reactionroles_panels_reaction_selection_check
|
|
152
|
+
CHECK (
|
|
153
|
+
control_type <> 'reactions'
|
|
154
|
+
OR selection_mode <> 'one_only'
|
|
155
|
+
OR persistent_reactions = false
|
|
156
|
+
);
|
|
157
|
+
END IF;
|
|
158
|
+
END
|
|
159
|
+
$$;
|
|
160
|
+
|
|
161
|
+
-- Baseline source: 0004_entry_lookup_indexes.sql
|
|
162
|
+
|
|
163
|
+
CREATE INDEX IF NOT EXISTS reactionroles_entries_role_panel_idx
|
|
164
|
+
ON reactionroles_entries (role_id, panel_id);
|
|
165
|
+
|
|
166
|
+
CREATE INDEX IF NOT EXISTS reactionroles_entries_emoji_panel_idx
|
|
167
|
+
ON reactionroles_entries (emoji_id, panel_id)
|
|
168
|
+
WHERE emoji_id IS NOT NULL;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helyx/module-reactionroles",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"description": "Configurable self-service Discord role panels for Helyx.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"helyx",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"build": "tsc -b"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@helyx/module-manifest": ">=0.
|
|
53
|
-
"@helyx/sdk": ">=0.
|
|
52
|
+
"@helyx/module-manifest": ">=0.7.0 <0.8.0",
|
|
53
|
+
"@helyx/sdk": ">=0.8.4 <0.9.0"
|
|
54
54
|
}
|
|
55
55
|
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
ALTER TABLE reactionroles_panels
|
|
2
|
-
ADD COLUMN IF NOT EXISTS persistent_reactions boolean NOT NULL DEFAULT true;
|
|
3
|
-
|
|
4
|
-
DO $$
|
|
5
|
-
DECLARE
|
|
6
|
-
constraint_name text;
|
|
7
|
-
BEGIN
|
|
8
|
-
FOR constraint_name IN
|
|
9
|
-
SELECT conname
|
|
10
|
-
FROM pg_constraint
|
|
11
|
-
WHERE conrelid = 'reactionroles_panels'::regclass
|
|
12
|
-
AND contype = 'c'
|
|
13
|
-
AND conname <> 'reactionroles_panels_reaction_selection_check'
|
|
14
|
-
AND pg_get_constraintdef(oid) LIKE '%control_type%reactions%selection_mode%'
|
|
15
|
-
LOOP
|
|
16
|
-
EXECUTE format(
|
|
17
|
-
'ALTER TABLE reactionroles_panels DROP CONSTRAINT %I',
|
|
18
|
-
constraint_name
|
|
19
|
-
);
|
|
20
|
-
END LOOP;
|
|
21
|
-
|
|
22
|
-
IF NOT EXISTS (
|
|
23
|
-
SELECT 1
|
|
24
|
-
FROM pg_constraint
|
|
25
|
-
WHERE conrelid = 'reactionroles_panels'::regclass
|
|
26
|
-
AND conname = 'reactionroles_panels_reaction_selection_check'
|
|
27
|
-
) THEN
|
|
28
|
-
ALTER TABLE reactionroles_panels
|
|
29
|
-
ADD CONSTRAINT reactionroles_panels_reaction_selection_check
|
|
30
|
-
CHECK (
|
|
31
|
-
control_type <> 'reactions'
|
|
32
|
-
OR selection_mode <> 'one_only'
|
|
33
|
-
OR persistent_reactions = false
|
|
34
|
-
);
|
|
35
|
-
END IF;
|
|
36
|
-
END
|
|
37
|
-
$$;
|