Swappar Docs Updates

This commit is contained in:
Admin9705
2025-06-10 08:17:06 -04:00
parent 37932caf1c
commit 719322394f
4 changed files with 250 additions and 136 deletions

View File

@@ -145,6 +145,21 @@
<a href="eros.html">View Documentation →</a>
</div>
</div>
<div class="app-card swaparr-card">
<div class="app-card-header">
<div class="app-card-icon swaparr">
<img src="../images/arrs/swaparr.png" alt="Swaparr Logo" width="48" height="48" style="object-fit: contain;">
</div>
<h3 class="app-card-title">Swaparr</h3>
</div>
<div class="app-card-content">
<p>Monitor and remove stalled downloads from your *arr applications automatically.</p>
</div>
<div class="app-card-footer">
<a href="swaparr.html">View Documentation →</a>
</div>
</div>
</div>
<div class="section-nav">

57
docs/apps/swaparr.html Normal file
View File

@@ -0,0 +1,57 @@
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Swaparr Documentation - Huntarr.io</title><link rel="stylesheet" href="../css/main.css"><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"><script src="../js/main.js" defer></script></head><body>
<div class="sidebar">
<div class="sidebar-logo">
<img src="../images/huntarr-logo.png" alt="Huntarr Logo">
<h2>Huntarr.io</h2>
</div>
<nav class="sidebar-nav">
<div class="sidebar-section">
<h3 class="sidebar-section-title">Getting Started</h3>
<ul>
<li><a href="../donate.html"><i class="fas fa-heart" style="color: #e91e63; font-size: 18px; width: 24px; height: 24px; margin-right: 8px; display: inline-flex; align-items: center; justify-content: center;"></i> Donate</a></li>
<li><a href="../getting-started/installation.html"><svg class="svg-icon" viewBox="0 0 24 24" fill="currentColor"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path></svg> Installation</a></li>
</ul>
</div>
<div class="sidebar-section">
<h3 class="sidebar-section-title">Core</h3>
<ul>
<li><a href="../index.html"><svg class="svg-icon" viewBox="0 0 24 24" fill="currentColor"><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"></path></svg> Home</a></li>
<li class="active"><a href="index.html"><svg class="svg-icon" viewBox="0 0 24 24" fill="currentColor"><path d="M4 8h4V4H4v4zm6 12h4v-4h-4v4zm-6 0h4v-4H4v4zm0-6h4v-4H4v4zm6 0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0 6h4v-4h-4v4z"></path></svg> Apps</a></li>
<li><a href="../settings/settings.html"><svg class="svg-icon" viewBox="0 0 24 24" fill="currentColor"><path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"></path></svg> Settings</a></li>
<li><a href="../features/index.html"><i class="fas fa-star" style="width: 24px; height: 24px; margin-right: 8px; display: inline-flex; align-items: center; justify-content: center;"></i> Features</a></li>
<li><a href="../faq.html"><i class="fas fa-question-circle" style="width: 24px; height: 24px; margin-right: 8px; display: inline-flex; align-items: center; justify-content: center;"></i> FAQ</a></li>
</ul>
</div>
<div class="sidebar-section">
<h3 class="sidebar-section-title">Resources</h3>
<ul>
<li><a href="https://github.com/plexguide/Huntarr.io" target="_blank"><svg class="svg-icon" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"></path></svg> GitHub</a></li>
<li><a href="https://discord.com/invite/PGJJjR5Cww" target="_blank"><i class="fab fa-discord" style="color: #5865F2; font-size: 18px; width: 24px; height: 24px; margin-right: 8px; display: inline-flex; align-items: center; justify-content: center;"></i> Discord</a></li>
<li><a href="https://www.reddit.com/r/huntarr/" target="_blank"><i class="fab fa-reddit-alien" style="color: #FF4500; font-size: 18px; width: 24px; height: 24px; margin-right: 8px; display: inline-flex; align-items: center; justify-content: center;"></i> Reddit</a></li>
</ul>
</div>
</nav>
</div>
<div class="main-content">
<div class="container">
<h1>Sonarr Documentation</h1>
<div style="text-align: center; margin: 20px auto;">
<img src="../images/arrs/sonarr.png" alt="Sonarr Logo" style="width: 80px; height: 80px; object-fit: contain;">
</div>
<p>Sonarr is an automated TV show downloading and management application. Huntarr integrates with your existing Sonarr instance to automatically search for missing episodes and quality upgrades that Sonarr doesn't actively hunt for.</p>
<h2 id="sonarr-instance-setup">Sonarr Instance Setup</h2>
<div class="main-content"><div class="container"><h1>Swaparr Documentation</h1><div style="text-align: center; margin: 20px auto;"><img src="../images/arrs/swaparr.png" alt="Swaparr Logo" style="width: 80px; height: 80px; object-fit: contain;"></div>
<div class="alert alert-warning" style="margin: 20px 0; padding: 15px; background: rgba(255, 193, 7, 0.1); border-left: 4px solid #ffc107;"><strong><i class="fas fa-info-circle" style="margin-right: 8px;"></i>Beta Notice:</strong> Swaparr is a rewritten implementation by Admin9705 for Huntarr integration. Please note that the original Swaparr project does not provide support for this Huntarr-specific implementation. For Huntarr-related issues, use Huntarr's support channels.</div>
<p>Swaparr is an automated download monitoring and cleanup utility that works with your *arr applications (Sonarr, Radarr, Lidarr, etc.). It monitors your download queues and automatically removes stalled, failed, or problematic downloads to keep your automation running smoothly.</p><div class="alert alert-info" style="margin: 20px 0; padding: 15px; background: rgba(13, 202, 240, 0.1); border-left: 4px solid #0dcaf0;"><strong><i class="fas fa-star" style="margin-right: 8px; color: #fbbf24;"></i>Project Credit:</strong> Original Swaparr by <a href="https://github.com/ThijmenGThN" target="_blank" style="color: #0dcaf0;">ThijmenGThN</a> • GitHub Stars: ⭐ 172 • Version: v0.10.0 • <a href="https://github.com/ThijmenGThN/swaparr" target="_blank" style="color: #fbbf24;">⭐ Star the Project</a></div>
<h2>Configuration</h2><h3>*arr Instance Setup</h3><p>Configure which of your *arr applications Swaparr should monitor using your existing Huntarr configurations.</p><h3>Monitoring Settings</h3><ul><li><strong>Sleep Duration:</strong> Time between monitoring cycles (recommended: 15-30 minutes)</li><li><strong>Strike Threshold:</strong> Number of times a download must be flagged before removal</li><li><strong>Dry Run Mode:</strong> Test mode that logs actions without actually removing downloads</li></ul>
<h2>How Swaparr Helps</h2><p>Swaparr automatically identifies and removes problematic downloads that can clog your download queues, including stalled downloads, failed imports, and stuck items. It uses a configurable strike system to ensure downloads are truly problematic before removal.</p><div class="section-nav"><a href="index.html">← Back to Apps</a><a href="../settings/settings.html">Settings Documentation →</a></div><footer>Huntarr.io | Swaparr Documentation | Thanks 4 Using Huntarr - Admin9705</footer></div></div></body></html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

