Brazen Framework - Download Manager

Cross-tab download queue, resolution pipeline, and immediate downloads for Brazen user scripts

이 스크립트는 직접 설치하는 용도가 아닙니다. 다른 스크립트에서 메타 지시문 // @require https://update.greasyfork.org/scripts/587126/1877680/Brazen%20Framework%20-%20Download%20Manager.js을(를) 사용하여 포함하는 라이브러리입니다.

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

Advertisement:

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

Advertisement:

작성자
brazenvoid
버전
1.2.0
생성일
2026-07-15
갱신일
2026-07-16
크기
125KB
라이선스
GPL-3.0-only

Brazen Framework — Download Manager (developer guide)

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


When to use / when not to use

  • Use when your app needs cross-tab download queues, search-tile selection enqueue, media-page immediate download, token-based paths, duplicate-ledger integration, or tag-discovery review before filenames are built.
  • Do not use for a single fire-and-forget 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.
  • Requires a dockconfigureDownloadManager() throws if configureDock() was not called first.
  • Requires IndexedDB — queue rows and shared state live in IDB via Configuration Manager repositories; when IDB is blocked, persistence gates apply.

Quick start

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,
  linkQueues: false, // default; set true when site + CDN share rate limits
})

BrazenDownloadManager.initialize() runs from Framework init() after Configuration Manager setup.


Configuration shape

Top-level keys

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
linkQueues When true, one serial resolution-first loop; tag discovery and any human-interaction block both pipelines. Default false: concurrent loops; tag discovery pauses resolution only; human-interaction blocks only its humanInteractionContext pipeline. Use true when site and download CDN share rate limits.
selectionModeDefaultConfigKey Optional override for Start in Selection Mode (OPTION_DOWNLOAD_SELECTION_MODE_DEFAULT)
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 roles

Each 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 set resolutionBlocked and open #bv-tag-discovery-panel. With default linkQueues: false, that pauses resolution only (downloads continue). With linkQueues: true, both pipelines pause. Confirm promotes types; Skip drops the item without confirming; Open media opens the source URL. State fields discoveryPanelTags and discoveryPanelKnownTags persist in downloadManagerState.

rateLimitHandlers

Keyed 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 query + hash, rel=opener), 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.

Initiation gaps

resolutionInitiationGapMs and downloadInitiationGapMs pace resolution fetches and GM_download respectively (defaults 2000 each; configure independently per app). Both use separate in-tab clocks hydrated from lastResolutionInitiationAt / lastDownloadInitiationAt in shared state so concurrent IDB writes cannot erase the gap. Resolution paces before every fetch attempt (including rate-limit retries). Confirming a human-interaction rate limit stamps only the blocked pipeline's clock so the next initiation waits a full gap without affecting the other queue.


Public API

Framework delegates most calls; you can also use this.getDownloadManager() for path helpers.

Queue and download

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)

Tag discovery

Method Role
confirmTagDiscoveryMappings() Confirm types; promote resolution item or run pending immediate
skipTagDiscoveryInclusion() Skip review — drop item and clear selection progress; do not confirm types
openTagDiscoveryMedia() Open media URL for item under review
toggleTagDiscoveryMode() Cross-tab discovery enable toggle

Progress and status

Method Role
getDownloadManagerProgress() { resolution: {current, total}, download: {current, total} } — both always live (dock panel shows while either queue has pending work)
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)

Human interaction

Method Role
BrazenDownloadManager.peekHumanInteractionBlockedMirror(scriptPrefix) Static. Sync localStorage mirror — usable in Phase-1 page ops before initialize()
BrazenDownloadManager.peekHumanInteractionBlockedIdb(scriptPrefix) Static. Async IndexedDB read of humanInteractionBlocked — Phase-1 fallback when query/hash/mirror/opener were stripped
BrazenDownloadManager.hasBrazenHumanInteractionMarker() Static. Query or hash still has brazen_hi
BrazenDownloadManager.isQueueOpenedVerificationTab() Static. Same-origin opener (queue-opened tab)
BrazenDownloadManager.shouldSilenceMediaCloudflarePrompt(scriptPrefix, instance?) Static. Whether a challenge page should stay silent
handleMediaCloudflarePage(options?) Phase-1 Cloudflare / challenge page: silence queue tabs; standalone shows themed Done — reload pane
shouldSilenceMediaCloudflarePrompt() Instance wrapper around the static silence gate
isHumanInteractionBlockedSync() Instance: IDB state humanInteractionBlocked

Path and substitution helpers (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>

Processors and leadership

One leader tab (processingTabId) owns both pipelines. With default linkQueues: false, resolution and download run as concurrent loops on that tab. With linkQueues: true, one serial loop prefers resolution then download.

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 (and, if unlinked, resolution is also idle), paused returns to true.
resolutionBlocked Tag discovery gate. Unlinked: stops resolution only (downloads continue). Linked: stops both pipelines.
humanInteractionBlocked Rate-limit gate. Unlinked: stops only the pipeline in humanInteractionContext (second pipeline yields if it also hits HI until the first clears). Linked: stops both.
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 (never requeues this tab's active item).
Claims Items move queuedresolving / downloading before work; in-tab active-item guards abort terminal puts after steal or clear.
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.

Tag discovery UI

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. Promote / Confirm wake the download processor so Ready rows are not stranded.

Human-interaction panel

Shown only on the processor-leader tab when humanInteractionBlocked. Verification tab stays silent (brazen_hi query + hash, localStorage mirror, preserved window.opener, or peekHumanInteractionBlockedIdb). Done — resume clears block; Reopen uses humanInteractionOpenUrl. Cross-tab enqueue while blocked still writes queued rows; processors resume after confirm. Only one HI panel at a time — a second pipeline that hits verification while the first is open requeues and waits.


Integration notes

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, item progress overlays, discovery/human-interaction panels — View Layer
IndexedDB downloadResolutionQueue, downloadQueue, downloadManagerStateIndexedDB Storage

Public API reference (index)

  • Setup: configureDownloadManager, getDownloadManager
  • Queue: downloadImmediate, enqueueDownload, dequeueDownload, isQueued, toggleDownloadManagerPaused, clearDownloadQueue, toggleSelectionMode, toggleCurrentMediaQueued
  • Discovery: confirmTagDiscoveryMappings, skipTagDiscoveryInclusion, openTagDiscoveryMedia, toggleTagDiscoveryMode
  • Status: getDownloadManagerProgress, getDownloadQueueCount, isDownloadPageRole, isDownloadManagerEnabled, isDownloadManagerLeaderTab, handleMediaCloudflarePage, shouldSilenceMediaCloudflarePrompt, peekHumanInteractionBlockedMirror, peekHumanInteractionBlockedIdb, hasBrazenHumanInteractionMarker, isQueueOpenedVerificationTab, isHumanInteractionBlockedSync
  • Paths: buildDownloadPathFromPatterns, parseDownloadTagSubstitutionLines, buildDownloadTagSubstitutionMap, buildDownloadPath