koishi-plugin-github-webhook-pusher 0.0.7 → 0.0.9

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/lib/index.js ADDED
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /**
3
+ * Koishi GitHub Webhook 推送插件入口
4
+ * 需求: 1.1, 7.1-7.7
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.Config = exports.inject = exports.name = void 0;
8
+ exports.apply = apply;
9
+ const koishi_1 = require("koishi");
10
+ const config_1 = require("./config");
11
+ Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return config_1.Config; } });
12
+ const database_1 = require("./database");
13
+ const webhook_1 = require("./webhook");
14
+ const commands_1 = require("./commands");
15
+ const repository_1 = require("./repository");
16
+ /** 插件名称 */
17
+ exports.name = 'github-webhook-pusher';
18
+ /** 声明服务依赖 - 需要 server 服务提供 router 和 database 服务 */
19
+ exports.inject = ['server', 'database'];
20
+ /** 插件日志 */
21
+ const logger = new koishi_1.Logger('github-webhook-pusher');
22
+ /**
23
+ * 插件入口函数
24
+ * @param ctx Koishi 上下文
25
+ * @param config 插件配置
26
+ */
27
+ function apply(ctx, config) {
28
+ // 需求 7.1-7.7: 使用配置项
29
+ logger.info(`正在加载 GitHub Webhook 插件...`);
30
+ // 初始化数据库
31
+ // 需求 6.1, 6.2, 6.3: 创建数据库表
32
+ (0, database_1.extendDatabase)(ctx);
33
+ logger.debug('数据库模型已注册');
34
+ // 需求 1.1: 注册 Webhook 处理器
35
+ (0, webhook_1.registerWebhook)(ctx, config);
36
+ logger.debug(`Webhook 处理器已注册: ${config.path}`);
37
+ // 注册所有命令
38
+ // 需求 2.1-2.5: 信任仓库管理命令
39
+ (0, commands_1.registerTrustCommands)(ctx);
40
+ logger.debug('信任仓库管理命令已注册');
41
+ // 需求 3.1-3.7: 订阅管理命令
42
+ (0, commands_1.registerSubscriptionCommands)(ctx, config);
43
+ logger.debug('订阅管理命令已注册');
44
+ // 需求 8.1, 8.2: 工具命令
45
+ (0, commands_1.registerUtilCommands)(ctx, config);
46
+ logger.debug('工具命令已注册');
47
+ scheduleDeliveryCleanup(ctx, config);
48
+ // 插件启动日志
49
+ logger.info(`GitHub Webhook 插件已加载`);
50
+ logger.info(`Webhook 路径: ${config.path}`);
51
+ logger.info(`默认订阅事件: ${config.defaultEvents.join(', ')}`);
52
+ if (config.debug) {
53
+ logger.info('调试模式已启用');
54
+ }
55
+ }
56
+ function scheduleDeliveryCleanup(ctx, config) {
57
+ if (config.deliveryRetentionDays <= 0) {
58
+ logger.debug('投递记录清理已禁用');
59
+ return;
60
+ }
61
+ const intervalHours = Math.max(1, config.deliveryCleanupIntervalHours || 24);
62
+ const intervalMs = intervalHours * 60 * 60 * 1000;
63
+ const runCleanup = async () => {
64
+ const beforeDate = new Date(Date.now() - config.deliveryRetentionDays * 24 * 60 * 60 * 1000);
65
+ const removed = await (0, repository_1.cleanupDeliveries)(ctx, beforeDate);
66
+ if (config.debug) {
67
+ logger.debug(`清理投递记录: ${removed} 条 (保留 ${config.deliveryRetentionDays} 天)`);
68
+ }
69
+ };
70
+ runCleanup().catch(error => {
71
+ const message = error instanceof Error ? error.message : String(error);
72
+ logger.warn(`投递记录清理失败: ${message}`);
73
+ });
74
+ ctx.setInterval(() => {
75
+ runCleanup().catch(error => {
76
+ const message = error instanceof Error ? error.message : String(error);
77
+ logger.warn(`投递记录清理失败: ${message}`);
78
+ });
79
+ }, intervalMs);
80
+ }
package/lib/message.js ADDED
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ /**
3
+ * 消息构建器
4
+ * 需求: 5.3, 5.4, 5.5
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.buildMessage = buildMessage;
8
+ const koishi_1 = require("koishi");
9
+ const types_1 = require("./types");
10
+ /**
11
+ * 构建推送消息
12
+ * @param event 解析后的事件
13
+ * @returns Koishi Element 消息数组
14
+ */
15
+ function buildMessage(event) {
16
+ switch (event.type) {
17
+ case 'issues':
18
+ return buildIssuesMessage(event);
19
+ case 'issue_comment':
20
+ return buildIssueCommentMessage(event);
21
+ case 'release':
22
+ return buildReleaseMessage(event);
23
+ case 'push':
24
+ return buildPushMessage(event);
25
+ case 'pull_request':
26
+ return buildPullRequestMessage(event);
27
+ case 'pull_request_review':
28
+ return buildPullRequestReviewMessage(event);
29
+ case 'pull_request_review_comment':
30
+ return buildPullRequestReviewCommentMessage(event);
31
+ case 'star':
32
+ return buildStarMessage(event);
33
+ case 'fork':
34
+ return buildForkMessage(event);
35
+ case 'create':
36
+ return buildCreateMessage(event);
37
+ case 'delete':
38
+ return buildDeleteMessage(event);
39
+ case 'workflow_run':
40
+ return buildWorkflowRunMessage(event);
41
+ default:
42
+ return buildGenericMessage(event);
43
+ }
44
+ }
45
+ /**
46
+ * 构建 Issues 事件消息
47
+ * 格式: 📌 [owner/repo] Issue
48
+ * user opened #123: Issue Title
49
+ * https://github.com/...
50
+ */
51
+ function buildIssuesMessage(event) {
52
+ const emoji = (0, types_1.getEventEmoji)(event.type);
53
+ const actionText = getActionText(event.action);
54
+ const lines = [
55
+ `${emoji} [${event.repo}] ${event.displayType}`,
56
+ `${event.actor} ${actionText} #${event.number}: ${event.title}`,
57
+ event.url,
58
+ ];
59
+ return [(0, koishi_1.h)('text', { content: lines.join('\n') })];
60
+ }
61
+ function buildIssueCommentMessage(event) {
62
+ const emoji = (0, types_1.getEventEmoji)(event.type);
63
+ const actionText = getActionText(event.action);
64
+ const lines = [
65
+ `${emoji} [${event.repo}] ${event.displayType}`,
66
+ `${event.actor} ${actionText} #${event.number}: ${event.title}`,
67
+ event.url,
68
+ ];
69
+ return [(0, koishi_1.h)('text', { content: lines.join('\n') })];
70
+ }
71
+ /**
72
+ * 构建 Release 事件消息
73
+ * 格式: 🚀 [owner/repo] Release
74
+ * user published v1.0.0
75
+ * https://github.com/...
76
+ */
77
+ function buildReleaseMessage(event) {
78
+ const emoji = (0, types_1.getEventEmoji)(event.type);
79
+ const actionText = getActionText(event.action);
80
+ const lines = [
81
+ `${emoji} [${event.repo}] ${event.displayType}`,
82
+ `${event.actor} ${actionText} ${event.tagName || event.title}`,
83
+ event.url,
84
+ ];
85
+ return [(0, koishi_1.h)('text', { content: lines.join('\n') })];
86
+ }
87
+ /**
88
+ * 构建 Push 事件消息
89
+ * 格式: ⬆️ [owner/repo] Commit
90
+ * user 推送了 3 个提交到 main
91
+ *
92
+ * • abc1234 - 提交消息1
93
+ * • def5678 - 提交消息2
94
+ * • ghi9012 - 提交消息3
95
+ *
96
+ * 还有 2 条提交...
97
+ * https://github.com/...
98
+ */
99
+ function buildPushMessage(event) {
100
+ const emoji = (0, types_1.getEventEmoji)(event.type);
101
+ const commits = event.commits || [];
102
+ const totalCommits = event.totalCommits || commits.length;
103
+ const lines = [
104
+ `${emoji} [${event.repo}] ${event.displayType}`,
105
+ `${event.actor} 推送了 ${totalCommits} 个提交到 ${event.ref}`,
106
+ '',
107
+ ];
108
+ // 添加提交列表
109
+ for (const commit of commits) {
110
+ lines.push(`• ${commit.sha} - ${commit.message}`);
111
+ }
112
+ // 如果有更多提交,显示提示
113
+ if (totalCommits > commits.length) {
114
+ lines.push('');
115
+ lines.push(`还有 ${totalCommits - commits.length} 条提交...`);
116
+ }
117
+ lines.push(event.url);
118
+ return [(0, koishi_1.h)('text', { content: lines.join('\n') })];
119
+ }
120
+ /**
121
+ * 构建 Pull Request 事件消息
122
+ * 格式: 🔀 [owner/repo] PR
123
+ * user opened #123: PR Title
124
+ * https://github.com/...
125
+ */
126
+ function buildPullRequestMessage(event) {
127
+ const emoji = (0, types_1.getEventEmoji)(event.type);
128
+ const actionText = getActionText(event.action);
129
+ const lines = [
130
+ `${emoji} [${event.repo}] ${event.displayType}`,
131
+ `${event.actor} ${actionText} #${event.number}: ${event.title}`,
132
+ event.url,
133
+ ];
134
+ return [(0, koishi_1.h)('text', { content: lines.join('\n') })];
135
+ }
136
+ function buildPullRequestReviewMessage(event) {
137
+ const emoji = (0, types_1.getEventEmoji)(event.type);
138
+ const actionText = getActionText(event.action);
139
+ const lines = [
140
+ `${emoji} [${event.repo}] ${event.displayType}`,
141
+ `${event.actor} ${actionText} #${event.number}: ${event.title}`,
142
+ event.url,
143
+ ];
144
+ return [(0, koishi_1.h)('text', { content: lines.join('\n') })];
145
+ }
146
+ function buildPullRequestReviewCommentMessage(event) {
147
+ const emoji = (0, types_1.getEventEmoji)(event.type);
148
+ const actionText = getActionText(event.action);
149
+ const lines = [
150
+ `${emoji} [${event.repo}] ${event.displayType}`,
151
+ `${event.actor} ${actionText} #${event.number}: ${event.title}`,
152
+ event.url,
153
+ ];
154
+ return [(0, koishi_1.h)('text', { content: lines.join('\n') })];
155
+ }
156
+ /**
157
+ * 构建 Star 事件消息
158
+ * 格式: ⭐ [owner/repo] Star
159
+ * user starred (⭐ 1234)
160
+ * https://github.com/...
161
+ */
162
+ function buildStarMessage(event) {
163
+ const emoji = (0, types_1.getEventEmoji)(event.type);
164
+ const actionText = event.action === 'created' ? 'starred' : 'unstarred';
165
+ const lines = [
166
+ `${emoji} [${event.repo}] ${event.displayType}`,
167
+ `${event.actor} ${actionText} (⭐ ${event.starCount})`,
168
+ event.url,
169
+ ];
170
+ return [(0, koishi_1.h)('text', { content: lines.join('\n') })];
171
+ }
172
+ function buildForkMessage(event) {
173
+ const emoji = (0, types_1.getEventEmoji)(event.type);
174
+ const target = event.title ? ` -> ${event.title}` : '';
175
+ const lines = [
176
+ `${emoji} [${event.repo}] ${event.displayType}`,
177
+ `${event.actor} forked${target}`,
178
+ event.url,
179
+ ];
180
+ return [(0, koishi_1.h)('text', { content: lines.join('\n') })];
181
+ }
182
+ function buildCreateMessage(event) {
183
+ const emoji = (0, types_1.getEventEmoji)(event.type);
184
+ const actionText = getActionText(event.action);
185
+ const refText = event.ref ? ` ${event.ref}` : '';
186
+ const lines = [
187
+ `${emoji} [${event.repo}] ${event.displayType}`,
188
+ `${event.actor} ${actionText}${refText}`,
189
+ event.url,
190
+ ];
191
+ return [(0, koishi_1.h)('text', { content: lines.join('\n') })];
192
+ }
193
+ function buildDeleteMessage(event) {
194
+ const emoji = (0, types_1.getEventEmoji)(event.type);
195
+ const actionText = getActionText(event.action);
196
+ const refText = event.ref ? ` ${event.ref}` : '';
197
+ const lines = [
198
+ `${emoji} [${event.repo}] ${event.displayType}`,
199
+ `${event.actor} ${actionText}${refText}`,
200
+ event.url,
201
+ ];
202
+ return [(0, koishi_1.h)('text', { content: lines.join('\n') })];
203
+ }
204
+ function buildWorkflowRunMessage(event) {
205
+ const emoji = (0, types_1.getEventEmoji)(event.type);
206
+ const actionText = getActionText(event.action);
207
+ const nameText = event.title ? ` ${event.title}` : '';
208
+ const lines = [
209
+ `${emoji} [${event.repo}] ${event.displayType}`,
210
+ `${event.actor} ${actionText}${nameText}`,
211
+ event.url,
212
+ ];
213
+ return [(0, koishi_1.h)('text', { content: lines.join('\n') })];
214
+ }
215
+ /**
216
+ * 构建通用事件消息(兜底)
217
+ */
218
+ function buildGenericMessage(event) {
219
+ const emoji = (0, types_1.getEventEmoji)(event.type);
220
+ const lines = [
221
+ `${emoji} [${event.repo}] ${event.displayType}`,
222
+ `${event.actor} ${event.action || 'triggered'}`,
223
+ event.url,
224
+ ];
225
+ return [(0, koishi_1.h)('text', { content: lines.join('\n') })];
226
+ }
227
+ /**
228
+ * 获取动作的中文描述
229
+ */
230
+ function getActionText(action) {
231
+ const actionMap = {
232
+ opened: 'opened',
233
+ closed: 'closed',
234
+ reopened: 'reopened',
235
+ edited: 'edited',
236
+ merged: 'merged',
237
+ published: 'published',
238
+ created: 'created',
239
+ deleted: 'deleted',
240
+ submitted: 'submitted',
241
+ dismissed: 'dismissed',
242
+ approved: 'approved',
243
+ changes_requested: 'changes requested',
244
+ commented: 'commented',
245
+ requested: 'requested',
246
+ completed: 'completed',
247
+ forked: 'forked',
248
+ };
249
+ return actionMap[action || ''] || action || '';
250
+ }
package/lib/parser.js ADDED
@@ -0,0 +1,304 @@
1
+ "use strict";
2
+ /**
3
+ * GitHub Webhook 事件解析器
4
+ * 需求: 4.1-4.7
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.parseIssuesEvent = parseIssuesEvent;
8
+ exports.parseIssueCommentEvent = parseIssueCommentEvent;
9
+ exports.parseReleaseEvent = parseReleaseEvent;
10
+ exports.parsePushEvent = parsePushEvent;
11
+ exports.parsePullRequestEvent = parsePullRequestEvent;
12
+ exports.parsePullRequestReviewEvent = parsePullRequestReviewEvent;
13
+ exports.parsePullRequestReviewCommentEvent = parsePullRequestReviewCommentEvent;
14
+ exports.parseStarEvent = parseStarEvent;
15
+ exports.parseForkEvent = parseForkEvent;
16
+ exports.parseCreateEvent = parseCreateEvent;
17
+ exports.parseDeleteEvent = parseDeleteEvent;
18
+ exports.parseWorkflowRunEvent = parseWorkflowRunEvent;
19
+ exports.parseEvent = parseEvent;
20
+ const types_1 = require("./types");
21
+ /** Push 事件最大显示提交数 */
22
+ const MAX_COMMITS = 3;
23
+ /**
24
+ * 解析 Issues 事件
25
+ * 需求 4.1: 提取 issue 标题、编号、操作者和链接
26
+ */
27
+ function parseIssuesEvent(payload) {
28
+ const { action, issue, repository, sender } = payload;
29
+ // 只处理 opened/closed/reopened/edited 动作
30
+ if (!['opened', 'closed', 'reopened', 'edited'].includes(action)) {
31
+ return null;
32
+ }
33
+ return {
34
+ type: 'issues',
35
+ displayType: (0, types_1.getDisplayType)('issues'),
36
+ repo: repository.full_name,
37
+ actor: sender.login,
38
+ action,
39
+ title: issue.title,
40
+ number: issue.number,
41
+ url: issue.html_url,
42
+ body: issue.body,
43
+ };
44
+ }
45
+ /**
46
+ * 解析 Issue Comment 事件
47
+ */
48
+ function parseIssueCommentEvent(payload) {
49
+ const { action, issue, comment, repository, sender } = payload;
50
+ // 只处理 created/edited/deleted 动作
51
+ if (!['created', 'edited', 'deleted'].includes(action)) {
52
+ return null;
53
+ }
54
+ return {
55
+ type: 'issue_comment',
56
+ displayType: (0, types_1.getDisplayType)('issue_comment'),
57
+ repo: repository.full_name,
58
+ actor: sender.login,
59
+ action,
60
+ title: issue.title,
61
+ number: issue.number,
62
+ url: comment?.html_url || issue.html_url,
63
+ body: comment?.body,
64
+ };
65
+ }
66
+ /**
67
+ * 解析 Release 事件
68
+ * 需求 4.2: 提取版本号、发布者和下载链接
69
+ */
70
+ function parseReleaseEvent(payload) {
71
+ const { action, release, repository, sender } = payload;
72
+ // 只处理 published/created 动作
73
+ if (!['published', 'created'].includes(action)) {
74
+ return null;
75
+ }
76
+ return {
77
+ type: 'release',
78
+ displayType: (0, types_1.getDisplayType)('release'),
79
+ repo: repository.full_name,
80
+ actor: sender.login,
81
+ action,
82
+ title: release.name || release.tag_name,
83
+ tagName: release.tag_name,
84
+ url: release.html_url,
85
+ body: release.body,
86
+ };
87
+ }
88
+ /**
89
+ * 解析 Push 事件
90
+ * 需求 4.3, 4.6: 提取分支名、提交列表(最多5条)和推送者信息
91
+ */
92
+ function parsePushEvent(payload) {
93
+ const { ref, commits, repository, sender, compare } = payload;
94
+ // 提取分支名(去掉 refs/heads/ 前缀)
95
+ const branch = ref?.replace('refs/heads/', '') || '';
96
+ // 解析提交列表
97
+ const allCommits = (commits || []).map((commit) => ({
98
+ sha: commit.id?.substring(0, 7) || '',
99
+ message: commit.message?.split('\n')[0] || '', // 只取第一行
100
+ author: commit.author?.name || commit.author?.username || '',
101
+ url: commit.url || '',
102
+ }));
103
+ // 截断到最多 MAX_COMMITS 条
104
+ const displayCommits = allCommits.slice(0, MAX_COMMITS);
105
+ return {
106
+ type: 'push',
107
+ displayType: (0, types_1.getDisplayType)('push'), // 显示为 "Commit"
108
+ repo: repository.full_name,
109
+ actor: sender.login,
110
+ ref: branch,
111
+ commits: displayCommits,
112
+ totalCommits: allCommits.length,
113
+ url: compare || `https://github.com/${repository.full_name}`,
114
+ };
115
+ }
116
+ /**
117
+ * 解析 Pull Request 事件
118
+ * 需求 4.4: 提取 PR 标题、编号、操作者和链接
119
+ */
120
+ function parsePullRequestEvent(payload) {
121
+ const { action, pull_request, repository, sender } = payload;
122
+ // 只处理 opened/closed/merged 动作
123
+ // 注意: merged 实际上是 closed + merged 标志
124
+ const validActions = ['opened', 'closed', 'reopened', 'edited'];
125
+ if (!validActions.includes(action)) {
126
+ return null;
127
+ }
128
+ // 判断是否为合并
129
+ const actualAction = action === 'closed' && pull_request.merged ? 'merged' : action;
130
+ return {
131
+ type: 'pull_request',
132
+ displayType: (0, types_1.getDisplayType)('pull_request'),
133
+ repo: repository.full_name,
134
+ actor: sender.login,
135
+ action: actualAction,
136
+ title: pull_request.title,
137
+ number: pull_request.number,
138
+ url: pull_request.html_url,
139
+ body: pull_request.body,
140
+ };
141
+ }
142
+ /**
143
+ * 解析 Pull Request Review 事件
144
+ */
145
+ function parsePullRequestReviewEvent(payload) {
146
+ const { action, review, pull_request, repository, sender } = payload;
147
+ // 只处理 submitted/edited/dismissed 动作
148
+ if (!['submitted', 'edited', 'dismissed'].includes(action)) {
149
+ return null;
150
+ }
151
+ return {
152
+ type: 'pull_request_review',
153
+ displayType: (0, types_1.getDisplayType)('pull_request_review'),
154
+ repo: repository.full_name,
155
+ actor: sender.login,
156
+ action: review?.state || action,
157
+ title: pull_request.title,
158
+ number: pull_request.number,
159
+ url: review?.html_url || pull_request.html_url,
160
+ body: review?.body,
161
+ };
162
+ }
163
+ /**
164
+ * 解析 Pull Request Review Comment 事件
165
+ */
166
+ function parsePullRequestReviewCommentEvent(payload) {
167
+ const { action, comment, pull_request, repository, sender } = payload;
168
+ // 只处理 created/edited/deleted 动作
169
+ if (!['created', 'edited', 'deleted'].includes(action)) {
170
+ return null;
171
+ }
172
+ return {
173
+ type: 'pull_request_review_comment',
174
+ displayType: (0, types_1.getDisplayType)('pull_request_review_comment'),
175
+ repo: repository.full_name,
176
+ actor: sender.login,
177
+ action,
178
+ title: pull_request.title,
179
+ number: pull_request.number,
180
+ url: comment?.html_url || pull_request.html_url,
181
+ body: comment?.body,
182
+ };
183
+ }
184
+ /**
185
+ * 解析 Star 事件
186
+ * 需求 4.5: 提取操作者和当前 star 数量
187
+ */
188
+ function parseStarEvent(payload) {
189
+ const { action, repository, sender } = payload;
190
+ // star 事件只有 created 和 deleted 动作
191
+ if (!['created', 'deleted'].includes(action)) {
192
+ return null;
193
+ }
194
+ return {
195
+ type: 'star',
196
+ displayType: (0, types_1.getDisplayType)('star'),
197
+ repo: repository.full_name,
198
+ actor: sender.login,
199
+ action,
200
+ starCount: repository.stargazers_count,
201
+ url: repository.html_url,
202
+ };
203
+ }
204
+ /**
205
+ * 解析 Fork 事件
206
+ */
207
+ function parseForkEvent(payload) {
208
+ const { forkee, repository, sender } = payload;
209
+ return {
210
+ type: 'fork',
211
+ displayType: (0, types_1.getDisplayType)('fork'),
212
+ repo: repository.full_name,
213
+ actor: sender.login,
214
+ action: 'forked',
215
+ title: forkee?.full_name,
216
+ url: forkee?.html_url || repository.html_url,
217
+ };
218
+ }
219
+ /**
220
+ * 解析 Create 事件
221
+ */
222
+ function parseCreateEvent(payload) {
223
+ const { ref, ref_type, repository, sender } = payload;
224
+ return {
225
+ type: 'create',
226
+ displayType: (0, types_1.getDisplayType)('create'),
227
+ repo: repository.full_name,
228
+ actor: sender.login,
229
+ action: 'created',
230
+ ref: ref ? `${ref_type}:${ref}` : ref_type,
231
+ url: repository.html_url,
232
+ };
233
+ }
234
+ /**
235
+ * 解析 Delete 事件
236
+ */
237
+ function parseDeleteEvent(payload) {
238
+ const { ref, ref_type, repository, sender } = payload;
239
+ return {
240
+ type: 'delete',
241
+ displayType: (0, types_1.getDisplayType)('delete'),
242
+ repo: repository.full_name,
243
+ actor: sender.login,
244
+ action: 'deleted',
245
+ ref: ref ? `${ref_type}:${ref}` : ref_type,
246
+ url: repository.html_url,
247
+ };
248
+ }
249
+ /**
250
+ * 解析 Workflow Run 事件
251
+ */
252
+ function parseWorkflowRunEvent(payload) {
253
+ const { action, workflow_run, repository, sender } = payload;
254
+ // 只处理 requested/completed 动作
255
+ if (!['requested', 'completed'].includes(action)) {
256
+ return null;
257
+ }
258
+ const conclusion = workflow_run?.conclusion ? `/${workflow_run.conclusion}` : '';
259
+ return {
260
+ type: 'workflow_run',
261
+ displayType: (0, types_1.getDisplayType)('workflow_run'),
262
+ repo: repository.full_name,
263
+ actor: sender.login,
264
+ action: `${action}${conclusion}`,
265
+ title: workflow_run?.name,
266
+ url: workflow_run?.html_url || repository.html_url,
267
+ };
268
+ }
269
+ /**
270
+ * 统一的事件解析入口函数
271
+ * @param eventName X-GitHub-Event 头的值
272
+ * @param payload 解析后的 JSON 负载
273
+ * @returns 解析后的事件数据,不支持的事件返回 null
274
+ */
275
+ function parseEvent(eventName, payload) {
276
+ switch (eventName) {
277
+ case 'issues':
278
+ return parseIssuesEvent(payload);
279
+ case 'issue_comment':
280
+ return parseIssueCommentEvent(payload);
281
+ case 'release':
282
+ return parseReleaseEvent(payload);
283
+ case 'push':
284
+ return parsePushEvent(payload);
285
+ case 'pull_request':
286
+ return parsePullRequestEvent(payload);
287
+ case 'pull_request_review':
288
+ return parsePullRequestReviewEvent(payload);
289
+ case 'pull_request_review_comment':
290
+ return parsePullRequestReviewCommentEvent(payload);
291
+ case 'star':
292
+ return parseStarEvent(payload);
293
+ case 'fork':
294
+ return parseForkEvent(payload);
295
+ case 'create':
296
+ return parseCreateEvent(payload);
297
+ case 'delete':
298
+ return parseDeleteEvent(payload);
299
+ case 'workflow_run':
300
+ return parseWorkflowRunEvent(payload);
301
+ default:
302
+ return null;
303
+ }
304
+ }