diff --git a/src/pipeline.ts b/src/pipeline.ts index 0293bd58..e572a704 100755 --- a/src/pipeline.ts +++ b/src/pipeline.ts @@ -10,8 +10,9 @@ import { filterByContent, filterDupes, filterTimestamps } from "./preFilter"; import { getRuntimeConfig } from "./runtimeConfig"; import { Searchee } from "./searchee"; import { + TorrentLocator, getInfoHashesToExclude, - getTorrentByName, + getTorrentByCriteria, loadTorrentDirLight, saveTorrentFile, } from "./torrent"; @@ -136,10 +137,10 @@ async function findMatchesBatch( return totalFound; } -export async function searchForSingleTorrentByName( - name: string +export async function searchForLocalTorrentByCriteria( + criteria: TorrentLocator ): Promise { - const meta = await getTorrentByName(name); + const meta = await getTorrentByCriteria(criteria); const hashesToExclude = getInfoHashesToExclude(); if (!filterByContent(meta)) return null; return findOnOtherSites(meta, hashesToExclude); diff --git a/src/server.ts b/src/server.ts index 735ca895..07fd9eae 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,10 +1,11 @@ import fs from "fs"; import http from "http"; import qs from "querystring"; -import { validateJackettApi } from "./jackett"; +import { inspect } from "util"; import { Label, logger } from "./logger"; -import { searchForSingleTorrentByName } from "./pipeline"; +import { searchForLocalTorrentByCriteria } from "./pipeline"; import { getRuntimeConfig } from "./runtimeConfig"; +import { TorrentLocator } from "./torrent"; function getData(req) { return new Promise((resolve) => { @@ -19,13 +20,21 @@ function getData(req) { } function parseData(data) { + let parsed; try { - return JSON.parse(data); + parsed = JSON.parse(data); } catch (_) { - const parsed = qs.parse(data); - if ("name" in parsed) return parsed; - throw new Error(`Unable to parse request body: "${data}"`); + parsed = qs.parse(data); } + + if ("infoHash" in parsed) { + parsed.infoHash = parsed.infoHash.toLowerCase(); + } + if ("name" in parsed || "infoHash" in parsed) { + return parsed; + } + + throw new Error(`Unable to parse request body: "${data}"`); } async function handleRequest(req, res) { @@ -40,21 +49,40 @@ async function handleRequest(req, res) { return; } const dataStr = await getData(req); - const { name } = parseData(dataStr); + const criteria: TorrentLocator = parseData(dataStr); + + 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 }); + + const message = `Received ${criteriaStr}`; res.writeHead(204); res.end(); - logger.info({ label: Label.SERVER, message: `Received name ${name}` }); + + logger.info({ label: Label.SERVER, message }); + try { - const numFound = await searchForSingleTorrentByName(name); + let numFound = null; + if (criteria) { + numFound = await searchForLocalTorrentByCriteria(criteria); + } + if (numFound === null) { logger.info({ label: Label.SERVER, - message: `Did not search for ${name}`, + message: `Did not search for ${criteriaStr}`, }); } else { logger.info({ label: Label.SERVER, - message: `Found ${numFound} torrents for ${name}`, + message: `Found ${numFound} torrents for ${criteriaStr}`, }); } } catch (e) { diff --git a/src/torrent.ts b/src/torrent.ts index f8d7d3e6..0c7231e9 100644 --- a/src/torrent.ts +++ b/src/torrent.ts @@ -2,6 +2,7 @@ import fs, { promises as fsPromises } from "fs"; import parseTorrent, { Metafile } from "parse-torrent"; import path from "path"; import { concat } from "simple-get"; +import { inspect } from "util"; import { INDEXED_TORRENTS } from "./constants"; import db from "./db"; import { CrossSeedError } from "./errors"; @@ -10,6 +11,11 @@ import { getRuntimeConfig } from "./runtimeConfig"; import { createSearcheeFromTorrentFile, Searchee } from "./searchee"; import { ok, stripExtension } from "./utils"; +export interface TorrentLocator { + infoHash?: string; + name?: string; +} + export async function parseTorrentFromFilename( filename: string ): Promise { @@ -144,14 +150,16 @@ export async function loadTorrentDirLight(): Promise { ).then((searcheeResults) => searcheeResults.filter(ok)); } -export async function getTorrentByName(name: string): Promise { +export async function getTorrentByCriteria( + criteria: TorrentLocator +): Promise { await indexNewTorrents(); - const findResult = db - .get(INDEXED_TORRENTS) - .value() - .find((e) => e.name === name); + + const findResult = db.get(INDEXED_TORRENTS).find(criteria).value(); if (findResult === undefined) { - const message = `could not find a torrent with the name ${name}`; + const message = `could not find a torrent with the criteria ${inspect( + criteria + )}`; throw new Error(message); } return parseTorrentFromFilename(findResult.filepath);