1
0
Fork 0
mirror of https://github.com/alangrainger/immich-public-proxy.git synced 2024-12-28 03:41:58 +00:00

Convert to Typescript

This commit is contained in:
Alan Grainger 2024-10-28 09:56:11 +01:00
parent 94ebc61867
commit ca0eba5949
10 changed files with 3888 additions and 14 deletions

26
.eslintrc Normal file
View file

@ -0,0 +1,26 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"env": { "node": true },
"plugins": [
"@typescript-eslint"
],
"extends": [
"standard",
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"parserOptions": {
"sourceType": "module"
},
"rules": {
"no-new": 0,
"no-unused-vars": "off",
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
"@typescript-eslint/ban-ts-comment": "off",
"no-prototype-builtins": "off",
"@typescript-eslint/no-empty-function": "off"
}
}

35
dist/immich.js vendored Normal file
View file

@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
class Immich {
request(endpoint_1) {
return tslib_1.__awaiter(this, arguments, void 0, function* (endpoint, json = true) {
const res = yield fetch(process.env.IMMICH_URL + '/api' + endpoint, {
headers: {
'x-api-key': process.env.API_KEY || ''
}
});
if (json) {
return res.json();
}
else {
return res;
}
});
}
getShareByKey(key) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const links = yield this.request('/shared-links');
return links.find(x => x.key === key);
});
}
getImage(id_1) {
return tslib_1.__awaiter(this, arguments, void 0, function* (id, size = 'original') {
size = size === 'thumbnail' ? 'thumbnail' : 'original';
return this.request('/assets/' + id + '/' + size, false);
});
}
}
const api = new Immich();
exports.default = api;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1taWNoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2ltbWljaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxNQUFNLE1BQU07SUFDSixPQUFPO3FFQUFFLFFBQWdCLEVBQUUsSUFBSSxHQUFHLElBQUk7WUFDMUMsTUFBTSxHQUFHLEdBQUcsTUFBTSxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEdBQUcsTUFBTSxHQUFHLFFBQVEsRUFBRTtnQkFDbEUsT0FBTyxFQUFFO29CQUNQLFdBQVcsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sSUFBSSxFQUFFO2lCQUN2QzthQUNGLENBQUMsQ0FBQTtZQUNGLElBQUksSUFBSSxFQUFFLENBQUM7Z0JBQ1QsT0FBTyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUE7WUFDbkIsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE9BQU8sR0FBRyxDQUFBO1lBQ1osQ0FBQztRQUNILENBQUM7S0FBQTtJQUVLLGFBQWEsQ0FBRSxHQUFXOztZQUM5QixNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFpQixDQUFBO1lBQ2pFLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssR0FBRyxDQUFDLENBQUE7UUFDdkMsQ0FBQztLQUFBO0lBRUssUUFBUTtxRUFBRSxFQUFVLEVBQUUsSUFBSSxHQUFHLFVBQVU7WUFDM0MsSUFBSSxHQUFHLElBQUksS0FBSyxXQUFXLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFBO1lBQ3RELE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEdBQUcsRUFBRSxHQUFHLEdBQUcsR0FBRyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUE7UUFDMUQsQ0FBQztLQUFBO0NBQ0Y7QUFFRCxNQUFNLEdBQUcsR0FBRyxJQUFJLE1BQU0sRUFBRSxDQUFBO0FBRXhCLGtCQUFlLEdBQUcsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFNoYXJlZExpbmsgfSBmcm9tICcuL3R5cGVzJ1xuXG5jbGFzcyBJbW1pY2gge1xuICBhc3luYyByZXF1ZXN0IChlbmRwb2ludDogc3RyaW5nLCBqc29uID0gdHJ1ZSkge1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoKHByb2Nlc3MuZW52LklNTUlDSF9VUkwgKyAnL2FwaScgKyBlbmRwb2ludCwge1xuICAgICAgaGVhZGVyczoge1xuICAgICAgICAneC1hcGkta2V5JzogcHJvY2Vzcy5lbnYuQVBJX0tFWSB8fCAnJ1xuICAgICAgfVxuICAgIH0pXG4gICAgaWYgKGpzb24pIHtcbiAgICAgIHJldHVybiByZXMuanNvbigpXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiByZXNcbiAgICB9XG4gIH1cblxuICBhc3luYyBnZXRTaGFyZUJ5S2V5IChrZXk6IHN0cmluZykge1xuICAgIGNvbnN0IGxpbmtzID0gYXdhaXQgdGhpcy5yZXF1ZXN0KCcvc2hhcmVkLWxpbmtzJykgYXMgU2hhcmVkTGlua1tdXG4gICAgcmV0dXJuIGxpbmtzLmZpbmQoeCA9PiB4LmtleSA9PT0ga2V5KVxuICB9XG5cbiAgYXN5bmMgZ2V0SW1hZ2UgKGlkOiBzdHJpbmcsIHNpemUgPSAnb3JpZ2luYWwnKSB7XG4gICAgc2l6ZSA9IHNpemUgPT09ICd0aHVtYm5haWwnID8gJ3RodW1ibmFpbCcgOiAnb3JpZ2luYWwnXG4gICAgcmV0dXJuIHRoaXMucmVxdWVzdCgnL2Fzc2V0cy8nICsgaWQgKyAnLycgKyBzaXplLCBmYWxzZSlcbiAgfVxufVxuXG5jb25zdCBhcGkgPSBuZXcgSW1taWNoKClcblxuZXhwb3J0IGRlZmF1bHQgYXBpXG4iXX0=

