slack_msgr 0.0.1 → 0.0.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: fd274c89233b9e5903e49f7e4243a859f2e78c74
4
- data.tar.gz: 7ba179fb4226cf6fafb36f6735c80b10daf28b3c
2
+ SHA256:
3
+ metadata.gz: 4e8ddbcbfbd549eb2c4ab898505896bf2d99ad950b1dda24167c4c7b0af2274f
4
+ data.tar.gz: 2d9f90f36aa0cc306ddf6b968b89cdf2280a41ef72b222ac00356c3fe685562b
5
5
  SHA512:
6
- metadata.gz: 1998160597b692ff67d57b2c6c794c6f3b807037c0da3186d6a5c6b4b46eb7caf1c70220dd8d08938b537fbae9078a06f305093a5efb99733ec8ce284fdb86ff
7
- data.tar.gz: 227e030f4de7db7f7c0ed5134217e6594d1efa5f2b71011dae41010bc2898754cbe76e952426d9b27cf107c5f2566df82707e5796a430fe808927000e4bc9f1b
6
+ metadata.gz: e8ee2351b8481befbd89f910b0f48855d5dfde409ac4611f7121de5311f2e7021b2553813f280539bdec5c17a208631f0e50c667766e443168ebb4475d72882b
7
+ data.tar.gz: 83810c251a1b51364de4d0f51ac216e3ceba00ee5f4a47a1a4d33dc35d88facc61826243212d11f9959acf12e099a20f686c1af6354aa6b43c12c9280459b570
@@ -58,10 +58,10 @@ AllCops:
58
58
  - bin/**
59
59
 
60
60
  Metrics/LineLength:
61
- Description: 'Limit lines to 100 characters.'
62
- StyleGuide: '#100-character-limits'
61
+ Description: 'Limit lines to 120 characters.'
62
+ StyleGuide: '#120-character-limits'
63
63
  Enabled: true
64
- Max: 100
64
+ Max: 120
65
65
  # To make it possible to copy or click on URIs in the code, we allow lines
66
66
  # containing a URI to be longer than Max.
67
67
  AllowHeredoc: true
@@ -0,0 +1 @@
1
+ ruby 2.6.2
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- slack_msgr (0.0.1)
4
+ slack_msgr (0.0.7)
5
5
  faraday (~> 0.15.4)
6
6
 
7
7
  GEM
@@ -26,7 +26,7 @@ GEM
26
26
  multipart-post (>= 1.2, < 3)
27
27
  ice_nine (0.11.2)
28
28
  jaro_winkler (1.5.2)
29
- json (2.2.0)
29
+ json (2.3.1)
30
30
  kwalify (0.7.2)
31
31
  method_source (0.9.2)
32
32
  multipart-post (2.1.1)
@@ -38,7 +38,7 @@ GEM
38
38
  method_source (~> 0.9.0)
39
39
  psych (3.1.0)
40
40
  rainbow (3.0.0)
41
- rake (10.5.0)
41
+ rake (13.0.1)
42
42
  reek (5.4.0)
43
43
  codeclimate-engine-rb (~> 0.4.0)
44
44
  kwalify (~> 0.7.0)
@@ -85,7 +85,7 @@ PLATFORMS
85
85
  DEPENDENCIES
86
86
  bundler (~> 2.0)
87
87
  pry
88
- rake (~> 10.0)
88
+ rake (~> 13.0)
89
89
  reek (~> 5.4.0)
90
90
  rspec (~> 3.0)
91
91
  rubocop (~> 0.71.0)
data/README.md CHANGED
@@ -33,14 +33,30 @@ If you are using this gem with a Rails project, create an initializer file.
33
33
  # ./config/initializers/slack_msgr.rb
34
34
 
35
35
  SlackMsgr.configure do |config|
36
- config.verification_token = '1a2b3c4d5e'
37
- config.client_secret = 'a1b2c3d4e5'
38
- config.signing_secret = 'aa11bb22cc3'
39
- config.oauth_access_token = 'xoxp-1234567-xxxxxxxxx'
40
- config.bot_user_oauth_access_token = 'xoxb-1234567-xxxxxxxxx'
36
+ config.verification_token = '1a2b3c4d5e'
37
+ config.client_secret = 'a1b2c3d4e5'
38
+ config.signing_secret = 'aa11bb22cc3'
39
+ config.access_tokens = {
40
+ bot: 'xoxp-1234567-xxxxxxxxx',
41
+ me: 'xoxb-1234567-xxxxxxxxx'
42
+ }
41
43
  end
42
44
  ```
43
45
 
46
+ _NOTE_: All access tokens are configured as a hash. The name of the keys are arbitrary, and there is no limit to keys that can be configured.
47
+
48
+ Multiple oauth tokens can be used during a single session. Oauth tokens are declared in the method execution. For example, considering the configuration above, to use the token attached to the key `:me` simply pass the parameter `use_token: :me`.
49
+
50
+ ```ruby
51
+ SlackMsgr.chat(:post_message,
52
+ use_token: :me,
53
+ channel: 'announcements',
54
+ text: 'Hello world'
55
+ )
56
+ ```
57
+
58
+ SlackMsgr will try to use a default token if a method is called without declaring `use_token:`. SlackMsgr takes the first token in the `access_tokens` hash as a default.
59
+
44
60
  If you are using this gem outside of a Rails project, follow the configuration pattern above, but be sure to run this code before using any functionality of the gem.
45
61
 
46
62
  ## Usage
@@ -59,6 +75,7 @@ SlackMsgr.chat(:post_message, channel: 'announcements', text: 'Hello world')
59
75
  # Sends the text 'Hello world' to the announcements channel
60
76
 
61
77
  SlackMsgr.chat(:post_message, {
78
+ use_token: :bot,
62
79
  channel: "C1H9RESGL",
63
80
  text: "Here's a message for you",
64
81
  as_user: false,
@@ -69,7 +86,7 @@ SlackMsgr.chat(:post_message, {
69
86
  fallback: "This is an attachment's fallback"
70
87
  }]
71
88
  })
72
- # Sends a message with an attachment as a user with the username 'testing'
89
+ # Sends a message with an attachment using the oauth token configured for :bot as a user with the username 'testing'
73
90
  ```
74
91
 
75
92
  ## License
@@ -5,5 +5,5 @@ module SlackMsgr
5
5
 
6
6
  SLACK_URL = 'https://slack.com'
7
7
 
8
- VERSION = '0.0.1'
8
+ VERSION = '0.0.7'
9
9
  end
@@ -2,6 +2,15 @@
2
2
 
3
3
  require 'json'
4
4
  require 'faraday'
5
+ require 'uri'
5
6
  require_relative './constants'
6
7
 
7
- Dir[File.expand_path 'lib/{slack_msgr,utils}/**/*.rb'].each { |f| require f }
8
+ path = __dir__
9
+
10
+ require "#{path}/../slack_msgr/slack_method"
11
+ require "#{path}/../slack_msgr/authenticate"
12
+ require "#{path}/../slack_msgr/chat"
13
+ require "#{path}/../slack_msgr/configuration"
14
+ require "#{path}/../slack_msgr/conversations"
15
+ require "#{path}/../slack_msgr/users"
16
+ require "#{path}/../utils/error_handling"
@@ -11,10 +11,19 @@ module SlackMsgr
11
11
 
