lucid_intercom 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -22
  3. data/lib/lucid_intercom/attributes.rb +10 -42
  4. data/lib/lucid_intercom/changed_plan_event.rb +31 -0
  5. data/lib/lucid_intercom/company_attributes.rb +21 -0
  6. data/lib/lucid_intercom/company_custom_attributes.rb +48 -0
  7. data/lib/lucid_intercom/config.rb +44 -0
  8. data/lib/lucid_intercom/convert.rb +32 -0
  9. data/lib/lucid_intercom/{errors/error.rb → error.rb} +0 -0
  10. data/lib/lucid_intercom/event.rb +77 -0
  11. data/lib/lucid_intercom/installed_event.rb +31 -0
  12. data/lib/lucid_intercom/post_request.rb +26 -0
  13. data/lib/lucid_intercom/render_snippet.rb +28 -24
  14. data/lib/lucid_intercom/response.rb +51 -0
  15. data/lib/lucid_intercom/send_event.rb +22 -60
  16. data/lib/lucid_intercom/snippet.html.erb +2 -14
  17. data/lib/lucid_intercom/uninstalled_event.rb +27 -0
  18. data/lib/lucid_intercom/update_user.rb +24 -54
  19. data/lib/lucid_intercom/user_attributes.rb +47 -0
  20. data/lib/lucid_intercom/version.rb +1 -1
  21. data/lib/lucid_intercom.rb +18 -6
  22. metadata +56 -16
  23. data/lib/lucid_intercom/attributes/base.rb +0 -63
  24. data/lib/lucid_intercom/attributes/company.rb +0 -22
  25. data/lib/lucid_intercom/attributes/custom.rb +0 -47
  26. data/lib/lucid_intercom/attributes/user.rb +0 -28
  27. data/lib/lucid_intercom/credentials.rb +0 -35
  28. data/lib/lucid_intercom/errors/missing_credentials_error.rb +0 -7
  29. data/lib/lucid_intercom/errors/request_error.rb +0 -17
  30. data/lib/lucid_intercom/errors.rb +0 -3
  31. data/lib/lucid_intercom/events/base.rb +0 -23
  32. data/lib/lucid_intercom/events/changed_plan.rb +0 -37
  33. data/lib/lucid_intercom/events/installed.rb +0 -37
  34. data/lib/lucid_intercom/events/uninstalled.rb +0 -33
  35. data/lib/lucid_intercom/events.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e093b7cbc34689c682b5f4f1d3fd4fdef7ac033c9cf0fba38b0404e54f50c9a8
4
- data.tar.gz: e08a13e91779a38d92d076bcfad7a7e6003ad5b3ea4de3086cfc0ca9432d162e
3
+ metadata.gz: 1a133b6b1ae95502c5f15501cd40ea84d155d7f703cccc56befe4a32500533d6
4
+ data.tar.gz: 4e0b268ce267c890be6bbf61fc52f8bfbca449d37a45ee68a1db8db25f5be494
5
5
  SHA512:
6
- metadata.gz: b02dbad3e5c7284f146b53f02e2bac8ed500edb95662ed5cfc1a709330b80db817c035973a451f2d9af7a58f3d62d2dcb33df4f1b1b04a188d71fb186ce90703
7
- data.tar.gz: e2de118f2b5767081d4f8bea3d75ec8e359644799f94e1542c69917d248d12635a3af5d0348ac1f98674242c90f992d33437ee7316ac07d3657e80d83d2e0c33
6
+ metadata.gz: 6b089504958e012d93ca00a847ced2243ee5c22fbe93e2395250898be6063726f5ba87d3b2a2fae48383a3214996e73fb4ccbbb9cd958d56a50cfaec1f898762
7
+ data.tar.gz: 470849470d05d34ed775f382af97866684559fd9e0c0fdb95fdad207729f74dc0f6169cf6a6c2916fe2341c61c13d1ec39e7918787866a1aec2916f476bf6e64
data/README.md CHANGED
@@ -14,7 +14,7 @@ Usage
14
14
 
