kameleoon-client-ruby 2.1.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/kameleoon/client.rb +79 -133
  3. data/lib/kameleoon/configuration/rule.rb +1 -1
  4. data/lib/kameleoon/data/browser.rb +33 -0
  5. data/lib/kameleoon/data/conversion.rb +26 -0
  6. data/lib/kameleoon/data/custom_data.rb +53 -0
  7. data/lib/kameleoon/data/data.rb +35 -0
  8. data/lib/kameleoon/data/device.rb +26 -0
  9. data/lib/kameleoon/data/page_view.rb +31 -0
  10. data/lib/kameleoon/data/user_agent.rb +14 -0
  11. data/lib/kameleoon/network/activity_event.rb +31 -0
  12. data/lib/kameleoon/network/experiment_event.rb +35 -0
  13. data/lib/kameleoon/network/uri_helper.rb +36 -0
  14. data/lib/kameleoon/network/url_provider.rb +71 -0
  15. data/lib/kameleoon/request.rb +5 -19
  16. data/lib/kameleoon/targeting/condition.rb +40 -11
  17. data/lib/kameleoon/targeting/condition_factory.rb +35 -12
  18. data/lib/kameleoon/targeting/conditions/browser_condition.rb +71 -0
  19. data/lib/kameleoon/targeting/conditions/conversion_condition.rb +21 -0
  20. data/lib/kameleoon/targeting/conditions/custom_datum.rb +60 -65
  21. data/lib/kameleoon/targeting/conditions/device_condition.rb +21 -0
  22. data/lib/kameleoon/targeting/conditions/exclusive_experiment.rb +0 -12
  23. data/lib/kameleoon/targeting/conditions/page_title_condition.rb +21 -0
  24. data/lib/kameleoon/targeting/conditions/page_url_condition.rb +21 -0
  25. data/lib/kameleoon/targeting/conditions/sdk_language_condition.rb +65 -0
  26. data/lib/kameleoon/targeting/conditions/string_value_condition.rb +40 -0
  27. data/lib/kameleoon/targeting/conditions/target_experiment.rb +4 -8
  28. data/lib/kameleoon/targeting/conditions/unknown_condition.rb +15 -0
  29. data/lib/kameleoon/targeting/conditions/visitor_code_condition.rb +16 -0
  30. data/lib/kameleoon/targeting/models.rb +0 -24
  31. data/lib/kameleoon/utils.rb +1 -1
  32. data/lib/kameleoon/version.rb +28 -1
  33. metadata +22 -3
  34. data/lib/kameleoon/data.rb +0 -175
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kameleoon/data/data'
4
+ require 'kameleoon/version'
5
+
6
+ module Kameleoon
7
+ # @api private
8
+ module Targeting
9
+ # Helper class for containing sdk information
10
+ class SdkInfo
11
+ attr_reader :language, :version
12
+
13
+ def initialize(language, version)
14
+ @language = language
15
+ @version = version
16
+ end
17
+ end
18
+
19
+ # SdkLanguageCondition is a condition for checking targeting sdk type and version
20
+ class SdkLanguageCondition < Condition
21
+ def initialize(json_condition)
22
+ super(json_condition)
23
+ @sdk_language = json_condition['sdkLanguage']
24
+ @version = json_condition['version']
25
+ @operator = json_condition['versionMatchType']
26
+ end
27
+
28
+ def check(data)
29
+ data.is_a?(SdkInfo) && check_targeting(data)
30
+ end
31
+
32
+ private
33
+
34
+ def check_targeting(sdk_info)
35
+ return false if @sdk_language != sdk_info.language
36
+
37
+ return true if @version.nil?
38
+
39
+ version_components_condition = SdkVersion.get_version_components(@version)
40
+ version_components_sdk_info = SdkVersion.get_version_components(sdk_info.version)
41
+
42
+ return false if version_components_condition.nil? || version_components_sdk_info.nil?
43
+
44
+ major_condition, minor_condition, patch_condition = version_components_condition
45
+ major_sdk, minor_sdk, patch_sdk = version_components_sdk_info
46
+
47
+ case @operator
48
+ when Operator::EQUAL
49
+ major_sdk == major_condition && minor_sdk == minor_condition && patch_sdk == patch_condition
50
+ when Operator::GREATER
51
+ major_sdk > major_condition ||
52
+ (major_sdk == major_condition && minor_sdk > minor_condition) ||
53
+ (major_sdk == major_condition && minor_sdk == minor_condition && patch_sdk > patch_condition)
54
+ when Operator::LOWER
55
+ major_sdk < major_condition ||
56
+ (major_sdk == major_condition && minor_sdk < minor_condition) ||
57
+ (major_sdk == major_condition && minor_sdk == minor_condition && patch_sdk < patch_condition)
58
+ else
59
+ puts "Unexpected comparing operation for SdkLanguage condition: #{@operator}"
60
+ false
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kameleoon/targeting/condition'
4
+
5
+ module Kameleoon
6
+ # @api private
7
+ module Targeting
8
+ # StringValueCondition is a base class for all conditions where string comparison happens
9
+ class StringValueCondition < Condition
10
+ def initialize(json_condition, value)
11
+ super(json_condition)
12
+ @condition_value = value
13
+ @operator = json_condition['matchType']
14
+ end
15
+
16
+ def check(data)
17
+ data.is_a?(String) && check_targeting(data)
18
+ end
19
+
20
+ protected
21
+
22
+ def check_targeting(value)
23
+ return false if value.nil?
24
+
25
+ case @operator
26
+ when Operator::EXACT
27
+ value == @condition_value
28
+ when Operator::CONTAINS
29
+ value.include?(@condition_value)
30
+ when Operator::REGULAR_EXPRESSION
31
+ pattern = Regexp.new(@condition_value)
32
+ pattern.match?(value)
33
+ else
34
+ puts "Unexpected comparing operation for #{@type} condition: #{@operator}"
35
+ false
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -13,16 +13,12 @@ module Kameleoon
13
13
  def initialize(json_condition)
