pindo 5.0.6 → 5.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da7db67cae593054d94da87ec555ccd0d6ed2691ca9d534729a386b4cc55f360
4
- data.tar.gz: 25b281165febd17ac56dfcadd64dcf2e55674e326b28575ff3952007b7dbdc2d
3
+ metadata.gz: cd1d664dc77bc75c43a1816a8316fafb10351c9133a4e9dabf403f010bd1882a
4
+ data.tar.gz: 7e4387a7ad42c6830898bd9466a7ea8131ab92429b78ed5ed61479b07eebe44f
5
5
  SHA512:
6
- metadata.gz: '089d77424e3f53c88de5d9839b6849a11c868e6bf637b485403cec677a0e320cc2292e09fe8c868ecec3950a28e21b060a0867eadcd9b01dd1cab7aaaf8b878d'
7
- data.tar.gz: 34a13c1bf0691285cd4d7c76c284c288c445ec2f3e67650d504ccdf1d3c2baa599c91492943ddee6078245372e5ae42746d2cd2bb881f9da0075305f7bd03d66
6
+ metadata.gz: 305e2b32210bf046c6d56a82cff9f799e9bf73672e812aa28e3c78e378b32bc8c4700f5f4f45cfe39e3301427632f6074c2f6b419778c51a21de15dc19d8a676
7
+ data.tar.gz: 991b426167216c8c2f95fbd99400314fe807f892a6975300d145ff1e07684611547f6a89df7fbabd634d5f0f076839928fb89a1787977b313e4b1e332029a997
@@ -49,10 +49,9 @@ module Pindo
49
49
 
50
50
  def do_login()
51
51
 
52
- # username = ask('请输入Boss网站的用户名:')
53
- # password = ask('请输入Boss网站的密码:')
54
- username = "shuangquan"
55
- password = "HIsdfUHfwdh"
52
+ username = ask('请输入Boss网站的用户名:')
53
+ password = ask('请输入Boss网站的密码:')
54
+
56
55
 
57
56
  do_login_req(username:username, password:password)
58
57
  end
@@ -10,66 +10,43 @@ require 'base64'
10
10
  require 'fileutils'
11
11
  require 'pindo/base/aeshelper'
12
12
  require 'pindo/config/pindouserlocalconfig'
13
+ require 'pindo/client/httpclient'
13
14
 
14
15
  module Pindo
15
16
 
16
17
  class PgyerFeishuOAuthCLI
17
- attr_reader :access_token, :refresh_token, :user_info
18
+ attr_reader :access_token, :username, :expires_at
18
19
 
19
20
  def initialize(client_id)
20
21
  @client_id = client_id
21
- @feishu_auth_url = 'https://open.feishu.cn/open-apis/authen/v1/index'
22
- @redirect_uri = 'https://jps-new.devtestapp.com/auth/jwt/login'
23
- # @state = SecureRandom.hex(16)
24
- @state = 'success_login'
22
+ @feishu_auth_url = 'https://passport.feishu.cn/suite/passport/oauth/authorize?'
23
+
24
+ # 保持原有的redirect_uri,飞书OAuth流程中仍使用这个URL
25
+ # 前端UI会检测state=terminal_login并自动跳转到localhost:8899
26
+ @redirect_uri = 'https://pgyerapps.com/login'
27
+ @pgyer_api_endpoint = 'https://api.pgyerapps.com/api/user/lark_qr_login'
28
+
29
+ @state = 'terminal_login'
30
+
25
31
  @larkScopeList = [
26
- 'offline_access',
27
32
  'task:task:write',
28
33
  'task:section:write',
29
34
  'task:custom_field:write',
30
- 'task:tasklist:write',
35
+ 'task:tasklist:write'
31
36
  ];
32
37
 
33
38
  @access_token = nil
