mirror of
https://github.com/iyear/tdl
synced 2025-01-08 11:57:55 +08:00
feat(login): select login mode with type flag
This commit is contained in:
parent
ff0d44688f
commit
8127fb7a7b
@ -1,69 +0,0 @@
|
||||
package login
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/fatih/color"
|
||||
"github.com/gotd/td/telegram/auth"
|
||||
"github.com/gotd/td/tg"
|
||||
)
|
||||
|
||||
// noSignUp can be embedded to prevent signing up.
|
||||
type noSignUp struct{}
|
||||
|
||||
func (c noSignUp) SignUp(_ context.Context) (auth.UserInfo, error) {
|
||||
return auth.UserInfo{}, errors.New("searchx don't support sign up Telegram account")
|
||||
}
|
||||
|
||||
func (c noSignUp) AcceptTermsOfService(_ context.Context, tos tg.HelpTermsOfService) error {
|
||||
return &auth.SignUpRequired{TermsOfService: tos}
|
||||
}
|
||||
|
||||
// termAuth implements authentication via terminal.
|
||||
type termAuth struct {
|
||||
noSignUp
|
||||
}
|
||||
|
||||
func (a termAuth) Phone(_ context.Context) (string, error) {
|
||||
phone := ""
|
||||
prompt := &survey.Input{
|
||||
Message: "Enter your phone number:",
|
||||
Default: "+86 12345678900",
|
||||
}
|
||||
|
||||
if err := survey.AskOne(prompt, &phone, survey.WithValidator(survey.Required)); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
color.Blue("Sending Code...")
|
||||
return strings.TrimSpace(phone), nil
|
||||
}
|
||||
|
||||
func (a termAuth) Password(_ context.Context) (string, error) {
|
||||
pwd := ""
|
||||
prompt := &survey.Input{
|
||||
Message: "Enter 2FA Password:",
|
||||
}
|
||||
|
||||
if err := survey.AskOne(prompt, &pwd, survey.WithValidator(survey.Required)); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strings.TrimSpace(pwd), nil
|
||||
}
|
||||
|
||||
func (a termAuth) Code(_ context.Context, _ *tg.AuthSentCode) (string, error) {
|
||||
code := ""
|
||||
prompt := &survey.Input{
|
||||
Message: "Enter Code:",
|
||||
}
|
||||
|
||||
if err := survey.AskOne(prompt, &code, survey.WithValidator(survey.Required)); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strings.TrimSpace(code), nil
|
||||
}
|
@ -3,13 +3,16 @@ package login
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
"github.com/fatih/color"
|
||||
"github.com/go-faster/errors"
|
||||
"github.com/gotd/td/telegram"
|
||||
"github.com/gotd/td/telegram/auth"
|
||||
"github.com/gotd/td/tg"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/iyear/tdl/pkg/consts"
|
||||
@ -71,8 +74,65 @@ func Code(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
color.Blue("Login successfully! ID: %d, Username: %s", user.ID, user.Username)
|
||||
color.Green("Login successfully! ID: %d, Username: %s", user.ID, user.Username)
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// noSignUp can be embedded to prevent signing up.
|
||||
type noSignUp struct{}
|
||||
|
||||
func (c noSignUp) SignUp(_ context.Context) (auth.UserInfo, error) {
|
||||
return auth.UserInfo{}, errors.New("don't support sign up Telegram account")
|
||||
}
|
||||
|
||||
func (c noSignUp) AcceptTermsOfService(_ context.Context, tos tg.HelpTermsOfService) error {
|
||||
return &auth.SignUpRequired{TermsOfService: tos}
|
||||
}
|
||||
|
||||
// termAuth implements authentication via terminal.
|
||||
type termAuth struct {
|
||||
noSignUp
|
||||
}
|
||||
|
||||
func (a termAuth) Phone(_ context.Context) (string, error) {
|
||||
phone := ""
|
||||
prompt := &survey.Input{
|
||||
Message: "Enter your phone number:",
|
||||
Default: "+86 12345678900",
|
||||
}
|
||||
|
||||
if err := survey.AskOne(prompt, &phone, survey.WithValidator(survey.Required)); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
color.Blue("Sending Code...")
|
||||
return strings.TrimSpace(phone), nil
|
||||
}
|
||||
|
||||
func (a termAuth) Password(_ context.Context) (string, error) {
|
||||
pwd := ""
|
||||
prompt := &survey.Password{
|
||||
Message: "Enter 2FA Password:",
|
||||
}
|
||||
|
||||
if err := survey.AskOne(prompt, &pwd, survey.WithValidator(survey.Required)); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strings.TrimSpace(pwd), nil
|
||||
}
|
||||
|
||||
func (a termAuth) Code(_ context.Context, _ *tg.AuthSentCode) (string, error) {
|
||||
code := ""
|
||||
prompt := &survey.Input{
|
||||
Message: "Enter Code:",
|
||||
}
|
||||
|
||||
if err := survey.AskOne(prompt, &code, survey.WithValidator(survey.Required)); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strings.TrimSpace(code), nil
|
||||
}
|
||||
|
@ -26,12 +26,7 @@ import (
|
||||
|
||||
const tdata = "tdata"
|
||||
|
||||
type Options struct {
|
||||
Desktop string
|
||||
Passcode string
|
||||
}
|
||||
|
||||
func Desktop(ctx context.Context, opts *Options) error {
|
||||
func Desktop(ctx context.Context, opts Options) error {
|
||||
ns := viper.GetString(consts.FlagNamespace)
|
||||
|
||||
kvd, err := kv.From(ctx).Open(ns)
|
||||
|
32
app/login/login.go
Normal file
32
app/login/login.go
Normal file
@ -0,0 +1,32 @@
|
||||
package login
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-faster/errors"
|
||||
)
|
||||
|
||||
//go:generate go-enum --values --names --flag --nocase
|
||||
|
||||
// Type
|
||||
// ENUM(desktop, code, qr)
|
||||
type Type int
|
||||
|
||||
type Options struct {
|
||||
Type Type
|
||||
Desktop string
|
||||
Passcode string
|
||||
}
|
||||
|
||||
func Run(ctx context.Context, opts Options) error {
|
||||
switch opts.Type {
|
||||
case TypeDesktop:
|
||||
return Desktop(ctx, opts)
|
||||
case TypeCode:
|
||||
return Code(ctx)
|
||||
case TypeQr:
|
||||
return QR(ctx)
|
||||
default:
|
||||
return errors.Errorf("unsupported login type: %s", opts.Type)
|
||||
}
|
||||
}
|
106
app/login/login_enum.go
Normal file
106
app/login/login_enum.go
Normal file
@ -0,0 +1,106 @@
|
||||
// Code generated by go-enum DO NOT EDIT.
|
||||
// Version: 0.5.8
|
||||
// Revision: 3d844c8ecc59661ed7aa17bfd65727bc06a60ad8
|
||||
// Build Date: 2023-09-18T14:55:21Z
|
||||
// Built By: goreleaser
|
||||
|
||||
package login
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// TypeDesktop is a Type of type Desktop.
|
||||
TypeDesktop Type = iota
|
||||
// TypeCode is a Type of type Code.
|
||||
TypeCode
|
||||
// TypeQr is a Type of type Qr.
|
||||
TypeQr
|
||||
)
|
||||
|
||||
var ErrInvalidType = fmt.Errorf("not a valid Type, try [%s]", strings.Join(_TypeNames, ", "))
|
||||
|
||||
const _TypeName = "desktopcodeqr"
|
||||
|
||||
var _TypeNames = []string{
|
||||
_TypeName[0:7],
|
||||
_TypeName[7:11],
|
||||
_TypeName[11:13],
|
||||
}
|
||||
|
||||
// TypeNames returns a list of possible string values of Type.
|
||||
func TypeNames() []string {
|
||||
tmp := make([]string, len(_TypeNames))
|
||||
copy(tmp, _TypeNames)
|
||||
return tmp
|
||||
}
|
||||
|
||||
// TypeValues returns a list of the values for Type
|
||||
func TypeValues() []Type {
|
||||
return []Type{
|
||||
TypeDesktop,
|
||||
TypeCode,
|
||||
TypeQr,
|
||||
}
|
||||
}
|
||||
|
||||
var _TypeMap = map[Type]string{
|
||||
TypeDesktop: _TypeName[0:7],
|
||||
TypeCode: _TypeName[7:11],
|
||||
TypeQr: _TypeName[11:13],
|
||||
}
|
||||
|
||||
// String implements the Stringer interface.
|
||||
func (x Type) String() string {
|
||||
if str, ok := _TypeMap[x]; ok {
|
||||
return str
|
||||
}
|
||||
return fmt.Sprintf("Type(%d)", x)
|
||||
}
|
||||
|
||||
// IsValid provides a quick way to determine if the typed value is
|
||||
// part of the allowed enumerated values
|
||||
func (x Type) IsValid() bool {
|
||||
_, ok := _TypeMap[x]
|
||||
return ok
|
||||
}
|
||||
|
||||
var _TypeValue = map[string]Type{
|
||||
_TypeName[0:7]: TypeDesktop,
|
||||
strings.ToLower(_TypeName[0:7]): TypeDesktop,
|
||||
_TypeName[7:11]: TypeCode,
|
||||
strings.ToLower(_TypeName[7:11]): TypeCode,
|
||||
_TypeName[11:13]: TypeQr,
|
||||
strings.ToLower(_TypeName[11:13]): TypeQr,
|
||||
}
|
||||
|
||||
// ParseType attempts to convert a string to a Type.
|
||||
func ParseType(name string) (Type, error) {
|
||||
if x, ok := _TypeValue[name]; ok {
|
||||
return x, nil
|
||||
}
|
||||
// Case insensitive parse, do a separate lookup to prevent unnecessary cost of lowercasing a string if we don't need to.
|
||||
if x, ok := _TypeValue[strings.ToLower(name)]; ok {
|
||||
return x, nil
|
||||
}
|
||||
return Type(0), fmt.Errorf("%s is %w", name, ErrInvalidType)
|
||||
}
|
||||
|
||||
// Set implements the Golang flag.Value interface func.
|
||||
func (x *Type) Set(val string) error {
|
||||
v, err := ParseType(val)
|
||||
*x = v
|
||||
return err
|
||||
}
|
||||
|
||||
// Get implements the Golang flag.Getter interface func.
|
||||
func (x *Type) Get() interface{} {
|
||||
return *x
|
||||
}
|
||||
|
||||
// Type implements the github.com/spf13/pFlag Value interface.
|
||||
func (x *Type) Type() string {
|
||||
return "Type"
|
||||
}
|
14
cmd/login.go
14
cmd/login.go
@ -1,6 +1,9 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@ -20,24 +23,27 @@ func NewLogin() *cobra.Command {
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
color.Yellow("WARN: If data exists in the namespace, data will be overwritten")
|
||||
|
||||
// Legacy flag
|
||||
if code {
|
||||
return login.Code(logger.Named(cmd.Context(), "login"))
|
||||
}
|
||||
|
||||
return login.Desktop(cmd.Context(), &opts)
|
||||
return login.Run(logger.Named(cmd.Context(), "login"), opts)
|
||||
},
|
||||
}
|
||||
|
||||
const (
|
||||
desktop = "desktop"
|
||||
)
|
||||
const desktop = "desktop"
|
||||
|
||||
cmd.Flags().VarP(&opts.Type, "type", "T", fmt.Sprintf("login mode: [%s]", strings.Join(login.TypeNames(), ", ")))
|
||||
cmd.Flags().StringVarP(&opts.Desktop, desktop, "d", "", "official desktop client path, and automatically find possible paths if empty")
|
||||
cmd.Flags().StringVarP(&opts.Passcode, "passcode", "p", "", "passcode for desktop client, keep empty if no passcode")
|
||||
|
||||
// Deprecated
|
||||
cmd.Flags().BoolVar(&code, "code", false, "login with code, instead of importing session from desktop client")
|
||||
|
||||
// completion and validation
|
||||
_ = cmd.MarkFlagDirname(desktop)
|
||||
_ = cmd.Flags().MarkDeprecated("code", "use `-T code` instead")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user