NAME

Net::Nostr::Comment - NIP-22 comment threading

SYNOPSIS

use Net::Nostr::Comment;

# Comment on a nostr event (regular or addressable)
my $comment = Net::Nostr::Comment->comment(
    event     => $blog_post,
    pubkey    => $my_pubkey,
    content   => 'Great blog post!',
    relay_url => 'wss://relay.example.com',
);

# Comment on an external identifier (URL, podcast, etc.)
my $comment = Net::Nostr::Comment->comment(
    identifier => 'https://abc.com/articles/1',
    kind       => 'web',
    pubkey     => $my_pubkey,
    content    => 'Nice article!',
);

# Reply to an existing comment
my $reply = Net::Nostr::Comment->reply(
    to        => $parent_comment,
    pubkey    => $my_pubkey,
    content   => 'I agree!',
    relay_url => 'wss://relay.example.com',
);

# Parse comment structure from an event
my $info = Net::Nostr::Comment->from_event($event);
if ($info) {
    say "Root kind: " . $info->root_kind;
    say "Parent kind: " . $info->parent_kind;
}

# Validate a comment event
Net::Nostr::Comment->validate($event);

DESCRIPTION

Implements NIP-22 comment threading for kind 1111 events. Comments are plaintext threading notes scoped to a root event or external identifier.

Comments use uppercase tags (E, A, I, K, P) for the root scope and lowercase tags (e, a, i, k, p) for the parent item. For top-level comments, root and parent point to the same target.

Comments MUST NOT be used to reply to kind 1 notes; use Net::Nostr::Thread (NIP-10) instead.

CONSTRUCTOR

new

my $info = Net::Nostr::Comment->new(%fields);

Creates a new Net::Nostr::Comment object. Typically returned by "from_event"; calling new directly is useful for testing or manual construction.

my $info = Net::Nostr::Comment->new(
    root_tag_name => 'E',
    root_kind     => '30023',
    root_value    => 'abc123',
    root_pubkey   => $hex_pubkey,
);

Accepted fields: root_tag_name, root_value, root_relay, root_kind, root_pubkey, parent_tag_name, parent_value, parent_relay, parent_kind, parent_pubkey. Croaks on unknown arguments.

CLASS METHODS

comment

my $event = Net::Nostr::Comment->comment(
    event      => $target_event,       # nostr event to comment on
    pubkey     => $hex_pubkey,
    content    => 'comment text',
    relay_url  => 'wss://relay.com/',  # optional, defaults to ''
    quotes     => [{id => $eid, relay_url => $r, pubkey => $pk}],  # optional
    mentions   => [$pubkey1],          # optional
    created_at => time(),              # optional, passed to Event
);

my $event = Net::Nostr::Comment->comment(
    identifier => 'https://example.com/article',
    kind       => 'web',
    pubkey     => $hex_pubkey,
    content    => 'comment text',
    hint       => 'https://...',       # optional hint for I/i tags
);

Creates a kind 1111 comment event. Pass event for nostr events or identifier and kind for external identifiers (URLs, podcasts, etc.).

For addressable events (kinds 30000-39999), generates A/a tags with the event coordinate and an additional e tag referencing the event ID. For regular events, generates E/e tags. Tags K/k are always included with the target kind, and P/p tags include the author pubkey for nostr events.

Croaks if the target is a kind 1 event (use Net::Nostr::Thread instead).

# Comment on a NIP-94 file event
my $comment = Net::Nostr::Comment->comment(
    event   => $file_event,
    pubkey  => $my_pk,
    content => 'Great file!',
);

# Comment on a podcast episode
my $comment = Net::Nostr::Comment->comment(
    identifier => 'podcast:item:guid:d98d189b-...',
    kind       => 'podcast:item:guid',
    pubkey     => $my_pk,
    content    => 'Great episode!',
    hint       => 'https://fountain.fm/episode/...',
);

reply

my $event = Net::Nostr::Comment->reply(
    to         => $parent_comment,
    pubkey     => $hex_pubkey,
    content    => 'reply text',
    relay_url  => 'wss://relay.com/',  # optional
    quotes     => [...],               # optional
    mentions   => [...],               # optional
);

Creates a kind 1111 reply to an existing comment. The root scope tags (E/A/I, K, P) are preserved from the parent comment's uppercase tags. The parent tags point to the comment being replied to with k set to 1111.

my $reply = Net::Nostr::Comment->reply(
    to      => $comment_event,
    pubkey  => $my_pk,
    content => 'I agree!',
);

from_event

my $info = Net::Nostr::Comment->from_event($event);

Parses comment structure from a kind 1111 event. Returns a Net::Nostr::Comment object with accessors for root and parent scope, or undef if the event is not kind 1111.

my $info = Net::Nostr::Comment->from_event($event);
say $info->root_kind;       # '30023'
say $info->parent_kind;     # '1111' (if replying to a comment)
say $info->root_pubkey;     # root event author, or undef

validate

Net::Nostr::Comment->validate($event);

Validates that an event is a well-formed NIP-22 comment. Croaks if:

  • Kind is not 1111

  • Missing root scope tag (E, A, or I)

  • Missing parent scope tag (e, a, or i)

  • Missing K tag (root kind)

  • Missing k tag (parent kind)

eval { Net::Nostr::Comment->validate($event) };
warn "Invalid comment: $@" if $@;

ACCESSORS

These are available on objects returned by "from_event".

root_tag_name

my $name = $info->root_tag_name;  # 'E', 'A', or 'I'

The tag name used for the root scope.

root_value

my $val = $info->root_value;

The root scope value (event ID, event coordinate, or external identifier).

root_relay

my $relay = $info->root_relay;

Relay or web page hint for the root scope, or empty string.

root_kind

my $kind = $info->root_kind;  # '30023', '1063', 'web', etc.

The K tag value identifying the root item kind.

root_pubkey

my $pk = $info->root_pubkey;  # or undef for external identifiers

The P tag pubkey of the root event author, or undef if not available (e.g. for external identifiers).

parent_tag_name

my $name = $info->parent_tag_name;  # 'e', 'a', or 'i'

The tag name used for the parent item.

parent_value

my $val = $info->parent_value;

The parent item value.

parent_relay

my $relay = $info->parent_relay;

Relay hint for the parent item, or empty string.

parent_kind

my $kind = $info->parent_kind;  # '1111' for replies to comments

The k tag value identifying the parent item kind.

parent_pubkey

my $pk = $info->parent_pubkey;

The p tag pubkey of the parent item author, or undef.

SEE ALSO

NIP-22, Net::Nostr::Thread, Net::Nostr, Net::Nostr::Event