14
14
  super(json_condition)
15
15
 
16
- if json_condition['experiment'].nil?
17
- raise Exception::NotFound.new('experiment'), 'experiment missed'
18
- end
19
-
20
- @experiment = json_condition['experiment']
21
-
16
+ raise Exception::NotFound.new('experiment'), 'experiment missed' if json_condition['experiment'].nil?
22
17
  if json_condition['variationMatchType'].nil?
23
18
  raise Exception::NotFound.new('variationMatchType'), 'variationMatchType missed'
24
19
  end
25
20
 
21
+ @experiment = json_condition['experiment']
26
22
  @operator = json_condition['variationMatchType']
27
23
  @variation = json_condition['variation']
28
24
  end
@@ -32,9 +28,9 @@ module Kameleoon
32
28
  variation_storage_exist = !variation_storage.nil? && !variation_storage.empty?
33
29
  saved_variation = variation_storage[@experiment] unless variation_storage.nil?
34
30
  case @operator
35
- when Operator::EXACT.to_s
31
+ when Operator::EXACT
36
32
  is_targeted = variation_storage_exist && saved_variation == @variation
37
- when Operator::ANY.to_s
33
+ when Operator::ANY
38
34
  is_targeted = variation_storage_exist
39
35
  end
40
36
  is_targeted
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kameleoon/targeting/condition'
4
+
5
+ module Kameleoon
6
+ # @api private
7
+ module Targeting
8
+ # UnknownCondition represents not defined condition, always returns that visitor is targeted (true)
9
+ class UnknownCondition < Condition
10
+ def check(_data)
11
+ true
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kameleoon/data/data'
4
+ require_relative 'string_value_condition'
5
+
6
+ module Kameleoon
7
+ # @api private
8
+ module Targeting
9
+ # VisitorCodeCondition is a condition for checking of targeting by visitor code
10
+ class VisitorCodeCondition < StringValueCondition
11
+ def initialize(json_condition)
12
+ super(json_condition, json_condition['visitorCode'])
13
+ end
14
+ end
15
+ end
16
+ end
@@ -133,29 +133,5 @@ module Kameleoon
133
133
  Marshal.load(Marshal.dump(is_targeted)) # Deep copy
