• Stars
    star
    104
  • Rank 323,613 (Top 7 %)
  • Language
    Elixir
  • License
    MIT License
  • Created over 8 years ago
  • Updated almost 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Push notifications for Elixir

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.

More Repositories

1

atomic-chrome

Edit Chrome textareas in Atom
JavaScript
916
star
2

fundle

A minimalist package manager for fish shell
Shell
363
star
3

opencov

Open source code coverage history webapp
Elixir
312
star
4

fish-ssh-agent

Shell
288
star
5

ex_cli

User friendly CLI apps for Elixir
Elixir
215
star
6

python-i18n

Easy to use i18n library for Python
Python
201
star
7

structomap

Easily and dynamically generate maps from Go static structures
Go
141
star
8

elixir-browser

Browser detection for Elixir
Elixir
95
star
9

atomic-chrome-atom

Edit Chrome textareas in Atom
CoffeeScript
93
star
10

elixir-temp

Temporary files and directories for Elixir
Elixir
74
star
11

plug-navigation-history

Elixir plug to keep navigation history
Elixir
69
star
12

elixir-git-cli

A simple interface to Git CLI for Elixir
Elixir
68
star
13

phoenix-active-link

Elixir/Phoenix view helper to manage "active" state of a link
Elixir
63
star
14

elixir-web-push-encryption

Elixir implementation of Web Push Payload encryption.
Elixir
54
star
15

bigcode-tools

Set of tools to help working with "Big Code"
Python
43
star
16

rust-simple-nn

Simple neural network implementation in Rust
Rust
33
star
17

seedex

Seed data generation for Ecto
Elixir
29
star
18

securerandom

Go
25
star
19

evm-analyzer

Code for Smart Contract Vulnerabilities: Vulnerable Does Not Imply Exploited
OCaml
22
star
20

fish-fastdir

Fast directory navigation for fish
Shell
19
star
21

asdf-exec

Native command to run asdf shims
Go
16
star
22

suplearn-clone-detection

Cross language clone detection using supervised learning
Python
16
star
23

node-git-cli

Simple CLI like git interface for Node.
CoffeeScript
16
star
24

defi-plf-analysis

Code and data for the paper: DeFi Protocols for Loanable Funds: Interest Rates, Liquidity and Market Efficiency
Jupyter Notebook
13
star
25

scalog

Datalog implementation in Scala.
Scala
12
star
26

atom-align-regexp

Regexp based alignment for Atom
JavaScript
11
star
27

koa-police

Policy based authentication library for Koa
JavaScript
9
star
28

fontawesome-icons-list

Fontawesome icons list
JavaScript
9
star
29

blockchain-analyzer

Tool to fetch and analyze blockchain transactions
Go
9
star
30

fish-kubectl

Shell
8
star
31

oh-my-fish-core

oh-my-fish core library extracted
Shell
7
star
32

sigma-bower

Bower repository for SigmaJS
JavaScript
6
star
33

dotfiles

TeX
5
star
34

ecto-secure-password

has_secure_password for Ecto models
Elixir
5
star
35

ocaml-monads

OCaml
5
star
36

fish-completion-helpers

Fish helper functions to simplify completions
Shell
5
star
37

wedding

Simple webapp to manage guests and invitations for my wedding with Ai.
Ruby
4
star
38

go-sqs-client

Go
4
star
39

ethereum-tools

Python
4
star
40

simple-bitcoin-parser

Simple Python Bitcoin parser/formatter implementation
Python
4
star
41

flashcards-cli

Text-based flashcards
OCaml
3
star
42

phd-thesis

TeX
3
star
43

deepsentence

和文文書からの要点抽出
Python
3
star
44

scala-simple-compiler

Scala
3
star
45

code-battle

HTML
3
star
46

fish-nvm

nvm wrapper for fish
Shell
3
star
47

meditable

WIP: markdown <-> html
JavaScript
2
star
48

fish-asdf

fish plugin for asdf vm
Shell
2
star
49

projare

Sample app using Elixir, Phoenix and RiotJS
JavaScript
2
star
50

sublime-file-commands

Commands to work with files in Sublime Text
Python
2
star
51

advent-2022

Rust
2
star
52

elixir-logger-sample

Elixir
2
star
53

websocket-rails-bower

1
star
54

master-thesis

A study of machine learning approaches to cross-language code clone detection
TeX
1
star
55

advent-2020

Haskell
1
star
56

advent-2023

F#
1
star
57

vim-config

Vim Script
1
star
58

go-ethereum-customized

Fork of the official geth client
Go
1
star
59

word-frequency-analyzer

Simple word frequency analyzer with JavaFX rendering.
Scala
1
star
60

bachelor-thesis

Repository for my bachelor thesis
TeX
1
star
61

js-easy-params

Decorator for JS functions with optional arguments
JavaScript
1
star
62

scala-x-server

System to run an X server in a web browser
Scala
1
star
63

jsurl_ex

Elixir
1
star
64

tokyo-ex-1-slides

HTML
1
star
65

erlang-sqs-client

Erlang
1
star
66

revealjs-jade-starter

HTML
1
star
67

sublime-rails-status-snippets

ST2/3 snippets for HTTP codes symbols in RoR
Python
1
star
68

ansible-exrm

1
star
69

koa-police-jwt

JWT strategy for koa-police
JavaScript
1
star
70

django-twitter-auth-sample

Python
1
star
71

aleth

C++
1
star