Optimize streaming from Real-Debrid
This commit is contained in:
@@ -68,28 +68,28 @@ func (dl *Downloader) DownloadFile(
|
||||
) {
|
||||
torrents, ok := torMgr.DirectoryMap.Get(directory)
|
||||
if !ok {
|
||||
log.Warnf("Cannot find directory %s", directory)
|
||||
log.Errorf("Cannot find directory %s", directory)
|
||||
http.Error(resp, "File not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
torrent, ok := torrents.Get(torrentName)
|
||||
if !ok {
|
||||
log.Warnf("Cannot find torrent %sfrom path %s", torrentName, req.URL.Path)
|
||||
log.Errorf("Cannot find torrent %s from path %s", torrentName, req.URL.Path)
|
||||
http.Error(resp, "File not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
file, ok := torrent.SelectedFiles.Get(fileName)
|
||||
if !ok || !file.State.Is("ok_file") {
|
||||
// log.Warnf("Cannot find file %s from path %s", fileName, req.URL.Path)
|
||||
log.Errorf("Cannot find file %s from path %s", fileName, req.URL.Path)
|
||||
http.Error(resp, "File not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
unrestrict, err := torMgr.UnrestrictFile(file, cfg.ShouldServeFromRclone())
|
||||
if dlErr, ok := err.(*zurghttp.DownloadErrorResponse); ok && dlErr.Message == "bytes_limit_reached" {
|
||||
// log.Warnf("Your account has reached the bandwidth limit, please try again after 12AM CET")
|
||||
// log.Errorf("Your account has reached the bandwidth limit, please try again after 12AM CET")
|
||||
http.Error(resp, "File is not available (bandwidth limit reached)", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
@@ -133,7 +133,7 @@ func (dl *Downloader) DownloadLink(
|
||||
// log.Debugf("Opening file %s (%s)", fileName, link)
|
||||
unrestrict, err := torMgr.UnrestrictLink(link, cfg.ShouldServeFromRclone())
|
||||
if dlErr, ok := err.(*zurghttp.DownloadErrorResponse); ok && dlErr.Message == "bytes_limit_reached" {
|
||||
// log.Warnf("Your account has reached the bandwidth limit, please try again after 12AM CET")
|
||||
// log.Errorf("Your account has reached the bandwidth limit, please try again after 12AM CET")
|
||||
http.Error(resp, "Link is not available (bandwidth limit reached)", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
@@ -172,18 +172,16 @@ func (dl *Downloader) streamFileToResponse(
|
||||
// Add the range header if it exists
|
||||
if req.Header.Get("Range") != "" {
|
||||
dlReq.Header.Add("Range", req.Header.Get("Range"))
|
||||
// log.Debugf("Serving file %s: %s", unrestrict.Filename, req.Header.Get("Range"))
|
||||
}
|
||||
|
||||
// Perform the request
|
||||
downloadResp, err := dl.client.Do(dlReq)
|
||||
if dlErr, ok := err.(*zurghttp.DownloadErrorResponse); ok && dlErr.Message == "bytes_limit_reached" {
|
||||
// log.Warnf("Your account has reached the bandwidth limit, please try again after 12AM CET")
|
||||
// log.Errorf("Your account has reached the bandwidth limit, please try again after 12AM CET")
|
||||
http.Error(resp, "File is not available (bandwidth limit reached)", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
log.Warnf("Cannot download file %s: %v", unrestrict.Download, err)
|
||||
log.Errorf("Cannot download file %s: %v", unrestrict.Download, err)
|
||||
if file != nil && file.State.Event(context.Background(), "break_file") == nil {
|
||||
torMgr.EnqueueForRepair(torrent)
|
||||
}
|
||||
@@ -194,7 +192,7 @@ func (dl *Downloader) streamFileToResponse(
|
||||
|
||||
// Check if the download was not successful
|
||||
if downloadResp.StatusCode != http.StatusOK && downloadResp.StatusCode != http.StatusPartialContent {
|
||||
log.Warnf("Received a %s status code for file %s", downloadResp.Status, unrestrict.Filename)
|
||||
log.Errorf("Received a %s status code for file %s", downloadResp.Status, unrestrict.Filename)
|
||||
if file != nil && file.State.Event(context.Background(), "break_file") == nil {
|
||||
torMgr.EnqueueForRepair(torrent)
|
||||
}
|
||||
@@ -202,15 +200,43 @@ func (dl *Downloader) streamFileToResponse(
|
||||
return
|
||||
}
|
||||
|
||||
// Copy the content-range header from the download response to the response
|
||||
if cr := downloadResp.Header.Get("Content-Range"); cr != "" {
|
||||
resp.Header().Set("Content-Range", cr)
|
||||
}
|
||||
|
||||
buf := make([]byte, cfg.GetNetworkBufferSize())
|
||||
n, _ := io.CopyBuffer(resp, downloadResp.Body, buf)
|
||||
var n int64
|
||||
|
||||
if cfg.ShouldLogRequests() {
|
||||
var totalBytes int64
|
||||
ticker := time.NewTicker(60 * time.Second)
|
||||
done := make(chan bool)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
mbps := float64(totalBytes*8) / 60_000_000
|
||||
if mbps > 0 {
|
||||
log.Debugf("%s | %.2f MB/s", dlReq.URL, mbps)
|
||||
}
|
||||
totalBytes = 0
|
||||
case <-done:
|
||||
ticker.Stop()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
done <- true
|
||||
}()
|
||||
n, _ = io.Copy(io.MultiWriter(resp, &byteCounter{&totalBytes}), downloadResp.Body)
|
||||
} else {
|
||||
n, _ = io.Copy(resp, downloadResp.Body)
|
||||
}
|
||||
|
||||
dl.workerPool.Submit(func() {
|
||||
if n == 0 {
|
||||
return
|
||||
}
|
||||
// Update the download statistics
|
||||
reqBytes, _ := parseRangeHeader(req.Header.Get("Range"))
|
||||
if reqBytes == 0 && unrestrict != nil {
|
||||
@@ -272,6 +298,16 @@ func parseRangeHeader(rangeHeader string) (uint64, error) {
|
||||
return bytesToRead, nil
|
||||
}
|
||||
|
||||
type byteCounter struct {
|
||||
totalBytes *int64
|
||||
}
|
||||
|
||||
func (bc *byteCounter) Write(p []byte) (int, error) {
|
||||
n := len(p)
|
||||
*bc.totalBytes += int64(n)
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func bToMb(b uint64) uint64 {
|
||||
return b / 1024 / 1024
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user