12
12
  def configure
13
13
  yield(configuration)
14
+ nil
14
15
  end
15
16
 
16
17
  def chat(method, opts = {})
17
18
  Chat.call(method, opts)
18
19
  end
20
+
21
+ def users(*methods, **opts)
22
+ Users.call(methods, opts)
23
+ end
24
+
25
+ def conversations(method, **opts)
26
+ Conversations.call(method, opts)
27
+ end
19
28
  end
20
29
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SlackMsgr
4
+ # Handles various authentication patterns offered by Slack
5
+ class Authenticate
6
+ class << self
7
+ def verification_token?(token)
8
+ token == SlackMsgr.configuration.verification_token
9
+ end
10
+
11
+ def signing_secret?(request)
12
+ signature = request.headers['X-Slack-Signature']
13
+ timestamp = request.headers['X-Slack-Request-Timestamp']
14
+ version = signature.split('=').first
15
+ body = request.body.read
16
+
17
+ # The request timestamp is more than five minutes from local time.
18
+ # It could be a replay attack, so let's ignore it.
19
+ return false if timestamp_over_five_minutes_old?(timestamp)
20
+
21
+ signature == "#{version}=#{compute_hash_sha256(version, timestamp, body)}"
22
+ end
23
+
24
+ private
25
+
26
+ def compute_hash_sha256(version, timestamp, body)
27
+ digest = OpenSSL::Digest::SHA256.new
28
+ OpenSSL::HMAC.hexdigest(digest, SlackMsgr.configuration.signing_secret, "#{version}:#{timestamp}:#{body}")
29
+ end
30
+
31
+ def timestamp_over_five_minutes_old?(timestamp)
32
+ (Time.now - Time.at(timestamp.to_i)) > (60 * 5)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -29,12 +29,7 @@ module SlackMsgr
29
29
  class << self
