noticed 1.6.3 → 2.0.1
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/README.md +269 -237
- data/app/jobs/noticed/application_job.rb +9 -0
- data/app/jobs/noticed/event_job.rb +19 -0
- data/app/models/concerns/noticed/deliverable.rb +115 -0
- data/app/models/concerns/noticed/notification_methods.rb +17 -0
- data/app/models/concerns/noticed/readable.rb +78 -0
- data/app/models/noticed/application_record.rb +6 -0
- data/app/models/noticed/deliverable/deliver_by.rb +43 -0
- data/app/models/noticed/event.rb +15 -0
- data/app/models/noticed/notification.rb +14 -0
- data/db/migrate/20231215190233_create_noticed_tables.rb +25 -0
- data/lib/generators/noticed/delivery_method_generator.rb +1 -1
- data/lib/generators/noticed/install_generator.rb +19 -0
- data/lib/generators/noticed/{notification_generator.rb → notifier_generator.rb} +2 -2
- data/lib/generators/noticed/templates/README +5 -4
- data/lib/generators/noticed/templates/delivery_method.rb.tt +4 -8
- data/lib/generators/noticed/templates/notifier.rb.tt +24 -0
- data/lib/noticed/api_client.rb +44 -0
- data/lib/noticed/bulk_delivery_method.rb +46 -0
- data/lib/noticed/bulk_delivery_methods/discord.rb +11 -0
- data/lib/noticed/bulk_delivery_methods/slack.rb +17 -0
- data/lib/noticed/bulk_delivery_methods/webhook.rb +18 -0
- data/lib/noticed/coder.rb +2 -0
- data/lib/noticed/delivery_method.rb +51 -0
- data/lib/noticed/delivery_methods/action_cable.rb +7 -39
- data/lib/noticed/delivery_methods/discord.rb +11 -0
- data/lib/noticed/delivery_methods/email.rb +13 -45
- data/lib/noticed/delivery_methods/fcm.rb +23 -64
- data/lib/noticed/delivery_methods/ios.rb +25 -112
- data/lib/noticed/delivery_methods/microsoft_teams.rb +5 -22
- data/lib/noticed/delivery_methods/slack.rb +6 -16
- data/lib/noticed/delivery_methods/test.rb +2 -12
- data/lib/noticed/delivery_methods/twilio_messaging.rb +37 -0
- data/lib/noticed/delivery_methods/vonage_sms.rb +20 -0
- data/lib/noticed/delivery_methods/webhook.rb +17 -0
- data/lib/noticed/engine.rb +1 -9
- data/lib/noticed/required_options.rb +21 -0
- data/lib/noticed/translation.rb +7 -3
- data/lib/noticed/version.rb +1 -1
- data/lib/noticed.rb +30 -15
- metadata +29 -40
- data/lib/generators/noticed/model/base_generator.rb +0 -47
- data/lib/generators/noticed/model/mysql_generator.rb +0 -18
- data/lib/generators/noticed/model/postgresql_generator.rb +0 -18
- data/lib/generators/noticed/model/sqlite3_generator.rb +0 -18
- data/lib/generators/noticed/model_generator.rb +0 -63
- data/lib/generators/noticed/templates/notification.rb.tt +0 -27
- data/lib/noticed/base.rb +0 -160
- data/lib/noticed/delivery_methods/base.rb +0 -95
- data/lib/noticed/delivery_methods/database.rb +0 -34
- data/lib/noticed/delivery_methods/twilio.rb +0 -51
- data/lib/noticed/delivery_methods/vonage.rb +0 -40
- data/lib/noticed/has_notifications.rb +0 -49
- data/lib/noticed/model.rb +0 -85
- data/lib/noticed/notification_channel.rb +0 -15
- data/lib/noticed/text_coder.rb +0 -16
- data/lib/rails_6_polyfills/actioncable/test_adapter.rb +0 -70
- data/lib/rails_6_polyfills/actioncable/test_helper.rb +0 -143
- data/lib/rails_6_polyfills/activejob/serializers.rb +0 -240
- data/lib/rails_6_polyfills/base.rb +0 -18
- data/lib/tasks/noticed_tasks.rake +0 -4
@@ -1,46 +1,14 @@
|
|
1
1
|
module Noticed
|
2
2
|
module DeliveryMethods
|
3
|
-
class ActionCable <
|
4
|
-
|
5
|
-
channel.broadcast_to stream, format
|
6
|
-
end
|
3
|
+
class ActionCable < DeliveryMethod
|
4
|
+
required_options :channel, :stream, :message
|
7
5
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
notification.send(method)
|
13
|
-
else
|
14
|
-
notification.params
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def channel
|
19
|
-
@channel ||= begin
|
20
|
-
value = options[:channel]
|
21
|
-
case value
|
22
|
-
when String
|
23
|
-
value.constantize
|
24
|
-
when Symbol
|
25
|
-
notification.send(value)
|
26
|
-
when Class
|
27
|
-
value
|
28
|
-
else
|
29
|
-
Noticed::NotificationChannel
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
6
|
+
def deliver
|
7
|
+
channel = fetch_constant(:channel)
|
8
|
+
stream = evaluate_option(:stream)
|
9
|
+
message = evaluate_option(:message)
|
33
10
|
|
34
|
-
|
35
|
-
value = options[:stream]
|
36
|
-
case value
|
37
|
-
when String
|
38
|
-
value
|
39
|
-
when Symbol
|
40
|
-
notification.send(value)
|
41
|
-
else
|
42
|
-
recipient
|
43
|
-
end
|
11
|
+
channel.broadcast_to stream, message
|
44
12
|
end
|
45
13
|
end
|
46
14
|
end
|
@@ -1,54 +1,22 @@
|
|
1
1
|
module Noticed
|
2
2
|
module DeliveryMethods
|
3
|
-
class Email <
|
4
|
-
|
3
|
+
class Email < DeliveryMethod
|
4
|
+
required_options :mailer, :method
|
5
5
|
|
6
6
|
def deliver
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
mailer = fetch_constant(:mailer)
|
8
|
+
email = evaluate_option(:method)
|
9
|
+
args = evaluate_option(:args) || []
|
10
|
+
mail = mailer.with(params).send(email, *args)
|
11
|
+
(!!evaluate_option(:enqueue)) ? mail.deliver_later : mail.deliver_now
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
option = options.fetch(:mailer)
|
21
|
-
case option
|
22
|
-
when String
|
23
|
-
option.constantize
|
24
|
-
when Symbol
|
25
|
-
notification.send(option)
|
26
|
-
else
|
27
|
-
option
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# Method should be a symbol
|
32
|
-
#
|
33
|
-
# If notification responds to symbol, call that method and use return value
|
34
|
-
# If notification does not respond to symbol, use the symbol for the mailer method
|
35
|
-
# Otherwise, use the underscored notification class name as the mailer method
|
36
|
-
def mailer_method
|
37
|
-
method_name = options[:method]&.to_sym
|
38
|
-
if method_name.present?
|
39
|
-
notification.respond_to?(method_name) ? notification.send(method_name) : method_name
|
40
|
-
else
|
41
|
-
notification.class.name.underscore
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def format
|
46
|
-
params = if (method = options[:format])
|
47
|
-
notification.send(method)
|
48
|
-
else
|
49
|
-
notification.params
|
50
|
-
end
|
51
|
-
params.merge(recipient: recipient, record: record)
|
14
|
+
def params
|
15
|
+
(evaluate_option(:params) || notification&.params || {}).merge(
|
16
|
+
notification: notification,
|
17
|
+
record: notification&.record,
|
18
|
+
recipient: notification&.recipient
|
19
|
+
)
|
52
20
|
end
|
53
21
|
end
|
54
22
|
end
|
@@ -1,95 +1,54 @@
|
|
1
1
|
require "googleauth"
|
2
2
|
|
3
|
-
# class CommentNotifier
|
4
|
-
# deliver_by :fcm, credentials: Rails.root.join("config/certs/fcm.json"), format: :format_notification
|
5
|
-
#
|
6
|
-
# deliver_by :fcm, credentials: :fcm_credentials
|
7
|
-
# def fcm_credentials
|
8
|
-
# { project_id: "api-12345" }
|
9
|
-
# end
|
10
|
-
# end
|
11
|
-
|
12
3
|
module Noticed
|
13
4
|
module DeliveryMethods
|
14
|
-
class Fcm <
|
15
|
-
|
16
|
-
|
17
|
-
option :format
|
5
|
+
class Fcm < DeliveryMethod
|
6
|
+
required_option :credentials, :device_tokens, :json
|
18
7
|
|
19
8
|
def deliver
|
20
|
-
device_tokens.each do |device_token|
|
21
|
-
|
22
|
-
rescue ResponseUnsuccessful => exception
|
23
|
-
if exception.response.code == 404
|
24
|
-
cleanup_invalid_token(device_token)
|
25
|
-
else
|
26
|
-
raise
|
27
|
-
end
|
9
|
+
evaluate_option(:device_tokens).each do |device_token|
|
10
|
+
send_notification device_token
|
28
11
|
end
|
29
12
|
end
|
30
13
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
14
|
+
def send_notification(device_token)
|
15
|
+
post_request("https://fcm.googleapis.com/v1/projects/#{credentials[:project_id]}/messages:send",
|
16
|
+
headers: {authorization: "Bearer #{access_token}"},
|
17
|
+
json: notification.instance_exec(device_token, &config[:json]))
|
18
|
+
rescue Noticed::ResponseUnsuccessful => exception
|
19
|
+
if exception.response.code == "404" && config[:invalid_token]
|
20
|
+
notification.instance_exec(device_token, &config[:invalid_token])
|
21
|
+
else
|
22
|
+
raise
|
23
|
+
end
|
34
24
|
end
|
35
25
|
|
36
26
|
def credentials
|
37
27
|
@credentials ||= begin
|
38
|
-
|
39
|
-
|
28
|
+
value = evaluate_option(:credentials)
|
29
|
+
case value
|
40
30
|
when Hash
|
41
|
-
|
31
|
+
value
|
42
32
|
when Pathname
|
43
|
-
load_json(
|
33
|
+
load_json(value)
|
44
34
|
when String
|
45
|
-
load_json(Rails.root.join(
|
46
|
-
when Symbol
|
47
|
-
notification.send(option)
|
35
|
+
load_json(Rails.root.join(value))
|
48
36
|
else
|
49
|
-
|
37
|
+
raise ArgumentError, "FCM credentials must be a Hash, String, Pathname, or Symbol"
|
50
38
|
end
|
51
|
-
|
52
|
-
credentials_hash.symbolize_keys
|
53
39
|
end
|
54
40
|
end
|
55
41
|
|
56
42
|
def load_json(path)
|
57
|
-
JSON.parse(File.read(path))
|
58
|
-
end
|
59
|
-
|
60
|
-
def project_id
|
61
|
-
credentials[:project_id]
|
43
|
+
JSON.parse(File.read(path), symbolize_names: true)
|
62
44
|
end
|
63
45
|
|
64
46
|
def access_token
|
65
|
-
|
66
|
-
token["access_token"]
|
67
|
-
end
|
68
|
-
|
69
|
-
def authorizer
|
70
|
-
@authorizer ||= options.fetch(:authorizer, Google::Auth::ServiceAccountCredentials).make_creds(
|
47
|
+
@authorizer ||= (evaluate_option(:authorizer) || Google::Auth::ServiceAccountCredentials).make_creds(
|
71
48
|
json_key_io: StringIO.new(credentials.to_json),
|
72
49
|
scope: "https://www.googleapis.com/auth/firebase.messaging"
|
73
50
|
)
|
74
|
-
|
75
|
-
|
76
|
-
def format(device_token)
|
77
|
-
notification.send(options[:format], device_token)
|
78
|
-
end
|
79
|
-
|
80
|
-
def device_tokens
|
81
|
-
if notification.respond_to?(:fcm_device_tokens)
|
82
|
-
Array.wrap(notification.fcm_device_tokens(recipient))
|
83
|
-
else
|
84
|
-
raise NoMethodError, <<~MESSAGE
|
85
|
-
You must implement `fcm_device_tokens` to send Firebase Cloud Messaging notifications
|
86
|
-
|
87
|
-
# This must return an Array of FCM device tokens
|
88
|
-
def fcm_device_tokens(recipient)
|
89
|
-
recipient.fcm_device_tokens.pluck(:token)
|
90
|
-
end
|
91
|
-
MESSAGE
|
92
|
-
end
|
51
|
+
@authorizer.fetch_access_token!["access_token"]
|
93
52
|
end
|
94
53
|
end
|
95
54
|
end
|
@@ -2,26 +2,24 @@ require "apnotic"
|
|
2
2
|
|
3
3
|
module Noticed
|
4
4
|
module DeliveryMethods
|
5
|
-
class Ios <
|
6
|
-
cattr_accessor :
|
5
|
+
class Ios < DeliveryMethod
|
6
|
+
cattr_accessor :development_connection_pool, :production_connection_pool
|
7
|
+
|
8
|
+
required_options :bundle_identifier, :key_id, :team_id, :apns_key, :device_tokens
|
7
9
|
|
8
10
|
def deliver
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
raise ArgumentError, "Could not find APN cert at '#{cert_path}'" unless valid_cert_path?
|
11
|
+
evaluate_option(:device_tokens).each do |device_token|
|
12
|
+
apn = Apnotic::Notification.new(device_token)
|
13
|
+
format_notification(apn)
|
13
14
|
|
14
|
-
|
15
|
+
connection_pool = (!!evaluate_option(:development)) ? development_pool : production_pool
|
15
16
|
connection_pool.with do |connection|
|
16
|
-
apn = Apnotic::Notification.new(device_token)
|
17
|
-
format_notification(apn)
|
18
|
-
|
19
17
|
response = connection.push(apn)
|
20
18
|
raise "Timeout sending iOS push notification" unless response
|
21
19
|
|
22
|
-
if bad_token?(response)
|
20
|
+
if bad_token?(response) && config[:invalid_token]
|
23
21
|
# Allow notification to cleanup invalid iOS device tokens
|
24
|
-
|
22
|
+
notification.instance_exec(device_token, &config[:invalid_token])
|
25
23
|
elsif !response.ok?
|
26
24
|
raise "Request failed #{response.body}"
|
27
25
|
end
|
@@ -32,53 +30,37 @@ module Noticed
|
|
32
30
|
private
|
33
31
|
|
34
32
|
def format_notification(apn)
|
35
|
-
apn.topic = bundle_identifier
|
33
|
+
apn.topic = evaluate_option(:bundle_identifier)
|
36
34
|
|
37
|
-
if (method =
|
38
|
-
notification.
|
39
|
-
elsif params
|
40
|
-
apn.alert = params[:message]
|
35
|
+
if (method = config[:format])
|
36
|
+
notification.instance_exec(apn, &method)
|
37
|
+
elsif notification.params.try(:has_key?, :message)
|
38
|
+
apn.alert = notification.params[:message]
|
41
39
|
else
|
42
40
|
raise ArgumentError, "No message for iOS delivery. Either include message in params or add the 'format' option in 'deliver_by :ios'."
|
43
41
|
end
|
44
42
|
end
|
45
43
|
|
46
|
-
def device_tokens
|
47
|
-
if notification.respond_to?(:ios_device_tokens)
|
48
|
-
Array.wrap(notification.ios_device_tokens(recipient))
|
49
|
-
else
|
50
|
-
raise NoMethodError, <<~MESSAGE
|
51
|
-
You must implement `ios_device_tokens` to send iOS notifications
|
52
|
-
|
53
|
-
# This must return an Array of iOS device tokens
|
54
|
-
def ios_device_tokens(recipient)
|
55
|
-
recipient.ios_device_tokens.pluck(:token)
|
56
|
-
end
|
57
|
-
MESSAGE
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
44
|
def bad_token?(response)
|
62
45
|
response.status == "410" || (response.status == "400" && response.body["reason"] == "BadDeviceToken")
|
63
46
|
end
|
64
47
|
|
65
|
-
def
|
66
|
-
|
67
|
-
notification.send(:cleanup_device_token, token: token, platform: "iOS")
|
48
|
+
def development_pool
|
49
|
+
self.class.development_connection_pool ||= new_connection_pool(development: true)
|
68
50
|
end
|
69
51
|
|
70
|
-
def
|
71
|
-
self.class.
|
52
|
+
def production_pool
|
53
|
+
self.class.production_connection_pool ||= new_connection_pool(development: false)
|
72
54
|
end
|
73
55
|
|
74
|
-
def new_connection_pool
|
56
|
+
def new_connection_pool(development:)
|
75
57
|
handler = proc do |connection|
|
76
58
|
connection.on(:error) do |exception|
|
77
59
|
Rails.logger.info "Apnotic exception raised: #{exception}"
|
78
60
|
end
|
79
61
|
end
|
80
62
|
|
81
|
-
if development
|
63
|
+
if development
|
82
64
|
Apnotic::ConnectionPool.development(connection_pool_options, pool_options, &handler)
|
83
65
|
else
|
84
66
|
Apnotic::ConnectionPool.new(connection_pool_options, pool_options, &handler)
|
@@ -88,83 +70,14 @@ module Noticed
|
|
88
70
|
def connection_pool_options
|
89
71
|
{
|
90
72
|
auth_method: :token,
|
91
|
-
cert_path:
|
92
|
-
key_id: key_id,
|
93
|
-
team_id: team_id
|
73
|
+
cert_path: StringIO.new(config.fetch(:apns_key)),
|
74
|
+
key_id: config.fetch(:key_id),
|
75
|
+
team_id: config.fetch(:team_id)
|
94
76
|
}
|
95
77
|
end
|
96
78
|
|
97
|
-
def bundle_identifier
|
98
|
-
option = options[:bundle_identifier]
|
99
|
-
case option
|
100
|
-
when String
|
101
|
-
option
|
102
|
-
when Symbol
|
103
|
-
notification.send(option)
|
104
|
-
else
|
105
|
-
Rails.application.credentials.dig(:ios, :bundle_identifier)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def cert_path
|
110
|
-
option = options[:cert_path]
|
111
|
-
case option
|
112
|
-
when String
|
113
|
-
option
|
114
|
-
when Symbol
|
115
|
-
notification.send(option)
|
116
|
-
else
|
117
|
-
Rails.root.join("config/certs/ios/apns.p8")
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
def key_id
|
122
|
-
option = options[:key_id]
|
123
|
-
case option
|
124
|
-
when String
|
125
|
-
option
|
126
|
-
when Symbol
|
127
|
-
notification.send(option)
|
128
|
-
else
|
129
|
-
Rails.application.credentials.dig(:ios, :key_id)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def team_id
|
134
|
-
option = options[:team_id]
|
135
|
-
case option
|
136
|
-
when String
|
137
|
-
option
|
138
|
-
when Symbol
|
139
|
-
notification.send(option)
|
140
|
-
else
|
141
|
-
Rails.application.credentials.dig(:ios, :team_id)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def development?
|
146
|
-
option = options[:development]
|
147
|
-
case option
|
148
|
-
when Symbol
|
149
|
-
!!notification.send(option)
|
150
|
-
else
|
151
|
-
!!option
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def valid_cert_path?
|
156
|
-
case cert_path
|
157
|
-
when File, StringIO
|
158
|
-
cert_path.size > 0
|
159
|
-
else
|
160
|
-
File.exist?(cert_path)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
79
|
def pool_options
|
165
|
-
{
|
166
|
-
size: options.fetch(:pool_size, 5)
|
167
|
-
}
|
80
|
+
{size: evaluate_option(:pool_size) || 5}
|
168
81
|
end
|
169
82
|
end
|
170
83
|
end
|
@@ -1,31 +1,14 @@
|
|
1
1
|
module Noticed
|
2
2
|
module DeliveryMethods
|
3
|
-
class MicrosoftTeams <
|
4
|
-
|
5
|
-
post(url, json: format)
|
6
|
-
end
|
3
|
+
class MicrosoftTeams < DeliveryMethod
|
4
|
+
required_options :json
|
7
5
|
|
8
|
-
|
9
|
-
|
10
|
-
def format
|
11
|
-
if (method = options[:format])
|
12
|
-
notification.send(method)
|
13
|
-
else
|
14
|
-
{
|
15
|
-
title: notification.params[:title],
|
16
|
-
text: notification.params[:text],
|
17
|
-
sections: notification.params[:sections],
|
18
|
-
potentialAction: notification.params[:notification_action]
|
19
|
-
}
|
20
|
-
end
|
6
|
+
def deliver
|
7
|
+
post_request url, headers: evaluate_option(:headers), json: evaluate_option(:json)
|
21
8
|
end
|
22
9
|
|
23
10
|
def url
|
24
|
-
|
25
|
-
notification.send(method)
|
26
|
-
else
|
27
|
-
Rails.application.credentials.microsoft_teams[:notification_url]
|
28
|
-
end
|
11
|
+
evaluate_option(:url) || Rails.application.credentials.dig(:microsoft_teams, :notification_url)
|
29
12
|
end
|
30
13
|
end
|
31
14
|
end
|
@@ -1,26 +1,16 @@
|
|
1
1
|
module Noticed
|
2
2
|
module DeliveryMethods
|
3
|
-
class Slack <
|
4
|
-
|
5
|
-
post(url, json: format)
|
6
|
-
end
|
3
|
+
class Slack < DeliveryMethod
|
4
|
+
DEFAULT_URL = "https://slack.com/api/chat.postMessage"
|
7
5
|
|
8
|
-
|
6
|
+
required_options :json
|
9
7
|
|
10
|
-
def
|
11
|
-
|
12
|
-
notification.send(method)
|
13
|
-
else
|
14
|
-
notification.params
|
15
|
-
end
|
8
|
+
def deliver
|
9
|
+
post_request url, headers: evaluate_option(:headers), json: evaluate_option(:json)
|
16
10
|
end
|
17
11
|
|
18
12
|
def url
|
19
|
-
|
20
|
-
notification.send(method)
|
21
|
-
else
|
22
|
-
Rails.application.credentials.slack[:notification_url]
|
23
|
-
end
|
13
|
+
evaluate_option(:url) || DEFAULT_URL
|
24
14
|
end
|
25
15
|
end
|
26
16
|
end
|
@@ -1,20 +1,10 @@
|
|
1
1
|
module Noticed
|
2
2
|
module DeliveryMethods
|
3
|
-
class Test <
|
3
|
+
class Test < DeliveryMethod
|
4
4
|
class_attribute :delivered, default: []
|
5
|
-
class_attribute :callbacks, default: []
|
6
|
-
|
7
|
-
after_deliver do
|
8
|
-
self.class.callbacks << :after
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.clear!
|
12
|
-
delivered.clear
|
13
|
-
callbacks.clear
|
14
|
-
end
|
15
5
|
|
16
6
|
def deliver
|
17
|
-
|
7
|
+
delivered << notification
|
18
8
|
end
|
19
9
|
end
|
20
10
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Noticed
|
2
|
+
module DeliveryMethods
|
3
|
+
class TwilioMessaging < DeliveryMethod
|
4
|
+
def deliver
|
5
|
+
post_request url, basic_auth: {user: account_sid, pass: auth_token}, form: json
|
6
|
+
end
|
7
|
+
|
8
|
+
def json
|
9
|
+
evaluate_option(:json) || {
|
10
|
+
From: phone_number,
|
11
|
+
To: recipient.phone_number,
|
12
|
+
Body: params.fetch(:message)
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def url
|
17
|
+
evaluate_option(:url) || "https://api.twilio.com/2010-04-01/Accounts/#{account_sid}/Messages.json"
|
18
|
+
end
|
19
|
+
|
20
|
+
def account_sid
|
21
|
+
evaluate_option(:account_sid) || credentials.fetch(:account_sid)
|
22
|
+
end
|
23
|
+
|
24
|
+
def auth_token
|
25
|
+
evaluate_option(:auth_token) || credentials.fetch(:auth_token)
|
26
|
+
end
|
27
|
+
|
28
|
+
def phone_number
|
29
|
+
evaluate_option(:phone_number) || credentials.fetch(:phone_number)
|
30
|
+
end
|
31
|
+
|
32
|
+
def credentials
|
33
|
+
evaluate_option(:credentials) || Rails.application.credentials.twilio
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Noticed
|
2
|
+
module DeliveryMethods
|
3
|
+
class VonageSms < DeliveryMethod
|
4
|
+
DEFAULT_URL = "https://rest.nexmo.com/sms/json"
|
5
|
+
|
6
|
+
required_options :json
|
7
|
+
|
8
|
+
def deliver
|
9
|
+
headers = evaluate_option(:headers)
|
10
|
+
json = evaluate_option(:json)
|
11
|
+
response = post_request url, headers: headers, json: json
|
12
|
+
raise ResponseUnsuccessful.new(response, url, headers: headers, json: json) if JSON.parse(response.body).dig("messages", 0, "status") != "0"
|
13
|
+
end
|
14
|
+
|
15
|
+
def url
|
16
|
+
evaluate_option(:url) || DEFAULT_URL
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Noticed
|
2
|
+
module DeliveryMethods
|
3
|
+
class Webhook < DeliveryMethod
|
4
|
+
required_options :url
|
5
|
+
|
6
|
+
def deliver
|
7
|
+
post_request(
|
8
|
+
evaluate_option(:url),
|
9
|
+
basic_auth: evaluate_option(:basic_auth),
|
10
|
+
headers: evaluate_option(:headers),
|
11
|
+
json: evaluate_option(:json),
|
12
|
+
form: evaluate_option(:form)
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/noticed/engine.rb
CHANGED
@@ -1,13 +1,5 @@
|
|
1
1
|
module Noticed
|
2
2
|
class Engine < ::Rails::Engine
|
3
|
-
|
4
|
-
ActiveSupport.on_load(:active_record) do
|
5
|
-
include Noticed::HasNotifications
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
initializer "noticed.rails_5_2_support" do
|
10
|
-
require "rails_6_polyfills/base" if Rails::VERSION::MAJOR < 6
|
11
|
-
end
|
3
|
+
isolate_namespace Noticed
|
12
4
|
end
|
13
5
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Noticed
|
2
|
+
module RequiredOptions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
class_attribute :required_option_names, instance_writer: false, default: []
|
7
|
+
end
|
8
|
+
|
9
|
+
class_methods do
|
10
|
+
def inherited(base)
|
11
|
+
base.required_option_names = required_option_names.dup
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
def required_options(*names)
|
16
|
+
required_option_names.concat names
|
17
|
+
end
|
18
|
+
alias_method :required_option, :required_options
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/noticed/translation.rb
CHANGED
@@ -4,7 +4,7 @@ module Noticed
|
|
4
4
|
|
5
5
|
# Returns the +i18n_scope+ for the class. Overwrite if you want custom lookup.
|
6
6
|
def i18n_scope
|
7
|
-
:
|
7
|
+
:notifiers
|
8
8
|
end
|
9
9
|
|
10
10
|
def class_scope
|
@@ -12,13 +12,17 @@ module Noticed
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def translate(key, **options)
|
15
|
-
|
15
|
+
if defined?(::ActiveSupport::HtmlSafeTranslation)
|
16
|
+
ActiveSupport::HtmlSafeTranslation.translate scope_translation_key(key), **options
|
17
|
+
else
|
18
|
+
I18n.translate scope_translation_key(key), **options
|
19
|
+
end
|
16
20
|
end
|
17
21
|
alias_method :t, :translate
|
18
22
|
|
19
23
|
def scope_translation_key(key)
|
20
24
|
if key.to_s.start_with?(".")
|
21
|
-
|
25
|
+
[i18n_scope, class_scope].compact.join(".") + key
|
22
26
|
else
|
23
27
|
key
|
24
28
|
end
|