NAME
Net::Nostr::Mention - NIP-27 text note references
SYNOPSIS
use Net::Nostr::Mention qw(
extract_mentions replace_mentions
mention_pubkey mention_event mention_addr
);
my $pk = '7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e';
my $id = 'aaf9dd42b3de2a1a2f95e50fdbbef66e1afb165152a581a3ee75ac39a0559cd2';
# Create mentions for use in event content
my $m1 = mention_pubkey($pk);
# nostr:npub1...
my $m2 = mention_pubkey($pk, relays => ['wss://relay.com']);
# nostr:nprofile1...
my $m3 = mention_event($id);
# nostr:note1...
my $m4 = mention_event($id, author => $pk, kind => 1);
# nostr:nevent1...
my $m5 = mention_addr(
identifier => 'my-article', pubkey => $pk, kind => 30023,
);
# nostr:naddr1...
# Extract all mentions from content
my $content = "hello $m1 see also $m3";
my @mentions = extract_mentions($content);
# @mentions = ({ type => 'npub', data => $pk, uri => 'nostr:npub1...', ... },
# { type => 'note', data => $id, uri => 'nostr:note1...', ... })
# Replace mentions with display text
my $display = replace_mentions($content, sub {
my ($mention) = @_;
return '@someone' if $mention->{type} eq 'npub';
return '[event]' if $mention->{type} eq 'note';
return $mention->{uri}; # keep as-is
});
# 'hello @someone see also [event]'
DESCRIPTION
Implements NIP-27 text note references. This NIP standardizes inline references to other events and profiles within event content using nostr: URIs (NIP-21) containing NIP-19 bech32-encoded entities.
When creating events, use "mention_pubkey", "mention_event", and "mention_addr" to produce properly formatted nostr: URIs to embed in content.
When displaying events, use "extract_mentions" to find all references in content, and "replace_mentions" to substitute them with display text such as profile names or event previews.
Including p, e, or q tags for mentioned entities is optional per NIP-27. Clients should add tags when they want the mentioned profile to be notified or the referenced event to recognize the mention as a reply.
FUNCTIONS
All functions are exportable. None are exported by default.
extract_mentions
my @mentions = extract_mentions($content);
Finds all nostr: URIs in the given content string. Returns a list of hashrefs, one per mention, in order of appearance. Each hashref contains:
type- entity type:npub,note,nprofile,nevent, ornaddrdata- decoded data: hex string for bare types (npub,note), hashref for TLV types (nprofile,nevent,naddr)uri- the fullnostr:...string as it appeared in contentstart- byte offset of the start of the URI in contentend- byte offset of the end of the URI in content
nsec URIs are silently skipped (they must not appear in nostr: URIs per NIP-21). Invalid bech32 strings are silently skipped.
use Net::Nostr::Bech32 qw(encode_npub);
my $npub = encode_npub('aa' x 32);
my $content = "hello nostr:$npub world";
my @m = extract_mentions($content);
say $m[0]{type}; # 'npub'
say $m[0]{start}; # 6
say substr($content, $m[0]{start}, $m[0]{end} - $m[0]{start});
# nostr:npub1...
say $m[0]{data}; # 'aa' x 32
replace_mentions
my $display = replace_mentions($content, \&callback);
Replaces each nostr: mention in content with the return value of the callback. The callback receives a mention hashref (same structure as "extract_mentions") and should return a replacement string.
use Net::Nostr::Bech32 qw(encode_npub encode_note);
my $npub = encode_npub('aa' x 32);
my $note = encode_note('bb' x 32);
my $content = "by nostr:$npub see nostr:$note";
my $display = replace_mentions($content, sub {
my ($m) = @_;
return '@' . substr($m->{data}, 0, 8) . '...' if $m->{type} eq 'npub';
return '[event]' if $m->{type} eq 'note' || $m->{type} eq 'nevent';
return $m->{uri};
});
# 'by @aaaaaaaa... see [event]'
mention_pubkey
my $uri = mention_pubkey($hex_pubkey);
my $uri = mention_pubkey($hex_pubkey, relays => ['wss://relay.com']);
Creates a nostr: URI for a public key. Returns nostr:npub1... when no options are given, or nostr:nprofile1... when relay hints are provided.
my $pk = 'aa' x 32;
my $content = "hello " . mention_pubkey($pk) . " how are you?";
# 'hello nostr:npub1... how are you?'
mention_event
my $uri = mention_event($hex_event_id);
my $uri = mention_event($hex_event_id, relays => \@r, author => $pk, kind => $k);
Creates a nostr: URI for an event. Returns nostr:note1... when no options are given, or nostr:nevent1... when any of relays, author, or kind are provided.
my $pk = 'aa' x 32;
my $id = 'bb' x 32;
my $content = "see " . mention_event($id, author => $pk, kind => 1);
# 'see nostr:nevent1...'
mention_addr
my $uri = mention_addr(
identifier => $d_tag,
pubkey => $hex_pubkey,
kind => $kind,
relays => \@relays, # optional
);
Creates a nostr:naddr1... URI for an addressable event. identifier, pubkey, and kind are required. relays is optional.
my $pk = 'aa' x 32;
my $content = "read " . mention_addr(
identifier => 'my-article', pubkey => $pk, kind => 30023,
);
# 'read nostr:naddr1...'