Browse Source

Code polish, minor refactors, and type hints

master
buttercat1791 3 months ago
parent
commit
b931109ac8
  1. 8
      lib/gc_index_relay/nostr.ex
  2. 2
      lib/gc_index_relay/nostr/event.ex
  3. 6
      lib/gc_index_relay/nostr/filter.ex
  4. 64
      lib/gc_index_relay/nostr/pub_event.ex
  5. 8
      lib/gc_index_relay_web/controllers/event_controller.ex

8
lib/gc_index_relay/nostr.ex

@ -5,7 +5,7 @@ defmodule GcIndexRelay.Nostr do @@ -5,7 +5,7 @@ defmodule GcIndexRelay.Nostr do
## Supported Operations
The Nostr context module supports create, read, and delete operations on events, as well as a
number of query types to find collections of events. Update operations are not supported, sincafter
number of query types to find collections of events. Update operations are not supported, since a
Nostr event, once signed, is immutable.
"""
@ -20,7 +20,8 @@ defmodule GcIndexRelay.Nostr do @@ -20,7 +20,8 @@ defmodule GcIndexRelay.Nostr do
Returns: `GcIndexRelay.Nostr.PubEvent`
"""
def get_event!(id) when is_binary(id) do
@spec get_event(binary()) :: {:ok, PubEvent.t()} | {:error, :not_found}
def get_event(id) when is_binary(id) do
Event
|> Repo.get(id)
|> Repo.preload(:tags)
@ -38,14 +39,13 @@ defmodule GcIndexRelay.Nostr do @@ -38,14 +39,13 @@ defmodule GcIndexRelay.Nostr do
%Event{}
|> Event.changeset(Map.from_struct(db_event))
|> Repo.insert()
else
{:error, reason} -> {:error, reason}
end
end
@doc """
Deletes a `GcIndexRelay.Nostr.PubEvent` from the database.
"""
@spec delete_event(PubEvent.t()) :: {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
def delete_event(event) when is_struct(event, PubEvent) do
db_event = PubEvent.to_db(event)

2
lib/gc_index_relay/nostr/event.ex

@ -21,12 +21,10 @@ defmodule GcIndexRelay.Nostr.Event do @@ -21,12 +21,10 @@ defmodule GcIndexRelay.Nostr.Event do
@primary_key {:id, :binary_id, autogenerate: false}
schema "events" do
# 32-bytes lowercase hex-encoded
field :pubkey, :binary
field :created_at, :utc_datetime
field :kind, :integer
field :content, :string
# 64 bytes lowercase hex-encoded
field :sig, :binary
has_many :tags, GcIndexRelay.Nostr.Tag
end

6
lib/gc_index_relay/nostr/filter.ex

@ -46,8 +46,6 @@ defmodule GcIndexRelay.Nostr.Filter do @@ -46,8 +46,6 @@ defmodule GcIndexRelay.Nostr.Filter do
until: until,
limit: limit
}}
else
{:error, reason} -> {:error, reason}
end
end
@ -139,8 +137,6 @@ defmodule GcIndexRelay.Nostr.Filter do @@ -139,8 +137,6 @@ defmodule GcIndexRelay.Nostr.Filter do
with :ok <- validate_tag_keys(tags),
:ok <- validate_tag_values(tags) do
{:ok, tags}
else
{:error, reason} -> {:error, reason}
end
end
@ -257,7 +253,7 @@ defmodule GcIndexRelay.Nostr.Filter do @@ -257,7 +253,7 @@ defmodule GcIndexRelay.Nostr.Filter do
@spec apply_authors(Ecto.Query.t(), [String.t()] | nil) :: Ecto.Query.t()
defp apply_authors(query, nil), do: query
defp apply_authors(query, []), do: query
defp apply_authors(query, authors), do: where(query, [e], e.author in ^authors)
defp apply_authors(query, authors), do: where(query, [e], e.pubkey in ^authors)
@spec apply_kinds(Ecto.Query.t(), [integer()] | nil) :: Ecto.Query.t()
defp apply_kinds(query, nil), do: query

64
lib/gc_index_relay/nostr/pub_event.ex

