Skip to main content

Module emoji_packs

Module emoji_packs 

Source
Expand description

NIP-30 / NIP-51 custom emoji + pack support.

Phase 1 (read path):

  • Parse kind 30030 emoji sets and kind 10030 user emoji lists.
  • Fetch a user’s subscribed packs from relays, persist them locally.
  • Expose a flat EmojiPack API to the frontend for picker rendering.

Spec: https://nips.nostr.com/30, https://nips.nostr.com/51.

Metadata interop: NIP-51 standardises title / image / description tags on kind 30030. Ditto and Nostria emit non-standard name / picture / about instead. Vector reads both with spec preference and (eventually) dual-writes both on publish.

Structs§

EmojiPack
PackAddress
Parsed NIP-19 / NIP-51 set address.
PackEmoji

Enums§

PackFetchOutcome
What one refresh sweep learned about a subscribed pack.

Constants§

KIND_EMOJI_SET
NIP-51 kind for an “Emoji set” (parameterised replaceable).
MAX_EMOJIS_PER_PACK
Base (free, tier-0) emojis-per-own-pack cap. Shared packs received from the network may exceed this — only what we author is capped, and the frontend truncates oversized received packs at display time.
MAX_EQUIPPED_PACKS
Base (free, tier-0) equipped-pack cap. Named const for the frontend mirror.
PACK_STATUS_ACTIVE
Pack is live on its relays (or hasn’t been judged otherwise).
PACK_STATUS_MISSING
No tombstone, but the pack has been absent across enough clean sweeps of live relays (see the gauntlet in apply_pack_health) that it’s considered gone.
PACK_STATUS_REVOKED
A deterministic tombstone was seen: the author replaced the pack with an EMPTY kind 30030 (Vector’s own delete flow) or published a kind-5 deletion naming it.

Functions§

apply_pack_health
Apply one refresh sweep’s verdict to a pack’s persisted health. Returns true when the pack’s STATUS changed (caller emits a UI refresh).
clear_nip65_cache
Drop every cached relay list (account swap — entries hold contact-graph metadata from the prior session, mirroring the inbox-relay cache’s swap hygiene).
decrypt_subscribed_addresses
Decrypt + parse a kind 10030 event’s encrypted subscription list.
delete_own_pack
Tombstone one of the user’s own packs by publishing an empty kind 30030 with just the d tag (relays replace the prior payload), drop the local subscription, and republish kind 10030.
effective_display_cap
Per-pack emoji cap mirrored from the frontend’s MAX_DISPLAY_EMOJIS_PER_PACK (applyBadgeLimits). The send resolver caps each subscribed pack to this many items so its ~N disambiguation of duplicate shortcodes matches exactly what the picker displayed — otherwise a large pack’s hidden tail (the picker only shows the first N) would enter the candidate set and shift the indices.
effective_max_emojis_per_pack
Per-pack emoji authoring cap for the current account, scaled by effective tier.
effective_max_equipped_packs
In-app equipped-pack cap for the current account, scaled by effective tier. Gate the in-app subscribe/create action on this — never the load/display path.
fetch_pack_by_naddr
Preview-only fetch by naddr — resolves + parses but never touches local DB. Lets the UI render a “Pack Preview” card without committing to a subscription.
fetch_subscribed_packs
Fetch the user’s kind 10030 list, resolve every referenced pack, and persist the result locally. Session-guarded against an account swap landing the new account’s pack list in account A’s DB.
get_or_fetch_theme_pack
Resolve a theme pack cache-first: return the locally-persisted copy instantly when present (and refresh it in the background), otherwise fetch live, persist, and return. Theme packs are pinned by the active theme, not subscribed — save_pack persists their data without a subscription row, so they survive restarts (no per-session relay round-trip) yet never occupy an equip slot or land in the kind-10030 list. Returns None if uncached and the live fetch finds nothing.
get_theme_slot_anchor
Return the theme-slot anchor as a NADDR (the pack the theme slot renders immediately after), or "" when the slot is at the top. Degrades to top on a malformed stored anchor rather than breaking the picker.
load_all_packs
Load every locally-cached pack the user is currently subscribed to (plus their own packs, which always count). Hydrated with items. Cached non-subscribed pack rows stay in the DB so historic reactions still resolve their image URLs — they’re just hidden from the picker.
load_cached_pack
Load a single cached pack by its raw kind:pubkey:identifier addr, regardless of subscription status. Used by the theme-pack path: a theme pack is persisted via save_pack (so it loads instantly across sessions) but never gets a subscription row, so load_all_packs rightly hides it.
load_subscriptions
naddr_from_addr
Encode a pack addr (kind:pubkey:identifier) into a NIP-19 naddr1... bech32 string. Used by the share-pack flow to put a portable reference on the user’s clipboard.
parse_naddr
Decode a NIP-19 naddr1... into a PackAddress. Rejects coordinates that don’t point at kind 30030 so a malformed paste can’t pull in an unrelated replaceable event.
parse_pack_address
Parse a kind:pubkey-hex:d-tag address as found in kind 10030 a tags. Rejects anything that isn’t kind 30030 — we don’t want a malformed list pulling in random replaceable events.
parse_pack_from_event
Parse a kind 30030 event into an EmojiPack. Returns None if the event is missing a d tag or has zero valid emoji rows.
publish_emoji_list
Publish a kind 10030 “Emojis” list containing every subscribed pack.
publish_pack
Publish (or replace) one of the user’s own packs as a kind 30030 event, persist it locally, and add it to the subscription list so the picker surfaces it immediately. SessionGuard-gated so a mid- network account swap can’t push account A’s pack signed by B’s key.
refresh_subscribed_packs
Convenience entry point that grabs the client + my_pubkey internally and runs the full subscribed-packs refresh. Intended for the boot path; in-app commands pass an explicit SessionGuard via the lower helper to make the safety contract visible at every call site.
reorder_emoji_packs
Persist a user-defined display order for the equipped packs (including the theme slot) and republish kind 10030 so it syncs across devices.
republish_emoji_list_debounced
Coalesce rapid subscribe/unsubscribe taps into one network publish. Captures SessionGuard BEFORE the spawn boundary so a mid-debounce account swap can’t sign account A’s pack list with account B’s key.
resolve_outbound_emoji_tags
Scan content for :shortcode: patterns and resolve them against the user’s currently-subscribed packs (plus the active theme pack). Returns deduped emoji tags in first-match order. Used by the send pipeline to attach NIP-30 emoji tags so recipients without the pack subscribed still render.
save_pack
save_subscriptions
set_theme_emoji_tags
Register (or clear, with an empty vec) the active theme pack’s emoji so the send resolver can tag them even though they aren’t a DB subscription.
subscribe_pack
Subscribe to a pack by naddr: fetch the pack, persist it + the subscription, then schedule a debounced republish of kind 10030. Returns the hydrated pack on success.
unsubscribe_pack
Unsubscribe locally and republish kind 10030 without the pack. The pack row itself stays in emoji_packs (caller may still want to render old reactions); only the subscription link is dropped.