134
134
  end
135
135
  end
136
-
137
- module DataType
138
- CUSTOM = 'CUSTOM'
139
- end
140
-
141
- module ConditionType
142
- CUSTOM_DATUM = 'CUSTOM_DATUM'
143
- TARGET_EXPERIMENT = 'TARGET_EXPERIMENT'
144
- EXCLUSIVE_EXPERIMENT = 'EXCLUSIVE_EXPERIMENT'
145
- end
146
-
147
- module Operator
148
- UNDEFINED = 'UNDEFINED'
149
- CONTAINS = 'CONTAINS'
150
- EXACT = 'EXACT'
151
- MATCH = 'REGULAR_EXPRESSION'
152
- LOWER = 'LOWER'
153
- EQUAL = 'EQUAL'
154
- GREATER = 'GREATER'
155
- IS_TRUE = 'TRUE'
156
- IS_FALSE = 'FALSE'
157
- AMONG_VALUES = 'AMONG_VALUES'
158
- ANY = 'ANY'
159
- end
160
136
  end
161
137
  end
@@ -3,7 +3,7 @@
3
3
  module Kameleoon
4
4
  # Utils is a helper module for project
5
5
  module Utils
6
- ALPHA_NUMERIC_CHARS = 'abcdef0123456789'
6
+ ALPHA_NUMERIC_CHARS = 'ABCDEF0123456789'
7
7
 
8
8
  def self.in_seconds(days)
9
9
  days * 60 * 60 * 24
@@ -1,5 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kameleoon
4
- VERSION = '2.1.0'
4
+ SDK_NAME = 'RUBY'
5
+ SDK_VERSION = '2.1.1'
6
+
7
+ # SdkManager is a helper method for fetching / obtaining version of SDK from string
8
+ class SdkVersion
9
+ def self.get_version_components(version_string)
10
+ versions = [0, 0, 0]
11
+
12
+ version_parts = version_string.split('.')
13
+ version_parts.each_with_index do |part, i|
14
+ versions[i] = Integer(part)
15
+ rescue ArgumentError
16
+ puts "Invalid version component, index: #{i}, value: #{part}"
17
+ return nil
18
+ end
19
+ versions
20
+ end
21
+
22
+ def self.get_float_version(version_string)
23
+ version_components = get_version_components(version_string)
24
+
25
+ return Float::NAN if version_components.nil?
26
+
27
+ major = version_components[0]
28
+ minor = version_components[1]
29
+ "#{major}.#{minor}".to_f
30
+ end
31
+ end
5
32
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kameleoon-client-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kameleoon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-20 00:00:00.000000000 Z
11
+ date: 2023-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: em-http-request
@@ -84,10 +84,20 @@ files:
84
84
  - lib/kameleoon/configuration/variation.rb
85
85
  - lib/kameleoon/configuration/variation_exposition.rb
86
86
  - lib/kameleoon/cookie.rb
87
- - lib/kameleoon/data.rb
87
+ - lib/kameleoon/data/browser.rb
88
+ - lib/kameleoon/data/conversion.rb
89
+ - lib/kameleoon/data/custom_data.rb
90
+ - lib/kameleoon/data/data.rb
91
+ - lib/kameleoon/data/device.rb
92
+ - lib/kameleoon/data/page_view.rb
93
+ - lib/kameleoon/data/user_agent.rb
88
94
  - lib/kameleoon/exceptions.rb
89
95
  - lib/kameleoon/factory.rb
