notify_user 0.0.1 → 0.0.5
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 +7 -0
- data/app/assets/javascripts/notify_user/notification.js +7 -0
- data/app/assets/stylesheets/notify_user/notify_user.css +50 -0
- data/app/controllers/notify_user/base_notifications_controller.rb +144 -0
- data/app/controllers/notify_user/notifications_controller.rb +7 -32
- data/app/helpers/notify_user/application_helper.rb +9 -0
- data/app/mailers/notify_user/notification_mailer.rb +2 -0
- data/app/models/notify_user/apns.rb +37 -0
- data/app/models/notify_user/base_notification.rb +136 -32
- data/app/models/notify_user/unsubscribe.rb +55 -0
- data/app/models/notify_user/user_hash.rb +36 -0
- data/app/serializers/notify_user/notification_serializer.rb +2 -2
- data/app/views/notify_user/action_mailer/aggregate_notification.html.erb +2 -1
- data/app/views/notify_user/action_mailer/notification.html.erb +1 -1
- data/app/views/notify_user/base_notifications/index.html.erb +20 -0
- data/app/views/notify_user/base_notifications/unsubscribe.html.erb +19 -0
- data/config/routes.rb +8 -0
- data/lib/generators/notify_user/install/install_generator.rb +20 -3
- data/lib/generators/notify_user/install/templates/{migration.rb → create_notify_user_notifications.rb} +1 -1
- data/lib/generators/notify_user/install/templates/create_notify_user_unsubscribes.rb +10 -0
- data/lib/generators/notify_user/install/templates/create_notify_user_user_hashes.rb +12 -0
- data/lib/generators/notify_user/install/templates/initializer.rb +2 -0
- data/lib/generators/notify_user/install/templates/notifications_controller.rb +9 -0
- data/lib/generators/notify_user/json_update/USAGE +5 -0
- data/lib/generators/notify_user/json_update/json_update_generator.rb +36 -0
- data/lib/generators/notify_user/json_update/templates/add_json_column_to_notifications.rb +9 -0
- data/lib/generators/notify_user/json_update/templates/move_params_to_json.rb +8 -0
- data/lib/generators/notify_user/notification/notification_generator.rb +2 -0
- data/lib/generators/notify_user/notification/templates/email_layout_template.html.erb.erb +6 -0
- data/lib/generators/notify_user/notification/templates/notification.rb.erb +2 -1
- data/lib/notify_user.rb +4 -1
- data/lib/notify_user/channels/action_mailer/action_mailer_channel.rb +2 -1
- data/lib/notify_user/channels/apns/apns_channel.rb +17 -0
- data/lib/notify_user/engine.rb +2 -0
- data/lib/notify_user/railtie.rb +10 -0
- data/lib/notify_user/version.rb +1 -1
- data/lib/tasks/notify_user.rake +15 -0
- data/spec/controllers/notify_user/notifications_controller_spec.rb +89 -1
- data/spec/dummy/rails-4.0.2/Gemfile +2 -2
- data/spec/dummy/rails-4.0.2/app/controllers/notify_user/notifications_controller.rb +9 -0
- data/spec/dummy/rails-4.0.2/app/notifications/new_post_notification.rb +2 -1
- data/spec/dummy/rails-4.0.2/app/views/notify_user/layouts/action_mailer.html.erb +6 -0
- data/spec/dummy/rails-4.0.2/config/database.yml +42 -13
- data/spec/dummy/rails-4.0.2/config/database2.yml +57 -0
- data/spec/dummy/rails-4.0.2/config/initializers/notify_user.rb +2 -0
- data/spec/dummy/rails-4.0.2/config/initializers/secret_token.rb +1 -1
- data/spec/dummy/rails-4.0.2/db/migrate/{20140105070446_create_users.rb → 20140428015529_create_users.rb} +0 -0
- data/spec/dummy/rails-4.0.2/db/migrate/{20140105070448_create_notify_user_notifications.rb → 20140428015531189189694000_create_notify_user_notifications.rb} +1 -1
- data/spec/dummy/rails-4.0.2/db/migrate/20140428015531190190743000_create_notify_user_unsubscribes.rb +10 -0
- data/spec/dummy/rails-4.0.2/db/migrate/20140428015531191191953000_create_notify_user_user_hashes.rb +12 -0
- data/spec/dummy/rails-4.0.2/db/schema.rb +23 -2
- data/spec/dummy/rails-4.0.2/log/test.log +787 -1414
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/13195a56ea8581e42f709ea01ea4604f +0 -0
- data/{app/assets/stylesheets/notify_user/application.css → spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705} +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/148f39f7dc2ea6cb194598111dbd4598 +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/1d6bc1877ba2bbb89f393e10e8303d39 +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/311d2b645a860b78f79ff156f12092ce +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/39651f0f2ac78423732234ebf092c632 +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/5c85b1b5ac27b699c5f800c4e7ec82fb +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/68752c7ddc300bee3e9823db8befc306 +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/6961013077b8573ed19d1e33abb8ebc5 +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/7a316b3629b980c6d3a28924cb5fbbd8 +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/8698d6fed0ef2f173a377160752b959f +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/8bab520aad78da438df1c428288cf229 +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/fa138a16887e031c0ae1b4caccfb4c05 +0 -0
- data/spec/mailers/notify_user/notification_mailer_spec.rb +1 -0
- data/spec/models/notify_user/notification_spec.rb +122 -1
- data/spec/models/notify_user/unsubscribe_spec.rb +40 -0
- data/spec/models/notify_user/user_hash_spec.rb +35 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/database.yml +21 -0
- data/spec/support/rails_template.rb +9 -0
- metadata +196 -65
- data/spec/dummy/rails-4.0.2/db/test.sqlite3 +0 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 6ccbda4d4f6f0bd85a37c2e9295789c8c3c28844
|
|
4
|
+
data.tar.gz: f8f67249b41082e9af5dc4686bb3f85639360507
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: b9258b901edd1eb111a33354aafc2aa668b7520587594fad58e03d5d887042836633cc620a8b49d167220ebb16cac1c18423c78d9d45d8fc9bbbf76d4d5eaf78
|
|
7
|
+
data.tar.gz: ae8fd4a46fde87ffe996adc8e42e63b667a5b0525ceb269205a76e437a17df21209ff5f7f8e59d1298f4eee57cec35738b0d3059b094aa80876808cf8712f42f
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
.unread a{
|
|
2
|
+
font-weight: bold;
|
|
3
|
+
}
|
|
4
|
+
.read a{
|
|
5
|
+
font-weight: normal;
|
|
6
|
+
}
|
|
7
|
+
#notifications_list{
|
|
8
|
+
margin: 0 auto;
|
|
9
|
+
width: 100%;
|
|
10
|
+
width: 720px;
|
|
11
|
+
color: #000;
|
|
12
|
+
font-family: arial;
|
|
13
|
+
font-size: 14px;
|
|
14
|
+
text-align: right;
|
|
15
|
+
padding: 5px;
|
|
16
|
+
text-align: center;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
#notifications_list .inner{
|
|
20
|
+
margin-top: 10px;
|
|
21
|
+
border: 1px solid #dedede;
|
|
22
|
+
text-align: left;
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
#notifications_list a{
|
|
26
|
+
color: #454545;
|
|
27
|
+
text-decoration: none;
|
|
28
|
+
}
|
|
29
|
+
#notifications_list .item:hover a{
|
|
30
|
+
text-decoration: underline;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
#notifications_list .title{
|
|
34
|
+
text-align: left;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
#notifications_list .item{
|
|
38
|
+
padding: 20px 10px;
|
|
39
|
+
border-bottom: 1px solid #dedede;
|
|
40
|
+
}
|
|
41
|
+
#notifications_list .item.read{
|
|
42
|
+
background: #eaeaea;
|
|
43
|
+
}
|
|
44
|
+
#notifications_list .item .time_ago{
|
|
45
|
+
font-size: 12px;
|
|
46
|
+
text-align: right;
|
|
47
|
+
}
|
|
48
|
+
#notifications_list .mark_as_read{
|
|
49
|
+
text-align: right;
|
|
50
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
class NotifyUser::BaseNotificationsController < ApplicationController
|
|
2
|
+
|
|
3
|
+
before_filter :authenticate!, :except => [:unauth_unsubscribe]
|
|
4
|
+
|
|
5
|
+
def index
|
|
6
|
+
@notifications = NotifyUser::BaseNotification.for_target(@user)
|
|
7
|
+
.order("created_at DESC")
|
|
8
|
+
.limit(30)
|
|
9
|
+
.page(params[:page]).per(params[:per_page])
|
|
10
|
+
|
|
11
|
+
respond_to do |format|
|
|
12
|
+
format.html
|
|
13
|
+
format.json {render :json => @notifications, meta: { pagination: { per_page: @notifications.limit_value, total_pages: @notifications.total_pages, total_objects: @notifications.total_count } }}
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def mark_read
|
|
18
|
+
@notifications = NotifyUser::BaseNotification.for_target(@user).where('id IN (?)', params[:ids])
|
|
19
|
+
@notifications.update_all(state: :read)
|
|
20
|
+
render json: @notifications
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def mark_all
|
|
24
|
+
@notifications = NotifyUser::BaseNotification.for_target(@user).where('state IN (?)', ["pending","sent"])
|
|
25
|
+
@notifications.update_all(state: :read)
|
|
26
|
+
redirect_to notify_user_notifications_path
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def notifications_count
|
|
30
|
+
@notifications = NotifyUser::BaseNotification.for_target(@user).where('state IN (?)', ["sent"])
|
|
31
|
+
render json: {:count => @notifications.count}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#get
|
|
35
|
+
def read
|
|
36
|
+
@notification = NotifyUser::BaseNotification.for_target(@user).where('id = ?', params[:id]).first
|
|
37
|
+
@notification.mark_as_read
|
|
38
|
+
redirect_logic(@notification)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def redirect_logic(notification)
|
|
42
|
+
render :text => "redirect setup goes here"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def unsubscribe
|
|
46
|
+
if params[:type]
|
|
47
|
+
unsubscribe_from(params[:type])
|
|
48
|
+
redirect_to notify_user_notifications_unsubscribe_path
|
|
49
|
+
end
|
|
50
|
+
@unsubscribale_types = NotifyUser.unsubscribable_notifications
|
|
51
|
+
@unsubscribale_channels = NotifyUser::BaseNotification.channels
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
#endpoint for accessing subscriptions and their statuses
|
|
55
|
+
def subscriptions
|
|
56
|
+
update_subscriptions(params[:types]) if params[:types]
|
|
57
|
+
@types = build_notification_types
|
|
58
|
+
render :json => @types
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def update_subscriptions(types)
|
|
62
|
+
types.each do |type|
|
|
63
|
+
unsubscribe = NotifyUser::Unsubscribe.has_unsubscribed_from(@user, type[:type])
|
|
64
|
+
if type[:status] == '0'
|
|
65
|
+
if unsubscribe.empty?
|
|
66
|
+
#if unsubscribe doesn't exist create it
|
|
67
|
+
unsubscribe = NotifyUser::Unsubscribe.create(target: @user, type: type[:type])
|
|
68
|
+
end
|
|
69
|
+
else
|
|
70
|
+
subscribe_to(type[:type])
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def unauth_unsubscribe
|
|
76
|
+
if params[:token] && params[:type]
|
|
77
|
+
if NotifyUser::UserHash.confirm_hash(params[:token], params[:type])
|
|
78
|
+
user_hash = NotifyUser::UserHash.where(token: params[:token], type: params[:type]).first
|
|
79
|
+
@user = user_hash.target
|
|
80
|
+
unsubscribe = NotifyUser::Unsubscribe.create(target: @user, type: params[:type])
|
|
81
|
+
user_hash.deactivate
|
|
82
|
+
return render :text => "successfully unsubscribed from #{params[:type]} notifications"
|
|
83
|
+
else
|
|
84
|
+
return render :text => "invalid token"
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
return render :text => "Something went wrong please try again later"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def subscribe
|
|
91
|
+
subscribe_to(params[:type]) if params[:type]
|
|
92
|
+
redirect_to notify_user_notifications_unsubscribe_path
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
protected
|
|
96
|
+
|
|
97
|
+
def default_serializer_options
|
|
98
|
+
{
|
|
99
|
+
each_serializer: NotifyUser::NotificationSerializer,
|
|
100
|
+
template_renderer: self
|
|
101
|
+
}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def authenticate!
|
|
105
|
+
method(NotifyUser.authentication_method).call
|
|
106
|
+
@user = method(NotifyUser.current_user_method).call
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
private
|
|
110
|
+
def build_notification_types()
|
|
111
|
+
#dirty way to build a json hash with pagination
|
|
112
|
+
types = {:subscriptions => []}
|
|
113
|
+
|
|
114
|
+
notification_types = NotifyUser.unsubscribable_notifications
|
|
115
|
+
|
|
116
|
+
#iterates over channels
|
|
117
|
+
NotifyUser::BaseNotification.channels.each do |type, options|
|
|
118
|
+
channel = (type.to_s + "_channel").camelize.constantize
|
|
119
|
+
types[:subscriptions] << {type: type, description: channel.default_options[:description],
|
|
120
|
+
status: NotifyUser::Unsubscribe.has_unsubscribed_from(@user, type).empty?}
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
#iterates over type
|
|
124
|
+
notification_types.each do |type|
|
|
125
|
+
types[:subscriptions] << {type: type, description: type.constantize.description,
|
|
126
|
+
status: NotifyUser::Unsubscribe.has_unsubscribed_from(@user, type).empty?}
|
|
127
|
+
end
|
|
128
|
+
return types
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def unsubscribe_from(type)
|
|
132
|
+
unsubscribe = NotifyUser::Unsubscribe.new(target: @user, type: type)
|
|
133
|
+
if unsubscribe.save
|
|
134
|
+
flash[:message] = "successfully unsubscribed from #{type} notifications"
|
|
135
|
+
else
|
|
136
|
+
flash[:message] = "Please try again"
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def subscribe_to(type)
|
|
141
|
+
NotifyUser::Unsubscribe.unsubscribe(@user,type)
|
|
142
|
+
flash[:message] = "successfully subscribed to #{type} notifications"
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -1,33 +1,8 @@
|
|
|
1
|
-
class NotifyUser::NotificationsController <
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
.limit(30)
|
|
9
|
-
.page(params[:page])
|
|
10
|
-
|
|
11
|
-
render json: @notifications
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def mark_read
|
|
15
|
-
@notifications = NotifyUser::BaseNotification.for_target(@user).where('id IN (?)', params[:ids])
|
|
16
|
-
@notifications.update_all(state: :read)
|
|
17
|
-
render json: @notifications
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
protected
|
|
21
|
-
|
|
22
|
-
def default_serializer_options
|
|
23
|
-
{
|
|
24
|
-
each_serializer: NotifyUser::NotificationSerializer,
|
|
25
|
-
template_renderer: self
|
|
26
|
-
}
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def authenticate!
|
|
30
|
-
method(NotifyUser.authentication_method).call
|
|
31
|
-
@user = method(NotifyUser.current_user_method).call
|
|
32
|
-
end
|
|
1
|
+
class NotifyUser::NotificationsController < NotifyUser::BaseNotificationsController
|
|
2
|
+
def redirect_logic(notification)
|
|
3
|
+
render :text => "set redirect logic in notify_user/notifications_controller.rb"
|
|
4
|
+
#notification redirect logic goes here
|
|
5
|
+
#property = Property.find(@notification.params[:property_id])
|
|
6
|
+
#redirect_to property_url(@property)
|
|
7
|
+
end
|
|
33
8
|
end
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
module NotifyUser
|
|
2
2
|
module ApplicationHelper
|
|
3
|
+
def unsubscribe_link(notification, text)
|
|
4
|
+
user_hash = notification.generate_unsubscribe_hash
|
|
5
|
+
html = link_to(text, notify_user_notifications_unauth_unsubscribe_url(:type => notification.type, :token => user_hash.token))
|
|
6
|
+
return html.to_s.html_safe
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def is_unsubscribeable?(notification)
|
|
10
|
+
return NotifyUser.unsubscribable_notifications.include? notification.type
|
|
11
|
+
end
|
|
3
12
|
end
|
|
4
13
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
module NotifyUser
|
|
2
2
|
class NotificationMailer < ActionMailer::Base
|
|
3
|
+
helper NotifyUser::ApplicationHelper
|
|
3
4
|
|
|
4
5
|
layout "notify_user/layouts/action_mailer"
|
|
5
6
|
|
|
@@ -15,6 +16,7 @@ module NotifyUser
|
|
|
15
16
|
|
|
16
17
|
def aggregate_notifications_email(notifications, options)
|
|
17
18
|
@notifications = notifications
|
|
19
|
+
@notification = notifications.first
|
|
18
20
|
|
|
19
21
|
mail to: @notifications.first.target.email,
|
|
20
22
|
template_name: "aggregate_notification",
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module NotifyUser
|
|
2
|
+
class Apns
|
|
3
|
+
SYMBOL_NAMES_SIZE = 10
|
|
4
|
+
PAYLOAD_LIMIT = 255
|
|
5
|
+
|
|
6
|
+
#sends push notification
|
|
7
|
+
def self.push_notification(notification)
|
|
8
|
+
#calculates the bytes already used
|
|
9
|
+
used_space = SYMBOL_NAMES_SIZE + notification.id.size + notification.created_at.to_time.to_i.size +
|
|
10
|
+
notification.type.size
|
|
11
|
+
|
|
12
|
+
used_space += notification.params[:action_id].size if notification.params[:action_id]
|
|
13
|
+
|
|
14
|
+
space_allowance = PAYLOAD_LIMIT - used_space
|
|
15
|
+
|
|
16
|
+
payload = {
|
|
17
|
+
:alias => notification.target_id,
|
|
18
|
+
:aps => {alert: notification.mobile_message(space_allowance), badge: 1},
|
|
19
|
+
:n_data => {
|
|
20
|
+
'#' => notification.id,
|
|
21
|
+
t: notification.created_at.to_time.to_i,
|
|
22
|
+
'?' => notification.type
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
payload[:n_data]['!'] = notification.params[:action_id] if notification.params[:action_id]
|
|
26
|
+
|
|
27
|
+
response = Urbanairship.push(payload)
|
|
28
|
+
if response.success?
|
|
29
|
+
puts "Push notification sent successfully."
|
|
30
|
+
return true
|
|
31
|
+
else
|
|
32
|
+
puts "Push notification failed."
|
|
33
|
+
return false
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -3,6 +3,7 @@ require 'sidekiq'
|
|
|
3
3
|
|
|
4
4
|
module NotifyUser
|
|
5
5
|
class BaseNotification < ActiveRecord::Base
|
|
6
|
+
include ActionView::Helpers::TextHelper
|
|
6
7
|
|
|
7
8
|
if ActiveRecord::VERSION::MAJOR < 4
|
|
8
9
|
attr_accessible :params, :target, :type, :state
|
|
@@ -11,8 +12,11 @@ module NotifyUser
|
|
|
11
12
|
# Override point in case of collisions, plus keeps the table name tidy.
|
|
12
13
|
self.table_name = "notify_user_notifications"
|
|
13
14
|
|
|
15
|
+
#checks if user has unsubscribed from this notif type
|
|
16
|
+
validate :unsubscribed_validation
|
|
17
|
+
|
|
14
18
|
# Params for creating the notification message.
|
|
15
|
-
serialize :params, Hash
|
|
19
|
+
# serialize :params, Hash
|
|
16
20
|
|
|
17
21
|
# The user to send the notification to
|
|
18
22
|
belongs_to :target, polymorphic: true
|
|
@@ -46,8 +50,29 @@ module NotifyUser
|
|
|
46
50
|
end
|
|
47
51
|
end
|
|
48
52
|
|
|
49
|
-
|
|
53
|
+
def params
|
|
54
|
+
if super.nil?
|
|
55
|
+
{}
|
|
56
|
+
else
|
|
57
|
+
super.with_indifferent_access
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def message
|
|
62
|
+
ActionView::Base.new(
|
|
63
|
+
Rails.configuration.paths["app/views"]).render(
|
|
64
|
+
:template => self.class.views[:mobile_sdk][:template_path].call(self), :formats => [:html],
|
|
65
|
+
:locals => { :params => self.params}, :layout => false)
|
|
66
|
+
end
|
|
50
67
|
|
|
68
|
+
def mobile_message(length=115)
|
|
69
|
+
truncate(ActionView::Base.new(
|
|
70
|
+
Rails.configuration.paths["app/views"]).render(
|
|
71
|
+
:template => self.class.views[:mobile_sdk][:template_path].call(self), :formats => [:html],
|
|
72
|
+
:locals => { :params => self.params}, :layout => false), :length => length)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
## Public Interface
|
|
51
76
|
def to(user)
|
|
52
77
|
self.target = user
|
|
53
78
|
self
|
|
@@ -59,7 +84,7 @@ module NotifyUser
|
|
|
59
84
|
end
|
|
60
85
|
|
|
61
86
|
def notify!
|
|
62
|
-
save
|
|
87
|
+
save
|
|
63
88
|
|
|
64
89
|
# Bang version of 'notify' ignores aggregation
|
|
65
90
|
self.deliver!
|
|
@@ -68,29 +93,35 @@ module NotifyUser
|
|
|
68
93
|
# Send any Emails/SMS/APNS
|
|
69
94
|
def notify
|
|
70
95
|
|
|
71
|
-
save
|
|
72
|
-
|
|
73
|
-
if self.class.aggregate_per
|
|
74
|
-
|
|
75
|
-
# Schedule to send later if there aren't already any scheduled.
|
|
76
|
-
# Otherwise ignore, as the already-scheduled aggregate job will pick this one up when it runs.
|
|
77
|
-
if not aggregation_pending?
|
|
96
|
+
save
|
|
78
97
|
|
|
79
|
-
|
|
80
|
-
|
|
98
|
+
#if aggregation is false bypass aggregation completely
|
|
99
|
+
self.channels.each do |channel_name, options|
|
|
100
|
+
if(options[:aggregate_per] == false)
|
|
101
|
+
self.class.delay.deliver_notification_channel(self.id, channel_name)
|
|
102
|
+
else
|
|
103
|
+
if not aggregation_pending?
|
|
104
|
+
self.class.delay_for(options[:aggregate_per] || self.aggregate_per).notify_aggregated_channel(self.id, channel_name)
|
|
105
|
+
end
|
|
81
106
|
end
|
|
82
|
-
else
|
|
83
|
-
# No aggregation, send immediately.
|
|
84
|
-
self.deliver
|
|
85
107
|
end
|
|
86
108
|
|
|
87
109
|
end
|
|
88
110
|
|
|
111
|
+
def generate_unsubscribe_hash
|
|
112
|
+
#check if a hash already exists for that user otherwise create a new one
|
|
113
|
+
return NotifyUser::UserHash.where(target_id: self.target.id).where(target_type: self.target.class.base_class).where(type: self.type).where(active: true).first || NotifyUser::UserHash.create(target: self.target, type: self.type, active: true)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
## Notification description
|
|
117
|
+
class_attribute :description
|
|
118
|
+
self.description = ""
|
|
119
|
+
|
|
89
120
|
## Channels
|
|
90
121
|
|
|
91
122
|
mattr_accessor :channels
|
|
92
123
|
@@channels = {
|
|
93
|
-
action_mailer: {}
|
|
124
|
+
action_mailer: {description: 'Email notifications'}
|
|
94
125
|
}
|
|
95
126
|
|
|
96
127
|
# Not sure about this. The JSON and web feeds don't fit into channels, because nothing is broadcast through
|
|
@@ -109,14 +140,14 @@ module NotifyUser
|
|
|
109
140
|
|
|
110
141
|
## Aggregation
|
|
111
142
|
|
|
112
|
-
|
|
113
|
-
|
|
143
|
+
class_attribute :aggregate_per
|
|
144
|
+
self.aggregate_per = 1.minute
|
|
114
145
|
|
|
115
146
|
## Sending
|
|
116
147
|
|
|
117
148
|
def self.for_target(target)
|
|
118
149
|
where(target_id: target.id)
|
|
119
|
-
.where(target_type: target.class.
|
|
150
|
+
.where(target_type: target.class.base_class)
|
|
120
151
|
end
|
|
121
152
|
|
|
122
153
|
def self.pending_aggregation_with(notification)
|
|
@@ -131,35 +162,88 @@ module NotifyUser
|
|
|
131
162
|
return (self.class.pending_aggregation_with(self).where('id != ?', id).count > 0)
|
|
132
163
|
end
|
|
133
164
|
|
|
134
|
-
def deliver
|
|
135
|
-
|
|
136
|
-
|
|
165
|
+
# def deliver
|
|
166
|
+
# unless user_has_unsubscribed?
|
|
167
|
+
# self.mark_as_sent
|
|
168
|
+
# self.save
|
|
137
169
|
|
|
138
|
-
|
|
139
|
-
end
|
|
170
|
+
# self.class.delay.deliver_channels(self.id)
|
|
171
|
+
# end
|
|
172
|
+
# end
|
|
140
173
|
|
|
141
174
|
def deliver!
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
175
|
+
unless user_has_unsubscribed?
|
|
176
|
+
self.mark_as_sent
|
|
177
|
+
self.save
|
|
178
|
+
self.class.deliver_channels(self.id)
|
|
179
|
+
end
|
|
145
180
|
end
|
|
146
181
|
|
|
147
182
|
# Deliver a single notification across each channel.
|
|
148
183
|
def self.deliver_channels(notification_id)
|
|
149
184
|
notification = self.where(id: notification_id).first
|
|
150
185
|
return unless notification
|
|
151
|
-
|
|
152
186
|
self.channels.each do |channel_name, options|
|
|
153
|
-
|
|
154
|
-
|
|
187
|
+
unless unsubscribed_from_channel?(notification.target, channel_name)
|
|
188
|
+
channel = (channel_name.to_s + "_channel").camelize.constantize
|
|
189
|
+
channel.deliver(notification, options)
|
|
190
|
+
end
|
|
155
191
|
end
|
|
156
192
|
end
|
|
157
193
|
|
|
158
194
|
# Deliver multiple notifications across each channel as an aggregate message.
|
|
159
195
|
def self.deliver_channels_aggregated(notifications)
|
|
160
196
|
self.channels.each do |channel_name, options|
|
|
161
|
-
|
|
162
|
-
|
|
197
|
+
if options[:aggregate_per] != false && !unsubscribed_from_channel?(notifications.first.target, channel_name)
|
|
198
|
+
channel = (channel_name.to_s + "_channel").camelize.constantize
|
|
199
|
+
channel.deliver_aggregated(notifications, options)
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
#deliver to specific channel methods
|
|
205
|
+
|
|
206
|
+
# Deliver a single notification to a specific channel.
|
|
207
|
+
def self.deliver_notification_channel(notification_id, channel_name)
|
|
208
|
+
notification = self.where(id: notification_id).first
|
|
209
|
+
return unless notification
|
|
210
|
+
channel_options = channels[channel_name.to_sym]
|
|
211
|
+
|
|
212
|
+
channel = (channel_name.to_s + "_channel").camelize.constantize
|
|
213
|
+
unless self.unsubscribed_from_channel?(notification.target, channel_name)
|
|
214
|
+
channel.deliver(notification, channel_options)
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# Deliver a aggregated notifications to a specific channel.
|
|
219
|
+
def self.deliver_notifications_channel(notifications, channel_name)
|
|
220
|
+
channel_options = channels[channel_name.to_sym]
|
|
221
|
+
channel = (channel_name.to_s + "_channel").camelize.constantize
|
|
222
|
+
|
|
223
|
+
#check if user unsubsribed from channel type
|
|
224
|
+
unless self.unsubscribed_from_channel?(notifications.first.target, channel_name)
|
|
225
|
+
channel.deliver_aggregated(notifications, channel_options)
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
#notifies a single channel for aggregation
|
|
230
|
+
def self.notify_aggregated_channel(notification_id, channel_name)
|
|
231
|
+
notification = self.find(notification_id) # Raise an exception if not found.
|
|
232
|
+
|
|
233
|
+
# Find any pending notifications with the same type and target, which can all be sent in one message.
|
|
234
|
+
notifications = self.pending_aggregation_with(notification)
|
|
235
|
+
|
|
236
|
+
notifications.map(&:mark_as_sent)
|
|
237
|
+
notifications.map(&:save)
|
|
238
|
+
|
|
239
|
+
return if notifications.empty?
|
|
240
|
+
|
|
241
|
+
if notifications.length == 1
|
|
242
|
+
# Despite waiting for more to aggregate, we only got one in the end.
|
|
243
|
+
self.deliver_notification_channel(notifications.first.id, channel_name)
|
|
244
|
+
else
|
|
245
|
+
# We got several notifications while waiting, send them aggregated.
|
|
246
|
+
self.deliver_notifications_channel(notifications, channel_name)
|
|
163
247
|
end
|
|
164
248
|
end
|
|
165
249
|
|
|
@@ -183,5 +267,25 @@ module NotifyUser
|
|
|
183
267
|
end
|
|
184
268
|
end
|
|
185
269
|
|
|
270
|
+
private
|
|
271
|
+
def unsubscribed_validation
|
|
272
|
+
errors.add(:target, (" has unsubscribed from this type")) if user_has_unsubscribed?
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def user_has_unsubscribed?
|
|
276
|
+
#return true if user has unsubscribed
|
|
277
|
+
return true unless NotifyUser::Unsubscribe.has_unsubscribed_from(self.target, self.type).empty?
|
|
278
|
+
|
|
279
|
+
return false
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def self.unsubscribed_from_channel?(user, type)
|
|
283
|
+
#return true if user has unsubscribed
|
|
284
|
+
return true unless NotifyUser::Unsubscribe.has_unsubscribed_from(user, type).empty?
|
|
285
|
+
|
|
286
|
+
return false
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
|
|
186
290
|
end
|
|
187
291
|
end
|