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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/sirrobot01/debrid-blackhole/common"
|
"github.com/sirrobot01/debrid-blackhole/common"
|
||||||
"github.com/sirrobot01/debrid-blackhole/pkg/arr"
|
"github.com/sirrobot01/debrid-blackhole/pkg/arr"
|
||||||
"github.com/sirrobot01/debrid-blackhole/pkg/debrid"
|
"github.com/sirrobot01/debrid-blackhole/pkg/debrid"
|
||||||
"github.com/sirrobot01/debrid-blackhole/pkg/qbit/shared"
|
"github.com/sirrobot01/debrid-blackhole/pkg/qbit/shared"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ImportRequest struct {
|
type ImportRequest struct {
|
||||||
@@ -66,6 +67,9 @@ func (i *ImportRequest) Process(q *shared.QBit) (err error) {
|
|||||||
// Use this for now.
|
// Use this for now.
|
||||||
// This sends the torrent to the arr
|
// This sends the torrent to the arr
|
||||||
magnet, err := common.GetMagnetFromUrl(i.URI)
|
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")
|
torrent := q.CreateTorrentFromMagnet(magnet, i.Arr.Name, "manual")
|
||||||
debridTorrent, err := debrid.ProcessTorrent(q.Debrid, magnet, i.Arr, i.IsSymlink)
|
debridTorrent, err := debrid.ProcessTorrent(q.Debrid, magnet, i.Arr, i.IsSymlink)
|
||||||
if err != nil || debridTorrent == nil {
|
if err != nil || debridTorrent == nil {
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form id="downloadForm">
|
<form id="downloadForm">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="magnetURI" class="form-label">Magnet Link or Torrent URL</label>
|
<label for="magnetURI" class="form-label">Magnet Link(s) or Torrent URL(s)</label>
|
||||||
<textarea class="form-control" id="magnetURI" rows="3" placeholder="Paste your magnet link here..."></textarea>
|
<textarea class="form-control" id="magnetURI" rows="8" placeholder="Paste your magnet links or torrent URLs here, one per line..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
@@ -46,24 +46,44 @@
|
|||||||
submitBtn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Adding...';
|
submitBtn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Adding...';
|
||||||
|
|
||||||
try {
|
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', {
|
const response = await fetch('/internal/add', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
url: document.getElementById('magnetURI').value,
|
urls: urls,
|
||||||
arr: document.getElementById('category').value,
|
arr: document.getElementById('category').value,
|
||||||
notSymlink: document.getElementById('isSymlink').checked
|
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 = '';
|
document.getElementById('magnetURI').value = '';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(`Error adding download: ${error.message}`);
|
alert(`Error adding downloads: ${error.message}`);
|
||||||
} finally {
|
} finally {
|
||||||
submitBtn.disabled = false;
|
submitBtn.disabled = false;
|
||||||
submitBtn.innerHTML = originalText;
|
submitBtn.innerHTML = originalText;
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/sirrobot01/debrid-blackhole/common"
|
"github.com/sirrobot01/debrid-blackhole/common"
|
||||||
@@ -12,9 +16,6 @@ import (
|
|||||||
"github.com/sirrobot01/debrid-blackhole/pkg/debrid"
|
"github.com/sirrobot01/debrid-blackhole/pkg/debrid"
|
||||||
"github.com/sirrobot01/debrid-blackhole/pkg/qbit/shared"
|
"github.com/sirrobot01/debrid-blackhole/pkg/qbit/shared"
|
||||||
"github.com/sirrobot01/debrid-blackhole/pkg/version"
|
"github.com/sirrobot01/debrid-blackhole/pkg/version"
|
||||||
"html/template"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AddRequest struct {
|
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) {
|
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 {
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
results := make([]*ImportRequest, 0, len(req.URLs))
|
||||||
|
errs := make([]string, 0)
|
||||||
|
|
||||||
_arr := u.qbit.Arrs.Get(req.Arr)
|
_arr := u.qbit.Arrs.Get(req.Arr)
|
||||||
if _arr == nil {
|
if _arr == nil {
|
||||||
_arr = arr.NewArr(req.Arr, "", "", arr.Sonarr)
|
_arr = arr.NewArr(req.Arr, "", "", arr.Sonarr)
|
||||||
}
|
}
|
||||||
importReq := NewImportRequest(req.Url, _arr, !req.NotSymlink)
|
|
||||||
err := importReq.Process(u.qbit)
|
for _, url := range req.URLs {
|
||||||
if err != nil {
|
if url == "" {
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
continue
|
||||||
return
|
}
|
||||||
|
|
||||||
|
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) {
|
func (u *uiHandler) handleCheckCached(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
Reference in New Issue
Block a user