forked from screeny05/letterboxd-list-radarr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
102 lines (85 loc) · 2.87 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import { LetterboxdPoster } from "./lib/letterboxd/list";
import express from "express";
import { normalizeSlug } from "./lib/letterboxd/util";
import { transformLetterboxdMovieToRadarr } from "./lib/radarr/transform";
import {
getMoviesDetailCached,
LetterboxdMovieDetails,
} from "./lib/letterboxd/movie-details";
import { sendChunkedJson } from "./lib/express/send-chunked-json";
import { fetchPostersFromSlug } from "./lib/letterboxd";
import { logger } from "./lib/logger";
import { cache } from "./lib/cache";
const appLogger = logger.child({ module: "App" });
const PORT = process.env.PORT || 5000;
const app = express();
const server = app.listen(PORT, () =>
appLogger.info(`Listening on port ${PORT}`)
);
server.keepAliveTimeout = 78;
app.get("/", (_, res) => res.send("Use letterboxd.com path as path here."));
app.get("/favicon.ico", (_, res) => res.status(404).send());
app.get(/(.*)/, async (req, res) => {
const chunk = sendChunkedJson(res);
// Abort fetching on client close
let isConnectionOpen = true;
let isFinished = false;
req.connection.once("close", () => {
isConnectionOpen = false;
if (!isFinished) {
appLogger.warn("Client closed connection before finish.");
}
});
const slug = normalizeSlug(req.params[0]);
const limit = req.query.limit
? Number.parseInt(req.query.limit)
: undefined;
let posters: LetterboxdPoster[];
try {
appLogger.info(`Fetching posters for ${slug}`);
posters = await fetchPostersFromSlug(slug);
if (!Array.isArray(posters)) {
throw new Error(`Fetching posters failed for ${slug}`);
}
if (limit) {
posters = posters.slice(0, limit);
}
} catch (e: any) {
isFinished = true;
appLogger.error(`Failed to fetch posters for ${slug} - ${e?.message}`);
chunk.fail(404, e?.message);
isConnectionOpen = false;
return;
}
const movieSlugs = posters.map((poster) => poster.slug);
const onMovie = (movie: LetterboxdMovieDetails) => {
// If there's no tmdb-id it may be a tv-show
// radarr throws an error, if an entry is missing an id
if (!movie.tmdb) {
return;
}
chunk.push(transformLetterboxdMovieToRadarr(movie));
};
try {
await getMoviesDetailCached(
movieSlugs,
7,
onMovie,
() => !isConnectionOpen
);
} catch (e: any) {
appLogger.error(`Failed to fetch movies for ${slug} - ${e?.message}`);
chunk.fail(404, e?.message);
isConnectionOpen = false;
return;
}
isFinished = true;
chunk.end();
});
process.on("unhandledRejection", (reason) => {
throw reason;
});
process.on("uncaughtException", (error) => {
appLogger.error("Uncaught Exception", error);
process.exit(1);
});