From ff0d44688f03d320995bace3219000d7e8fa9465 Mon Sep 17 00:00:00 2001 From: iyear Date: Mon, 18 Dec 2023 10:48:10 +0800 Subject: [PATCH] feat(login): add qr login --- app/login/qr.go | 103 ++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 + 3 files changed, 106 insertions(+) create mode 100644 app/login/qr.go diff --git a/app/login/qr.go b/app/login/qr.go new file mode 100644 index 000000000..004d93c4a --- /dev/null +++ b/app/login/qr.go @@ -0,0 +1,103 @@ +package login + +import ( + "context" + "fmt" + "strings" + + "github.com/AlecAivazis/survey/v2" + "github.com/fatih/color" + "github.com/go-faster/errors" + "github.com/gotd/td/telegram/auth/qrlogin" + "github.com/gotd/td/tg" + "github.com/gotd/td/tgerr" + "github.com/jedib0t/go-pretty/v6/text" + "github.com/skip2/go-qrcode" + "github.com/spf13/viper" + + "github.com/iyear/tdl/pkg/consts" + "github.com/iyear/tdl/pkg/key" + "github.com/iyear/tdl/pkg/kv" + "github.com/iyear/tdl/pkg/tclient" +) + +func QR(ctx context.Context) error { + kvd, err := kv.From(ctx).Open(viper.GetString(consts.FlagNamespace)) + if err != nil { + return errors.Wrap(err, "open kv") + } + + if err = kvd.Set(key.App(), []byte(tclient.AppDesktop)); err != nil { + return errors.Wrap(err, "set app") + } + + d := tg.NewUpdateDispatcher() + + c, err := tclient.New(ctx, tclient.Options{ + KV: kvd, + Proxy: viper.GetString(consts.FlagProxy), + NTP: viper.GetString(consts.FlagNTP), + ReconnectTimeout: viper.GetDuration(consts.FlagReconnectTimeout), + Test: viper.GetString(consts.FlagTest) != "", + UpdateHandler: d, + }, true) + if err != nil { + return errors.Wrap(err, "create client") + } + + return c.Run(ctx, func(ctx context.Context) error { + color.Blue("Scan QR code with your Telegram app...") + + var lines int + _, err = c.QR().Auth(ctx, qrlogin.OnLoginToken(d), func(ctx context.Context, token qrlogin.Token) error { + qr, err := qrcode.New(token.URL(), qrcode.Medium) + if err != nil { + return errors.Wrap(err, "create qr") + } + code := qr.ToSmallString(false) + lines = strings.Count(code, "\n") + + fmt.Print(code) + fmt.Print(strings.Repeat(text.CursorUp.Sprint(), lines)) + return nil + }) + + // clear qrcode + out := &strings.Builder{} + for i := 0; i < lines; i++ { + out.WriteString(text.EraseLine.Sprint()) + out.WriteString(text.CursorDown.Sprint()) + } + out.WriteString(text.CursorUp.Sprintn(lines)) + fmt.Print(out.String()) + + if err != nil { + // https://core.telegram.org/api/auth#2fa + if !tgerr.Is(err, "SESSION_PASSWORD_NEEDED") { + return errors.Wrap(err, "qr auth") + } + + pwd := "" + prompt := &survey.Password{ + Message: "Enter 2FA Password:", + } + + if err = survey.AskOne(prompt, &pwd, survey.WithValidator(survey.Required)); err != nil { + return errors.Wrap(err, "2fa password") + } + + if _, err = c.Auth().Password(ctx, pwd); err != nil { + return errors.Wrap(err, "2fa auth") + } + } + + user, err := c.Self(ctx) + if err != nil { + return errors.Wrap(err, "get self") + } + + fmt.Print(text.EraseLine.Sprint()) + color.Green("Login successfully! ID: %d, Username: %s", user.ID, user.Username) + return nil + }) +} diff --git a/go.mod b/go.mod index 1879e75fc..f973f578c 100644 --- a/go.mod +++ b/go.mod @@ -75,6 +75,7 @@ require ( github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect diff --git a/go.sum b/go.sum index 0fa4a7209..30d9dc76e 100644 --- a/go.sum +++ b/go.sum @@ -141,6 +141,8 @@ github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFt github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=