slack_bot-events 0.0.4 → 0.2.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 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