openvibers/openvibe.mediahub Commits
An upload with a short description gets a meta description that says what the video is (#280)
Changes
@@@ -267,11 +267,19 @@ ${fresh.map((x) => html`<tr><td><a href="/u/${x.id}">${x.title}</a></td><td>${stconst reel = cutsOn ? await ctx.videoCuts.highlightsPlan(row) : null;const original = own && row.edited_from ? await up.byId(row.edited_from) : null;if (cutBusy) res.set('Refresh', '15');++ // The description search results and share cards show: the uploader's own words when they say enough. A short one++ // ("Wheeeee", SEO audit 11-03) is kept and followed by the AI's overview when there is one, or by who made the++ // video, when and how long it is, so the snippet says what the page is.++ const said = String(row.description || '').trim();++ const { lengthWords, dayLabel } = require('./watch-ui');++ const madeBy = `A video by @${channel || 'someone'} on OpenVibe.Video${dayLabel(row.created_at) ? `, uploaded ${dayLabel(row.created_at)}` : ''}${lengthWords(row.duration_seconds) ? `, ${lengthWords(row.duration_seconds)} long` : ''}.`;++ const about = said.length >= 50 ? said.slice(0, 300)++ : [said ? `${said.replace(/[\s.!?…]+$/u, '')}.` : '', aiDone && ai.overview ? String(ai.overview).trim() : madeBy].filter(Boolean).join(' ').slice(0, 300);return page(req, res, {index: listed, noindex: !listed,...(listed ? {} : { cache: cache.htmlHeaders({ private: true }) }),title: row.title,-- description: row.description ? row.description.slice(0, 300) : `A video by @${channel || 'someone'} on OpenVibe.Video.`,++ description: about,...(listed && thumb ? { image: thumb, ogType: 'video.other' } : {}),scripts: ready ? ['js/video.js'] : [],player: !!(ready && vod),@@@ -145,6 +145,14 @@ function vreq(base, path, { method = 'GET', cookie, form, json, body, same = truawait vreq(t.base, `/u/${id}/manage`, { method: 'POST', cookie: kimCookie, form: { title: 'Coast trip', visibility: 'public' } });});++ await check('a short description is kept, and the meta description says what the video is (SEO audit 11-03)', async () => {++ const page = (await vreq(t.base, `/u/${id}`)).text;++ const m = page.match(/<meta name="description" content="([^"]*)"/);++ assert.ok(m, 'a meta description');++ assert.ok(m[1].startsWith('x. '), `the uploader's own word first (${m[1]})`);++ assert.ok(m[1].length >= 50 && m[1].length <= 300, `long enough for a search result (${m[1].length})`);++ });++await check('a child-safety report hides it at once; one report per person; the owner sees why', async () => {const r = await vreq(t.base, `/u/${id}/report`, { method: 'POST', cookie: samCookie, form: { reason: 'child_safety', note: 'look at 0:12' } });assert.strictEqual(r.status, 303);
@@ -267,11 +267,19 @@ ${fresh.map((x) => html`<tr><td><a href="/u/${x.id}">${x.title}</a></td><td>${st
@@ -267,11 +267,19 @@ ${fresh.map((x) => html`<tr><td><a href="/u/${x.id}">${x.title}</a></td><td>${st
const reel = cutsOn ? await ctx.videoCuts.highlightsPlan(row) : null;
const reel = cutsOn ? await ctx.videoCuts.highlightsPlan(row) : null;
const original = own && row.edited_from ? await up.byId(row.edited_from) : null;
const original = own && row.edited_from ? await up.byId(row.edited_from) : null;
if (cutBusy) res.set('Refresh', '15');
if (cutBusy) res.set('Refresh', '15');
+ // The description search results and share cards show: the uploader's own words when they say enough. A short one
+ // ("Wheeeee", SEO audit 11-03) is kept and followed by the AI's overview when there is one, or by who made the
+ // video, when and how long it is, so the snippet says what the page is.
+ const said = String(row.description || '').trim();
+ const { lengthWords, dayLabel } = require('./watch-ui');
+ const madeBy = `A video by @${channel || 'someone'} on OpenVibe.Video${dayLabel(row.created_at) ? `, uploaded ${dayLabel(row.created_at)}` : ''}${lengthWords(row.duration_seconds) ? `, ${lengthWords(row.duration_seconds)} long` : ''}.`;
+ const about = said.length >= 50 ? said.slice(0, 300)
+ : [said ? `${said.replace(/[\s.!?…]+$/u, '')}.` : '', aiDone && ai.overview ? String(ai.overview).trim() : madeBy].filter(Boolean).join(' ').slice(0, 300);
return page(req, res, {
return page(req, res, {
index: listed, noindex: !listed,
index: listed, noindex: !listed,
...(listed ? {} : { cache: cache.htmlHeaders({ private: true }) }),
...(listed ? {} : { cache: cache.htmlHeaders({ private: true }) }),
title: row.title,
title: row.title,
- description: row.description ? row.description.slice(0, 300) : `A video by @${channel || 'someone'} on OpenVibe.Video.`,
+ description: about,
...(listed && thumb ? { image: thumb, ogType: 'video.other' } : {}),
...(listed && thumb ? { image: thumb, ogType: 'video.other' } : {}),
scripts: ready ? ['js/video.js'] : [],
scripts: ready ? ['js/video.js'] : [],
player: !!(ready && vod),
player: !!(ready && vod),
@@ -145,6 +145,14 @@ function vreq(base, path, { method = 'GET', cookie, form, json, body, same = tru
@@ -145,6 +145,14 @@ function vreq(base, path, { method = 'GET', cookie, form, json, body, same = tru
await vreq(t.base, `/u/${id}/manage`, { method: 'POST', cookie: kimCookie, form: { title: 'Coast trip', visibility: 'public' } });
await vreq(t.base, `/u/${id}/manage`, { method: 'POST', cookie: kimCookie, form: { title: 'Coast trip', visibility: 'public' } });
});
});
+ await check('a short description is kept, and the meta description says what the video is (SEO audit 11-03)', async () => {
+ const page = (await vreq(t.base, `/u/${id}`)).text;
+ const m = page.match(/<meta name="description" content="([^"]*)"/);
+ assert.ok(m, 'a meta description');
+ assert.ok(m[1].startsWith('x. '), `the uploader's own word first (${m[1]})`);
+ assert.ok(m[1].length >= 50 && m[1].length <= 300, `long enough for a search result (${m[1].length})`);
+ });
+
await check('a child-safety report hides it at once; one report per person; the owner sees why', async () => {
await check('a child-safety report hides it at once; one report per person; the owner sees why', async () => {
const r = await vreq(t.base, `/u/${id}/report`, { method: 'POST', cookie: samCookie, form: { reason: 'child_safety', note: 'look at 0:12' } });
const r = await vreq(t.base, `/u/${id}/report`, { method: 'POST', cookie: samCookie, form: { reason: 'child_safety', note: 'look at 0:12' } });
assert.strictEqual(r.status, 303);
assert.strictEqual(r.status, 303);