feat(clients): override arr download client by name (#1328)

* feat(clients): override arr client by name

* feat(clients): add missing file

* feat(clients): add section download client arr
This commit is contained in:
ze0s 2024-01-01 17:57:19 +01:00 committed by GitHub
parent 45b522abf8
commit fbabdfb217
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 143 additions and 49 deletions

View file

@ -43,11 +43,14 @@ func (s *service) lidarr(ctx context.Context, action *domain.Action, release dom
cfg.Password = client.Settings.Basic.Password
}
externalId := 0
if client.Settings.ExternalDownloadClientId > 0 {
externalId = client.Settings.ExternalDownloadClientId
} else if action.ExternalDownloadClientID > 0 {
externalId = int(action.ExternalDownloadClientID)
externalClientId := client.Settings.ExternalDownloadClientId
if action.ExternalDownloadClientID > 0 {
externalClientId = int(action.ExternalDownloadClientID)
}
externalClient := client.Settings.ExternalDownloadClient
if action.ExternalDownloadClient != "" {
externalClient = action.ExternalDownloadClient
}
r := lidarr.Release{
@ -57,7 +60,8 @@ func (s *service) lidarr(ctx context.Context, action *domain.Action, release dom
MagnetUrl: release.MagnetURI,
Size: int64(release.Size),
Indexer: release.Indexer,
DownloadClientId: externalId,
DownloadClientId: externalClientId,
DownloadClient: externalClient,
DownloadProtocol: string(release.Protocol),
Protocol: string(release.Protocol),
PublishDate: time.Now().Format(time.RFC3339),

View file

@ -42,11 +42,14 @@ func (s *service) radarr(ctx context.Context, action *domain.Action, release dom
cfg.Password = client.Settings.Basic.Password
}
externalId := 0
if client.Settings.ExternalDownloadClientId > 0 {
externalId = client.Settings.ExternalDownloadClientId
} else if action.ExternalDownloadClientID > 0 {
externalId = int(action.ExternalDownloadClientID)
externalClientId := client.Settings.ExternalDownloadClientId
if action.ExternalDownloadClientID > 0 {
externalClientId = int(action.ExternalDownloadClientID)
}
externalClient := client.Settings.ExternalDownloadClient
if action.ExternalDownloadClient != "" {
externalClient = action.ExternalDownloadClient
}
r := radarr.Release{
@ -56,7 +59,8 @@ func (s *service) radarr(ctx context.Context, action *domain.Action, release dom
MagnetUrl: release.MagnetURI,
Size: int64(release.Size),
Indexer: release.Indexer,
DownloadClientId: externalId,
DownloadClientId: externalClientId,
DownloadClient: externalClient,
DownloadProtocol: string(release.Protocol),
Protocol: string(release.Protocol),
PublishDate: time.Now().Format(time.RFC3339),

View file

@ -42,11 +42,14 @@ func (s *service) readarr(ctx context.Context, action *domain.Action, release do
cfg.Password = client.Settings.Basic.Password
}
externalId := 0
if client.Settings.ExternalDownloadClientId > 0 {
externalId = client.Settings.ExternalDownloadClientId
} else if action.ExternalDownloadClientID > 0 {
externalId = int(action.ExternalDownloadClientID)
externalClientId := client.Settings.ExternalDownloadClientId
if action.ExternalDownloadClientID > 0 {
externalClientId = int(action.ExternalDownloadClientID)
}
externalClient := client.Settings.ExternalDownloadClient
if action.ExternalDownloadClient != "" {
externalClient = action.ExternalDownloadClient
}
r := readarr.Release{
@ -56,7 +59,8 @@ func (s *service) readarr(ctx context.Context, action *domain.Action, release do
MagnetUrl: release.MagnetURI,
Size: int64(release.Size),
Indexer: release.Indexer,
DownloadClientId: externalId,
DownloadClientId: externalClientId,
DownloadClient: externalClient,
DownloadProtocol: string(release.Protocol),
Protocol: string(release.Protocol),
PublishDate: time.Now().Format(time.RFC3339),

View file

@ -42,11 +42,14 @@ func (s *service) sonarr(ctx context.Context, action *domain.Action, release dom
cfg.Password = client.Settings.Basic.Password
}
externalId := 0
if client.Settings.ExternalDownloadClientId > 0 {
externalId = client.Settings.ExternalDownloadClientId
} else if action.ExternalDownloadClientID > 0 {
externalId = int(action.ExternalDownloadClientID)
externalClientId := client.Settings.ExternalDownloadClientId
if action.ExternalDownloadClientID > 0 {
externalClientId = int(action.ExternalDownloadClientID)
}
externalClient := client.Settings.ExternalDownloadClient
if action.ExternalDownloadClient != "" {
externalClient = action.ExternalDownloadClient
}
r := sonarr.Release{
@ -56,7 +59,8 @@ func (s *service) sonarr(ctx context.Context, action *domain.Action, release dom
MagnetUrl: release.MagnetURI,
Size: int64(release.Size),
Indexer: release.Indexer,
DownloadClientId: externalId,
DownloadClientId: externalClientId,
DownloadClient: externalClient,
DownloadProtocol: string(release.Protocol),
Protocol: string(release.Protocol),
PublishDate: time.Now().Format(time.RFC3339),

View file

@ -42,11 +42,14 @@ func (s *service) whisparr(ctx context.Context, action *domain.Action, release d
cfg.Password = client.Settings.Basic.Password
}
externalId := 0
if client.Settings.ExternalDownloadClientId > 0 {
externalId = client.Settings.ExternalDownloadClientId
} else if action.ExternalDownloadClientID > 0 {
externalId = int(action.ExternalDownloadClientID)
externalClientId := client.Settings.ExternalDownloadClientId
if action.ExternalDownloadClientID > 0 {
externalClientId = int(action.ExternalDownloadClientID)
}
externalClient := client.Settings.ExternalDownloadClient
if action.ExternalDownloadClient != "" {
externalClient = action.ExternalDownloadClient
}
r := whisparr.Release{
@ -56,7 +59,8 @@ func (s *service) whisparr(ctx context.Context, action *domain.Action, release d
MagnetUrl: release.MagnetURI,
Size: int64(release.Size),
Indexer: release.Indexer,
DownloadClientId: externalId,
DownloadClientId: externalClientId,
DownloadClient: externalClient,
DownloadProtocol: string(release.Protocol),
Protocol: string(release.Protocol),
PublishDate: time.Now().Format(time.RFC3339),

View file

@ -91,6 +91,7 @@ func (r *ActionRepo) findByFilterID(ctx context.Context, tx *Tx, filterID int, a
"webhook_method",
"webhook_data",
"external_client_id",
"external_client",
"client_id",
).
From("action").
@ -116,14 +117,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, priorityLayout, webhookHost, webhookType, webhookMethod, webhookData sql.NullString
var execCmd, execArgs, watchFolder, category, tags, label, savePath, contentLayout, priorityLayout, webhookHost, webhookType, webhookMethod, webhookData, externalClient 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, &priorityLayout, &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, &externalClient, &clientID); err != nil {
return nil, errors.Wrap(err, "error scanning row")
}
@ -150,6 +151,7 @@ func (r *ActionRepo) findByFilterID(ctx context.Context, tx *Tx, filterID int, a
a.WebhookData = webhookData.String
a.ExternalDownloadClientID = externalClientID.Int32
a.ExternalDownloadClient = externalClient.String
a.ClientID = clientID.Int32
actions = append(actions, &a)
@ -243,6 +245,7 @@ func (r *ActionRepo) List(ctx context.Context) ([]domain.Action, error) {
"webhook_method",
"webhook_data",
"external_client_id",
"external_client",
"client_id",
).
From("action")
@ -263,13 +266,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, priorityLayout, webhookHost, webhookType, webhookMethod, webhookData sql.NullString
var execCmd, execArgs, watchFolder, category, tags, label, savePath, contentLayout, priorityLayout, webhookHost, webhookType, webhookMethod, webhookData, externalClient 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, &priorityLayout, &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, &externalClient, &clientID); err != nil {
return nil, errors.Wrap(err, "error scanning row")
}
@ -293,6 +296,7 @@ func (r *ActionRepo) List(ctx context.Context) ([]domain.Action, error) {
a.WebhookData = webhookData.String
a.ExternalDownloadClientID = externalClientID.Int32
a.ExternalDownloadClient = externalClient.String
a.ClientID = clientID.Int32
actions = append(actions, a)
@ -337,6 +341,7 @@ func (r *ActionRepo) Get(ctx context.Context, req *domain.GetActionRequest) (*do
"webhook_method",
"webhook_data",
"external_client_id",
"external_client",
"client_id",
"filter_id",
).
@ -359,13 +364,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, priorityLayout, webhookHost, webhookType, webhookMethod, webhookData sql.NullString
var execCmd, execArgs, watchFolder, category, tags, label, savePath, contentLayout, priorityLayout, webhookHost, webhookType, webhookMethod, webhookData, externalClient 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, &priorityLayout, &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, &externalClient, &clientID, &filterID); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, domain.ErrRecordNotFound
}
@ -396,6 +401,7 @@ func (r *ActionRepo) Get(ctx context.Context, req *domain.GetActionRequest) (*do
a.WebhookData = webhookData.String
a.ExternalDownloadClientID = externalClientID.Int32
a.ExternalDownloadClient = externalClient.String
a.ClientID = clientID.Int32
a.FilterID = int(filterID.Int32)
@ -474,6 +480,7 @@ func (r *ActionRepo) Store(ctx context.Context, action domain.Action) (*domain.A
"webhook_method",
"webhook_data",
"external_client_id",
"external_client",
"client_id",
"filter_id",
).
@ -506,6 +513,7 @@ func (r *ActionRepo) Store(ctx context.Context, action domain.Action) (*domain.A
toNullString(action.WebhookMethod),
toNullString(action.WebhookData),
toNullInt32(action.ExternalDownloadClientID),
toNullString(action.ExternalDownloadClient),
toNullInt32(action.ClientID),
toNullInt32(int32(action.FilterID)),
).
@ -556,6 +564,7 @@ func (r *ActionRepo) Update(ctx context.Context, action domain.Action) (*domain.
Set("webhook_method", toNullString(action.WebhookMethod)).
Set("webhook_data", toNullString(action.WebhookData)).
Set("external_client_id", toNullInt32(action.ExternalDownloadClientID)).
Set("external_client", toNullString(action.ExternalDownloadClient)).
Set("client_id", toNullInt32(action.ClientID)).
Set("filter_id", toNullInt32(int32(action.FilterID))).
Where(sq.Eq{"id": action.ID})
@ -616,6 +625,7 @@ func (r *ActionRepo) StoreFilterActions(ctx context.Context, filterID int64, act
Set("webhook_method", toNullString(action.WebhookMethod)).
Set("webhook_data", toNullString(action.WebhookData)).
Set("external_client_id", toNullInt32(action.ExternalDownloadClientID)).
Set("external_client", toNullString(action.ExternalDownloadClient)).
Set("client_id", toNullInt32(action.ClientID)).
Set("filter_id", toNullInt64(filterID)).
Where(sq.Eq{"id": action.ID})
@ -663,6 +673,7 @@ func (r *ActionRepo) StoreFilterActions(ctx context.Context, filterID int64, act
"webhook_method",
"webhook_data",
"external_client_id",
"external_client",
"client_id",
"filter_id",
).
@ -695,6 +706,7 @@ func (r *ActionRepo) StoreFilterActions(ctx context.Context, filterID int64, act
toNullString(action.WebhookMethod),
toNullString(action.WebhookData),
toNullInt32(action.ExternalDownloadClientID),
toNullString(action.ExternalDownloadClient),
toNullInt32(action.ClientID),
toNullInt64(filterID),
).

View file

@ -185,6 +185,7 @@ func (r *DownloadClientRepo) Store(ctx context.Context, client domain.DownloadCl
Basic: client.Settings.Basic,
Rules: client.Settings.Rules,
ExternalDownloadClientId: client.Settings.ExternalDownloadClientId,
ExternalDownloadClient: client.Settings.ExternalDownloadClient,
}
settingsJson, err := json.Marshal(&settings)
@ -224,6 +225,7 @@ func (r *DownloadClientRepo) Update(ctx context.Context, client domain.DownloadC
Basic: client.Settings.Basic,
Rules: client.Settings.Rules,
ExternalDownloadClientId: client.Settings.ExternalDownloadClientId,
ExternalDownloadClient: client.Settings.ExternalDownloadClient,
}
settingsJson, err := json.Marshal(&settings)

View file

@ -41,6 +41,7 @@ func getMockDownloadClient() domain.DownloadClient {
UploadSpeedThreshold: 0,
},
ExternalDownloadClientId: 0,
ExternalDownloadClient: "",
},
}
}

View file

@ -210,6 +210,7 @@ CREATE TABLE action
webhook_data TEXT,
webhook_headers TEXT[] DEFAULT '{}',
external_client_id INTEGER,
external_client TEXT,
client_id INTEGER,
filter_id INTEGER,
FOREIGN KEY (filter_id) REFERENCES filter (id),
@ -838,5 +839,8 @@ ALTER TABLE filter_external
`,
`ALTER TABLE action
ADD COLUMN priority TEXT;
`,
`ALTER TABLE action
ADD COLUMN external_client TEXT;
`,
}

View file

@ -210,6 +210,7 @@ CREATE TABLE action
webhook_data TEXT,
webhook_headers TEXT[] DEFAULT '{}',
external_client_id INTEGER,
external_client TEXT,
client_id INTEGER,
filter_id INTEGER,
FOREIGN KEY (filter_id) REFERENCES filter (id),
@ -1479,5 +1480,8 @@ ALTER TABLE feed_dg_tmp
`,
`ALTER TABLE action
ADD COLUMN priority TEXT;
`,
`ALTER TABLE action
ADD COLUMN external_client TEXT;
`,
}

View file

@ -53,6 +53,7 @@ type Action struct {
WebhookData string `json:"webhook_data,omitempty"`
WebhookHeaders []string `json:"webhook_headers,omitempty"`
ExternalDownloadClientID int32 `json:"external_download_client_id,omitempty"`
ExternalDownloadClient string `json:"external_download_client,omitempty"`
FilterID int `json:"filter_id,omitempty"`
ClientID int32 `json:"client_id,omitempty"`
Client *DownloadClient `json:"client,omitempty"`

View file

@ -45,6 +45,7 @@ type DownloadClientSettings struct {
Basic BasicAuth `json:"basic,omitempty"`
Rules DownloadClientRules `json:"rules,omitempty"`
ExternalDownloadClientId int `json:"external_download_client_id,omitempty"`
ExternalDownloadClient string `json:"external_download_client,omitempty"`
}
type DownloadClientRules struct {

View file

@ -72,6 +72,7 @@ type Release struct {
Protocol string `json:"protocol"`
PublishDate string `json:"publishDate"`
DownloadClientId int `json:"downloadClientId,omitempty"`
DownloadClient string `json:"downloadClient,omitempty"`
}
type PushResponse struct {

View file

@ -71,6 +71,7 @@ type Release struct {
Protocol string `json:"protocol"`
PublishDate string `json:"publishDate"`
DownloadClientId int `json:"downloadClientId,omitempty"`
DownloadClient string `json:"downloadClient,omitempty"`
}
type PushResponse struct {

View file

@ -73,6 +73,7 @@ type Release struct {
Protocol string `json:"protocol"`
PublishDate string `json:"publishDate"`
DownloadClientId int `json:"downloadClientId,omitempty"`
DownloadClient string `json:"downloadClient,omitempty"`
}
type PushResponse struct {

View file

@ -73,6 +73,7 @@ type Release struct {
Protocol string `json:"protocol"`
PublishDate string `json:"publishDate"`
DownloadClientId int `json:"downloadClientId,omitempty"`
DownloadClient string `json:"downloadClient,omitempty"`
}
type PushResponse struct {

View file

@ -70,6 +70,7 @@ type Release struct {
Protocol string `json:"protocol"`
PublishDate string `json:"publishDate"`
DownloadClientId int `json:"downloadClientId,omitempty"`
DownloadClient string `json:"downloadClient,omitempty"`
}
type PushResponse struct {

View file

@ -41,6 +41,8 @@ interface InitialValuesSettings {
download_speed_threshold?: number;
max_active_downloads?: number;
};
external_download_client_id?: number;
external_download_client?: string;
}
interface InitialValues {
@ -135,8 +137,6 @@ function FormFieldsArr() {
<PasswordFieldWide name="settings.basic.password" label="Password" />
</>
)}
<NumberFieldWide name="settings.external_download_client_id" label="Download Client ID" tooltip={<div><p>Specify what client the arr should use by default. Can be overridden per filter action. You can find the id in the arr by looking at the network responses for download clients.</p></div>} />
</div>
);
}
@ -432,6 +432,29 @@ function FormFieldsRulesBasic() {
);
}
function FormFieldsRulesArr() {
// const {
// values: { settings }
// } = useFormikContext<InitialValues>();
return (
<div className="border-t border-gray-200 dark:border-gray-700 py-5 px-2">
<div className="px-4 space-y-1">
<Dialog.Title className="text-lg font-medium text-gray-900 dark:text-white">
Download Client
</Dialog.Title>
<p className="text-sm text-gray-500 dark:text-gray-400">
Override download client to use. Can also be overridden per Filter Action.
</p>
</div>
<TextFieldWide name="settings.external_download_client" label="Client Name" tooltip={<div><p>Specify what client the arr should use by default. Can be overridden per filter action.</p></div>} />
<NumberFieldWide name="settings.external_download_client_id" label="Client ID DEPRECATED" tooltip={<div><p>DEPRECATED: Use Client name field instead.</p></div>} />
</div>
);
}
function FormFieldsRulesQbit() {
const {
values: { settings }
@ -544,7 +567,12 @@ export const rulesComponentMap: componentMapType = {
DELUGE_V2: <FormFieldsRulesBasic />,
QBITTORRENT: <FormFieldsRulesQbit />,
PORLA: <FormFieldsRulesBasic />,
TRANSMISSION: <FormFieldsRulesTransmission />
TRANSMISSION: <FormFieldsRulesTransmission />,
RADARR: <FormFieldsRulesArr />,
SONARR: <FormFieldsRulesArr />,
LIDARR: <FormFieldsRulesArr />,
WHISPARR: <FormFieldsRulesArr />,
READARR: <FormFieldsRulesArr />,
};
interface formButtonsProps {

View file

@ -70,6 +70,7 @@ export function Actions({ filter, values }: FilterActionsProps) {
webhook_data: "",
webhook_headers: [],
external_download_client_id: 0,
external_download_client: "",
client_id: 0
};

View file

@ -118,9 +118,21 @@ export const Arr = ({ idx, action, clients }: ClientActionProps) => (
</FilterSection.HalfRow>
<FilterSection.HalfRow>
<div className="">
<Input.TextField
name={`actions.${idx}.external_download_client`}
label="Override download client name for arr"
tooltip={
<p>
Override Download client name from the one set in Clients. Useful if you
have multiple clients inside the arr.
</p>
}
/>
<Input.NumberField
name={`actions.${idx}.external_download_client_id`}
label="Override download client id for arr"
label="Override download client id for arr DEPRECATED"
className="mt-4"
tooltip={
<p>
Override Download client Id from the one set in Clients. Useful if you
@ -128,6 +140,7 @@ export const Arr = ({ idx, action, clients }: ClientActionProps) => (
</p>
}
/>
</div>
</FilterSection.HalfRow>
</FilterSection.Layout>
</FilterSection.Section>

View file

@ -49,6 +49,7 @@ interface DownloadClientSettings {
basic?: DownloadClientBasicAuth;
rules?: DownloadClientRules;
external_download_client_id?: number;
external_download_client?: string;
}
interface DownloadClient {

View file

@ -105,6 +105,7 @@ interface Action {
webhook_data: string,
webhook_headers: string[];
external_download_client_id?: number;
external_download_client?: string;
client_id?: number;
filter_id?: number;
}