37
dist/index.js vendored Normal file
View file

@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const express_1 = tslib_1.__importDefault(require("express"));
const immich_1 = tslib_1.__importDefault(require("./immich"));
const dayjs_1 = tslib_1.__importDefault(require("dayjs"));
const app = (0, express_1.default)();
require('dotenv').config();
app.get('/share/:key', (req, res) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
var _a;
if (req.params.key.match(/[^A-Za-z0-9-]/)) {
// Invalid characters in the incoming URL
res.status(404).send();
}
else {
const share = yield immich_1.default.getShareByKey(req.params.key);
if (((_a = share === null || share === void 0 ? void 0 : share.assets) === null || _a === void 0 ? void 0 : _a.length) === 1) {
// This is an individual item (not a gallery)
// Return the full-size image.
const size = req.query.size === 'thumbnail' ? 'thumbnail' : 'original';
const image = yield immich_1.default.getImage(share.assets[0].id, size);
for (const header of ['content-type', 'content-length']) {
res.set(header, image.headers[header]);
}
const data = yield image.arrayBuffer();
console.log((0, dayjs_1.default)().format() + ' Serving image ' + share.assets[0].id);
res.send(Buffer.from(data));
}
else {
res.send();
}
}
}));
app.listen(3000, () => {
console.log((0, dayjs_1.default)().format() + ' Server started');
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsOERBQTZCO0FBQzdCLDhEQUEwQjtBQUMxQiwwREFBeUI7QUFFekIsTUFBTSxHQUFHLEdBQUcsSUFBQSxpQkFBTyxHQUFFLENBQUE7QUFFckIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFBO0FBRTFCLEdBQUcsQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLENBQU8sR0FBRyxFQUFFLEdBQUcsRUFBRSxFQUFFOztJQUN4QyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO1FBQzFDLHlDQUF5QztRQUN6QyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFBO0lBQ3hCLENBQUM7U0FBTSxDQUFDO1FBQ04sTUFBTSxLQUFLLEdBQUcsTUFBTSxnQkFBRyxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBQ3JELElBQUksQ0FBQSxNQUFBLEtBQUssYUFBTCxLQUFLLHVCQUFMLEtBQUssQ0FBRSxNQUFNLDBDQUFFLE1BQU0sTUFBSyxDQUFDLEVBQUUsQ0FBQztZQUNoQyw2Q0FBNkM7WUFDN0MsOEJBQThCO1lBQzlCLE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUE7WUFDdEUsTUFBTSxLQUFLLEdBQUcsTUFBTSxnQkFBRyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQTtZQUMxRCxLQUFLLE1BQU0sTUFBTSxJQUFJLENBQUMsY0FBYyxFQUFFLGdCQUFnQixDQUFDLEVBQUUsQ0FBQztnQkFDeEQsR0FBRyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFBO1lBQ3hDLENBQUM7WUFDRCxNQUFNLElBQUksR0FBRyxNQUFNLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQTtZQUN0QyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUEsZUFBSyxHQUFFLENBQUMsTUFBTSxFQUFFLEdBQUcsaUJBQWlCLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQTtZQUN0RSxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtRQUM3QixDQUFDO2FBQU0sQ0FBQztZQUNOLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQTtRQUNaLENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQyxDQUFBLENBQUMsQ0FBQTtBQUVGLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRTtJQUNwQixPQUFPLENBQUMsR0FBRyxDQUFDLElBQUEsZUFBSyxHQUFFLENBQUMsTUFBTSxFQUFFLEdBQUcsaUJBQWlCLENBQUMsQ0FBQTtBQUNuRCxDQUFDLENBQUMsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBleHByZXNzIGZyb20gJ2V4cHJlc3MnXG5pbXBvcnQgYXBpIGZyb20gJy4vaW1taWNoJ1xuaW1wb3J0IGRheWpzIGZyb20gJ2RheWpzJ1xuXG5jb25zdCBhcHAgPSBleHByZXNzKClcblxucmVxdWlyZSgnZG90ZW52JykuY29uZmlnKClcblxuYXBwLmdldCgnL3NoYXJlLzprZXknLCBhc3luYyAocmVxLCByZXMpID0+IHtcbiAgaWYgKHJlcS5wYXJhbXMua2V5Lm1hdGNoKC9bXkEtWmEtejAtOS1dLykpIHtcbiAgICAvLyBJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdGhlIGluY29taW5nIFVSTFxuICAgIHJlcy5zdGF0dXMoNDA0KS5zZW5kKClcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBzaGFyZSA9IGF3YWl0IGFwaS5nZXRTaGFyZUJ5S2V5KHJlcS5wYXJhbXMua2V5KVxuICAgIGlmIChzaGFyZT8uYXNzZXRzPy5sZW5ndGggPT09IDEpIHtcbiAgICAgIC8vIFRoaXMgaXMgYW4gaW5kaXZpZHVhbCBpdGVtIChub3QgYSBnYWxsZXJ5KVxuICAgICAgLy8gUmV0dXJuIHRoZSBmdWxsLXNpemUgaW1hZ2UuXG4gICAgICBjb25zdCBzaXplID0gcmVxLnF1ZXJ5LnNpemUgPT09ICd0aHVtYm5haWwnID8gJ3RodW1ibmFpbCcgOiAnb3JpZ2luYWwnXG4gICAgICBjb25zdCBpbWFnZSA9IGF3YWl0IGFwaS5nZXRJbWFnZShzaGFyZS5hc3NldHNbMF0uaWQsIHNpemUpXG4gICAgICBmb3IgKGNvbnN0IGhlYWRlciBvZiBbJ2NvbnRlbnQtdHlwZScsICdjb250ZW50LWxlbmd0aCddKSB7XG4gICAgICAgIHJlcy5zZXQoaGVhZGVyLCBpbWFnZS5oZWFkZXJzW2hlYWRlcl0pXG4gICAgICB9XG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgaW1hZ2UuYXJyYXlCdWZmZXIoKVxuICAgICAgY29uc29sZS5sb2coZGF5anMoKS5mb3JtYXQoKSArICcgU2VydmluZyBpbWFnZSAnICsgc2hhcmUuYXNzZXRzWzBdLmlkKVxuICAgICAgcmVzLnNlbmQoQnVmZmVyLmZyb20oZGF0YSkpXG4gICAgfSBlbHNlIHtcbiAgICAgIHJlcy5zZW5kKClcbiAgICB9XG4gIH1cbn0pXG5cbmFwcC5saXN0ZW4oMzAwMCwgKCkgPT4ge1xuICBjb25zb2xlLmxvZyhkYXlqcygpLmZvcm1hdCgpICsgJyBTZXJ2ZXIgc3RhcnRlZCcpXG59KVxuIl19

3
dist/types.js vendored Normal file
View file

@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBpbnRlcmZhY2UgU2hhcmVkTGlua0Fzc2V0IHtcbiAgaWQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTaGFyZWRMaW5rIHtcbiAga2V5OiBzdHJpbmc7XG4gIGFzc2V0czogU2hhcmVkTGlua0Fzc2V0W11cbn1cbiJdfQ==

3722
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,12 @@
{
"name": "immich-public-proxy",
"version": "1.0.0",
"main": "src/index.js",
"main": "src/index.ts",
"scripts": {
"dev": "node src/index.js",
"start": "node src/index.js"
"dev": "ts-node src/index.ts",
"build": "npx tsc",
"start": "node dist/index.js"
},
"type": "module",
"author": "",
"license": "ISC",
"description": "",
@ -14,5 +14,16 @@
"express": "^4.21.1",
"dotenv": "^16.4.5",
"dayjs": "^1.11.13"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/node": "^16.18.111",
"@immich/sdk": "^1.118.2",
"@typescript-eslint/eslint-plugin": "5.29.0",
"@typescript-eslint/parser": "5.29.0",
"eslint": "^8.49.0",
"eslint-config-standard": "^17.1.0",
"ts-node": "^10.9.2",
"typescript": "^5.6.2"
}
}

View file

@ -1,8 +1,10 @@
import { SharedLink } from './types'
class Immich {
async request (endpoint, json = true) {
async request (endpoint: string, json = true) {
const res = await fetch(process.env.IMMICH_URL + '/api' + endpoint, {
headers: {
'x-api-key': process.env.API_KEY
'x-api-key': process.env.API_KEY || ''
}
})
if (json) {
@ -12,16 +14,17 @@ class Immich {
}
}
async getShareByKey (key) {
const links = await this.request('/shared-links')
async getShareByKey (key: string) {
const links = await this.request('/shared-links') as SharedLink[]
return links.find(x => x.key === key)
}
async getImage (id, size) {
async getImage (id: string, size = 'original') {
size = size === 'thumbnail' ? 'thumbnail' : 'original'
return this.request('/assets/' + id + '/' + size, false)
}
}
const api = new Immich()
export default api

View file

@ -1,13 +1,13 @@
const express = require('express')
const api = require('./immich').default
const dayjs = require('dayjs')
import express from 'express'
import api from './immich'
import dayjs from 'dayjs'
const app = express()
require('dotenv').config()
app.get('/share/:key', async (req, res) => {
if (req.params.key.match(/[^A-Za-z0-9\-]/)) {
if (req.params.key.match(/[^A-Za-z0-9-]/)) {
// Invalid characters in the incoming URL
res.status(404).send()
} else {
@ -15,11 +15,13 @@ app.get('/share/:key', async (req, res) => {
if (share?.assets?.length === 1) {
// This is an individual item (not a gallery)
// Return the full-size image.
const image = await api.getImage(share.assets[0].id, req.query.size)
const size = req.query.size === 'thumbnail' ? 'thumbnail' : 'original'
const image = await api.getImage(share.assets[0].id, size)
for (const header of ['content-type', 'content-length']) {
res.set(header, image.headers[header])
}
const data = await image.arrayBuffer()
console.log(dayjs().format() + ' Serving image ' + share.assets[0].id)
res.send(Buffer.from(data))
} else {
res.send()

8
src/types.ts Normal file
View file

@ -0,0 +1,8 @@
export interface SharedLinkAsset {
id: string;
}
export interface SharedLink {
key: string;
assets: SharedLinkAsset[]
}

27
tsconfig.json Normal file
View file

@ -0,0 +1,27 @@
{
"compilerOptions": {
"baseUrl": "src",
"outDir": "dist",
"inlineSourceMap": true,
"inlineSources": true,
"module": "CommonJS",
"target": "ES6",
"allowJs": true,
"noImplicitAny": true,
"esModuleInterop": true,
"moduleResolution": "node",
"importHelpers": true,
"isolatedModules": true,
"strictNullChecks": true,
"lib": [
"DOM",
"ES5",
"ES6",
"ES7"
],
"allowSyntheticDefaultImports": true
},
"include": [
"**/*.ts"
]
}