Pigeon Elixir Library

repository·main·Indexed 20 days ago

https://github.com/codedge-llc/pigeon

An Elixir library for sending push notifications to iOS (APNS), Android (FCM), and Amazon Android (ADM). It supports synchronous and asynchronous pushing, dynamic runtime dispatchers, and custom adapter implementation via Pigeon.Adapter. Features include built-in support for Pigeon.APNS, Pigeon.FCM (v1 API), and Pigeon.ADM, with comprehensive handling for service-specific authentication and error responses.

Tokens
20.7K
Snippets
55
Records
70
Agent score
63%

What's inside Pigeon

  1. Create dynamic runtime dispatchers

    main
    For advanced use cases—such as supporting dozens of different dispatcher configurations or implementing custom connection pools—you can use Pigeon to spin up dynamic dispatchers at runtime. Refer to the Pigeon.Dispatcher documentation for implementation details.
  2. Handle push responses and errors

    main

    When calling Pigeon.FCM.push/2, you can provide an optional anonymous function as the second argument to handle the response. This is useful for managing device registration lifecycles (e.g., removing invalid IDs) or handling authentication errors.

    Common patterns include checking n.status and using helper functions like FCM.Notification.remove?(n) or FCM.Notification.retry?(n) to manage the registration list.

    on_response = fn(n) ->
      case n.status do
        :success ->
          bad_regids = FCM.Notification.remove?(n)
          to_retry = FCM.Notification.retry?(n)
          # Handle updated regids, remove bad ones, etc
        :unauthorized ->
          # Bad FCM key
        error ->
          # Some other error
      end
    end
    
    data = %{message: "your message"}
    n = Pigeon.FCM.Notification.new("your device token", data)
    Pigeon.FCM.push(n, on_response: on_response)
  3. Send a push notification via FCM

    main

    To send a notification, create a %Pigeon.FCM.Notification{} struct using Pigeon.FCM.Notification.new/2 and pass it to Pigeon.FCM.push/1.

    Pushes are synchronous and return the notification struct with updated :status and :response keys. If :status is :success, the :response key will contain a keyword list of individual registration ID responses.

    # 1. Create a notification packet
    msg = %{"body" => "your message"}
    n = Pigeon.FCM.Notification.new("your device registration ID", msg)
    
    # 2. Send the packet
    Pigeon.FCM.push(n)
  4. Configure and supervise a Pigeon push worker in v2.0

    main

    In Pigeon v2.0, you define a worker module using Pigeon.Dispatcher and supervise it in your application tree. You can pass configuration either via your application's config.exs or directly as arguments to the worker in the supervision tree.

    Option 1: Configuration via config.exs

    1. Define the worker module:
    # lib/your_app/apns.ex
    defmodule YourApp.APNS do
      use Pigeon.Dispatcher, otp_app: :your_app
    end
    1. Configure the module in config.exs:
    # config.exs
    config :your_app, YourApp.APNS, 
      adapter: Pigeon.APNS, 
      cert: File.read!("cert.pem"), 
      key: File.read!("key_unencrypted.pem"), 
      mode: :dev
    1. Add to supervision tree:
    defmodule YourApp.Application do
      use Application
    
      def start(_type, _args) do
        children = [YourApp.APNS]
        opts = [strategy: :one_for_one, name: YourApp.Supervisor]
        Supervisor.start_link(children, opts)
      end
    end

    Option 2: Configuration via Supervision Arguments

    You can pass configuration directly when starting the child in the supervision tree:

    defmodule YourApp.Application do
      use Application
    
      def start(_type, _args) do
        children = [{YourApp.APNS, apns_opts()}]
        opts = [strategy: :one_for_one, name: YourApp.Supervisor]
        Supervisor.start_link(children, opts)
      end
    
      defp apns_opts do
        [
          adapter: Pigeon.APNS,
          cert: File.read!("cert.pem"),
          key: File.read!("key_unencrypted.pem"),
          mode: :dev
        ]
      end
    end
  5. Send a push notification via ADM

    main

    To send a notification, first create a notification packet using Pigeon.ADM.Notification.new/2 with the device registration ID and the message payload. Then, pass that packet to Pigeon.ADM.push/1.

    msg = %{ "body" => "your message" }
    n = Pigeon.ADM.Notification.new("your device registration ID", msg)
    Pigeon.ADM.push(n)
  6. Install Pigeon via mix

    main

    To use Pigeon in your Elixir project, add it to your mix.exs dependencies. It is recommended to use the ~> 2.0 version constraint for compatibility with the v2 series.

    def deps do
      [
        {:pigeon, "~> 2.0"}
      ]
    end
  7. Send an APNS push notification

    main

    To send a push notification, create a notification packet using Pigeon.APNS.Notification.new/3 and then pass it to Pigeon.APNS.push/2.

    Note: The topic parameter is generally your app's bundle identifier.

    Pushes are synchronous by default and return the notification struct with an updated :response key.

    n = Pigeon.APNS.Notification.new("your message", "your device token", "your push topic (optional)")
    Pigeon.APNS.push(n)
  8. Migrate to synchronous push behavior

    main

    In Pigeon v1.1.0 and later, pushes are synchronous by default for all services. If you require asynchronous functionality, you must pass an :on_response callback as an option to the push/2 function.

    # Synchronous push (default)
    Pigeon.push(notification, options)
    
    # Asynchronous push
    Pigeon.push(notification, [on_response: fn response -> ... end])
  9. Migrate from Pigeon v1.6 to v2.0

    main

    To upgrade from version 1.6 to 2.0, you must update your dependencies and change how push workers are supervised and configured.

    1. Update Dependencies

    Update your mix.exs to use ~> 2.0 and remove the kadadbra dependency.

    2. Update Push Worker Supervision

    In v2.0, push workers are no longer started under Pigeon. Instead, you must define a module that uses Pigeon.Dispatcher and add it directly to your application's supervision tree.

    3. Update Configuration

    Configuration is no longer handled via the :pigeon configuration key. Instead, configure your worker module directly under your application's name.

    # mix.exs
    [ 
      {:pigeon, "~> 2.0"}, 
      # Remove {:kadadbra, ~> 0.6.0}
    ]