koishi-plugin-rocom 1.0.9 → 1.0.11

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,77 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=1600, initial-scale=1">
6
+ <title>{{title}}</title>
7
+ <link rel="stylesheet" href="{{_res_path}}render-templates/activities/style.css">
8
+ </head>
9
+ <body>
10
+ <div class="activity-calendar-page">
11
+ <div class="calendar-header">
12
+ <div class="super-title">ROCOM WORLD</div>
13
+ <div class="title-wrap">
14
+ <div class="bg-word">CALENDAR</div>
15
+ <div class="main-title">
16
+ <div class="title-mark"></div>
17
+ <h1>{{title}}</h1>
18
+ <div class="dot-line"><span></span><span></span><span></span><span></span></div>
19
+ </div>
20
+ <div class="subtitle">{{subtitle}}</div>
21
+ </div>
22
+ <img class="header-logo" src="{{_res_path}}img/logo.cVSpb3sL.png" alt="">
23
+ </div>
24
+
25
+ <div class="axis-area">
26
+ <div class="axis-line-horizontal"></div>
27
+ {{each axis_dates d}}
28
+ <div class="axis-marker" style="left: {{d.left_pct}}%;">
29
+ <div class="axis-flag">{{d.label}}<i></i></div>
30
+ <div class="axis-line-vertical"></div>
31
+ </div>
32
+ {{/each}}
33
+ {{if now_line}}
34
+ <div class="axis-marker now-marker" style="left: {{now_line.left_pct}}%;">
35
+ <div class="axis-flag now-flag">{{now_line.label}}<i></i></div>
36
+ <div class="axis-line-vertical now-vertical"></div>
37
+ </div>
38
+ {{/if}}
39
+ </div>
40
+
41
+ <div class="gantt-area">
42
+ {{if empty}}
43
+ <div class="empty-state">暂无进行中的活动。</div>
44
+ {{else}}
45
+ {{each lanes lane}}
46
+ <div class="gantt-row">
47
+ {{each lane act}}
48
+ <div class="gantt-bar-wrapper" style="left: {{act.left_pct}}%; width: {{act.width_pct}}%;">
49
+ <div class="gantt-bar theme-{{act.theme}}">
50
+ {{if act.cover}}
51
+ <div class="bar-cover-wrap"><img class="bar-cover" src="{{act.cover}}" alt=""></div>
52
+ {{/if}}
53
+ <div class="bar-tag {{act.statusClass}}">{{act.statusText}}</div>
54
+ <div class="bar-content">
55
+ <div class="bar-bracket">[ {{act.desc}} ]</div>
56
+ <div class="bar-name">{{act.name}}</div>
57
+ <div class="bar-time">{{act.time_label}}</div>
58
+ <div class="bar-rewards">{{act.rewards_text}}</div>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ {{/each}}
63
+ </div>
64
+ {{/each}}
65
+ {{/if}}
66
+ {{if now_line}}
67
+ <div class="gantt-now-line" style="left: {{now_line.left_pct}}%;"></div>
68
+ {{/if}}
69
+ </div>
70
+
71
+ <div class="footer">
72
+ <span>{{commandHint}}</span>
73
+ <span>{{copyright}}</span>
74
+ </div>
75
+ </div>
76
+ </body>
77
+ </html>
@@ -0,0 +1,434 @@
1
+ @font-face {
2
+ font-family: "RocomWenHei";
3
+ src: url("../../ttf/HYWenHei-85W-1.ttf") format("truetype");
4
+ }
5
+
6
+ * {
7
+ box-sizing: border-box;
8
+ }
9
+
10
+ body {
11
+ margin: 0;
12
+ color: #21190f;
13
+ background: #f7efe0;
14
+ font-family: "RocomWenHei", "Microsoft YaHei", sans-serif;
15
+ }
16
+
17
+ .activity-calendar-page {
18
+ position: relative;
19
+ width: 100%;
20
+ min-height: 900px;
21
+ padding: 34px 38px 30px;
22
+ background:
23
+ linear-gradient(180deg, rgba(255, 247, 226, .90), rgba(255, 231, 188, .86)),
24
+ url("../../img/bg.C8CUoi7I.jpg") center top / cover;
25
+ overflow: hidden;
26
+ }
27
+
28
+ .activity-calendar-page::before {
29
+ content: "";
30
+ position: absolute;
31
+ inset: 0;
32
+ background: radial-gradient(circle at 12% 0, rgba(255, 255, 255, .58), transparent 30%),
33
+ linear-gradient(90deg, rgba(94, 54, 18, .10), transparent 40%, rgba(94, 54, 18, .08));
34
+ pointer-events: none;
35
+ }
36
+
37
+ .calendar-header,
38
+ .axis-area,
39
+ .gantt-area,
40
+ .footer {
41
+ position: relative;
42
+ z-index: 1;
43
+ }
44
+
45
+ .calendar-header {
46
+ min-height: 178px;
47
+ padding: 16px 28px;
48
+ border-radius: 28px;
49
+ background: linear-gradient(135deg, rgba(255, 246, 207, .95), rgba(255, 208, 107, .90));
50
+ border: 4px solid rgba(126, 75, 26, .20);
51
+ box-shadow: 0 18px 38px rgba(72, 43, 17, .18);
52
+ }
53
+
54
+ .super-title {
55
+ font-size: 18px;
56
+ color: rgba(102, 63, 26, .60);
57
+ letter-spacing: 3px;
58
+ }
59
+
60
+ .title-wrap {
61
+ position: relative;
62
+ margin-top: 8px;
63
+ }
64
+
65
+ .bg-word {
66
+ position: absolute;
67
+ top: -28px;
68
+ left: -8px;
69
+ color: rgba(111, 77, 42, .10);
70
+ font-size: 112px;
71
+ letter-spacing: 16px;
72
+ line-height: 1;
73
+ }
74
+
75
+ .main-title {
76
+ position: relative;
77
+ display: flex;
78
+ align-items: center;
79
+ gap: 18px;
80
+ }
81
+
82
+ .title-mark {
83
+ width: 42px;
84
+ height: 42px;
85
+ background: #ffca42;
86
+ border: 5px solid #5e3a18;
87
+ box-shadow: 4px 4px 0 rgba(75, 42, 16, .22);
88
+ }
89
+
90
+ h1 {
91
+ margin: 0;
92
+ color: #4f2d0f;
93
+ font-size: 54px;
94
+ letter-spacing: 4px;
95
+ }
96
+
97
+ .subtitle {
98
+ position: relative;
99
+ margin-top: 12px;
100
+ color: rgba(80, 48, 20, .72);
101
+ font-size: 24px;
102
+ }
103
+
104
+ .dot-line {
105
+ display: flex;
106
+ gap: 8px;
107
+ margin-left: 18px;
108
+ }
109
+
110
+ .dot-line span {
111
+ width: 10px;
112
+ height: 10px;
113
+ border-radius: 50%;
114
+ background: rgba(94, 54, 18, .32);
115
+ }
116
+
117
+ .header-logo {
118
+ position: absolute;
119
+ right: 34px;
120
+ top: 28px;
121
+ width: 300px;
122
+ max-height: 120px;
123
+ object-fit: contain;
124
+ }
125
+
126
+ .axis-area {
127
+ z-index: 4;
128
+ height: 72px;
129
+ margin-top: 30px;
130
+ pointer-events: none;
131
+ }
132
+
133
+ .axis-line-horizontal {
134
+ position: absolute;
135
+ left: 0;
136
+ right: 0;
137
+ top: 36px;
138
+ height: 3px;
139
+ background: rgba(83, 53, 28, .18);
140
+ }
141
+
142
+ .axis-marker {
143
+ position: absolute;
144
+ top: 0;
145
+ width: 80px;
146
+ transform: translateX(-40px);
147
+ text-align: center;
148
+ }
149
+
150
+ .axis-flag {
151
+ position: relative;
152
+ display: inline-block;
153
+ padding: 5px 10px;
154
+ background: #ffca42;
155
+ color: #3f260f;
156
+ font-size: 18px;
157
+ box-shadow: 3px 3px 0 rgba(68, 39, 14, .18);
158
+ white-space: nowrap;
159
+ }
160
+
161
+ .axis-flag i {
162
+ position: absolute;
163
+ left: 50%;
164
+ bottom: -8px;
165
+ width: 0;
166
+ height: 0;
167
+ transform: translateX(-50%);
168
+ border-left: 8px solid transparent;
169
+ border-right: 8px solid transparent;
170
+ border-top: 8px solid #ffca42;
171
+ }
172
+
173
+ .axis-line-vertical {
174
+ position: absolute;
175
+ left: 50%;
176
+ top: 42px;
177
+ width: 2px;
178
+ height: 900px;
179
+ background: rgba(83, 53, 28, .08);
180
+ }
181
+
182
+ .now-marker {
183
+ z-index: 10;
184
+ }
185
+
186
+ .now-flag {
187
+ color: #fff7dc;
188
+ background: #cc5530;
189
+ }
190
+
191
+ .now-flag i {
192
+ border-top-color: #cc5530;
193
+ }
194
+
195
+ .now-vertical {
196
+ width: 3px;
197
+ height: 38px;
198
+ background: transparent;
199
+ border-left: 3px dashed rgba(204, 85, 48, .78);
200
+ }
201
+
202
+ .gantt-area {
203
+ z-index: 2;
204
+ position: relative;
205
+ margin-top: 8px;
206
+ }
207
+
208
+ .gantt-now-line {
209
+ position: absolute;
210
+ top: -38px;
211
+ bottom: 0;
212
+ width: 0;
213
+ transform: translateX(-1.5px);
214
+ border-left: 3px dashed rgba(204, 85, 48, .82);
215
+ z-index: 30;
216
+ pointer-events: none;
217
+ }
218
+
219
+ .gantt-row {
220
+ position: relative;
221
+ height: 112px;
222
+ margin-bottom: 14px;
223
+ border-bottom: 2px dashed rgba(83, 53, 28, .14);
224
+ background: repeating-linear-gradient(-45deg, rgba(255,255,255,.30), rgba(255,255,255,.30) 12px, rgba(255,231,188,.28) 12px, rgba(255,231,188,.28) 24px);
225
+ }
226
+
227
+ .gantt-bar-wrapper {
228
+ position: absolute;
229
+ height: 100%;
230
+ min-width: 270px;
231
+ container-type: inline-size;
232
+ }
233
+
234
+ .gantt-bar {
235
+ position: relative;
236
+ height: 100%;
237
+ overflow: hidden;
238
+ display: flex;
239
+ align-items: center;
240
+ justify-content: flex-end;
241
+ padding: 10px 18px 10px 104px;
242
+ border-left: 8px solid rgba(255, 218, 92, .90);
243
+ box-shadow: 0 8px 18px rgba(69, 38, 12, .25);
244
+ }
245
+
246
+ .theme-gold {
247
+ background: linear-gradient(90deg, rgba(118, 77, 37, .92), rgba(211, 143, 46, .95));
248
+ }
249
+
250
+ .theme-green {
251
+ background: linear-gradient(90deg, rgba(69, 93, 50, .92), rgba(135, 166, 65, .95));
252
+ }
253
+
254
+ .theme-brown {
255
+ background: linear-gradient(90deg, rgba(80, 63, 47, .94), rgba(151, 102, 58, .95));
256
+ }
257
+
258
+ .bar-cover-wrap {
259
+ position: absolute;
260
+ inset: 0 auto 0 0;
261
+ width: 58%;
262
+ max-width: 620px;
263
+ -webkit-mask-image: linear-gradient(to right, #000 55%, transparent 100%);
264
+ mask-image: linear-gradient(to right, #000 55%, transparent 100%);
265
+ }
266
+
267
+ .bar-cover {
268
+ width: 100%;
269
+ height: 100%;
270
+ object-fit: cover;
271
+ }
272
+
273
+ .bar-tag {
274
+ position: absolute;
275
+ left: 16px;
276
+ top: 50%;
277
+ transform: translateY(-50%);
278
+ max-width: 76px;
279
+ padding: 5px 10px;
280
+ border-radius: 999px;
281
+ color: #fff8dc;
282
+ background: rgba(65, 39, 17, .70);
283
+ overflow: hidden;
284
+ text-overflow: ellipsis;
285
+ white-space: nowrap;
286
+ font-size: 14px;
287
+ z-index: 2;
288
+ }
289
+
290
+ .bar-tag.active {
291
+ background: #d46926;
292
+ }
293
+
294
+ .bar-tag.upcoming {
295
+ background: #57894a;
296
+ }
297
+
298
+ .bar-tag.ended {
299
+ background: #7c746b;
300
+ }
301
+
302
+ .bar-tag.permanent {
303
+ background: #a35f24;
304
+ }
305
+
306
+ .bar-content {
307
+ position: relative;
308
+ z-index: 2;
309
+ width: 100%;
310
+ min-width: 0;
311
+ max-width: 100%;
312
+ text-align: right;
313
+ color: #fff8dc;
314
+ text-shadow: 0 2px 4px rgba(47, 25, 8, .55);
315
+ }
316
+
317
+ .bar-bracket {
318
+ overflow: hidden;
319
+ text-overflow: ellipsis;
320
+ white-space: nowrap;
321
+ font-size: 11px;
322
+ letter-spacing: 1px;
323
+ opacity: .90;
324
+ }
325
+
326
+ .bar-name {
327
+ margin-top: 3px;
328
+ overflow: hidden;
329
+ display: -webkit-box;
330
+ overflow-wrap: anywhere;
331
+ -webkit-box-orient: vertical;
332
+ -webkit-line-clamp: 2;
333
+ font-size: 20px;
334
+ line-height: 1.1;
335
+ }
336
+
337
+ .bar-time,
338
+ .bar-rewards {
339
+ display: block;
340
+ margin-top: 5px;
341
+ padding: 3px 9px;
342
+ background: rgba(42, 26, 10, .54);
343
+ overflow: hidden;
344
+ overflow-wrap: anywhere;
345
+ font-size: 11px;
346
+ line-height: 1.25;
347
+ }
348
+
349
+ .bar-rewards {
350
+ max-width: 100%;
351
+ display: -webkit-box;
352
+ -webkit-box-orient: vertical;
353
+ -webkit-line-clamp: 2;
354
+ }
355
+
356
+ .empty-state {
357
+ min-height: 260px;
358
+ display: flex;
359
+ align-items: center;
360
+ justify-content: center;
361
+ border: 2px dashed rgba(83, 53, 28, .20);
362
+ background: rgba(255, 255, 255, .36);
363
+ color: rgba(80, 48, 20, .72);
364
+ font-size: 32px;
365
+ }
366
+
367
+ @container (max-width: 420px) {
368
+ .gantt-bar {
369
+ padding-left: 88px;
370
+ padding-right: 12px;
371
+ }
372
+
373
+ .bar-tag {
374
+ left: 10px;
375
+ max-width: 66px;
376
+ padding: 4px 8px;
377
+ font-size: 12px;
378
+ }
379
+
380
+ .bar-bracket {
381
+ display: none;
382
+ }
383
+
384
+ .bar-name {
385
+ font-size: 17px;
386
+ line-height: 1.12;
387
+ }
388
+
389
+ .bar-time,
390
+ .bar-rewards {
391
+ margin-top: 4px;
392
+ padding: 2px 6px;
393
+ font-size: 10px;
394
+ }
395
+ }
396
+
397
+ @container (max-width: 320px) {
398
+ .gantt-bar {
399
+ align-items: stretch;
400
+ padding: 8px 10px 8px 72px;
401
+ }
402
+
403
+ .bar-tag {
404
+ left: 8px;
405
+ max-width: 56px;
406
+ font-size: 11px;
407
+ }
408
+
409
+ .bar-content {
410
+ display: flex;
411
+ min-height: 0;
412
+ flex-direction: column;
413
+ justify-content: center;
414
+ }
415
+
416
+ .bar-name {
417
+ font-size: 15px;
418
+ -webkit-line-clamp: 2;
419
+ }
420
+
421
+ .bar-rewards {
422
+ display: none;
423
+ }
424
+ }
425
+
426
+ .footer {
427
+ display: flex;
428
+ justify-content: space-between;
429
+ margin-top: 22px;
430
+ padding-top: 16px;
431
+ border-top: 2px solid rgba(83, 53, 28, .16);
432
+ color: rgba(71, 43, 20, .72);
433
+ font-size: 18px;
434
+ }
package/lib/render.js CHANGED
@@ -47,6 +47,13 @@ const logger = new koishi_1.Logger('rocom-render');
47
47
  const TEMPLATE_CAPTURE_PADDING = {
48
48
  package: { left: 0, right: 0, top: 0, bottom: 0 },
49
49
  };
50
+ const TEMPLATE_VIEWPORTS = {
51
+ activities: { width: 1600, height: 1200, deviceScaleFactor: 2 },
52
+ };
53
+ const DEFAULT_SCREENSHOT_OPTIONS = {
54
+ type: 'jpeg',
55
+ quality: 82,
56
+ };
50
57
  function toDirectoryFileUrl(dirPath) {
51
58
  const href = (0, node_url_1.pathToFileURL)(dirPath).href;
52
59
  return href.endsWith('/') ? href : `${href}/`;
@@ -119,7 +126,8 @@ class Renderer {
119
126
  try {
120
127
  await page.setCacheEnabled(false);
121
128
  node_fs_1.default.writeFileSync(tempHtmlPath, html, 'utf-8');
122
- await page.setViewport({ width: 1280, height: 768, deviceScaleFactor: 2 });
129
+ const initialViewport = TEMPLATE_VIEWPORTS[templateName] || { width: 1280, height: 768, deviceScaleFactor: 2 };
130
+ await page.setViewport(initialViewport);
123
131
  try {
124
132
  await page.goto((0, node_url_1.pathToFileURL)(tempHtmlPath).href, {
125
133
  waitUntil: 'networkidle0',
@@ -172,6 +180,7 @@ class Renderer {
172
180
  '.home-page',
173
181
  '.pet-panel-page',
174
182
  '.pet-detail-page',
183
+ '.activity-calendar-page',
175
184
  ];
176
185
  let target = null;
177
186
  for (const selector of selectors) {
@@ -199,7 +208,7 @@ class Renderer {
199
208
  await page.setViewport({
200
209
  width: Math.max(Math.ceil(elementMetrics.x + elementMetrics.width + capturePadding.right) + 8, 200),
201
210
  height: Math.max(Math.ceil(elementMetrics.y + elementMetrics.height + capturePadding.bottom) + 8, 200),
202
- deviceScaleFactor: 2,
211
+ deviceScaleFactor: initialViewport.deviceScaleFactor,
203
212
  });
204
213
  await new Promise(resolve => setTimeout(resolve, 100));
205
214
  const hasOverflow = elementMetrics.width > box.width + 0.5 ||
@@ -210,7 +219,7 @@ class Renderer {
210
219
  const clipWidth = elementMetrics.width + capturePadding.left + capturePadding.right;
211
220
  const clipHeight = elementMetrics.height + capturePadding.top + capturePadding.bottom;
212
221
  const screenshot = await page.screenshot({
213
- type: 'png',
222
+ ...DEFAULT_SCREENSHOT_OPTIONS,
214
223
  clip: {
215
224
  x: clipX,
216
225
  y: clipY,
@@ -221,10 +230,10 @@ class Renderer {
221
230
  return Buffer.isBuffer(screenshot) ? screenshot : Buffer.from(screenshot);
222
231
  }
223
232
  }
224
- const screenshot = await target.screenshot({ type: 'png' });
233
+ const screenshot = await target.screenshot(DEFAULT_SCREENSHOT_OPTIONS);
225
234
  return Buffer.isBuffer(screenshot) ? screenshot : Buffer.from(screenshot);
226
235
  }
227
- const screenshot = await page.screenshot({ fullPage: true });
236
+ const screenshot = await page.screenshot({ ...DEFAULT_SCREENSHOT_OPTIONS, fullPage: true });
228
237
  return Buffer.isBuffer(screenshot) ? screenshot : Buffer.from(screenshot);
229
238
  }
230
239
  finally {
@@ -1,3 +1,4 @@
1
1
  import { PluginConfig } from './types';
2
+ export declare function detectImageMime(image: Buffer): string;
2
3
  export declare function compressPngImage(image: Buffer, config: Pick<PluginConfig, 'imageCompressionEnabled' | 'imageCompressionMinBytes' | 'imageCompressionLevel'>): Buffer;
3
4
  export declare function sendImageWithFallback(session: any, image: Buffer | null, fallbackText: string, scene: string, compressionConfig?: Pick<PluginConfig, 'imageCompressionEnabled' | 'imageCompressionMinBytes' | 'imageCompressionLevel'>): Promise<void>;
package/lib/send-image.js CHANGED
@@ -3,12 +3,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.detectImageMime = detectImageMime;
6
7
  exports.compressPngImage = compressPngImage;
7
8
  exports.sendImageWithFallback = sendImageWithFallback;
8
9
  const koishi_1 = require("koishi");
9
10
  const node_zlib_1 = __importDefault(require("node:zlib"));
10
11
  const logger = new koishi_1.Logger('rocom-send');
11
12
  const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
13
+ const JPEG_SIGNATURE = Buffer.from([0xff, 0xd8, 0xff]);
12
14
  function formatSessionContext(session) {
13
15
  if (!session)
14
16
  return 'session=<null>';
@@ -48,6 +50,16 @@ function pngChunk(type, data) {
48
50
  function isPng(buffer) {
49
51
  return buffer.length > PNG_SIGNATURE.length && buffer.subarray(0, PNG_SIGNATURE.length).equals(PNG_SIGNATURE);
50
52
  }
53
+ function isJpeg(buffer) {
54
+ return buffer.length > JPEG_SIGNATURE.length && buffer.subarray(0, JPEG_SIGNATURE.length).equals(JPEG_SIGNATURE);
55
+ }
56
+ function detectImageMime(image) {
57
+ if (isPng(image))
58
+ return 'image/png';
59
+ if (isJpeg(image))
60
+ return 'image/jpeg';
61
+ return 'image/png';
62
+ }
51
63
  function compressPngImage(image, config) {
52
64
  if (!config.imageCompressionEnabled)
53
65
  return image;
@@ -118,7 +130,7 @@ async function sendImageWithFallback(session, image, fallbackText, scene, compre
118
130
  logger.info(`[${scene}] compressed image ${image.length}B -> ${outputImage.length}B | ${ctxInfo}`);
119
131
  }
120
132
  try {
121
- const result = await session.send(koishi_1.h.image(outputImage, 'image/png'));
133
+ const result = await session.send(koishi_1.h.image(outputImage, detectImageMime(outputImage)));
122
134
  if (!hasSendResult(result)) {
123
135
  logger.warn(`[${scene}] image send returned empty result | size=${outputImage.length}B | ${ctxInfo}`);
124
136
  }
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.sendScheduledMessage = sendScheduledMessage;
4
4
  exports.sendScheduledImageWithFallback = sendScheduledImageWithFallback;
5
5
  const koishi_1 = require("koishi");
6
+ const send_image_1 = require("./send-image");
6
7
  const logger = new koishi_1.Logger('rocom-subscription-send');
7
8
  function findBot(ctx, platform = '') {
8
9
  if (!ctx.bots?.length)
@@ -52,7 +53,7 @@ async function sendScheduledImageWithFallback(ctx, target, image, fallbackText,
52
53
  if (!image) {
53
54
  return sendScheduledMessage(ctx, target, `${prefix}${fallbackText}`);
54
55
  }
55
- const imageSegment = koishi_1.h.image(image, 'image/png');
56
+ const imageSegment = koishi_1.h.image(image, (0, send_image_1.detectImageMime)(image));
56
57
  const content = mentionAll ? `${prefix}${imageSegment}` : imageSegment;
57
58
  const sent = await sendScheduledMessage(ctx, target, content);
58
59
  if (sent)
package/lib/types.d.ts CHANGED
@@ -13,7 +13,9 @@ export interface PluginConfig {
13
13
  merchantSubscriptionEnabled: boolean;
14
14
  merchantSubscriptionItems: string[];
15
15
  merchantPrivateSubscriptionEnabled: boolean;
16
+ merchantCheckMode: 'interval' | 'times';
16
17
  merchantCheckInterval: number;
18
+ merchantCheckTimes: string[];
17
19
  homeSubscriptionEnabled: boolean;
18
20
  homeSubscriptionIntervalMinutes: number;
19
21
  imageCompressionEnabled: boolean;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-rocom",
3
3
  "description": "洛克王国查询与订阅插件",
4
- "version": "1.0.9",
4
+ "version": "1.0.11",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "homepage": "https://github.com/staytomorrow/koishi-plugin-rocom",
package/readme.md CHANGED
@@ -9,12 +9,7 @@
9
9
 
10
10
  ---
11
11
 
12
- 临时APIKey(任选其一)
13
- sk-ba042e079cf9ccb30e72b3d5af458f45
14
- sk-c7952558b84a176b76d0215760732330
15
- sk-b3d96323b2b045282c52f81ca43fcad8
16
- sk-5c14c1e5da063037d02c15e50285dd04
17
-
12
+ APIkey获取请访问:[洛克魔法书](https://rocom.shallow.ink/)
18
13
  ---
19
14
 
20
15
  </div>
@@ -38,7 +33,7 @@ Koishi 版洛克王国数据查询插件。插件基于 WeGame / 后端接口提
38
33
  - `puppeteer`
39
34
  - `rocom`
40
35
 
41
- 如果图片渲染失败,插件会尽量回落为文字结果;但档案、战绩、背包、阵容、交换大厅、远行商人和查蛋配种等功能推荐配合 Puppeteer 使用。
36
+ 如果图片渲染失败,插件会尽量回落为文字结果;但档案、战绩、背包、阵容、交换大厅、远行商人、活动日历和查蛋配种等功能推荐配合 Puppeteer 使用。
42
37
 
43
38
  | 功能 | 示例图片 | 功能 | 示例图片 |
44
39
  | -------- | -------------------------------------------------- | -------- | -------------------------------------------------- |
@@ -64,13 +59,13 @@ Koishi 版洛克王国数据查询插件。插件基于 WeGame / 后端接口提
64
59
  | `merchantPrivateSubscriptionEnabled` | `true` | 是否允许私聊订阅远行商人推送 |
65
60
  | `homeSubscriptionEnabled` | `true` | 是否启用家园菜园和灵感订阅推送 |
66
61
  | `homeSubscriptionIntervalMinutes` | `5` | 家园订阅检查间隔,单位分钟 |
67
- | `imageCompressionEnabled` | `true` | 是否在发送图片前启用 PNG 无损压缩 |
62
+ | `imageCompressionEnabled` | `true` | 是否对 PNG 图片启用无损压缩 |
68
63
  | `imageCompressionMinBytes` | `262144` | 触发压缩的最小图片大小,单位字节 |
69
64
  | `imageCompressionLevel` | `9` | PNG zlib 压缩等级,范围 `0-9`,数值越大通常越小但更耗时 |
70
65
 
71
66
  ### 图片压缩设置
72
67
 
73
- 后台配置页中有单独的“图片压缩设置”分组。该功能会在图片发送前对 PNG IDAT 数据做无损重压缩,不会改变图片尺寸、画质或透明度。若压缩失败,或压缩后文件没有变小,会自动发送原图。
68
+ 后台配置页中有单独的“图片压缩设置”分组。Puppeteer 渲染图默认以 JPEG 发送,用于降低图片体积;仍以 PNG 进入发送链路的图片会按该设置对 IDAT 数据做无损重压缩,不会改变图片尺寸、画质或透明度。若压缩失败,或压缩后文件没有变小,会自动发送原图。
74
69
 
75
70
  ## 快速开始
76
71