slack-notify 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/README.md +12 -1
- data/Rakefile +10 -0
- data/lib/slack-notify/client.rb +55 -0
- data/lib/slack-notify/connection.rb +34 -0
- data/lib/slack-notify/payload.rb +29 -0
- data/lib/slack-notify/version.rb +1 -1
- data/lib/slack-notify.rb +3 -73
- data/spec/slack-notify/client_spec.rb +31 -69
- data/spec/slack-notify/payload_spec.rb +105 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03e6c9b0e49fde578cd9f35b06f842d31d4f37cd
|
4
|
+
data.tar.gz: 6a6cb121c35a1e62ecb7dd0f47e1da4a773d37a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4d94d98b07f026fbd651e5b3cb87e03af147cb33ea8758109a4ee11680c120997d0337571413d9b2ed307d6d551c1679d07fc345db3e48c02da927684041f9d
|
7
|
+
data.tar.gz: f57fd7011d8295e0de59c755b774ddffa9b664e2aa960c565bb7b7913d7e39b447fa638d085bce9d10b1f3eeb8d8253e6f8c7bf22afc751f355b29b810060d65
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
Send notifications to [Slack](http://slack.com/)
|
4
4
|
|
5
|
+
[![Build Status](https://travis-ci.org/sosedoff/slack-notify.png?branch=master)](https://travis-ci.org/sosedoff/slack-notify)
|
6
|
+
[![Code Climate](https://codeclimate.com/github/sosedoff/slack-notify.png)](https://codeclimate.com/github/sosedoff/slack-notify)
|
7
|
+
|
5
8
|
## Installation
|
6
9
|
|
7
10
|
Add this line to your application's Gemfile:
|
@@ -41,7 +44,9 @@ Initialize with options:
|
|
41
44
|
```ruby
|
42
45
|
client = SlackNotify::Client.new("team", "token", {
|
43
46
|
channel: "#development",
|
44
|
-
username: "mybot"
|
47
|
+
username: "mybot",
|
48
|
+
icon_url: "http://mydomain.com/myimage.png",
|
49
|
+
icon_emoji: ":shipit:"
|
45
50
|
})
|
46
51
|
```
|
47
52
|
|
@@ -65,6 +70,12 @@ Send direct message:
|
|
65
70
|
client.notify("Hello There!", "@username")
|
66
71
|
```
|
67
72
|
|
73
|
+
You can also test gem via rake console:
|
74
|
+
|
75
|
+
```
|
76
|
+
rake console
|
77
|
+
```
|
78
|
+
|
68
79
|
## Gotchas
|
69
80
|
|
70
81
|
Current issues with Slack API:
|
data/Rakefile
CHANGED
@@ -0,0 +1,55 @@
|
|
1
|
+
require "json"
|
2
|
+
require "faraday"
|
3
|
+
|
4
|
+
module SlackNotify
|
5
|
+
class Client
|
6
|
+
include SlackNotify::Connection
|
7
|
+
|
8
|
+
def initialize(team, token, options = {})
|
9
|
+
@team = team
|
10
|
+
@token = token
|
11
|
+
@username = options[:username]
|
12
|
+
@channel = options[:channel]
|
13
|
+
@icon_url = options[:icon_url]
|
14
|
+
@icon_emoji = options[:icon_emoji]
|
15
|
+
|
16
|
+
validate_arguments
|
17
|
+
end
|
18
|
+
|
19
|
+
def test
|
20
|
+
notify("Test Message")
|
21
|
+
end
|
22
|
+
|
23
|
+
def notify(text, channel = nil)
|
24
|
+
delivery_channels(channel).each do |chan|
|
25
|
+
payload = SlackNotify::Payload.new(
|
26
|
+
text: text,
|
27
|
+
channel: chan,
|
28
|
+
username: @username,
|
29
|
+
icon_url: @icon_url,
|
30
|
+
icon_emoji: @icon_emoji
|
31
|
+
)
|
32
|
+
|
33
|
+
send_payload(payload)
|
34
|
+
end
|
35
|
+
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def validate_arguments
|
42
|
+
raise ArgumentError, "Team name required" if @team.nil?
|
43
|
+
raise ArgumentError, "Token required" if @token.nil?
|
44
|
+
raise ArgumentError, "Invalid team name" unless valid_team_name?
|
45
|
+
end
|
46
|
+
|
47
|
+
def valid_team_name?
|
48
|
+
@team =~ /^[a-z\d\-]+$/ ? true : false
|
49
|
+
end
|
50
|
+
|
51
|
+
def delivery_channels(channel)
|
52
|
+
[channel || @channel || "#general"].flatten.compact.uniq
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module SlackNotify
|
2
|
+
module Connection
|
3
|
+
def send_payload(payload)
|
4
|
+
conn = Faraday.new(hook_url, { timeout: 5, open_timeout: 5 }) do |c|
|
5
|
+
c.use(Faraday::Request::UrlEncoded)
|
6
|
+
c.adapter(Faraday.default_adapter)
|
7
|
+
end
|
8
|
+
|
9
|
+
response = conn.post do |req|
|
10
|
+
req.body = JSON.dump(payload.to_hash)
|
11
|
+
end
|
12
|
+
|
13
|
+
handle_response(response)
|
14
|
+
end
|
15
|
+
|
16
|
+
def handle_response(response)
|
17
|
+
unless response.success?
|
18
|
+
if response.body.include?("\n")
|
19
|
+
raise SlackNotify::Error
|
20
|
+
else
|
21
|
+
raise SlackNotify::Error.new(response.body)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def hook_url
|
27
|
+
"#{base_url}/services/hooks/incoming-webhook?token=#{@token}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def base_url
|
31
|
+
"https://#{@team}.slack.com"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module SlackNotify
|
2
|
+
class Payload
|
3
|
+
attr_accessor :username, :text, :channel, :icon_url, :icon_emoji
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@username = options[:username] || "webhookbot"
|
7
|
+
@channel = options[:channel] || "#general"
|
8
|
+
@text = options[:text]
|
9
|
+
@icon_url = options[:icon_url]
|
10
|
+
@icon_emoji = options[:icon_emoji]
|
11
|
+
|
12
|
+
unless channel[0] =~ /^(#|@)/
|
13
|
+
@channel = "##{@channel}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_hash
|
18
|
+
hash = {
|
19
|
+
text: text,
|
20
|
+
username: username,
|
21
|
+
channel: channel,
|
22
|
+
icon_url: icon_url,
|
23
|
+
icon_emoji: icon_emoji
|
24
|
+
}
|
25
|
+
|
26
|
+
hash.delete_if { |_,v| v.nil? }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/slack-notify/version.rb
CHANGED
data/lib/slack-notify.rb
CHANGED
@@ -1,75 +1,5 @@
|
|
1
1
|
require "slack-notify/version"
|
2
2
|
require "slack-notify/error"
|
3
|
-
|
4
|
-
require "
|
5
|
-
require "
|
6
|
-
|
7
|
-
module SlackNotify
|
8
|
-
class Client
|
9
|
-
def initialize(team, token, options = {})
|
10
|
-
@team = team
|
11
|
-
@token = token
|
12
|
-
@username = options[:username] || "webhookbot"
|
13
|
-
@channel = options[:channel] || "#general"
|
14
|
-
|
15
|
-
raise ArgumentError, "Team name required" if @team.nil?
|
16
|
-
raise ArgumentError, "Token required" if @token.nil?
|
17
|
-
raise ArgumentError, "Invalid team name" unless valid_team_name?
|
18
|
-
end
|
19
|
-
|
20
|
-
def test
|
21
|
-
notify("This is a test message!")
|
22
|
-
end
|
23
|
-
|
24
|
-
def notify(text, channel = nil)
|
25
|
-
format_channel(channel).each do |chan|
|
26
|
-
send_payload(text: text, username: @username, channel: chan)
|
27
|
-
end
|
28
|
-
|
29
|
-
true
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def format_channel(channel)
|
35
|
-
[channel || @channel].flatten.compact.uniq.map do |name|
|
36
|
-
name[0].match(/^(#|@)/) && name || "##{name}"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def send_payload(payload)
|
41
|
-
conn = Faraday.new(hook_url, { timeout: 5, open_timeout: 5 }) do |c|
|
42
|
-
c.use(Faraday::Request::UrlEncoded)
|
43
|
-
c.adapter(Faraday.default_adapter)
|
44
|
-
end
|
45
|
-
|
46
|
-
response = conn.post do |req|
|
47
|
-
req.body = JSON.dump(payload)
|
48
|
-
end
|
49
|
-
|
50
|
-
handle_response(response)
|
51
|
-
end
|
52
|
-
|
53
|
-
def handle_response(response)
|
54
|
-
unless response.success?
|
55
|
-
if response.body.include?("\n")
|
56
|
-
raise SlackNotify::Error
|
57
|
-
else
|
58
|
-
raise SlackNotify::Error.new(response.body)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def valid_team_name?
|
64
|
-
@team =~ /^[a-z\d\-]+$/ ? true : false
|
65
|
-
end
|
66
|
-
|
67
|
-
def hook_url
|
68
|
-
"#{base_url}/services/hooks/incoming-webhook?token=#{@token}"
|
69
|
-
end
|
70
|
-
|
71
|
-
def base_url
|
72
|
-
"https://#{@team}.slack.com"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
3
|
+
require "slack-notify/connection"
|
4
|
+
require "slack-notify/payload"
|
5
|
+
require "slack-notify/client"
|
@@ -23,68 +23,20 @@ describe SlackNotify::Client do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
describe "#test" do
|
26
|
-
let(:client)
|
27
|
-
described_class.new("foo", "token")
|
28
|
-
end
|
29
|
-
|
30
|
-
let(:payload) do
|
31
|
-
{
|
32
|
-
text: "This is a test message!",
|
33
|
-
channel: "#general",
|
34
|
-
username: "webhookbot"
|
35
|
-
}
|
36
|
-
end
|
26
|
+
let(:client) { described_class.new("foo", "token") }
|
37
27
|
|
38
28
|
before do
|
39
|
-
client.stub(:
|
29
|
+
client.stub(:notify)
|
30
|
+
client.test
|
40
31
|
end
|
41
32
|
|
42
|
-
it "sends a test
|
43
|
-
expect(client).to
|
44
|
-
client.test
|
33
|
+
it "it sends a test message" do
|
34
|
+
expect(client).to have_received(:notify).with("Test Message")
|
45
35
|
end
|
46
36
|
end
|
47
37
|
|
48
38
|
describe "#notify" do
|
49
|
-
let(:client)
|
50
|
-
described_class.new("foo", "token")
|
51
|
-
end
|
52
|
-
|
53
|
-
it "sends message to default channel" do
|
54
|
-
client.stub(:send_payload) { true }
|
55
|
-
|
56
|
-
expect(client).to receive(:send_payload).with(
|
57
|
-
text: "Message",
|
58
|
-
channel: "#general",
|
59
|
-
username: "webhookbot"
|
60
|
-
)
|
61
|
-
|
62
|
-
client.notify("Message")
|
63
|
-
end
|
64
|
-
|
65
|
-
it "sends message as default user" do
|
66
|
-
client.stub(:send_payload) { true }
|
67
|
-
|
68
|
-
expect(client).to receive(:send_payload).with(
|
69
|
-
text: "Message",
|
70
|
-
channel: "#general",
|
71
|
-
username: "webhookbot"
|
72
|
-
)
|
73
|
-
|
74
|
-
client.notify("Message")
|
75
|
-
end
|
76
|
-
|
77
|
-
it "sends message to a specified channel" do
|
78
|
-
client.stub(:send_payload) { true }
|
79
|
-
|
80
|
-
expect(client).to receive(:send_payload).with(
|
81
|
-
text: "Message",
|
82
|
-
channel: "#mychannel",
|
83
|
-
username: "webhookbot"
|
84
|
-
)
|
85
|
-
|
86
|
-
client.notify("Message", "#mychannel")
|
87
|
-
end
|
39
|
+
let(:client) { described_class.new("foo", "token") }
|
88
40
|
|
89
41
|
it "delivers payload" do
|
90
42
|
stub_request(:post, "https://foo.slack.com/services/hooks/incoming-webhook?token=token").
|
@@ -119,34 +71,44 @@ describe SlackNotify::Client do
|
|
119
71
|
end
|
120
72
|
end
|
121
73
|
|
122
|
-
context "
|
74
|
+
context "when icon_url is set" do
|
75
|
+
let(:client) { described_class.new("foo", "bar", icon_url: "foobar") }
|
76
|
+
|
123
77
|
before do
|
124
|
-
|
78
|
+
stub_request(:post, "https://foo.slack.com/services/hooks/incoming-webhook?token=bar").
|
79
|
+
with(:body => {"{\"text\":\"Message\",\"username\":\"webhookbot\",\"channel\":\"#general\",\"icon_url\":\"foobar\"}"=>true},
|
80
|
+
:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'Faraday v0.8.9'}).
|
81
|
+
to_return(:status => 200, :body => "", :headers => {})
|
125
82
|
end
|
126
83
|
|
127
|
-
it "
|
128
|
-
|
129
|
-
client.notify("Message", ["#channel1", "#channel2"])
|
84
|
+
it "includes url in payload" do
|
85
|
+
client.notify("Message")
|
130
86
|
end
|
131
87
|
end
|
132
88
|
|
133
|
-
context "when
|
134
|
-
|
89
|
+
context "when icon_emoji is set" do
|
90
|
+
let(:client) { described_class.new("foo", "bar", icon_emoji: "foobar") }
|
135
91
|
|
136
|
-
|
137
|
-
|
138
|
-
|
92
|
+
before do
|
93
|
+
stub_request(:post, "https://foo.slack.com/services/hooks/incoming-webhook?token=bar").
|
94
|
+
with(:body => {"{\"text\":\"Message\",\"username\":\"webhookbot\",\"channel\":\"#general\",\"icon_emoji\":\"foobar\"}"=>true},
|
95
|
+
:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'Faraday v0.8.9'}).
|
96
|
+
to_return(:status => 200, :body => "", :headers => {})
|
97
|
+
end
|
98
|
+
|
99
|
+
it "includes icon in payload" do
|
100
|
+
client.notify("Message")
|
139
101
|
end
|
140
102
|
end
|
141
103
|
|
142
|
-
context "
|
104
|
+
context "with multiple channels" do
|
143
105
|
before do
|
144
|
-
client.stub(:send_payload)
|
145
|
-
client.notify("Message", "
|
106
|
+
client.stub(:send_payload) { true }
|
107
|
+
client.notify("Message", ["#channel1", "#channel2"])
|
146
108
|
end
|
147
109
|
|
148
|
-
it "
|
149
|
-
expect(client).to have_received(:send_payload).
|
110
|
+
it "delivers payload to multiple channels" do
|
111
|
+
expect(client).to have_received(:send_payload).exactly(2).times
|
150
112
|
end
|
151
113
|
end
|
152
114
|
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe SlackNotify::Payload do
|
4
|
+
let(:options) do
|
5
|
+
{
|
6
|
+
username: "foo",
|
7
|
+
channel: "#bar",
|
8
|
+
text: "hola",
|
9
|
+
icon_url: "http://domain.com/image.png",
|
10
|
+
icon_emoji: ":chart_with_upwards_trend:"
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#initialize" do
|
15
|
+
let(:payload) { described_class.new(options) }
|
16
|
+
|
17
|
+
context "with options" do
|
18
|
+
it "sets username" do
|
19
|
+
expect(payload.username).to eq "foo"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "sets channel" do
|
23
|
+
expect(payload.channel).to eq "#bar"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "sets text" do
|
27
|
+
expect(payload.text).to eq "hola"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "sets icon url" do
|
31
|
+
expect(payload.icon_url).to eq "http://domain.com/image.png"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "sets icon emoji" do
|
35
|
+
expect(payload.icon_emoji).to eq ":chart_with_upwards_trend:"
|
36
|
+
end
|
37
|
+
|
38
|
+
context "on missing pound in channel" do
|
39
|
+
let(:options) do
|
40
|
+
{ channel: "foo" }
|
41
|
+
end
|
42
|
+
|
43
|
+
it "adds pound symbol" do
|
44
|
+
expect(payload.channel).to eq "#foo"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "on direct message" do
|
49
|
+
let(:options) do
|
50
|
+
{ channel: "@dan" }
|
51
|
+
end
|
52
|
+
|
53
|
+
it "keeps the symbol" do
|
54
|
+
expect(payload.channel).to eq "@dan"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "without options" do
|
60
|
+
let(:options) { Hash.new }
|
61
|
+
|
62
|
+
it "sets username" do
|
63
|
+
expect(payload.username).to eq "webhookbot"
|
64
|
+
end
|
65
|
+
|
66
|
+
it "sets channel" do
|
67
|
+
expect(payload.channel).to eq "#general"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#to_hash" do
|
73
|
+
let(:hash) { described_class.new(options).to_hash }
|
74
|
+
|
75
|
+
it "includes basic attributes" do
|
76
|
+
expect(hash).to eq Hash(
|
77
|
+
channel: "#bar",
|
78
|
+
icon_url: "http://domain.com/image.png",
|
79
|
+
icon_emoji: ":chart_with_upwards_trend:",
|
80
|
+
text: "hola",
|
81
|
+
username: "foo"
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
context "when icon url is not set" do
|
86
|
+
before do
|
87
|
+
options[:icon_url] = nil
|
88
|
+
end
|
89
|
+
|
90
|
+
it "excludes icon_url" do
|
91
|
+
expect(hash.keys).not_to include "icon_url"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "when icon emoji is not set" do
|
96
|
+
before do
|
97
|
+
options[:icon_emoji] = nil
|
98
|
+
end
|
99
|
+
|
100
|
+
it "excludes icon_emoji" do
|
101
|
+
expect(hash.keys).not_to include "icon_emoji"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slack-notify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Sosedoff
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-04-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -117,15 +117,20 @@ extra_rdoc_files: []
|
|
117
117
|
files:
|
118
118
|
- .gitignore
|
119
119
|
- .rspec
|
120
|
+
- .travis.yml
|
120
121
|
- Gemfile
|
121
122
|
- LICENSE.txt
|
122
123
|
- README.md
|
123
124
|
- Rakefile
|
124
125
|
- lib/slack-notify.rb
|
126
|
+
- lib/slack-notify/client.rb
|
127
|
+
- lib/slack-notify/connection.rb
|
125
128
|
- lib/slack-notify/error.rb
|
129
|
+
- lib/slack-notify/payload.rb
|
126
130
|
- lib/slack-notify/version.rb
|
127
131
|
- slack-notify.gemspec
|
128
132
|
- spec/slack-notify/client_spec.rb
|
133
|
+
- spec/slack-notify/payload_spec.rb
|
129
134
|
- spec/spec_helper.rb
|
130
135
|
homepage: https://github.com/sosedoff/slack-notify
|
131
136
|
licenses:
|
@@ -153,4 +158,5 @@ specification_version: 4
|
|
153
158
|
summary: Send notifications to a Slack channel
|
154
159
|
test_files:
|
155
160
|
- spec/slack-notify/client_spec.rb
|
161
|
+
- spec/slack-notify/payload_spec.rb
|
156
162
|
- spec/spec_helper.rb
|