From d87be8d42a22ba0d0f993083413ce6bddb669b17 Mon Sep 17 00:00:00 2001 From: mehbark Date: Sun, 18 Jan 2026 21:57:39 -0500 Subject: [PATCH] feature parity --- lib/top_poster_server.ex | 19 +++------ lib/top_poster_server/plug.ex | 40 +++++++++++++------ lib/top_poster_server/user.ex | 14 +++++-- .../migrations/20260119015123_initial.exs | 10 +++++ 4 files changed, 54 insertions(+), 29 deletions(-) create mode 100644 priv/repo/migrations/20260119015123_initial.exs diff --git a/lib/top_poster_server.ex b/lib/top_poster_server.ex index 45c86a9..36de81e 100644 --- a/lib/top_poster_server.ex +++ b/lib/top_poster_server.ex @@ -1,18 +1,11 @@ defmodule TopPosterServer do - @moduledoc """ - Documentation for `TopPosterServer`. - """ - @doc """ - Hello world. - - ## Examples - - iex> TopPosterServer.hello() - :world - + Checks that `discord_id` *could be* a valid discord user id """ - def hello do - :world + @spec is_valid_discord_id(term()) :: boolean() + def is_valid_discord_id(discord_id) when is_binary(discord_id) do + String.match?(discord_id, ~r/^\d{17,20}$/) end + + def is_valid_discord_id(_), do: false end diff --git a/lib/top_poster_server/plug.ex b/lib/top_poster_server/plug.ex index d668b62..b9bcc91 100644 --- a/lib/top_poster_server/plug.ex +++ b/lib/top_poster_server/plug.ex @@ -20,25 +20,39 @@ defmodule TopPosterServer.Plug do discord_id = conn.query_params["id"] - if is_valid_discord_id(discord_id) do - conn - |> send_resp(200, "valid id") - else - Repo.insert!(%User{discord_id: "354988989100589058", posts: 413}) + if conn.method == "POST" and TopPosterServer.is_valid_discord_id(discord_id) do + result = + case Repo.get(User, discord_id) do + nil -> + Repo.insert!(%User{id: discord_id, posts: 1}).posts - query = from u in User, order_by: [desc: u.posts, asc: u.discord_id] + _user -> + query = + from u in User, + update: [inc: [posts: 1]], + where: u.id == ^discord_id, + select: u.posts + + {1, [posts]} = Repo.update_all(query, []) + posts + end + + conn + |> send_resp(200, "#{inspect(result)}\n") + else + query = from u in User, order_by: [desc: u.posts, asc: u.id] users = Repo.all(query) conn - |> send_resp(200, "default page #{inspect(users)}") + |> send_resp(400, leaderboard(users)) end end - # Valid in format, not necessarily actually existing lol - @spec is_valid_discord_id(term()) :: boolean() - defp is_valid_discord_id(discord_id) when is_binary(discord_id) do - String.match?(discord_id, ~r/^\d{17,20}$/) - end + @spec leaderboard([User]) :: String.t() + defp leaderboard(users) do + "POST https://puyo.cattenheimer.xyz/top-poster?id= - defp is_valid_discord_id(_), do: false +#{users |> Enum.map(fn user -> "#{String.pad_leading(user.id, 20)}: #{user.posts}" end) |> Enum.join("\n")} +" + end end diff --git a/lib/top_poster_server/user.ex b/lib/top_poster_server/user.ex index 86fbcf8..6b110ae 100644 --- a/lib/top_poster_server/user.ex +++ b/lib/top_poster_server/user.ex @@ -1,13 +1,21 @@ defmodule TopPosterServer.User do use Ecto.Schema + import Ecto.Changeset @type t :: %__MODULE__{ - discord_id: String.t(), + id: String.t(), posts: non_neg_integer() } + @primary_key {:id, :string, []} + schema "users" do - field(:discord_id, :string) - field(:posts, :integer, default: 0) + field :posts, :integer, default: 0 + end + + def changeset(user, params \\ %{}) do + user + |> cast(params, [:id, :posts]) + |> validate_required([:id, :posts]) end end diff --git a/priv/repo/migrations/20260119015123_initial.exs b/priv/repo/migrations/20260119015123_initial.exs new file mode 100644 index 0000000..53e869c --- /dev/null +++ b/priv/repo/migrations/20260119015123_initial.exs @@ -0,0 +1,10 @@ +defmodule TopPosterServer.Repo.Migrations.Initial do + use Ecto.Migration + + def change do + create table("users", primary_key: false) do + add :id, :string, size: 32, primary_key: true, null: false + add :posts, :integer, default: 0, null: false + end + end +end