feat: add support for HTTP and SOCKS5 proxy for telegram client

This commit is contained in:
divyam234 2024-05-15 17:24:44 +05:30
parent bf56ddd218
commit c47eef0d70
8 changed files with 66 additions and 6 deletions

View file

@ -190,6 +190,7 @@ teldrive run --help
| --tg-bg-bots-limit | Start at most this no of bots in the background to prevent connection recreation on every request.Increase this if you are streaming or downloading large no of files simultaneously. | No | 5
| --tg-uploads-threads | Concurrent Uploads threads for uploading file | No | 16 |
| --tg-uploads-retention | Uploads retention duration.Duration to keep failed uploaded chunks in db for resuming uploads. | No | 7d |
| --tg-proxy | Socks5 or HTTP proxy for telegram client. | No | "" |
**You Can also set config values through env varibles.**
- For example ```tg-session-file``` will become ```TELDRIVE_TG_SESSION_FILE``` same for all possible flags.

View file

@ -80,6 +80,7 @@ func NewRun() *cobra.Command {
runCmd.Flags().StringVar(&config.TG.LangCode, "tg-lang-code", "en", "Language code")
runCmd.Flags().StringVar(&config.TG.SystemLangCode, "tg-system-lang-code", "en-US", "System language code")
runCmd.Flags().StringVar(&config.TG.LangPack, "tg-lang-pack", "webk", "Language pack")
runCmd.Flags().StringVar(&config.TG.Proxy, "tg-proxy", "", "HTTP OR SOCKS5 proxy URL")
runCmd.Flags().IntVar(&config.TG.BgBotsLimit, "tg-bg-bots-limit", 5, "Background bots limit")
runCmd.Flags().BoolVar(&config.TG.DisableStreamBots, "tg-disable-stream-bots", false, "Disable stream bots")
runCmd.Flags().StringVar(&config.TG.Uploads.EncryptionKey, "tg-uploads-encryption-key", "", "Uploads encryption key")

1
go.mod
View file

@ -39,6 +39,7 @@ require (
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/iyear/connectproxy v0.1.1 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/mfridman/interpolate v0.0.2 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect

2
go.sum
View file

@ -91,6 +91,8 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/iyear/connectproxy v0.1.1 h1:JZOF/62vvwRGBWcgSyWRb0BpKD4FSs0++B5/y5pNE4c=
github.com/iyear/connectproxy v0.1.1/go.mod h1:yD4zOmSMQCmwHIT4fk8mg4k2M15z8VoMSoeY6NNJdsA=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=

View file

@ -32,6 +32,7 @@ type TGConfig struct {
SessionFile string
BgBotsLimit int
DisableStreamBots bool
Proxy string
Uploads struct {
EncryptionKey string
Threads int

View file

@ -9,11 +9,15 @@ import (
"github.com/divyam234/teldrive/internal/kv"
"github.com/divyam234/teldrive/internal/recovery"
"github.com/divyam234/teldrive/internal/retry"
"github.com/divyam234/teldrive/internal/utils"
"github.com/gotd/contrib/middleware/floodwait"
"github.com/gotd/contrib/middleware/ratelimit"
tdclock "github.com/gotd/td/clock"
"github.com/gotd/td/session"
"github.com/gotd/td/telegram"
"github.com/gotd/td/telegram/dcs"
"github.com/pkg/errors"
"golang.org/x/net/proxy"
"golang.org/x/time/rate"
)
@ -26,9 +30,21 @@ func defaultMiddlewares(ctx context.Context) ([]telegram.Middleware, error) {
}, nil
}
func New(ctx context.Context, config *config.TGConfig, handler telegram.UpdateHandler, storage session.Storage, middlewares ...telegram.Middleware) *telegram.Client {
func New(ctx context.Context, config *config.TGConfig, handler telegram.UpdateHandler, storage session.Storage, middlewares ...telegram.Middleware) (*telegram.Client, error) {
var dialer dcs.DialFunc = proxy.Direct.DialContext
if config.Proxy != "" {
d, err := utils.Proxy.GetDial(config.Proxy)
if err != nil {
return nil, errors.Wrap(err, "get dialer")
}
dialer = d.DialContext
}
opts := telegram.Options{
Resolver: dcs.Plain(dcs.PlainOptions{
Dial: dialer,
}),
Device: telegram.DeviceConfig{
DeviceModel: config.DeviceModel,
SystemVersion: config.SystemVersion,
@ -45,10 +61,10 @@ func New(ctx context.Context, config *config.TGConfig, handler telegram.UpdateHa
UpdateHandler: handler,
}
return telegram.NewClient(config.AppId, config.AppHash, opts)
return telegram.NewClient(config.AppId, config.AppHash, opts), nil
}
func NoAuthClient(ctx context.Context, config *config.TGConfig, handler telegram.UpdateHandler, storage session.Storage) *telegram.Client {
func NoAuthClient(ctx context.Context, config *config.TGConfig, handler telegram.UpdateHandler, storage session.Storage) (*telegram.Client, error) {
middlewares, _ := defaultMiddlewares(ctx)
middlewares = append(middlewares, ratelimit.New(rate.Every(time.Millisecond*100), 5))
return New(ctx, config, handler, storage, middlewares...)
@ -72,7 +88,7 @@ func AuthClient(ctx context.Context, config *config.TGConfig, sessionStr string)
middlewares, _ := defaultMiddlewares(ctx)
middlewares = append(middlewares, ratelimit.New(rate.Every(time.Millisecond*
time.Duration(config.Rate)), config.RateBurst))
return New(ctx, config, nil, storage, middlewares...), nil
return New(ctx, config, nil, storage, middlewares...)
}
func BotClient(ctx context.Context, KV kv.KV, config *config.TGConfig, token string) (*telegram.Client, error) {
@ -83,7 +99,7 @@ func BotClient(ctx context.Context, KV kv.KV, config *config.TGConfig, token str
time.Duration(config.Rate)), config.RateBurst))
}
return New(ctx, config, nil, storage, middlewares...), nil
return New(ctx, config, nil, storage, middlewares...)
}
func Backoff(_clock tdclock.Clock) backoff.BackOff {
b := backoff.NewExponentialBackOff()

38
internal/utils/proxy.go Normal file
View file

@ -0,0 +1,38 @@
// Taken from /iyear/tdl
package utils
import (
"net/url"
"github.com/go-faster/errors"
"github.com/iyear/connectproxy"
"golang.org/x/net/proxy"
)
type _proxy struct{}
var Proxy = _proxy{}
func init() {
connectproxy.Register(&connectproxy.Config{
InsecureSkipVerify: true,
})
}
func (p _proxy) GetDial(_url string) (proxy.ContextDialer, error) {
u, err := url.Parse(_url)
if err != nil {
return nil, errors.Wrap(err, "parse proxy url")
}
dialer, err := proxy.FromURL(u, proxy.Direct)
if err != nil {
return nil, errors.Wrap(err, "proxy from url")
}
if d, ok := dialer.(proxy.ContextDialer); ok {
return d, nil
}
return nil, errors.New("proxy dialer is not ContextDialer")
}

View file

@ -184,7 +184,7 @@ func (as *AuthService) HandleMultipleLogin(c *gin.Context) {
dispatcher := tg.NewUpdateDispatcher()
loggedIn := qrlogin.OnLoginToken(dispatcher)
sessionStorage := &session.StorageMemory{}
tgClient := tgc.NoAuthClient(c, &as.cnf.TG, dispatcher, sessionStorage)
tgClient, _ := tgc.NoAuthClient(c, &as.cnf.TG, dispatcher, sessionStorage)
err = tgClient.Run(c, func(ctx context.Context) error {
for {