koishi-plugin-githubsth 1.0.1-test8 → 1.0.2-beta1
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/commands/subscribe.d.ts +1 -1
- package/lib/commands/subscribe.js +62 -5
- package/lib/config.d.ts +2 -0
- package/lib/config.js +4 -0
- package/lib/index.js +2 -23
- package/lib/services/notifier.d.ts +1 -0
- package/lib/services/notifier.js +241 -32
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { Context } from 'koishi';
|
|
2
|
-
export declare function apply(ctx: Context): void;
|
|
2
|
+
export declare function apply(ctx: Context, config: any): void;
|
|
@@ -1,11 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.apply = apply;
|
|
4
|
-
function apply(ctx) {
|
|
4
|
+
function apply(ctx, config) {
|
|
5
5
|
const logger = ctx.logger('githubsth');
|
|
6
6
|
const repoRegex = /^[\w-]+\/[\w-\.]+$/;
|
|
7
|
+
const validEvents = [
|
|
8
|
+
'push', 'issues', 'issue_comment', 'pull_request',
|
|
9
|
+
'pull_request_review', 'star', 'fork', 'release',
|
|
10
|
+
'discussion', 'workflow_run'
|
|
11
|
+
];
|
|
12
|
+
const defaultConfigEvents = config.defaultEvents || ['push', 'issues', 'issue_comment', 'pull_request', 'pull_request_review', 'release', 'star', 'fork'];
|
|
7
13
|
ctx.command('githubsth.subscribe <repo> [events:text]', '订阅 GitHub 仓库')
|
|
8
14
|
.alias('gh.sub')
|
|
15
|
+
.usage(`
|
|
16
|
+
订阅 GitHub 仓库通知。
|
|
17
|
+
如果不指定事件,默认订阅: ${defaultConfigEvents.join(', ')}
|
|
18
|
+
|
|
19
|
+
可选事件:
|
|
20
|
+
- push: 代码推送
|
|
21
|
+
- issues: Issue 创建/关闭/重开
|
|
22
|
+
- issue_comment: Issue 评论
|
|
23
|
+
- pull_request: PR 创建/关闭/重开
|
|
24
|
+
- pull_request_review: PR 审查
|
|
25
|
+
- star: 标星
|
|
26
|
+
- fork: 仓库 Fork
|
|
27
|
+
- release: 发布新版本
|
|
28
|
+
- discussion: 讨论区更新
|
|
29
|
+
- workflow_run: Workflow 运行
|
|
30
|
+
|
|
31
|
+
示例:
|
|
32
|
+
gh.sub koishijs/koishi
|
|
33
|
+
gh.sub koishijs/koishi push,issues,star
|
|
34
|
+
`)
|
|
9
35
|
.action(async ({ session }, repo, eventsStr) => {
|
|
10
36
|
if (!repo)
|
|
11
37
|
return '请指定仓库名称 (owner/repo)。';
|
|
@@ -19,15 +45,46 @@ function apply(ctx) {
|
|
|
19
45
|
return '该仓库不在信任列表中,无法订阅。请联系管理员添加。';
|
|
20
46
|
}
|
|
21
47
|
// Parse events
|
|
22
|
-
|
|
48
|
+
let events;
|
|
49
|
+
if (eventsStr) {
|
|
50
|
+
// Split by comma, Chinese comma, or whitespace
|
|
51
|
+
events = eventsStr.split(/[,,\s]+/).map(e => e.trim()).filter(Boolean);
|
|
52
|
+
// Normalize events (kebab-case to snake_case)
|
|
53
|
+
events = events.map(e => e.replace(/-/g, '_'));
|
|
54
|
+
// Validate events
|
|
55
|
+
const invalidEvents = events.filter(e => !validEvents.includes(e) && e !== '*');
|
|
56
|
+
if (invalidEvents.length > 0) {
|
|
57
|
+
return `无效的事件类型: ${invalidEvents.join(', ')}。\n可选事件: ${validEvents.join(', ')}`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// Default events
|
|
62
|
+
events = [...defaultConfigEvents];
|
|
63
|
+
}
|
|
23
64
|
try {
|
|
24
|
-
|
|
65
|
+
// Check if subscription exists
|
|
66
|
+
const existing = await ctx.database.get('github_subscription', {
|
|
25
67
|
repo,
|
|
26
68
|
channelId: session.channelId,
|
|
27
69
|
platform: session.platform || 'unknown',
|
|
28
|
-
events,
|
|
29
70
|
});
|
|
30
|
-
|
|
71
|
+
if (existing.length > 0) {
|
|
72
|
+
// Update existing subscription
|
|
73
|
+
await ctx.database.set('github_subscription', { id: existing[0].id }, {
|
|
74
|
+
events,
|
|
75
|
+
});
|
|
76
|
+
return `已更新 ${repo} 的订阅,当前监听事件: ${events.join(', ')}。`;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// Create new subscription
|
|
80
|
+
await ctx.database.create('github_subscription', {
|
|
81
|
+
repo,
|
|
82
|
+
channelId: session.channelId,
|
|
83
|
+
platform: session.platform || 'unknown',
|
|
84
|
+
events,
|
|
85
|
+
});
|
|
86
|
+
return `已订阅 ${repo} 的 ${events.join(', ')} 事件。`;
|
|
87
|
+
}
|
|
31
88
|
}
|
|
32
89
|
catch (e) {
|
|
33
90
|
logger.warn(e);
|
package/lib/config.d.ts
CHANGED
package/lib/config.js
CHANGED
|
@@ -6,6 +6,10 @@ exports.Config = koishi_1.Schema.object({
|
|
|
6
6
|
defaultOwner: koishi_1.Schema.string().description('默认仓库拥有者'),
|
|
7
7
|
defaultRepo: koishi_1.Schema.string().description('默认仓库名称'),
|
|
8
8
|
debug: koishi_1.Schema.boolean().default(false).description('启用调试模式,输出详细日志'),
|
|
9
|
+
logUnhandledEvents: koishi_1.Schema.boolean().default(false).description('是否记录未处理的 Webhook 事件 (Unknown events)'),
|
|
10
|
+
defaultEvents: koishi_1.Schema.array(koishi_1.Schema.string())
|
|
11
|
+
.default(['push', 'issues', 'issue_comment', 'pull_request', 'pull_request_review', 'release', 'star', 'fork'])
|
|
12
|
+
.description('默认订阅事件列表 (当不指定事件时使用)'),
|
|
9
13
|
rules: koishi_1.Schema.array(koishi_1.Schema.object({
|
|
10
14
|
repo: koishi_1.Schema.string().required(),
|
|
11
15
|
channelId: koishi_1.Schema.string().required(),
|
package/lib/index.js
CHANGED
|
@@ -41,7 +41,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
41
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
42
|
exports.inject = exports.name = void 0;
|
|
43
43
|
exports.apply = apply;
|
|
44
|
-
const
|
|
44
|
+
const commands_1 = require("./commands");
|
|
45
45
|
const database = __importStar(require("./database"));
|
|
46
46
|
const zh_CN_1 = __importDefault(require("./locales/zh-CN"));
|
|
47
47
|
const notifier_1 = require("./services/notifier");
|
|
@@ -60,33 +60,12 @@ function apply(ctx, config) {
|
|
|
60
60
|
// 数据库
|
|
61
61
|
ctx.plugin(database);
|
|
62
62
|
// 注册服务
|
|
63
|
-
logger.info('Registering Formatter...');
|
|
64
63
|
ctx.plugin(formatter_1.Formatter);
|
|
65
|
-
logger.info('Registering Notifier...');
|
|
66
64
|
ctx.plugin(notifier_1.Notifier, config);
|
|
67
|
-
// Debug listener for raw events
|
|
68
|
-
ctx.on('github/issues', (payload) => {
|
|
69
|
-
logger.info('[DEBUG] Global listener caught github/issues');
|
|
70
|
-
});
|
|
71
|
-
ctx.on('github/opened', (payload) => {
|
|
72
|
-
logger.info('[DEBUG] Global listener caught github/opened');
|
|
73
|
-
});
|
|
74
|
-
// Comprehensive debug listeners
|
|
75
|
-
ctx.on('github/webhook', (payload) => {
|
|
76
|
-
logger.info('[DEBUG] Global listener caught github/webhook');
|
|
77
|
-
});
|
|
78
|
-
// Middleware to log all sessions
|
|
79
|
-
ctx.middleware((session, next) => {
|
|
80
|
-
// Log any session event from github
|
|
81
|
-
if (session.platform === 'github') {
|
|
82
|
-
logger.info(`[DEBUG] Middleware saw session.type: ${session.type}, subtype: ${session.subtype}`);
|
|
83
|
-
}
|
|
84
|
-
return next();
|
|
85
|
-
});
|
|
86
65
|
// 注册命令
|
|
87
66
|
// admin and subscribe are already loaded in commands/index.ts, remove duplicate loading here
|
|
88
67
|
try {
|
|
89
|
-
ctx.plugin(
|
|
68
|
+
ctx.plugin(commands_1.apply, config);
|
|
90
69
|
logger.info('Plugin loaded successfully');
|
|
91
70
|
}
|
|
92
71
|
catch (e) {
|
package/lib/services/notifier.js
CHANGED
|
@@ -23,12 +23,55 @@ class Notifier extends koishi_1.Service {
|
|
|
23
23
|
this.ctx.on('github/workflow-run', (payload) => this.handleEvent('workflow_run', payload));
|
|
24
24
|
this.ctx.on('github/issue_comment', (payload) => this.handleEvent('issue_comment', payload));
|
|
25
25
|
this.ctx.on('github/issue-comment', (payload) => this.handleEvent('issue_comment', payload));
|
|
26
|
-
this.ctx.on('github/pull_request_review', (payload) => this.handleEvent('pull_request_review', payload));
|
|
27
26
|
this.ctx.on('github/pull-request-review', (payload) => this.handleEvent('pull_request_review', payload));
|
|
27
|
+
// Fallback: Listen to message-created for adapters that map webhooks to messages
|
|
28
|
+
this.ctx.on('message-created', (session) => {
|
|
29
|
+
if (session.platform !== 'github')
|
|
30
|
+
return;
|
|
31
|
+
// Try to find payload
|
|
32
|
+
const payload = session.payload || session.extra || session.data;
|
|
33
|
+
if (payload) {
|
|
34
|
+
if (this.config.debug) {
|
|
35
|
+
this.ctx.logger('githubsth').info('Found payload in session, attempting to handle');
|
|
36
|
+
}
|
|
37
|
+
// Infer event type
|
|
38
|
+
let eventType = 'unknown';
|
|
39
|
+
if (payload.issue && payload.comment)
|
|
40
|
+
eventType = 'issue_comment';
|
|
41
|
+
else if (payload.issue)
|
|
42
|
+
eventType = 'issues';
|
|
43
|
+
else if (payload.pull_request && payload.review)
|
|
44
|
+
eventType = 'pull_request_review';
|
|
45
|
+
else if (payload.pull_request)
|
|
46
|
+
eventType = 'pull_request';
|
|
47
|
+
else if (payload.commits)
|
|
48
|
+
eventType = 'push';
|
|
49
|
+
else if (payload.starred_at !== undefined || (payload.action === 'started'))
|
|
50
|
+
eventType = 'star'; // star event usually has action 'created' but check payload structure
|
|
51
|
+
else if (payload.forkee)
|
|
52
|
+
eventType = 'fork';
|
|
53
|
+
else if (payload.release)
|
|
54
|
+
eventType = 'release';
|
|
55
|
+
else if (payload.discussion)
|
|
56
|
+
eventType = 'discussion';
|
|
57
|
+
else if (payload.workflow_run)
|
|
58
|
+
eventType = 'workflow_run';
|
|
59
|
+
// Handle raw star event if it has repository info directly
|
|
60
|
+
else if (payload.repository && (payload.action === 'created' || payload.action === 'started'))
|
|
61
|
+
eventType = 'star';
|
|
62
|
+
if (eventType !== 'unknown') {
|
|
63
|
+
this.handleEvent(eventType, payload);
|
|
64
|
+
}
|
|
65
|
+
else if (this.config.logUnhandledEvents) {
|
|
66
|
+
this.ctx.logger('githubsth').info(`Unhandled payload structure. Keys: ${Object.keys(payload).join(', ')}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
});
|
|
28
70
|
}
|
|
29
71
|
async handleEvent(event, payload) {
|
|
30
|
-
|
|
31
|
-
|
|
72
|
+
if (this.config.debug) {
|
|
73
|
+
this.ctx.logger('githubsth').info(`Received event: ${event}`);
|
|
74
|
+
}
|
|
32
75
|
// Check if payload is nested in an 'event' object (common in some adapter versions)
|
|
33
76
|
// or if the event data is directly in payload
|
|
34
77
|
const realPayload = payload.payload || payload;
|
|
@@ -43,24 +86,77 @@ class Notifier extends koishi_1.Service {
|
|
|
43
86
|
if (!repoName && realPayload.pull_request?.base?.repo?.full_name) {
|
|
44
87
|
repoName = realPayload.pull_request.base.repo.full_name;
|
|
45
88
|
}
|
|
89
|
+
// Special handling for 'star' event (which might be 'watch' event with action 'started')
|
|
90
|
+
// The payload might be missing repository info in the main object but have it in the original session payload
|
|
91
|
+
if (!repoName && event === 'star') {
|
|
92
|
+
// Sometimes the repository info is at the root of the payload, not inside 'payload' property
|
|
93
|
+
if (payload.repository?.full_name) {
|
|
94
|
+
repoName = payload.repository.full_name;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
46
97
|
if (!repoName) {
|
|
47
|
-
this.ctx.logger('githubsth').warn(`Missing repo info for event: ${event}`);
|
|
48
98
|
if (this.config.debug) {
|
|
49
|
-
this.ctx.logger('
|
|
99
|
+
this.ctx.logger('githubsth').warn(`Missing repo info for event: ${event}. Keys: ${Object.keys(realPayload).join(', ')}`);
|
|
100
|
+
}
|
|
101
|
+
else if (this.config.logUnhandledEvents) {
|
|
102
|
+
// Log at warning level if repo info is missing and logUnhandledEvents is on
|
|
103
|
+
this.ctx.logger('githubsth').warn(`Missing repo info for event: ${event}. Keys: ${Object.keys(realPayload).join(', ')}`);
|
|
50
104
|
}
|
|
51
105
|
return;
|
|
52
106
|
}
|
|
53
|
-
|
|
107
|
+
// Patch realPayload with extracted repo info if missing
|
|
108
|
+
// This is crucial for formatter to work correctly as it expects repository object
|
|
109
|
+
if (!realPayload.repository) {
|
|
110
|
+
realPayload.repository = { full_name: repoName };
|
|
111
|
+
}
|
|
112
|
+
else if (!realPayload.repository.full_name) {
|
|
113
|
+
realPayload.repository.full_name = repoName;
|
|
114
|
+
}
|
|
115
|
+
// Patch realPayload with sender info if missing (e.g. issues event)
|
|
116
|
+
if (!realPayload.sender) {
|
|
117
|
+
if (realPayload.issue?.user) {
|
|
118
|
+
realPayload.sender = realPayload.issue.user;
|
|
119
|
+
}
|
|
120
|
+
else if (realPayload.pull_request?.user) {
|
|
121
|
+
realPayload.sender = realPayload.pull_request.user;
|
|
122
|
+
}
|
|
123
|
+
else if (realPayload.discussion?.user) {
|
|
124
|
+
realPayload.sender = realPayload.discussion.user;
|
|
125
|
+
}
|
|
126
|
+
else if (realPayload.pusher) {
|
|
127
|
+
realPayload.sender = { login: realPayload.pusher.name || 'Pusher' };
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
// Fallback sender
|
|
131
|
+
realPayload.sender = { login: 'GitHub' };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// Comprehensive patching for specific events to prevent formatter crashes
|
|
135
|
+
try {
|
|
136
|
+
this.patchPayloadForEvent(event, realPayload, repoName);
|
|
137
|
+
}
|
|
138
|
+
catch (e) {
|
|
139
|
+
this.ctx.logger('githubsth').warn(`Failed to patch payload for ${event}:`, e);
|
|
140
|
+
}
|
|
54
141
|
if (this.config.debug) {
|
|
142
|
+
this.ctx.logger('githubsth').info(`Processing event ${event} for ${repoName}`);
|
|
55
143
|
this.ctx.logger('notifier').info(`Received event ${event} for ${repoName}`);
|
|
56
144
|
this.ctx.logger('notifier').debug(JSON.stringify(realPayload, null, 2));
|
|
57
145
|
}
|
|
58
146
|
// Get rules from database
|
|
147
|
+
// Try to match both exact name and lowercase name to handle case sensitivity
|
|
148
|
+
const repoNames = [repoName];
|
|
149
|
+
if (repoName !== repoName.toLowerCase()) {
|
|
150
|
+
repoNames.push(repoName.toLowerCase());
|
|
151
|
+
}
|
|
59
152
|
const dbRules = await this.ctx.database.get('github_subscription', {
|
|
60
|
-
repo:
|
|
153
|
+
repo: repoNames
|
|
61
154
|
});
|
|
62
155
|
// Combine with config rules (if any, for backward compatibility or static rules)
|
|
63
|
-
|
|
156
|
+
// Also match config rules case-insensitively if needed
|
|
157
|
+
const configRules = (this.config.rules || []).filter((r) => r.repo === repoName ||
|
|
158
|
+
r.repo === repoName.toLowerCase() ||
|
|
159
|
+
r.repo === '*');
|
|
64
160
|
const allRules = [
|
|
65
161
|
...dbRules.map(r => ({ ...r, platform: r.platform })),
|
|
66
162
|
...configRules
|
|
@@ -72,14 +168,17 @@ class Notifier extends koishi_1.Service {
|
|
|
72
168
|
return true;
|
|
73
169
|
});
|
|
74
170
|
if (matchedRules.length === 0) {
|
|
75
|
-
this.ctx.logger('githubsth').info(`No matching rules for ${repoName} (event: ${event})`);
|
|
76
171
|
if (this.config.debug) {
|
|
172
|
+
this.ctx.logger('githubsth').info(`No matching rules for ${repoName} (event: ${event})`);
|
|
77
173
|
this.ctx.logger('notifier').debug(`No matching rules for ${repoName} (event: ${event})`);
|
|
78
174
|
}
|
|
175
|
+
else if (this.config.logUnhandledEvents) {
|
|
176
|
+
this.ctx.logger('githubsth').warn(`No matching rules for ${repoName} (event: ${event})`);
|
|
177
|
+
}
|
|
79
178
|
return;
|
|
80
179
|
}
|
|
81
|
-
this.ctx.logger('githubsth').info(`Found ${matchedRules.length} matching rules for ${repoName}`);
|
|
82
180
|
if (this.config.debug) {
|
|
181
|
+
this.ctx.logger('githubsth').info(`Found ${matchedRules.length} matching rules for ${repoName}`);
|
|
83
182
|
this.ctx.logger('notifier').debug(`Found ${matchedRules.length} matching rules for ${repoName}`);
|
|
84
183
|
}
|
|
85
184
|
let message = null;
|
|
@@ -88,50 +187,160 @@ class Notifier extends koishi_1.Service {
|
|
|
88
187
|
this.ctx.logger('notifier').warn('Formatter service not available');
|
|
89
188
|
return;
|
|
90
189
|
}
|
|
190
|
+
try {
|
|
191
|
+
switch (event) {
|
|
192
|
+
case 'push':
|
|
193
|
+
message = this.ctx.githubsthFormatter.formatPush(realPayload);
|
|
194
|
+
break;
|
|
195
|
+
case 'issues':
|
|
196
|
+
message = this.ctx.githubsthFormatter.formatIssue(realPayload);
|
|
197
|
+
break;
|
|
198
|
+
case 'pull_request':
|
|
199
|
+
message = this.ctx.githubsthFormatter.formatPullRequest(realPayload);
|
|
200
|
+
break;
|
|
201
|
+
case 'star':
|
|
202
|
+
message = this.ctx.githubsthFormatter.formatStar(realPayload);
|
|
203
|
+
break;
|
|
204
|
+
case 'fork':
|
|
205
|
+
message = this.ctx.githubsthFormatter.formatFork(realPayload);
|
|
206
|
+
break;
|
|
207
|
+
case 'release':
|
|
208
|
+
message = this.ctx.githubsthFormatter.formatRelease(realPayload);
|
|
209
|
+
break;
|
|
210
|
+
case 'discussion':
|
|
211
|
+
message = this.ctx.githubsthFormatter.formatDiscussion(realPayload);
|
|
212
|
+
break;
|
|
213
|
+
case 'workflow_run':
|
|
214
|
+
message = this.ctx.githubsthFormatter.formatWorkflowRun(realPayload);
|
|
215
|
+
break;
|
|
216
|
+
case 'issue_comment':
|
|
217
|
+
message = this.ctx.githubsthFormatter.formatIssueComment(realPayload);
|
|
218
|
+
break;
|
|
219
|
+
case 'pull_request_review':
|
|
220
|
+
message = this.ctx.githubsthFormatter.formatPullRequestReview(realPayload);
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch (e) {
|
|
225
|
+
this.ctx.logger('githubsth').error(`Error formatting event ${event}:`, e);
|
|
226
|
+
if (this.config.debug) {
|
|
227
|
+
this.ctx.logger('notifier').error(`Error formatting event ${event}:`, e);
|
|
228
|
+
}
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (!message) {
|
|
232
|
+
if (this.config.debug) {
|
|
233
|
+
this.ctx.logger('notifier').debug(`Formatter returned null for event ${event}`);
|
|
234
|
+
}
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
for (const rule of matchedRules) {
|
|
238
|
+
if (this.config.debug) {
|
|
239
|
+
this.ctx.logger('notifier').debug(`Sending message to channel ${rule.channelId} (platform: ${rule.platform || 'any'})`);
|
|
240
|
+
}
|
|
241
|
+
await this.sendMessage(rule, message);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
patchPayloadForEvent(event, payload, repoName) {
|
|
245
|
+
// Ensure sender exists (handled before, but good for type safety)
|
|
246
|
+
const defaultUser = { login: 'GitHub', id: 0, avatar_url: '' };
|
|
247
|
+
if (!payload.sender)
|
|
248
|
+
payload.sender = defaultUser;
|
|
249
|
+
// Ensure repository exists (handled before, but good for type safety)
|
|
250
|
+
const defaultRepo = { full_name: repoName, stargazers_count: 0, html_url: `https://github.com/${repoName}` };
|
|
251
|
+
if (!payload.repository)
|
|
252
|
+
payload.repository = defaultRepo;
|
|
91
253
|
switch (event) {
|
|
92
254
|
case 'push':
|
|
93
|
-
|
|
255
|
+
if (!payload.pusher)
|
|
256
|
+
payload.pusher = { name: payload.sender.login };
|
|
257
|
+
if (!payload.commits)
|
|
258
|
+
payload.commits = [];
|
|
259
|
+
if (!payload.ref)
|
|
260
|
+
payload.ref = 'refs/heads/unknown';
|
|
261
|
+
if (!payload.compare)
|
|
262
|
+
payload.compare = '';
|
|
263
|
+
// Ensure author exists in commits
|
|
264
|
+
if (payload.commits.length > 0) {
|
|
265
|
+
payload.commits.forEach((c) => {
|
|
266
|
+
if (!c.author)
|
|
267
|
+
c.author = { name: 'Unknown' };
|
|
268
|
+
if (!c.id)
|
|
269
|
+
c.id = '0000000';
|
|
270
|
+
if (!c.message)
|
|
271
|
+
c.message = 'No message';
|
|
272
|
+
});
|
|
273
|
+
}
|
|
94
274
|
break;
|
|
95
275
|
case 'issues':
|
|
96
|
-
|
|
276
|
+
if (!payload.action)
|
|
277
|
+
payload.action = 'updated';
|
|
278
|
+
if (!payload.issue)
|
|
279
|
+
payload.issue = { number: 0, title: 'Unknown Issue', html_url: '', user: payload.sender };
|
|
280
|
+
// Ensure user exists in issue
|
|
281
|
+
if (!payload.issue.user)
|
|
282
|
+
payload.issue.user = payload.sender;
|
|
97
283
|
break;
|
|
98
284
|
case 'pull_request':
|
|
99
|
-
|
|
285
|
+
if (!payload.action)
|
|
286
|
+
payload.action = 'updated';
|
|
287
|
+
if (!payload.pull_request)
|
|
288
|
+
payload.pull_request = { number: 0, title: 'Unknown PR', state: 'unknown', html_url: '', user: payload.sender };
|
|
289
|
+
if (!payload.pull_request.user)
|
|
290
|
+
payload.pull_request.user = payload.sender;
|
|
100
291
|
break;
|
|
101
292
|
case 'star':
|
|
102
|
-
|
|
293
|
+
if (!payload.action)
|
|
294
|
+
payload.action = 'created';
|
|
295
|
+
if (payload.repository && payload.repository.stargazers_count === undefined) {
|
|
296
|
+
payload.repository.stargazers_count = '?';
|
|
297
|
+
}
|
|
103
298
|
break;
|
|
104
299
|
case 'fork':
|
|
105
|
-
|
|
300
|
+
if (!payload.forkee)
|
|
301
|
+
payload.forkee = { full_name: 'unknown/fork' };
|
|
106
302
|
break;
|
|
107
303
|
case 'release':
|
|
108
|
-
|
|
304
|
+
if (!payload.action)
|
|
305
|
+
payload.action = 'published';
|
|
306
|
+
if (!payload.release)
|
|
307
|
+
payload.release = { tag_name: 'unknown', name: 'Unknown Release', html_url: '' };
|
|
109
308
|
break;
|
|
110
309
|
case 'discussion':
|
|
111
|
-
|
|
310
|
+
if (!payload.action)
|
|
311
|
+
payload.action = 'updated';
|
|
312
|
+
if (!payload.discussion)
|
|
313
|
+
payload.discussion = { number: 0, title: 'Unknown Discussion', html_url: '', user: payload.sender };
|
|
314
|
+
if (!payload.discussion.user)
|
|
315
|
+
payload.discussion.user = payload.sender;
|
|
112
316
|
break;
|
|
113
317
|
case 'workflow_run':
|
|
114
|
-
|
|
318
|
+
if (!payload.action)
|
|
319
|
+
payload.action = 'completed';
|
|
320
|
+
if (!payload.workflow_run)
|
|
321
|
+
payload.workflow_run = { conclusion: 'unknown', name: 'Unknown Workflow', head_branch: 'unknown', html_url: '' };
|
|
115
322
|
break;
|
|
116
323
|
case 'issue_comment':
|
|
117
|
-
|
|
324
|
+
if (!payload.action)
|
|
325
|
+
payload.action = 'created';
|
|
326
|
+
if (!payload.issue)
|
|
327
|
+
payload.issue = { number: 0, title: 'Unknown Issue', html_url: '', user: payload.sender };
|
|
328
|
+
if (!payload.comment)
|
|
329
|
+
payload.comment = { body: '', html_url: '' };
|
|
330
|
+
if (!payload.issue.user)
|
|
331
|
+
payload.issue.user = payload.sender;
|
|
118
332
|
break;
|
|
119
333
|
case 'pull_request_review':
|
|
120
|
-
|
|
334
|
+
if (!payload.action)
|
|
335
|
+
payload.action = 'submitted';
|
|
336
|
+
if (!payload.pull_request)
|
|
337
|
+
payload.pull_request = { number: 0, title: 'Unknown PR', html_url: '', user: payload.sender };
|
|
338
|
+
if (!payload.review)
|
|
339
|
+
payload.review = { state: 'unknown', html_url: '' };
|
|
340
|
+
if (!payload.pull_request.user)
|
|
341
|
+
payload.pull_request.user = payload.sender;
|
|
121
342
|
break;
|
|
122
343
|
}
|
|
123
|
-
if (!message) {
|
|
124
|
-
if (this.config.debug) {
|
|
125
|
-
this.ctx.logger('notifier').debug(`Formatter returned null for event ${event}`);
|
|
126
|
-
}
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
for (const rule of matchedRules) {
|
|
130
|
-
if (this.config.debug) {
|
|
131
|
-
this.ctx.logger('notifier').debug(`Sending message to channel ${rule.channelId} (platform: ${rule.platform || 'any'})`);
|
|
132
|
-
}
|
|
133
|
-
await this.sendMessage(rule, message);
|
|
134
|
-
}
|
|
135
344
|
}
|
|
136
345
|
async sendMessage(rule, message) {
|
|
137
346
|
// Find suitable bots
|
package/package.json
CHANGED