mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 00:39:13 +00:00
feat: add support for proxies to use with IRC and Indexers (#1421)
* feat: add support for proxies * fix(http): release handler * fix(migrations): define proxy early * fix(migrations): pg proxy * fix(proxy): list update delete * fix(proxy): remove log and imports * feat(irc): use proxy * feat(irc): tests * fix(web): update imports for ProxyForms.tsx * fix(database): migration * feat(proxy): test * feat(proxy): validate proxy type * feat(proxy): validate and test * feat(proxy): improve validate and test * feat(proxy): fix db schema * feat(proxy): add db tests * feat(proxy): handle http errors * fix(http): imports * feat(proxy): use proxy for indexer downloads * feat(proxy): indexerforms select proxy * feat(proxy): handle torrent download * feat(proxy): skip if disabled * feat(proxy): imports * feat(proxy): implement in Feeds * feat(proxy): update helper text indexer proxy * feat(proxy): add internal cache
This commit is contained in:
parent
472d327308
commit
bc0f4cc055
59 changed files with 2533 additions and 371 deletions
265
internal/database/proxy.go
Normal file
265
internal/database/proxy.go
Normal file
|
@ -0,0 +1,265 @@
|
|||
// Copyright (c) 2021 - 2024, Ludvig Lundgren and the autobrr contributors.
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"github.com/autobrr/autobrr/internal/domain"
|
||||
"github.com/autobrr/autobrr/internal/logger"
|
||||
"github.com/autobrr/autobrr/pkg/errors"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type ProxyRepo struct {
|
||||
log zerolog.Logger
|
||||
db *DB
|
||||
}
|
||||
|
||||
func NewProxyRepo(log logger.Logger, db *DB) domain.ProxyRepo {
|
||||
return &ProxyRepo{
|
||||
log: log.With().Str("repo", "proxy").Logger(),
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ProxyRepo) Store(ctx context.Context, p *domain.Proxy) error {
|
||||
queryBuilder := r.db.squirrel.
|
||||
Insert("proxy").
|
||||
Columns(
|
||||
"enabled",
|
||||
"name",
|
||||
"type",
|
||||
"addr",
|
||||
"auth_user",
|
||||
"auth_pass",
|
||||
"timeout",
|
||||
).
|
||||
Values(
|
||||
p.Enabled,
|
||||
p.Name,
|
||||
p.Type,
|
||||
toNullString(p.Addr),
|
||||
toNullString(p.User),
|
||||
toNullString(p.Pass),
|
||||
p.Timeout,
|
||||
).
|
||||
Suffix("RETURNING id").
|
||||
RunWith(r.db.handler)
|
||||
|
||||
var retID int64
|
||||
err := queryBuilder.QueryRowContext(ctx).Scan(&retID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error executing query")
|
||||
}
|
||||
|
||||
p.ID = retID
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ProxyRepo) Update(ctx context.Context, p *domain.Proxy) error {
|
||||
queryBuilder := r.db.squirrel.
|
||||
Update("proxy").
|
||||
Set("enabled", p.Enabled).
|
||||
Set("name", p.Name).
|
||||
Set("type", p.Type).
|
||||
Set("addr", p.Addr).
|
||||
Set("auth_user", toNullString(p.User)).
|
||||
Set("auth_pass", toNullString(p.Pass)).
|
||||
Set("timeout", p.Timeout).
|
||||
Set("updated_at", time.Now().Format(time.RFC3339)).
|
||||
Where(sq.Eq{"id": p.ID})
|
||||
|
||||
query, args, err := queryBuilder.ToSql()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error building query")
|
||||
}
|
||||
|
||||
// update record
|
||||
res, err := r.db.handler.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error executing query")
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting affected rows")
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return domain.ErrUpdateFailed
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *ProxyRepo) List(ctx context.Context) ([]domain.Proxy, error) {
|
||||
queryBuilder := r.db.squirrel.
|
||||
Select(
|
||||
"id",
|
||||
"enabled",
|
||||
"name",
|
||||
"type",
|
||||
"addr",
|
||||
"auth_user",
|
||||
"auth_pass",
|
||||
"timeout",
|
||||
).
|
||||
From("proxy").
|
||||
OrderBy("name ASC")
|
||||
|
||||
query, args, err := queryBuilder.ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error building query")
|
||||
}
|
||||
|
||||
rows, err := r.db.handler.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error executing query")
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
proxies := make([]domain.Proxy, 0)
|
||||
for rows.Next() {
|
||||
var proxy domain.Proxy
|
||||
|
||||
var user, pass sql.NullString
|
||||
|
||||
if err := rows.Scan(&proxy.ID, &proxy.Enabled, &proxy.Name, &proxy.Type, &proxy.Addr, &user, &pass, &proxy.Timeout); err != nil {
|
||||
return nil, errors.Wrap(err, "error scanning row")
|
||||
}
|
||||
|
||||
proxy.User = user.String
|
||||
proxy.Pass = pass.String
|
||||
|
||||
proxies = append(proxies, proxy)
|
||||
}
|
||||
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error row")
|
||||
}
|
||||
|
||||
return proxies, nil
|
||||
}
|
||||
|
||||
func (r *ProxyRepo) Delete(ctx context.Context, id int64) error {
|
||||
tx, err := r.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error begin transaction")
|
||||
}
|
||||
|
||||
defer tx.Rollback()
|
||||
|
||||
queryBuilder := r.db.squirrel.
|
||||
Delete("proxy").
|
||||
Where(sq.Eq{"id": id})
|
||||
|
||||
query, args, err := queryBuilder.ToSql()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error building query")
|
||||
}
|
||||
|
||||
res, err := tx.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error executing query")
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting affected rows")
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return domain.ErrDeleteFailed
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error commit deleting proxy")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ProxyRepo) FindByID(ctx context.Context, id int64) (*domain.Proxy, error) {
|
||||
queryBuilder := r.db.squirrel.
|
||||
Select(
|
||||
"id",
|
||||
"enabled",
|
||||
"name",
|
||||
"type",
|
||||
"addr",
|
||||
"auth_user",
|
||||
"auth_pass",
|
||||
"timeout",
|
||||
).
|
||||
From("proxy").
|
||||
OrderBy("name ASC").
|
||||
Where(sq.Eq{"id": id})
|
||||
|
||||
query, args, err := queryBuilder.ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error building query")
|
||||
}
|
||||
|
||||
row := r.db.handler.QueryRowContext(ctx, query, args...)
|
||||
if err := row.Err(); err != nil {
|
||||
return nil, errors.Wrap(err, "error executing query")
|
||||
}
|
||||
|
||||
var proxy domain.Proxy
|
||||
|
||||
var user, pass sql.NullString
|
||||
|
||||
err = row.Scan(&proxy.ID, &proxy.Enabled, &proxy.Name, &proxy.Type, &proxy.Addr, &user, &pass, &proxy.Timeout)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, domain.ErrRecordNotFound
|
||||
}
|
||||
|
||||
return nil, errors.Wrap(err, "error scanning row")
|
||||
}
|
||||
|
||||
proxy.User = user.String
|
||||
proxy.Pass = pass.String
|
||||
|
||||
return &proxy, nil
|
||||
}
|
||||
|
||||
func (r *ProxyRepo) ToggleEnabled(ctx context.Context, id int64, enabled bool) error {
|
||||
queryBuilder := r.db.squirrel.
|
||||
Update("proxy").
|
||||
Set("enabled", enabled).
|
||||
Set("updated_at", time.Now().Format(time.RFC3339)).
|
||||
Where(sq.Eq{"id": id})
|
||||
|
||||
query, args, err := queryBuilder.ToSql()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error building query")
|
||||
}
|
||||
|
||||
// update record
|
||||
res, err := r.db.handler.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error executing query")
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting affected rows")
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return domain.ErrUpdateFailed
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue