wechat 0.6.3 → 0.6.4
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 +4 -4
- data/CHANGELOG.md +8 -1
- data/README.md +45 -12
- data/bin/wechat +213 -248
- data/lib/generators/wechat/templates/app/controllers/wechats_controller.rb +1 -1
- data/lib/wechat.rb +2 -27
- data/lib/wechat/api_base.rb +1 -3
- data/lib/wechat/api_loader.rb +65 -0
- data/lib/wechat/message.rb +4 -0
- data/lib/wechat/responder.rb +5 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 66ecda4306d9d5a9fde71ae0477d99682fd443a0
|
4
|
+
data.tar.gz: 13b71709c26cc139d1be233a0449741eb404adbc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85fb0b5a0745542d5c9e9ec09095125c393192da41335592c58561353c6e5d91cc7eeb112a61c2456ac68cda0768391ae33a65a98aa7f05292abd2cfad78a2fc
|
7
|
+
data.tar.gz: 09d88487602a96a6bc1d9b3c7dad3a5f9199c1d8df1f40e96d7b5a5ec6692cc894b4fb071de20ac27a1df42f6536cb17fe691651a044c876c4c117bc80602f17
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,15 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v0.6.4 (released at 11/16/2015)
|
4
|
+
|
5
|
+
* Command mode now display different command set based on enterprise/public account setting
|
6
|
+
* Move config logic in command/wechat to ApiLoader class
|
7
|
+
* Unsubscribe can only reply plain text 'success' #68
|
8
|
+
* Fix 404 qrcode download problem, by @huangxiangdan #69
|
9
|
+
|
3
10
|
## v0.6.3 (released at 11/14/2015)
|
4
11
|
|
5
|
-
* Official testing and support public encrypt mode, also fix one cipher bug, many thanks to hlltc #67
|
12
|
+
* Official testing and support public encrypt mode, also fix one cipher bug, many thanks to @hlltc #67
|
6
13
|
* hlltc report public account FILE_BASE no longer needs, clean code #67
|
7
14
|
* Media command line reflect recent Tecent json schema change. #67
|
8
15
|
|
data/README.md
CHANGED
@@ -157,6 +157,46 @@ wechat gems 内部不会检查权限。但因公众号类型不同,和微信
|
|
157
157
|
|
158
158
|
## 使用命令行
|
159
159
|
|
160
|
+
根据企业号和公众号配置不同,wechat提供了的命令行命令。
|
161
|
+
|
162
|
+
#### 公众号命令行
|
163
|
+
|
164
|
+
```
|
165
|
+
$ wechat
|
166
|
+
Wechat commands:
|
167
|
+
wechat callbackip # 获取微信服务器IP地址
|
168
|
+
wechat custom_image [OPENID, IMAGE_PATH] # 发送图片客服消息
|
169
|
+
wechat custom_music [OPENID, THUMBNAIL_PATH, MUSIC_URL] # 发送音乐客服消息
|
170
|
+
wechat custom_news [OPENID, NEWS_YAML_PATH] # 发送图文客服消息
|
171
|
+
wechat custom_text [OPENID, TEXT_MESSAGE] # 发送文字客服消息
|
172
|
+
wechat custom_video [OPENID, VIDEO_PATH] # 发送视频客服消息
|
173
|
+
wechat custom_voice [OPENID, VOICE_PATH] # 发送语音客服消息
|
174
|
+
wechat group_create [GROUP_NAME] # 创建分组
|
175
|
+
wechat group_delete [GROUP_ID] # 删除分组
|
176
|
+
wechat group_update [GROUP_ID, NEW_GROUP_NAME] # 修改分组名
|
177
|
+
wechat groups # 查询所有分组
|
178
|
+
wechat material [MEDIA_ID, PATH] # 永久媒体下载
|
179
|
+
wechat material_add [MEDIA_TYPE, PATH] # 永久媒体上传
|
180
|
+
wechat material_count # 获取永久素材总数
|
181
|
+
wechat material_delete [MEDIA_ID] # 删除永久素材
|
182
|
+
wechat material_list [TYPE, OFFSET, COUNT] # 获取永久素材列表
|
183
|
+
wechat media [MEDIA_ID, PATH] # 媒体下载
|
184
|
+
wechat media_create [MEDIA_TYPE, PATH] # 媒体上传
|
185
|
+
wechat menu # 当前菜单
|
186
|
+
wechat menu_create [MENU_YAML_PATH] # 创建菜单
|
187
|
+
wechat menu_delete # 删除菜单
|
188
|
+
wechat qrcode_create_limit_scene [SCENE_ID_OR_STR] # 请求永久二维码
|
189
|
+
wechat qrcode_create_scene [SCENE_ID, EXPIRE_SECONDS] # 请求临时二维码
|
190
|
+
wechat qrcode_download [TICKET, QR_CODE_PIC_PATH] # 通过ticket下载二维码
|
191
|
+
wechat template_message [OPENID, TEMPLATE_YAML_PATH] # 模板消息接口
|
192
|
+
wechat user [OPEN_ID] # 获取用户基本信息
|
193
|
+
wechat user_change_group [OPEN_ID, TO_GROUP_ID] # 移动用户分组
|
194
|
+
wechat user_group [OPEN_ID] # 查询用户所在分组
|
195
|
+
wechat user_update_remark [OPEN_ID, REMARK] # 设置备注名
|
196
|
+
wechat users # 关注者列表
|
197
|
+
```
|
198
|
+
|
199
|
+
#### 企业号命令行
|
160
200
|
```
|
161
201
|
$ wechat
|
162
202
|
Wechat commands:
|
@@ -177,11 +217,7 @@ Wechat commands:
|
|
177
217
|
wechat department [DEPARTMENT_ID] # 获取部门列表
|
178
218
|
wechat department_create [NAME, PARENT_ID] # 创建部门
|
179
219
|
wechat department_delete [DEPARTMENT_ID] # 删除部门
|
180
|
-
wechat department_update [DEPARTMENT_ID, NAME] # 更新部门
|
181
|
-
wechat group_create [GROUP_NAME] # 创建分组
|
182
|
-
wechat group_delete [GROUP_ID] # 删除分组
|
183
|
-
wechat group_update [GROUP_ID, NEW_GROUP_NAME] # 修改分组名
|
184
|
-
wechat groups # 所有用户分组列表
|
220
|
+
wechat department_update [DEPARTMENT_ID, NAME] # 更新部门
|
185
221
|
wechat invite_user [USER_ID] # 邀请成员关注
|
186
222
|
wechat material [MEDIA_ID, PATH] # 永久媒体下载
|
187
223
|
wechat material_add [MEDIA_TYPE, PATH] # 永久媒体上传
|
@@ -193,7 +229,7 @@ Wechat commands:
|
|
193
229
|
wechat menu # 当前菜单
|
194
230
|
wechat menu_create [MENU_YAML_PATH] # 创建菜单
|
195
231
|
wechat menu_delete # 删除菜单
|
196
|
-
wechat message_send [OPENID, TEXT_MESSAGE] # 发送文字消息
|
232
|
+
wechat message_send [OPENID, TEXT_MESSAGE] # 发送文字消息
|
197
233
|
wechat qrcode_create_limit_scene [SCENE_ID_OR_STR] # 请求永久二维码
|
198
234
|
wechat qrcode_create_scene [SCENE_ID, EXPIRE_SECONDS] # 请求临时二维码
|
199
235
|
wechat qrcode_download [TICKET, QR_CODE_PIC_PATH] # 通过ticket下载二维码
|
@@ -201,21 +237,18 @@ Wechat commands:
|
|
201
237
|
wechat tag_add_department [TAG_ID, PARTY_IDS] # 增加标签部门
|
202
238
|
wechat tag_add_user [TAG_ID, USER_IDS] # 增加标签成员
|
203
239
|
wechat tag_create [TAGNAME, TAG_ID] # 创建标签
|
204
|
-
wechat tag_del_user [TAG_ID, USER_IDS] # 删除标签成员
|
205
240
|
wechat tag_del_department [TAG_ID, PARTY_IDS] # 删除标签部门
|
241
|
+
wechat tag_del_user [TAG_ID, USER_IDS] # 删除标签成员
|
206
242
|
wechat tag_delete [TAG_ID] # 删除标签
|
207
243
|
wechat tag_update [TAG_ID, TAGNAME] # 更新标签名字
|
208
244
|
wechat tags # 获取标签列表
|
209
245
|
wechat template_message [OPENID, TEMPLATE_YAML_PATH] # 模板消息接口
|
210
246
|
wechat user [OPEN_ID] # 获取用户基本信息
|
211
|
-
wechat user_batchdelete [USER_ID_LIST] # 批量删除成员
|
212
|
-
wechat user_change_group [OPEN_ID, TO_GROUP_ID] # 移动用户分组
|
247
|
+
wechat user_batchdelete [USER_ID_LIST] # 批量删除成员
|
213
248
|
wechat user_delete [USER_ID] # 删除成员
|
214
|
-
wechat user_group [OPEN_ID] # 查询用户所在分组
|
215
249
|
wechat user_list [DEPARTMENT_ID] # 获取部门成员详情
|
216
250
|
wechat user_simplelist [DEPARTMENT_ID] # 获取部门成员
|
217
251
|
wechat user_update_remark [OPEN_ID, REMARK] # 设置备注名
|
218
|
-
wechat users # 关注者列表
|
219
252
|
```
|
220
253
|
|
221
254
|
### 使用场景
|
@@ -449,7 +482,7 @@ class WechatsController < ApplicationController
|
|
449
482
|
|
450
483
|
# 当用户取消关注订阅
|
451
484
|
on :event, with: 'unsubscribe' do |request|
|
452
|
-
request.reply.
|
485
|
+
request.reply.success # user can not receive this message
|
453
486
|
end
|
454
487
|
|
455
488
|
# 成员进入应用的事件推送
|
data/bin/wechat
CHANGED
@@ -12,316 +12,284 @@ require 'active_support/core_ext'
|
|
12
12
|
require 'active_support/json'
|
13
13
|
require 'fileutils'
|
14
14
|
require 'yaml'
|
15
|
+
require 'wechat/api_loader'
|
15
16
|
|
16
17
|
class App < Thor
|
17
|
-
|
18
|
-
|
19
|
-
config = loading_config
|
20
|
-
|
21
|
-
appid = config['appid']
|
22
|
-
secret = config['secret']
|
23
|
-
corpid = config['corpid']
|
24
|
-
corpsecret = config['corpsecret']
|
25
|
-
token_file = options[:toke_file] || config['access_token'] || '/var/tmp/wechat_access_token'
|
26
|
-
agentid = config['agentid']
|
27
|
-
skip_verify_ssl = config['skip_verify_ssl']
|
28
|
-
|
29
|
-
if appid.present? && secret.present? && token_file.present?
|
30
|
-
Wechat::Api.new(appid, secret, token_file, skip_verify_ssl)
|
31
|
-
elsif corpid.present? && corpsecret.present? && token_file.present?
|
32
|
-
Wechat::CorpApi.new(corpid, corpsecret, token_file, agentid, skip_verify_ssl)
|
33
|
-
else
|
34
|
-
puts <<-HELP
|
35
|
-
Need create ~/.wechat.yml with wechat appid and secret
|
36
|
-
or running at rails root folder so wechat can read config/wechat.yml
|
37
|
-
HELP
|
38
|
-
exit 1
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.loading_config
|
43
|
-
config = {}
|
44
|
-
|
45
|
-
rails_config_file = File.join(Dir.getwd, 'config/wechat.yml')
|
46
|
-
home_config_file = File.join(Dir.home, '.wechat.yml')
|
47
|
-
|
48
|
-
if File.exist?(rails_config_file)
|
49
|
-
config = YAML.load(ERB.new(File.read(rails_config_file)).result)['default']
|
50
|
-
if config.present? && (config['appid'] || config['corpid'])
|
51
|
-
puts 'Using rails project config/wechat.yml default setting...'
|
52
|
-
else
|
53
|
-
config = {}
|
54
|
-
end
|
55
|
-
end
|
18
|
+
package_name 'Wechat'
|
19
|
+
option :toke_file, aliases: '-t', desc: 'File to store access token'
|
56
20
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
21
|
+
attr_reader :wechat_api_client
|
22
|
+
no_commands do
|
23
|
+
def wechat_api
|
24
|
+
@wechat_api_client ||= Wechat::ApiLoader.with(options)
|
61
25
|
end
|
62
26
|
end
|
63
27
|
|
64
|
-
package_name 'Wechat'
|
65
|
-
option :toke_file, aliases: '-t', desc: 'File to store access token'
|
66
|
-
|
67
28
|
desc 'callbackip', '获取微信服务器IP地址'
|
68
29
|
def callbackip
|
69
|
-
puts
|
30
|
+
puts wechat_api.callbackip
|
70
31
|
end
|
71
32
|
|
72
33
|
desc 'qrcode_download [TICKET, QR_CODE_PIC_PATH]', '通过ticket下载二维码'
|
73
34
|
def qrcode_download(ticket, qr_code_pic_path)
|
74
|
-
tmp_file =
|
35
|
+
tmp_file = wechat_api.qrcode(ticket)
|
75
36
|
FileUtils.mv(tmp_file.path, qr_code_pic_path)
|
76
37
|
puts 'File downloaded'
|
77
38
|
end
|
78
39
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
puts Helper.with(options).group_create(group_name)
|
87
|
-
end
|
88
|
-
|
89
|
-
desc 'group_update [GROUP_ID, NEW_GROUP_NAME]', '修改分组名'
|
90
|
-
def group_update(groupid, new_group_name)
|
91
|
-
puts Helper.with(options).group_update(groupid, new_group_name)
|
92
|
-
end
|
40
|
+
if Wechat::ApiLoader.with(options).is_a?(Wechat::CorpApi)
|
41
|
+
desc 'department_create [NAME, PARENT_ID]', '创建部门'
|
42
|
+
method_option :parentid, aliases: '-p', desc: '父亲部门id。根部门id为1'
|
43
|
+
def department_create(name)
|
44
|
+
api_opts = options.slice(:parentid)
|
45
|
+
puts wechat_api.department_create(name, api_opts[:parentid] || '1')
|
46
|
+
end
|
93
47
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
48
|
+
desc 'department_delete [DEPARTMENT_ID]', '删除部门'
|
49
|
+
def department_delete(departmentid)
|
50
|
+
puts wechat_api.department_delete(departmentid)
|
51
|
+
end
|
98
52
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
53
|
+
desc 'department_update [DEPARTMENT_ID, NAME]', '更新部门'
|
54
|
+
method_option :parentid, aliases: '-p', desc: '父亲部门id。根部门id为1', default: nil
|
55
|
+
method_option :order, aliases: '-o', desc: '在父部门中的次序值。order值小的排序靠前。', default: nil
|
56
|
+
def department_update(departmentid, name)
|
57
|
+
api_opts = options.slice(:parentid, :order)
|
58
|
+
puts wechat_api.department_update(departmentid, name, api_opts[:parentid], api_opts[:order])
|
59
|
+
end
|
105
60
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
61
|
+
desc 'department [DEPARTMENT_ID]', '获取部门列表'
|
62
|
+
def department(departmentid = 0)
|
63
|
+
r = wechat_api.department(departmentid)
|
64
|
+
puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
|
65
|
+
puts 'Or# pid id name'
|
66
|
+
r['department'].sort_by { |d| d['order'].to_i + d['parentid'].to_i * 1000 } .each do |i|
|
67
|
+
puts format('%3d %3d %3d %s', i['order'], i['parentid'], i['id'], i['name'])
|
68
|
+
end
|
69
|
+
end
|
110
70
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
api_opts = options.slice(:parentid, :order)
|
116
|
-
puts Helper.with(options).department_update(departmentid, name, api_opts[:parentid], api_opts[:order])
|
117
|
-
end
|
71
|
+
desc 'user_delete [USER_ID]', '删除成员'
|
72
|
+
def user_delete(userid)
|
73
|
+
puts wechat_api.user_delete(userid)
|
74
|
+
end
|
118
75
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
|
123
|
-
puts 'Or# pid id name'
|
124
|
-
r['department'].sort_by { |d| d['order'].to_i + d['parentid'].to_i * 1000 } .each do |i|
|
125
|
-
puts format('%3d %3d %3d %s', i['order'], i['parentid'], i['id'], i['name'])
|
76
|
+
desc 'user_batchdelete [USER_ID_LIST]', '批量删除成员'
|
77
|
+
def user_batchdelete(useridlist)
|
78
|
+
puts wechat_api.user_batchdelete(useridlist.split(','))
|
126
79
|
end
|
127
|
-
end
|
128
80
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
81
|
+
desc 'user_simplelist [DEPARTMENT_ID]', '获取部门成员'
|
82
|
+
method_option :fetch_child, aliases: '-c', desc: '是否递归获取子部门下面的成员', default: 1
|
83
|
+
method_option :status, aliases: '-s', desc: '0 获取全部成员,1 获取已关注成员列表,2 获取禁用成员列表,4 获取未关注成员列表。status可叠加', default: 0
|
84
|
+
def user_simplelist(departmentid = 0)
|
85
|
+
api_opts = options.slice(:fetch_child, :status)
|
86
|
+
|
87
|
+
r = wechat_api.user_simplelist(departmentid, api_opts[:fetch_child], api_opts[:status])
|
88
|
+
puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
|
89
|
+
puts " userid Name #{' ' * 20} department_ids"
|
90
|
+
r['userlist'].sort_by { |d| d['userid'] } .each do |i|
|
91
|
+
puts format('%7s %-25s %-14s', i['userid'], i['name'], i['department'])
|
92
|
+
end
|
93
|
+
end
|
134
94
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
95
|
+
desc 'user_list [DEPARTMENT_ID]', '获取部门成员详情'
|
96
|
+
method_option :fetch_child, aliases: '-c', desc: '是否递归获取子部门下面的成员', default: 0
|
97
|
+
method_option :status, aliases: '-s', desc: '0 获取全部成员,1 获取已关注成员列表,2 获取禁用成员列表,4 获取未关注成员列表。status可叠加', default: 0
|
98
|
+
def user_list(departmentid = 0)
|
99
|
+
api_opts = options.slice(:fetch_child, :status)
|
100
|
+
|
101
|
+
r = wechat_api.user_list(departmentid, api_opts[:fetch_child], api_opts[:status])
|
102
|
+
puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
|
103
|
+
puts " userid Name #{' ' * 15} department_ids position mobile #{' ' * 5}gender email #{' ' * 10}weixinid status extattr"
|
104
|
+
r['userlist'].sort_by { |d| d['userid'] } .each do |i|
|
105
|
+
puts format('%7s %-20s %-14s %-8s %-11s %-6s %-15s %-15s %-6s %s',
|
106
|
+
i['userid'], i['name'], i['department'], i['position'], i['mobile'],
|
107
|
+
i['gender'], i['email'], i['weixinid'], i['status'], i['extattr'])
|
108
|
+
end
|
140
109
|
end
|
141
|
-
end
|
142
110
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
api_opts = options.slice(:fetch_child, :status)
|
111
|
+
desc 'invite_user [USER_ID]', '邀请成员关注'
|
112
|
+
def invite_user(userid)
|
113
|
+
puts wechat_api.invite_user(userid)
|
114
|
+
end
|
148
115
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
puts
|
154
|
-
i['userid'], i['name'], i['department'], i['position'], i['mobile'],
|
155
|
-
i['gender'], i['email'], i['weixinid'], i['status'], i['extattr'])
|
116
|
+
desc 'tag_create [TAGNAME, TAG_ID]', '创建标签'
|
117
|
+
method_option :tagid, aliases: '-id', desc: '整型,指定此参数时新增的标签会生成对应的标签id,不指定时则以目前最大的id自增'
|
118
|
+
def tag_create(name)
|
119
|
+
api_opts = options.slice(:tagid)
|
120
|
+
puts wechat_api.tag_create(name, api_opts[:tagid])
|
156
121
|
end
|
157
|
-
end
|
158
122
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
puts Helper.with(options).tag_create(name, api_opts[:tagid])
|
164
|
-
end
|
123
|
+
desc 'tag_update [TAG_ID, TAGNAME]', '更新标签名字'
|
124
|
+
def tag_update(tagid, tagname)
|
125
|
+
puts wechat_api.tag_update(tagid, tagname)
|
126
|
+
end
|
165
127
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
128
|
+
desc 'tag_delete [TAG_ID]', '删除标签'
|
129
|
+
def tag_delete(tagid)
|
130
|
+
puts wechat_api.tag_delete(tagid)
|
131
|
+
end
|
170
132
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
133
|
+
desc 'tag [TAG_ID]', '获取标签成员'
|
134
|
+
def tag(tagid)
|
135
|
+
puts wechat_api.tag(tagid)
|
136
|
+
end
|
175
137
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
138
|
+
desc 'tag_add_user [TAG_ID, USER_IDS]', '增加标签成员'
|
139
|
+
def tag_add_user(tagid, userids)
|
140
|
+
puts wechat_api.tag_add_user(tagid, userids.split(','))
|
141
|
+
end
|
180
142
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
143
|
+
desc 'tag_add_department [TAG_ID, PARTY_IDS]', '增加标签部门'
|
144
|
+
def tag_add_department(tagid, partyids)
|
145
|
+
puts wechat_api.tag_add_user(tagid, nil, partyids.split(','))
|
146
|
+
end
|
185
147
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
148
|
+
desc 'tag_del_user [TAG_ID, USER_IDS]', '删除标签成员'
|
149
|
+
def tag_del_user(tagid, userids)
|
150
|
+
puts wechat_api.tag_del_user(tagid, userids.split(','))
|
151
|
+
end
|
190
152
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
153
|
+
desc 'tag_del_department [TAG_ID, PARTY_IDS]', '删除标签部门'
|
154
|
+
def tag_del_department(tagid, partyids)
|
155
|
+
puts wechat_api.tag_del_user(tagid, nil, partyids.split(','))
|
156
|
+
end
|
195
157
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
158
|
+
desc 'tags', '获取标签列表'
|
159
|
+
def tags
|
160
|
+
puts wechat_api.tags
|
161
|
+
end
|
200
162
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
163
|
+
desc 'batch_job_result [JOB_ID]', '获取异步任务结果'
|
164
|
+
def batch_job_result(job_id)
|
165
|
+
puts wechat_api.batch_job_result(job_id)
|
166
|
+
end
|
205
167
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
|
210
|
-
puts 'ag# name square_logo_url round_logo_url'
|
211
|
-
r['agentlist'].sort_by { |d| d['agentid'] } .each do |i|
|
212
|
-
puts format('%3d %s %s %s', i['agentid'], i['name'], i['square_logo_url'], i['round_logo_url'])
|
168
|
+
desc 'batch_replaceparty [BATCH_PARTY_CSV_MEDIA_ID]', '全量覆盖部门'
|
169
|
+
def batch_replaceparty(batch_party_csv_media_id)
|
170
|
+
puts wechat_api.batch_replaceparty(batch_party_csv_media_id)
|
213
171
|
end
|
214
|
-
end
|
215
172
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
puts "name: #{r['name']}"
|
221
|
-
puts "description: #{r['description']}"
|
222
|
-
puts " square_logo_url: #{r['square_logo_url']}"
|
223
|
-
puts " round_logo_url: #{r['round_logo_url']}"
|
224
|
-
puts "allow_userinfos: #{r['allow_userinfos']}"
|
225
|
-
puts "allow_partys: #{r['allow_partys']}"
|
226
|
-
puts "allow_tags: #{r['allow_tags']}"
|
227
|
-
puts "close: #{r['close']} redirect_domain: #{r['redirect_domain']}"
|
228
|
-
puts "report_location_flag: #{r['report_location_flag']} isreportuser: #{r['isreportuser']} isreportenter: #{r['isreportenter']}"
|
229
|
-
end
|
173
|
+
desc 'batch_syncuser [SYNC_USER_CSV_MEDIA_ID]', '增量更新成员'
|
174
|
+
def batch_syncuser(sync_user_csv_media_id)
|
175
|
+
puts wechat_api.batch_syncuser(sync_user_csv_media_id)
|
176
|
+
end
|
230
177
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
178
|
+
desc 'batch_replaceuser [BATCH_USER_CSV_MEDIA_ID]', '全量覆盖成员'
|
179
|
+
def batch_replaceuser(batch_user_csv_media_id)
|
180
|
+
puts wechat_api.batch_replaceuser(batch_user_csv_media_id)
|
181
|
+
end
|
235
182
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
183
|
+
desc 'convert_to_openid [USER_ID]', 'userid转换成openid'
|
184
|
+
def convert_to_openid(userid)
|
185
|
+
puts wechat_api.convert_to_openid(userid)
|
186
|
+
end
|
240
187
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
188
|
+
desc 'agent_list', '获取应用概况列表'
|
189
|
+
def agent_list
|
190
|
+
r = wechat_api.agent_list
|
191
|
+
puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
|
192
|
+
puts 'ag# name square_logo_url round_logo_url'
|
193
|
+
r['agentlist'].sort_by { |d| d['agentid'] } .each do |i|
|
194
|
+
puts format('%3d %s %s %s', i['agentid'], i['name'], i['square_logo_url'], i['round_logo_url'])
|
195
|
+
end
|
196
|
+
end
|
245
197
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
198
|
+
desc 'agent [AGENT_ID]', '获取企业号应用详情'
|
199
|
+
def agent(agentid)
|
200
|
+
r = wechat_api.agent(agentid)
|
201
|
+
puts "agentid: #{r['agentid']} errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
|
202
|
+
puts "name: #{r['name']}"
|
203
|
+
puts "description: #{r['description']}"
|
204
|
+
puts " square_logo_url: #{r['square_logo_url']}"
|
205
|
+
puts " round_logo_url: #{r['round_logo_url']}"
|
206
|
+
puts "allow_userinfos: #{r['allow_userinfos']}"
|
207
|
+
puts "allow_partys: #{r['allow_partys']}"
|
208
|
+
puts "allow_tags: #{r['allow_tags']}"
|
209
|
+
puts "close: #{r['close']} redirect_domain: #{r['redirect_domain']}"
|
210
|
+
puts "report_location_flag: #{r['report_location_flag']} isreportuser: #{r['isreportuser']} isreportenter: #{r['isreportenter']}"
|
211
|
+
end
|
250
212
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
213
|
+
desc 'message_send [OPENID, TEXT_MESSAGE]', '发送文字消息'
|
214
|
+
def message_send(openid, text_message)
|
215
|
+
puts wechat_api.message_send openid, text_message
|
216
|
+
end
|
217
|
+
else
|
218
|
+
desc 'group_create [GROUP_NAME]', '创建分组'
|
219
|
+
def group_create(group_name)
|
220
|
+
puts wechat_api.group_create(group_name)
|
221
|
+
end
|
255
222
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
223
|
+
desc 'groups', '查询所有分组'
|
224
|
+
def groups
|
225
|
+
puts wechat_api.groups
|
226
|
+
end
|
260
227
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
228
|
+
desc 'user_group [OPEN_ID]', '查询用户所在分组'
|
229
|
+
def user_group(openid)
|
230
|
+
puts wechat_api.user_group(openid)
|
231
|
+
end
|
265
232
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
233
|
+
desc 'group_update [GROUP_ID, NEW_GROUP_NAME]', '修改分组名'
|
234
|
+
def group_update(groupid, new_group_name)
|
235
|
+
puts wechat_api.group_update(groupid, new_group_name)
|
236
|
+
end
|
270
237
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
238
|
+
desc 'user_change_group [OPEN_ID, TO_GROUP_ID]', '移动用户分组'
|
239
|
+
def user_change_group(openid, to_groupid)
|
240
|
+
puts wechat_api.user_change_group(openid, to_groupid)
|
241
|
+
end
|
275
242
|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
243
|
+
desc 'group_delete [GROUP_ID]', '删除分组'
|
244
|
+
def group_delete(groupid)
|
245
|
+
puts wechat_api.group_delete(groupid)
|
246
|
+
end
|
280
247
|
|
281
|
-
|
282
|
-
|
283
|
-
|
248
|
+
desc 'users', '关注者列表'
|
249
|
+
def users
|
250
|
+
puts wechat_api.users
|
251
|
+
end
|
284
252
|
end
|
285
253
|
|
286
|
-
desc '
|
287
|
-
def
|
288
|
-
puts
|
254
|
+
desc 'user [OPEN_ID]', '获取用户基本信息'
|
255
|
+
def user(open_id)
|
256
|
+
puts wechat_api.user(open_id)
|
289
257
|
end
|
290
258
|
|
291
259
|
desc 'user_update_remark [OPEN_ID, REMARK]', '设置备注名'
|
292
260
|
def user_update_remark(openid, remark)
|
293
|
-
puts
|
261
|
+
puts wechat_api.user_update_remark(openid, remark)
|
294
262
|
end
|
295
263
|
|
296
264
|
desc 'qrcode_create_scene [SCENE_ID, EXPIRE_SECONDS]', '请求临时二维码'
|
297
265
|
def qrcode_create_scene(scene_id, expire_seconds = 604800)
|
298
|
-
puts
|
266
|
+
puts wechat_api.qrcode_create_scene(scene_id, expire_seconds)
|
299
267
|
end
|
300
268
|
|
301
269
|
desc 'qrcode_create_limit_scene [SCENE_ID_OR_STR]', '请求永久二维码'
|
302
270
|
def qrcode_create_limit_scene(scene_id_or_str)
|
303
|
-
puts
|
271
|
+
puts wechat_api.qrcode_create_limit_scene(scene_id_or_str)
|
304
272
|
end
|
305
273
|
|
306
274
|
desc 'menu', '当前菜单'
|
307
275
|
def menu
|
308
|
-
puts
|
276
|
+
puts wechat_api.menu
|
309
277
|
end
|
310
278
|
|
311
279
|
desc 'menu_delete', '删除菜单'
|
312
280
|
def menu_delete
|
313
|
-
puts 'Menu deleted' if
|
281
|
+
puts 'Menu deleted' if wechat_api.menu_delete
|
314
282
|
end
|
315
283
|
|
316
284
|
desc 'menu_create [MENU_YAML_PATH]', '创建菜单'
|
317
285
|
def menu_create(menu_yaml_path)
|
318
286
|
menu = YAML.load(File.read(menu_yaml_path))
|
319
|
-
puts 'Menu created' if
|
287
|
+
puts 'Menu created' if wechat_api.menu_create(menu)
|
320
288
|
end
|
321
289
|
|
322
290
|
desc 'media [MEDIA_ID, PATH]', '媒体下载'
|
323
291
|
def media(media_id, path)
|
324
|
-
tmp_file =
|
292
|
+
tmp_file = wechat_api.media(media_id)
|
325
293
|
FileUtils.mv(tmp_file.path, path)
|
326
294
|
puts 'File downloaded'
|
327
295
|
end
|
@@ -329,12 +297,12 @@ HELP
|
|
329
297
|
desc 'media_create [MEDIA_TYPE, PATH]', '媒体上传'
|
330
298
|
def media_create(type, path)
|
331
299
|
file = File.new(path)
|
332
|
-
puts
|
300
|
+
puts wechat_api.media_create(type, file)
|
333
301
|
end
|
334
302
|
|
335
303
|
desc 'material [MEDIA_ID, PATH]', '永久媒体下载'
|
336
304
|
def material(media_id, path)
|
337
|
-
tmp_file =
|
305
|
+
tmp_file = wechat_api.material(media_id)
|
338
306
|
FileUtils.mv(tmp_file.path, path)
|
339
307
|
puts 'File downloaded'
|
340
308
|
end
|
@@ -342,46 +310,43 @@ HELP
|
|
342
310
|
desc 'material_add [MEDIA_TYPE, PATH]', '永久媒体上传'
|
343
311
|
def material_add(type, path)
|
344
312
|
file = File.new(path)
|
345
|
-
puts
|
313
|
+
puts wechat_api.material_add(type, file)
|
346
314
|
end
|
347
315
|
|
348
316
|
desc 'material_delete [MEDIA_ID]', '删除永久素材'
|
349
317
|
def material_delete(media_id)
|
350
|
-
puts
|
318
|
+
puts wechat_api.material_delete(media_id)
|
351
319
|
end
|
352
320
|
|
353
321
|
desc 'material_count', '获取永久素材总数'
|
354
322
|
def material_count
|
355
|
-
puts
|
323
|
+
puts wechat_api.material_count
|
356
324
|
end
|
357
325
|
|
358
326
|
desc 'material_list [TYPE, OFFSET, COUNT]', '获取永久素材列表'
|
359
327
|
def material_list(type, offset, count)
|
360
|
-
r =
|
328
|
+
r = wechat_api.material_list(type, offset, count)
|
361
329
|
if %w(image voice video file).include?(type)
|
362
330
|
puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']} total_count: #{r['total_count']} item_count: #{r['item_count']}"
|
363
|
-
|
364
|
-
puts "#{i['media_id']} #{i['
|
331
|
+
if wechat_api.is_a?(Wechat::CorpApi)
|
332
|
+
r['itemlist'].each { |i| puts "#{i['media_id']} #{i['filename']} #{Time.at(i['update_time'].to_i)}" }
|
333
|
+
else
|
334
|
+
r['item'].each { |i| puts "#{i['media_id']} #{i['name']} #{Time.at(i['update_time'].to_i)}" }
|
365
335
|
end
|
366
336
|
else
|
367
337
|
puts r
|
368
338
|
end
|
369
339
|
end
|
370
340
|
|
371
|
-
desc 'message_send [OPENID, TEXT_MESSAGE]', '发送文字消息(仅企业号)'
|
372
|
-
def message_send(openid, text_message)
|
373
|
-
puts Helper.with(options).message_send openid, text_message
|
374
|
-
end
|
375
|
-
|
376
341
|
desc 'custom_text [OPENID, TEXT_MESSAGE]', '发送文字客服消息'
|
377
342
|
def custom_text(openid, text_message)
|
378
|
-
puts
|
343
|
+
puts wechat_api.custom_message_send Wechat::Message.to(openid).text(text_message)
|
379
344
|
end
|
380
345
|
|
381
346
|
desc 'custom_image [OPENID, IMAGE_PATH]', '发送图片客服消息'
|
382
347
|
def custom_image(openid, image_path)
|
383
348
|
file = File.new(image_path)
|
384
|
-
api =
|
349
|
+
api = wechat_api
|
385
350
|
|
386
351
|
media_id = api.media_create('image', file)['media_id']
|
387
352
|
puts api.custom_message_send Wechat::Message.to(openid).image(media_id)
|
@@ -390,7 +355,7 @@ HELP
|
|
390
355
|
desc 'custom_voice [OPENID, VOICE_PATH]', '发送语音客服消息'
|
391
356
|
def custom_voice(openid, voice_path)
|
392
357
|
file = File.new(voice_path)
|
393
|
-
api =
|
358
|
+
api = wechat_api
|
394
359
|
|
395
360
|
media_id = api.media_create('voice', file)['media_id']
|
396
361
|
puts api.custom_message_send Wechat::Message.to(openid).voice(media_id)
|
@@ -401,7 +366,7 @@ HELP
|
|
401
366
|
method_option :description, aliases: '-d', desc: '视频描述'
|
402
367
|
def custom_video(openid, video_path)
|
403
368
|
file = File.new(video_path)
|
404
|
-
api =
|
369
|
+
api = wechat_api
|
405
370
|
|
406
371
|
api_opts = options.slice(:title, :description)
|
407
372
|
media_id = api.media_create('video', file)['media_id']
|
@@ -414,7 +379,7 @@ HELP
|
|
414
379
|
method_option :HQ_music_url, aliases: '-u', desc: '高质量音乐URL链接'
|
415
380
|
def custom_music(openid, thumbnail_path, music_url)
|
416
381
|
file = File.new(thumbnail_path)
|
417
|
-
api =
|
382
|
+
api = wechat_api
|
418
383
|
|
419
384
|
api_opts = options.slice(:title, :description, :HQ_music_url)
|
420
385
|
thumb_media_id = api.media_create('thumb', file)['thumb_media_id']
|
@@ -424,13 +389,13 @@ HELP
|
|
424
389
|
desc 'custom_news [OPENID, NEWS_YAML_PATH]', '发送图文客服消息'
|
425
390
|
def custom_news(openid, news_yaml_path)
|
426
391
|
articles = YAML.load(File.read(news_yaml_path))
|
427
|
-
puts
|
392
|
+
puts wechat_api.custom_message_send Wechat::Message.to(openid).news(articles['articles'])
|
428
393
|
end
|
429
394
|
|
430
395
|
desc 'template_message [OPENID, TEMPLATE_YAML_PATH]', '模板消息接口'
|
431
396
|
def template_message(openid, template_yaml_path)
|
432
397
|
template = YAML.load(File.read(template_yaml_path))
|
433
|
-
puts
|
398
|
+
puts wechat_api.template_message_send Wechat::Message.to(openid).template(template['template'])
|
434
399
|
end
|
435
400
|
end
|
436
401
|
|
@@ -81,7 +81,7 @@ class WechatsController < ApplicationController
|
|
81
81
|
end
|
82
82
|
|
83
83
|
on :event, with: 'unsubscribe' do |request|
|
84
|
-
request.reply.
|
84
|
+
request.reply.success # user can not receive this message
|
85
85
|
end
|
86
86
|
|
87
87
|
# When user enter the app / agent app
|
data/lib/wechat.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'wechat/api_loader'
|
1
2
|
require 'wechat/api'
|
2
3
|
require 'wechat/corp_api'
|
3
4
|
require 'action_controller/wechat_responder'
|
@@ -19,18 +20,7 @@ module Wechat
|
|
19
20
|
attr_reader :config
|
20
21
|
|
21
22
|
def self.config
|
22
|
-
@config ||=
|
23
|
-
if defined? Rails
|
24
|
-
config_file = Rails.root.join('config/wechat.yml')
|
25
|
-
config = YAML.load(ERB.new(File.new(config_file).read).result)[Rails.env] if File.exist?(config_file)
|
26
|
-
end
|
27
|
-
|
28
|
-
config ||= config_from_environment
|
29
|
-
config.symbolize_keys!
|
30
|
-
config[:access_token] ||= Rails.root.join('tmp/access_token').to_s
|
31
|
-
config[:jsapi_ticket] ||= Rails.root.join('tmp/jsapi_ticket').to_s
|
32
|
-
OpenStruct.new(config)
|
33
|
-
end
|
23
|
+
@config ||= ApiLoader.loading_config
|
34
24
|
end
|
35
25
|
|
36
26
|
def self.api
|
@@ -40,19 +30,4 @@ module Wechat
|
|
40
30
|
@api ||= Api.new(config.appid, config.secret, config.access_token, config.skip_verify_ssl, config.jsapi_ticket)
|
41
31
|
end
|
42
32
|
end
|
43
|
-
|
44
|
-
private
|
45
|
-
|
46
|
-
def self.config_from_environment
|
47
|
-
{ appid: ENV['WECHAT_APPID'],
|
48
|
-
secret: ENV['WECHAT_SECRET'],
|
49
|
-
corpid: ENV['WECHAT_CORPID'],
|
50
|
-
corpsecret: ENV['WECHAT_CORPSECRET'],
|
51
|
-
agentid: ENV['WECHAT_AGENTID'],
|
52
|
-
token: ENV['WECHAT_TOKEN'],
|
53
|
-
access_token: ENV['WECHAT_ACCESS_TOKEN'],
|
54
|
-
encrypt_mode: ENV['WECHAT_ENCRYPT_MODE'],
|
55
|
-
skip_verify_ssl: ENV['WECHAT_SKIP_VERIFY_SSL'],
|
56
|
-
encoding_aes_key: ENV['WECHAT_ENCODING_AES_KEY'] }
|
57
|
-
end
|
58
33
|
end
|
data/lib/wechat/api_base.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'cgi'
|
2
|
-
|
3
1
|
module Wechat
|
4
2
|
class ApiBase
|
5
3
|
attr_reader :access_token, :client
|
@@ -11,7 +9,7 @@ module Wechat
|
|
11
9
|
end
|
12
10
|
|
13
11
|
def qrcode(ticket)
|
14
|
-
client.get 'showqrcode', ticket:
|
12
|
+
client.get 'showqrcode', params: { ticket: ticket }, base: MP_BASE, as: :file
|
15
13
|
end
|
16
14
|
|
17
15
|
def media(media_id)
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Wechat
|
2
|
+
class ApiLoader
|
3
|
+
def self.with(options)
|
4
|
+
c = loading_config
|
5
|
+
|
6
|
+
token_file = options[:toke_file] || c.access_token || '/var/tmp/wechat_access_token'
|
7
|
+
|
8
|
+
if c.appid && c.secret && token_file.present?
|
9
|
+
Wechat::Api.new(c.appid, c.secret, token_file, c.skip_verify_ssl)
|
10
|
+
elsif c.corpid && c.corpsecret && token_file.present?
|
11
|
+
Wechat::CorpApi.new(c.corpid, c.corpsecret, token_file, c.agentid, c.skip_verify_ssl)
|
12
|
+
else
|
13
|
+
puts <<-HELP
|
14
|
+
Need create ~/.wechat.yml with wechat appid and secret
|
15
|
+
or running at rails root folder so wechat can read config/wechat.yml
|
16
|
+
HELP
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.loading_config
|
22
|
+
if defined?(::Rails)
|
23
|
+
config_file = Rails.root.join('config/wechat.yml')
|
24
|
+
config = YAML.load(ERB.new(File.read(config_file)).result)[Rails.env] if File.exist?(config_file)
|
25
|
+
else
|
26
|
+
rails_config_file = File.join(Dir.getwd, 'config/wechat.yml')
|
27
|
+
home_config_file = File.join(Dir.home, '.wechat.yml')
|
28
|
+
|
29
|
+
if File.exist?(rails_config_file)
|
30
|
+
config = YAML.load(ERB.new(File.read(rails_config_file)).result)['default']
|
31
|
+
if config.present? && (config['appid'] || config['corpid'])
|
32
|
+
puts 'Using rails project config/wechat.yml default setting...'
|
33
|
+
else
|
34
|
+
config = {}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
if config.blank? && File.exist?(home_config_file)
|
39
|
+
config = YAML.load ERB.new(File.read(home_config_file)).result
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
config ||= config_from_environment
|
44
|
+
if defined?(::Rails)
|
45
|
+
config[:access_token] ||= Rails.root.join('tmp/access_token').to_s
|
46
|
+
config[:jsapi_ticket] ||= Rails.root.join('tmp/jsapi_ticket').to_s
|
47
|
+
end
|
48
|
+
config.symbolize_keys!
|
49
|
+
OpenStruct.new(config)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.config_from_environment
|
53
|
+
{ appid: ENV['WECHAT_APPID'],
|
54
|
+
secret: ENV['WECHAT_SECRET'],
|
55
|
+
corpid: ENV['WECHAT_CORPID'],
|
56
|
+
corpsecret: ENV['WECHAT_CORPSECRET'],
|
57
|
+
agentid: ENV['WECHAT_AGENTID'],
|
58
|
+
token: ENV['WECHAT_TOKEN'],
|
59
|
+
access_token: ENV['WECHAT_ACCESS_TOKEN'],
|
60
|
+
encrypt_mode: ENV['WECHAT_ENCRYPT_MODE'],
|
61
|
+
skip_verify_ssl: ENV['WECHAT_SKIP_VERIFY_SSL'],
|
62
|
+
encoding_aes_key: ENV['WECHAT_ENCODING_AES_KEY'] }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/wechat/message.rb
CHANGED
data/lib/wechat/responder.rb
CHANGED
@@ -200,7 +200,11 @@ module Wechat
|
|
200
200
|
end
|
201
201
|
|
202
202
|
def process_response(response)
|
203
|
-
|
203
|
+
if response[:MsgType] == 'success'
|
204
|
+
msg = 'success'
|
205
|
+
else
|
206
|
+
msg = response.to_xml
|
207
|
+
end
|
204
208
|
|
205
209
|
if self.class.encrypt_mode
|
206
210
|
encrypt = Base64.strict_encode64(encrypt(pack(msg, @app_id), self.class.encoding_aes_key))
|
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.6.
|
4
|
+
version: 0.6.4
|
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-11-
|
12
|
+
date: 2015-11-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -39,6 +39,20 @@ dependencies:
|
|
39
39
|
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: 1.6.0
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: thor
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
42
56
|
- !ruby/object:Gem::Dependency
|
43
57
|
name: rest-client
|
44
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -101,6 +115,7 @@ files:
|
|
101
115
|
- lib/wechat/access_token.rb
|
102
116
|
- lib/wechat/api.rb
|
103
117
|
- lib/wechat/api_base.rb
|
118
|
+
- lib/wechat/api_loader.rb
|
104
119
|
- lib/wechat/cipher.rb
|
105
120
|
- lib/wechat/client.rb
|
106
121
|
- lib/wechat/corp_api.rb
|