Packages
pigeon
0.9.0
2.0.1
2.0.0
2.0.0-rc.3
2.0.0-rc.2
2.0.0-rc.1
2.0.0-rc.0
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.4.0
1.3.2
1.3.1
1.3.0
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.1.0-rc.1
1.1.0-rc.0
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.13.1
0.13.0
0.12.1
0.12.0
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.1
0.9.0
0.8.0
0.7.0
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
iOS (APNS), Android (FCM), and Amazon Android (ADM) push notifications for Elixir.
Current section
57 Versions
Jump to
Current section
57 Versions
Compare versions
6
files changed
+50
additions
-30
deletions
| @@ -5,12 +5,15 @@ | |
| 5 5 | HTTP2-compliant wrapper for sending iOS and Android push notifications. |
| 6 6 | |
| 7 7 | ## Installation |
| 8 | - Add pigeon as a `mix.exs` dependency: |
| 9 | - |
| 10 8 | **Note: Pigeon's API will likely change until v1.0** |
| 9 | + |
| 10 | + Add pigeon and chatterbox as `mix.exs` dependencies: |
| 11 11 | ```elixir |
| 12 12 | def deps do |
| 13 | - [{:pigeon, "~> 0.8.0"}] |
| 13 | + [ |
| 14 | + {:pigeon, "~> 0.8.0"}, |
| 15 | + {:chatterbox, github: "joedevivo/chatterbox"} |
| 16 | + ] |
| 14 17 | end |
| 15 18 | ``` |
| 16 19 | |
| @@ -91,7 +94,7 @@ or | |
| 91 94 | |
| 92 95 | 2. Create a notification packet. **Note: Your push topic is generally the app's bundle identifier.** |
| 93 96 | ```elixir |
| 94 | - n = Pigeon.APNS.Notification.new("your message", "your device token", "your push topic") |
| 97 | + n = Pigeon.APNS.Notification.new("your message", "your device token", "your push topic (optional)") |
| 95 98 | ``` |
| 96 99 | |
| 97 100 | |
| @@ -104,6 +107,7 @@ or | |
| 104 107 | The contents of `payload` is what will be received on the iOS device. If updating this field directly, use strings for your keys. It is recommended to use the convenience functions defined in *Notifications with Custom Data*. `expiration` is a UNIX epoch date in seconds (UTC). Passing a value of `0` expires the notification immediately and Apple will not attempt to redeliver it. |
| 105 108 | ```elixir |
| 106 109 | %Pigeon.APNS.Notification{ |
| 110 | + id: nil, |
| 107 111 | device_token: nil, |
| 108 112 | topic: nil, |
| 109 113 | expiration: nil, |
| @@ -141,6 +145,7 @@ Notifications can contain additional information in `payload`. (e.g. setting bad | |
| 141 145 | |> put_badge(5) |
| 142 146 | |> put_sound("default") |
| 143 147 | |> put_content_available |
| 148 | + |> put_mutable_content |
| 144 149 | |> put_category("category") |
| 145 150 | ``` |
| @@ -21,4 +21,4 @@ | |
| 21 21 | {<<"name">>,<<"httpoison">>}, |
| 22 22 | {<<"optional">>,false}, |
| 23 23 | {<<"requirement">>,<<"~> 0.7">>}]]}. |
| 24 | - {<<"version">>,<<"0.8.0">>}. |
| 24 | + {<<"version">>,<<"0.9.0">>}. |
| @@ -95,9 +95,9 @@ defmodule Pigeon.APNSWorker do | |
| 95 95 | req_headers = [ |
| 96 96 | {":method", "POST"}, |
| 97 97 | {":path", "/3/device/#{notification.device_token}"}, |
| 98 | - {"apns-topic", notification.topic}, |
| 99 98 | {"content-length", "#{byte_size(json)}"}] |
| 100 99 | |> put_apns_id(notification) |
| 100 | + |> put_apns_topic(notification) |
| 101 101 | |
| 102 102 | :h2_client.send_request(socket, req_headers, json) |
| 103 103 | new_q = Map.put(queue, "#{stream_id}", {notification, on_response}) |
| @@ -112,9 +112,16 @@ defmodule Pigeon.APNSWorker do | |
| 112 112 | end |
| 113 113 | end |
| 114 114 | |
| 115 | + defp put_apns_topic(headers, notification) do |
| 116 | + case notification.topic do |
| 117 | + nil -> headers |
| 118 | + topic -> headers ++ [{"apns-topic", topic}] |
| 119 | + end |
| 120 | + end |
| 121 | + |
| 115 122 | defp parse_error(data) do |
| 116 123 | {:ok, response} = Poison.decode(data) |
| 117 | - response["reason"] |> Mix.Utils.underscore |> String.to_atom |
| 124 | + response["reason"] |> Macro.underscore |> String.to_existing_atom |
| 118 125 | end |
| 119 126 | |
| 120 127 | defp log_error(reason, notification) do |
| @@ -18,37 +18,43 @@ defmodule Pigeon.GCM do | |
| 18 18 | @spec push(Pigeon.GCM.Notification) :: none |
| 19 19 | def push(notification) do |
| 20 20 | gcm_key = Application.get_env(:pigeon, :gcm_key) |
| 21 | - requests = |
| 22 | - notification.registration_id |
| 23 | - |> chunk_registration_ids |
| 24 | - |> encode_requests(notification.payload) |
| 25 | - |
| 26 | - response = fn({_reg_ids, payload}) -> |
| 27 | - HTTPoison.post(gcm_uri, payload, gcm_headers(gcm_key)) |
| 28 | - end |
| 29 | - |
| 30 | - for r <- requests, do: Task.async(fn -> response.(r) end) |
| 31 | - :ok |
| 21 | + do_push(notification, %{gcm_key: gcm_key}) |
| 32 22 | end |
| 33 23 | |
| 34 24 | @doc """ |
| 35 25 | Sends a push over GCM and executes function on success/failure. |
| 36 26 | """ |
| 37 27 | @spec push(Pigeon.GCM.Notification, (() -> none)) :: none |
| 38 | - def push(notification, on_response) do |
| 28 | + def push(notification, on_response) when is_function(on_response) do |
| 39 29 | gcm_key = Application.get_env(:pigeon, :gcm_key) |
| 30 | + do_push(notification, %{gcm_key: gcm_key}, on_response) |
| 31 | + end |
| 32 | + |
| 33 | + def push(notification, config, on_response \\ nil) do |
| 34 | + do_push(notification, config, on_response) |
| 35 | + end |
| 36 | + |
| 37 | + defp do_push(notification, %{gcm_key: gcm_key}, on_response \\ nil) do |
| 40 38 | requests = |
| 41 39 | notification.registration_id |
| 42 40 | |> chunk_registration_ids |
| 43 41 | |> encode_requests(notification.payload) |
| 44 42 | |
| 45 | - response = fn({reg_ids, payload}) -> |
| 46 | - {:ok, %HTTPoison.Response{status_code: status, body: body}} = |
| 47 | - HTTPoison.post(gcm_uri, payload, gcm_headers(gcm_key)) |
| 43 | + response = |
| 44 | + case on_response do |
| 45 | + nil -> |
| 46 | + fn({_reg_ids, payload}) -> |
| 47 | + HTTPoison.post(gcm_uri, payload, gcm_headers(gcm_key)) |
| 48 | + end |
| 49 | + _ -> |
| 50 | + fn({reg_ids, payload}) -> |
| 51 | + {:ok, %HTTPoison.Response{status_code: status, body: body}} = |
| 52 | + HTTPoison.post(gcm_uri, payload, gcm_headers(gcm_key)) |
| 48 53 | |
| 49 | - notification = %{ notification | registration_id: reg_ids } |
| 50 | - process_response(status, body, notification, on_response) |
| 51 | - end |
| 54 | + notification = %{ notification | registration_id: reg_ids } |
| 55 | + process_response(status, body, notification, on_response) |
| 56 | + end |
| 57 | + end |
| 52 58 | for r <- requests, do: Task.async(fn -> response.(r) end) |
| 53 59 | :ok |
| 54 60 | end |
| @@ -125,7 +131,7 @@ defmodule Pigeon.GCM do | |
| 125 131 | if is_nil(error) do |
| 126 132 | parse_success(result) |
| 127 133 | else |
| 128 | - error_atom = error |> Mix.Utils.underscore |> String.to_atom |
| 134 | + error_atom = error |> Macro.underscore |> String.to_existing_atom |
| 129 135 | {:error, error_atom} |
| 130 136 | end |
| 131 137 | end |
| @@ -21,7 +21,7 @@ defmodule Pigeon.APNS.Notification do | |
| 21 21 | """ |
| 22 22 | defstruct device_token: nil, payload: %{"aps" => %{}}, expiration: nil, topic: nil, id: nil |
| 23 23 | |
| 24 | - def new(msg, token, topic) do |
| 24 | + def new(msg, token, topic \\ nil) do |
| 25 25 | %Pigeon.APNS.Notification{ |
| 26 26 | device_token: token, |
| 27 27 | topic: topic, |
| @@ -48,6 +48,8 @@ defmodule Pigeon.APNS.Notification do | |
| 48 48 | |
| 49 49 | def put_category(notification, category), do: update_payload(notification, "category", category) |
| 50 50 | |
| 51 | + def put_mutable_content(notification), do: update_payload(notification, "mutable-content", 1) |
| 52 | + |
| 51 53 | defp update_payload(notification, key, value) do |
| 52 54 | new_aps = |
| 53 55 | notification.payload |
Loading more files…