defmodule Rivet.Ident.Handle.Lib do alias Rivet.Ident use Rivet.Ecto.Collection.Context, model: Ident.Handle @doc """ Check if handle is open, return double-error (internal/external msg) """ def available(handle, user_id \\ nil) when is_binary(handle) do if String.length(handle) < 4 do {:error, "short handle", "Your handle should be at least 4 characters long"} else case Ident.Handle.one(handle: handle) do {:ok, %Ident.Handle{user_id: ^user_id}} -> {:ok, :current} {:error, :not_found} -> {:ok, :available} {:ok, _} -> {:error, "existing handle not by user", "Sorry, that handle isn't available"} {:error, err} -> {:error, "unexpected error=#{inspect(err)}", "Sorry, that handle isn't available"} end end end defp clean_handle(handle) when is_binary(handle) do String.split(handle, "@", parts: 2) |> Enum.at(0) |> String.downcase() |> String.replace(~r/[^a-z0-9-]/, "-") |> String.replace(~r/-+/, "-") |> String.replace(~r/(^-|-$)/, "") end @chars String.graphemes("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") defp randchar(), do: Enum.random(@chars) def gen_good_handle(handle) do handle = clean_handle(handle) case Ident.Handle.Lib.available(handle) do {:error, _, _} -> gen_good_handle(handle <> randchar() <> randchar()) {:ok, _available_msg} -> handle end end end