generated from oklookat/gostarter
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
217 lines (177 loc) · 4.92 KB
/
main.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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
package vkmauth
import (
"context"
"fmt"
"strings"
"time"
"github.com/oklookat/vantuz"
"golang.org/x/oauth2"
)
const (
_clientId = "6767438"
_clientSecret = "ppBOmwQYYOMGulmaiPyK"
_apiId = _clientId
// VK API version?
_apiVersion = "5.209"
// VK Music app version?
_sakVersion = "1.107"
)
const (
_vkApiUrl = "https://api.vk.com"
_vkOAuthUrl = _vkApiUrl + "/oauth"
_moosicApiUrl = "https://api.moosic.io"
_moosicVkConnectTokenUrl = _moosicApiUrl + "/oauth/vkconnect/vk/token"
)
const (
_errPrefix = "vkmauth"
)
var (
_authSupportedWays = authSupportedWaySlice{AuthSupportedWayPush, AuthSupportedWayEmail}
)
// Токен истекает через ~80 дней.
//
// Phone: полный номер телефона VK (+7 и так далее).
//
// Password: пароль от VK.
//
// # onCodeWaiting
//
// На вход приходит CodeSended.
// Поле Current означает куда был отправлен код.
// Поле Resend означает куда можно еще отправить код.
//
// # Чтобы отправить код другим методом
//
// Функция должна вернуть GotCode.
// Либо вы передаете код, либо делаете поле Resend = true,
// чтобы получить код другим методом (см. CodeSended).
// Но перед Resend проверьте, CodeSended.Resend.
// Если поле будет пустым, то код больше некуда отправлять.
func New(
ctx context.Context,
phone, password string,
onCodeWaiting func(by CodeSended) (GotCode, error),
) (*oauth2.Token, error) {
anTokens, err := getAnonymousToken(ctx)
if err != nil {
return nil, err
}
var (
sid string
code string
valResp *validatePhoneResponse
)
resend := true
for resend {
valResp, err = validatePhone(ctx, phone, sid, anTokens)
if err != nil {
return nil, err
}
valRespReal := valResp.Response
sid = valRespReal.Sid
sended := CodeSended{
Current: valRespReal.ValidationType,
Resend: valRespReal.ValidationResend,
}
gotCode, err := onCodeWaiting(sended)
if err != nil {
return nil, err
}
resend = gotCode.Resend
if resend && len(sended.Resend) == 0 {
return nil, newError("no available resend method", "New()")
}
code = gotCode.Code
if !resend {
break
}
}
if len(code) == 0 {
return nil, newError("empty code", "New()")
}
conf, err := validatePhoneConfirm(ctx, anTokens.DeviceId, code, phone, anTokens.Token, valResp.Response.Sid)
if err != nil {
return nil, err
}
silentToken, err := getSilentToken(ctx,
conf.Response.Sid, phone, password, anTokens.Token,
anTokens.DeviceId, conf.Response.Profile.Has2Fa)
if err != nil {
return nil, err
}
silentTokenChecked, err := checkSilentToken(ctx,
silentToken.SilentToken,
silentToken.SilentTokenUUID,
anTokens.Token, anTokens.DeviceId)
if err != nil {
return nil, err
}
tokensResp, err := getToken(ctx, anTokens.DeviceId,
silentTokenChecked.SilentTokenUUID, silentTokenChecked.SilentToken)
if err != nil {
return nil, err
}
tokens := &oauth2.Token{
TokenType: "Bearer",
AccessToken: tokensResp.AccessToken,
RefreshToken: tokensResp.RefreshToken,
// -1 hour for sure.
Expiry: time.Now().Add(time.Duration(tokensResp.ExpiresIn-3600) * time.Second),
}
return tokens, err
}
func getClient() *vantuz.Client {
cl := vantuz.C()
cl.SetUserAgent(fmt.Sprintf("SAK_%s(com.uma.musicvk)/6.1.229-10477", _sakVersion))
return cl
}
type AuthSupportedWay string
func (e AuthSupportedWay) String() string {
return string(e)
}
const (
AuthSupportedWayPush AuthSupportedWay = "push"
AuthSupportedWayEmail AuthSupportedWay = "email"
AuthSupportedWaySms AuthSupportedWay = "sms"
)
type authSupportedWaySlice []AuthSupportedWay
func (e authSupportedWaySlice) ToSlice() []string {
var result []string
for _, v := range e {
result = append(result, v.String())
}
return result
}
func (e authSupportedWaySlice) Join(sep string) string {
return strings.Join(e.ToSlice(), sep)
}
type ResponseWithError struct {
Errord *struct {
ErrorCode int `json:"error_code"`
ErrorMsg string `json:"error_msg"`
} `json:"error"`
}
func (e ResponseWithError) IsError() bool {
return e.Errord != nil && len(e.Error()) > 0
}
func (e ResponseWithError) Error() string {
if e.Errord == nil {
return _errPrefix + ": no error actually (nil Errord)"
}
return fmt.Sprintf("%s: %s", _errPrefix, e.Errord.ErrorMsg)
}
type (
CodeSended struct {
// Куда отправлен код.
Current AuthSupportedWay
// Если делать resend, код будет отправлен туда.
// Проверяте, не пустая ли строка если будете делать resend.
Resend AuthSupportedWay
}
GotCode struct {
// Код.
Code string
// Получить код другим методом?
Resend bool
}
)