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.
Files changed (2) hide show
  1. package/lib/index.js +29 -18
  2. 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(info.Content);
206
+ if (isChapter && parent) {
207
+ displayCover = parent.Background || extractImage(parent.Content);
208
208
  }
209
209
  if (!displayCover) {
210
- displayCover = isChapter && parent ? parent.Background || extractImage(parent.Content) : info.Background || extractImage(info.Content);
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 > 110) summary = summary.substring(0, 110) + "...";
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: 22px 26px; display: flex; flex-direction: column; justify-content: space-between; overflow: hidden; }
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: 6px; font-weight: 400; }
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: 10px 0; max-height: 56px; overflow: hidden; align-content: flex-start; }
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
- .footer { border-top: 1px solid #eee; padding-top: 14px; display: flex; justify-content: space-between; font-size: 12px; color: #888; margin-top: 12px; }
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
- <div class="summary">${summary}</div>
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: 460, deviceScaleFactor: 2 });
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
- return "Tip: 发送 /ft.read <ID> 阅读";
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错误";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-fimtale-api",
3
3
  "description": "Koishi插件,从fimtale搜索/订阅/随机获取小说/解析链接等",
4
- "version": "0.0.5",
4
+ "version": "0.0.7",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [