Skip to content

Commit

Permalink
Add apnotic for iOS notifications (#163)
Browse files Browse the repository at this point in the history
* Add apnotic for iOS notifications

* Standardize

* APNS updates (#165)

* Fix namespace typo

* Fix typo

* Fail if response isn't 200

* Set topic (bundle identifier)

* Use development vs. production APNS servers

* Configurable iOS credentials

* Move delivery method docs to docs folder

Co-authored-by: Joe Masilotti <[email protected]>
  • Loading branch information
excid3 and joemasilotti authored Oct 19, 2021
1 parent d52aa7b commit 0791277
Show file tree
Hide file tree
Showing 13 changed files with 408 additions and 183 deletions.
190 changes: 10 additions & 180 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Currently, we support these notification delivery methods out of the box:
* Microsoft Teams
* Twilio (SMS)
* Vonage / Nexmo (SMS)
* iOS Apple Push Notifications

And you can easily add new notification types for any other delivery methods.

Expand Down Expand Up @@ -195,186 +196,15 @@ The delivery methods are designed to be modular so you can customize the way eac

For example, emails will require a subject, body, and email address while an SMS requires a phone number and simple message. You can define the formats for each of these in your Notification and the delivery method will handle the processing of it.

### Database

Writes notification to the database.

`deliver_by :database`

**Note:** Database notifications are special in that they will run before the other delivery methods. We do this so you can reference the database record ID in other delivery methods. For that same reason, the delivery can't be delayed (via the `delay` option) or an error will be raised.

##### Options

* `association` - *Optional*

The name of the database association to use. Defaults to `:notifications`

* `format: :format_for_database` - *Optional*

Use a custom method to define the attributes saved to the database

### Email

Sends an email notification. Emails will always be sent with `deliver_later`

`deliver_by :email, mailer: "UserMailer"`

##### Options

* `mailer` - **Required**

The mailer that should send the email

* `method: :invoice_paid` - *Optional*

Used to customize the method on the mailer that is called

* `format: :format_for_email` - *Optional*

Use a custom method to define the params sent to the mailer. `recipient` will be merged into the params.

### ActionCable

Sends a notification to the browser via websockets (ActionCable channel by default).

`deliver_by :action_cable`

##### Options

* `format: :format_for_action_cable` - *Optional*

Use a custom method to define the Hash sent through ActionCable

* `channel` - *Optional*

Override the ActionCable channel used to send notifications.

Defaults to `Noticed::NotificationChannel`

### Slack

Sends a Slack notification via webhook.

`deliver_by :slack`

##### Options

* `format: :format_for_slack` - *Optional*

Use a custom method to define the payload sent to Slack. Method should return a Hash.

* `url: :url_for_slack` - *Optional*

Use a custom method to retrieve the Slack Webhook URL. Method should return a String.

Defaults to `Rails.application.credentials.slack[:notification_url]`

### Microsoft Teams

Sends a Teams notification via webhook.

`deliver_by :microsoft_teams`

#### Options

* `format: :format_for_teams` - *Optional*

Use a custom method to define the payload sent to Microsoft Teams. Method should return a Hash.
Documentation for posting via Webhooks available at: https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook

```ruby
{
title: "This is the title for the card",
text: "This is the body text for the card",
sections: [{activityTitle: "Section Title", activityText: "Section Text"}],
"potentialAction": [{
"@type": "OpenUri",
name: "Button Text",
targets: [{
os: "default",
uri: "https://example.com/foo/action"
}]
}]

}
```

* `url: :url_for_teams_channel`: - *Optional*

Use a custom method to retrieve the MS Teams Webhook URL. Method should return a string.

Defaults to `Rails.application.credentials.microsoft_teams[:notification_url]`

### Twilio SMS

Sends an SMS notification via Twilio.

`deliver_by :twilio`

##### Options

* `credentials: :get_twilio_credentials` - *Optional*

Use a custom method to retrieve the credentials for Twilio. Method should return a Hash with `:account_sid`, `:auth_token` and `:phone_number` keys.

Defaults to `Rails.application.credentials.twilio[:account_sid]` and `Rails.application.credentials.twilio[:auth_token]`

* `url: :get_twilio_url` - *Optional*

Use a custom method to retrieve the Twilio URL. Method should return the Twilio API url as a string.

Defaults to `"https://api.twilio.com/2010-04-01/Accounts/#{twilio_credentials(recipient)[:account_sid]}/Messages.json"`

* `format: :format_for_twilio` - *Optional*

Use a custom method to define the payload sent to Twilio. Method should return a Hash.

Defaults to:

```ruby
{
Body: notification.params[:message],
From: twilio_credentials[:number],
To: recipient.phone_number
}
```

* `message` - *Required*

Message is required and needs to be passed in as part of the params:

```
SmsNotification.with(message: "Howdy!")
```

### Vonage SMS

Sends an SMS notification via Vonage / Nexmo.

`deliver_by :vonage`

##### Options

* `credentials: :get_credentials` - *Optional*

Use a custom method for retrieving credentials. Method should return a Hash with `:api_key` and `:api_secret` keys.

Defaults to `Rails.application.credentials.vonage[:api_key]` and `Rails.application.credentials.vonage[:api_secret]`

* `deliver_by :vonage, format: :format_for_vonage` - *Optional*

Use a custom method to generate the params sent to Vonage. Method should return a Hash. Defaults to:

```ruby
{
api_key: vonage_credentials[:api_key],
api_secret: vonage_credentials[:api_secret],
from: notification.params[:from],
text: notification.params[:body],
to: notification.params[:to],
type: "unicode"
}
```
* [Database](docs/delivery_methods/database.md)
* [Email](docs/delivery_methods/email.md)
* [ActionCable](docs/delivery_methods/action_cable.md)
* [iOS Apple Push Notifications](docs/delivery_methods/ios.md)
* [Microsoft Teams](docs/delivery_methods/microsoft_teams.md)
* [Slack](docs/delivery_methods/slack.md)
* [Test](docs/delivery_methods/test.md)
* [Twilio](docs/delivery_methods/twilio.md)
* [Vonage](docs/delivery_methods/vonage.md)

### Fallback Notifications

Expand Down
2 changes: 1 addition & 1 deletion docs/actioncable.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

ActionCable notifications in noticed are broadcast to the Noticed::NotificationChannel.

By default, we simply send over the `params` as JSON and subscribe to the `current_user` stream.
By default, we simply send over the `params` as JSON and subscribe to the `current_user` stream.

This requires `identified_by :current_user` in your ApplicationCable::Connection. For example, using Devise for authentication:

Expand Down
17 changes: 17 additions & 0 deletions docs/delivery_methods/action_cable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
### ActionCable Delivery Method

Sends a notification to the browser via websockets (ActionCable channel by default).

`deliver_by :action_cable`

##### Options

* `format: :format_for_action_cable` - *Optional*

Use a custom method to define the Hash sent through ActionCable

* `channel` - *Optional*

Override the ActionCable channel used to send notifications.

Defaults to `Noticed::NotificationChannel`
19 changes: 19 additions & 0 deletions docs/delivery_methods/database.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
### Database Delivery Method

Writes notification to the database.

`deliver_by :database`

**Note:** Database notifications are special in that they will run before the other delivery methods. We do this so you can reference the database record ID in other delivery methods. For that same reason, the delivery can't be delayed (via the `delay` option) or an error will be raised.

##### Options

* `association` - *Optional*

The name of the database association to use. Defaults to `:notifications`

* `format: :format_for_database` - *Optional*

Use a custom method to define the attributes saved to the database


21 changes: 21 additions & 0 deletions docs/delivery_methods/email.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
### Email Delivery Method

Sends an email notification. Emails will always be sent with `deliver_later`

`deliver_by :email, mailer: "UserMailer"`

##### Options

* `mailer` - **Required**

The mailer that should send the email

* `method: :invoice_paid` - *Optional*

Used to customize the method on the mailer that is called

* `format: :format_for_email` - *Optional*

Use a custom method to define the params sent to the mailer. `recipient` will be merged into the params.


79 changes: 79 additions & 0 deletions docs/delivery_methods/ios.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# iOS Notification Delivery Method

Send Apple Push Notifications with HTTP2 using the `apnotic` gem. The benefit of HTTP2 is that we can receive feedback for invalid device tokens without running a separate feedback service like RPush does.

```bash
bundle add "apnotic"
```

## Usage

```ruby
class CommentNotification
deliver_by :ios
end
```

With custom configuration:

```ruby
class CommentNotification
deliver_by :ios, format: :ios_format, cert_path: :ios_cert_path, key_id: :ios_key_id, team_id: :ios_team_id, pool_size: 5

# Customize notification
# See https://github.com/ostinelli/apnotic#apnoticnotification
def ios_format(apn)
apn.alert = "Hello world"
apn.custom_payload = { url: root_url }
end

def ios_cert_path
Rails.root.join("config/certs/ios/apns.p8")
end

def ios_key_id
Rails.application.credentials.dig(:ios, :key_id)
end

def ios_team_id
Rails.application.credentials.dig(:ios, :team_id)
end
end
```

## Options

* `format: :ios_format` - *Optional*

Customize the Apnotic notification object

See https://github.com/ostinelli/apnotic#apnoticnotification

* `bundle_identifier: Rails.application.credentials.dig(:ios, :bundle_identifier)` - *Optional*

The APN bundle identifier

* `cert_path: Rails.root.join("config/certs/ios/apns.p8")` - *Optional*

The location of your APNs p8 certificate

* `key_id: Rails.application.credentials.dig(:ios, :key_id)` - *Optional*

Your APN Key ID

If nothing passed, we'll default to `Rails.application.credentials.dig(:ios, :key_id)`
If a String is passed, we'll use that as the key ID.
If a Symbol is passed, we'll call the matching method and you can return the Key ID.

* `team_id: Rails.application.credentials.dig(:ios, :team_id)` - *Optional*

Your APN Team ID

If nothing passed, we'll default to `Rails.application.credentials.dig(:ios, :team_id)`
If a String is passed, we'll use that as the team ID.
If a Symbol is passed, we'll call the matching method and you can return the team ID.

* `pool_size: 5` - *Optional*

The connection pool size for Apnotic

37 changes: 37 additions & 0 deletions docs/delivery_methods/microsoft_teams.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
### Microsoft Teams Delivery Method

Sends a Teams notification via webhook.

`deliver_by :microsoft_teams`

#### Options

* `format: :format_for_teams` - *Optional*

Use a custom method to define the payload sent to Microsoft Teams. Method should return a Hash.
Documentation for posting via Webhooks available at: https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook

```ruby
{
title: "This is the title for the card",
text: "This is the body text for the card",
sections: [{activityTitle: "Section Title", activityText: "Section Text"}],
"potentialAction": [{
"@type": "OpenUri",
name: "Button Text",
targets: [{
os: "default",
uri: "https://example.com/foo/action"
}]
}]

}
```

* `url: :url_for_teams_channel`: - *Optional*

Use a custom method to retrieve the MS Teams Webhook URL. Method should return a string.

Defaults to `Rails.application.credentials.microsoft_teams[:notification_url]`


Loading

0 comments on commit 0791277

Please sign in to comment.