GithubHelp home page GithubHelp logo

esl / sparrow Goto Github PK

View Code? Open in Web Editor NEW
30.0 30.0 11.0 343 KB

iOS and Android push notifications for Elixir.

License: Apache License 2.0

Elixir 99.98% Euphoria 0.02%
apns elixir fcm push-notifications

sparrow's Introduction

Sparrow

Summary

Sparrow is an Elixir library for push notifications. Build Status Coverage Status

Currently it provides support for the following APIs:

Requirements

  • Elixir 1.6 or higher
  • Erlang OTP 20.3.6 or higher

Build sparrow config

This section describes how to write a config file for Sparrow. If you wish to use just one of the following services, do not include the other in the config.

config :sparrow, 
    fcm: [...],
    apns: [...]

Config examples

FCM only:

config :sparrow, fcm: [
        [
            path_to_json: "path/to/google-services.json"
        ]
    ]

APNS only:

config :sparrow, 
    apns: [
        dev:
        [
            [
                auth_type: :certificate_based,
                cert: "path/to/apns/cert.pem",
                key: "path/to/apns/key.pem"
            ]
        ],
        prod:
        [
            [ 
                auth_type: :token_based,
                token_id: :some_atom_id,
                tags: [:production, :token_based_auth]
            ],
            [ 
                auth_type: :token_based,
                token_id: :other_atom_id,
                tags: [:other_production_pool, :token_based_auth]
            ]
        ],
        tokens:
        [
            [
                token_id: :some_atom_id,
                key_id: "FAKE_KEY_ID",
                team_id: "FAKE_TEAM_ID",
                p8_file_path: "path/to/file/token.p8"
            ],
             [
                token_id: :other_atom_id,
                key_id: "OTHER_FAKE_KEY_ID",
                team_id: "OTHER_FAKE_TEAM_ID",
                p8_file_path: "path/to/file/other/token.p8"
            ]
        ]
    ]

Both FCM and APNS:

config :sparrow,
    fcm: [
        [
            path_to_json: "path/to/fcm_token.json"
        ]
    ],
    apns: [
        dev:
        [
            [
                auth_type: :certificate_based,
                cert: "path/to/apns/cert.pem",
                key: "path/to/apns/key.pem"
            ]
        ]
    ]

Config options description

FCM specific

  • :path_to_json - is a path to a json file provided by FCM

APNS specific

  • :auth_type - defines the authentication type, the allowed values are: :token_based, :certificate_based

    • :token_based requires setting:

      • :token_id - is a unique atom referring to a token with the same :token_id in config
    • :certificate_based requires setting:

      • :cert - path to the certificate file provided by APNS
      • :key - path to the key file provided by APNS

Connection config

  • :endpoint - service uri
  • :port - service port
  • :tls_opts - passed to erlang ssl module (see DATA TYPES -> ssl_option())
  • :ping_interval - number of miliseconds between each ping, to switch ping off set :ping_interval to nil
  • :reconnect_attempts - number of attempts to reconnect before failing the connection

Connection pool config

  • :pool_name - defines pool name, not recommended - please use tags instead
  • :tags - see the tags section
  • :worker_num - number of workers in a pool
  • :raw_opts - opts passed directly to wpool

FCM config example

fcm_config = 
    [
        [
            # Authentication
            path_to_json: "path/to/fcm_token.json", # mandatory, path to FCM authentication JSON file
            # Connection config
            endpoint: "fcm.googleapis.com", # optional
            port: 443, # optional
            tls_opts: [], # optional
            ping_interval: 5000, # optional
            reconnect_attempts: 3, # optional
            # Pool config 
            tags: [], # optional
            worker_num: 3, # optional
            raw_opts: [] # optional, options passed directly to wpool
        ]
    ]

APNS config example

apns_config = 
[
    dev: [apns_pool_1, apns_pool_2 ], # list of apns_pool_configs by default set to APNS development endpoint, is a list of APNS pools
    prod: [apns_pool_3 ],  # list of apns_pool_configs by default set to APNS production endpoint, is a list of APNS pools
    tokens: [apns_token_1, apns_token_2 ] # optional, is a list of APNS tokens
]

APNS pool example

Token based authentication example:

apns_pool = [
    # Token based authentication
    auth_type: :token_based, # mandatory, :token_based or :certificate_based
    token_id: :some_atom_id, # mandatory, token with the same id must be in `tokens` in `apns_config`
    # Connection config
    endpoint: "api.development.push.apple.com", # optional
    port: 443, # optional
    tls_opts: [], # optional
    ping_interval: 5000, # optional
    reconnect_attempts: 3, # optional
    # pool config
    tags: [:first_batch_clients, :beta_users], # optional
    worker_num: 3, # optional
    raw_opts: [], # optional
]

Certificate based authentication example:

apns_pool = [
    # Certificate based authentication
    auth_type: :certificate_based, # mandatory, :token_based or :certificate_based
    cert: "path/to/apns/cert.pem", # mandatory, path to certificate file provided by APNS
    key: "path/to/apns/key.pem", # mandatory, path to key file provided by APNS
    # Connection config
    endpoint: "api.push.apple.com", # optional
    port: 443, # optional
    tls_opts: [], # optional
    ping_interval: 5000, # optional
    reconnect_attempts: 3, # optional
    # pool config
    tags: [:another_batch_clients], # optional
    worker_num: 3, # optional
    raw_opts: [] # optional
]

APNS token example

apns_token = [
          token_id: :some_atom_id, # mandatory, the same as in APNSPOOL
          key_id: "FAKE_KEY_ID", # mandatory, data obtained form APNS account
          team_id: "FAKE_TEAM_ID", # mandatory, data obtained form APNS account
          p8_file_path: "path/to/file/token.p8" # mandatory, path to file storing APNS token
        ]

Include sparrow in your project

defp deps do
    [
      {:sparrow, github: "esl/sparrow", tag: "cc80bbc"},
      ]
  end

Many pools

Sparrow suports many pools in a single :sparrow instance. Tags are used to choose a pool when sending a notification.

Tags

Tags is a mechanism allowing to choose a pool to send a notification from. Each pool has a defined list of tags ([] as default). The algorithm has the following steps:

  1. Filter pooltype based on notification type (:fcm or :{apns, :dev} or {:apns, :prod}).
  2. Choose only pools that have all tags (from the function call) included in their tags (from pool configuration).
  3. Choose first of the filtered pools.

Example: Let's say you have the following pools:

  • {:apns, :dev}:
    • pool1: [:test_pool, :dev_pool, :homer],
    • pool2: [:test_pool, :dev_pool, :bart],
    • pool3: [:test_pool, :dev_pool, :ned, :bart]
  • {:apns, :prod}:
    • pool1: [:prod_pool]

Lets assume the notification type is {:apns, :dev}.

If you pass [], pool1 is chosen.

If you pass [:homer], pool1 is chosen.

If you pass [:bart], pool2 is chosen.

If you pass [:ned], pool3 is chosen.

If you pass [:test_pool], pool1 is chosen.

If you pass [:test_pool, :homer], pool1 is chosen.

If you pass [:test_pool, :dev_pool, :homer], pool1 is chosen.

If you pass [:test_pool, :dev_pool, :ned], pool3 is chosen.

If you pass [:not_existing, :set_of_tags], {:error, :configuration_error} is returned.

It is not recommended to choose a pool based on pools order!

Telemetry

