Skip to content

Commit

Permalink
Merge pull request #210 from meppu/switch-to-better-libs
Browse files Browse the repository at this point in the history
General improvements for Lanyard
  • Loading branch information
Phineas authored Jun 28, 2023
2 parents 888052f + 17a0c69 commit 7b10c43
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 100 deletions.
26 changes: 13 additions & 13 deletions config/runtime.exs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import Config

if config_env() == :prod do
config :lanyard,
http_port: String.to_integer(System.get_env("PORT") || "4001"),
discord_spotify_activity_id: "spotify:1",
command_prefix: System.get_env("COMMAND_PREFIX") || ".",
bot_presence: System.get_env("BOT_PRESENCE") || "you <3",
bot_presence_type: String.to_integer(System.get_env("BOT_PRESENCE_TYPE") || "3"),
bot_token: System.get_env("BOT_TOKEN"),
redis_uri:
System.get_env("REDIS_DSN") || System.get_env("REDIS_URI") || System.get_env("REDIS_URL")
end
import Config

if config_env() == :prod do
config :lanyard,
http_port: String.to_integer(System.get_env("PORT") || "4001"),
discord_spotify_activity_id: "spotify:1",
command_prefix: System.get_env("COMMAND_PREFIX") || ".",
bot_presence: System.get_env("BOT_PRESENCE") || "you <3",
bot_presence_type: String.to_integer(System.get_env("BOT_PRESENCE_TYPE") || "3"),
bot_token: System.get_env("BOT_TOKEN"),
redis_uri:
System.get_env("REDIS_DSN") || System.get_env("REDIS_URI") || System.get_env("REDIS_URL")
end
8 changes: 8 additions & 0 deletions lib/api/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ defmodule Lanyard.Api.Router do
Util.respond(conn, {:ok, response})
end

get "/socket" do
conn = %Plug.Conn{query_params: params} = fetch_query_params(conn)

conn
|> WebSockAdapter.upgrade(Lanyard.SocketHandler, params, timeout: 60_000)
|> halt()
end

forward("/v1", to: V1)
forward("/discord", to: Discord)
forward("/metrics", to: Metrics)
Expand Down
21 changes: 18 additions & 3 deletions lib/api/routes/quicklinks/discord_cdn.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule Lanyard.Api.Quicklinks.DiscordCdn do
alias Lanyard.Api.Util

import Plug.Conn
import Bitwise

@discord_cdn "https://cdn.discordapp.com"

Expand All @@ -16,7 +17,7 @@ defmodule Lanyard.Api.Quicklinks.DiscordCdn do

