openvibers/openvibe.live Commits

Screenshot paste fallbacks link the screenshot directly, without the /raw hop; pasteRawUrl removed (#27)

OP OpenVibers committed 5 Oct 2026 · 3538ab0231 · 4 files, +13 −4

## Changes

**1. Chat paste share — skipped.** Live no longer builds this URL. Production Live runs `CHAT_AUTHORITY=chat` (`server/chat/chat-authority.js:20`, `server/chat/chat-server.js:2648` exports `RemoteChatServer`, which never serves sockets), so `/ws/chat` and the `/paste` command are handled by **OpenVibe.Chat**, whose `~/OpenVibers/OpenVibe.Chat/server/chat/chat-server.js:1793-1797` builds `${siteUrl}/p/${paste.slug}`. Live's `server/chat/chat-server.js:1619-1620` survives only as the `CHAT_AUTHORITY` rollback path (unreachable in production), so per the prompt I left it untouched. If that Live-origin share URL should be fixed, the edit belongs in OpenVibe.Chat, not this checkout.

**2. Screenshot fallbacks:**
- `server/home/routes.js:70` — `_pasteThumb` screenshot fallback now calls `media.pasteScreenshotUrl(slug)`.
- `server/auth/routes.js:223` — avatar screenshot fallback now calls `media.pasteScreenshotUrl(paste.slug)`.
- `server/media-client.js` — deleted `pasteRawUrl` (was `:308`) and dropped it from the exports (`:419`); no remaining references in `server/`, `public/`, `test/`.
- `test/paste-canonical.test.js:107` — added assertion that `pasteRawUrl` is gone, `pasteScreenshotUrl('a b')` is `<MEDIA_PUBLIC_URL>/p/a%20b/screenshot`, and both routes fall back to it.

## Tests

`ov test test/paste-canonical.test.js test/pastes-community.test.js test/content-feed.test.js test/frozen-tables.test.js` → **4 passed in 7 s** (content-feed, frozen-tables, paste-canonical, pastes-community).

No commit or push performed.

Changes

ddiff --git a/server/auth/routes.js b/server/auth/routes.js
iindex 66a3a521..d36edf11 100644
---- a/server/auth/routes.js
++++ b/server/auth/routes.js
@@@ -220,7 +220,7 @@ router.post('/avatar', requireAuth, avatarUpload.single('avatar'), async (req, r
contentType: req.file.mimetype || 'image/png',
},
});
-- const screenshotUrl = media.publicUrl(paste.screenshot_url) || media.pasteRawUrl(paste.slug);
++ const screenshotUrl = media.publicUrl(paste.screenshot_url) || media.pasteScreenshotUrl(paste.slug);
db.updateUserAvatar(req.user.id, screenshotUrl, paste.id || null);
const updated = db.getUserById(req.user.id);
ddiff --git a/server/home/routes.js b/server/home/routes.js
iindex 4b42dbac..bde0f3cf 100644
---- a/server/home/routes.js
++++ b/server/home/routes.js
@@@ -67,7 +67,7 @@ async function _mediaContent() {
function _pasteThumb(p) {
if (p.screenshot_url) return media.publicUrl(p.screenshot_url);
-- if (p.type === 'screenshot' && p.slug) return media.pasteRawUrl(p.slug);
++ if (p.type === 'screenshot' && p.slug) return media.pasteScreenshotUrl(p.slug);
return null;
}
ddiff --git a/server/media-client.js b/server/media-client.js
iindex abe247bd..40b911f1 100644
---- a/server/media-client.js
++++ b/server/media-client.js
@@@ -305,7 +305,6 @@ function generateThumbnail(kind, id, opts = {}) {
function vodPlaybackUrl(id) { return `${MEDIA_PUBLIC_URL}/v/${id}`; }
function clipUrl(id) { return `${MEDIA_PUBLIC_URL}/c/${id}`; }
function pasteScreenshotUrl(slug) { return `${MEDIA_PUBLIC_URL}/p/${encodeURIComponent(slug)}/screenshot`; }
--function pasteRawUrl(slug) { return `${MEDIA_PUBLIC_URL}/p/${encodeURIComponent(slug)}/raw`; }
function thumbUrl(id) { return `${MEDIA_PUBLIC_URL}/t/${id}`; }
function fileUrl(key) { return `${MEDIA_PUBLIC_URL}/f/${key}`; }
// TODO(contract): paste screenshots have no explicit public route in the contract;
@@@ -417,5 +416,5 @@ module.exports = {
uploadFile, getFileMeta, deleteFile,
uploadThumbnail, generateThumbnail,
// URL builders
-- vodPlaybackUrl, clipUrl, pasteScreenshotUrl, pasteRawUrl, thumbUrl, fileUrl, screenshotUrl, publicUrl,
++ vodPlaybackUrl, clipUrl, pasteScreenshotUrl, thumbUrl, fileUrl, screenshotUrl, publicUrl,
};
ddiff --git a/test/paste-canonical.test.js b/test/paste-canonical.test.js
iindex d0ef618e..96874b01 100644
---- a/test/paste-canonical.test.js
++++ b/test/paste-canonical.test.js
@@@ -104,6 +104,16 @@ const server = http.createServer(app).listen(0, '127.0.0.1', async () => {
assert.ok(/MEDIA_PUBLIC_URL\}\/p\/\$\{encodeURIComponent\(req\.params\.slug\)\}\/screenshot/.test(src), 'screenshot bytes still on Media');
});
++ await check('screenshot fallbacks use Media\'s screenshot URL, not the /raw hop', () => {
++ assert.strictEqual(typeof media.pasteRawUrl, 'undefined', 'the /raw URL builder is gone');
++ assert.strictEqual(media.pasteScreenshotUrl('a b'), `${media.MEDIA_PUBLIC_URL}/p/a%20b/screenshot`);
++ for (const rel of ['server/home/routes.js', 'server/auth/routes.js']) {
++ const src = fs.readFileSync(path.join(__dirname, '..', rel), 'utf8');
++ assert.ok(/pasteScreenshotUrl\(/.test(src), `${rel} falls back to the screenshot URL`);
++ assert.ok(!/pasteRawUrl/.test(src), `${rel} no longer takes the /raw hop`);
++ }
++ });
++
await check('Live\'s sitemap lists no paste', async () => {
const xml = await seo.buildSitemap();
assert.ok(!/<loc>[^<]*\/p\//.test(xml), 'a /p/ URL in the sitemap');