Skip to content

Commit 02deb22

Browse files
authored
Add: glob in fetch delay (#361)
* Add: glob in fetch delay * Fix: escape special chars * Update readme * Update readme * Update readme
1 parent 3272660 commit 02deb22

File tree

2 files changed

+32
-9
lines changed

2 files changed

+32
-9
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,15 @@ http://example.com 10
130130
- The origin of the image.
131131
- The delay (in seconds).
132132

133+
After v0.19.0, you can use wildcard in the origin. This also allows you to set a default delay for all images. For example, set a default delay to 10s and 5s for imgur:
134+
135+
```
136+
https://*.imgur.com 5
137+
* 10
138+
```
139+
140+
Note that rules are applied from top to bottom. The first matched rule will be used.
141+
133142
Retry on failure
134143
----------------
135144

src/lib/fetch-delay.js

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,34 +13,48 @@ pref.ready().then(() => {
1313
});
1414

1515
const lock = createLockPool({maxActiveReader: 3});
16-
let meta = new Map;
16+
let rules = [];
1717

1818
function update() {
19-
const newMeta = new Map;
19+
const newRules = [];
2020
for (const lines of parseText(pref.get('fetchDelay'))) {
2121
const [origin, delay] = lines[0].trim().split(/\s+/);
2222
const delayMs = Number(delay) * 1000;
23-
newMeta.set(origin, {
24-
...meta.get(origin),
23+
const oldRule = rules.find(rule => rule.origin === origin);
24+
newRules.push({
25+
...oldRule,
26+
origin,
2527
delayMs
2628
});
2729
}
28-
meta = newMeta;
30+
rules = newRules;
31+
}
32+
33+
function matchGlob(pattern, string) {
34+
if (!pattern.includes("*")) {
35+
return pattern === string;
36+
}
37+
// compile a glob pattern to a regular expression, also escape special characters
38+
const rx = new RegExp(`^${pattern.replace(/[-/\\^$+?.()|[\]{}]/g, "\\$&").replace(/\*/g, ".*")}$`);
39+
return rx.test(string);
2940
}
3041

3142
export async function fetchDelay(url, cb) {
3243
const origin = new URL(url).origin;
33-
if (meta.has(origin)) {
34-
return await lock.write([origin], async () => {
35-
const t = (meta.get(origin).lastFetch || 0) + meta.get(origin).delayMs - Date.now();
44+
const rule = rules.find(rule => matchGlob(rule.origin, origin));
45+
// calculate the delay if there is a matching rule
46+
if (rule) {
47+
return await lock.write([rule.origin], async () => {
48+
const t = (rule.lastFetch || 0) + rule.delayMs - Date.now();
3649
await delay(t > 0 ? t : 0);
3750
try {
3851
return await cb();
3952
} finally {
40-
meta.get(origin).lastFetch = Date.now();
53+
rule.lastFetch = Date.now();
4154
}
4255
});
4356
}
57+
// no matching rule, just fetch, still restricted by the maxActiveReader
4458
return await lock.read([origin], cb);
4559
}
4660

0 commit comments

Comments
 (0)