koishi-plugin-githubsth 1.0.5-alpha.2 → 1.0.5
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/assets/render-card.html +75 -93
- package/lib/commands/admin.js +12 -20
- package/lib/commands/render.js +135 -53
- package/lib/commands/repo.js +5 -10
- package/lib/commands/subscribe.js +24 -17
- package/lib/config.d.ts +6 -0
- package/lib/config.js +47 -41
- package/lib/database.d.ts +2 -1
- package/lib/database.js +1 -0
- package/lib/index.js +20 -0
- package/lib/locales/en-US.d.ts +67 -0
- package/lib/locales/en-US.js +67 -0
- package/lib/locales/zh-CN.d.ts +67 -0
- package/lib/locales/zh-CN.js +67 -0
- package/lib/services/formatter.js +31 -27
- package/lib/services/notifier.d.ts +11 -1
- package/lib/services/notifier.js +83 -9
- package/lib/services/render-card.d.ts +7 -4
- package/lib/services/render-card.js +155 -53
- package/package.json +1 -1
|
@@ -10,11 +10,9 @@
|
|
|
10
10
|
background: {{background}};
|
|
11
11
|
color: {{text}};
|
|
12
12
|
font-family: {{font}};
|
|
13
|
+
--status-accent: {{statusAccent}};
|
|
13
14
|
}
|
|
14
|
-
.wrap {
|
|
15
|
-
padding: 18px;
|
|
16
|
-
position: relative;
|
|
17
|
-
}
|
|
15
|
+
.wrap { padding: 18px; position: relative; }
|
|
18
16
|
.wrap::before {
|
|
19
17
|
content: '';
|
|
20
18
|
position: absolute;
|
|
@@ -40,6 +38,12 @@
|
|
|
40
38
|
background: {{cardTexture}};
|
|
41
39
|
opacity: 0.28;
|
|
42
40
|
}
|
|
41
|
+
.status-bar {
|
|
42
|
+
position: relative;
|
|
43
|
+
z-index: 2;
|
|
44
|
+
height: 3px;
|
|
45
|
+
background: linear-gradient(90deg, var(--status-accent), transparent);
|
|
46
|
+
}
|
|
43
47
|
.head {
|
|
44
48
|
position: relative;
|
|
45
49
|
z-index: 1;
|
|
@@ -51,24 +55,18 @@
|
|
|
51
55
|
gap: 12px;
|
|
52
56
|
}
|
|
53
57
|
.head-left { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
|
54
|
-
.dot {
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
.dot { width: 10px; height: 10px; border-radius: 999px; background: var(--status-accent); box-shadow: 0 0 0 3px {{pillBg}}; }
|
|
59
|
+
.repo { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; letter-spacing: 0.2px; }
|
|
60
|
+
.meta { color: {{muted}}; font-size: 12px; letter-spacing: 0.3px; }
|
|
61
|
+
.type-badge {
|
|
62
|
+
display: inline-flex;
|
|
63
|
+
align-items: center;
|
|
64
|
+
padding: 2px 8px;
|
|
57
65
|
border-radius: 999px;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
font-weight: 700;
|
|
63
|
-
white-space: nowrap;
|
|
64
|
-
overflow: hidden;
|
|
65
|
-
text-overflow: ellipsis;
|
|
66
|
-
letter-spacing: 0.2px;
|
|
67
|
-
}
|
|
68
|
-
.meta {
|
|
69
|
-
color: {{muted}};
|
|
70
|
-
font-size: 12px;
|
|
71
|
-
letter-spacing: 0.3px;
|
|
66
|
+
font-size: 11px;
|
|
67
|
+
border: 1px solid {{border}};
|
|
68
|
+
color: var(--status-accent);
|
|
69
|
+
margin-right: 8px;
|
|
72
70
|
}
|
|
73
71
|
.pill {
|
|
74
72
|
display: inline-flex;
|
|
@@ -81,21 +79,9 @@
|
|
|
81
79
|
background: {{pillBg}};
|
|
82
80
|
margin-left: 6px;
|
|
83
81
|
}
|
|
84
|
-
.body {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
padding: 14px 16px 16px;
|
|
88
|
-
}
|
|
89
|
-
.title {
|
|
90
|
-
font-size: 18px;
|
|
91
|
-
font-weight: 700;
|
|
92
|
-
margin-bottom: 6px;
|
|
93
|
-
letter-spacing: 0.2px;
|
|
94
|
-
}
|
|
95
|
-
.sub {
|
|
96
|
-
color: {{muted}};
|
|
97
|
-
margin-bottom: 12px;
|
|
98
|
-
}
|
|
82
|
+
.body { position: relative; z-index: 1; padding: 14px 16px 16px; }
|
|
83
|
+
.title { font-size: 18px; font-weight: 700; margin-bottom: 6px; letter-spacing: 0.2px; }
|
|
84
|
+
.sub { color: {{muted}}; margin-bottom: 12px; }
|
|
99
85
|
.content {
|
|
100
86
|
border: 1px dashed {{border}};
|
|
101
87
|
border-radius: 10px;
|
|
@@ -106,19 +92,27 @@
|
|
|
106
92
|
margin-top: 8px;
|
|
107
93
|
background: {{contentBg}};
|
|
108
94
|
}
|
|
109
|
-
.
|
|
95
|
+
.detail-grid {
|
|
110
96
|
margin-top: 10px;
|
|
111
|
-
border
|
|
112
|
-
|
|
97
|
+
border: 1px solid {{border}};
|
|
98
|
+
border-radius: 10px;
|
|
99
|
+
background: {{contentBg}};
|
|
100
|
+
overflow: hidden;
|
|
113
101
|
}
|
|
114
|
-
.
|
|
115
|
-
display:
|
|
116
|
-
|
|
117
|
-
gap:
|
|
102
|
+
.detail-row {
|
|
103
|
+
display: grid;
|
|
104
|
+
grid-template-columns: 120px 1fr;
|
|
105
|
+
gap: 10px;
|
|
106
|
+
padding: 8px 10px;
|
|
107
|
+
border-bottom: 1px solid {{border}};
|
|
118
108
|
font-size: 13px;
|
|
119
|
-
margin-bottom: 6px;
|
|
120
109
|
}
|
|
121
|
-
.
|
|
110
|
+
.detail-row:last-child { border-bottom: 0; }
|
|
111
|
+
.detail-key { color: {{muted}}; }
|
|
112
|
+
.detail-value { word-break: break-word; }
|
|
113
|
+
.commit-list { margin-top: 10px; border-top: 1px solid {{border}}; padding-top: 10px; }
|
|
114
|
+
.commit-item { display: flex; align-items: baseline; gap: 6px; font-size: 13px; margin-bottom: 6px; }
|
|
115
|
+
.commit-icon { width: 22px; text-align: center; color: var(--status-accent); }
|
|
122
116
|
.commit-hash {
|
|
123
117
|
display: inline-block;
|
|
124
118
|
padding: 1px 6px;
|
|
@@ -129,67 +123,52 @@
|
|
|
129
123
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
130
124
|
}
|
|
131
125
|
.commit-author { color: {{muted}}; }
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
border
|
|
135
|
-
|
|
136
|
-
|
|
126
|
+
.digest-list {
|
|
127
|
+
margin-top: 10px;
|
|
128
|
+
border: 1px solid {{border}};
|
|
129
|
+
border-radius: 10px;
|
|
130
|
+
background: {{contentBg}};
|
|
131
|
+
overflow: hidden;
|
|
137
132
|
}
|
|
138
|
-
|
|
139
|
-
|
|
133
|
+
.digest-item {
|
|
134
|
+
display: grid;
|
|
135
|
+
grid-template-columns: 90px 1fr;
|
|
136
|
+
gap: 10px;
|
|
137
|
+
padding: 8px 10px;
|
|
138
|
+
border-bottom: 1px solid {{border}};
|
|
139
|
+
font-size: 13px;
|
|
140
140
|
}
|
|
141
|
+
.digest-item:last-child { border-bottom: 0; }
|
|
142
|
+
.digest-event { color: var(--status-accent); font-weight: 600; }
|
|
141
143
|
|
|
142
|
-
body.style-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
body.style-neon .dot {
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
body.style-neon .title {
|
|
150
|
-
text-transform: uppercase;
|
|
151
|
-
letter-spacing: 0.8px;
|
|
152
|
-
}
|
|
144
|
+
body.style-glass .card { border-radius: 18px; backdrop-filter: blur(6px); box-shadow: 0 20px 50px rgba(0,0,0,0.35); }
|
|
145
|
+
body.style-glass .head { background: linear-gradient(180deg, rgba(255,255,255,0.08), rgba(255,255,255,0)); }
|
|
146
|
+
|
|
147
|
+
body.style-neon .card { border-width: 2px; box-shadow: 0 0 0 1px var(--status-accent) inset, 0 0 28px rgba(0,0,0,0.38); }
|
|
148
|
+
body.style-neon .dot { box-shadow: 0 0 0 4px {{pillBg}}, 0 0 14px var(--status-accent); }
|
|
149
|
+
body.style-neon .title { text-transform: uppercase; letter-spacing: 0.8px; }
|
|
153
150
|
|
|
154
151
|
body.style-compact .wrap { padding: 10px; }
|
|
155
152
|
body.style-compact .head { padding: 10px 12px; }
|
|
156
153
|
body.style-compact .body { padding: 10px 12px 12px; }
|
|
157
154
|
body.style-compact .title { font-size: 16px; }
|
|
158
155
|
body.style-compact .content { font-size: 13px; }
|
|
156
|
+
body.style-compact .detail-row { grid-template-columns: 90px 1fr; padding: 6px 8px; }
|
|
159
157
|
|
|
160
|
-
body.style-card .card {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
box-shadow: 0 26px 54px rgba(0, 0, 0, 0.35);
|
|
164
|
-
}
|
|
165
|
-
body.style-card .head {
|
|
166
|
-
border-bottom-style: dashed;
|
|
167
|
-
}
|
|
168
|
-
body.style-card .content {
|
|
169
|
-
border-style: solid;
|
|
170
|
-
}
|
|
158
|
+
body.style-card .card { border-radius: 24px; box-shadow: 0 26px 54px rgba(0,0,0,0.35); }
|
|
159
|
+
body.style-card .head { border-bottom-style: dashed; }
|
|
160
|
+
body.style-card .content { border-style: solid; }
|
|
171
161
|
|
|
172
|
-
body.style-terminal .card {
|
|
173
|
-
border-radius: 0;
|
|
174
|
-
border-width: 2px;
|
|
175
|
-
box-shadow: none;
|
|
176
|
-
}
|
|
162
|
+
body.style-terminal .card { border-radius: 0; border-width: 2px; box-shadow: none; }
|
|
177
163
|
body.style-terminal .head,
|
|
178
164
|
body.style-terminal .content,
|
|
179
165
|
body.style-terminal .pill,
|
|
180
|
-
body.style-terminal .commit-hash
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
body.style-terminal .title {
|
|
184
|
-
font-size: 17px;
|
|
185
|
-
letter-spacing: 0.5px;
|
|
186
|
-
}
|
|
166
|
+
body.style-terminal .commit-hash,
|
|
167
|
+
body.style-terminal .detail-grid,
|
|
168
|
+
body.style-terminal .digest-list { border-radius: 0; }
|
|
169
|
+
body.style-terminal .title { font-size: 17px; letter-spacing: 0.5px; }
|
|
187
170
|
|
|
188
|
-
body.style-github .repo::before {
|
|
189
|
-
content: '#';
|
|
190
|
-
margin-right: 4px;
|
|
191
|
-
color: {{muted}};
|
|
192
|
-
}
|
|
171
|
+
body.style-github .repo::before { content: '#'; margin-right: 4px; color: {{muted}}; }
|
|
193
172
|
|
|
194
173
|
{{extraCss}}
|
|
195
174
|
</style>
|
|
@@ -197,6 +176,7 @@
|
|
|
197
176
|
<body class="theme-{{themeKey}} style-{{styleVariant}}">
|
|
198
177
|
<div class="wrap">
|
|
199
178
|
<div class="card">
|
|
179
|
+
<div class="status-bar"></div>
|
|
200
180
|
<div class="head">
|
|
201
181
|
<div class="head-left">
|
|
202
182
|
<span class="dot"></span>
|
|
@@ -205,10 +185,12 @@
|
|
|
205
185
|
<div class="meta">{{themeTitle}}</div>
|
|
206
186
|
</div>
|
|
207
187
|
<div class="body">
|
|
208
|
-
<div class="title">{{eventTitle}}</div>
|
|
209
|
-
<div class="sub">by {{actor}}
|
|
188
|
+
<div class="title"><span class="type-badge">{{typeLabel}}</span>{{eventTitle}}</div>
|
|
189
|
+
<div class="sub">by {{actor}}{{actionPill}}{{statusPills}}</div>
|
|
210
190
|
<div class="content">{{content}}</div>
|
|
191
|
+
{{detailBlock}}
|
|
211
192
|
{{commitBlock}}
|
|
193
|
+
{{digestBlock}}
|
|
212
194
|
</div>
|
|
213
195
|
</div>
|
|
214
196
|
</div>
|
package/lib/commands/admin.js
CHANGED
|
@@ -3,26 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.apply = apply;
|
|
4
4
|
function apply(ctx) {
|
|
5
5
|
const logger = ctx.logger('githubsth');
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// repo: [\w-\.]+ (alphanumeric, underscore, dash, dot)
|
|
9
|
-
const repoRegex = /^[\w-]+\/[\w-\.]+$/;
|
|
10
|
-
ctx.command('githubsth.trust', '管理信任仓库', { authority: 3 })
|
|
11
|
-
.alias('gh.trust');
|
|
6
|
+
const repoRegex = /^[\w-]+\/[\w-.]+$/;
|
|
7
|
+
ctx.command('githubsth.trust', '管理信任仓库', { authority: 3 }).alias('gh.trust');
|
|
12
8
|
ctx.command('githubsth.trust.add <repo>', '添加信任仓库')
|
|
13
9
|
.action(async ({ session }, repo) => {
|
|
14
10
|
if (!repo)
|
|
15
|
-
return '
|
|
16
|
-
if (!repoRegex.test(repo))
|
|
17
|
-
return '
|
|
18
|
-
}
|
|
11
|
+
return '请指定仓库名称(owner/repo)。';
|
|
12
|
+
if (!repoRegex.test(repo))
|
|
13
|
+
return '仓库名称格式不正确(应为 owner/repo)。';
|
|
19
14
|
try {
|
|
20
15
|
logger.debug(`Adding trusted repo: ${repo}`);
|
|
21
|
-
// Check existence first to avoid UNIQUE constraint error log from driver
|
|
22
16
|
const existing = await ctx.database.get('github_trusted_repo', { repo });
|
|
23
|
-
if (existing.length > 0)
|
|
17
|
+
if (existing.length > 0)
|
|
24
18
|
return '该仓库已在信任列表中。';
|
|
25
|
-
}
|
|
26
19
|
await ctx.database.create('github_trusted_repo', {
|
|
27
20
|
repo,
|
|
28
21
|
enabled: true,
|
|
@@ -33,16 +26,15 @@ function apply(ctx) {
|
|
|
33
26
|
}
|
|
34
27
|
catch (e) {
|
|
35
28
|
logger.warn('Failed to add trusted repo:', e);
|
|
36
|
-
if (e.code === 'SQLITE_CONSTRAINT')
|
|
29
|
+
if (e.code === 'SQLITE_CONSTRAINT')
|
|
37
30
|
return '该仓库已在信任列表中。';
|
|
38
|
-
}
|
|
39
31
|
return `添加失败: ${e.message}`;
|
|
40
32
|
}
|
|
41
33
|
});
|
|
42
34
|
ctx.command('githubsth.trust.remove <repo>', '移除信任仓库')
|
|
43
|
-
.action(async (
|
|
35
|
+
.action(async (_, repo) => {
|
|
44
36
|
if (!repo)
|
|
45
|
-
return '
|
|
37
|
+
return '请指定仓库名称(owner/repo)。';
|
|
46
38
|
const result = await ctx.database.remove('github_trusted_repo', { repo });
|
|
47
39
|
if (result.matched === 0)
|
|
48
40
|
return '未找到该信任仓库。';
|
|
@@ -53,17 +45,17 @@ function apply(ctx) {
|
|
|
53
45
|
const repos = await ctx.database.get('github_trusted_repo', {});
|
|
54
46
|
if (repos.length === 0)
|
|
55
47
|
return '暂无信任仓库。';
|
|
56
|
-
return repos.map(r => `${r.repo} [${r.enabled ? '启用' : '禁用'}]`).join('\n');
|
|
48
|
+
return repos.map((r) => `${r.repo} [${r.enabled ? '启用' : '禁用'}]`).join('\n');
|
|
57
49
|
});
|
|
58
50
|
ctx.command('githubsth.trust.enable <repo>', '启用信任仓库')
|
|
59
|
-
.action(async (
|
|
51
|
+
.action(async (_, repo) => {
|
|
60
52
|
const result = await ctx.database.set('github_trusted_repo', { repo }, { enabled: true });
|
|
61
53
|
if (result.matched === 0)
|
|
62
54
|
return '未找到该信任仓库。';
|
|
63
55
|
return `已启用信任仓库: ${repo}`;
|
|
64
56
|
});
|
|
65
57
|
ctx.command('githubsth.trust.disable <repo>', '禁用信任仓库')
|
|
66
|
-
.action(async (
|
|
58
|
+
.action(async (_, repo) => {
|
|
67
59
|
const result = await ctx.database.set('github_trusted_repo', { repo }, { enabled: false });
|
|
68
60
|
if (result.matched === 0)
|
|
69
61
|
return '未找到该信任仓库。';
|
package/lib/commands/render.js
CHANGED
|
@@ -2,104 +2,180 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.apply = apply;
|
|
4
4
|
const modes = ['text', 'image', 'auto'];
|
|
5
|
-
const events = ['push', 'issues', 'issue_comment', 'pull_request', 'pull_request_review', 'star', 'fork', 'release', 'discussion', 'workflow_run'];
|
|
5
|
+
const events = ['push', 'issues', 'issue_comment', 'pull_request', 'pull_request_review', 'star', 'fork', 'release', 'discussion', 'workflow_run', 'digest'];
|
|
6
6
|
function apply(ctx, config) {
|
|
7
|
-
ctx.command('githubsth.render', '
|
|
8
|
-
.alias('gh.render');
|
|
7
|
+
ctx.command('githubsth.render', '渲染设置', { authority: 3 }).alias('gh.render');
|
|
9
8
|
ctx.command('githubsth.render.status', '查看渲染状态', { authority: 3 })
|
|
10
|
-
.action(async () => {
|
|
9
|
+
.action(async ({ session }) => {
|
|
11
10
|
const status = ctx.githubsthNotifier.getRenderStatus();
|
|
12
|
-
return [
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
return session?.text('commands.githubsth.render.messages.status_text', [
|
|
12
|
+
status.mode,
|
|
13
|
+
status.configuredMode,
|
|
14
|
+
status.fallback,
|
|
15
|
+
status.theme,
|
|
16
|
+
status.style,
|
|
17
|
+
status.width,
|
|
18
|
+
status.timeoutMs,
|
|
19
|
+
status.digestEnabled ? 'on' : 'off',
|
|
20
|
+
status.digestWindowSec,
|
|
21
|
+
status.digestMaxItems,
|
|
22
|
+
status.hasPuppeteer ? 'ready' : 'missing',
|
|
23
|
+
]);
|
|
20
24
|
});
|
|
21
|
-
ctx.command('githubsth.render.mode <mode:string>', '
|
|
22
|
-
.action(async (
|
|
25
|
+
ctx.command('githubsth.render.mode <mode:string>', '设置渲染模式', { authority: 3 })
|
|
26
|
+
.action(async ({ session }, mode) => {
|
|
23
27
|
if (!mode || !modes.includes(mode)) {
|
|
24
|
-
return
|
|
28
|
+
return session?.text('commands.githubsth.render.messages.invalid_mode', [modes.join(', ')]);
|
|
25
29
|
}
|
|
26
30
|
ctx.githubsthNotifier.setRenderMode(mode);
|
|
27
|
-
return
|
|
31
|
+
return session?.text('commands.githubsth.render.messages.mode_set', [mode, config.renderMode]);
|
|
28
32
|
});
|
|
29
|
-
ctx.command('githubsth.render.theme <theme:string>', '
|
|
30
|
-
.action(async (
|
|
33
|
+
ctx.command('githubsth.render.theme <theme:string>', '设置默认主题', { authority: 3 })
|
|
34
|
+
.action(async ({ session }, theme) => {
|
|
31
35
|
const normalized = ctx.githubsthNotifier.normalizeTheme(theme);
|
|
32
|
-
if (!normalized)
|
|
33
|
-
return
|
|
34
|
-
}
|
|
36
|
+
if (!normalized)
|
|
37
|
+
return session?.text('commands.githubsth.render.messages.invalid_theme');
|
|
35
38
|
config.renderTheme = normalized;
|
|
36
|
-
return
|
|
39
|
+
return session?.text('commands.githubsth.render.messages.theme_set', [normalized]);
|
|
40
|
+
});
|
|
41
|
+
ctx.command('githubsth.render.style <style:string>', '设置默认样式', { authority: 3 })
|
|
42
|
+
.action(async ({ session }, style) => {
|
|
43
|
+
const normalized = ctx.githubsthNotifier.normalizeStyle(style);
|
|
44
|
+
if (!normalized)
|
|
45
|
+
return session?.text('commands.githubsth.render.messages.invalid_style');
|
|
46
|
+
config.renderStyle = normalized;
|
|
47
|
+
return session?.text('commands.githubsth.render.messages.style_set', [normalized]);
|
|
37
48
|
});
|
|
38
49
|
ctx.command('githubsth.render.width <width:number>', '设置图片宽度', { authority: 3 })
|
|
39
|
-
.action(async (
|
|
50
|
+
.action(async ({ session }, width) => {
|
|
40
51
|
if (!width || Number.isNaN(width))
|
|
41
|
-
return '
|
|
52
|
+
return session?.text('commands.githubsth.render.messages.invalid_width');
|
|
42
53
|
const normalized = Math.max(480, Math.min(1600, Math.floor(width)));
|
|
43
54
|
config.renderWidth = normalized;
|
|
44
|
-
return
|
|
55
|
+
return session?.text('commands.githubsth.render.messages.width_set', [normalized]);
|
|
45
56
|
});
|
|
46
|
-
ctx.command('githubsth.render.
|
|
47
|
-
.action(async () => {
|
|
48
|
-
const
|
|
49
|
-
|
|
57
|
+
ctx.command('githubsth.render.digest <enabled:string>', '切换 digest 模式(on/off)', { authority: 3 })
|
|
58
|
+
.action(async ({ session }, enabled) => {
|
|
59
|
+
const key = String(enabled || '').toLowerCase();
|
|
60
|
+
if (!['on', 'off', 'true', 'false', '1', '0'].includes(key))
|
|
61
|
+
return session?.text('commands.githubsth.render.messages.digest_usage');
|
|
62
|
+
config.digestEnabled = ['on', 'true', '1'].includes(key);
|
|
63
|
+
return session?.text('commands.githubsth.render.messages.digest_set', [config.digestEnabled ? 'on' : 'off']);
|
|
64
|
+
});
|
|
65
|
+
ctx.command('githubsth.render.digest.window <seconds:number>', '设置 digest 窗口秒数', { authority: 3 })
|
|
66
|
+
.action(async ({ session }, seconds) => {
|
|
67
|
+
if (!seconds || Number.isNaN(seconds))
|
|
68
|
+
return session?.text('commands.githubsth.render.messages.invalid_seconds');
|
|
69
|
+
config.digestWindowSec = Math.max(5, Math.min(3600, Math.floor(seconds)));
|
|
70
|
+
return session?.text('commands.githubsth.render.messages.digest_window_set', [config.digestWindowSec]);
|
|
50
71
|
});
|
|
51
|
-
ctx.command('githubsth.render.
|
|
52
|
-
.action(async ({ session },
|
|
72
|
+
ctx.command('githubsth.render.digest.max <count:number>', '设置 digest 最大条目数', { authority: 3 })
|
|
73
|
+
.action(async ({ session }, count) => {
|
|
74
|
+
if (!count || Number.isNaN(count))
|
|
75
|
+
return session?.text('commands.githubsth.render.messages.invalid_count');
|
|
76
|
+
config.digestMaxItems = Math.max(2, Math.min(100, Math.floor(count)));
|
|
77
|
+
return session?.text('commands.githubsth.render.messages.digest_max_set', [config.digestMaxItems]);
|
|
78
|
+
});
|
|
79
|
+
ctx.command('githubsth.render.themes', '查看主题列表', { authority: 3 })
|
|
80
|
+
.action(async ({ session }) => session?.text('commands.githubsth.render.messages.themes_list', [ctx.githubsthNotifier.listThemes().join('\n- ')]));
|
|
81
|
+
ctx.command('githubsth.render.styles', '查看样式列表', { authority: 3 })
|
|
82
|
+
.action(async ({ session }) => session?.text('commands.githubsth.render.messages.styles_list', [ctx.githubsthNotifier.listStyles().join('\n- ')]));
|
|
83
|
+
ctx.command('githubsth.render.preview [event:string] [theme:string] [style:string]', '预览渲染效果', { authority: 3 })
|
|
84
|
+
.action(async ({ session }, event, theme, style) => {
|
|
53
85
|
const selectedEvent = event && events.includes(event) ? event : 'issue_comment';
|
|
54
|
-
if (event && !events.includes(event))
|
|
55
|
-
await session?.send(
|
|
56
|
-
}
|
|
86
|
+
if (event && !events.includes(event))
|
|
87
|
+
await session?.send(session?.text('commands.githubsth.render.messages.unknown_event', [event]) || '');
|
|
57
88
|
const normalizedTheme = theme ? ctx.githubsthNotifier.normalizeTheme(theme) : null;
|
|
58
|
-
if (theme && !normalizedTheme)
|
|
59
|
-
await session?.send(
|
|
60
|
-
|
|
89
|
+
if (theme && !normalizedTheme)
|
|
90
|
+
await session?.send(session?.text('commands.githubsth.render.messages.unknown_theme', [theme]) || '');
|
|
91
|
+
const normalizedStyle = style ? ctx.githubsthNotifier.normalizeStyle(style) : null;
|
|
92
|
+
if (style && !normalizedStyle)
|
|
93
|
+
await session?.send(session?.text('commands.githubsth.render.messages.unknown_style', [style]) || '');
|
|
94
|
+
const prevTheme = config.renderTheme;
|
|
95
|
+
const prevStyle = config.renderStyle;
|
|
96
|
+
if (normalizedTheme)
|
|
97
|
+
config.renderTheme = normalizedTheme;
|
|
98
|
+
if (normalizedStyle)
|
|
99
|
+
config.renderStyle = normalizedStyle;
|
|
61
100
|
const preview = await ctx.githubsthNotifier.renderPreview(selectedEvent, normalizedTheme || undefined);
|
|
62
|
-
|
|
101
|
+
config.renderTheme = prevTheme;
|
|
102
|
+
config.renderStyle = prevStyle;
|
|
103
|
+
return preview || session?.text('commands.githubsth.render.messages.preview_failed');
|
|
63
104
|
});
|
|
64
|
-
ctx.command('githubsth.render.repo-theme <repo:string> <theme:string>', '
|
|
105
|
+
ctx.command('githubsth.render.repo-theme <repo:string> <theme:string>', '设置订阅专属主题', { authority: 3 })
|
|
65
106
|
.action(async ({ session }, repo, theme) => {
|
|
66
107
|
if (!repo)
|
|
67
|
-
return '
|
|
108
|
+
return session?.text('commands.githubsth.render.messages.repo_required');
|
|
68
109
|
if (!session?.channelId)
|
|
69
|
-
return '
|
|
110
|
+
return session?.text('commands.githubsth.subscribe.messages.run_in_channel');
|
|
70
111
|
const normalized = ctx.githubsthNotifier.normalizeTheme(theme);
|
|
71
112
|
if (!normalized)
|
|
72
|
-
return '
|
|
113
|
+
return session?.text('commands.githubsth.render.messages.invalid_theme');
|
|
73
114
|
const target = await ctx.database.get('github_subscription', {
|
|
74
115
|
repo,
|
|
75
116
|
channelId: session.channelId,
|
|
76
117
|
platform: session.platform || 'unknown',
|
|
77
118
|
});
|
|
78
119
|
if (!target.length)
|
|
79
|
-
return '
|
|
120
|
+
return session?.text('commands.githubsth.render.messages.no_sub_in_channel');
|
|
80
121
|
await ctx.database.set('github_subscription', { id: target[0].id }, { renderTheme: normalized });
|
|
81
|
-
return
|
|
122
|
+
return session?.text('commands.githubsth.render.messages.repo_theme_set', [repo, normalized]);
|
|
82
123
|
});
|
|
83
|
-
ctx.command('githubsth.render.repo-theme.clear <repo:string>', '
|
|
124
|
+
ctx.command('githubsth.render.repo-theme.clear <repo:string>', '清除订阅专属主题', { authority: 3 })
|
|
84
125
|
.action(async ({ session }, repo) => {
|
|
85
126
|
if (!repo)
|
|
86
|
-
return '
|
|
127
|
+
return session?.text('commands.githubsth.render.messages.repo_required');
|
|
87
128
|
if (!session?.channelId)
|
|
88
|
-
return '
|
|
129
|
+
return session?.text('commands.githubsth.subscribe.messages.run_in_channel');
|
|
89
130
|
const target = await ctx.database.get('github_subscription', {
|
|
90
131
|
repo,
|
|
91
132
|
channelId: session.channelId,
|
|
92
133
|
platform: session.platform || 'unknown',
|
|
93
134
|
});
|
|
94
135
|
if (!target.length)
|
|
95
|
-
return '
|
|
136
|
+
return session?.text('commands.githubsth.render.messages.no_sub_in_channel');
|
|
96
137
|
await ctx.database.set('github_subscription', { id: target[0].id }, { renderTheme: null });
|
|
97
|
-
return
|
|
138
|
+
return session?.text('commands.githubsth.render.messages.repo_theme_cleared', [repo]);
|
|
139
|
+
});
|
|
140
|
+
ctx.command('githubsth.render.repo-style <repo:string> <style:string>', '设置订阅专属样式', { authority: 3 })
|
|
141
|
+
.action(async ({ session }, repo, style) => {
|
|
142
|
+
if (!repo)
|
|
143
|
+
return session?.text('commands.githubsth.render.messages.repo_required');
|
|
144
|
+
if (!session?.channelId)
|
|
145
|
+
return session?.text('commands.githubsth.subscribe.messages.run_in_channel');
|
|
146
|
+
const normalized = ctx.githubsthNotifier.normalizeStyle(style);
|
|
147
|
+
if (!normalized)
|
|
148
|
+
return session?.text('commands.githubsth.render.messages.invalid_style');
|
|
149
|
+
const target = await ctx.database.get('github_subscription', {
|
|
150
|
+
repo,
|
|
151
|
+
channelId: session.channelId,
|
|
152
|
+
platform: session.platform || 'unknown',
|
|
153
|
+
});
|
|
154
|
+
if (!target.length)
|
|
155
|
+
return session?.text('commands.githubsth.render.messages.no_sub_in_channel');
|
|
156
|
+
await ctx.database.set('github_subscription', { id: target[0].id }, { renderStyle: normalized });
|
|
157
|
+
return session?.text('commands.githubsth.render.messages.repo_style_set', [repo, normalized]);
|
|
158
|
+
});
|
|
159
|
+
ctx.command('githubsth.render.repo-style.clear <repo:string>', '清除订阅专属样式', { authority: 3 })
|
|
160
|
+
.action(async ({ session }, repo) => {
|
|
161
|
+
if (!repo)
|
|
162
|
+
return session?.text('commands.githubsth.render.messages.repo_required');
|
|
163
|
+
if (!session?.channelId)
|
|
164
|
+
return session?.text('commands.githubsth.subscribe.messages.run_in_channel');
|
|
165
|
+
const target = await ctx.database.get('github_subscription', {
|
|
166
|
+
repo,
|
|
167
|
+
channelId: session.channelId,
|
|
168
|
+
platform: session.platform || 'unknown',
|
|
169
|
+
});
|
|
170
|
+
if (!target.length)
|
|
171
|
+
return session?.text('commands.githubsth.render.messages.no_sub_in_channel');
|
|
172
|
+
await ctx.database.set('github_subscription', { id: target[0].id }, { renderStyle: null });
|
|
173
|
+
return session?.text('commands.githubsth.render.messages.repo_style_cleared', [repo]);
|
|
98
174
|
});
|
|
99
|
-
ctx.command('githubsth.render.repo-theme.list [repo:string]', '
|
|
175
|
+
ctx.command('githubsth.render.repo-theme.list [repo:string]', '查看订阅主题/样式', { authority: 3 })
|
|
100
176
|
.action(async ({ session }, repo) => {
|
|
101
177
|
if (!session?.channelId)
|
|
102
|
-
return '
|
|
178
|
+
return session?.text('commands.githubsth.subscribe.messages.run_in_channel');
|
|
103
179
|
const query = {
|
|
104
180
|
channelId: session.channelId,
|
|
105
181
|
platform: session.platform || 'unknown',
|
|
@@ -108,7 +184,13 @@ function apply(ctx, config) {
|
|
|
108
184
|
query.repo = repo;
|
|
109
185
|
const subs = await ctx.database.get('github_subscription', query);
|
|
110
186
|
if (!subs.length)
|
|
111
|
-
return '
|
|
112
|
-
return subs
|
|
187
|
+
return session?.text('commands.githubsth.render.messages.no_matched_subs');
|
|
188
|
+
return subs
|
|
189
|
+
.map((sub) => session?.text('commands.githubsth.render.messages.repo_style_item', [
|
|
190
|
+
sub.repo,
|
|
191
|
+
sub.renderTheme || '(default)',
|
|
192
|
+
sub.renderStyle || '(default)',
|
|
193
|
+
]) || `${sub.repo}`)
|
|
194
|
+
.join('\n');
|
|
113
195
|
});
|
|
114
196
|
}
|
package/lib/commands/repo.js
CHANGED
|
@@ -2,35 +2,30 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.apply = apply;
|
|
4
4
|
function apply(ctx, config) {
|
|
5
|
-
ctx.command('githubsth.repo [name:string]')
|
|
5
|
+
ctx.command('githubsth.repo [name:string]', '获取仓库信息')
|
|
6
6
|
.action(async ({ session }, name) => {
|
|
7
|
-
if (!name && !config.defaultRepo)
|
|
7
|
+
if (!name && !config.defaultRepo)
|
|
8
8
|
return session?.text('.specify_repo');
|
|
9
|
-
}
|
|
10
9
|
const fullRepo = name || (config.defaultOwner ? `${config.defaultOwner}/${config.defaultRepo}` : name);
|
|
11
10
|
if (!fullRepo)
|
|
12
11
|
return session?.text('.specify_repo');
|
|
13
12
|
try {
|
|
14
13
|
let data;
|
|
15
14
|
if (ctx.github && typeof ctx.github.request === 'function') {
|
|
16
|
-
// If adapter provides a request method (hypothetical, based on common adapter patterns)
|
|
17
15
|
data = await ctx.github.request('GET /repos/:owner/:repo', {
|
|
18
16
|
owner: fullRepo.split('/')[0],
|
|
19
|
-
repo: fullRepo.split('/')[1]
|
|
17
|
+
repo: fullRepo.split('/')[1],
|
|
20
18
|
});
|
|
21
19
|
}
|
|
22
20
|
else {
|
|
23
|
-
const headers = {
|
|
24
|
-
'User-Agent': 'Koishi-Plugin-GithubSth'
|
|
25
|
-
};
|
|
21
|
+
const headers = { 'User-Agent': 'Koishi-Plugin-GithubSth' };
|
|
26
22
|
data = await ctx.http.get(`https://api.github.com/repos/${fullRepo}`, { headers });
|
|
27
23
|
}
|
|
28
24
|
return session?.text('.repo_info', [data.owner.login, data.name, data.description || '无描述', data.stargazers_count]);
|
|
29
25
|
}
|
|
30
26
|
catch (e) {
|
|
31
|
-
if (e.response?.status === 404)
|
|
27
|
+
if (e.response?.status === 404)
|
|
32
28
|
return session?.text('.not_found');
|
|
33
|
-
}
|
|
34
29
|
return session?.text('.error', [e.message]);
|
|
35
30
|
}
|
|
36
31
|
});
|