octocore 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +12 -0
- data/Gemfile.lock +7 -5
- data/README.md +3 -1
- data/Rakefile +3 -3
- data/bin/fakestream +2 -4
- data/lib/octocore.rb +7 -2
- data/lib/octocore/callbacks.rb +30 -3
- data/lib/octocore/email.rb +61 -0
- data/lib/octocore/helpers/api_consumer_helper.rb +156 -100
- data/lib/octocore/mailer.rb +1 -0
- data/lib/octocore/mailer/subscriber_mailer.rb +32 -0
- data/lib/octocore/models.rb +12 -0
- data/lib/octocore/models/contactus.rb +26 -1
- data/lib/octocore/models/enterprise/funnel_tracker.rb +19 -0
- data/lib/octocore/models/subscribe.rb +2 -1
- data/lib/octocore/models/user.rb +0 -7
- data/lib/octocore/scheduler.rb +13 -0
- data/lib/octocore/version.rb +1 -1
- metadata +27 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0ea80f8160f1f05b3d5259a207e76f7b2c75410
|
4
|
+
data.tar.gz: 80624160dd4076191d70c284fcb6c25bce21f660
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: efbe9cdda85b673d4adf8e7b4764cfe4eed2aad44e84c35a6f7a70b691ee82461994cb37ddde95fc85f3cd40f643af54d84fde4dab8e02a1232c21a83f0f3c27
|
7
|
+
data.tar.gz: 8116ecd4d607d55a64823920e48156a2f74dd3388121af4887d91321e82554336fa6b6f50227ef4774ba58c5e774a9fb0f4a840462a004d574e133f80d61162b
|
data/CHANGES.md
ADDED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
octocore (0.0.
|
4
|
+
octocore (0.0.2)
|
5
5
|
cequel (~> 1.9, >= 1.9.0)
|
6
6
|
descriptive_statistics (~> 2.5.1, >= 2.5.0)
|
7
7
|
elasticsearch (~> 1.0.17, >= 1.0.17)
|
@@ -9,6 +9,7 @@ PATH
|
|
9
9
|
hiredis (~> 0.6.1, >= 0.6.0)
|
10
10
|
hooks (~> 0.4.1, >= 0.4.1)
|
11
11
|
json (~> 1.8.1, >= 1.8.1)
|
12
|
+
mandrill-api (~> 1.0, >= 1.0.53)
|
12
13
|
rake (~> 11.1.0, >= 11.1.0)
|
13
14
|
redis (~> 3.2.2, >= 3.2.0)
|
14
15
|
resque (~> 1.26.0, >= 1.26.0)
|
@@ -44,6 +45,7 @@ GEM
|
|
44
45
|
elasticsearch-transport (1.0.18)
|
45
46
|
faraday
|
46
47
|
multi_json
|
48
|
+
excon (0.51.0)
|
47
49
|
faraday (0.9.2)
|
48
50
|
multipart-post (>= 1.2, < 3)
|
49
51
|
hiredis (0.6.1)
|
@@ -52,6 +54,9 @@ GEM
|
|
52
54
|
i18n (0.7.0)
|
53
55
|
ione (1.2.3)
|
54
56
|
json (1.8.3)
|
57
|
+
mandrill-api (1.0.53)
|
58
|
+
excon (>= 0.16.0, < 1.0)
|
59
|
+
json (>= 1.7.7, < 2.0)
|
55
60
|
minitest (5.9.0)
|
56
61
|
mono_logger (1.1.0)
|
57
62
|
multi_json (1.12.1)
|
@@ -90,7 +95,7 @@ GEM
|
|
90
95
|
diff-lcs (>= 1.2.0, < 2.0)
|
91
96
|
rspec-support (~> 3.4.0)
|
92
97
|
rspec-support (3.4.1)
|
93
|
-
ruby-kafka (0.3.
|
98
|
+
ruby-kafka (0.3.11)
|
94
99
|
rufus-scheduler (3.2.1)
|
95
100
|
sinatra (1.4.7)
|
96
101
|
rack (~> 1.5)
|
@@ -112,6 +117,3 @@ DEPENDENCIES
|
|
112
117
|
octocore!
|
113
118
|
parallel_tests (~> 2.5.0, >= 2.5.0)
|
114
119
|
rspec (~> 3.4.0, >= 3.4.0)
|
115
|
-
|
116
|
-
BUNDLED WITH
|
117
|
-
1.11.2
|
data/README.md
CHANGED
@@ -32,7 +32,9 @@ rake spec
|
|
32
32
|
You can use the following set of commands in `irb` to verify all things working with this gem. Execute it from irb in PROJ_DIR.
|
33
33
|
|
34
34
|
```ruby
|
35
|
-
require
|
35
|
+
%w(octocore).each { |x| require x }
|
36
|
+
config_file = 'lib/octocore/config/config.yml'
|
37
|
+
Octo.connect_with_config_file(config_file)
|
36
38
|
```
|
37
39
|
|
38
40
|
# Creating fake stream
|
data/Rakefile
CHANGED
@@ -9,13 +9,13 @@ require 'octocore/config'
|
|
9
9
|
RSpec::Core::RakeTask.new('spec')
|
10
10
|
|
11
11
|
task :environment do
|
12
|
-
config_dir = 'lib/octocore/config
|
12
|
+
config_dir = 'lib/octocore/config'
|
13
13
|
config = {}
|
14
|
-
Dir[
|
14
|
+
Dir['**{,/*/**}/*.yml'].each do |file|
|
15
15
|
_config = YAML.load_file(file)
|
16
16
|
if _config
|
17
17
|
puts "loading from file: #{ file }"
|
18
|
-
config
|
18
|
+
config.merge!(_config.deep_symbolize_keys)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
Octo.load_config config
|
data/bin/fakestream
CHANGED
@@ -7,7 +7,6 @@
|
|
7
7
|
|
8
8
|
require 'net/http'
|
9
9
|
require 'json'
|
10
|
-
|
11
10
|
require 'octocore'
|
12
11
|
|
13
12
|
module Octo
|
@@ -25,8 +24,6 @@ module Octo
|
|
25
24
|
MAX_TAGS = 15
|
26
25
|
|
27
26
|
|
28
|
-
|
29
|
-
|
30
27
|
#How many no. of pages to view before going to product page
|
31
28
|
MAX_PAGES_TO_VISIT = 3
|
32
29
|
|
@@ -40,7 +37,6 @@ module Octo
|
|
40
37
|
|
41
38
|
# simulate an app login
|
42
39
|
app_init user
|
43
|
-
|
44
40
|
# simulate a random number of page views before going to product
|
45
41
|
for i in 1..(1+rand(MAX_PAGES_TO_VISIT))
|
46
42
|
pv user, fakepage(user.enterprise)
|
@@ -49,11 +45,13 @@ module Octo
|
|
49
45
|
# simulate a product page view
|
50
46
|
ppv user, fakeproduct(user.enterprise)
|
51
47
|
|
48
|
+
|
52
49
|
#visit a page or not after going to the product page
|
53
50
|
for i in 0..rand(2)
|
54
51
|
pv user, fakepage(user.enterprise)
|
55
52
|
end
|
56
53
|
|
54
|
+
puts "---- Next User ----"
|
57
55
|
end
|
58
56
|
|
59
57
|
def stream_forever
|
data/lib/octocore.rb
CHANGED
@@ -3,17 +3,22 @@ require 'yaml'
|
|
3
3
|
require 'logger'
|
4
4
|
|
5
5
|
require 'octocore/version'
|
6
|
-
require 'octocore/utils'
|
7
6
|
require 'octocore/config'
|
8
7
|
require 'octocore/models'
|
9
8
|
require 'octocore/counter'
|
9
|
+
require 'octocore/email'
|
10
|
+
require 'octocore/utils'
|
10
11
|
|
11
12
|
require 'octocore/trendable'
|
12
13
|
require 'octocore/baseline'
|
13
14
|
require 'octocore/trends'
|
14
15
|
require 'octocore/kldivergence'
|
15
16
|
require 'octocore/segment'
|
17
|
+
|
18
|
+
# Mailer and scheduler should always be required in the following order
|
19
|
+
require 'octocore/mailer'
|
16
20
|
require 'octocore/scheduler'
|
21
|
+
|
17
22
|
require 'octocore/schedeuleable'
|
18
23
|
require 'octocore/helpers'
|
19
24
|
require 'octocore/kafka_bridge'
|
@@ -138,4 +143,4 @@ module Octo
|
|
138
143
|
@logger
|
139
144
|
end
|
140
145
|
|
141
|
-
end
|
146
|
+
end
|
data/lib/octocore/callbacks.rb
CHANGED
@@ -30,11 +30,13 @@ module Octo
|
|
30
30
|
|
31
31
|
# Define the after_page_view hook
|
32
32
|
after_page_view do |args|
|
33
|
+
add_session args
|
33
34
|
update_counters args
|
34
35
|
end
|
35
36
|
|
36
37
|
# Define the after_productpage_view hook
|
37
38
|
after_productpage_view do |args|
|
39
|
+
add_session args
|
38
40
|
update_counters args
|
39
41
|
end
|
40
42
|
end
|
@@ -64,8 +66,34 @@ module Octo
|
|
64
66
|
Octo::ApiHit.increment_for(opts[:event])
|
65
67
|
end
|
66
68
|
end
|
67
|
-
|
69
|
+
# Adds user session for page_view and
|
70
|
+
# product_page_view to redis.
|
71
|
+
# It self expires in n seconds from last hit
|
72
|
+
def add_session(opts)
|
73
|
+
if opts.has_key?(:type)
|
74
|
+
createRedisShadowKey(opts[:enterprise].id.to_s + '_' + opts[:user].id.to_s,
|
75
|
+
opts[:type].to_s,
|
76
|
+
Octo.get_config(:session_length))
|
77
|
+
end
|
78
|
+
end
|
68
79
|
|
80
|
+
# Method was created because when a redis key
|
81
|
+
# expires you can just catch the key name,
|
82
|
+
# and not its value. So what we do is
|
83
|
+
# create a shadow key for the given key name
|
84
|
+
# and make it expire in the given amt of
|
85
|
+
# time (seconds).
|
86
|
+
# This helps us in catching the event
|
87
|
+
# when the (shadow) key expires, after which we
|
88
|
+
# read the value of the main key and later
|
89
|
+
# delete the main key
|
90
|
+
# You can change it from rpush to lpush, or set
|
91
|
+
# whichever you want to use.
|
92
|
+
def createRedisShadowKey(keyname, value, duration)
|
93
|
+
Cequel::Record.redis.setex("shadow:" + keyname,duration,"")
|
94
|
+
Cequel::Record.redis.rpush(keyname, value)
|
95
|
+
end
|
96
|
+
end
|
69
97
|
end
|
70
98
|
|
71
99
|
# The class responsible for handling callbacks.
|
@@ -73,6 +101,5 @@ module Octo
|
|
73
101
|
class Callbacks
|
74
102
|
include Hooks
|
75
103
|
include Octo::OctoHooks
|
76
|
-
|
77
104
|
end
|
78
|
-
end
|
105
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'mandrill'
|
2
|
+
require 'resque'
|
3
|
+
require 'resque-scheduler'
|
4
|
+
|
5
|
+
module Octo
|
6
|
+
|
7
|
+
# Octo Email Sender
|
8
|
+
module Email
|
9
|
+
|
10
|
+
# Send Emails using mandrill api
|
11
|
+
# @param [Text] email Email Address of the receiver
|
12
|
+
# @param [Text] subject Subject of Email
|
13
|
+
# @param [Hash] opt Hash contain other message details
|
14
|
+
def send(email, subject, opts = {})
|
15
|
+
if email.nil? or subject.nil?
|
16
|
+
raise ArgumentError, 'Email Address or Subject is missing'
|
17
|
+
else
|
18
|
+
message = {
|
19
|
+
from_name: Octo.get_config(:email_sender).fetch(:name),
|
20
|
+
from_email: Octo.get_config(:email_sender).fetch(:email),
|
21
|
+
|
22
|
+
subject: subject,
|
23
|
+
|
24
|
+
text: opts.fetch('text', nil),
|
25
|
+
html: opts.fetch('html', nil),
|
26
|
+
|
27
|
+
to: [{
|
28
|
+
email: email,
|
29
|
+
name: opts.fetch('name', nil)
|
30
|
+
}]
|
31
|
+
}
|
32
|
+
# Pass the message to resque only when mandrill key is present
|
33
|
+
if Octo.get_config(:mandrill_api_key) != ''
|
34
|
+
enqueue_msg(message)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Adding Email details to Resque Queue
|
40
|
+
# @param [Hash] message Hash contain message details
|
41
|
+
def enqueue_msg(message)
|
42
|
+
Resque.enqueue(Octo::EmailSender, message)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
# Class to perform Resque operations for sending email
|
48
|
+
class EmailSender
|
49
|
+
|
50
|
+
@queue = :email_sender
|
51
|
+
|
52
|
+
# Resque Perform method
|
53
|
+
# @param [Hash] message The details of email
|
54
|
+
def self.perform(message)
|
55
|
+
m = Mandrill::API.new Octo.get_config(:mandrill_api_key)
|
56
|
+
m.messages.send message
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -5,7 +5,7 @@ module Octo
|
|
5
5
|
module Helpers
|
6
6
|
|
7
7
|
module ApiConsumerHelper
|
8
|
-
|
8
|
+
extend Cequel::Metal
|
9
9
|
# Get all the valid events
|
10
10
|
# @return [Set<Symbol>] Valid events globally
|
11
11
|
def valid_events
|
@@ -14,89 +14,92 @@ module Octo
|
|
14
14
|
|
15
15
|
# Get the API events. These are the ones that the client is billed for
|
16
16
|
# This should eventually be placed under kong helpers when that is
|
17
|
-
# ready
|
17
|
+
# ready.
|
18
18
|
# @return [Set<Symbol>] Set of api_events
|
19
19
|
def api_events
|
20
20
|
Set.new(%w(app.init app.login app.logout page.view productpage.view update.profile))
|
21
21
|
end
|
22
22
|
|
23
23
|
def handle(msg)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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,
|
24
|
+
msg_dump = msg
|
25
|
+
msg = parse(msg)
|
26
|
+
eventName = msg.delete(:event_name)
|
27
|
+
if (valid_events.include?eventName)
|
28
|
+
enterprise = checkEnterprise(msg)
|
29
|
+
unless enterprise
|
30
|
+
Octo.logger.info 'Unable to find enterprise. Something\'s wrong'
|
31
|
+
end
|
32
|
+
user = checkUser(enterprise, msg)
|
33
|
+
|
34
|
+
hook_opts = {
|
35
|
+
enterprise: enterprise,
|
36
|
+
user: user
|
37
|
+
}
|
38
|
+
|
39
|
+
if api_events.include?eventName
|
40
|
+
hook_opts[:event] = register_api_event(enterprise, eventName)
|
41
|
+
Octo::ApiTrack.new(customid: msg[:id],
|
72
42
|
created_at: Time.now,
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
43
|
+
json_dump: msg_dump,
|
44
|
+
type: eventName).save!
|
45
|
+
end
|
46
|
+
|
47
|
+
case eventName
|
48
|
+
when 'app.init'
|
49
|
+
Octo::AppInit.new(enterprise: enterprise,
|
50
|
+
created_at: Time.now,
|
51
|
+
userid: user.id).save!
|
52
|
+
updateUserDeviceDetails(user, msg)
|
53
|
+
hook_opts.merge!({type: 'init'})
|
54
|
+
call_hooks(eventName, hook_opts)
|
55
|
+
when 'app.login'
|
56
|
+
Octo::AppLogin.new(enterprise: enterprise,
|
57
|
+
created_at: Time.now,
|
58
|
+
userid: user.id).save!
|
59
|
+
updateUserDeviceDetails(user, msg)
|
60
|
+
call_hooks(eventName, hook_opts)
|
61
|
+
when 'app.logout'
|
62
|
+
event = Octo::AppLogout.new(enterprise: enterprise,
|
63
|
+
created_at: Time.now,
|
64
|
+
userid: user.id).save!
|
65
|
+
updateUserDeviceDetails(user, msg)
|
66
|
+
call_hooks(eventName, hook_opts)
|
67
|
+
when 'page.view'
|
68
|
+
page, categories, tags = checkPage(enterprise, msg)
|
69
|
+
Octo::PageView.new(enterprise: enterprise,
|
70
|
+
created_at: Time.now,
|
71
|
+
userid: user.id,
|
72
|
+
routeurl: page.routeurl
|
73
|
+
).save!
|
74
|
+
hook_opts.merge!({type: page.routeurl})
|
75
|
+
updateUserDeviceDetails(user, msg)
|
76
|
+
call_hooks(eventName, hook_opts)
|
77
|
+
when 'productpage.view'
|
78
|
+
product, categories, tags = checkProduct(enterprise, msg)
|
79
|
+
Octo::ProductPageView.new(
|
80
|
+
enterprise: enterprise,
|
81
|
+
created_at: Time.now,
|
82
|
+
userid: user.id,
|
83
|
+
product_id: product.id
|
84
|
+
).save!
|
85
|
+
updateUserDeviceDetails(user, msg)
|
86
|
+
hook_opts.merge!({ product: product,
|
87
|
+
categories: categories,
|
88
|
+
tags: tags,
|
89
|
+
type: product.routeurl
|
90
|
+
})
|
91
|
+
call_hooks(eventName, hook_opts)
|
92
|
+
when 'update.profile'
|
93
|
+
checkUserProfileDetails(enterprise, user, msg)
|
94
|
+
updateUserDeviceDetails(user, msg)
|
95
|
+
call_hooks(eventName, hook_opts)
|
96
|
+
when 'update.push_token'
|
97
|
+
checkPushToken(enterprise, user, msg)
|
98
|
+
checkPushKey(enterprise, msg)
|
99
|
+
when 'funnel_update'
|
100
|
+
checkRedisSession(enterprise,msg)
|
101
|
+
end
|
98
102
|
end
|
99
|
-
end
|
100
103
|
end
|
101
104
|
|
102
105
|
private
|
@@ -111,6 +114,50 @@ module Octo
|
|
111
114
|
Octo::Callbacks.run_hook(hook, *args)
|
112
115
|
end
|
113
116
|
|
117
|
+
# Checks for msg[:rediskey] in redis, parses it and
|
118
|
+
# then calls updateFunnelTracker.
|
119
|
+
# @param [Octo::Enterprise] enterprise The Enterprise object
|
120
|
+
# @param [Hash] msg The message hash, MUST contain, :rediskey
|
121
|
+
# @return [void]
|
122
|
+
def checkRedisSession(enterprise,msg)
|
123
|
+
sessionList = Cequel::Record.redis.lrange(msg[:rediskey],0,-1)
|
124
|
+
Cequel::Record.redis.del(msg[:rediskey])
|
125
|
+
sessionList.each_index{ |index|
|
126
|
+
if index!=(sessionList.length-1)
|
127
|
+
updateFunnelTracker(enterprise,sessionList[index],sessionList[index+1])
|
128
|
+
end
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
# Checks if transition from page1 -> page2 exists, then
|
133
|
+
# updates the value of its weight, else creates
|
134
|
+
# the transition with default weight 1. It also creates an
|
135
|
+
# entry for page 2 <- page 1, which helps us understand the
|
136
|
+
# incoming entries for a particular node.
|
137
|
+
# @param [Octo::Enterprise] enterprise The Enterprise object
|
138
|
+
# @param [string] page1 The url of page1
|
139
|
+
# @param [string] page2 The url of page2
|
140
|
+
# @return [void]
|
141
|
+
def updateFunnelTracker(enterprise,page1,page2)
|
142
|
+
args_to = {
|
143
|
+
enterprise_id: enterprise.id,
|
144
|
+
p1: page1,
|
145
|
+
direction:1,
|
146
|
+
p2: page2
|
147
|
+
}
|
148
|
+
args_from = {
|
149
|
+
enterprise_id: enterprise.id,
|
150
|
+
p1: page2,
|
151
|
+
direction: 0,
|
152
|
+
p2: page1
|
153
|
+
}
|
154
|
+
counters = {
|
155
|
+
weight:1,
|
156
|
+
}
|
157
|
+
Octo::FunnelTracker.findOrCreateOrAdjust(args_to,counters)
|
158
|
+
Octo::FunnelTracker.findOrCreateOrAdjust(args_from,counters)
|
159
|
+
end
|
160
|
+
|
114
161
|
def checkUserProfileDetails(enterprise, user, msg)
|
115
162
|
args = {
|
116
163
|
user_id: user.id,
|
@@ -313,31 +360,13 @@ module Octo
|
|
313
360
|
def parse(msg)
|
314
361
|
msg2 = JSON.parse(msg)
|
315
362
|
msg = msg2
|
316
|
-
|
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
|
-
}
|
363
|
+
m = { event_name: msg['event_name'] }
|
340
364
|
case msg['event_name']
|
365
|
+
when 'funnel_update'
|
366
|
+
m.merge!({
|
367
|
+
rediskey: msg['rediskey']
|
368
|
+
})
|
369
|
+
# return m
|
341
370
|
when 'update.profile'
|
342
371
|
m.merge!({
|
343
372
|
profileDetails: msg['profileDetails']
|
@@ -364,8 +393,35 @@ module Octo
|
|
364
393
|
pushToken: msg['pushToken']
|
365
394
|
})
|
366
395
|
end
|
396
|
+
enterprise = msg['enterprise']
|
397
|
+
raise StandardError, 'Parse Error' if enterprise.nil?
|
398
|
+
|
399
|
+
eid = if enterprise.has_key?'custom_id'
|
400
|
+
enterprise['custom_id']
|
401
|
+
elsif enterprise.has_key?'customId'
|
402
|
+
enterprise['customId']
|
403
|
+
end
|
404
|
+
|
405
|
+
ename = if enterprise.has_key?'user_name'
|
406
|
+
enterprise['user_name']
|
407
|
+
elsif enterprise.has_key?'userName'
|
408
|
+
enterprise['userName']
|
409
|
+
else
|
410
|
+
nil
|
411
|
+
end
|
412
|
+
m.merge!({
|
413
|
+
id: msg.fetch('uuid', nil),
|
414
|
+
enterpriseId: eid,
|
415
|
+
enterpriseName: ename,
|
416
|
+
phone: msg.fetch('phoneDetails', nil),
|
417
|
+
browser: msg.fetch('browserDetails', nil),
|
418
|
+
userId: msg.fetch('userId', -1),
|
419
|
+
created_at: Time.now
|
420
|
+
})
|
421
|
+
|
367
422
|
m
|
368
423
|
end
|
369
424
|
end
|
370
425
|
end
|
371
426
|
end
|
427
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'octocore/mailer/subscriber_mailer'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'octocore'
|
2
|
+
|
3
|
+
module Octo
|
4
|
+
module Mailer
|
5
|
+
class SubscriberMailer
|
6
|
+
@queue = :subscriber_notifier
|
7
|
+
|
8
|
+
# Method for the scheduler to call
|
9
|
+
# Counts the number of subscriber in the last 24 hours
|
10
|
+
# and then sends a mail with subscriber count to the
|
11
|
+
# email mentioned
|
12
|
+
|
13
|
+
def perform (from=nil)
|
14
|
+
if from.nil?
|
15
|
+
subscribers = Octo::Subscriber.where(created_at: 24.hours.ago..Time.now.floor)
|
16
|
+
else
|
17
|
+
subscribers = Octo::Subscriber.where(created_at: from..Time.now.floor)
|
18
|
+
end
|
19
|
+
# MAIL CODE
|
20
|
+
Octo.get_config(:email_to).each { |x|
|
21
|
+
opts1 = {
|
22
|
+
text: "Today number of new susbcribes are " + subscribers.length,
|
23
|
+
name: x.fetch('name')
|
24
|
+
}
|
25
|
+
Octo::Email.send(x.fetch('email'), subject, opts1)
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
data/lib/octocore/models.rb
CHANGED
@@ -145,6 +145,16 @@ module Cequel
|
|
145
145
|
res
|
146
146
|
end
|
147
147
|
|
148
|
+
|
149
|
+
# If a record exists in a COUNTER TABLE, it will find
|
150
|
+
# it and increment or decrement it's value with the
|
151
|
+
# provided options. Else, will just create the
|
152
|
+
# record with default value.
|
153
|
+
def findOrCreateOrAdjust(args, options)
|
154
|
+
self.where(args).data_set.increment(options)
|
155
|
+
end
|
156
|
+
|
157
|
+
|
148
158
|
# Perform a cache backed get
|
149
159
|
# @param [Hash] args The arguments hash for the record
|
150
160
|
# to be found
|
@@ -224,6 +234,8 @@ require 'octocore/models/enterprise/dimension_choice'
|
|
224
234
|
require 'octocore/models/enterprise/engagement_time'
|
225
235
|
require 'octocore/models/enterprise/funnels'
|
226
236
|
require 'octocore/models/enterprise/funnel_data'
|
237
|
+
require 'octocore/models/enterprise/funnel_tracker'
|
238
|
+
|
227
239
|
require 'octocore/models/enterprise/gcm'
|
228
240
|
require 'octocore/models/enterprise/newsfeed_hit'
|
229
241
|
require 'octocore/models/enterprise/notification_hit'
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'cequel'
|
2
|
-
|
2
|
+
|
3
|
+
# Model for contact us page on the microsite
|
3
4
|
module Octo
|
4
5
|
class ContactUs
|
5
6
|
include Cequel::Record
|
@@ -12,6 +13,30 @@ module Octo
|
|
12
13
|
column :lastname, :text
|
13
14
|
column :message, :text
|
14
15
|
|
16
|
+
after_create :send_email
|
17
|
+
|
18
|
+
# Send Email after model save
|
19
|
+
def send_email
|
20
|
+
|
21
|
+
# Send thankyou mail
|
22
|
+
subject = 'Thanks for contacting us - Octo.ai'
|
23
|
+
opts = {
|
24
|
+
text: 'Hey we will get in touch with you shortly. Thanks :)',
|
25
|
+
name: self.firstname + ' ' + self.lastname
|
26
|
+
}
|
27
|
+
Octo::Email.send(self.email, subject, opts)
|
28
|
+
|
29
|
+
# Send mail to aron and param
|
30
|
+
Octo.get_config(:email_to).each { |x|
|
31
|
+
opts1 = {
|
32
|
+
text: self.email + ' \n\r ' + self.typeofrequest + '\n\r' + self.message,
|
33
|
+
name: x.fetch('name')
|
34
|
+
}
|
35
|
+
Octo::Email.send(x.fetch('email'), subject, opts1)
|
36
|
+
}
|
37
|
+
|
38
|
+
|
39
|
+
end
|
15
40
|
|
16
41
|
end
|
17
42
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'cequel'
|
2
|
+
|
3
|
+
module Octo
|
4
|
+
# A model for tracking the user web flow
|
5
|
+
# Used to build a markov model on the basis
|
6
|
+
# of the activity. eg p1 --> p2 will be entered
|
7
|
+
# with weight 1, and increased by +1 every time any
|
8
|
+
# user goes from p1 to p2
|
9
|
+
class FunnelTracker
|
10
|
+
include Cequel::Record
|
11
|
+
|
12
|
+
key :enterprise_id, :uuid
|
13
|
+
|
14
|
+
key :p1, :text
|
15
|
+
key :direction, :int
|
16
|
+
key :p2, :text
|
17
|
+
column :weight, :counter
|
18
|
+
end
|
19
|
+
end
|
data/lib/octocore/models/user.rb
CHANGED
@@ -3,20 +3,13 @@ require 'cequel'
|
|
3
3
|
module Octo
|
4
4
|
class User
|
5
5
|
include Cequel::Record
|
6
|
-
|
7
6
|
belongs_to :enterprise, class_name: 'Octo::Enterprise'
|
8
7
|
|
9
8
|
key :id, :bigint
|
10
9
|
|
11
10
|
timestamps
|
12
11
|
|
13
|
-
# Define the associations
|
14
12
|
has_many :user_location_histories
|
15
|
-
has_many :user_phone_details
|
16
|
-
has_many :push_token
|
17
|
-
has_many :user_browser_details
|
18
|
-
has_many :user_personas
|
19
|
-
|
20
13
|
end
|
21
14
|
end
|
22
15
|
|
data/lib/octocore/scheduler.rb
CHANGED
@@ -54,6 +54,19 @@ module Octo
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
# Schedules the daily mail, to be sent at noon
|
58
|
+
def schedule_subscribermail
|
59
|
+
name = 'SubscriberDailyMailer'
|
60
|
+
config = {
|
61
|
+
class: Octo::Mailer::SubscriberMailer,
|
62
|
+
args: [],
|
63
|
+
cron: '0 0 * * *',
|
64
|
+
persist: true,
|
65
|
+
queue: 'subscriber_notifier'
|
66
|
+
}
|
67
|
+
Resque.set_schedule name, config
|
68
|
+
end
|
69
|
+
|
57
70
|
end
|
58
71
|
end
|
59
72
|
end
|
data/lib/octocore/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: octocore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pranav Prakash
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-07-
|
11
|
+
date: 2016-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cequel
|
@@ -230,6 +230,26 @@ dependencies:
|
|
230
230
|
- - ">="
|
231
231
|
- !ruby/object:Gem::Version
|
232
232
|
version: 0.3.2
|
233
|
+
- !ruby/object:Gem::Dependency
|
234
|
+
name: mandrill-api
|
235
|
+
requirement: !ruby/object:Gem::Requirement
|
236
|
+
requirements:
|
237
|
+
- - "~>"
|
238
|
+
- !ruby/object:Gem::Version
|
239
|
+
version: '1.0'
|
240
|
+
- - ">="
|
241
|
+
- !ruby/object:Gem::Version
|
242
|
+
version: 1.0.53
|
243
|
+
type: :runtime
|
244
|
+
prerelease: false
|
245
|
+
version_requirements: !ruby/object:Gem::Requirement
|
246
|
+
requirements:
|
247
|
+
- - "~>"
|
248
|
+
- !ruby/object:Gem::Version
|
249
|
+
version: '1.0'
|
250
|
+
- - ">="
|
251
|
+
- !ruby/object:Gem::Version
|
252
|
+
version: 1.0.53
|
233
253
|
- !ruby/object:Gem::Dependency
|
234
254
|
name: elasticsearch
|
235
255
|
requirement: !ruby/object:Gem::Requirement
|
@@ -320,6 +340,7 @@ extensions: []
|
|
320
340
|
extra_rdoc_files:
|
321
341
|
- README.md
|
322
342
|
files:
|
343
|
+
- CHANGES.md
|
323
344
|
- Gemfile
|
324
345
|
- Gemfile.lock
|
325
346
|
- README.md
|
@@ -333,6 +354,7 @@ files:
|
|
333
354
|
- lib/octocore/config/search/index/user.yml
|
334
355
|
- lib/octocore/counter.rb
|
335
356
|
- lib/octocore/counter/helpers.rb
|
357
|
+
- lib/octocore/email.rb
|
336
358
|
- lib/octocore/helpers.rb
|
337
359
|
- lib/octocore/helpers/api_consumer_helper.rb
|
338
360
|
- lib/octocore/helpers/api_helper.rb
|
@@ -342,6 +364,8 @@ files:
|
|
342
364
|
- lib/octocore/helpers/sinatra_helper.rb
|
343
365
|
- lib/octocore/kafka_bridge.rb
|
344
366
|
- lib/octocore/kldivergence.rb
|
367
|
+
- lib/octocore/mailer.rb
|
368
|
+
- lib/octocore/mailer/subscriber_mailer.rb
|
345
369
|
- lib/octocore/models.rb
|
346
370
|
- lib/octocore/models/contactus.rb
|
347
371
|
- lib/octocore/models/enterprise.rb
|
@@ -361,6 +385,7 @@ files:
|
|
361
385
|
- lib/octocore/models/enterprise/dimension_choice.rb
|
362
386
|
- lib/octocore/models/enterprise/engagement_time.rb
|
363
387
|
- lib/octocore/models/enterprise/funnel_data.rb
|
388
|
+
- lib/octocore/models/enterprise/funnel_tracker.rb
|
364
389
|
- lib/octocore/models/enterprise/funnels.rb
|
365
390
|
- lib/octocore/models/enterprise/gcm.rb
|
366
391
|
- lib/octocore/models/enterprise/newsfeed_hit.rb
|