defmodule ZoeyscomputerWeb.DiscordHandler do require Logger alias ExAws.S3 import Plug.Conn import Mogrify def init(opts), do: opts @discord_patterns [ ~r/^Mozilla\/5\.0 \(compatible; Discordbot\//, # 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.]+$/ ] def call(%{path_info: ["images", _id | _]} = conn, _opts) do user_agent = List.first(get_req_header(conn, "user-agent")) Logger.metadata()[:request_id] Logger.info("Processing image request:\n user_agent: #{user_agent}") Logger.info("Is discord request: #{is_discord_request?(user_agent)}") cond do is_discord_request?(user_agent) -> handle_discord(conn) true -> conn end end def call(conn, _opts), do: conn 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 defp handle_discord(%{path_info: ["images", id]} = conn) do case download_from_s3("imgs", id) do {:ok, image_binary, content_type} -> conn |> put_resp_content_type(content_type) # Optional: Add caching |> put_resp_header("cache-control", "public, max-age=86400") |> 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 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 end end