30
30
  def call(method, opts = {})
31
31
  chat = new(method, opts)
32
-
33
- conn.post do |req|
34
- req.url "/api/#{chat.method}"
35
- req.headers['Content-Type'] = 'application/json; charset=utf-8'
36
- req.body = chat.body
37
- end
32
+ send_post_request_to_slack(chat)
38
33
  end
39
34
  end
40
35
 
@@ -54,7 +49,8 @@ module SlackMsgr
54
49
  private
55
50
 
56
51
  def sanitize_body
57
- ErrorHandling.raise(:req_args_missing, req_args: REQUIRED_ARGUMENTS, method: method) if req_args_missing? # rubocop:disable LineLength
52
+ ErrorHandling.raise(:req_args_missing, req_args: REQUIRED_ARGUMENTS, method: method) if req_args_missing?
53
+
58
54
  opts.keys.each_with_object({}) do |key, body|
59
55
  body[key] ||= opts[key] if PERMITTED_ARGUMENTS.include?(key)
60
56
  body
@@ -6,29 +6,50 @@ module SlackMsgr
6
6
  attr_accessor :verification_token,
7
7
  :client_secret,
8
8
  :signing_secret,
9
- :oauth_access_token,
10
- :bot_user_oauth_access_token
9
+ :legacy_token,
10
+ :access_tokens,
11
+ :set_default_token
11
12
 
