From 8d9fc4e55b5eb9cae19b92b3683c6576f4be8adf Mon Sep 17 00:00:00 2001 From: Silberengel Date: Tue, 7 Apr 2026 08:28:12 +0200 Subject: [PATCH] fix issue #2 single-element tags need to be handled --- lib/gc_index_relay/nostr/pub_event.ex | 15 ++++++++++--- lib/gc_index_relay/nostr/tag.ex | 2 +- .../20260407062511_allow_null_tag_value.exs | 9 ++++++++ test/gc_index_relay/nostr/pub_event_test.exs | 22 +++++++++++++++++++ 4 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 priv/repo/migrations/20260407062511_allow_null_tag_value.exs diff --git a/lib/gc_index_relay/nostr/pub_event.ex b/lib/gc_index_relay/nostr/pub_event.ex index e204d53..64038bf 100644 --- a/lib/gc_index_relay/nostr/pub_event.ex +++ b/lib/gc_index_relay/nostr/pub_event.ex @@ -59,8 +59,12 @@ defmodule GcIndexRelay.Nostr.PubEvent do 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 + + {value, rest} = + case values do + [] -> {nil, []} + [v | r] -> {v, r} + end %Tag{ name: name, @@ -93,6 +97,11 @@ defmodule GcIndexRelay.Nostr.PubEvent do end defp from_tags(tags) when is_list(tags) do - for t <- tags, do: [t.name, t.value | t.additional_values] + for t <- tags do + case t.value do + nil -> [t.name] + value -> [t.name, value | t.additional_values] + end + end end end diff --git a/lib/gc_index_relay/nostr/tag.ex b/lib/gc_index_relay/nostr/tag.ex index dfaf26c..2b9b96c 100644 --- a/lib/gc_index_relay/nostr/tag.ex +++ b/lib/gc_index_relay/nostr/tag.ex @@ -13,6 +13,6 @@ defmodule GcIndexRelay.Nostr.Tag do def changeset(tag, attrs) do tag |> cast(attrs, [:name, :value, :additional_values]) - |> validate_required([:name, :value]) + |> validate_required([:name]) end end diff --git a/priv/repo/migrations/20260407062511_allow_null_tag_value.exs b/priv/repo/migrations/20260407062511_allow_null_tag_value.exs new file mode 100644 index 0000000..45e6950 --- /dev/null +++ b/priv/repo/migrations/20260407062511_allow_null_tag_value.exs @@ -0,0 +1,9 @@ +defmodule GcIndexRelay.Repo.Migrations.AllowNullTagValue do + use Ecto.Migration + + def change do + alter table(:tags) do + modify :value, :string, null: true, from: {:string, null: false} + end + end +end diff --git a/test/gc_index_relay/nostr/pub_event_test.exs b/test/gc_index_relay/nostr/pub_event_test.exs index 8d948e9..7ab9f7e 100644 --- a/test/gc_index_relay/nostr/pub_event_test.exs +++ b/test/gc_index_relay/nostr/pub_event_test.exs @@ -127,6 +127,28 @@ defmodule GcIndexRelay.Nostr.PubEventTest do assert result.tags == tags end + test "preserves single-element tags (e.g. ['bot'])" do + tags = [["bot"]] + + pub_event = valid_pub_event_fixture(tags: tags) + + assert {:ok, result} = pub_event |> PubEvent.to_db() |> PubEvent.from_db() + assert result.tags == tags + end + + test "preserves mixed single-element and multi-element tags" do + tags = [ + ["bot"], + ["p", "def456"], + ["content-warning"] + ] + + pub_event = valid_pub_event_fixture(tags: tags) + + assert {:ok, result} = pub_event |> PubEvent.to_db() |> PubEvent.from_db() + assert result.tags == tags + end + test "preserves event with empty content" do pub_event = valid_pub_event_fixture(content: "")