dingtalk-cli 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +3 -0
- data/Gemfile.lock +45 -0
- data/README.md +56 -14
- data/bin/dt +4 -0
- data/lib/DingTalk/command.rb +30 -5
- data/lib/DingTalk/command/action_card.rb +60 -0
- data/lib/DingTalk/command/feed_card.rb +51 -0
- data/lib/DingTalk/command/link.rb +48 -0
- data/lib/DingTalk/command/markdown.rb +53 -0
- data/lib/DingTalk/command/text.rb +50 -0
- data/lib/DingTalk/core/action_card.rb +102 -0
- data/lib/DingTalk/core/base_message.rb +32 -0
- data/lib/DingTalk/core/feed_card.rb +65 -0
- data/lib/DingTalk/core/link.rb +43 -0
- data/lib/DingTalk/core/markdown.rb +52 -0
- data/lib/DingTalk/core/text.rb +48 -0
- data/lib/DingTalk/utils/http_helper.rb +74 -0
- data/lib/DingTalk/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7439813349565e2f9216e7f6052fbdf12d0aaffbe7515747aa6e84b6df5a87e
|
4
|
+
data.tar.gz: 657930f4050eaffeb6b47588a730af548edaebad473271fd279f95aa2c172d4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e43f8923c3e66ada748e9ea5254263f8244f08d9d2db960297cdca1e176df241697fec65a8134fbd0fe48da90df1b75eb0a84db3d13bbe23bba272f7f28d672d
|
7
|
+
data.tar.gz: cfb488bd25d6d0e1db6942dc8f6a13f7da6ffa2c3a91caf7fbae911cac6ed8a76657a2974d7573bc78138f00551c3e6d7cd22f9f5476b2cf2ece54cf657164fa
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
dingtalk-cli (0.0.4)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
claide (1.0.3)
|
10
|
+
colored2 (3.1.2)
|
11
|
+
diff-lcs (1.3)
|
12
|
+
faraday (0.17.3)
|
13
|
+
multipart-post (>= 1.2, < 3)
|
14
|
+
faraday_middleware (0.14.0)
|
15
|
+
faraday (>= 0.7.4, < 1.0)
|
16
|
+
multipart-post (2.1.1)
|
17
|
+
rake (12.3.3)
|
18
|
+
rspec (3.9.0)
|
19
|
+
rspec-core (~> 3.9.0)
|
20
|
+
rspec-expectations (~> 3.9.0)
|
21
|
+
rspec-mocks (~> 3.9.0)
|
22
|
+
rspec-core (3.9.1)
|
23
|
+
rspec-support (~> 3.9.1)
|
24
|
+
rspec-expectations (3.9.1)
|
25
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
26
|
+
rspec-support (~> 3.9.0)
|
27
|
+
rspec-mocks (3.9.1)
|
28
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
29
|
+
rspec-support (~> 3.9.0)
|
30
|
+
rspec-support (3.9.2)
|
31
|
+
|
32
|
+
PLATFORMS
|
33
|
+
ruby
|
34
|
+
|
35
|
+
DEPENDENCIES
|
36
|
+
claide (~> 1.0, >= 1.0.3)
|
37
|
+
colored2 (~> 3.1, >= 3.1.2)
|
38
|
+
dingtalk-cli!
|
39
|
+
faraday
|
40
|
+
faraday_middleware (~> 0.14.0)
|
41
|
+
rake (~> 12.0)
|
42
|
+
rspec (~> 3.0)
|
43
|
+
|
44
|
+
BUNDLED WITH
|
45
|
+
2.1.2
|
data/README.md
CHANGED
@@ -1,41 +1,83 @@
|
|
1
|
-
[![Build Status](https://travis-ci.
|
2
|
-
|
1
|
+
[![Build Status](https://travis-ci.com/iospai/dingtalk.svg?branch=master)](https://travis-ci.com/iospai/dingtalk)
|
3
2
|
|
4
3
|
# DingTalk
|
5
4
|
|
6
|
-
|
5
|
+
群机器人是钉钉群的高级扩展功能。群机器人可以将第三方服务的信息聚合到群聊中,实现自动化的信息同步。目前,大部分机器人在添加后,还需要进行Webhook配置,才可正常使用(配置说明详见操作流程中的帮助链接)。
|
6
|
+
|
7
|
+
例如:
|
8
|
+
通过聚合GitHub,GitLab等源码管理服务,实现源码更新同步。
|
9
|
+
通过聚合Trello,JIRA等项目协调服务,实现项目信息同步。
|
7
10
|
|
8
|
-
|
11
|
+
另外,群机器人支持Webhook协议的自定义接入,支持更多可能性,例如:你可将运维报警通过自定义机器人聚合到钉钉群实现提醒功能。
|
9
12
|
|
10
|
-
|
13
|
+
[前往详细文档](https://ding-doc.dingtalk.com/doc#/serverapi2/krgddi)
|
14
|
+
## 安装
|
11
15
|
|
12
|
-
|
16
|
+
添加下面代码到您的应用工程的`Gemfile`文件:
|
13
17
|
|
14
18
|
```ruby
|
15
19
|
gem 'dingtalk-cli'
|
16
20
|
```
|
17
21
|
|
18
|
-
|
22
|
+
然后执行:
|
19
23
|
|
20
24
|
$ bundle install
|
21
25
|
|
22
|
-
|
26
|
+
或者,通过下面命令安装,可以运行可执行文件`dingtalk`
|
23
27
|
|
24
28
|
$ gem install dingtalk-cli
|
25
29
|
|
26
|
-
##
|
30
|
+
## 使用
|
31
|
+
|
32
|
+
```shell script
|
33
|
+
Usage:
|
34
|
+
|
35
|
+
$ dingtalk COMMAND
|
36
|
+
|
37
|
+
自定义钉钉群机器人 DingTalk for CLI
|
27
38
|
|
28
|
-
|
39
|
+
Commands:
|
40
|
+
|
41
|
+
+ action-card 发送整体跳转ActionCard类型消息
|
42
|
+
+ feed-card 发送FeedCard类型消息
|
43
|
+
+ link 发送link类型消息
|
44
|
+
+ markdown 发送link类型消息
|
45
|
+
+ text 发送text类型消息
|
46
|
+
|
47
|
+
Options:
|
48
|
+
|
49
|
+
--token=`token` 自定义机器人access_token
|
50
|
+
--secret=`secret` 自定义机器人加签密钥
|
51
|
+
--version Show the version of the tool
|
52
|
+
--verbose Show more debugging information
|
53
|
+
--no-ansi Show output without ANSI codes
|
54
|
+
--help Show help banner of specified command
|
55
|
+
```
|
56
|
+
其中,`token`和`secret`有以下三种配置方式
|
57
|
+
#### 方式一、参数配置
|
58
|
+
通过`--token`和`--secret`拼接的方式配置。
|
59
|
+
|
60
|
+
#### 方式二、临时环境变量配置
|
61
|
+
直接执行,`DINGTALK_TOKEN="xxxxxxx" DINGTALK_SECRET="xxxxxxx" dingtalk ` + 其他配置
|
62
|
+
|
63
|
+
#### 方式三、全局环境变量配置
|
64
|
+
配置在`~/.bash_profile`文件。
|
65
|
+
```shell script
|
66
|
+
echo 'export DINGTALK_TOKEN="xxxxxxx"' >> ~/.bash_profile;
|
67
|
+
echo 'export DINGTALK_SECRET="xxxxxxx"' >> ~/.bash_profile;
|
68
|
+
source ~/.bash_profile
|
69
|
+
```
|
29
70
|
|
30
|
-
|
71
|
+
> 说明:配置的优先级为:参数配置 > 临时环境变量配置 > 全局环境变量配置
|
72
|
+
## 开发
|
31
73
|
|
32
74
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
33
75
|
|
34
76
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
35
77
|
|
36
|
-
##
|
78
|
+
## 贡献
|
37
79
|
|
38
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
80
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/iospai/dingtalk. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/iospai/DingTalk/blob/master/CODE_OF_CONDUCT.md).
|
39
81
|
|
40
82
|
|
41
83
|
## License
|
@@ -44,4 +86,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
44
86
|
|
45
87
|
## Code of Conduct
|
46
88
|
|
47
|
-
Everyone interacting in the DingTalk project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
89
|
+
Everyone interacting in the DingTalk project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/iospai/DingTalk/blob/master/CODE_OF_CONDUCT.md).
|
data/bin/dt
ADDED
data/lib/DingTalk/command.rb
CHANGED
@@ -1,9 +1,34 @@
|
|
1
1
|
require 'claide'
|
2
2
|
|
3
3
|
module DingTalk
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
class Command < CLAide::Command
|
5
|
+
|
6
|
+
require 'DingTalk/command/text'
|
7
|
+
require 'DingTalk/command/link'
|
8
|
+
require 'DingTalk/command/markdown'
|
9
|
+
require 'DingTalk/command/action_card'
|
10
|
+
require 'DingTalk/command/feed_card'
|
11
|
+
|
12
|
+
self.abstract_command = true
|
13
|
+
self.command = 'dingtalk'
|
14
|
+
self.version = DingTalk::VERSION
|
15
|
+
self.description = '自定义钉钉群机器人 DingTalk for CLI'
|
16
|
+
|
17
|
+
def self.options
|
18
|
+
[
|
19
|
+
%w(--token=`token` 自定义机器人access_token),
|
20
|
+
%w(--secret=`secret` 自定义机器人加签密钥),
|
21
|
+
].concat(super)
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(argv)
|
25
|
+
@token = argv.option('token')
|
26
|
+
@secret = argv.option('secret')
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
def run
|
31
|
+
# puts '开始执行 DingTalk for CLI'
|
8
32
|
end
|
9
|
-
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'colored2'
|
2
|
+
|
3
|
+
require_relative '../utils/http_helper'
|
4
|
+
|
5
|
+
module DingTalk
|
6
|
+
class Command
|
7
|
+
class ActionCard < Command
|
8
|
+
self.summary = '发送整体跳转ActionCard类型消息'
|
9
|
+
|
10
|
+
self.description = <<-DESC
|
11
|
+
发送text类型消息,消息内容为`CONTENT`
|
12
|
+
DESC
|
13
|
+
|
14
|
+
self.arguments = [
|
15
|
+
CLAide::Argument.new('content', true)
|
16
|
+
]
|
17
|
+
|
18
|
+
def self.options
|
19
|
+
[
|
20
|
+
%w(--title=`title` 消息内容。如果太长只会部分展示。),
|
21
|
+
%w(--buttons=`buttons` JSON数组\ 按钮的信息`[{ "title": "xxx", "url": "https://xxx.com", "pic": "https://xxx.com/" }]`),
|
22
|
+
%w(--orientation [可选]按钮是否按钮横向排列),
|
23
|
+
%w(--hide [可选]是否隐藏发消息者头像),
|
24
|
+
].concat(super)
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(argv)
|
28
|
+
@content = argv.shift_argument
|
29
|
+
@title = argv.option('title');
|
30
|
+
buttons_str = argv.option('buttons');
|
31
|
+
@buttons = []
|
32
|
+
if buttons_str then
|
33
|
+
begin
|
34
|
+
JSON.parser(buttons_str).each do | button |
|
35
|
+
@buttons << DingTalk::Message::ActionCardButton.new(button.title, button.url) if button.title && button.url
|
36
|
+
end
|
37
|
+
rescue
|
38
|
+
ensure
|
39
|
+
end
|
40
|
+
end
|
41
|
+
@btn_orientation = argv.flag?('orientation', false)
|
42
|
+
@hide_avatar = argv.flag?('hide', false)
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
46
|
+
def validate!
|
47
|
+
super
|
48
|
+
help! 'A message title is required.' unless @title
|
49
|
+
help! 'A message content is required.' unless @content
|
50
|
+
help! 'A message button is required.' unless @buttons.size < 1
|
51
|
+
end
|
52
|
+
|
53
|
+
def run
|
54
|
+
res = DingTalk::HttpHelper.send_action_card2(@title, @text, @buttons, @btn_orientation, @hide_avatar, @token, @secret)
|
55
|
+
puts res.bold.green
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'colored2'
|
2
|
+
|
3
|
+
require_relative '../utils/http_helper'
|
4
|
+
|
5
|
+
module DingTalk
|
6
|
+
class Command
|
7
|
+
class FeedCard < Command
|
8
|
+
self.summary = '发送FeedCard类型消息'
|
9
|
+
|
10
|
+
self.description = <<-DESC
|
11
|
+
发送text类型消息,消息内容为`LINK Array JSON`,格式:`[{ "title": "xxx", "pic": "https://xxx.com/icon.png", "link": "https://xxx.com/" }]`
|
12
|
+
DESC
|
13
|
+
|
14
|
+
self.arguments = [
|
15
|
+
CLAide::Argument.new('JSONArray', true)
|
16
|
+
]
|
17
|
+
|
18
|
+
def self.options
|
19
|
+
[
|
20
|
+
].concat(super)
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(argv)
|
24
|
+
links_str = argv.shift_argument
|
25
|
+
@links = []
|
26
|
+
if links_str then
|
27
|
+
begin
|
28
|
+
JSON.parser(links_str).each do | link |
|
29
|
+
@links << DingTalk::Message::FeedCardLink.new(link.title, link.pic, link.link) if link.title && link.pic && link.link
|
30
|
+
end
|
31
|
+
rescue
|
32
|
+
ensure
|
33
|
+
end
|
34
|
+
end
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
def validate!
|
39
|
+
super
|
40
|
+
help! 'A message button is required.' unless @links.size < 1
|
41
|
+
end
|
42
|
+
|
43
|
+
def run
|
44
|
+
res = DingTalk::HttpHelper.send_feed_card(@links, @token, @secret)
|
45
|
+
puts res.bold.green
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'colored2'
|
2
|
+
|
3
|
+
require_relative '../utils/http_helper'
|
4
|
+
|
5
|
+
module DingTalk
|
6
|
+
class Command
|
7
|
+
class Link < Command
|
8
|
+
self.summary = '发送link类型消息'
|
9
|
+
|
10
|
+
self.description = <<-DESC
|
11
|
+
发送text类型消息,消息内容为`CONTENT`
|
12
|
+
DESC
|
13
|
+
|
14
|
+
self.arguments = [
|
15
|
+
CLAide::Argument.new('content', true)
|
16
|
+
]
|
17
|
+
|
18
|
+
def self.options
|
19
|
+
[
|
20
|
+
%w(--title=`title` 消息内容。如果太长只会部分展示。),
|
21
|
+
%w(--link=`link` 点击消息跳转的URL。),
|
22
|
+
%w(--pic=`pic` 图片URL。),
|
23
|
+
].concat(super)
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(argv)
|
27
|
+
@content = argv.shift_argument
|
28
|
+
@title = argv.option('title');
|
29
|
+
@message_url = argv.option('link');
|
30
|
+
@pic_url = argv.option('pic');
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
def validate!
|
35
|
+
super
|
36
|
+
help! 'A message title is required.' unless @title
|
37
|
+
help! 'A message content is required.' unless @content
|
38
|
+
help! 'A message link is required.' unless @message_url
|
39
|
+
end
|
40
|
+
|
41
|
+
def run
|
42
|
+
res = DingTalk::HttpHelper.send_link(@title, @text, @pic_url, @message_url, @token, @secret)
|
43
|
+
puts res.bold.green
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'colored2'
|
2
|
+
|
3
|
+
require_relative '../utils/http_helper'
|
4
|
+
|
5
|
+
module DingTalk
|
6
|
+
class Command
|
7
|
+
class Markdown < Command
|
8
|
+
self.summary = '发送link类型消息'
|
9
|
+
|
10
|
+
self.description = <<-DESC
|
11
|
+
发送text类型消息,消息内容为`CONTENT`
|
12
|
+
DESC
|
13
|
+
|
14
|
+
self.arguments = [
|
15
|
+
CLAide::Argument.new('content', true)
|
16
|
+
]
|
17
|
+
|
18
|
+
def self.options
|
19
|
+
[
|
20
|
+
%w(--title=`title` 消息内容。如果太长只会部分展示。),
|
21
|
+
%w(--at=`at` [可选]被@人的手机号(在content里添加@人的手机号),多个手机号以英文逗号(`,`)分隔。),
|
22
|
+
%w(--all [可选]@所有人),
|
23
|
+
].concat(super)
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(argv)
|
27
|
+
@content = argv.shift_argument
|
28
|
+
@title = argv.option('title');
|
29
|
+
at_str = argv.option('at');
|
30
|
+
@at_mobiles = []
|
31
|
+
if at_str then
|
32
|
+
at_str.split(%r{,\s*}).each do |at_mobile|
|
33
|
+
@at_mobiles << at_mobile unless at_mobile.nil? || at_mobile.empty?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
@is_at_all = argv.flag?('all', false)
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate!
|
41
|
+
super
|
42
|
+
help! 'A message title is required.' unless @title
|
43
|
+
help! 'A message content is required.' unless @content
|
44
|
+
end
|
45
|
+
|
46
|
+
def run
|
47
|
+
res = DingTalk::HttpHelper.send_markdown(@title, @content, @at_mobiles, @is_at_all, @token, @secret)
|
48
|
+
puts res.bold.green
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'colored2'
|
2
|
+
|
3
|
+
require_relative '../utils/http_helper'
|
4
|
+
|
5
|
+
module DingTalk
|
6
|
+
class Command
|
7
|
+
class Text < Command
|
8
|
+
self.summary = '发送text类型消息'
|
9
|
+
|
10
|
+
self.description = <<-DESC
|
11
|
+
发送text类型消息,消息内容为`CONTENT`
|
12
|
+
DESC
|
13
|
+
|
14
|
+
self.arguments = [
|
15
|
+
CLAide::Argument.new('content', true)
|
16
|
+
]
|
17
|
+
|
18
|
+
def self.options
|
19
|
+
[
|
20
|
+
%w(--at=`at` [可选]被@人的手机号(在content里添加@人的手机号),多个手机号以英文逗号(`,`)分隔。),
|
21
|
+
%w(--all [可选]@所有人),
|
22
|
+
].concat(super)
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(argv)
|
26
|
+
@content = argv.shift_argument
|
27
|
+
at_str = argv.option('at');
|
28
|
+
@at_mobiles = []
|
29
|
+
if at_str then
|
30
|
+
at_str.split(%r{,\s*}).each do |at_mobile|
|
31
|
+
@at_mobiles << at_mobile unless at_mobile.nil? || at_mobile.empty?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
@is_at_all = argv.flag?('all', false)
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
def validate!
|
39
|
+
super
|
40
|
+
help! 'A message content is required.' unless @content
|
41
|
+
end
|
42
|
+
|
43
|
+
def run
|
44
|
+
res = DingTalk::HttpHelper.send_text(@content, @at_mobiles, @is_at_all, @token, @secret)
|
45
|
+
puts res.bold.green
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module DingTalk
|
2
|
+
module Message
|
3
|
+
# 消息类型及数据格式 - 整体跳转ActionCard类型
|
4
|
+
# {
|
5
|
+
# "actionCard": {
|
6
|
+
# "title": "乔布斯 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身",
|
7
|
+
# "text": "![screenshot](@lADOpwk3K80C0M0FoA)
|
8
|
+
# ### 乔布斯 20 年前想打造的苹果咖啡厅
|
9
|
+
# Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
|
10
|
+
# "hideAvatar": "0",
|
11
|
+
# "btnOrientation": "0",
|
12
|
+
# "singleTitle" : "阅读全文",
|
13
|
+
# "singleURL" : "https://www.dingtalk.com/"
|
14
|
+
# },
|
15
|
+
# "msgtype": "actionCard"
|
16
|
+
# }
|
17
|
+
#
|
18
|
+
# 消息类型及数据格式 - 独立跳转ActionCard类型
|
19
|
+
# {
|
20
|
+
# "actionCard": {
|
21
|
+
# "title": "乔布斯 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身",
|
22
|
+
# "text": "![screenshot](@lADOpwk3K80C0M0FoA)
|
23
|
+
# ### 乔布斯 20 年前想打造的苹果咖啡厅
|
24
|
+
# Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
|
25
|
+
# "hideAvatar": "0",
|
26
|
+
# "btnOrientation": "0",
|
27
|
+
# "btns": [
|
28
|
+
# {
|
29
|
+
# "title": "内容不错",
|
30
|
+
# "actionURL": "https://www.dingtalk.com/"
|
31
|
+
# },
|
32
|
+
# {
|
33
|
+
# "title": "不感兴趣",
|
34
|
+
# "actionURL": "https://www.dingtalk.com/"
|
35
|
+
# }
|
36
|
+
# ]
|
37
|
+
# },
|
38
|
+
# "msgtype": "actionCard"
|
39
|
+
# }
|
40
|
+
class ActionCard < BaseMessage
|
41
|
+
|
42
|
+
attr_accessor :title, :text, :btns, :btn_orientation, :hide_avatar
|
43
|
+
|
44
|
+
def initialize(title, text, buttons, btn_orientation = '0', hide_avatar = '0')
|
45
|
+
@title = title # 首屏会话透出的展示内容
|
46
|
+
@text = text # markdown格式的消息
|
47
|
+
@buttons = buttons # 按钮的信息:title-按钮方案,actionURL-点击按钮触发的URL
|
48
|
+
@btn_orientation = btn_orientation # 0-按钮竖直排列,1-按钮横向排列
|
49
|
+
@hide_avatar = hide_avatar # 0-正常发消息者头像,1-隐藏发消息者头像
|
50
|
+
end
|
51
|
+
|
52
|
+
def message_type
|
53
|
+
TYPE::ACTION_CARD # 此消息类型为固定actionCard
|
54
|
+
end
|
55
|
+
|
56
|
+
def build_message
|
57
|
+
if @buttons.size == 1 then
|
58
|
+
single_title = @buttons[0].title
|
59
|
+
single_url = @buttons[0].action_url
|
60
|
+
super.merge(
|
61
|
+
{
|
62
|
+
:actionCard => {
|
63
|
+
:title => @title,
|
64
|
+
:text => @text,
|
65
|
+
:singleTitle => single_title,
|
66
|
+
:singleURL => single_url,
|
67
|
+
:btnOrientation => @btn_orientation,
|
68
|
+
:hideAvatar => @hide_avatar
|
69
|
+
}
|
70
|
+
}
|
71
|
+
)
|
72
|
+
else
|
73
|
+
super.merge(
|
74
|
+
{
|
75
|
+
:actionCard => {
|
76
|
+
:title => @title,
|
77
|
+
:text => @text,
|
78
|
+
:btns => @buttons.map { | button | button.build_message },
|
79
|
+
:btnOrientation => @btn_orientation,
|
80
|
+
:hideAvatar => @hide_avatar
|
81
|
+
}
|
82
|
+
}
|
83
|
+
)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class ActionCardButton
|
89
|
+
|
90
|
+
attr_accessor :title, :action_url
|
91
|
+
|
92
|
+
def initialize(title, action_url)
|
93
|
+
@title = title # 按钮方案
|
94
|
+
@action_url = action_url # 点击按钮触发的URL
|
95
|
+
end
|
96
|
+
|
97
|
+
def build_message
|
98
|
+
{ :title => @title, :actionURL => @action_url }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module DingTalk
|
4
|
+
module Message
|
5
|
+
module TYPE
|
6
|
+
TEXT = 'text'.freeze
|
7
|
+
LINK = 'link'.freeze
|
8
|
+
MARKDOWN = 'markdown'.freeze
|
9
|
+
ACTION_CARD = 'actionCard'.freeze # 整体跳转ActionCard类型
|
10
|
+
FEED_CARD = 'feedCard'.freeze
|
11
|
+
end
|
12
|
+
|
13
|
+
# 消息 BaseMessage 类
|
14
|
+
class BaseMessage
|
15
|
+
|
16
|
+
def message_type
|
17
|
+
# implement in child
|
18
|
+
end
|
19
|
+
|
20
|
+
def build_message
|
21
|
+
{
|
22
|
+
:msgtype => message_type
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_json
|
27
|
+
build_message.to_json
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module DingTalk
|
2
|
+
module Message
|
3
|
+
# 消息类型及数据格式 - FeedCard类型
|
4
|
+
# {
|
5
|
+
# "feedCard": {
|
6
|
+
# "links": [
|
7
|
+
# {
|
8
|
+
# "title": "时代的火车向前开",
|
9
|
+
# "messageURL": "https://www.dingtalk.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI",
|
10
|
+
# "picURL": "https://www.dingtalk.com/"
|
11
|
+
# },
|
12
|
+
# {
|
13
|
+
# "title": "时代的火车向前开2",
|
14
|
+
# "messageURL": "https://www.dingtalk.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI",
|
15
|
+
# "picURL": "https://www.dingtalk.com/"
|
16
|
+
# }
|
17
|
+
# ]
|
18
|
+
# },
|
19
|
+
# "msgtype": "feedCard"
|
20
|
+
# }
|
21
|
+
class FeedCard < BaseMessage
|
22
|
+
|
23
|
+
attr_accessor :links
|
24
|
+
|
25
|
+
def initialize(links)
|
26
|
+
@links = links
|
27
|
+
end
|
28
|
+
|
29
|
+
def message_type
|
30
|
+
TYPE::FEED_CARD # 此消息类型为固定feedCard
|
31
|
+
end
|
32
|
+
|
33
|
+
def build_message
|
34
|
+
super.merge(
|
35
|
+
{
|
36
|
+
:feedCard => {
|
37
|
+
:links => @links.map { | link | link.build_message }
|
38
|
+
}
|
39
|
+
}
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# FeedCard跳转链接
|
45
|
+
class FeedCardLink
|
46
|
+
|
47
|
+
attr_accessor :title, :pic_url, :message_url
|
48
|
+
|
49
|
+
def initialize(title, pic_url, message_url)
|
50
|
+
@title = title
|
51
|
+
@pic_url = pic_url
|
52
|
+
@message_url = message_url
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_message
|
56
|
+
{
|
57
|
+
:title => @title, # 单条信息文本
|
58
|
+
:messageURL => @message_url, # 点击单条信息到跳转链接
|
59
|
+
:picURL => @pic_url # 单条信息后面图片的URL
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module DingTalk
|
2
|
+
module Message
|
3
|
+
# 消息类型及数据格式 - link类型
|
4
|
+
# {
|
5
|
+
# "msgtype": "link",
|
6
|
+
# "link": {
|
7
|
+
# "text": "这个即将发布的新版本,创始人xx称它为“红树林”。
|
8
|
+
# 而在此之前,每当面临重大升级,产品经理们都会取一个应景的代号,这一次,为什么是“红树林”?",
|
9
|
+
# "title": "时代的火车向前开",
|
10
|
+
# "picUrl": "",
|
11
|
+
# "messageUrl": "https://www.dingtalk.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI"
|
12
|
+
# }
|
13
|
+
# }
|
14
|
+
class Link < BaseMessage
|
15
|
+
|
16
|
+
attr_accessor :title, :text, :pic_url, :message_url
|
17
|
+
|
18
|
+
def initialize(title, text, pic_url, message_url = '')
|
19
|
+
@title = title # 消息标题
|
20
|
+
@text = text # 消息内容。如果太长只会部分展示
|
21
|
+
@pic_url = pic_url # 图片URL
|
22
|
+
@message_url = message_url # 点击消息跳转的URL
|
23
|
+
end
|
24
|
+
|
25
|
+
def message_type
|
26
|
+
TYPE::LINK # 消息类型,此时固定为:link
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_message
|
30
|
+
super.merge(
|
31
|
+
{
|
32
|
+
:link => {
|
33
|
+
:title => @title,
|
34
|
+
:text => @text,
|
35
|
+
:picUrl => @pic_url,
|
36
|
+
:messageUrl => @message_url,
|
37
|
+
}
|
38
|
+
}
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module DingTalk
|
2
|
+
module Message
|
3
|
+
# 消息类型及数据格式 - markdown类型
|
4
|
+
# {
|
5
|
+
# "msgtype": "markdown",
|
6
|
+
# "markdown": {
|
7
|
+
# "title":"杭州天气",
|
8
|
+
# "text": "#### 杭州天气 @156xxxx8827\n" +
|
9
|
+
# "> 9度,西北风1级,空气良89,相对温度73%\n\n" +
|
10
|
+
# "> ![screenshot](https://gw.alicdn.com/tfs/TB1ut3xxbsrBKNjSZFpXXcXhFXa-846-786.png)\n" +
|
11
|
+
# "> ###### 10点20分发布 [天气](http://www.thinkpage.cn/) \n"
|
12
|
+
# },
|
13
|
+
# "at": {
|
14
|
+
# "atMobiles": [
|
15
|
+
# "156xxxx8827",
|
16
|
+
# "189xxxx8325"
|
17
|
+
# ],
|
18
|
+
# "isAtAll": false
|
19
|
+
# }
|
20
|
+
# }
|
21
|
+
class Markdown < BaseMessage
|
22
|
+
|
23
|
+
attr_accessor :title, :text, :at_mobiles, :is_at_all
|
24
|
+
|
25
|
+
def initialize(title, text, at_mobiles = [], is_at_all = false)
|
26
|
+
@title = title # 首屏会话透出的展示内容
|
27
|
+
@text = text # markdown格式的消息
|
28
|
+
@at_mobiles = at_mobiles # 被@人的手机号(在text内容里要有@手机号)
|
29
|
+
@is_at_all = is_at_all # @所有人时:true,否则为:false
|
30
|
+
end
|
31
|
+
|
32
|
+
def message_type
|
33
|
+
TYPE::MARKDOWN # 此消息类型为固定markdown
|
34
|
+
end
|
35
|
+
|
36
|
+
def build_message
|
37
|
+
super.merge(
|
38
|
+
{
|
39
|
+
:markdown => {
|
40
|
+
:title => @title,
|
41
|
+
:text => @text
|
42
|
+
},
|
43
|
+
:at => {
|
44
|
+
:atMobiles => @at_mobiles,
|
45
|
+
:isAtAll => @is_at_all
|
46
|
+
}
|
47
|
+
}
|
48
|
+
)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative './base_message'
|
2
|
+
|
3
|
+
module DingTalk
|
4
|
+
module Message
|
5
|
+
# 消息类型及数据格式 - text类型
|
6
|
+
# {
|
7
|
+
# "msgtype": "text",
|
8
|
+
# "text": {
|
9
|
+
# "content": "我就是我, 是不一样的烟火@156xxxx8827"
|
10
|
+
# },
|
11
|
+
# "at": {
|
12
|
+
# "atMobiles": [
|
13
|
+
# "156xxxx8827",
|
14
|
+
# "189xxxx8325"
|
15
|
+
# ],
|
16
|
+
# "isAtAll": false
|
17
|
+
# }
|
18
|
+
# }
|
19
|
+
class Text < BaseMessage
|
20
|
+
|
21
|
+
attr_accessor :content, :at_mobiles, :is_at_all
|
22
|
+
|
23
|
+
def initialize(content, at_mobiles = [], is_at_all = false)
|
24
|
+
@content = content # 消息内容
|
25
|
+
@at_mobiles = at_mobiles # 被@人的手机号(在content里添加@人的手机号)
|
26
|
+
@is_at_all = is_at_all # @所有人时:true,否则为:false
|
27
|
+
end
|
28
|
+
|
29
|
+
def message_type
|
30
|
+
TYPE::TEXT # 消息类型,此时固定为:text
|
31
|
+
end
|
32
|
+
|
33
|
+
def build_message
|
34
|
+
super.merge(
|
35
|
+
{
|
36
|
+
:text => {
|
37
|
+
:content => @content
|
38
|
+
},
|
39
|
+
:at => {
|
40
|
+
:atMobiles => @at_mobiles,
|
41
|
+
:isAtAll => @is_at_all
|
42
|
+
}
|
43
|
+
}
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'faraday';
|
2
|
+
require 'faraday_middleware'
|
3
|
+
|
4
|
+
require_relative '../core/text'
|
5
|
+
require_relative '../core/link'
|
6
|
+
require_relative '../core/markdown'
|
7
|
+
require_relative '../core/action_card'
|
8
|
+
require_relative '../core/feed_card'
|
9
|
+
|
10
|
+
module DingTalk
|
11
|
+
class HttpHelper
|
12
|
+
DINGTALK_URL = 'https://oapi.dingtalk.com/robot/send'.freeze
|
13
|
+
|
14
|
+
def self.send_http(params = {}, token = nil, secret = nil)
|
15
|
+
access_token = token || ENV['DINGTALK_TOKEN']
|
16
|
+
access_secret = token || ENV['DINGTALK_SECRET']
|
17
|
+
return 'A message access token is required.' unless access_token
|
18
|
+
if access_secret then
|
19
|
+
timestamp = "#{ Time.now.to_i * 1000 }\n#{ access_secret }"
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
# Long timestamp = System.currentTimeMillis();
|
24
|
+
# String stringToSign = timestamp + "\n" + secret;
|
25
|
+
# Mac mac = Mac.getInstance("HmacSHA256");
|
26
|
+
# mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
|
27
|
+
# byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
|
28
|
+
# return URLEncoder.encode(new String(Base64.encodeBase64(signData)),"UTF-8");
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
end
|
34
|
+
url = "#{ DINGTALK_URL }?access_token=#{ access_token }"
|
35
|
+
http_client = Faraday.new() do |builder|
|
36
|
+
builder.request :url_encoded
|
37
|
+
builder.request :json
|
38
|
+
builder.response :logger
|
39
|
+
builder.adapter :net_http
|
40
|
+
end
|
41
|
+
res = http_client.post url, params.to_json, 'Content-Type' => 'application/json'
|
42
|
+
res.body
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.send_text(content, at_mobiles = [], is_at_all = false, token = nil, secret = nil)
|
46
|
+
send_http DingTalk::Message::Text.new(content, at_mobiles, is_at_all), token, secret
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.send_link(title, text, pic_url, message_url = '', token = nil, secret = nil)
|
50
|
+
send_http DingTalk::Message::Link.new(title, text, pic_url, message_url), token, secret
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.send_markdown(title, text, at_mobiles = [], is_at_all = false, token = nil, secret = nil)
|
54
|
+
send_http DingTalk::Message::Markdown.new(title, text, at_mobiles, is_at_all), token, secret
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.send_action_card(title, text, single_title, single_url, btn_orientation = '0', hide_avatar = '0', token = nil, secret = nil)
|
58
|
+
buttons = [
|
59
|
+
DingTalk::Message::ActionCardButton.new(single_title, single_url)
|
60
|
+
]
|
61
|
+
send_http DingTalk::Message::ActionCard.new(title, text, buttons, btn_orientation, hide_avatar), token, secret
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.send_action_card2(title, text, buttons, btn_orientation = '0', hide_avatar = '0', token = nil, secret = nil)
|
65
|
+
send_http DingTalk::Message::ActionCard.new(title, text, buttons, btn_orientation, hide_avatar), token, secret
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.send_feed_card(links, token = nil, secret = nil)
|
69
|
+
send_http DingTalk::Message::FeedCard.new(links), token, secret
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
data/lib/DingTalk/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dingtalk-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 大龙侠
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-04-29 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: 自定义钉钉群机器人 dingtalk-cli
|
14
14
|
email:
|
@@ -16,6 +16,7 @@ email:
|
|
16
16
|
executables:
|
17
17
|
- console
|
18
18
|
- dingtalk
|
19
|
+
- dt
|
19
20
|
- setup
|
20
21
|
extensions: []
|
21
22
|
extra_rdoc_files: []
|
@@ -26,15 +27,29 @@ files:
|
|
26
27
|
- CHANGELOG.md
|
27
28
|
- CODE_OF_CONDUCT.md
|
28
29
|
- Gemfile
|
30
|
+
- Gemfile.lock
|
29
31
|
- LICENSE.txt
|
30
32
|
- README.md
|
31
33
|
- Rakefile
|
32
34
|
- bin/console
|
33
35
|
- bin/dingtalk
|
36
|
+
- bin/dt
|
34
37
|
- bin/setup
|
35
38
|
- dingtalk-cli.gemspec
|
36
39
|
- lib/DingTalk.rb
|
37
40
|
- lib/DingTalk/command.rb
|
41
|
+
- lib/DingTalk/command/action_card.rb
|
42
|
+
- lib/DingTalk/command/feed_card.rb
|
43
|
+
- lib/DingTalk/command/link.rb
|
44
|
+
- lib/DingTalk/command/markdown.rb
|
45
|
+
- lib/DingTalk/command/text.rb
|
46
|
+
- lib/DingTalk/core/action_card.rb
|
47
|
+
- lib/DingTalk/core/base_message.rb
|
48
|
+
- lib/DingTalk/core/feed_card.rb
|
49
|
+
- lib/DingTalk/core/link.rb
|
50
|
+
- lib/DingTalk/core/markdown.rb
|
51
|
+
- lib/DingTalk/core/text.rb
|
52
|
+
- lib/DingTalk/utils/http_helper.rb
|
38
53
|
- lib/DingTalk/version.rb
|
39
54
|
homepage: https://ding-doc.dingtalk.com/
|
40
55
|
licenses:
|