Qnet match v upload queue — auto-prepoznavanje pesmi takoj ko izbere\u0161 fajle (parallel POST /api/qnet/match-batch). \u010ce baza prepozna komad, prikaz Artist \u2014 Title z station badge namesto 'Brez razvidnega imena'.
This commit is contained in:
parent
b938d1e4d8
commit
24e1b53aa8
21
app/main.py
21
app/main.py
@ -1772,6 +1772,27 @@ async def qnet_match_filename(filename: str, user: str = Depends(check_auth)):
|
||||
return qnet_match.match_filename(filename)
|
||||
|
||||
|
||||
class QnetBatchMatchRequest(BaseModel):
|
||||
filenames: list[str]
|
||||
min_confidence: float = 0.85
|
||||
|
||||
|
||||
@app.post("/api/qnet/match-batch")
|
||||
async def qnet_match_batch(payload: QnetBatchMatchRequest, user: str = Depends(check_auth)):
|
||||
"""Batch match — kliče client ob izbiri datotek za live preview v queue."""
|
||||
results = {}
|
||||
for fn in payload.filenames:
|
||||
if not fn:
|
||||
continue
|
||||
r = qnet_match.match_filename(fn)
|
||||
# Vrni samo zadetke nad minimum confidence; sicer null
|
||||
if r["matched"] and r["confidence"] >= payload.min_confidence:
|
||||
results[fn] = r
|
||||
else:
|
||||
results[fn] = None
|
||||
return {"results": results}
|
||||
|
||||
|
||||
@app.post("/api/qnet/sync")
|
||||
async def qnet_sync(background: BackgroundTasks, user: str = Depends(check_auth)):
|
||||
"""Sproži sync (fetch Songs.txt iz vseh playerjev). Async background task."""
|
||||
|
||||
@ -504,28 +504,45 @@
|
||||
const newItems = [];
|
||||
for (const f of files) {
|
||||
const [artist, title] = parseArtistTitle(f.name);
|
||||
newItems.push({ file: f, artist, title, dedup: null });
|
||||
newItems.push({ file: f, artist, title, dedup: null, qnetMatch: null });
|
||||
}
|
||||
|
||||
// Dedup check pred dodanjem v queue
|
||||
const filenames = newItems.map(i => i.file.name);
|
||||
const tvStation = $("#tv-station-input").value || "FOLX SLOVENIJA";
|
||||
try {
|
||||
const r = await fetch("/api/dedup/check", {
|
||||
|
||||
// Vzporedno: dedup check + Qnet match (oba endpointa, neodvisna)
|
||||
const [dedupRes, qnetRes] = await Promise.all([
|
||||
fetch("/api/dedup/check", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ filenames: newItems.map(i => i.file.name), tv_station: tvStation }),
|
||||
});
|
||||
if (r.ok) {
|
||||
const data = await r.json();
|
||||
body: JSON.stringify({ filenames, tv_station: tvStation }),
|
||||
}).then(r => r.ok ? r.json() : null).catch(e => { console.warn("Dedup check failed:", e); return null; }),
|
||||
fetch("/api/qnet/match-batch", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ filenames, min_confidence: 0.85 }),
|
||||
}).then(r => r.ok ? r.json() : null).catch(e => { console.warn("Qnet match failed:", e); return null; }),
|
||||
]);
|
||||
|
||||
// Apply dedup
|
||||
if (dedupRes && dedupRes.results) {
|
||||
newItems.forEach(item => {
|
||||
const match = data.results[item.file.name];
|
||||
if (match) {
|
||||
item.dedup = match; // {normalized_name, tv_station, filename_orig, job_id, nextcloud_url, file_size_mb, uploaded_at}
|
||||
}
|
||||
const m = dedupRes.results[item.file.name];
|
||||
if (m) item.dedup = m;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("Dedup check failed:", e);
|
||||
|
||||
// Apply Qnet match — če baza prepozna komad, prepiši artist+title
|
||||
if (qnetRes && qnetRes.results) {
|
||||
newItems.forEach(item => {
|
||||
const m = qnetRes.results[item.file.name];
|
||||
if (m && m.matched) {
|
||||
item.qnetMatch = m;
|
||||
// Auto-fill artist+title iz Qnet baze (clean podatki)
|
||||
item.artist = m.artist;
|
||||
item.title = m.title;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pendingFiles.push(...newItems);
|
||||
@ -579,7 +596,14 @@
|
||||
div.className = "file-queue-item";
|
||||
const sizeMB = (item.file.size / 1024 / 1024).toFixed(1);
|
||||
let nameHtml;
|
||||
if (item.artist && item.title) {
|
||||
if (item.qnetMatch) {
|
||||
// Prepoznano iz Qnet player baze — clean artist+title + station badge
|
||||
const m = item.qnetMatch;
|
||||
const stationBadge = `<span style="font-size:9px; padding:1px 5px; background:rgba(74,222,128,0.18); border:1px solid rgba(74,222,128,0.5); border-radius:3px; color:#4ade80; font-weight:600; margin-left:6px; vertical-align:middle;">${escapeHtml(m.station)}</span>`;
|
||||
const confLabel = m.confidence >= 0.95 ? "" : ` <span style="color:var(--muted); font-size:10px;">(${Math.round(m.confidence*100)}%)</span>`;
|
||||
nameHtml = `<b>${escapeHtml(m.artist)} — ${escapeHtml(m.title)}</b>${stationBadge}` +
|
||||
`<div style="font-size:10px;color:var(--muted)">🎵 prepoznano iz Qnet baze${confLabel} · ${escapeHtml(item.file.name)}</div>`;
|
||||
} else if (item.artist && item.title) {
|
||||
nameHtml = `<b>${escapeHtml(item.artist)} — ${escapeHtml(item.title)}</b>` +
|
||||
`<div style="font-size:10px;color:var(--muted)">${escapeHtml(item.file.name)}</div>`;
|
||||
} else {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user