slack_bot-events 0.0.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 214337c85ccf72326faf95c1fca9b46bc46293d98e404bb3dc8856bec70534c3
4
- data.tar.gz: 4fa855274d80b70ece04fad550fe949fbda80557b8629d2595f40f9d09c66b7b
3
+ metadata.gz: e221d5ba2b7822f18b4079b73bc35005488510570b1c6bf1121b29ae3a38a85f
4
+ data.tar.gz: 7c6fd667337ad3eaefc080abac2d53295b6226c41570dcebc118eb321e218a0b
5
5
  SHA512:
6
- metadata.gz: be57b63b5ce9a1aeea150b8944a38a764094be0970c9cddff0538877f70ba3723fa9dd869b4b5df916ea2474ab7fd05c56c89c2dc984a760d87039f8dc7dfe95
7
- data.tar.gz: 58ac99258d980088a670194c496248edaad9e4cb2dcd1639278079a9108e983a8981c56419781d9db3ce468f0558f81e6a499b41cd8b0edecfa834bf618d039e
6
+ metadata.gz: 9545811f097ea137483b27bfd4b93cfb9d64040487051fd9f906de4d67e09503768fa4341faad9eed36348edf644ad33be7f9109f3c5a9d5741d59fc9c8ca17b
7
+ data.tar.gz: 2afc096dd076de82f0f3443a7ac437be405f6b8613db994072a94cb05623797cc631b178e163c756ddfbd7f2c29e337bbb42db5fe71e42aed0b5b148c3bfd5ea
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- slack_bot-events (0.0.1)
4
+ slack_bot-events (0.1.0)
5
5
  class_composer (~> 1.0)
6
6
  faraday
7
7
  faye-websocket
@@ -13,32 +13,80 @@ module SlackBot
13
13
  def start!
14
14
  EM.run do
15
15
  websocket.on :open do |event|
16
- p [:open]
16
+ event_tracer(:open)
17
17
  end
18
18
 
19
19
  websocket.on :message do |event|
20
- parsed_data = JSON.parse(event.data)
21
- if parsed_data["type"] == "events_api"
22
- puts parsed_data.to_json
23
- item = SlackBot::Events::Schemas::SocketPayload.new(parsed_data)
24
- s = {
25
- type: item.payload.event.type,
26
- tldr: item.payload.event.tldr,
27
- }
28
- puts s
29
- websocket.send("#{{ envelope_id: item.envelope_id }.to_json}")
30
- else
31
- puts event.data
20
+ event_tracer(:message) do
21
+ parsed_data = JSON.parse(event.data)
22
+ case parsed_data["type"]
23
+ when "events_api"
24
+ events_api(parsed_data)
25
+ when "app_rate_limited"
26
+ # https://api.slack.com/apis/rate-limits#events
27
+ # Total allowed workspace events are 30,000 per hour
28
+ # This message type is received once you have gone beyond that
29
+ params = {
30
+ minute_rate_limited: parsed_data["minute_rate_limited"],
31
+ team_id: parsed_data["team_id"],
32
+ api_app_id: parsed_data["api_app_id"],
33
+ }
34
+ event_tracer("message:app_rate_limited", **params)
35
+ when "hello"
36
+ params = {
37
+ num_connections: parsed_data["num_connections"],
38
+ debug_info_host: parsed_data["debug_info"]["host"],
39
+ debug_info_connect_time: parsed_data["debug_info"]["approximate_connection_time"],
40
+ }
41
+ event_tracer("message:hello", **params)
42
+ end
32
43
  end
33
44
  end
34
45
 
35
46
  websocket.on :close do |event|
36
- p [:close, event.code, event.reason]
47
+ event_tracer(:close, code: event.code, reason: event.reason)
37
48
  @websocket = nil
38
49
  end
39
50
  end
40
51
  end
41
52
 
