Add SABnzbd Usenet/NZB integration and documentation

Introduces SABnzbd as a supported download client for Usenet/NZB alongside qBittorrent, including service implementation, setup wizard and admin settings UI updates, and protocol-specific job processor logic. Updates documentation, PRD, and database schema to support NZB downloads, adds comprehensive technical details and testing strategies, and fixes Audible integration issues related to search and ASIN extraction.
This commit is contained in:
kikootwo
2026-01-07 02:40:11 -05:00
parent 23881eb670
commit e008744df1
21 changed files with 2378 additions and 254 deletions
+58 -15
View File
@@ -5,37 +5,80 @@
import { NextRequest, NextResponse } from 'next/server';
import { QBittorrentService } from '@/lib/integrations/qbittorrent.service';
import { SABnzbdService } from '@/lib/integrations/sabnzbd.service';
export async function POST(request: NextRequest) {
try {
const { type, url, username, password, disableSSLVerify } = await request.json();
if (!type || !url || !username || !password) {
if (!type || !url) {
return NextResponse.json(
{ success: false, error: 'All fields are required' },
{ success: false, error: 'Type and URL are required' },
{ status: 400 }
);
}
if (type !== 'qbittorrent') {
if (type !== 'qbittorrent' && type !== 'sabnzbd') {
return NextResponse.json(
{ success: false, error: 'Only qBittorrent is currently supported' },
{ success: false, error: 'Invalid client type. Must be qbittorrent or sabnzbd' },
{ status: 400 }
);
}
// Test connection with custom credentials
const version = await QBittorrentService.testConnectionWithCredentials(
url,
username,
password,
disableSSLVerify || false
// Validate required fields per client type
if (type === 'qbittorrent') {
if (!username || !password) {
return NextResponse.json(
{ success: false, error: 'Username and password are required for qBittorrent' },
{ status: 400 }
);
}
// Test qBittorrent connection
const version = await QBittorrentService.testConnectionWithCredentials(
url,
username,
password,
disableSSLVerify || false
);
return NextResponse.json({
success: true,
version,
});
} else if (type === 'sabnzbd') {
if (!password) {
return NextResponse.json(
{ success: false, error: 'API key (password) is required for SABnzbd' },
{ status: 400 }
);
}
// Test SABnzbd connection
const sabnzbd = new SABnzbdService(url, password, 'readmeabook', disableSSLVerify || false);
const result = await sabnzbd.testConnection();
if (!result.success) {
return NextResponse.json(
{
success: false,
error: result.error || 'Failed to connect to SABnzbd',
},
{ status: 500 }
);
}
return NextResponse.json({
success: true,
version: result.version,
});
}
// Should never reach here
return NextResponse.json(
{ success: false, error: 'Invalid client type' },
{ status: 400 }
);
return NextResponse.json({
success: true,
version,
});
} catch (error) {
console.error('[Setup] Download client test failed:', error);
return NextResponse.json(