34
- @refresh_token = nil
35
- @token_expired_at = nil
36
-
37
- @pgyer_token_file = File.join(File::expand_path(Pindoconfig.instance.pindo_dir), ".pgyer_token")
38
-
39
- # 尝试读取配置文件中的AES密钥
40
- begin
41
- config_file = File.join(File::expand_path(Pindoconfig.instance.pindo_common_configdir), "pgyer_client_config.json")
42
- if File.exist?(config_file)
43
- config_json = JSON.parse(File.read(config_file))
44
- @pgyer_aes_key = config_json["pgyerapps_aes_key"] if config_json["pgyerapps_aes_key"]
45
- end
46
- rescue => e
47
- puts "读取配置文件失败: #{e.message}"
48
- end
49
-
50
- # 如果配置文件中没有找到密钥,则使用默认密钥
51
- @pgyer_aes_key ||= ENV['PGYER_AES_KEY'] || "pgyerOauthToken2024"
52
-
53
- # Pgyer API endpoints
54
- @pgyer_api_endpoint = 'https://jps-api.devtestapp.com/api/lark_login'
39
+ @username = nil
40
+ @expires_at = nil
55
41
  end
56
42
 
57
43
  # 启动授权流程
58
44
  def authorize
59
- # 先检查是否有存储的令牌
60
- if load_token
61
- puts "找到已保存的Pgyer令牌,尝试验证..."
62
- if validate_pgyer_token
63
- puts "已有令牌验证成功!"
64
- return true
65
- else
66
- puts "已有令牌已失效,需要重新授权。"
67
- end
68
- end
69
-
45
+ # 不再检查已存储的令牌,直接开始授权流程
70
46
  authorization_uri = build_authorization_uri
71
47
  puts "正在打开浏览器进行飞书OAuth授权..."
72
48
  puts "授权URI: #{authorization_uri}"
49
+ puts "注意:授权成功后,网页将自动跳转至本地http://localhost:8899"
73
50
 
74
51
  # 在浏览器中打开授权URL
75
52
  open_browser(authorization_uri)
@@ -77,10 +54,38 @@ module Pindo
77
54
  # 启动本地服务器处理回调
78
55
  code = start_callback_server
79
56
 
57
+ # 如果自动获取失败,提示用户手动输入
58
+ if code.nil?
59
+ puts "自动获取授权码失败,您可以手动输入:"
60
+ puts "1. 授权码 (直接复制'code='后面的内容)"
61
+ puts "2. 完整回调URL (例如: http://localhost:8899/?code=xxxx...)"
62
+ print "> "
63
+ input = STDIN.gets.chomp
64
+
65
+ if input.start_with?("http")
66
+ # 尝试从URL中提取code
67
+ begin
68
+ uri = URI(input)
69
+ query_params = URI.decode_www_form(uri.query || '').to_h
70
+ code = query_params['code']
71
+ if code
72
+ puts "从URL中成功提取授权码"
73
+ end
74
+ rescue => e
75
+ puts "无法从URL中提取授权码: #{e.message}"
76
+ end
77
+ else
78
+ # 将输入直接作为code
79
+ code = input unless input.empty?
80
+ end
81
+ end
82
+
80
83
  if code
81
- puts "正在使用飞书身份登录Pgyer..."
84
+ puts "成功获取授权码!正在使用飞书身份登录Pgyer..."
85
+ puts "code: #{code}"
82
86
  if login_pgyer_with_feishu(code:code)
83
- store_token
87
+ puts "Pgyer登录成功!"
88
+ # 登录成功后,返回true,外部程序可以通过访问access_token属性获取token
84
89
  return true
85
90
  end
86
91
  return false
@@ -91,14 +96,23 @@ module Pindo
91
96
  end
92
97
 
93
98
  # 验证Pgyer令牌
94
- def validate_pgyer_token
95
- return false unless @access_token
99
+ def validate_pgyer_token(token = nil, expires_at = nil)
100
+ token_to_check = token || @access_token
101
+ expiration_time = expires_at || @expires_at
96
102
 
97
- # 这里应该调用Pgyer的API验证令牌有效性
98
- # 由于没有具体API文档,这里仅做示例
103
+ # 首先检查token是否存在
104
+ return false unless token_to_check
105
+
106
+ # 然后检查token是否过期
107
+ if expiration_time && Time.now.to_i > expiration_time
108
+ puts "令牌已过期,需要重新登录"
109
+ return false
110
+ end
111
+
112
+ # 最后验证token是否有效
99
113
  uri = URI("https://www.pgyer.com/api/user/profile")
100
114
  request = Net::HTTP::Get.new(uri)
