GithubHelp home page GithubHelp logo

danhper / pushex Goto Github PK

View Code? Open in Web Editor NEW
104.0 2.0 7.0 115 KB

Push notifications for Elixir

Home Page: https://hexdocs.pm/pushex

License: MIT License

Elixir 100.00%
elixir apns gcm notifications

pushex's Introduction

Pushex

Build Status Coverage Status

Pushex is a library to easily send push notifications with Elixir.

About

Goals

The main goals are the following:

  • Easy to use async API
  • Common API for iOS and Android
  • Multiple applications handling
  • Proper error and response handling
  • Testable using a sanbox mode

Status

Both GCM and APNS are working. APNS delegates to apns4ex for now, I will probably use the HTTP2 API in a later version.

The API is still subject to change, with a minor version bump for each change.

Installation

Add the following to your dependencies mix.ex.

[{:pushex, "~> 0.2"}]

Then, add :pushex to your applications.

Usage

The most basic usage, with no configuration looks like this:

app = %Pushex.GCM.App{name: "a_unique_name_you_like", auth_key: "a GCM API auth key"}
Pushex.push(%{title: "my_title", body: "my_body"}, to: "registration_id", with_app: app)

To avoid having to create or retreive your app each time, you can configure as many apps as you want in your config.exs:

config :pushex,
  gcm: [
    default_app: "first_app",
    apps: [
      [name: "first_app", auth_key: "a key"],
      [name: "other_app", auth_key: "another key"]
    ]
  ],
  apns: [
    default_app: "first_app",
    apps: [
      [name: "first_app", env: :dev, certfile: "/path/to/certfile", pool_size: 5]
    ]
  ]

You can then do the following:

# this will use the default app, "first_app" with the above configuration
Pushex.push(%{title: "my_title", body: "my_body"}, to: "registration_id", using: :gcm)

# this will use the other_app
Pushex.push(%{title: "my_title", body: "my_body"}, to: "registration_id", using: :gcm, with_app: "other_app")

Note that the function is async and only returns a reference, see the response and error handling documentation for more information.

Sending to multiple platforms

If you want to use the same message for both platforms, you can define messages as follow:

message = %{
  common: "this will be in both payloads",
  other: "this will also be in both payloads",
  apns: %{
    alert: "My alert",
    badge: 1
  },
  gcm: %{
    title: "GCM title",
    body: "My body"
  }
}

Pushex.push(message, to: ["apns_token1", "apns_token2"], using: :apns)
Pushex.push(message, to: ["gcm_registration_id1", "gcm_registration_id2"], using: :gcm)

Only :gcm and :apns are currently available.

Passing more options

If you need to pass options, priority for example, you can just pass it in the keyword list and it will be sent.

See

https://developers.google.com/cloud-messaging/http-server-ref#downstream-http-messages-json

for more information.

The parameters from Table 1 should be passed in the keyword list, while the parameters from Table 2 should be passed in the first argument.

For more information about APNS options, see apns4ex docs.

NOTE: if you pass an array to the to parameter, if will automatically be converted to registration_ids when sending the request, to keep a consistent API.

Loading app from somewhere else

If you are saving your auth_keys in your database, you can override the default way to retreive the apps:

# config.exs
config :pushex,
  app_manager_impl: MyAppManager

# my_app_manager.ex
defmodule MyAppManager do
  @behaviour Pushex.AppManager

  def find_app(platform, name) do
    if app = Repo.get_by(App, platform: platform, name: name) do
      make_app(platform, app)
    end
  end

  # transform to a `Pushex._.App`
  defp make_app(:gcm, app) do
    struct(Pushex.GCM.App, Map.from_struct(app))
  end
  defp make_app(:apns, app) do
    struct(Pushex.APNS.App, Map.from_struct(app))
  end
end

Handling responses

To handle responses, you can define a module using Pushex.EventHandler which uses :gen_event to process events.

# config.exs
config :pushex,
  event_handlers: [MyEventHandler]

# my_event_handler.ex
defmodule MyEventHandler do
  use Pushex.EventHandler

  def handle_event({:request, request, {pid, ref}}, state) do
    # do whatever you want with the request
    # for example, logging or saving in a DB
    {:ok, state}
  end

  def handle_event({:response, response, request, {pid, ref}}, state) do
    # do whatever you want with the response and request
    {:ok, state}
  end
