mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 08:49: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
|
@ -30,7 +30,7 @@ func NewIrcRepo(log logger.Logger, db *DB) domain.IrcRepo {
|
|||
|
||||
func (r *IrcRepo) GetNetworkByID(ctx context.Context, id int64) (*domain.IrcNetwork, error) {
|
||||
queryBuilder := r.db.squirrel.
|
||||
Select("id", "enabled", "name", "server", "port", "tls", "pass", "nick", "auth_mechanism", "auth_account", "auth_password", "invite_command", "bouncer_addr", "use_bouncer", "bot_mode").
|
||||
Select("id", "enabled", "name", "server", "port", "tls", "pass", "nick", "auth_mechanism", "auth_account", "auth_password", "invite_command", "bouncer_addr", "use_bouncer", "bot_mode", "use_proxy", "proxy_id").
|
||||
From("irc_network").
|
||||
Where(sq.Eq{"id": id})
|
||||
|
||||
|
@ -42,26 +42,27 @@ func (r *IrcRepo) GetNetworkByID(ctx context.Context, id int64) (*domain.IrcNetw
|
|||
|
||||
var n domain.IrcNetwork
|
||||
|
||||
var pass, nick, inviteCmd, bouncerAddr sql.NullString
|
||||
var account, password sql.NullString
|
||||
var tls sql.NullBool
|
||||
var pass, nick, inviteCmd, bouncerAddr sql.Null[string]
|
||||
var account, password sql.Null[string]
|
||||
var tls sql.Null[bool]
|
||||
var proxyId sql.Null[int64]
|
||||
|
||||
row := r.db.handler.QueryRowContext(ctx, query, args...)
|
||||
if err := row.Scan(&n.ID, &n.Enabled, &n.Name, &n.Server, &n.Port, &tls, &pass, &nick, &n.Auth.Mechanism, &account, &password, &inviteCmd, &bouncerAddr, &n.UseBouncer, &n.BotMode); err != nil {
|
||||
if err := row.Scan(&n.ID, &n.Enabled, &n.Name, &n.Server, &n.Port, &tls, &pass, &nick, &n.Auth.Mechanism, &account, &password, &inviteCmd, &bouncerAddr, &n.UseBouncer, &n.BotMode, &n.UseProxy, &proxyId); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, domain.ErrRecordNotFound
|
||||
}
|
||||
|
||||
return nil, errors.Wrap(err, "error scanning row")
|
||||
}
|
||||
|
||||
n.TLS = tls.Bool
|
||||
n.Pass = pass.String
|
||||
n.Nick = nick.String
|
||||
n.InviteCommand = inviteCmd.String
|
||||
n.Auth.Account = account.String
|
||||
n.Auth.Password = password.String
|
||||
n.BouncerAddr = bouncerAddr.String
|
||||
n.TLS = tls.V
|
||||
n.Pass = pass.V
|
||||
n.Nick = nick.V
|
||||
n.InviteCommand = inviteCmd.V
|
||||
n.BouncerAddr = bouncerAddr.V
|
||||
n.Auth.Account = account.V
|
||||
n.Auth.Password = password.V
|
||||
n.ProxyId = proxyId.V
|
||||
|
||||
return &n, nil
|
||||
}
|
||||
|
@ -111,7 +112,7 @@ func (r *IrcRepo) DeleteNetwork(ctx context.Context, id int64) error {
|
|||
|
||||
func (r *IrcRepo) FindActiveNetworks(ctx context.Context) ([]domain.IrcNetwork, error) {
|
||||
queryBuilder := r.db.squirrel.
|
||||
Select("id", "enabled", "name", "server", "port", "tls", "pass", "nick", "auth_mechanism", "auth_account", "auth_password", "invite_command", "bouncer_addr", "use_bouncer", "bot_mode").
|
||||
Select("id", "enabled", "name", "server", "port", "tls", "pass", "nick", "auth_mechanism", "auth_account", "auth_password", "invite_command", "bouncer_addr", "use_bouncer", "bot_mode", "use_proxy", "proxy_id").
|
||||
From("irc_network").
|
||||
Where(sq.Eq{"enabled": true})
|
||||
|
||||
|
@ -131,22 +132,24 @@ func (r *IrcRepo) FindActiveNetworks(ctx context.Context) ([]domain.IrcNetwork,
|
|||
for rows.Next() {
|
||||
var net domain.IrcNetwork
|
||||
|
||||
var pass, nick, inviteCmd, bouncerAddr sql.NullString
|
||||
var account, password sql.NullString
|
||||
var tls sql.NullBool
|
||||
var pass, nick, inviteCmd, bouncerAddr sql.Null[string]
|
||||
var account, password sql.Null[string]
|
||||
var tls sql.Null[bool]
|
||||
var proxyId sql.Null[int64]
|
||||
|
||||
if err := rows.Scan(&net.ID, &net.Enabled, &net.Name, &net.Server, &net.Port, &tls, &pass, &nick, &net.Auth.Mechanism, &account, &password, &inviteCmd, &bouncerAddr, &net.UseBouncer, &net.BotMode); err != nil {
|
||||
if err := rows.Scan(&net.ID, &net.Enabled, &net.Name, &net.Server, &net.Port, &tls, &pass, &nick, &net.Auth.Mechanism, &account, &password, &inviteCmd, &bouncerAddr, &net.UseBouncer, &net.BotMode, &net.UseProxy, &proxyId); err != nil {
|
||||
return nil, errors.Wrap(err, "error scanning row")
|
||||
}
|
||||
|
||||
net.TLS = tls.Bool
|
||||
net.Pass = pass.String
|
||||
net.Nick = nick.String
|
||||
net.InviteCommand = inviteCmd.String
|
||||
net.BouncerAddr = bouncerAddr.String
|
||||
net.TLS = tls.V
|
||||
net.Pass = pass.V
|
||||
net.Nick = nick.V
|
||||
net.InviteCommand = inviteCmd.V
|
||||
net.BouncerAddr = bouncerAddr.V
|
||||
net.Auth.Account = account.V
|
||||
net.Auth.Password = password.V
|
||||
|
||||
net.Auth.Account = account.String
|
||||
net.Auth.Password = password.String
|
||||
net.ProxyId = proxyId.V
|
||||
|
||||
networks = append(networks, net)
|
||||
}
|
||||
|
@ -159,7 +162,7 @@ func (r *IrcRepo) FindActiveNetworks(ctx context.Context) ([]domain.IrcNetwork,
|
|||
|
||||
func (r *IrcRepo) ListNetworks(ctx context.Context) ([]domain.IrcNetwork, error) {
|
||||
queryBuilder := r.db.squirrel.
|
||||
Select("id", "enabled", "name", "server", "port", "tls", "pass", "nick", "auth_mechanism", "auth_account", "auth_password", "invite_command", "bouncer_addr", "use_bouncer", "bot_mode").
|
||||
Select("id", "enabled", "name", "server", "port", "tls", "pass", "nick", "auth_mechanism", "auth_account", "auth_password", "invite_command", "bouncer_addr", "use_bouncer", "bot_mode", "use_proxy", "proxy_id").
|
||||
From("irc_network").
|
||||
OrderBy("name ASC")
|
||||
|
||||
|
@ -179,22 +182,24 @@ func (r *IrcRepo) ListNetworks(ctx context.Context) ([]domain.IrcNetwork, error)
|
|||
for rows.Next() {
|
||||
var net domain.IrcNetwork
|
||||
|
||||
var pass, nick, inviteCmd, bouncerAddr sql.NullString
|
||||
var account, password sql.NullString
|
||||
var tls sql.NullBool
|
||||
var pass, nick, inviteCmd, bouncerAddr sql.Null[string]
|
||||
var account, password sql.Null[string]
|
||||
var tls sql.Null[bool]
|
||||
var proxyId sql.Null[int64]
|
||||
|
||||
if err := rows.Scan(&net.ID, &net.Enabled, &net.Name, &net.Server, &net.Port, &tls, &pass, &nick, &net.Auth.Mechanism, &account, &password, &inviteCmd, &bouncerAddr, &net.UseBouncer, &net.BotMode); err != nil {
|
||||
if err := rows.Scan(&net.ID, &net.Enabled, &net.Name, &net.Server, &net.Port, &tls, &pass, &nick, &net.Auth.Mechanism, &account, &password, &inviteCmd, &bouncerAddr, &net.UseBouncer, &net.BotMode, &net.UseProxy, &proxyId); err != nil {
|
||||
return nil, errors.Wrap(err, "error scanning row")
|
||||
}
|
||||
|
||||
net.TLS = tls.Bool
|
||||
net.Pass = pass.String
|
||||
net.Nick = nick.String
|
||||
net.InviteCommand = inviteCmd.String
|
||||
net.BouncerAddr = bouncerAddr.String
|
||||
net.TLS = tls.V
|
||||
net.Pass = pass.V
|
||||
net.Nick = nick.V
|
||||
net.InviteCommand = inviteCmd.V
|
||||
net.BouncerAddr = bouncerAddr.V
|
||||
net.Auth.Account = account.V
|
||||
net.Auth.Password = password.V
|
||||
|
||||
net.Auth.Account = account.String
|
||||
net.Auth.Password = password.String
|
||||
net.ProxyId = proxyId.V
|
||||
|
||||
networks = append(networks, net)
|
||||
}
|
||||
|
@ -225,13 +230,13 @@ func (r *IrcRepo) ListChannels(networkID int64) ([]domain.IrcChannel, error) {
|
|||
var channels []domain.IrcChannel
|
||||
for rows.Next() {
|
||||
var ch domain.IrcChannel
|
||||
var pass sql.NullString
|
||||
var pass sql.Null[string]
|
||||
|
||||
if err := rows.Scan(&ch.ID, &ch.Name, &ch.Enabled, &pass); err != nil {
|
||||
return nil, errors.Wrap(err, "error scanning row")
|
||||
}
|
||||
|
||||
ch.Password = pass.String
|
||||
ch.Password = pass.V
|
||||
|
||||
channels = append(channels, ch)
|
||||
}
|
||||
|
@ -244,7 +249,7 @@ func (r *IrcRepo) ListChannels(networkID int64) ([]domain.IrcChannel, error) {
|
|||
|
||||
func (r *IrcRepo) CheckExistingNetwork(ctx context.Context, network *domain.IrcNetwork) (*domain.IrcNetwork, error) {
|
||||
queryBuilder := r.db.squirrel.
|
||||
Select("id", "enabled", "name", "server", "port", "tls", "pass", "nick", "auth_mechanism", "auth_account", "auth_password", "invite_command", "bouncer_addr", "use_bouncer", "bot_mode").
|
||||
Select("id", "enabled", "name", "server", "port", "tls", "pass", "nick", "auth_mechanism", "auth_account", "auth_password", "invite_command", "bouncer_addr", "use_bouncer", "bot_mode", "use_proxy", "proxy_id").
|
||||
From("irc_network").
|
||||
Where(sq.Eq{"server": network.Server}).
|
||||
Where(sq.Eq{"port": network.Port}).
|
||||
|
@ -263,11 +268,12 @@ func (r *IrcRepo) CheckExistingNetwork(ctx context.Context, network *domain.IrcN
|
|||
|
||||
var net domain.IrcNetwork
|
||||
|
||||
var pass, nick, inviteCmd, bouncerAddr sql.NullString
|
||||
var account, password sql.NullString
|
||||
var tls sql.NullBool
|
||||
var pass, nick, inviteCmd, bouncerAddr sql.Null[string]
|
||||
var account, password sql.Null[string]
|
||||
var tls sql.Null[bool]
|
||||
var proxyId sql.Null[int64]
|
||||
|
||||
if err = row.Scan(&net.ID, &net.Enabled, &net.Name, &net.Server, &net.Port, &tls, &pass, &nick, &net.Auth.Mechanism, &account, &password, &inviteCmd, &bouncerAddr, &net.UseBouncer, &net.BotMode); err != nil {
|
||||
if err = row.Scan(&net.ID, &net.Enabled, &net.Name, &net.Server, &net.Port, &tls, &pass, &nick, &net.Auth.Mechanism, &account, &password, &inviteCmd, &bouncerAddr, &net.UseBouncer, &net.BotMode, &net.UseProxy, &proxyId); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
// no result is not an error in our case
|
||||
return nil, nil
|
||||
|
@ -276,29 +282,20 @@ func (r *IrcRepo) CheckExistingNetwork(ctx context.Context, network *domain.IrcN
|
|||
return nil, errors.Wrap(err, "error scanning row")
|
||||
}
|
||||
|
||||
net.TLS = tls.Bool
|
||||
net.Pass = pass.String
|
||||
net.Nick = nick.String
|
||||
net.InviteCommand = inviteCmd.String
|
||||
net.BouncerAddr = bouncerAddr.String
|
||||
net.Auth.Account = account.String
|
||||
net.Auth.Password = password.String
|
||||
net.TLS = tls.V
|
||||
net.Pass = pass.V
|
||||
net.Nick = nick.V
|
||||
net.InviteCommand = inviteCmd.V
|
||||
net.BouncerAddr = bouncerAddr.V
|
||||
net.Auth.Account = account.V
|
||||
net.Auth.Password = password.V
|
||||
|
||||
net.ProxyId = proxyId.V
|
||||
|
||||
return &net, nil
|
||||
}
|
||||
|
||||
func (r *IrcRepo) StoreNetwork(ctx context.Context, network *domain.IrcNetwork) error {
|
||||
netName := toNullString(network.Name)
|
||||
pass := toNullString(network.Pass)
|
||||
nick := toNullString(network.Nick)
|
||||
inviteCmd := toNullString(network.InviteCommand)
|
||||
bouncerAddr := toNullString(network.BouncerAddr)
|
||||
|
||||
account := toNullString(network.Auth.Account)
|
||||
password := toNullString(network.Auth.Password)
|
||||
|
||||
var retID int64
|
||||
|
||||
queryBuilder := r.db.squirrel.
|
||||
Insert("irc_network").
|
||||
Columns(
|
||||
|
@ -319,60 +316,49 @@ func (r *IrcRepo) StoreNetwork(ctx context.Context, network *domain.IrcNetwork)
|
|||
).
|
||||
Values(
|
||||
network.Enabled,
|
||||
netName,
|
||||
toNullString(network.Name),
|
||||
network.Server,
|
||||
network.Port,
|
||||
network.TLS,
|
||||
pass,
|
||||
nick,
|
||||
toNullString(network.Pass),
|
||||
toNullString(network.Nick),
|
||||
network.Auth.Mechanism,
|
||||
account,
|
||||
password,
|
||||
inviteCmd,
|
||||
bouncerAddr,
|
||||
toNullString(network.Auth.Account),
|
||||
toNullString(network.Auth.Password),
|
||||
toNullString(network.InviteCommand),
|
||||
toNullString(network.BouncerAddr),
|
||||
network.UseBouncer,
|
||||
network.BotMode,
|
||||
).
|
||||
Suffix("RETURNING id").
|
||||
RunWith(r.db.handler)
|
||||
|
||||
if err := queryBuilder.QueryRowContext(ctx).Scan(&retID); err != nil {
|
||||
if err := queryBuilder.QueryRowContext(ctx).Scan(&network.ID); err != nil {
|
||||
return errors.Wrap(err, "error executing query")
|
||||
}
|
||||
|
||||
network.ID = retID
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *IrcRepo) UpdateNetwork(ctx context.Context, network *domain.IrcNetwork) error {
|
||||
netName := toNullString(network.Name)
|
||||
pass := toNullString(network.Pass)
|
||||
nick := toNullString(network.Nick)
|
||||
inviteCmd := toNullString(network.InviteCommand)
|
||||
bouncerAddr := toNullString(network.BouncerAddr)
|
||||
|
||||
account := toNullString(network.Auth.Account)
|
||||
password := toNullString(network.Auth.Password)
|
||||
|
||||
var err error
|
||||
|
||||
queryBuilder := r.db.squirrel.
|
||||
Update("irc_network").
|
||||
Set("enabled", network.Enabled).
|
||||
Set("name", netName).
|
||||
Set("name", toNullString(network.Name)).
|
||||
Set("server", network.Server).
|
||||
Set("port", network.Port).
|
||||
Set("tls", network.TLS).
|
||||
Set("pass", pass).
|
||||
Set("nick", nick).
|
||||
Set("pass", toNullString(network.Pass)).
|
||||
Set("nick", toNullString(network.Nick)).
|
||||
Set("auth_mechanism", network.Auth.Mechanism).
|
||||
Set("auth_account", account).
|
||||
Set("auth_password", password).
|
||||
Set("invite_command", inviteCmd).
|
||||
Set("bouncer_addr", bouncerAddr).
|
||||
Set("auth_account", toNullString(network.Auth.Account)).
|
||||
Set("auth_password", toNullString(network.Auth.Password)).
|
||||
Set("invite_command", toNullString(network.InviteCommand)).
|
||||
Set("bouncer_addr", toNullString(network.BouncerAddr)).
|
||||
Set("use_bouncer", network.UseBouncer).
|
||||
Set("bot_mode", network.BotMode).
|
||||
Set("use_proxy", network.UseProxy).
|
||||
Set("proxy_id", toNullInt64(network.ProxyId)).
|
||||
Set("updated_at", time.Now().Format(time.RFC3339)).
|
||||
Where(sq.Eq{"id": network.ID})
|
||||
|
||||
|
@ -414,7 +400,6 @@ func (r *IrcRepo) StoreNetworkChannels(ctx context.Context, networkID int64, cha
|
|||
|
||||
for _, channel := range channels {
|
||||
// values
|
||||
pass := toNullString(channel.Password)
|
||||
|
||||
channelQueryBuilder := r.db.squirrel.
|
||||
Insert("irc_channel").
|
||||
|
@ -429,21 +414,17 @@ func (r *IrcRepo) StoreNetworkChannels(ctx context.Context, networkID int64, cha
|
|||
channel.Enabled,
|
||||
true,
|
||||
channel.Name,
|
||||
pass,
|
||||
toNullString(channel.Password),
|
||||
networkID,
|
||||
).
|
||||
Suffix("RETURNING id").
|
||||
RunWith(tx)
|
||||
|
||||
// returning
|
||||
var retID int64
|
||||
|
||||
if err = channelQueryBuilder.QueryRowContext(ctx).Scan(&retID); err != nil {
|
||||
if err = channelQueryBuilder.QueryRowContext(ctx).Scan(&channel.ID); err != nil {
|
||||
return errors.Wrap(err, "error executing query storeNetworkChannels")
|
||||
}
|
||||
|
||||
channel.ID = retID
|
||||
|
||||
//channelQuery, channelArgs, err := channelQueryBuilder.ToSql()
|
||||
//if err != nil {
|
||||
// r.log.Error().Stack().Err(err).Msg("irc.storeNetworkChannels: error building query")
|
||||
|
@ -467,8 +448,6 @@ func (r *IrcRepo) StoreNetworkChannels(ctx context.Context, networkID int64, cha
|
|||
}
|
||||
|
||||
func (r *IrcRepo) StoreChannel(ctx context.Context, networkID int64, channel *domain.IrcChannel) error {
|
||||
pass := toNullString(channel.Password)
|
||||
|
||||
if channel.ID != 0 {
|
||||
// update record
|
||||
channelQueryBuilder := r.db.squirrel.
|
||||
|
@ -476,7 +455,7 @@ func (r *IrcRepo) StoreChannel(ctx context.Context, networkID int64, channel *do
|
|||
Set("enabled", channel.Enabled).
|
||||
Set("detached", channel.Detached).
|
||||
Set("name", channel.Name).
|
||||
Set("password", pass).
|
||||
Set("password", toNullString(channel.Password)).
|
||||
Where(sq.Eq{"id": channel.ID})
|
||||
|
||||
query, args, err := channelQueryBuilder.ToSql()
|
||||
|
@ -501,21 +480,17 @@ func (r *IrcRepo) StoreChannel(ctx context.Context, networkID int64, channel *do
|
|||
channel.Enabled,
|
||||
true,
|
||||
channel.Name,
|
||||
pass,
|
||||
toNullString(channel.Password),
|
||||
networkID,
|
||||
).
|
||||
Suffix("RETURNING id").
|
||||
RunWith(r.db.handler)
|
||||
|
||||
// returning
|
||||
var retID int64
|
||||
|
||||
if err := queryBuilder.QueryRowContext(ctx).Scan(&retID); err != nil {
|
||||
if err := queryBuilder.QueryRowContext(ctx).Scan(&channel.ID); err != nil {
|
||||
return errors.Wrap(err, "error executing query")
|
||||
}
|
||||
|
||||
channel.ID = retID
|
||||
|
||||
//channelQuery, channelArgs, err := channelQueryBuilder.ToSql()
|
||||
//if err != nil {
|
||||
// r.log.Error().Stack().Err(err).Msg("irc.storeChannel: error building query")
|
||||
|
@ -536,15 +511,13 @@ func (r *IrcRepo) StoreChannel(ctx context.Context, networkID int64, channel *do
|
|||
}
|
||||
|
||||
func (r *IrcRepo) UpdateChannel(channel *domain.IrcChannel) error {
|
||||
pass := toNullString(channel.Password)
|
||||
|
||||
// update record
|
||||
channelQueryBuilder := r.db.squirrel.
|
||||
Update("irc_channel").
|
||||
Set("enabled", channel.Enabled).
|
||||
Set("detached", channel.Detached).
|
||||
Set("name", channel.Name).
|
||||
Set("password", pass).
|
||||
Set("password", toNullString(channel.Password)).
|
||||
Where(sq.Eq{"id": channel.ID})
|
||||
|
||||
query, args, err := channelQueryBuilder.ToSql()
|
||||
|
@ -561,7 +534,6 @@ func (r *IrcRepo) UpdateChannel(channel *domain.IrcChannel) error {
|
|||
}
|
||||
|
||||
func (r *IrcRepo) UpdateInviteCommand(networkID int64, invite string) error {
|
||||
|
||||
// update record
|
||||
channelQueryBuilder := r.db.squirrel.
|
||||
Update("irc_network").
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue