koishi-plugin-githubsth 1.0.3 → 1.0.4

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.
@@ -37,17 +37,12 @@ exports.apply = apply;
37
37
  const repo = __importStar(require("./repo"));
38
38
  const admin = __importStar(require("./admin"));
39
39
  const subscribe = __importStar(require("./subscribe"));
40
+ const render = __importStar(require("./render"));
40
41
  function apply(ctx, config) {
41
- console.log('Applying githubsth commands...');
42
- // Register parent command to show help
43
- ctx.command('githubsth', 'GitHub 推送通知')
44
- .action(({ session }) => {
45
- session?.execute('help githubsth');
46
- });
42
+ ctx.command('githubsth', 'GitHub 订阅通知')
43
+ .action(({ session }) => session?.execute('help githubsth'));
47
44
  ctx.plugin(repo, config);
48
- console.log('githubsth.repo loaded');
49
45
  ctx.plugin(admin, config);
50
- console.log('githubsth.admin loaded');
51
46
  ctx.plugin(subscribe, config);
52
- console.log('githubsth.subscribe loaded');
47
+ ctx.plugin(render, config);
53
48
  }
@@ -0,0 +1,3 @@
1
+ import { Context } from 'koishi';
2
+ import { Config } from '../config';
3
+ export declare function apply(ctx: Context, config: Config): void;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.apply = apply;
4
+ const modes = ['text', 'image', 'auto'];
5
+ const themes = ['compact', 'card', 'terminal'];
6
+ const events = ['push', 'issues', 'issue_comment', 'pull_request', 'pull_request_review', 'star', 'fork', 'release', 'discussion', 'workflow_run'];
7
+ function apply(ctx, config) {
8
+ ctx.command('githubsth.render', '通知渲染设置(文本/图片)', { authority: 3 })
9
+ .alias('gh.render');
10
+ ctx.command('githubsth.render.status', '查看渲染状态', { authority: 3 })
11
+ .action(async () => {
12
+ const status = ctx.githubsthNotifier.getRenderStatus();
13
+ return [
14
+ `mode: ${status.mode} (configured: ${status.configuredMode})`,
15
+ `fallback: ${status.fallback}`,
16
+ `theme: ${status.theme}`,
17
+ `width: ${status.width}`,
18
+ `timeout: ${status.timeoutMs}ms`,
19
+ `puppeteer: ${status.hasPuppeteer ? 'ready' : 'missing'}`,
20
+ ].join('\n');
21
+ });
22
+ ctx.command('githubsth.render.mode <mode:string>', '切换渲染模式(text/image/auto)', { authority: 3 })
23
+ .action(async (_, mode) => {
24
+ if (!mode || !modes.includes(mode)) {
25
+ return `无效模式。可选:${modes.join(', ')}`;
26
+ }
27
+ ctx.githubsthNotifier.setRenderMode(mode);
28
+ return `已切换运行时渲染模式为 ${mode}(重启后恢复配置值 ${config.renderMode})。`;
29
+ });
30
+ ctx.command('githubsth.render.theme <theme:string>', '切换图片主题(compact/card/terminal)', { authority: 3 })
31
+ .action(async (_, theme) => {
32
+ if (!theme || !themes.includes(theme)) {
33
+ return `无效主题。可选:${themes.join(', ')}`;
34
+ }
35
+ config.renderTheme = theme;
36
+ return `已切换图片主题为 ${theme}(当前进程生效)。`;
37
+ });
38
+ ctx.command('githubsth.render.width <width:number>', '设置图片宽度', { authority: 3 })
39
+ .action(async (_, width) => {
40
+ if (!width || Number.isNaN(width))
41
+ return '请提供有效的数字宽度。';
42
+ const normalized = Math.max(480, Math.min(1600, Math.floor(width)));
43
+ config.renderWidth = normalized;
44
+ return `已设置图片宽度为 ${normalized}px(当前进程生效)。`;
45
+ });
46
+ ctx.command('githubsth.render.preview [event:string]', '预览通知渲染', { authority: 3 })
47
+ .action(async ({ session }, event) => {
48
+ const selected = event && events.includes(event) ? event : 'issue_comment';
49
+ if (event && !events.includes(event)) {
50
+ await session?.send(`未知事件 ${event},已改用默认事件 issue_comment。`);
51
+ }
52
+ const preview = await ctx.githubsthNotifier.renderPreview(selected);
53
+ return preview || '预览失败:请检查 puppeteer 或渲染配置。';
54
+ });
55
+ }
package/lib/config.d.ts CHANGED
@@ -5,6 +5,9 @@ export interface Rule {
5
5
  platform?: string;
6
6
  events: string[];
7
7
  }