end

The ref passed here is the one returned when calling push.

Testing

Pushex offers a sandbox mode to make testing easier.

To enable it, you should add the following to your configuration:

config :pushex,
  sandbox: true

Once you are using the sandbox, the messages will not be sent to GCM or APNS anymore, but stored in Pushex.Sandbox. Furthermore, all the messages will be returned to the process that sent them. Here is a sample test.

test "send notification to users" do
  ref = Pushex.push(%{body: "my message"}, to: "my-user", using: :gcm)
  pid = self()
  assert_receive {{:ok, response}, request, ^ref}
  assert [{{:ok, ^response}, ^request, {^pid, ^ref}}] = Pushex.Sandbox.list_notifications
end

Note that list_notifications depends on the running process, so if you call it from another process, you need to explicitly pass the pid with the :pid option.

Also note that Pushex.push is asynchronous, so if you remove the assert_receive, you will have a race condition. To avoid this, you can use Pushex.Sandbox.wait_notifications/1 instead of Pushex.Sandbox.list_notifications. It will wait (by default for 100ms) until at least :count notifications arrive

test "send notification to users and wait" do
  Enum.each (1..10), fn _ ->
    Pushex.push(%{body: "foo"}, to: "whoever", using: :gcm)
  end
  notifications = Pushex.Sandbox.wait_notifications(count: 10, timeout: 50)
  assert length(notifications) == 10
end

However, the requests are asynchronous, so there is no guaranty that the notifications in the sandbox will in the same order they have been sent.

pushex's People

Contributors

danhper avatar joe-noh avatar mauricionr 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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

pushex's Issues

Could not start application apns: exited in: APNS.start(:normal, [])

It seems that the documentation is incomplete.

I tried the config with my updated infos in the README example without success it seems that the apns config needs a pools section. Can you update the README.md ?

** (Mix) Could not start application apns: exited in: APNS.start(:normal, [])
    ** (EXIT) an exception was raised:
        ** (Protocol.UndefinedError) protocol Enumerable not implemented for nil
            (elixir) lib/enum.ex:1: Enumerable.impl_for!/1
            (elixir) lib/enum.ex:116: Enumerable.reduce/3
            (elixir) lib/enum.ex:1636: Enum.reduce/3
            (elixir) lib/enum.ex:1188: Enum.map/2
            (apns) lib/apns.ex:35: APNS.start/2
            (kernel) application_master.erl:273: :application_master.start_it_old/4

FCM Support planned?

Hi,

are you planning to support fcm?
The implmentation is very similar to gcm. I think the endpoint is the only difference right now.

UserNotification support

Im trying to send mutable-content and attachment-url to create a customized UserNotification.

but, I don't see this parameters arriving at my Swift App.

Im I doing something wrong? how should I send the mutable-content, no examples in documentation.

regards

Vex validation error

Hello! I'm trying to get Pushex to work and I started with the docs. (of course I replace auth_key and to fields).

Here is what I want to do:
app = %Pushex.GCM.App{name: "a_unique_name_you_like", auth_key: "a GCM API auth key"} Pushex.push(%{title: "my_title", body: "my_body"}, to: "registration_id", with_app: app)

The result that I'm getting is the following:
** (Vex.InvalidValidatorError) validator :type from sources [Vex.Validators] lib/vex.ex:71: Vex.validator/1 lib/vex.ex:46: Vex.result/4 (elixir) lib/enum.ex:1183: Enum."-map/2-lists^map/1-0-"/2 (elixir) lib/enum.ex:1183: Enum."-map/2-lists^map/1-0-"/2 (elixir) lib/enum.ex:1187: anonymous fn/3 in Enum.map/2 (stdlib) lists.erl:1262: :lists.foldl/3 (elixir) lib/enum.ex:1187: Enum.map/2 lib/vex.ex:31: Vex.results/2 lib/vex.ex:24: Vex.errors/2 lib/pushex/util.ex:8: Pushex.Util.validate/2 lib/pushex/util.ex:27: Pushex.Util.create_struct!/2 lib/pushex/helpers.ex:61: Pushex.Helpers.do_send_notification/3

Could anyone point me into a good direction? Is this a bug or my fault ๐Ÿ˜„ ?

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.