15
15
  ### Configure the default API credentials
16
16
 
17
- LucidIntercom.credentials = LucidIntercom::Credentials.new(
17
+ LucidIntercom.config = LucidIntercom::Config.new(
18
18
  '...', # access_token
19
19
  '...', # secret
20
20
  '...', # app_id
@@ -23,13 +23,10 @@ Usage
23
23
 
24
24
  Here, ‘app_prefix’ is the snakecased app name, e.g. ‘smart_order_tags’
25
25
 
26
- Alternatively, a credentials object may optionally be passed as a
27
- keyword argument to any of the classes listed below.
28
-
29
26
 
30
27
  ### Render the browser snippet
31
28
 
32
- LucidIntercom::RenderSnippet.new(shop_attributes, app_attributes).()
29
+ LucidIntercom::RenderSnippet.new.(shopify_data, app_data)
33
30
 
34
31
  This returns an HTML string which you can use in your view layout.
35
32
 
@@ -40,12 +37,14 @@ See the source code for documentation of arguments.
40
37
 
41
38
  When a user installs/uninstalls the app, or changes their plan:
42
39
 
43
- LucidIntercom::Events::Installed.new(shop_attributes).(plan_name)
44
- LucidIntercom::Events::Uninstalled.new(shop_attributes).()
45
- LucidIntercom::Events::ChangedPlan.new(shop_attributes).(plan_name)
40
+ event = LucidIntercom::InstalledEvent.new(shopify_data, new_plan)
41
+ event = LucidIntercom::UninstalledEvent.new(shopify_data)
42
+ event = LucidIntercom::ChangedPlanEvent.new(shopify_data, new_plan)
43
+
44
+ LucidIntercom::SendEvent.new.(event)
46
45
 
47
- Note that the `shop_attributes` hash for uninstalled events cannot
48
- be read from the API (as the access token is invalid at this stage).
46
+ Note that the `shopify_data` hash for uninstalled events cannot be
47
+ read from the API (as the access token is invalid at this stage).
49
48
  You should use the data hash provided with Shopify’s ‘app/uninstalled’
50
49
  webhook instead.
51
50
 
@@ -61,16 +60,7 @@ For free apps, use ‘free’.
61
60
  For partner-friendly app installs, use ‘partner’.
62
61
 
63
62
 
64
- ### Send a custom event
65
-
66
- LucidIntercom::SendEvent.new(shop_attributes).(event_name, event_metadata)
67
-
68
- See the source code for documentation of arguments.
69
-
70
-
71
- ### Update a user
72
-
73
- LucidIntercom::UpdateUser.new(shop_attributes, app_attributes).()
63
+ ### Custom events
74
64
 
75
- When this is called, and the user did not previously exist, the
76
- user will be created.
65
+ To define a custom event, subclass `LucidIntercom::Event`. See the
66
+ source code for documentation.
@@ -1,57 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'lucid_intercom/attributes/user'
4
- require 'lucid_intercom/attributes/company'
5
- require 'lucid_intercom/attributes/custom'
3
+ require 'dry-initializer'
4
+
5
+ require 'lucid_intercom/convert'
6
6
 
7
7
  module LucidIntercom
8
8
  class Attributes
9
- #
10
- # @see LucidIntercom::Attributes::Base#initialize
11
- #
12
- def initialize(*args)
13
- @args = args
14
- end
9
+ extend Dry::Initializer
15
10
 
16
- #
17
- # @return [Hash]
18
- #
19
- def user
20
- user_browser.reject { |k, _| k == :user_hash }
21
- end
11
+ # @return [Hash] shop attributes as returned by the Shopify API
12
+ param :shopify_data, reader: :private
22
13
 
23
14
  #
24
- # User attributes for browser (with 'user_hash').
25
- #
26
- # @return [Hash]
15
+ # @abstract
27
16
  #
28
- def user_browser
29
- User.new(*@args).()
30
- end
31
-
32
- #
33
- # @return [Hash]
34
- #
35
- def company
36
- Company.new(*@args).()
37
- end
38
-
39
- #
40
- # Company attributes for browser (expects 'id', not 'company_id').
41
- #
42
- # @return [Hash]
43
- #
44
- def company_browser
45
- company2 = company
46
- company2[:id] = company2.delete(:company_id)
47
- company2
48
- end
49
-
17
+ # @param convert [#call]
50
18
  #
51
19
  # @return [Hash]
52
20
  #
53
- def custom
54
- Custom.new(*@args).()
21
+ def to_h(convert: Convert.new)
22
+ convert.({})
55
23
  end
56
24
  end
57
25
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lucid_intercom/event'
4
+
5
+ module LucidIntercom
6
+ class ChangedPlanEvent < Event
7
+ # @return [String, nil] e.g. 'free', or nil to unset
8
+ param :new_plan
9
+
10
+ event :changed_plan
11
+
12
+ #
13
+ # @return [Hash]
14
+ #
15
+ def event_metadata
16
+ {
17
+ company_id: company.to_h[:company_id],
18
+ new_plan: new_plan,
19
+ }
20
+ end
21
+
22
+ #
23
+ # @return [Hash]
24
+ #
25
+ def app_data
26
+ {
27
+ plan: new_plan,
28
+ }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lucid_intercom/attributes'
4
+
5
+ module LucidIntercom
6
+ class CompanyAttributes < Attributes
7
+ #
8
+ # @param browser [Boolean] format for browser snippet
9
+ # @param convert [#call]
10
+ #
11
+ # @return [Hash]
12
+ #
13
+ def to_h(browser: false, convert: Convert.new)
14
+ convert.({}.tap do |h|
15
+ h[browser ? :id : :company_id] = shopify_data['myshopify_domain']
16
+ h[:name] = shopify_data['name']
17
+ h[:plan] = shopify_data['plan_name']
18
+ end)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lucid_intercom/attributes'
4
+ require 'lucid_intercom/config'
5
+
6
+ module LucidIntercom
7
+ class CompanyCustomAttributes < Attributes
8
+ # @return [Hash] app attributes (unprefixed)
9
+ param :app_data, reader: :private
10
+
11
+ #
12
+ # @param convert [#call]
13
+ #
14
+ # @return [Hash]
15
+ #
16
+ def to_h(convert: Convert.new)
17
+ convert.(shopify.merge(app))
18
+ end
19
+
20
+ #
21
+ # These attributes are prefixed with 'merchant_' to distinguish them from
22
+ # the Shopify intergration's 'shopify_' prefix.
23
+ #
24
+ # @return [Hash]
25
+ #
26
+ private def shopify
27
+ {
28
+ merchant_domain: shopify_data['domain'],
29
+ merchant_myshopify_domain: shopify_data['myshopify_domain'],
30
+ merchant_shop_owner: shopify_data['shop_owner'],
31
+ merchant_timezone: shopify_data['timezone'],
32
+ }
33
+ end
34
+
35
+ #
36
+ # Any app-specific attributes.
37
+ #
38
+ # @return [Hash]
39
+ #
40
+ private def app
41
+ prefix = LucidIntercom.app_prefix
42
+
43
+ app_data.each_with_object({}) do |(k, v), h|
44
+ h["#{prefix}_#{k}"] = v
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-initializer'
4
+ require 'forwardable'
5
+
6
+ require 'lucid_intercom/error'
7
+
8
+ module LucidIntercom
9
+ NotConfiguredError = Class.new(Error)
10
+
11
+ class << self
12
+ extend Forwardable
13
+
14
+ # TODO: *Config.dry_initializer.attributes (version 2.0.0+)
15
+ def_delegators :config, :access_token, :secret, :app_id, :app_prefix
16
+
17
+ # @param config [Config]
18
+ attr_writer :config
19
+
20
+ #
21
+ # @return [Config]
22
+ #
23
+ # @raise [NotConfiguredError] if config is unset
24
+ #
25
+ def config
26
+ raise LucidIntercom::NotConfiguredError unless @config
27
+
28
+ @config
29
+ end
30
+ end
31
+
32
+ class Config
33
+ extend Dry::Initializer
34
+
35
+ # @return [String]
36
+ param :access_token
37
+ # @return [String]
38
+ param :secret
39
+ # @return [String]
40
+ param :app_id
41
+ # @return [String] the snakecased app name, e.g. 'smart_order_tags'
42
+ param :app_prefix
43
+ end
44
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LucidIntercom
4
+ class Convert
5
+ #
6
+ # @param attributes [Hash]
7
+ #
8
+ # @return [Hash]
9
+ #
10
+ def call(attributes)
11
+ attributes.each_with_object({}) do |(k, obj), h|
12
+ h[k] = convert(obj)
13
+ end
14
+ end
15
+
16
+ #
17
+ # @param obj [Object]
18
+ #
19
+ # @return [Object] a valid Intercom type
20
+ #
21
+ private def convert(obj)
22
+ case obj
23
+ when Numeric, nil # nil to unset
24
+ obj
25
+ when Time
26
+ obj.to_i
27
+ else
28
+ obj.to_s
29
+ end
30
+ end
31
+ end
32
+ end
File without changes
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lucid_intercom/company_attributes'
4
+ require 'lucid_intercom/company_custom_attributes'
5
+ require 'lucid_intercom/config'
6
+ require 'lucid_intercom/user_attributes'
7
+
8
+ module LucidIntercom
9
+ class Event
10
+ extend Dry::Initializer
11
+
12
+ # @return [Hash] shop attributes as returned by the Shopify API
13
+ param :shopify_data
14
+ # @return [CompanyAttributes]
15
+ option :company, default: proc { CompanyAttributes.new(shopify_data) }
16
+ # @return [CompanyCustomAttributes]
17
+ option :company_custom, default: proc { CompanyCustomAttributes.new(shopify_data, app_data) }
18
+ # @return [UserAttributes]
19
+ option :user, default: proc { UserAttributes.new(shopify_data) }
20
+
21
+ #
22
+ # Set the event name for the subclass.
23
+ #
24
+ # @param event_name [String, #to_s]
25
+ #
26
+ # @example
27
+ # event :changed_plan
28
+ #
29
+ def self.event(event_name)
30
+ define_method(:event_name) do
31
+ "#{LucidIntercom.app_prefix}_#{event_name}"
32
+ end
33
+ end
34
+
35
+ #
36
+ # @abstract
37
+ #
38
+ # @return [String]
39
+ #
40
+ def event_name
41
+ raise NotImplementedError
42
+ end
43
+
44
+ #
45
+ # @abstract
46
+ #
47
+ # @return [Hash]
48
+ #
49
+ def event_metadata
50
+ raise NotImplementedError
51
+ end
52
+
53
+ #
54
+ # Additional custom attributes related to the event (unprefixed).
55
+ #
56
+ # @example
57
+ # {plan: 'free'}
58
+ #
59
+ # @example
60
+ # {plan: nil}
61
+ #
62
+ # @return [Hash]
63
+ #
64
+ def app_data
65
+ {}
66
+ end
67
+
68
+ #
69
+ # @return [Hash]
70
+ #
71
+ def user_id
72
+ {
73
+ user.id_key => user.id,
74
+ }
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lucid_intercom/event'
4
+
5
+ module LucidIntercom
6
+ class InstalledEvent < Event
7
+ # @return [String] e.g. 'free'
8
+ param :new_plan
9
+
10
+ event :installed
11
+
12
+ #
13
+ # @return [Hash]
14
+ #
15
+ def event_metadata
16
+ {
17
+ company_id: company.to_h[:company_id],
18
+ new_plan: new_plan,
19
+ }
20
+ end
21
+
22
+ #
23
+ # @return [Hash]
24
+ #
25
+ def app_data
26
+ {
27
+ plan: new_plan,
28
+ }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'http'
4
+
5
+ require 'lucid_intercom/config'
6
+ require 'lucid_intercom/response'
7
+
8
+ module LucidIntercom
9
+ class PostRequest
10
+ #
11
+ # @param path [String] path relative to the domain
12
+ # @param data [Hash]
13
+ #
14
+ # @return [Response]
15
+ #
16
+ def call(path, data)
17
+ res = HTTP.headers(
18
+ 'Authorization' => "Bearer #{LucidIntercom.access_token}",
19
+ 'Accept' => 'application/json',
20
+ 'Content-Type' => 'application/json'
21
+ ).post("https://api.intercom.io/#{path}", json: data)
22
+
23
+ Response.new(res.code)
24
+ end
25
+ end
26
+ end
@@ -1,46 +1,50 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'erb'
4
- require 'lucid_intercom/attributes'
5
- require 'lucid_intercom/credentials'
4
+
5
+ require 'lucid_intercom/config'
6
6
 
7
7
  module LucidIntercom
8
8
  class RenderSnippet
9
9
  TEMPLATE = ERB.new(File.read("#{__dir__}/snippet.html.erb")).freeze
10
10
 
11
11
  #
12
- # Leave arguments unset for unauthenticated visitors.
13
- #
14
- # @param credentials [LucidIntercom::Credentials]
12
+ # @param shopify_data [Hash] shop attributes as returned by the Shopify API
13
+ # @param app_data [Hash] app attributes (unprefixed)
15
14
  #
16
- # @see LucidIntercom::Attributes#initialize
15
+ # @example Unauthenticated visitor
16
+ # render_snippet.()
17
17
  #
18
- def initialize(shop_attributes = {}, app_attributes = {}, credentials = LucidIntercom.credentials)
19
- @credentials = credentials
20
- @attributes = Attributes.new(shop_attributes, app_attributes, credentials) if shop_attributes.empty?
21
- end
22
-
23
- # @return [LucidIntercom::Attributes]
24
- attr_reader :attributes
25
- # @return [LucidIntercom::Credentials]
26
- attr_reader :credentials
27
-
18
+ # @example
19
+ # render_snippet.(shopify_data, app_data)
28
20
  #
29
- # @return [String] the rendered HTML
21
+ # @return [String]
30
22
  #
31
- def call
23
+ def call(shopify_data = {}, app_data = {})
24
+ company = CompanyAttributes.new(shopify_data).to_h(browser: true)
25
+ company_custom = CompanyCustomAttributes.new(shopify_data, app_data).to_h
26
+ user = UserAttributes.new(shopify_data).to_h(browser: true)
27
+
32
28
  TEMPLATE.result(binding)
33
29
  end
34
30
 
35
31
  #
36
- # Quote and escape a value for the window.intercomSettings object.
32
+ # Quote and escape a value for JavaScript.
37
33
  #
38
- private def h(v)
39
- v.is_a?(String) ? ?" + v.gsub(/./) { |c| escape_char(c) } + ?" : v
40
- end
34
+ # @param obj [Object]
35
+ #
36
+ # @return [Object]
37
+ #
38
+ def escape(obj)
39
+ return obj unless obj.is_a?(String)
40
+
41
+ s = obj.gsub(/./) do |c|
42
+ return c unless %w(" ' / < > \\).include?(c)
43
+
44
+ "\\#{c}"
45
+ end
41
46
 
42
- private def escape_char(c)
43
- %w(" ' / < > \\).include?(c) ? '\%s' % c : c
47
+ "\"#{s}\""
44
48
  end
45
49
  end
46
50
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-initializer'
4
+
5
+ require 'lucid_intercom/error'
6
+
7
+ module LucidIntercom
8
+ class Response
9
+ #
10
+ # @abstract
11
+ #
12
+ class Error < LucidIntercom::Error
13
+ extend Dry::Initializer
14
+
15
+ # @return [Integer]
16
+ param :status_code
17
+
18
+ #
19
+ # @return [String]
20
+ #
21
+ def message
22
+ "bad response (#{status_code})"
23
+ end
24
+ end
25
+
26
+ ClientError = Class.new(Error)
27
+ ServerError = Class.new(Error)
28
+
29
+ extend Dry::Initializer
30
+
31
+ # @return [Integer]
32
+ param :status_code
33
+
34
+ #
35
+ # @return [Boolean]
36
+ #
37
+ # @raise [ClientError] for status 4xx
38
+ # @raise [ServerError] for status 5xx
39
+ #
40
+ def assert!
41
+ case status_code
42
+ when 400..499
43
+ raise ClientError.new(status_code)
44
+ when 500..599
45
+ raise ServerError.new(status_code)
46
+ end
47
+
48
+ true
49
+ end
50
+ end
51
+ end
@@ -1,80 +1,42 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'json'
4
- require 'net/http'
5
- require 'uri'
6
- require 'lucid_intercom/attributes'
7
- require 'lucid_intercom/credentials'
8
- require 'lucid_intercom/errors'
3
+ require 'dry-initializer'
4
+
5
+ require 'lucid_intercom/post_request'
9
6
 
10
7
  module LucidIntercom
11
8
  class SendEvent
12
- #
13
- # @param shop_attributes [Hash] shop attributes in format returned by the Shopify API
14
- # @param credentials [LucidIntercom::Credentials]
15
- #
16
- def initialize(shop_attributes, credentials = LucidIntercom.credentials)
17
- @attributes = Attributes.new(shop_attributes, {}, credentials)
18
- @credentials = credentials
19
- end
20
-
21
- # @return [LucidIntercom::Attributes]
22
- attr_reader :attributes
23
- # @return [LucidIntercom::Credentials]
24
- attr_reader :credentials
25
-
26
- #
27
- # Send event for user identified by attributes.
28
- #
29
- # @param event_name [String]
30
- # @param event_metadata [Hash]
31
- #
32
- # @raise [LucidIntercom::RequestError] if the response status >= 400
33
- #
34
- def call(event_name, event_metadata)
35
- res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
36
- http.request(req, data(event_name, event_metadata))
37
- end
9
+ extend Dry::Initializer
38
10
 
39
- status = res.code.to_i
40
-
41
- if status >= 400 # rubocop:disable Style/GuardClause
42
- raise LucidIntercom::RequestError.new(status), 'invalid response code %s' % status
43
- end
44
- end
11
+ # @return [PostRequest]
12
+ option :post_request, default: proc { PostRequest.new }
13
+ # @return [UpdateUser]
14
+ option :update_user, default: proc { UpdateUser.new }
45
15
 
46
16
  #
47
- # @return [URI::HTTPS]
17
+ # @param event [Events::Event]
48
18
  #
49
- private def uri
50
- URI('https://api.intercom.io/events')
51
- end
52
-
19
+ # @raise [Response::ClientError] for status 4xx
20
+ # @raise [Response::ServerError] for status 5xx
53
21
  #
54
- # @return [Net::HTTP::Post]
55
- #
56
- private def req
57
- req = Net::HTTP::Post.new(uri)
58
- req['Authorization'] = "Bearer #{credentials.access_token}"
59
- req['Content-Type'] = 'application/json'
22
+ def call(event)
23
+ post_request.('events', data(event)).assert!
60
24
 
61
- req
25
+ update_user.(event)
62
26
  end
63
27
 
64
28
  #
65
- # @param event_name [String]
66
- # @param event_metadata [Hash]
29
+ # @param event [Events::Event]
67
30
  #
68
31
  # @return [Hash]
69
32
  #
70
- private def data(event_name, event_metadata)
71
- event = {}
72
- event[:email] = attributes.user[:email]
73
- event[:event_name] = event_name
74
- event[:created_at] = Time.now.utc.to_i
75
- event[:metadata] = event_metadata
76
-
77
- event.to_json
33
+ private def data(event)
34
+ {
35
+ **event.user_id,
36
+ event_name: event.event_name,
37
+ created_at: Time.now.utc.to_i,
38
+ metadata: event.event_metadata,
39
+ }
78
40
  end
79
41
  end
80
42
  end