101
- request['Authorization'] = "Bearer #{@access_token}"
115
+ request['Authorization'] = "Bearer #{token_to_check}"
102
116
 
103
117
  response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
104
118
  http.request(request)
@@ -111,118 +125,70 @@ module Pindo
111
125
  def login_pgyer_with_feishu(code: nil)
112
126
  return false unless code
113
127
 
114
- uri = URI(@pgyer_api_endpoint)
115
- request = Net::HTTP::Post.new(uri)
116
- request['Content-Type'] = 'application/json'
117
-
118
- # 根据Pgyer的API要求构造请求体
119
- request.body = {
128
+ # 构造请求体
129
+ body_params = {
120
130
  code: code,
121
131
  redirectUri: @redirect_uri,
122
132
  scope: @larkScopeList.join(' ')
123
- }.to_json
133
+ }
124
134
 
125
- response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
126
- http.request(request)
127
- end
135
+ puts "请求Pgyer API: #{@pgyer_api_endpoint}"
136
+ puts "请求参数: #{body_params.to_json}"
128
137
 
129
- if response.code == '200'
130
- begin
131
- result = JSON.parse(response.body)
132
- if !result['meta'].nil? && result['meta']['code'] == 200 && !result['data'].nil? && !result['data']['token'].nil?
133
- @access_token = result['data']['token']
134
- @username = result['data']['token']
135
- @user_id = result['data']['user_id']
136
-
137
- return true
138
- else
139
- puts "Pgyer登录失败: #{result['message'] || '未知错误'}"
140
- return false
141
- end
142
- rescue JSON::ParserError
143
- puts "解析Pgyer响应失败"
144
- return false
145
- end
146
- else
147
- puts "Pgyer登录请求失败: HTTP #{response.code}"
148
- return false
149
- end
150
-
151
- end
152
-
153
-
154
- # 加载存储的令牌
155
- def load_token
156
- return false unless File.exist?(@pgyer_token_file)
138
+ # 使用HttpClient发送请求
139
+ con = HttpClient.create_instance_with_proxy
157
140
 
158
141
  begin
159
- encrypted_data = File.read(@pgyer_token_file)
160
- json_data = aes_decrypt(encrypted_data, @pgyer_aes_key)
161
- token_data = JSON.parse(json_data)
142
+ res = con.post do |req|
143
+ req.url @pgyer_api_endpoint
144
+ req.headers['Content-Type'] = 'application/json'
145
+ req.body = body_params.to_json
146
+ end
162
147
 
163
- @access_token = token_data['token']
164
- @user_info = token_data['user_info'] if token_data['user_info']
165
- @token_expired_at = Time.at(token_data['expires_at']) if token_data['expires_at']
148
+ puts "API响应状态码: #{res.status}"
166
149
 
167
- # 检查令牌是否过期
168
- if @token_expired_at && Time.now >= @token_expired_at
169
- puts "令牌已过期,需要重新授权"
150
+ # 处理响应
151
+ result = nil
152
+ if !res.body.nil?
153
+ begin
154
+ result = JSON.parse(res.body)
155
+ # puts "解析后的响应: #{result.inspect}"
156
+
157
+ if result['code'] == 200 && !result['data'].nil? && !result['data']['token'].nil?
158
+ @access_token = result['data']['token']
159
+ @username = result['data']['username'] if result['data']['username']
160
+ # 设置token有效期为7天后
161
+ @expires_at = Time.now.to_i + 6 * 24 * 60 * 60 # 7天的秒数
162
+ return true
163
+ else
164
+ error_msg = result['meta'] && result['meta']['message'] ? result['meta']['message'] : '未知错误'
165
+ puts "Pgyer登录失败: #{error_msg}"
166
+ return false
167
+ end
168
+ rescue => e
169
+ puts "解析响应失败: #{e.message}"
170
+ puts "原始响应: #{res.body[0..200]}"
171
+ return false
172
+ end
173
+ else
174
+ puts "请求返回空响应"
170
175
  return false
171
176
  end
