zoeys.computer/lib/zoeyscomputer_web/plugs/discord_handler.ex

76 lines
2 KiB
Elixir
Raw Normal View History

2024-10-25 20:09:50 -04:00
defmodule ZoeyscomputerWeb.DiscordHandler do
2024-10-25 22:37:24 -04:00
require Logger
2024-10-25 22:34:20 -04:00
alias ExAws.S3
2024-10-25 20:09:50 -04:00
import Plug.Conn
2024-10-25 22:34:20 -04:00
import Mogrify
2024-10-25 20:09:50 -04:00
def init(opts), do: opts
2024-10-25 22:44:04 -04:00
@discord_patterns [
~r/^Mozilla\/5\.0 \(compatible; Discordbot\//,
2024-10-25 23:03:44 -04:00
# Discord's specific Mac client pattern
~r/^Mozilla\/5\.0 \(Macintosh; Intel Mac OS X [0-9_.]+; rv:[0-9.]+\) Gecko\/20100101 Firefox\/[0-9.]+$/
2024-10-25 22:44:04 -04:00
]
2024-10-25 22:37:24 -04:00
2024-10-25 22:44:04 -04:00
def call(%{path_info: ["images", _id | _]} = conn, _opts) do
user_agent = List.first(get_req_header(conn, "user-agent"))
2024-10-26 15:01:33 -04:00
Logger.metadata()[:request_id]
2024-10-25 22:44:04 -04:00
2024-10-25 23:04:08 -04:00
Logger.info("Processing image request:\n user_agent: #{user_agent}")
2024-10-25 22:44:04 -04:00
2024-10-25 22:54:36 -04:00
Logger.info("Is discord request: #{is_discord_request?(user_agent)}")
2024-10-25 22:44:04 -04:00
cond do
is_discord_request?(user_agent) -> handle_discord(conn)
true -> conn
2024-10-25 20:09:50 -04:00
end
end
def call(conn, _opts), do: conn
2024-10-25 22:44:04 -04:00
defp is_discord_request?(nil), do: false
defp is_discord_request?(user_agent) do
Enum.any?(@discord_patterns, fn pattern ->
Regex.match?(pattern, user_agent)
end)
end
2024-10-25 20:09:50 -04:00
defp handle_discord(%{path_info: ["images", id]} = conn) do
2024-10-25 22:34:20 -04:00
case download_from_s3("imgs", id) do
{:ok, image_binary, content_type} ->
conn
|> put_resp_content_type(content_type)
2024-10-25 22:44:04 -04:00
# Optional: Add caching
|> put_resp_header("cache-control", "public, max-age=86400")
2024-10-25 22:34:20 -04:00
|> send_resp(200, image_binary)
|> halt()
{:error, reason} ->
IO.inspect(reason)
conn
|> put_resp_content_type("text/plain")
|> send_resp(500, "Failed to retrieve image")
|> halt()
end
end
2024-10-25 20:09:50 -04:00
2024-10-25 22:34:20 -04:00
defp download_from_s3(bucket, key) do
case S3.get_object(bucket, "uploads/#{key}.png") |> ExAws.request() do
{:ok, %{body: image_binary}} ->
local_path = "/tmp/#{key}.png"
File.write!(local_path, image_binary)
image = open(local_path) |> format("webp") |> save()
{:ok, file_binary} = File.read(image.path)
{:ok, file_binary, "image/webp"}
error ->
error
end
2024-10-25 20:09:50 -04:00
end
end