mirror of
https://github.com/baairon/torlink.git
synced 2026-07-08 18:28:22 +02:00
- new PromptHints action row shared by the folder and trackers prompts - download-to prompt shows the torrent name and size, enter reads "download" - export torrent rebound from T to s and centralized in the store - footer trimmed to essentials, d/D and z detail live in the ? sheet - z keeps FitGirl and SubsPlease rows: their feeds carry no seeder data, a new per-source reportsHealth flag marks seeders: 0 as unknown, not dead - version 1.3.0
52 lines
1.8 KiB
TypeScript
52 lines
1.8 KiB
TypeScript
import { fetchResilient, HttpError, USER_AGENT } from "../util/net";
|
|
import { buildMagnet } from "./magnet";
|
|
import { unescapeEntities } from "./rss";
|
|
import { parseSize } from "../util/format";
|
|
import type { SearchOptions, Source, TorrentResult } from "./types";
|
|
|
|
const BASE = "https://nyaa.si/";
|
|
|
|
function tag(item: string, name: string): string {
|
|
return item.match(new RegExp(`<${name}>(?:<!\\[CDATA\\[)?(.*?)(?:\\]\\]>)?</${name}>`, "s"))?.[1]?.trim() ?? "";
|
|
}
|
|
|
|
async function search(query: string, opts: SearchOptions = {}): Promise<TorrentResult[]> {
|
|
const params = new URLSearchParams({ page: "rss", q: query.trim(), c: "0_0", f: "0" });
|
|
const res = await fetchResilient(`${BASE}?${params.toString()}`, {
|
|
headers: { "User-Agent": USER_AGENT },
|
|
signal: opts.signal,
|
|
});
|
|
if (!res.ok) throw new HttpError(res.status, `Nyaa returned ${res.status}`);
|
|
|
|
const xml = await res.text();
|
|
const out: TorrentResult[] = [];
|
|
for (const item of xml.split("<item>").slice(1)) {
|
|
const infoHash = tag(item, "nyaa:infoHash").toLowerCase();
|
|
const name = unescapeEntities(tag(item, "title"));
|
|
if (!infoHash || !name) continue;
|
|
const seeders = Number(tag(item, "nyaa:seeders"));
|
|
const leechers = Number(tag(item, "nyaa:leechers"));
|
|
const dateStr = tag(item, "pubDate");
|
|
out.push({
|
|
infoHash,
|
|
name,
|
|
sizeBytes: parseSize(tag(item, "nyaa:size")),
|
|
seeders: Number.isFinite(seeders) ? seeders : 0,
|
|
leechers: Number.isFinite(leechers) ? leechers : 0,
|
|
source: "nyaa",
|
|
magnet: buildMagnet(infoHash, name),
|
|
added: dateStr ? new Date(dateStr).getTime() / 1000 : undefined,
|
|
});
|
|
}
|
|
return out;
|
|
}
|
|
|
|
export const nyaa: Source = {
|
|
id: "nyaa",
|
|
label: "Nyaa",
|
|
group: "Anime",
|
|
homepage: "https://nyaa.si",
|
|
reportsHealth: true,
|
|
search,
|
|
};
|