OverviewFilesCommitsIssuesDocsReleasesPeers

keet-cli commits / f6c7f41

Fix file extraction: use encoded structure (entry.httpLink, metadata.name)
keet-core API returns encoded files with metadata/entry/pointer structure, not flat objects. Extract httpLink from entry.httpLink (full authenticated URL with blob/token params), name from metadata.name, and use filename as canonical ID for file.preview matching (supports both blob ID and filename lookup). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
f6c7f4174963095f0145d462f7a07f4b148cd2db
by plankatron <fleeky@gmail.com> · 2026-02-17T19:04:58.000Z

Changed files (2) +61 -23

lib/router.js +42 -13
……@@ -249,16 +249,27 @@ export class Router {
249249 } else if (generic) {
250250 system = generic
251251 }
252 // Extract file attachments
253 const rawFiles = msg.message?.files || []
254 const files = Array.isArray(rawFiles) ? rawFiles.map(f => ({
255 id: f.pointer?.externalBlob?.id || null,
256 name: f.name || f.fileName || 'file',
257 type: f.mimeType || '',
258 size: f.size || 0,
259 dimensions: f.dimensions || null,
260 httpLink: f.httpLink || ''
261 })) : []
252 // Extract file attachments (encoded file structure from keet-core API)
253 // Encoded files have: metadata.{name,mimetype,size,dimensions}, entry.{httpLink, preview.small.httpLink},
254 // pointer.externalBlob.id (z32 key). Raw files have: name, mimeType, size at top level.
255 const rawFiles = msg.message?.files || msg.files || []
256 const files = Array.isArray(rawFiles) ? rawFiles.map(f => {
257 const meta = f.metadata || {}
258 const entry = f.entry || {}
259 const name = meta.name || f.name || f.fileName || 'file'
260 return {
261 id: name, // Use filename as canonical ID (most reliable across encoded/raw formats)
262 name,
263 type: meta.mimetype || f.mimeType || '',
264 size: meta.size || f.size || 0,
265 dimensions: meta.dimensions || f.dimensions || null,
266 httpLink: entry.httpLink || f.httpLink || '',
267 preview: entry.preview ? {
268 small: entry.preview.small?.httpLink || '',
269 medium: entry.preview.medium?.httpLink || ''
270 } : null
271 }
272 }) : []
262273
263274 return {
264275 memberId,
……@@ -776,16 +787,33 @@ export class Router {
776787 const files = await this.backend.api.core.getLocalFiles(params.roomId)
777788 const entries = Array.isArray(files) ? files : (files?.data || files?.entries || [])
778789
779 // Match file by blob ID — handle Buffer vs string comparison
790 console.log('[keet-daemon] file.preview: looking for "%s" among %d local files', params.fileId, entries.length)
791 if (entries.length > 0) {
792 const sample = entries[0]
793 const sObj = sample.file || sample
794 console.log('[keet-daemon] sample entry keys:', Object.keys(sObj).join(','),
795 'metadata.name:', sObj?.metadata?.name,
796 'pointer.externalBlob:', sObj?.pointer?.externalBlob ? 'yes' : 'no')
797 }
798
799 // Match file by FILENAME (primary) or blob ID (fallback)
780800 const targetId = String(params.fileId)
781801 const entry = entries.find(f => {
782802 const fileObj = f.file || f
803 // Try filename match first (most reliable — Godot sends filename as fileId)
804 const name = fileObj?.metadata?.name || ''
805 if (name && name === targetId) return true
806 // Fallback: match by blob ID (z32 or hex)
783807 const blobId = fileObj?.pointer?.externalBlob?.id
784808 if (!blobId) return false
785809 const idStr = Buffer.isBuffer(blobId) ? blobId.toString('hex') : String(blobId)
786810 return idStr === targetId
787811 })
788 if (!entry) throw new Error('File not found: ' + params.fileId)
812
813 if (!entry) {
814 const names = entries.slice(0, 5).map(f => (f.file || f)?.metadata?.name || '?').join(', ')
815 throw new Error('File not found: ' + params.fileId + ' (have: ' + names + ')')
816 }
789817
790818 // Generate httpLink using FileManager's blob server
791819 const fileObj = entry.file || entry
……@@ -796,13 +824,14 @@ export class Router {
796824 console.error('[keet-daemon] getFileLink error:', err.message)
797825 }
798826
827 console.log('[keet-daemon] file.preview: found "%s" -> httpLink=%s', params.fileId, (httpLink || '').slice(0, 80))
828
799829 const meta = fileObj?.metadata || {}
800830 return {
801831 name: meta.name || 'file',
802832 type: meta.mimetype || '',
803833 size: meta.size || 0,
804834 httpLink,
805 fullHttpLink: httpLink,
806835 dimensions: meta.dimensions || null
807836 }
808837 }
lib/uds-transport.js +19 -10
……@@ -252,16 +252,25 @@ function normalizeEvent (event, nameMap) {
252252 system = generic
253253 }
254254
255 // Extract file attachments
256 const rawFiles = event.message?.files || []
257 const files = Array.isArray(rawFiles) ? rawFiles.map(f => ({
258 id: f.pointer?.externalBlob?.id || null,
259 name: f.name || f.fileName || 'file',
260 type: f.mimeType || '',
261 size: f.size || 0,
262 dimensions: f.dimensions || null,
263 httpLink: f.httpLink || ''
264 })) : []
255 // Extract file attachments (encoded file structure from keet-core API)
256 const rawFiles = event.message?.files || event.files || []
257 const files = Array.isArray(rawFiles) ? rawFiles.map(f => {
258 const meta = f.metadata || {}
259 const entry = f.entry || {}
260 const name = meta.name || f.name || f.fileName || 'file'
261 return {
262 id: name,
263 name,
264 type: meta.mimetype || f.mimeType || '',
265 size: meta.size || f.size || 0,
266 dimensions: meta.dimensions || f.dimensions || null,
267 httpLink: entry.httpLink || f.httpLink || '',
268 preview: entry.preview ? {
269 small: entry.preview.small?.httpLink || '',
270 medium: entry.preview.medium?.httpLink || ''
271 } : null
272 }
273 }) : []
265274
266275 if (!text && !system && files.length === 0) return null
267276