Changeset 1d6f9a2 in Klonkt
- Timestamp:
- 06/30/2026 05:29:01 PM (2 months ago)
- Branches:
- main
- Children:
- b5a09ce2
- Parents:
- ecbfa41
- Location:
- src
- Files:
-
- 2 edited
-
config/database.js (modified) (1 diff)
-
routes/posts.js (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/config/database.js
recbfa41 r1d6f9a2 84 84 ensureColumn('posts', 'fan_only', 'INTEGER DEFAULT 0'); // fan-only preview (premium #3) 85 85 ensureColumn('posts', 'nsfw', 'INTEGER DEFAULT 0'); // sensitive content → blur + click-to-reveal; fediverse sensitive 86 ensureColumn('posts', 'cover_video_url', 'TEXT'); // muted loop MP4 for an animated cover (Safari-smooth) 86 87 ensureColumn('posts', 'content_warning', 'TEXT'); // custom CW label (empty = default "Gevoelige inhoud") 87 88 ensureColumn('posts', 'type', "TEXT DEFAULT 'post'"); // post | foto | video | audio -
src/routes/posts.js
recbfa41 r1d6f9a2 18 18 import { audioUrl } from '../services/AudioStreamService.js'; 19 19 import { toWebp } from '../services/ImageWebpService.js'; 20 import VideoCoverService from '../services/VideoCoverService.js'; 20 21 import ActivityPubService from '../services/ActivityPubService.js'; 21 22 import MusicMeta from '../services/MusicMeta.js'; … … 72 73 // insert a markdown  into content. 73 74 router.post('/posts/upload-image', requireAuth, (req, res) => { 74 imageUpload.single('image')(req, res, (err) => {75 imageUpload.single('image')(req, res, async (err) => { 75 76 if (err) return res.status(400).json({ error: err.message }); 76 77 if (!req.file) return res.status(400).json({ error: 'No file' }); 77 const url = '/media/post-images/' + toWebp(req.file); 78 res.json({ url, size: req.file.size, mime: req.file.mimetype }); 78 const name = toWebp(req.file); 79 const url = '/media/post-images/' + name; 80 // An animated WebP cover → also make a muted loop MP4 (Safari plays it smoothly where the 81 // animated WebP is janky on iOS). Best-effort; on failure we just return the still image. 82 // The editor stores `video` in the hidden cover_video_url field for the cover. 83 let video = null; 84 try { 85 const src = path.join(POST_IMAGES_DIR, name); 86 if (VideoCoverService.isAnimatedWebp(src)) { 87 const r = await VideoCoverService.animatedWebpToVideo(src, POST_IMAGES_DIR, path.basename(name, path.extname(name)) + '-v'); 88 if (r) video = '/media/post-images/' + path.basename(r.videoPath); 89 } 90 } catch { /* keep the still image */ } 91 res.json({ url, video, size: req.file.size, mime: req.file.mimetype }); 79 92 }); 80 93 }); … … 245 258 INSERT INTO posts ( 246 259 id, site_id, slug, author_id, title, content, excerpt, 247 status, cover_image_url, pinned, tags, type, noindex, fan_only, nsfw, content_warning, publish_at,260 status, cover_image_url, cover_video_url, pinned, tags, type, noindex, fan_only, nsfw, content_warning, publish_at, 248 261 created_at, updated_at, published_at 249 ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )262 ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 250 263 `).run( 251 264 postId, site.id, finalSlug, req.session.user.id, 252 265 title || finalSlug, cleanContent, excerpt || '', 253 finalStatus, cover_image_url || null, parsePinnedRank(pinned),266 finalStatus, cover_image_url || null, (req.body.cover_video_url || null), parsePinnedRank(pinned), 254 267 JSON.stringify((tags || '').split(',').map(t => t.trim()).filter(Boolean)), 255 268 finalType, noindex ? 1 : 0, fanOnly, nsfw, cw, publishAt, … … 372 385 UPDATE posts SET 373 386 title = ?, content = ?, excerpt = ?, status = ?, 374 cover_image_url = ?, pinned = ?, tags = ?,387 cover_image_url = ?, cover_video_url = ?, pinned = ?, tags = ?, 375 388 type = ?, noindex = ?, fan_only = ?, nsfw = ?, content_warning = ?, publish_at = ?, 376 389 slug = ?, published_at = ?, updated_at = ? … … 378 391 `).run( 379 392 title, cleanContent, excerpt, finalStatus, 380 cover_image_url || null, parsePinnedRank(pinned),393 cover_image_url || null, (req.body.cover_video_url || null), parsePinnedRank(pinned), 381 394 JSON.stringify((tags || '').split(',').map(t => t.trim()).filter(Boolean)), 382 395 finalType, noindex ? 1 : 0, fanOnly, nsfw, cw, publishAt,
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)