From 45bfb8fa5fe74f349c2104f28f4cd915d3884d7f Mon Sep 17 00:00:00 2001 From: Karol Labus Date: Thu, 3 Sep 2026 12:38:56 +0200 Subject: [PATCH] Improve sync feedback and dashboard layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add request counters to Radio 357 backfill logs, clarify RNŚ warnings, and refine responsive dashboard metrics and configuration layout. --- core/scrapers/radio357.py | 10 +++++----- core/scrapers/rns.py | 8 +++++++- templates/base.html | 3 +++ templates/index.html | 39 +++++++++++++++++++-------------------- 4 files changed, 34 insertions(+), 26 deletions(-) diff --git a/core/scrapers/radio357.py b/core/scrapers/radio357.py index 4ecfbdb..07d2146 100644 --- a/core/scrapers/radio357.py +++ b/core/scrapers/radio357.py @@ -240,12 +240,12 @@ class Radio357Scraper: if self.requests_made >= self.hard_limit or backfill_count >= self.backfill_limit: break - self.logger(f"R357: Pobieram URL dla {ep.title[:30]}...") gateway_url = f"https://gateway.r357.eu/api/content/podcast/{ep.ep_id}/url" self.requests_made += 1 if self.progress_callback: self.progress_callback(self.requests_made, self.hard_limit) backfill_count += 1 + self.logger(f"R357: [{self.requests_made}/{self.hard_limit}] Pobieram URL dla {ep.title[:30]}...") try: r = requests.get(gateway_url, headers={ "Authorization": f"Bearer {token}", @@ -259,22 +259,22 @@ class Radio357Scraper: ep.url = audio_url fetched += 1 elif r.status_code == 401 or r.status_code == 403: - self.logger("R357: Token odrzucony przez gateway. Wymagam reloginu.") + self.logger(f"R357: [{self.requests_made}/{self.hard_limit}] Token odrzucony przez gateway. Wymagam reloginu.") # Usuwamy token, zeby przy nastepnym runie pobral nowy self.db.query(Config).filter_by(key="r357_token").delete() self.db.commit() raise Exception("R357 Token Expired") else: - self.logger(f"R357 Błąd HTTP {r.status_code} podczas pobierania audio: {r.text[:100]}") + self.logger(f"R357: [{self.requests_made}/{self.hard_limit}] Błąd HTTP {r.status_code} podczas pobierania audio: {r.text[:100]}") except Exception as e: - self.logger(f"R357: Błąd URL dla odcinka {ep.ep_id}: {e}") + self.logger(f"R357: [{self.requests_made}/{self.hard_limit}] Błąd URL dla odcinka {ep.ep_id}: {e}") if "Token Expired" in str(e): raise time.sleep(0.5) self.db.commit() - self.logger(f"R357: Pomyślnie pobrano {fetched} nowych linków.") + self.logger(f"R357: [{self.requests_made}/{self.hard_limit}] Pomyślnie pobrano {fetched} nowych linków.") def run_full_sync(self, specific_program_slug=None): self.sync_episodes(specific_program_slug) diff --git a/core/scrapers/rns.py b/core/scrapers/rns.py index 579db1b..9475445 100644 --- a/core/scrapers/rns.py +++ b/core/scrapers/rns.py @@ -253,6 +253,7 @@ class RNScraper: new_found = 0 missing_player_count = 0 + missing_player_titles = [] valid_cards = 0 for card in cards: @@ -266,6 +267,8 @@ class RNScraper: if not player_box: missing_player_count += 1 + if title_el := card.find("p", class_="rns-post-title"): + missing_player_titles.append(title_el.get_text(strip=True)) if audio_url and not audio_url.startswith("http"): audio_url = f"{BASE_URL}/{audio_url.lstrip('/')}" @@ -315,7 +318,10 @@ class RNScraper: invalid_response("rns", "HTML_SCHEMA_CHANGED", "Znaleziono karty podcastów bez oczekiwanych identyfikatorów", url, content=html) if missing_player_count: - warning = f"{missing_player_count} odcinków bez dostępnego playera audio; pomijam ich URL-e." + titles = ", ".join(missing_player_titles[:3]) + warning = f"Audycja {program_slug}: {missing_player_count} odcinków bez dostępnego playera audio; pomijam ich URL-e." + if titles: + warning += f" Odcinki: {titles}." if self.warning_callback: self.warning_callback(warning) else: diff --git a/templates/base.html b/templates/base.html index 192c25b..101c91e 100644 --- a/templates/base.html +++ b/templates/base.html @@ -69,6 +69,9 @@ .episode-title { font-size: 1.05rem; } .page-toolbar { border-bottom: 1px solid var(--line); padding-bottom: 1rem; margin-bottom: 1.25rem; } .empty-state { color: var(--muted); padding: 2rem 0; } + .config-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: .5rem; } + .config-grid > div { min-width: 0; } + .config-grid .form-label { display: block; min-height: 2.5em; line-height: 1.35; } @media (max-width: 767.98px) { .container { padding-left: 18px; padding-right: 18px; } .navbar .container { padding-left: 18px; padding-right: 18px; } diff --git a/templates/index.html b/templates/index.html index 0fefffd..292674f 100644 --- a/templates/index.html +++ b/templates/index.html @@ -60,25 +60,20 @@ {% endif %} -
- - - -
{% if status[st].status == 'W trakcie' %}
+ {% else %} +
+ + + +
{% endif %} @@ -100,6 +95,10 @@ {{ error.last_seen.strftime('%Y-%m-%d %H:%M') }}
{{ error.message }}
+ {% if error.source == 'missing_player' and error.message.startswith('Audycja ') %} + {% set program_slug = error.message.split(':', 1)[0].replace('Audycja ', '') %} + Otwórz odcinki audycji + {% endif %}
Powtórzenia: {{ error.occurrences }}
@@ -157,16 +156,16 @@
-
-
+
+
-
+
-
+
@@ -179,16 +178,16 @@
-
-
+
+
-
+
-
+