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
@@ -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
|