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.
share_naddr
Mint the SHAREABLE form of a pack naddr: the same coordinate plus up to 3 relay hints naming the pack’s own home. A pack lives on its AUTHOR’s write relays (NIP-65), never the sharer’s — a subscribed pack must not get the sharer’s personal set stamped onto it. An author with no published kind 10002 falls back to this client’s pool, which is where an own pack was published and where a subscribed one was actually seen.
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.