Handle multiple torrent submissions (#16)
* feat: Handle multiple torrent submissions
This commit is contained in:
committed by
GitHub
parent
e2eb11056d
commit
530de20276
@@ -2,12 +2,13 @@ package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/sirrobot01/debrid-blackhole/common"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/arr"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/debrid"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/qbit/shared"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ImportRequest struct {
|
||||
@@ -66,6 +67,9 @@ func (i *ImportRequest) Process(q *shared.QBit) (err error) {
|
||||
// Use this for now.
|
||||
// This sends the torrent to the arr
|
||||
magnet, err := common.GetMagnetFromUrl(i.URI)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing magnet link: %w", err)
|
||||
}
|
||||
torrent := q.CreateTorrentFromMagnet(magnet, i.Arr.Name, "manual")
|
||||
debridTorrent, err := debrid.ProcessTorrent(q.Debrid, magnet, i.Arr, i.IsSymlink)
|
||||
if err != nil || debridTorrent == nil {
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
<div class="card-body">
|
||||
<form id="downloadForm">
|
||||
<div class="mb-3">
|
||||
<label for="magnetURI" class="form-label">Magnet Link or Torrent URL</label>
|
||||
<textarea class="form-control" id="magnetURI" rows="3" placeholder="Paste your magnet link here..."></textarea>
|
||||
<label for="magnetURI" class="form-label">Magnet Link(s) or Torrent URL(s)</label>
|
||||
<textarea class="form-control" id="magnetURI" rows="8" placeholder="Paste your magnet links or torrent URLs here, one per line..."></textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
@@ -46,24 +46,44 @@
|
||||
submitBtn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Adding...';
|
||||
|
||||
try {
|
||||
const urls = document.getElementById('magnetURI').value
|
||||
.split('\n')
|
||||
.map(url => url.trim())
|
||||
.filter(url => url.length > 0);
|
||||
|
||||
if (urls.length === 0) {
|
||||
alert('Please submit at least one torrent');
|
||||
return;
|
||||
}
|
||||
if (urls.length >= 100) {
|
||||
alert('Please submit less than 100 torrents at a time');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const response = await fetch('/internal/add', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
url: document.getElementById('magnetURI').value,
|
||||
urls: urls,
|
||||
arr: document.getElementById('category').value,
|
||||
notSymlink: document.getElementById('isSymlink').checked
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error(await response.text());
|
||||
const result = await response.json();
|
||||
if (!response.ok) throw new Error(result.error || 'Unknown error');
|
||||
if (result.errors && result.errors.length > 0) {
|
||||
alert(`Added ${result.results.length} torrents with ${result.errors.length} errors:\n${result.errors.join('\n')}`);
|
||||
} else {
|
||||
alert(`Successfully added ${result.results.length} torrents!`);
|
||||
}
|
||||
|
||||
alert('Download added successfully!');
|
||||
document.getElementById('magnetURI').value = '';
|
||||
} catch (error) {
|
||||
alert(`Error adding download: ${error.message}`);
|
||||
alert(`Error adding downloads: ${error.message}`);
|
||||
} finally {
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.innerHTML = originalText;
|
||||
|
||||
@@ -5,6 +5,10 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/sirrobot01/debrid-blackhole/common"
|
||||
@@ -12,9 +16,6 @@ import (
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/debrid"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/qbit/shared"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/version"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AddRequest struct {
|
||||
@@ -117,22 +118,46 @@ func (u *uiHandler) handleGetArrs(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (u *uiHandler) handleAddContent(w http.ResponseWriter, r *http.Request) {
|
||||
var req AddRequest
|
||||
var req struct {
|
||||
URLs []string `json:"urls"`
|
||||
Arr string `json:"arr"`
|
||||
NotSymlink bool `json:"notSymlink"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
results := make([]*ImportRequest, 0, len(req.URLs))
|
||||
errs := make([]string, 0)
|
||||
|
||||
_arr := u.qbit.Arrs.Get(req.Arr)
|
||||
if _arr == nil {
|
||||
_arr = arr.NewArr(req.Arr, "", "", arr.Sonarr)
|
||||
}
|
||||
importReq := NewImportRequest(req.Url, _arr, !req.NotSymlink)
|
||||
err := importReq.Process(u.qbit)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
|
||||
for _, url := range req.URLs {
|
||||
if url == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
importReq := NewImportRequest(url, _arr, !req.NotSymlink)
|
||||
err := importReq.Process(u.qbit)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Sprintf("URL %s: %v", url, err))
|
||||
continue
|
||||
}
|
||||
results = append(results, importReq)
|
||||
}
|
||||
common.JSONResponse(w, importReq, http.StatusOK)
|
||||
|
||||
common.JSONResponse(w, struct {
|
||||
Results []*ImportRequest `json:"results"`
|
||||
Errors []string `json:"errors,omitempty"`
|
||||
}{
|
||||
Results: results,
|
||||
Errors: errs,
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
func (u *uiHandler) handleCheckCached(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
Reference in New Issue
Block a user