koishi-plugin-fimtale-api 0.0.5 → 0.0.7
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 +29 -18
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -61,7 +61,7 @@ function apply(ctx, config) {
|
|
|
61
61
|
}, { primary: "id", autoInc: true });
|
|
62
62
|
const sleep = /* @__PURE__ */ __name((ms) => new Promise((resolve) => setTimeout(resolve, ms)), "sleep");
|
|
63
63
|
const formatDate = /* @__PURE__ */ __name((timestamp) => {
|
|
64
|
-
if (!timestamp) return "
|
|
64
|
+
if (!timestamp) return "Unknown";
|
|
65
65
|
const date = new Date(timestamp * 1e3);
|
|
66
66
|
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}`;
|
|
67
67
|
}, "formatDate");
|
|
@@ -99,7 +99,7 @@ function apply(ctx, config) {
|
|
|
99
99
|
const url = `${config.apiUrl}/t/${threadId}`;
|
|
100
100
|
const params = { APIKey: config.apiKey, APIPass: config.apiPass };
|
|
101
101
|
const res = await ctx.http.get(url, { params });
|
|
102
|
-
if (res.Status !== 1 || !res.TopicInfo) return { valid: false, msg: res.ErrorMessage || "API
|
|
102
|
+
if (res.Status !== 1 || !res.TopicInfo) return { valid: false, msg: res.ErrorMessage || "API Error" };
|
|
103
103
|
return {
|
|
104
104
|
valid: true,
|
|
105
105
|
data: res.TopicInfo,
|
|
@@ -107,7 +107,7 @@ function apply(ctx, config) {
|
|
|
107
107
|
menu: res.Menu || []
|
|
108
108
|
};
|
|
109
109
|
} catch (e) {
|
|
110
|
-
return { valid: false, msg: "
|
|
110
|
+
return { valid: false, msg: "Request Failed" };
|
|
111
111
|
}
|
|
112
112
|
}, "fetchThread");
|
|
113
113
|
const fetchRandomId = /* @__PURE__ */ __name(async () => {
|
|
@@ -147,7 +147,7 @@ function apply(ctx, config) {
|
|
|
147
147
|
const titleEl = card.querySelector(".card-title");
|
|
148
148
|
if (titleEl) title = titleEl.textContent?.trim() || "";
|
|
149
149
|
else title = link.textContent?.trim() || "";
|
|
150
|
-
let author = "
|
|
150
|
+
let author = "Unknown";
|
|
151
151
|
const authorEl = card.querySelector('a[href^="/u/"] span.grey-text');
|
|
152
152
|
if (authorEl) author = authorEl.textContent?.trim() || "";
|
|
153
153
|
let cover = void 0;
|
|
@@ -203,11 +203,11 @@ function apply(ctx, config) {
|
|
|
203
203
|
const isChapter = info.IsChapter || !!parent && parent.ID !== info.ID;
|
|
204
204
|
const displayTitle = isChapter && parent ? parent.Title : info.Title;
|
|
205
205
|
let displayCover = null;
|
|
206
|
-
if (isChapter) {
|
|
207
|
-
displayCover = extractImage(
|
|
206
|
+
if (isChapter && parent) {
|
|
207
|
+
displayCover = parent.Background || extractImage(parent.Content);
|
|
208
208
|
}
|
|
209
209
|
if (!displayCover) {
|
|
210
|
-
displayCover =
|
|
210
|
+
displayCover = info.Background || extractImage(info.Content);
|
|
211
211
|
}
|
|
212
212
|
const displayTagsObj = isChapter && parent ? parent.Tags : info.Tags;
|
|
213
213
|
const subTitle = isChapter ? info.Title : null;
|
|
@@ -218,7 +218,7 @@ function apply(ctx, config) {
|
|
|
218
218
|
const bgStyle = displayCover ? `background-image: url('${displayCover}');` : `background: ${generateGradient(displayTitle)};`;
|
|
219
219
|
let summary = stripHtml(info.Content);
|
|
220
220
|
if (summary.length < 10 && parent && isChapter) summary = stripHtml(parent.Content);
|
|
221
|
-
if (summary.length >
|
|
221
|
+
if (summary.length > 100) summary = summary.substring(0, 100) + "...";
|
|
222
222
|
if (!summary) summary = "暂无简介";
|
|
223
223
|
const tagsArr = [];
|
|
224
224
|
if (displayTagsObj?.Type) tagsArr.push(displayTagsObj.Type);
|
|
@@ -236,7 +236,7 @@ function apply(ctx, config) {
|
|
|
236
236
|
.card { width: 620px; height: 340px; background: #fff; border-radius: 16px; box-shadow: 0 10px 30px rgba(0,0,0,0.15); display: flex; overflow: hidden; }
|
|
237
237
|
.cover { width: 220px; height: 100%; ${bgStyle} background-size: cover; background-position: center; position: relative; flex-shrink: 0; }
|
|
238
238
|
.id-tag { position: absolute; top: 12px; left: 12px; background: rgba(0,0,0,0.6); color: #fff; padding: 4px 10px; border-radius: 6px; font-size: 13px; font-weight: bold; backdrop-filter: blur(4px); font-family: monospace; }
|
|
239
|
-
.info { flex: 1; padding:
|
|
239
|
+
.info { flex: 1; padding: 24px; display: flex; flex-direction: column; justify-content: space-between; overflow: hidden; }
|
|
240
240
|
|
|
241
241
|
.title {
|
|
242
242
|
font-size: 22px; font-weight: 700; color: #333; line-height: 1.35;
|
|
@@ -248,18 +248,23 @@ function apply(ctx, config) {
|
|
|
248
248
|
padding-left: 10px; border-left: 3px solid #e91e63;
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
-
.author { font-size: 13px; color: #888; margin-top:
|
|
251
|
+
.author { font-size: 13px; color: #888; margin-top: 8px; font-weight: 400; }
|
|
252
252
|
|
|
253
|
-
.tags { display: flex; flex-wrap: wrap; gap: 6px; margin:
|
|
253
|
+
.tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0; max-height: 56px; overflow: hidden; flex-shrink: 0;}
|
|
254
254
|
.tag { background: #eff2f5; color: #5c6b7f; padding: 3px 9px; border-radius: 4px; font-size: 11px; font-weight: 500; }
|
|
255
255
|
.tag-imp { background: #e3f2fd; color: #1565c0; }
|
|
256
256
|
|
|
257
|
+
.summary-box {
|
|
258
|
+
flex: 1; overflow: hidden; position: relative; margin-top: 8px;
|
|
259
|
+
}
|
|
257
260
|
.summary {
|
|
258
261
|
font-size: 13px; color: #666; line-height: 1.6;
|
|
262
|
+
/* 精确控制行数和高度防止截断 */
|
|
263
|
+
max-height: 6.4em;
|
|
259
264
|
display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
|
|
260
|
-
margin-top: auto;
|
|
261
265
|
}
|
|
262
|
-
|
|
266
|
+
|
|
267
|
+
.footer { border-top: 1px solid #eee; padding-top: 14px; display: flex; justify-content: space-between; font-size: 12px; color: #888; margin-top: 15px; flex-shrink: 0;}
|
|
263
268
|
.stat b { color: #555; font-weight: bold; margin-right: 2px;}
|
|
264
269
|
</style>
|
|
265
270
|
</head>
|
|
@@ -267,13 +272,18 @@ function apply(ctx, config) {
|
|
|
267
272
|
<div class="card">
|
|
268
273
|
<div class="cover"><div class="id-tag">ID: ${info.ID}</div></div>
|
|
269
274
|
<div class="info">
|
|
270
|
-
<div>
|
|
275
|
+
<div class="header-group">
|
|
271
276
|
<div class="title">${displayTitle}</div>
|
|
272
277
|
${subTitle ? `<div class="subtitle">${subTitle}</div>` : ""}
|
|
273
278
|
<div class="author">@${info.UserName}</div>
|
|
274
|
-
<div class="tags">${displayTags.map((t) => `<span class="tag ${["文", "译", "R"].includes(t) ? "tag-imp" : ""}">${t}</span>`).join("")}</div>
|
|
275
279
|
</div>
|
|
276
|
-
|
|
280
|
+
|
|
281
|
+
<div class="tags">${displayTags.map((t) => `<span class="tag ${["文", "译", "R"].includes(t) ? "tag-imp" : ""}">${t}</span>`).join("")}</div>
|
|
282
|
+
|
|
283
|
+
<div class="summary-box">
|
|
284
|
+
<div class="summary">${summary}</div>
|
|
285
|
+
</div>
|
|
286
|
+
|
|
277
287
|
<div class="footer">
|
|
278
288
|
<span class="stat"><b style="color:#009688">热度</b>${views}</span>
|
|
279
289
|
<span class="stat"><b style="color:#673ab7">评论</b>${comments}</span>
|
|
@@ -286,7 +296,7 @@ function apply(ctx, config) {
|
|
|
286
296
|
const page = await ctx.puppeteer.page();
|
|
287
297
|
await injectCookies(page);
|
|
288
298
|
await page.setContent(html);
|
|
289
|
-
await page.setViewport({ width: 660, height:
|
|
299
|
+
await page.setViewport({ width: 660, height: 480, deviceScaleFactor: 2 });
|
|
290
300
|
const el = await page.$(".card");
|
|
291
301
|
const img = await el.screenshot({ type: "png" });
|
|
292
302
|
await page.close();
|
|
@@ -482,7 +492,8 @@ function apply(ctx, config) {
|
|
|
482
492
|
if (!results.length) return "未找到结果。";
|
|
483
493
|
const img = await renderSearchResults(keyword, results);
|
|
484
494
|
await session.send(import_koishi.h.image(img, "image/png"));
|
|
485
|
-
|
|
495
|
+
const exampleId = results[0]?.id || "12345";
|
|
496
|
+
return `Tip: 发送 /ft.read [ID] 阅读 (例: /ft.read ${exampleId})`;
|
|
486
497
|
});
|
|
487
498
|
ctx.command("ft.sub <threadId:string>", "订阅").action(async ({ session }, threadId) => {
|
|
488
499
|
if (!/^\d+$/.test(threadId)) return "ID错误";
|