@ -12,42 +12,53 @@ defmodule GcIndexRelay.Nostr.PubEvent do @@ -12,42 +12,53 @@ defmodule GcIndexRelay.Nostr.PubEvent do
@derive Jason.Encoder
defstruct [:id, :pubkey, :created_at, :kind, :tags, :content, :sig]
@type t :: %__MODULE__{
id: binary(),
pubkey: binary(),
created_at: integer(),
kind: integer(),
tags: [[String.t()]],
content: String.t(),
sig: binary()
}
@doc """
Converts a `GcIndexRelay.Nostr.PubEvent` to its corresponding `GcIndexRelay.Nostr.Event` and
`GcIndexRelay.Nostr.Tag` representations.
Returns an Ecto changeset for `GcIndexRelay.Nostr.Event`.
Returns an Ecto for `GcIndexRelay.Nostr.Event`.
"""
@spec to_db(t()) :: Ecto.Schema.t()
def to_db(%__MODULE__{tags: tags} = pub_event) do
%Event{to_event(pub_event) | tags: to_tags(tags)}
end
defp to_event(%__MODULE__{
@spec to_event(t()) :: Ecto.Schema.t()
defp to_event(%__MODULE__{} = pub_event)
when is_binary(pub_event.id) and is_binary(pub_event.pubkey) and
is_integer(pub_event.created_at) and is_integer(pub_event.kind) and
is_binary(pub_event.sig) do
with {:ok, id} <- Base.decode16(pub_event.id, case: :lower),
{:ok, pubkey} <- Base.decode16(pub_event.pubkey, case: :lower),
{:ok, signature} <- Base.decode16(pub_event.sig, case: :lower) do
%Event{
id: id,
pubkey: pubkey,
created_at: epoch,
kind: kind,
content: content,
created_at: DateTime.from_unix!(pub_event.created_at),
kind: pub_event.kind,
content: pub_event.content,
sig: signature
})
when is_binary(id) and is_binary(pubkey) and is_integer(epoch) and is_integer(kind) and
is_binary(signature) do
%Event{
id: Base.decode16(id, case: :lower),
pubkey: Base.decode16(pubkey, case: :lower),
created_at: DateTime.from_unix!(epoch),
kind: kind,
content: content,
sig: Base.decode16(signature, case: :lower)
}
else
error -> {:error, error}
end
defp to_tags(tags) when is_list(tags) do
for t <- tags, do: to_tag(t)
end
defp to_tag(tag) when is_list(tag) do
[name | values] = tag
@spec to_tags([[String.t()]]) :: [Ecto.Schema.t()]
defp to_tags(tags) when is_list(tags) do
for t <- tags do
[name | values] = t
# Single-element tags will cause a crash
[value | rest] = values
%Tag{
@ -56,13 +67,17 @@ defmodule GcIndexRelay.Nostr.PubEvent do @@ -56,13 +67,17 @@ defmodule GcIndexRelay.Nostr.PubEvent do
additional_values: rest
}
end
end
@doc """
Converts the DB representations of `GcIndexRelay.Nostr.Event` and `GcIndexRelay.Nostr.Tag` to the
domain representation `GcIndexRelay.Nostr.PubEvent`.
"""
@spec from_db(struct()) :: {:ok, t()} | {:error, :not_found}
def from_db(event) when is_nil(event), do: {:error, :not_found}
def from_db(%Event{tags: tags} = event) when is_struct(event, Event) and is_list(tags) do
%{from_event(event) | tags: from_tags(tags)}
{:ok, %{from_event(event) | tags: from_tags(tags)}}
end
defp from_event(%Event{} = event) when is_struct(event, Event) do
@ -77,11 +92,6 @@ defmodule GcIndexRelay.Nostr.PubEvent do @@ -77,11 +92,6 @@ defmodule GcIndexRelay.Nostr.PubEvent do
end
defp from_tags(tags) when is_list(tags) do
for t <- tags, do: from_tag(t)
end
defp from_tag(%Tag{name: name, value: value, additional_values: rest})
when is_binary(name) and is_binary(value) and is_list(rest) do
[name | [value | rest]]
for t <- tags, do: [t.name, t.value | t.additional_values]
end
end

8
lib/gc_index_relay_web/controllers/event_controller.ex

@ -3,6 +3,7 @@ defmodule GcIndexRelayWeb.EventController do @@ -3,6 +3,7 @@ defmodule GcIndexRelayWeb.EventController do
alias GcIndexRelay.Nostr
alias GcIndexRelay.Nostr.Event
alias GcIndexRelay.Nostr.PubEvent
action_fallback GcIndexRelayWeb.FallbackController
@ -18,14 +19,13 @@ defmodule GcIndexRelayWeb.EventController do @@ -18,14 +19,13 @@ defmodule GcIndexRelayWeb.EventController do
def show(conn, %{"id" => id}) do
# TODO: Add 404 for event not found in FallbackController
event = Nostr.get_event!(id)
event = Nostr.get_event(id)
render(conn, :show, event: event)
end
def delete(conn, %{"id" => id}) do
event = Nostr.get_event!(id)
with {:ok, %Event{}} <- Nostr.delete_event(event) do
with {:ok, %PubEvent{} = pub_event} <- Nostr.get_event(id),
{:ok, %Event{} = _} <- Nostr.delete_event(pub_event) do
send_resp(conn, :no_content, "")
end
end

Loading…
Cancel
Save