koishi-plugin-luogu-saver-bot 0.1.2 → 0.1.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/index.js +239 -26
- package/package.json +7 -4
package/lib/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
1
2
|
var __defProp = Object.defineProperty;
|
|
2
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
6
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
7
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
8
|
var __export = (target, all) => {
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -43,6 +53,9 @@ function statusToString(status) {
|
|
|
43
53
|
__name(statusToString, "statusToString");
|
|
44
54
|
|
|
45
55
|
// src/index.ts
|
|
56
|
+
var import_markdown_it = __toESM(require("markdown-it"));
|
|
57
|
+
var import_markdown_it_katex = __toESM(require("markdown-it-katex"));
|
|
58
|
+
var import_highlight = __toESM(require("highlight.js"));
|
|
46
59
|
var name = "luogu-saver-bot";
|
|
47
60
|
var inject = ["puppeteer"];
|
|
48
61
|
var Config = import_koishi.Schema.object({
|
|
@@ -62,7 +75,6 @@ var LuoguSaverClient = class {
|
|
|
62
75
|
buildUrl(path) {
|
|
63
76
|
const base = this.endpoint.replace(/\/$/, "");
|
|
64
77
|
if (!base) return path;
|
|
65
|
-
console.log(`${base}${path}`);
|
|
66
78
|
if (path.startsWith("/")) return `${base}${path}`;
|
|
67
79
|
return `${base}/${path}`;
|
|
68
80
|
}
|
|
@@ -119,6 +131,183 @@ var LuoguSaverClient = class {
|
|
|
119
131
|
return res.data;
|
|
120
132
|
}
|
|
121
133
|
};
|
|
134
|
+
var md = new import_markdown_it.default({
|
|
135
|
+
html: true,
|
|
136
|
+
// 允许 HTML 标签
|
|
137
|
+
breaks: true,
|
|
138
|
+
// 转换换行符为 <br>
|
|
139
|
+
linkify: true,
|
|
140
|
+
// 自动识别链接
|
|
141
|
+
highlight: /* @__PURE__ */ __name(function(str, lang) {
|
|
142
|
+
if (lang && import_highlight.default.getLanguage(lang)) {
|
|
143
|
+
try {
|
|
144
|
+
return '<pre class="hljs"><code>' + import_highlight.default.highlight(str, { language: lang, ignoreIllegals: true }).value + "</code></pre>";
|
|
145
|
+
} catch (__) {
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + "</code></pre>";
|
|
149
|
+
}, "highlight")
|
|
150
|
+
});
|
|
151
|
+
md.use(import_markdown_it_katex.default);
|
|
152
|
+
function generateHtml(title, authorInfo, markdownContent) {
|
|
153
|
+
const renderedBody = md.render(markdownContent);
|
|
154
|
+
return `<!doctype html>
|
|
155
|
+
<html>
|
|
156
|
+
<head>
|
|
157
|
+
<meta charset="utf-8">
|
|
158
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
159
|
+
|
|
160
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/styles/github.min.css">
|
|
161
|
+
|
|
162
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css">
|
|
163
|
+
|
|
164
|
+
<style>
|
|
165
|
+
/* 基础重置与变量 */
|
|
166
|
+
:root {
|
|
167
|
+
--bg-color: #f6f8fa;
|
|
168
|
+
--card-bg: #ffffff;
|
|
169
|
+
--text-primary: #24292f;
|
|
170
|
+
--text-secondary: #57606a;
|
|
171
|
+
--border-color: #d0d7de;
|
|
172
|
+
--accent-color: #0969da;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
body {
|
|
176
|
+
margin: 0;
|
|
177
|
+
padding: 40px;
|
|
178
|
+
background-color: var(--bg-color);
|
|
179
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
|
|
180
|
+
color: var(--text-primary);
|
|
181
|
+
line-height: 1.5;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.container {
|
|
185
|
+
max-width: 900px;
|
|
186
|
+
margin: 0 auto;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.card {
|
|
190
|
+
background: var(--card-bg);
|
|
191
|
+
border: 1px solid var(--border-color);
|
|
192
|
+
border-radius: 6px;
|
|
193
|
+
padding: 32px 40px;
|
|
194
|
+
box-shadow: 0 3px 6px rgba(140, 149, 159, 0.15);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/* 头部信息 */
|
|
198
|
+
header {
|
|
199
|
+
border-bottom: 1px solid var(--border-color);
|
|
200
|
+
padding-bottom: 20px;
|
|
201
|
+
margin-bottom: 24px;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
h1.title {
|
|
205
|
+
margin: 0 0 8px 0;
|
|
206
|
+
font-size: 28px;
|
|
207
|
+
font-weight: 600;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.meta {
|
|
211
|
+
font-size: 14px;
|
|
212
|
+
color: var(--text-secondary);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* Markdown 内容美化 (仿 GitHub 风格) */
|
|
216
|
+
.markdown-body {
|
|
217
|
+
font-size: 16px;
|
|
218
|
+
line-height: 1.6;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.markdown-body h1, .markdown-body h2, .markdown-body h3 {
|
|
222
|
+
margin-top: 24px;
|
|
223
|
+
margin-bottom: 16px;
|
|
224
|
+
font-weight: 600;
|
|
225
|
+
line-height: 1.25;
|
|
226
|
+
}
|
|
227
|
+
.markdown-body h1 { font-size: 2em; padding-bottom: .3em; border-bottom: 1px solid #d0d7de; }
|
|
228
|
+
.markdown-body h2 { font-size: 1.5em; padding-bottom: .3em; border-bottom: 1px solid #d0d7de; }
|
|
229
|
+
.markdown-body h3 { font-size: 1.25em; }
|
|
230
|
+
|
|
231
|
+
.markdown-body p { margin-bottom: 16px; }
|
|
232
|
+
|
|
233
|
+
.markdown-body a { color: var(--accent-color); text-decoration: none; }
|
|
234
|
+
.markdown-body a:hover { text-decoration: underline; }
|
|
235
|
+
|
|
236
|
+
.markdown-body blockquote {
|
|
237
|
+
margin: 0 0 16px;
|
|
238
|
+
padding: 0 1em;
|
|
239
|
+
color: var(--text-secondary);
|
|
240
|
+
border-left: 0.25em solid var(--border-color);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.markdown-body ul, .markdown-body ol { padding-left: 2em; margin-bottom: 16px; }
|
|
244
|
+
|
|
245
|
+
/* 表格样式 */
|
|
246
|
+
.markdown-body table {
|
|
247
|
+
border-spacing: 0;
|
|
248
|
+
border-collapse: collapse;
|
|
249
|
+
margin-bottom: 16px;
|
|
250
|
+
width: max-content;
|
|
251
|
+
max-width: 100%;
|
|
252
|
+
overflow: auto;
|
|
253
|
+
display: block;
|
|
254
|
+
}
|
|
255
|
+
.markdown-body table th, .markdown-body table td {
|
|
256
|
+
padding: 6px 13px;
|
|
257
|
+
border: 1px solid var(--border-color);
|
|
258
|
+
}
|
|
259
|
+
.markdown-body table tr { background-color: #fff; border-top: 1px solid #c6cbd1; }
|
|
260
|
+
.markdown-body table tr:nth-child(2n) { background-color: #f6f8fa; }
|
|
261
|
+
|
|
262
|
+
/* 代码块微调 */
|
|
263
|
+
.markdown-body pre {
|
|
264
|
+
padding: 16px;
|
|
265
|
+
overflow: auto;
|
|
266
|
+
font-size: 85%;
|
|
267
|
+
line-height: 1.45;
|
|
268
|
+
background-color: #f6f8fa;
|
|
269
|
+
border-radius: 6px;
|
|
270
|
+
}
|
|
271
|
+
.markdown-body code {
|
|
272
|
+
padding: 0.2em 0.4em;
|
|
273
|
+
margin: 0;
|
|
274
|
+
font-size: 85%;
|
|
275
|
+
background-color: rgba(175,184,193,0.2);
|
|
276
|
+
border-radius: 6px;
|
|
277
|
+
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
|
|
278
|
+
}
|
|
279
|
+
.markdown-body pre code {
|
|
280
|
+
padding: 0;
|
|
281
|
+
background-color: transparent;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/* 图片自适应 */
|
|
285
|
+
.markdown-body img {
|
|
286
|
+
max-width: 100%;
|
|
287
|
+
box-sizing: content-box;
|
|
288
|
+
background-color: #fff;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/* KaTeX 字体修复 */
|
|
292
|
+
.katex { font-size: 1.1em; }
|
|
293
|
+
</style>
|
|
294
|
+
</head>
|
|
295
|
+
<body>
|
|
296
|
+
<div class="container">
|
|
297
|
+
<div class="card">
|
|
298
|
+
<header>
|
|
299
|
+
<h1 class="title">${md.utils.escapeHtml(title)}</h1>
|
|
300
|
+
<div class="meta">${md.utils.escapeHtml(authorInfo)}</div>
|
|
301
|
+
</header>
|
|
302
|
+
<article class="markdown-body">
|
|
303
|
+
${renderedBody}
|
|
304
|
+
</article>
|
|
305
|
+
</div>
|
|
306
|
+
</div>
|
|
307
|
+
</body>
|
|
308
|
+
</html>`;
|
|
309
|
+
}
|
|
310
|
+
__name(generateHtml, "generateHtml");
|
|
122
311
|
function apply(ctx, config = {}) {
|
|
123
312
|
const endpoint = config.endpoint || "";
|
|
124
313
|
const userAgent = config.userAgent || "Uptime-Kuma";
|
|
@@ -147,27 +336,39 @@ function apply(ctx, config = {}) {
|
|
|
147
336
|
if (!id) return "请提供文章 ID";
|
|
148
337
|
const art = await ctx.luogu_saver.getArticle(id);
|
|
149
338
|
if (!art) return "未找到文章";
|
|
150
|
-
const
|
|
339
|
+
const rawContent = art.content ?? art.renderedContent ?? "";
|
|
151
340
|
const title = art.title ?? "";
|
|
152
|
-
const
|
|
153
|
-
const html =
|
|
341
|
+
const authorInfo = `作者 UID: ${art.authorId}`;
|
|
342
|
+
const html = generateHtml(title, authorInfo, rawContent);
|
|
154
343
|
if (!ctx.puppeteer) return "当前没有可用的 puppeteer 服务。";
|
|
155
344
|
const page = await ctx.puppeteer.page();
|
|
156
345
|
try {
|
|
157
346
|
const width = Number(options.width) || 960;
|
|
158
|
-
await page.setViewport({ width, height: 800 });
|
|
159
|
-
if (typeof page.emulateMediaFeatures === "function") {
|
|
160
|
-
await page.emulateMediaFeatures([{ name: "prefers-color-scheme", value: "light" }]);
|
|
161
|
-
}
|
|
347
|
+
await page.setViewport({ width, height: 800, deviceScaleFactor: 2 });
|
|
162
348
|
await page.setContent(html, { waitUntil: "networkidle0" });
|
|
163
349
|
try {
|
|
164
|
-
await page.evaluate(() => {
|
|
165
|
-
|
|
166
|
-
if (
|
|
167
|
-
|
|
350
|
+
await page.evaluate(() => new Promise((resolve) => {
|
|
351
|
+
const imgs = Array.from(document.images);
|
|
352
|
+
if (!imgs.length) return resolve(null);
|
|
353
|
+
let loaded = 0;
|
|
354
|
+
imgs.forEach((img) => {
|
|
355
|
+
if (img.complete) {
|
|
356
|
+
loaded++;
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
const handler = /* @__PURE__ */ __name(() => {
|
|
360
|
+
loaded++;
|
|
361
|
+
if (loaded === imgs.length) resolve(null);
|
|
362
|
+
}, "handler");
|
|
363
|
+
img.addEventListener("load", handler);
|
|
364
|
+
img.addEventListener("error", handler);
|
|
365
|
+
});
|
|
366
|
+
if (loaded === imgs.length) resolve(null);
|
|
367
|
+
setTimeout(() => resolve(null), 5e3);
|
|
368
|
+
}));
|
|
168
369
|
} catch (e) {
|
|
169
370
|
}
|
|
170
|
-
const buffer = await page.screenshot({ fullPage: true, type: "png"
|
|
371
|
+
const buffer = await page.screenshot({ fullPage: true, type: "png" });
|
|
171
372
|
return import_koishi.h.image(buffer, "image/png");
|
|
172
373
|
} catch (err) {
|
|
173
374
|
ctx.logger.error("截图文章失败", err);
|
|
@@ -180,27 +381,39 @@ function apply(ctx, config = {}) {
|
|
|
180
381
|
if (!id) return "请提供剪贴板 ID";
|
|
181
382
|
const paste = await ctx.luogu_saver.getPaste(id);
|
|
182
383
|
if (!paste) return "未找到剪贴板内容";
|
|
183
|
-
const
|
|
184
|
-
const title = paste.id
|
|
185
|
-
const
|
|
186
|
-
const html =
|
|
384
|
+
const rawContent = paste.content ?? paste.renderedContent ?? "";
|
|
385
|
+
const title = `剪贴板: ${paste.id}`;
|
|
386
|
+
const authorInfo = paste.author ? `创建者: ${paste.author.name} (UID: ${paste.author.id})` : `创建者 UID: ${paste.authorId}`;
|
|
387
|
+
const html = generateHtml(title, authorInfo, rawContent);
|
|
187
388
|
if (!ctx.puppeteer) return "当前没有可用的 puppeteer 服务。";
|
|
188
389
|
const page = await ctx.puppeteer.page();
|
|
189
390
|
try {
|
|
190
391
|
const width = Number(options.width) || 960;
|
|
191
|
-
await page.setViewport({ width, height: 800 });
|
|
192
|
-
if (typeof page.emulateMediaFeatures === "function") {
|
|
193
|
-
await page.emulateMediaFeatures([{ name: "prefers-color-scheme", value: "light" }]);
|
|
194
|
-
}
|
|
392
|
+
await page.setViewport({ width, height: 800, deviceScaleFactor: 2 });
|
|
195
393
|
await page.setContent(html, { waitUntil: "networkidle0" });
|
|
196
394
|
try {
|
|
197
|
-
await page.evaluate(() => {
|
|
198
|
-
|
|
199
|
-
if (
|
|
200
|
-
|
|
395
|
+
await page.evaluate(() => new Promise((resolve) => {
|
|
396
|
+
const imgs = Array.from(document.images);
|
|
397
|
+
if (!imgs.length) return resolve(null);
|
|
398
|
+
let loaded = 0;
|
|
399
|
+
imgs.forEach((img) => {
|
|
400
|
+
if (img.complete) {
|
|
401
|
+
loaded++;
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
const handler = /* @__PURE__ */ __name(() => {
|
|
405
|
+
loaded++;
|
|
406
|
+
if (loaded === imgs.length) resolve(null);
|
|
407
|
+
}, "handler");
|
|
408
|
+
img.addEventListener("load", handler);
|
|
409
|
+
img.addEventListener("error", handler);
|
|
410
|
+
});
|
|
411
|
+
if (loaded === imgs.length) resolve(null);
|
|
412
|
+
setTimeout(() => resolve(null), 5e3);
|
|
413
|
+
}));
|
|
201
414
|
} catch (e) {
|
|
202
415
|
}
|
|
203
|
-
const buffer = await page.screenshot({ fullPage: true, type: "png"
|
|
416
|
+
const buffer = await page.screenshot({ fullPage: true, type: "png" });
|
|
204
417
|
return import_koishi.h.image(buffer, "image/png");
|
|
205
418
|
} catch (err) {
|
|
206
419
|
ctx.logger.error("截图剪贴板失败", err);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-luogu-saver-bot",
|
|
3
3
|
"description": "洛谷保存站机器人",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.5",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"files": [
|
|
@@ -15,9 +15,12 @@
|
|
|
15
15
|
"koishi",
|
|
16
16
|
"plugin"
|
|
17
17
|
],
|
|
18
|
-
"devDependencies": {},
|
|
19
18
|
"peerDependencies": {
|
|
20
|
-
"koishi": "^4.18.7"
|
|
21
|
-
|
|
19
|
+
"koishi": "^4.18.7"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"highlight.js": "^11.11.1",
|
|
23
|
+
"markdown-it": "^14.1.0",
|
|
24
|
+
"markdown-it-katex": "^2.0.3"
|
|
22
25
|
}
|
|
23
26
|
}
|