Skip to content

Commit

Permalink
Merge pull request #119 from afraazali/feature/daemon-mode-search-by-…
Browse files Browse the repository at this point in the history
…hash

[FEATURE] - Allow daemon mode to search for torrents via hash
  • Loading branch information
mmgoodnow committed Jul 30, 2021
2 parents 7d161eb + c6d9445 commit 30f1518
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 21 deletions.
9 changes: 5 additions & 4 deletions src/pipeline.ts
Expand Up @@ -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";
Expand Down Expand Up @@ -136,10 +137,10 @@ async function findMatchesBatch(
return totalFound;
}

export async function searchForSingleTorrentByName(
name: string
export async function searchForLocalTorrentByCriteria(
criteria: TorrentLocator
): Promise<number> {
const meta = await getTorrentByName(name);
const meta = await getTorrentByCriteria(criteria);
const hashesToExclude = getInfoHashesToExclude();
if (!filterByContent(meta)) return null;
return findOnOtherSites(meta, hashesToExclude);
Expand Down
50 changes: 39 additions & 11 deletions 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) => {
Expand All @@ -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) {
Expand All @@ -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) {
Expand Down
20 changes: 14 additions & 6 deletions src/torrent.ts
Expand Up @@ -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";
Expand All @@ -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<Metafile> {
Expand Down Expand Up @@ -144,14 +150,16 @@ export async function loadTorrentDirLight(): Promise<Searchee[]> {
).then((searcheeResults) => searcheeResults.filter(ok));
}

export async function getTorrentByName(name: string): Promise<Metafile> {
export async function getTorrentByCriteria(
criteria: TorrentLocator
): Promise<Metafile> {
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);
Expand Down

0 comments on commit 30f1518

Please sign in to comment.