feat: add network, container, edition, remastered, repack, uncensored, unrated, upscaled, attributes to formatter

refactor: consolidate file parsing with new library
This commit is contained in:
Viren070
2025-11-01 20:38:46 +00:00
parent 87667f16db
commit b1dba0d24b
15 changed files with 144 additions and 494 deletions
-6
View File
@@ -32,11 +32,5 @@
},
"engines": {
"node": ">=20.0.0"
},
"pnpm": {
"overrides": {
"@grpc/grpc-js": "1.13.4",
"@bufbuild/protobuf": "2.9.0"
}
}
}
+1 -2
View File
@@ -11,6 +11,7 @@
"description": "Combine all your streams into one addon and display them with consistent formatting, sorting, and filtering.",
"dependencies": {
"@torbox/torbox-api": "github:viren070/torbox-sdk-js#dist",
"@viren070/parse-torrent-title": "^0.1.0",
"bcrypt": "^6.0.0",
"bytes": "^3.1.2",
"dotenv": "^16.4.7",
@@ -18,11 +19,9 @@
"expr-eval": "^2.0.2",
"fetch-socks": "^1.3.2",
"fuzzball": "^2.2.3",
"go-ptt": "0.4.1",
"moment-timezone": "^0.5.48",
"p-limit": "^7.2.0",
"parse-torrent": "^11.0.19",
"parse-torrent-title": "github:TheBeastLT/parse-torrent-title",
"pg": "^8.16.0",
"redis": "^5.9.0",
"sqlite": "^5.1.1",
+44 -41
View File
@@ -18,8 +18,7 @@ import {
DebridDownload,
isNotVideoFile,
} from '../../debrid/index.js';
import { PTT } from '../../parser/index.js';
import { ParseResult } from 'go-ptt';
import { parseTorrentTitle, ParsedResult } from '@viren070/parse-torrent-title';
import { preprocessTitle } from '../../parser/utils.js';
// we have a list of torrents which need to be
@@ -132,20 +131,22 @@ async function processTorrentsForDebridService(
});
// Parse only torrent titles and perform validation checks
const processingStart = Date.now();
const parseStart = Date.now();
const torrentTitles = torrents.map((torrent) => torrent.title ?? '');
const parsedTitles = await PTT.parse(torrentTitles);
const parsedTitlesMap = new Map<string, ParseResult>();
const parsedTitles: ParsedResult[] = torrentTitles.map((title) =>
parseTorrentTitle(title)
);
const parsedTitlesMap = new Map<string, ParsedResult>();
for (const [index, result] of parsedTitles.entries()) {
if (result) {
parsedTitlesMap.set(torrentTitles[index], result);
}
parsedTitlesMap.set(torrentTitles[index], result);
}
// Filter torrents that pass validation checks
const validTorrents: {
torrent: Torrent;
magnetCheckResult: DebridDownload | undefined;
parsedTitle: ParseResult;
parsedTitle: ParsedResult;
}[] = [];
for (const torrent of torrents) {
const magnetCheckResult = magnetCheckResults.find(
@@ -155,7 +156,7 @@ async function processTorrentsForDebridService(
if (metadata && parsedTorrent) {
const preprocessedTitle = preprocessTitle(
parsedTorrent.title,
parsedTorrent.title ?? '',
torrent.title ?? '',
metadata.titles
);
@@ -192,15 +193,14 @@ async function processTorrentsForDebridService(
}
// Parse all file strings in one call
const allParsedFiles = await PTT.parse(allFileStrings);
const parsedFiles = new Map<string, ParseResult>();
const allParsedFiles: ParsedResult[] = allFileStrings.map((string) =>
parseTorrentTitle(string)
);
const parsedFiles = new Map<string, ParsedResult>();
for (const [index, result] of allParsedFiles.entries()) {
if (result) {
parsedFiles.set(allFileStrings[index], result);
}
parsedFiles.set(allFileStrings[index], result);
}
const processingStart = Date.now();
const parseTime = getTimeTakenSincePoint(parseStart);
for (const { torrent, magnetCheckResult, parsedTitle } of validTorrents) {
let file: DebridFile | undefined;
@@ -229,9 +229,12 @@ async function processTorrentsForDebridService(
}
}
logger.debug(
`Processed ${torrents.length} torrents for ${service.id} in ${getTimeTakenSincePoint(processingStart)}`
);
logger.debug(`Finished processing of torrents`, {
service: service.id,
torrents: torrents.length,
totalTime: getTimeTakenSincePoint(processingStart),
parseTime,
});
return results;
}
@@ -244,16 +247,16 @@ export async function processTorrentsForP2P(
// Parse only torrent titles and perform validation checks
const torrentTitles = torrents.map((torrent) => torrent.title ?? '');
const parsedTitles = await PTT.parse(torrentTitles);
const parsedTitlesMap = new Map<string, ParseResult>();
const parsedTitles: ParsedResult[] = torrentTitles.map((title) =>
parseTorrentTitle(title)
);
const parsedTitlesMap = new Map<string, ParsedResult>();
for (const [index, result] of parsedTitles.entries()) {
if (result) {
parsedTitlesMap.set(torrentTitles[index], result);
}
parsedTitlesMap.set(torrentTitles[index], result);
}
// Filter torrents that pass validation checks
const validTorrents: { torrent: Torrent; parsedTitle: ParseResult }[] = [];
const validTorrents: { torrent: Torrent; parsedTitle: ParsedResult }[] = [];
for (const torrent of torrents) {
const parsedTorrent = parsedTitlesMap.get(torrent.title ?? '');
if (metadata && parsedTorrent) {
@@ -278,12 +281,12 @@ export async function processTorrentsForP2P(
}
}
const allParsedFiles = await PTT.parse(allFileStrings);
const parsedFiles = new Map<string, ParseResult>();
const allParsedFiles: ParsedResult[] = allFileStrings.map((string) =>
parseTorrentTitle(string)
);
const parsedFiles = new Map<string, ParsedResult>();
for (const [index, result] of allParsedFiles.entries()) {
if (result) {
parsedFiles.set(allFileStrings[index], result);
}
parsedFiles.set(allFileStrings[index], result);
}
for (const { torrent } of validTorrents) {
@@ -396,19 +399,19 @@ async function processNZBsForDebridService(
// Parse only NZB titles and perform validation checks
const nzbTitles = nzbs.map((nzb) => nzb.title ?? '');
const parsedTitles = await PTT.parse(nzbTitles);
const parsedTitlesMap = new Map<string, ParseResult>();
const parsedTitles: ParsedResult[] = nzbTitles.map((title) =>
parseTorrentTitle(title)
);
const parsedTitlesMap = new Map<string, ParsedResult>();
for (const [index, result] of parsedTitles.entries()) {
if (result) {
parsedTitlesMap.set(nzbTitles[index], result);
}
parsedTitlesMap.set(nzbTitles[index], result);
}
// Filter NZBs that pass validation checks
const validNZBs: {
nzb: NZB;
nzbCheckResult: any;
parsedTitle: ParseResult;
parsedTitle: ParsedResult;
}[] = [];
for (const nzb of nzbs) {
const nzbCheckResult = nzbCheckResults.find(
@@ -437,12 +440,12 @@ async function processNZBsForDebridService(
}
}
const allParsedFiles = await PTT.parse(allFileStrings);
const parsedFiles = new Map<string, ParseResult>();
const allParsedFiles: ParsedResult[] = allFileStrings.map((string) =>
parseTorrentTitle(string)
);
const parsedFiles = new Map<string, ParsedResult>();
for (const [index, result] of allParsedFiles.entries()) {
if (result) {
parsedFiles.set(allFileStrings[index], result);
}
parsedFiles.set(allFileStrings[index], result);
}
const processingStart = Date.now();
+8
View File
@@ -655,6 +655,14 @@ export const ParsedFileSchema = z.object({
seasons: z.array(z.number()).optional(),
episode: z.number().optional(),
seasonEpisode: z.array(z.string()).optional(),
edition: z.string().optional(),
remastered: z.boolean().optional(),
repack: z.boolean().optional(),
uncensored: z.boolean().optional(),
unrated: z.boolean().optional(),
upscaled: z.boolean().optional(),
network: z.string().optional(),
container: z.string().optional(),
});
export const ParsedStreamSchema = z.object({
+6 -7
View File
@@ -16,8 +16,7 @@ import {
DebridError,
} from './base.js';
import { StremThruServiceId } from '../presets/stremthru.js';
import { PTT } from '../parser/index.js';
import { ParseResult } from 'go-ptt';
import { parseTorrentTitle, ParsedResult } from '@viren070/parse-torrent-title';
import assert from 'assert';
const logger = createLogger('debrid:stremthru');
@@ -313,12 +312,12 @@ export class StremThruInterface implements DebridService {
const allStrings: string[] = [];
allStrings.push(magnetDownload.name ?? '');
allStrings.push(...magnetDownload.files.map((file) => file.name ?? ''));
const parseResults = await PTT.parse(allStrings);
const parsedFiles = new Map<string, ParseResult>();
const parseResults: ParsedResult[] = allStrings.map((string) =>
parseTorrentTitle(string)
);
const parsedFiles = new Map<string, ParsedResult>();
for (const [index, result] of parseResults.entries()) {
if (result) {
parsedFiles.set(allStrings[index], result);
}
parsedFiles.set(allStrings[index], result);
}
const file = await selectFileInTorrentOrNZB(
+6 -7
View File
@@ -1,6 +1,5 @@
import { TorboxApi } from '@torbox/torbox-api';
import { StremThruError } from 'stremthru';
import { ParseResult } from 'go-ptt';
import {
Env,
ServiceId,
@@ -9,7 +8,6 @@ import {
Cache,
DistributedLock,
} from '../utils/index.js';
import { PTT } from '../parser/index.js';
import { selectFileInTorrentOrNZB } from './utils.js';
import {
DebridService,
@@ -19,6 +17,7 @@ import {
DebridError,
} from './base.js';
import { StremThruInterface } from './stremthru.js';
import { ParsedResult, parseTorrentTitle } from '@viren070/parse-torrent-title';
const logger = createLogger('debrid:torbox');
@@ -378,12 +377,12 @@ export class TorboxDebridService implements DebridService {
allStrings.push(usenetDownload.name ?? '');
allStrings.push(...usenetDownload.files.map((file) => file.name ?? ''));
const parseResults = await PTT.parse(allStrings);
const parsedFiles = new Map<string, ParseResult>();
const parseResults: ParsedResult[] = allStrings.map((string) =>
parseTorrentTitle(string)
);
const parsedFiles = new Map<string, ParsedResult>();
for (const [index, result] of parseResults.entries()) {
if (result) {
parsedFiles.set(allStrings[index], result);
}
parsedFiles.set(allStrings[index], result);
}
const file = await selectFileInTorrentOrNZB(
+16
View File
@@ -74,6 +74,14 @@ export interface ParseValue {
regexMatched: string | null;
encode: string | null;
audioChannels: string[] | null;
edition: string | null;
remastered: boolean | null;
repack: boolean | null;
uncensored: boolean | null;
unrated: boolean | null;
upscaled: boolean | null;
network: string | null;
container: string | null;
indexer: string | null;
year: string | null;
title: string | null;
@@ -276,6 +284,14 @@ export abstract class BaseFormatter {
age: stream.age || null,
message: stream.message || null,
proxied: stream.proxied !== undefined ? stream.proxied : null,
edition: stream.parsedFile?.edition || null,
remastered: stream.parsedFile?.remastered || null,
repack: stream.parsedFile?.repack || null,
uncensored: stream.parsedFile?.uncensored || null,
unrated: stream.parsedFile?.unrated || null,
upscaled: stream.parsedFile?.upscaled || null,
network: stream.parsedFile?.network || null,
container: stream.parsedFile?.container || null,
},
addon: {
name: stream.addon?.name || null,
+47 -22
View File
@@ -1,6 +1,8 @@
import { PARSE_REGEX } from './regex.js';
import { ParsedFile } from '../db/schemas.js';
import ptt from './ptt.js';
// import ptt from './ptt.js';
// import { parseTorrentTitle } from './parse-torrent-title/index.js';
import { parseTorrentTitle } from '@viren070/parse-torrent-title';
function matchPattern(
filename: string,
@@ -22,7 +24,7 @@ function matchMultiplePatterns(
class FileParser {
static parse(filename: string): ParsedFile {
const parsed = ptt.parse(filename);
const parsed = parseTorrentTitle(filename);
if (
['vinland', 'furiosaamadmax', 'horizonanamerican'].includes(
(parsed.title || '')
@@ -54,26 +56,41 @@ class FileParser {
const getPaddedNumber = (number: number, length: number) =>
number.toString().padStart(length, '0');
const releaseGroup = filename.match(PARSE_REGEX.releaseGroup)?.[1] ?? parsed.group;
const releaseGroup =
filename.match(PARSE_REGEX.releaseGroup)?.[1] ?? parsed.group;
const title = parsed.title;
const year = parsed.year ? parsed.year.toString() : undefined;
const season = parsed.season;
const seasons = parsed.seasons;
const episode = parsed.episode;
const formattedSeasonString = seasons?.length
? seasons.length === 1
? `S${getPaddedNumber(seasons[0], 2)}`
: `S${getPaddedNumber(seasons[0], 2)}-${getPaddedNumber(
seasons[seasons.length - 1],
2
)}`
: season
? `S${getPaddedNumber(season, 2)}`
: undefined;
const formattedEpisodeString = episode
? `E${getPaddedNumber(episode, 2)}`
: undefined;
// const season = parsed.season;
// const seasons = parsed.seasons;
// const episode = parsed.episode;
// const formattedSeasonString = seasons?.length
// ? seasons.length === 1
// ? `S${getPaddedNumber(seasons[0], 2)}`
// : `S${getPaddedNumber(seasons[0], 2)}-${getPaddedNumber(
// seasons[seasons.length - 1],
// 2
// )}`
// : season
// ? `S${getPaddedNumber(season, 2)}`
// : undefined;
// const formattedEpisodeString = episode
// ? `E${getPaddedNumber(episode, 2)}`
// : undefined;
// const seasonEpisode = [
// formattedSeasonString,
// formattedEpisodeString,
// ].filter((v) => v !== undefined);
const formattedSeasonString = parsed.seasons?.length
? parsed.seasons.length === 1
? `S${getPaddedNumber(parsed.seasons[0], 2)}`
: `S${getPaddedNumber(parsed.seasons[0], 2)}-${getPaddedNumber(parsed.seasons[parsed.seasons.length - 1], 2)}`
: undefined;
const formattedEpisodeString = parsed.episodes?.length
? parsed.episodes.length === 1
? `E${getPaddedNumber(parsed.episodes[0], 2)}`
: `E${getPaddedNumber(parsed.episodes[0], 2)}-${getPaddedNumber(parsed.episodes[parsed.episodes.length - 1], 2)}`
: undefined;
const seasonEpisode = [
formattedSeasonString,
formattedEpisodeString,
@@ -90,9 +107,17 @@ class FileParser {
releaseGroup,
title,
year,
season,
seasons,
episode,
edition: parsed.edition,
remastered: parsed.remastered ?? false,
repack: parsed.repack ?? false,
uncensored: parsed.uncensored ?? false,
unrated: parsed.unrated ?? false,
upscaled: parsed.upscaled ?? false,
network: parsed.network,
container: parsed.container,
season: parsed.seasons?.[0],
seasons: parsed.seasons,
episode: parsed.episodes?.[0],
seasonEpisode,
};
}
-130
View File
@@ -1,130 +0,0 @@
import { ParseResult, PTTServer } from 'go-ptt';
import os from 'os';
import {
Cache,
createLogger,
Env,
getTimeTakenSincePoint,
} from '../utils/index.js';
import { normaliseTitle } from './utils.js';
const logger = createLogger('parser');
const parseCache = Cache.getInstance<string, ParseResult | null>(
'ptt',
10000,
'memory'
);
class PTT {
private static _pttServer: PTTServer | null = null;
private static _pttConfig: {
network: 'tcp' | 'unix';
address: string;
} = {
network: 'tcp',
address: `:${Env.PTT_PORT}`,
};
// os.platform() === 'win32'
// ? {
// network: 'tcp',
// address: `:${Env.PTT_PORT}`,
// }
// : {
// network: 'unix',
// address: Env.PTT_SOCKET,
// };
private constructor() {}
public static async initialise(): Promise<PTTServer> {
if (PTT._pttServer) {
return PTT._pttServer;
}
PTT._pttServer = new PTTServer(PTT._pttConfig);
await PTT._pttServer.start();
logger.debug('PTT server started');
return PTT._pttServer;
}
public static async cleanup(): Promise<void> {
await PTT._pttServer?.stop();
PTT._pttServer = null;
}
public static async parse(titles: string[]): Promise<(ParseResult | null)[]> {
if (!PTT._pttServer) {
throw new Error('PTT server not running');
}
if (titles.length === 0) {
return [];
}
const startTime = Date.now();
// Check cache for each normalized title
const titlesToProcess: { title: string; index: number }[] = [];
const results: (ParseResult | null)[] = new Array(titles.length);
// First pass - check cache and collect titles that need processing
await Promise.all(
titles.map(async (title, index) => {
const normalizedTitle = normaliseTitle(title);
const cached = await parseCache.get(normalizedTitle);
if (cached !== undefined) {
results[index] = cached;
} else {
titlesToProcess.push({ title, index });
}
})
);
// If all titles were cached, return early
if (titlesToProcess.length === 0) {
return results;
}
// Process uncached titles
try {
const parseResults = await PTT._pttServer.parse({
torrent_titles: titlesToProcess.map((t) => t.title),
normalize: true,
});
// Store results and cache them
parseResults.forEach((result, idx) => {
const { title, index } = titlesToProcess[idx];
const finalResult = result.err ? null : result;
results[index] = finalResult;
if (result.err) {
logger.error(`Error parsing title ${title}: ${result.err}`);
}
// Cache the result
parseCache.set(
normaliseTitle(title),
finalResult,
60 * 60 * 24 // 24 hours
);
});
} catch (error) {
logger.error(
`Error calling PTT server: ${error}, ${JSON.stringify((error as any).metadata)}`,
error
);
// Fill remaining results with null on error
titlesToProcess.forEach(({ index }) => {
results[index] = null;
});
}
logger.debug(
`PTT server parsed ${titlesToProcess.length} titles in ${getTimeTakenSincePoint(startTime)}`
);
return results;
}
}
export default PTT;
-1
View File
@@ -1,3 +1,2 @@
export { default as FileParser } from './file.js';
export { default as StreamParser } from './streams.js';
export { default as PTT } from './go-ptt.js';
-55
View File
@@ -1,55 +0,0 @@
import * as PTT from 'parse-torrent-title';
const array = (chain: (input: string) => number) => (input: string) => [
chain ? chain(input) : input,
];
const integer = (input: string) => parseInt(input, 10);
const parser = new PTT.Parser();
PTT.addDefaults(parser);
parser.addHandler(
'seasons',
/(?:s)(\d{3})[. ]?[xх-]?[. ]?(?:e|x|х|ep|-|\.)[. ]?\d{1,4}(?:[abc]|v0?[1-4]|\D|$)/i,
array(integer)
);
parser.addHandler(
'seasons',
/(?:so?|t)(\d{3})[. ]?[xх-]?[. ]?(?:e|x|х|ep|-|\.)[. ]?\d{1,4}(?:[abc]|v0?[1-4]|\D|$)/i,
array(integer)
);
parser.addHandler(
'seasons',
/(?:(?:\bthe\W)?\bcomplete\W)?(?:saison|seizoen|sezon(?:SO?)?|stagione|season|series|temp(?:orada)?):?[. ]?(\d{3})/i,
array(integer)
);
parser.addHandler(
'seasons',
/(?:(?:\bthe\W)?\bcomplete\W)?(?:\W|^)(\d{3})[. ]?(?:st|nd|rd|th)[. ]*season/i,
array(integer)
);
parser.addHandler(
'seasons',
/(\d{3})(?:-?й)?[. _]?(?:[Сс]езон|sez(?:on)?)(?:\W?\D|$)/i,
array(integer)
);
parser.addHandler(
'seasons',
/(?:\D|^)(\d{3})[Xxх]\d{1,3}(?:\D|$)/,
array(integer)
);
parser.addHandler('seasons', /[[(](\d{3})\.\d{1,3}[)\]]/, array(integer));
parser.addHandler('seasons', /-\s?(\d{3})\.\d{2,3}\s?-/, array(integer));
parser.addHandler('seasons', /^(\d{3})\.\d{2,3} - /, array(integer), {
skipIfBefore: ['year, source', 'resolution'],
});
parser.addHandler('seasons', /\bS(\d{3})E\d{1,2}\b/i, array(integer));
parser.addHandler('episodes', /\bS\d{3}E(\d{1,2})\b/i, array(integer));
parser.addHandler(
'episodes',
/(?:so?|t)\d{3}[. ]?[xх-]?[. ]?(?:e|x|х|ep)[. ]?(\d{1,4})(?:[abc]|v0?[1-4]|\D|$)/i,
array(integer)
);
export default parser;
+8
View File
@@ -437,6 +437,14 @@ class StreamParser {
quality: fileParsed?.quality || folderParsed?.quality,
encode: fileParsed?.encode || folderParsed?.encode,
releaseGroup: fileParsed?.releaseGroup || folderParsed?.releaseGroup,
edition: fileParsed?.edition || folderParsed?.edition,
remastered: fileParsed?.remastered || folderParsed?.remastered,
repack: fileParsed?.repack || folderParsed?.repack,
uncensored: fileParsed?.uncensored || folderParsed?.uncensored,
unrated: fileParsed?.unrated || folderParsed?.unrated,
upscaled: fileParsed?.upscaled || folderParsed?.upscaled,
network: fileParsed?.network || folderParsed?.network,
container: fileParsed?.container || folderParsed?.container,
seasonEpisode:
fileParsed?.seasonEpisode && fileParsed?.seasonEpisode.length > 0
? fileParsed?.seasonEpisode
-8
View File
@@ -3,7 +3,6 @@ import {
Env,
getEnvironmentServiceDetails,
PresetManager,
PTT,
UserRepository,
} from '@aiostreams/core';
import { StatusResponse } from '@aiostreams/core';
@@ -21,13 +20,6 @@ const statusInfo = async (): Promise<StatusResponse> => {
forcedPublicProxyUrl = `${Env.FORCE_PUBLIC_PROXY_PROTOCOL}://${Env.FORCE_PUBLIC_PROXY_HOST}:${Env.FORCE_PUBLIC_PROXY_PORT ?? ''}`;
}
// test PTT server.
const parsed = (await PTT.parse(['The Flash S01E01']))[0];
if (!parsed || parsed.err) {
throw new Error('Failed to parse title: ' + parsed?.err || 'Unknown error');
}
return {
version: Env.VERSION,
tag: Env.TAG,
-12
View File
@@ -11,7 +11,6 @@ import {
logStartupFooter,
Cache,
FeatureControl,
PTT,
AnimeDatabase,
ProwlarrAddon,
TemplateManager,
@@ -28,15 +27,6 @@ async function initialiseDatabase() {
}
}
async function initialisePTT() {
try {
await PTT.initialise();
} catch (error) {
logger.error('Failed to initialise PTT Server:', error);
throw error;
}
}
async function startAutoPrune() {
try {
if (Env.PRUNE_MAX_DAYS < 0) {
@@ -83,7 +73,6 @@ async function start() {
await initialiseTemplates();
await initialiseDatabase();
await initialiseRedis();
await initialisePTT();
initialiseAnimeDatabase();
FeatureControl.initialise();
await initialiseProwlarr();
@@ -108,7 +97,6 @@ async function start() {
async function shutdown() {
await Cache.close();
await PTT.cleanup();
FeatureControl.cleanup();
await DB.getInstance().close();
}
+8 -203
View File
@@ -4,10 +4,6 @@ settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
overrides:
'@grpc/grpc-js': 1.13.4
'@bufbuild/protobuf': 2.9.0
importers:
.:
@@ -36,6 +32,9 @@ importers:
'@torbox/torbox-api':
specifier: github:viren070/torbox-sdk-js#dist
version: https://codeload.github.com/viren070/torbox-sdk-js/tar.gz/dc1d0bc148dd35fa5e5d39f699f070aadeccad5c
'@viren070/parse-torrent-title':
specifier: ^0.1.0
version: 0.1.0
bcrypt:
specifier: ^6.0.0
version: 6.0.0
@@ -57,9 +56,6 @@ importers:
fuzzball:
specifier: ^2.2.3
version: 2.2.3
go-ptt:
specifier: 0.4.1
version: 0.4.1
moment-timezone:
specifier: ^0.5.48
version: 0.5.48
@@ -69,9 +65,6 @@ importers:
parse-torrent:
specifier: ^11.0.19
version: 11.0.19
parse-torrent-title:
specifier: github:TheBeastLT/parse-torrent-title
version: https://codeload.github.com/TheBeastLT/parse-torrent-title/tar.gz/1169487e316a4eed898dcfd900957f89a253604c
pg:
specifier: ^8.16.0
version: 8.16.3
@@ -329,9 +322,6 @@ packages:
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
engines: {node: '>=6.0.0'}
'@bufbuild/protobuf@2.9.0':
resolution: {integrity: sha512-rnJenoStJ8nvmt9Gzye8nkYd6V22xUAnu4086ER7h1zJ508vStko4pMvDeQ446ilDTFpV5wnoc5YS7XvMwwMqA==}
'@colors/colors@1.6.0':
resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==}
engines: {node: '>=0.1.90'}
@@ -748,15 +738,6 @@ packages:
'@gar/promisify@1.1.3':
resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==}
'@grpc/grpc-js@1.13.4':
resolution: {integrity: sha512-GsFaMXCkMqkKIvwCQjCrwH+GHbPKBjhwo/8ZuUkWHqbI73Kky9I+pQltrlT0+MWpedCoosda53lgjYfyEPgxBg==}
engines: {node: '>=12.10.0'}
'@grpc/proto-loader@0.7.15':
resolution: {integrity: sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==}
engines: {node: '>=6'}
hasBin: true
'@headlessui/react@2.2.7':
resolution: {integrity: sha512-WKdTymY8Y49H8/gUc/lIyYK1M+/6dq0Iywh4zTZVAaiTDprRfioxSgD0wnXTQTBpjpGJuTL1NO/mqEvc//5SSg==}
engines: {node: '>=10'}
@@ -939,9 +920,6 @@ packages:
'@jridgewell/trace-mapping@0.3.9':
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
'@js-sdsl/ordered-map@4.4.2':
resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==}
'@napi-rs/wasm-runtime@0.2.12':
resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
@@ -1027,36 +1005,6 @@ packages:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
'@protobufjs/aspromise@1.1.2':
resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
'@protobufjs/base64@1.1.2':
resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
'@protobufjs/codegen@2.0.4':
resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==}
'@protobufjs/eventemitter@1.1.0':
resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==}
'@protobufjs/fetch@1.1.0':
resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==}
'@protobufjs/float@1.0.2':
resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
'@protobufjs/inquire@1.1.0':
resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==}
'@protobufjs/path@1.1.2':
resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
'@protobufjs/pool@1.1.0':
resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
'@protobufjs/utf8@1.1.0':
resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==}
'@radix-ui/number@1.1.1':
resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==}
@@ -2078,6 +2026,9 @@ packages:
cpu: [x64]
os: [win32]
'@viren070/parse-torrent-title@0.1.0':
resolution: {integrity: sha512-AQ90ILks8+xN4FXh4im2pf8J8s8UlW6abvABShH2bo+m6Ydnx5FOcHNp4WIkAVQBCjLNYonJZUIuvpTdrXwBmA==}
'@vitest/expect@2.1.9':
resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==}
@@ -2438,10 +2389,6 @@ packages:
client-only@0.0.1:
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
cliui@8.0.1:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'}
clsx@2.1.1:
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
engines: {node: '>=6'}
@@ -3057,10 +3004,6 @@ packages:
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
deprecated: This package is no longer supported.
get-caller-file@2.0.5:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
get-intrinsic@1.3.0:
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
engines: {node: '>= 0.4'}
@@ -3111,10 +3054,6 @@ packages:
resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
engines: {node: '>= 0.4'}
go-ptt@0.4.1:
resolution: {integrity: sha512-N2S6oI0cGUrqErovxhByrTN21fKtr5v/y3jDh8+LVZv7HM+0MmExQP7xxTvRthnLf+9UhFGoe3vsmXRJ/ENW6A==}
hasBin: true
gopd@1.2.0:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
engines: {node: '>= 0.4'}
@@ -3524,9 +3463,6 @@ packages:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
lodash.camelcase@4.3.0:
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
lodash.castarray@4.4.0:
resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==}
@@ -3543,9 +3479,6 @@ packages:
resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==}
engines: {node: '>= 12.0.0'}
long@5.3.2:
resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
longest-streak@3.1.0:
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
@@ -3998,11 +3931,6 @@ packages:
parse-entities@4.0.2:
resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
parse-torrent-title@https://codeload.github.com/TheBeastLT/parse-torrent-title/tar.gz/1169487e316a4eed898dcfd900957f89a253604c:
resolution: {tarball: https://codeload.github.com/TheBeastLT/parse-torrent-title/tar.gz/1169487e316a4eed898dcfd900957f89a253604c}
version: 1.3.0
engines: {node: '>=12'}
parse-torrent@11.0.19:
resolution: {integrity: sha512-T0lEkDdFVQsy0YxHIKjzDHSgt/yl57f3INs5jl7OZqAm77XDF0FgRgrv3LCKgSqsTOrMwYaF0t2761WKdvhgig==}
engines: {node: '>=12.20.0'}
@@ -4212,10 +4140,6 @@ packages:
property-information@7.1.0:
resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
protobufjs@7.5.4:
resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==}
engines: {node: '>=12.0.0'}
proxy-addr@2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'}
@@ -4337,10 +4261,6 @@ packages:
remark-rehype@11.1.2:
resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
resolve-from@4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
@@ -4702,10 +4622,6 @@ packages:
resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==}
engines: {node: '>=18'}
tar@7.5.1:
resolution: {integrity: sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==}
engines: {node: '>=18'}
text-hex@1.0.0:
resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==}
@@ -5067,10 +4983,6 @@ packages:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'}
y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
@@ -5083,14 +4995,6 @@ packages:
engines: {node: '>= 14.6'}
hasBin: true
yargs-parser@21.1.1:
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
engines: {node: '>=12'}
yargs@17.7.2:
resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
engines: {node: '>=12'}
yn@3.1.1:
resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
engines: {node: '>=6'}
@@ -5121,8 +5025,6 @@ snapshots:
'@jridgewell/gen-mapping': 0.3.12
'@jridgewell/trace-mapping': 0.3.29
'@bufbuild/protobuf@2.9.0': {}
'@colors/colors@1.6.0': {}
'@cspotcode/source-map-support@0.8.1':
@@ -5410,18 +5312,6 @@ snapshots:
'@gar/promisify@1.1.3':
optional: true
'@grpc/grpc-js@1.13.4':
dependencies:
'@grpc/proto-loader': 0.7.15
'@js-sdsl/ordered-map': 4.4.2
'@grpc/proto-loader@0.7.15':
dependencies:
lodash.camelcase: 4.3.0
long: 5.3.2
protobufjs: 7.5.4
yargs: 17.7.2
'@headlessui/react@2.2.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
dependencies:
'@floating-ui/react': 0.26.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
@@ -5571,8 +5461,6 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.4
'@js-sdsl/ordered-map@4.4.2': {}
'@napi-rs/wasm-runtime@0.2.12':
dependencies:
'@emnapi/core': 1.5.0
@@ -5639,29 +5527,6 @@ snapshots:
'@pkgjs/parseargs@0.11.0':
optional: true
'@protobufjs/aspromise@1.1.2': {}
'@protobufjs/base64@1.1.2': {}
'@protobufjs/codegen@2.0.4': {}
'@protobufjs/eventemitter@1.1.0': {}
'@protobufjs/fetch@1.1.0':
dependencies:
'@protobufjs/aspromise': 1.1.2
'@protobufjs/inquire': 1.1.0
'@protobufjs/float@1.0.2': {}
'@protobufjs/inquire@1.1.0': {}
'@protobufjs/path@1.1.2': {}
'@protobufjs/pool@1.1.0': {}
'@protobufjs/utf8@1.1.0': {}
'@radix-ui/number@1.1.1': {}
'@radix-ui/primitive@1.1.2': {}
@@ -6673,6 +6538,8 @@ snapshots:
'@unrs/resolver-binding-win32-x64-msvc@1.11.1':
optional: true
'@viren070/parse-torrent-title@0.1.0': {}
'@vitest/expect@2.1.9':
dependencies:
'@vitest/spy': 2.1.9
@@ -7109,12 +6976,6 @@ snapshots:
client-only@0.0.1: {}
cliui@8.0.1:
dependencies:
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi: 7.0.0
clsx@2.1.1: {}
cluster-key-slot@1.1.2: {}
@@ -7916,8 +7777,6 @@ snapshots:
wide-align: 1.1.5
optional: true
get-caller-file@2.0.5: {}
get-intrinsic@1.3.0:
dependencies:
call-bind-apply-helpers: 1.0.2
@@ -7986,13 +7845,6 @@ snapshots:
define-properties: 1.2.1
gopd: 1.2.0
go-ptt@0.4.1:
dependencies:
'@bufbuild/protobuf': 2.9.0
'@grpc/grpc-js': 1.13.4
node-fetch: 3.3.2
tar: 7.5.1
gopd@1.2.0: {}
graceful-fs@4.2.11: {}
@@ -8393,8 +8245,6 @@ snapshots:
dependencies:
p-locate: 5.0.0
lodash.camelcase@4.3.0: {}
lodash.castarray@4.4.0: {}
lodash.isplainobject@4.0.6: {}
@@ -8412,8 +8262,6 @@ snapshots:
safe-stable-stringify: 2.5.0
triple-beam: 1.4.1
long@5.3.2: {}
longest-streak@3.1.0: {}
loose-envify@1.4.0:
@@ -9016,10 +8864,6 @@ snapshots:
is-decimal: 2.0.1
is-hexadecimal: 2.0.1
parse-torrent-title@https://codeload.github.com/TheBeastLT/parse-torrent-title/tar.gz/1169487e316a4eed898dcfd900957f89a253604c:
dependencies:
moment: 2.30.1
parse-torrent@11.0.19:
dependencies:
bencode: 4.0.0
@@ -9212,21 +9056,6 @@ snapshots:
property-information@7.1.0: {}
protobufjs@7.5.4:
dependencies:
'@protobufjs/aspromise': 1.1.2
'@protobufjs/base64': 1.1.2
'@protobufjs/codegen': 2.0.4
'@protobufjs/eventemitter': 1.1.0
'@protobufjs/fetch': 1.1.0
'@protobufjs/float': 1.0.2
'@protobufjs/inquire': 1.1.0
'@protobufjs/path': 1.1.2
'@protobufjs/pool': 1.1.0
'@protobufjs/utf8': 1.1.0
'@types/node': 20.19.23
long: 5.3.2
proxy-addr@2.0.7:
dependencies:
forwarded: 0.2.0
@@ -9384,8 +9213,6 @@ snapshots:
unified: 11.0.5
vfile: 6.0.3
require-directory@2.1.1: {}
resolve-from@4.0.0: {}
resolve-pkg-maps@1.0.0: {}
@@ -9890,14 +9717,6 @@ snapshots:
mkdirp: 3.0.1
yallist: 5.0.0
tar@7.5.1:
dependencies:
'@isaacs/fs-minipass': 4.0.1
chownr: 3.0.0
minipass: 7.1.2
minizlib: 3.1.0
yallist: 5.0.0
text-hex@1.0.0: {}
thenify-all@1.6.0:
@@ -10354,26 +10173,12 @@ snapshots:
xtend@4.0.2: {}
y18n@5.0.8: {}
yallist@4.0.0: {}
yallist@5.0.0: {}
yaml@2.8.1: {}
yargs-parser@21.1.1: {}
yargs@17.7.2:
dependencies:
cliui: 8.0.1
escalade: 3.2.0
get-caller-file: 2.0.5
require-directory: 2.1.1
string-width: 4.2.3
y18n: 5.0.8
yargs-parser: 21.1.1
yn@3.1.1: {}
yocto-queue@0.1.0: {}