@helyx/module-reactionroles 1.0.21 → 1.1.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.
- package/CHANGELOG.md +22 -19
- package/README.md +1 -1
- package/dist/panel-lifecycle.js +14 -2
- package/manifest.json +3 -2
- package/migrations-mysql/0001_reactionroles_foundation.sql +89 -0
- package/package.json +5 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @helyx/module-reactionroles
|
|
2
2
|
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Prepare the coordinated Phase 8 minor release and align internal package dependencies. Existing deployment and database-support restrictions are unchanged.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Defer owned-message recovery until Discord is ready so restarts do not consume cleanup retries before login.
|
|
12
|
+
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
- @helyx/module-manifest@0.13.0
|
|
15
|
+
- @helyx/sdk@0.15.0
|
|
16
|
+
|
|
17
|
+
## 1.0.22
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- Bound internal dependencies to compatible releases while preserving each
|
|
22
|
+
consumer's required minimum API version.
|
|
23
|
+
|
|
3
24
|
## 1.0.21
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
|
@@ -97,25 +118,7 @@
|
|
|
97
118
|
|
|
98
119
|
### Patch Changes
|
|
99
120
|
|
|
100
|
-
- Accept compatible internal Helyx releases within explicit minor-safe pre-1.0 or major-safe stable ranges, preventing dependency-only patch cascades
|
|
101
|
-
"@helyx/bot": patch
|
|
102
|
-
"@helyx/cli": patch
|
|
103
|
-
"@helyx/core": patch
|
|
104
|
-
"@helyx/framework": patch
|
|
105
|
-
"@helyx/platform": patch
|
|
106
|
-
"@helyx/sdk": patch
|
|
107
|
-
"@helyx/module-account-gate": patch
|
|
108
|
-
"@helyx/module-feedback": patch
|
|
109
|
-
"@helyx/module-giveaways": patch
|
|
110
|
-
"@helyx/module-levels": patch
|
|
111
|
-
"@helyx/module-logging": patch
|
|
112
|
-
"@helyx/module-polls": patch
|
|
113
|
-
"@helyx/module-reactionroles": patch
|
|
114
|
-
"@helyx/module-suggestions": patch
|
|
115
|
-
"@helyx/module-welcome": patch
|
|
116
|
-
---
|
|
117
|
-
|
|
118
|
-
Accept compatible internal Helyx releases within explicit minor-safe pre-1.0 or major-safe stable ranges, preventing dependency-only patch cascades.
|
|
121
|
+
- Accept compatible internal Helyx releases within explicit minor-safe pre-1.0 or major-safe stable ranges, preventing dependency-only patch cascades.
|
|
119
122
|
|
|
120
123
|
## 1.0.8
|
|
121
124
|
|
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ Helyx stores panel and entry configuration, Helyx-owned message references, life
|
|
|
28
28
|
|
|
29
29
|
## Operations and failure behavior
|
|
30
30
|
|
|
31
|
-
Every owned-message cleanup record atomically schedules a bounded one-shot retry through the core scheduler
|
|
31
|
+
Every owned-message cleanup record atomically schedules a bounded one-shot retry through the core scheduler. Startup reconciles paginated pending work when Discord is ready and warms the bounded active-panel cache; otherwise the normal worker handles cleanup after connection without consuming a pre-login attempt. Exhausted cleanup remains durable for operator review. Unknown message reactions use a short negative cache and coalesced lookups. Deleted or invalid Discord resources move affected panels to `message_missing` or `needs_attention`; repair or repost restores them. Health is unhealthy while stopped, when required services are missing, or after a recent primary operation failure, and degraded for cold-cache startup, cache saturation, or pending cleanup failure.
|
|
32
32
|
|
|
33
33
|
Disablement stops new interactions without deleting configuration. Re-enable only after checking channel access, role hierarchy, and emoji availability. Rollback may restore compatible application code, but must not reverse migrations or delete panel data.
|
|
34
34
|
|
package/dist/panel-lifecycle.js
CHANGED
|
@@ -31,8 +31,10 @@ export class PanelLifecycleService {
|
|
|
31
31
|
async recoverMessageCleanup(services) {
|
|
32
32
|
if (!services.has(HELYX_SERVICE_NAMES.discordOwnedMessages))
|
|
33
33
|
return { completed: 0, failed: 0, abandoned: 0 };
|
|
34
|
-
const repository = this.repositoryFor(services);
|
|
35
34
|
const messages = services.get(HELYX_SERVICE_NAMES.discordOwnedMessages);
|
|
35
|
+
if (messages.isReady?.() === false)
|
|
36
|
+
return { completed: 0, failed: 0, abandoned: 0 };
|
|
37
|
+
const repository = this.repositoryFor(services);
|
|
36
38
|
let completed = 0;
|
|
37
39
|
let failed = 0;
|
|
38
40
|
let abandoned = 0;
|
|
@@ -75,6 +77,16 @@ export class PanelLifecycleService {
|
|
|
75
77
|
},
|
|
76
78
|
recovered: false,
|
|
77
79
|
};
|
|
80
|
+
const messages = services.get(HELYX_SERVICE_NAMES.discordOwnedMessages);
|
|
81
|
+
if (messages.isReady?.() === false)
|
|
82
|
+
return {
|
|
83
|
+
result: {
|
|
84
|
+
outcome: "deferred",
|
|
85
|
+
delayMs: 60_000,
|
|
86
|
+
safeCode: "reaction_role_cleanup_discord_not_ready",
|
|
87
|
+
},
|
|
88
|
+
recovered: false,
|
|
89
|
+
};
|
|
78
90
|
const repository = this.repositoryFor(services);
|
|
79
91
|
let cleanup;
|
|
80
92
|
try {
|
|
@@ -134,7 +146,7 @@ export class PanelLifecycleService {
|
|
|
134
146
|
recovered: false,
|
|
135
147
|
};
|
|
136
148
|
try {
|
|
137
|
-
await this.completeClaimedCleanup(repository,
|
|
149
|
+
await this.completeClaimedCleanup(repository, messages, claimed);
|
|
138
150
|
return { result: { outcome: "completed" }, recovered: true };
|
|
139
151
|
}
|
|
140
152
|
catch {
|
package/manifest.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifestVersion": "0.4",
|
|
3
|
+
"databaseEngines": ["postgresql", "mysql"],
|
|
3
4
|
"releaseStatus": "live",
|
|
4
5
|
"deploymentSupport": "both",
|
|
5
6
|
"credentialRisk": "none",
|
|
@@ -10,10 +11,10 @@
|
|
|
10
11
|
"healthExposure": "direct",
|
|
11
12
|
"id": "helyx.reactionroles",
|
|
12
13
|
"name": "Reaction Roles",
|
|
13
|
-
"version": "1.0
|
|
14
|
+
"version": "1.1.0",
|
|
14
15
|
"description": "Let members select approved roles themselves.",
|
|
15
16
|
"entry": "./dist/index.js",
|
|
16
|
-
"framework": "^0.
|
|
17
|
+
"framework": "^0.2.0",
|
|
17
18
|
"dependencies": [],
|
|
18
19
|
"permissions": [
|
|
19
20
|
"ADD_REACTIONS",
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
CREATE TABLE reactionroles_panels (
|
|
2
|
+
panel_id CHAR(36) CHARACTER SET ascii COLLATE ascii_bin PRIMARY KEY,
|
|
3
|
+
guild_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
4
|
+
channel_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
5
|
+
message_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NULL,
|
|
6
|
+
title VARCHAR(80) COLLATE utf8mb4_bin NOT NULL,
|
|
7
|
+
message_body VARCHAR(1000) COLLATE utf8mb4_bin NOT NULL,
|
|
8
|
+
message_style VARCHAR(5) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
9
|
+
control_type VARCHAR(9) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
10
|
+
selection_mode VARCHAR(8) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
11
|
+
embed_colour INT NULL,
|
|
12
|
+
dropdown_placeholder VARCHAR(100) COLLATE utf8mb4_bin NULL,
|
|
13
|
+
status VARCHAR(15) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
14
|
+
revision BIGINT NOT NULL DEFAULT 1,
|
|
15
|
+
created_by_user_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NULL,
|
|
16
|
+
updated_by_user_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NULL,
|
|
17
|
+
created_at DATETIME(3) NOT NULL,
|
|
18
|
+
updated_at DATETIME(3) NOT NULL,
|
|
19
|
+
persistent_reactions BOOLEAN NOT NULL DEFAULT TRUE,
|
|
20
|
+
CONSTRAINT reactionroles_panels_message_unique UNIQUE (guild_id, message_id),
|
|
21
|
+
KEY reactionroles_panels_guild_status_idx (guild_id, status, updated_at DESC, panel_id),
|
|
22
|
+
CHECK (CHAR_LENGTH(title) BETWEEN 1 AND 80),
|
|
23
|
+
CHECK (CHAR_LENGTH(message_body) BETWEEN 1 AND 1000),
|
|
24
|
+
CHECK (message_style IN ('text', 'embed')),
|
|
25
|
+
CHECK (control_type IN ('buttons', 'dropdown', 'reactions')),
|
|
26
|
+
CHECK (selection_mode IN ('multiple', 'one_only')),
|
|
27
|
+
CHECK (embed_colour IS NULL OR embed_colour BETWEEN 0 AND 16777215),
|
|
28
|
+
CHECK (dropdown_placeholder IS NULL OR CHAR_LENGTH(dropdown_placeholder) BETWEEN 1 AND 100),
|
|
29
|
+
CHECK (status IN ('pending', 'active', 'disabled', 'message_missing',
|
|
30
|
+
'needs_attention', 'cleanup_pending', 'deleting')),
|
|
31
|
+
CHECK (revision > 0),
|
|
32
|
+
CHECK (persistent_reactions IN (0, 1)),
|
|
33
|
+
CONSTRAINT reactionroles_panels_reaction_selection_check CHECK (
|
|
34
|
+
control_type <> 'reactions' OR selection_mode <> 'one_only'
|
|
35
|
+
OR persistent_reactions = FALSE
|
|
36
|
+
)
|
|
37
|
+
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4 COLLATE=utf8mb4_bin;
|
|
38
|
+
|
|
39
|
+
CREATE TABLE reactionroles_entries (
|
|
40
|
+
entry_id VARCHAR(100) CHARACTER SET ascii COLLATE ascii_bin PRIMARY KEY,
|
|
41
|
+
panel_id CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
42
|
+
position INT NOT NULL,
|
|
43
|
+
role_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
44
|
+
nameplate VARCHAR(80) COLLATE utf8mb4_bin NOT NULL,
|
|
45
|
+
emoji_kind VARCHAR(7) CHARACTER SET ascii COLLATE ascii_bin NULL,
|
|
46
|
+
emoji_name VARCHAR(80) COLLATE utf8mb4_bin NULL,
|
|
47
|
+
emoji_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NULL,
|
|
48
|
+
emoji_animated BOOLEAN NULL,
|
|
49
|
+
button_style VARCHAR(9) CHARACTER SET ascii COLLATE ascii_bin NULL,
|
|
50
|
+
created_at DATETIME(3) NOT NULL,
|
|
51
|
+
updated_at DATETIME(3) NOT NULL,
|
|
52
|
+
emoji_id_unique VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin
|
|
53
|
+
GENERATED ALWAYS AS (COALESCE(emoji_id, '')) STORED,
|
|
54
|
+
CONSTRAINT reactionroles_entries_panel_fk FOREIGN KEY (panel_id)
|
|
55
|
+
REFERENCES reactionroles_panels (panel_id) ON DELETE CASCADE,
|
|
56
|
+
CONSTRAINT reactionroles_entries_panel_position_unique UNIQUE (panel_id, position),
|
|
57
|
+
CONSTRAINT reactionroles_entries_panel_role_unique UNIQUE (panel_id, role_id),
|
|
58
|
+
CONSTRAINT reactionroles_entries_emoji_unique UNIQUE
|
|
59
|
+
(panel_id, emoji_kind, emoji_name, emoji_id_unique),
|
|
60
|
+
KEY reactionroles_entries_panel_idx (panel_id, position),
|
|
61
|
+
KEY reactionroles_entries_role_panel_idx (role_id, panel_id),
|
|
62
|
+
KEY reactionroles_entries_emoji_panel_idx (emoji_id, panel_id),
|
|
63
|
+
CHECK (position BETWEEN 0 AND 24),
|
|
64
|
+
CHECK (CHAR_LENGTH(nameplate) BETWEEN 1 AND 80),
|
|
65
|
+
CHECK (emoji_kind IS NULL OR emoji_kind IN ('unicode', 'custom')),
|
|
66
|
+
CHECK (emoji_animated IS NULL OR emoji_animated IN (0, 1)),
|
|
67
|
+
CHECK (button_style IS NULL OR button_style IN ('primary', 'secondary', 'success', 'danger')),
|
|
68
|
+
CHECK ((emoji_kind IS NULL AND emoji_name IS NULL AND emoji_id IS NULL)
|
|
69
|
+
OR (emoji_kind = 'unicode' AND emoji_name IS NOT NULL AND emoji_id IS NULL)
|
|
70
|
+
OR (emoji_kind = 'custom' AND emoji_name IS NOT NULL AND emoji_id IS NOT NULL))
|
|
71
|
+
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4 COLLATE=utf8mb4_bin;
|
|
72
|
+
|
|
73
|
+
CREATE TABLE reactionroles_message_cleanup (
|
|
74
|
+
cleanup_id CHAR(36) CHARACTER SET ascii COLLATE ascii_bin PRIMARY KEY,
|
|
75
|
+
guild_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
76
|
+
panel_id CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
77
|
+
channel_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
78
|
+
message_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
79
|
+
reason VARCHAR(11) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
80
|
+
attempts INT NOT NULL DEFAULT 0,
|
|
81
|
+
next_attempt_at DATETIME(3) NOT NULL,
|
|
82
|
+
created_at DATETIME(3) NOT NULL,
|
|
83
|
+
completed_at DATETIME(3) NULL,
|
|
84
|
+
CONSTRAINT reactionroles_cleanup_message_reason_unique UNIQUE
|
|
85
|
+
(guild_id, channel_id, message_id, reason),
|
|
86
|
+
KEY reactionroles_cleanup_pending_idx (completed_at, next_attempt_at, created_at),
|
|
87
|
+
CHECK (reason IN ('replacement', 'rollback', 'delete')),
|
|
88
|
+
CHECK (attempts BETWEEN 0 AND 10)
|
|
89
|
+
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4 COLLATE=utf8mb4_bin;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helyx/module-reactionroles",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Configurable self-service Discord role panels for Helyx.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"helyx",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"publishConfig": {
|
|
27
27
|
"access": "public",
|
|
28
|
-
"provenance":
|
|
28
|
+
"provenance": false
|
|
29
29
|
},
|
|
30
30
|
"type": "module",
|
|
31
31
|
"files": [
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"!dist/*.tsbuildinfo",
|
|
34
34
|
"!dist/**/*.map",
|
|
35
35
|
"migrations",
|
|
36
|
+
"migrations-mysql",
|
|
36
37
|
"manifest.json",
|
|
37
38
|
"README.md",
|
|
38
39
|
"CHANGELOG.md",
|
|
@@ -49,7 +50,7 @@
|
|
|
49
50
|
"build": "tsc -b"
|
|
50
51
|
},
|
|
51
52
|
"dependencies": {
|
|
52
|
-
"@helyx/module-manifest": ">=0.
|
|
53
|
-
"@helyx/sdk": ">=0.
|
|
53
|
+
"@helyx/module-manifest": ">=0.13.0 <0.14.0",
|
|
54
|
+
"@helyx/sdk": ">=0.15.0 <0.16.0"
|
|
54
55
|
}
|
|
55
56
|
}
|