Db struct provides a comprehensive interface to Hoot’s SQLite database, which stores Nostr events, email threads, contact information, and profile metadata with encryption support via SQLCipher.
Initialization
new()
Creates a new database connection at the specified path.File path where the database should be created or opened
A new Db instance connected to the database file
new_in_memory()
Creates an in-memory database for testing purposes.A new Db instance with an in-memory database (not persisted)
unlock_with_password()
Unlocks an encrypted database and applies migrations.SQLCipher encryption password
Ok(()) if unlocked successfully, or an error if the password is incorrect
is_unlocked()
Checks if the database is currently unlocked and accessible.true if the database can be queried, false if locked or inaccessible
is_initialized()
Checks if database migrations have been applied.true if tables exist, false if the schema hasn’t been set up
Event storage
store_event()
Stores a Nostr event in the database, optionally unwrapping gift-wrapped events.The Nostr event to store
If the event is a gift wrap, the unwrapped contents (rumor) to store instead
Public key of the gift wrap recipient (for tracking)
Ok(()) if stored successfully, or an error
Behavior
- If
unwrappedis provided, stores the rumor instead of the wrapper - Creates a mapping in
gift_wrap_maptable linking wrap_id to inner_id - Uses
INSERT OR IGNOREto skip duplicate events - Checks deletion markers before storing
- Verifies that seal signer matches rumor pubkey for security
has_event()
Checks if an event ID exists in the database.Event ID (hex string) to check
true if the event exists in the events table
gift_wrap_exists()
Checks if a gift wrap ID has been processed.Gift wrap event ID to check
true if the wrap ID exists in the gift_wrap_map table
Message queries
get_email_thread()
Fetches an entire email thread starting from any message in the thread.Event ID of any message in the thread
Vector of MailMessage objects sorted by creation time (oldest first)
Behavior
Uses recursive SQL queries to:- Walk up the thread to find the root message
- Walk down from the root to find all replies
- Return all messages in chronological order
- Exclude trashed and deleted messages
get_top_level_messages()
Retrieves all root-level messages for the inbox view.Vector of TableEntry objects representing conversation threads
Filtering logic
Includes messages from:- Your own accounts (pubkeys table)
- Contacts (contacts table)
- Allowed senders (sender_status table with status=‘allowed’)
- People you’ve messaged before (derived from sent messages)
- Deleted messages
- Trashed messages
- Messages with parent references (replies)
- Junk senders
get_trash_messages()
Retrieves all messages in the trash.Vector of trashed messages sorted by trash date (newest first)
get_request_messages()
Retrieves messages from unknown senders awaiting approval.Vector of messages from senders not in contacts, pubkeys, or sender_status
get_junk_messages()
Retrieves messages from blocked senders.Vector of messages from senders marked as ‘junked’ in sender_status
search_messages()
Searches messages by content, subject, or sender name.Search query string (case-insensitive, supports partial matches)
Up to 100 matching messages sorted by date (newest first)
Search scope
- Message content
- Subject line
- Sender name and display name (from profile metadata)
- Only searches mail events (kind 2024)
- Excludes trash and junk
- Only searches messages from contacts, allowed senders, or your accounts
Contact management
get_contacts()
Retrieves all contacts with their profile metadata.Vector of tuples containing (pubkey, ProfileMetadata) sorted by display name
get_user_contacts()
Retrieves contacts from the contacts table with optional petnames.Vector of tuples: (pubkey, petname, ProfileMetadata) sorted by petname/display name
save_contact()
Adds a contact or updates their petname.Public key (hex) of the contact
Optional custom name for the contact
Ok(()) if saved successfully
delete_contact()
Removes a contact from the contacts table.Public key of the contact to remove
Ok(()) if deleted successfully
is_contact()
Checks if a public key is in the contacts table.Public key to check
true if the pubkey exists in the contacts table
get_profile_metadata()
Retrieves cached profile metadata for a public key.Public key (hex) to get metadata for
ProfileMetadata if cached, or None if not found
update_profile_metadata()
Updates the profile metadata cache if the event is newer.Nostr kind 0 metadata event
Ok(()) if updated (only updates if newer than existing)
Deletion and trash
record_deletions()
Marks events as deleted and removes them from the database.List of event IDs to delete
If specified, only deletes events authored by this pubkey
Event ID of the deletion request (kind 5)
Ok(()) if deletion markers were recorded successfully
record_trash()
Moves events to trash with an expiration time.List of event IDs to trash
Unix timestamp when these events should be permanently deleted
Ok(()) if moved to trash successfully
restore_from_trash()
Restores a trashed event back to the inbox.Event ID to restore
Ok(()) if restored successfully
purge_expired_trash()
Permanently deletes events whose trash expiration time has passed.Current unix timestamp
List of event IDs that were permanently deleted
is_deleted()
Checks if an event has been marked as deleted.Event ID to check
Optional author pubkey for scoped deletion checks
true if the event is marked as deleted
is_trashed()
Checks if an event is in the trash.Event ID to check
true if the event is in trash_events table
Account management
get_pubkeys()
Retrieves all saved account public keys.Vector of public keys (hex strings) for all accounts
add_pubkey()
Adds a public key to the pubkeys table.Public key (hex) to add
Ok(()) if added successfully
delete_pubkey()
Removes a public key from the pubkeys table.Public key (hex) to remove
Ok(()) if deleted successfully
Example usage
Storing a received message
Loading inbox messages
Viewing a conversation thread
Managing contacts
Searching messages
Trash management
Database schema notes
- events table: Stores raw Nostr events as JSON with virtual columns for efficient querying
- gift_wrap_map: Maps gift wrap IDs to inner rumor IDs
- profile_metadata: Caches kind 0 metadata events (name, picture, NIP-05)
- contacts: User’s contact list with optional petnames
- sender_status: Tracks allowed/junked senders
- trash_events: Soft-deleted events with expiration timestamps
- deleted_events: Deletion markers for permanently removed events
Related
- MailMessage - For message structure
- AccountManager - For key management
- RelayPool - For receiving events to store