WeebCentral and MangaPill are off by default, with an admin switch per source

Both are unofficial sites that mostly host unlicensed copies; MangaDex (official
API) stays on. Settings → Admin → Scraper → Hoster settings has a 'Use <source>'
switch. A switched-off source refuses new jobs, keeps queued jobs waiting and is
skipped by nightly update checks. Installations whose queue or history already
used a source keep it switched on, so upgrades don't stop a working queue.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MaashkinoozheandClaude Opus 5.5 committed 2026-10-25 07:47:47 +01:00
1 parent 336d3325fe
commit 57a571d2f0
6 files changed
+84 -10

No files matched your search

+12 -2
View File
@@ -206,7 +206,8 @@
return;
}
const activeEntries = state.active?.length ? state.active : state.current ? [{ source: state.current.source, current: state.current, job: state.job }] : [];
const url = h('input', { type: 'url', placeholder: 'WeebCentral or MangaDex title URL', class: 'grow' });
const usable = (state.adapters || []).filter(adapter => state.settings?.sourcesEnabled?.[adapter.id] !== false).map(adapter => adapter.label);
const url = h('input', { type: 'url', placeholder: `${usable.join(', ') || 'Source'} title URL`, class: 'grow' });
const title = h('input', { placeholder: 'Title override (optional)' });
const scope = h('select', {},
h('option', { value: 'missing' }, 'All missing chapters'),
@@ -229,8 +230,16 @@
const max = h('input', { type: 'number', min: '.5', step: '.5', value: (sourceRate.maxMs ?? 4000) / 1000, title: 'Maximum seconds between image and API requests' });
const chapterMin = h('input', { type: 'number', min: '.5', step: '1', value: (sourceRate.chapterMinMs ?? 5000) / 1000, title: 'Minimum seconds between chapters' });
const chapterMax = h('input', { type: 'number', min: '.5', step: '1', value: (sourceRate.chapterMaxMs ?? 15000) / 1000, title: 'Maximum seconds between chapters' });
// Sources with a switch (sourcesEnabled) start switched off on new installations.
const switchable = Object.hasOwn(rate.sourcesEnabled || {}, adapter.id);
const enabled = switchable ? h('input', { type: 'checkbox', checked: rate.sourcesEnabled[adapter.id] === true,
onchange: e => command({ command: 'settings', settings: { sourcesEnabled: { [adapter.id]: e.target.checked } } }) }) : null;
return h('div', { class: 'source-rate' },
h('b', {}, adapter.label),
switchable ? h('label', { class: 'check' }, enabled, h('span', {}, `Use ${adapter.label}`,
h('div', { class: 'muted small' }, adapter.id === 'mangadex'
? 'Official API; titles removed at a publisher\'s request are not offered.'
: 'Unofficial site that mostly hosts unlicensed copies. Switch it on only for what you may copy. While it is off, its queued jobs wait and update checks skip it.'))) : null,
h('div', { class: 'row rate-row' },
h('label', {}, h('small', {}, 'Requests min (s)'), min), h('label', {}, h('small', {}, 'Requests max (s)'), max),
h('label', {}, h('small', {}, 'Chapters min (s)'), chapterMin), h('label', {}, h('small', {}, 'Chapters max (s)'), chapterMax),
@@ -248,7 +257,8 @@
const completed = visible(state.queue.filter(item => item.status === 'complete' && item.kind === 'download'));
const when = value => value && !Number.isNaN(Date.parse(value)) ? new Date(value).toLocaleString() : 'Never';
const chips = h('div', { class: 'row scraper-filters', role: 'group', 'aria-label': 'Filter by source' },
[{ id: '', label: 'All sources' }, ...(state.adapters || []).map(adapter => ({ id: adapter.id, label: adapter.label }))].map(option =>
[{ id: '', label: 'All sources' }, ...(state.adapters || []).map(adapter => ({ id: adapter.id,
label: adapter.label + (state.settings?.sourcesEnabled?.[adapter.id] === false ? ' (off)' : '') }))].map(option =>
h('button', { class: 'btn small', type: 'button', 'aria-pressed': sourceFilter === option.id ? 'true' : 'false',
onclick: () => { sourceFilter = option.id; draw(lastState); } }, option.label)));
card.append(chips);