Skip to content

Commit 332a9a7

Browse files
committed
Add detailed Prowlarr status reporting and UI updates
- Implemented Prowlarr status polling in the frontend, refreshing every 30 seconds when the home section is active. - Enhanced the backend API to return detailed indexer information, including active, throttled, and failed indexers. - Updated the UI to display connection status, indexer statistics, and health status with improved error handling and user feedback. - Added manual refresh functionality for Prowlarr data in the UI.
1 parent 66ab6b5 commit 332a9a7

File tree

2 files changed

+169
-14
lines changed

2 files changed

+169
-14
lines changed

frontend/static/js/new-main.js

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4642,6 +4642,150 @@ let huntarrUI = {
46424642
// Fall back to loading Swaparr status/info
46434643
this.loadSwaparrStatus();
46444644
}
4645+
},
4646+
4647+
// Setup Prowlarr status polling
4648+
setupProwlarrStatusPolling: function() {
4649+
console.log('[huntarrUI] Setting up Prowlarr status polling');
4650+
4651+
// Load initial status
4652+
this.loadProwlarrStatus();
4653+
4654+
// Set up polling to refresh Prowlarr status every 30 seconds
4655+
// Only poll when home section is active to reduce unnecessary requests
4656+
this.prowlarrPollingInterval = setInterval(() => {
4657+
if (this.currentSection === 'home') {
4658+
this.loadProwlarrStatus();
4659+
}
4660+
}, 30000);
4661+
4662+
// Set up refresh button handler
4663+
const refreshButton = document.getElementById('refresh-prowlarr-data');
4664+
if (refreshButton) {
4665+
refreshButton.addEventListener('click', () => {
4666+
console.log('[huntarrUI] Manual Prowlarr refresh triggered');
4667+
this.loadProwlarrStatus();
4668+
});
4669+
}
4670+
},
4671+
4672+
// Load and update Prowlarr status card
4673+
loadProwlarrStatus: function() {
4674+
console.log('[huntarrUI] Loading Prowlarr status');
4675+
4676+
HuntarrUtils.fetchWithTimeout('./api/prowlarr/stats')
4677+
.then(response => response.json())
4678+
.then(data => {
4679+
console.log('[huntarrUI] Prowlarr stats received:', data);
4680+
4681+
const prowlarrCard = document.getElementById('prowlarrStatusCard');
4682+
if (!prowlarrCard) {
4683+
console.log('[huntarrUI] Prowlarr card not found in DOM');
4684+
return;
4685+
}
4686+
4687+
if (data.success && data.stats) {
4688+
const stats = data.stats;
4689+
4690+
// Show the card since we have data
4691+
prowlarrCard.style.display = 'block';
4692+
4693+
// Update connection status
4694+
const connectionStatus = document.getElementById('prowlarrConnectionStatus');
4695+
if (connectionStatus) {
4696+
if (stats.connected) {
4697+
connectionStatus.textContent = '🟢 Connected';
4698+
connectionStatus.className = 'status-badge connected';
4699+
} else {
4700+
connectionStatus.textContent = '🔴 Disconnected';
4701+
connectionStatus.className = 'status-badge disconnected';
4702+
}
4703+
}
4704+
4705+
// Update stats display
4706+
const updateElement = (id, value, tooltip = '') => {
4707+
const element = document.getElementById(id);
4708+
if (element) {
4709+
element.textContent = value || '--';
4710+
if (tooltip) {
4711+
element.title = tooltip;
4712+
}
4713+
}
4714+
};
4715+
4716+
// Update basic stats
4717+
updateElement('prowlarr-active-indexers', stats.active_indexers);
4718+
updateElement('prowlarr-total-calls', stats.total_api_calls);
4719+
updateElement('prowlarr-throttled', stats.throttled_indexers);
4720+
updateElement('prowlarr-failed', stats.failed_indexers);
4721+
4722+
// Update detailed tooltips with indexer names if available
4723+
if (stats.indexer_details) {
4724+
const activeNames = stats.indexer_details.active?.map(idx => idx.name).join(', ') || 'None';
4725+
const throttledNames = stats.indexer_details.throttled?.map(idx => idx.name).join(', ') || 'None';
4726+
const failedNames = stats.indexer_details.failed?.map(idx => idx.name).join(', ') || 'None';
4727+
4728+
updateElement('prowlarr-active-indexers', stats.active_indexers, `Active: ${activeNames}`);
4729+
updateElement('prowlarr-throttled', stats.throttled_indexers, `Throttled: ${throttledNames}`);
4730+
updateElement('prowlarr-failed', stats.failed_indexers, `Failed: ${failedNames}`);
4731+
}
4732+
4733+
// Update health status
4734+
const healthStatus = document.getElementById('prowlarr-health-status');
4735+
if (healthStatus) {
4736+
healthStatus.textContent = stats.health_status || 'Unknown';
4737+
4738+
// Color-code health status
4739+
healthStatus.className = 'health-status-text';
4740+
if (stats.health_status?.includes('healthy')) {
4741+
healthStatus.style.color = '#10b981'; // Green
4742+
} else if (stats.health_status?.includes('throttled')) {
4743+
healthStatus.style.color = '#f59e0b'; // Amber
4744+
} else if (stats.health_status?.includes('failed') || stats.health_status?.includes('disabled')) {
4745+
healthStatus.style.color = '#ef4444'; // Red
4746+
} else {
4747+
healthStatus.style.color = '#9ca3af'; // Gray
4748+
}
4749+
}
4750+
4751+
} else {
4752+
// Handle error case
4753+
console.log('[huntarrUI] Error in Prowlarr stats:', data.message || 'Unknown error');
4754+
4755+
// Still show the card but with error states
4756+
prowlarrCard.style.display = 'block';
4757+
4758+
const connectionStatus = document.getElementById('prowlarrConnectionStatus');
4759+
if (connectionStatus) {
4760+
connectionStatus.textContent = '🔴 Error';
4761+
connectionStatus.className = 'status-badge error';
4762+
}
4763+
4764+
// Set all stats to error state
4765+
['prowlarr-active-indexers', 'prowlarr-total-calls', 'prowlarr-throttled', 'prowlarr-failed'].forEach(id => {
4766+
const element = document.getElementById(id);
4767+
if (element) {
4768+
element.textContent = '--';
4769+
element.title = data.message || 'Connection error';
4770+
}
4771+
});
4772+
4773+
const healthStatus = document.getElementById('prowlarr-health-status');
4774+
if (healthStatus) {
4775+
healthStatus.textContent = data.message || 'Connection error';
4776+
healthStatus.style.color = '#ef4444'; // Red
4777+
}
4778+
}
4779+
})
4780+
.catch(error => {
4781+
console.error('[huntarrUI] Error loading Prowlarr status:', error);
4782+
4783+
// Hide the card on error
4784+
const prowlarrCard = document.getElementById('prowlarrStatusCard');
4785+
if (prowlarrCard) {
4786+
prowlarrCard.style.display = 'none';
4787+
}
4788+
});
46454789
}
46464790
};
46474791

