noticed 1.6.3 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,9 @@
|
|
1
|
+
module Noticed
|
2
|
+
class ApplicationJob < ActiveJob::Base
|
3
|
+
# Automatically retry jobs that encountered a deadlock
|
4
|
+
# retry_on ActiveRecord::Deadlocked
|
5
|
+
|
6
|
+
# Most jobs are safe to ignore if the underlying records are no longer available
|
7
|
+
discard_on ActiveJob::DeserializationError
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Noticed
|
2
|
+
class EventJob < ApplicationJob
|
3
|
+
queue_as :default
|
4
|
+
|
5
|
+
def perform(event)
|
6
|
+
# Enqueue bulk deliveries
|
7
|
+
event.bulk_delivery_methods.each do |_, deliver_by|
|
8
|
+
deliver_by.perform_later(event)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Enqueue individual deliveries
|
12
|
+
event.notifications.each do |notification|
|
13
|
+
event.delivery_methods.each do |_, deliver_by|
|
14
|
+
deliver_by.perform_later(notification)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Noticed
|
2
|
+
module Deliverable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
class_attribute :bulk_delivery_methods, instance_writer: false, default: {}
|
7
|
+
class_attribute :delivery_methods, instance_writer: false, default: {}
|
8
|
+
class_attribute :required_param_names, instance_writer: false, default: []
|
9
|
+
|
10
|
+
attribute :params, default: {}
|
11
|
+
|
12
|
+
if Rails.gem_version >= Gem::Version.new("7.1.0.alpha")
|
13
|
+
serialize :params, coder: Coder
|
14
|
+
else
|
15
|
+
serialize :params, Coder
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class_methods do
|
20
|
+
def inherited(base)
|
21
|
+
base.bulk_delivery_methods = bulk_delivery_methods.dup
|
22
|
+
base.delivery_methods = delivery_methods.dup
|
23
|
+
base.required_param_names = required_param_names.dup
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
def bulk_deliver_by(name, options = {})
|
28
|
+
raise NameError, "#{name} has already been used for this Notifier." if bulk_delivery_methods.has_key?(name)
|
29
|
+
|
30
|
+
config = ActiveSupport::OrderedOptions.new.merge(options)
|
31
|
+
yield config if block_given?
|
32
|
+
bulk_delivery_methods[name] = DeliverBy.new(name, config, bulk: true)
|
33
|
+
end
|
34
|
+
|
35
|
+
def deliver_by(name, options = {})
|
36
|
+
raise NameError, "#{name} has already been used for this Notifier." if delivery_methods.has_key?(name)
|
37
|
+
|
38
|
+
config = ActiveSupport::OrderedOptions.new.merge(options)
|
39
|
+
yield config if block_given?
|
40
|
+
delivery_methods[name] = DeliverBy.new(name, config)
|
41
|
+
end
|
42
|
+
|
43
|
+
def required_params(*names)
|
44
|
+
required_param_names.concat names
|
45
|
+
end
|
46
|
+
alias_method :required_param, :required_params
|
47
|
+
|
48
|
+
def with(params)
|
49
|
+
record = params.delete(:record)
|
50
|
+
new(params: params, record: record)
|
51
|
+
end
|
52
|
+
|
53
|
+
def deliver(recipients = nil, options = {})
|
54
|
+
new.deliver(recipients, options)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# CommentNotifier.deliver(User.all)
|
59
|
+
# CommentNotifier.deliver(User.all, priority: 10)
|
60
|
+
# CommentNotifier.deliver(User.all, queue: :low_priority)
|
61
|
+
# CommentNotifier.deliver(User.all, wait: 5.minutes)
|
62
|
+
# CommentNotifier.deliver(User.all, wait_until: 1.hour.from_now)
|
63
|
+
def deliver(recipients = nil, options = {})
|
64
|
+
validate!
|
65
|
+
|
66
|
+
transaction do
|
67
|
+
save!
|
68
|
+
|
69
|
+
recipients_attributes = Array.wrap(recipients).map do |recipient|
|
70
|
+
recipient_attributes_for(recipient)
|
71
|
+
end
|
72
|
+
|
73
|
+
if Rails.gem_version >= Gem::Version.new("7.0.0.alpha1")
|
74
|
+
notifications.insert_all!(recipients_attributes, record_timestamps: true) if recipients_attributes.any?
|
75
|
+
else
|
76
|
+
time = Time.current
|
77
|
+
recipients_attributes.each do |attributes|
|
78
|
+
attributes[:created_at] = time
|
79
|
+
attributes[:updated_at] = time
|
80
|
+
end
|
81
|
+
notifications.insert_all!(recipients_attributes) if recipients_attributes.any?
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Enqueue delivery job
|
86
|
+
EventJob.set(options).perform_later(self)
|
87
|
+
|
88
|
+
self
|
89
|
+
end
|
90
|
+
|
91
|
+
def recipient_attributes_for(recipient)
|
92
|
+
{
|
93
|
+
type: "#{self.class.name}::Notification",
|
94
|
+
recipient_type: recipient.class.name,
|
95
|
+
recipient_id: recipient.id
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
def validate!
|
100
|
+
validate_params!
|
101
|
+
validate_delivery_methods!
|
102
|
+
end
|
103
|
+
|
104
|
+
def validate_params!
|
105
|
+
required_param_names.each do |param_name|
|
106
|
+
raise ValidationError, "Param `#{param_name}` is required for #{self.class.name}." unless params[param_name].present?
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def validate_delivery_methods!
|
111
|
+
bulk_delivery_methods.values.each(&:validate!)
|
112
|
+
delivery_methods.values.each(&:validate!)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Noticed
|
2
|
+
module NotificationMethods
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
class_methods do
|
6
|
+
# Generate a Notification class each time a Notifier is defined
|
7
|
+
def inherited(notifier)
|
8
|
+
super
|
9
|
+
notifier.const_set :Notification, Class.new(Noticed::Notification)
|
10
|
+
end
|
11
|
+
|
12
|
+
def notification_methods(&block)
|
13
|
+
const_get(:Notification).class_eval(&block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Noticed
|
2
|
+
module Readable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
scope :read, -> { where.not(read_at: nil) }
|
7
|
+
scope :unread, -> { where(read_at: nil) }
|
8
|
+
scope :seen, -> { where.not(seen_at: nil) }
|
9
|
+
scope :unseen, -> { where(seen_at: nil) }
|
10
|
+
end
|
11
|
+
|
12
|
+
class_methods do
|
13
|
+
def mark_as_read
|
14
|
+
update_all(read_at: Time.current)
|
15
|
+
end
|
16
|
+
|
17
|
+
def mark_as_unread
|
18
|
+
update_all(read_at: nil)
|
19
|
+
end
|
20
|
+
|
21
|
+
def mark_as_seen
|
22
|
+
update_all(seen_at: Time.current)
|
23
|
+
end
|
24
|
+
|
25
|
+
def mark_as_unseen
|
26
|
+
update_all(seen_at: nil)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def mark_as_read
|
31
|
+
update(read_at: Time.current)
|
32
|
+
end
|
33
|
+
|
34
|
+
def mark_as_read!
|
35
|
+
update!(read_at: Time.current)
|
36
|
+
end
|
37
|
+
|
38
|
+
def mark_as_unread
|
39
|
+
update(read_at: nil)
|
40
|
+
end
|
41
|
+
|
42
|
+
def mark_as_unread!
|
43
|
+
update!(read_at: nil)
|
44
|
+
end
|
45
|
+
|
46
|
+
def mark_as_seen
|
47
|
+
update(seen_at: Time.current)
|
48
|
+
end
|
49
|
+
|
50
|
+
def mark_as_seen!
|
51
|
+
update!(seen_at: Time.current)
|
52
|
+
end
|
53
|
+
|
54
|
+
def mark_as_unseen
|
55
|
+
update(seen_at: nil)
|
56
|
+
end
|
57
|
+
|
58
|
+
def mark_as_unseen!
|
59
|
+
update!(seen_at: nil)
|
60
|
+
end
|
61
|
+
|
62
|
+
def read?
|
63
|
+
read_at?
|
64
|
+
end
|
65
|
+
|
66
|
+
def unread?
|
67
|
+
!read_at?
|
68
|
+
end
|
69
|
+
|
70
|
+
def seen?
|
71
|
+
seen_at?
|
72
|
+
end
|
73
|
+
|
74
|
+
def unseen?
|
75
|
+
!seen_at?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Noticed
|
2
|
+
module Deliverable
|
3
|
+
class DeliverBy
|
4
|
+
attr_reader :name, :config, :bulk
|
5
|
+
|
6
|
+
def initialize(name, config, bulk: false)
|
7
|
+
@name, @config, @bulk, = name, config, bulk
|
8
|
+
end
|
9
|
+
|
10
|
+
def constant
|
11
|
+
namespace = bulk ? "Noticed::BulkDeliveryMethods" : "Noticed::DeliveryMethods"
|
12
|
+
config.fetch(:class, [namespace, name.to_s.camelize].join("::")).constantize
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate!
|
16
|
+
constant.required_option_names.each do |option|
|
17
|
+
raise ValidationError, "option `#{option}` must be set for `deliver_by :#{name}`" unless config[option].present?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def perform_later(event_or_notification, options = {})
|
22
|
+
options[:wait] = evaluate_option(:wait, event_or_notification) if config.has_key?(:wait)
|
23
|
+
options[:wait_until] = evaluate_option(:wait_until, event_or_notification) if config.has_key?(:wait_until)
|
24
|
+
options[:queue] = evaluate_option(:queue, event_or_notification) if config.has_key?(:queue)
|
25
|
+
options[:priority] = evaluate_option(:priority, event_or_notification) if config.has_key?(:priority)
|
26
|
+
|
27
|
+
constant.set(options).perform_later(name, event_or_notification)
|
28
|
+
end
|
29
|
+
|
30
|
+
def evaluate_option(name, context)
|
31
|
+
option = config[name]
|
32
|
+
|
33
|
+
if option&.respond_to?(:call)
|
34
|
+
context.instance_exec(&option)
|
35
|
+
elsif option.is_a?(Symbol) && context.respond_to?(option)
|
36
|
+
context.send(option)
|
37
|
+
else
|
38
|
+
option
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Noticed
|
2
|
+
class Event < ApplicationRecord
|
3
|
+
include Deliverable
|
4
|
+
include NotificationMethods
|
5
|
+
include Translation
|
6
|
+
include Rails.application.routes.url_helpers
|
7
|
+
|
8
|
+
belongs_to :record, polymorphic: true, optional: true
|
9
|
+
has_many :notifications, dependent: :delete_all
|
10
|
+
|
11
|
+
accepts_nested_attributes_for :notifications
|
12
|
+
|
13
|
+
scope :newest_first, -> { order(created_at: :desc) }
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Noticed
|
2
|
+
class Notification < ApplicationRecord
|
3
|
+
include Rails.application.routes.url_helpers
|
4
|
+
include Readable
|
5
|
+
include Translation
|
6
|
+
|
7
|
+
belongs_to :event
|
8
|
+
belongs_to :recipient, polymorphic: true
|
9
|
+
|
10
|
+
scope :newest_first, -> { order(created_at: :desc) }
|
11
|
+
|
12
|
+
delegate :params, :record, to: :event
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class CreateNoticedTables < ActiveRecord::Migration[6.1]
|
2
|
+
def change
|
3
|
+
create_table :noticed_events do |t|
|
4
|
+
t.string :type
|
5
|
+
t.belongs_to :record, polymorphic: true
|
6
|
+
if t.respond_to?(:jsonb)
|
7
|
+
t.jsonb :params
|
8
|
+
else
|
9
|
+
t.json :params
|
10
|
+
end
|
11
|
+
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
|
15
|
+
create_table :noticed_notifications do |t|
|
16
|
+
t.string :type
|
17
|
+
t.belongs_to :event, null: false
|
18
|
+
t.belongs_to :recipient, polymorphic: true, null: false
|
19
|
+
t.datetime :read_at
|
20
|
+
t.datetime :seen_at
|
21
|
+
|
22
|
+
t.timestamps
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -12,7 +12,7 @@ module Noticed
|
|
12
12
|
desc "Generates a class for a custom delivery method with the given NAME."
|
13
13
|
|
14
14
|
def generate_notification
|
15
|
-
template "delivery_method.rb", "app/
|
15
|
+
template "delivery_method.rb", "app/notifiers/delivery_methods/#{singular_name}.rb"
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Noticed
|
4
|
+
module Generators
|
5
|
+
class ModelGenerator < Rails::Generators::Base
|
6
|
+
include Rails::Generators::ResourceHelpers
|
7
|
+
|
8
|
+
source_root File.expand_path("../templates", __FILE__)
|
9
|
+
|
10
|
+
def create_migrations
|
11
|
+
rails_command "railties:install:migrations FROM=noticed", inline: true
|
12
|
+
end
|
13
|
+
|
14
|
+
def done
|
15
|
+
readme "README" if behavior == :invoke
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -4,7 +4,7 @@ require "rails/generators/named_base"
|
|
4
4
|
|
5
5
|
module Noticed
|
6
6
|
module Generators
|
7
|
-
class
|
7
|
+
class NotifierGenerator < Rails::Generators::NamedBase
|
8
8
|
include Rails::Generators::ResourceHelpers
|
9
9
|
|
10
10
|
source_root File.expand_path("../templates", __FILE__)
|
@@ -12,7 +12,7 @@ module Noticed
|
|
12
12
|
desc "Generates a notification with the given NAME."
|
13
13
|
|
14
14
|
def generate_notification
|
15
|
-
template "
|
15
|
+
template "notifier.rb", "app/notifiers/#{file_path}.rb"
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
|
2
|
-
🚚
|
2
|
+
🚚 You're ready to start sending notifications!
|
3
3
|
|
4
4
|
Next steps:
|
5
|
-
1. Run
|
6
|
-
2. Add
|
7
|
-
|
5
|
+
1. Run `rails db:migrate`
|
6
|
+
2. Add `has_many :notifications, as: :recipient, dependent: :destroy, class_name: "Noticed::Notification"` to your User model(s).
|
7
|
+
2. Add `has_many :notifications, as: :record, dependent: :destroy, class_name: "Noticed::Event"` to your model(s) that notifications reference.
|
8
|
+
3. Generate notifiers with "rails g noticed:notifier"
|
@@ -1,12 +1,8 @@
|
|
1
|
-
class DeliveryMethods::<%= class_name %> < Noticed::
|
1
|
+
class DeliveryMethods::<%= class_name %> < Noticed::DeliveryMethod
|
2
|
+
# Specify the config options your delivery method requires in its config block
|
3
|
+
required_options # :foo, :bar
|
4
|
+
|
2
5
|
def deliver
|
3
6
|
# Logic for sending the notification
|
4
7
|
end
|
5
|
-
|
6
|
-
# You may override this method to validate options for the delivery method
|
7
|
-
# Invalid options should raise a ValidationError
|
8
|
-
#
|
9
|
-
# def self.validate!(options)
|
10
|
-
# raise ValidationError, "required_option missing" unless options[:required_option]
|
11
|
-
# end
|
12
8
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# To deliver this notification:
|
2
|
+
#
|
3
|
+
# <%= class_name %>.with(record: @post, message: "New post").deliver(User.all)
|
4
|
+
|
5
|
+
class <%= class_name %> < Noticed::Event
|
6
|
+
# Add your delivery methods
|
7
|
+
#
|
8
|
+
# deliver_by :email do |config|
|
9
|
+
# config.mailer = "UserMailer"
|
10
|
+
# config.method = "new_post"
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# bulk_deliver_by :slack do |config|
|
14
|
+
# config.url = -> { Rails.application.credentials.slack_webhook_url }
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# deliver_by :custom do |config|
|
18
|
+
# config.class = "MyDeliveryMethod"
|
19
|
+
# end
|
20
|
+
|
21
|
+
# Add required params
|
22
|
+
#
|
23
|
+
# required_param :message
|
24
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "net/http"
|
2
|
+
|
3
|
+
module Noticed
|
4
|
+
module ApiClient
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
# Helper method for making POST requests from delivery methods
|
8
|
+
#
|
9
|
+
# Usage:
|
10
|
+
# post_request("http://example.com", basic_auth: {user:, pass:}, headers: {}, json: {}, form: {})
|
11
|
+
#
|
12
|
+
def post_request(url, args = {})
|
13
|
+
args.compact!
|
14
|
+
|
15
|
+
uri = URI(url)
|
16
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
17
|
+
http.use_ssl = true if uri.instance_of? URI::HTTPS
|
18
|
+
|
19
|
+
headers = args.delete(:headers) || {}
|
20
|
+
headers["Content-Type"] = "application/json" if args.has_key?(:json)
|
21
|
+
|
22
|
+
request = Net::HTTP::Post.new(uri.request_uri, headers)
|
23
|
+
|
24
|
+
if (basic_auth = args.delete(:basic_auth))
|
25
|
+
request.basic_auth basic_auth.fetch(:user), basic_auth.fetch(:pass)
|
26
|
+
end
|
27
|
+
|
28
|
+
if (json = args.delete(:json))
|
29
|
+
request.body = json.to_json
|
30
|
+
elsif (form = args.delete(:form))
|
31
|
+
request.set_form(form, "multipart/form-data")
|
32
|
+
end
|
33
|
+
|
34
|
+
logger.debug("POST #{url}")
|
35
|
+
logger.debug(request.body)
|
36
|
+
response = http.request(request)
|
37
|
+
logger.debug("Response: #{response.code}: #{response.body.inspect}")
|
38
|
+
|
39
|
+
raise ResponseUnsuccessful.new(response, url, args) unless response.code.start_with?("20")
|
40
|
+
|
41
|
+
response
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Noticed
|
2
|
+
class BulkDeliveryMethod < ApplicationJob
|
3
|
+
include ApiClient
|
4
|
+
include RequiredOptions
|
5
|
+
|
6
|
+
class_attribute :logger, default: Rails.logger
|
7
|
+
|
8
|
+
attr_reader :config, :event
|
9
|
+
|
10
|
+
def perform(delivery_method_name, event)
|
11
|
+
@event = event
|
12
|
+
@config = event.bulk_delivery_methods.fetch(delivery_method_name).config
|
13
|
+
|
14
|
+
return false if config.has_key?(:if) && !evaluate_option(:if)
|
15
|
+
return false if config.has_key?(:unless) && evaluate_option(:unless)
|
16
|
+
|
17
|
+
deliver
|
18
|
+
end
|
19
|
+
|
20
|
+
def deliver
|
21
|
+
raise NotImplementedError, "Bulk delivery methods must implement the `deliver` method"
|
22
|
+
end
|
23
|
+
|
24
|
+
def fetch_constant(name)
|
25
|
+
option = config[name]
|
26
|
+
option.is_a?(String) ? option.constantize : option
|
27
|
+
end
|
28
|
+
|
29
|
+
def evaluate_option(name)
|
30
|
+
option = config[name]
|
31
|
+
|
32
|
+
# Evaluate Proc within the context of the notifier
|
33
|
+
if option&.respond_to?(:call)
|
34
|
+
event.instance_exec(&option)
|
35
|
+
|
36
|
+
# Call method if symbol and matching method
|
37
|
+
elsif option.is_a?(Symbol) && event.respond_to?(option)
|
38
|
+
event.send(option)
|
39
|
+
|
40
|
+
# Return the value
|
41
|
+
else
|
42
|
+
option
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Noticed
|
2
|
+
module BulkDeliveryMethods
|
3
|
+
class Slack < BulkDeliveryMethod
|
4
|
+
DEFAULT_URL = "https://slack.com/api/chat.postMessage"
|
5
|
+
|
6
|
+
required_options :json
|
7
|
+
|
8
|
+
def deliver
|
9
|
+
post_request url, headers: evaluate_option(:headers), json: evaluate_option(:json)
|
10
|
+
end
|
11
|
+
|
12
|
+
def url
|
13
|
+
evaluate_option(:url) || DEFAULT_URL
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Noticed
|
2
|
+
module BulkDeliveryMethods
|
3
|
+
class Webhook < BulkDeliveryMethod
|
4
|
+
required_options :url
|
5
|
+
|
6
|
+
def deliver
|
7
|
+
Rails.logger.debug(evaluate_option(:json))
|
8
|
+
post_request(
|
9
|
+
evaluate_option(:url),
|
10
|
+
basic_auth: evaluate_option(:basic_auth),
|
11
|
+
headers: evaluate_option(:headers),
|
12
|
+
json: evaluate_option(:json),
|
13
|
+
form: evaluate_option(:form)
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/noticed/coder.rb
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Noticed
|
2
|
+
class DeliveryMethod < ApplicationJob
|
3
|
+
include ApiClient
|
4
|
+
include RequiredOptions
|
5
|
+
|
6
|
+
class_attribute :logger, default: Rails.logger
|
7
|
+
|
8
|
+
attr_reader :config, :event, :notification
|
9
|
+
delegate :recipient, to: :notification
|
10
|
+
delegate :record, :params, to: :event
|
11
|
+
|
12
|
+
def perform(delivery_method_name, notification, overrides: {})
|
13
|
+
@notification = notification
|
14
|
+
@event = notification.event
|
15
|
+
|
16
|
+
# Look up config from Notifier and merge overrides
|
17
|
+
@config = event.delivery_methods.fetch(delivery_method_name).config.merge(overrides)
|
18
|
+
|
19
|
+
return false if config.has_key?(:if) && !evaluate_option(:if)
|
20
|
+
return false if config.has_key?(:unless) && evaluate_option(:unless)
|
21
|
+
|
22
|
+
deliver
|
23
|
+
end
|
24
|
+
|
25
|
+
def deliver
|
26
|
+
raise NotImplementedError, "Delivery methods must implement the `deliver` method"
|
27
|
+
end
|
28
|
+
|
29
|
+
def fetch_constant(name)
|
30
|
+
option = config[name]
|
31
|
+
option.is_a?(String) ? option.constantize : option
|
32
|
+
end
|
33
|
+
|
34
|
+
def evaluate_option(name)
|
35
|
+
option = config[name]
|
36
|
+
|
37
|
+
# Evaluate Proc within the context of the Notification
|
38
|
+
if option&.respond_to?(:call)
|
39
|
+
notification.instance_exec(&option)
|
40
|
+
|
41
|
+
# Call method if symbol and matching method on Notifier
|
42
|
+
elsif option.is_a?(Symbol) && event.respond_to?(option)
|
43
|
+
event.send(option, self)
|
44
|
+
|
45
|
+
# Return the value
|
46
|
+
else
|
47
|
+
option
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|