69 lines
2.0 kB
1
defmodule BlogWeb.SkeetChannel do
2
use Phoenix.Channel
3
require Logger
4
5
@max_body_length 250
6
@max_handle_length 16
7
@table_name :skeet_messages
8
9
def join("skeet:lobby", _params, socket) do
10
# Create ETS table if it doesn't exist
11
:ets.new(@table_name, [:set, :public, :named_table, read_concurrency: true])
12
{:ok, socket}
13
rescue
14
ArgumentError ->
15
# Table already exists
16
{:ok, socket}
17
end
18
19
def handle_in("new_message", %{"body" => body, "user" => user, "reply_to" => reply_to}, socket) do
20
with {:ok, body} <- validate_body(body),
21
{:ok, user} <- validate_user(user),
22
{:ok, reply_to} <- validate_reply_to(reply_to) do
23
message = %{
24
id: generate_sha(),
25
body: body,
26
user: user,
27
reply_to: reply_to,
28
created_at: DateTime.utc_now()
29
}
30
31
:ets.insert(@table_name, {message.id, message})
32
broadcast!(socket, "new_message", message)
33
34
{:reply, {:ok, message}, socket}
35
else
36
{:error, reason} ->
37
{:reply, {:error, %{reason: reason}}, socket}
38
end
39
end
40
41
defp validate_body(body) when is_binary(body) do
42
if String.length(body) <= @max_body_length do
43
{:ok, body}
44
else
45
{:error, "Body exceeds maximum length of #{@max_body_length} characters"}
46
end
47
end
48
49
defp validate_body(_), do: {:error, "Body must be a string"}
50
51
defp validate_user(user) when is_binary(user) do
52
if String.length(user) <= @max_handle_length do
53
{:ok, user}
54
else
55
{:error, "User handle exceeds maximum length of #{@max_handle_length} characters"}
56
end
57
end
58
59
defp validate_user(_), do: {:error, "User handle must be a string"}
60
61
defp validate_reply_to(nil), do: {:ok, nil}
62
defp validate_reply_to(reply_to) when is_binary(reply_to), do: {:ok, reply_to}
63
defp validate_reply_to(_), do: {:error, "Reply_to must be nil or a string"}
64
65
defp generate_sha do
66
:crypto.strong_rand_bytes(20)
67
|> Base.encode16(case: :lower)
68
end
69
end
70