wechat 0.2.0 → 0.3.0

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
  SHA1:
3
- metadata.gz: e8ac0d453ab3b09ebc953fc377d87e3e4faaa691
4
- data.tar.gz: db19e37a02a7361aed18294bc10782f276af4bb3
3
+ metadata.gz: f1a9041e7d411063724f87e3a8393a120542e1bf
4
+ data.tar.gz: 1dfa35792fa8f41f9872b00e645196115658308c
5
5
  SHA512:
6
- metadata.gz: c7ed1bc6f07ded18760833ecfc8a19f5daba4ccb8ad0d6e1ed0ce484ef58ae08558c097c37aae5b014101400786d3b76c9a572ef2ce21c3cc56a8c9a3cf71224
7
- data.tar.gz: 205d9c379adec3226e9fa51600ead4905a259133ff724eb49a56d7dec18b14304232a1e75aa92553e4c7048f83837295b2c1ce65c37b2789c40ca1f4fa5e21e3
6
+ metadata.gz: 14df5df5f86412bbb4076095903884c26a8a7942927d3afa5bdb34d2b0d4c65ff330f41fed0bdf38f970f80893117429efd48e531b6a8f9f566b169314cbfc3d
7
+ data.tar.gz: 7daf46b7df72eb76dc8508a6bbc6f575acd44e2beb214d9c81d6cb51bf551591ec0c1a172d942e89e0b65fe92fc5bd713454ccd7a4b93add0a40059500a9fc36
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.3.0 (released at 8/30/2015)
4
+
5
+ * New user group management API
6
+ * Allow transfer to customer service on fallback. #42
7
+ * Read and write access_token properly using file locking, #43
8
+
3
9
  ## v0.2.0 (released at 8/27/2015)
4
10
 
5
11
  * Add wechat enterprise account support
data/README.md CHANGED
@@ -136,18 +136,24 @@ $ wechat
136
136
  Wechat commands:
137
137
  wechat custom_image [OPENID, IMAGE_PATH] # 发送图片客服消息
138
138
  wechat custom_music [OPENID, THUMBNAIL_PATH, MUSIC_URL] # 发送音乐客服消息
139
- wechat custom_news [OPENID, NEWS_YAML_FILE] # 发送图文客服消息
139
+ wechat custom_news [OPENID, NEWS_YAML_PATH] # 发送图文客服消息
140
140
  wechat custom_text [OPENID, TEXT_MESSAGE] # 发送文字客服消息
141
141
  wechat custom_video [OPENID, VIDEO_PATH] # 发送视频客服消息
142
142
  wechat custom_voice [OPENID, VOICE_PATH] # 发送语音客服消息
143
+ wechat group_create [GROUP_NAME] # 创建分组
144
+ wechat group_delete [GROUP_ID] # 删除分组
145
+ wechat group_update [GROUP_ID, NEW_GROUP_NAME] # 修改分组名
146
+ wechat groups # 所有用户分组列表
143
147
  wechat media [MEDIA_ID, PATH] # 媒体下载
144
- wechat media_create [MEDIA_ID, PATH] # 媒体上传
148
+ wechat media_create [MEDIA_TYPE, PATH] # 媒体上传
145
149
  wechat menu # 当前菜单
146
- wechat menu_create [MENU_YAML] # 创建菜单
150
+ wechat menu_create [MENU_YAML_PATH] # 创建菜单
147
151
  wechat menu_delete # 删除菜单
148
152
  wechat message_send [OPENID, TEXT_MESSAGE] # 发送文字消息(仅企业号)
149
- wechat template_message [OPENID, TEMPLATE_YAML_FILE] # 模板消息接口
153
+ wechat template_message [OPENID, TEMPLATE_YAML_PATH] # 模板消息接口
150
154
  wechat user [OPEN_ID] # 查找关注者
155
+ wechat user_change_group [OPEN_ID, TO_GROUP_ID] # 移动用户分组
156
+ wechat user_group [OPEN_ID] # 查询用户所在分组
151
157
  wechat users # 关注者列表
152
158
  ```
153
159
 
@@ -237,7 +243,7 @@ button:
237
243
 
238
244
  ```
239
245
 
