Add support for adding torrent file

This commit is contained in:
Mukhtar Akere
2025-04-13 12:40:31 +01:00
parent 19b8664146
commit 8029cd3840
8 changed files with 73 additions and 26 deletions

View File

View File

@@ -94,5 +94,4 @@ The documentation includes:
Contributions are welcome! Please feel free to submit a Pull Request. Contributions are welcome! Please feel free to submit a Pull Request.
## License ## License
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
This project is licensed under the [License Name] - see the LICENSE file for details.

View File

@@ -25,21 +25,38 @@ type Magnet struct {
InfoHash string InfoHash string
Size int64 Size int64
Link string Link string
File []byte
}
func (m *Magnet) IsTorrent() bool {
return m.File != nil
} }
func GetMagnetFromFile(file io.Reader, filePath string) (*Magnet, error) { func GetMagnetFromFile(file io.Reader, filePath string) (*Magnet, error) {
var (
m *Magnet
err error
)
if filepath.Ext(filePath) == ".torrent" { if filepath.Ext(filePath) == ".torrent" {
torrentData, err := io.ReadAll(file) torrentData, err := io.ReadAll(file)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return GetMagnetFromBytes(torrentData) m, err = GetMagnetFromBytes(torrentData)
if err != nil {
return nil, err
}
} else { } else {
// .magnet file // .magnet file
magnetLink := ReadMagnetFile(file) magnetLink := ReadMagnetFile(file)
return GetMagnetInfo(magnetLink) m, err = GetMagnetInfo(magnetLink)
if err != nil {
return nil, err
} }
} }
m.Name = strings.TrimSuffix(filePath, filepath.Ext(filePath))
return m, nil
}
func GetMagnetFromUrl(url string) (*Magnet, error) { func GetMagnetFromUrl(url string) (*Magnet, error) {
if strings.HasPrefix(url, "magnet:") { if strings.HasPrefix(url, "magnet:") {
@@ -68,6 +85,7 @@ func GetMagnetFromBytes(torrentData []byte) (*Magnet, error) {
Name: info.Name, Name: info.Name,
Size: info.Length, Size: info.Length,
Link: mi.Magnet(&hash, &info).String(), Link: mi.Magnet(&hash, &info).String(),
File: torrentData,
} }
return magnet, nil return magnet, nil
} }

View File

@@ -1,6 +1,7 @@
package realdebrid package realdebrid
import ( import (
"bytes"
"errors" "errors"
"fmt" "fmt"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@@ -211,6 +212,35 @@ func (r *RealDebrid) IsAvailable(hashes []string) map[string]bool {
} }
func (r *RealDebrid) SubmitMagnet(t *types.Torrent) (*types.Torrent, error) { func (r *RealDebrid) SubmitMagnet(t *types.Torrent) (*types.Torrent, error) {
if t.Magnet.IsTorrent() {
return r.addTorrent(t)
}
return r.addMagnet(t)
}
func (r *RealDebrid) addTorrent(t *types.Torrent) (*types.Torrent, error) {
url := fmt.Sprintf("%s/torrents/addTorrent", r.Host)
var data AddMagnetSchema
req, err := http.NewRequest(http.MethodPut, url, bytes.NewReader(t.Magnet.File))
if err != nil {
return nil, err
}
req.Header.Add("Content-Type", "application/x-bittorrent")
resp, err := r.client.MakeRequest(req)
if err != nil {
return nil, err
}
if err = json.Unmarshal(resp, &data); err != nil {
return nil, err
}
t.Id = data.Id
t.Debrid = r.Name
t.MountPath = r.MountPath
return t, nil
}
func (r *RealDebrid) addMagnet(t *types.Torrent) (*types.Torrent, error) {
url := fmt.Sprintf("%s/torrents/addMagnet", r.Host) url := fmt.Sprintf("%s/torrents/addMagnet", r.Host)
payload := gourl.Values{ payload := gourl.Values{
"magnet": {t.Magnet.Link}, "magnet": {t.Magnet.Link},

View File

@@ -14,7 +14,7 @@ import (
type ImportRequest struct { type ImportRequest struct {
ID string `json:"id"` ID string `json:"id"`
Path string `json:"path"` Path string `json:"path"`
URI string `json:"uri"` Magnet *utils.Magnet `json:"magnet"`
Arr *arr.Arr `json:"arr"` Arr *arr.Arr `json:"arr"`
IsSymlink bool `json:"isSymlink"` IsSymlink bool `json:"isSymlink"`
SeriesId int `json:"series"` SeriesId int `json:"series"`
@@ -41,10 +41,10 @@ type ManualImportResponseSchema struct {
Id int `json:"id"` Id int `json:"id"`
} }
func NewImportRequest(uri string, arr *arr.Arr, isSymlink, downloadUncached bool) *ImportRequest { func NewImportRequest(magnet *utils.Magnet, arr *arr.Arr, isSymlink, downloadUncached bool) *ImportRequest {
return &ImportRequest{ return &ImportRequest{
ID: uuid.NewString(), ID: uuid.NewString(),
URI: uri, Magnet: magnet,
Arr: arr, Arr: arr,
Failed: false, Failed: false,
Completed: false, Completed: false,
@@ -69,12 +69,8 @@ func (i *ImportRequest) Process(q *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
svc := service.GetService() svc := service.GetService()
magnet, err := utils.GetMagnetFromUrl(i.URI) torrent := createTorrentFromMagnet(i.Magnet, i.Arr.Name, "manual")
if err != nil { debridTorrent, err := debrid.ProcessTorrent(svc.Debrid, i.Magnet, i.Arr, i.IsSymlink, i.DownloadUncached)
return fmt.Errorf("error parsing magnet link: %w", err)
}
torrent := CreateTorrentFromMagnet(magnet, i.Arr.Name, "manual")
debridTorrent, err := debrid.ProcessTorrent(svc.Debrid, magnet, i.Arr, i.IsSymlink, i.DownloadUncached)
if err != nil || debridTorrent == nil { if err != nil || debridTorrent == nil {
if debridTorrent != nil { if debridTorrent != nil {
dbClient := service.GetDebrid().GetByName(debridTorrent.Debrid) dbClient := service.GetDebrid().GetByName(debridTorrent.Debrid)

View File

@@ -6,7 +6,7 @@ import (
"strings" "strings"
) )
func CreateTorrentFromMagnet(magnet *utils.Magnet, category, source string) *Torrent { func createTorrentFromMagnet(magnet *utils.Magnet, category, source string) *Torrent {
torrent := &Torrent{ torrent := &Torrent{
ID: uuid.NewString(), ID: uuid.NewString(),
Hash: strings.ToLower(magnet.InfoHash), Hash: strings.ToLower(magnet.InfoHash),

View File

@@ -50,7 +50,7 @@ func (q *QBit) AddTorrent(ctx context.Context, fileHeader *multipart.FileHeader,
func (q *QBit) Process(ctx context.Context, magnet *utils.Magnet, category string) error { func (q *QBit) Process(ctx context.Context, magnet *utils.Magnet, category string) error {
svc := service.GetService() svc := service.GetService()
torrent := CreateTorrentFromMagnet(magnet, category, "auto") torrent := createTorrentFromMagnet(magnet, category, "auto")
a, ok := ctx.Value("arr").(*arr.Arr) a, ok := ctx.Value("arr").(*arr.Arr)
if !ok { if !ok {
return fmt.Errorf("arr not found in context") return fmt.Errorf("arr not found in context")

View File

@@ -322,9 +322,13 @@ func (ui *Handler) handleAddContent(w http.ResponseWriter, r *http.Request) {
} }
for _, url := range urlList { for _, url := range urlList {
importReq := qbit.NewImportRequest(url, _arr, !notSymlink, downloadUncached) magnet, err := utils.GetMagnetFromUrl(url)
err := importReq.Process(ui.qbit)
if err != nil { if err != nil {
errs = append(errs, fmt.Sprintf("Failed to parse URL %s: %v", url, err))
continue
}
importReq := qbit.NewImportRequest(magnet, _arr, !notSymlink, downloadUncached)
if err := importReq.Process(ui.qbit); err != nil {
errs = append(errs, fmt.Sprintf("URL %s: %v", url, err)) errs = append(errs, fmt.Sprintf("URL %s: %v", url, err))
continue continue
} }
@@ -347,7 +351,7 @@ func (ui *Handler) handleAddContent(w http.ResponseWriter, r *http.Request) {
continue continue
} }
importReq := qbit.NewImportRequest(magnet.Link, _arr, !notSymlink, downloadUncached) importReq := qbit.NewImportRequest(magnet, _arr, !notSymlink, downloadUncached)
err = importReq.Process(ui.qbit) err = importReq.Process(ui.qbit)
if err != nil { if err != nil {
errs = append(errs, fmt.Sprintf("File %s: %v", fileHeader.Filename, err)) errs = append(errs, fmt.Sprintf("File %s: %v", fileHeader.Filename, err))