53
+ def events_api(parsed_data)
54
+ schematized = SlackBot::Events::Schemas::SocketPayload.new(parsed_data)
55
+ Events.logger.info(schematized.tldr) if Events.config.print_tldr
56
+ object = Events.config.listeners[schematized.type.to_sym]
57
+ if object
58
+ safe_handler(type: schematized.type.to_sym, object: object, schema: schematized, parsed_data: parsed_data)
59
+ end
60
+ websocket.send("#{{ envelope_id: schematized.envelope_id }.to_json}")
61
+ end
62
+
63
+ def event_tracer(type, **params)
64
+ stringify = params.map { |k,v| "#{k}:#{v}" }.join("; ")
65
+ Events.logger.info "[Event Received] #{type} #{stringify}"
66
+ if block_given?
67
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
68
+ yield
69
+ elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time
70
+ Events.logger.info "[Event completed] [#{elapsed_time.round(3)}s] #{type} #{stringify}"
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ def safe_handler(type:, object:, schema:, parsed_data:)
77
+ Events.logger.info "Received Handler for #{type}"
78
+ object[:handler].call(schema: schema, raw_data: parsed_data)
79
+ object[:on_success]&.call(schema)
80
+ rescue => error
81
+ Events.logger.error("#{object[:handler]} returned #{error.class} => #{error.message}. Safely returning to websocket. #{error.backtrace[0...10]}")
82
+
83
+ begin
84
+ object[:on_failure]&.call(schema, error)
85
+ rescue => on_failure_error
86
+ Events.logger.error("Failure occured during on_failure block. #{on_failure_error}")
87
+ end
88
+ end
89
+
42
90
  def websocket
43
91
  @websocket ||= Faye::WebSocket::Client.new(socket_endpoint)
44
92
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "class_composer"
4
+ require "logger"
4
5
 
5
6
  module SlackBot
6
7
  module Events
@@ -11,22 +12,59 @@ module SlackBot
11
12
  add_composer :client_signing_secret, allowed: String, default: ENV["SLACK_SIGNING_SECRET"]
12
13
  add_composer :client_socket_token, allowed: String, default: ENV["SLACK_SOCKET_TOKEN"]
13
14
  add_composer :client_verification_token, allowed: String, default: ENV["SLACK_VERIFICATION_TOKEN"]
15
+ add_composer :print_tldr, allowed: [true.class, false.class], default: true
14
16
 
15
- def register_listener(name:, handler:)
16
- @listeners ||= {}
17
-
18
- if @listeners.has_key(name.to_sym)
17
+ def register_listener(name:, handler:, on_success: nil, on_failure: nil)
18
+ if event_handler = listeners[name.to_sym]
19
+ logger.warn "`#{name}` already exists as listener event. Reseting with new input"
19
20
  end
20
21
 
21
- @listeners[name] = handler
22
+ validate_listener!(handler: handler, on_success: on_success, on_failure: on_failure)
22
23
 
24
+ listeners[name.to_sym] = { handler: handler, name: name, on_success: on_success, on_failure: on_failure }
23
25
  true
24
26
  end
25
27
 
26
28
  def remove_listener(name:)
29
+ listeners ||= {}
30
+ end
31
+
32
+ def logger
33
+ @logger ||= Logger.new(STDOUT)
34
+ end
35
+
36
+ def logger=(log)
37
+ @logger = log
38
+ end
39
+
40
+ def listeners
27
41
  @listeners ||= {}
42
+ end
43
+
44
+ private
45
+
46
+ def validate_listener!(handler:, on_success:, on_failure:)
47
+ unless retreive_method(object: handler, meth_name: :call)
48
+ raise ArgumentError, "When present, handler argument needs to respond_to :call with schema: and raw_data: kwargs"
49
+ end
28
50
 
51
+ if on_success
52
+ unless retreive_method(object: on_success, meth_name: :call)
53
+ raise ArgumentError, "When present, on_success argument needs to respond_to :call with 1 arguments passed in"
54
+ end
55
+ end
56
+
57
+ if on_failure
58
+ unless retreive_method(object: on_failure, meth_name: :call)
59
+ raise ArgumentError, "When present, on_failure argument needs to respond_to :call with 2 arguments passed in"
60
+ end
61
+ end
62
+ end
29
63
 
64
+ def retreive_method(object:, meth_name:)
65
+ object.method(meth_name.to_sym)
66
+ rescue NameError
67
+ nil
30
68
  end
31
69
  end
32
70
  end
@@ -19,6 +19,17 @@ module SlackBot
19
19
  add_field name: :accepts_response_payload, type: JsonSchematize::Boolean
20
20
  add_field name: :retry_attempt, type: Integer
21
21
  add_field name: :retry_reason, type: String
22
+
23
+
24
+ def type
25
+ payload.event.type
26
+ end
27
+
28
+ def tldr
29
+ retry_language = "#{retry_attempt}"
30
+ retry_language += ":#{retry_reason}" if retry_attempt > 0
31
+ "tldr:#{payload.event.tldr}; retry:#{retry_language}"
32
+ end
22
33
  end
23
34
  end
