koishi-plugin-githubsth 1.0.2 → 1.0.3-alpha.1
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/services/notifier.d.ts +1 -0
- package/lib/services/notifier.js +27 -35
- package/package.json +1 -1
package/lib/services/notifier.js
CHANGED
|
@@ -11,16 +11,20 @@ class Notifier extends koishi_1.Service {
|
|
|
11
11
|
this.registerListeners();
|
|
12
12
|
}
|
|
13
13
|
registerListeners() {
|
|
14
|
+
// adapter-github canonical event names
|
|
15
|
+
this.ctx.on('github/issue', (payload) => this.handleEvent('issues', payload));
|
|
16
|
+
this.ctx.on('github/issue-comment', (payload) => this.handleEvent('issue_comment', payload));
|
|
17
|
+
this.ctx.on('github/pull-request', (payload) => this.handleEvent('pull_request', payload));
|
|
18
|
+
this.ctx.on('github/workflow-run', (payload) => this.handleEvent('workflow_run', payload));
|
|
19
|
+
// Backward compatibility aliases
|
|
14
20
|
this.ctx.on('github/push', (payload) => this.handleEvent('push', payload));
|
|
15
21
|
this.ctx.on('github/issues', (payload) => this.handleEvent('issues', payload));
|
|
16
22
|
this.ctx.on('github/pull_request', (payload) => this.handleEvent('pull_request', payload));
|
|
17
|
-
this.ctx.on('github/pull-request', (payload) => this.handleEvent('pull_request', payload));
|
|
18
23
|
this.ctx.on('github/star', (payload) => this.handleEvent('star', payload));
|
|
19
24
|
this.ctx.on('github/fork', (payload) => this.handleEvent('fork', payload));
|
|
20
25
|
this.ctx.on('github/release', (payload) => this.handleEvent('release', payload));
|
|
21
26
|
this.ctx.on('github/discussion', (payload) => this.handleEvent('discussion', payload));
|
|
22
27
|
this.ctx.on('github/workflow_run', (payload) => this.handleEvent('workflow_run', payload));
|
|
23
|
-
this.ctx.on('github/workflow-run', (payload) => this.handleEvent('workflow_run', payload));
|
|
24
28
|
this.ctx.on('github/issue_comment', (payload) => this.handleEvent('issue_comment', payload));
|
|
25
29
|
this.ctx.on('github/issue-comment', (payload) => this.handleEvent('issue_comment', payload));
|
|
26
30
|
this.ctx.on('github/pull-request-review', (payload) => this.handleEvent('pull_request_review', payload));
|
|
@@ -50,7 +54,7 @@ class Notifier extends koishi_1.Service {
|
|
|
50
54
|
else if (realPayload.commits)
|
|
51
55
|
eventType = 'push';
|
|
52
56
|
else if (realPayload.starred_at !== undefined || (realPayload.action === 'started'))
|
|
53
|
-
eventType = 'star';
|
|
57
|
+
eventType = 'star';
|
|
54
58
|
else if (realPayload.forkee)
|
|
55
59
|
eventType = 'fork';
|
|
56
60
|
else if (realPayload.release)
|
|
@@ -59,7 +63,6 @@ class Notifier extends koishi_1.Service {
|
|
|
59
63
|
eventType = 'discussion';
|
|
60
64
|
else if (realPayload.workflow_run)
|
|
61
65
|
eventType = 'workflow_run';
|
|
62
|
-
// Handle raw star event if it has repository info directly
|
|
63
66
|
else if (realPayload.repository && (realPayload.action === 'created' || realPayload.action === 'started'))
|
|
64
67
|
eventType = 'star';
|
|
65
68
|
if (eventType !== 'unknown') {
|
|
@@ -75,19 +78,15 @@ class Notifier extends koishi_1.Service {
|
|
|
75
78
|
if (this.config.debug) {
|
|
76
79
|
this.ctx.logger('githubsth').info(`Received event: ${event}`);
|
|
77
80
|
}
|
|
78
|
-
// Check if payload is nested in an 'event' object (common in some adapter versions)
|
|
79
|
-
// or if the event data is directly in payload
|
|
80
81
|
const realPayload = payload.payload || payload;
|
|
81
|
-
// Extract sender from wrapper if available (adapter-github often puts it in 'actor')
|
|
82
82
|
if (payload.actor && !realPayload.sender) {
|
|
83
|
-
|
|
83
|
+
const actorLogin = payload.actor.login || payload.actor.name || 'GitHub';
|
|
84
|
+
realPayload.sender = { ...payload.actor, login: actorLogin };
|
|
84
85
|
}
|
|
85
|
-
// Extract repository from wrapper if available
|
|
86
86
|
if (payload.repository && !realPayload.repository) {
|
|
87
87
|
realPayload.repository = payload.repository;
|
|
88
88
|
}
|
|
89
89
|
let repoName = realPayload.repository?.full_name;
|
|
90
|
-
// Try to fallback if repoName is missing
|
|
91
90
|
if (!repoName && realPayload.issue?.repository_url) {
|
|
92
91
|
const parts = realPayload.issue.repository_url.split('/');
|
|
93
92
|
if (parts.length >= 2) {
|
|
@@ -97,33 +96,38 @@ class Notifier extends koishi_1.Service {
|
|
|
97
96
|
if (!repoName && realPayload.pull_request?.base?.repo?.full_name) {
|
|
98
97
|
repoName = realPayload.pull_request.base.repo.full_name;
|
|
99
98
|
}
|
|
100
|
-
//
|
|
101
|
-
|
|
99
|
+
// adapter-github eventData fields
|
|
100
|
+
if (!repoName && typeof payload.repoKey === 'string' && payload.repoKey.includes('/')) {
|
|
101
|
+
repoName = payload.repoKey;
|
|
102
|
+
}
|
|
103
|
+
if (!repoName && typeof payload.owner === 'string' && typeof payload.repo === 'string') {
|
|
104
|
+
repoName = `${payload.owner}/${payload.repo}`;
|
|
105
|
+
}
|
|
106
|
+
if (!repoName && typeof payload.repo === 'string' && payload.repo.includes('/')) {
|
|
107
|
+
repoName = payload.repo;
|
|
108
|
+
}
|
|
102
109
|
if (!repoName && event === 'star') {
|
|
103
|
-
// Sometimes the repository info is at the root of the payload, not inside 'payload' property
|
|
104
110
|
if (payload.repository?.full_name) {
|
|
105
111
|
repoName = payload.repository.full_name;
|
|
106
112
|
}
|
|
107
113
|
}
|
|
114
|
+
if (!repoName && payload.repository?.full_name) {
|
|
115
|
+
repoName = payload.repository.full_name;
|
|
116
|
+
}
|
|
108
117
|
if (!repoName) {
|
|
109
118
|
if (this.config.debug) {
|
|
110
119
|
this.ctx.logger('githubsth').warn(`Missing repo info for event: ${event}. Keys: ${Object.keys(realPayload).join(', ')}`);
|
|
111
120
|
}
|
|
112
121
|
else if (this.config.logUnhandledEvents) {
|
|
113
|
-
// Log at warning level if repo info is missing and logUnhandledEvents is on
|
|
114
122
|
this.ctx.logger('githubsth').warn(`Missing repo info for event: ${event}. Keys: ${Object.keys(realPayload).join(', ')}`);
|
|
115
123
|
}
|
|
116
|
-
// Do not return here, let patching logic handle it with defaultRepo
|
|
117
124
|
}
|
|
118
|
-
// Patch realPayload with extracted repo info if missing
|
|
119
|
-
// This is crucial for formatter to work correctly as it expects repository object
|
|
120
125
|
if (!realPayload.repository) {
|
|
121
126
|
realPayload.repository = { full_name: repoName || 'Unknown/Repo' };
|
|
122
127
|
}
|
|
123
128
|
else if (!realPayload.repository.full_name) {
|
|
124
129
|
realPayload.repository.full_name = repoName || 'Unknown/Repo';
|
|
125
130
|
}
|
|
126
|
-
// Patch realPayload with sender info if missing (e.g. issues event)
|
|
127
131
|
if (!realPayload.sender) {
|
|
128
132
|
if (realPayload.issue?.user) {
|
|
129
133
|
realPayload.sender = realPayload.issue.user;
|
|
@@ -138,11 +142,9 @@ class Notifier extends koishi_1.Service {
|
|
|
138
142
|
realPayload.sender = { login: realPayload.pusher.name || 'Pusher' };
|
|
139
143
|
}
|
|
140
144
|
else {
|
|
141
|
-
// Fallback sender
|
|
142
145
|
realPayload.sender = { login: 'GitHub' };
|
|
143
146
|
}
|
|
144
147
|
}
|
|
145
|
-
// Comprehensive patching for specific events to prevent formatter crashes
|
|
146
148
|
try {
|
|
147
149
|
this.patchPayloadForEvent(event, realPayload, repoName || 'Unknown/Repo');
|
|
148
150
|
}
|
|
@@ -154,10 +156,6 @@ class Notifier extends koishi_1.Service {
|
|
|
154
156
|
this.ctx.logger('notifier').info(`Received event ${event} for ${repoName}`);
|
|
155
157
|
this.ctx.logger('notifier').debug(JSON.stringify(realPayload, null, 2));
|
|
156
158
|
}
|
|
157
|
-
// Get rules from database
|
|
158
|
-
// Try to match both exact name and lowercase name to handle case sensitivity
|
|
159
|
-
// If repoName is missing (undefined), we can't query rules effectively by repo name
|
|
160
|
-
// But we might want to support global subscriptions or handle it gracefully
|
|
161
159
|
if (!repoName) {
|
|
162
160
|
this.ctx.logger('githubsth').warn('Cannot query rules: repoName is missing');
|
|
163
161
|
return;
|
|
@@ -169,8 +167,6 @@ class Notifier extends koishi_1.Service {
|
|
|
169
167
|
const dbRules = await this.ctx.database.get('github_subscription', {
|
|
170
168
|
repo: repoNames
|
|
171
169
|
});
|
|
172
|
-
// Combine with config rules (if any, for backward compatibility or static rules)
|
|
173
|
-
// Also match config rules case-insensitively if needed
|
|
174
170
|
const configRules = (this.config.rules || []).filter((r) => r.repo === repoName ||
|
|
175
171
|
r.repo === repoName.toLowerCase() ||
|
|
176
172
|
r.repo === '*');
|
|
@@ -179,7 +175,6 @@ class Notifier extends koishi_1.Service {
|
|
|
179
175
|
...configRules
|
|
180
176
|
];
|
|
181
177
|
const matchedRules = allRules.filter(rule => {
|
|
182
|
-
// Event match
|
|
183
178
|
if (!rule.events.includes('*') && !rule.events.includes(event))
|
|
184
179
|
return false;
|
|
185
180
|
return true;
|
|
@@ -199,7 +194,6 @@ class Notifier extends koishi_1.Service {
|
|
|
199
194
|
this.ctx.logger('notifier').debug(`Found ${matchedRules.length} matching rules for ${repoName}`);
|
|
200
195
|
}
|
|
201
196
|
let message = null;
|
|
202
|
-
// Ensure formatter is loaded
|
|
203
197
|
if (!this.ctx.githubsthFormatter) {
|
|
204
198
|
this.ctx.logger('notifier').warn('Formatter service not available');
|
|
205
199
|
return;
|
|
@@ -259,11 +253,9 @@ class Notifier extends koishi_1.Service {
|
|
|
259
253
|
}
|
|
260
254
|
}
|
|
261
255
|
patchPayloadForEvent(event, payload, repoName) {
|
|
262
|
-
// Ensure sender exists (handled before, but good for type safety)
|
|
263
256
|
const defaultUser = { login: 'GitHub', id: 0, avatar_url: '' };
|
|
264
257
|
if (!payload.sender)
|
|
265
258
|
payload.sender = defaultUser;
|
|
266
|
-
// Ensure repository exists (handled before, but good for type safety)
|
|
267
259
|
const defaultRepo = { full_name: repoName, stargazers_count: 0, html_url: `https://github.com/${repoName}` };
|
|
268
260
|
if (!payload.repository)
|
|
269
261
|
payload.repository = defaultRepo;
|
|
@@ -277,7 +269,6 @@ class Notifier extends koishi_1.Service {
|
|
|
277
269
|
payload.ref = 'refs/heads/unknown';
|
|
278
270
|
if (!payload.compare)
|
|
279
271
|
payload.compare = '';
|
|
280
|
-
// Ensure author exists in commits
|
|
281
272
|
if (payload.commits.length > 0) {
|
|
282
273
|
payload.commits.forEach((c) => {
|
|
283
274
|
if (!c.author)
|
|
@@ -294,7 +285,6 @@ class Notifier extends koishi_1.Service {
|
|
|
294
285
|
payload.action = 'updated';
|
|
295
286
|
if (!payload.issue)
|
|
296
287
|
payload.issue = { number: 0, title: 'Unknown Issue', html_url: '', user: payload.sender };
|
|
297
|
-
// Ensure user exists in issue
|
|
298
288
|
if (!payload.issue.user)
|
|
299
289
|
payload.issue.user = payload.sender;
|
|
300
290
|
break;
|
|
@@ -309,6 +299,8 @@ class Notifier extends koishi_1.Service {
|
|
|
309
299
|
case 'star':
|
|
310
300
|
if (!payload.action)
|
|
311
301
|
payload.action = 'created';
|
|
302
|
+
if (payload.action === 'started')
|
|
303
|
+
payload.action = 'created';
|
|
312
304
|
if (payload.repository && payload.repository.stargazers_count === undefined) {
|
|
313
305
|
payload.repository.stargazers_count = '?';
|
|
314
306
|
}
|
|
@@ -360,11 +352,10 @@ class Notifier extends koishi_1.Service {
|
|
|
360
352
|
}
|
|
361
353
|
}
|
|
362
354
|
async sendMessage(rule, message) {
|
|
363
|
-
// Find suitable bots
|
|
364
355
|
const bots = this.ctx.bots.filter(bot => {
|
|
365
356
|
if (rule.platform)
|
|
366
357
|
return bot.platform === rule.platform;
|
|
367
|
-
return true;
|
|
358
|
+
return true;
|
|
368
359
|
});
|
|
369
360
|
if (bots.length === 0) {
|
|
370
361
|
if (this.config.debug) {
|
|
@@ -380,7 +371,7 @@ class Notifier extends koishi_1.Service {
|
|
|
380
371
|
if (this.config.debug) {
|
|
381
372
|
this.ctx.logger('notifier').info(`Sent message to ${rule.channelId} via ${bot.platform}:${bot.selfId}`);
|
|
382
373
|
}
|
|
383
|
-
break;
|
|
374
|
+
break;
|
|
384
375
|
}
|
|
385
376
|
catch (e) {
|
|
386
377
|
if (this.config.debug) {
|
|
@@ -394,3 +385,4 @@ class Notifier extends koishi_1.Service {
|
|
|
394
385
|
}
|
|
395
386
|
}
|
|
396
387
|
exports.Notifier = Notifier;
|
|
388
|
+
Notifier.inject = ['githubsthFormatter'];
|
package/package.json
CHANGED