octocore 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +117 -0
- data/README.md +50 -0
- data/Rakefile +138 -0
- data/bin/fakestream +258 -0
- data/lib/octocore.rb +141 -0
- data/lib/octocore/baseline.rb +131 -0
- data/lib/octocore/callbacks.rb +78 -0
- data/lib/octocore/config.rb +37 -0
- data/lib/octocore/config/config.yml +1 -0
- data/lib/octocore/config/search/index/user.yml +42 -0
- data/lib/octocore/counter.rb +265 -0
- data/lib/octocore/counter/helpers.rb +168 -0
- data/lib/octocore/helpers.rb +6 -0
- data/lib/octocore/helpers/api_consumer_helper.rb +371 -0
- data/lib/octocore/helpers/api_helper.rb +53 -0
- data/lib/octocore/helpers/api_logger.rb +14 -0
- data/lib/octocore/helpers/client_helper.rb +104 -0
- data/lib/octocore/helpers/kong_helper.rb +156 -0
- data/lib/octocore/helpers/sinatra_helper.rb +22 -0
- data/lib/octocore/kafka_bridge.rb +60 -0
- data/lib/octocore/kldivergence.rb +14 -0
- data/lib/octocore/models.rb +260 -0
- data/lib/octocore/models/contactus.rb +17 -0
- data/lib/octocore/models/enterprise.rb +76 -0
- data/lib/octocore/models/enterprise/api_event.rb +14 -0
- data/lib/octocore/models/enterprise/api_hit.rb +20 -0
- data/lib/octocore/models/enterprise/api_track.rb +13 -0
- data/lib/octocore/models/enterprise/app_init.rb +13 -0
- data/lib/octocore/models/enterprise/app_login.rb +12 -0
- data/lib/octocore/models/enterprise/app_logout.rb +12 -0
- data/lib/octocore/models/enterprise/authorization.rb +61 -0
- data/lib/octocore/models/enterprise/category.rb +14 -0
- data/lib/octocore/models/enterprise/category_baseline.rb +19 -0
- data/lib/octocore/models/enterprise/category_hit.rb +26 -0
- data/lib/octocore/models/enterprise/category_trend.rb +19 -0
- data/lib/octocore/models/enterprise/conversions.rb +69 -0
- data/lib/octocore/models/enterprise/ctr.rb +54 -0
- data/lib/octocore/models/enterprise/dimension_choice.rb +21 -0
- data/lib/octocore/models/enterprise/engagement_time.rb +43 -0
- data/lib/octocore/models/enterprise/funnel_data.rb +20 -0
- data/lib/octocore/models/enterprise/funnels.rb +126 -0
- data/lib/octocore/models/enterprise/gcm.rb +21 -0
- data/lib/octocore/models/enterprise/newsfeed_hit.rb +52 -0
- data/lib/octocore/models/enterprise/notification_hit.rb +42 -0
- data/lib/octocore/models/enterprise/page.rb +15 -0
- data/lib/octocore/models/enterprise/page_view.rb +14 -0
- data/lib/octocore/models/enterprise/pageload_time.rb +43 -0
- data/lib/octocore/models/enterprise/product.rb +22 -0
- data/lib/octocore/models/enterprise/product_baseline.rb +20 -0
- data/lib/octocore/models/enterprise/product_hit.rb +26 -0
- data/lib/octocore/models/enterprise/product_page_view.rb +13 -0
- data/lib/octocore/models/enterprise/product_trend.rb +18 -0
- data/lib/octocore/models/enterprise/push_key.rb +15 -0
- data/lib/octocore/models/enterprise/rules.rb +45 -0
- data/lib/octocore/models/enterprise/segment.rb +65 -0
- data/lib/octocore/models/enterprise/segment_data.rb +22 -0
- data/lib/octocore/models/enterprise/tag.rb +14 -0
- data/lib/octocore/models/enterprise/tag_baseline.rb +19 -0
- data/lib/octocore/models/enterprise/tag_hit.rb +26 -0
- data/lib/octocore/models/enterprise/tag_trend.rb +19 -0
- data/lib/octocore/models/enterprise/template.rb +18 -0
- data/lib/octocore/models/plans.rb +17 -0
- data/lib/octocore/models/subscribe.rb +12 -0
- data/lib/octocore/models/user.rb +22 -0
- data/lib/octocore/models/user/push_token.rb +15 -0
- data/lib/octocore/models/user/user_browser_details.rb +16 -0
- data/lib/octocore/models/user/user_location_history.rb +15 -0
- data/lib/octocore/models/user/user_persona.rb +101 -0
- data/lib/octocore/models/user/user_phone_details.rb +17 -0
- data/lib/octocore/models/user/user_profile.rb +20 -0
- data/lib/octocore/models/user/user_timeline.rb +111 -0
- data/lib/octocore/record.rb +20 -0
- data/lib/octocore/schedeuleable.rb +20 -0
- data/lib/octocore/scheduler.rb +59 -0
- data/lib/octocore/search.rb +5 -0
- data/lib/octocore/search/client.rb +33 -0
- data/lib/octocore/search/indexer.rb +0 -0
- data/lib/octocore/search/searchable.rb +18 -0
- data/lib/octocore/search/setup.rb +71 -0
- data/lib/octocore/segment.rb +285 -0
- data/lib/octocore/stats.rb +33 -0
- data/lib/octocore/trendable.rb +88 -0
- data/lib/octocore/trends.rb +158 -0
- data/lib/octocore/utils.rb +90 -0
- data/lib/octocore/version.rb +4 -0
- data/spec/lib/stats_spec.rb +20 -0
- data/spec/spec_helper.rb +103 -0
- metadata +436 -0
@@ -0,0 +1,168 @@
|
|
1
|
+
module Octo
|
2
|
+
module Counter
|
3
|
+
module Helper
|
4
|
+
|
5
|
+
|
6
|
+
#The prefix to use when converting a type constant into an
|
7
|
+
#aggregator method name
|
8
|
+
METHOD_PREFIX = 'aggregate'
|
9
|
+
|
10
|
+
|
11
|
+
# Defined the method names for the type counters.
|
12
|
+
def type_counters_method_names(type = nil)
|
13
|
+
if type.nil?
|
14
|
+
get_typecounters.map do |typ|
|
15
|
+
[METHOD_PREFIX, typ.to_s.downcase].join('_')
|
16
|
+
end
|
17
|
+
else
|
18
|
+
[METHOD_PREFIX, type.to_s.downcase].join('_')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Get all the type counters i.e. TYPE_MINUTE_30 etc from
|
23
|
+
# Counter class.
|
24
|
+
# @return [Array] Array of all the constants that define a counter type
|
25
|
+
def get_typecounters
|
26
|
+
max = max_type
|
27
|
+
Counter.constants.select do |x|
|
28
|
+
if x.to_s.start_with?('TYPE')
|
29
|
+
Counter.const_get(x) <= max
|
30
|
+
else
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Define the max granularity that should exist
|
37
|
+
def max_type(type = nil)
|
38
|
+
if @max_type
|
39
|
+
@max_type
|
40
|
+
else
|
41
|
+
if type
|
42
|
+
@max_type = type
|
43
|
+
else
|
44
|
+
@max_type = 9
|
45
|
+
end
|
46
|
+
end
|
47
|
+
@max_type
|
48
|
+
end
|
49
|
+
|
50
|
+
# Coverts the method name to the constant type
|
51
|
+
# @param [String] method_name The method name to convert into constant
|
52
|
+
# @return [Symbol] The constant
|
53
|
+
def method_names_type_counter(method_name)
|
54
|
+
prefix, *counterType = method_name.to_s.split('_')
|
55
|
+
if prefix == METHOD_PREFIX
|
56
|
+
cnst = counterType.join('_').upcase.to_sym
|
57
|
+
string_to_const_val(cnst)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Converts a string (which may represent a counter constant) into its
|
62
|
+
# corresponding constant
|
63
|
+
# @param [String] cnst The string which may represent a constant
|
64
|
+
# @return [Fixnum] The constant value; iff the string represent a constant.
|
65
|
+
# Nil otherwise
|
66
|
+
def string_to_const_val(cnst)
|
67
|
+
index = Counter.constants.index(cnst)
|
68
|
+
if index
|
69
|
+
Counter.const_get(cnst)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Generates a fromtype for a totype. This defines the relation
|
74
|
+
# of aggregation needed for the counters.
|
75
|
+
def get_fromtype_for_totype(totype)
|
76
|
+
case totype
|
77
|
+
when TYPE_MINUTE_30
|
78
|
+
TYPE_MINUTE
|
79
|
+
when TYPE_HOUR
|
80
|
+
TYPE_MINUTE_30
|
81
|
+
when TYPE_HOUR_3
|
82
|
+
TYPE_HOUR
|
83
|
+
when TYPE_HOUR_6
|
84
|
+
TYPE_HOUR_3
|
85
|
+
when TYPE_HOUR_12
|
86
|
+
TYPE_HOUR_6
|
87
|
+
when TYPE_DAY
|
88
|
+
TYPE_HOUR_6
|
89
|
+
when TYPE_DAY_3
|
90
|
+
TYPE_DAY
|
91
|
+
when TYPE_DAY_6
|
92
|
+
TYPE_DAY_3
|
93
|
+
when TYPE_WEEK
|
94
|
+
TYPE_DAY_3
|
95
|
+
else
|
96
|
+
TYPE_WEEK
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Gets the duration for a particular counter type. This helps in
|
101
|
+
# aggregation.
|
102
|
+
# @param [Fixnum] type The counter type
|
103
|
+
# @param [Time] ts The time at wich duration needs to be passed
|
104
|
+
# @return [Time] The time or time range for the given specs
|
105
|
+
def get_duration_for_counter_type(type, ts=Time.now.ceil)
|
106
|
+
start_time, step = case type
|
107
|
+
when TYPE_MINUTE
|
108
|
+
[2.minute.ago, 1.minute]
|
109
|
+
when TYPE_MINUTE_30
|
110
|
+
[30.minute.ago, 1.minute]
|
111
|
+
when TYPE_HOUR
|
112
|
+
[1.hour.ago, 30.minute]
|
113
|
+
when TYPE_HOUR_3
|
114
|
+
[3.hour.ago, 1.hour]
|
115
|
+
when TYPE_HOUR_6
|
116
|
+
[6.hour.ago, 3.hour]
|
117
|
+
when TYPE_HOUR_12
|
118
|
+
[12.hour.ago, 6.hour]
|
119
|
+
when TYPE_DAY
|
120
|
+
[1.day.ago, 6.hour]
|
121
|
+
when TYPE_DAY_3
|
122
|
+
[3.day.ago, 1.day]
|
123
|
+
when TYPE_DAY_6
|
124
|
+
[6.day.ago, 3.day]
|
125
|
+
when TYPE_WEEK
|
126
|
+
[1.week.ago, 1.week]
|
127
|
+
end
|
128
|
+
start_time.ceil.to(ts, step)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Returns the mapping for counters as text
|
132
|
+
# @return [Hash]
|
133
|
+
def self.counter_text
|
134
|
+
{
|
135
|
+
TYPE_MINUTE => 'Near Real Time',
|
136
|
+
TYPE_MINUTE_30 => '30 Minute',
|
137
|
+
TYPE_HOUR => 'Hourly',
|
138
|
+
TYPE_HOUR_3 => '3 Hourly',
|
139
|
+
TYPE_HOUR_6 => '6 Hourly',
|
140
|
+
TYPE_HOUR_12 => '12 Hourly',
|
141
|
+
TYPE_DAY => 'Daily',
|
142
|
+
TYPE_DAY_3 => '3 Days',
|
143
|
+
TYPE_DAY_6 => '6 Days',
|
144
|
+
TYPE_WEEK => 'Weekly'
|
145
|
+
}
|
146
|
+
end
|
147
|
+
|
148
|
+
# Generate aggregator methods for a class. You can pass
|
149
|
+
# your own block to generator for all custom needs.
|
150
|
+
# Check out the implementation at Octo::Counter#countables
|
151
|
+
# or Octo::Trends#trendable
|
152
|
+
# @param [Block] block The block to be evaluated while executing
|
153
|
+
# the method
|
154
|
+
def generate_aggregators(&block)
|
155
|
+
@stored_block = block
|
156
|
+
type_counters_method_names.each do |method_name|
|
157
|
+
singleton_class.module_eval(<<-RUBY, __FILE__, __LINE__+1)
|
158
|
+
def #{ method_name } (ts=Time.now.floor)
|
159
|
+
bl = self.instance_variable_get(:@stored_block)
|
160
|
+
instance_exec(ts, __method__, &bl) if bl
|
161
|
+
end
|
162
|
+
RUBY
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,371 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
module Octo
|
5
|
+
module Helpers
|
6
|
+
|
7
|
+
module ApiConsumerHelper
|
8
|
+
|
9
|
+
# Get all the valid events
|
10
|
+
# @return [Set<Symbol>] Valid events globally
|
11
|
+
def valid_events
|
12
|
+
Set.new(Octo.get_config(:allowed_events))
|
13
|
+
end
|
14
|
+
|
15
|
+
# Get the API events. These are the ones that the client is billed for
|
16
|
+
# This should eventually be placed under kong helpers when that is
|
17
|
+
# ready
|
18
|
+
# @return [Set<Symbol>] Set of api_events
|
19
|
+
def api_events
|
20
|
+
Set.new(%w(app.init app.login app.logout page.view productpage.view update.profile))
|
21
|
+
end
|
22
|
+
|
23
|
+
def handle(msg)
|
24
|
+
msg_dump = msg
|
25
|
+
msg = parse(msg)
|
26
|
+
|
27
|
+
eventName = msg.delete(:event_name)
|
28
|
+
|
29
|
+
if valid_events.include?eventName
|
30
|
+
enterprise = checkEnterprise(msg)
|
31
|
+
unless enterprise
|
32
|
+
Octo.logger.info 'Unable to find enterprise. Something\'s wrong'
|
33
|
+
end
|
34
|
+
user = checkUser(enterprise, msg)
|
35
|
+
|
36
|
+
hook_opts = {
|
37
|
+
enterprise: enterprise,
|
38
|
+
user: user
|
39
|
+
}
|
40
|
+
|
41
|
+
if api_events.include?eventName
|
42
|
+
hook_opts[:event] = register_api_event(enterprise, eventName)
|
43
|
+
end
|
44
|
+
|
45
|
+
Octo::ApiTrack.new(customid: msg[:id],
|
46
|
+
created_at: Time.now,
|
47
|
+
json_dump: msg_dump,
|
48
|
+
type: eventName).save!
|
49
|
+
|
50
|
+
case eventName
|
51
|
+
when 'app.init'
|
52
|
+
Octo::AppInit.new(enterprise: enterprise,
|
53
|
+
created_at: Time.now,
|
54
|
+
userid: user.id).save!
|
55
|
+
updateUserDeviceDetails(user, msg)
|
56
|
+
call_hooks(eventName, hook_opts)
|
57
|
+
when 'app.login'
|
58
|
+
Octo::AppLogin.new(enterprise: enterprise,
|
59
|
+
created_at: Time.now,
|
60
|
+
userid: user.id).save!
|
61
|
+
updateUserDeviceDetails(user, msg)
|
62
|
+
call_hooks(eventName, hook_opts)
|
63
|
+
when 'app.logout'
|
64
|
+
event = Octo::AppLogout.new(enterprise: enterprise,
|
65
|
+
created_at: Time.now,
|
66
|
+
userid: user.id).save!
|
67
|
+
updateUserDeviceDetails(user, msg)
|
68
|
+
call_hooks(eventName, hook_opts)
|
69
|
+
when 'page.view'
|
70
|
+
page, categories, tags = checkPage(enterprise, msg)
|
71
|
+
Octo::PageView.new(enterprise: enterprise,
|
72
|
+
created_at: Time.now,
|
73
|
+
userid: user.id,
|
74
|
+
routeurl: page.routeurl
|
75
|
+
).save!
|
76
|
+
updateUserDeviceDetails(user, msg)
|
77
|
+
call_hooks(eventName, hook_opts)
|
78
|
+
when 'productpage.view'
|
79
|
+
product, categories, tags = checkProduct(enterprise, msg)
|
80
|
+
Octo::ProductPageView.new(
|
81
|
+
enterprise: enterprise,
|
82
|
+
created_at: Time.now,
|
83
|
+
userid: user.id,
|
84
|
+
product_id: product.id
|
85
|
+
).save!
|
86
|
+
updateUserDeviceDetails(user, msg)
|
87
|
+
hook_opts.merge!({ product: product,
|
88
|
+
categories: categories,
|
89
|
+
tags: tags })
|
90
|
+
call_hooks(eventName, hook_opts)
|
91
|
+
when 'update.profile'
|
92
|
+
checkUserProfileDetails(enterprise, user, msg)
|
93
|
+
updateUserDeviceDetails(user, msg)
|
94
|
+
call_hooks(eventName, hook_opts)
|
95
|
+
when 'update.push_token'
|
96
|
+
checkPushToken(enterprise, user, msg)
|
97
|
+
checkPushKey(enterprise, msg)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def register_api_event(enterprise, event_name)
|
105
|
+
Octo::ApiEvent.findOrCreate({ enterprise_id: enterprise.id,
|
106
|
+
eventname: event_name})
|
107
|
+
end
|
108
|
+
|
109
|
+
def call_hooks(event, *args)
|
110
|
+
hook = [:after, event.gsub('.', '_')].join('_').to_sym
|
111
|
+
Octo::Callbacks.run_hook(hook, *args)
|
112
|
+
end
|
113
|
+
|
114
|
+
def checkUserProfileDetails(enterprise, user, msg)
|
115
|
+
args = {
|
116
|
+
user_id: user.id,
|
117
|
+
user_enterprise_id: enterprise.id,
|
118
|
+
email: msg[:profileDetails].fetch('email')
|
119
|
+
}
|
120
|
+
opts = {
|
121
|
+
username: msg[:profileDetails].fetch('username', ''),
|
122
|
+
gender: msg[:profileDetails].fetch('gender', ''),
|
123
|
+
dob: msg[:profileDetails].fetch('dob', ''),
|
124
|
+
alternate_email: msg[:profileDetails].fetch('alternate_email', ''),
|
125
|
+
mobile: msg[:profileDetails].fetch('mobile', ''),
|
126
|
+
extras: msg[:profileDetails].fetch('extras', '{}').to_s
|
127
|
+
}
|
128
|
+
Octo::UserProfileDetails.findOrCreateOrUpdate(args, opts)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Checks for push tokens and creates or updates it
|
132
|
+
# @param [Octo::Enterprise] enterprise The Enterprise object
|
133
|
+
# @param [Octo::User] user The user to whom this token belongs to
|
134
|
+
# @param [Hash] msg The message hash
|
135
|
+
# @return [Octo::PushToken] The push token object corresponding to this user
|
136
|
+
def checkPushToken(enterprise, user, msg)
|
137
|
+
args = {
|
138
|
+
user_id: user.id,
|
139
|
+
user_enterprise_id: enterprise.id,
|
140
|
+
push_type: msg[:pushType].to_i
|
141
|
+
}
|
142
|
+
opts = {
|
143
|
+
pushtoken: msg[:pushToken]
|
144
|
+
}
|
145
|
+
Octo::PushToken.findOrCreateOrUpdate(args, opts)
|
146
|
+
end
|
147
|
+
|
148
|
+
# Checks for push keys and creates or updates it
|
149
|
+
# @param [Octo::Enterprise] enterprise The Enterprise object
|
150
|
+
# @param [Hash] msg The message hash
|
151
|
+
# @return [Octo::PushKey] The push key object corresponding to this user
|
152
|
+
def checkPushKey(enterprise, msg)
|
153
|
+
args = {
|
154
|
+
enterprise_id: enterprise.id,
|
155
|
+
push_type: msg[:pushType].to_i
|
156
|
+
}
|
157
|
+
opts = {
|
158
|
+
key: msg[:pushKey]
|
159
|
+
}
|
160
|
+
Octo::PushKey.findOrCreateOrUpdate(args, opts)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Check if the enterprise exists. Create a new enterprise if it does
|
164
|
+
# not exist. This method makes sense because the enterprise authentication
|
165
|
+
# is handled by kong. Hence we can be sure that all these enterprises
|
166
|
+
# are valid.
|
167
|
+
# @param [Hash] msg The message hash
|
168
|
+
# @return [Octo::Enterprise] The enterprise object
|
169
|
+
def checkEnterprise(msg)
|
170
|
+
Octo::Enterprise.findOrCreate({id: msg[:enterpriseId]},
|
171
|
+
{name: msg[:enterpriseName]})
|
172
|
+
end
|
173
|
+
|
174
|
+
# Checks for user and creates if not exists
|
175
|
+
# @param [Octo::Enterprise] enterprise The Enterprise object
|
176
|
+
# @param [Hash] msg The message hash
|
177
|
+
# @return [Octo::User] The push user object corresponding to this user
|
178
|
+
def checkUser(enterprise, msg)
|
179
|
+
args = {
|
180
|
+
enterprise_id: enterprise.id,
|
181
|
+
id: msg[:userId]
|
182
|
+
}
|
183
|
+
Octo::User.findOrCreate(args)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Updates location for a user
|
187
|
+
# @param [Octo::User] user The user to whom this token belongs to
|
188
|
+
# @param [Hash] msg The message hash
|
189
|
+
# @return [Octo::UserLocationHistory] The location history object
|
190
|
+
# corresponding to this user
|
191
|
+
def updateLocationHistory(user, msg)
|
192
|
+
Octo::UserLocationHistory.new(
|
193
|
+
user: user,
|
194
|
+
latitude: msg[:phone].fetch('latitude', 0.0),
|
195
|
+
longitude: msg[:phone].fetch('longitude', 0.0),
|
196
|
+
created_at: Time.now
|
197
|
+
).save!
|
198
|
+
end
|
199
|
+
|
200
|
+
# Updates user's device details
|
201
|
+
# @param [Octo::User] user The user to whom this token belongs to
|
202
|
+
# @param [Hash] msg The message hash
|
203
|
+
def updateUserDeviceDetails(user, msg)
|
204
|
+
args = {user_id: user.id, user_enterprise_id: user.enterprise.id}
|
205
|
+
|
206
|
+
# Check Device Type
|
207
|
+
if msg[:browser]
|
208
|
+
updateUserBrowserDetails(args, msg)
|
209
|
+
elsif msg[:phone]
|
210
|
+
updateLocationHistory(user, msg)
|
211
|
+
updateUserPhoneDetails(args, msg)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# Updates user's phone details
|
216
|
+
# @param [Hash] args The user details to whom this token belongs to
|
217
|
+
# @param [Hash] msg The message hash
|
218
|
+
# @return [Octo::UserPhoneDetails] The phone details object
|
219
|
+
# corresponding to this user
|
220
|
+
def updateUserPhoneDetails(args, msg)
|
221
|
+
opts = {deviceid: msg[:phone].fetch('deviceId', ''),
|
222
|
+
manufacturer: msg[:phone].fetch('manufacturer', ''),
|
223
|
+
model: msg[:phone].fetch('model', ''),
|
224
|
+
os: msg[:phone].fetch('os', '')}
|
225
|
+
Octo::UserPhoneDetails.findOrCreateOrUpdate(args, opts)
|
226
|
+
end
|
227
|
+
|
228
|
+
# Updates user's browser details
|
229
|
+
# @param [Hash] args The user details to whom this token belongs to
|
230
|
+
# @param [Hash] msg The message hash
|
231
|
+
# @return [Octo::UserBrowserDetails] The browser details object
|
232
|
+
# corresponding to this user
|
233
|
+
def updateUserBrowserDetails(args, msg)
|
234
|
+
opts = {name: msg[:browser].fetch('name', ''),
|
235
|
+
platform: msg[:browser].fetch('platform', ''),
|
236
|
+
manufacturer: msg[:browser].fetch('manufacturer', ''),
|
237
|
+
cookieid: msg[:browser].fetch('cookieid', '')}
|
238
|
+
Octo::UserBrowserDetails.findOrCreateOrUpdate(args, opts)
|
239
|
+
end
|
240
|
+
|
241
|
+
# Checks the existence of a page and creates if not found
|
242
|
+
# @param [Octo::Enterprise] enterprise The Enterprise object
|
243
|
+
# @param [Hash] msg The message hash
|
244
|
+
# @return [Array<Octo::Page, Array<Octo::Category>, Array<Octo::Tag>] The
|
245
|
+
# page object, array of categories objects and the array of tags
|
246
|
+
# object
|
247
|
+
def checkPage(enterprise, msg)
|
248
|
+
cats = checkCategories(enterprise, msg[:categories])
|
249
|
+
tags = checkTags(enterprise, msg[:tags])
|
250
|
+
|
251
|
+
args = {
|
252
|
+
enterprise_id: enterprise.id,
|
253
|
+
routeurl: msg[:routeUrl]
|
254
|
+
}
|
255
|
+
opts = {
|
256
|
+
categories: Set.new(msg[:categories]),
|
257
|
+
tags: Set.new(msg[:tags])
|
258
|
+
}
|
259
|
+
page = Octo::Page.findOrCreateOrUpdate(args, opts)
|
260
|
+
[page, cats, tags]
|
261
|
+
end
|
262
|
+
|
263
|
+
# Checks for existence of a product and creates if not found
|
264
|
+
# @param [Octo::Enterprise] enterprise The Enterprise object
|
265
|
+
# @param [Hash] msg The message hash
|
266
|
+
# @return [Array<Octo::Product, Array<Octo::Category>, Array<Octo::Tag>] The
|
267
|
+
# product object, array of categories objects and the array of tags
|
268
|
+
# object
|
269
|
+
def checkProduct(enterprise, msg)
|
270
|
+
categories = checkCategories(enterprise, msg[:categories])
|
271
|
+
tags = checkTags(enterprise, msg[:tags])
|
272
|
+
|
273
|
+
args = {
|
274
|
+
enterprise_id: enterprise.id,
|
275
|
+
id: msg[:productId]
|
276
|
+
}
|
277
|
+
opts = {
|
278
|
+
categories: Set.new(msg[:categories]),
|
279
|
+
tags: Set.new(msg[:tags]),
|
280
|
+
price: msg[:price].to_f.round(2),
|
281
|
+
name: msg[:productName],
|
282
|
+
routeurl: msg[:routeUrl]
|
283
|
+
}
|
284
|
+
prod = Octo::Product.findOrCreateOrUpdate(args, opts)
|
285
|
+
[prod, categories, tags]
|
286
|
+
end
|
287
|
+
|
288
|
+
# Checks for categories and creates if not found
|
289
|
+
# @param [Octo::Enterprise] enterprise The enterprise object
|
290
|
+
# @param [Array<String>] categories An array of categories to be checked
|
291
|
+
# @return [Array<Octo::Category>] An array of categories object
|
292
|
+
def checkCategories(enterprise, categories)
|
293
|
+
if categories
|
294
|
+
categories.collect do |category|
|
295
|
+
Octo::Category.findOrCreate({enterprise_id: enterprise.id,
|
296
|
+
cat_text: category})
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
# Checks for tags and creates if not found
|
302
|
+
# @param [Octo::Enterprise] enterprise The enterprise object
|
303
|
+
# @param [Array<String>] tags An array of tags to be checked
|
304
|
+
# @return [Array<Octo::Tag>] An array of tags object
|
305
|
+
def checkTags(enterprise, tags)
|
306
|
+
if tags
|
307
|
+
tags.collect do |tag|
|
308
|
+
Octo::Tag.findOrCreate({enterprise_id: enterprise.id, tag_text: tag})
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
def parse(msg)
|
314
|
+
msg2 = JSON.parse(msg)
|
315
|
+
msg = msg2
|
316
|
+
enterprise = msg['enterprise']
|
317
|
+
raise StandardError, 'Parse Error' if enterprise.nil?
|
318
|
+
|
319
|
+
eid = if enterprise.has_key?'custom_id'
|
320
|
+
enterprise['custom_id']
|
321
|
+
elsif enterprise.has_key?'customId'
|
322
|
+
enterprise['customId']
|
323
|
+
end
|
324
|
+
|
325
|
+
ename = if enterprise.has_key?'user_name'
|
326
|
+
enterprise['user_name']
|
327
|
+
elsif enterprise.has_key?'userName'
|
328
|
+
enterprise['userName']
|
329
|
+
end
|
330
|
+
m = {
|
331
|
+
id: msg['uuid'],
|
332
|
+
enterpriseId: eid,
|
333
|
+
enterpriseName: ename,
|
334
|
+
event_name: msg['event_name'],
|
335
|
+
phone: msg.fetch('phoneDetails', nil),
|
336
|
+
browser: msg.fetch('browserDetails', nil),
|
337
|
+
userId: msg.fetch('userId', -1),
|
338
|
+
created_at: Time.now
|
339
|
+
}
|
340
|
+
case msg['event_name']
|
341
|
+
when 'update.profile'
|
342
|
+
m.merge!({
|
343
|
+
profileDetails: msg['profileDetails']
|
344
|
+
})
|
345
|
+
when 'page.view'
|
346
|
+
m.merge!({
|
347
|
+
routeUrl: msg['routeUrl'],
|
348
|
+
categories: msg.fetch('categories', []),
|
349
|
+
tags: msg.fetch('tags', [])
|
350
|
+
})
|
351
|
+
when 'productpage.view'
|
352
|
+
m.merge!({
|
353
|
+
routeUrl: msg['routeUrl'],
|
354
|
+
categories: msg.fetch('categories', []),
|
355
|
+
tags: msg.fetch('tags', []),
|
356
|
+
productId: msg['productId'],
|
357
|
+
productName: msg['productName'],
|
358
|
+
price: msg['price']
|
359
|
+
})
|
360
|
+
when 'update.push_token'
|
361
|
+
m.merge!({
|
362
|
+
pushType: msg['notificationType'],
|
363
|
+
pushKey: msg['pushKey'],
|
364
|
+
pushToken: msg['pushToken']
|
365
|
+
})
|
366
|
+
end
|
367
|
+
m
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|