Clipboard/screenshot sync across own devices via a single DEVICE_TOKEN-gated blob store, plus a small installable web app so a phone can push/pull clips and share screenshots via the OS share sheet.
50 lines
1.8 KiB
TypeScript
50 lines
1.8 KiB
TypeScript
import { Router } from 'express'
|
|
import fs from 'node:fs'
|
|
import multer from 'multer'
|
|
import { config } from './config.js'
|
|
import { blobPath } from './db.js'
|
|
import { newBlobId } from './ids.js'
|
|
import { insertBlobRecord } from './blobs.js'
|
|
import { timingSafeStringEqual } from './auth.js'
|
|
|
|
// Separate from routes.ts: the OS share sheet POSTs here directly (no
|
|
// custom headers possible), so auth rides in the query string instead of
|
|
// X-Device-Token — see manifest.ts for where that URL gets the token baked
|
|
// in. Same trust level as the token in ~/.config/scrot/env: not a secret
|
|
// from the machine it's on, just from the network.
|
|
export const shareRouter = Router()
|
|
|
|
const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: config.maxUploadBytes } })
|
|
|
|
shareRouter.post('/share', upload.any(), (req, res) => {
|
|
const token = typeof req.query.t === 'string' ? req.query.t : ''
|
|
if (!timingSafeStringEqual(token, config.deviceToken)) {
|
|
res.status(401).send('bad or missing device token — re-add scrot to your home screen to re-onboard')
|
|
return
|
|
}
|
|
|
|
const files = (req.files as Express.Multer.File[] | undefined) ?? []
|
|
const image = files.find((f) => f.mimetype.startsWith('image/'))
|
|
|
|
if (image) {
|
|
const id = newBlobId()
|
|
fs.writeFileSync(blobPath(id), image.buffer)
|
|
insertBlobRecord(id, 'shot', image.mimetype, image.buffer.length)
|
|
res.redirect(303, `/?shared=shot&id=${id}`)
|
|
return
|
|
}
|
|
|
|
const body = req.body as Record<string, string>
|
|
const text = (body.text || body.url || body.title || '').trim()
|
|
if (text) {
|
|
const id = newBlobId()
|
|
const buf = Buffer.from(text, 'utf8')
|
|
fs.writeFileSync(blobPath(id), buf)
|
|
insertBlobRecord(id, 'clip', 'text/plain; charset=utf-8', buf.length)
|
|
res.redirect(303, '/?shared=clip')
|
|
return
|
|
}
|
|
|
|
res.redirect(303, '/?shared=empty')
|
|
})
|