From 6c0958b92ec096ba4693c9eadf6b8e84f8a06e19 Mon Sep 17 00:00:00 2001 From: StenFredd Date: Sun, 3 May 2026 15:18:09 +0300 Subject: [PATCH] Update metadata --- frontend/index.html | 80 +++++++++++++++++++++-- src/api.py | 156 ++++++++++++++++++-------------------------- src/worker.py | 128 +++++++++++++++++++++++++++++++++++- 3 files changed, 265 insertions(+), 99 deletions(-) diff --git a/frontend/index.html b/frontend/index.html index adea8db..1426e35 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -222,6 +222,19 @@
+ +

Сменить пароль

@@ -703,6 +716,18 @@ function handleEvent(msg) { _updateMetaBtn(msg.url, msg.failed === -1 ? 'error' : 'done'); break; + case 'refresh_all_started': + _handleRefreshAllStarted(msg); + break; + + case 'refresh_all_progress': + _handleRefreshAllProgress(msg); + break; + + case 'refresh_all_done': + _handleRefreshAllDone(msg); + break; + case 'manga_meta_updated': if(state.mangas[msg.url]) { state.mangas[msg.url].title = msg.title; @@ -812,7 +837,7 @@ function switchTab(tab) { document.getElementById('manga-filters').classList.toggle('hidden', tab !== 'mangas'); if(tab === 'history') loadHistory(); if(tab === 'news') { newsUnreadCount = 0; updateNewsBadge(); loadNews(); } - if(tab === 'settings') { loadSources(); showUsersSection(); } + if(tab === 'settings') { loadSources(); showUsersSection(); showRefreshAllSection(); } } function updateNewsBadge() { @@ -1132,6 +1157,11 @@ function showUsersSection() { } } +function showRefreshAllSection() { + const el = document.getElementById('refresh-all-section'); + if(el) el.classList.toggle('hidden', !isAdmin()); +} + async function loadUsers() { if(!isAdmin()) return; try { @@ -1654,7 +1684,7 @@ function _updateMetaBtn(url, result) { btn.style.color = '#4ade80'; btn.style.borderColor = '#166534'; setTimeout(() => { - btn.innerHTML = '🏷 Обновить метатеги'; + btn.innerHTML = '🏷 Обновить метаданные'; btn.style.color = '#a78bfa'; btn.style.borderColor = '#312e81'; }, 2500); @@ -1664,12 +1694,12 @@ function _updateMetaBtn(url, result) { btn.style.color = '#f87171'; btn.style.borderColor = '#7f1d1d'; setTimeout(() => { - btn.innerHTML = '🏷 Обновить метатеги'; + btn.innerHTML = '🏷 Обновить метаданные'; btn.style.color = '#a78bfa'; btn.style.borderColor = '#312e81'; }, 3000); } else { - btn.innerHTML = '🏷 Обновить метатеги'; + btn.innerHTML = '🏷 Обновить метаданные'; btn.disabled = false; btn.style.color = '#a78bfa'; btn.style.borderColor = '#312e81'; @@ -1691,6 +1721,46 @@ async function refreshMetaModal(url) { // Спиннер появится через WS meta_refresh_started, исчезнет через meta_refreshed } +async function refreshAllMeta() { + const btn = document.getElementById('refresh-all-btn'); + const status = document.getElementById('refresh-all-status'); + const r = await fetch('/api/mangas/refresh_all_meta', {method:'POST'}); + if(!r.ok) { + const err = await r.json().catch(() => ({})); + if(status) { status.textContent = err.detail || 'Ошибка запуска'; status.classList.remove('hidden'); status.style.color = '#f87171'; } + return; + } + if(btn) { btn.disabled = true; btn.textContent = '⏳ Запускаем...'; } + if(status) { status.textContent = 'Инициализация...'; status.classList.remove('hidden'); status.style.color = '#94a3b8'; } +} + +function _handleRefreshAllStarted(data) { + const btn = document.getElementById('refresh-all-btn'); + const status = document.getElementById('refresh-all-status'); + if(btn) { btn.disabled = true; btn.textContent = '⏳ Обновляем...'; } + if(status) { status.textContent = `0 / ${data.total}`; status.classList.remove('hidden'); status.style.color = '#94a3b8'; } +} + +function _handleRefreshAllProgress(data) { + const status = document.getElementById('refresh-all-status'); + if(status) { + const title = data.title ? ` — ${data.title}` : ''; + status.textContent = `${data.done + 1} / ${data.total}${title}`; + status.style.color = '#94a3b8'; + } +} + +function _handleRefreshAllDone(data) { + const btn = document.getElementById('refresh-all-btn'); + const status = document.getElementById('refresh-all-status'); + if(btn) { btn.disabled = false; btn.textContent = '🔄 Обновить все метаданные'; } + if(status) { + status.textContent = `Готово: ${data.total} манг, обновлено файлов: ${data.total_updated}`; + status.style.color = '#4ade80'; + status.classList.remove('hidden'); + } +} + async function forceRedownload(url, closeModalAfter = false) { if(!confirm('Скачать заново ВСЕ главы? Уже скачанные файлы будут перезаписаны.')) return; const r = await fetch('/api/mangas/force_redownload?url='+encodeURIComponent(url), {method:'POST'}); @@ -2236,7 +2306,7 @@ function renderModalBody(data) { ` : ''} ${data.status !== 'downloading' && data.status !== 'queued' && isAdmin() ? `