240
- 然后执行命令行
246
+ 然后执行命令行,需确保设置,权限管理中有对此应用的管理权限,否则会报[60011](http://qydev.weixin.qq.com/wiki/index.php?title=%E5%85%A8%E5%B1%80%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E)错。
241
247
 
242
248
  ```
243
249
  $ wechat menu_create menu.yaml
@@ -311,11 +317,10 @@ $ wechat template_message oCfEht9oM*********** template.yml
311
317
  然后创建Controller class, 例如
312
318
 
313
319
  ```ruby
314
-
315
320
  class WechatsController < ApplicationController
316
321
  wechat_responder
317
322
 
318
- # 默认的文字信息responder
323
+ # 默认文字信息responder
319
324
  on :text do |request, content|
320
325
  request.reply.text "echo: #{content}" #Just echo
321
326
  end
@@ -396,10 +401,25 @@ end
396
401
  - :event 响应事件消息, 可以用`:with`参数来匹配事件类型
397
402
  - :fallback 默认响应,当收到的消息无法被其他responder响应时,会使用这个responder.
398
403
 
404
+ ### 多客服消息转发
405
+
406
+ ```ruby
407
+ class WechatsController < ApplicationController
408
+ # 当无任何responder处理用户信息时,转发至客服处理。
409
+ on :fallback, respond: nil do |message|
410
+ message.reply.transfer_customer_service
411
+ end
412
+ end
413
+ ```
414
+
415
+ 注意设置了[多客服消息转发](http://dkf.qq.com/)后,不能再添加`默认文字信息responder`,否则文字消息将得不到转发。
416
+
399
417
  ## Message DSL
400
418
 
401
419
  Wechat 的核心是一个Message DSL,帮助开发者构建各种类型的消息,包括主动推送的和被动响应的。
402
420
  ....
403
421
 
404
422
 
423
+ ## 已知问题
405
424
 
425
+ 企业号接受菜单消息时,Wechat腾讯服务器无法解析部分域名,请使用IP绑定回调URL,用户的普通消息目前不受影响。
data/bin/wechat CHANGED
@@ -37,8 +37,6 @@ HELP
37
37
  end
38
38
  end
39
39
 
40
- private
41
-
42
40
  def self.loading_config
43
41
  config = {}
44
42
 
@@ -64,6 +62,26 @@ HELP
64
62
  package_name 'Wechat'
65
63
  option :toke_file, aliases: '-t', desc: 'File to store access token'
66
64
 
65
+ desc 'groups', '所有用户分组列表'
66
+ def groups
67
+ puts Helper.with(options).groups
68
+ end
69
+
70
+ desc 'group_create [GROUP_NAME]', '创建分组'
71
+ def group_create(group_name)
72
+ puts Helper.with(options).group_create(group_name)
73
+ end
74
+
75
+ desc 'group_update [GROUP_ID, NEW_GROUP_NAME]', '修改分组名'
76
+ def group_update(groupid, new_group_name)
77
+ puts Helper.with(options).group_update(groupid, new_group_name)
78
+ end
79
+
80
+ desc 'group_delete [GROUP_ID]', '删除分组'
81
+ def group_delete(groupid)
82
+ puts Helper.with(options).group_delete(groupid)
83
+ end
84
+
67
85
  desc 'users', '关注者列表'
68
86
  def users
69
87
  puts Helper.with(options).users
@@ -74,6 +92,16 @@ HELP
74
92
  puts Helper.with(options).user(open_id)
75
93
  end
76
94
 
95
+ desc 'user_group [OPEN_ID]', '查询用户所在分组'
96
+ def user_group(openid)
97
+ puts Helper.with(options).user_group(openid)
98
+ end
99
+
100
+ desc 'user_change_group [OPEN_ID, TO_GROUP_ID]', '移动用户分组'
101
+ def user_change_group(openid, to_groupid)
102
+ puts Helper.with(options).user_change_group(openid, to_groupid)
103
+ end
104
+
77
105
  desc 'menu', '当前菜单'
78
106
  def menu
79
107
  puts Helper.with(options).menu
@@ -11,7 +11,7 @@ module Wechat
11
11
 
12
12
  def token
13
13
  begin
14
- @token_data ||= JSON.parse(File.read(token_file))
14
+ @token_data ||= JSON.parse(File.read(token_file, open_args: File::LOCK_SH))
15
15
  created_at = token_data['created_at'].to_i
16
16
  expires_in = token_data['expires_in'].to_i
17
17
  if Time.now.to_i - created_at >= expires_in - 3 * 60
@@ -26,7 +26,7 @@ module Wechat
26
26
  def refresh
27
27
  data = client.get('token', params: { grant_type: 'client_credential', appid: appid, secret: secret })
28
28
  data.merge!(created_at: Time.now.to_i)
29
- File.open(token_file, 'w') { |f| f.write(data.to_json) } if valid_token(data)
29
+ File.write(token_file, data.to_json) if valid_token(data)
30
30
  @token_data = data
31
31
  end
32
32
 
@@ -15,6 +15,22 @@ class Wechat::Api
15
15
  @jsapi_ticket = Wechat::JsapiTicket.new(@client, @access_token, jsapi_ticket_file)
16
16
  end
17
17
 
18
+ def groups
19
+ get('groups/get')
20
+ end
21
+
22
+ def group_create(group_name)
23
+ post 'groups/create', JSON.generate(group: { name: group_name })
24
+ end
25
+
26
+ def group_update(groupid, new_group_name)
27
+ post 'groups/update', JSON.generate(group: { id: groupid, name: new_group_name })
28
+ end
29
+
30
+ def group_delete(groupid)
31
+ post 'groups/delete', JSON.generate(group: { id: groupid })
32
+ end
33
+
18
34
  def users(nextid = nil)
19
35
  params = { params: { next_openid: nextid } } if nextid.present?
20
36
  get('user/get', params || {})
@@ -24,6 +40,14 @@ class Wechat::Api
24
40
  get('user/info', params: { openid: openid })
25
41
  end
26
42
 
43
+ def user_group(openid)
44
+ post 'groups/getid', JSON.generate(openid: openid)
45
+ end
46
+
47
+ def user_change_group(openid, to_groupid)
48
+ post 'groups/members/update', JSON.generate(openid: openid, to_groupid: to_groupid)
49
+ end
50
+
27
51
  def menu
28
52
  get('menu/get')
29
53
  end
@@ -49,7 +49,7 @@ module Wechat
49
49
  # }
50
50
  def signature(url)
51
51
  timestamp = Time.now.to_i
52
- noncestr = generate_noncestr
52
+ noncestr = SecureRandom.base64(16)
53
53
  params = {
54
54
  noncestr: noncestr,
55
55
  timestamp: timestamp,
@@ -70,17 +70,5 @@ module Wechat
70
70
  raise "Response didn't have ticket" if ticket.blank?
71
71
  ticket
72
72
  end
73
-
74
- # 生成随机字符串
75
- # @param Integer length 长度, 默认为16
76
- # @return String
77
- def generate_noncestr(length = 16)
78
- chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
79
- str = ''
80
- 1.upto(length) do |i|
81
- str += chars[rand(chars.length)]
82
- end
83
- str
84
- end
85
73
  end
86
74
  end
@@ -49,8 +49,9 @@ module Wechat
49
49
  Wechat.api.media(message_hash[:MediaId])
50
50
 
51
51
  when :location
52
- message_hash.slice(:Location_X, :Location_Y, :Scale, :Label).inject({}) { |results, value|
53
- results[value[0].to_s.underscore.to_sym] = value[1]; results }
52
+ message_hash.slice(:Location_X, :Location_Y, :Scale, :Label).each_with_object({}) do |value, results|
53
+ results[value[0].to_s.underscore.to_sym] = value[1]
54
+ end
54
55
  else
55
56
  raise "Don't know how to parse message as #{type}"
56
57
  end
@@ -68,6 +69,10 @@ module Wechat
68
69
  update(MsgType: 'text', Content: content)
69
70
  end
70
71
 
72
+ def transfer_customer_service
73
+ update(MsgType: 'transfer_customer_service')
74
+ end
75
+
71
76
  def image(media_id)
72
77
  update(MsgType: 'image', Image: { MediaId: media_id })
73
78
  end
@@ -56,20 +56,19 @@ module Wechat
56
56
  private
57
57
 
58
58
  def match_responders(responders, value)
59
- matched = responders.inject({ scoped: nil, general: nil }) do |matched, responder|
59
+ matched = responders.each_with_object({}) do |responder, memo|
60
60
  condition = responder[:with]
61
61
 
62
62
  if condition.nil?
63
- matched[:general] ||= [responder, value]
64
- next matched
63
+ memo[:general] ||= [responder, value]
64
+ next
65
65
  end
66
66
 
67
67
  if condition.is_a? Regexp
68
- matched[:scoped] ||= [responder] + $LAST_MATCH_INFO.captures if value =~ condition
68
+ memo[:scoped] ||= [responder] + $LAST_MATCH_INFO.captures if value =~ condition
69
69
  else
70
- matched[:scoped] ||= [responder, value] if value == condition
70
+ memo[:scoped] ||= [responder, value] if value == condition
71
71
  end
72
- matched
73
72
  end
74
73
  matched[:scoped] || matched[:general]
75
74
  end
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.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Skinnyworm
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-08-26 00:00:00.000000000 Z
12
+ date: 2015-08-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails