feat(actions): qBittorrent add priority handling (#1315)

* feat(qbittorrent): add priority handling

* fix: check if torrent queueing is enabled

* fix: only check for torrent queueing if priority is set

* fix: improve tooltip message

* feat: enable torrent queueing if disabled

* change to SetPreferencesQueueingEnabled

* feat(actions): rename field

* chore: bump pkg go-qbittorrent to v1.8.0

* chore(deps): update go-qbittorrent to v1.8.1

* chore(deps): go mod tidy

---------

Co-authored-by: ze0s <ze0s@riseup.net>
This commit is contained in:
soup 2023-12-25 22:39:31 +01:00 committed by GitHub
parent 0ab404f81a
commit c6122dbc41
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 115 additions and 30 deletions

4
go.mod
View file

@ -10,7 +10,7 @@ require (
github.com/anacrolix/torrent v1.53.1
github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef
github.com/autobrr/go-deluge v1.1.0
github.com/autobrr/go-qbittorrent v1.7.2-0.20231029234932-67580aa0e42a
github.com/autobrr/go-qbittorrent v1.8.1
github.com/autobrr/go-rtorrent v1.10.0
github.com/avast/retry-go v3.0.0+incompatible
github.com/avast/retry-go/v4 v4.5.1
@ -18,6 +18,7 @@ require (
github.com/dustin/go-humanize v1.0.1
github.com/ergochat/irc-go v0.4.0
github.com/fsnotify/fsnotify v1.7.0
github.com/go-andiamo/splitter v1.2.5
github.com/go-chi/chi/v5 v5.0.10
github.com/go-chi/render v1.0.3
github.com/gorilla/sessions v1.2.2
@ -61,7 +62,6 @@ require (
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/gdm85/go-rencode v0.1.8 // indirect
github.com/go-andiamo/splitter v1.2.5 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
github.com/gosimple/unidecode v1.0.1 // indirect

10
go.sum
View file

@ -94,8 +94,8 @@ github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef h1:2JGTg6JapxP
github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef/go.mod h1:JS7hed4L1fj0hXcyEejnW57/7LCetXggd+vwrRnYeII=
github.com/autobrr/go-deluge v1.1.0 h1:wT+FUxjNrYnUhOcZmZSIApCz4tT2n0FzXVfuvOBtcIM=
github.com/autobrr/go-deluge v1.1.0/go.mod h1:ndiXT1eHWv/ATNk9TpE8GHIs8OSSUnsImt4Syk+y5LM=
github.com/autobrr/go-qbittorrent v1.7.2-0.20231029234932-67580aa0e42a h1:oMPFpu0QXbkpeJu1LhcO2+pu5pff2cQLWQx/Fv5z8AM=
github.com/autobrr/go-qbittorrent v1.7.2-0.20231029234932-67580aa0e42a/go.mod h1:z88B3+O/1/3doQABErvIOOxE4hjpmIpulu6XzDG/q78=
github.com/autobrr/go-qbittorrent v1.8.1 h1:QQxuEaCKThTmV0LhU6tHZQvYv+eCrKmiCRY0G1RiJG4=
github.com/autobrr/go-qbittorrent v1.8.1/go.mod h1:z88B3+O/1/3doQABErvIOOxE4hjpmIpulu6XzDG/q78=
github.com/autobrr/go-rtorrent v1.10.0 h1:SCs7Rdi1BZ3MxNoVIdWK0qTUHQyhSj9rEU8KUTRi4Ug=
github.com/autobrr/go-rtorrent v1.10.0/go.mod h1:1CyQ2tcLOGP+p9drOqFiVPb/+QvfExMPCHnEGQd0BmM=
github.com/autobrr/sse/v2 v2.0.0-20230520125637-530e06346d7d h1:9EGCYgeugAVWLBAtjHC7AFnXSwUdYfCB98WaOgdDREE=
@ -475,8 +475,6 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/exp v0.0.0-20231127185646-65229373498e h1:Gvh4YaCaXNs6dKTlfgismwWZKyjVZXwOPfIyUaqU3No=
golang.org/x/exp v0.0.0-20231127185646-65229373498e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
@ -504,8 +502,6 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -702,8 +698,6 @@ golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM=
golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View file

@ -65,6 +65,45 @@ func (s *service) qbittorrent(ctx context.Context, action *domain.Action, releas
return nil, errors.Wrap(err, "could not add torrent %s to client: %s", release.TorrentTmpFile, c.Dc.Name)
}
if release.TorrentHash != "" {
// check if torrent queueing is enabled if priority is set
switch action.PriorityLayout {
case domain.PriorityLayoutMax, domain.PriorityLayoutMin:
prefs, err := c.Qbt.GetAppPreferencesCtx(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not get application preferences from client: '%s'", c.Dc.Name)
}
// enable queueing if it's disabled
if !prefs.QueueingEnabled {
if err := c.Qbt.SetPreferencesQueueingEnabled(true); err != nil {
return nil, errors.Wrap(err, "could not enable torrent queueing")
}
s.log.Trace().Msgf("torrent queueing was disabled, now enabled in client: '%s'", c.Dc.Name)
}
// set priority if queueing is enabled
if action.PriorityLayout == domain.PriorityLayoutMax {
if err := c.Qbt.SetMaxPriorityCtx(ctx, []string{release.TorrentHash}); err != nil {
return nil, errors.Wrap(err, "could not set torrent %s to max priority", release.TorrentHash)
}
s.log.Debug().Msgf("torrent with hash %s set to max priority in client: '%s'", release.TorrentHash, c.Dc.Name)
} else { // domain.PriorityLayoutMin
if err := c.Qbt.SetMinPriorityCtx(ctx, []string{release.TorrentHash}); err != nil {
return nil, errors.Wrap(err, "could not set torrent %s to min priority", release.TorrentHash)
}
s.log.Debug().Msgf("torrent with hash %s set to min priority in client: '%s'", release.TorrentHash, c.Dc.Name)
}
case domain.PriorityLayoutDefault:
// do nothing as it's disabled or unset
default:
s.log.Warn().Msgf("unknown priority setting: '%v', no priority changes made", action.PriorityLayout)
}
} else {
// add anyway if no hash
s.log.Trace().Msg("no torrent hash provided, skipping priority setting")
}
if !action.Paused && !action.ReAnnounceSkip && release.TorrentHash != "" {
opts := qbittorrent.ReannounceOptions{
Interval: int(action.ReAnnounceInterval),

View file

@ -77,6 +77,7 @@ func (r *ActionRepo) findByFilterID(ctx context.Context, tx *Tx, filterID int, a
"ignore_rules",
"skip_hash_check",
"content_layout",
"priority",
"limit_download_speed",
"limit_upload_speed",
"limit_ratio",
@ -115,14 +116,14 @@ func (r *ActionRepo) findByFilterID(ctx context.Context, tx *Tx, filterID int, a
for rows.Next() {
var a domain.Action
var execCmd, execArgs, watchFolder, category, tags, label, savePath, contentLayout, webhookHost, webhookType, webhookMethod, webhookData sql.NullString
var execCmd, execArgs, watchFolder, category, tags, label, savePath, contentLayout, priorityLayout, webhookHost, webhookType, webhookMethod, webhookData sql.NullString
var limitUl, limitDl, limitSeedTime sql.NullInt64
var limitRatio sql.NullFloat64
var externalClientID, clientID sql.NullInt32
var paused, ignoreRules sql.NullBool
if err := rows.Scan(&a.ID, &a.Name, &a.Type, &a.Enabled, &execCmd, &execArgs, &watchFolder, &category, &tags, &label, &savePath, &paused, &ignoreRules, &a.SkipHashCheck, &contentLayout, &limitDl, &limitUl, &limitRatio, &limitSeedTime, &a.ReAnnounceSkip, &a.ReAnnounceDelete, &a.ReAnnounceInterval, &a.ReAnnounceMaxAttempts, &webhookHost, &webhookType, &webhookMethod, &webhookData, &externalClientID, &clientID); err != nil {
if err := rows.Scan(&a.ID, &a.Name, &a.Type, &a.Enabled, &execCmd, &execArgs, &watchFolder, &category, &tags, &label, &savePath, &paused, &ignoreRules, &a.SkipHashCheck, &contentLayout, &priorityLayout, &limitDl, &limitUl, &limitRatio, &limitSeedTime, &a.ReAnnounceSkip, &a.ReAnnounceDelete, &a.ReAnnounceInterval, &a.ReAnnounceMaxAttempts, &webhookHost, &webhookType, &webhookMethod, &webhookData, &externalClientID, &clientID); err != nil {
return nil, errors.Wrap(err, "error scanning row")
}
@ -136,6 +137,7 @@ func (r *ActionRepo) findByFilterID(ctx context.Context, tx *Tx, filterID int, a
a.Paused = paused.Bool
a.IgnoreRules = ignoreRules.Bool
a.ContentLayout = domain.ActionContentLayout(contentLayout.String)
a.PriorityLayout = domain.PriorityLayout(priorityLayout.String)
a.LimitDownloadSpeed = limitDl.Int64
a.LimitUploadSpeed = limitUl.Int64
@ -227,6 +229,7 @@ func (r *ActionRepo) List(ctx context.Context) ([]domain.Action, error) {
"ignore_rules",
"skip_hash_check",
"content_layout",
"priority",
"limit_download_speed",
"limit_upload_speed",
"limit_ratio",
@ -260,13 +263,13 @@ func (r *ActionRepo) List(ctx context.Context) ([]domain.Action, error) {
for rows.Next() {
var a domain.Action
var execCmd, execArgs, watchFolder, category, tags, label, savePath, contentLayout, webhookHost, webhookType, webhookMethod, webhookData sql.NullString
var execCmd, execArgs, watchFolder, category, tags, label, savePath, contentLayout, priorityLayout, webhookHost, webhookType, webhookMethod, webhookData sql.NullString
var limitUl, limitDl, limitSeedTime sql.NullInt64
var limitRatio sql.NullFloat64
var externalClientID, clientID sql.NullInt32
var paused, ignoreRules sql.NullBool
if err := rows.Scan(&a.ID, &a.Name, &a.Type, &a.Enabled, &execCmd, &execArgs, &watchFolder, &category, &tags, &label, &savePath, &paused, &ignoreRules, &a.SkipHashCheck, &contentLayout, &limitDl, &limitUl, &limitRatio, &limitSeedTime, &a.ReAnnounceSkip, &a.ReAnnounceDelete, &a.ReAnnounceInterval, &a.ReAnnounceMaxAttempts, &webhookHost, &webhookType, &webhookMethod, &webhookData, &externalClientID, &clientID); err != nil {
if err := rows.Scan(&a.ID, &a.Name, &a.Type, &a.Enabled, &execCmd, &execArgs, &watchFolder, &category, &tags, &label, &savePath, &paused, &ignoreRules, &a.SkipHashCheck, &contentLayout, &priorityLayout, &limitDl, &limitUl, &limitRatio, &limitSeedTime, &a.ReAnnounceSkip, &a.ReAnnounceDelete, &a.ReAnnounceInterval, &a.ReAnnounceMaxAttempts, &webhookHost, &webhookType, &webhookMethod, &webhookData, &externalClientID, &clientID); err != nil {
return nil, errors.Wrap(err, "error scanning row")
}
@ -277,6 +280,7 @@ func (r *ActionRepo) List(ctx context.Context) ([]domain.Action, error) {
a.Paused = paused.Bool
a.IgnoreRules = ignoreRules.Bool
a.ContentLayout = domain.ActionContentLayout(contentLayout.String)
a.PriorityLayout = domain.PriorityLayout(priorityLayout.String)
a.LimitDownloadSpeed = limitDl.Int64
a.LimitUploadSpeed = limitUl.Int64
@ -319,6 +323,7 @@ func (r *ActionRepo) Get(ctx context.Context, req *domain.GetActionRequest) (*do
"ignore_rules",
"skip_hash_check",
"content_layout",
"priority",
"limit_download_speed",
"limit_upload_speed",
"limit_ratio",
@ -354,13 +359,13 @@ func (r *ActionRepo) Get(ctx context.Context, req *domain.GetActionRequest) (*do
var a domain.Action
var execCmd, execArgs, watchFolder, category, tags, label, savePath, contentLayout, webhookHost, webhookType, webhookMethod, webhookData sql.NullString
var execCmd, execArgs, watchFolder, category, tags, label, savePath, contentLayout, priorityLayout, webhookHost, webhookType, webhookMethod, webhookData sql.NullString
var limitUl, limitDl, limitSeedTime sql.NullInt64
var limitRatio sql.NullFloat64
var externalClientID, clientID, filterID sql.NullInt32
var paused, ignoreRules sql.NullBool
if err := row.Scan(&a.ID, &a.Name, &a.Type, &a.Enabled, &execCmd, &execArgs, &watchFolder, &category, &tags, &label, &savePath, &paused, &ignoreRules, &a.SkipHashCheck, &contentLayout, &limitDl, &limitUl, &limitRatio, &limitSeedTime, &a.ReAnnounceSkip, &a.ReAnnounceDelete, &a.ReAnnounceInterval, &a.ReAnnounceMaxAttempts, &webhookHost, &webhookType, &webhookMethod, &webhookData, &externalClientID, &clientID, &filterID); err != nil {
if err := row.Scan(&a.ID, &a.Name, &a.Type, &a.Enabled, &execCmd, &execArgs, &watchFolder, &category, &tags, &label, &savePath, &paused, &ignoreRules, &a.SkipHashCheck, &contentLayout, &priorityLayout, &limitDl, &limitUl, &limitRatio, &limitSeedTime, &a.ReAnnounceSkip, &a.ReAnnounceDelete, &a.ReAnnounceInterval, &a.ReAnnounceMaxAttempts, &webhookHost, &webhookType, &webhookMethod, &webhookData, &externalClientID, &clientID, &filterID); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, domain.ErrRecordNotFound
}
@ -378,6 +383,7 @@ func (r *ActionRepo) Get(ctx context.Context, req *domain.GetActionRequest) (*do
a.Paused = paused.Bool
a.IgnoreRules = ignoreRules.Bool
a.ContentLayout = domain.ActionContentLayout(contentLayout.String)
a.PriorityLayout = domain.PriorityLayout(priorityLayout.String)
a.LimitDownloadSpeed = limitDl.Int64
a.LimitUploadSpeed = limitUl.Int64
@ -454,6 +460,7 @@ func (r *ActionRepo) Store(ctx context.Context, action domain.Action) (*domain.A
"ignore_rules",
"skip_hash_check",
"content_layout",
"priority",
"limit_upload_speed",
"limit_download_speed",
"limit_ratio",
@ -485,6 +492,7 @@ func (r *ActionRepo) Store(ctx context.Context, action domain.Action) (*domain.A
action.IgnoreRules,
action.SkipHashCheck,
toNullString(string(action.ContentLayout)),
toNullString(string(action.PriorityLayout)),
toNullInt64(action.LimitUploadSpeed),
toNullInt64(action.LimitDownloadSpeed),
toNullFloat64(action.LimitRatio),
@ -534,6 +542,7 @@ func (r *ActionRepo) Update(ctx context.Context, action domain.Action) (*domain.
Set("ignore_rules", action.IgnoreRules).
Set("skip_hash_check", action.SkipHashCheck).
Set("content_layout", toNullString(string(action.ContentLayout))).
Set("priority", toNullString(string(action.PriorityLayout))).
Set("limit_upload_speed", toNullInt64(action.LimitUploadSpeed)).
Set("limit_download_speed", toNullInt64(action.LimitDownloadSpeed)).
Set("limit_ratio", toNullFloat64(action.LimitRatio)).
@ -593,6 +602,7 @@ func (r *ActionRepo) StoreFilterActions(ctx context.Context, filterID int64, act
Set("ignore_rules", action.IgnoreRules).
Set("skip_hash_check", action.SkipHashCheck).
Set("content_layout", toNullString(string(action.ContentLayout))).
Set("priority", toNullString(string(action.PriorityLayout))).
Set("limit_upload_speed", toNullInt64(action.LimitUploadSpeed)).
Set("limit_download_speed", toNullInt64(action.LimitDownloadSpeed)).
Set("limit_ratio", toNullFloat64(action.LimitRatio)).
@ -639,6 +649,7 @@ func (r *ActionRepo) StoreFilterActions(ctx context.Context, filterID int64, act
"ignore_rules",
"skip_hash_check",
"content_layout",
"priority",
"limit_upload_speed",
"limit_download_speed",
"limit_ratio",
@ -670,6 +681,7 @@ func (r *ActionRepo) StoreFilterActions(ctx context.Context, filterID int64, act
action.IgnoreRules,
action.SkipHashCheck,
toNullString(string(action.ContentLayout)),
toNullString(string(action.PriorityLayout)),
toNullInt64(action.LimitUploadSpeed),
toNullInt64(action.LimitDownloadSpeed),
toNullFloat64(action.LimitRatio),

View file

@ -199,6 +199,7 @@ CREATE TABLE action
limit_download_speed INT,
limit_ratio REAL,
limit_seed_time INT,
priority TEXT,
reannounce_skip BOOLEAN DEFAULT false,
reannounce_delete BOOLEAN DEFAULT false,
reannounce_interval INTEGER DEFAULT 7,
@ -507,20 +508,20 @@ var postgresMigrations = []string{
`
ALTER TABLE "action"
ADD COLUMN reannounce_skip BOOLEAN DEFAULT false;
ALTER TABLE "action"
ADD COLUMN reannounce_delete BOOLEAN DEFAULT false;
ALTER TABLE "action"
ADD COLUMN reannounce_interval INTEGER DEFAULT 7;
ALTER TABLE "action"
ADD COLUMN reannounce_max_attempts INTEGER DEFAULT 50;
`,
`
ALTER TABLE "action"
ADD COLUMN limit_ratio REAL DEFAULT 0;
ALTER TABLE "action"
ADD COLUMN limit_seed_time INTEGER DEFAULT 0;
`,
@ -685,7 +686,7 @@ FROM filter f WHERE f.name = release_action_status.filter);
`,
`ALTER TABLE "release"
ADD COLUMN info_url TEXT;
ALTER TABLE "release"
ADD COLUMN download_url TEXT;
`,
@ -728,7 +729,7 @@ ALTER TABLE irc_network
ADD COLUMN bouncer_addr TEXT;`,
`ALTER TABLE release_action_status
DROP CONSTRAINT IF EXISTS release_action_status_action_id_fkey;
ALTER TABLE release_action_status
DROP CONSTRAINT IF EXISTS release_action_status_action_id_fk;
@ -834,5 +835,8 @@ ALTER TABLE filter_external
`,
`ALTER TABLE feed
ALTER COLUMN max_age SET DEFAULT 0;
`,
`ALTER TABLE action
ADD COLUMN priority TEXT;
`,
}

View file

@ -199,6 +199,7 @@ CREATE TABLE action
limit_download_speed INT,
limit_ratio REAL,
limit_seed_time INT,
priority TEXT,
reannounce_skip BOOLEAN DEFAULT false,
reannounce_delete BOOLEAN DEFAULT false,
reannounce_interval INTEGER DEFAULT 7,
@ -763,20 +764,20 @@ ALTER TABLE release_action_status_dg_tmp
`
ALTER TABLE "action"
ADD COLUMN reannounce_skip BOOLEAN DEFAULT false;
ALTER TABLE "action"
ADD COLUMN reannounce_delete BOOLEAN DEFAULT false;
ALTER TABLE "action"
ADD COLUMN reannounce_interval INTEGER DEFAULT 7;
ALTER TABLE "action"
ADD COLUMN reannounce_max_attempts INTEGER DEFAULT 50;
`,
`
ALTER TABLE "action"
ADD COLUMN limit_ratio REAL DEFAULT 0;
ALTER TABLE "action"
ADD COLUMN limit_seed_time INTEGER DEFAULT 0;
`,
@ -986,7 +987,7 @@ CREATE TABLE irc_network_dg_tmp
unique (server, port, nick)
);
INSERT INTO irc_network_dg_tmp(id, enabled, name, server, port, tls, pass, nick, auth_mechanism, auth_account, auth_password, invite_command,
INSERT INTO irc_network_dg_tmp(id, enabled, name, server, port, tls, pass, nick, auth_mechanism, auth_account, auth_password, invite_command,
connected, connected_since, created_at, updated_at)
SELECT id,
enabled,
@ -1079,7 +1080,7 @@ FROM filter f WHERE f.name = release_action_status.filter);
`,
`ALTER TABLE "release"
ADD COLUMN info_url TEXT;
ALTER TABLE "release"
ADD COLUMN download_url TEXT;
`,
@ -1088,7 +1089,7 @@ ADD COLUMN download_url TEXT;
ALTER TABLE filter
ADD COLUMN except_tags_match_logic TEXT;
UPDATE filter
SET tags_match_logic = 'ANY'
WHERE tags IS NOT NULL;
@ -1475,5 +1476,8 @@ DROP TABLE feed;
ALTER TABLE feed_dg_tmp
RENAME TO feed;
`,
`ALTER TABLE action
ADD COLUMN priority TEXT;
`,
}

View file

@ -42,6 +42,7 @@ type Action struct {
LimitDownloadSpeed int64 `json:"limit_download_speed,omitempty"`
LimitRatio float64 `json:"limit_ratio,omitempty"`
LimitSeedTime int64 `json:"limit_seed_time,omitempty"`
PriorityLayout PriorityLayout `json:"priority,omitempty"`
ReAnnounceSkip bool `json:"reannounce_skip,omitempty"`
ReAnnounceDelete bool `json:"reannounce_delete,omitempty"`
ReAnnounceInterval int64 `json:"reannounce_interval,omitempty"`
@ -128,6 +129,14 @@ const (
ActionContentLayoutSubfolderCreate ActionContentLayout = "SUBFOLDER_CREATE"
)
type PriorityLayout string
const (
PriorityLayoutMax PriorityLayout = "MAX"
PriorityLayoutMin PriorityLayout = "MIN"
PriorityLayoutDefault PriorityLayout = ""
)
type GetActionRequest struct {
Id int
}

View file

@ -349,6 +349,12 @@ export const ActionContentLayoutOptions: SelectGenericOption<ActionContentLayout
{ label: "Don't create subfolder", description: "Don't create subfolder", value: "SUBFOLDER_NONE" }
];
export const ActionPriorityOptions: SelectGenericOption<ActionPriorityLayout>[] = [
{ label: "Top of queue", description: "Top of queue", value: "MAX" },
{ label: "Bottom of queue", description: "Bottom of queue", value: "MIN" },
{ label: "Disabled", description: "Disabled", value: "" }
];
export const ActionRtorrentRenameOptions: SelectGenericOption<ActionContentLayout>[] = [
{ label: "No", description: "No", value: "ORIGINAL" },
{ label: "Yes", description: "Yes", value: "SUBFOLDER_NONE" }

View file

@ -54,6 +54,7 @@ export function Actions({ filter, values }: FilterActionsProps) {
ignore_rules: false,
skip_hash_check: false,
content_layout: "" || undefined,
priority: "" || undefined,
limit_upload_speed: 0,
limit_download_speed: 0,
limit_ratio: 0,

View file

@ -1,7 +1,7 @@
import { Link } from "react-router-dom";
import { DocsLink } from "@components/ExternalLink";
import { ActionContentLayoutOptions } from "@domain/constants";
import { ActionContentLayoutOptions, ActionPriorityOptions } from "@domain/constants";
import * as Input from "@components/inputs";
import { CollapsibleSection } from "../_components";
@ -105,6 +105,19 @@ export const QBittorrent = ({ idx, action, clients }: ClientActionProps) => (
description="Add torrent and skip hash check"
/>
</FilterSection.HalfRow>
<FilterSection.HalfRow>
<Input.Select
name={`actions.${idx}.priority`}
label="Priority"
optionDefaultText="Disabled"
options={ActionPriorityOptions}
tooltip={
<div>
<p>Torrent Queueing will be enabled for you if it is disabled. Ensure you set your preferred limits for it in your client.</p>
</div>
}
/>
</FilterSection.HalfRow>
</CollapsibleSection>
<CollapsibleSection

View file

@ -90,6 +90,7 @@ interface Action {
ignore_rules?: boolean;
skip_hash_check: boolean;
content_layout?: ActionContentLayout;
priority?: ActionPriorityLayout;
limit_upload_speed?: number;
limit_download_speed?: number;
limit_ratio?: number;
@ -110,6 +111,8 @@ interface Action {
type ActionContentLayout = "ORIGINAL" | "SUBFOLDER_CREATE" | "SUBFOLDER_NONE";
type ActionPriorityLayout = "MAX" | "MIN" | "";
type ActionType = "TEST" | "EXEC" | "WATCH_FOLDER" | "WEBHOOK" | DownloadClientType;
type ExternalType = "EXEC" | "WEBHOOK";