refactor(prj): separate tclient core code to core module

This commit is contained in:
iyear 2024-06-17 00:55:37 +08:00
parent 75b86da710
commit d06ca3a065
9 changed files with 150 additions and 98 deletions

View File

@ -17,12 +17,12 @@ import (
"github.com/iyear/tdl/core/dcpool"
"github.com/iyear/tdl/core/downloader"
"github.com/iyear/tdl/core/logctx"
"github.com/iyear/tdl/core/tclient"
"github.com/iyear/tdl/pkg/consts"
"github.com/iyear/tdl/pkg/key"
"github.com/iyear/tdl/pkg/kv"
"github.com/iyear/tdl/pkg/prog"
"github.com/iyear/tdl/pkg/storage"
"github.com/iyear/tdl/pkg/tclient"
"github.com/iyear/tdl/pkg/tmessage"
"github.com/iyear/tdl/pkg/utils"
)

View File

@ -19,12 +19,12 @@ import (
"github.com/iyear/tdl/app/internal/tctx"
"github.com/iyear/tdl/core/dcpool"
"github.com/iyear/tdl/core/forwarder"
"github.com/iyear/tdl/core/tclient"
"github.com/iyear/tdl/core/util/tutil"
"github.com/iyear/tdl/pkg/consts"
"github.com/iyear/tdl/pkg/kv"
"github.com/iyear/tdl/pkg/prog"
"github.com/iyear/tdl/pkg/storage"
"github.com/iyear/tdl/pkg/tclient"
"github.com/iyear/tdl/pkg/texpr"
"github.com/iyear/tdl/pkg/tmessage"
)

View File

@ -12,13 +12,13 @@ import (
"go.uber.org/multierr"
"github.com/iyear/tdl/core/dcpool"
"github.com/iyear/tdl/core/tclient"
"github.com/iyear/tdl/core/uploader"
"github.com/iyear/tdl/core/util/tutil"
"github.com/iyear/tdl/pkg/consts"
"github.com/iyear/tdl/pkg/kv"
"github.com/iyear/tdl/pkg/prog"
"github.com/iyear/tdl/pkg/storage"
"github.com/iyear/tdl/pkg/tclient"
"github.com/iyear/tdl/pkg/utils"
)

View File

