feat(ombi): Add Ombi PALDRA integration for request management
Docs Check / Markdown lint (push) Successful in 1m43s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m1s
CI / Security audit (push) Successful in 2m48s
Docs Check / Mermaid diagram parse check (push) Successful in 3m8s
CI / Tests & coverage (push) Failing after 3m33s
CI / Swagger Validation & Coverage (push) Successful in 3m34s
Build and Push Docker Image / build (push) Successful in 4m36s
Docs Check / Markdown lint (push) Successful in 1m43s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m1s
CI / Security audit (push) Successful in 2m48s
Docs Check / Mermaid diagram parse check (push) Successful in 3m8s
CI / Tests & coverage (push) Failing after 3m33s
CI / Swagger Validation & Coverage (push) Successful in 3m34s
Build and Push Docker Image / build (push) Successful in 4m36s
- Add OmbiRetriever extending ArrRetriever for PALDRA compliance - Add OmbiClient for low-level Ombi API communication - Add getOmbiInstances() to config.js following multi-instance pattern - Register Ombi in PALDRA registry with Ombi-specific methods - Add external ID matching (TMDB/TVDB/IMDB) to Ombi requests - Update DownloadMatcher to be async and enrich downloads with Ombi links - Add getOmbiLink/getOmbiSearchLink helpers to DownloadAssembler - Implement new service icon layout (Ombi + Sonarr/Radarr icons) - Add CSS styling for service icons - Update dashboard routes to include Ombi configuration - Extend OpenAPI with Ombi tag and NormalizedDownload properties - Update documentation (README, ARCHITECTURE, SECURITY, CHANGELOG) - Add Ombi configuration to .env.sample
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
// Copyright (c) 2026 Gordon Bolton. MIT License.
|
||||
const axios = require('axios');
|
||||
const { logToFile } = require('../utils/logger');
|
||||
|
||||
/**
|
||||
* Ombi API client for fetching requests and searching media.
|
||||
* Provides integration with Ombi request management system.
|
||||
*/
|
||||
class OmbiClient {
|
||||
constructor(url, apiKey) {
|
||||
this.url = url.replace(/\/$/, ''); // Remove trailing slash
|
||||
this.apiKey = apiKey;
|
||||
this.axios = axios.create({
|
||||
headers: { 'ApiKey': this.apiKey },
|
||||
timeout: 10000
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all movie requests from Ombi
|
||||
* @returns {Promise<Array>} Array of movie request objects
|
||||
*/
|
||||
async getMovieRequests() {
|
||||
try {
|
||||
const response = await this.axios.get(`${this.url}/api/v1/Request/movie`);
|
||||
return response.data || [];
|
||||
} catch (error) {
|
||||
logToFile(`[OmbiClient] Movie requests error: ${error.message}`);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all TV requests from Ombi
|
||||
* @returns {Promise<Array>} Array of TV request objects
|
||||
*/
|
||||
async getTvRequests() {
|
||||
try {
|
||||
const response = await this.axios.get(`${this.url}/api/v1/Request/tv`);
|
||||
return response.data || [];
|
||||
} catch (error) {
|
||||
logToFile(`[OmbiClient] TV requests error: ${error.message}`);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for movies by TMDB ID
|
||||
* @param {string} tmdbId - TheMovieDB ID
|
||||
* @returns {Promise<Object|null>} Search result object or null if not found
|
||||
*/
|
||||
async searchMovieByTmdbId(tmdbId) {
|
||||
if (!tmdbId) return null;
|
||||
|
||||
try {
|
||||
const response = await this.axios.get(`${this.url}/api/v1/Search/movie/${tmdbId}`);
|
||||
return response.data || null;
|
||||
} catch (error) {
|
||||
logToFile(`[OmbiClient] Movie search error for TMDB ID ${tmdbId}: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for movies by IMDB ID
|
||||
* @param {string} imdbId - IMDB ID
|
||||
* @returns {Promise<Object|null>} Search result object or null if not found
|
||||
*/
|
||||
async searchMovieByImdbId(imdbId) {
|
||||
if (!imdbId) return null;
|
||||
|
||||
try {
|
||||
const response = await this.axios.get(`${this.url}/api/v1/Search/movie/imdb/${imdbId}`);
|
||||
return response.data || null;
|
||||
} catch (error) {
|
||||
logToFile(`[OmbiClient] Movie search error for IMDB ID ${imdbId}: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for TV shows by TVDB ID
|
||||
* @param {string} tvdbId - TheTVDB ID
|
||||
* @returns {Promise<Object|null>} Search result object or null if not found
|
||||
*/
|
||||
async searchTvByTvdbId(tvdbId) {
|
||||
if (!tvdbId) return null;
|
||||
|
||||
try {
|
||||
const response = await this.axios.get(`${this.url}/api/v1/Search/tv/${tvdbId}`);
|
||||
return response.data || null;
|
||||
} catch (error) {
|
||||
logToFile(`[OmbiClient] TV search error for TVDB ID ${tvdbId}: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for TV shows by TMDB ID
|
||||
* @param {string} tmdbId - TheMovieDB ID
|
||||
* @returns {Promise<Object|null>} Search result object or null if not found
|
||||
*/
|
||||
async searchTvByTmdbId(tmdbId) {
|
||||
if (!tmdbId) return null;
|
||||
|
||||
try {
|
||||
const response = await this.axios.get(`${this.url}/api/v1/Search/tv/tmdb/${tmdbId}`);
|
||||
return response.data || null;
|
||||
} catch (error) {
|
||||
logToFile(`[OmbiClient] TV search error for TMDB ID ${tmdbId}: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test connection to Ombi API
|
||||
* @returns {Promise<boolean>} True if connection is successful
|
||||
*/
|
||||
async testConnection() {
|
||||
try {
|
||||
const response = await this.axios.get(`${this.url}/api/v1/Request/movie`);
|
||||
return response.status === 200;
|
||||
} catch (error) {
|
||||
logToFile(`[OmbiClient] Connection test failed: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = OmbiClient;
|
||||
Reference in New Issue
Block a user