TV station tabs + per-station Nextcloud upload target

User feedback: 'Sarah Connor in Abracadabra grejo v ONE DE, ne v FOLX SLO.
Naredi zavihke za vsako TV postajo (FOLX SLO, FOLX DE, ONE DE, ZWEI MUSIC, ADRIA)
in upload gre v ustrezno Nextcloud podmapo.'

Backend changes:
- StartJobIn + YouTubeJobIn: nov field 'tv_station' (default 'FOLX SLOVENIJA')
- update_job: shrani tv_station v job JSON
- POST /api/jobs/{id}/upload-nextcloud:
  bere tv_station iz job, target_subdir = folxspeed/REELS/{station}

Frontend changes:
- 5 TV station tabs: FOLX SLOVENIJA (active), FOLX DE, ONE DE, ZWEI MUSIC, ADRIA
- Hidden input #tv-station-input drži current selection
- Klik na tab ga aktivira (accent color)
- collectSettings() vključuje tv_station

Manual fix: Sarah Connor in Abracadabra job.json popravljena → tv_station=ONE DE
Reset njihovih nextcloud_* polj da bo upload v pravo mapo.
This commit is contained in:
Sebastjan Artič 2026-04-30 14:38:45 +00:00
parent 8284181fb3
commit 1c11dfe630
2 changed files with 42 additions and 5 deletions

View File

@ -1008,6 +1008,7 @@ class YouTubeJobIn(BaseModel):
subtitle_style: str = "reels"
whisper_model: str = "large-v3"
quality: str = "medium"
tv_station: str = "FOLX SLOVENIJA" # za Nextcloud target mapo
class StartJobIn(BaseModel):
@ -1031,6 +1032,8 @@ class StartJobIn(BaseModel):
whisper_provider: str = "auto" # auto / elevenlabs / local
# Batch tracking za multi-upload (Telegram summary)
batch_id: Optional[str] = None
# TV postaja — določa Nextcloud target mapo
tv_station: str = "FOLX SLOVENIJA"
# ────────────────────────────────────────────────────────────────
@ -1160,6 +1163,7 @@ async def start_processing(
llm_model=payload.llm_model,
whisper_provider=payload.whisper_provider,
batch_id=payload.batch_id,
tv_station=payload.tv_station,
current_step="V vrsti za obdelavo",
# Počisti pretekle napake (retry-friendly)
chorus_error=None,
@ -1592,7 +1596,7 @@ def _nextcloud_upload(local_path: str, remote_filename: str, target_subdir: str
@app.post("/api/jobs/{job_id}/upload-nextcloud")
async def upload_nextcloud(job_id: str, user: str = Depends(check_auth)):
"""Naloži dokončan reel na Nextcloud /folxspeed/REELS/FOLX SLOVENIJA/."""
"""Naloži dokončan reel na Nextcloud /folxspeed/REELS/{TV STATION}/."""
if not _nextcloud_configured():
raise HTTPException(500, "Nextcloud ni konfiguriran (manjka env vars)")
@ -1613,13 +1617,17 @@ async def upload_nextcloud(job_id: str, user: str = Depends(check_auth)):
# Lepo ime datoteke
download_name = build_download_filename(job)
print(f"☁️ Uploading {output_path} → Nextcloud as {download_name}", flush=True)
success, result = _nextcloud_upload(output_path, download_name)
# TV postaja določa target mapo
tv_station = job.get("tv_station", "FOLX SLOVENIJA")
target_subdir = f"folxspeed/REELS/{tv_station}"
print(f"☁️ Uploading {output_path} → Nextcloud /{target_subdir}/{download_name}", flush=True)
success, result = _nextcloud_upload(output_path, download_name, target_subdir=target_subdir)
if success:
update_job(job_id, nextcloud_status="uploaded", nextcloud_url=result, nextcloud_error=None)
print(f"☁️ Upload OK: {download_name}", flush=True)
return {"ok": True, "url": result, "filename": download_name}
print(f"☁️ Upload OK: /{target_subdir}/{download_name}", flush=True)
return {"ok": True, "url": result, "filename": download_name, "tv_station": tv_station}
else:
update_job(job_id, nextcloud_status="error", nextcloud_error=result)
raise HTTPException(500, f"Upload failed: {result}")

View File

@ -344,6 +344,17 @@
<input type="url" id="yt-url" placeholder="https://www.youtube.com/watch?v=...">
</div>
<!-- TV postaja: določa Nextcloud target mapo -->
<label style="margin-top:8px;">📺 TV postaja (določa kam gre na Nextcloud)</label>
<div class="tv-station-tabs" style="display:flex; flex-wrap:wrap; gap:6px; margin-bottom:14px;">
<button type="button" class="tv-tab active" data-station="FOLX SLOVENIJA" style="padding:6px 12px; border:1px solid var(--accent); background:var(--accent); color:#fff; border-radius:4px; cursor:pointer; font-size:13px;">🇸🇮 FOLX SLOVENIJA</button>
<button type="button" class="tv-tab" data-station="FOLX DE" style="padding:6px 12px; border:1px solid #444; background:transparent; color:#ccc; border-radius:4px; cursor:pointer; font-size:13px;">🇩🇪 FOLX DE</button>
<button type="button" class="tv-tab" data-station="ONE DE" style="padding:6px 12px; border:1px solid #444; background:transparent; color:#ccc; border-radius:4px; cursor:pointer; font-size:13px;">🇩🇪 ONE DE</button>
<button type="button" class="tv-tab" data-station="ZWEI MUSIC" style="padding:6px 12px; border:1px solid #444; background:transparent; color:#ccc; border-radius:4px; cursor:pointer; font-size:13px;">🎵 ZWEI MUSIC</button>
<button type="button" class="tv-tab" data-station="ADRIA" style="padding:6px 12px; border:1px solid #444; background:transparent; color:#ccc; border-radius:4px; cursor:pointer; font-size:13px;">🌊 ADRIA</button>
</div>
<input type="hidden" id="tv-station-input" value="FOLX SLOVENIJA">
<label>Način reframe</label>
<select id="mode">
<option value="track">Track (sledi obrazu — intervjuji, vlogi)</option>
@ -609,8 +620,26 @@
quality: $("#quality").value,
no_subs: $("#no-subs").checked,
llm_provider: $("#llm-provider").value,
tv_station: $("#tv-station-input").value || "FOLX SLOVENIJA",
};
}
// ─── TV station tabs ─────────────────────────
document.querySelectorAll(".tv-tab").forEach(btn => {
btn.addEventListener("click", () => {
document.querySelectorAll(".tv-tab").forEach(b => {
b.classList.remove("active");
b.style.background = "transparent";
b.style.color = "#ccc";
b.style.borderColor = "#444";
});
btn.classList.add("active");
btn.style.background = "var(--accent)";
btn.style.color = "#fff";
btn.style.borderColor = "var(--accent)";
$("#tv-station-input").value = btn.dataset.station;
});
});
function parseTimestamp(s) {
s = s.trim();