Add feature to remove torrent tracker URLs from torrents for private tracker downloads (#99)

- Remove trackers from torrenst/magnet URI

---------

Co-authored-by: Mukhtar Akere <akeremukhtar10@gmail.com>
This commit is contained in:
crashxer
2025-10-22 09:44:23 -06:00
committed by GitHub
parent 7032cc368b
commit 7af90ebe47
25 changed files with 525 additions and 74 deletions
+9 -2
View File
@@ -46,6 +46,13 @@ func (wb *Web) handleAddContent(w http.ResponseWriter, r *http.Request) {
skipMultiSeason := r.FormValue("skipMultiSeason") == "true"
downloadUncached := r.FormValue("downloadUncached") == "true"
rmTrackerUrls := r.FormValue("rmTrackerUrls") == "true"
// Check config setting - if always remove tracker URLs is enabled, force it to true
cfg := config.Get()
if cfg.QBitTorrent.AlwaysRmTrackerUrls {
rmTrackerUrls = true
}
_arr := _store.Arr().Get(arrName)
if _arr == nil {
@@ -63,7 +70,7 @@ func (wb *Web) handleAddContent(w http.ResponseWriter, r *http.Request) {
}
for _, url := range urlList {
magnet, err := utils.GetMagnetFromUrl(url)
magnet, err := utils.GetMagnetFromUrl(url, rmTrackerUrls)
if err != nil {
errs = append(errs, fmt.Sprintf("Failed to parse URL %s: %v", url, err))
continue
@@ -88,7 +95,7 @@ func (wb *Web) handleAddContent(w http.ResponseWriter, r *http.Request) {
continue
}
magnet, err := utils.GetMagnetFromFile(file, fileHeader.Filename)
magnet, err := utils.GetMagnetFromFile(file, fileHeader.Filename, rmTrackerUrls)
if err != nil {
errs = append(errs, fmt.Sprintf("Failed to parse torrent file %s: %v", fileHeader.Filename, err))
continue
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -2
View File
@@ -114,7 +114,7 @@ class ConfigManager {
populateQBittorrentSettings(qbitConfig) {
if (!qbitConfig) return;
const fields = ['download_folder', 'refresh_interval', 'max_downloads', 'skip_pre_cache'];
const fields = ['download_folder', 'refresh_interval', 'max_downloads', 'skip_pre_cache', 'always_rm_tracker_urls'];
fields.forEach(field => {
const element = document.querySelector(`[name="qbit.${field}"]`);
@@ -1183,7 +1183,8 @@ class ConfigManager {
download_folder: document.querySelector('[name="qbit.download_folder"]').value,
refresh_interval: parseInt(document.querySelector('[name="qbit.refresh_interval"]').value) || 30,
max_downloads: parseInt(document.querySelector('[name="qbit.max_downloads"]').value) || 0,
skip_pre_cache: document.querySelector('[name="qbit.skip_pre_cache"]').checked
skip_pre_cache: document.querySelector('[name="qbit.skip_pre_cache"]').checked,
always_rm_tracker_urls: document.querySelector('[name="qbit.always_rm_tracker_urls"]').checked
};
}
+11
View File
@@ -9,6 +9,7 @@ class DownloadManager {
arr: document.getElementById('arr'),
downloadAction: document.getElementById('downloadAction'),
downloadUncached: document.getElementById('downloadUncached'),
rmTrackerUrls: document.getElementById('rmTrackerUrls'),
downloadFolder: document.getElementById('downloadFolder'),
debrid: document.getElementById('debrid'),
submitBtn: document.getElementById('submitDownload'),
@@ -34,6 +35,7 @@ class DownloadManager {
this.refs.arr.addEventListener('change', () => this.saveOptions());
this.refs.downloadAction.addEventListener('change', () => this.saveOptions());
this.refs.downloadUncached.addEventListener('change', () => this.saveOptions());
this.refs.rmTrackerUrls.addEventListener('change', () => this.saveOptions());
this.refs.downloadFolder.addEventListener('change', () => this.saveOptions());
// File input enhancement
@@ -48,12 +50,14 @@ class DownloadManager {
category: localStorage.getItem('downloadCategory') || '',
action: localStorage.getItem('downloadAction') || 'symlink',
uncached: localStorage.getItem('downloadUncached') === 'true',
rmTrackerUrls: localStorage.getItem('rmTrackerUrls') === 'true',
folder: localStorage.getItem('downloadFolder') || this.downloadFolder
};
this.refs.arr.value = savedOptions.category;
this.refs.downloadAction.value = savedOptions.action;
this.refs.downloadUncached.checked = savedOptions.uncached;
this.refs.rmTrackerUrls.checked = savedOptions.rmTrackerUrls;
this.refs.downloadFolder.value = savedOptions.folder;
}
@@ -61,6 +65,12 @@ class DownloadManager {
localStorage.setItem('downloadCategory', this.refs.arr.value);
localStorage.setItem('downloadAction', this.refs.downloadAction.value);
localStorage.setItem('downloadUncached', this.refs.downloadUncached.checked.toString());
// Only save rmTrackerUrls if not disabled (i.e., not forced by config)
if (!this.refs.rmTrackerUrls.disabled) {
localStorage.setItem('rmTrackerUrls', this.refs.rmTrackerUrls.checked.toString());
}
localStorage.setItem('downloadFolder', this.refs.downloadFolder.value);
}
@@ -114,6 +124,7 @@ class DownloadManager {
formData.append('downloadFolder', this.refs.downloadFolder.value);
formData.append('action', this.refs.downloadAction.value);
formData.append('downloadUncached', this.refs.downloadUncached.checked);
formData.append('rmTrackerUrls', this.refs.rmTrackerUrls.checked);
if (this.refs.debrid) {
formData.append('debrid', this.refs.debrid.value);
+10
View File
@@ -346,6 +346,16 @@
</div>
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox" class="checkbox" name="qbit.always_rm_tracker_urls" id="qbit.always_rm_tracker_urls">
<div>
<span class="label-text font-medium">Always Remove Tracker URLs</span>
<div class="label-text-alt">Allows you to <a href="https://sirrobot01.github.io/decypharr/features/repair-worker/private-tracker-downloads" class="link link-hover font-semibold" target="_blank">download private tracker torrents</a> with lower risk</div>
</div>
</label>
</div>
</div>
</div>
</div>
+9
View File
@@ -131,6 +131,15 @@
</div>
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox" class="checkbox" name="rmTrackerUrls" id="rmTrackerUrls" {{ if .AlwaysRmTrackerUrls }}checked disabled{{ end }}>
<div>
<span class="label-text font-medium">Remove Tracker</span>
<div class="label-text-alt">Allows you to <a href="https://sirrobot01.github.io/decypharr/features/repair-worker/private-tracker-downloads" class="link link-hover font-semibold" target="_blank">download private tracker torrents</a> with lower risk</div>
</div>
</label>
</div>
</div>
<div class="form-control">
+9 -8
View File
@@ -130,14 +130,15 @@ func (wb *Web) DownloadHandler(w http.ResponseWriter, r *http.Request) {
debrids = append(debrids, d.Name)
}
data := map[string]interface{}{
"URLBase": cfg.URLBase,
"Page": "download",
"Title": "Download",
"Debrids": debrids,
"HasMultiDebrid": len(debrids) > 1,
"DownloadFolder": cfg.QBitTorrent.DownloadFolder,
"NeedSetup": cfg.CheckSetup() != nil,
"SetupError": cfg.CheckSetup(),
"URLBase": cfg.URLBase,
"Page": "download",
"Title": "Download",
"Debrids": debrids,
"HasMultiDebrid": len(debrids) > 1,
"DownloadFolder": cfg.QBitTorrent.DownloadFolder,
"AlwaysRmTrackerUrls": cfg.QBitTorrent.AlwaysRmTrackerUrls,
"NeedSetup": cfg.CheckSetup() != nil,
"SetupError": cfg.CheckSetup(),
}
_ = wb.templates.ExecuteTemplate(w, "layout", data)
}