immich-public-proxy/src/index.ts

69 lines
2.2 KiB
TypeScript
Raw Normal View History

2024-10-28 04:56:11 -04:00
import express from 'express'
2024-10-28 15:47:14 -04:00
import immich from './immich'
2024-10-29 05:29:14 -04:00
import render from './render'
2024-10-28 04:56:11 -04:00
import dayjs from 'dayjs'
2024-10-28 15:47:14 -04:00
import { AssetType, ImageSize } from './types'
2024-10-29 05:29:14 -04:00
import { Request } from 'express-serve-static-core'
2024-10-28 15:47:14 -04:00
require('dotenv').config()
2024-10-28 04:08:16 -04:00
const app = express()
2024-10-28 15:47:14 -04:00
app.set('view engine', 'ejs')
app.use(express.static('public'))
2024-10-28 04:08:16 -04:00
2024-10-28 15:47:14 -04:00
const getSize = (req: Request) => {
return req?.query?.size === 'thumbnail' ? ImageSize.thumbnail : ImageSize.original
}
2024-10-28 04:08:16 -04:00
app.get('/share/:key', async (req, res) => {
2024-10-29 10:07:54 -04:00
if (!immich.isKey(req.params.key)) {
2024-10-28 04:08:16 -04:00
res.status(404).send()
} else {
2024-10-29 10:07:54 -04:00
const sharedLink = await immich.getShareByKey(req.params.key)
if (!sharedLink || !sharedLink.assets.length) {
2024-10-28 15:47:14 -04:00
res.status(404).send()
2024-10-29 10:07:54 -04:00
} else if (sharedLink.assets.length === 1) {
2024-10-28 04:08:16 -04:00
// This is an individual item (not a gallery)
2024-10-29 10:07:54 -04:00
const asset = sharedLink.assets[0]
2024-10-29 05:29:14 -04:00
if (asset.type === AssetType.image) {
2024-10-29 06:48:16 -04:00
// For photos, output the image directly
2024-10-29 10:07:54 -04:00
await render.assetBuffer(res, sharedLink.assets[0], getSize(req))
2024-10-29 05:29:14 -04:00
} else if (asset.type === AssetType.video) {
2024-10-29 06:48:16 -04:00
// For videos, show the video as a web player
2024-10-29 10:07:54 -04:00
await render.gallery(res, sharedLink, 1)
2024-10-29 05:29:14 -04:00
}
2024-10-28 04:08:16 -04:00
} else {
2024-10-28 15:47:14 -04:00
// Multiple images - render as a gallery
2024-10-29 10:07:54 -04:00
await render.gallery(res, sharedLink)
2024-10-28 04:08:16 -04:00
}
}
})
2024-10-29 05:29:14 -04:00
// Output the buffer data for an photo or video
2024-10-29 10:07:54 -04:00
app.get('/:type(photo|video)/:key/:id', async (req, res) => {
// Check for valid key and ID
if (immich.isKey(req.params.key) && immich.isId(req.params.id)) {
// Check if the key is a valid share link
const sharedLink = await immich.getShareByKey(req.params.key)
if (sharedLink?.assets.length) {
// Check that the requested asset exists in this share
const asset = sharedLink.assets.find(x => x.id === req.params.id)
if (asset) {
asset.type = req.params.type === 'video' ? AssetType.video : AssetType.image
render.assetBuffer(res, asset, getSize(req)).then()
return
}
}
2024-10-29 05:29:14 -04:00
}
2024-10-29 10:07:54 -04:00
res.status(404).send()
2024-10-29 06:48:16 -04:00
})
// Send a 404 for all other unmatched routes
app.get('*', (_req, res) => {
res.status(404).send()
2024-10-28 15:47:14 -04:00
})
2024-10-28 04:08:16 -04:00
app.listen(3000, () => {
console.log(dayjs().format() + ' Server started')
})