-
Notifications
You must be signed in to change notification settings - Fork 65
/
server.ts
111 lines (98 loc) · 2.37 KB
/
server.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
103
104
105
106
107
108
109
110
111
import http from "http";
import { pick } from "lodash-es";
import { parse as qsParse } from "querystring";
import { inspect } from "util";
import { Label, logger } from "./logger.js";
import { searchForLocalTorrentByCriteria } from "./pipeline.js";
import { NonceOptions } from "./runtimeConfig.js";
import { TorrentLocator } from "./torrent.js";
function getData(req) {
return new Promise((resolve) => {
const chunks = [];
req.on("data", (chunk) => {
chunks.push(chunk.toString());
});
req.on("end", async () => {
resolve(chunks.join(""));
});
});
}
function parseData(data) {
let parsed;
try {
parsed = JSON.parse(data);
} catch (_) {
parsed = qsParse(data);
}
// transformations
{
if ("infoHash" in parsed) {
parsed.infoHash = parsed.infoHash.toLowerCase();
}
if ("trackers" in parsed && !Array.isArray(parsed.trackers)) {
parsed.trackers = [parsed.trackers];
}
}
if ("name" in parsed || "infoHash" in parsed) {
return parsed;
}
throw new Error(`Unable to parse request body: "${data}"`);
}
async function handleRequest(req, res) {
if (req.method !== "POST") {
res.writeHead(405);
res.end();
return;
}
if (req.url !== "/api/webhook") {
res.writeHead(404);
res.end();
return;
}
const dataStr = await getData(req);
const data = parseData(dataStr);
const criteria: TorrentLocator = pick(data, ["infoHash", "name"]);
const nonceOptions: NonceOptions = pick(data, ["trackers", "outputDir"]);
if (!criteria) {
logger.error({
label: Label.SERVER,
message: "A name or info hash must be provided",
});
res.writeHead(400);
res.end();
}
const criteriaStr = inspect(criteria);
res.writeHead(204);
res.end();
logger.info({ label: Label.SERVER, message: `Received ${criteriaStr}` });
try {
let numFound = null;
if (criteria) {
numFound = await searchForLocalTorrentByCriteria(
criteria,
nonceOptions
);
}
if (numFound === null) {
logger.info({
label: Label.SERVER,
message: `Did not search for ${criteriaStr}`,
});
} else {
logger.info({
label: Label.SERVER,
message: `Found ${numFound} torrents for ${criteriaStr}`,
});
}
} catch (e) {
logger.error(e);
}
}
export async function serve(): Promise<void> {
const server = http.createServer(handleRequest);
server.listen(2468);
logger.info({
label: Label.SERVER,
message: "Server is running on port 2468, ^C to stop.",
});
}