wechat 0.13.2 → 0.15.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c6d51ad6518aa5f2e9482ce73220e29b4cceed409a896d8eb355afd34ccb9150
4
- data.tar.gz: a8ee3145ed887165c6d708b1eccaeb77906c4dd4d6971b0cae82d076af2a9d77
3
+ metadata.gz: a4b435dd326d145908b8d8bfd395a3c6f8238b0fcbba8c1c75610665f11dac23
4
+ data.tar.gz: 760ac7cb8cb35629c1f4724b6edad484702dd62f5ba1b9125aac1e3f2414310c
5
5
  SHA512:
6
- metadata.gz: 832b031759ec823b0a2f22637e1372bc029b16e9ef51012b8a9a7040500e3b36b7bfdf1f0cfde6bbb8f641790e15aa76202f79aac331f56b4e2da741aa41ad0c
7
- data.tar.gz: 9504b8ce9e37b2ae35a64f1a45e2ae0f372aa8657196013e7bf84983d326ebebb5190d6e3b4662f840df04cfd19d83effc99dde8c2ce1483b6691737bcde0972
6
+ metadata.gz: ab4bddc39dcd6c471b128e7ba01dd8a5876215d26b8257b22db535355cfcd4a862c7740098d440fe86633f79191ea9dece7b0b4ff633e4f3994c3d121bc3ec22
7
+ data.tar.gz: f3ed54350f992c62584f3ddebb130b1162d8b73103ea99ddb86f5b99a9b60383b36b122b253ab37b6ddbe4303388319d858ec53b4f033255bd5261c39b992a50
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -1,15 +1,35 @@
1
1
  # Changelog
2
2
 
3
- ## v0.13.2 (released at 4/21/2021)
3
+ ## v0.15.1 (released at 2022-02-16)
4
+
5
+ * fix "Psych::BadAlias (Unknown alias: default)" in ruby 3.1.0 #309, reported by @otorain
6
+
7
+ ## v0.15.0 (released at 2021-12-21)
8
+
9
+ * Add wechat message json format support, by @younthu #306
10
+ * Support Rails 7 in this version.
11
+ * Fix wechat command-line 1st attempt bug #307
12
+
13
+ ## v0.14.0 (released at 2021-09-15)
14
+
15
+ * Add beta support for Conversation archive in WeCom, discuss at #303
16
+ * Avoid using 1.hour in early loading to improve Rails 6+ compatibility.
17
+
18
+ ## v0.13.3 (released at 2021-06-18)
19
+
20
+ * material add video description by @zlei1 #301
21
+ * Allow using http v5
22
+
23
+ ## v0.13.2 (released at 2021-04-21)
4
24
 
5
25
  * New material_add_news API, by @zlei1 #300
6
26
  * Support open_tag, by @xiajian2019 #299
7
27
 
8
- ## v0.13.1 (released at 3/15/2021)
28
+ ## v0.13.1 (released at 2021-03-15)
9
29
 
10
30
  * Fix MpApi initialize bug, by @hardywu #296
11
31
 
12
- ## v0.13.0 (released at 3/3/2021)
32
+ ## v0.13.0 (released at 2021-03-03)
13
33
 
14
34
  * Support zeitwerk only and Rails 6+ only.
15
35
  * Support Ruby 2.6+ only.
