feat(clients): Transmission set label (#1204)

* feat(clients): Transmission set label

* fix(clients): Transmission fmt

* fix(clients): Transmission set label before reannounce
This commit is contained in:
ze0s 2023-10-23 19:02:04 +02:00 committed by GitHub
parent d602b1e868
commit 522f22db46
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 40 deletions

View file

@ -5,6 +5,7 @@ package action
import ( import (
"context" "context"
"fmt"
"strings" "strings"
"time" "time"
@ -16,9 +17,11 @@ import (
const ( const (
ReannounceMaxAttempts = 50 ReannounceMaxAttempts = 50
ReannounceInterval = 7000 ReannounceInterval = 7 // interval in seconds
) )
var ErrReannounceTookTooLong = errors.New("ErrReannounceTookTooLong")
func (s *service) transmission(ctx context.Context, action *domain.Action, release domain.Release) ([]string, error) { func (s *service) transmission(ctx context.Context, action *domain.Action, release domain.Release) ([]string, error) {
s.log.Debug().Msgf("action Transmission: %s", action.Name) s.log.Debug().Msgf("action Transmission: %s", action.Name)
@ -36,8 +39,9 @@ func (s *service) transmission(ctx context.Context, action *domain.Action, relea
} }
tbt, err := transmissionrpc.New(client.Host, client.Username, client.Password, &transmissionrpc.AdvancedConfig{ tbt, err := transmissionrpc.New(client.Host, client.Username, client.Password, &transmissionrpc.AdvancedConfig{
HTTPS: client.TLS, HTTPS: client.TLS,
Port: uint16(client.Port), Port: uint16(client.Port),
UserAgent: "autobrr",
}) })
if err != nil { if err != nil {
return nil, errors.Wrap(err, "error logging into client: %s", client.Host) return nil, errors.Wrap(err, "error logging into client: %s", client.Host)
@ -70,42 +74,71 @@ func (s *service) transmission(ctx context.Context, action *domain.Action, relea
return nil, errors.Wrap(err, "could not add torrent from magnet %s to client: %s", release.MagnetURI, client.Host) return nil, errors.Wrap(err, "could not add torrent from magnet %s to client: %s", release.MagnetURI, client.Host)
} }
if action.Label != "" {
p := transmissionrpc.TorrentSetPayload{
IDs: []int64{*torrent.ID},
Labels: []string{action.Label},
}
if err := tbt.TorrentSet(ctx, p); err != nil {
return nil, errors.Wrap(err, "could not set label for hash %s to client: %s", *torrent.HashString, client.Host)
}
s.log.Debug().Msgf("set label for torrent hash %s successful to client: '%s'", *torrent.HashString, client.Name)
}
s.log.Info().Msgf("torrent from magnet with hash %v successfully added to client: '%s'", torrent.HashString, client.Name) s.log.Info().Msgf("torrent from magnet with hash %v successfully added to client: '%s'", torrent.HashString, client.Name)
return nil, nil return nil, nil
} else {
if release.TorrentTmpFile == "" {
if err := release.DownloadTorrentFileCtx(ctx); err != nil {
s.log.Error().Err(err).Msgf("could not download torrent file for release: %s", release.TorrentName)
return nil, err
}
}
b64, err := transmissionrpc.File2Base64(release.TorrentTmpFile)
if err != nil {
return nil, errors.Wrap(err, "cant encode file %s into base64", release.TorrentTmpFile)
}
payload.MetaInfo = &b64
// Prepare and send payload
torrent, err := tbt.TorrentAdd(ctx, payload)
if err != nil {
return nil, errors.Wrap(err, "could not add torrent %v to client: %v", release.TorrentTmpFile, client.Host)
}
if !action.Paused && !action.ReAnnounceSkip {
if err := s.transmissionReannounce(ctx, action, tbt, *torrent.ID); err != nil {
return nil, errors.Wrap(err, "could not reannounce torrent: %s", *torrent.HashString)
}
return nil, nil
}
s.log.Info().Msgf("torrent with hash %s successfully added to client: '%s'", *torrent.HashString, client.Name)
} }
if release.TorrentTmpFile == "" {
if err := release.DownloadTorrentFileCtx(ctx); err != nil {
s.log.Error().Err(err).Msgf("could not download torrent file for release: %s", release.TorrentName)
return nil, err
}
}
b64, err := transmissionrpc.File2Base64(release.TorrentTmpFile)
if err != nil {
return nil, errors.Wrap(err, "cant encode file %s into base64", release.TorrentTmpFile)
}
payload.MetaInfo = &b64
// Prepare and send payload
torrent, err := tbt.TorrentAdd(ctx, payload)
if err != nil {
return nil, errors.Wrap(err, "could not add torrent %s to client: %s", release.TorrentTmpFile, client.Host)
}
if action.Label != "" {
p := transmissionrpc.TorrentSetPayload{
IDs: []int64{*torrent.ID},
Labels: []string{action.Label},
}
if err := tbt.TorrentSet(ctx, p); err != nil {
return nil, errors.Wrap(err, "could not set label for hash %s to client: %s", *torrent.HashString, client.Host)
}
s.log.Debug().Msgf("set label for torrent hash %s successful to client: '%s'", *torrent.HashString, client.Name)
}
if !action.Paused && !action.ReAnnounceSkip {
if err := s.transmissionReannounce(ctx, action, tbt, *torrent.ID); err != nil {
if errors.Is(err, ErrReannounceTookTooLong) {
return []string{fmt.Sprintf("reannounce took too long for torrent: %s, deleted", *torrent.HashString)}, nil
}
return nil, errors.Wrap(err, "could not reannounce torrent: %s", *torrent.HashString)
}
return nil, nil
}
s.log.Info().Msgf("torrent with hash %s successfully added to client: '%s'", *torrent.HashString, client.Name)
return rejections, nil return rejections, nil
} }
@ -123,7 +156,7 @@ func (s *service) transmissionReannounce(ctx context.Context, action *domain.Act
attempts := 0 attempts := 0
for attempts <= maxAttempts { for attempts <= maxAttempts {
s.log.Debug().Msgf("re-announce %v attempt: %d/%d", torrentId, attempts, maxAttempts) s.log.Debug().Msgf("re-announce %d attempt: %d/%d", torrentId, attempts, maxAttempts)
// add delay for next run // add delay for next run
time.Sleep(time.Duration(interval) * time.Second) time.Sleep(time.Duration(interval) * time.Second)
@ -157,7 +190,7 @@ func (s *service) transmissionReannounce(ctx context.Context, action *domain.Act
} }
} }
s.log.Debug().Msgf("transmission re-announce not working yet, lets re-announce %v again attempt: %d/%d", torrentId, attempts, maxAttempts) s.log.Debug().Msgf("transmission re-announce not working yet, lets re-announce %d again attempt: %d/%d", torrentId, attempts, maxAttempts)
if err := tbt.TorrentReannounceIDs(ctx, []int64{torrentId}); err != nil { if err := tbt.TorrentReannounceIDs(ctx, []int64{torrentId}); err != nil {
return errors.Wrap(err, "failed to reannounce") return errors.Wrap(err, "failed to reannounce")
@ -173,7 +206,7 @@ func (s *service) transmissionReannounce(ctx context.Context, action *domain.Act
return errors.Wrap(err, "could not delete torrent: %v from client after max re-announce attempts reached", torrentId) return errors.Wrap(err, "could not delete torrent: %v from client after max re-announce attempts reached", torrentId)
} }
return errors.New("transmission re-announce took too long, deleted torrent %v", torrentId) return errors.Wrap(ErrReannounceTookTooLong, "transmission re-announce took too long, deleted torrent %v", torrentId)
} }
return nil return nil

View file

@ -346,8 +346,8 @@ const TypeForm = ({ action, idx, clients }: TypeFormProps) => {
<div className="col-span-6"> <div className="col-span-6">
<SwitchGroup <SwitchGroup
name={`actions.${idx}.reannounce_skip`} name={`actions.${idx}.reannounce_skip`}
label="Skip reannounce" label="Disable reannounce"
description="If reannounce is not needed, skip" description="Reannounce is enabled by default. Disable if not needed."
/> />
<SwitchGroup <SwitchGroup
name={`actions.${idx}.reannounce_delete`} name={`actions.${idx}.reannounce_delete`}
@ -484,6 +484,13 @@ const TypeForm = ({ action, idx, clients }: TypeFormProps) => {
label="Add paused" label="Add paused"
/> />
</div> </div>
<TextField
name={`actions.${idx}.label`}
label="Label"
columns={6}
placeholder="eg. label1"
/>
</div> </div>
<CollapsableSection title="Re-announce" subtitle="Re-announce options"> <CollapsableSection title="Re-announce" subtitle="Re-announce options">
@ -504,7 +511,7 @@ const TypeForm = ({ action, idx, clients }: TypeFormProps) => {
<SwitchGroup <SwitchGroup
name={`actions.${idx}.reannounce_skip`} name={`actions.${idx}.reannounce_skip`}
label="Disable reannounce" label="Disable reannounce"
description="Reannounce is enabled by default. Disable if needed." description="Reannounce is enabled by default. Disable if not needed."
/> />
<SwitchGroup <SwitchGroup
name={`actions.${idx}.reannounce_delete`} name={`actions.${idx}.reannounce_delete`}