koishi-plugin-github-webhook-pusher 0.0.6 → 0.0.8

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.
@@ -0,0 +1,99 @@
1
+ /**
2
+ * 订阅数据访问层
3
+ * 需求: 3.1-3.7, 5.1, 5.2
4
+ */
5
+ import { Context } from 'koishi';
6
+ import { Subscription } from '../database';
7
+ import { EventType } from '../types';
8
+ /** 推送目标信息 */
9
+ export interface PushTarget {
10
+ platform: string;
11
+ channelId: string;
12
+ guildId?: string;
13
+ userId?: string;
14
+ }
15
+ /** 会话标识 */
16
+ export interface SessionIdentifier {
17
+ platform: string;
18
+ channelId: string;
19
+ guildId?: string;
20
+ userId?: string;
21
+ }
22
+ /**
23
+ * 创建订阅
24
+ * 需求 3.1: 为当前会话创建订阅记录
25
+ * @param ctx Koishi 上下文
26
+ * @param session 会话标识
27
+ * @param repo 仓库名 (owner/repo)
28
+ * @param defaultEvents 默认事件列表
29
+ * @returns 创建的订阅记录
30
+ */
31
+ export declare function createSubscription(ctx: Context, session: SessionIdentifier, repo: string, defaultEvents: EventType[]): Promise<Subscription>;
32
+ /**
33
+ * 移除订阅
34
+ * 需求 3.3: 移除当前会话对该仓库的订阅
35
+ * @param ctx Koishi 上下文
36
+ * @param session 会话标识
37
+ * @param repo 仓库名 (owner/repo)
38
+ * @returns 是否成功移除
39
+ */
40
+ export declare function removeSubscription(ctx: Context, session: SessionIdentifier, repo: string): Promise<boolean>;
41
+ /**
42
+ * 列出会话的所有订阅
43
+ * 需求 3.4: 显示当前会话的所有订阅及其事件设置
44
+ * @param ctx Koishi 上下文
45
+ * @param session 会话标识
46
+ * @returns 订阅列表
47
+ */
48
+ export declare function listSubscriptions(ctx: Context, session: SessionIdentifier): Promise<Subscription[]>;
49
+ /**
50
+ * 获取单个订阅
51
+ * 需求 3.5: 显示该仓库订阅的事件类型列表
52
+ * @param ctx Koishi 上下文
53
+ * @param session 会话标识
54
+ * @param repo 仓库名 (owner/repo)
55
+ * @returns 订阅记录,不存在返回 null
56
+ */
57
+ export declare function getSubscription(ctx: Context, session: SessionIdentifier, repo: string): Promise<Subscription | null>;
58
+ /**
59
+ * 更新订阅的事件类型
60
+ * 需求 3.6: 根据 +/- 前缀启用或禁用对应事件类型
61
+ * @param ctx Koishi 上下文
62
+ * @param session 会话标识
63
+ * @param repo 仓库名 (owner/repo)
64
+ * @param events 新的事件列表
65
+ * @returns 是否成功更新
66
+ */
67
+ export declare function updateEvents(ctx: Context, session: SessionIdentifier, repo: string, events: EventType[]): Promise<boolean>;
68
+ /**
69
+ * 查询订阅目标
70
+ * 需求 5.1, 5.2: 查询所有订阅该仓库的目标会话,并根据事件类型过滤
71
+ * @param ctx Koishi 上下文
72
+ * @param repo 仓库名 (owner/repo)
73
+ * @param eventType 事件类型
74
+ * @returns 推送目标列表
75
+ */
76
+ export declare function queryTargets(ctx: Context, repo: string, eventType: EventType): Promise<PushTarget[]>;
77
+ /**
78
+ * 获取仓库的所有订阅
79
+ * @param ctx Koishi 上下文
80
+ * @param repo 仓库名 (owner/repo)
81
+ * @returns 订阅列表
82
+ */
83
+ export declare function getRepoSubscriptions(ctx: Context, repo: string): Promise<Subscription[]>;
84
+ /**
85
+ * 启用订阅
86
+ * @param ctx Koishi 上下文
87
+ * @param session 会话标识
88
+ * @param repo 仓库名 (owner/repo)
89
+ * @returns 是否成功启用
90
+ */
91
+ export declare function enableSubscription(ctx: Context, session: SessionIdentifier, repo: string): Promise<boolean>;
92
+ /**
93
+ * 禁用订阅
94
+ * @param ctx Koishi 上下文
95
+ * @param session 会话标识
96
+ * @param repo 仓库名 (owner/repo)
97
+ * @returns 是否成功禁用
98
+ */
99
+ export declare function disableSubscription(ctx: Context, session: SessionIdentifier, repo: string): Promise<boolean>;
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ /**
3
+ * 订阅数据访问层
4
+ * 需求: 3.1-3.7, 5.1, 5.2
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.createSubscription = createSubscription;
8
+ exports.removeSubscription = removeSubscription;
9
+ exports.listSubscriptions = listSubscriptions;
10
+ exports.getSubscription = getSubscription;
11
+ exports.updateEvents = updateEvents;
12
+ exports.queryTargets = queryTargets;
13
+ exports.getRepoSubscriptions = getRepoSubscriptions;
14
+ exports.enableSubscription = enableSubscription;
15
+ exports.disableSubscription = disableSubscription;
16
+ /**
17
+ * 创建订阅
18
+ * 需求 3.1: 为当前会话创建订阅记录
19
+ * @param ctx Koishi 上下文
20
+ * @param session 会话标识
21
+ * @param repo 仓库名 (owner/repo)
22
+ * @param defaultEvents 默认事件列表
23
+ * @returns 创建的订阅记录
24
+ */
25
+ async function createSubscription(ctx, session, repo, defaultEvents) {
26
+ const now = new Date();
27
+ // 检查是否已存在
28
+ const existing = await ctx.database.get('github_subscriptions', {
29
+ platform: session.platform,
30
+ channelId: session.channelId,
31
+ repo,
32
+ });
33
+ if (existing.length > 0) {
34
+ return existing[0];
35
+ }
36
+ await ctx.database.create('github_subscriptions', {
37
+ platform: session.platform,
38
+ channelId: session.channelId,
39
+ guildId: session.guildId || '',
40
+ userId: session.userId || '',
41
+ repo,
42
+ events: defaultEvents,
43
+ enabled: true,
44
+ createdAt: now,
45
+ updatedAt: now,
46
+ });
47
+ const [created] = await ctx.database.get('github_subscriptions', {
48
+ platform: session.platform,
49
+ channelId: session.channelId,
50
+ repo,
51
+ });
52
+ return created;
53
+ }
54
+ /**
55
+ * 移除订阅
56
+ * 需求 3.3: 移除当前会话对该仓库的订阅
57
+ * @param ctx Koishi 上下文
58
+ * @param session 会话标识
59
+ * @param repo 仓库名 (owner/repo)
60
+ * @returns 是否成功移除
61
+ */
62
+ async function removeSubscription(ctx, session, repo) {
63
+ const result = await ctx.database.remove('github_subscriptions', {
64
+ platform: session.platform,
65
+ channelId: session.channelId,
66
+ repo,
67
+ });
68
+ return (result.removed ?? 0) > 0;
69
+ }
70
+ /**
71
+ * 列出会话的所有订阅
72
+ * 需求 3.4: 显示当前会话的所有订阅及其事件设置
73
+ * @param ctx Koishi 上下文
74
+ * @param session 会话标识
75
+ * @returns 订阅列表
76
+ */
77
+ async function listSubscriptions(ctx, session) {
78
+ return ctx.database.get('github_subscriptions', {
79
+ platform: session.platform,
80
+ channelId: session.channelId,
81
+ });
82
+ }
83
+ /**
84
+ * 获取单个订阅
85
+ * 需求 3.5: 显示该仓库订阅的事件类型列表
86
+ * @param ctx Koishi 上下文
87
+ * @param session 会话标识
88
+ * @param repo 仓库名 (owner/repo)
89
+ * @returns 订阅记录,不存在返回 null
90
+ */
91
+ async function getSubscription(ctx, session, repo) {
92
+ const subs = await ctx.database.get('github_subscriptions', {
93
+ platform: session.platform,
94
+ channelId: session.channelId,
95
+ repo,
96
+ });
97
+ return subs.length > 0 ? subs[0] : null;
98
+ }
99
+ /**
100
+ * 更新订阅的事件类型
101
+ * 需求 3.6: 根据 +/- 前缀启用或禁用对应事件类型
102
+ * @param ctx Koishi 上下文
103
+ * @param session 会话标识
104
+ * @param repo 仓库名 (owner/repo)
105
+ * @param events 新的事件列表
106
+ * @returns 是否成功更新
107
+ */
108
+ async function updateEvents(ctx, session, repo, events) {
109
+ const result = await ctx.database.set('github_subscriptions', {
110
+ platform: session.platform,
111
+ channelId: session.channelId,
112
+ repo,
113
+ }, {
114
+ events,
115
+ updatedAt: new Date(),
116
+ });
117
+ return (result.modified ?? 0) > 0;
118
+ }
119
+ /**
120
+ * 查询订阅目标
121
+ * 需求 5.1, 5.2: 查询所有订阅该仓库的目标会话,并根据事件类型过滤
122
+ * @param ctx Koishi 上下文
123
+ * @param repo 仓库名 (owner/repo)
124
+ * @param eventType 事件类型
125
+ * @returns 推送目标列表
126
+ */
127
+ async function queryTargets(ctx, repo, eventType) {
128
+ // 获取所有订阅该仓库且已启用的订阅
129
+ const subscriptions = await ctx.database.get('github_subscriptions', {
130
+ repo,
131
+ enabled: true,
132
+ });
133
+ // 过滤出订阅了该事件类型的目标
134
+ return subscriptions
135
+ .filter(sub => sub.events.includes(eventType))
136
+ .map(sub => ({
137
+ platform: sub.platform,
138
+ channelId: sub.channelId,
139
+ guildId: sub.guildId || undefined,
140
+ userId: sub.userId || undefined,
141
+ }));
142
+ }
143
+ /**
144
+ * 获取仓库的所有订阅
145
+ * @param ctx Koishi 上下文
146
+ * @param repo 仓库名 (owner/repo)
147
+ * @returns 订阅列表
148
+ */
149
+ async function getRepoSubscriptions(ctx, repo) {
150
+ return ctx.database.get('github_subscriptions', { repo });
151
+ }
152
+ /**
153
+ * 启用订阅
154
+ * @param ctx Koishi 上下文
155
+ * @param session 会话标识
156
+ * @param repo 仓库名 (owner/repo)
157
+ * @returns 是否成功启用
158
+ */
159
+ async function enableSubscription(ctx, session, repo) {
160
+ const result = await ctx.database.set('github_subscriptions', {
161
+ platform: session.platform,
162
+ channelId: session.channelId,
163
+ repo,
164
+ }, {
165
+ enabled: true,
166
+ updatedAt: new Date(),
167
+ });
168
+ return (result.modified ?? 0) > 0;
169
+ }
170
+ /**
171
+ * 禁用订阅
172
+ * @param ctx Koishi 上下文
173
+ * @param session 会话标识
174
+ * @param repo 仓库名 (owner/repo)
175
+ * @returns 是否成功禁用
176
+ */
177
+ async function disableSubscription(ctx, session, repo) {
178
+ const result = await ctx.database.set('github_subscriptions', {
179
+ platform: session.platform,
180
+ channelId: session.channelId,
181
+ repo,
182
+ }, {
183
+ enabled: false,
184
+ updatedAt: new Date(),
185
+ });
186
+ return (result.modified ?? 0) > 0;
187
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * 信任仓库数据访问层
3
+ * 需求: 2.1-2.7
4
+ */
5
+ import { Context } from 'koishi';
6
+ import { TrustedRepo } from '../database';
7
+ /**
8
+ * 验证仓库名格式是否符合 owner/repo 格式
9
+ * @param repo 仓库名
10
+ * @returns 是否有效
11
+ */
12
+ export declare function isValidRepoFormat(repo: string): boolean;
13
+ /**
14
+ * 添加信任仓库
15
+ * 需求 2.1: 将仓库添加到信任列表并持久化到数据库
16
+ * @param ctx Koishi 上下文
17
+ * @param repo 仓库名 (owner/repo)
18
+ * @returns 添加的仓库记录,如果格式错误返回 null
19
+ */
20
+ export declare function addTrustedRepo(ctx: Context, repo: string): Promise<TrustedRepo | null>;
21
+ /**
22
+ * 移除信任仓库
23
+ * 需求 2.2: 从信任列表中移除该仓库
24
+ * @param ctx Koishi 上下文
25
+ * @param repo 仓库名 (owner/repo)
26
+ * @returns 是否成功移除
27
+ */
28
+ export declare function removeTrustedRepo(ctx: Context, repo: string): Promise<boolean>;
29
+ /**
30
+ * 列出所有信任仓库
31
+ * 需求 2.3: 显示所有信任仓库及其启用状态
32
+ * @param ctx Koishi 上下文
33
+ * @returns 信任仓库列表
34
+ */
35
+ export declare function listTrustedRepos(ctx: Context): Promise<TrustedRepo[]>;
36
+ /**
37
+ * 检查仓库是否在信任列表中且已启用
38
+ * 需求 2.6: 验证仓库是否可以处理事件
39
+ * @param ctx Koishi 上下文
40
+ * @param repo 仓库名 (owner/repo)
41
+ * @returns 是否信任且启用
42
+ */
43
+ export declare function isTrusted(ctx: Context, repo: string): Promise<boolean>;
44
+ /**
45
+ * 检查仓库是否在信任列表中(不考虑启用状态)
46
+ * @param ctx Koishi 上下文
47
+ * @param repo 仓库名 (owner/repo)
48
+ * @returns 是否在信任列表中
49
+ */
50
+ export declare function isInTrustList(ctx: Context, repo: string): Promise<boolean>;
51
+ /**
52
+ * 启用信任仓库
53
+ * 需求 2.4: 启用该仓库的事件处理
54
+ * @param ctx Koishi 上下文
55
+ * @param repo 仓库名 (owner/repo)
56
+ * @returns 是否成功启用
57
+ */
58
+ export declare function enableRepo(ctx: Context, repo: string): Promise<boolean>;
59
+ /**
60
+ * 禁用信任仓库
61
+ * 需求 2.5: 禁用该仓库的事件处理
62
+ * @param ctx Koishi 上下文
63
+ * @param repo 仓库名 (owner/repo)
64
+ * @returns 是否成功禁用
65
+ */
66
+ export declare function disableRepo(ctx: Context, repo: string): Promise<boolean>;
67
+ /**
68
+ * 获取单个信任仓库信息
69
+ * @param ctx Koishi 上下文
70
+ * @param repo 仓库名 (owner/repo)
71
+ * @returns 仓库信息,不存在返回 null
72
+ */
73
+ export declare function getTrustedRepo(ctx: Context, repo: string): Promise<TrustedRepo | null>;
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ /**
3
+ * 信任仓库数据访问层
4
+ * 需求: 2.1-2.7
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.isValidRepoFormat = isValidRepoFormat;
8
+ exports.addTrustedRepo = addTrustedRepo;
9
+ exports.removeTrustedRepo = removeTrustedRepo;
10
+ exports.listTrustedRepos = listTrustedRepos;
11
+ exports.isTrusted = isTrusted;
12
+ exports.isInTrustList = isInTrustList;
13
+ exports.enableRepo = enableRepo;
14
+ exports.disableRepo = disableRepo;
15
+ exports.getTrustedRepo = getTrustedRepo;
16
+ /** 仓库名格式验证正则表达式 */
17
+ const REPO_NAME_REGEX = /^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+$/;
18
+ /**
19
+ * 验证仓库名格式是否符合 owner/repo 格式
20
+ * @param repo 仓库名
21
+ * @returns 是否有效
22
+ */
23
+ function isValidRepoFormat(repo) {
24
+ if (!repo || typeof repo !== 'string') {
25
+ return false;
26
+ }
27
+ return REPO_NAME_REGEX.test(repo);
28
+ }
29
+ /**
30
+ * 添加信任仓库
31
+ * 需求 2.1: 将仓库添加到信任列表并持久化到数据库
32
+ * @param ctx Koishi 上下文
33
+ * @param repo 仓库名 (owner/repo)
34
+ * @returns 添加的仓库记录,如果格式错误返回 null
35
+ */
36
+ async function addTrustedRepo(ctx, repo) {
37
+ if (!isValidRepoFormat(repo)) {
38
+ return null;
39
+ }
40
+ const now = new Date();
41
+ // 检查是否已存在
42
+ const existing = await ctx.database.get('github_trusted_repos', { repo });
43
+ if (existing.length > 0) {
44
+ return existing[0];
45
+ }
46
+ await ctx.database.create('github_trusted_repos', {
47
+ repo,
48
+ enabled: true,
49
+ createdAt: now,
50
+ updatedAt: now,
51
+ });
52
+ const [created] = await ctx.database.get('github_trusted_repos', { repo });
53
+ return created;
54
+ }
55
+ /**
56
+ * 移除信任仓库
57
+ * 需求 2.2: 从信任列表中移除该仓库
58
+ * @param ctx Koishi 上下文
59
+ * @param repo 仓库名 (owner/repo)
60
+ * @returns 是否成功移除
61
+ */
62
+ async function removeTrustedRepo(ctx, repo) {
63
+ const result = await ctx.database.remove('github_trusted_repos', { repo });
64
+ return (result.removed ?? 0) > 0;
65
+ }
66
+ /**
67
+ * 列出所有信任仓库
68
+ * 需求 2.3: 显示所有信任仓库及其启用状态
69
+ * @param ctx Koishi 上下文
70
+ * @returns 信任仓库列表
71
+ */
72
+ async function listTrustedRepos(ctx) {
73
+ return ctx.database.get('github_trusted_repos', {});
74
+ }
75
+ /**
76
+ * 检查仓库是否在信任列表中且已启用
77
+ * 需求 2.6: 验证仓库是否可以处理事件
78
+ * @param ctx Koishi 上下文
79
+ * @param repo 仓库名 (owner/repo)
80
+ * @returns 是否信任且启用
81
+ */
82
+ async function isTrusted(ctx, repo) {
83
+ const repos = await ctx.database.get('github_trusted_repos', { repo, enabled: true });
84
+ return repos.length > 0;
85
+ }
86
+ /**
87
+ * 检查仓库是否在信任列表中(不考虑启用状态)
88
+ * @param ctx Koishi 上下文
89
+ * @param repo 仓库名 (owner/repo)
90
+ * @returns 是否在信任列表中
91
+ */
92
+ async function isInTrustList(ctx, repo) {
93
+ const repos = await ctx.database.get('github_trusted_repos', { repo });
94
+ return repos.length > 0;
95
+ }
96
+ /**
97
+ * 启用信任仓库
98
+ * 需求 2.4: 启用该仓库的事件处理
99
+ * @param ctx Koishi 上下文
100
+ * @param repo 仓库名 (owner/repo)
101
+ * @returns 是否成功启用
102
+ */
103
+ async function enableRepo(ctx, repo) {
104
+ const result = await ctx.database.set('github_trusted_repos', { repo }, {
105
+ enabled: true,
106
+ updatedAt: new Date(),
107
+ });
108
+ return (result.modified ?? 0) > 0;
109
+ }
110
+ /**
111
+ * 禁用信任仓库
112
+ * 需求 2.5: 禁用该仓库的事件处理
113
+ * @param ctx Koishi 上下文
114
+ * @param repo 仓库名 (owner/repo)
115
+ * @returns 是否成功禁用
116
+ */
117
+ async function disableRepo(ctx, repo) {
118
+ const result = await ctx.database.set('github_trusted_repos', { repo }, {
119
+ enabled: false,
120
+ updatedAt: new Date(),
121
+ });
122
+ return (result.modified ?? 0) > 0;
123
+ }
124
+ /**
125
+ * 获取单个信任仓库信息
126
+ * @param ctx Koishi 上下文
127
+ * @param repo 仓库名 (owner/repo)
128
+ * @returns 仓库信息,不存在返回 null
129
+ */
130
+ async function getTrustedRepo(ctx, repo) {
131
+ const repos = await ctx.database.get('github_trusted_repos', { repo });
132
+ return repos.length > 0 ? repos[0] : null;
133
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 创建 GitHub Webhook 签名
3
+ * @param payload 原始请求体
4
+ * @param secret Webhook Secret
5
+ * @returns 签名字符串,格式为 sha256=<hex_digest>
6
+ */
7
+ export declare function createSignature(payload: string, secret: string): string;
8
+ /**
9
+ * 验证 GitHub Webhook 签名
10
+ * @param payload 原始请求体
11
+ * @param signature X-Hub-Signature-256 头的值
12
+ * @param secret 配置的 Webhook Secret
13
+ * @returns 签名是否有效
14
+ */
15
+ export declare function verifySignature(payload: string, signature: string, secret: string): boolean;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSignature = createSignature;
4
+ exports.verifySignature = verifySignature;
5
+ const crypto_1 = require("crypto");
6
+ /**
7
+ * 创建 GitHub Webhook 签名
8
+ * @param payload 原始请求体
9
+ * @param secret Webhook Secret
10
+ * @returns 签名字符串,格式为 sha256=<hex_digest>
11
+ */
12
+ function createSignature(payload, secret) {
13
+ const hmac = (0, crypto_1.createHmac)('sha256', secret);
14
+ hmac.update(payload, 'utf8');
15
+ return `sha256=${hmac.digest('hex')}`;
16
+ }
17
+ /**
18
+ * 验证 GitHub Webhook 签名
19
+ * @param payload 原始请求体
20
+ * @param signature X-Hub-Signature-256 头的值
21
+ * @param secret 配置的 Webhook Secret
22
+ * @returns 签名是否有效
23
+ */
24
+ function verifySignature(payload, signature, secret) {
25
+ // 检查签名格式
26
+ if (!signature || !signature.startsWith('sha256=')) {
27
+ return false;
28
+ }
29
+ const expected = createSignature(payload, secret);
30
+ // 使用常量时间比较防止时序攻击
31
+ const sigBuffer = Buffer.from(signature);
32
+ const expectedBuffer = Buffer.from(expected);
33
+ // 长度不同时也需要进行比较以保持常量时间
34
+ if (sigBuffer.length !== expectedBuffer.length) {
35
+ return false;
36
+ }
37
+ return (0, crypto_1.timingSafeEqual)(sigBuffer, expectedBuffer);
38
+ }
package/lib/types.d.ts ADDED
@@ -0,0 +1,49 @@
1
+ /**
2
+ * 事件类型和接口定义
3
+ * 需求: 4.1-4.7
4
+ */
5
+ /** 支持的事件类型 */
6
+ export type EventType = 'issues' | 'issue_comment' | 'pull_request' | 'pull_request_review' | 'pull_request_review_comment' | 'release' | 'push' | 'star' | 'fork' | 'create' | 'delete' | 'workflow_run';
7
+ /** 提交信息 */
8
+ export interface CommitInfo {
9
+ sha: string;
10
+ message: string;
11
+ author: string;
12
+ url: string;
13
+ }
14
+ /** 解析后的事件数据 */
15
+ export interface ParsedEvent {
16
+ type: EventType;
17
+ displayType: string;
18
+ repo: string;
19
+ actor: string;
20
+ action?: string;
21
+ title?: string;
22
+ number?: number;
23
+ url: string;
24
+ body?: string;
25
+ commits?: CommitInfo[];
26
+ totalCommits?: number;
27
+ ref?: string;
28
+ tagName?: string;
29
+ starCount?: number;
30
+ }
31
+ /** 事件类型显示信息 */
32
+ export interface EventDisplayInfo {
33
+ name: string;
34
+ emoji: string;
35
+ }
36
+ /** 事件类型到显示名称和 emoji 的映射 */
37
+ export declare const EVENT_DISPLAY_MAP: Record<EventType, EventDisplayInfo>;
38
+ /**
39
+ * 获取事件类型的显示名称
40
+ * @param type 事件类型
41
+ * @returns 显示名称
42
+ */
43
+ export declare function getDisplayType(type: EventType): string;
44
+ /**
45
+ * 获取事件类型的 emoji
46
+ * @param type 事件类型
47
+ * @returns emoji 字符
48
+ */
49
+ export declare function getEventEmoji(type: EventType): string;
package/lib/types.js ADDED
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ /**
3
+ * 事件类型和接口定义
4
+ * 需求: 4.1-4.7
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.EVENT_DISPLAY_MAP = void 0;
8
+ exports.getDisplayType = getDisplayType;
9
+ exports.getEventEmoji = getEventEmoji;
10
+ /** 事件类型到显示名称和 emoji 的映射 */
11
+ exports.EVENT_DISPLAY_MAP = {
12
+ issues: { name: 'Issue', emoji: '📌' },
13
+ issue_comment: { name: 'Issue Comment', emoji: '💬' },
14
+ release: { name: 'Release', emoji: '🚀' },
15
+ push: { name: 'Commit', emoji: '⬆️' },
16
+ pull_request: { name: 'PR', emoji: '🔀' },
17
+ pull_request_review: { name: 'PR Review', emoji: '🧪' },
18
+ pull_request_review_comment: { name: 'PR Review Comment', emoji: '💬' },
19
+ star: { name: 'Star', emoji: '⭐' },
20
+ fork: { name: 'Fork', emoji: '🍴' },
21
+ create: { name: 'Create', emoji: '✨' },
22
+ delete: { name: 'Delete', emoji: '🗑️' },
23
+ workflow_run: { name: 'Workflow', emoji: '🧩' },
24
+ };
25
+ /**
26
+ * 获取事件类型的显示名称
27
+ * @param type 事件类型
28
+ * @returns 显示名称
29
+ */
30
+ function getDisplayType(type) {
31
+ return exports.EVENT_DISPLAY_MAP[type].name;
32
+ }
33
+ /**
34
+ * 获取事件类型的 emoji
35
+ * @param type 事件类型
36
+ * @returns emoji 字符
37
+ */
38
+ function getEventEmoji(type) {
39
+ return exports.EVENT_DISPLAY_MAP[type].emoji;
40
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Webhook 处理器
3
+ * 需求: 1.1-1.6, 2.6, 9.1-9.6
4
+ */
5
+ import { Context } from 'koishi';
6
+ import type { Context as KoaContext } from 'koa';
7
+ import { Config } from './config';
8
+ declare module 'koishi' {
9
+ interface Context {
10
+ server: {
11
+ post(path: string, handler: (ctx: KoaContext) => Promise<void>): void;
12
+ };
13
+ }
14
+ }
15
+ /**
16
+ * 注册 Webhook 处理器
17
+ * 需求 1.1: 在配置的路径上监听 HTTP POST 请求
18
+ * @param ctx Koishi 上下文
19
+ * @param config 插件配置
20
+ */
21
+ export declare function registerWebhook(ctx: Context, config: Config): void;