12
- def initialize(
13
+ def initialize( # rubocop:disable Metrics/ParameterLists
13
14
  verification_token: nil,
14
15
  client_secret: nil,
15
16
  signing_secret: nil,
16
- oauth_access_token: nil,
17
- bot_user_oauth_access_token: nil
17
+ legacy_token: nil,
18
+ access_tokens: {},
19
+ set_default_token: nil
18
20
  )
19
- @verification_token = verification_token
20
- @client_secret = client_secret
21
- @signing_secret = signing_secret
22
- @oauth_access_token = oauth_access_token
23
- @bot_user_oauth_access_token = bot_user_oauth_access_token
21
+ @verification_token = verification_token
22
+ @client_secret = client_secret
23
+ @signing_secret = signing_secret
24
+ @legacy_token = legacy_token
25
+ @access_tokens = access_tokens
26
+ @set_default_token = set_default_token
24
27
  end
25
28
 
26
29
  def clear!
27
- @verification_token = nil
28
- @client_secret = nil
29
- @signing_secret = nil
30
- @oauth_access_token = nil
31
- @bot_user_oauth_access_token = nil
30
+ @verification_token = nil
31
+ @client_secret = nil
32
+ @signing_secret = nil
33
+ @legacy_token = nil
34
+ @access_tokens = {}
35
+ @set_default_token = nil
36
+ @default_token = nil
37
+ end
38
+
39
+ def default_token
40
+ @default_token ||= initialize_default_token
41
+ end
42
+
43
+ def initialize_default_token
44
+ return unless access_tokens&.first
45
+
46
+ access_tokens[set_default_token] || access_tokens.first[1]
47
+ end
48
+
49
+ def oauth_access_token(given_token)
50
+ token = access_tokens[given_token] || default_token
51
+ ErrorHandling.raise(:configuration_error) unless token
52
+ token
32
53
  end
33
54
  end
34
55
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SlackMsgr
4
+ # Handles all conversations functionality and methods corresponding with Slack API
5
+ class Conversations < SlackMethod
6
+ CONVERSATIONS_METHODS = { open: 'open' }.freeze
7
+
8
+ REQUIRED_ARGUMENTS = %i[token users].freeze
9
+
10
+ PERMITTED_ARGUMENTS = %i[token channel return_im users].freeze
11
+
12
+ class << self
13
+ def call(method, opts = {})
14
+ chat = new(method, opts)
15
+ send_post_request_to_slack(chat)
16
+ end
17
+ end
18
+
19
+ attr_reader :method,
20
+ :opts,
21
+ :body
22
+
23
+ def initialize(method, opts)
24
+ conversations_method = CONVERSATIONS_METHODS[method]
25
+ ErrorHandling.raise(:unknown_method, method: method) unless conversations_method
26
+
27
+ @method = "conversations.#{conversations_method}"
28
+ @opts = opts
29
+ @body = sanitize_body
30
+ end
31
+
32
+ private
33
+
34
+ def sanitize_body
35
+ ErrorHandling.raise(:req_args_missing, req_args: REQUIRED_ARGUMENTS, method: method) if req_args_missing?
36
+
37
+ opts.keys.each_with_object({}) do |key, body|
38
+ body[key] ||= opts[key] if PERMITTED_ARGUMENTS.include?(key)
39
+ body
40
+ end.to_json
41
+ end
42
+
43
+ def req_args_missing?
44
+ !(REQUIRED_ARGUMENTS - opts.keys).empty?
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SlackMsgr
4
+ # Handles all requests with Slack API
5
+ class SlackMethod
6
+ class << self
7
+ private
8
+
9
+ def conn
10
+ @conn ||= Faraday.new(url: SLACK_URL) do |config|
11
+ config.request :url_encoded # form-encode POST params
12
+ config.adapter Faraday.default_adapter # make requests with Net::HTTP
13
+ end
14
+ end
15
+
16
+ def conceal(token)
17
+ token.split('Bearer ').last[0..-6].gsub(/[a-zA-Z0-9]/, 'X') + token[-5..-1]
18
+ end
19
+
20
+ def add_metadata_to_response(response)
21
+ JSON.parse(response.body, symbolize_names: true)
22
+ .merge!(auth_token: conceal(conn.headers['Authorization']))
23
+ end
24
+
25
+ def send_post_request_to_slack(obj)
26
+ conn.authorization :Bearer, SlackMsgr.configuration.oauth_access_token(obj.opts[:use_token])
27
+ response = conn.post do |req|
28
+ req.url "/api/#{obj.method}"
29
+ req.headers['Content-Type'] = 'application/json; charset=utf-8'
30
+ req.body = obj.body
31
+ end
32
+ add_metadata_to_response(response)
33
+ end
34
+
35
+ def send_legacy_request_to_slack(obj)
36
+ conn.authorization :Bearer, SlackMsgr.configuration.legacy_token
37
+ response = conn.post do |req|
38
+ req.url "/api/#{obj.method}"
39
+ req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
40
+ req.body = URI.encode_www_form(obj.body)
41
+ end
42
+ JSON.parse(response.body, symbolize_names: true)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SlackMsgr
4
+ # Handles all users functionality and methods corresponding with Slack API
5
+ class Users < SlackMethod
6
+ USERS_METHODS = {
7
+ admin: 'admin',
8
+ invite: 'invite'
9
+ }.freeze
10
+
11
+ REQUIRED_ARGUMENTS = %i[email].freeze
12
+
13
+ PERMITTED_ARGUMENTS = %i[
14
+ token
15
+ email
16
+ channels
17
+ real_name
18
+ resend
19
+ restricted
20
+ ultra_restricted
21
+ expiration_ts
22
+ ].freeze
23
+
24
+ class << self
25
+ def call(method, opts = {})
26
+ users = new(method, opts)
27
+ send_legacy_request_to_slack(users)
28
+ end
29
+ end
30
+
31
+ attr_reader :method,
32
+ :opts,
33
+ :body
34
+
35
+ def initialize(methods, opts)
36
+ users_method = methods.map do |method|
37
+ ErrorHandling.raise(:unknown_method, method: method) unless USERS_METHODS[method]
38
+
39
+ USERS_METHODS[method]
40
+ end.join('.')
41
+
42
+ @method = "users.#{users_method}"
43
+ @opts = opts
44
+ @body = sanitize_body
45
+ end
46
+
47
+ private
48
+
49
+ def sanitize_body
50
+ ErrorHandling.raise(:req_args_missing, req_args: REQUIRED_ARGUMENTS, method: method) if req_args_missing?
51
+
52
+ opts.merge!(token).keys.each_with_object({}) do |key, body|
53
+ body[key] ||= opts[key] if PERMITTED_ARGUMENTS.include?(key)
54
+ body
55
+ end
56
+ end
57
+
58
+ def req_args_missing?
59
+ !(REQUIRED_ARGUMENTS - opts.keys).empty?
60
+ end
61
+
62
+ def token
63
+ { token: SlackMsgr.configuration.legacy_token }
64
+ end
65
+ end
66
+ end
@@ -21,8 +21,8 @@ module SlackMsgr
21
21
  def configuration_error(_opts)
22
22
  {
23
23
  exception: ConfigurationError,
24
- message: "Error with configruation: oauth_access_token not found\n" \
25
- 'Be sure to configure all tokens and secrets'
24
+ message: "Error with configruation: access_tokens not found\n" \
25
+ 'At least one oauth token must be configured using access_tokens'
26
26
  }
27
27
  end
28
28
 
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
33
33
  spec.add_dependency 'faraday', '~>0.15.4'
34
34
 
35
35
  spec.add_development_dependency 'bundler', '~> 2.0'
36
- spec.add_development_dependency 'rake', '~> 10.0'
36
+ spec.add_development_dependency 'rake', '~> 13.0'
37
37
  spec.add_development_dependency 'rspec', '~> 3.0'
38
38
  spec.add_development_dependency 'rubocop', '~> 0.71.0'
39
39
  spec.add_development_dependency 'reek', '~> 5.4.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slack_msgr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Workman
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-03 00:00:00.000000000 Z
11
+ date: 2020-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: '13.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: '13.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -134,6 +134,7 @@ files:
134
134
  - ".reek.yml"
135
135
  - ".rspec"
136
136
  - ".rubocop.yml"
137
+ - ".tool-versions"
137
138
  - CODE_OF_CONDUCT.md
138
139
  - Gemfile
139
140
  - Gemfile.lock
@@ -145,9 +146,12 @@ files:
145
146
  - lib/config/constants.rb
146
147
  - lib/config/initializer.rb
147
148
  - lib/slack_msgr.rb
149
+ - lib/slack_msgr/authenticate.rb
148
150
  - lib/slack_msgr/chat.rb
149
151
  - lib/slack_msgr/configuration.rb
150
- - lib/slack_msgr/fetcher.rb
152
+ - lib/slack_msgr/conversations.rb
153
+ - lib/slack_msgr/slack_method.rb
154
+ - lib/slack_msgr/users.rb
151
155
  - lib/utils/error_handling.rb
152
156
  - slack_msgr.gemspec
153
157
  homepage: https://github.com/rdavid1099/slack-msgr
@@ -156,7 +160,7 @@ licenses:
156
160
  metadata:
157
161
  homepage_uri: https://github.com/rdavid1099/slack-msgr
158
162
  source_code_uri: https://github.com/rdavid1099/slack_msgr
159
- post_install_message:
163
+ post_install_message:
160
164
  rdoc_options: []
161
165
  require_paths:
162
166
  - lib
@@ -171,9 +175,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
175
  - !ruby/object:Gem::Version
172
176
  version: '0'
173
177
  requirements: []
174
- rubyforge_project:
175
- rubygems_version: 2.6.14
176
- signing_key:
178
+ rubygems_version: 3.1.4
179
+ signing_key:
177
180
  specification_version: 4
178
181
  summary: A Ruby gem to send and receive messages through Slack
179
182
  test_files: []
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SlackMsgr
4
- # Handles all requests with Slack API
5
- class SlackMethod
6
- class << self
7
- private
8
-
9
- def conn
10
- oauth_access_token = SlackMsgr.configuration.oauth_access_token
11
- ErrorHandling.raise(:configuration_error) unless oauth_access_token
12
-
13
- faraday = Faraday.new(url: SLACK_URL) do |config|
14
- config.request :url_encoded # form-encode POST params
15
- config.adapter Faraday.default_adapter # make requests with Net::HTTP
16
- end
17
- faraday.authorization :Bearer, oauth_access_token
18
- faraday
19
- end
20
- end
21
- end
22
- end