All Projects → stepnivlk → pushest

stepnivlk / pushest

Licence: MIT License
Bidirectional Pusher client in Elixir

Programming Languages

elixir
2628 projects

Projects that are alternatives of or similar to pushest

soketi
Just another simple, fast, and resilient open-source WebSockets server. 📣
Stars: ✭ 2,202 (+6572.73%)
Mutual labels:  pusher, websockets
Laravel Websockets Demo
Demo application to use with the Laravel WebSockets package.
Stars: ✭ 286 (+766.67%)
Mutual labels:  pusher, websockets
echo-server
Echo Server is a container-ready, multi-scalable Node.js application used to host your own Socket.IO server for Laravel Broadcasting.
Stars: ✭ 36 (+9.09%)
Mutual labels:  pusher, websockets
Laravel Websockets
Websockets for Laravel. Done right.
Stars: ✭ 4,157 (+12496.97%)
Mutual labels:  pusher, websockets
Dashboard.spatie.be
The source code of dashboard.spatie.be
Stars: ✭ 1,916 (+5706.06%)
Mutual labels:  pusher, websockets
Wsify
Just a tiny, simple and real-time self-hosted pub/sub messaging service
Stars: ✭ 452 (+1269.7%)
Mutual labels:  pusher, websockets
Mercurius
Real-time Messenger for Laravel
Stars: ✭ 309 (+836.36%)
Mutual labels:  pusher, websockets
docs
The official soketi documentation. 📡
Stars: ✭ 55 (+66.67%)
Mutual labels:  pusher, websockets
btc-ticker-esp8266
realtime bitcoin price on 7 segment display with arduino on esp8266
Stars: ✭ 18 (-45.45%)
Mutual labels:  pusher, websockets
gochess
Online real time chess web server using websockets
Stars: ✭ 32 (-3.03%)
Mutual labels:  websockets
dataviewer-example
📊 Usage examples of dataviewer - https://github.com/jasrodis/dataviewer
Stars: ✭ 15 (-54.55%)
Mutual labels:  websockets
simple-websocket-server
A simple WebSocket server
Stars: ✭ 26 (-21.21%)
Mutual labels:  websockets
real-time-todo
A real time todo list using websockets
Stars: ✭ 22 (-33.33%)
Mutual labels:  websockets
push-notifications-php
Pusher Beams PHP Server SDK
Stars: ✭ 31 (-6.06%)
Mutual labels:  pusher
WebSocketPipe
System.IO.Pipelines API adapter for System.Net.WebSockets
Stars: ✭ 17 (-48.48%)
Mutual labels:  websockets
realtime-chat-go-react
An example of a Real-Time Chat Application built using React.js and Go!
Stars: ✭ 61 (+84.85%)
Mutual labels:  websockets
spontit-api-python-wrapper
Send functional, flexible push notifications to iOS, Android, and desktop devices (without your own app or website).
Stars: ✭ 35 (+6.06%)
Mutual labels:  pusher
Geluid
Made with Electron. Streams audio from your soundcard to a browser in an easy way
Stars: ✭ 29 (-12.12%)
Mutual labels:  websockets
megaphone
Hear ye, hear ye 📣
Stars: ✭ 15 (-54.55%)
Mutual labels:  websockets
React-Help-Desk
Help desk style live chat with administrative control panel in React, Node.js and Websockets
Stars: ✭ 29 (-12.12%)
Mutual labels:  websockets

Pushest

Pushest is bidirectional Pusher client leveraging Elixir/OTP to combine server and client-side Pusher features together in one library. Pushest communicates both via WebSockets and REST API. You can trigger on any channel, subscribe to channels, handle events using callbacks or keep track of presence.

Build Status Ebert

TODO

  • Event scoping
  • Presence
  • Unsubscribe method
  • Channels list method
  • Auth token generated only for private/presence channels
  • Missing tests
  • Handle pusher:error
  • Generate documentation
  • :gun.conn monitoring
  • start_link/3 - opts to Pushest
  • Named process option
  • Propagate app version to url
  • Overall error handling
  • Publish to hex.pm
  • Fallback to REST when triggering on a public channel
  • Test recovery from :gun_down / EXIT
  • expose auth function to generate a token for client-side libraries.
  • trigger batching
  • Push notifications
  • Subscribe to a list of channels after startup
  • Full recovery after network outage, exit, etc. Buffer needed.
  • Refactor :gun.conn PID handling.
  • Add a support for testing of modules using Pushest

Usage

A simple implementation in an OTP application would be:

# Add necessary pusher configuration to your application config:
# simple_client/config/config.exs
config :simple_client, SimpleClient,
  pusher_app_id: System.get_env("PUSHER_APP_ID"),
  pusher_key: System.get_env("PUSHER_APP_KEY"),
  pusher_secret: System.get_env("PUSHER_SECRET"),
  pusher_cluster: System.get_env("PUSHER_CLUSTER"),
  pusher_encrypted: true

# simple_client/simple_client.ex
defmodule SimpleClient do
  use Pushest, otp_app: :simple_client

  # Subscribe to these channels right after application startup.
  def init_channels do
    [
      [name: "public-init-channel", user_data: %{}],
      [name: "private-init-channel", user_data: %{}],
      [name: "presence-init-channel", user_data: %{user_id: 123}],
    ]
  end

  # handle_event/2 is user-defined callback which is triggered whenever an event
  # occurs on the channel.
  def handle_event({:ok, "public-init-channel", "some-event"}, frame) do
    # do something with public-init-channel frame
  end

  def handle_event({:ok, "public-channel", "some-event"}, frame) do
    # do something with public-channel frame
  end

  def handle_event({:ok, "private-channel", "some-other-event"}, frame) do
    # do something with private-channel frame
  end
  
  # We can also catch errors.
  def handle_event({:error, msg}, frame) do
    # do something with error
  end
