feat(actions): qbit rules set ratio and seed time limits (#264)

This commit is contained in:
Ludvig Lundgren 2022-05-03 14:57:47 +02:00 committed by GitHub
parent 43d37fc859
commit 8b1174c65f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 86 additions and 6 deletions

View file

@ -62,6 +62,12 @@ func (s *service) qbittorrent(qbt *qbittorrent.Client, action domain.Action, rel
if action.LimitDownloadSpeed > 0 {
options["dlLimit"] = strconv.FormatInt(action.LimitDownloadSpeed, 10)
}
if action.LimitRatio > 0 {
options["ratioLimit"] = strconv.FormatFloat(action.LimitRatio, 'r', 2, 64)
}
if action.LimitSeedTime > 0 {
options["seedingTimeLimit"] = strconv.FormatInt(action.LimitSeedTime, 10)
}
log.Trace().Msgf("action qBittorrent options: %+v", options)

View file

@ -68,6 +68,8 @@ func (r *ActionRepo) findByFilterID(ctx context.Context, tx *Tx, filterID int) (
"ignore_rules",
"limit_download_speed",
"limit_upload_speed",
"limit_ratio",
"limit_seed_time",
"reannounce_skip",
"reannounce_delete",
"reannounce_interval",
@ -100,12 +102,14 @@ func (r *ActionRepo) findByFilterID(ctx context.Context, tx *Tx, filterID int) (
var a domain.Action
var execCmd, execArgs, watchFolder, category, tags, label, savePath, webhookHost, webhookType, webhookMethod, webhookData sql.NullString
var limitUl, limitDl sql.NullInt64
var limitUl, limitDl, limitSeedTime sql.NullInt64
var limitRatio sql.NullFloat64
var clientID sql.NullInt32
// filterID
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, &limitDl, &limitUl, &a.ReAnnounceSkip, &a.ReAnnounceDelete, &a.ReAnnounceInterval, &a.ReAnnounceMaxAttempts, &webhookHost, &webhookType, &webhookMethod, &webhookData, &clientID); err != nil {
if err := rows.Scan(&a.ID, &a.Name, &a.Type, &a.Enabled, &execCmd, &execArgs, &watchFolder, &category, &tags, &label, &savePath, &paused, &ignoreRules, &limitDl, &limitUl, &limitRatio, &limitSeedTime, &a.ReAnnounceSkip, &a.ReAnnounceDelete, &a.ReAnnounceInterval, &a.ReAnnounceMaxAttempts, &webhookHost, &webhookType, &webhookMethod, &webhookData, &clientID); err != nil {
log.Error().Stack().Err(err).Msg("action.findByFilterID: error scanning row")
return nil, err
}
@ -122,6 +126,8 @@ func (r *ActionRepo) findByFilterID(ctx context.Context, tx *Tx, filterID int) (
a.LimitDownloadSpeed = limitDl.Int64
a.LimitUploadSpeed = limitUl.Int64
a.LimitRatio = limitRatio.Float64
a.LimitSeedTime = limitSeedTime.Int64
a.WebhookHost = webhookHost.String
a.WebhookType = webhookType.String
@ -206,6 +212,8 @@ func (r *ActionRepo) List(ctx context.Context) ([]domain.Action, error) {
"ignore_rules",
"limit_download_speed",
"limit_upload_speed",
"limit_ratio",
"limit_seed_time",
"reannounce_skip",
"reannounce_delete",
"reannounce_interval",
@ -237,11 +245,12 @@ func (r *ActionRepo) List(ctx context.Context) ([]domain.Action, error) {
var a domain.Action
var execCmd, execArgs, watchFolder, category, tags, label, savePath, webhookHost, webhookType, webhookMethod, webhookData sql.NullString
var limitUl, limitDl sql.NullInt64
var limitUl, limitDl, limitSeedTime sql.NullInt64
var limitRatio sql.NullFloat64
var 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, &limitDl, &limitUl, &a.ReAnnounceSkip, &a.ReAnnounceDelete, &a.ReAnnounceInterval, &a.ReAnnounceMaxAttempts, &webhookHost, &webhookType, &webhookMethod, &webhookData, &clientID); err != nil {
if err := rows.Scan(&a.ID, &a.Name, &a.Type, &a.Enabled, &execCmd, &execArgs, &watchFolder, &category, &tags, &label, &savePath, &paused, &ignoreRules, &limitDl, &limitUl, &limitRatio, &limitSeedTime, &a.ReAnnounceSkip, &a.ReAnnounceDelete, &a.ReAnnounceInterval, &a.ReAnnounceMaxAttempts, &webhookHost, &webhookType, &webhookMethod, &webhookData, &clientID); err != nil {
log.Error().Stack().Err(err).Msg("action.list: error scanning row")
return nil, err
}
@ -255,6 +264,8 @@ func (r *ActionRepo) List(ctx context.Context) ([]domain.Action, error) {
a.LimitDownloadSpeed = limitDl.Int64
a.LimitUploadSpeed = limitUl.Int64
a.LimitRatio = limitRatio.Float64
a.LimitSeedTime = limitSeedTime.Int64
a.WebhookHost = webhookHost.String
a.WebhookType = webhookType.String
@ -332,6 +343,8 @@ func (r *ActionRepo) Store(ctx context.Context, action domain.Action) (*domain.A
limitDL := toNullInt64(action.LimitDownloadSpeed)
limitUL := toNullInt64(action.LimitUploadSpeed)
limitRatio := toNullFloat64(action.LimitRatio)
limitSeedTime := toNullInt64(action.LimitSeedTime)
clientID := toNullInt32(action.ClientID)
filterID := toNullInt32(int32(action.FilterID))
@ -352,6 +365,8 @@ func (r *ActionRepo) Store(ctx context.Context, action domain.Action) (*domain.A
"ignore_rules",
"limit_upload_speed",
"limit_download_speed",
"limit_ratio",
"limit_seed_time",
"reannounce_skip",
"reannounce_delete",
"reannounce_interval",
@ -378,6 +393,8 @@ func (r *ActionRepo) Store(ctx context.Context, action domain.Action) (*domain.A
action.IgnoreRules,
limitUL,
limitDL,
limitRatio,
limitSeedTime,
action.ReAnnounceSkip,
action.ReAnnounceDelete,
action.ReAnnounceInterval,
@ -421,6 +438,9 @@ func (r *ActionRepo) Update(ctx context.Context, action domain.Action) (*domain.
limitDL := toNullInt64(action.LimitDownloadSpeed)
limitUL := toNullInt64(action.LimitUploadSpeed)
limitRatio := toNullFloat64(action.LimitRatio)
limitSeedTime := toNullInt64(action.LimitSeedTime)
clientID := toNullInt32(action.ClientID)
filterID := toNullInt32(int32(action.FilterID))
@ -442,6 +462,8 @@ func (r *ActionRepo) Update(ctx context.Context, action domain.Action) (*domain.
Set("ignore_rules", action.IgnoreRules).
Set("limit_upload_speed", limitUL).
Set("limit_download_speed", limitDL).
Set("limit_ratio", limitRatio).
Set("limit_seed_time", limitSeedTime).
Set("reannounce_skip", action.ReAnnounceSkip).
Set("reannounce_delete", action.ReAnnounceDelete).
Set("reannounce_interval", action.ReAnnounceInterval).
@ -509,6 +531,8 @@ func (r *ActionRepo) StoreFilterActions(ctx context.Context, actions []*domain.A
limitDL := toNullInt64(action.LimitDownloadSpeed)
limitUL := toNullInt64(action.LimitUploadSpeed)
limitRatio := toNullFloat64(action.LimitRatio)
limitSeedTime := toNullInt64(action.LimitSeedTime)
clientID := toNullInt32(action.ClientID)
queryBuilder := r.db.squirrel.
@ -528,6 +552,8 @@ func (r *ActionRepo) StoreFilterActions(ctx context.Context, actions []*domain.A
"ignore_rules",
"limit_upload_speed",
"limit_download_speed",
"limit_ratio",
"limit_seed_time",
"reannounce_skip",
"reannounce_delete",
"reannounce_interval",
@ -554,6 +580,8 @@ func (r *ActionRepo) StoreFilterActions(ctx context.Context, actions []*domain.A
action.IgnoreRules,
limitUL,
limitDL,
limitRatio,
limitSeedTime,
action.ReAnnounceSkip,
action.ReAnnounceDelete,
action.ReAnnounceInterval,

View file

@ -147,6 +147,8 @@ CREATE TABLE action
ignore_rules BOOLEAN,
limit_upload_speed INT,
limit_download_speed INT,
limit_ratio REAL,
limit_seed_time INT,
reannounce_skip BOOLEAN DEFAULT false,
reannounce_delete BOOLEAN DEFAULT false,
reannounce_interval INTEGER DEFAULT 7,
@ -665,6 +667,13 @@ ALTER TABLE release_action_status_dg_tmp
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;
`,
}
const postgresSchema = `
@ -814,6 +823,8 @@ CREATE TABLE action
ignore_rules BOOLEAN,
limit_upload_speed INT,
limit_download_speed INT,
limit_ratio REAL,
limit_seed_time INT,
reannounce_skip BOOLEAN DEFAULT false,
reannounce_delete BOOLEAN DEFAULT false,
reannounce_interval INTEGER DEFAULT 7,
@ -1085,4 +1096,11 @@ var postgresMigrations = []string{
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;
`,
}

View file

@ -32,3 +32,10 @@ func toNullInt64(s int64) sql.NullInt64 {
Valid: s != 0,
}
}
func toNullFloat64(s float64) sql.NullFloat64 {
return sql.NullFloat64{
Float64: s,
Valid: s != 0,
}
}

View file

@ -28,6 +28,8 @@ type Action struct {
IgnoreRules bool `json:"ignore_rules,omitempty"`
LimitUploadSpeed int64 `json:"limit_upload_speed,omitempty"`
LimitDownloadSpeed int64 `json:"limit_download_speed,omitempty"`
LimitRatio float64 `json:"limit_ratio,omitempty"`
LimitSeedTime int64 `json:"limit_seed_time,omitempty"`
ReAnnounceSkip bool `json:"reannounce_skip,omitempty"`
ReAnnounceDelete bool `json:"reannounce_delete,omitempty"`
ReAnnounceInterval int64 `json:"reannounce_interval,omitempty"`

View file

@ -131,12 +131,14 @@ interface NumberFieldProps {
name: string;
label?: string;
placeholder?: string;
step?: number;
}
export const NumberField = ({
name,
label,
placeholder
placeholder,
step,
}: NumberFieldProps) => (
<div className="col-span-12 sm:col-span-6">
<label htmlFor={name} className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
@ -151,6 +153,7 @@ export const NumberField = ({
<div className="sm:col-span-2">
<input
type="number"
step={step}
{...field}
className={classNames(
meta.touched && meta.error

View file

@ -587,6 +587,8 @@ function FilterActions({ filter, values }: FilterActionsProps) {
ignore_rules: false,
limit_upload_speed: 0,
limit_download_speed: 0,
limit_ratio: 0,
limit_seed_time: 0,
reannounce_skip: false,
reannounce_delete: false,
reannounce_interval: 7,
@ -746,7 +748,19 @@ function FilterActionsItem({ action, clients, idx, remove }: FilterActionsItemPr
label="Limit upload speed (KB/s)"
/>
</div>
</div>
<div className="mt-6 grid grid-cols-12 gap-6">
<NumberField
name={`actions.${idx}.limit_ratio`}
label="Ratio limit"
step={0.5}
/>
<NumberField
name={`actions.${idx}.limit_seed_time`}
label="Seed time limit (seconds)"
/>
</div>
</div>
<div className="col-span-6">
<SwitchGroup
name={`actions.${idx}.paused`}

View file

@ -68,6 +68,8 @@ interface Action {
ignore_rules?: boolean;
limit_upload_speed?: number;
limit_download_speed?: number;
limit_ratio?: number;
limit_seed_time?: number;
reannounce_skip: boolean;
reannounce_delete: boolean;
reannounce_interval: number;