172
-
173
- return true
174
- rescue => e
175
- puts "加载令牌失败: #{e.message}"
176
- return false
177
- end
178
- end
179
-
180
- # 存储令牌
181
- def store_token
182
- return false unless @access_token
183
-
184
- token_data = {
185
- 'token' => @access_token,
186
- 'user_info' => @user_info,
187
- 'expires_at' => Time.now.to_i + 7*24*60*60 # 假设令牌有效期为7天
188
- }
189
-
190
- encrypted_data = aes_encrypt(token_data.to_json, @pgyer_aes_key)
191
-
192
- begin
193
- File.open(@pgyer_token_file, 'w') do |f|
194
- f.write(encrypted_data)
195
- end
196
- puts "令牌已安全存储"
197
- return true
198
177
  rescue => e
199
- puts "存储令牌失败: #{e.message}"
178
+ puts "请求过程中出错: #{e.class} - #{e.message}"
200
179
  return false
201
180
  end
202
181
  end
203
182
 
204
183
  private
205
184
 
206
- # AES加密
207
- def aes_encrypt(data, key)
208
- # 使用Pindo的AESHelper类进行真正的AES加密
209
- AESHelper::aes_128_ecb_encrypt(key, data)
210
- end
211
-
212
- # AES解密
213
- def aes_decrypt(encrypted_data, key)
214
- # 使用Pindo的AESHelper类进行真正的AES解密
215
- AESHelper::aes_128_ecb_decrypt(key, encrypted_data)
216
- end
217
185
 
218
186
  # 构建授权URI
219
187
  def build_authorization_uri
220
188
  uri = URI(@feishu_auth_url)
221
189
 
