Last active
November 3, 2021 18:33
-
-
Save jackalcooper/697c8ba2da945fc6dcc07582e2a747ec to your computer and use it in GitHub Desktop.
Elixir Faye Websocket client example, heartbeat and subscription
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Tuna.Client.FayeWebsocket do | |
import Tuna.Ewhine | |
require Logger | |
import Tuna.Ewhine | |
use Maxwell.Builder, ~w(get post)a | |
adapter Maxwell.Adapter.Ibrowse | |
middleware Maxwell.Middleware.BaseUrl, endpoint | |
middleware Maxwell.Middleware.Headers, %{ | |
"Content-Type" => "application/json", | |
# "User-Agent" => "Subway", | |
# "Content-Type" => "application/x-www-form-urlencoded" | |
} | |
middleware Maxwell.Middleware.Opts, [connect_timeout: 5000, recv_timeout: 10000] | |
middleware Maxwell.Middleware.Json | |
def connect_socket(client_id, account_channel) do | |
socket = Socket.Web.connect! faye, path: "/comet" | |
send_heart_beat(socket, client_id, 2) | |
connect_socket(socket, client_id, 1, account_channel) | |
end | |
# "account_channel" => "/u/--Q1DTWcRLbX856MJen59Q" | |
def connect_socket(socket, client_id, id, account_channel, second \\ 0) do | |
case socket |> Socket.Web.recv! do | |
{:text, data} -> | |
Logger.debug data | |
data = data | |
|> Poison.decode! | |
|> List.last | |
case data do | |
%{"id" => id_new} -> | |
id_new = String.to_integer(id_new) | |
id = if id_new > id, do: id_new, else: id | |
case id_new do | |
2 -> | |
subscribe(socket, client_id, "#{account_channel}/messages", id + 1) | |
3 -> | |
subscribe(socket, client_id, "#{account_channel}", id + 1) | |
4 -> | |
send_heart_beat(socket, client_id, id + 1) | |
_ -> | |
send_heart_beat(socket, client_id, id + 1) | |
end | |
_ -> | |
id = 0 | |
end | |
socket |> Socket.Web.send!({:ping, ""}) | |
{:pong, _ } -> | |
Logger.debug "pong from server" | |
{:ping, _ } -> | |
Logger.debug "ping from server" | |
socket |> Socket.Web.send!({:pong, ""}) | |
{:close, :normal, ""} -> | |
id = 0 | |
{:close, :abnormal, nil} -> | |
id = 0 | |
end | |
connect_socket(socket, client_id, id, account_channel, second + 1) | |
end | |
def connect_socket(socket, client_id, 0, _account_channel, _second) do | |
Logger.debug "quit" | |
end | |
def send_heart_beat(socket, client_id, id) do | |
str = | |
""" | |
[ | |
{ | |
"channel": "/meta/connect", | |
"clientId": "#{client_id}", | |
"connectionType": "websocket", | |
"id": "#{id}", | |
"accountId": 666, | |
"clientType": 0 | |
} | |
] | |
""" | |
Socket.Web.send!(socket, {:text, str}) | |
end | |
def subscribe(socket, client_id, subscription, id) do | |
str = | |
""" | |
[ | |
{ | |
"channel": "/meta/subscribe", | |
"clientId": "#{client_id}", | |
"subscription": "#{subscription}", | |
"id": "#{id}", | |
"accountId": 666, | |
"clientType": 0 | |
} | |
] | |
""" | |
Socket.Web.send!(socket, {:text, str}) | |
end | |
def hand_shake do | |
params = """ | |
[ | |
{ | |
"channel": "/meta/handshake", | |
"version": "1.0", | |
"supportedConnectionTypes": [ | |
"websocket", | |
"eventsource", | |
"long-polling", | |
"cross-origin-long-polling", | |
"callback-polling" | |
], | |
"id": "1", | |
"accountId": 666, | |
"clientType": 0 | |
} | |
] | |
""" |> Poison.decode! | |
{:ok, client_id} = new | |
|> put_path("/comet") | |
|> put_req_body(params) | |
|> post! | |
|> get_resp_body | |
|> List.first | |
|> Map.fetch("clientId") | |
client_id | |
end | |
#Tuna.Client.FayeWebsocket.test | |
def test do | |
resp_body = Tuna.Client.login_resp_body!(%{login_name: "t16", password: "111111"}) | |
%{"user_info" => %{"account_channel" => account_channel}} = resp_body | |
client_id = Tuna.Client.FayeWebsocket.hand_shake | |
Tuna.Client.FayeWebsocket.connect_socket(client_id, account_channel) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
What is in the Tuna.eWhine import? This is fantastic, btw!