Cross-tab download queue, resolution pipeline, and immediate downloads for Brazen user scripts
Αυτός ο κώδικας δεν πρέπει να εγκατασταθεί άμεσα. Είναι μια βιβλιοθήκη για άλλους κώδικες που περιλαμβάνεται μέσω της οδηγίας meta // @require https://update.greasyfork.org/scripts/587126/1876991/Brazen%20Framework%20-%20Download%20Manager.js
Cross-tab batch downloads, page resolution, immediate GM_download orchestration, optional tag discovery review, and human-interaction rate-limit handling. Apps extend BrazenFramework, call configureDownloadManager() after configureDock(), and @require this module after Framework core.
Greasy Fork: Download Manager · Requires: Framework core, IndexedDB Storage (v1.1.0+ download queue stores) · Grant on this module: GM_download
GM_download with no queue, no cross-tab state, and no path tokens — that is rare; most Brazen apps still benefit from ledger + path helpers here.configureDownloadManager() throws if configureDock() was not called first.Load order (after Framework core):
// @require … Brazen Framework - Framework.js
// @require … Brazen Framework - Download Manager.js
In the app constructor (after configureDock):
this.configureDock({ orientations: ['right'], scriptName: 'My App', showBranding: true })
this.configureDownloadManager({
enableConfigKey: 'enable-download-manager',
downloadPaths: {
folderConfigKey: 'download-folder',
filenamePatternConfigKey: 'filename-pattern',
subfolderPatternConfigKey: 'subfolder-pattern',
defaultFolder: 'my-downloads',
getPatternResolver: () => ({
chips, tagTypes, ignore, substitutions, unknownDefault,
}),
extractMediaData: (el) => ({ id, md5, ext }),
extractTagGroups: () => ({ author: [], character: [], general: [] }),
extractTagIncidences: () => ({ 'tag name': 12 }), // optional; discovery panel counts
appendExtension: true,
nameFallback: (data) => data.id || 'media',
},
pages: {
search: {
roles: ['selection'],
itemSelector: 'span.thumb',
resolveItem: (item) => ({ itemId, sourceUrl }),
setItemProgress: (item, progress) => { /* optional tile overlay */ },
},
media: {
roles: ['enqueueMedia', 'immediateDownload'],
defaultDownloadType: 'post',
},
},
downloadTypes: {
post: {
resolveFromSearch: (ctx) => ({ nextUrl: ctx.sourceUrl }),
resolveFromMedia: (doc, ctx) => ({ mediaUrl, tagGroups, downloadId, data }),
},
},
getQueueItemId: (ctx) => ctx.itemId,
resolutionInitiationGapMs: 2000,
downloadInitiationGapMs: 2000,
})
BrazenDownloadManager.initialize() runs from Framework init() after Configuration Manager setup.
| Key | Role |
|---|---|
enableConfigKey |
Flag field key for Enable Download Manager (auto-registered unless enabled: true) |
enableDefault |
Default for enable flag when auto-registered |
enabled |
When true, skip enable-flag registration and treat manager as always on |
downloadPaths |
Path/token extraction and pattern resolver (see below) |
pages |
Named page configs with roles (see below) |
downloadTypes |
Per-type resolution handlers (resolveFromSearch, resolveFromMedia, …) |
getQueueItemId |
(context) => string stable queue id |
resolutionInitiationGapMs |
ms between resolution fetches (default 2000) |
downloadInitiationGapMs |
ms between GM_download calls (default 2000; replaces Framework downloadsDelay) |
tagDiscovery |
Optional review panel config (see below) |
rateLimitHandlers |
Per-context rate-limit strategies (see below) |
downloadPaths| Key | Role |
|---|---|
folderConfigKey / filenamePatternConfigKey / subfolderPatternConfigKey |
Configuration Manager keys for folder and patterns |
defaultFolder |
Fallback root folder |
getPatternResolver |
() => { chips, tagTypes, ignore, substitutions, unknownDefault, … } — tag-type tokens use registry attributes when TagRuntime is warmed |
extractMediaData(el) |
Metadata object for pattern chips (id, md5, ext, …) |
extractTagGroups() |
{ typeKey: string[] } tag lists for path tokens |
extractTagIncidences() |
Optional { tagName: count } map for discovery panel incidence meta |
appendExtension |
Append data.ext to filename when set |
nameFallback(data) |
When pattern resolves empty |
Path helpers (buildDownloadPathFromPatterns, buildDownloadPath, sanitizePathSegment, substitution parse/map) live on the manager instance — use getDownloadManager() from the app.
pages and rolesEach pages[pageName] entry:
| Key | Role |
|---|---|
roles |
Capability flags for the active page (see table) |
itemSelector |
Search tiles for selection mode |
resolveItem(item) |
{ itemId, sourceUrl, … } for enqueue |
defaultDownloadType |
Fallback type key for media enqueue |
setItemProgress(item, progress) |
Optional hook for per-tile pipeline UI |
| Role | Enables |
|---|---|
selection |
Selection mode + click-to-enqueue on search tiles |
enqueueMedia |
Media-page add/remove queue toggle |
immediateDownload |
downloadImmediate() on media pages |
tagDiscoveryToggle |
Dock tag-discovery mode button |
Query with isDownloadPageRole('selection') (delegated on Framework).
tagDiscovery (optional)| Key | Role |
|---|---|
discoverAt |
Steps that scan pattern-relevant types, e.g. ['resolution', 'immediate'] |
tagTypes |
Panel grouping: { label, rowClass, color } per type — colors via View Layer applyTagDiscoveryTypeColors |
panel |
Extra options forwarded to renderTagDiscoveryPanelContent (section labels, groupOrder, …) |
actions |
Incidence options for tag-attribute buttons (buildUrl, field keys, CSS, explore gate) — framework owns button chrome |
isTagKnown(tagName) |
Optional override; default checks tag registry |
When discovery is on, unknown tags block the pipeline and open #bv-tag-discovery-panel. Confirm promotes types; Skip drops the item without confirming; Open media opens the source URL. State fields discoveryPanelTags and discoveryPanelKnownTags persist in downloadManagerState.
rateLimitHandlersKeyed by context (resolution, download, …). Each context may define:
| Handler | Role |
|---|---|
humanInteraction |
{ detect(ctx), openUrl?(ctx), confirmTitle?, confirmMessage?, confirmLabel?, reopenLabel? } — opens verification tab (brazen_hi=1), sets humanInteractionBlocked + humanInteractionOpenUrl, shows processor-leader panel. Runs before timedReload. |
timedReload |
{ detect(doc, ctx), reloadDelayMs? } — document detect only (not bare HTTP 429) |
reopenLabel defaults to Reopen verification tab on the human-interaction panel. humanInteractionOpenUrl is stored in shared DM state for Reopen.
resolutionInitiationGapMs and downloadInitiationGapMs pace resolution fetches and GM_download respectively. Download pacing uses an in-tab clock hydrated from lastDownloadInitiationAt in shared state so concurrent IDB writes cannot erase the gap.
Framework delegates most calls; you can also use this.getDownloadManager() for path helpers.
| Method | Role |
|---|---|
downloadImmediate({ mediaElement, removeMediaOnSuccess?, source? }) |
Immediate download; registers path tags; optional discovery gate |
enqueueDownload(context) |
Add to resolution queue; returns whether added |
dequeueDownload(itemId) |
Remove from either queue |
isQueued(itemId) |
Cross-tab pipeline membership |
toggleDownloadManagerPaused() |
Start/pause download queue only; no-op when download pending is 0 |
clearDownloadQueue() |
Wipe download queue only; clears download-context human-interaction block |
toggleCurrentMediaQueued() |
Media-page enqueue toggle |
toggleSelectionMode() |
Local session selection mode (search) |
| Method | Role |
|---|---|
confirmTagDiscoveryMappings() |
Confirm types; promote resolution item or run pending immediate |
skipTagDiscoveryInclusion() |
Skip review — drop item, do not confirm types |
openTagDiscoveryMedia() |
Open media URL for item under review |
toggleTagDiscoveryMode() |
Cross-tab discovery enable toggle |
| Method | Role |
|---|---|
getDownloadManagerProgress() |
{ resolution: {current, total}, download: {current, total} } |
getDownloadQueueCount() |
Dock counter; excludes resolution queue when discovery mode is on |
getPendingPipelineCount() |
Non-terminal items in both queues |
isDownloadManagerEnabled() |
Enable flag + dock active |
isDownloadPageRole(role) |
Page role gate |
isDownloadManagerLeaderTab() |
This tab owns processingTabId |
isDownloadManagerRunning() |
Pipeline active (queues, blocked state, or in-tab processing) |
| Method | Role |
|---|---|
BrazenDownloadManager.peekHumanInteractionBlockedMirror(scriptPrefix) |
Static. Sync localStorage mirror — usable in Phase-1 page ops before initialize() |
isHumanInteractionBlockedSync() |
Instance: IDB state humanInteractionBlocked |
getDownloadManager())| Method | Role |
|---|---|
buildDownloadPathFromPatterns(data, tagGroups) |
Token path assembly |
buildDownloadPath(folder, name) |
Sanitized folder + filename |
sanitizePathSegment(segment) |
Illegal char strip + entity decode |
decodeHtmlEntities(text) |
DOM textarea decode |
parseDownloadTagSubstitutionLines(lines, normalizeToken) |
Substitution parser |
buildDownloadTagSubstitutionMap(rules) |
Map<subject, replacement> |
One leader tab (processingTabId) runs resolution then download loops when not blocked.
| Behaviour | Detail |
|---|---|
paused |
Pauses the download queue only. Resolution auto-runs on enqueue. Start/Pause disabled when download queue is empty. When download queue drains to 0, paused returns to true. |
| Leadership | Heartbeat processingHeartbeatAt (~3 s) + sync localStorage mirror. Stale steal ~12 s or immediate after pagehide mirror clear. Steal requeues in-flight resolving / downloading rows. |
| Claims | Items move queued → resolving / downloading before work; in-tab lock is synchronous before any await. |
| Ledger | Duplicate claim at download time in Download Manager when Skip or Hide is on; ledgerClaimed on download rows prevents double-claim after lock steal. |
| UI cadence | Queue/state puts do not rebuild dock; one UI reset per resolution/download task. Full _syncFromStorage on init, enqueue, Start, tab focus. |
Scans pattern-relevant tag types only. Always registers path tags via _registerResolvedTagGroups (discovery on → seen-only; off → confirm as typeEntryId). Panel lists unknown then known tags with incidence counts; framework maps tag-attribute actions internally. Reload / tab focus restores panel when review pending.
Shown only on the processor-leader tab when humanInteractionBlocked. Verification tab stays silent (brazen_hi=1 + mirror). Done — resume clears block; Reopen uses humanInteractionOpenUrl. Cross-tab enqueue while blocked still writes queued rows; processors resume after confirm.
| Topic | Detail |
|---|---|
| Grant | @grant GM_download on this module (and typically on the app too) |
| Load order | After Framework core; before app script |
| Dock | Manager registers dock fields (selection, enqueue, start/pause, clear, progress, discovery). Apps pushField enable key on the rail. |
| Ledger | Constructor downloadDuplicateLedger on Framework; claims happen in Download Manager — see Framework developer guide |
| View Layer | Progress slot, selection marks, item progress overlays, discovery/human-interaction panels — View Layer |
| IndexedDB | downloadResolutionQueue, downloadQueue, downloadManagerState — IndexedDB Storage |
configureDownloadManager, getDownloadManagerdownloadImmediate, enqueueDownload, dequeueDownload, isQueued, toggleDownloadManagerPaused, clearDownloadQueue, toggleSelectionMode, toggleCurrentMediaQueuedconfirmTagDiscoveryMappings, skipTagDiscoveryInclusion, openTagDiscoveryMedia, toggleTagDiscoveryModegetDownloadManagerProgress, getDownloadQueueCount, isDownloadPageRole, isDownloadManagerEnabled, isDownloadManagerLeaderTab, peekHumanInteractionBlockedMirror, isHumanInteractionBlockedSyncbuildDownloadPathFromPatterns, parseDownloadTagSubstitutionLines, buildDownloadTagSubstitutionMap, buildDownloadPath