90
96
  - lib/kameleoon/hybrid/manager.rb
97
+ - lib/kameleoon/network/activity_event.rb
98
+ - lib/kameleoon/network/experiment_event.rb
99
+ - lib/kameleoon/network/uri_helper.rb
100
+ - lib/kameleoon/network/url_provider.rb
91
101
  - lib/kameleoon/real_time/real_time_configuration_service.rb
92
102
  - lib/kameleoon/real_time/real_time_event.rb
93
103
  - lib/kameleoon/real_time/sse_client.rb
@@ -100,9 +110,18 @@ files:
100
110
  - lib/kameleoon/storage/visitor_variation.rb
101
111
  - lib/kameleoon/targeting/condition.rb
102
112
  - lib/kameleoon/targeting/condition_factory.rb
113
+ - lib/kameleoon/targeting/conditions/browser_condition.rb
114
+ - lib/kameleoon/targeting/conditions/conversion_condition.rb
103
115
  - lib/kameleoon/targeting/conditions/custom_datum.rb
116
+ - lib/kameleoon/targeting/conditions/device_condition.rb
104
117
  - lib/kameleoon/targeting/conditions/exclusive_experiment.rb
118
+ - lib/kameleoon/targeting/conditions/page_title_condition.rb
119
+ - lib/kameleoon/targeting/conditions/page_url_condition.rb
120
+ - lib/kameleoon/targeting/conditions/sdk_language_condition.rb
121
+ - lib/kameleoon/targeting/conditions/string_value_condition.rb
105
122
  - lib/kameleoon/targeting/conditions/target_experiment.rb
123
+ - lib/kameleoon/targeting/conditions/unknown_condition.rb
124
+ - lib/kameleoon/targeting/conditions/visitor_code_condition.rb
106
125
  - lib/kameleoon/targeting/models.rb
107
126
  - lib/kameleoon/targeting/tree_builder.rb
108
127
  - lib/kameleoon/utils.rb
