nuntius 0.1.1 → 1.0.27
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +199 -63
- data/Rakefile +62 -1
- data/app/controllers/nuntius/admin/campaigns_controller.rb +56 -0
- data/app/controllers/nuntius/admin/layouts/attachments_controller.rb +32 -0
- data/app/controllers/nuntius/admin/layouts_controller.rb +50 -0
- data/app/controllers/nuntius/admin/lists/subscribers_controller.rb +50 -0
- data/app/controllers/nuntius/admin/lists_controller.rb +46 -0
- data/app/controllers/nuntius/admin/locales_controller.rb +46 -0
- data/app/controllers/nuntius/admin/messages_controller.rb +24 -0
- data/app/controllers/nuntius/admin/templates_controller.rb +56 -0
- data/app/controllers/nuntius/api/events_controller.rb +16 -0
- data/app/controllers/nuntius/application_admin_controller.rb +11 -0
- data/app/controllers/nuntius/application_controller.rb +12 -0
- data/app/controllers/nuntius/callbacks_controller.rb +21 -0
- data/app/controllers/nuntius/dashboard_controller.rb +12 -0
- data/app/controllers/nuntius/feedback_controller.rb +17 -0
- data/app/controllers/nuntius/inbound_messages/twilio_inbound_smses_controller.rb +56 -0
- data/app/controllers/nuntius/messages_controller.rb +13 -0
- data/app/drops/nuntius/application_drop.rb +17 -0
- data/app/drops/nuntius/campaign_drop.rb +7 -0
- data/app/drops/nuntius/layout_drop.rb +11 -0
- data/app/drops/nuntius/message_drop.rb +11 -0
- data/app/drops/nuntius/template_drop.rb +7 -0
- data/app/exceptions/nuntius/base_exception.rb +4 -0
- data/app/exceptions/nuntius/missing_messenger_exception.rb +4 -0
- data/app/helpers/nuntius/application_helper.rb +78 -0
- data/app/jobs/nuntius/application_job.rb +9 -0
- data/app/jobs/nuntius/deliver_inbound_message_job.rb +10 -0
- data/app/jobs/nuntius/messenger_job.rb +17 -0
- data/app/jobs/nuntius/process_inbound_message_job.rb +10 -0
- data/app/jobs/nuntius/purge_message_job.rb +13 -0
- data/app/jobs/nuntius/retrieve_mail_job.rb +18 -0
- data/app/jobs/nuntius/transport_delivery_job.rb +32 -0
- data/app/jobs/nuntius/transport_refresh_job.rb +22 -0
- data/app/message_boxes/nuntius/base_message_box.rb +75 -0
- data/app/messengers/nuntius/base_messenger.rb +193 -0
- data/app/messengers/nuntius/custom_messenger.rb +6 -0
- data/app/models/nuntius/application_record.rb +11 -0
- data/app/models/nuntius/attachment.rb +13 -0
- data/app/models/nuntius/campaign.rb +75 -0
- data/app/models/nuntius/concerns/metadata_scoped.rb +31 -0
- data/app/models/nuntius/concerns/yamlify.rb +23 -0
- data/app/models/nuntius/inbound_message.rb +14 -0
- data/app/models/nuntius/layout.rb +13 -0
- data/app/models/nuntius/list.rb +10 -0
- data/app/models/nuntius/locale.rb +11 -0
- data/app/models/nuntius/message.rb +148 -0
- data/app/models/nuntius/subscriber.rb +12 -0
- data/app/models/nuntius/template.rb +102 -0
- data/app/presenters/application_presenter.rb +28 -0
- data/app/presenters/template_presenter.rb +17 -0
- data/app/providers/nuntius/apnotic_push_provider.rb +44 -0
- data/app/providers/nuntius/base_provider.rb +72 -0
- data/app/providers/nuntius/firebase_push_provider.rb +26 -0
- data/app/providers/nuntius/houston_push_provider.rb +40 -0
- data/app/providers/nuntius/message_bird_sms_provider.rb +39 -0
- data/app/providers/nuntius/slack_slack_provider.rb +36 -0
- data/app/providers/nuntius/smtp_mail_provider.rb +80 -0
- data/app/providers/nuntius/twilio_sms_provider.rb +37 -0
- data/app/providers/nuntius/twilio_voice_provider.rb +70 -0
- data/app/reportlets/nuntius/application_reportlet.rb +35 -0
- data/app/reportlets/nuntius/daily_messages_per_template_reportlet.rb +50 -0
- data/app/runners/nuntius/application_runner.rb +6 -0
- data/app/runners/nuntius/basic_application_runner.rb +15 -0
- data/app/runners/nuntius/timebased_events_runner.rb +15 -0
- data/app/services/nuntius/application_service.rb +7 -0
- data/app/services/nuntius/aws_sns_processor_service.rb +81 -0
- data/app/services/nuntius/deliver_inbound_message_service.rb +14 -0
- data/app/services/nuntius/retrieve_inbound_mail_service.rb +36 -0
- data/app/tables/nuntius_campaigns_table.rb +21 -0
- data/app/tables/nuntius_layouts_table.rb +24 -0
- data/app/tables/nuntius_lists_table.rb +19 -0
- data/app/tables/nuntius_locales_table.rb +18 -0
- data/app/tables/nuntius_messages_table.rb +36 -0
- data/app/tables/nuntius_subscribers_table.rb +19 -0
- data/app/tables/nuntius_templates_table.rb +30 -0
- data/app/transports/nuntius/base_transport.rb +36 -0
- data/app/transports/nuntius/mail_transport.rb +35 -0
- data/app/transports/nuntius/push_transport.rb +15 -0
- data/app/transports/nuntius/slack_transport.rb +6 -0
- data/app/transports/nuntius/sms_transport.rb +6 -0
- data/app/transports/nuntius/voice_transport.rb +6 -0
- data/app/validators/liquid_validator.rb +11 -0
- data/app/views/nuntius/admin/campaigns/edit.html.slim +49 -0
- data/app/views/nuntius/admin/campaigns/index.html.slim +2 -0
- data/app/views/nuntius/admin/layouts/attachments/_attachments.html.slim +28 -0
- data/app/views/nuntius/admin/layouts/attachments/_index.html.slim +2 -0
- data/app/views/nuntius/admin/layouts/attachments/create.json.jbuilder +5 -0
- data/app/views/nuntius/admin/layouts/edit.html.slim +24 -0
- data/app/views/nuntius/admin/layouts/index.html.slim +2 -0
- data/app/views/nuntius/admin/lists/edit.html.slim +14 -0
- data/app/views/nuntius/admin/lists/index.html.slim +2 -0
- data/app/views/nuntius/admin/lists/subscribers/edit.html.slim +14 -0
- data/app/views/nuntius/admin/locales/edit.html.slim +14 -0
- data/app/views/nuntius/admin/locales/index.html.slim +2 -0
- data/app/views/nuntius/admin/messages/index.html.slim +2 -0
- data/app/views/nuntius/admin/messages/show.html.slim +56 -0
- data/app/views/nuntius/admin/templates/edit.html.slim +81 -0
- data/app/views/nuntius/admin/templates/index.html.slim +2 -0
- data/app/views/nuntius/dashboard/show.html.slim +7 -0
- data/app/views/nuntius/messages/show.html.slim +7 -0
- data/config/locales/en.yml +22 -0
- data/config/locales/nl.yml +22 -0
- data/config/routes.rb +38 -0
- data/config/webpack/development.js +5 -0
- data/config/webpack/environment.js +4 -0
- data/config/webpack/production.js +5 -0
- data/config/webpack/test.js +5 -0
- data/config/webpacker.yml +119 -0
- data/db/migrate/20190301201541_create_nuntius_templates.rb +27 -0
- data/db/migrate/20190301202436_create_nuntius_messages.rb +30 -0
- data/db/migrate/20190322112815_create_nuntius_lists.rb +12 -0
- data/db/migrate/20190322114340_create_nuntius_campaigns.rb +18 -0
- data/db/migrate/20190322121338_create_nuntius_subscribers.rb +17 -0
- data/db/migrate/20190327123535_add_metadata_to_models.rb +8 -0
- data/db/migrate/20190327124407_create_nuntius_layouts.rb +24 -0
- data/db/migrate/20190327143921_add_campaign_to_message.rb +7 -0
- data/db/migrate/20190327155112_add_state_to_campaign.rb +7 -0
- data/db/migrate/20190412103335_add_enabled_to_templates.rb +7 -0
- data/db/migrate/20190417125153_change_message_status_default.rb +9 -0
- data/db/migrate/20190417144554_add_nuntiable_to_subscriber.rb +7 -0
- data/db/migrate/20190521135011_add_payload_to_nuntius_messages.rb +7 -0
- data/db/migrate/20190522122657_add_metadata_to_nuntius_message.rb +7 -0
- data/db/migrate/20190825080757_update_nuntius_message_sending_to_sent.rb +11 -0
- data/db/migrate/20200220154927_change_nuntius_templates_payload_type.rb +7 -0
- data/db/migrate/20200224132337_create_nuntius_locales.rb +13 -0
- data/db/migrate/20200318095339_create_nuntius_attachments.rb +12 -0
- data/db/migrate/20200407050646_add_interval_to_nuntius_template.rb +5 -0
- data/db/migrate/20200430131219_make_html_processing_optional.rb +6 -0
- data/db/migrate/20200430154032_make_html_processing_optional_revert.rb +6 -0
- data/db/migrate/20201121185718_create_nuntius_inbound_messages.rb +21 -0
- data/db/migrate/20220412114148_add_last_sent_to_message.rb +5 -0
- data/lib/nuntius/active_record_helpers.rb +28 -0
- data/lib/nuntius/active_storage_helpers.rb +8 -0
- data/lib/nuntius/configuration.rb +97 -0
- data/lib/nuntius/deprecator.rb +8 -0
- data/lib/nuntius/devise.rb +19 -0
- data/lib/nuntius/engine.rb +46 -0
- data/lib/nuntius/i18n_store.rb +100 -0
- data/lib/nuntius/liquid/tags/attach_tag.rb +44 -0
- data/lib/nuntius/mail_allow_list.rb +23 -0
- data/lib/nuntius/nuntiable.rb +24 -0
- data/lib/nuntius/state_machine.rb +19 -0
- data/lib/nuntius/transactio.rb +30 -0
- data/lib/nuntius/version.rb +3 -1
- data/lib/nuntius.rb +74 -8
- data/lib/preamble.rb +87 -0
- data/lib/tasks/nuntius_tasks.rake +27 -0
- metadata +532 -67
- data/.gitignore +0 -4
- data/Gemfile +0 -4
- data/lib/nuntius/encodings/url_safe_base64.rb +0 -26
- data/lib/nuntius/encodings.rb +0 -9
- data/lib/nuntius/envelope.rb +0 -45
- data/lib/nuntius/key.rb +0 -47
- data/lib/nuntius/messenger.rb +0 -37
- data/nuntius.gemspec +0 -23
- data/spec/keys/alice.pem +0 -27
- data/spec/keys/alice.pub +0 -9
- data/spec/keys/bob.pem +0 -27
- data/spec/keys/bob.pub +0 -9
- data/spec/nuntius/encodings/url_safe_base64_spec.rb +0 -36
- data/spec/nuntius/envelope_spec.rb +0 -6
- data/spec/nuntius/key_spec.rb +0 -12
- data/spec/nuntius/messenger_spec.rb +0 -26
- data/spec/spec_helper.rb +0 -9
- data/spec/support/keys.rb +0 -3
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 736ed78b3a455b90aad20c47ba9bf6c3946cb7d45dc064c33d689a622ac40f18
|
4
|
+
data.tar.gz: c2f9abeeffe69fe5f28df8af6b0ff1c72c3c73d743b9156f0a12ed6daca3d1a9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a6fe800fc712a05dc2a35166a28a6d3c0d41f248365ca1cdb3f529f1430e77ca11553342cc0681490b1aaad952de6f87b89412f8329501e79765c556efa3428f
|
7
|
+
data.tar.gz: 4e79093e36ffeb8967aa5568a064b41828c33dcd3da32bf87ff0a5ed3504f5c3dc2794560c237254e63ed042a521442d3c51e57ca54690f209057e5bc29b73a5
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2018 Tom de Grunt
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,93 +1,229 @@
|
|
1
|
-
# Nuntius
|
1
|
+
# Nuntius
|
2
2
|
|
3
|
-
|
3
|
+
Nuntius offers messaging and notifications for ActiveRecord models in Ruby on Rails applications.
|
4
4
|
|
5
|
-
|
5
|
+
## Setup
|
6
|
+
|
7
|
+
Add Nuntius to your Gemfile and run bundle install to install it.
|
8
|
+
|
9
|
+
Create an initializer (config/initializers/messaging.rb) and configure as desired:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
Nuntius.setup do
|
13
|
+
# Have Nuntius log to the Rails.logger
|
14
|
+
config.logger = Rails.logger
|
15
|
+
|
16
|
+
# Allow custom events (default = false)
|
17
|
+
# Enable this option to allow use of Nuntius with a Hash
|
18
|
+
config.allow_custom_events = true
|
19
|
+
|
20
|
+
# Configure the transport you want to use
|
21
|
+
|
22
|
+
# Enable e-mail
|
23
|
+
config.transport :mail
|
24
|
+
# Enable push notifications
|
25
|
+
config.transport :push
|
26
|
+
# Enable SMS
|
27
|
+
config.transport :sms
|
28
|
+
# Enable voice
|
29
|
+
config.transport :voice
|
30
|
+
# Enable Slack
|
31
|
+
config.transport :slack
|
32
|
+
|
33
|
+
# Configure providers for each of the transports you enabled above.
|
34
|
+
# Advised is to either do this using credentials, environment variables, or somewhere in a model (securely stored away).
|
35
|
+
config.provider :slack, transport: :slack, settings: lambda { |_message|
|
36
|
+
Rails.application.credentials[:slack]
|
37
|
+
}
|
38
|
+
end
|
39
|
+
```
|
40
|
+
|
41
|
+
Mount the Rails engine in your routes.rb to enable Nuntius' maintenance pages:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
Rails.application.routes.draw do
|
45
|
+
# your own routes ...
|
46
|
+
mount Nuntius::Engine, at: '/messaging', as: 'nuntius' # change the path and aliases at your own discretion
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
To enable you to send messages with Nuntius you need to make one or more ActiveRecord models nuntiable:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
class Car < ApplicationRecord
|
54
|
+
nuntiable
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
Additionally you need to define an extension of the Nuntius::BaseMessenger for the same model with a matching name (in app/messengers):
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
class CarMessenger < Nuntius::BaseMessenger
|
62
|
+
def your_event(car, params)
|
63
|
+
# your optional logic here
|
64
|
+
end
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
If you are using the state_machines-activemodel gem you can pass use_state_machine: true to the
|
69
|
+
nuntiable call, this will automatically define empty methods for these events on the model's
|
70
|
+
messenger class if they are not defined already.
|
71
|
+
|
72
|
+
Additionally the use_state_machine option will add an after_commit hook to the state machine
|
73
|
+
to automatically trigger the event for the state transition.
|
6
74
|
|
7
75
|
## Usage
|
8
76
|
|
9
|
-
###
|
77
|
+
### With templates
|
78
|
+
|
79
|
+
Usually you would call Nuntius programatically with code by using Templates. In this case you would use for example:
|
10
80
|
|
11
81
|
```ruby
|
12
|
-
|
13
|
-
|
14
|
-
sender = Nuntius::Key.new( File.read('private_key_path') )
|
15
|
-
messenger = Nuntius::Mesenger.new({
|
16
|
-
:key => sender
|
17
|
-
})
|
18
|
-
|
19
|
-
receiver = Nuntius::Key.new( File.read('public_key_path') )
|
20
|
-
|
21
|
-
envelope = messenger.wrap({
|
22
|
-
:message => "Message Content",
|
23
|
-
:to => receiver
|
24
|
-
})
|
25
|
-
|
26
|
-
envelope.data
|
27
|
-
# => The encripted message
|
28
|
-
envelope.key
|
29
|
-
# => The encripted message key
|
30
|
-
envelope.signature
|
31
|
-
# => The encripted message signature
|
82
|
+
Nuntius.event(:your_event, car)
|
32
83
|
```
|
33
84
|
|
34
|
-
|
85
|
+
When custom events are enabled you can also do the following:
|
35
86
|
|
36
87
|
```ruby
|
37
|
-
|
88
|
+
Nuntius.event('shipped', { shipped: { to: 'test@example.com', ref: 'Test-123'} }, attachments: [ { url: 'http://example.com' } ])
|
89
|
+
```
|
38
90
|
|
39
|
-
|
40
|
-
|
41
|
-
:key => receiver
|
42
|
-
})
|
91
|
+
For the above cases you need to define templates, this is done with the maintenace pages under
|
92
|
+
/messaging/admin/templates (/messaging is whatever you have defined in your routes file).
|
43
93
|
|
44
|
-
|
94
|
+
When Nuntius#message is called a message will be sent for every matching template. To allow you to
|
95
|
+
send different messages under different circumstances you can specify a template_scope on the messenger
|
96
|
+
class that uses the template's metadata in combination with the nuntiable object to determine whether
|
97
|
+
or not the template should be used.
|
45
98
|
|
46
|
-
|
47
|
-
:data => 'The encripted message'
|
48
|
-
:key => 'The encripted message key'
|
49
|
-
:signature => 'The encripted message signature'
|
50
|
-
})
|
99
|
+
### Timebased events
|
51
100
|
|
52
|
-
|
53
|
-
|
54
|
-
:from => sender
|
55
|
-
})
|
101
|
+
If you want to send messages based on time intervals you can add such events to your messenger with the
|
102
|
+
timebased_scope class method like so:
|
56
103
|
|
57
|
-
|
58
|
-
|
104
|
+
```ruby
|
105
|
+
class CarMessenger < Nuntius::BaseMessenger
|
106
|
+
# time_range is a range, for a before scope the time_range the interval is added to the current
|
107
|
+
# time, the end of the range is 1 hour from the start.
|
108
|
+
timebased_scope :before_tuneup do |time_range, metadata|
|
109
|
+
cars = Car.where(tuneup_at: time_range)
|
110
|
+
cars = cars.where(color: metadata['color']) if metadata['color'].present?
|
111
|
+
cars
|
112
|
+
end
|
113
|
+
|
114
|
+
# For an after scope the time_range the interval is taken from the current time, the end of the
|
115
|
+
# range is 1 hour from its start.
|
116
|
+
timebased_scope :after_tuneup do |time_range, metadata|
|
117
|
+
cars = Car.where(tuneup_at: time_range)
|
118
|
+
cars = cars.where(color: metadata['color']) if metadata['color'].present?
|
119
|
+
cars
|
120
|
+
end
|
121
|
+
end
|
59
122
|
```
|
60
123
|
|
61
|
-
|
124
|
+
This method also requires you to configure a template using the maintenance pages. When you choose
|
125
|
+
a timebased scope as an event you will be prompted to enter an interval, you can enter anything in the
|
126
|
+
following formats:
|
62
127
|
|
63
|
-
|
128
|
+
- N minute(s)
|
129
|
+
- N hour(s)
|
130
|
+
- N day(s)
|
131
|
+
- N week(s)
|
132
|
+
- N month(s)
|
64
133
|
|
65
|
-
|
134
|
+
To send timebased messages you need to execute Nuntius::TimestampBasedMessagesRunner.call, you could do this
|
135
|
+
in a cronjob every 5 minutes with "bundle exec rails runner Nuntius::TimestampBasedMessagesRunner.call"
|
66
136
|
|
67
|
-
|
68
|
-
* The key is then encrypted using the receiver's public RSA key.
|
69
|
-
* The encripted message's digest is calculated using SHA512 and then signed using the sender's private RSA key.
|
70
|
-
* Finally the encripted message, the encripted key and the signed digest are encoded using the RFC4648 URL Safe Base 64 encoding
|
137
|
+
### Direct
|
71
138
|
|
72
|
-
|
139
|
+
Another more direct way of using Nuntius is by just instantiating a message:
|
73
140
|
|
74
141
|
```ruby
|
75
|
-
|
142
|
+
Nuntius::Message.new(to: 'tom@boxture.com', subject: 'Test', text: 'Test text', nuntiable: channel).deliver_as(:mail)
|
143
|
+
```
|
76
144
|
|
77
|
-
|
78
|
-
receiver = OpenSSL::PKey::RSA.new( File.read('receiver_public_key') )
|
145
|
+
or
|
79
146
|
|
80
|
-
|
81
|
-
|
82
|
-
|
147
|
+
```ruby
|
148
|
+
user = User.find(1)
|
149
|
+
user.messages.new(to: 'test@example.com', subject: 'Test', text: 'Test text').deliver_as(:mail)
|
150
|
+
```
|
83
151
|
|
84
|
-
|
152
|
+
Here we still need a nuntiable object, in case provider settings can differ from object to object.
|
85
153
|
|
86
|
-
|
154
|
+
You can also define custom events, which take a scope and an event name:
|
87
155
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
156
|
+
```ruby
|
157
|
+
Nuntius.event('packed', packing: {smurrefluts: 'hatseflats'})
|
158
|
+
```
|
159
|
+
|
160
|
+
The main key of the hash passed will also be the liquid variable.
|
161
|
+
|
162
|
+
### Inbound
|
163
|
+
|
164
|
+
Inbound messages are also possible, currently mail/IMAP and Twilio inbound SMS are supported.
|
165
|
+
|
166
|
+
## Transports
|
167
|
+
|
168
|
+
### Mail
|
169
|
+
|
170
|
+
#### AWS SES
|
171
|
+
|
172
|
+
In case you use AWS SES, you can use the SNS Feedback Notifications to automatically mark messages as read, or deal with complaints and bounces. Create a AWS SNS topic, with a HTTPS subscription with the following URL (pattern):
|
173
|
+
|
174
|
+
Use the following URL: https://<host>/messaging/feedback/awssns
|
175
|
+
|
176
|
+
The actual URL may be different depending on your routing setup.
|
177
|
+
|
178
|
+
The subscription will automatically be confirmed.
|
179
|
+
|
180
|
+
Next in AWS SES, configure the SNS topic to receive feedback notifications for Bounce, Complaint and Delivery and include original headers.
|
181
|
+
|
182
|
+
### SMS
|
183
|
+
|
184
|
+
### Push
|
185
|
+
|
186
|
+
### Voice
|
187
|
+
|
188
|
+
#### Twilio
|
189
|
+
|
190
|
+
Information on voice TWIML is here: https://www.twilio.com/docs/voice/twiml/gather
|
191
|
+
You can try voices here: https://www.twilio.com/console/voice/twiml/text-to-speech
|
192
|
+
|
193
|
+
```
|
194
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
195
|
+
<Response>
|
196
|
+
<Say language="nl-NL">
|
197
|
+
Hallo, dit is een bericht van Boxture!
|
198
|
+
<break strength="x-weak" time="100ms"/>
|
199
|
+
<p>We geven je zo je wachtwoord-herstel-code, dus pak een pen en schrijf mee.</p>
|
200
|
+
</Say>
|
201
|
+
<Gather input="dtmf" numDigits="1" action="{%raw%}{{url}}{%endraw%}/code">
|
202
|
+
<Say language="nl-NL">Druk een toets om verder te gaan.</Say>
|
203
|
+
</Gather>
|
204
|
+
<Redirect>{%raw%}{{url}}{%endraw%}/code</Redirect>
|
205
|
+
</Response>
|
206
|
+
|
207
|
+
---
|
208
|
+
path: /code
|
209
|
+
---
|
210
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
211
|
+
<Response>
|
212
|
+
<Gather input="dtmf" numDigits="1">
|
213
|
+
<Say language="nl-NL">
|
214
|
+
<s>Je code is:</s>
|
215
|
+
<break strength="x-weak" time="100ms"/>
|
216
|
+
<prosody rate="x-slow"><say-as interpret-as="character">1 n a x d 8 b</say-as></prosody>
|
217
|
+
<break strength="x-weak" time="1s"/>
|
218
|
+
Druk een toets om te herhalen, of hang op.
|
219
|
+
</Say>
|
220
|
+
</Gather>
|
221
|
+
<Redirect>{%raw%}{{url}}{%endraw%}/code</Redirect>
|
222
|
+
</Response>
|
223
|
+
```
|
224
|
+
|
225
|
+
## Testing
|
226
|
+
|
227
|
+
```
|
228
|
+
bundle exec sidekiq -C test/dummy/config/sidekiq.yml -r test/dummy
|
93
229
|
```
|
data/Rakefile
CHANGED
@@ -1 +1,62 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
rescue LoadError
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'rdoc/task'
|
10
|
+
|
11
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
12
|
+
rdoc.rdoc_dir = 'rdoc'
|
13
|
+
rdoc.title = 'Nuntius'
|
14
|
+
rdoc.options << '--line-numbers'
|
15
|
+
rdoc.rdoc_files.include('README.md')
|
16
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
17
|
+
end
|
18
|
+
|
19
|
+
APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
|
20
|
+
load 'rails/tasks/engine.rake'
|
21
|
+
|
22
|
+
load 'rails/tasks/statistics.rake'
|
23
|
+
|
24
|
+
require 'bundler/gem_tasks'
|
25
|
+
|
26
|
+
require 'rake/testtask'
|
27
|
+
|
28
|
+
Rake::TestTask.new(:test) do |t|
|
29
|
+
t.libs << 'test'
|
30
|
+
t.pattern = 'test/**/*_test.rb'
|
31
|
+
t.verbose = false
|
32
|
+
t.warning = false
|
33
|
+
end
|
34
|
+
|
35
|
+
task default: :test
|
36
|
+
|
37
|
+
# Adds the Auxilium semver task
|
38
|
+
spec = Gem::Specification.find_by_name 'auxilium'
|
39
|
+
load "#{spec.gem_dir}/lib/tasks/semver.rake"
|
40
|
+
|
41
|
+
namespace :nuntius do
|
42
|
+
namespace :webpacker do
|
43
|
+
desc 'Install deps with yarn'
|
44
|
+
task :yarn_install do
|
45
|
+
Dir.chdir(File.join(__dir__, '../..')) do
|
46
|
+
system 'yarn install --no-progress --production'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
desc 'Compile JavaScript packs using webpack for production with digests'
|
51
|
+
task compile: %i[yarn_install environment] do
|
52
|
+
Webpacker.with_node_env('production') do
|
53
|
+
if Nuntius.webpacker.commands.compile
|
54
|
+
# Successful compilation!
|
55
|
+
else
|
56
|
+
# Failed compilation
|
57
|
+
exit!
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_dependency 'nuntius/application_admin_controller'
|
4
|
+
|
5
|
+
module Nuntius
|
6
|
+
module Admin
|
7
|
+
class CampaignsController < ApplicationAdminController
|
8
|
+
before_action :set_objects, except: [:index]
|
9
|
+
|
10
|
+
def index
|
11
|
+
@campaigns = Nuntius::Campaign.visible.order(created_at: :desc)
|
12
|
+
end
|
13
|
+
|
14
|
+
def new
|
15
|
+
render :edit
|
16
|
+
end
|
17
|
+
|
18
|
+
def create
|
19
|
+
@campaign.save
|
20
|
+
respond_with :admin, @campaign, action: :edit
|
21
|
+
end
|
22
|
+
|
23
|
+
def show
|
24
|
+
redirect_to :edit_admin_campaign, status: :see_other
|
25
|
+
end
|
26
|
+
|
27
|
+
def edit; end
|
28
|
+
|
29
|
+
def update
|
30
|
+
saved = @campaign.update(campaign_params)
|
31
|
+
|
32
|
+
if saved && params[:commit] == 'send'
|
33
|
+
@campaign.publish! if @campaign.can_publish?
|
34
|
+
redirect_to :edit_admin_campaign, status: :see_other
|
35
|
+
else
|
36
|
+
respond_with :admin, @campaign
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def set_objects
|
43
|
+
@campaign = params[:id] ? Nuntius::Campaign.visible.find(params[:id]) : Nuntius::Campaign.new(campaign_params)
|
44
|
+
@lists = Nuntius::List.visible
|
45
|
+
@layouts = Nuntius::Layout.visible
|
46
|
+
@messages = Nuntius::Message.where(campaign: @campaign)
|
47
|
+
end
|
48
|
+
|
49
|
+
def campaign_params
|
50
|
+
return unless params[:campaign]
|
51
|
+
|
52
|
+
params.require(:campaign).permit(:name, :transport, :layout_id, :list_id, :from, :subject, :text, :html)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nuntius
|
4
|
+
module Admin
|
5
|
+
module Layouts
|
6
|
+
class AttachmentsController < ApplicationController
|
7
|
+
before_action :set_objects
|
8
|
+
|
9
|
+
def index; end
|
10
|
+
|
11
|
+
def create
|
12
|
+
params[:attachments].each do |file|
|
13
|
+
@layout.attachments.attach(file)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def destroy
|
18
|
+
attachment = @layout.attachments.find_by(id: params[:id])
|
19
|
+
attachment&.purge
|
20
|
+
|
21
|
+
render :create
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def set_objects
|
27
|
+
@layout = Nuntius::Layout.visible.find(params[:layout_id]) if params[:layout_id]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_dependency 'nuntius/application_admin_controller'
|
4
|
+
|
5
|
+
module Nuntius
|
6
|
+
module Admin
|
7
|
+
class LayoutsController < ApplicationAdminController
|
8
|
+
def index
|
9
|
+
@layouts = Nuntius::Layout.visible.order(:name)
|
10
|
+
end
|
11
|
+
|
12
|
+
def new
|
13
|
+
@layout = Nuntius::Layout.new
|
14
|
+
render :edit
|
15
|
+
end
|
16
|
+
|
17
|
+
def create
|
18
|
+
@layout = Nuntius::Layout.new(layout_params)
|
19
|
+
@layout.save
|
20
|
+
respond_with :admin, @layout
|
21
|
+
end
|
22
|
+
|
23
|
+
def edit
|
24
|
+
@layout = Nuntius::Layout.visible.find(params[:id])
|
25
|
+
end
|
26
|
+
|
27
|
+
def show
|
28
|
+
redirect_to :edit_admin_layout, status: :see_other
|
29
|
+
end
|
30
|
+
|
31
|
+
def update
|
32
|
+
@layout = Nuntius::Layout.visible.find(params[:id])
|
33
|
+
@layout.update(layout_params)
|
34
|
+
respond_with :admin, @layout
|
35
|
+
end
|
36
|
+
|
37
|
+
def destroy
|
38
|
+
@layout = Nuntius::Layout.visible.find(params[:id])
|
39
|
+
@layout.destroy
|
40
|
+
respond_with @layout
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def layout_params
|
46
|
+
params.require(:layout).permit(:name, :data, :metadata_yaml)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_dependency 'nuntius/application_admin_controller'
|
4
|
+
|
5
|
+
module Nuntius
|
6
|
+
module Admin
|
7
|
+
module Lists
|
8
|
+
class SubscribersController < ApplicationAdminController
|
9
|
+
before_action :set_objects
|
10
|
+
|
11
|
+
def index
|
12
|
+
@subscribers = @list.subscribers.all
|
13
|
+
end
|
14
|
+
|
15
|
+
def new
|
16
|
+
@subscriber = @list.subscribers.new
|
17
|
+
render :edit
|
18
|
+
end
|
19
|
+
|
20
|
+
def create
|
21
|
+
@subscriber = @list.subscribers.new(subscriber_params)
|
22
|
+
@subscriber.save
|
23
|
+
# FIXME: This should redirect to list
|
24
|
+
respond_with :admin, :list, @subscriber, collection_location: -> { nuntius.admin_list_url(@list) }, location: -> { nuntius.admin_list_url(@list) }, status: :see_other
|
25
|
+
end
|
26
|
+
|
27
|
+
def edit
|
28
|
+
@subscriber = @list.subscribers.find(params[:id])
|
29
|
+
end
|
30
|
+
|
31
|
+
def update
|
32
|
+
@subscriber = @list.subscribers.find(params[:id])
|
33
|
+
@subscriber.update(subscriber_params)
|
34
|
+
# FIXME: This should redirect to list
|
35
|
+
respond_with :admin, :list, @subscriber, collection_location: -> { nuntius.admin_list_url(@list) }, location: -> { nuntius.admin_list_url(@list) }, status: :see_other
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def subscriber_params
|
41
|
+
params.require(:subscriber).permit(:first_name, :last_name, :email, :phone_number, tags: [])
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_objects
|
45
|
+
@list = List.find(params[:list_id])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_dependency 'nuntius/application_admin_controller'
|
4
|
+
|
5
|
+
module Nuntius
|
6
|
+
module Admin
|
7
|
+
class ListsController < ApplicationAdminController
|
8
|
+
|
9
|
+
def index
|
10
|
+
@lists = Nuntius::List.visible.order(:name)
|
11
|
+
end
|
12
|
+
|
13
|
+
def new
|
14
|
+
@list = Nuntius::List.new
|
15
|
+
render :edit
|
16
|
+
end
|
17
|
+
|
18
|
+
def create
|
19
|
+
@list = Nuntius::List.create(list_params)
|
20
|
+
respond_with :admin, @list
|
21
|
+
end
|
22
|
+
|
23
|
+
def show
|
24
|
+
redirect_to :edit_admin_list, status: :see_other
|
25
|
+
end
|
26
|
+
|
27
|
+
def edit
|
28
|
+
@list = Nuntius::List.visible.find(params[:id])
|
29
|
+
end
|
30
|
+
|
31
|
+
def update
|
32
|
+
@list = Nuntius::List.visible.find(params[:id])
|
33
|
+
@list.update(list_params)
|
34
|
+
respond_with :admin, @list
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def set_objects; end
|
40
|
+
|
41
|
+
def list_params
|
42
|
+
params.require(:list).permit(:name)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_dependency 'nuntius/application_admin_controller'
|
4
|
+
|
5
|
+
module Nuntius
|
6
|
+
module Admin
|
7
|
+
class LocalesController < ApplicationAdminController
|
8
|
+
def index
|
9
|
+
@locales = Nuntius::Locale.visible.order(:key)
|
10
|
+
end
|
11
|
+
|
12
|
+
def new
|
13
|
+
@locale = Nuntius::Locale.new
|
14
|
+
render :edit
|
15
|
+
end
|
16
|
+
|
17
|
+
def create
|
18
|
+
@locale = Nuntius::Locale.new(locale_params)
|
19
|
+
@locale.save
|
20
|
+
respond_with :admin, @locale
|
21
|
+
end
|
22
|
+
|
23
|
+
def show
|
24
|
+
redirect_to :edit_admin_locales, status: :see_other
|
25
|
+
end
|
26
|
+
|
27
|
+
def edit
|
28
|
+
@locale = Nuntius::Locale.visible.find(params[:id])
|
29
|
+
end
|
30
|
+
|
31
|
+
def update
|
32
|
+
@locale = Nuntius::Locale.visible.find(params[:id])
|
33
|
+
@locale.update(locale_params)
|
34
|
+
respond_with :admin, @locale
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def set_objects; end
|
40
|
+
|
41
|
+
def locale_params
|
42
|
+
params.require(:locale).permit(:key, :data, :metadata_yaml, :data_yaml)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|