View File

@@ -975,11 +975,80 @@ const SettingsForms = {
container.setAttribute('data-app-type', 'swaparr');
const html = `
<!-- Swaparr Developer Credit Section -->
<div class="settings-group" style="margin-bottom: 25px;">
<div class="swaparr-credit-section" style="
background: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #334155 100%);
border: 2px solid #00c2ce;
border-radius: 12px;
padding: 20px;
margin: 15px 0 25px 0;
box-shadow: 0 8px 25px rgba(0, 194, 206, 0.2);
">
<div style="
background: rgba(255, 255, 255, 0.05);
border-radius: 8px;
padding: 15px;
margin: 15px 0;
border-left: 4px solid #00c2ce;
">
<p style="color: #e2e8f0; margin: 0 0 8px 0; font-size: 0.95em; line-height: 1.6;">
<strong>Developer:</strong> <a href="https://github.com/ThijmenGThN" target="_blank" rel="noopener" style="color: #00c2ce; text-decoration: none;">ThijmenGThN</a> •
<strong>GitHub Stars:</strong> <span style="color: #fbbf24;">⭐ <span id="swaparr-stars-count">172</span></span> •
<strong>Version:</strong> v0.10.0
</p>
<p style="color: #cbd5e1; margin: 0; font-size: 0.85em; line-height: 1.4; font-style: italic;">
<strong>Beta Notice:</strong> This is a rewritten implementation by Admin9705 for Huntarr integration.
Please note that the original Swaparr project does not provide support for this Huntarr-specific implementation.
For Huntarr-related issues, use Huntarr's support channels.
</p>
</div>
<div style="text-align: center; margin: 15px 0;">
<a href="https://github.com/ThijmenGThN/swaparr" target="_blank" rel="noopener" style="
display: inline-block;
background: linear-gradient(90deg, #00c2ce 0%, #0891b2 100%);
color: white;
padding: 8px 16px;
border-radius: 6px;
text-decoration: none;
font-weight: 500;
font-size: 0.9em;
transition: all 0.3s ease;
margin-right: 10px;
" onmouseover="this.style.transform='scale(1.05)'" onmouseout="this.style.transform='scale(1)'">
<i class="fas fa-star" style="margin-right: 5px;"></i>
Star Swaparr Project
</a>
</div>
</div>
<!-- Advanced Options Notice -->
<div style="
background: linear-gradient(135deg, #164e63 0%, #0e7490 50%, #0891b2 100%);
border: 1px solid #22d3ee;
border-radius: 8px;
padding: 15px;
margin: 15px 0 20px 0;
box-shadow: 0 4px 12px rgba(34, 211, 238, 0.15);
">
<p style="color: #e0f7fa; margin: 0; font-size: 0.9em; line-height: 1.5;">
<i class="fas fa-rocket" style="margin-right: 8px; color: #22d3ee;"></i>
<strong>Need Advanced Options?</strong> For enhanced control and features, we recommend
<a href="https://github.com/flmorg/cleanuperr" target="_blank" rel="noopener" style="color: #fbbf24; text-decoration: none; font-weight: 600;">
<strong>Cleanuperr</strong>
</a> which offers more comprehensive management capabilities.
</p>
</div>
</div>
<div class="settings-group">
<h3>Swaparr Configuration</h3>
<p class="setting-help" style="margin-bottom: 20px; color: #9ca3af;">
Swaparr monitors your *arr applications' download queues and removes stalled downloads automatically.
Based on <a href="https://github.com/ThijmenGThN/swaparr" target="_blank" style="color: #3b82f6;">Swaparr v0.10.0</a>.
</p>
<div class="setting-item">
@@ -1075,40 +1144,13 @@ const SettingsForms = {
</div>
</div>
<div class="settings-group">
<h3>Swaparr Status</h3>
<div id="swaparrStatus" class="status-panel">
<div class="loading-panel">
<i class="fas fa-spinner fa-spin"></i> Loading status...
</div>
</div>
<div style="margin-top: 15px; display: flex; gap: 10px; align-items: center;">
<button type="button" id="resetSwaparrBtn" class="btn btn-secondary" style="background-color: #dc2626; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 14px;">
<i class="fas fa-undo"></i> Reset Data
</button>
<button type="button" id="resetSwaparrCycleBtn" class="btn btn-secondary cycle-reset-button" data-app="swaparr" style="background-color: #00c2ce; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 14px;">
<i class="fas fa-sync-alt"></i> Reset Cycle
</button>
</div>
</div>
`;
container.innerHTML = html;
// Load status immediately
this.loadSwaparrStatus(container);
// Set up button event listeners
const resetBtn = container.querySelector('#resetSwaparrBtn');
const resetCycleBtn = container.querySelector('#resetSwaparrCycleBtn');
if (resetBtn) {
resetBtn.addEventListener('click', () => this.resetSwaparrData(resetBtn));
}
if (resetCycleBtn) {
resetCycleBtn.addEventListener('click', () => this.resetSwaparrCycle(resetCycleBtn));
}
// Load Swaparr GitHub star count dynamically
this.loadSwaparrStarCount();
// Add event listener for sleep duration display update
const sleepInput = container.querySelector('#swaparr_sleep_duration');
@@ -1138,130 +1180,130 @@ const SettingsForms = {
}
},
// Load Swaparr status
loadSwaparrStatus: function(container) {
const statusPanel = container.querySelector('#swaparrStatus');
if (!statusPanel) return;
// Generate Hunt Manager placeholder form
generateHuntingForm: function(container, settings = {}) {
// Add data-app-type attribute to container
container.setAttribute('data-app-type', 'hunting');
HuntarrUtils.fetchWithTimeout('./api/swaparr/status')
.then(response => response.json())
.then(data => {
const sessionStats = data.session_statistics || {};
const appStats = data.app_statistics || {};
const settings = data.settings || {};
let statusHtml = `
<div class="status-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 15px;">
<div class="stat-item">
<div class="stat-label">Session Processed</div>
<div class="stat-value" style="color: #3b82f6;">${sessionStats.processed || 0}</div>
</div>
<div class="stat-item">
<div class="stat-label">Session Strikes</div>
<div class="stat-value" style="color: #f59e0b;">${sessionStats.strikes || 0}</div>
</div>
<div class="stat-item">
<div class="stat-label">Session Removals</div>
<div class="stat-value" style="color: #ef4444;">${sessionStats.removals || 0}</div>
</div>
<div class="stat-item">
<div class="stat-label">Session Ignored</div>
<div class="stat-value" style="color: #6b7280;">${sessionStats.ignored || 0}</div>
</div>
const html = `
<div class="settings-group">
<div class="development-notice" style="
background: linear-gradient(135deg, #1e3a8a 0%, #3b82f6 100%);
border: 2px solid #60a5fa;
border-radius: 12px;
padding: 25px;
margin: 20px 0;
text-align: center;
box-shadow: 0 8px 25px rgba(59, 130, 246, 0.3);
">
<div style="margin-bottom: 15px;">
<i class="fas fa-code-branch" style="font-size: 2.5em; color: #60a5fa; margin-bottom: 10px;"></i>
</div>
`;
// Countdown Timer section
statusHtml += `
<div class="countdown-summary" style="margin-top: 15px; padding: 10px; background-color: rgba(0,0,0,0.2); border-radius: 6px;">
<h4>Countdown Timer</h4>
<div id="swaparrCycleTimer" class="cycle-timer" style="display: flex; align-items: center; justify-content: center; font-size: 0.9rem; padding: 8px 12px; border-radius: 4px; margin: 8px auto 6px auto; background-color: rgba(0, 0, 0, 0.15); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); transition: all 0.3s ease; user-select: none; max-width: 200px; border-left: 2px solid #00c2ce;">
<i class="fas fa-clock" style="margin-right: 5px; font-size: 0.9rem;"></i>
<span class="timer-value" style="font-family: monospace; font-weight: 600; color: white;">--:--:--</span>
</div>
<h3 style="color: white; margin: 0 0 15px 0; font-size: 1.4em; font-weight: 600;">
Hunt Manager - Under Development
</h3>
<p style="color: #dbeafe; margin: 0 0 20px 0; font-size: 1.1em; line-height: 1.6;">
Hunt Manager is currently in active development and serves as a placeholder for upcoming advanced media discovery features.
This module will provide sophisticated hunting algorithms and enhanced discovery mechanisms for your media library.
</p>
<div style="
background: rgba(255, 255, 255, 0.1);
border-radius: 8px;
padding: 15px;
margin: 15px 0;
border-left: 4px solid #60a5fa;
">
<p style="color: #f1f5f9; margin: 0; font-size: 0.95em;">
<i class="fas fa-info-circle" style="margin-right: 8px; color: #60a5fa;"></i>
<strong>Current Status:</strong> Planning & Architecture Phase
</p>
</div>
`;
statusPanel.innerHTML = statusHtml;
// Initialize countdown timer for Swaparr if CycleCountdown is available
if (window.CycleCountdown) {
console.log('Initializing Swaparr countdown timer');
// The countdown will be handled by the existing CycleCountdown system
// which will find the swaparrCycleTimer element and the cycle-reset-button
}
})
.catch(error => {
console.error('Error loading Swaparr status:', error);
statusPanel.innerHTML = `
<div class="error-message" style="color: #ef4444; text-align: center;">
<i class="fas fa-exclamation-triangle"></i>
Failed to load status. Check if any *arr apps are configured.
</div>
`;
});
<p style="color: #cbd5e1; margin: 10px 0 0 0; font-size: 0.9em;">
Stay tuned for updates as we continue to enhance Huntarr's capabilities!
</p>
</div>
</div>
`;
container.innerHTML = html;
},
// Reset Swaparr data
resetSwaparrData: function(button) {
if (!confirm('Are you sure you want to reset all Swaparr data? This will clear strikes and removed items.')) {
return;
// Load Swaparr GitHub star count dynamically
loadSwaparrStarCount: function() {
const starsElement = document.getElementById('swaparr-stars-count');
if (!starsElement) return;
// First, try to load from cache immediately for fast display
const cachedData = localStorage.getItem('swaparr-github-stars');
if (cachedData) {
try {
const parsed = JSON.parse(cachedData);
if (parsed.stars !== undefined) {
starsElement.textContent = parsed.stars.toLocaleString();
// If cache is recent (less than 1 hour), skip API call
const cacheAge = Date.now() - (parsed.timestamp || 0);
if (cacheAge < 3600000) { // 1 hour = 3600000ms
return;
}
}
} catch (e) {
console.warn('Invalid cached Swaparr star data, will fetch fresh');
localStorage.removeItem('swaparr-github-stars');
}
}
const originalText = button.innerHTML;
button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Resetting...';
button.disabled = true;
starsElement.textContent = 'Loading...';
HuntarrUtils.fetchWithTimeout('./api/swaparr/reset', { method: 'POST' })
.then(response => response.json())
// GitHub API endpoint for Swaparr repository
const apiUrl = 'https://api.github.com/repos/ThijmenGThN/swaparr';
HuntarrUtils.fetchWithTimeout(apiUrl)
.then(response => {
if (!response.ok) {
throw new Error(`GitHub API error: ${response.status}`);
}
return response.json();
})
.then(data => {
button.innerHTML = originalText;
button.disabled = false;
if (data.success) {
alert('Swaparr data reset successfully!');
// Reload status
const container = button.closest('.settings-group').parentElement;
this.loadSwaparrStatus(container);
if (data && data.stargazers_count !== undefined) {
// Format the number with commas for thousands
const formattedStars = data.stargazers_count.toLocaleString();
starsElement.textContent = formattedStars;
// Store in localStorage to avoid excessive API requests
const cacheData = {
stars: data.stargazers_count,
timestamp: Date.now()
};
localStorage.setItem('swaparr-github-stars', JSON.stringify(cacheData));
} else {
alert(`Reset failed: ${data.message || 'Unknown error'}`);
throw new Error('Star count not found in response');
}
})
.catch(error => {
button.innerHTML = originalText;
button.disabled = false;
alert(`Reset failed: ${error.message}`);
});
},
// Reset Swaparr cycle
resetSwaparrCycle: function(button) {
const originalText = button.innerHTML;
button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Resetting...';
button.disabled = true;
HuntarrUtils.fetchWithTimeout('./api/cycle/reset/swaparr', { method: 'POST' })
.then(response => response.json())
.then(data => {
button.innerHTML = originalText;
button.disabled = false;
console.error('Error fetching Swaparr GitHub stars:', error);
if (data.success) {
alert('Swaparr cycle reset successfully!');
// Trigger countdown timer update if available
if (window.CycleCountdown) {
console.log('Cycle reset completed for Swaparr, CycleCountdown will handle the refresh');
// Try to load from cache if we have it
const cachedData = localStorage.getItem('swaparr-github-stars');
if (cachedData) {
try {
const parsed = JSON.parse(cachedData);
if (parsed.stars !== undefined) {
starsElement.textContent = parsed.stars.toLocaleString();
} else {
starsElement.textContent = '172'; // Fallback to known value
}
} catch (e) {
console.error('Failed to parse cached Swaparr star data:', e);
starsElement.textContent = '172'; // Fallback to known value
localStorage.removeItem('swaparr-github-stars'); // Clear bad cache
}
} else {
alert(`Cycle reset failed: ${data.message || 'Unknown error'}`);
starsElement.textContent = '172'; // Fallback to known value
}
})
.catch(error => {
button.innerHTML = originalText;
button.disabled = false;
alert(`Cycle reset failed: ${error.message}`);
});
},
// Format date nicely for display
formatDate: function(date) {