@@ -1,175 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'kameleoon/exceptions'
4
-
5
- module Kameleoon
6
- NONCE_LENGTH = 16
7
-
8
- module DataType
9
- CUSTOM = 'CUSTOM'
10
- BROWSER = 'BROWSER'
11
- CONVERSION = 'CONVERSION'
12
- DEVICE = 'DEVICE'
13
- PAGE_VIEW = 'PAGE_VIEW'
14
- end
15
-
16
- module BrowserType
17
- CHROME = 0
18
- INTERNET_EXPLORER = 1
19
- FIREFOX = 2
20
- SAFARI = 3
21
- OPERA = 4
22
- OTHER = 5
23
- end
24
-
25
- module DeviceType
26
- PHONE = 'PHONE'
27
- TABLET = 'TABLET'
28
- DESKTOP = 'DESKTOP'
29
- end
30
-
31
- class Data
32
- attr_accessor :instance, :sent
33
-
34
- def initialize(*args)
35
- raise KameleoonError.new("Cannot initialise interface.")
36
- end
37
-
38
- def obtain_full_post_text_line
39
- raise KameleoonError.new("ToDo: implement this method.")
40
- end
41
-
42
- def encode(url)
43
- encoded_url = CGI.escape(url)
44
- encoded_url.gsub! "%27", "'"
45
- encoded_url.gsub! "%21", "!"
46
- encoded_url.gsub! "+", "%20"
47
- encoded_url.gsub! "%2A", "*"
48
- encoded_url.gsub! "%28", "("
49
- encoded_url.gsub! "%29", ")"
50
- encoded_url
51
- end
52
- end
53
-
54
- class CustomData < Data
55
- attr_reader :id, :values
56
-
57
- # @param [Integer] id Id of the custom data
58
- # @param [String] value Value of the custom data
59
- #
60
- # @overload
61
- # @param [Hash] hash Json value encoded in a hash.
62
- def initialize(arg0, *args)
63
- @instance = DataType::CUSTOM
64
- @sent = false
65
- if arg0.is_a?(Hash)
66
- hash = arg0
67
- id = hash['id']
68
- raise Kameleoon::Exception::NotFound.new('id') if id.nil?
69
- @id = id.to_s
70
- value = hash['value']
71
- values = hash['values']
72
- raise Kameleoon::Exception::NotFound.new('values') if values.nil? && value.nil?
73
- if values.nil?
74
- @values = [value]
75
- else
76
- @values = values.dup
77
- @values.append(value) unless value.nil?
78
- end
79
- else
80
- @id = arg0.to_s
81
- @values = args
82
- end
83
- end
84
-
85
- def obtain_full_post_text_line
86
- return '' if @values.empty?
87
-
88
- str_values = "[[\"#{@values.join('",1],["')}\",1]]"
89
- nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
90
- "eventType=customData&index=#{@id}&valueToCount=#{encode(str_values)}&overwrite=true&nonce=#{nonce}"
91
- end
92
- end
93
-
94
- class Browser < Data
95
- attr_accessor :browser
96
-
97
- # @param [BrowserType] browser_type Browser type, can be: CHROME, INTERNET_EXPLORER, FIREFOX, SAFARI, OPERA, OTHER
98
- def initialize(browser_type)
99
- @instance = DataType::BROWSER
100
- @sent = false
101
- @browser = browser_type
102
- end
103
-
104
- def obtain_full_post_text_line
105
- nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
106
- "eventType=staticData&browserIndex=" + @browser.to_s + "&nonce=" + nonce
107
- end
108
- end
109
-
110
- class PageView < Data
111
- attr_accessor :url, :title, :referrer
112
-
113
- # @param [String] url Url of the page
114
- # @param [String] title Title of the page
115
- # @param [Array] referrers Optional field - Referrer ids
116
- def initialize(url, title, referrers = nil)
117
- @instance = DataType::PAGE_VIEW
118
- @sent = false
119
- @url = url
120
- @title = title
121
- @referrers = referrers
122
- end
123
-
124
- def obtain_full_post_text_line
125
- nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
126
- referrer_text = ''
127
- unless @referrers.nil?
128
- referrer_text = "&referrersIndices=" + @referrers.to_s
129
- end
130
- "eventType=page&href=" + encode(@url) + "&title=" + @title + referrer_text + "&nonce=" + nonce
131
- end
132
- end
133
-
134
- class Conversion < Data
135
- attr_accessor :goal_id, :revenue, :negative
136
-
137
- # @param [Integer] goal_id Id of the goal associated to the conversion
138
- # @param [Float] revenue Optional field - Revenue associated to the conversion.
139
- # @param [Boolean] negative Optional field - If the revenue is negative. By default it's positive.
140
- def initialize(goal_id, revenue = 0.0, negative = false)
141
- @instance = DataType::CONVERSION
142
- @sent = false
143
- @goal_id = goal_id
144
- @revenue = revenue
145
- @negative = negative
146
- end
147
-
148
- def obtain_full_post_text_line
149
- nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
150
- "eventType=conversion&goalId=" + @goal_id.to_s + "&revenue=" + @revenue.to_s + "&negative=" + @negative.to_s + "&nonce=" + nonce
151
- end
152
- end
153
-
154
- # Device uses for sending deviceType parameter for tracking calls
155
- class Device < Data
156
- def initialize(device_type)
157
- @instance = DataType::DEVICE
158
- @sent = false
159
- @device_type = device_type
160
- end
161
-
162
- def obtain_full_post_text_line
163
- nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
164
- "eventType=staticData&deviceType=#{@device_type}&nonce=#{nonce}"
165
- end
166
- end
167
-
168
- # UserAgent uses for changing User-Agent header for tracking calls
169
- class UserAgent
170
- attr_accessor :value
171
- def initialize(value)
172
- @value = value
173
- end
174
- end
175
- end