openvibers/openvibe.live Commits
Show guided personal quest on Live home (#817)
Changes
@@@ -48,7 +48,10 @@ async function readDailyQuest({ token = null, timeZone = 'UTC', more = false, feawait get('/api/v1/me/daily/time-zone', { method: 'PUT', headers: { 'Content-Type': 'application/json' },body: JSON.stringify({ time_zone: timeZone }) });}-- const [quest, extra] = await Promise.all([get('/api/v1/me/daily'), withMore({})]);++ // The guided reader carries this person's opaque step links. Older Quest deployments answer 404,++ // so keep the existing daily card until the guided release is enabled.++ const [guided, extra] = await Promise.all([get('/api/v1/quests/today'), withMore({})]);++ const quest = guided || await get('/api/v1/me/daily');if (!quest) return null;return { signed_in: true, quest, ...extra };} catch { return null; }@@@ -401,7 +401,7 @@ app.use(helmet({imgSrc: ["'self'", "data:", "blob:", "image.tmdb.org", "https://openvibe.network", "https://openvibe.media", "cdn.frankerfacez.com", "cdn.betterttv.net", "cdn.7tv.app", "https://files.kick.com", "https://i.ytimg.com", "https://img.youtube.com", "https://i.vimeocdn.com", "https://openvibe.community"], // paste screenshots (OpenVibe.Community owns pastes)// https://cloudflareinsights.com is where Cloudflare Web Analytics' beacon (script-src static.cloudflareinsights.com) reports.// https://openvibe.chat: the channel chat's feed card asks Chat which feed a slot shows (public/js/chat.js).-- connectSrc: ["'self'", "wss:", "https://openvibe.network", "https://openvibe.chat", "https://openvibe.events", "https://openvibe.media", "https://openvibe.games", "https://cdn.jsdelivr.net", "https://esm.sh", "https://static.cloudflareinsights.com", "https://cloudflareinsights.com", whipConnectSrc],++ connectSrc: ["'self'", "wss:", "https://openvibe.network", "https://openvibe.chat", "https://openvibe.quest", "https://openvibe.events", "https://openvibe.media", "https://openvibe.games", "https://cdn.jsdelivr.net", "https://esm.sh", "https://static.cloudflareinsights.com", "https://cloudflareinsights.com", whipConnectSrc],// VODs/clips play from openvibe.media (the /api proxies 302 there), which may// itself redirect to presigned B2/R2 object-store URLs or, for a B2 copy, to its// origin shield edge.openvibe.media — all must be allowed or the browser blocks@@@ -23,6 +23,12 @@ const { summarizeHistory } = require('../server/home/recent-facts');assert.equal(signedIn.quest.time_zone, 'America/Los_Angeles');assert.equal(signedIn.quest.progress, 1);assert.ok(calls.slice(1).every(c => c.options.headers.Authorization === 'Bearer person-token' && !('Cookie' in c.options.headers)));++ const guided = await readDailyQuest({ token: 'person-token', fetchImpl: async (url) => ({++ ok: url.endsWith('/api/v1/quests/today'),++ json: async () => ({ title: 'Made for you', steps: [{ guide_id: 'opaque-1' }, {}, {}], progress: 0 }),++ }) });++ assert.equal(guided.quest.title, 'Made for you');++ assert.equal(guided.quest.steps[0].guide_id, 'opaque-1');assert.equal(await readDailyQuest({ fetchImpl: async () => { throw Error('down'); } }), null);// The card's door to Quest: the catalog's size for everyone (kept ten minutes), a person's badges and started quests.
@@ -48,7 +48,10 @@ async function readDailyQuest({ token = null, timeZone = 'UTC', more = false, fe
@@ -48,7 +48,10 @@ async function readDailyQuest({ token = null, timeZone = 'UTC', more = false, fe
await get('/api/v1/me/daily/time-zone', { method: 'PUT', headers: { 'Content-Type': 'application/json' },
await get('/api/v1/me/daily/time-zone', { method: 'PUT', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ time_zone: timeZone }) });
body: JSON.stringify({ time_zone: timeZone }) });
}
}
- const [quest, extra] = await Promise.all([get('/api/v1/me/daily'), withMore({})]);
+ // The guided reader carries this person's opaque step links. Older Quest deployments answer 404,
+ // so keep the existing daily card until the guided release is enabled.
+ const [guided, extra] = await Promise.all([get('/api/v1/quests/today'), withMore({})]);
+ const quest = guided || await get('/api/v1/me/daily');
if (!quest) return null;
if (!quest) return null;
return { signed_in: true, quest, ...extra };
return { signed_in: true, quest, ...extra };
} catch { return null; }
} catch { return null; }
@@ -401,7 +401,7 @@ app.use(helmet({
@@ -401,7 +401,7 @@ app.use(helmet({
imgSrc: ["'self'", "data:", "blob:", "image.tmdb.org", "https://openvibe.network", "https://openvibe.media", "cdn.frankerfacez.com", "cdn.betterttv.net", "cdn.7tv.app", "https://files.kick.com", "https://i.ytimg.com", "https://img.youtube.com", "https://i.vimeocdn.com", "https://openvibe.community"], // paste screenshots (OpenVibe.Community owns pastes)
imgSrc: ["'self'", "data:", "blob:", "image.tmdb.org", "https://openvibe.network", "https://openvibe.media", "cdn.frankerfacez.com", "cdn.betterttv.net", "cdn.7tv.app", "https://files.kick.com", "https://i.ytimg.com", "https://img.youtube.com", "https://i.vimeocdn.com", "https://openvibe.community"], // paste screenshots (OpenVibe.Community owns pastes)
// https://cloudflareinsights.com is where Cloudflare Web Analytics' beacon (script-src static.cloudflareinsights.com) reports.
// https://cloudflareinsights.com is where Cloudflare Web Analytics' beacon (script-src static.cloudflareinsights.com) reports.
// https://openvibe.chat: the channel chat's feed card asks Chat which feed a slot shows (public/js/chat.js).
// https://openvibe.chat: the channel chat's feed card asks Chat which feed a slot shows (public/js/chat.js).
- connectSrc: ["'self'", "wss:", "https://openvibe.network", "https://openvibe.chat", "https://openvibe.events", "https://openvibe.media", "https://openvibe.games", "https://cdn.jsdelivr.net", "https://esm.sh", "https://static.cloudflareinsights.com", "https://cloudflareinsights.com", whipConnectSrc],
+ connectSrc: ["'self'", "wss:", "https://openvibe.network", "https://openvibe.chat", "https://openvibe.quest", "https://openvibe.events", "https://openvibe.media", "https://openvibe.games", "https://cdn.jsdelivr.net", "https://esm.sh", "https://static.cloudflareinsights.com", "https://cloudflareinsights.com", whipConnectSrc],
// VODs/clips play from openvibe.media (the /api proxies 302 there), which may
// VODs/clips play from openvibe.media (the /api proxies 302 there), which may
// itself redirect to presigned B2/R2 object-store URLs or, for a B2 copy, to its
// itself redirect to presigned B2/R2 object-store URLs or, for a B2 copy, to its
// origin shield edge.openvibe.media — all must be allowed or the browser blocks
// origin shield edge.openvibe.media — all must be allowed or the browser blocks
@@ -23,6 +23,12 @@ const { summarizeHistory } = require('../server/home/recent-facts');
@@ -23,6 +23,12 @@ const { summarizeHistory } = require('../server/home/recent-facts');
assert.equal(signedIn.quest.time_zone, 'America/Los_Angeles');
assert.equal(signedIn.quest.time_zone, 'America/Los_Angeles');
assert.equal(signedIn.quest.progress, 1);
assert.equal(signedIn.quest.progress, 1);
assert.ok(calls.slice(1).every(c => c.options.headers.Authorization === 'Bearer person-token' && !('Cookie' in c.options.headers)));
assert.ok(calls.slice(1).every(c => c.options.headers.Authorization === 'Bearer person-token' && !('Cookie' in c.options.headers)));
+ const guided = await readDailyQuest({ token: 'person-token', fetchImpl: async (url) => ({
+ ok: url.endsWith('/api/v1/quests/today'),
+ json: async () => ({ title: 'Made for you', steps: [{ guide_id: 'opaque-1' }, {}, {}], progress: 0 }),
+ }) });
+ assert.equal(guided.quest.title, 'Made for you');
+ assert.equal(guided.quest.steps[0].guide_id, 'opaque-1');
assert.equal(await readDailyQuest({ fetchImpl: async () => { throw Error('down'); } }), null);
assert.equal(await readDailyQuest({ fetchImpl: async () => { throw Error('down'); } }), null);
// The card's door to Quest: the catalog's size for everyone (kept ten minutes), a person's badges and started quests.
// The card's door to Quest: the catalog's size for everyone (kept ten minutes), a person's badges and started quests.