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:
@@ -44,6 +44,68 @@ function buildMoviesMapFromRecords(queueRecords, historyRecords) {
|
||||
return moviesMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches a download object with Ombi requests and adds Ombi links
|
||||
* @param {Object} downloadObj - Download object to enhance
|
||||
* @param {Object} seriesOrMovie - Series or movie object from Sonarr/Radarr
|
||||
* @param {Object} context - Context containing Ombi retriever and base URL
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function addOmbiMatching(downloadObj, seriesOrMovie, context) {
|
||||
const { ombiRetriever, ombiBaseUrl } = context;
|
||||
|
||||
if (!ombiRetriever || !ombiBaseUrl || !seriesOrMovie) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let ombiRequest = null;
|
||||
let searchResult = null;
|
||||
|
||||
if (downloadObj.type === 'series') {
|
||||
// For TV shows, try TVDB ID first, then TMDB ID
|
||||
const tvdbId = seriesOrMovie.tvdbId;
|
||||
const tmdbId = seriesOrMovie.tmdbId;
|
||||
|
||||
ombiRequest = await ombiRetriever.findTvRequest(tvdbId, tmdbId);
|
||||
|
||||
if (!ombiRequest) {
|
||||
// Fallback to search
|
||||
searchResult = await ombiRetriever.searchTv(tvdbId, tmdbId);
|
||||
}
|
||||
} else if (downloadObj.type === 'movie') {
|
||||
// For movies, try TMDB ID first, then IMDB ID
|
||||
const tmdbId = seriesOrMovie.tmdbId;
|
||||
const imdbId = seriesOrMovie.imdbId;
|
||||
|
||||
ombiRequest = await ombiRetriever.findMovieRequest(tmdbId, imdbId);
|
||||
|
||||
if (!ombiRequest) {
|
||||
// Fallback to search
|
||||
searchResult = await ombiRetriever.searchMovie(tmdbId, imdbId);
|
||||
}
|
||||
}
|
||||
|
||||
if (ombiRequest) {
|
||||
// Found existing request
|
||||
downloadObj.ombiLink = `${ombiBaseUrl}/#/request/${ombiRequest.type}/${ombiRequest.id}`;
|
||||
downloadObj.ombiRequestId = ombiRequest.id;
|
||||
downloadObj.ombiTooltip = 'Request';
|
||||
} else if (searchResult) {
|
||||
// No request found, but search succeeded
|
||||
if (downloadObj.type === 'series') {
|
||||
downloadObj.ombiLink = `${ombiBaseUrl}/#/tv/search/${searchResult.id}`;
|
||||
} else {
|
||||
downloadObj.ombiLink = `${ombiBaseUrl}/#/movie/search/${searchResult.id}`;
|
||||
}
|
||||
downloadObj.ombiTooltip = 'Search';
|
||||
}
|
||||
} catch (error) {
|
||||
// Silently fail Ombi matching - don't break the download object creation
|
||||
console.error('[DownloadMatcher] Ombi matching error:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the status and speed for a SABnzbd slot based on queue state.
|
||||
* @param {Object} slot - SABnzbd queue slot
|
||||
@@ -68,7 +130,7 @@ function getSlotStatusAndSpeed(slot, queueStatus, queueSpeed, queueKbpersec) {
|
||||
* @param {Object} context - Matching context with records, maps, and user info
|
||||
* @returns {Array} Array of matched download objects
|
||||
*/
|
||||
function matchSabSlots(slots, context) {
|
||||
async function matchSabSlots(slots, context) {
|
||||
const {
|
||||
sonarrQueueRecords,
|
||||
sonarrHistoryRecords,
|
||||
@@ -84,7 +146,9 @@ function matchSabSlots(slots, context) {
|
||||
embyUserMap,
|
||||
queueStatus,
|
||||
queueSpeed,
|
||||
queueKbpersec
|
||||
queueKbpersec,
|
||||
ombiRetriever,
|
||||
ombiBaseUrl
|
||||
} = context;
|
||||
|
||||
const matched = [];
|
||||
@@ -198,6 +262,7 @@ function matchSabSlots(slots, context) {
|
||||
dlObj.arrContentType = 'episode';
|
||||
}
|
||||
dlObj.canBlocklist = DownloadAssembler.canBlocklist(dlObj, isAdmin);
|
||||
await addOmbiMatching(dlObj, series, context);
|
||||
matched.push(dlObj);
|
||||
}
|
||||
}
|
||||
@@ -250,6 +315,7 @@ function matchSabSlots(slots, context) {
|
||||
dlObj.arrContentType = 'movie';
|
||||
}
|
||||
dlObj.canBlocklist = DownloadAssembler.canBlocklist(dlObj, isAdmin);
|
||||
await addOmbiMatching(dlObj, movie, context);
|
||||
matched.push(dlObj);
|
||||
}
|
||||
}
|
||||
@@ -264,7 +330,7 @@ function matchSabSlots(slots, context) {
|
||||
* @param {Object} context - Matching context with records, maps, and user info
|
||||
* @returns {Array} Array of matched download objects
|
||||
*/
|
||||
function matchSabHistory(slots, context) {
|
||||
async function matchSabHistory(slots, context) {
|
||||
const {
|
||||
sonarrHistoryRecords,
|
||||
radarrHistoryRecords,
|
||||
@@ -275,7 +341,9 @@ function matchSabHistory(slots, context) {
|
||||
username,
|
||||
isAdmin,
|
||||
showAll,
|
||||
embyUserMap
|
||||
embyUserMap,
|
||||
ombiRetriever,
|
||||
ombiBaseUrl
|
||||
} = context;
|
||||
|
||||
const matched = [];
|
||||
@@ -317,6 +385,7 @@ function matchSabHistory(slots, context) {
|
||||
dlObj.targetPath = series.path || null;
|
||||
dlObj.arrLink = DownloadAssembler.getSonarrLink(series);
|
||||
}
|
||||
await addOmbiMatching(dlObj, series, context);
|
||||
matched.push(dlObj);
|
||||
}
|
||||
}
|
||||
@@ -355,6 +424,7 @@ function matchSabHistory(slots, context) {
|
||||
dlObj.targetPath = movie.path || null;
|
||||
dlObj.arrLink = DownloadAssembler.getRadarrLink(movie);
|
||||
}
|
||||
await addOmbiMatching(dlObj, movie, context);
|
||||
matched.push(dlObj);
|
||||
}
|
||||
}
|
||||
@@ -369,7 +439,7 @@ function matchSabHistory(slots, context) {
|
||||
* @param {Object} context - Matching context with records, maps, and user info
|
||||
* @returns {Array} Array of matched download objects
|
||||
*/
|
||||
function matchTorrents(torrents, context) {
|
||||
async function matchTorrents(torrents, context) {
|
||||
const {
|
||||
sonarrQueueRecords,
|
||||
sonarrHistoryRecords,
|
||||
@@ -382,7 +452,9 @@ function matchTorrents(torrents, context) {
|
||||
username,
|
||||
isAdmin,
|
||||
showAll,
|
||||
embyUserMap
|
||||
embyUserMap,
|
||||
ombiRetriever,
|
||||
ombiBaseUrl
|
||||
} = context;
|
||||
|
||||
const matched = [];
|
||||
@@ -430,6 +502,7 @@ function matchTorrents(torrents, context) {
|
||||
download.arrContentType = 'episode';
|
||||
}
|
||||
download.canBlocklist = DownloadAssembler.canBlocklist(download, isAdmin);
|
||||
await addOmbiMatching(download, series, context);
|
||||
matched.push(download);
|
||||
matchedAny = true;
|
||||
continue;
|
||||
@@ -474,6 +547,7 @@ function matchTorrents(torrents, context) {
|
||||
download.arrContentType = 'movie';
|
||||
}
|
||||
download.canBlocklist = DownloadAssembler.canBlocklist(download, isAdmin);
|
||||
await addOmbiMatching(download, movie, context);
|
||||
matched.push(download);
|
||||
matchedAny = true;
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user