openvibers/openvibe.live Commits
Search suggestions: one per type and title (many VODs share a title), the best-ranked
Changes
@@@ -60,7 +60,17 @@ function createSearchRouter({ fetchImpl = globalThis.fetch, baseUrl = SEARCH_URLconst r = await fetchImpl(`${baseUrl}/api/v1/suggest?${params}`, { headers: { accept: 'application/json' }, signal: AbortSignal.timeout(2000) });const body = r.ok ? await r.json().catch(() => null) : null;const list = body && Array.isArray(body.suggestions) ? body.suggestions : [];-- res.json({ suggestions: list.filter((s) => s && TYPES.has(s.type) && s.title).map((s) => ({ type: s.type, id: s.id, title: s.title, canonical_url: s.canonical_url })) });++ // Many VODs share a title ("<name>'s Stream"): one suggestion per type and title, the best-ranked.++ const seen = new Set();++ const out = [];++ for (const s of list) {++ if (!s || !TYPES.has(s.type) || !s.title) continue;++ const key = `${s.type}\u0000${String(s.title).toLowerCase()}`;++ if (seen.has(key)) continue;++ seen.add(key);++ out.push({ type: s.type, id: s.id, title: s.title, canonical_url: s.canonical_url });++ }++ res.json({ suggestions: out });} catch {res.json({ suggestions: [] }); // typing never shows an error; submitting does}@@@ -19,7 +19,7 @@ const { createSearchRouter } = require('../server/search/routes');const u = new URL(url);if (u.pathname === '/api/v1/suggest') {if (mode === 'suggest-down') throw new Error('timeout');-- return new Response(JSON.stringify({ suggestions: [{ owner: 'live', type: 'channel', id: '7', title: 'Forum builders', canonical_url: 'https://openvibe.live/@forum' }, { owner: 'community', type: 'thread', id: 'x', title: 'Not ours' }] }), { status: 200 });++ return new Response(JSON.stringify({ suggestions: [{ owner: 'live', type: 'channel', id: '7', title: 'Forum builders', canonical_url: 'https://openvibe.live/@forum' }, { owner: 'community', type: 'thread', id: 'x', title: 'Not ours' }, { owner: 'live', type: 'channel', id: '8', title: 'forum builders', canonical_url: 'https://openvibe.live/@forum2' }] }), { status: 200 });}const facets = u.searchParams.get('facets') ? { facets: { category: [{ value: 'irl', count: 12 }, { value: 'gaming', count: 3 }], channel: [{ value: 'alex', count: 9 }, { value: 42, count: 1 }], secret: [{ value: 'x', count: 1 }] } } : {};return new Response(JSON.stringify({ ...facets, results: [{ owner: 'live', type: 'vod', id: '912', title: 'Building a forum', canonical_url: 'https://openvibe.live/vod/912', facets: { channel: 'alex' }, snippet_html: '<mark>forum</mark>', acl: ['secret'], revision: 3 }], next_cursor: 'c1' }), { status: 200 });
@@ -60,7 +60,17 @@ function createSearchRouter({ fetchImpl = globalThis.fetch, baseUrl = SEARCH_URL
@@ -60,7 +60,17 @@ function createSearchRouter({ fetchImpl = globalThis.fetch, baseUrl = SEARCH_URL
const r = await fetchImpl(`${baseUrl}/api/v1/suggest?${params}`, { headers: { accept: 'application/json' }, signal: AbortSignal.timeout(2000) });
const r = await fetchImpl(`${baseUrl}/api/v1/suggest?${params}`, { headers: { accept: 'application/json' }, signal: AbortSignal.timeout(2000) });
const body = r.ok ? await r.json().catch(() => null) : null;
const body = r.ok ? await r.json().catch(() => null) : null;
const list = body && Array.isArray(body.suggestions) ? body.suggestions : [];
const list = body && Array.isArray(body.suggestions) ? body.suggestions : [];
- res.json({ suggestions: list.filter((s) => s && TYPES.has(s.type) && s.title).map((s) => ({ type: s.type, id: s.id, title: s.title, canonical_url: s.canonical_url })) });
+ // Many VODs share a title ("<name>'s Stream"): one suggestion per type and title, the best-ranked.
+ const seen = new Set();
+ const out = [];
+ for (const s of list) {
+ if (!s || !TYPES.has(s.type) || !s.title) continue;
+ const key = `${s.type}\u0000${String(s.title).toLowerCase()}`;
+ if (seen.has(key)) continue;
+ seen.add(key);
+ out.push({ type: s.type, id: s.id, title: s.title, canonical_url: s.canonical_url });
+ }
+ res.json({ suggestions: out });
} catch {
} catch {
res.json({ suggestions: [] }); // typing never shows an error; submitting does
res.json({ suggestions: [] }); // typing never shows an error; submitting does
}
}
@@ -19,7 +19,7 @@ const { createSearchRouter } = require('../server/search/routes');
@@ -19,7 +19,7 @@ const { createSearchRouter } = require('../server/search/routes');
const u = new URL(url);
const u = new URL(url);
if (u.pathname === '/api/v1/suggest') {
if (u.pathname === '/api/v1/suggest') {
if (mode === 'suggest-down') throw new Error('timeout');
if (mode === 'suggest-down') throw new Error('timeout');
- return new Response(JSON.stringify({ suggestions: [{ owner: 'live', type: 'channel', id: '7', title: 'Forum builders', canonical_url: 'https://openvibe.live/@forum' }, { owner: 'community', type: 'thread', id: 'x', title: 'Not ours' }] }), { status: 200 });
+ return new Response(JSON.stringify({ suggestions: [{ owner: 'live', type: 'channel', id: '7', title: 'Forum builders', canonical_url: 'https://openvibe.live/@forum' }, { owner: 'community', type: 'thread', id: 'x', title: 'Not ours' }, { owner: 'live', type: 'channel', id: '8', title: 'forum builders', canonical_url: 'https://openvibe.live/@forum2' }] }), { status: 200 });
}
}
const facets = u.searchParams.get('facets') ? { facets: { category: [{ value: 'irl', count: 12 }, { value: 'gaming', count: 3 }], channel: [{ value: 'alex', count: 9 }, { value: 42, count: 1 }], secret: [{ value: 'x', count: 1 }] } } : {};
const facets = u.searchParams.get('facets') ? { facets: { category: [{ value: 'irl', count: 12 }, { value: 'gaming', count: 3 }], channel: [{ value: 'alex', count: 9 }, { value: 42, count: 1 }], secret: [{ value: 'x', count: 1 }] } } : {};
return new Response(JSON.stringify({ ...facets, results: [{ owner: 'live', type: 'vod', id: '912', title: 'Building a forum', canonical_url: 'https://openvibe.live/vod/912', facets: { channel: 'alex' }, snippet_html: '<mark>forum</mark>', acl: ['secret'], revision: 3 }], next_cursor: 'c1' }), { status: 200 });
return new Response(JSON.stringify({ ...facets, results: [{ owner: 'live', type: 'vod', id: '912', title: 'Building a forum', canonical_url: 'https://openvibe.live/vod/912', facets: { channel: 'alex' }, snippet_html: '<mark>forum</mark>', acl: ['secret'], revision: 3 }], next_cursor: 'c1' }), { status: 200 });