Skip to content

Instantly share code, notes, and snippets.

@jackalcooper
Last active November 3, 2021 18:33
Show Gist options
  • Save jackalcooper/697c8ba2da945fc6dcc07582e2a747ec to your computer and use it in GitHub Desktop.
Save jackalcooper/697c8ba2da945fc6dcc07582e2a747ec to your computer and use it in GitHub Desktop.
Elixir Faye Websocket client example, heartbeat and subscription
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
@mrcampbell
Copy link

What is in the Tuna.eWhine import? This is fantastic, btw!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment