- Fix ARR flaky bug

- Refined download uncached options
- Deprecate qbittorent log level
- Skip Repair for specified arr
This commit is contained in:
Mukhtar Akere
2025-03-09 03:56:34 +01:00
parent a83f3d72ce
commit 2b2a682218
26 changed files with 276 additions and 181 deletions
+14 -7
View File
@@ -307,10 +307,11 @@ func (ui *Handler) handleAddContent(w http.ResponseWriter, r *http.Request) {
arrName := r.FormValue("arr")
notSymlink := r.FormValue("notSymlink") == "true"
downloadUncached := r.FormValue("downloadUncached") == "true"
_arr := svc.Arr.Get(arrName)
if _arr == nil {
_arr = arr.New(arrName, "", "", false)
_arr = arr.New(arrName, "", "", false, false, false)
}
// Handle URLs
@@ -323,7 +324,7 @@ func (ui *Handler) handleAddContent(w http.ResponseWriter, r *http.Request) {
}
for _, url := range urlList {
importReq := qbit.NewImportRequest(url, _arr, !notSymlink)
importReq := qbit.NewImportRequest(url, _arr, !notSymlink, downloadUncached)
err := importReq.Process(ui.qbit)
if err != nil {
errs = append(errs, fmt.Sprintf("URL %s: %v", url, err))
@@ -348,7 +349,7 @@ func (ui *Handler) handleAddContent(w http.ResponseWriter, r *http.Request) {
continue
}
importReq := qbit.NewImportRequest(magnet.Link, _arr, !notSymlink)
importReq := qbit.NewImportRequest(magnet.Link, _arr, !notSymlink, downloadUncached)
err = importReq.Process(ui.qbit)
if err != nil {
errs = append(errs, fmt.Sprintf("File %s: %v", fileHeader.Filename, err))
@@ -384,7 +385,7 @@ func (ui *Handler) handleRepairMedia(w http.ResponseWriter, r *http.Request) {
if req.Async {
go func() {
if err := svc.Repair.AddJob([]string{req.ArrName}, req.MediaIds, req.AutoProcess); err != nil {
if err := svc.Repair.AddJob([]string{req.ArrName}, req.MediaIds, req.AutoProcess, false); err != nil {
ui.logger.Error().Err(err).Msg("Failed to repair media")
}
}()
@@ -392,10 +393,9 @@ func (ui *Handler) handleRepairMedia(w http.ResponseWriter, r *http.Request) {
return
}
if err := svc.Repair.AddJob([]string{req.ArrName}, req.MediaIds, req.AutoProcess); err != nil {
if err := svc.Repair.AddJob([]string{req.ArrName}, req.MediaIds, req.AutoProcess, false); err != nil {
http.Error(w, fmt.Sprintf("Failed to repair: %v", err), http.StatusInternalServerError)
return
}
request.JSONResponse(w, "Repair completed", http.StatusOK)
@@ -437,7 +437,14 @@ func (ui *Handler) handleGetConfig(w http.ResponseWriter, r *http.Request) {
arrCfgs := make([]config.Arr, 0)
svc := service.GetService()
for _, a := range svc.Arr.GetAll() {
arrCfgs = append(arrCfgs, config.Arr{Host: a.Host, Name: a.Name, Token: a.Token, Cleanup: a.Cleanup})
arrCfgs = append(arrCfgs, config.Arr{
Host: a.Host,
Name: a.Name,
Token: a.Token,
Cleanup: a.Cleanup,
SkipRepair: a.SkipRepair,
DownloadUncached: a.DownloadUncached,
})
}
cfg.Arrs = arrCfgs
request.JSONResponse(w, cfg, http.StatusOK)
+14 -14
View File
@@ -12,7 +12,7 @@
<div class="col-md-6">
<div class="form-group">
<label for="qbitDebug">Log Level</label>
<select class="form-select" name="qbit.log_level" id="log-level" disabled>
<select class="form-select" name="log_level" id="log-level" disabled>
<option value="info">Info</option>
<option value="debug">Debug</option>
<option value="warn">Warning</option>
@@ -114,18 +114,6 @@
<label class="form-label">Refresh Interval (seconds)</label>
<input type="number" class="form-control" name="qbit.refresh_interval">
</div>
<div class="col-12 mb-3">
<div class="form-group">
<label for="qbitDebug">Log Level</label>
<select class="form-select" name="qbit.log_level" id="qbitDebug" disabled>
<option value="info">Info</option>
<option value="debug">Debug</option>
<option value="warn">Warning</option>
<option value="error">Error</option>
<option value="trace">Trace</option>
</select>
</div>
</div>
</div>
</div>
@@ -225,10 +213,22 @@
<div class="row">
<div class="col-md-2 mb-3">
<div class="form-check">
<label class="form-check-label" for="repairOnStart">Cleanup Queue</label>
<label class="form-check-label">Cleanup Queue</label>
<input type="checkbox" disabled class="form-check-input" name="arr[${index}].cleanup">
</div>
</div>
<div class="col-md-2 mb-3">
<div class="form-check">
<label class="form-check-label">Skip Repair</label>
<input type="checkbox" disabled class="form-check-input" name="arr[${index}].skip_repair">
</div>
</div>
<div class="col-md-2 mb-3">
<div class="form-check">
<label class="form-check-label">Download Uncached</label>
<input type="checkbox" disabled class="form-check-input" name="arr[${index}].download_uncached">
</div>
</div>
</div>
</div>
`;
+20 -7
View File
@@ -22,13 +22,21 @@
<input type="text" class="form-control" id="category" name="arr" placeholder="Enter Category (e.g sonarr, radarr, radarr4k)">
</div>
<div class="mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="isSymlink" name="notSymlink">
<label class="form-check-label" for="isSymlink">
Download real files instead of symlinks
</label>
<div class="row mb-3">
<div class="col-md-2 mb-3">
<div class="form-check d-inline-block me-3">
<input type="checkbox" class="form-check-input" id="isSymlink" name="notSymlink">
<label class="form-check-label" for="isSymlink">No Symlinks</label>
</div>
</div>
<div class="col-md-2 mb-3">
<div class="form-check d-inline-block">
<input type="checkbox" class="form-check-input" name="downloadUncached" id="downloadUncached">
<label class="form-check-label" for="downloadUncached">Download Uncached</label>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary" id="submitDownload">
@@ -44,15 +52,19 @@
const loadSavedDownloadOptions = () => {
const savedCategory = localStorage.getItem('downloadCategory');
const savedSymlink = localStorage.getItem('downloadSymlink');
const savedDownloadUncached = localStorage.getItem('downloadUncached');
document.getElementById('category').value = savedCategory || '';
document.getElementById('isSymlink').checked = savedSymlink === 'true'
document.getElementById('isSymlink').checked = savedSymlink === 'true';
document.getElementById('downloadUncached').checked = savedDownloadUncached === 'true';
};
const saveCurrentDownloadOptions = () => {
const category = document.getElementById('category').value;
const isSymlink = document.getElementById('isSymlink').checked;
const downloadUncached = document.getElementById('downloadUncached').checked;
localStorage.setItem('downloadCategory', category);
localStorage.setItem('downloadSymlink', isSymlink.toString());
localStorage.setItem('downloadUncached', downloadUncached.toString());
};
// Load the last used download options from local storage
@@ -98,6 +110,7 @@
formData.append('arr', document.getElementById('category').value);
formData.append('notSymlink', document.getElementById('isSymlink').checked);
formData.append('downloadUncached', document.getElementById('downloadUncached').checked);
const response = await fetch('/internal/add', {
method: 'POST',
+1 -1
View File
@@ -31,7 +31,7 @@
<div class="mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="autoProcess" checked>
<input class="form-check-input" type="checkbox" id="autoProcess">
<label class="form-check-label" for="autoProcess">
Auto Process(this will delete and re-search broken media)
</label>