77 * Date : Tue 14 Mar 2017 03:19:07 PM CST
88 */
99
10+ // import parser
1011const setCookieParser = require ( 'set-cookie-parser' )
1112
1213module . exports = app => {
@@ -15,38 +16,38 @@ module.exports = app => {
1516 /**
1617 * @constructor
1718 *
18- * @param ctx
19+ * @param { Objet } ctx - context object
1920 */
2021 constructor ( ctx ) {
2122 super ( ctx )
23+
2224 this . commonHeaders = {
2325 "Accept" : "text/html,application/xhtml+xml,application/xml" ,
2426 "Origin" : "https://www.v2ex.com" ,
25- "Referer" : "https://www.v2ex.com/mission/daily " ,
27+ "Referer" : "https://www.v2ex.com" ,
2628 "User-Agent" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"
2729 }
2830
2931 this . commonCookies = {
3032 tab : 'V2EX_TAB="2|1:0|10:1489746039|8:V2EX_TAB|8:dGVjaA==|b72b63fabe0f8faeff147ac38e26299655d713ad1880feef6679b56d8d1e9f47"' ,
31- lang : 'V2EX_LANG=zhcn; _ga=GA1.2.1254455933.1474272858; _gat=1'
33+ others : 'V2EX_LANG=zhcn; _ga=GA1.2.1254455933.1474272858; _gat=1'
3234 }
3335
34- // sessionid
36+ // sessionid cookie name
3537 this . sessionCookieName = 'PB3_SESSION'
3638
37- // token cookie name
39+ // token cookie name
3840 this . tokenCookieName = 'A2'
3941
4042 // 首页url
4143 this . homeUrl = 'https://www.v2ex.com/'
4244
43- // 获取登陆签名
45+ // 登陆相关
4446 this . loginUrl = 'https://www.v2ex.com/signin'
45- this . sessionCookie = '' // 供 `login`接口放在Header里 `Set-Cookie` 使用
46- // this.loginCookieArr = '' // get到的cookie暂存,供合并给最终的cookie
47- this . userKey = '' // 用户名 输入框埋下的随机key
48- this . passKey = '' // 密码 输入框埋下的随机key
49- this . once = '' // input[type="hidden"][name="once"]的随机令牌值(5位数字目前)
47+ this . sessionCookieStr = '' // 未登陆的sessionid, 供 `login` 接口放在请求Headers里的 `Set-Cookie` 项中使用
48+ this . userField = '' // 用户名 输入框埋下的随机表单域
49+ this . passField = '' // 密码 输入框埋下的随机表单域
50+ this . once = '' // input[type="hidden"][name="once"]的随机令牌值(目前是5位数字)
5051
5152 // 签到领金币url
5253 this . signinUrl = 'https://www.v2ex.com/mission/daily'
@@ -56,8 +57,8 @@ module.exports = app => {
5657 * request
5758 * 封装统一的请求方法
5859 *
59- * @param url
60- * @param opts
60+ * @param { String } url - 请求地址
61+ * @param { Object } opts - 请求选项
6162 * @returns {Promise }
6263 */
6364 async request ( url , opts ) {
@@ -75,14 +76,10 @@ module.exports = app => {
7576 * @returns {Promise }
7677 */
7778 async enterHomePage ( ) {
78- const result = await this . request ( this . homeUrl , {
79- method : 'GET' ,
80- dataType : 'text' ,
81- headers : this . commonHeaders
82- } )
79+ const result = await this . request ( this . homeUrl )
8380
84- const cs = setCookieParser ( result )
85- cs . forEach ( c => {
81+ const session = setCookieParser ( result )
82+ session . forEach ( c => {
8683 this . ctx . cookies . set ( c . name , c . value , {
8784 httpOnly : c . httpOnly ,
8885 domain : '' ,
@@ -93,23 +90,28 @@ module.exports = app => {
9390 }
9491
9592 /**
96- * getLoginKeys
93+ * getLoginFields
9794 * 获取登陆的各种凭证
9895 *
99- * @param content
96+ * @param { String } result - 请求登陆页返回的response,包含html字符串和Headers
10097 */
101- getLoginKeys ( content ) {
102- var keyRe = / c l a s s = " s l " n a m e = " ( [ 0 - 9 A - Z a - z ] { 64 } ) " / g
103- this . userKey = keyRe . exec ( content ) [ 1 ]
104- this . passKey = keyRe . exec ( content ) [ 1 ]
105- var onceRe = / v a l u e = " ( \d + ) " n a m e = " o n c e " /
98+ getLoginFields ( result ) {
99+ const content = result . data
100+
101+ const keyRe = / c l a s s = " s l " n a m e = " ( [ 0 - 9 A - Z a - z ] { 64 } ) " / g
102+ this . userField = keyRe . exec ( content ) [ 1 ]
103+ this . passField = keyRe . exec ( content ) [ 1 ]
104+
105+ const onceRe = / v a l u e = " ( \d + ) " n a m e = " o n c e " /
106106 this . once = onceRe . exec ( content ) [ 1 ]
107+
108+ this . sessionCookieStr = result . headers [ 'set-cookie' ] [ 0 ]
107109 }
108110
109111 /**
110112 * enterLoginPage
111113 * login前的准备
112- * 获取sessionid,获取userKey, passKey , once等
114+ * 获取sessionid,获取userField, passField , once等
113115 *
114116 * @returns {Promise }
115117 */
@@ -120,61 +122,47 @@ module.exports = app => {
120122 headers : this . commonHeaders
121123 } )
122124
123- // 供发起login的header里使用
124- this . sessionCookie = result . headers [ 'set-cookie' ] [ 0 ]
125- console . log ( '================================before login' , this . sessionCookie )
126-
127- const cs = setCookieParser ( result )
128-
129- return this . getLoginKeys ( result . data )
125+ return this . getLoginFields ( result )
130126 }
131127
132128 /**
133129 * login
134130 * login获取签名主方法
135131 *
136- * @param params
132+ * @param { Object } params - 请求参数
137133 */
138134 async login ( params ) {
139135
140- // @step 1: 获取提交的用户名密码
136+ // @step 1 获取提交的用户名密码
141137 const { username, password } = params
142138
143- // 进入登陆页,获取页面隐藏登陆域以及once的值
139+ // @step 2 进入登陆页,获取页面隐藏登陆域以及once的值
144140 await this . enterLoginPage ( )
145141
146- // 设置请求选项
142+ // @step 3 设置请求参数
147143 const opts = {
148144 method : 'POST' ,
149- headers : Object . assign ( this . commonHeaders , { Cookie : this . sessionCookie } ) ,
145+ headers : Object . assign ( this . commonHeaders , { Cookie : this . sessionCookieStr } ) ,
150146 data : {
151- [ this . userKey ] : username ,
152- [ this . passKey ] : password ,
147+ [ this . userField ] : username ,
148+ [ this . passField ] : password ,
153149 "once" : this . once
154150 }
155151 }
156152
157- // 发起请求
153+ // @step 4 发起请求
158154 const result = await this . request ( this . loginUrl , opts )
159155
160- // 获取cookies
156+ // @step 5 更新session并设置在客户端
157+ await this . enterHomePage ( )
158+
159+ // @step 6 解析获取到的cookies
161160 const cs = setCookieParser ( result )
162161
163- // 更新session并设置在客户端
164- const r = this . request ( this . homeUrl )
165- const session = setCookieParser ( r )
166- session . forEach ( c => {
167- this . ctx . cookies . set ( c . name , c . value , {
168- httpOnly : c . httpOnly ,
169- domain : '' ,
170- path : c . path ,
171- expires : c . expires
172- } )
173- } )
174-
175- // 判断是否登陆成功并设置客户端cookies
162+ // @step 7 判断是否登陆成功并种下客户端cookies
176163 let success = false
177164 cs . forEach ( c => {
165+ // 查看是否有令牌项的cookie,有就说明登陆成功了
178166 if ( c . name === this . tokenCookieName ) success = true
179167 this . ctx . cookies . set ( c . name , c . value , {
180168 httpOnly : c . httpOnly ,
@@ -187,7 +175,7 @@ module.exports = app => {
187175 // 设置API返回结果
188176 return {
189177 result : success ,
190- msg : success ? 'success ' : 'sorry! Not get enough token for you ' ,
178+ msg : success ? 'ok ' : 'sorry! Not get enough `Token`... ' ,
191179 data : {
192180 username : username
193181 }
@@ -198,14 +186,13 @@ module.exports = app => {
198186 * getSigninOnce
199187 * 获取签到的once值
200188 *
201- * @param content
189+ * @param { String } content - 签到页html字符串
202190 */
203191 getSigninOnce ( content ) {
204- // update this.once
205192 try {
206- const onceResult = content . match ( / o n c e = ( \w * ) / g ) [ 1 ]
207- this . once = onceResult . match ( / o n c e = ( \w * ) / ) [ 1 ]
208- console . log ( ' once------------------------' , this . once )
193+ // update this. once
194+ const onceRe = / r e d e e m \? o n c e = ( \d + ) /
195+ this . once = onceRe . exec ( content ) [ 1 ]
209196 } catch ( e ) {
210197 throw new Error ( '已经签到过了' )
211198 }
@@ -215,57 +202,58 @@ module.exports = app => {
215202 * enterSigninPage
216203 * 进入签到页面,获取once值
217204 *
218- * @returns {undefined }
219205 */
220206 async enterSigninPage ( ) {
221- await this . enterHomePage ( )
222207
223208 const token = `${ this . tokenCookieName } =${ this . ctx . cookies . get ( this . tokenCookieName ) } `
224209 const session = `${ this . sessionCookieName } =${ this . ctx . cookies . get ( this . sessionCookieName ) } `
225210 const headers = Object . assign ( this . commonHeaders , { Cookie : `${ session } ; ${ token } ` } )
211+
226212 const result = await this . request ( this . signinUrl , {
227213 method : 'GET' ,
228214 dataType : 'text' ,
229215 headers : headers
230216 } )
231217
232- return this . getSigninOnce ( result . data )
218+ this . getSigninOnce ( result . data )
219+ return
233220 }
234221
235222 /**
236223 * signin
237224 * 签到领金币
238- *
239- * @param params
240225 */
241- async signin ( params ) {
242- // 进入签到页面
226+ async signin ( ) {
227+
228+ // @step 1 进入签到页面
243229 await this . enterSigninPage ( )
244230
245- // 获取客户端凭证和cookie
246- const { tab, lang } = this . commonCookies
231+ // @step 2 获取客户端凭证和各种cookies
247232 const session = `${ this . sessionCookieName } =${ this . ctx . cookies . get ( this . sessionCookieName ) } `
248233 const token = `${ this . tokenCookieName } =${ this . ctx . cookies . get ( this . tokenCookieName ) } `
234+ const { tab, others } = this . commonCookies
249235
250- // 设置header
251- const headers = Object . assign ( this . commonHeaders , { Cookie : `${ session } ; ${ token } ; ${ tab } ; ${ lang } ;` } )
252- console . log ( 'headers: -------------------------------' , headers )
236+ // @step 3 设置Headers
237+ const headers = Object . assign ( this . commonHeaders ,
238+ { Referer : 'https://www.v2ex.com/mission/daily' } ,
239+ { Cookie : `${ session } ; ${ token } ; ${ tab } ; ${ others } ;` }
240+ )
253241
254- // 设置请求选项
242+ // @step 4 设置请求选项
255243 const opts = {
256244 dataType : 'text' ,
257245 method : 'get'
258246 }
259247
260- // 获取请求结果,会302
248+ // @step 5 获取请求结果,会302
261249 const result = await this . request ( `${ this . signinUrl } /redeem` , Object . assign ( opts , {
262250 headers : headers ,
263251 data : {
264252 'once' : this . once
265253 }
266254 } ) )
267255
268- // 重新进入签到页面,确认是否签到成功
256+ // @step 6 重新进入签到页面,确认是否签到成功
269257 const success = await this . request ( `${ this . signinUrl } ` , Object . assign ( opts , {
270258 headers : this . commonHeaders
271259 } ) )
0 commit comments