24
35
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json_schematize"
4
+ require "json_schematize/generator"
5
+
6
+ module SlackBot
7
+ module Events
8
+ module Schemas
9
+ module Type
10
+ class BotProfile < JsonSchematize::Generator
11
+ schema_default option: :dig_type, value: :string
12
+
13
+ add_field name: :id, type: String
14
+ add_field name: :app_id, type: String
15
+ add_field name: :name, type: String
16
+ add_field name: :deleted, type: JsonSchematize::Boolean
17
+ add_field name: :updated, type: String
18
+ add_field name: :team_id, type: String
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -4,6 +4,7 @@ require "json_schematize"
4
4
  require "json_schematize/generator"
5
5
 
6
6
  require "slack_bot/events/schemas/type/block"
7
+ require "slack_bot/events/schemas/type/bot_profile"
7
8
 
8
9
  module SlackBot
9
10
  module Events
@@ -20,14 +21,40 @@ module SlackBot
20
21
  add_field name: :team, type: String
21
22
 
22
23
  add_field name: :blocks, type: SlackBot::Events::Schemas::Type::Block, array_of_types: true
24
+ add_field name: :bot_profile, type: SlackBot::Events::Schemas::Type::BotProfile, required: false
25
+
26
+ add_field name: :thread_ts, type: String, required: false
27
+ add_field name: :parent_user_id, type: String, required: false
23
28
 
24
29
  add_field name: :channel, type: String
25
30
  add_field name: :event_ts, type: String
26
31
  add_field name: :channel_type, type: String
27
32
 
33
+ def made_from_user?
34
+ bot_profile.nil? || JsonSchematize::EmptyValue === bot_profile
35
+ end
36
+
37
+ def made_from_bot?
38
+ !made_from_user?
39
+ end
40
+
28
41
  def tldr
29
42
  "type: #{type}; channel:#{channel}; raw_text:#{text}"
30
43
  end
44
+
45
+ def thread_ts
46
+ return_nil?(@thread_ts) ? nil : @thread_ts
47
+ end
48
+
49
+ def parent_user_id
50
+ return_nil?(@parent_user_id) ? nil : @parent_user_id
51
+ end
52
+
53
+ private
54
+
55
+ def return_nil?(val)
56
+ JsonSchematize::EmptyValue === val || val.nil?
57
+ end
31
58
  end
32
59
  end
33
60
  end
@@ -23,6 +23,10 @@ module SlackBot
23
23
  item.channel
24
24
  end
25
25
 
26
+ def message_ts
27
+ item.ts
28
+ end
29
+
26
30
  def tldr
27
31
  "type: #{type}; channel:#{channel}; reaction:#{reaction}"
28
32
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module SlackBot
4
4
  module Events
5
- VERSION = "0.0.4"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
@@ -29,12 +29,16 @@ module SlackBot
29
29
  raise Error, "Expected configuration to be a SlackBot::Events::Configuration"
30
30
  end
31
31
 
32
- def self.register_listener(name:, handler:)
33
- config.register_listener(name: name, handler: handler)
32
+ def self.register_listener(name:, handler:, on_success: nil, on_failure: nil)
33
+ config.register_listener(name: name, handler: handler, on_success: on_success, on_failure: on_failure)
34
34
  end
35
35
 
36
36
  def self.remove_listener(name:)
37
37
  config.remove_listener(name: name)
38
38
  end
39
+
40
+ def self.logger
41
+ config.logger
42
+ end
39
43
  end
40
44
  end
@@ -0,0 +1 @@
1
+ require "slack_bot/events"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slack_bot-events
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Taylor
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-16 00:00:00.000000000 Z
11
+ date: 2024-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -130,6 +130,7 @@ files:
130
130
  - bin/setup
131
131
  - bin/start
132
132
  - docker-compose.yml
133
+ - lib/slack_bot-events.rb
133
134
  - lib/slack_bot/events.rb
134
135
  - lib/slack_bot/events/client.rb
135
136
  - lib/slack_bot/events/configuration.rb
@@ -138,6 +139,7 @@ files:
138
139
  - lib/slack_bot/events/schemas/socket_payload.rb
139
140
  - lib/slack_bot/events/schemas/type/base.rb
140
141
  - lib/slack_bot/events/schemas/type/block.rb
142
+ - lib/slack_bot/events/schemas/type/bot_profile.rb
141
143
  - lib/slack_bot/events/schemas/type/element.rb
142
144
  - lib/slack_bot/events/schemas/type/item.rb
143
145
  - lib/slack_bot/events/schemas/type/message.rb