octocore 0.0.2 → 0.0.3
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 +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
|