8
+ export type RenderMode = 'text' | 'image' | 'auto';
9
+ export type RenderFallback = 'text' | 'drop';
10
+ export type RenderTheme = 'compact' | 'card' | 'terminal';
8
11
  export interface Config {
9
12
  defaultOwner?: string;
10
13
  defaultRepo?: string;
@@ -16,6 +19,11 @@ export interface Config {
16
19
  sendRetryCount: number;
17
20
  sendRetryBaseDelayMs: number;
18
21
  formatterLocale: 'zh-CN' | 'en-US';
22
+ renderMode: RenderMode;
23
+ renderFallback: RenderFallback;
24
+ renderTheme: RenderTheme;
25
+ renderWidth: number;
26
+ renderTimeoutMs: number;
19
27
  rules?: Rule[];
20
28
  }
21
29
  export declare const Config: Schema<Config>;
package/lib/config.js CHANGED
@@ -15,6 +15,22 @@ exports.Config = koishi_1.Schema.object({
15
15
  koishi_1.Schema.const('zh-CN').description('中文'),
16
16
  koishi_1.Schema.const('en-US').description('English'),
17
17
  ]).default('zh-CN').description('通知文本语言。'),
18
+ renderMode: koishi_1.Schema.union([
19
+ koishi_1.Schema.const('auto').description('自动:优先图片,失败回退'),
20
+ koishi_1.Schema.const('image').description('仅图片'),
21
+ koishi_1.Schema.const('text').description('仅文本'),
22
+ ]).default('auto').description('通知渲染模式。'),
23
+ renderFallback: koishi_1.Schema.union([
24
+ koishi_1.Schema.const('text').description('图片失败回退文本'),
25
+ koishi_1.Schema.const('drop').description('图片失败则丢弃'),
26
+ ]).default('text').description('图片渲染失败时的回退策略。'),
27
+ renderTheme: koishi_1.Schema.union([
28
+ koishi_1.Schema.const('compact').description('紧凑样式'),
29
+ koishi_1.Schema.const('card').description('卡片样式'),
30
+ koishi_1.Schema.const('terminal').description('终端样式'),
31
+ ]).default('compact').description('图片通知主题。'),
32
+ renderWidth: koishi_1.Schema.number().min(480).max(1600).default(840).description('图片宽度(像素)。'),
33
+ renderTimeoutMs: koishi_1.Schema.number().min(1000).max(60000).default(12000).description('单次图片渲染超时(毫秒)。'),
18
34
  defaultEvents: koishi_1.Schema.array(koishi_1.Schema.string())
19
35
  .default(['push', 'issues', 'issue_comment', 'pull_request', 'pull_request_review', 'release', 'star', 'fork'])
20
36
  .description('未显式指定时使用的默认订阅事件列表。'),
package/lib/database.js CHANGED
@@ -10,6 +10,7 @@ function apply(ctx) {
10
10
  events: 'list',
11
11
  }, {
12
12
  autoInc: true,
13
+ unique: ['repo', 'channelId', 'platform'],
13
14
  });