222
-
223
-
224
190
  params = {
225
- 'app_id' => @client_id,
191
+ 'client_id' => @client_id,
226
192
  'redirect_uri' => @redirect_uri,
227
193
  'response_type' => 'code',
228
194
  'state' => @state,
@@ -249,61 +215,194 @@ module Pindo
249
215
  # 启动本地服务器处理回调
250
216
  def start_callback_server
251
217
  code = nil
252
- uri = URI(@redirect_uri)
218
+
219
+ puts "启动本地服务器,监听端口8899..."
220
+
221
+ # 使用本地8899端口处理回调,不管redirect_uri配置如何
253
222
  server = WEBrick::HTTPServer.new(
254
- Port: uri.port,
223
+ Port: 8899,
255
224
  Logger: WEBrick::Log.new("/dev/null"),
256
225
  AccessLog: []
257
226
  )
258
227
 
259
- path = uri.path.empty? ? '/' : uri.path
260
- server.mount_proc path do |req, res|
261
- query_params = URI.decode_www_form(req.query_string || '').to_h
262
-
263
- if query_params['state'] != @state
264
- res.body = "状态不匹配,可能存在CSRF攻击风险"
265
- elsif query_params['error']
266
- res.body = "授权错误: #{query_params['error']}"
267
- elsif query_params['code']
268
- code = query_params['code']
269
- res.body = <<-HTML
270
- <!DOCTYPE html>
271
- <html>
272
- <head>
273
- <title>飞书授权成功</title>
274
- <style>
275
- body { font-family: Arial, sans-serif; text-align: center; padding: 40px; }
276
- .container { max-width: 600px; margin: 0 auto; }
277
- .success { color: #4CAF50; }
278
- </style>
279
- </head>
280
- <body>
281
- <div class="container">
282
- <h1 class="success">授权成功!</h1>
283
- <p>飞书OAuth授权已完成,您现在可以关闭此窗口并返回命令行。</p>
284
- </div>
285
- </body>
286
- </html>
287
- HTML
288
- else
289
- res.body = "未获取到授权码"
290
- end
228
+ # 处理根路径的请求
229
+ server.mount_proc '/' do |req, res|
230
+ begin
231
+ # puts "接收到请求: #{req.request_line}"
232
+ # puts "请求参数: #{req.query_string}"
233
+
234
+ # 安全解析请求参数
235
+ begin
236
+ query_params = URI.decode_www_form(req.query_string || '').to_h
237
+ puts "解析的参数: #{query_params.inspect}"
238
+ rescue => e
239
+ puts "解析请求参数失败: #{e.message}"
240
+ query_params = {}
241
+ end
242
+
243
+ # if query_params['state'] != @state
244
+ # puts "状态不匹配: 接收到 #{query_params['state']},期望 #{@state}"
245
+ # res.content_type = "text/html; charset=UTF-8"
246
+ # res.body = "状态不匹配,可能存在CSRF攻击风险"
247
+ # elsif query_params['error']
248
+ if query_params['error']
249
+ puts "授权错误: #{query_params['error']}"
250
+ res.content_type = "text/html; charset=UTF-8"
251
+ res.body = "授权错误: #{query_params['error']}"
252
+ elsif query_params['code']
253
+ code = query_params['code']
254
+ puts "成功获取授权码: #{code}"
255
+ res.content_type = "text/html; charset=UTF-8"
256
+ res.body = <<-HTML
257
+ <!DOCTYPE html>
258
+ <html>
259
+ <head>
260
+ <meta charset="UTF-8">
261
+ <title>飞书授权成功</title>
262
+ <style>
263
+ body { font-family: Arial, sans-serif; text-align: center; padding: 40px; }
264
+ .container { max-width: 600px; margin: 0 auto; }
265
+ .success { color: #4CAF50; }
266
+ .code { font-family: monospace; background: #f5f5f5; padding: 10px; border-radius: 4px; word-break: break-all; }
267
+ .countdown { font-weight: bold; color: #FF5722; }
268
+ .autoclose-banner {
269
+ background-color: #333; color: white; padding: 10px;
270
+ position: fixed; top: 0; left: 0; right: 0;
271
+ display: flex; justify-content: space-between; align-items: center;
272
+ }
273
+ .close-btn {
274
+ background: #f44336; color: white; border: none;
275
+ padding: 5px 10px; cursor: pointer; border-radius: 3px;
276
+ }
277
+ </style>
278
+ <script>
279
+ // 尝试多种方法关闭窗口
280
+ function attemptClose() {
281
+ try {
282
+ // 方法1: 最基本的关闭尝试
283
+ window.close();
284
+
285
+ // 方法2: 对于某些浏览器需要历史记录操作
286
+ window.history.back();
287
+
288
+ // 方法3: 空白页替换
289
+ window.location.href = "about:blank";
290
+
291
+ // 方法4: 尝试使用opener关系
292
+ if (window.opener) {
293
+ window.opener.focus();
294
+ window.close();
295
+ }
296
+
297
+ // 如果以上方法都失败了,显示手动关闭提示
298
+ setTimeout(function() {
299
+ document.getElementById('close-message').style.display = 'block';
300
+ document.getElementById('countdown-container').style.display = 'none';
301
+ }, 1000);
302
+ } catch (e) {
303
+ console.error("关闭窗口失败:", e);
304
+ document.getElementById('close-message').style.display = 'block';
305
+ document.getElementById('countdown-container').style.display = 'none';
306
+ }
307
+ }
308
+
309
+ // 倒计时函数
310
+ var secondsLeft = 3;
311
+ function updateCountdown() {
312
+ document.getElementById('countdown').innerText = secondsLeft;
313
+ if (secondsLeft <= 0) {
314
+ attemptClose();
315
+ } else {
316
+ secondsLeft -= 1;
317
+ setTimeout(updateCountdown, 1000);
318
+ }
319
+ }
320
+
321
+ // 初始化
322
+ window.onload = function() {
323
+ updateCountdown();
324
+ }
325
+ </script>
326
+ </head>
327
+ <body>
328
+ <div class="autoclose-banner">
329
+ <span>授权成功! 此窗口将自动关闭 (<span id="countdown" class="countdown">3</span>)</span>
330
+ <button class="close-btn" onclick="attemptClose()">立即关闭</button>
331
+ </div>
332
+
333
+ <div class="container">
334
+ <h1 class="success">飞书授权成功!</h1>
335
+ <p>已获取授权码,正在返回命令行...</p>
336
+
337
+ <div id="countdown-container">
338
+ <p>此窗口将在 <span id="countdown-text" class="countdown">3</span> 秒后自动关闭</p>
339
+ </div>
340
+
341
+ <div id="close-message" style="display: none;">
342
+ <p>自动关闭失败,请手动关闭此窗口</p>
343
+ <button class="close-btn" onclick="attemptClose()">尝试再次关闭</button>
344
+ </div>
345
+
346
+ <p>授权码:</p>
347
+ <div class="code">#{code}</div>
348
+ </div>
349
+
350
+ <script>
351
+ // 同步倒计时显示
352
+ document.getElementById('countdown-text').innerText = secondsLeft;
353
+ </script>
354
+ </body>
355
+ </html>
356
+ HTML
357
+ else
358
+ puts "未获取到授权码"
359
+ res.content_type = "text/html; charset=UTF-8"
360
+ res.body = "未获取到授权码"
361
+ end
291
362
 
292
- server.shutdown
363
+ # 给用户更多时间看到页面内容,并让JavaScript倒计时完成
364
+ puts "4秒后关闭服务器..."
365
+ Thread.new do
366
+ sleep 4 # 设置为4秒,比JavaScript的3秒稍长一点,确保客户端有足够时间执行
367
+ server.shutdown
368
+ end
369
+ rescue => e
370
+ puts "处理请求时出错: #{e.class} - #{e.message}"
371
+ puts e.backtrace.join("\n")
372
+
373
+ # 确保即使出错也返回有效的响应
374
+ res.content_type = "text/html; charset=UTF-8"
375
+ res.body = "处理请求时出错"
376
+
377
+ # 出错时也关闭服务器
378
+ Thread.new do
379
+ sleep 4 # 与正常情况保持一致
380
+ server.shutdown
381
+ end
382
+ end
293
383
  end
294
-
384
+
295
385
  # 捕获Ctrl+C以允许用户中断
296
386
  trap('INT') { server.shutdown }
297
387
 
298
- # 在线程中运行服务器,最多等待2分钟
388
+ # puts "正在监听http://localhost:8899等待飞书重定向..."
389
+ # puts "您也可以手动访问: http://localhost:8899/?code=YOUR_CODE&state=terminal_login"
390
+
391
+ # 在线程中运行服务器,最多等待3分钟
299
392
  thread = Thread.new { server.start }
300
393
  begin
301
- thread.join(120) # 最多等待2分钟
394
+ thread.join(180) # 最多等待3分钟
302
395
  rescue Timeout::Error
303
396
  puts "授权超时"
304
397
  server.shutdown
305
398
  end
306
399
 
400
+ if code
401
+ puts "成功获取授权码: #{code}"
402
+ else
403
+ puts "未获取到授权码"
404
+ end
405
+
307
406
  code
308
407
  end
309
408
 
@@ -1,9 +1,8 @@
1
-
2
1
  require 'uri'
3
2
  require 'pindo/base/aeshelper'
4
3
  require 'pindo/config/pindouserlocalconfig'
5
4
  require 'pindo/client/httpclient'
6
-
5
+ require 'pindo/client/pgyer_feishu_oauth_cli'
7
6
 
8
7
  module Pindo
9
8
 
@@ -35,124 +34,44 @@ module Pindo
35
34
 
36
35
  end
37
36
 
38
- def get_faraday_instance
39
-
40
- end
41
-
42
-
43
37
  def do_login(force_login:false)
44
38
 
39
+ login_success = false
40
+ need_req_login = true
45
41
 
46
-
47
- login_success = false
48
- @token = load_token()
49
- if !@token.nil? && !@token["token"].nil? && !force_login
50
- login_success = true
51
-
52
- # puts "用户#{@token["username"]}登录pgyer成功!!!"
53
- # puts
54
-
55
- else
56
- username = nil
57
- if !@token.nil? && !@token["username"].nil?
58
- username = @token["username"]
59
- checksum_password = nil
60
- if !@token["password"].nil?
61
- checksum_password = @token["password"]
62
- end
63
- end
64
- token = do_login_req(username:username, checksum_password:checksum_password)
65
- if !token.nil? && !token["token"].nil?
66
- @token = token
67
- login_success = true
68
- end
69
- end
70
-
71
- return login_success
72
- end
73
-
74
- def do_login_req(username:nil, checksum_password:nil)
75
-
76
-
77
- login_name = username
78
- if login_name.nil? || login_name.empty?
79
- login_name = ask('请输入pgger网站的usernmae:') || nil
80
- end
81
-
82
- checksum_pass = checksum_password
83
- if checksum_pass.nil? || checksum_pass.empty?
84
- login_passwork = ask('请输入pgger网站的密码:') || nil
85
- checksum_pass = Digest::MD5.hexdigest(login_passwork)
86
- end
87
-
88
- if !login_name.nil? && !login_name.empty? && !checksum_pass.nil? && !checksum_pass.empty?
89
-
42
+ if force_login
43
+ need_req_login = true
90
44
  else
91
- raise Informative, "请输入正确的用户名和密码!"
92
- end
93
-
94
-
95
- Funlog.instance.fancyinfo_start("正在登录pgyer...")
96
-
97
-
98
- result_data = do_send_code(username:login_name)
99
-
100
-
101
- boss_url = @baseurl + @request_config["do_login"]
102
- body_params = {
103
- username:login_name,
104
- phoneCode:result_data["msg"],
105
- password:checksum_pass
106
- }
107
-
108
- # puts JSON.pretty_generate(body_params)
109
-
110
- login_response_data = nil
111
-
112
- begin
113
-
114
- con = HttpClient.create_instance_with_proxy
115
- res = con.post do |req|
116
- req.url boss_url
117
- req.headers['Content-Type'] = 'application/json'
118
- req.body = body_params.to_json
45
+ @token = load_token()
46
+ if !@token.nil? && !@token["token"].nil? && !@token["username"].nil?
47
+ # 检查token是否已过期(超过7天)
48
+ if @token["expires_at"] && Time.now.to_i < @token["expires_at"]
49
+ need_req_login = false
50
+ else
51
+ Funlog.instance.fancyinfo_error("令牌已过期,需要重新登录...")
52
+ login_success = true
53
+ end
54
+ else
55
+ need_req_login = true
56
+ end
119
57
  end
120
-
121
- if !res.body.nil?
122
-
123
- login_response_data = JSON.parse(res.body)
58
+ if need_req_login
59
+ login_handle = PgyerFeishuOAuthCLI.new("cli_a7db8213883ed00d")
60
+ result = login_handle.authorize
61
+ @token = {}
62
+ @token["token"] = login_handle.access_token
63
+ @token["username"] = login_handle.username
64
+ @token["expires_at"] = login_handle.expires_at
65
+ store_token(token:@token)
66
+ login_success = true
67
+ else
68
+ login_success = true
124
69
  end
125
70
 
126
- rescue => error
127
- Funlog.instance.fancyinfo_error("pgyer登录失败!")
128
- puts "登录失败,请重试!!!"
129
- end
130
-
131
-
132
-
133
- # puts JSON.pretty_generate(login_response_data)
134
-
135
- if !login_response_data.nil? && !login_response_data["code"].nil? && login_response_data["code"].to_s.eql?("200")
136
-
137
- token = {}
138
- token= login_response_data["data"]
139
- token["password"] = checksum_pass
140
- # puts JSON.pretty_generate(token)
141
- store_token(token:token)
142
-
143
- Funlog.instance.fancyinfo_success("用户:#{@token["username"]}登录pgyer成功!")
144
-
145
- else
146
- if File.exist?(@pgyer_token_file)
147
- FileUtils.rm_rf(@pgyer_token_file)
148
- end
149
- Funlog.instance.fancyinfo_error("pgyer登录失败!")
150
- end
151
-
152
- return token
153
-
71
+ return login_success
154
72
  end
155
73
 
74
+
156
75
  def load_token()
157
76
 
158
77
  @token = nil
@@ -165,6 +84,12 @@ module Pindo
165
84
  temp_token = data_string
166
85
  temp_token = JSON.parse(data_string)
167
86
  if !temp_token.nil? && !temp_token["token"].nil? && !temp_token["username"].nil?
87
+ # 检查token是否已过期
88
+ if temp_token["expires_at"] && Time.now.to_i > temp_token["expires_at"]
89
+ Funlog.instance.fancyinfo_error("令牌已过期,需要重新登录...")
90
+ return nil
91
+ end
92
+
168
93
  @token = temp_token
169
94
  Funlog.instance.fancyinfo_success("读取pgyer token成功!")
170
95
  end
data/lib/pindo/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Pindo
2
2
 
3
- VERSION = "5.0.6"
3
+ VERSION = "5.0.7"
4
4
 
5
5
  class VersionCheck
6
6
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pindo
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.6
4
+ version: 5.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - wade