Skip to content

Commit

Permalink
Add: fetchDelay option (#339)
Browse files Browse the repository at this point in the history
  • Loading branch information
eight04 authored Oct 6, 2023
1 parent 3c1bf32 commit c9cecce
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 10 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,20 @@ pbs.twimg.com/media/$1:orig
* Lines starting with `#` are ignored.
* Empty lines are ignored.

Fetch delay
------------

You can set a delay between each download:

```
https://i.imgur.com 5
http://example.com 10
```

* Each line includes
- The origin of the image.
- The delay (in seconds).

Retry on failure
----------------

Expand Down
22 changes: 20 additions & 2 deletions src/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,25 @@ let INC = 0;
const batches = new Map;
const batchDownloadLock = createLock({maxActiveReader: 5});

browser.runtime.onMessage.addListener((message, sender) => {
// this is used to log error raised by onMessage handler,
// otherwise the stack trace will be removed after passing the error to the content script.
function logError(fn) {
return (...args) => {
try {
const result = fn(...args);
if (!result || !result.catch) return result;
return result.catch(err => {
console.error(err);
throw err;
});
} catch (err) {
console.error(err);
throw err;
}
};
}

browser.runtime.onMessage.addListener(logError((message, sender) => {
switch (message.method) {
case "singleDownload":
message.tabId = sender.tab.id;
Expand Down Expand Up @@ -76,7 +94,7 @@ browser.runtime.onMessage.addListener((message, sender) => {
return imageCache.get(message.url)
.then(blob => URL.createObjectURL(blob));
}
});
}));

browser.browserAction.onClicked.addListener(tab => {
MENU_ACTIONS[pref.get("browserAction")].handler(tab);
Expand Down
49 changes: 49 additions & 0 deletions src/lib/fetch-delay.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {createLockPool} from "@eight04/read-write-lock";

import {pref} from "./pref.js";
import {parseText} from "./readline.js";

pref.ready().then(() => {
update();
pref.on("change", change => {
if (change.fetchDelay != null) {
update();
}
});
});

const lock = createLockPool({maxActiveReader: 3});
let meta = new Map;

function update() {
const newMeta = new Map;
for (const lines of parseText(pref.get('fetchDelay'))) {
const [origin, delay] = lines[0].trim().split(/\s+/);
const delayMs = Number(delay) * 1000;
newMeta.set(origin, {
...meta.get(origin),
delayMs
});
}
meta = newMeta;
}

export async function fetchDelay(url, cb) {
const origin = new URL(url).origin;
if (meta.has(origin)) {
return await lock.write([origin], async () => {
const t = (meta.get(origin).lastFetch || 0) + meta.get(origin).delayMs - Date.now();
await delay(t > 0 ? t : 0);
try {
return await cb();
} finally {
meta.get(origin).lastFetch = Date.now();
}
});
}
return await lock.read([origin], cb);
}

function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
13 changes: 8 additions & 5 deletions src/lib/image-cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {IS_CHROME} from "./env.js";
import {fetchImage} from "./fetch-image.js";
import {fetchXHR} from "./fetch.js";
import {retry} from "./retry.js";
import {fetchDelay} from "./fetch-delay.js";

export const imageCache = createImageCache();

Expand All @@ -27,11 +28,13 @@ function createImageCache() {

function add({url, tabId, frameId, referrer}) {
return cache.set(url, async () => {
const data = await retry(() => _fetchImage(url, tabId, frameId, referrer), url);
const resource = data.blob;
delete data.blob;
const meta = Object.assign(data, await detectDimension(resource));
return {resource, meta};
return await fetchDelay(url, async () => {
const data = await retry(() => _fetchImage(url, tabId, frameId, referrer), url);
const resource = data.blob;
delete data.blob;
const meta = Object.assign(data, await detectDimension(resource));
return {resource, meta};
});
});
}

Expand Down
1 change: 1 addition & 0 deletions src/lib/pref.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const DEFAULT = {
urlMap: "",
useCache: true,
useExpression: false,
fetchDelay: "",
variableMaxLength: 128,
filePattern: "Image Picka/${pageTitle}/${name}${ext}",
filePatternHistory: [],
Expand Down
7 changes: 7 additions & 0 deletions src/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,13 @@ const root = createUI({
learnMore: "https://github.com/eight04/image-picka#transform-url-with-regexp",
className: "form-monospace"
},
{
type: "textarea",
key: "fetchDelay",
label: _("optionFetchDelayLabel"),
learnMore: "https://github.com/eight04/image-picka#fetch-delay",
className: "form-monospace"
},
{
type: "textarea",
key: "retryOnFailure",
Expand Down
10 changes: 7 additions & 3 deletions src/static/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,13 @@
"message": "Detect image URLs from links.",
"description": "Label of detectLink option"
},
"optionDblClickLabel": {
"message": "Download with double click",
"description": "Label of dblClick option"
"optionDblClickLabel": {
"message": "Download with double click",
"description": "Label of dblClick option"
},
"optionFetchDelayLabel": {
"message": "Delay between each image fetch",
"description": "Label of fetchDelay option"
},
"optionPreviewMaxHeightUpperBoundLabel": {
"message": "The maximum value of the thumbnail size slider",
Expand Down

0 comments on commit c9cecce

Please sign in to comment.