mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 08:49:13 +00:00
feat(actions): add more macro variables (#157)
* feat(actions): add more macro variables * feat: add more macros * feat: add more tests
This commit is contained in:
parent
e0e4bf6202
commit
5a45851677
6 changed files with 252 additions and 68 deletions
|
@ -13,7 +13,7 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *service) deluge(action domain.Action, torrentFile string) error {
|
func (s *service) deluge(action domain.Action, release domain.Release) error {
|
||||||
log.Debug().Msgf("action Deluge: %v", action.Name)
|
log.Debug().Msgf("action Deluge: %v", action.Name)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
@ -40,12 +40,12 @@ func (s *service) deluge(action domain.Action, torrentFile string) error {
|
||||||
|
|
||||||
switch client.Type {
|
switch client.Type {
|
||||||
case "DELUGE_V1":
|
case "DELUGE_V1":
|
||||||
if err = delugeV1(client, settings, action, torrentFile); err != nil {
|
if err = delugeV1(client, settings, action, release); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case "DELUGE_V2":
|
case "DELUGE_V2":
|
||||||
if err = delugeV2(client, settings, action, torrentFile); err != nil {
|
if err = delugeV2(client, settings, action, release); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ func (s *service) delugeCheckRulesCanDownload(action domain.Action) (bool, error
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func delugeV1(client *domain.DownloadClient, settings delugeClient.Settings, action domain.Action, torrentFile string) error {
|
func delugeV1(client *domain.DownloadClient, settings delugeClient.Settings, action domain.Action, release domain.Release) error {
|
||||||
|
|
||||||
deluge := delugeClient.NewV1(settings)
|
deluge := delugeClient.NewV1(settings)
|
||||||
|
|
||||||
|
@ -148,27 +148,37 @@ func delugeV1(client *domain.DownloadClient, settings delugeClient.Settings, act
|
||||||
|
|
||||||
defer deluge.Close()
|
defer deluge.Close()
|
||||||
|
|
||||||
t, err := ioutil.ReadFile(torrentFile)
|
t, err := ioutil.ReadFile(release.TorrentTmpFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msgf("could not read torrent file: %v", torrentFile)
|
log.Error().Stack().Err(err).Msgf("could not read torrent file: %v", release.TorrentTmpFile)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// encode file to base64 before sending to deluge
|
// encode file to base64 before sending to deluge
|
||||||
encodedFile := base64.StdEncoding.EncodeToString(t)
|
encodedFile := base64.StdEncoding.EncodeToString(t)
|
||||||
if encodedFile == "" {
|
if encodedFile == "" {
|
||||||
log.Error().Stack().Err(err).Msgf("could not encode torrent file: %v", torrentFile)
|
log.Error().Stack().Err(err).Msgf("could not encode torrent file: %v", release.TorrentTmpFile)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// set options
|
// set options
|
||||||
options := delugeClient.Options{}
|
options := delugeClient.Options{}
|
||||||
|
|
||||||
|
// macros handle args and replace vars
|
||||||
|
m := NewMacro(release)
|
||||||
|
|
||||||
if action.Paused {
|
if action.Paused {
|
||||||
options.AddPaused = &action.Paused
|
options.AddPaused = &action.Paused
|
||||||
}
|
}
|
||||||
if action.SavePath != "" {
|
if action.SavePath != "" {
|
||||||
options.DownloadLocation = &action.SavePath
|
// parse and replace values in argument string before continuing
|
||||||
|
savePathArgs, err := m.Parse(action.SavePath)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err).Msgf("could not parse macro: %v", action.SavePath)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
options.DownloadLocation = &savePathArgs
|
||||||
}
|
}
|
||||||
if action.LimitDownloadSpeed > 0 {
|
if action.LimitDownloadSpeed > 0 {
|
||||||
maxDL := int(action.LimitDownloadSpeed)
|
maxDL := int(action.LimitDownloadSpeed)
|
||||||
|
@ -181,9 +191,9 @@ func delugeV1(client *domain.DownloadClient, settings delugeClient.Settings, act
|
||||||
|
|
||||||
log.Trace().Msgf("action Deluge options: %+v", options)
|
log.Trace().Msgf("action Deluge options: %+v", options)
|
||||||
|
|
||||||
torrentHash, err := deluge.AddTorrentFile(torrentFile, encodedFile, &options)
|
torrentHash, err := deluge.AddTorrentFile(release.TorrentTmpFile, encodedFile, &options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msgf("could not add torrent %v to client: %v", torrentFile, client.Name)
|
log.Error().Stack().Err(err).Msgf("could not add torrent %v to client: %v", release.TorrentTmpFile, client.Name)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,9 +204,16 @@ func delugeV1(client *domain.DownloadClient, settings delugeClient.Settings, act
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parse and replace values in argument string before continuing
|
||||||
|
labelArgs, err := m.Parse(action.Label)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err).Msgf("could not parse macro: %v", action.Label)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if p != nil {
|
if p != nil {
|
||||||
// TODO first check if label exists, if not, add it, otherwise set
|
// TODO first check if label exists, if not, add it, otherwise set
|
||||||
err = p.SetTorrentLabel(torrentHash, action.Label)
|
err = p.SetTorrentLabel(torrentHash, labelArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msgf("could not set label: %v on client: %v", action.Label, client.Name)
|
log.Error().Stack().Err(err).Msgf("could not set label: %v on client: %v", action.Label, client.Name)
|
||||||
return err
|
return err
|
||||||
|
@ -209,7 +226,7 @@ func delugeV1(client *domain.DownloadClient, settings delugeClient.Settings, act
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func delugeV2(client *domain.DownloadClient, settings delugeClient.Settings, action domain.Action, torrentFile string) error {
|
func delugeV2(client *domain.DownloadClient, settings delugeClient.Settings, action domain.Action, release domain.Release) error {
|
||||||
|
|
||||||
deluge := delugeClient.NewV2(settings)
|
deluge := delugeClient.NewV2(settings)
|
||||||
|
|
||||||
|
@ -222,27 +239,37 @@ func delugeV2(client *domain.DownloadClient, settings delugeClient.Settings, act
|
||||||
|
|
||||||
defer deluge.Close()
|
defer deluge.Close()
|
||||||
|
|
||||||
t, err := ioutil.ReadFile(torrentFile)
|
t, err := ioutil.ReadFile(release.TorrentTmpFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msgf("could not read torrent file: %v", torrentFile)
|
log.Error().Stack().Err(err).Msgf("could not read torrent file: %v", release.TorrentTmpFile)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// encode file to base64 before sending to deluge
|
// encode file to base64 before sending to deluge
|
||||||
encodedFile := base64.StdEncoding.EncodeToString(t)
|
encodedFile := base64.StdEncoding.EncodeToString(t)
|
||||||
if encodedFile == "" {
|
if encodedFile == "" {
|
||||||
log.Error().Stack().Err(err).Msgf("could not encode torrent file: %v", torrentFile)
|
log.Error().Stack().Err(err).Msgf("could not encode torrent file: %v", release.TorrentTmpFile)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// set options
|
// set options
|
||||||
options := delugeClient.Options{}
|
options := delugeClient.Options{}
|
||||||
|
|
||||||
|
// macros handle args and replace vars
|
||||||
|
m := NewMacro(release)
|
||||||
|
|
||||||
if action.Paused {
|
if action.Paused {
|
||||||
options.AddPaused = &action.Paused
|
options.AddPaused = &action.Paused
|
||||||
}
|
}
|
||||||
if action.SavePath != "" {
|
if action.SavePath != "" {
|
||||||
options.DownloadLocation = &action.SavePath
|
// parse and replace values in argument string before continuing
|
||||||
|
savePathArgs, err := m.Parse(action.SavePath)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err).Msgf("could not parse macro: %v", action.SavePath)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
options.DownloadLocation = &savePathArgs
|
||||||
}
|
}
|
||||||
if action.LimitDownloadSpeed > 0 {
|
if action.LimitDownloadSpeed > 0 {
|
||||||
maxDL := int(action.LimitDownloadSpeed)
|
maxDL := int(action.LimitDownloadSpeed)
|
||||||
|
@ -255,9 +282,9 @@ func delugeV2(client *domain.DownloadClient, settings delugeClient.Settings, act
|
||||||
|
|
||||||
log.Trace().Msgf("action Deluge options: %+v", options)
|
log.Trace().Msgf("action Deluge options: %+v", options)
|
||||||
|
|
||||||
torrentHash, err := deluge.AddTorrentFile(torrentFile, encodedFile, &options)
|
torrentHash, err := deluge.AddTorrentFile(release.TorrentTmpFile, encodedFile, &options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msgf("could not add torrent %v to client: %v", torrentFile, client.Name)
|
log.Error().Stack().Err(err).Msgf("could not add torrent %v to client: %v", release.TorrentTmpFile, client.Name)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,9 +295,16 @@ func delugeV2(client *domain.DownloadClient, settings delugeClient.Settings, act
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parse and replace values in argument string before continuing
|
||||||
|
labelArgs, err := m.Parse(action.Label)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err).Msgf("could not parse macro: %v", action.Label)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if p != nil {
|
if p != nil {
|
||||||
// TODO first check if label exists, if not, add it, otherwise set
|
// TODO first check if label exists, if not, add it, otherwise set
|
||||||
err = p.SetTorrentLabel(torrentHash, action.Label)
|
err = p.SetTorrentLabel(torrentHash, labelArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msgf("could not set label: %v on client: %v", action.Label, client.Name)
|
log.Error().Stack().Err(err).Msgf("could not set label: %v on client: %v", action.Label, client.Name)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *service) execCmd(release domain.Release, action domain.Action, torrentFile string) {
|
func (s *service) execCmd(release domain.Release, action domain.Action) {
|
||||||
log.Debug().Msgf("action exec: %v release: %v", action.Name, release.TorrentName)
|
log.Debug().Msgf("action exec: %v release: %v", action.Name, release.TorrentName)
|
||||||
|
|
||||||
// check if program exists
|
// check if program exists
|
||||||
|
@ -21,11 +21,7 @@ func (s *service) execCmd(release domain.Release, action domain.Action, torrentF
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle args and replace vars
|
// handle args and replace vars
|
||||||
m := Macro{
|
m := NewMacro(release)
|
||||||
TorrentName: release.TorrentName,
|
|
||||||
TorrentPathName: torrentFile,
|
|
||||||
TorrentUrl: release.TorrentURL,
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse and replace values in argument string before continuing
|
// parse and replace values in argument string before continuing
|
||||||
parsedArgs, err := m.Parse(action.ExecArgs)
|
parsedArgs, err := m.Parse(action.ExecArgs)
|
||||||
|
@ -46,7 +42,7 @@ func (s *service) execCmd(release domain.Release, action domain.Action, torrentF
|
||||||
output, err := command.CombinedOutput()
|
output, err := command.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// everything other than exit 0 is considered an error
|
// everything other than exit 0 is considered an error
|
||||||
log.Error().Stack().Err(err).Msgf("command: %v args: %v failed, torrent: %v", cmd, parsedArgs, torrentFile)
|
log.Error().Stack().Err(err).Msgf("command: %v args: %v failed, torrent: %v", cmd, parsedArgs, release.TorrentTmpFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Trace().Msgf("executed command: '%v'", string(output))
|
log.Trace().Msgf("executed command: '%v'", string(output))
|
||||||
|
|
|
@ -3,12 +3,53 @@ package action
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/autobrr/autobrr/internal/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Macro struct {
|
type Macro struct {
|
||||||
TorrentName string
|
TorrentName string
|
||||||
TorrentPathName string
|
TorrentPathName string
|
||||||
|
TorrentHash string
|
||||||
TorrentUrl string
|
TorrentUrl string
|
||||||
|
Indexer string
|
||||||
|
Resolution string
|
||||||
|
Source string
|
||||||
|
HDR string
|
||||||
|
Season int
|
||||||
|
Episode int
|
||||||
|
Year int
|
||||||
|
Month int
|
||||||
|
Day int
|
||||||
|
Hour int
|
||||||
|
Minute int
|
||||||
|
Second int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMacro(release domain.Release) Macro {
|
||||||
|
currentTime := time.Now()
|
||||||
|
|
||||||
|
ma := Macro{
|
||||||
|
TorrentName: release.TorrentName,
|
||||||
|
TorrentUrl: release.TorrentURL,
|
||||||
|
TorrentPathName: release.TorrentTmpFile,
|
||||||
|
TorrentHash: release.TorrentHash,
|
||||||
|
Indexer: release.Indexer,
|
||||||
|
Resolution: release.Resolution,
|
||||||
|
Source: release.Source,
|
||||||
|
HDR: release.HDR,
|
||||||
|
Season: release.Season,
|
||||||
|
Episode: release.Episode,
|
||||||
|
Year: currentTime.Year(),
|
||||||
|
Month: int(currentTime.Month()),
|
||||||
|
Day: currentTime.Day(),
|
||||||
|
Hour: currentTime.Hour(),
|
||||||
|
Minute: currentTime.Minute(),
|
||||||
|
Second: currentTime.Second(),
|
||||||
|
}
|
||||||
|
|
||||||
|
return ma
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse takes a string and replaces valid vars
|
// Parse takes a string and replaces valid vars
|
||||||
|
|
|
@ -1,14 +1,21 @@
|
||||||
package action
|
package action
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/autobrr/autobrr/internal/domain"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMacros_Parse(t *testing.T) {
|
func TestMacros_Parse(t *testing.T) {
|
||||||
|
currentTime := time.Now()
|
||||||
|
|
||||||
type fields struct {
|
type fields struct {
|
||||||
TorrentName string
|
TorrentName string
|
||||||
TorrentPathName string
|
TorrentPathName string
|
||||||
TorrentUrl string
|
TorrentUrl string
|
||||||
|
Indexer string
|
||||||
}
|
}
|
||||||
type args struct {
|
type args struct {
|
||||||
text string
|
text string
|
||||||
|
@ -16,43 +23,60 @@ func TestMacros_Parse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
fields fields
|
fields fields
|
||||||
|
release domain.Release
|
||||||
args args
|
args args
|
||||||
want string
|
want string
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "test_ok",
|
name: "test_ok",
|
||||||
fields: fields{TorrentPathName: "/tmp/a-temporary-file.torrent"},
|
release: domain.Release{
|
||||||
|
TorrentName: "This movie 2021",
|
||||||
|
TorrentTmpFile: "/tmp/a-temporary-file.torrent",
|
||||||
|
Indexer: "mock1",
|
||||||
|
},
|
||||||
args: args{text: "Print mee {{.TorrentPathName}}"},
|
args: args{text: "Print mee {{.TorrentPathName}}"},
|
||||||
want: "Print mee /tmp/a-temporary-file.torrent",
|
want: "Print mee /tmp/a-temporary-file.torrent",
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "test_bad",
|
name: "test_bad",
|
||||||
fields: fields{TorrentPathName: "/tmp/a-temporary-file.torrent"},
|
release: domain.Release{
|
||||||
|
TorrentName: "This movie 2021",
|
||||||
|
TorrentTmpFile: "/tmp/a-temporary-file.torrent",
|
||||||
|
Indexer: "mock1",
|
||||||
|
},
|
||||||
args: args{text: "Print mee {{TorrentPathName}}"},
|
args: args{text: "Print mee {{TorrentPathName}}"},
|
||||||
want: "",
|
want: "",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "test_program_arg",
|
name: "test_program_arg",
|
||||||
fields: fields{TorrentPathName: "/tmp/a-temporary-file.torrent"},
|
release: domain.Release{
|
||||||
|
TorrentName: "This movie 2021",
|
||||||
|
TorrentTmpFile: "/tmp/a-temporary-file.torrent",
|
||||||
|
Indexer: "mock1",
|
||||||
|
},
|
||||||
args: args{text: "add {{.TorrentPathName}} --category test"},
|
args: args{text: "add {{.TorrentPathName}} --category test"},
|
||||||
want: "add /tmp/a-temporary-file.torrent --category test",
|
want: "add /tmp/a-temporary-file.torrent --category test",
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "test_program_arg_bad",
|
name: "test_program_arg_bad",
|
||||||
fields: fields{TorrentPathName: "/tmp/a-temporary-file.torrent"},
|
release: domain.Release{
|
||||||
|
TorrentTmpFile: "/tmp/a-temporary-file.torrent",
|
||||||
|
Indexer: "mock1",
|
||||||
|
},
|
||||||
args: args{text: "add {{.TorrenttPathName}} --category test"},
|
args: args{text: "add {{.TorrenttPathName}} --category test"},
|
||||||
want: "",
|
want: "",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "test_program_arg",
|
name: "test_program_arg",
|
||||||
fields: fields{
|
release: domain.Release{
|
||||||
TorrentName: "This movie 2021",
|
TorrentName: "This movie 2021",
|
||||||
TorrentPathName: "/tmp/a-temporary-file.torrent",
|
TorrentTmpFile: "/tmp/a-temporary-file.torrent",
|
||||||
|
Indexer: "mock1",
|
||||||
},
|
},
|
||||||
args: args{text: "add {{.TorrentPathName}} --category test --other {{.TorrentName}}"},
|
args: args{text: "add {{.TorrentPathName}} --category test --other {{.TorrentName}}"},
|
||||||
want: "add /tmp/a-temporary-file.torrent --category test --other This movie 2021",
|
want: "add /tmp/a-temporary-file.torrent --category test --other This movie 2021",
|
||||||
|
@ -60,31 +84,87 @@ func TestMacros_Parse(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "test_args_long",
|
name: "test_args_long",
|
||||||
fields: fields{
|
release: domain.Release{
|
||||||
TorrentName: "This movie 2021",
|
TorrentName: "This movie 2021",
|
||||||
TorrentUrl: "https://some.site/download/fakeid",
|
TorrentURL: "https://some.site/download/fakeid",
|
||||||
|
Indexer: "mock1",
|
||||||
},
|
},
|
||||||
args: args{text: "{{.TorrentName}} {{.TorrentUrl}} SOME_LONG_TOKEN"},
|
args: args{text: "{{.TorrentName}} {{.TorrentUrl}} SOME_LONG_TOKEN"},
|
||||||
want: "This movie 2021 https://some.site/download/fakeid SOME_LONG_TOKEN",
|
want: "This movie 2021 https://some.site/download/fakeid SOME_LONG_TOKEN",
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "test_args_long_1",
|
||||||
|
release: domain.Release{
|
||||||
|
TorrentName: "This movie 2021",
|
||||||
|
TorrentURL: "https://some.site/download/fakeid",
|
||||||
|
Indexer: "mock1",
|
||||||
|
},
|
||||||
|
args: args{text: "{{.Indexer}} {{.TorrentName}} {{.TorrentUrl}} SOME_LONG_TOKEN"},
|
||||||
|
want: "mock1 This movie 2021 https://some.site/download/fakeid SOME_LONG_TOKEN",
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test_args_category",
|
||||||
|
release: domain.Release{
|
||||||
|
TorrentName: "This movie 2021",
|
||||||
|
TorrentURL: "https://some.site/download/fakeid",
|
||||||
|
Indexer: "mock1",
|
||||||
|
},
|
||||||
|
args: args{text: "{{.Indexer}}-race"},
|
||||||
|
want: "mock1-race",
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test_args_category_year",
|
||||||
|
release: domain.Release{
|
||||||
|
TorrentName: "This movie 2021",
|
||||||
|
TorrentURL: "https://some.site/download/fakeid",
|
||||||
|
Indexer: "mock1",
|
||||||
|
},
|
||||||
|
args: args{text: "{{.Indexer}}-{{.Year}}-race"},
|
||||||
|
want: fmt.Sprintf("mock1-%v-race", currentTime.Year()),
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test_args_category_year",
|
||||||
|
release: domain.Release{
|
||||||
|
TorrentName: "This movie 2021",
|
||||||
|
TorrentURL: "https://some.site/download/fakeid",
|
||||||
|
Indexer: "mock1",
|
||||||
|
Resolution: "2160p",
|
||||||
|
HDR: "DV",
|
||||||
|
},
|
||||||
|
args: args{text: "movies-{{.Resolution}}{{ if .HDR }}-{{.HDR}}{{ end }}"},
|
||||||
|
want: "movies-2160p-DV",
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test_args_category_and_if",
|
||||||
|
release: domain.Release{
|
||||||
|
TorrentName: "This movie 2021",
|
||||||
|
TorrentURL: "https://some.site/download/fakeid",
|
||||||
|
Indexer: "mock1",
|
||||||
|
Resolution: "2160p",
|
||||||
|
HDR: "HDR",
|
||||||
|
},
|
||||||
|
args: args{text: "movies-{{.Resolution}}{{ if .HDR }}-{{.HDR}}{{ end }}"},
|
||||||
|
want: "movies-2160p-HDR",
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
m := Macro{
|
m := NewMacro(tt.release)
|
||||||
TorrentPathName: tt.fields.TorrentPathName,
|
|
||||||
TorrentUrl: tt.fields.TorrentUrl,
|
|
||||||
TorrentName: tt.fields.TorrentName,
|
|
||||||
}
|
|
||||||
got, err := m.Parse(tt.args.text)
|
got, err := m.Parse(tt.args.text)
|
||||||
|
|
||||||
|
assert.Equal(t, currentTime.Year(), m.Year)
|
||||||
|
|
||||||
if (err != nil) != tt.wantErr {
|
if (err != nil) != tt.wantErr {
|
||||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if got != tt.want {
|
assert.Equal(t, tt.want, got)
|
||||||
t.Errorf("Parse() got = %v, want %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,31 +5,56 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"github.com/autobrr/autobrr/internal/domain"
|
"github.com/autobrr/autobrr/internal/domain"
|
||||||
"github.com/autobrr/autobrr/pkg/qbittorrent"
|
"github.com/autobrr/autobrr/pkg/qbittorrent"
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const ReannounceMaxAttempts = 50
|
const ReannounceMaxAttempts = 50
|
||||||
const ReannounceInterval = 7000
|
const ReannounceInterval = 7000
|
||||||
|
|
||||||
func (s *service) qbittorrent(qbt *qbittorrent.Client, action domain.Action, torrentFile string, hash string) error {
|
func (s *service) qbittorrent(qbt *qbittorrent.Client, action domain.Action, release domain.Release) error {
|
||||||
log.Debug().Msgf("action qBittorrent: %v", action.Name)
|
log.Debug().Msgf("action qBittorrent: %v", action.Name)
|
||||||
|
|
||||||
|
// macros handle args and replace vars
|
||||||
|
m := NewMacro(release)
|
||||||
|
|
||||||
options := map[string]string{}
|
options := map[string]string{}
|
||||||
|
|
||||||
if action.Paused {
|
if action.Paused {
|
||||||
options["paused"] = "true"
|
options["paused"] = "true"
|
||||||
}
|
}
|
||||||
if action.SavePath != "" {
|
if action.SavePath != "" {
|
||||||
options["savepath"] = action.SavePath
|
// parse and replace values in argument string before continuing
|
||||||
|
actionArgs, err := m.Parse(action.SavePath)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err).Msgf("could not parse macro: %v", action.SavePath)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
options["savepath"] = actionArgs
|
||||||
options["autoTMM"] = "false"
|
options["autoTMM"] = "false"
|
||||||
}
|
}
|
||||||
if action.Category != "" {
|
if action.Category != "" {
|
||||||
options["category"] = action.Category
|
// parse and replace values in argument string before continuing
|
||||||
|
categoryArgs, err := m.Parse(action.Category)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err).Msgf("could not parse macro: %v", action.Category)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
options["category"] = categoryArgs
|
||||||
}
|
}
|
||||||
if action.Tags != "" {
|
if action.Tags != "" {
|
||||||
options["tags"] = action.Tags
|
// parse and replace values in argument string before continuing
|
||||||
|
tagsArgs, err := m.Parse(action.Tags)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err).Msgf("could not parse macro: %v", action.Tags)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
options["tags"] = tagsArgs
|
||||||
}
|
}
|
||||||
if action.LimitUploadSpeed > 0 {
|
if action.LimitUploadSpeed > 0 {
|
||||||
options["upLimit"] = strconv.FormatInt(action.LimitUploadSpeed, 10)
|
options["upLimit"] = strconv.FormatInt(action.LimitUploadSpeed, 10)
|
||||||
|
@ -40,21 +65,21 @@ func (s *service) qbittorrent(qbt *qbittorrent.Client, action domain.Action, tor
|
||||||
|
|
||||||
log.Trace().Msgf("action qBittorrent options: %+v", options)
|
log.Trace().Msgf("action qBittorrent options: %+v", options)
|
||||||
|
|
||||||
err := qbt.AddTorrentFromFile(torrentFile, options)
|
err := qbt.AddTorrentFromFile(release.TorrentTmpFile, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msgf("could not add torrent %v to client: %v", torrentFile, qbt.Name)
|
log.Error().Stack().Err(err).Msgf("could not add torrent %v to client: %v", release.TorrentTmpFile, qbt.Name)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !action.Paused && hash != "" {
|
if !action.Paused && release.TorrentHash != "" {
|
||||||
err = checkTrackerStatus(qbt, hash)
|
err = checkTrackerStatus(qbt, release.TorrentHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msgf("could not reannounce torrent: %v", hash)
|
log.Error().Stack().Err(err).Msgf("could not reannounce torrent: %v", release.TorrentHash)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info().Msgf("torrent with hash %v successfully added to client: '%v'", hash, qbt.Name)
|
log.Info().Msgf("torrent with hash %v successfully added to client: '%v'", release.TorrentHash, qbt.Name)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ func (s *service) runAction(action domain.Action, release domain.Release) error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.execCmd(release, action, release.TorrentTmpFile)
|
s.execCmd(release, action)
|
||||||
|
|
||||||
case domain.ActionTypeWatchFolder:
|
case domain.ActionTypeWatchFolder:
|
||||||
if release.TorrentTmpFile == "" {
|
if release.TorrentTmpFile == "" {
|
||||||
|
@ -71,7 +71,7 @@ func (s *service) runAction(action domain.Action, release domain.Release) error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.watchFolder(action.WatchFolder, release.TorrentTmpFile)
|
s.watchFolder(action, release)
|
||||||
|
|
||||||
case domain.ActionTypeDelugeV1, domain.ActionTypeDelugeV2:
|
case domain.ActionTypeDelugeV1, domain.ActionTypeDelugeV2:
|
||||||
canDownload, err := s.delugeCheckRulesCanDownload(action)
|
canDownload, err := s.delugeCheckRulesCanDownload(action)
|
||||||
|
@ -91,7 +91,7 @@ func (s *service) runAction(action domain.Action, release domain.Release) error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.deluge(action, release.TorrentTmpFile)
|
err = s.deluge(action, release)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msg("error sending torrent to Deluge")
|
log.Error().Stack().Err(err).Msg("error sending torrent to Deluge")
|
||||||
return err
|
return err
|
||||||
|
@ -115,7 +115,7 @@ func (s *service) runAction(action domain.Action, release domain.Release) error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.qbittorrent(client, action, release.TorrentTmpFile, release.TorrentHash)
|
err = s.qbittorrent(client, action, release)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msg("error sending torrent to qBittorrent")
|
log.Error().Stack().Err(err).Msg("error sending torrent to qBittorrent")
|
||||||
return err
|
return err
|
||||||
|
@ -215,19 +215,27 @@ func (s *service) test(name string) {
|
||||||
log.Info().Msgf("action TEST: %v", name)
|
log.Info().Msgf("action TEST: %v", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) watchFolder(dir string, torrentFile string) {
|
func (s *service) watchFolder(action domain.Action, release domain.Release) {
|
||||||
log.Trace().Msgf("action WATCH_FOLDER: %v file: %v", dir, torrentFile)
|
m := NewMacro(release)
|
||||||
|
|
||||||
|
// parse and replace values in argument string before continuing
|
||||||
|
watchFolderArgs, err := m.Parse(action.WatchFolder)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Stack().Err(err).Msgf("could not parse macro: %v", action.WatchFolder)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Trace().Msgf("action WATCH_FOLDER: %v file: %v", watchFolderArgs, release.TorrentTmpFile)
|
||||||
|
|
||||||
// Open original file
|
// Open original file
|
||||||
original, err := os.Open(torrentFile)
|
original, err := os.Open(release.TorrentTmpFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Stack().Err(err).Msgf("could not open temp file '%v'", torrentFile)
|
log.Error().Stack().Err(err).Msgf("could not open temp file '%v'", release.TorrentTmpFile)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer original.Close()
|
defer original.Close()
|
||||||
|
|
||||||
_, tmpFileName := path.Split(torrentFile)
|
_, tmpFileName := path.Split(release.TorrentTmpFile)
|
||||||
fullFileName := path.Join(dir, tmpFileName+".torrent")
|
fullFileName := path.Join(watchFolderArgs, tmpFileName+".torrent")
|
||||||
|
|
||||||
// Create new file
|
// Create new file
|
||||||
newFile, err := os.Create(fullFileName)
|
newFile, err := os.Create(fullFileName)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue