-
Notifications
You must be signed in to change notification settings - Fork 43
/
Copy pathauthHelper.go
170 lines (160 loc) · 4.49 KB
/
authHelper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package gotgproto
import (
"context"
"github.com/gotd/td/telegram/auth"
"github.com/gotd/td/tg"
"github.com/gotd/td/tgerr"
"github.com/pkg/errors"
)
type Flow auth.Flow
func (f Flow) handleSignUp(ctx context.Context, client auth.FlowClient, phone, hash string, s *auth.SignUpRequired) error {
if err := f.Auth.AcceptTermsOfService(ctx, s.TermsOfService); err != nil {
return errors.Wrap(err, "confirm TOS")
}
info, err := f.Auth.SignUp(ctx)
if err != nil {
return errors.Wrap(err, "sign up info not provided")
}
if _, err := client.SignUp(ctx, auth.SignUp{
PhoneNumber: phone,
PhoneCodeHash: hash,
FirstName: info.FirstName,
LastName: info.LastName,
}); err != nil {
return errors.Wrap(err, "sign up")
}
return nil
}
func authFlow(ctx context.Context, client *auth.Client, conversator AuthConversator, phone string, sendOpts auth.SendCodeOptions) error {
f := Flow(auth.NewFlow(
termAuth{
phone: phone,
client: client,
conversator: conversator,
},
sendOpts,
))
if f.Auth == nil {
return errors.New("no UserAuthenticator provided")
}
var (
sentCode tg.AuthSentCodeClass
err error
)
SendAuthStatus(conversator, AuthStatusPhoneAsked)
for i := 0; i < 3; i++ {
var err1 error
if i == 0 {
phone, err1 = f.Auth.Phone(ctx)
} else {
SendAuthStatusWithRetrials(conversator, AuthStatusPhoneRetrial, 3-i)
phone, err1 = conversator.AskPhoneNumber()
}
if err1 != nil {
return errors.Wrap(err, "get phone")
}
sentCode, err = client.SendCode(ctx, phone, f.Options)
if tgerr.Is(err, "PHONE_NUMBER_INVALID") {
continue
}
break
}
if err != nil {
SendAuthStatus(conversator, AuthStatusPhoneFailed)
return err
}
// phone, err := f.Auth.Phone(ctx)
// if err != nil {
// return errors.Wrap(err, "get phone")
// }
// sentCode, err := client.SendCode(ctx, phone, f.Options)
// if err != nil {
// return err
// }
switch s := sentCode.(type) {
case *tg.AuthSentCode:
hash := s.PhoneCodeHash
var signInErr error
for i := 0; i < 3; i++ {
var code string
if i == 0 {
SendAuthStatus(conversator, AuthStatusPhoneCodeAsked)
code, err = f.Auth.Code(ctx, s)
} else {
SendAuthStatusWithRetrials(conversator, AuthStatusPhoneCodeRetrial, 3-i)
code, err = conversator.AskCode()
}
if err != nil {
SendAuthStatus(conversator, AuthStatusPhoneCodeFailed)
return errors.Wrap(err, "get code")
}
_, signInErr = client.SignIn(ctx, phone, code, hash)
if tgerr.Is(signInErr, "PHONE_CODE_INVALID") {
continue
}
break
}
// code, err := f.Auth.Code(ctx, s)
// if err != nil {
// return errors.Wrap(err, "get code")
// }
// _, signInErr := client.SignIn(ctx, phone, code, hash)
if errors.Is(signInErr, auth.ErrPasswordAuthNeeded) {
SendAuthStatus(conversator, AuthStatusPasswordAsked)
err = signInErr
for i := 0; err != nil && i < 3; i++ {
var password string
var err1 error
if i == 0 {
password, err1 = f.Auth.Password(ctx)
} else {
SendAuthStatusWithRetrials(conversator, AuthStatusPasswordRetrial, 3-i)
password, err1 = conversator.AskPassword()
}
if err1 != nil {
return errors.Wrap(err1, "get password")
}
_, err = client.Password(ctx, password)
if err == auth.ErrPasswordInvalid {
continue
}
break
}
if err != nil {
SendAuthStatus(conversator, AuthStatusPasswordFailed)
return errors.Wrap(err, "sign in with password")
}
SendAuthStatus(conversator, AuthStatusSuccess)
return nil
}
var signUpRequired *auth.SignUpRequired
if errors.As(signInErr, &signUpRequired) {
return f.handleSignUp(ctx, client, phone, hash, signUpRequired)
}
if signInErr != nil {
SendAuthStatus(conversator, AuthStatusPhoneCodeFailed)
return errors.Wrap(signInErr, "sign in")
}
SendAuthStatus(conversator, AuthStatusSuccess)
case *tg.AuthSentCodeSuccess:
switch a := s.Authorization.(type) {
case *tg.AuthAuthorization:
SendAuthStatus(conversator, AuthStatusSuccess)
// Looks that we are already authorized.
return nil
case *tg.AuthAuthorizationSignUpRequired:
if err := f.handleSignUp(ctx, client, phone, "", &auth.SignUpRequired{
TermsOfService: a.TermsOfService,
}); err != nil {
// TODO: not sure that blank hash will work here
return errors.Wrap(err, "sign up after auth sent code success")
}
return nil
default:
return errors.Errorf("unexpected authorization type: %T", a)
}
default:
return errors.Errorf("unexpected sent code type: %T", sentCode)
}
return nil
}