koishi-plugin-booth-get 6.0.0-beta.1 β 6.0.0-beta.2
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/discount-tracker.js +92 -63
- package/package.json +1 -1
package/lib/discount-tracker.js
CHANGED
|
@@ -8,6 +8,8 @@ class DiscountTracker {
|
|
|
8
8
|
this.config = null;
|
|
9
9
|
this.DISCOUNT_ITEMS_FILE = path.join(__dirname, "discount_items.json");
|
|
10
10
|
this.DISCOUNT_GROUPS_FILE = path.join(__dirname, "discount_groups.json");
|
|
11
|
+
this.discountCache = new Map();
|
|
12
|
+
this.CACHE_DURATION = 24 * 60 * 60 * 1000;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
init(ctx, config) {
|
|
@@ -19,6 +21,30 @@ class DiscountTracker {
|
|
|
19
21
|
}
|
|
20
22
|
}
|
|
21
23
|
|
|
24
|
+
cleanupExpiredCache() {
|
|
25
|
+
const now = Date.now();
|
|
26
|
+
for (const [id, timestamp] of this.discountCache.entries()) {
|
|
27
|
+
if (now - timestamp > this.CACHE_DURATION) {
|
|
28
|
+
this.discountCache.delete(id);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
isCached(itemId) {
|
|
34
|
+
const timestamp = this.discountCache.get(itemId);
|
|
35
|
+
if (!timestamp) return false;
|
|
36
|
+
|
|
37
|
+
if (Date.now() - timestamp > this.CACHE_DURATION) {
|
|
38
|
+
this.discountCache.delete(itemId);
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
addToCache(itemId) {
|
|
45
|
+
this.discountCache.set(itemId, Date.now());
|
|
46
|
+
}
|
|
47
|
+
|
|
22
48
|
async loadJSON(file, def = {}) {
|
|
23
49
|
try {
|
|
24
50
|
const raw = await fs.readFile(file, "utf8");
|
|
@@ -123,78 +149,81 @@ class DiscountTracker {
|
|
|
123
149
|
}
|
|
124
150
|
}
|
|
125
151
|
|
|
126
|
-
async notifyDiscountGroups(discountItems) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
for (const groupKey of this.config.targetGroups || []) {
|
|
131
|
-
const parts = groupKey.split(':');
|
|
132
|
-
if (parts.length < 3) continue;
|
|
133
|
-
const platform = parts[1];
|
|
134
|
-
const channelId = parts.slice(2).join(':');
|
|
152
|
+
async notifyDiscountGroups(discountItems) {
|
|
153
|
+
const logger = this.ctx.logger("booth-discount");
|
|
154
|
+
const cardGenerator = require('./card-generator');
|
|
135
155
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
156
|
+
const itemsToPush = discountItems.slice(0, this.config.maxDiscountPushCount || 5);
|
|
157
|
+
|
|
158
|
+
for (const groupKey of this.config.targetGroups || []) {
|
|
159
|
+
const parts = groupKey.split(':');
|
|
160
|
+
if (parts.length < 3) continue;
|
|
161
|
+
const platform = parts[1];
|
|
162
|
+
const channelId = parts.slice(2).join(':');
|
|
163
|
+
|
|
164
|
+
for (const item of itemsToPush) {
|
|
165
|
+
try {
|
|
166
|
+
const html = cardGenerator.generateDiscountCardHTML(item);
|
|
167
|
+
const buffer = await cardGenerator.captureCardHTML(html, this.config);
|
|
168
|
+
if (!buffer) continue;
|
|
169
|
+
|
|
170
|
+
const message = `π εη°ζζ£εεοΌ\n` +
|
|
171
|
+
`εειΎζ₯οΌ${item.url}\n` +
|
|
172
|
+
`εδ»·οΌΒ₯${item.original_price.toLocaleString()}\n` +
|
|
173
|
+
`η°δ»·οΌΒ₯${item.price.toLocaleString()}\n` +
|
|
174
|
+
`ζζ£οΌ${item.discount_rate}% OFF\n` +
|
|
175
|
+
`θηοΌΒ₯${(item.original_price - item.price).toLocaleString()}`;
|
|
176
|
+
|
|
177
|
+
await this.ctx.bots[0].sendMessage(channelId, [message, import_koishi.h.image(buffer, "image/png")]);
|
|
178
|
+
|
|
179
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
180
|
+
} catch (e) {
|
|
181
|
+
logger.warn(`εηΎ€η» ${channelId} ζ¨ιζζ£δΏ‘ζ―ε€±θ΄₯:`, e);
|
|
182
|
+
}
|
|
154
183
|
}
|
|
155
184
|
}
|
|
156
185
|
}
|
|
157
|
-
}
|
|
158
186
|
|
|
159
|
-
startDiscountTracking() {
|
|
160
|
-
|
|
161
|
-
|
|
187
|
+
startDiscountTracking() {
|
|
188
|
+
const logger = this.ctx.logger("booth-discount");
|
|
189
|
+
logger.info('ε―ε¨ζζ£εεθΏ½θΈͺε¨');
|
|
162
190
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
191
|
+
this.ctx.setInterval(async () => {
|
|
192
|
+
try {
|
|
193
|
+
this.cleanupExpiredCache();
|
|
194
|
+
|
|
195
|
+
logger.info('εΌε§ζ£ζ₯ζζ£εε...');
|
|
196
|
+
const discountItems = await this.searchDiscountItems();
|
|
197
|
+
const knownItems = await this.loadJSON(this.DISCOUNT_ITEMS_FILE);
|
|
198
|
+
const newDiscountItems = [];
|
|
199
|
+
|
|
200
|
+
for (const item of discountItems) {
|
|
201
|
+
if (!this.isCached(item.id)) {
|
|
202
|
+
if (!knownItems[item.id] || knownItems[item.id].discount_rate !== item.discount_rate) {
|
|
203
|
+
newDiscountItems.push(item);
|
|
204
|
+
this.addToCache(item.id);
|
|
205
|
+
knownItems[item.id] = {
|
|
206
|
+
...item,
|
|
207
|
+
first_seen: knownItems[item.id]?.first_seen || Date.now(),
|
|
208
|
+
last_updated: Date.now()
|
|
209
|
+
};
|
|
210
|
+
}
|
|
182
211
|
}
|
|
183
212
|
}
|
|
213
|
+
|
|
214
|
+
if (newDiscountItems.length > 0) {
|
|
215
|
+
logger.info(`εη° ${newDiscountItems.length} δΈͺζ°ηζζ£εε`);
|
|
216
|
+
await this.saveJSON(this.DISCOUNT_ITEMS_FILE, knownItems);
|
|
217
|
+
await this.notifyDiscountGroups(newDiscountItems);
|
|
218
|
+
} else {
|
|
219
|
+
logger.info('ζͺεη°ζ°ηζζ£εε');
|
|
220
|
+
}
|
|
221
|
+
} catch (error) {
|
|
222
|
+
logger.error('ζζ£εεζ£ζ₯ε€±θ΄₯:', error);
|
|
184
223
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
await this.saveJSON(this.DISCOUNT_ITEMS_FILE, knownItems);
|
|
189
|
-
await this.notifyDiscountGroups(newDiscountItems);
|
|
190
|
-
} else {
|
|
191
|
-
logger.info('ζͺεη°ζ°ηζζ£εε');
|
|
192
|
-
}
|
|
193
|
-
} catch (error) {
|
|
194
|
-
logger.error('ζζ£εεζ£ζ₯ε€±θ΄₯:', error);
|
|
195
|
-
}
|
|
196
|
-
}, (this.config.discountCheckInterval || 60) * 60 * 1000);
|
|
197
|
-
}
|
|
224
|
+
}, (this.config.discountCheckInterval || 60) * 60 * 1000);
|
|
225
|
+
}
|
|
226
|
+
|
|
198
227
|
async addDiscountGroupSubscription(platform, channelId) {
|
|
199
228
|
const groupKey = `group:${platform}:${channelId}`;
|
|
200
229
|
const discountGroups = await this.loadJSON(this.DISCOUNT_GROUPS_FILE);
|
package/package.json
CHANGED