data/README-CN.md CHANGED
@@ -1,4 +1,4 @@
1
- WeChat [![Gem Version](https://badge.fury.io/rb/wechat.svg)](https://rubygems.org/gems/wechat) [![Build Status](https://travis-ci.com/Eric-Guo/wechat.svg)](https://travis-ci.com/github/Eric-Guo/wechat) [![Maintainability](https://api.codeclimate.com/v1/badges/12885358487c13e91e00/maintainability)](https://codeclimate.com/github/Eric-Guo/wechat/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/12885358487c13e91e00/test_coverage)](https://codeclimate.com/github/Eric-Guo/wechat/test_coverage)
1
+ WeChat [![Gem Version](https://badge.fury.io/rb/wechat.svg)](https://rubygems.org/gems/wechat) [![Build Status](https://mixtint.semaphoreci.com/badges/wechat/branches/main.svg?style=shields)](https://mixtint.semaphoreci.com/projects/wechat) [![Maintainability](https://api.codeclimate.com/v1/badges/12885358487c13e91e00/maintainability)](https://codeclimate.com/github/Eric-Guo/wechat/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/12885358487c13e91e00/test_coverage)](https://codeclimate.com/github/Eric-Guo/wechat/test_coverage)
2
2
  ======
3
3
 
4
4
  [![Join the chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Eric-Guo/wechat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@@ -794,6 +794,18 @@ class WechatsController < ActionController::Base
794
794
  request.reply.success # request is XML result hash.
795
795
  end
796
796
 
797
+ # 客户同意进行聊天内容存档事件回调
798
+ on :change_external_contact do |request|
799
+ # https://open.work.weixin.qq.com/api/doc/90000/90135/92005
800
+ request.reply.success # request is XML result hash.
801
+ end
802
+
803
+ # 会话事件回调
804
+ on :msgaudit_notify do |request|
805
+ # https://open.work.weixin.qq.com/api/doc/90000/90135/95039
806
+ request.reply.success # request is XML result hash.
807
+ end
808
+
797
809
  # 当无任何 responder 处理用户信息时,使用这个 responder 处理
798
810
  on :fallback, respond: 'fallback message'
799
811
  end
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- WeChat [![Gem Version](https://badge.fury.io/rb/wechat.svg)](https://rubygems.org/gems/wechat) [![Build Status](https://travis-ci.com/Eric-Guo/wechat.svg)](https://travis-ci.com/github/Eric-Guo/wechat) [![Maintainability](https://api.codeclimate.com/v1/badges/12885358487c13e91e00/maintainability)](https://codeclimate.com/github/Eric-Guo/wechat/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/12885358487c13e91e00/test_coverage)](https://codeclimate.com/github/Eric-Guo/wechat/test_coverage)
1
+ WeChat [![Gem Version](https://badge.fury.io/rb/wechat.svg)](https://rubygems.org/gems/wechat) [![Build Status](https://mixtint.semaphoreci.com/badges/wechat/branches/main.svg?style=shields)](https://mixtint.semaphoreci.com/projects/wechat) [![Maintainability](https://api.codeclimate.com/v1/badges/12885358487c13e91e00/maintainability)](https://codeclimate.com/github/Eric-Guo/wechat/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/12885358487c13e91e00/test_coverage)](https://codeclimate.com/github/Eric-Guo/wechat/test_coverage)
2
2
  ======
3
3
 
4
4
  [![Join the chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Eric-Guo/wechat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@@ -828,6 +828,18 @@ class WechatsController < ActionController::Base
828
828
  request.reply.success # request is XML result hash.
829
829
  end
830
830
 
831
+ # The customer agrees to call back the chat content archive event
832
+ on :change_external_contact do |request|
833
+ # https://open.work.weixin.qq.com/api/doc/90000/90135/92005
834
+ request.reply.success # request is XML result hash.
835
+ end
836
+
837
+ # Session event callback
838
+ on :msgaudit_notify do |request|
839
+ # https://open.work.weixin.qq.com/api/doc/90000/90135/95039
840
+ request.reply.success # request is XML result hash.
841
+ end
842
+
831
843
  # If no match above will fallback to below
832
844
  on :fallback, respond: 'fallback message'
833
845
  end
data/bin/wechat CHANGED
@@ -6,8 +6,6 @@ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
6
6
  require 'thor'
7
7
  require 'wechat'
8
8
  require 'json'
9
- require 'active_support/core_ext'
10
- require 'active_support/json'
11
9
  require 'fileutils'
12
10
  require 'yaml'
13
11
  require 'cgi'
@@ -234,7 +232,7 @@ class App < Thor
234
232
 
235
233
  desc 'media_uploadnews [MPNEWS_YAML_PATH]', '上传图文消息素材'
236
234
  def media_uploadnews(mpnews_yaml_path)
237
- mpnew = YAML.load(File.read(mpnews_yaml_path))
235
+ mpnew = Wechat::ApiLoader.load_yaml(File.read(mpnews_yaml_path))
238
236
  puts wechat_api.media_uploadnews(Wechat::Message.new(MsgType: 'uploadnews').mpnews(mpnew[:articles]))
239
237
  end
240
238
 
@@ -351,13 +349,13 @@ class App < Thor
351
349
 
352
350
  desc 'menu_create [MENU_YAML_PATH]', '创建菜单'
353
351
  def menu_create(menu_yaml_path)
354
- menu = YAML.load(File.read(menu_yaml_path))
352
+ menu = Wechat::ApiLoader.load_yaml(File.read(menu_yaml_path))
355
353
  puts 'Menu created' if wechat_api.menu_create(menu)
356
354
  end
357
355
 
358
356
  desc 'menu_addconditional [CONDITIONAL_MENU_YAML_PATH]', '创建个性化菜单'
359
357
  def menu_addconditional(conditional_menu_yaml_path)
360
- conditional_menu = YAML.load(File.read(conditional_menu_yaml_path))
358
+ conditional_menu = Wechat::ApiLoader.load_yaml(File.read(conditional_menu_yaml_path))
361
359
  add_result = wechat_api.menu_addconditional(conditional_menu)
362
360
  puts "Conditional menu created: #{add_result}" if add_result
363
361
  end
@@ -410,7 +408,7 @@ class App < Thor
410
408
 
411
409
  desc 'material_add_news [MPNEWS_YAML_PATH]', '永久图文素材上传'
412
410
  def material_add_news(mpnews_yaml_path)
413
- new = YAML.load(File.read(mpnews_yaml_path))
411
+ new = Wechat::ApiLoader.load_yaml(File.read(mpnews_yaml_path))
414
412
  puts wechat_api.material_add_news(Wechat::Message.new(MsgType: 'mpnews').mpnews(new['articles']))
415
413
  end
416
414
 
@@ -481,13 +479,13 @@ class App < Thor
481
479
 
482
480
  desc 'custom_news [OPENID, NEWS_YAML_PATH]', '发送图文客服消息'
483
481
  def custom_news(openid, news_yaml_path)
484
- articles = YAML.load(File.read(news_yaml_path))
482
+ articles = Wechat::ApiLoader.load_yaml(File.read(news_yaml_path))
485
483
  puts wechat_api.custom_message_send Wechat::Message.to(openid).news(articles['articles'])
486
484
  end
487
485
 
488
486
  desc 'template_message [OPENID, TEMPLATE_YAML_PATH]', '模板消息接口'
489
487
  def template_message(openid, template_yaml_path)
490
- template = YAML.load(File.read(template_yaml_path))
488
+ template = Wechat::ApiLoader.load_yaml(File.read(template_yaml_path))
491
489
  puts wechat_api.template_message_send Wechat::Message.to(openid).template(template['template'])
492
490
  end
493
491
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_support/core_ext/object/blank'
4
+
3
5
  module Wechat
4
6
  module ApiLoader
5
7
  def self.with(options)
@@ -38,15 +40,19 @@ module Wechat
38
40
  @configs = loading_config!
39
41
  end
40
42
 
43
+ def self.load_yaml(result)
44
+ YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(result) : YAML.load(result)
45
+ end
46
+
41
47
  private_class_method def self.loading_config!
42
48
  configs = config_from_file || config_from_environment
43
49
  configs.merge!(config_from_db)
44
50
 
45
- configs.symbolize_keys!
51
+ configs.transform_keys! { |key| key.to_sym rescue key }
46
52
  configs.each do |key, cfg|
47
53
  raise "wrong wechat configuration format for #{key}" unless cfg.is_a?(Hash)
48
54
 
49
- cfg.symbolize_keys!
55
+ cfg.transform_keys! { |key| key.to_sym rescue key }
50
56
  end
51
57
 
52
58
  if defined?(::Rails)
@@ -60,8 +66,8 @@ module Wechat
60
66
  configs.each do |_, cfg|
61
67
  cfg[:timeout] ||= 20
62
68
  cfg[:qcloud_token_lifespan] ||= 7200
63
- cfg[:have_session_class] = class_exists?('WechatSession')
64
- cfg[:oauth2_cookie_duration] ||= 1.hour
69
+ cfg[:have_session_class] ||= class_exists?('WechatSession')
70
+ cfg[:oauth2_cookie_duration] ||= 3600 # 1 hour
65
71
  end
66
72
 
67
73
  # create config object using raw config data
@@ -84,6 +90,7 @@ module Wechat
84
90
  config_file = ENV['WECHAT_CONF_FILE'] || Rails.root.join('config', 'wechat.yml')
85
91
  resolve_config_file(config_file, Rails.env.to_s)
86
92
  else
93
+ require 'erb'
87
94
  rails_config_file = ENV['WECHAT_CONF_FILE'] || File.join(Dir.getwd, 'config', 'wechat.yml')
88
95
  application_config_file = File.join(Dir.getwd, 'config', 'application.yml')
89
96
  home_config_file = File.join(Dir.home, '.wechat.yml')
@@ -107,9 +114,7 @@ module Wechat
107
114
  return unless File.exist?(config_file)
108
115
 
109
116
  begin
110
- # rubocop:disable Security/YAMLLoad
111
- raw_data = YAML.load(ERB.new(File.read(config_file)).result)
112
- # rubocop:enable Security/YAMLLoad
117
+ raw_data = load_yaml(ERB.new(File.read(config_file)).result)
113
118
  rescue NameError
114
119
  puts "WARNING: If using 'Rails.application.credentials.wechat_secret!' in wechat.yml, you need run in 'rails c' and access via 'Wechat.api' or gem 'figaro' instead."
115
120
  end
@@ -148,8 +148,11 @@ module Wechat
148
148
  post 'material/batchget_material', JSON.generate(type: type, offset: offset, count: count)
149
149
  end
150
150
 
151
- def material_add(type, file)
152
- post_file 'material/add_material', file, params: { type: type }
151
+ def material_add(type, file, opts = {})
152
+ params = { type: type }
153
+ params.merge!(description: opts.slice(:title, :introduction).to_json) if type == 'video'
154
+
155
+ post_file 'material/add_material', file, params: params
153
156
  end
154
157
 
155
158
  def material_add_news(mpnews_message)
@@ -99,7 +99,7 @@ module Wechat
99
99
  form_file = file.is_a?(HTTP::FormData::File) ? file : HTTP::FormData::File.new(file)
100
100
  form_data = HTTP::FormData.create({ key: q_path,
101
101
  Signature: signature,
102
- "x-cos-security-token": x_cos_security_token,
102
+ 'x-cos-security-token': x_cos_security_token,
103
103
  'x-cos-meta-fileid': x_cos_meta_fileid,
104
104
  file: form_file })
105
105
  client.httprb.post(upload_url, form: form_data, ssl_context: client.ssl_context)
@@ -53,9 +53,9 @@ module Wechat
53
53
  yield openid, { 'openid' => openid, 'unionid' => unionid, 'access_token' => we_token }
54
54
  elsif params[:code].present? && params[:state] == oauth2_params[:state]
55
55
  access_info = wechat(account).web_access_token(params[:code])
56
- cookies.signed_or_encrypted[:we_openid] = { value: access_info['openid'], expires: self.class.oauth2_cookie_duration.from_now }
57
- cookies.signed_or_encrypted[:we_unionid] = { value: access_info['unionid'], expires: self.class.oauth2_cookie_duration.from_now }
58
- cookies.signed_or_encrypted[:we_access_token] = { value: access_info['access_token'], expires: self.class.oauth2_cookie_duration.from_now }
56
+ cookies.signed_or_encrypted[:we_openid] = { value: access_info['openid'], expires: (Time.now + self.class.oauth2_cookie_duration) }
57
+ cookies.signed_or_encrypted[:we_unionid] = { value: access_info['unionid'], expires: (Time.now + self.class.oauth2_cookie_duration) }
58
+ cookies.signed_or_encrypted[:we_access_token] = { value: access_info['access_token'], expires: (Time.now + self.class.oauth2_cookie_duration) }
59
59
  yield access_info['openid'], access_info
60
60
  else
61
61
  redirect_to generate_oauth2_url(oauth2_params), allow_other_host: true
@@ -69,8 +69,8 @@ module Wechat
69
69
  yield userid, { 'UserId' => userid, 'DeviceId' => deviceid }
70
70
  elsif params[:code].present? && params[:state] == oauth2_params[:state]
71
71
  userinfo = wechat(account).getuserinfo(params[:code])
72
- cookies.signed_or_encrypted[:we_userid] = { value: userinfo['UserId'], expires: self.class.oauth2_cookie_duration.from_now }
73
- cookies.signed_or_encrypted[:we_deviceid] = { value: userinfo['DeviceId'], expires: self.class.oauth2_cookie_duration.from_now }
72
+ cookies.signed_or_encrypted[:we_userid] = { value: userinfo['UserId'], expires: (Time.now + self.class.oauth2_cookie_duration) }
73
+ cookies.signed_or_encrypted[:we_deviceid] = { value: userinfo['DeviceId'], expires: (Time.now + self.class.oauth2_cookie_duration) }
74
74
  yield userinfo['UserId'], userinfo
75
75
  else
76
76
  redirect_to generate_oauth2_url(oauth2_params), allow_other_host: true
@@ -188,5 +188,21 @@ module Wechat
188
188
  def custom_message_send(message)
189
189
  post 'message/send', message.is_a?(Wechat::Message) ? message.agent_id(agentid).to_json : JSON.generate(message.merge(agent_id: agentid)), content_type: :json
190
190
  end
191
+
192
+ def msgaudit_get_permit_user_list(type = nil)
193
+ post 'msgaudit/get_permit_user_list', JSON.generate(type: type)
194
+ end
195
+
196
+ def msgaudit_check_single_agree(info)
197
+ post 'msgaudit/get_permit_user_list', JSON.generate(info: info)
198
+ end
199
+
200
+ def msgaudit_check_room_agree(roomid)
201
+ post 'msgaudit/check_room_agree', JSON.generate(roomid: roomid)
202
+ end
203
+
204
+ def msgaudit_groupchat(roomid)
205
+ post 'msgaudit/groupchat/get', JSON.generate(roomid: roomid)
206
+ end
191
207
  end
192
208
  end
@@ -22,7 +22,7 @@ module Wechat
22
22
  def token(tries = 2)
23
23
  # Possible two worker running, one worker refresh ticket, other unaware, so must read every time
24
24
  read_qcloud_token_from_store
25
- refresh if remain_life_seconds < @random_generator.rand(30..3 * 60)
25
+ refresh if remain_life_seconds < @random_generator.rand(30..(3 * 60))
26
26
  qcloud_token
27
27
  rescue AccessTokenExpiredError
28
28
  access_token.refresh
@@ -50,6 +50,10 @@ module Wechat
50
50
  user_defined_location_responders << config
51
51
  when :label_location
52
52
  user_defined_label_location_responders << config
53
+ when :change_external_contact
54
+ user_defined_change_external_contact_responders << config
55
+ when :msgaudit_notify
56
+ user_defined_msgaudit_notify_responders << config
53
57
  else
54
58
  user_defined_responders(message_type) << config
55
59
  end
@@ -84,6 +88,14 @@ module Wechat
84
88
  @user_defined_label_location_responders ||= []
85
89
  end
86
90
 
91
+ def user_defined_change_external_contact_responders
92
+ @user_defined_change_external_contact_responders ||= []
93
+ end
94
+
95
+ def user_defined_msgaudit_notify_responders
96
+ @user_defined_msgaudit_notify_responders ||= []
97
+ end
98
+
87
99
  def user_defined_responders(type)
88
100
  @responders ||= {}
89
101
  @responders[type] ||= []
@@ -109,6 +121,10 @@ module Wechat
109
121
  yield(* user_defined_batch_job_responders(message[:BatchJob][:JobType]), message[:BatchJob])
110
122
  elsif message[:Event] == 'location'
111
123
  yield(* user_defined_location_responders, message)
124
+ elsif message[:Event] == 'change_external_contact'
125
+ yield(* user_defined_change_external_contact_responders, message)
126
+ elsif message[:Event] == 'msgaudit_notify'
127
+ yield(* user_defined_msgaudit_notify_responders, message)
112
128
  else
113
129
  yield(* match_responders(responders, message[:Event]))
114
130
  end
@@ -171,7 +187,7 @@ module Wechat
171
187
  end
172
188
 
173
189
  def create
174
- request_msg = Wechat::Message.from_hash(post_xml)
190
+ request_msg = Wechat::Message.from_hash(post_body)
175
191
  response_msg = run_responder(request_msg)
176
192
 
177
193
  if response_msg.respond_to? :to_xml
@@ -213,6 +229,24 @@ module Wechat
213
229
  msg_encrypt)
214
230
  end
215
231
 
232
+ def post_body
233
+ if request.media_type == 'application/json'
234
+ data_hash = params
235
+
236
+ if @we_encrypt_mode && data['Encrypt'].present?
237
+ content, @we_app_id = unpack(decrypt(Base64.decode64(data['Encrypt']), @we_encoding_aes_key))
238
+ data_hash = content
239
+ end
240
+
241
+ data_hash = data_hash.to_unsafe_hash if data_hash.instance_of?(ActionController::Parameters)
242
+ HashWithIndifferentAccess.new(data_hash).tap do |msg|
243
+ msg[:Event]&.downcase!
244
+ end
245
+ else
246
+ post_xml
247
+ end
248
+ end
249
+
216
250
  def post_xml
217
251
  data = request_content
218
252
 
@@ -18,7 +18,7 @@ module Wechat
18
18
  def ticket(tries = 2)
19
19
  # Possible two worker running, one worker refresh ticket, other unaware, so must read every time
20
20
  read_ticket_from_store
21
- refresh if remain_life_seconds < @random_generator.rand(30..3 * 60)
21
+ refresh if remain_life_seconds < @random_generator.rand(30..(3 * 60))
22
22
  access_ticket
23
23
  rescue AccessTokenExpiredError
24
24
  access_token.refresh
@@ -16,7 +16,7 @@ module Wechat
16
16
  def token
17
17
  # Possible two worker running, one worker refresh token, other unaware, so must read every time
18
18
  read_token_from_store
19
- refresh if remain_life_seconds < @random_generator.rand(30..3 * 60)
19
+ refresh if remain_life_seconds < @random_generator.rand(30..(3 * 60))
20
20
  access_token
21
21
  end
22
22
 
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wechat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.2
4
+ version: 0.15.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Skinnyworm
@@ -11,31 +11,31 @@ bindir: bin
11
11
  cert_chain:
12
12
  - |
13
13
  -----BEGIN CERTIFICATE-----
14
- MIIEQDCCAqigAwIBAgIBATANBgkqhkiG9w0BAQsFADAlMSMwIQYDVQQDDBplcmlj
15
- Lmd1b2N6L0RDPWdtYWlsL0RDPWNvbTAeFw0yMDA5MDIwNDUzMjFaFw0yMTA5MDIw
16
- NDUzMjFaMCUxIzAhBgNVBAMMGmVyaWMuZ3VvY3ovREM9Z21haWwvREM9Y29tMIIB
17
- ojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAwSfWr5RlUBlv9OuNgmxjPwhU
18
- 7eoT/m7K5h0PzUaue+dtno4WqjodoCPHF6r9hh8Ys0h1VAPu3sobH2gNaL18M0CY
19
- bmq+ik6LgH5tX2E6c2BmhMuURt2y1YvIwvx0dDOlEXll9J8ZVqGyo3Rm9AIblA3/
20
- w/V5VJGCj3XY6iipNkHHDlSWSYeD2mNr0wJW8EAUFFcyRddpotxR9Es8JwUpXdj8
21
- Bc5a/OWxKvzqLVlu76zYRYuZ41+3gWNxYF9OPnp55sNtsboGh5LJSdXZOs5+gMw9
22
- gEW/KsP4GSMlqBT7SQEO5EH3qjp3aatHaMT8Fq9h3AnNESQMubMWtlPqEYyrYkli
23
- wr8A8SGiX3rCkNG0cc4zVsagtXm4csbSeaIjLV57LA2sKngI4/kw55UYlloAtGPh
24
- qNEqsPLbN/RkyS1zQjf14mQBpBt3SdxnT7YDSPIYiAPTtLuThcy3Flgh6cDX1RH7
25
- FQPZJzQ7pSb/3Edj+VBaYhpo+y4ySLxx9DOLfm6lAgMBAAGjezB5MAkGA1UdEwQC
26
- MAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBRWBfZurpq8AmvpfBq7eSA0ivhotDAf
27
- BgNVHREEGDAWgRRlcmljLmd1b2N6QGdtYWlsLmNvbTAfBgNVHRIEGDAWgRRlcmlj
28
- Lmd1b2N6QGdtYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAJ1tLpEqCXma9fFeU
29
- l6N4tEDrwYVxdbkXgOScUZBsagNlEM9vvskygivKu8AV8ffdtsg9OAuhdfAjPjX+
30
- GvGnmuoweHFTsIrOhNryqFDgvkufBczmFLOskjRuzt4NoBNgge8+xoNo+N9o/0jz
31
- GZi69Dth2i92rffuEzyFbfA9xzkjL+uSqJRJVDP5UbIWGnQ99M4GfplJZWRkmoX9
32
- 5Ek/ZVhzEz6kdZuZErloYKqjWWvFHUFAYmJd3fqKpb468yTIaL4bl4aUl2+xLdyK
33
- fPI/ZWGy2uNjffzbrhJ+Ti6qAdubkJoMIqrfbrFV1ew2Bxkp/93etXVNjAgHNmu1
34
- o3VAf3sbhnj33jAri7JYx/1MhAcJXlvpKxX9QnYouxU/RgzBF7oqcT0dJ2jWUnAI
35
- spvOK5/LPXWX6ZGc2SR8SH/s7ftYH2EkeM1VUbtemow08NdgCwJ4IG+fRQ9dcrJ+
36
- L9TbpLHvVrCe1w8duMqNeUmqj+M1iC/5Zst2vIe14QcOTuAh
14
+ MIIEODCCAqCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhlcmlj
15
+ L0RDPWNsb3VkLW1lcy9EQz1jb20wHhcNMjEwOTE1MDIxMDMzWhcNMjIwOTE1MDIx
16
+ MDMzWjAjMSEwHwYDVQQDDBhlcmljL0RDPWNsb3VkLW1lcy9EQz1jb20wggGiMA0G
17
+ CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDfweHJdAqu5+BQ6t+F923czZvUynqe
18
+ DyacqWVUbDg53oVwYxldDNqUea5hMlSs1UWj2sJ5ZHiU02ly0QVyDCw/5pFP2CKJ
19
+ ukQbw35ZoCF0t2i0/GPYAtBMxb1qUynkxDAtCefQG33lBt2u9scgE9xOIiPrxtJg
20
+ shl3XFYmOx1ol66JR540l7NBS1OHR7UV6WiJrRW1cZTcR+py7jIbo6ud/rhZVHCO
21
+ B2RTZtpH1I7ilknT1/NXMX6aw+XoNda4w+4lsrHfqKssfwJcsGMq1IbbG8illxRT
22
+ wsYLiUXNJaAacT9HVO4B0jIFPP5Me7FIkiqZZKr7uyHNQE0S/5OOUkIM0v5kkUOF
23
+ IE+A6WwVCyi05+JNcbLuxeSZnNeqQcXiqxl1RcodIJxw0VTcSE1CO2eYCsvfzLJ2
24
+ fn9fLaSA/mrosg72UV126GeXu/y/N6gf3F6ZHM2qAMZhJ9ZUR03bUVIqApsJN28g
25
+ JOkm/lV0PutN0Y2UrD0gSKxgrN24ZSsWlBECAwEAAaN3MHUwCQYDVR0TBAIwADAL
26
+ BgNVHQ8EBAMCBLAwHQYDVR0OBBYEFHHJIHijHoPxeoZDyGAvLbBalVvoMB0GA1Ud
27
+ EQQWMBSBEmVyaWNAY2xvdWQtbWVzLmNvbTAdBgNVHRIEFjAUgRJlcmljQGNsb3Vk
28
+ LW1lcy5jb20wDQYJKoZIhvcNAQELBQADggGBACYpors2s6sGEq0ErgijhSkAQRoj
29
+ W1EO3ORYYyCRFPFX1KLtUpFuXi/1rZoMoSug2Lpr+GWqt7eZIwNoryjYMbuE/sOn
30
+ sANkOvLx8x4RMlmTFe+WkPiV9NasFqNn7EBSpjqQRWRlCuh6rMiYzzxNbbNvbRT4
31
+ WMhBf7eWRpr1TBXDr51E8RtA+LG6wZuJFnKWBisgKOmpUw79f7EvIQAGS3MEWk/g
32
+ fSvIf14zM5Dw0whGa/n60jgSc5yiW3/75GXt8608BK+bs5dViJ/3ofuIhqpOvvdp
33
+ 4Oiv2zIXsfUIGAIwHN5mLwAwHty1d0s8Kt0jtJAXDUODgTuXaBj/aOqTZUUgp8Kv
34
+ 6SoPdaa0LFPbkI2eiUN1xUPelsgKz0kyRBJtkMnSKFxcCxw7VHGRGFsw0ORZodQ3
35
+ ZM9IDtdMg8E/4ujwilV8HKmgU77vVN6vSMvxx8zQFSz9a6GbdpB4egPZ++peSk/Q
36
+ uaIJtOX6M4VC6u7eZfotARKyUy6EcoN2zNqEAQ==
37
37
  -----END CERTIFICATE-----
38
- date: 2021-04-21 00:00:00.000000000 Z
38
+ date: 2022-02-16 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: activesupport
@@ -44,9 +44,6 @@ dependencies:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
46
  version: '6.0'
47
- - - "<"
48
- - !ruby/object:Gem::Version
49
- version: '7'
50
47
  type: :runtime
51
48
  prerelease: false
52
49
  version_requirements: !ruby/object:Gem::Requirement
@@ -54,9 +51,6 @@ dependencies:
54
51
  - - ">="
55
52
  - !ruby/object:Gem::Version
56
53
  version: '6.0'
57
- - - "<"
58
- - !ruby/object:Gem::Version
59
- version: '7'
60
54
  - !ruby/object:Gem::Dependency
61
55
  name: http
62
56
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +60,7 @@ dependencies:
66
60
  version: 1.0.4
67
61
  - - "<"
68
62
  - !ruby/object:Gem::Version
69
- version: '5'
63
+ version: '6'
70
64
  type: :runtime
71
65
  prerelease: false
72
66
  version_requirements: !ruby/object:Gem::Requirement
@@ -76,7 +70,7 @@ dependencies:
76
70
  version: 1.0.4
77
71
  - - "<"
78
72
  - !ruby/object:Gem::Version
79
- version: '5'
73
+ version: '6'
80
74
  - !ruby/object:Gem::Dependency
81
75
  name: nokogiri
82
76
  requirement: !ruby/object:Gem::Requirement
@@ -153,28 +147,42 @@ dependencies:
153
147
  requirements:
154
148
  - - ">="
155
149
  - !ruby/object:Gem::Version
156
- version: '6.0'
150
+ version: 7.0.0
157
151
  type: :development
158
152
  prerelease: false
159
153
  version_requirements: !ruby/object:Gem::Requirement
160
154
  requirements:
161
155
  - - ">="
162
156
  - !ruby/object:Gem::Version
163
- version: '6.0'
157
+ version: 7.0.0
164
158
  - !ruby/object:Gem::Dependency
165
159
  name: rspec-rails
166
160
  requirement: !ruby/object:Gem::Requirement
167
161
  requirements:
168
162
  - - "~>"
169
163
  - !ruby/object:Gem::Version
170
- version: '5.0'
164
+ version: '5.1'
171
165
  type: :development
172
166
  prerelease: false
173
167
  version_requirements: !ruby/object:Gem::Requirement
174
168
  requirements:
175
169
  - - "~>"
176
170
  - !ruby/object:Gem::Version
177
- version: '5.0'
171
+ version: '5.1'
172
+ - !ruby/object:Gem::Dependency
173
+ name: rspec-mocks
174
+ requirement: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - '='
177
+ - !ruby/object:Gem::Version
178
+ version: 3.10.2
179
+ type: :development
180
+ prerelease: false
181
+ version_requirements: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - '='
184
+ - !ruby/object:Gem::Version
185
+ version: 3.10.2
178
186
  - !ruby/object:Gem::Dependency
179
187
  name: sqlite3
180
188
  requirement: !ruby/object:Gem::Requirement
@@ -242,7 +250,12 @@ files:
242
250
  homepage: https://github.com/Eric-Guo/wechat
243
251
  licenses:
244
252
  - MIT
245
- metadata: {}
253
+ metadata:
254
+ bug_tracker_uri: https://github.com/Eric-Guo/wechat/issues
255
+ changelog_uri: https://github.com/Eric-Guo/wechat/releases
256
+ documentation_uri: https://github.com/Eric-Guo/wechat/tree/v0.15.1#readme
257
+ source_code_uri: https://github.com/Eric-Guo/wechat/tree/v0.15.1
258
+ rubygems_mfa_required: 'true'
246
259
  post_install_message:
247
260
  rdoc_options: []
248
261
  require_paths:
@@ -256,9 +269,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
256
269
  requirements:
257
270
  - - ">="
258
271
  - !ruby/object:Gem::Version
259
- version: '0'
272
+ version: 1.8.11
260
273
  requirements: []
261
- rubygems_version: 3.2.16
274
+ rubygems_version: 3.3.7
262
275
  signing_key:
263
276
  specification_version: 4
264
277
  summary: DSL for wechat message handling and API
metadata.gz.sig CHANGED
Binary file