case presence do
{:ok, p} ->
{:ok, %HTTPoison.Response{body: b, headers: h, status_code: status_code}} =
{:ok, %Finch.Response{body: b, headers: h, status: status_code}} =
get_proxied_avatar(
user_id,
p.discord_user.avatar,
Expand All @@ -26,6 +27,7 @@ defmodule Lanyard.Api.Quicklinks.DiscordCdn do

conn
|> merge_resp_headers(h)
|> delete_resp_header("content-length")
|> send_resp(status_code, b)

error ->
Expand All @@ -36,11 +38,24 @@ defmodule Lanyard.Api.Quicklinks.DiscordCdn do
defp get_proxied_avatar(id, avatar, _discriminator, file_type) when is_binary(avatar) do
constructed_cdn_url = "#{@discord_cdn}/avatars/#{id}/#{avatar}.#{file_type}?size=1024"

HTTPoison.get(constructed_cdn_url)
:get
|> Finch.build(constructed_cdn_url)
|> Finch.request(Lanyard.Finch)
end

defp get_proxied_avatar(id, avatar, "0", _file_type) when is_nil(avatar) do
mod = Integer.mod(String.to_integer(id) >>> 22, 6)

:get
|> Finch.build("#{@discord_cdn}/embed/avatars/#{mod}.png")
|> Finch.request(Lanyard.Finch)
end

defp get_proxied_avatar(_id, avatar, discriminator, _file_type) when is_nil(avatar) do
mod = Integer.mod(String.to_integer(discriminator), 5)
HTTPoison.get("#{@discord_cdn}/embed/avatars/#{mod}.png")

:get
|> Finch.build("#{@discord_cdn}/embed/avatars/#{mod}.png")
|> Finch.request(Lanyard.Finch)
end
end
2 changes: 1 addition & 1 deletion lib/api/routes/v1/users.ex
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ defmodule Lanyard.Api.Routes.V1.Users do
case validate_resource_access(conn) do
:ok ->
try do
{:ok, parsed} = Poison.decode(body)
{:ok, parsed} = Jason.decode(body)

Enum.each(parsed, fn {k, v} ->
with {:error, _reason} = err <- Lanyard.KV.Interface.validate_pair({k, v}) do
Expand Down
4 changes: 2 additions & 2 deletions lib/api/util.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ defmodule Lanyard.Api.Util do
def respond(conn, {:ok, data}) do
conn
|> put_resp_content_type("application/json")
|> send_resp(200, Poison.encode!(%{success: true, data: data}))
|> send_resp(200, Jason.encode!(%{success: true, data: data}))
end

@spec respond(Plug.Conn.t(), {:error, atom, binary}) :: Plug.Conn.t()
Expand All @@ -32,7 +32,7 @@ defmodule Lanyard.Api.Util do
|> put_resp_content_type("application/json")
|> send_resp(
http_code,
Poison.encode!(%{
Jason.encode!(%{
success: false,
error: %{
code: Atom.to_string(code),
Expand Down
18 changes: 11 additions & 7 deletions lib/bot/discord_api.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,32 @@ defmodule Lanyard.DiscordBot.DiscordApi do
content
|> String.replace("@", "@​\u200b")

HTTPoison.post(
:post
|> Finch.build(
"#{@api_host}/channels/#{channel_id}/messages",
Poison.encode!(%{content: sanitized_content}),
[
{"Authorization", "Bot " <> Application.get_env(:lanyard, :bot_token)},
{"Content-Type", "application/json"}
]
],
Jason.encode!(%{content: sanitized_content})
)
|> Finch.request(Lanyard.Finch)
end

def create_dm(recipient) do
{:ok, response} =
HTTPoison.post(
:post
|> Finch.build(
"#{@api_host}/users/@me/channels",
Poison.encode!(%{recipient_id: recipient}),
[
{"Authorization", "Bot " <> Application.get_env(:lanyard, :bot_token)},
{"Content-Type", "application/json"}
]
],
Jason.encode!(%{recipient_id: recipient})
)
|> Finch.request(Lanyard.Finch)

case Poison.decode!(response.body) do
case Jason.decode!(response.body) do
%{"id" => id} ->
id

Expand Down
4 changes: 2 additions & 2 deletions lib/gateway/utility.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ defmodule Lanyard.Gateway.Utility do
load
|> _update_payload(seq_num, "s", seq_num)
|> _update_payload(event_name, "t", seq_num)
|> Poison.encode!()
|> Jason.encode!()
end

@doc "Decode binary payload received from discord into a map"
Expand All @@ -42,7 +42,7 @@ defmodule Lanyard.Gateway.Utility do
@doc "Decode json payload received from discord into a map"
@spec payload_decode(list(), {:text, binary()}) :: map
def payload_decode(codes, {:text, payload}) do
payload = Poison.decode!(payload)
payload = Jason.decode!(payload)

%{
op: opcode(codes, payload[:op] || payload["op"]),
Expand Down
24 changes: 4 additions & 20 deletions lib/lanyard.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,16 @@ defmodule Lanyard do
:ets.new(:analytics, [:named_table, :set, :public])

children = [
{Finch, name: Lanyard.Finch},
{GenRegistry, worker_module: Lanyard.Presence},
{Lanyard.Metrics, :normal},
Plug.Cowboy.child_spec(
scheme: :http,
plug: Lanyard.Router,
options: [
port: Application.get_env(:lanyard, :http_port),
dispatch: dispatch(),
protocol_options: [idle_timeout: :infinity]
]
),
{Lanyard.Connectivity.Redis, []},
{Lanyard.DiscordBot, %{token: Application.get_env(:lanyard, :bot_token)}},
{Lanyard.Connectivity.Redis, []}
{Bandit,
plug: Lanyard.Api.Router, scheme: :http, port: Application.get_env(:lanyard, :http_port)}
]

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

defp dispatch do
[
{:_,
[
{"/socket", Lanyard.SocketHandler, []},
{:_, Plug.Cowboy.Handler, {Lanyard.Api.Router, []}}
]}
]
end
end
3 changes: 3 additions & 0 deletions lib/presence/presence.ex
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
defmodule Lanyard.Presence.PublicFields do
@derive Jason.Encoder
defstruct [:user_id, :discord_user, :discord_presence, :kv]
end

defmodule Lanyard.Presence.PrettyPresence do
@derive Jason.Encoder
defstruct discord_user: %{},
discord_status: "offline",
active_on_discord_web: false,
Expand All @@ -20,6 +22,7 @@ defmodule Lanyard.Presence do
alias Lanyard.Presence.Spotify
alias Lanyard.Presence.Activity

@derive Jason.Encoder
defstruct user_id: nil,
discord_user: nil,
discord_presence: nil,
Expand Down
39 changes: 16 additions & 23 deletions lib/socket/socket_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,9 @@ defmodule Lanyard.SocketHandler do
encoding: nil,
compression: nil

@behaviour :cowboy_websocket

def init(request, _state) do
def init(params) do
compression =
request
|> :cowboy_req.parse_qs()
params
|> Enum.find(fn {name, _value} -> name == "compression" end)
|> case do
{_name, "zlib_json"} -> :zlib
Expand All @@ -27,30 +24,26 @@ defmodule Lanyard.SocketHandler do

state = %__MODULE__{awaiting_init: true, encoding: "json", compression: compression}

{:cowboy_websocket, request, state}
end

def websocket_init(state) do
Lanyard.Metrics.Collector.inc(:gauge, :lanyard_connected_sessions)

{:reply,
{:reply, :ok,
construct_socket_msg(state.compression, %{op: 1, d: %{"heartbeat_interval" => 30000}}),
state}
end

def websocket_handle({:ping, _binary}, state) do
def handle_control({_message, [opcode: :ping]}, state) do
{:ok, state}
end

def websocket_handle({_type, json}, state) do
def handle_in({json, _type}, state) do
Lanyard.Metrics.Collector.inc(:counter, :lanyard_messages_inbound)

case Poison.decode(json) do
case Jason.decode(json) do
{:ok, json} when is_map(json) ->
case json["op"] do
2 ->
if json["d"] == nil || !is_map(json["d"]) || map_size(json["d"]) == 0 do
{:reply, {:close, 4005, "requires_data_object"}, state}
{:stop, :normal, {4005, "requires_data_object"}, state}
else
init_state =
case json["d"] do
Expand Down Expand Up @@ -99,9 +92,9 @@ defmodule Lanyard.SocketHandler do
end

if init_state == nil do
{:reply, {:close, 4006, "invalid_payload"}, state}
{:stop, :normal, {4006, "invalid_payload"}, state}
else
{:reply,
{:reply, :ok,
construct_socket_msg(state.compression, %{op: 0, t: "INIT_STATE", d: init_state}),
state}
end
Expand All @@ -125,19 +118,19 @@ defmodule Lanyard.SocketHandler do
{:ok, state}

_ ->
{:reply, {:close, 4004, "unknown_opcode"}, state}
{:stop, :normal, {4004, "unknown_opcode"}, state}
end

_ ->
{:reply, {:close, 4006, "invalid_payload"}, state}
{:stop, :normal, {4006, "invalid_payload"}, state}
end
end

def websocket_info({:remote_send, message}, state) do
{:reply, construct_socket_msg(state.compression, message), state}
def handle_info({:remote_send, message}, state) do
{:reply, :ok, construct_socket_msg(state.compression, message), state}
end

def terminate(_reason, _req, _state) do
def terminate(_reason, _state) do
:ets.insert(
:global_subscribers,
{"subscribers", List.delete(get_global_subscriber_list(), self())}
Expand All @@ -163,7 +156,7 @@ defmodule Lanyard.SocketHandler do

case compression do
:zlib ->
data = data |> Poison.encode!()
data = data |> Jason.encode!()

z = :zlib.open()
:zlib.deflateInit(z)
Expand All @@ -177,7 +170,7 @@ defmodule Lanyard.SocketHandler do
_ ->
data =
data
|> Poison.encode!()
|> Jason.encode!()

{:text, data}
end
Expand Down
14 changes: 8 additions & 6 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,18 @@ defmodule Lanyard.MixProject do
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:plug_cowboy, "~> 2.0"},
{:plug, "~> 1.14"},
{:bandit, "~> 0.7.7"},
{:websock_adapter, "~> 0.5.3"},
{:prometheus_plugs, "~> 1.1"},
{:prometheus_ex,
git: "https://github.com/lanodan/prometheus.ex", branch: "fix/elixir-1.14", override: true},
{:websocket_client, "~> 1.5"},
{:poison, "~> 4.0"},
{:gen_registry, "~> 1.0"},
{:corsica, "~> 1.0"},
{:manifold, "~> 1.0"},
{:httpoison, "~> 1.8"},
{:jason, "~> 1.4"},
{:gen_registry, "~> 1.3"},
{:corsica, "~> 1.3"},
{:manifold, "~> 1.6"},
{:finch, "~> 0.16.0"},
{:redix, "~> 1.2"}
]
end
Expand Down
Loading

0 comments on commit 7b10c43

Please sign in to comment.