active_notifier 0.2.0 → 0.3.0
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/.rubocop.yml +1 -0
- data/.travis.yml +13 -0
- data/README.md +40 -66
- data/active_notifier.gemspec +1 -0
- data/lib/active_notifier/adapters/abstract_adapter.rb +3 -2
- data/lib/active_notifier/adapters/dingtalk_adapter.rb +3 -2
- data/lib/active_notifier/configurable.rb +4 -3
- data/lib/active_notifier/core.rb +65 -42
- data/lib/active_notifier/templates/default.markdown.erb +1 -1
- data/lib/active_notifier/templates/default.text.erb +1 -0
- data/lib/active_notifier/version.rb +1 -1
- metadata +19 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11d89dfa1aff8c314539b8ff79b5cbb72ed89f98e2fdce3c324a7e8ee097c789
|
4
|
+
data.tar.gz: b8edd79f2f6244a442a2d4bfb603ef0f4e6504971d6c9b4a33b66330f87a60e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 53025b951b32263b901f958d9200fa0eae7c954960a39299a1d249686fdeac091bedeee457256c379a4bd44e09274a02e1c2d613e8b1003c918501cee18be66d
|
7
|
+
data.tar.gz: 2d83333750347d2ec943ac14a273111de68ccb02226898ffea26c4e22792efc460859b1c17306c8cd0c521c9d74ffe3a2399ff098a8338120aed489c4d3dda2d
|
data/.rubocop.yml
CHANGED
data/.travis.yml
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.5.1
|
4
|
+
cache: bundler
|
5
|
+
script:
|
6
|
+
- bundle exec rspec
|
7
|
+
- bundle exec rubocop
|
8
|
+
deploy:
|
9
|
+
provider: rubygems
|
10
|
+
api_key:
|
11
|
+
secure: Kuaq/l0/f+pasOQRFpiF43o5bOqlhP3wbStxSYVAZye8YuGCMZ7wnzhNlD8cU57nc1e2tsONv78OT8qUKr8uNTeDU1RpRzAq8FEAiIHYHe2Rw/JUibE2c7GJchvpoQNCSCZZJbr6NZ5EcK6yx/mOoiZgWlAcvLWb2SdkIwDsRkucl6UEE6DP87ddkjBsE9TYAKV+Q+U76JHr20E0ANjoyTq4K6htdLuOqY2GwwhosQzZw/ixHNS+9GMCDJNJAJg5VYbv8AgCNgzkOPmPydfca1GWHSVul1QLvxC5EC7Sv8gt+uAcfxErf860hwoymenobhCMNPPmRZk65I+a2PC2O0Ni8xWriT8zsOJC15kFEGvmWFT5Vhix1fOCglB2C0CCanbfId+NjGu9AzfuT2cn7ySKbl3f2A7U3Kaopqge38z4xg0uYudfh9TkcZteUM8bq/S3Ioh3Z7NrynMfWcaFxArMkFoiAyCcJhXmQg/WXFKJjDXIC5AEWaEfv1xnBh/UZPIaqB5KC7MU2VRoesebr3EQl3rLU1AS+ga5m50lqnTIMRyH6clxvwojgfg51hkFRc16svTXshDvCq+u+ZfQUghO93jkeVHXernbiZFyzPFosBUwTxk75o5OaSKs6l6O52OIGa+mp6YqlCPXw5AGfQLBdS7qcuFokAKNesJQnts=
|
12
|
+
on:
|
13
|
+
tags: true
|
data/README.md
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
|
3
3
|
Notify message through webhooks.
|
4
4
|
|
5
|
+
[](https://badge.fury.io/rb/active_notifier)
|
6
|
+
[](https://travis-ci.org/pinewong/active_notifier)
|
7
|
+
[](https://codecov.io/github/pinewong/active_notifier?branch=master)
|
8
|
+
|
5
9
|
## Installation
|
6
10
|
|
7
11
|
Add this line to your application's Gemfile:
|
@@ -18,118 +22,88 @@ Or install it yourself as:
|
|
18
22
|
|
19
23
|
$ gem install active_notifier
|
20
24
|
|
21
|
-
## Usage
|
25
|
+
## Basic Usage
|
22
26
|
|
23
|
-
|
27
|
+
Just notify the message through a webhook token, ActiveNotifier use Dingtalk by default, the webhook token
|
28
|
+
need be a accessible dingtalk webhook token.
|
24
29
|
|
25
30
|
```ruby
|
26
|
-
|
27
|
-
ActiveNotifier.exec(:default)
|
28
|
-
# This will notifier message, use options:
|
29
|
-
# token: config.channel_tokens[:default],
|
30
|
-
# template: "#{config.template_home}/default.*.erb"
|
31
|
-
|
32
|
-
ActiveNotifier.exec(:default, template: "orders/create")
|
33
|
-
# Use specific template file but not get by channel
|
34
|
-
# This will notifier message, use options:
|
35
|
-
# token: config.channel_tokens[:default],
|
36
|
-
# template: "#{config.template_home}/orders/create.*.erb"
|
37
|
-
|
38
|
-
ActiveNotifier.exec(:default, token: "special_token", data: { title: "Title", message: "Message" })
|
39
|
-
# Use specific token but not get by channel
|
40
|
-
# This will notifier message, use options:
|
41
|
-
# token: "special_token",
|
42
|
-
# template: "#{config.template_home}/default.*.erb"
|
43
|
-
# And the Hash data will inject to template, and get a dynamic message after parse template
|
31
|
+
ActiveNotifier.exec(token: "your-webhook-token", message: "your-message")
|
44
32
|
```
|
45
33
|
|
46
|
-
|
34
|
+
Is it too much trouble to set the token and message always? You can save commonly used ones and access them via better ways.
|
35
|
+
For token, ActiveNotifier use channel_tokens to store it, and for message, we can use the ERB template and locals data, like the familiar ActiveView does.
|
47
36
|
|
48
|
-
Set token and template home for Rails application
|
49
37
|
|
50
38
|
```ruby
|
51
39
|
ActiveNotifier.configure do |config|
|
52
|
-
config.channel_tokens = {
|
40
|
+
config.channel_tokens = { my_channel: "xxx" }
|
53
41
|
config.template_home = Rails.root.join("app", "views", "active_notifier")
|
54
42
|
end
|
55
43
|
```
|
56
44
|
|
57
|
-
|
58
|
-
|
59
|
-
> app/views/active_notifier/default.markdown.erb
|
60
|
-
|
61
|
-
```erb
|
62
|
-
## #{data[:title]}
|
63
|
-
> #{data[:message]}
|
45
|
+
```shell
|
46
|
+
echo "## #{data[:title]\n> #{data[:body]}}" > app/views/active_notifier/my_channel.markdown.erb
|
64
47
|
```
|
65
48
|
|
66
|
-
Notify message
|
67
|
-
|
68
49
|
```ruby
|
69
|
-
ActiveNotifier.exec(:
|
50
|
+
ActiveNotifier.exec(token_channel: :my_channel, template: :my_channel, data: { title: "Message Title", body: "Message Body" })
|
70
51
|
```
|
71
52
|
|
72
|
-
|
73
|
-
|
74
|
-
Message type will dynamic set according by valid template files, when we
|
75
|
-
set a template named `order.text.erb`
|
53
|
+
Also when token_channel and template is the same, we can simplify it by using the first optional argument channel
|
76
54
|
|
77
55
|
```ruby
|
78
|
-
ActiveNotifier.
|
79
|
-
config.channel_tokens = { order: "xxx" }
|
80
|
-
config.template_home = Rails.root.join("app", "views", "active_notifier")
|
56
|
+
ActiveNotifier.exec(:my_channel, data: { title: "Message Title", body: "Message Body" })
|
81
57
|
```
|
82
58
|
|
83
|
-
|
59
|
+
## Advanced knowledge
|
84
60
|
|
85
|
-
|
86
|
-
title: #{data[:title]}
|
87
|
-
message: #{data[:message]}
|
88
|
-
```
|
61
|
+
### Send message with dynamic type
|
89
62
|
|
90
|
-
|
91
|
-
|
63
|
+
Message type will dynamic set according to a valid template, imagine we have two template files named `order.text.erb` and `order.markdown.erb`,
|
64
|
+
now we want use the text type of template, we need add a type option
|
92
65
|
|
93
66
|
```ruby
|
94
|
-
ActiveNotifier.exec(:
|
67
|
+
ActiveNotifier.exec(:order, data: { title: "Message Title", body: "Message Body" }, type: :text)
|
95
68
|
```
|
96
69
|
|
97
|
-
|
98
|
-
are exist, we still can make it OK which no need for type option, just
|
99
|
-
set the priority type
|
70
|
+
But if there is only one type of template, the type option is optional
|
100
71
|
|
101
|
-
|
72
|
+
```ruby
|
73
|
+
# Now we have only template file `product.text.erb` for product channel
|
102
74
|
|
103
|
-
|
104
|
-
title: #{data[:title]}
|
105
|
-
message: #{data[:message]}
|
75
|
+
ActiveNotifier.exec(:product, data: { title: "Message Title", body: "Message Body" }) # Needn't type option
|
106
76
|
```
|
107
77
|
|
108
|
-
|
78
|
+
And also we can configure priority type for ActiveNotifier
|
109
79
|
|
110
|
-
```
|
111
|
-
|
112
|
-
|
80
|
+
```ruby
|
81
|
+
ActiveNotifier.configure do |config|
|
82
|
+
# default is :markdown
|
83
|
+
config.priority_type = :text
|
84
|
+
end
|
113
85
|
```
|
114
86
|
|
115
87
|
```ruby
|
116
|
-
#
|
117
|
-
ActiveNotifer.config.priority_type = :text
|
88
|
+
# Now even we have template files `book.text.erb` and `book.markdown.erb` for book channel
|
118
89
|
|
119
|
-
#
|
120
|
-
ActiveNotifier.exec(:default, data: { title: "Title", message: "Message" }) # => Notifer message OK by text type template
|
90
|
+
ActiveNotifier.exec(:book, data: { title: "Message Title", body: "Message Body" }) # Needn't type option, and will choose the text type
|
121
91
|
```
|
122
92
|
|
123
|
-
### Set a short constant
|
93
|
+
### Set a short constant
|
94
|
+
|
95
|
+
ActiveSupport hook `after_initialize` will set this by default
|
124
96
|
|
125
97
|
```ruby
|
126
98
|
ActiveNotifer.config.const_name = :Notifier
|
127
99
|
Notifer.exec(...)
|
128
100
|
```
|
129
101
|
|
130
|
-
|
102
|
+
## Help and Docs
|
131
103
|
|
132
|
-
|
104
|
+
* [More Examples](https://github.com/pinewong/active_notifier/blob/master/spec/active_notifier_spec.rb)
|
105
|
+
* [RDoc](https://www.rubydoc.info/github/pinewong/active_notifier)
|
106
|
+
* [Gem RDoc](http://www.rubydoc.info/gems/active_notifier/0.3.0)
|
133
107
|
|
134
108
|
## Development
|
135
109
|
|
data/active_notifier.gemspec
CHANGED
@@ -34,6 +34,7 @@ Gem::Specification.new do |spec|
|
|
34
34
|
|
35
35
|
spec.add_development_dependency "bundler", "~> 1.16"
|
36
36
|
spec.add_development_dependency "byebug"
|
37
|
+
spec.add_development_dependency "codecov", ">= 0.1.10"
|
37
38
|
spec.add_development_dependency "rake", "~> 10.0"
|
38
39
|
spec.add_development_dependency "rspec", "~> 3.7"
|
39
40
|
spec.add_development_dependency "rubocop", "~> 0.58.1"
|
@@ -7,15 +7,16 @@ module ActiveNotifier
|
|
7
7
|
end
|
8
8
|
|
9
9
|
# Notify message
|
10
|
+
#
|
10
11
|
# @abstract Implement through setting a real adapter, like :dingtalk
|
11
12
|
# @param token [String] Channel webhook token
|
12
13
|
# @param type [Symbol] Message type
|
13
14
|
# @param message [String] Message body
|
14
|
-
# @param options [Hash]
|
15
|
-
# some adapters require some another options
|
15
|
+
# @param options [Hash] Adapter message options, some adapters require some another options
|
16
16
|
# @raise [AdapterOptionsInvalidError]
|
17
17
|
# @raise [AdapterTypeInvalidError]
|
18
18
|
# @raise [MessageBlankError]
|
19
|
+
# @see ActiveNotitifier::exec for usage
|
19
20
|
def notify(token, type, message, **options)
|
20
21
|
adapter.notify(token, type, message, **options)
|
21
22
|
end
|
@@ -2,14 +2,15 @@ module ActiveNotifier
|
|
2
2
|
class DingtalkAdapter
|
3
3
|
VALID_TYPES = %i[markdown].freeze
|
4
4
|
|
5
|
+
# (see AbstractAdapter#notify)
|
5
6
|
def notify(token, type, message, **options)
|
6
7
|
webhook = "#{ActiveNotifier.config.adapters_with_base_url.fetch(:dingtalk)}#{token}"
|
7
8
|
unless VALID_TYPES.include?(type)
|
8
|
-
error_message = "
|
9
|
+
error_message = "The Dingtalk adapter only support types: #{VALID_TYPES.join(', ')}"
|
9
10
|
raise ActiveNotifier::AdapterTypeInvalidError, error_message
|
10
11
|
end
|
11
12
|
raise ActiveNotifier::MessageBlankError, "message can't be blank, please check template file" if message.empty?
|
12
|
-
title = options[:title]
|
13
|
+
title = options[:title]&.to_s
|
13
14
|
raise ActiveNotifier::AdapterOptionsInvalidError, "Dingtalk adapter require other options: title" if title.empty?
|
14
15
|
|
15
16
|
body = {
|
@@ -3,15 +3,16 @@ module ActiveNotifier
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
module ClassMethods
|
6
|
-
# Configure for ActiveNotifier
|
7
|
-
#
|
8
|
-
# @raise [ConfigureError]
|
6
|
+
# Configure for ActiveNotifier.
|
7
|
+
#
|
9
8
|
# @example
|
10
9
|
# ActiveNotifier.configure do |config|
|
11
10
|
# config.const_name = :Message
|
12
11
|
# config.adapter = :slack
|
13
12
|
# # ...
|
14
13
|
# end
|
14
|
+
# @yield [config] Give a Configuration instance for settings
|
15
|
+
# @raise [ConfigureError]
|
15
16
|
def configure
|
16
17
|
yield config
|
17
18
|
end
|
data/lib/active_notifier/core.rb
CHANGED
@@ -3,59 +3,77 @@ module ActiveNotifier
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
module ClassMethods
|
6
|
-
# Message execute
|
7
|
-
#
|
8
|
-
# @
|
9
|
-
#
|
10
|
-
# @
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
6
|
+
# Message execute.
|
7
|
+
#
|
8
|
+
# @example Command Usage
|
9
|
+
# ActiveNotifier.exec(token: "your-webhook-token", message: "your-message")
|
10
|
+
# @example Common Usage
|
11
|
+
# # Configure it
|
12
|
+
# ActiveNotifier.configure do |config|
|
13
|
+
# config.channel_tokens = { my_channel: "xxx" }
|
14
|
+
# config.template_home = Rails.root.join("app", "views", "active_notifier")
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # Add template
|
18
|
+
# echo "## #{data[:title]\n> #{data[:body]}}" > app/views/active_notifier/my_channel.markdown.erb
|
19
|
+
#
|
20
|
+
# # Execute it
|
21
|
+
# ActiveNotifier.exec(:my_channel, data: { title: "Message Title", body: "Message Body" })
|
22
|
+
# @param channel [#to_sym] (nil) Message channel, it will set template and token_channel together
|
23
|
+
# @param options [#to_h] ({})
|
24
|
+
# @option options [#to_s] :token (nil) Message webhook token,
|
25
|
+
# @option options [#to_s] :message (nil) Message
|
26
|
+
# @option options [#to_sym] :token_channel (nil) Message webhook token channel,
|
27
|
+
# will use `channel` when this value is blank
|
28
|
+
# @option options [#to_sym] :template (nil) Message template, will use `channel` when this value is blank
|
29
|
+
# @option options [#to_sym] :adapter (ActiveNotifier.config.adapter) Message adapter
|
30
|
+
# @option options [#to_sym] :type (nil) Message type, it will use a specific template file, for example,
|
31
|
+
# when type is :text and template is :order, then ActiveNotifier will choose `order.text.erb` for template file
|
32
|
+
# @option options [#to_h] :data ({}) Message variable data for template, it can used in erb template file
|
33
|
+
# @option options [Anything] Other options will used in adapter message execute, like Dingtalk require title
|
34
|
+
# for message, we can pass it here: `ActiveNotifer.exec(:default, title: "dingtalk title")`
|
20
35
|
# @raise [TemplateNotFoundError]
|
21
36
|
# @raise [UndefinedTokenError]
|
22
37
|
# @raise [AdapterOptionsInvalidError]
|
23
38
|
# @raise [AdapterTypeInvalidError]
|
24
39
|
# @raise [MessageBlankError]
|
25
|
-
# @
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
adapter
|
41
|
-
|
42
|
-
adapter.notify(token, type, message, adapter_options)
|
40
|
+
# @see Get more see README
|
41
|
+
def exec(channel = nil, **options)
|
42
|
+
channel = channel&.to_sym
|
43
|
+
token = options[:token]&.to_s
|
44
|
+
message = options[:message]&.to_s
|
45
|
+
token_channel = options[:token_channel]&.to_sym
|
46
|
+
template = options[:template]&.to_sym
|
47
|
+
adapter = options[:adapter]&.to_sym
|
48
|
+
type = options[:type]&.to_sym
|
49
|
+
data = options[:data].to_h
|
50
|
+
token = fetch_token(token, token_channel, channel)
|
51
|
+
template ||= channel
|
52
|
+
type ||= get_type_by_template(template)
|
53
|
+
message ||= get_message(template, type, data)
|
54
|
+
adapter_options = options.except(:token, :message, :token_channel, :template, :adapter, :type, :data)
|
55
|
+
adapter ||= ActiveNotifier.config.adapter.to_sym
|
56
|
+
ActiveNotifier.adapt(adapter).notify(token, type, message, adapter_options)
|
43
57
|
end
|
44
58
|
|
45
59
|
private
|
46
60
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
61
|
+
# @param token [String, nil]
|
62
|
+
# @param token_channel [Symbol, nil]
|
63
|
+
# @param channel [Symbol, nil]
|
64
|
+
# @return [String]
|
65
|
+
def fetch_token(token, token_channel, channel)
|
66
|
+
token = token ||
|
67
|
+
token_channel && ActiveNotifier.config.channel_tokens[token_channel]&.to_s ||
|
68
|
+
channel && ActiveNotifier.config.channel_tokens[channel]&.to_s
|
69
|
+
raise ActiveNotifier::UndefinedTokenError unless token
|
70
|
+
token
|
56
71
|
end
|
57
72
|
|
58
|
-
|
73
|
+
# @param template [Symbol, nil]
|
74
|
+
# @return [Symbol, nil]
|
75
|
+
def get_type_by_template(template)
|
76
|
+
return unless template
|
59
77
|
template_paths = Dir["#{ActiveNotifier.config.template_home}/#{template}.*.erb"]
|
60
78
|
raise ActiveNotifier::TemplateNotFoundError if template_paths.empty?
|
61
79
|
types = template_paths.map do |template_path|
|
@@ -68,7 +86,12 @@ module ActiveNotifier
|
|
68
86
|
end
|
69
87
|
end
|
70
88
|
|
89
|
+
# @param template [Symbol, nil]
|
90
|
+
# @param type [Symbol]
|
91
|
+
# @param data [Hash]
|
92
|
+
# @return [String, nil]
|
71
93
|
def get_message(template, type, data)
|
94
|
+
return unless template
|
72
95
|
template_data = File.read("#{ActiveNotifier.config.template_home}/#{template}.#{type}.erb")
|
73
96
|
ERB.new(template_data).result_with_hash(data: data)
|
74
97
|
rescue Errno::ENOENT => e
|
@@ -1 +1 @@
|
|
1
|
-
<%= data %>
|
1
|
+
> <%= data %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= data %>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_notifier
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pine Wong
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-07-
|
11
|
+
date: 2018-07-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: codecov
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.1.10
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.1.10
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -151,6 +165,7 @@ extra_rdoc_files: []
|
|
151
165
|
files:
|
152
166
|
- ".gitignore"
|
153
167
|
- ".rubocop.yml"
|
168
|
+
- ".travis.yml"
|
154
169
|
- CODE_OF_CONDUCT.md
|
155
170
|
- Gemfile
|
156
171
|
- README.md
|
@@ -166,6 +181,7 @@ files:
|
|
166
181
|
- lib/active_notifier/core.rb
|
167
182
|
- lib/active_notifier/errors.rb
|
168
183
|
- lib/active_notifier/templates/default.markdown.erb
|
184
|
+
- lib/active_notifier/templates/default.text.erb
|
169
185
|
- lib/active_notifier/version.rb
|
170
186
|
homepage: https://github.com/pinewong/active_notifier
|
171
187
|
licenses: []
|
@@ -186,7 +202,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
186
202
|
version: '0'
|
187
203
|
requirements: []
|
188
204
|
rubyforge_project:
|
189
|
-
rubygems_version: 2.7.
|
205
|
+
rubygems_version: 2.7.7
|
190
206
|
signing_key:
|
191
207
|
specification_version: 4
|
192
208
|
summary: Notify message through webhooks.
|