src/primary/apps/prowlarr_routes.py

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -205,33 +205,44 @@ def get_prowlarr_stats():
205205
indexers = indexers_response.json()
206206
stats['total_indexers'] = len(indexers)
207207

208-
# Count active, throttled, and failed indexers
209-
active_count = 0
210-
throttled_count = 0
211-
failed_count = 0
208+
# Process indexers and collect detailed information
209+
active_indexers = []
210+
throttled_indexers = []
211+
failed_indexers = []
212212

213213
for indexer in indexers:
214+
indexer_info = {
215+
'name': indexer.get('name', 'Unknown'),
216+
'protocol': indexer.get('protocol', 'unknown'),
217+
'id': indexer.get('id')
218+
}
219+
214220
if indexer.get('enable', False):
215-
active_count += 1
221+
active_indexers.append(indexer_info)
216222

217223
# Check for throttling/rate limiting
218224
capabilities = indexer.get('capabilities', {})
219225
if capabilities.get('limitsexceeded', False):
220-
throttled_count += 1
226+
throttled_indexers.append(indexer_info)
221227

222228
# Check for failures - look for disabled indexers or low priority
223229
if not indexer.get('enable', False):
224-
failed_count += 1
230+
failed_indexers.append(indexer_info)
225231

226-
stats['active_indexers'] = active_count
227-
stats['throttled_indexers'] = throttled_count
228-
stats['failed_indexers'] = failed_count
232+
stats['active_indexers'] = len(active_indexers)
233+
stats['throttled_indexers'] = len(throttled_indexers)
234+
stats['failed_indexers'] = len(failed_indexers)
235+
stats['indexer_details'] = {
236+
'active': active_indexers,
237+
'throttled': throttled_indexers,
238+
'failed': failed_indexers
239+
}
229240

230241
# Update health status based on indexer health
231-
if throttled_count > 0:
232-
stats['health_status'] = f'{throttled_count} indexer(s) throttled'
233-
elif failed_count > 0:
234-
stats['health_status'] = f'{failed_count} indexer(s) disabled'
242+
if len(throttled_indexers) > 0:
243+
stats['health_status'] = f'{len(throttled_indexers)} indexer(s) throttled'
244+
elif len(failed_indexers) > 0:
245+
stats['health_status'] = f'{len(failed_indexers)} indexer(s) disabled'
235246
else:
236247
stats['health_status'] = 'All indexers healthy'
237248

0 commit comments

Comments
 (0)