Sparrow supports telemetry. Emitted events are defined with following tags:

  • [:sparrow, :h2_worker, :init]
  • [:sparrow, :h2_worker, :terminate]
  • [:sparrow, :h2_worker, :conn_lost]
  • [:sparrow, :h2_worker, :request_error]
  • [:sparrow, :h2_worker, :request_success]
  • [:sparrow, :h2_worker, :conn_success]
  • [:sparrow, :h2_worker, :conn_fail]
  • [:sparrow, :pools_warden, :init]
  • [:sparrow, :pools_warden, :terminate]
  • [:sparrow, :pools_warden, :choose_pool]
  • [:sparrow, :pools_warden, :pool_down]
  • [:sparrow, :pools_warden, :add_pool]

There are also events measuring the duration of a few chosen function calls:

  • [:sparrow, :push, :api]
  • [:sparrow, :push, :apns]
  • [:sparrow, :push, :fcm]
  • [:sparrow, :h2_worker, :handle]

Send your first push notification

  1. Define your config
  2. Start an application
Application.start(:sparrow)
  1. Build and Push the notification 3.1 APNS
        :ok =
            "my_device_token"
            |> Sparrow.APNS.Notification.new(:dev)
            |> Sparrow.APNS.Notification.add_title("my first notification title")
            |> Sparrow.APNS.Notification.add_body("my first notification body")
            # |> Sparrow.APNS.Notification.add_...
            |> Sparrow.API.push()
    3.1 FCM
    android =
        Sparrow.FCM.V1.Android.new()
        |> Sparrow.FCM.V1.Android.add_title("my first notification title")
        |> Sparrow.FCM.V1.Android.add_body("my first notification body")
    
    webpush = 
        Sparrow.FCM.V1.Webpush.new("www.my.test.link.com")
        |> Sparrow.FCM.V1.Webpush.add_title("my first notification title")
        |> Sparrow.FCM.V1.Webpush.add_body("my first notification body")
      
    notification =
        Sparrow.FCM.V1.Notification.new(:topic, "news")
        |> Sparrow.FCM.V1.Notification.add_android(android)
        |> Sparrow.FCM.V1.Notification.add_webpush(webpush)
        Sparrow.API.push()

How to obtain and use APNS certificate for certificate based authorization?

Pre Requirements:

  • MacOS with Xcode installed
  • Apple mobile device
  • Tutorial (*) requirements

First, follow this tutorial (*), specifically the "Step 3, get APNS certificate" section.

When you reach point where you have exampleName.cer file, import it to Keychain Access: File -> Import Items... -> Chose exampleName.cer

Next, export the certificate you just imported as exampleName.p12. Note: you can just go with no password by pressing Enter. If you enter a password, remember it. I shall refer to this password as (pass1) later in tutorial.

Open terminal, go to your exampleName.p12 file location

$ cd my/p12/file/location

Next convert .p12 to .pem:

$ openssl pkcs12 -in `exampleName.p12` -out `exampleName.pem`

Type (pass1), and then exampleName.pem file password (pass2), which cannot be empty.

Next extract key:

openssl rsa -in `exampleName.pem` -out `exampleKey.pem`

How to obtain a device token?

Try this.

How to obtain an apns-topic?

Last but not least, to get the 'apns-topic' header value, go to: Xcode -> open your swift app -> General -> Identity -> Bundle Identifier

Good luck :)

sparrow's People

Contributors

ahamez avatar aleklisi avatar arkgil avatar kamilwaz avatar kmakiela avatar kzemek avatar michalwski avatar rslota avatar zofpolkowska avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sparrow's Issues

Project state and hex.pm

Hello everyone,

I have not found any other feedback channel, so I'm opening an issue for this question. I have been using codedge-llc/pigeon for handling push notifications in the past but am looking for alternatives due to some missing features. (APNS headers)

Sparrow looks like a complete, well-tested implementation of all essential mobile push services. And as far as I can see, has been used in production already, so it would be a perfect fit. Yet, looking at the repository it looks a bit experimental. Is there a reason why this has not been published on hex.pm yet?

Thanks!

Typo in readme

Typo in readme {:sparrow, github: "esl/sprrow", tag: "cc80bbc"},
to {:sparrow, github: "esl/sparrow", tag: "cc80bbc"},

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.