mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-03 04:40:09 +00:00
Refactor indexer management and improve search logic
Refactors admin settings to use a new IndexersTab and card-based indexer management UI, supporting category selection and improved configuration. Updates backend and API routes to handle indexer categories, propagate ASIN for better search scoring, and group indexers by categories to optimize Prowlarr searches. Enhances documentation to clarify non-terminal request matching and auto-completion behavior. Adds new reusable components for indexer management and category selection.
This commit is contained in:
@@ -805,6 +805,36 @@ export class AudibleService {
|
||||
return totalMinutes > 0 ? totalMinutes : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get runtime (in minutes) for an audiobook by ASIN
|
||||
* Lightweight method for size validation during search
|
||||
* Returns null if not found or error
|
||||
*/
|
||||
async getRuntime(asin: string): Promise<number | null> {
|
||||
try {
|
||||
// Use Audnexus API for fast, reliable runtime data
|
||||
const audnexusRegion = AUDIBLE_REGIONS[this.region].audnexusParam;
|
||||
|
||||
const response = await axios.get(`https://api.audnex.us/books/${asin}`, {
|
||||
params: { region: audnexusRegion },
|
||||
timeout: 5000, // Quick timeout for search performance
|
||||
headers: { 'User-Agent': 'ReadMeABook/1.0' },
|
||||
});
|
||||
|
||||
const runtimeMin = response.data?.runtimeLengthMin;
|
||||
if (runtimeMin) {
|
||||
return parseInt(runtimeMin);
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (error: any) {
|
||||
if (error.response?.status !== 404) {
|
||||
logger.debug(`Runtime fetch failed for ASIN ${asin}: ${error.message}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add delay between requests to respect rate limits
|
||||
*/
|
||||
|
||||
@@ -12,12 +12,18 @@ import { RMABLogger } from '../utils/logger';
|
||||
const logger = RMABLogger.create('Prowlarr');
|
||||
|
||||
export interface SearchFilters {
|
||||
category?: number;
|
||||
category?: number; // Deprecated: use categories instead
|
||||
categories?: number[]; // Array of category IDs to search
|
||||
minSeeders?: number;
|
||||
maxResults?: number;
|
||||
indexerIds?: number[];
|
||||
}
|
||||
|
||||
export interface IndexerCategory {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface Indexer {
|
||||
id: number;
|
||||
name: string;
|
||||
@@ -26,6 +32,7 @@ export interface Indexer {
|
||||
priority: number;
|
||||
capabilities?: {
|
||||
supportsRss?: boolean;
|
||||
categories?: IndexerCategory[];
|
||||
};
|
||||
fields?: Array<{
|
||||
name: string;
|
||||
@@ -119,12 +126,23 @@ export class ProwlarrService {
|
||||
const configService = getConfigService();
|
||||
const clientType = (await configService.get('download_client_type')) || 'qbittorrent';
|
||||
|
||||
// Determine which categories to search
|
||||
// Priority: filters.categories > filters.category > defaultCategory
|
||||
let categoriesToSearch: number[];
|
||||
if (filters?.categories && filters.categories.length > 0) {
|
||||
categoriesToSearch = filters.categories;
|
||||
} else if (filters?.category) {
|
||||
categoriesToSearch = [filters.category];
|
||||
} else {
|
||||
categoriesToSearch = [this.defaultCategory];
|
||||
}
|
||||
|
||||
const params: Record<string, any> = {
|
||||
query,
|
||||
type: 'search',
|
||||
limit: 100, // Maximum results to return from Prowlarr
|
||||
extended: 1, // Enable searching in tags, labels, and metadata
|
||||
categories: filters?.category?.toString() || this.defaultCategory.toString(), // 3030 = Audiobooks (standard Newznab category)
|
||||
categories: categoriesToSearch, // Will be serialized as categories=3030&categories=3040 etc
|
||||
};
|
||||
|
||||
// Filter by specific indexers if provided
|
||||
|
||||
Reference in New Issue
Block a user