end

# Now you can start your application with Pushest as a part of your supervision tree:
# simple_client/lib/simple_client/application.ex
def start(_type, _args) do
  children = [
    {SimpleClient, []}
  ]

  opts = [strategy: :one_for_one, name: Sup.Supervisor]
  Supervisor.start_link(children, opts)
end

You can also provide Pusher options directly via start_link/1 (without using OTP app configuration):

config = %{
  app_id:  System.get_env("PUSHER_APP_ID"),
  key: System.get_env("PUSHER_APP_KEY"),
  secret: System.get_env("PUSHER_SECRET"),
  cluster: System.get_env("PUSHER_CLUSTER"),
  encrypted: true
}

{:ok, pid} = SimpleClient.start_link(config)

Now you can use various functions injected in your module

SimpleClient.channels()
# => %{
"channels" => %{
  "presence-init-channel" => %{},
  "private-init-channel" => %{},
  "public-init-channel" => %{}
}
# ...
SimpleClient.subscribe("public-channel")
:ok
# ...
SimpleClient.subscribe("private-channel")
:ok
# ...
SimpleClient.subscribe("presence-channel", %{user_id: "1", user_info: %{name: "Tomas"}})
:ok
# ...
SimpleClient.presence()
%Pushest.Data.Presence{
  count: 2,
  hash: %{"1" => %{"name" => "Tomas"}, "2" => %{"name" => "Jose"}},
  ids: ["1", "2"],
  me: %{user_id: "1", user_info: %{name: "Tomas"}}
}
# ...
SimpleClient.trigger("private-channel", "first-event", %{message: "Ahoj"})
:ok
# ...
SimpleClient.subscribed_channels()
["presence-channel", "private-channel", "public-channel",
 "presence-init-channel", "private-init-channel", "public-init-channel"]
# ...
SimpleClient.unsubscribe("public-channel")
:ok

Functions list

subscribe/1

Subscribes to public or private channel

SimpleClient.subscribe("public-channel")
:ok

subscribe/2

Subscribes to private or presence channel with user data as second parameter. User data has to contain user_id key with unique identifier for current user. Can optionally contain user_info field with map of additional informations about user.

user_data = %{user_id: 123, user_info: %{name: "Tomas", email: "[email protected]"}}
SimpleClient.subscribe("presence-channel", user_data)
:ok
# ...
SimpleClient.subscribe("private-channel", user_data)
:ok

trigger/3

Triggers on given channel and event with given data payload. Pushest sends data by default to REST API endpoint of Pusher, however when subscribed to private or presence channel it sends data to Pusher via WebSockets.

SimpleClient.trigger("public-channel", "event", %{message: "message"})
:ok
# ..
SimpleClient.trigger("private-channel", "event", %{message: "message"})
:ok

trigger/4

Same as trigger/3 but lets you force trigger over the REST API (so it never triggers via WebSockets).

SimpleClient.trigger("private-channel", "event", %{message: "message"}, force_api: true)

channels/0

Returns map of all the active channels which are being used in your Pusher application. Can contain informations about subscribed users.

SimpleClient.channels()
%{"channels" => %{"public-channel" => %{}, "private-channel" => %{}}}

subscribed_channels/0

Returns list of all the subscribed channels for current instance.

SimpleClient.subscribed_channels()
["private-channel"]

presence/0

Returns information about all the users subscribed to a presence channel.

SimpleClient.presence()
%Pushest.Data.Presence{
  count: 2,
  hash: %{"1" => %{"name" => "Tomas"}, "2" => %{"name" => "Jose"}},
  ids: ["1", "2"],
  me: %{user_id: "2", user_info: %{name: "Jose"}}
}

unsubscribe/1

Unsubscribes from given channel

SimpleClient.unsubscribe("public-channel")

Overridable functions

These functions are meant to be overridden in a module using Pushest

handle_event/2

Callback being triggered when there is a WebSocket event on a subscribed channel.

defmodule MyApp.MyModule
  use Pushest, otp_app: :my_app

  def handle_event({:ok, "my-channel", "my-event"}, frame) do
    IO.inspect frame
  end
end

init_channels/0

Subscribes to given list of channels right after application startup. Each element has to be a keyword list in exact format of: [name: String.t(), user_data: map]

defmodule MyApp.MyModule
  use Pushest, otp_app: :my_app

  def init_channels do
    [
      [name: "public-init-channel", user_data: %{}],
      [name: "private-init-channel", user_data: %{}],
      [name: "presence-init-channel", user_data: %{user_id: 123}],
    ]
  end
end

frame example

frame is a Pushest.Socket.Data.Frame or Pushest.Api.Data.Frame struct with data payload as a map.

%Pushest.Data.Frame{
  channel: "private-channel",
  data: %{"name" => "John", "message" => "Hello"},
  event: "second-event"
}

Installation

The package can be installed by adding pushest to your list of dependencies in mix.exs:

def deps do
  [
    {:pushest, "~> 0.2.2"}
  ]
end

Documentation

Documentation can be be found at https://hexdocs.pm/pushest.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].