14
15
  ctx.model.extend('github_trusted_repo', {
15
16
  id: 'unsigned',
package/lib/index.js CHANGED
@@ -50,7 +50,7 @@ const formatter_1 = require("./services/formatter");
50
50
  exports.name = 'githubsth';
51
51
  exports.inject = {
52
52
  required: ['database'],
53
- optional: ['github'],
53
+ optional: ['github', 'puppeteer'],
54
54
  };
55
55
  __exportStar(require("./config"), exports);
56
56
  function apply(ctx, config) {
@@ -1,4 +1,4 @@
1
- import { Context, Service, h } from 'koishi';
1
+ import { Context, Service } from 'koishi';
2
2
  import type { Config } from '../config';
3
3
  declare module 'koishi' {
4
4
  interface Context {
@@ -8,16 +8,16 @@ declare module 'koishi' {
8
8
  export declare class Formatter extends Service {
9
9
  private readonly locale;
10
10
  constructor(ctx: Context, config?: Partial<Config>);
11
- formatPush(payload: any): h | null;
12
- formatIssue(payload: any): h;
13
- formatPullRequest(payload: any): h;
14
- formatStar(payload: any): h | null;
15
- formatFork(payload: any): h;
16
- formatRelease(payload: any): h | null;
17
- formatDiscussion(payload: any): h;
18
- formatWorkflowRun(payload: any): h | null;
19
- formatIssueComment(payload: any): h | null;
20
- formatPullRequestReview(payload: any): h | null;
11
+ formatPush(payload: any): string | null;
12
+ formatIssue(payload: any): string;
13
+ formatPullRequest(payload: any): string;
14
+ formatStar(payload: any): string | null;
15
+ formatFork(payload: any): string;
16
+ formatRelease(payload: any): string | null;
17
+ formatDiscussion(payload: any): string;
18
+ formatWorkflowRun(payload: any): string | null;
19
+ formatIssueComment(payload: any): string | null;
20
+ formatPullRequestReview(payload: any): string | null;
21
21
  private summarizeCommentBody;
22
22
  private mapAction;
23
23
  private t;
@@ -10,7 +10,6 @@ const I18N = {
10
10
  unknownState: '未知状态',
11
11
  unknownBranch: '未知分支',
12
12
  unknownResult: '未知结果',
13
- noDescription: '无描述',
14
13
  emptyComment: '(空评论)',
15
14
  hiddenMachinePayload: '检测到自动化系统签名/编码载荷,已省略原始内容。',
16
15
  pushTitle: '🚀 [代码推送]',
@@ -71,7 +70,6 @@ const I18N = {
71
70
  unknownState: 'Unknown state',
72
71
  unknownBranch: 'Unknown branch',
73
72
  unknownResult: 'Unknown result',
74
- noDescription: 'No description',
75
73
  emptyComment: '(empty comment)',
76
74
  hiddenMachinePayload: 'Detected automated signature/encoded payload. Raw content hidden.',
77
75
  pushTitle: '🚀 [Push Event]',
@@ -280,11 +278,9 @@ class Formatter extends koishi_1.Service {
280
278
  const content = String(raw || '').replace(/\r/g, '').trim();
281
279
  if (!content)
282
280
  return this.t('emptyComment');
283
- // Typical Vercel/GitHub app machine signature payload: [vc]: #<token>:<payload>
284
281
  if (/^\[vc\]:\s*#[A-Za-z0-9+/=_:-]+/i.test(content)) {
285
282
  return this.t('hiddenMachinePayload');
286
283
  }
287
- // Very long high-entropy lines are usually bot payloads/signatures.
288
284
  const oneLine = content.replace(/\n+/g, ' ');
289
285
  const looksEncoded = oneLine.length > 120 && !/\s/.test(oneLine.slice(0, 80));
290
286
  if (looksEncoded)
@@ -301,7 +297,7 @@ class Formatter extends koishi_1.Service {
301
297
  return template.replace(/\{(\d+)\}/g, (_, idx) => String(params[Number(idx)] ?? ''));
302
298
  }
303
299
  render(lines) {
304
- return (0, koishi_1.h)('message', [(0, koishi_1.h)('text', { content: `${lines.join('\n')}\n` })]);
300
+ return `${lines.join('\n')}\n`;
305
301
  }
306
302
  }
307
303
  exports.Formatter = Formatter;
@@ -1,5 +1,5 @@
1
- import { Context, Service } from 'koishi';
2
- import { Config } from '../config';
1
+ import { Context, Service, h } from 'koishi';
2
+ import { Config, RenderMode } from '../config';
3
3
  declare module 'koishi' {
4
4
  interface Context {
5
5
  githubsthNotifier: Notifier;
@@ -11,9 +11,27 @@ export declare class Notifier extends Service {
11
11
  private readonly recentEventKeys;
12
12
  private readonly memoryDedupWindowMs;
13
13
  private dedupWriteCounter;
14
+ private runtimeRenderMode;
14
15
  constructor(ctx: Context, config: Config);
16
+ setRenderMode(mode: RenderMode): void;
17
+ getRenderMode(): RenderMode;
18
+ getRenderStatus(): {
19
+ mode: RenderMode;
20
+ configuredMode: RenderMode;
21
+ fallback: import("../config").RenderFallback;
22
+ theme: import("../config").RenderTheme;
23
+ width: number;
24
+ timeoutMs: number;
25
+ hasPuppeteer: boolean;
26
+ };
27
+ renderPreview(event?: string): Promise<string | h | null>;
15
28
  private registerListeners;
16
29
  private handleEvent;
30
+ private formatByEvent;
31
+ private prepareOutboundMessage;
32
+ private renderTextAsImage;
33
+ private buildImageHtml;
34
+ private escapeHtml;
17
35
  private extractRepoName;
18
36
  private patchPayloadForEvent;
19
37
  private buildEventDedupKey;
@@ -22,4 +40,5 @@ export declare class Notifier extends Service {
22
40
  private sendMessage;
23
41
  private sendWithRetry;
24
42
  private sleep;
43
+ private getPreviewPayload;
25
44
  }
@@ -10,9 +10,33 @@ class Notifier extends koishi_1.Service {
10
10
  this.recentEventKeys = new Map();
11
11
  this.memoryDedupWindowMs = 5000;
12
12
  this.dedupWriteCounter = 0;
13
+ this.runtimeRenderMode = null;
13
14
  this.ctx.logger('githubsth').info('Notifier service initialized');
14
15
  this.registerListeners();
15
16
  }
17
+ setRenderMode(mode) {
18
+ this.runtimeRenderMode = mode;
19
+ }
20
+ getRenderMode() {
21
+ return this.runtimeRenderMode || this.config.renderMode;
22
+ }
23
+ getRenderStatus() {
24
+ const puppeteer = this.ctx.puppeteer;
25
+ return {
26
+ mode: this.getRenderMode(),
27
+ configuredMode: this.config.renderMode,
28
+ fallback: this.config.renderFallback,
29
+ theme: this.config.renderTheme,
30
+ width: this.config.renderWidth,
31
+ timeoutMs: this.config.renderTimeoutMs,
32
+ hasPuppeteer: Boolean(puppeteer?.render),
33
+ };
34
+ }
35
+ async renderPreview(event = 'issue_comment') {
36
+ const payload = this.getPreviewPayload(event);
37
+ const text = this.formatByEvent(event, payload) || this.formatByEvent('issue_comment', this.getPreviewPayload('issue_comment')) || 'Preview unavailable.';
38
+ return this.prepareOutboundMessage(text);
39
+ }
16
40
  registerListeners() {
17
41
  const bind = (name, event) => {
18
42
  this.ctx.on(name, (payload) => this.handleEvent(event, payload));
@@ -76,9 +100,6 @@ class Notifier extends koishi_1.Service {
76
100
  }
77
101
  }
78
102
  async handleEvent(event, payload) {
79
- if (this.config.debug) {
80
- this.ctx.logger('githubsth').info(`Received event: ${event}`);
81
- }
82
103
  const realPayload = payload.payload || payload;
83
104
  if (payload.actor && !realPayload.sender) {
84
105
  const actorLogin = payload.actor.login || payload.actor.name || 'GitHub';
@@ -128,10 +149,6 @@ class Notifier extends koishi_1.Service {
128
149
  this.ctx.logger('githubsth').warn('Cannot query rules: repoName is missing');
129
150
  return;
130
151
  }
131
- if (this.config.debug) {
132
- this.ctx.logger('githubsth').info(`Processing event ${event} for ${repoName}`);
133
- this.ctx.logger('notifier').debug(JSON.stringify(realPayload, null, 2));
134
- }
135
152
  const repoNames = [repoName];
136
153
  if (repoName !== repoName.toLowerCase())
137
154
  repoNames.push(repoName.toLowerCase());
@@ -144,50 +161,151 @@ class Notifier extends koishi_1.Service {
144
161
  const matchedRules = allRules.filter((rule) => rule.events.includes('*') || rule.events.includes(event));
145
162
  if (!matchedRules.length)
146
163
  return;
147
- let message = null;
164
+ // De-duplicate same delivery target to avoid double push caused by duplicated rules.
165
+ const uniqueRules = Array.from(new Map(matchedRules.map((rule) => [`${repoName}|${rule.channelId}`, rule])).values());
166
+ const textMessage = this.formatByEvent(event, realPayload);
167
+ if (!textMessage)
168
+ return;
169
+ const outbound = await this.prepareOutboundMessage(textMessage);
170
+ if (!outbound) {
171
+ if (this.config.debug)
172
+ this.ctx.logger('githubsth').warn(`Drop message because render failed and fallback=drop (${event}, ${repoName})`);
173
+ return;
174
+ }
175
+ for (const rule of uniqueRules) {
176
+ await this.sendMessage(rule, outbound);
177
+ }
178
+ }
179
+ formatByEvent(event, payload) {
180
+ switch (event) {
181
+ case 'push':
182
+ return this.ctx.githubsthFormatter.formatPush(payload);
183
+ case 'issues':
184
+ return this.ctx.githubsthFormatter.formatIssue(payload);
185
+ case 'pull_request':
186
+ return this.ctx.githubsthFormatter.formatPullRequest(payload);
187
+ case 'star':
188
+ return this.ctx.githubsthFormatter.formatStar(payload);
189
+ case 'fork':
190
+ return this.ctx.githubsthFormatter.formatFork(payload);
191
+ case 'release':
192
+ return this.ctx.githubsthFormatter.formatRelease(payload);
193
+ case 'discussion':
194
+ return this.ctx.githubsthFormatter.formatDiscussion(payload);
195
+ case 'workflow_run':
196
+ return this.ctx.githubsthFormatter.formatWorkflowRun(payload);
197
+ case 'issue_comment':
198
+ return this.ctx.githubsthFormatter.formatIssueComment(payload);
199
+ case 'pull_request_review':
200
+ return this.ctx.githubsthFormatter.formatPullRequestReview(payload);
201
+ default:
202
+ return null;
203
+ }
204
+ }
205
+ async prepareOutboundMessage(textMessage) {
206
+ const mode = this.getRenderMode();
207
+ if (mode === 'text')
208
+ return textMessage;
209
+ const image = await this.renderTextAsImage(textMessage);
210
+ if (image)
211
+ return image;
212
+ if (mode === 'image' && this.config.renderFallback === 'drop')
213
+ return null;
214
+ return textMessage;
215
+ }
216
+ async renderTextAsImage(textMessage) {
217
+ const puppeteer = this.ctx.puppeteer;
218
+ if (!puppeteer || typeof puppeteer.render !== 'function')
219
+ return null;
148
220
  try {
149
- switch (event) {
150
- case 'push':
151
- message = this.ctx.githubsthFormatter.formatPush(realPayload);
152
- break;
153
- case 'issues':
154
- message = this.ctx.githubsthFormatter.formatIssue(realPayload);
155
- break;
156
- case 'pull_request':
157
- message = this.ctx.githubsthFormatter.formatPullRequest(realPayload);
158
- break;
159
- case 'star':
160
- message = this.ctx.githubsthFormatter.formatStar(realPayload);
161
- break;
162
- case 'fork':
163
- message = this.ctx.githubsthFormatter.formatFork(realPayload);
164
- break;
165
- case 'release':
166
- message = this.ctx.githubsthFormatter.formatRelease(realPayload);
167
- break;
168
- case 'discussion':
169
- message = this.ctx.githubsthFormatter.formatDiscussion(realPayload);
170
- break;
171
- case 'workflow_run':
172
- message = this.ctx.githubsthFormatter.formatWorkflowRun(realPayload);
173
- break;
174
- case 'issue_comment':
175
- message = this.ctx.githubsthFormatter.formatIssueComment(realPayload);
176
- break;
177
- case 'pull_request_review':
178
- message = this.ctx.githubsthFormatter.formatPullRequestReview(realPayload);
179
- break;
180
- }
221
+ const html = this.buildImageHtml(textMessage);
222
+ const task = puppeteer.render(html);
223
+ const timeout = this.config.renderTimeoutMs || 12000;
224
+ const buffer = await Promise.race([
225
+ task,
226
+ new Promise((resolve) => setTimeout(() => resolve(null), timeout)),
227
+ ]);
228
+ if (!buffer)
229
+ return null;
230
+ return koishi_1.h.image(buffer, 'image/png');
181
231
  }
182
232
  catch (error) {
183
- this.ctx.logger('githubsth').error(`Error formatting event ${event}:`, error);
184
- return;
233
+ this.ctx.logger('githubsth').warn('Image render failed:', error);
234
+ return null;
185
235
  }
186
- if (!message)
187
- return;
188
- for (const rule of matchedRules) {
189
- await this.sendMessage(rule, message);
236
+ }
237
+ buildImageHtml(textMessage) {
238
+ const escaped = this.escapeHtml(textMessage).replace(/\n/g, '<br/>');
239
+ const width = this.config.renderWidth || 840;
240
+ let bg = 'linear-gradient(135deg, #1f2937, #111827)';
241
+ let card = 'rgba(17, 24, 39, 0.92)';
242
+ let accent = '#22d3ee';
243
+ let font = "'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif";
244
+ if (this.config.renderTheme === 'card') {
245
+ bg = 'linear-gradient(140deg, #0f172a, #1e293b)';
246
+ card = 'rgba(15, 23, 42, 0.9)';
247
+ accent = '#60a5fa';
248
+ }
249
+ else if (this.config.renderTheme === 'terminal') {
250
+ bg = '#0b1020';
251
+ card = '#0b1220';
252
+ accent = '#34d399';
253
+ font = "'Consolas', 'Courier New', monospace";
190
254
  }
255
+ return `<!doctype html>
256
+ <html>
257
+ <head>
258
+ <meta charset="utf-8" />
259
+ <style>
260
+ * { box-sizing: border-box; }
261
+ body {
262
+ margin: 0;
263
+ width: ${width}px;
264
+ background: ${bg};
265
+ color: #e5e7eb;
266
+ font-family: ${font};
267
+ }
268
+ .wrap {
269
+ padding: 20px;
270
+ }
271
+ .card {
272
+ border-radius: 14px;
273
+ border: 1px solid rgba(148, 163, 184, 0.28);
274
+ background: ${card};
275
+ overflow: hidden;
276
+ }
277
+ .head {
278
+ padding: 12px 16px;
279
+ border-bottom: 1px solid rgba(148, 163, 184, 0.24);
280
+ font-weight: 700;
281
+ color: ${accent};
282
+ letter-spacing: .3px;
283
+ }
284
+ .content {
285
+ padding: 14px 16px;
286
+ line-height: 1.55;
287
+ word-break: break-word;
288
+ font-size: 14px;
289
+ }
290
+ </style>
291
+ </head>
292
+ <body>
293
+ <div class="wrap">
294
+ <div class="card">
295
+ <div class="head">GitHub Notification</div>
296
+ <div class="content">${escaped}</div>
297
+ </div>
298
+ </div>
299
+ </body>
300
+ </html>`;
301
+ }
302
+ escapeHtml(input) {
303
+ return String(input)
304
+ .replace(/&/g, '&amp;')
305
+ .replace(/</g, '&lt;')
306
+ .replace(/>/g, '&gt;')
307
+ .replace(/"/g, '&quot;')
308
+ .replace(/'/g, '&#39;');
191
309
  }
192
310
  extractRepoName(payload, realPayload, event) {
193
311
  let repoName = realPayload.repository?.full_name;
@@ -329,7 +447,6 @@ class Notifier extends koishi_1.Service {
329
447
  if (recent && now - recent <= this.memoryDedupWindowMs)
330
448
  return false;
331
449
  this.recentEventKeys.set(dedupKey, now);
332
- // durable dedup
333
450
  const exists = await this.ctx.database.get('github_event_dedup', { dedupKey });
334
451
  if (exists.length > 0)
335
452
  return false;
@@ -407,6 +524,55 @@ class Notifier extends koishi_1.Service {
407
524
  sleep(ms) {
408
525
  return new Promise((resolve) => setTimeout(resolve, ms));
409
526
  }
527
+ getPreviewPayload(event) {
528
+ const baseRepo = { full_name: 'acmuhan/JackalClientDocs', stargazers_count: 128 };
529
+ const baseUser = { login: 'acmuhan' };
530
+ const payload = {
531
+ action: 'created',
532
+ repository: baseRepo,
533
+ sender: baseUser,
534
+ issue: {
535
+ number: 29,
536
+ title: 'Delete demobot',
537
+ html_url: 'https://github.com/acmuhan/JackalClientDocs/issues/29',
538
+ pull_request: { html_url: 'https://github.com/acmuhan/JackalClientDocs/pull/29' },
539
+ },
540
+ comment: {
541
+ body: '[vc]: #gOsUN...=eyJpc01vbm9yZXBvIjp0cnVl...'
542
+ },
543
+ pull_request: {
544
+ number: 29,
545
+ title: 'Delete demobot',
546
+ state: 'open',
547
+ html_url: 'https://github.com/acmuhan/JackalClientDocs/pull/29',
548
+ },
549
+ workflow_run: {
550
+ name: 'Deploy',
551
+ conclusion: 'success',
552
+ head_branch: 'main',
553
+ html_url: 'https://github.com/acmuhan/JackalClientDocs/actions/runs/1',
554
+ },
555
+ commits: [
556
+ { id: 'ea5eaddca38f25ce013ee50d70addb49c8d28844', message: 'Delete demobot', author: { name: 'MuHan' } },
557
+ ],
558
+ ref: 'refs/heads/main',
559
+ compare: 'https://github.com/acmuhan/JackalClientDocs/compare/old...new',
560
+ pusher: { name: 'acmuhan' },
561
+ release: { tag_name: 'v1.2.0', name: 'Spring Patch', html_url: 'https://github.com/acmuhan/JackalClientDocs/releases/tag/v1.2.0' },
562
+ forkee: { full_name: 'acmuhan/JackalClientDocs-fork' },
563
+ discussion: { number: 7, title: 'Roadmap', html_url: 'https://github.com/acmuhan/JackalClientDocs/discussions/7' },
564
+ review: { state: 'approved', html_url: 'https://github.com/acmuhan/JackalClientDocs/pull/29#pullrequestreview-1' },
565
+ };
566
+ if (event === 'star')
567
+ payload.action = 'created';
568
+ if (event === 'workflow_run')
569
+ payload.action = 'completed';
570
+ if (event === 'pull_request_review')
571
+ payload.action = 'submitted';
572
+ if (event === 'release')
573
+ payload.action = 'published';
574
+ return payload;
575
+ }
410
576
  }
411
577
  exports.Notifier = Notifier;
412
578
  Notifier.inject = ['githubsthFormatter', 'database'];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koishi-plugin-githubsth",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Github Subscriptions Notifications, push notifications for GitHub subscriptions For koishi",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",