Changeset feced2c in Klonkt for src/routes
- Timestamp:
- 07/19/2026 05:25:26 PM (7 weeks ago)
- Branches:
- main
- Children:
- 5190152
- Parents:
- 33e1dbd
- git-author:
- Robin <roboburr@…> (07/19/2026 05:24:58 PM)
- git-committer:
- Robin <roboburr@…> (07/19/2026 05:25:26 PM)
- File:
-
- 1 edited
-
src/routes/posts.js (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/routes/posts.js
r33e1dbd rfeced2c 32 32 const MAX_IMAGE_BYTES = 10 * 1024 * 1024; 33 33 34 // Rich replies: media dropped/pasted into the reply editor. Images, audio and 35 // video, stored as-is (no transcode; a reply attachment is not a track). 36 const REPLY_MEDIA_DIR = path.resolve( 37 process.env.REPLY_MEDIA_PATH || 38 path.join(__dirname, '..', '..', 'storage', 'media', 'reply-media') 39 ); 40 fs.mkdirSync(REPLY_MEDIA_DIR, { recursive: true }); 41 const ALLOWED_REPLY_MEDIA_EXT = new Set([ 42 '.jpg', '.jpeg', '.png', '.webp', '.gif', 43 '.mp3', '.m4a', '.ogg', '.opus', '.flac', '.wav', 44 '.mp4', '.webm', '.mov', 45 ]); 46 const MAX_REPLY_MEDIA_BYTES = 32 * 1024 * 1024; 47 const replyMediaUpload = multer({ 48 storage: multer.diskStorage({ 49 destination: (req, file, cb) => cb(null, REPLY_MEDIA_DIR), 50 filename: (req, file, cb) => cb(null, `${uuid()}${path.extname(file.originalname).toLowerCase()}`), 51 }), 52 limits: { fileSize: MAX_REPLY_MEDIA_BYTES }, 53 fileFilter: (req, file, cb) => { 54 const ext = path.extname(file.originalname).toLowerCase(); 55 if (!ALLOWED_REPLY_MEDIA_EXT.has(ext)) return cb(new Error('Media must be an image, audio or video file')); 56 cb(null, true); 57 }, 58 }); 59 34 60 const imageStorage = multer.diskStorage({ 35 61 destination: (req, file, cb) => cb(null, POST_IMAGES_DIR), … … 90 116 } catch { /* keep the still image */ } 91 117 res.json({ url, video, size: req.file.size, mime: req.file.mimetype }); 118 }); 119 }); 120 121 // Rich replies: media for a reply (image/audio/video). Returns { url, mediaType, name } 122 // exactly as the editor's attachments JSON wants it; deliverReply re-validates. 123 router.post('/posts/upload-reply-media', requireSiteManager, (req, res) => { 124 replyMediaUpload.single('media')(req, res, (err) => { 125 if (err) return res.status(400).json({ error: err.message }); 126 if (!req.file) return res.status(400).json({ error: 'No file' }); 127 const mime = String(req.file.mimetype || ''); 128 if (!/^(image|audio|video)\//.test(mime)) { 129 try { fs.unlinkSync(req.file.path); } catch { /* best effort */ } 130 return res.status(400).json({ error: 'Media must be an image, audio or video file' }); 131 } 132 res.json({ 133 url: '/media/reply-media/' + req.file.filename, 134 mediaType: mime, 135 name: String(req.file.originalname || '').slice(0, 120), 136 }); 92 137 }); 93 138 }); … … 714 759 const html = (req.body.content || '').toString(); // rich reply editor HTML (sanitized in deliverReply) 715 760 const language = (req.body.language || '').toString(); 716 if (site && uri && (text.trim() || html.trim())) { 761 let attachments = []; 762 try { attachments = JSON.parse(req.body.attachments || '[]'); } catch { /* geen media */ } 763 if (site && uri && (text.trim() || html.trim() || (Array.isArray(attachments) && attachments.length))) { 717 764 // Resolve + deliver in the background so Send responds instantly. 718 765 ActivityPubService.resolveRemoteNote(uri) 719 .then((parent) => parent && ActivityPubService.deliverReply(site, { postId: parent.localPostId || '', postSlug: null, parent, text, html, language }))766 .then((parent) => parent && ActivityPubService.deliverReply(site, { postId: parent.localPostId || '', postSlug: null, parent, text, html, language, attachments })) 720 767 .catch((e) => console.warn('[AP] remote reply failed:', e.message)); 721 768 } … … 1260 1307 const text = (req.body.text || '').toString(); 1261 1308 const html = (req.body.content || '').toString(); // rich reply editor HTML (sanitized in deliverReply) 1262 if (parent && parent.post_id === post.id && (text.trim() || html.trim())) { 1309 let attachments = []; 1310 try { attachments = JSON.parse(req.body.attachments || '[]'); } catch { /* geen media */ } 1311 if (parent && parent.post_id === post.id && (text.trim() || html.trim() || (Array.isArray(attachments) && attachments.length))) { 1263 1312 try { 1264 1313 await ActivityPubService.deliverReply(site, { 1265 postId: post.id, postSlug: post.slug, parent, text, html, 1314 postId: post.id, postSlug: post.slug, parent, text, html, attachments, 1266 1315 language: (req.body.language || '').toString(), 1267 1316 });
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)