@ -15,6 +15,7 @@ import (
"go.uber.org/zap"
"github.com/iyear/tdl/core/logctx"
tclientcore "github.com/iyear/tdl/core/tclient"
"github.com/iyear/tdl/core/util/fsutil"
"github.com/iyear/tdl/core/util/logutil"
"github.com/iyear/tdl/pkg/consts"
@ -158,7 +159,7 @@ func tRun(ctx context.Context, f func(ctx context.Context, c *telegram.Client, k
return errors.Wrap(err, "create client")
}
return tclient.Run(ctx, client, func(ctx context.Context) error {
return tclientcore.RunWithAuth(ctx, client, func(ctx context.Context) error {
return f(ctx, client, kvd)
})
}

View File

@ -6,6 +6,7 @@ require (
github.com/cenkalti/backoff/v4 v4.3.0
github.com/gabriel-vasile/mimetype v1.4.4
github.com/go-faster/errors v0.7.1
github.com/gotd/contrib v0.20.0
github.com/gotd/td v0.102.0
github.com/iyear/connectproxy v0.1.1
github.com/yapingcat/gomedia v0.0.0-20240601043430-920523f8e5c7
@ -14,10 +15,12 @@ require (
go.uber.org/zap v1.27.0
golang.org/x/net v0.25.0
golang.org/x/sync v0.7.0
golang.org/x/time v0.5.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
)
require (
github.com/beevik/ntp v1.3.1 // indirect
github.com/go-faster/jx v1.1.0 // indirect
github.com/go-faster/xor v1.0.0 // indirect
github.com/gotd/ige v0.2.2 // indirect

View File

@ -1,3 +1,5 @@
github.com/beevik/ntp v1.3.1 h1:Y/srlT8L1yQr58kyPWFPZIxRL8ttx2SRIpVYJqZIlAM=
github.com/beevik/ntp v1.3.1/go.mod h1:fT6PylBq86Tsq23ZMEe47b7QQrZfYBFPnpzt0a9kJxw=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@ -13,6 +15,8 @@ github.com/go-faster/xor v1.0.0 h1:2o8vTOgErSGHP3/7XwA5ib1FTtUsNtwCoLLBjl31X38=
github.com/go-faster/xor v1.0.0/go.mod h1:x5CaDY9UKErKzqfRfFZdfu+OSTfoZny3w5Ak7UxcipQ=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gotd/contrib v0.20.0 h1:1Wc4+HMQiIKYQuGHVwVksIx152HFTP6B5n88dDe0ZYw=
github.com/gotd/contrib v0.20.0/go.mod h1:P6o8W4niqhDPHLA0U+SA/L7l3BQHYLULpeHfRSePn9o=
github.com/gotd/ige v0.2.2 h1:XQ9dJZwBfDnOGSTxKXBGP4gMud3Qku2ekScRjDWWfEk=
github.com/gotd/ige v0.2.2/go.mod h1:tuCRb+Y5Y3eNTo3ypIfNpQ4MFjrnONiL2jN2AKZXmb0=
github.com/gotd/neo v0.1.5 h1:oj0iQfMbGClP8xI59x7fE/uHoTJD7NZH9oV1WNuPukQ=
@ -45,8 +49,8 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20230116083435-1de6713980de h1:DBWn//IJw30uYCgERoxCg84hWtA97F4wMiKOIh00Uf0=
golang.org/x/exp v0.0.0-20230116083435-1de6713980de/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -54,6 +58,8 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

122
core/tclient/tclient.go Normal file
View File

@ -0,0 +1,122 @@
package tclient
import (
"context"
"fmt"
"time"
"github.com/cenkalti/backoff/v4"
"github.com/go-faster/errors"
"github.com/gotd/contrib/clock"
"github.com/gotd/contrib/middleware/floodwait"
"github.com/gotd/contrib/middleware/ratelimit"
tdclock "github.com/gotd/td/clock"
"github.com/gotd/td/telegram"
"github.com/gotd/td/telegram/dcs"
"golang.org/x/net/proxy"
"golang.org/x/time/rate"
"github.com/iyear/tdl/core/logctx"
"github.com/iyear/tdl/core/middlewares/recovery"
"github.com/iyear/tdl/core/middlewares/retry"
"github.com/iyear/tdl/core/util/netutil"
"github.com/iyear/tdl/core/util/tutil"
)
type Options struct {
AppID int
AppHash string
Session telegram.SessionStorage
Middlewares []telegram.Middleware
Proxy string
NTP string
ReconnectTimeout time.Duration
Test bool
UpdateHandler telegram.UpdateHandler
}
// New creates new telegram client with given options.
// Default middlewares(retry, recovery, flood wait) always added.
func New(ctx context.Context, o Options) (*telegram.Client, error) {
// process clock
tclock := tdclock.System
if ntp := o.NTP; ntp != "" {
var err error
tclock, err = clock.NewNTP(ntp)
if err != nil {
return nil, errors.Wrap(err, "create network clock")
}
}
// process proxy
var dialer dcs.DialFunc = proxy.Direct.DialContext
if p := o.Proxy; p != "" {
d, err := netutil.NewProxy(p)
if err != nil {
return nil, errors.Wrap(err, "get dialer")
}
dialer = d.DialContext
}
appID, appHash := o.AppID, o.AppHash
opts := telegram.Options{
Resolver: dcs.Plain(dcs.PlainOptions{
Dial: dialer,
}),
ReconnectionBackoff: func() backoff.BackOff {
return newBackoff(o.ReconnectTimeout)
},
UpdateHandler: o.UpdateHandler,
Device: tutil.Device,
SessionStorage: o.Session,
RetryInterval: 5 * time.Second,
MaxRetries: -1, // infinite retries
DialTimeout: 10 * time.Second,
Middlewares: append(NewDefaultMiddlewares(ctx, o.ReconnectTimeout), o.Middlewares...),
Clock: tclock,
Logger: logctx.From(ctx).Named("td"),
}
// test mode, hook options
if o.Test {
appID, appHash = telegram.TestAppID, telegram.TestAppHash
opts.DC = 2
opts.DCList = dcs.Test()
// add rate limit to avoid frequent flood wait
opts.Middlewares = append(opts.Middlewares, ratelimit.New(rate.Every(100*time.Millisecond), 5))
}
return telegram.NewClient(appID, appHash, opts), nil
}
func NewDefaultMiddlewares(ctx context.Context, timeout time.Duration) []telegram.Middleware {
return []telegram.Middleware{
recovery.New(ctx, newBackoff(timeout)),
retry.New(5),
floodwait.NewSimpleWaiter(),
}
}
func newBackoff(timeout time.Duration) backoff.BackOff {
b := backoff.NewExponentialBackOff()
b.Multiplier = 1.1
b.MaxElapsedTime = timeout
b.MaxInterval = 10 * time.Second
return b
}
func RunWithAuth(ctx context.Context, client *telegram.Client, f func(ctx context.Context) error) error {
return client.Run(ctx, func(ctx context.Context) error {
status, err := client.Auth().Status(ctx)
if err != nil {
return err
}
if !status.Authorized {
return fmt.Errorf("not authorized. please login first")
}
return f(ctx)
})
}

1
go.sum
View File

@ -155,6 +155,7 @@ github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=

View File

@ -5,22 +5,9 @@ import (
"fmt"
"time"
"github.com/cenkalti/backoff/v4"
"github.com/go-faster/errors"
"github.com/gotd/contrib/middleware/floodwait"
"github.com/gotd/contrib/middleware/ratelimit"
tdclock "github.com/gotd/td/clock"
"github.com/gotd/td/telegram"
"github.com/gotd/td/telegram/dcs"
"golang.org/x/net/proxy"
"golang.org/x/time/rate"
"github.com/iyear/tdl/core/logctx"
"github.com/iyear/tdl/core/middlewares/recovery"
"github.com/iyear/tdl/core/middlewares/retry"
"github.com/iyear/tdl/core/util/netutil"
"github.com/iyear/tdl/core/util/tutil"
"github.com/iyear/tdl/pkg/clock"
"github.com/iyear/tdl/core/tclient"
"github.com/iyear/tdl/pkg/key"
"github.com/iyear/tdl/pkg/kv"
"github.com/iyear/tdl/pkg/storage"
@ -36,15 +23,6 @@ type Options struct {
}
func New(ctx context.Context, o Options, login bool, middlewares ...telegram.Middleware) (*telegram.Client, error) {
_clock := tdclock.System
if ntp := o.NTP; ntp != "" {
var err error
_clock, err = clock.New()
if err != nil {
return nil, errors.Wrap(err, "create network clock")
}
}
mode, err := o.KV.Get(key.App())
if err != nil {
mode = []byte(AppBuiltin)
@ -53,75 +31,16 @@ func New(ctx context.Context, o Options, login bool, middlewares ...telegram.Mid
if !ok {
return nil, fmt.Errorf("can't find app: %s, please try re-login", mode)
}
appId, appHash := app.AppID, app.AppHash
// process proxy
var dialer dcs.DialFunc = proxy.Direct.DialContext
if p := o.Proxy; p != "" {
d, err := netutil.NewProxy(p)
if err != nil {
return nil, errors.Wrap(err, "get dialer")
}
dialer = d.DialContext
}
opts := telegram.Options{
Resolver: dcs.Plain(dcs.PlainOptions{
Dial: dialer,
}),
ReconnectionBackoff: func() backoff.BackOff {
return newBackoff(o.ReconnectTimeout)
},
UpdateHandler: o.UpdateHandler,
Device: tutil.Device,
SessionStorage: storage.NewSession(o.KV, login),
RetryInterval: 5 * time.Second,
MaxRetries: -1, // infinite retries
DialTimeout: 10 * time.Second,
Middlewares: append(NewDefaultMiddlewares(ctx, o.ReconnectTimeout), middlewares...),
Clock: _clock,
Logger: logctx.From(ctx).Named("td"),
}
// test mode, hook options
if o.Test {
appId, appHash = telegram.TestAppID, telegram.TestAppHash
opts.DC = 2
opts.DCList = dcs.Test()
// add rate limit to avoid frequent flood wait
opts.Middlewares = append(opts.Middlewares, ratelimit.New(rate.Every(100*time.Millisecond), 5))
}
return telegram.NewClient(appId, appHash, opts), nil
}
func NewDefaultMiddlewares(ctx context.Context, timeout time.Duration) []telegram.Middleware {
return []telegram.Middleware{
recovery.New(ctx, newBackoff(timeout)),
retry.New(5),
floodwait.NewSimpleWaiter(),
}
}
func newBackoff(timeout time.Duration) backoff.BackOff {
b := backoff.NewExponentialBackOff()
b.Multiplier = 1.1
b.MaxElapsedTime = timeout
b.MaxInterval = 10 * time.Second
return b
}
func Run(ctx context.Context, client *telegram.Client, f func(ctx context.Context) error) error {
return client.Run(ctx, func(ctx context.Context) error {
status, err := client.Auth().Status(ctx)
if err != nil {
return err
}
if !status.Authorized {
return fmt.Errorf("not authorized. please login first")
}
return f(ctx)
return tclient.New(ctx, tclient.Options{
AppID: app.AppID,
AppHash: app.AppHash,
Session: storage.NewSession(o.KV, login),
Middlewares: middlewares,
Proxy: o.Proxy,
NTP: o.NTP,
ReconnectTimeout: o.ReconnectTimeout,
Test: o.Test,
UpdateHandler: o.UpdateHandler,
})
}