koishi-plugin-githubsth 1.0.4 → 1.0.5-alpha.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/lib/services/notifier.d.ts +1 -0
- package/lib/services/notifier.js +45 -16
- package/package.json +1 -1
package/lib/services/notifier.js
CHANGED
|
@@ -35,7 +35,8 @@ class Notifier extends koishi_1.Service {
|
|
|
35
35
|
async renderPreview(event = 'issue_comment') {
|
|
36
36
|
const payload = this.getPreviewPayload(event);
|
|
37
37
|
const text = this.formatByEvent(event, payload) || this.formatByEvent('issue_comment', this.getPreviewPayload('issue_comment')) || 'Preview unavailable.';
|
|
38
|
-
|
|
38
|
+
const preview = await this.prepareOutboundMessage(text);
|
|
39
|
+
return preview?.message || null;
|
|
39
40
|
}
|
|
40
41
|
registerListeners() {
|
|
41
42
|
const bind = (name, event) => {
|
|
@@ -204,14 +205,16 @@ class Notifier extends koishi_1.Service {
|
|
|
204
205
|
}
|
|
205
206
|
async prepareOutboundMessage(textMessage) {
|
|
206
207
|
const mode = this.getRenderMode();
|
|
207
|
-
if (mode === 'text')
|
|
208
|
-
return textMessage;
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
208
|
+
if (mode === 'text') {
|
|
209
|
+
return { message: textMessage, text: textMessage, isImage: false };
|
|
210
|
+
}
|
|
211
|
+
const imageMessage = await this.renderTextAsImage(textMessage);
|
|
212
|
+
if (imageMessage) {
|
|
213
|
+
return { message: imageMessage, text: textMessage, isImage: true };
|
|
214
|
+
}
|
|
212
215
|
if (mode === 'image' && this.config.renderFallback === 'drop')
|
|
213
216
|
return null;
|
|
214
|
-
return textMessage;
|
|
217
|
+
return { message: textMessage, text: textMessage, isImage: false };
|
|
215
218
|
}
|
|
216
219
|
async renderTextAsImage(textMessage) {
|
|
217
220
|
const puppeteer = this.ctx.puppeteer;
|
|
@@ -221,19 +224,36 @@ class Notifier extends koishi_1.Service {
|
|
|
221
224
|
const html = this.buildImageHtml(textMessage);
|
|
222
225
|
const task = puppeteer.render(html);
|
|
223
226
|
const timeout = this.config.renderTimeoutMs || 12000;
|
|
224
|
-
const
|
|
227
|
+
const rendered = await Promise.race([
|
|
225
228
|
task,
|
|
226
229
|
new Promise((resolve) => setTimeout(() => resolve(null), timeout)),
|
|
227
230
|
]);
|
|
228
|
-
if (!
|
|
231
|
+
if (!rendered)
|
|
229
232
|
return null;
|
|
230
|
-
return
|
|
233
|
+
return this.normalizeRenderedImage(rendered);
|
|
231
234
|
}
|
|
232
235
|
catch (error) {
|
|
233
236
|
this.ctx.logger('githubsth').warn('Image render failed:', error);
|
|
234
237
|
return null;
|
|
235
238
|
}
|
|
236
239
|
}
|
|
240
|
+
normalizeRenderedImage(rendered) {
|
|
241
|
+
if (!rendered)
|
|
242
|
+
return null;
|
|
243
|
+
if (typeof rendered === 'string') {
|
|
244
|
+
const trimmed = rendered.trim();
|
|
245
|
+
if (trimmed.startsWith('<img'))
|
|
246
|
+
return trimmed;
|
|
247
|
+
if (trimmed.startsWith('data:image/'))
|
|
248
|
+
return koishi_1.h.image(trimmed);
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
if (Buffer.isBuffer(rendered))
|
|
252
|
+
return koishi_1.h.image(rendered, 'image/png');
|
|
253
|
+
if (rendered instanceof Uint8Array)
|
|
254
|
+
return koishi_1.h.image(Buffer.from(rendered), 'image/png');
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
237
257
|
buildImageHtml(textMessage) {
|
|
238
258
|
const escaped = this.escapeHtml(textMessage).replace(/\n/g, '<br/>');
|
|
239
259
|
const width = this.config.renderWidth || 840;
|
|
@@ -482,22 +502,31 @@ class Notifier extends koishi_1.Service {
|
|
|
482
502
|
}
|
|
483
503
|
}
|
|
484
504
|
}
|
|
485
|
-
async sendMessage(rule,
|
|
505
|
+
async sendMessage(rule, outbound) {
|
|
486
506
|
const bots = this.ctx.bots.filter((bot) => !rule.platform || bot.platform === rule.platform);
|
|
487
507
|
if (!bots.length)
|
|
488
508
|
return;
|
|
489
509
|
for (const bot of bots) {
|
|
490
510
|
try {
|
|
491
|
-
await this.sendWithRetry(bot, rule.channelId, message);
|
|
492
|
-
if (this.config.debug)
|
|
511
|
+
await this.sendWithRetry(bot, rule.channelId, outbound.message);
|
|
512
|
+
if (this.config.debug)
|
|
493
513
|
this.ctx.logger('notifier').info(`Sent message to ${rule.channelId} via ${bot.platform}:${bot.selfId}`);
|
|
494
|
-
}
|
|
495
514
|
return;
|
|
496
515
|
}
|
|
497
516
|
catch (error) {
|
|
498
|
-
if (this.config.
|
|
499
|
-
|
|
517
|
+
if (outbound.isImage && this.config.renderFallback === 'text') {
|
|
518
|
+
try {
|
|
519
|
+
await this.sendWithRetry(bot, rule.channelId, outbound.text);
|
|
520
|
+
this.ctx.logger('notifier').warn(`Image failed on ${bot.platform}:${bot.selfId}, fallback to text succeeded.`);
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
catch (fallbackError) {
|
|
524
|
+
if (this.config.debug)
|
|
525
|
+
this.ctx.logger('notifier').warn(`Fallback text send failed: ${fallbackError}`);
|
|
526
|
+
}
|
|
500
527
|
}
|
|
528
|
+
if (this.config.debug)
|
|
529
|
+
this.ctx.logger('notifier').warn(`Bot ${bot.sid} failed to send message with retries: ${error}`);
|
|
501
530
|
}
|
|
502
531
|
}
|
|
503
532
|
this.ctx.logger('notifier').warn(`Failed to send message to ${rule.channelId}`);
|
package/package.json
CHANGED