mirror of
https://github.com/plexguide/Huntarr.io.git
synced 2026-02-09 07:39:18 -06:00
Swaparr Docs Update
This commit is contained in:
@@ -160,6 +160,139 @@
|
||||
</ul>
|
||||
<p><strong>Consider your setup:</strong> If you have many active downloads, shorter intervals help. If you have a slower system or fewer downloads, longer intervals are fine.</p>
|
||||
|
||||
<h2 id="security-features">Security Features</h2>
|
||||
|
||||
<p>Swaparr includes advanced security features to protect your system from malicious downloads and suspicious content by analyzing download names and titles. Detection is based on filename patterns, not file contents.</p>
|
||||
|
||||
<h3 id="malicious-file-detection"><i class="fas fa-shield-alt" style="margin-right: 8px; color: #e74c3c;"></i>Malicious File Detection</h3>
|
||||
<p><strong>What it does:</strong> Automatically detect and immediately remove downloads with malicious file types.</p>
|
||||
<p><strong>How it works:</strong> Scans download names for dangerous file extensions and suspicious patterns. Unlike the strike system, malicious content is removed immediately without warnings.</p>
|
||||
<p><strong>When to enable:</strong> Highly recommended for all users, especially those using public trackers where malicious content is more common.</p>
|
||||
|
||||
<div class="alert alert-warning" style="margin: 15px 0; padding: 15px; background: rgba(255, 193, 7, 0.1); border-left: 4px solid #ffc107;">
|
||||
<strong><i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i>Important:</strong>
|
||||
This feature analyzes filename patterns only, not actual file contents. It's designed to catch obviously malicious downloads based on their names.
|
||||
</div>
|
||||
|
||||
<h3 id="malicious-extensions"><i class="fas fa-file-code" style="margin-right: 8px; color: #e67e22;"></i>Malicious File Extensions</h3>
|
||||
<p><strong>What it does:</strong> File extensions to consider malicious and block immediately.</p>
|
||||
<p><strong>Default blocked extensions:</strong></p>
|
||||
<ul>
|
||||
<li><strong>Executable files:</strong> .exe, .bat, .cmd, .com, .scr, .pif</li>
|
||||
<li><strong>Script files:</strong> .vbs, .js, .jse, .wsf, .wsh</li>
|
||||
<li><strong>Archive formats:</strong> .zipx (suspicious variant)</li>
|
||||
<li><strong>Link files:</strong> .lnk (Windows shortcuts)</li>
|
||||
<li><strong>Java archives:</strong> .jar (can contain malware)</li>
|
||||
</ul>
|
||||
<p><strong>Customization:</strong> Use the tag input system to add or remove extensions. Type the extension (with or without the dot) and press Enter or click the + button.</p>
|
||||
|
||||
<h3 id="suspicious-patterns"><i class="fas fa-search" style="margin-right: 8px; color: #f39c12;"></i>Suspicious Patterns</h3>
|
||||
<p><strong>What it does:</strong> Filename patterns that indicate potentially malicious or unwanted content.</p>
|
||||
<p><strong>Default blocked patterns:</strong></p>
|
||||
<ul>
|
||||
<li><strong>Common malware indicators:</strong> keygen, crack, patch.exe, activator</li>
|
||||
<li><strong>Suspicious files:</strong> password.txt, readme.txt, install.exe, setup.exe</li>
|
||||
</ul>
|
||||
<p><strong>Examples of what gets blocked:</strong></p>
|
||||
<ul>
|
||||
<li>"Movie.Name.2024.1080p.KEYGEN.mkv" - Contains "keygen"</li>
|
||||
<li>"Software.Name.v1.2.Crack.Only.zip" - Contains "crack"</li>
|
||||
<li>"Game.Install.Password.txt.exe" - Contains suspicious pattern</li>
|
||||
</ul>
|
||||
<p><strong>Customization:</strong> Add patterns that are common in your region or specific to content you want to avoid.</p>
|
||||
|
||||
<h2 id="age-based-cleanup">Age-Based Cleanup</h2>
|
||||
|
||||
<p>Age-based cleanup automatically removes downloads that have been stuck for too long, regardless of strike count. This provides a safety net for downloads that might slip through the normal strike system.</p>
|
||||
|
||||
<h3 id="age-based-removal"><i class="fas fa-calendar-times" style="margin-right: 8px; color: #e74c3c;"></i>Enable Age-Based Removal</h3>
|
||||
<p><strong>What it does:</strong> Remove downloads that have been stuck longer than the specified age limit.</p>
|
||||
<p><strong>How it works:</strong> Tracks when Swaparr first noticed each download and removes it after the specified number of days, even if it hasn't reached the maximum strike count.</p>
|
||||
<p><strong>When to use:</strong> Enable this to prevent downloads from sitting in queues indefinitely. Particularly useful for handling edge cases where the normal strike system might not catch problematic downloads.</p>
|
||||
|
||||
<h3 id="max-age-days"><i class="fas fa-hourglass-end" style="margin-right: 8px; color: #f39c12;"></i>Maximum Age (Days)</h3>
|
||||
<p><strong>What it does:</strong> Remove downloads older than this many days (default: 7 days).</p>
|
||||
<p><strong>Recommended values:</strong></p>
|
||||
<ul>
|
||||
<li><strong>3-5 days:</strong> Aggressive cleanup, good for users with reliable download sources</li>
|
||||
<li><strong>7-10 days:</strong> Balanced approach, gives enough time for slow downloads (recommended)</li>
|
||||
<li><strong>14+ days:</strong> Conservative, for users with very slow connections or unreliable trackers</li>
|
||||
</ul>
|
||||
<p><strong>Consider your setup:</strong> Private trackers with limited seeders might need longer age limits. Public trackers with many alternatives can use shorter limits.</p>
|
||||
|
||||
<div class="alert alert-info" style="margin: 15px 0; padding: 15px; background: rgba(13, 202, 240, 0.1); border-left: 4px solid #0dcaf0;">
|
||||
<strong><i class="fas fa-info-circle" style="margin-right: 8px;"></i>Age Tracking:</strong>
|
||||
The age timer starts when Swaparr first sees a download in the queue, not when the download actually started. This ensures accurate tracking across Swaparr restarts.
|
||||
</div>
|
||||
|
||||
<h2 id="quality-based-filtering">Quality-Based Filtering</h2>
|
||||
|
||||
<p>Quality-based filtering automatically removes downloads with poor or undesirable quality indicators in their names. This helps maintain high standards for your media library.</p>
|
||||
|
||||
<h3 id="quality-based-removal"><i class="fas fa-filter" style="margin-right: 8px; color: #9b59b6;"></i>Enable Quality-Based Filtering</h3>
|
||||
<p><strong>What it does:</strong> Automatically remove downloads with blocked quality patterns in their names.</p>
|
||||
<p><strong>How it works:</strong> Scans download names for quality indicators that suggest poor viewing/listening experience. Like malicious file detection, quality-blocked content is removed immediately without strikes.</p>
|
||||
<p><strong>When to use:</strong> Enable if you want to maintain high quality standards and automatically reject low-quality releases.</p>
|
||||
|
||||
<h3 id="blocked-quality-patterns"><i class="fas fa-ban" style="margin-right: 8px; color: #e74c3c;"></i>Blocked Quality Patterns</h3>
|
||||
<p><strong>What it does:</strong> Quality patterns to block based on their indicators in filenames.</p>
|
||||
<p><strong>Default blocked qualities:</strong></p>
|
||||
<ul>
|
||||
<li><strong>Camera recordings:</strong> cam, camrip, hdcam - Recorded in theaters with handheld cameras</li>
|
||||
<li><strong>Telesyncs:</strong> ts, telesync, tc, telecine - Audio/video from different sources, poor sync</li>
|
||||
<li><strong>Pre-retail:</strong> r6, dvdscr, dvdscreener - Pre-release screeners, often watermarked</li>
|
||||
<li><strong>Workprints:</strong> workprint, wp - Unfinished cuts, missing effects or audio</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>Examples of what gets blocked:</strong></p>
|
||||
<ul>
|
||||
<li>"Movie.Name.2024.CAM.XviD.avi" - CAM recording</li>
|
||||
<li>"Show.S01E01.TS.HDTV.x264.mkv" - Telesync quality</li>
|
||||
<li>"Movie.2024.R6.DVDScr.XviD.avi" - DVD screener</li>
|
||||
<li>"New.Movie.2024.WORKPRINT.x264.mp4" - Work print</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>Quality standards comparison:</strong></p>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Quality Type</th>
|
||||
<th>Video Quality</th>
|
||||
<th>Audio Quality</th>
|
||||
<th>Recommendation</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>CAM/TS</strong></td>
|
||||
<td>Very Poor</td>
|
||||
<td>Very Poor</td>
|
||||
<td style="color: #e74c3c;">Block (Default)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>DVDScr/R6</strong></td>
|
||||
<td>Poor</td>
|
||||
<td>Fair</td>
|
||||
<td style="color: #e74c3c;">Block (Default)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>HDTV/WEB-DL</strong></td>
|
||||
<td>Good</td>
|
||||
<td>Good</td>
|
||||
<td style="color: #2ecc71;">Allow</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>BluRay/Remux</strong></td>
|
||||
<td>Excellent</td>
|
||||
<td>Excellent</td>
|
||||
<td style="color: #2ecc71;">Allow</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p><strong>Customization:</strong> Use the tag input system to add quality patterns specific to your preferences. For example, you might want to block "720p" if you only accept 1080p or higher.</p>
|
||||
|
||||
<div class="alert alert-warning" style="margin: 15px 0; padding: 15px; background: rgba(255, 193, 7, 0.1); border-left: 4px solid #ffc107;">
|
||||
<strong><i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i>Be Careful:</strong>
|
||||
Adding too many quality patterns might block legitimate releases. Start with the defaults and add patterns gradually based on your specific needs.
|
||||
</div>
|
||||
|
||||
<h2 id="*arr-instance-setup">*arr Instance Setup</h2>
|
||||
|
||||
<p>Swaparr uses your existing *arr configurations from Huntarr. In the Swaparr configuration, you'll see checkboxes for each of your configured instances:</p>
|
||||
@@ -240,9 +373,24 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Removals</strong></td>
|
||||
<td>Downloads actually removed</td>
|
||||
<td>Downloads removed via strike system</td>
|
||||
<td>When a download reaches max strikes and gets removed</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Malicious Removals</strong></td>
|
||||
<td>Downloads removed for malicious content</td>
|
||||
<td>When malicious file detection blocks a download</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Quality Removals</strong></td>
|
||||
<td>Downloads removed for poor quality</td>
|
||||
<td>When quality-based filtering blocks a download</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Age Removals</strong></td>
|
||||
<td>Downloads removed for being too old</td>
|
||||
<td>When age-based cleanup removes stale downloads</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Ignored</strong></td>
|
||||
<td>Downloads skipped due to rules</td>
|
||||
@@ -285,6 +433,9 @@
|
||||
<li><strong>Ignore Above Size:</strong> 50GB</li>
|
||||
<li><strong>Sleep Duration:</strong> 600 seconds (10 minutes)</li>
|
||||
<li><strong>Remove from Client:</strong> Enabled</li>
|
||||
<li><strong>Malicious File Detection:</strong> Enabled</li>
|
||||
<li><strong>Age-Based Removal:</strong> Enabled (5 days)</li>
|
||||
<li><strong>Quality-Based Filtering:</strong> Enabled (default patterns)</li>
|
||||
</ul>
|
||||
|
||||
<h3><i class="fas fa-balance-scale" style="margin-right: 8px; color: #2ecc71;"></i>Balanced Setup (Most Users)</h3>
|
||||
@@ -294,6 +445,9 @@
|
||||
<li><strong>Ignore Above Size:</strong> 25GB</li>
|
||||
<li><strong>Sleep Duration:</strong> 900 seconds (15 minutes)</li>
|
||||
<li><strong>Remove from Client:</strong> Enabled</li>
|
||||
<li><strong>Malicious File Detection:</strong> Enabled</li>
|
||||
<li><strong>Age-Based Removal:</strong> Enabled (7 days)</li>
|
||||
<li><strong>Quality-Based Filtering:</strong> Optional (based on preferences)</li>
|
||||
</ul>
|
||||
|
||||
<h3><i class="fas fa-shield-alt" style="margin-right: 8px; color: #3498db;"></i>Conservative Setup (Slower Connection, Private Trackers)</h3>
|
||||
@@ -303,6 +457,9 @@
|
||||
<li><strong>Ignore Above Size:</strong> 15GB</li>
|
||||
<li><strong>Sleep Duration:</strong> 1800 seconds (30 minutes)</li>
|
||||
<li><strong>Remove from Client:</strong> Enabled</li>
|
||||
<li><strong>Malicious File Detection:</strong> Enabled</li>
|
||||
<li><strong>Age-Based Removal:</strong> Enabled (14 days)</li>
|
||||
<li><strong>Quality-Based Filtering:</strong> Disabled (manual quality control)</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="troubleshooting">Troubleshooting</h2>
|
||||
|
||||
@@ -1225,6 +1225,91 @@ const SettingsForms = {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-group" style="
|
||||
background: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #334155 100%);
|
||||
border: 2px solid rgba(90, 109, 137, 0.3);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin: 15px 0 25px 0;
|
||||
box-shadow: 0 4px 12px rgba(90, 109, 137, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
">
|
||||
<h3>Age-Based Cleanup</h3>
|
||||
<p class="setting-help" style="margin-bottom: 20px; color: #9ca3af;">
|
||||
Automatically remove downloads that have been stuck for too long, regardless of strike count.
|
||||
</p>
|
||||
|
||||
<div class="setting-item">
|
||||
<label for="swaparr_age_based_removal">
|
||||
<a href="https://plexguide.github.io/Huntarr.io/apps/swaparr.html#age-based-removal" class="info-icon" title="Enable age-based removal" target="_blank" rel="noopener">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</a>
|
||||
Enable Age-Based Removal:
|
||||
</label>
|
||||
<label class="toggle-switch" style="width:40px; height:20px; display:inline-block; position:relative;">
|
||||
<input type="checkbox" id="swaparr_age_based_removal" ${settings.age_based_removal === true ? 'checked' : ''}>
|
||||
<span class="toggle-slider" style="position:absolute; cursor:pointer; top:0; left:0; right:0; bottom:0; background-color:#3d4353; border-radius:20px; transition:0.4s;"></span>
|
||||
</label>
|
||||
<p class="setting-help">Remove downloads that have been stuck longer than the specified age limit</p>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<label for="swaparr_max_age_days">
|
||||
<a href="https://plexguide.github.io/Huntarr.io/apps/swaparr.html#max-age-days" class="info-icon" title="Maximum age before removal" target="_blank" rel="noopener">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</a>
|
||||
Maximum Age (Days):
|
||||
</label>
|
||||
<input type="number" id="swaparr_max_age_days" min="1" max="30" value="${settings.max_age_days || 7}">
|
||||
<p class="setting-help">Remove downloads older than this many days (default: 7 days)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-group" style="
|
||||
background: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #334155 100%);
|
||||
border: 2px solid rgba(90, 109, 137, 0.3);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin: 15px 0 25px 0;
|
||||
box-shadow: 0 4px 12px rgba(90, 109, 137, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
">
|
||||
<h3>Quality-Based Filtering</h3>
|
||||
<p class="setting-help" style="margin-bottom: 20px; color: #9ca3af;">
|
||||
Automatically remove downloads with poor or undesirable quality indicators in their names.
|
||||
</p>
|
||||
|
||||
<div class="setting-item">
|
||||
<label for="swaparr_quality_based_removal">
|
||||
<a href="https://plexguide.github.io/Huntarr.io/apps/swaparr.html#quality-based-removal" class="info-icon" title="Enable quality-based filtering" target="_blank" rel="noopener">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</a>
|
||||
Enable Quality-Based Filtering:
|
||||
</label>
|
||||
<label class="toggle-switch" style="width:40px; height:20px; display:inline-block; position:relative;">
|
||||
<input type="checkbox" id="swaparr_quality_based_removal" ${settings.quality_based_removal === true ? 'checked' : ''}>
|
||||
<span class="toggle-slider" style="position:absolute; cursor:pointer; top:0; left:0; right:0; bottom:0; background-color:#3d4353; border-radius:20px; transition:0.4s;"></span>
|
||||
</label>
|
||||
<p class="setting-help">Automatically remove downloads with blocked quality patterns in their names</p>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<label for="swaparr_quality_patterns_input">
|
||||
<a href="https://plexguide.github.io/Huntarr.io/apps/swaparr.html#blocked-quality-patterns" class="info-icon" title="Quality patterns to block" target="_blank" rel="noopener">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</a>
|
||||
Blocked Quality Patterns:
|
||||
</label>
|
||||
<div class="tag-input-container">
|
||||
<div class="tag-list" id="swaparr_quality_patterns_tags"></div>
|
||||
<div class="tag-input-wrapper">
|
||||
<input type="text" id="swaparr_quality_patterns_input" placeholder="Type quality pattern and press Enter (e.g. cam)" class="tag-input">
|
||||
<button type="button" class="tag-add-btn" onclick="addQualityTag()">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="setting-help">Quality patterns to block. Type pattern and press Enter or click +. Examples: cam, ts, hdcam, workprint</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
`;
|
||||
|
||||
@@ -1276,9 +1361,15 @@ const SettingsForms = {
|
||||
const patterns = settings.suspicious_patterns || defaultPatterns;
|
||||
this.loadTags('swaparr_suspicious_patterns_tags', patterns);
|
||||
|
||||
// Initialize quality patterns
|
||||
const defaultQualityPatterns = ['cam', 'camrip', 'hdcam', 'ts', 'telesync', 'tc', 'telecine', 'r6', 'dvdscr', 'dvdscreener', 'workprint', 'wp'];
|
||||
const qualityPatterns = settings.blocked_quality_patterns || defaultQualityPatterns;
|
||||
this.loadTags('swaparr_quality_patterns_tags', qualityPatterns);
|
||||
|
||||
// Add enter key listeners
|
||||
const extensionInput = document.getElementById('swaparr_malicious_extensions_input');
|
||||
const patternInput = document.getElementById('swaparr_suspicious_patterns_input');
|
||||
const qualityInput = document.getElementById('swaparr_quality_patterns_input');
|
||||
|
||||
if (extensionInput) {
|
||||
extensionInput.addEventListener('keypress', (e) => {
|
||||
@@ -1298,9 +1389,19 @@ const SettingsForms = {
|
||||
});
|
||||
}
|
||||
|
||||
if (qualityInput) {
|
||||
qualityInput.addEventListener('keypress', (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
this.addQualityTag();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Make functions globally accessible
|
||||
window.addExtensionTag = () => this.addExtensionTag();
|
||||
window.addPatternTag = () => this.addPatternTag();
|
||||
window.addQualityTag = () => this.addQualityTag();
|
||||
},
|
||||
|
||||
// Load tags into a tag list
|
||||
@@ -1374,6 +1475,27 @@ const SettingsForms = {
|
||||
input.value = '';
|
||||
},
|
||||
|
||||
// Add quality pattern tag
|
||||
addQualityTag: function() {
|
||||
const input = document.getElementById('swaparr_quality_patterns_input');
|
||||
const container = document.getElementById('swaparr_quality_patterns_tags');
|
||||
|
||||
if (!input || !container) return;
|
||||
|
||||
const value = input.value.trim().toLowerCase();
|
||||
if (!value) return;
|
||||
|
||||
// Check for duplicates
|
||||
const existing = Array.from(container.querySelectorAll('.tag-text')).map(el => el.textContent.toLowerCase());
|
||||
if (existing.includes(value)) {
|
||||
input.value = '';
|
||||
return;
|
||||
}
|
||||
|
||||
this.createTagElement(container, value);
|
||||
input.value = '';
|
||||
},
|
||||
|
||||
// Get tags from a container
|
||||
getTagsFromContainer: function(containerId) {
|
||||
const container = document.getElementById(containerId);
|
||||
@@ -1427,6 +1549,7 @@ const SettingsForms = {
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
||||
container.innerHTML = html;
|
||||
},
|
||||
|
||||
@@ -1766,6 +1889,14 @@ const SettingsForms = {
|
||||
// Get tags from tag containers
|
||||
settings.malicious_extensions = this.getTagsFromContainer('swaparr_malicious_extensions_tags');
|
||||
settings.suspicious_patterns = this.getTagsFromContainer('swaparr_suspicious_patterns_tags');
|
||||
|
||||
// Age-based removal settings
|
||||
settings.age_based_removal = getInputValue('#swaparr_age_based_removal', false);
|
||||
settings.max_age_days = getInputValue('#swaparr_max_age_days', 7);
|
||||
|
||||
// Quality-based removal settings
|
||||
settings.quality_based_removal = getInputValue('#swaparr_quality_based_removal', false);
|
||||
settings.blocked_quality_patterns = this.getTagsFromContainer('swaparr_quality_patterns_tags');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -168,6 +168,51 @@ def check_for_malicious_files(item, settings):
|
||||
|
||||
return False, None
|
||||
|
||||
def check_age_based_removal(item, strike_data, settings):
|
||||
"""Check if download should be removed based on age"""
|
||||
if not settings.get('age_based_removal', False):
|
||||
return False, None
|
||||
|
||||
max_age_days = settings.get('max_age_days', 7)
|
||||
item_id = str(item.get('id', ''))
|
||||
|
||||
# Check if we have strike data for this item
|
||||
if item_id not in strike_data or not strike_data[item_id].get('first_strike_time'):
|
||||
return False, None
|
||||
|
||||
try:
|
||||
first_strike = datetime.fromisoformat(strike_data[item_id]['first_strike_time'].replace('Z', '+00:00'))
|
||||
age_days = (datetime.utcnow() - first_strike).days
|
||||
|
||||
if age_days >= max_age_days:
|
||||
swaparr_logger.warning(f"Age-based removal triggered for '{item['name']}': {age_days} days old (max: {max_age_days})")
|
||||
return True, f"Too old: {age_days} days (max: {max_age_days})"
|
||||
except (ValueError, KeyError) as e:
|
||||
swaparr_logger.error(f"Error parsing first strike time for item {item_id}: {e}")
|
||||
|
||||
return False, None
|
||||
|
||||
def check_quality_based_removal(item, settings):
|
||||
"""Check if download should be removed based on quality"""
|
||||
if not settings.get('quality_based_removal', False):
|
||||
return False, None
|
||||
|
||||
# Use user-defined blocked quality patterns from settings
|
||||
blocked_qualities = settings.get('blocked_quality_patterns', [
|
||||
'cam', 'camrip', 'hdcam', 'ts', 'telesync', 'tc', 'telecine',
|
||||
'r6', 'dvdscr', 'dvdscreener', 'workprint', 'wp'
|
||||
])
|
||||
|
||||
item_name = item.get('name', '').lower()
|
||||
|
||||
# Check for blocked quality patterns
|
||||
for quality in blocked_qualities:
|
||||
if quality.lower() in item_name:
|
||||
swaparr_logger.warning(f"Quality-based removal triggered for '{item['name']}': contains blocked quality '{quality}'")
|
||||
return True, f"Blocked quality: {quality}"
|
||||
|
||||
return False, None
|
||||
|
||||
def parse_time_string_to_seconds(time_string):
|
||||
"""Parse a time string like '2h', '30m', '1d' to seconds"""
|
||||
if not time_string:
|
||||
@@ -508,6 +553,35 @@ def process_stalled_downloads(app_name, instance_name, instance_data, settings):
|
||||
|
||||
continue # Skip to next item - don't process further
|
||||
|
||||
# Check for quality-based removal SECOND - immediate removal without strikes
|
||||
is_quality_blocked, quality_reason = check_quality_based_removal(item, settings)
|
||||
if is_quality_blocked:
|
||||
swaparr_logger.warning(f"QUALITY-BASED REMOVAL: {item['name']} - {quality_reason}")
|
||||
|
||||
if not settings.get("dry_run", False):
|
||||
if delete_download(app_name, instance_data["api_url"], instance_data["api_key"], item["id"], True):
|
||||
swaparr_logger.info(f"Successfully removed quality-blocked download: {item['name']}")
|
||||
|
||||
# Mark as removed to prevent reappearance
|
||||
removed_items[item_hash] = {
|
||||
"name": item["name"],
|
||||
"removed_time": datetime.utcnow().isoformat(),
|
||||
"reason": f"Quality: {quality_reason}",
|
||||
"size": item["size"]
|
||||
}
|
||||
save_removed_items(app_name, removed_items)
|
||||
|
||||
item_state = f"REMOVED (Quality: {quality_reason})"
|
||||
|
||||
# Track quality removal statistics
|
||||
SWAPARR_STATS['quality_removed'] = SWAPARR_STATS.get('quality_removed', 0) + 1
|
||||
increment_swaparr_stat("quality_removals", 1)
|
||||
else:
|
||||
swaparr_logger.info(f"DRY RUN: Would remove quality-blocked download: {item['name']} - {quality_reason}")
|
||||
item_state = f"Would Remove (Quality: {quality_reason})"
|
||||
|
||||
continue # Skip to next item - don't process further
|
||||
|
||||
# Initialize strike count if not already in strike data
|
||||
if item_id not in strike_data:
|
||||
strike_data[item_id] = {
|
||||
@@ -517,6 +591,39 @@ def process_stalled_downloads(app_name, instance_name, instance_data, settings):
|
||||
"last_strike_time": None
|
||||
}
|
||||
|
||||
# Check for age-based removal THIRD - immediate removal without strikes
|
||||
is_age_expired, age_reason = check_age_based_removal(item, strike_data, settings)
|
||||
if is_age_expired:
|
||||
swaparr_logger.warning(f"AGE-BASED REMOVAL: {item['name']} - {age_reason}")
|
||||
|
||||
if not settings.get("dry_run", False):
|
||||
if delete_download(app_name, instance_data["api_url"], instance_data["api_key"], item["id"], True):
|
||||
swaparr_logger.info(f"Successfully removed age-expired download: {item['name']}")
|
||||
|
||||
# Mark as removed to prevent reappearance
|
||||
removed_items[item_hash] = {
|
||||
"name": item["name"],
|
||||
"removed_time": datetime.utcnow().isoformat(),
|
||||
"reason": f"Age: {age_reason}",
|
||||
"size": item["size"]
|
||||
}
|
||||
save_removed_items(app_name, removed_items)
|
||||
|
||||
# Keep the item in strike data for reference but mark as removed
|
||||
strike_data[item_id]["removed"] = True
|
||||
strike_data[item_id]["removed_time"] = datetime.utcnow().isoformat()
|
||||
|
||||
item_state = f"REMOVED (Age: {age_reason})"
|
||||
|
||||
# Track age removal statistics
|
||||
SWAPARR_STATS['age_removed'] = SWAPARR_STATS.get('age_removed', 0) + 1
|
||||
increment_swaparr_stat("age_removals", 1)
|
||||
else:
|
||||
swaparr_logger.info(f"DRY RUN: Would remove age-expired download: {item['name']} - {age_reason}")
|
||||
item_state = f"Would Remove (Age: {age_reason})"
|
||||
|
||||
continue # Skip to next item - don't process further
|
||||
|
||||
# Check if download should be striked
|
||||
should_strike = False
|
||||
strike_reason = ""
|
||||
|
||||
@@ -8,5 +8,9 @@
|
||||
"sleep_duration": 900,
|
||||
"malicious_file_detection": false,
|
||||
"malicious_extensions": [".lnk", ".exe", ".bat", ".cmd", ".scr", ".pif", ".com", ".zipx", ".jar", ".vbs", ".js", ".jse", ".wsf", ".wsh"],
|
||||
"suspicious_patterns": ["password.txt", "readme.txt", "install.exe", "setup.exe", "keygen", "crack", "patch.exe", "activator"]
|
||||
"suspicious_patterns": ["password.txt", "readme.txt", "install.exe", "setup.exe", "keygen", "crack", "patch.exe", "activator"],
|
||||
"age_based_removal": false,
|
||||
"max_age_days": 7,
|
||||
"quality_based_removal": false,
|
||||
"blocked_quality_patterns": ["cam", "camrip", "hdcam", "ts", "telesync", "tc", "telecine", "r6", "dvdscr", "dvdscreener", "workprint", "wp"]
|
||||
}
|
||||
Reference in New Issue
Block a user