Revert former beta chnages
This commit is contained in:
@@ -302,7 +302,7 @@ func (ad *AllDebrid) GetFileDownloadLinks(t *types.Torrent) error {
|
|||||||
for _, file := range t.Files {
|
for _, file := range t.Files {
|
||||||
go func(file types.File) {
|
go func(file types.File) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
link, err := ad.GetDownloadLink(t, &file)
|
link, _, err := ad.GetDownloadLink(t, &file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errCh <- err
|
errCh <- err
|
||||||
return
|
return
|
||||||
@@ -337,7 +337,7 @@ func (ad *AllDebrid) GetFileDownloadLinks(t *types.Torrent) error {
|
|||||||
links[link.Link] = link
|
links[link.Link] = link
|
||||||
}
|
}
|
||||||
// Update the files with download links
|
// Update the files with download links
|
||||||
ad.accounts.SetDownloadLinks(links)
|
ad.accounts.SetDownloadLinks(nil, links)
|
||||||
|
|
||||||
// Check for errors
|
// Check for errors
|
||||||
for err := range errCh {
|
for err := range errCh {
|
||||||
@@ -350,7 +350,7 @@ func (ad *AllDebrid) GetFileDownloadLinks(t *types.Torrent) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ad *AllDebrid) GetDownloadLink(t *types.Torrent, file *types.File) (*types.DownloadLink, error) {
|
func (ad *AllDebrid) GetDownloadLink(t *types.Torrent, file *types.File) (*types.DownloadLink, *types.Account, error) {
|
||||||
url := fmt.Sprintf("%s/link/unlock", ad.Host)
|
url := fmt.Sprintf("%s/link/unlock", ad.Host)
|
||||||
query := gourl.Values{}
|
query := gourl.Values{}
|
||||||
query.Add("link", file.Link)
|
query.Add("link", file.Link)
|
||||||
@@ -358,22 +358,21 @@ func (ad *AllDebrid) GetDownloadLink(t *types.Torrent, file *types.File) (*types
|
|||||||
req, _ := http.NewRequest(http.MethodGet, url, nil)
|
req, _ := http.NewRequest(http.MethodGet, url, nil)
|
||||||
resp, err := ad.client.MakeRequest(req)
|
resp, err := ad.client.MakeRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
var data DownloadLink
|
var data DownloadLink
|
||||||
if err = json.Unmarshal(resp, &data); err != nil {
|
if err = json.Unmarshal(resp, &data); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if data.Error != nil {
|
if data.Error != nil {
|
||||||
return nil, fmt.Errorf("error getting download link: %s", data.Error.Message)
|
return nil, nil, fmt.Errorf("error getting download link: %s", data.Error.Message)
|
||||||
}
|
}
|
||||||
link := data.Data.Link
|
link := data.Data.Link
|
||||||
if link == "" {
|
if link == "" {
|
||||||
return nil, fmt.Errorf("download link is empty")
|
return nil, nil, fmt.Errorf("download link is empty")
|
||||||
}
|
}
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
account := ad.accounts.Current()
|
|
||||||
return &types.DownloadLink{
|
return &types.DownloadLink{
|
||||||
Link: file.Link,
|
Link: file.Link,
|
||||||
DownloadLink: link,
|
DownloadLink: link,
|
||||||
@@ -382,9 +381,7 @@ func (ad *AllDebrid) GetDownloadLink(t *types.Torrent, file *types.File) (*types
|
|||||||
Filename: file.Name,
|
Filename: file.Name,
|
||||||
Generated: now,
|
Generated: now,
|
||||||
ExpiresAt: now.Add(ad.autoExpiresLinksAfter),
|
ExpiresAt: now.Add(ad.autoExpiresLinksAfter),
|
||||||
Token: account.Token,
|
}, nil, nil
|
||||||
MaskedToken: account.MaskedToken,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ad *AllDebrid) GetTorrents() ([]*types.Torrent, error) {
|
func (ad *AllDebrid) GetTorrents() ([]*types.Torrent, error) {
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ func (dl *DebridLink) UpdateTorrent(t *types.Torrent) error {
|
|||||||
t.Files[f.Name] = file
|
t.Files[f.Name] = file
|
||||||
}
|
}
|
||||||
|
|
||||||
dl.accounts.SetDownloadLinks(links)
|
dl.accounts.SetDownloadLinks(nil, links)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +287,6 @@ func (dl *DebridLink) SubmitMagnet(t *types.Torrent) (*types.Torrent, error) {
|
|||||||
|
|
||||||
links := make(map[string]*types.DownloadLink)
|
links := make(map[string]*types.DownloadLink)
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
account := dl.accounts.Current()
|
|
||||||
for _, f := range data.Files {
|
for _, f := range data.Files {
|
||||||
file := types.File{
|
file := types.File{
|
||||||
TorrentId: t.Id,
|
TorrentId: t.Id,
|
||||||
@@ -304,14 +303,12 @@ func (dl *DebridLink) SubmitMagnet(t *types.Torrent) (*types.Torrent, error) {
|
|||||||
DownloadLink: f.DownloadURL,
|
DownloadLink: f.DownloadURL,
|
||||||
Generated: now,
|
Generated: now,
|
||||||
ExpiresAt: now.Add(dl.autoExpiresLinksAfter),
|
ExpiresAt: now.Add(dl.autoExpiresLinksAfter),
|
||||||
Token: account.Token,
|
|
||||||
MaskedToken: account.MaskedToken,
|
|
||||||
}
|
}
|
||||||
links[file.Link] = link
|
links[file.Link] = link
|
||||||
file.DownloadLink = link
|
file.DownloadLink = link
|
||||||
t.Files[f.Name] = file
|
t.Files[f.Name] = file
|
||||||
}
|
}
|
||||||
dl.accounts.SetDownloadLinks(links)
|
dl.accounts.SetDownloadLinks(nil, links)
|
||||||
|
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
@@ -359,7 +356,7 @@ func (dl *DebridLink) RefreshDownloadLinks() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dl *DebridLink) GetDownloadLink(t *types.Torrent, file *types.File) (*types.DownloadLink, error) {
|
func (dl *DebridLink) GetDownloadLink(t *types.Torrent, file *types.File) (*types.DownloadLink, *types.Account, error) {
|
||||||
return dl.accounts.GetDownloadLink(file.Link)
|
return dl.accounts.GetDownloadLink(file.Link)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,7 +407,6 @@ func (dl *DebridLink) getTorrents(page, perPage int) ([]*types.Torrent, error) {
|
|||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return torrents, nil
|
return torrents, nil
|
||||||
}
|
}
|
||||||
account := dl.accounts.Current()
|
|
||||||
for _, t := range data {
|
for _, t := range data {
|
||||||
if t.Status != 100 {
|
if t.Status != 100 {
|
||||||
continue
|
continue
|
||||||
@@ -448,8 +444,6 @@ func (dl *DebridLink) getTorrents(page, perPage int) ([]*types.Torrent, error) {
|
|||||||
DownloadLink: f.DownloadURL,
|
DownloadLink: f.DownloadURL,
|
||||||
Generated: now,
|
Generated: now,
|
||||||
ExpiresAt: now.Add(dl.autoExpiresLinksAfter),
|
ExpiresAt: now.Add(dl.autoExpiresLinksAfter),
|
||||||
Token: account.Token,
|
|
||||||
MaskedToken: account.MaskedToken,
|
|
||||||
}
|
}
|
||||||
links[file.Link] = link
|
links[file.Link] = link
|
||||||
file.DownloadLink = link
|
file.DownloadLink = link
|
||||||
@@ -457,7 +451,7 @@ func (dl *DebridLink) getTorrents(page, perPage int) ([]*types.Torrent, error) {
|
|||||||
}
|
}
|
||||||
torrents = append(torrents, torrent)
|
torrents = append(torrents, torrent)
|
||||||
}
|
}
|
||||||
dl.accounts.SetDownloadLinks(links)
|
dl.accounts.SetDownloadLinks(nil, links)
|
||||||
|
|
||||||
return torrents, nil
|
return torrents, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ func (r *RealDebrid) handleRarArchive(t *types.Torrent, data torrentInfo, select
|
|||||||
|
|
||||||
r.logger.Info().Msgf("RAR file detected, unpacking: %s", t.Name)
|
r.logger.Info().Msgf("RAR file detected, unpacking: %s", t.Name)
|
||||||
linkFile := &types.File{TorrentId: t.Id, Link: data.Links[0]}
|
linkFile := &types.File{TorrentId: t.Id, Link: data.Links[0]}
|
||||||
downloadLinkObj, err := r.GetDownloadLink(t, linkFile)
|
downloadLinkObj, account, err := r.GetDownloadLink(t, linkFile)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Debug().Err(err).Msgf("Error getting download link for RAR file: %s. Falling back to single file representation.", t.Name)
|
r.logger.Debug().Err(err).Msgf("Error getting download link for RAR file: %s. Falling back to single file representation.", t.Name)
|
||||||
@@ -244,7 +244,7 @@ func (r *RealDebrid) handleRarArchive(t *types.Torrent, data torrentInfo, select
|
|||||||
return r.handleRarFallback(t, data)
|
return r.handleRarFallback(t, data)
|
||||||
}
|
}
|
||||||
r.logger.Info().Msgf("Unpacked RAR archive for torrent: %s with %d files", t.Name, len(files))
|
r.logger.Info().Msgf("Unpacked RAR archive for torrent: %s with %d files", t.Name, len(files))
|
||||||
r.accounts.SetDownloadLink(downloadLinkObj)
|
r.accounts.SetDownloadLink(account, downloadLinkObj)
|
||||||
return files, nil
|
return files, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,7 +591,7 @@ func (r *RealDebrid) GetFileDownloadLinks(t *types.Torrent) error {
|
|||||||
go func(file types.File) {
|
go func(file types.File) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
link, err := r.GetDownloadLink(t, &file)
|
link, account, err := r.GetDownloadLink(t, &file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
if firstErr == nil {
|
if firstErr == nil {
|
||||||
@@ -610,7 +610,7 @@ func (r *RealDebrid) GetFileDownloadLinks(t *types.Torrent) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
file.DownloadLink = link
|
file.DownloadLink = link
|
||||||
r.accounts.SetDownloadLink(link)
|
r.accounts.SetDownloadLink(account, link)
|
||||||
|
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
files[file.Name] = file
|
files[file.Name] = file
|
||||||
@@ -703,8 +703,6 @@ func (r *RealDebrid) getDownloadLink(account *types.Account, file *types.File) (
|
|||||||
}
|
}
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
return &types.DownloadLink{
|
return &types.DownloadLink{
|
||||||
MaskedToken: account.MaskedToken,
|
|
||||||
Token: account.Token,
|
|
||||||
Filename: data.Filename,
|
Filename: data.Filename,
|
||||||
Size: data.Filesize,
|
Size: data.Filesize,
|
||||||
Link: data.Link,
|
Link: data.Link,
|
||||||
@@ -715,13 +713,14 @@ func (r *RealDebrid) getDownloadLink(account *types.Account, file *types.File) (
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RealDebrid) GetDownloadLink(t *types.Torrent, file *types.File) (*types.DownloadLink, error) {
|
func (r *RealDebrid) GetDownloadLink(t *types.Torrent, file *types.File) (*types.DownloadLink, *types.Account, error) {
|
||||||
|
|
||||||
accounts := r.accounts.Active()
|
accounts := r.accounts.Active()
|
||||||
for _, account := range accounts {
|
for _, account := range accounts {
|
||||||
downloadLink, err := r.getDownloadLink(account, file)
|
downloadLink, err := r.getDownloadLink(account, file)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return downloadLink, nil
|
return downloadLink, account, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
retries := 0
|
retries := 0
|
||||||
@@ -730,16 +729,16 @@ func (r *RealDebrid) GetDownloadLink(t *types.Torrent, file *types.File) (*types
|
|||||||
retries = 5
|
retries = 5
|
||||||
} else {
|
} else {
|
||||||
// If the error is not traffic exceeded, return the error
|
// If the error is not traffic exceeded, return the error
|
||||||
return nil, err
|
return nil, account, err
|
||||||
}
|
}
|
||||||
backOff := 1 * time.Second
|
backOff := 1 * time.Second
|
||||||
for retries > 0 {
|
for retries > 0 {
|
||||||
downloadLink, err = r.getDownloadLink(account, file)
|
downloadLink, err = r.getDownloadLink(account, file)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return downloadLink, nil
|
return downloadLink, account, nil
|
||||||
}
|
}
|
||||||
if !errors.Is(err, utils.TrafficExceededError) {
|
if !errors.Is(err, utils.TrafficExceededError) {
|
||||||
return nil, err
|
return nil, account, err
|
||||||
}
|
}
|
||||||
// Add a delay before retrying
|
// Add a delay before retrying
|
||||||
time.Sleep(backOff)
|
time.Sleep(backOff)
|
||||||
@@ -747,7 +746,7 @@ func (r *RealDebrid) GetDownloadLink(t *types.Torrent, file *types.File) (*types
|
|||||||
retries--
|
retries--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("realdebrid API error: download link not found")
|
return nil, nil, fmt.Errorf("realdebrid API error: used all active accounts")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RealDebrid) getTorrents(offset int, limit int) (int, []*types.Torrent, error) {
|
func (r *RealDebrid) getTorrents(offset int, limit int) (int, []*types.Torrent, error) {
|
||||||
@@ -873,7 +872,7 @@ func (r *RealDebrid) RefreshDownloadLinks() error {
|
|||||||
|
|
||||||
offset += len(dl)
|
offset += len(dl)
|
||||||
}
|
}
|
||||||
r.accounts.SetDownloadLinks(links)
|
r.accounts.SetDownloadLinks(account, links)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -983,7 +982,7 @@ func (r *RealDebrid) SyncAccounts() error {
|
|||||||
}
|
}
|
||||||
for _, account := range r.accounts.All() {
|
for _, account := range r.accounts.All() {
|
||||||
if err := r.syncAccount(account); err != nil {
|
if err := r.syncAccount(account); err != nil {
|
||||||
r.logger.Error().Err(err).Str("account", account.MaskedToken).Msgf("Error syncing account %s", account.Username)
|
r.logger.Error().Err(err).Msgf("Error syncing account %s", account.Username)
|
||||||
continue // Skip this account and continue with the next
|
continue // Skip this account and continue with the next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -412,7 +412,7 @@ func (tb *Torbox) GetFileDownloadLinks(t *types.Torrent) error {
|
|||||||
for _, file := range t.Files {
|
for _, file := range t.Files {
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
link, err := tb.GetDownloadLink(t, &file)
|
link, _, err := tb.GetDownloadLink(t, &file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errCh <- err
|
errCh <- err
|
||||||
return
|
return
|
||||||
@@ -440,7 +440,7 @@ func (tb *Torbox) GetFileDownloadLinks(t *types.Torrent) error {
|
|||||||
// Collect download links
|
// Collect download links
|
||||||
for link := range linkCh {
|
for link := range linkCh {
|
||||||
if link != nil {
|
if link != nil {
|
||||||
tb.accounts.SetDownloadLink(link)
|
tb.accounts.SetDownloadLink(nil, link)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,7 +455,7 @@ func (tb *Torbox) GetFileDownloadLinks(t *types.Torrent) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tb *Torbox) GetDownloadLink(t *types.Torrent, file *types.File) (*types.DownloadLink, error) {
|
func (tb *Torbox) GetDownloadLink(t *types.Torrent, file *types.File) (*types.DownloadLink, *types.Account, error) {
|
||||||
url := fmt.Sprintf("%s/api/torrents/requestdl/", tb.Host)
|
url := fmt.Sprintf("%s/api/torrents/requestdl/", tb.Host)
|
||||||
query := gourl.Values{}
|
query := gourl.Values{}
|
||||||
query.Add("torrent_id", t.Id)
|
query.Add("torrent_id", t.Id)
|
||||||
@@ -471,7 +471,7 @@ func (tb *Torbox) GetDownloadLink(t *types.Torrent, file *types.File) (*types.Do
|
|||||||
Str("torrent_id", t.Id).
|
Str("torrent_id", t.Id).
|
||||||
Str("file_id", file.Id).
|
Str("file_id", file.Id).
|
||||||
Msg("Failed to make request to Torbox API")
|
Msg("Failed to make request to Torbox API")
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var data DownloadLinksResponse
|
var data DownloadLinksResponse
|
||||||
@@ -481,7 +481,7 @@ func (tb *Torbox) GetDownloadLink(t *types.Torrent, file *types.File) (*types.Do
|
|||||||
Str("torrent_id", t.Id).
|
Str("torrent_id", t.Id).
|
||||||
Str("file_id", file.Id).
|
Str("file_id", file.Id).
|
||||||
Msg("Failed to unmarshal Torbox API response")
|
Msg("Failed to unmarshal Torbox API response")
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if data.Data == nil {
|
if data.Data == nil {
|
||||||
@@ -492,7 +492,7 @@ func (tb *Torbox) GetDownloadLink(t *types.Torrent, file *types.File) (*types.Do
|
|||||||
Interface("error", data.Error).
|
Interface("error", data.Error).
|
||||||
Str("detail", data.Detail).
|
Str("detail", data.Detail).
|
||||||
Msg("Torbox API returned no data")
|
Msg("Torbox API returned no data")
|
||||||
return nil, fmt.Errorf("error getting download links")
|
return nil, nil, fmt.Errorf("error getting download links")
|
||||||
}
|
}
|
||||||
|
|
||||||
link := *data.Data
|
link := *data.Data
|
||||||
@@ -501,7 +501,7 @@ func (tb *Torbox) GetDownloadLink(t *types.Torrent, file *types.File) (*types.Do
|
|||||||
Str("torrent_id", t.Id).
|
Str("torrent_id", t.Id).
|
||||||
Str("file_id", file.Id).
|
Str("file_id", file.Id).
|
||||||
Msg("Torbox API returned empty download link")
|
Msg("Torbox API returned empty download link")
|
||||||
return nil, fmt.Errorf("error getting download links")
|
return nil, nil, fmt.Errorf("error getting download links")
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
@@ -511,11 +511,9 @@ func (tb *Torbox) GetDownloadLink(t *types.Torrent, file *types.File) (*types.Do
|
|||||||
Id: file.Id,
|
Id: file.Id,
|
||||||
Generated: now,
|
Generated: now,
|
||||||
ExpiresAt: now.Add(tb.autoExpiresLinksAfter),
|
ExpiresAt: now.Add(tb.autoExpiresLinksAfter),
|
||||||
Token: tb.APIKey,
|
|
||||||
MaskedToken: utils.Mask(tb.APIKey),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return downloadLink, nil
|
return downloadLink, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tb *Torbox) GetDownloadingStatus() []string {
|
func (tb *Torbox) GetDownloadingStatus() []string {
|
||||||
|
|||||||
@@ -30,21 +30,22 @@ func (r *downloadLinkRequest) Wait() (string, error) {
|
|||||||
return r.result, r.err
|
return r.result, r.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) GetDownloadLink(torrentName, filename, fileLink string) (*types.DownloadLink, error) {
|
func (c *Cache) GetDownloadLink(torrentName, filename, fileLink string) (string, error) {
|
||||||
// Check link cache
|
// Check link cache
|
||||||
if dl, err := c.checkDownloadLink(fileLink); dl != nil && err == nil {
|
if dl, err := c.checkDownloadLink(fileLink); dl != "" && err == nil {
|
||||||
return dl, nil
|
return dl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
dl, err := c.fetchDownloadLink(torrentName, filename, fileLink)
|
dl, err := c.fetchDownloadLink(torrentName, filename, fileLink)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return dl, err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if dl == nil || dl.DownloadLink == "" {
|
if dl == nil || dl.DownloadLink == "" {
|
||||||
return nil, fmt.Errorf("download link is empty for %s in torrent %s", filename, torrentName)
|
err = fmt.Errorf("download link is empty for %s in torrent %s", filename, torrentName)
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
return dl, nil
|
return dl.DownloadLink, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) fetchDownloadLink(torrentName, filename, fileLink string) (*types.DownloadLink, error) {
|
func (c *Cache) fetchDownloadLink(torrentName, filename, fileLink string) (*types.DownloadLink, error) {
|
||||||
@@ -85,10 +86,11 @@ func (c *Cache) fetchDownloadLink(torrentName, filename, fileLink string) (*type
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.logger.Trace().Msgf("Getting download link for %s(%s)", filename, file.Link)
|
c.logger.Trace().Msgf("Getting download link for %s(%s)", filename, file.Link)
|
||||||
downloadLink, err := c.client.GetDownloadLink(ct.Torrent, &file)
|
downloadLink, account, err := c.client.GetDownloadLink(ct.Torrent, &file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, utils.HosterUnavailableError) {
|
if errors.Is(err, utils.HosterUnavailableError) {
|
||||||
c.logger.Trace().
|
c.logger.Trace().
|
||||||
|
Str("account", account.Username).
|
||||||
Str("filename", filename).
|
Str("filename", filename).
|
||||||
Str("torrent_id", ct.Id).
|
Str("torrent_id", ct.Id).
|
||||||
Msg("Hoster unavailable, attempting to reinsert torrent")
|
Msg("Hoster unavailable, attempting to reinsert torrent")
|
||||||
@@ -103,7 +105,7 @@ func (c *Cache) fetchDownloadLink(torrentName, filename, fileLink string) (*type
|
|||||||
return nil, fmt.Errorf("file %s not found in reinserted torrent %s", filename, torrentName)
|
return nil, fmt.Errorf("file %s not found in reinserted torrent %s", filename, torrentName)
|
||||||
}
|
}
|
||||||
// Retry getting the download link
|
// Retry getting the download link
|
||||||
downloadLink, err = c.client.GetDownloadLink(ct.Torrent, &file)
|
downloadLink, account, err = c.client.GetDownloadLink(ct.Torrent, &file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("retry failed to get download link: %w", err)
|
return nil, fmt.Errorf("retry failed to get download link: %w", err)
|
||||||
}
|
}
|
||||||
@@ -123,7 +125,7 @@ func (c *Cache) fetchDownloadLink(torrentName, filename, fileLink string) (*type
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set link to cache
|
// Set link to cache
|
||||||
go c.client.Accounts().SetDownloadLink(downloadLink)
|
go c.client.Accounts().SetDownloadLink(account, downloadLink)
|
||||||
return downloadLink, nil
|
return downloadLink, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,30 +136,25 @@ func (c *Cache) GetFileDownloadLinks(t CachedTorrent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) checkDownloadLink(link string) (*types.DownloadLink, error) {
|
func (c *Cache) checkDownloadLink(link string) (string, error) {
|
||||||
|
|
||||||
dl, err := c.client.Accounts().GetDownloadLink(link)
|
dl, _, err := c.client.Accounts().GetDownloadLink(link)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return "", err
|
||||||
}
|
}
|
||||||
if !c.downloadLinkIsInvalid(dl.DownloadLink) {
|
if !c.downloadLinkIsInvalid(dl.DownloadLink) {
|
||||||
return dl, nil
|
return dl.DownloadLink, nil
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("download link not found for %s", link)
|
return "", fmt.Errorf("download link not found for %s", link)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) MarkDownloadLinkAsInvalid(link string, downloadLink *types.DownloadLink, reason string) {
|
func (c *Cache) MarkDownloadLinkAsInvalid(link, downloadLink, reason string) {
|
||||||
c.invalidDownloadLinks.Store(downloadLink.DownloadLink, reason)
|
c.invalidDownloadLinks.Store(downloadLink, reason)
|
||||||
// Remove the download api key from active
|
// Remove the download api key from active
|
||||||
if reason == "bandwidth_exceeded" {
|
if reason == "bandwidth_exceeded" {
|
||||||
// Disable the account
|
// Disable the account
|
||||||
account, err := c.client.Accounts().GetAccountFromLink(link)
|
account, err := c.client.Accounts().GetAccountFromLink(link)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
maskedToken := ""
|
|
||||||
if account != nil {
|
|
||||||
maskedToken = account.MaskedToken
|
|
||||||
}
|
|
||||||
c.logger.Warn().Err(err).Str("account", maskedToken).Str("link", link).Msg("Failed to mark download link as invalid")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.client.Accounts().Disable(account)
|
c.client.Accounts().Disable(account)
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/sirrobot01/decypharr/internal/config"
|
"github.com/sirrobot01/decypharr/internal/config"
|
||||||
"github.com/sirrobot01/decypharr/internal/utils"
|
|
||||||
"slices"
|
"slices"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@@ -39,7 +37,6 @@ type Account struct {
|
|||||||
Disabled bool
|
Disabled bool
|
||||||
InUse bool
|
InUse bool
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
MaskedToken string `json:"masked_token"`
|
|
||||||
links map[string]*DownloadLink
|
links map[string]*DownloadLink
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
TrafficUsed int64 `json:"traffic_used"` // Traffic used in bytes
|
TrafficUsed int64 `json:"traffic_used"` // Traffic used in bytes
|
||||||
@@ -98,12 +95,13 @@ func (a *Accounts) Current() *Account {
|
|||||||
return current
|
return current
|
||||||
}
|
}
|
||||||
current = activeAccounts[0]
|
current = activeAccounts[0]
|
||||||
return a.setCurrent(current)
|
a.setCurrent(current)
|
||||||
|
return current
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Accounts) setCurrent(account *Account) *Account {
|
func (a *Accounts) setCurrent(account *Account) {
|
||||||
if account == nil {
|
if account == nil {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
// Set every account InUse to false
|
// Set every account InUse to false
|
||||||
a.accounts.Range(func(key, value interface{}) bool {
|
a.accounts.Range(func(key, value interface{}) bool {
|
||||||
@@ -116,24 +114,25 @@ func (a *Accounts) setCurrent(account *Account) *Account {
|
|||||||
})
|
})
|
||||||
account.InUse = true
|
account.InUse = true
|
||||||
a.current.Store(account)
|
a.current.Store(account)
|
||||||
return account
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Accounts) Disable(account *Account) {
|
func (a *Accounts) Disable(account *Account) {
|
||||||
account.Disabled = true
|
account.Disabled = true
|
||||||
account.InUse = false
|
|
||||||
a.accounts.Store(account.Token, account)
|
a.accounts.Store(account.Token, account)
|
||||||
|
|
||||||
current := a.getCurrent()
|
current := a.getCurrent()
|
||||||
|
|
||||||
if current.Equals(account) {
|
if current.Equals(account) {
|
||||||
var newCurrent *Account
|
var newCurrent *Account
|
||||||
activeAccounts := a.Active()
|
|
||||||
if len(activeAccounts) > 0 {
|
a.accounts.Range(func(key, value interface{}) bool {
|
||||||
newCurrent = activeAccounts[0]
|
acc, ok := value.(*Account)
|
||||||
} else {
|
if ok && !acc.Disabled {
|
||||||
newCurrent = a.All()[0]
|
newCurrent = acc
|
||||||
}
|
return false // Break the loop
|
||||||
|
}
|
||||||
|
return true // Continue the loop
|
||||||
|
})
|
||||||
a.setCurrent(newCurrent)
|
a.setCurrent(newCurrent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,20 +155,19 @@ func (a *Accounts) Reset() {
|
|||||||
a.setCurrent(current)
|
a.setCurrent(current)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Accounts) GetDownloadLink(fileLink string) (*DownloadLink, error) {
|
func (a *Accounts) GetDownloadLink(fileLink string) (*DownloadLink, *Account, error) {
|
||||||
current := a.Current()
|
current := a.Current()
|
||||||
if current == nil {
|
if current == nil {
|
||||||
return nil, NoActiveAccountsError
|
return nil, nil, NoActiveAccountsError
|
||||||
}
|
}
|
||||||
dl, ok := current.GetDownloadLink(fileLink)
|
dl, ok := current.getLink(fileLink)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, NoDownloadLinkError
|
return nil, current, NoDownloadLinkError
|
||||||
}
|
}
|
||||||
if !dl.Valid() {
|
if err := dl.Valid(); err != nil {
|
||||||
return nil, fmt.Errorf("invalid download link: %s", dl.Link)
|
return nil, current, err
|
||||||
}
|
}
|
||||||
dl.Token = current.Token
|
return dl, current, nil
|
||||||
return dl, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Accounts) GetAccountFromLink(fileLink string) (*Account, error) {
|
func (a *Accounts) GetAccountFromLink(fileLink string) (*Account, error) {
|
||||||
@@ -177,7 +175,7 @@ func (a *Accounts) GetAccountFromLink(fileLink string) (*Account, error) {
|
|||||||
if currentAccount == nil {
|
if currentAccount == nil {
|
||||||
return nil, NoActiveAccountsError
|
return nil, NoActiveAccountsError
|
||||||
}
|
}
|
||||||
dl, ok := currentAccount.GetDownloadLink(fileLink)
|
dl, ok := currentAccount.getLink(fileLink)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, NoDownloadLinkError
|
return nil, NoDownloadLinkError
|
||||||
}
|
}
|
||||||
@@ -188,22 +186,13 @@ func (a *Accounts) GetAccountFromLink(fileLink string) (*Account, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetDownloadLink sets the download link for the current account
|
// SetDownloadLink sets the download link for the current account
|
||||||
func (a *Accounts) SetDownloadLink(dl *DownloadLink) {
|
func (a *Accounts) SetDownloadLink(account *Account, dl *DownloadLink) {
|
||||||
if dl == nil {
|
if dl == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var account *Account
|
|
||||||
// Get account from link token
|
|
||||||
if dl.Token != "" {
|
|
||||||
|
|
||||||
if acc, ok := a.accounts.Load(dl.Token); ok {
|
|
||||||
account = acc.(*Account)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if account == nil {
|
if account == nil {
|
||||||
account = a.getCurrent()
|
account = a.getCurrent()
|
||||||
}
|
}
|
||||||
|
|
||||||
account.setLink(dl.Link, dl)
|
account.setLink(dl.Link, dl)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,11 +210,12 @@ func (a *Accounts) GetLinksCount() int {
|
|||||||
return a.Current().LinksCount()
|
return a.Current().LinksCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Accounts) SetDownloadLinks(links map[string]*DownloadLink) {
|
func (a *Accounts) SetDownloadLinks(account *Account, links map[string]*DownloadLink) {
|
||||||
if a.Current() == nil {
|
if account == nil {
|
||||||
return
|
account = a.Current()
|
||||||
}
|
}
|
||||||
a.Current().setLinks(links)
|
account.setLinks(links)
|
||||||
|
a.accounts.Store(account.Token, account)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Accounts) Update(account *Account) {
|
func (a *Accounts) Update(account *Account) {
|
||||||
@@ -237,11 +227,10 @@ func (a *Accounts) Update(account *Account) {
|
|||||||
|
|
||||||
func newAccount(debridName, token string, index int) *Account {
|
func newAccount(debridName, token string, index int) *Account {
|
||||||
return &Account{
|
return &Account{
|
||||||
Debrid: debridName,
|
Debrid: debridName,
|
||||||
Token: token,
|
Token: token,
|
||||||
MaskedToken: utils.Mask(token),
|
Order: index,
|
||||||
Order: index,
|
links: make(map[string]*DownloadLink),
|
||||||
links: make(map[string]*DownloadLink),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +241,7 @@ func (a *Account) Equals(other *Account) bool {
|
|||||||
return a.Token == other.Token && a.Debrid == other.Debrid
|
return a.Token == other.Token && a.Debrid == other.Debrid
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Account) GetDownloadLink(fileLink string) (*DownloadLink, bool) {
|
func (a *Account) getLink(fileLink string) (*DownloadLink, bool) {
|
||||||
a.mu.RLock()
|
a.mu.RLock()
|
||||||
defer a.mu.RUnlock()
|
defer a.mu.RUnlock()
|
||||||
dl, ok := a.links[a.sliceFileLink(fileLink)]
|
dl, ok := a.links[a.sliceFileLink(fileLink)]
|
||||||
@@ -284,7 +273,7 @@ func (a *Account) setLinks(links map[string]*DownloadLink) {
|
|||||||
a.mu.Lock()
|
a.mu.Lock()
|
||||||
defer a.mu.Unlock()
|
defer a.mu.Unlock()
|
||||||
for _, dl := range links {
|
for _, dl := range links {
|
||||||
if !dl.Valid() {
|
if err := dl.Valid(); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
a.links[a.sliceFileLink(dl.Link)] = dl
|
a.links[a.sliceFileLink(dl.Link)] = dl
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ type Client interface {
|
|||||||
SubmitMagnet(tr *Torrent) (*Torrent, error)
|
SubmitMagnet(tr *Torrent) (*Torrent, error)
|
||||||
CheckStatus(tr *Torrent) (*Torrent, error)
|
CheckStatus(tr *Torrent) (*Torrent, error)
|
||||||
GetFileDownloadLinks(tr *Torrent) error
|
GetFileDownloadLinks(tr *Torrent) error
|
||||||
GetDownloadLink(tr *Torrent, file *File) (*DownloadLink, error)
|
GetDownloadLink(tr *Torrent, file *File) (*DownloadLink, *Account, error)
|
||||||
DeleteTorrent(torrentId string) error
|
DeleteTorrent(torrentId string) error
|
||||||
IsAvailable(infohashes []string) map[string]bool
|
IsAvailable(infohashes []string) map[string]bool
|
||||||
GetDownloadUncached() bool
|
GetDownloadUncached() bool
|
||||||
|
|||||||
@@ -176,19 +176,17 @@ type DownloadLink struct {
|
|||||||
Generated time.Time `json:"generated"`
|
Generated time.Time `json:"generated"`
|
||||||
Size int64 `json:"size"`
|
Size int64 `json:"size"`
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
ExpiresAt time.Time `json:"expires_at"`
|
ExpiresAt time.Time
|
||||||
MaskedToken string `json:"masked_token"`
|
|
||||||
Token string `json:"token"` // The token or api key used to generate this link
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dl *DownloadLink) Valid() bool {
|
func (dl *DownloadLink) Valid() error {
|
||||||
if dl.DownloadLink == "" {
|
if dl.DownloadLink == "" {
|
||||||
return false
|
return EmptyDownloadLinkError
|
||||||
}
|
}
|
||||||
if dl.ExpiresAt.IsZero() || dl.ExpiresAt.Before(time.Now()) {
|
if dl.ExpiresAt.IsZero() || dl.ExpiresAt.Before(time.Now()) {
|
||||||
return false
|
return DownloadLinkExpiredError
|
||||||
}
|
}
|
||||||
return true
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dl *DownloadLink) String() string {
|
func (dl *DownloadLink) String() string {
|
||||||
|
|||||||
@@ -123,11 +123,21 @@ func (s *Server) handleStats(w http.ResponseWriter, r *http.Request) {
|
|||||||
accounts := client.Accounts().All()
|
accounts := client.Accounts().All()
|
||||||
accountDetails := make([]map[string]any, 0)
|
accountDetails := make([]map[string]any, 0)
|
||||||
for _, account := range accounts {
|
for _, account := range accounts {
|
||||||
|
// Mask token - show first 8 characters and last 4 characters
|
||||||
|
maskedToken := ""
|
||||||
|
if len(account.Token) > 12 {
|
||||||
|
maskedToken = account.Token[:8] + "****" + account.Token[len(account.Token)-4:]
|
||||||
|
} else if len(account.Token) > 8 {
|
||||||
|
maskedToken = account.Token[:4] + "****" + account.Token[len(account.Token)-2:]
|
||||||
|
} else {
|
||||||
|
maskedToken = "****"
|
||||||
|
}
|
||||||
|
|
||||||
accountDetail := map[string]any{
|
accountDetail := map[string]any{
|
||||||
"order": account.Order,
|
"order": account.Order,
|
||||||
"disabled": account.Disabled,
|
"disabled": account.Disabled,
|
||||||
"in_use": account.InUse,
|
"in_use": account.InUse,
|
||||||
"masked_token": account.MaskedToken,
|
"token_masked": maskedToken,
|
||||||
"username": account.Username,
|
"username": account.Username,
|
||||||
"traffic_used": account.TrafficUsed,
|
"traffic_used": account.TrafficUsed,
|
||||||
"links_count": account.LinksCount(),
|
"links_count": account.LinksCount(),
|
||||||
|
|||||||
@@ -384,13 +384,12 @@
|
|||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h5 class="font-medium text-sm">Account #${account.order + 1}</h5>
|
<h5 class="font-medium text-sm">Account #${account.order + 1}</h5>
|
||||||
${statusBadge}
|
${statusBadge}
|
||||||
${inUseBadge}
|
|
||||||
</div>
|
</div>
|
||||||
<p class="text-xs text-base-content/70 mt-1">${account.username || 'No username'}</p>
|
<p class="text-xs text-base-content/70 mt-1">${account.username || 'No username'}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<div class="text-xs font-mono text-base-content/80">
|
<div class="text-xs font-mono text-base-content/80">
|
||||||
Token: ${account.masked_token || '****'}
|
Token: ${account.token_masked || '****'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package webdav
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/sirrobot01/decypharr/pkg/debrid/types"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@@ -30,7 +29,7 @@ type File struct {
|
|||||||
name string
|
name string
|
||||||
torrentName string
|
torrentName string
|
||||||
link string
|
link string
|
||||||
downloadLink *types.DownloadLink
|
downloadLink string
|
||||||
size int64
|
size int64
|
||||||
isDir bool
|
isDir bool
|
||||||
fileId string
|
fileId string
|
||||||
@@ -56,26 +55,26 @@ func (f *File) Close() error {
|
|||||||
// This is just to satisfy the os.File interface
|
// This is just to satisfy the os.File interface
|
||||||
f.content = nil
|
f.content = nil
|
||||||
f.children = nil
|
f.children = nil
|
||||||
f.downloadLink = nil
|
f.downloadLink = ""
|
||||||
f.readOffset = 0
|
f.readOffset = 0
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) getDownloadLink() (*types.DownloadLink, error) {
|
func (f *File) getDownloadLink() (string, error) {
|
||||||
// Check if we already have a final URL cached
|
// Check if we already have a final URL cached
|
||||||
|
|
||||||
if f.downloadLink != nil && isValidURL(f.downloadLink.DownloadLink) {
|
if f.downloadLink != "" && isValidURL(f.downloadLink) {
|
||||||
return f.downloadLink, nil
|
return f.downloadLink, nil
|
||||||
}
|
}
|
||||||
downloadLink, err := f.cache.GetDownloadLink(f.torrentName, f.name, f.link)
|
downloadLink, err := f.cache.GetDownloadLink(f.torrentName, f.name, f.link)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return "", err
|
||||||
}
|
}
|
||||||
if downloadLink != nil && isValidURL(downloadLink.DownloadLink) {
|
if downloadLink != "" && isValidURL(downloadLink) {
|
||||||
f.downloadLink = downloadLink
|
f.downloadLink = downloadLink
|
||||||
return downloadLink, nil
|
return downloadLink, nil
|
||||||
}
|
}
|
||||||
return nil, os.ErrNotExist
|
return "", os.ErrNotExist
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) getDownloadByteRange() (*[2]int64, error) {
|
func (f *File) getDownloadByteRange() (*[2]int64, error) {
|
||||||
@@ -139,12 +138,12 @@ func (f *File) streamWithRetry(w http.ResponseWriter, r *http.Request, retryCoun
|
|||||||
return &streamError{Err: err, StatusCode: http.StatusPreconditionFailed}
|
return &streamError{Err: err, StatusCode: http.StatusPreconditionFailed}
|
||||||
}
|
}
|
||||||
|
|
||||||
if downloadLink == nil {
|
if downloadLink == "" {
|
||||||
return &streamError{Err: fmt.Errorf("empty download link"), StatusCode: http.StatusNotFound}
|
return &streamError{Err: fmt.Errorf("empty download link"), StatusCode: http.StatusNotFound}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create upstream request with streaming optimizations
|
// Create upstream request with streaming optimizations
|
||||||
upstreamReq, err := http.NewRequest("GET", downloadLink.DownloadLink, nil)
|
upstreamReq, err := http.NewRequest("GET", downloadLink, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &streamError{Err: err, StatusCode: http.StatusInternalServerError}
|
return &streamError{Err: err, StatusCode: http.StatusInternalServerError}
|
||||||
}
|
}
|
||||||
@@ -169,7 +168,6 @@ func (f *File) streamWithRetry(w http.ResponseWriter, r *http.Request, retryCoun
|
|||||||
// Retry with new download link
|
// Retry with new download link
|
||||||
_log.Debug().
|
_log.Debug().
|
||||||
Int("retry_count", retryCount+1).
|
Int("retry_count", retryCount+1).
|
||||||
Str("account", downloadLink.MaskedToken).
|
|
||||||
Str("file", f.name).
|
Str("file", f.name).
|
||||||
Msg("Retrying stream request")
|
Msg("Retrying stream request")
|
||||||
return f.streamWithRetry(w, r, retryCount+1)
|
return f.streamWithRetry(w, r, retryCount+1)
|
||||||
@@ -281,7 +279,6 @@ func (f *File) handleUpstream(resp *http.Response, retryCount, maxRetries int) (
|
|||||||
_log.Debug().
|
_log.Debug().
|
||||||
Str("file", f.name).
|
Str("file", f.name).
|
||||||
Int("retry_count", retryCount).
|
Int("retry_count", retryCount).
|
||||||
Str("account", f.downloadLink.MaskedToken).
|
|
||||||
Msg("Bandwidth exceeded. Marking link as invalid")
|
Msg("Bandwidth exceeded. Marking link as invalid")
|
||||||
|
|
||||||
f.cache.MarkDownloadLinkAsInvalid(f.link, f.downloadLink, "bandwidth_exceeded")
|
f.cache.MarkDownloadLinkAsInvalid(f.link, f.downloadLink, "bandwidth_exceeded")
|
||||||
@@ -292,7 +289,7 @@ func (f *File) handleUpstream(resp *http.Response, retryCount, maxRetries int) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false, &streamError{
|
return false, &streamError{
|
||||||
Err: fmt.Errorf("bandwidth exceeded for %s after %d retries", f.downloadLink.MaskedToken, retryCount),
|
Err: fmt.Errorf("bandwidth exceeded after %d retries", retryCount),
|
||||||
StatusCode: http.StatusServiceUnavailable,
|
StatusCode: http.StatusServiceUnavailable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -315,7 +312,7 @@ func (f *File) handleUpstream(resp *http.Response, retryCount, maxRetries int) (
|
|||||||
// Try to regenerate download link if we haven't exceeded retries
|
// Try to regenerate download link if we haven't exceeded retries
|
||||||
if retryCount < maxRetries {
|
if retryCount < maxRetries {
|
||||||
// Clear cached link to force regeneration
|
// Clear cached link to force regeneration
|
||||||
f.downloadLink = nil
|
f.downloadLink = ""
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -451,15 +451,15 @@ func (h *Handler) handleGet(w http.ResponseWriter, r *http.Request) {
|
|||||||
// Handle nginx proxy (X-Accel-Redirect)
|
// Handle nginx proxy (X-Accel-Redirect)
|
||||||
if file.content == nil && !file.isRar && h.cache.StreamWithRclone() {
|
if file.content == nil && !file.isRar && h.cache.StreamWithRclone() {
|
||||||
link, err := file.getDownloadLink()
|
link, err := file.getDownloadLink()
|
||||||
if err != nil || link == nil {
|
if err != nil || link == "" {
|
||||||
http.Error(w, "Could not fetch download link", http.StatusPreconditionFailed)
|
http.Error(w, "Could not fetch download link", http.StatusPreconditionFailed)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", fi.Name()))
|
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", fi.Name()))
|
||||||
w.Header().Set("X-Accel-Redirect", link.DownloadLink)
|
w.Header().Set("X-Accel-Redirect", link)
|
||||||
w.Header().Set("X-Accel-Buffering", "no")
|
w.Header().Set("X-Accel-Buffering", "no")
|
||||||
http.Redirect(w, r, link.DownloadLink, http.StatusFound)
|
http.Redirect(w, r, link, http.StatusFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user