mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 08:49:13 +00:00
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:
parent
0ab404f81a
commit
c6122dbc41
11 changed files with 115 additions and 30 deletions
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
`,
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
`,
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue