Documentation
¶
Overview ¶
Package neo4j provides hex utilities for normalizing pubkeys and event IDs.
The nostr library applies binary optimization to e/p tags, storing 64-character hex strings as 33-byte binary (32 bytes + null terminator). This file provides utilities to ensure all pubkeys and event IDs stored in Neo4j are in consistent lowercase hex format.
Package neo4j provides a Neo4j-based implementation of the database interface. Neo4j is a native graph database optimized for relationship-heavy queries, making it ideal for Nostr's social graph and event reference patterns.
Index ¶
- Constants
- func ExtractETagValue(t *tag.T) string
- func ExtractPTagValue(t *tag.T) string
- func IsBinaryEncoded(val []byte) bool
- func IsValidHexPubkey(s string) bool
- func NewLogger(logLevel int, label string) (l *logger)
- func NormalizePubkeyHex(val []byte) string
- type CollectedResult
- type GraphAdapter
- func (a *GraphAdapter) FindMentions(pubkey []byte, kinds []uint16) (graph.GraphResultI, error)
- func (a *GraphAdapter) TraverseFollowers(seedPubkey []byte, maxDepth int) (graph.GraphResultI, error)
- func (a *GraphAdapter) TraverseFollows(seedPubkey []byte, maxDepth int) (graph.GraphResultI, error)
- func (a *GraphAdapter) TraverseThread(seedEventID []byte, maxDepth int, direction string) (graph.GraphResultI, error)
- type GraphResult
- func (r *GraphResult) AddEventAtDepth(eventIDHex string, depth int) bool
- func (r *GraphResult) AddPubkeyAtDepth(pubkeyHex string, depth int) bool
- func (r *GraphResult) GetAllEvents() []string
- func (r *GraphResult) GetAllPubkeys() []string
- func (r *GraphResult) GetDepthsSorted() []int
- func (r *GraphResult) GetEventDepthsSorted() []int
- func (r *GraphResult) GetEventsByDepth() map[int][]string
- func (r *GraphResult) GetPubkeysByDepth() map[int][]string
- func (r *GraphResult) GetTotalEvents() int
- func (r *GraphResult) GetTotalPubkeys() int
- func (r *GraphResult) HasEvent(eventIDHex string) bool
- func (r *GraphResult) HasPubkey(pubkeyHex string) bool
- func (r *GraphResult) ToDepthArrays() [][]string
- func (r *GraphResult) ToEventDepthArrays() [][]string
- type Migration
- type N
- func (n *N) AddNIP43Member(pubkey []byte, inviteCode string) error
- func (n *N) CacheEvents(f *filter.F, events event.S)
- func (n *N) CacheMarshaledJSON(f *filter.F, marshaledJSON [][]byte)
- func (n *N) CheckForDeleted(ev *event.E, admins [][]byte) error
- func (n *N) Close() (err error)
- func (n *N) CountEvents(c context.Context, f *filter.F) (count int, approximate bool, err error)
- func (n *N) DeleteEvent(c context.Context, eid []byte) error
- func (n *N) DeleteEventBySerial(c context.Context, ser *types.Uint40, ev *event.E) error
- func (n *N) DeleteExpired()
- func (n *N) DeleteInviteCode(code string) error
- func (n *N) DeleteMarker(key string) error
- func (n *N) Driver() neo4j.DriverWithContext
- func (n *N) EventIdsBySerial(start uint64, count int) (evs []uint64, err error)
- func (n *N) ExecuteRead(ctx context.Context, cypher string, params map[string]any) (*CollectedResult, error)
- func (n *N) ExecuteWrite(ctx context.Context, cypher string, params map[string]any) (neo4j.ResultWithContext, error)
- func (n *N) ExecuteWriteTransaction(ctx context.Context, work func(tx neo4j.ManagedTransaction) (any, error)) (any, error)
- func (n *N) Export(c context.Context, w io.Writer, pubkeys ...[]byte)
- func (n *N) ExtendBlossomSubscription(pubkey []byte, tier string, storageMB int64, daysExtended int) error
- func (n *N) ExtendSubscription(pubkey []byte, days int) error
- func (n *N) FetchEventBySerial(ser *types.Uint40) (ev *event.E, err error)
- func (n *N) FetchEventsBySerials(serials []*types.Uint40) (events map[uint64]*event.E, err error)
- func (n *N) FindMentions(pubkey []byte, kinds []uint16) (graph.GraphResultI, error)
- func (n *N) FindMentionsByPubkeys(pubkeys []string, kinds []uint16) (*GraphResult, error)
- func (n *N) FindMentionsFromHex(pubkeyHex string, kinds []uint16) (*GraphResult, error)
- func (n *N) GetAllNIP43Members() ([][]byte, error)
- func (n *N) GetBlossomStorageQuota(pubkey []byte) (quotaMB int64, err error)
- func (n *N) GetCachedEvents(f *filter.F) (event.S, bool)
- func (n *N) GetCachedJSON(f *filter.F) ([][]byte, bool)
- func (n *N) GetFullIdPubkeyBySerial(ser *types.Uint40) (fidpk *store.IdPkTs, err error)
- func (n *N) GetFullIdPubkeyBySerials(sers []*types.Uint40) (fidpks []*store.IdPkTs, err error)
- func (n *N) GetMarker(key string) (value []byte, err error)
- func (n *N) GetNIP43Membership(pubkey []byte) (*database.NIP43Membership, error)
- func (n *N) GetOrCreateRelayIdentitySecret() (skb []byte, err error)
- func (n *N) GetPaymentHistory(pubkey []byte) ([]database.Payment, error)
- func (n *N) GetRelayIdentitySecret() (skb []byte, err error)
- func (n *N) GetSerialById(id []byte) (ser *types.Uint40, err error)
- func (n *N) GetSerialsByIds(ids *tag.T) (serials map[string]*types.Uint40, err error)
- func (n *N) GetSerialsByIdsWithFilter(ids *tag.T, fn func(ev *event.E, ser *types.Uint40) bool) (serials map[string]*types.Uint40, err error)
- func (n *N) GetSerialsByRange(idx database.Range) (serials types.Uint40s, err error)
- func (n *N) GetSerialsFromFilter(f *filter.F) (serials types.Uint40s, err error)
- func (n *N) GetSubscription(pubkey []byte) (*database.Subscription, error)
- func (n *N) GetThreadParents(eventID []byte) (*GraphResult, error)
- func (n *N) GetThreadReplies(eventID []byte, kinds []uint16) (*GraphResult, error)
- func (n *N) HasMarker(key string) bool
- func (n *N) Import(rr io.Reader)
- func (n *N) ImportEventsFromReader(ctx context.Context, rr io.Reader) error
- func (n *N) ImportEventsFromStrings(ctx context.Context, eventJSONs []string, policyManager interface{ ... }) error
- func (n *N) Init(path string) (err error)
- func (n *N) InvalidateQueryCache()
- func (n *N) IsFirstTimeUser(pubkey []byte) (bool, error)
- func (n *N) IsNIP43Member(pubkey []byte) (isMember bool, err error)
- func (n *N) IsSubscriptionActive(pubkey []byte) (bool, error)
- func (n *N) MaxConcurrentQueries() int
- func (n *N) Path() string
- func (n *N) ProcessDelete(ev *event.E, admins [][]byte) error
- func (n *N) PublishNIP43MembershipEvent(kind int, pubkey []byte) error
- func (n *N) QueryAllVersions(c context.Context, f *filter.F) (evs event.S, err error)
- func (n *N) QueryDeleteEventsByTargetId(c context.Context, targetEventId []byte) (evs event.S, err error)
- func (n *N) QueryEvents(c context.Context, f *filter.F) (evs event.S, err error)
- func (n *N) QueryEventsWithOptions(c context.Context, f *filter.F, includeDeleteEvents bool, showAllVersions bool) (evs event.S, err error)
- func (n *N) QueryForIds(c context.Context, f *filter.F) (idPkTs []*store.IdPkTs, err error)
- func (n *N) QueryForSerials(c context.Context, f *filter.F) (serials types.Uint40s, err error)
- func (n *N) QuerySem() chan struct{}
- func (n *N) Ready() <-chan struct{}
- func (n *N) RecordPayment(pubkey []byte, amount int64, invoice, preimage string) error
- func (n *N) RemoveNIP43Member(pubkey []byte) error
- func (n *N) RunMigrations()
- func (n *N) SaveEvent(c context.Context, ev *event.E) (exists bool, err error)
- func (n *N) SetLogLevel(level string)
- func (n *N) SetMarker(key string, value []byte) error
- func (n *N) SetRelayIdentitySecret(skb []byte) error
- func (n *N) StoreInviteCode(code string, expiresAt time.Time) error
- func (n *N) Sync() (err error)
- func (n *N) TraverseFollowers(seedPubkey []byte, maxDepth int) (graph.GraphResultI, error)
- func (n *N) TraverseFollowersFromHex(seedPubkeyHex string, maxDepth int) (*GraphResult, error)
- func (n *N) TraverseFollows(seedPubkey []byte, maxDepth int) (graph.GraphResultI, error)
- func (n *N) TraverseFollowsFromHex(seedPubkeyHex string, maxDepth int) (*GraphResult, error)
- func (n *N) TraverseThread(seedEventID []byte, maxDepth int, direction string) (graph.GraphResultI, error)
- func (n *N) TraverseThreadFromHex(seedEventIDHex string, maxDepth int, direction string) (*GraphResult, error)
- func (n *N) ValidateInviteCode(code string) (valid bool, err error)
- func (n *N) Wipe() (err error)
- func (n *N) WouldReplaceEvent(ev *event.E) (bool, types.Uint40s, error)
- type ProcessedSocialEvent
- type SocialEventProcessor
- type UpdateContactListParams
- type UpdateMuteListParams
Constants ¶
const ( // BinaryEncodedLen is the length of a binary-encoded 32-byte hash with null terminator BinaryEncodedLen = 33 // HexEncodedLen is the length of a hex-encoded 32-byte hash (pubkey or event ID) HexEncodedLen = 64 // HashLen is the raw length of a hash (pubkey/event ID) HashLen = 32 )
Tag binary encoding constants (matching the nostr library)
Variables ¶
This section is empty.
Functions ¶
func ExtractETagValue ¶ added in v0.32.2
ExtractETagValue extracts an event ID from an e-tag, handling binary encoding. Returns lowercase hex string suitable for Neo4j storage. Returns empty string if the tag doesn't have a valid value.
func ExtractPTagValue ¶ added in v0.32.2
ExtractPTagValue extracts a pubkey from a p-tag, handling binary encoding. Returns lowercase hex string suitable for Neo4j storage. Returns empty string if the tag doesn't have a valid value.
func IsBinaryEncoded ¶ added in v0.32.2
IsBinaryEncoded checks if a value is stored in the nostr library's binary-optimized format
func IsValidHexPubkey ¶ added in v0.32.2
IsValidHexPubkey checks if a string is a valid 64-character hex pubkey
func NewLogger ¶
NewLogger creates a new neo4j logger.
func NormalizePubkeyHex ¶ added in v0.32.2
NormalizePubkeyHex ensures a pubkey/event ID is in lowercase hex format. It handles: - Binary-encoded values (33 bytes with null terminator) -> converts to lowercase hex - Raw binary values (32 bytes) -> converts to lowercase hex - Uppercase hex strings -> converts to lowercase - Already lowercase hex -> returns as-is
This should be used for all pubkeys and event IDs before storing in Neo4j to prevent duplicate nodes due to case differences.
Types ¶
type CollectedResult ¶ added in v0.30.0
type CollectedResult struct {
// contains filtered or unexported fields
}
CollectedResult wraps pre-fetched Neo4j records for iteration after session close This is necessary because Neo4j results are lazy and need an open session for iteration
func (*CollectedResult) Err ¶ added in v0.32.1
func (r *CollectedResult) Err() error
Err returns any error from iteration (always nil for pre-collected results) This method satisfies the resultiter.Neo4jResultIterator interface
func (*CollectedResult) Len ¶ added in v0.30.0
func (r *CollectedResult) Len() int
Len returns the number of records
func (*CollectedResult) Next ¶ added in v0.30.0
func (r *CollectedResult) Next(ctx context.Context) bool
Next advances to the next record, returning true if there is one
func (*CollectedResult) Record ¶ added in v0.30.0
func (r *CollectedResult) Record() *neo4j.Record
Record returns the current record
type GraphAdapter ¶ added in v0.35.0
type GraphAdapter struct {
// contains filtered or unexported fields
}
GraphAdapter wraps a Neo4j database instance and implements graph.GraphDatabase interface. This allows the graph executor to call database traversal methods without the database package importing the graph package.
func NewGraphAdapter ¶ added in v0.35.0
func NewGraphAdapter(db *N) *GraphAdapter
NewGraphAdapter creates a new GraphAdapter wrapping the given Neo4j database.
func (*GraphAdapter) FindMentions ¶ added in v0.35.0
func (a *GraphAdapter) FindMentions(pubkey []byte, kinds []uint16) (graph.GraphResultI, error)
FindMentions implements graph.GraphDatabase.
func (*GraphAdapter) TraverseFollowers ¶ added in v0.35.0
func (a *GraphAdapter) TraverseFollowers(seedPubkey []byte, maxDepth int) (graph.GraphResultI, error)
TraverseFollowers implements graph.GraphDatabase.
func (*GraphAdapter) TraverseFollows ¶ added in v0.35.0
func (a *GraphAdapter) TraverseFollows(seedPubkey []byte, maxDepth int) (graph.GraphResultI, error)
TraverseFollows implements graph.GraphDatabase.
func (*GraphAdapter) TraverseThread ¶ added in v0.35.0
func (a *GraphAdapter) TraverseThread(seedEventID []byte, maxDepth int, direction string) (graph.GraphResultI, error)
TraverseThread implements graph.GraphDatabase.
type GraphResult ¶ added in v0.35.0
type GraphResult struct {
// PubkeysByDepth maps depth -> pubkeys first discovered at that depth.
// Each pubkey appears ONLY in the array for the depth where it was first seen.
// Depth 1 = direct connections, Depth 2 = connections of connections, etc.
PubkeysByDepth map[int][]string
// EventsByDepth maps depth -> event IDs discovered at that depth.
// Used for thread traversal queries.
EventsByDepth map[int][]string
// FirstSeenPubkey tracks which depth each pubkey was first discovered.
// Key is pubkey hex, value is the depth (1-indexed).
FirstSeenPubkey map[string]int
// FirstSeenEvent tracks which depth each event was first discovered.
// Key is event ID hex, value is the depth (1-indexed).
FirstSeenEvent map[string]int
// TotalPubkeys is the count of unique pubkeys discovered across all depths.
TotalPubkeys int
// TotalEvents is the count of unique events discovered across all depths.
TotalEvents int
}
GraphResult contains depth-organized traversal results for graph queries. It tracks pubkeys and events discovered at each depth level, ensuring each entity appears only at the depth where it was first discovered.
This is the Neo4j implementation that mirrors the Badger implementation in pkg/database/graph-result.go, implementing the graph.GraphResultI interface.
func NewGraphResult ¶ added in v0.35.0
func NewGraphResult() *GraphResult
NewGraphResult creates a new initialized GraphResult.
func (*GraphResult) AddEventAtDepth ¶ added in v0.35.0
func (r *GraphResult) AddEventAtDepth(eventIDHex string, depth int) bool
AddEventAtDepth adds an event ID to the result at the specified depth if not already seen. Returns true if the event was added (first time seen), false if already exists.
func (*GraphResult) AddPubkeyAtDepth ¶ added in v0.35.0
func (r *GraphResult) AddPubkeyAtDepth(pubkeyHex string, depth int) bool
AddPubkeyAtDepth adds a pubkey to the result at the specified depth if not already seen. Returns true if the pubkey was added (first time seen), false if already exists.
func (*GraphResult) GetAllEvents ¶ added in v0.35.0
func (r *GraphResult) GetAllEvents() []string
GetAllEvents returns all event IDs discovered across all depths.
func (*GraphResult) GetAllPubkeys ¶ added in v0.35.0
func (r *GraphResult) GetAllPubkeys() []string
GetAllPubkeys returns all pubkeys discovered across all depths.
func (*GraphResult) GetDepthsSorted ¶ added in v0.35.0
func (r *GraphResult) GetDepthsSorted() []int
GetDepthsSorted returns all depths that have pubkeys, sorted ascending.
func (*GraphResult) GetEventDepthsSorted ¶ added in v0.35.0
func (r *GraphResult) GetEventDepthsSorted() []int
GetEventDepthsSorted returns all depths that have events, sorted ascending.
func (*GraphResult) GetEventsByDepth ¶ added in v0.35.0
func (r *GraphResult) GetEventsByDepth() map[int][]string
GetEventsByDepth returns the EventsByDepth map for external access.
func (*GraphResult) GetPubkeysByDepth ¶ added in v0.35.0
func (r *GraphResult) GetPubkeysByDepth() map[int][]string
GetPubkeysByDepth returns the PubkeysByDepth map for external access.
func (*GraphResult) GetTotalEvents ¶ added in v0.35.0
func (r *GraphResult) GetTotalEvents() int
GetTotalEvents returns the total event count for external access.
func (*GraphResult) GetTotalPubkeys ¶ added in v0.35.0
func (r *GraphResult) GetTotalPubkeys() int
GetTotalPubkeys returns the total pubkey count for external access.
func (*GraphResult) HasEvent ¶ added in v0.35.0
func (r *GraphResult) HasEvent(eventIDHex string) bool
HasEvent returns true if the event has been discovered at any depth.
func (*GraphResult) HasPubkey ¶ added in v0.35.0
func (r *GraphResult) HasPubkey(pubkeyHex string) bool
HasPubkey returns true if the pubkey has been discovered at any depth.
func (*GraphResult) ToDepthArrays ¶ added in v0.35.0
func (r *GraphResult) ToDepthArrays() [][]string
ToDepthArrays converts the result to the response format: array of arrays. Index 0 = depth 1 pubkeys, Index 1 = depth 2 pubkeys, etc. Empty arrays are included for depths with no pubkeys to maintain index alignment.
func (*GraphResult) ToEventDepthArrays ¶ added in v0.35.0
func (r *GraphResult) ToEventDepthArrays() [][]string
ToEventDepthArrays converts event results to the response format: array of arrays. Index 0 = depth 1 events, Index 1 = depth 2 events, etc.
type Migration ¶ added in v0.32.6
type Migration struct {
Version string
Description string
Migrate func(ctx context.Context, n *N) error
}
Migration represents a database migration with a version identifier
type N ¶
type N struct {
Logger *logger
// contains filtered or unexported fields
}
N implements the database.Database interface using Neo4j as the storage backend
func New ¶
func New( ctx context.Context, cancel context.CancelFunc, dataDir, logLevel string, ) ( n *N, err error, )
New creates a new Neo4j-based database instance with default configuration. This is provided for backward compatibility with existing callers (tests, etc.). For full configuration control, use NewWithConfig instead.
func NewWithConfig ¶ added in v0.31.8
func NewWithConfig( ctx context.Context, cancel context.CancelFunc, cfg *database.DatabaseConfig, ) ( n *N, err error, )
NewWithConfig creates a new Neo4j-based database instance with full configuration. Configuration is passed from the centralized app config via DatabaseConfig.
func (*N) AddNIP43Member ¶
AddNIP43Member adds a member using an invite code
func (*N) CacheEvents ¶ added in v0.29.11
CacheEvents caches events (not implemented for Neo4j)
func (*N) CacheMarshaledJSON ¶
CacheMarshaledJSON caches marshaled JSON results (not implemented for Neo4j)
func (*N) CheckForDeleted ¶
CheckForDeleted checks if an event has been deleted
func (*N) CountEvents ¶
CountEvents counts events matching a filter
func (*N) DeleteEvent ¶
DeleteEvent deletes an event by its ID
func (*N) DeleteEventBySerial ¶
DeleteEventBySerial deletes an event by its serial number
func (*N) DeleteExpired ¶
func (n *N) DeleteExpired()
DeleteExpired deletes expired events based on NIP-40 expiration tags Events with an expiration property > 0 and <= current time are deleted
func (*N) DeleteInviteCode ¶
DeleteInviteCode removes an invite code
func (*N) DeleteMarker ¶
DeleteMarker removes a metadata marker
func (*N) Driver ¶ added in v0.35.1
func (n *N) Driver() neo4j.DriverWithContext
Driver returns the Neo4j driver for use in rate limiting.
func (*N) EventIdsBySerial ¶
EventIdsBySerial retrieves event IDs by serial range (stub)
func (*N) ExecuteRead ¶
func (n *N) ExecuteRead(ctx context.Context, cypher string, params map[string]any) (*CollectedResult, error)
ExecuteRead executes a read query against Neo4j with rate limiting and retry Returns a collected result that can be iterated after the session closes
func (*N) ExecuteWrite ¶
func (n *N) ExecuteWrite(ctx context.Context, cypher string, params map[string]any) (neo4j.ResultWithContext, error)
ExecuteWrite executes a write query against Neo4j with rate limiting and retry
func (*N) ExecuteWriteTransaction ¶
func (n *N) ExecuteWriteTransaction(ctx context.Context, work func(tx neo4j.ManagedTransaction) (any, error)) (any, error)
ExecuteWriteTransaction executes a transactional write operation with rate limiting
func (*N) Export ¶
Export exports events to a writer (JSONL format) If pubkeys are provided, only exports events from those authors Otherwise exports all events
func (*N) ExtendBlossomSubscription ¶
func (n *N) ExtendBlossomSubscription( pubkey []byte, tier string, storageMB int64, daysExtended int, ) error
ExtendBlossomSubscription extends a Blossom storage subscription
func (*N) ExtendSubscription ¶
ExtendSubscription extends a subscription by the specified number of days
func (*N) FetchEventBySerial ¶
FetchEventBySerial retrieves an event by its serial number
func (*N) FetchEventsBySerials ¶
func (n *N) FetchEventsBySerials(serials []*types.Uint40) ( events map[uint64]*event.E, err error, )
FetchEventsBySerials retrieves multiple events by their serial numbers
func (*N) FindMentions ¶ added in v0.35.0
FindMentions finds events that mention a pubkey via p-tags. This returns events grouped by depth, where depth represents how the events relate:
- Depth 1: Events that directly mention the seed pubkey
- Depth 2+: Not typically used for mentions (reserved for future expansion)
The kinds parameter filters which event kinds to include (e.g., [1] for notes only, [1,7] for notes and reactions, etc.)
Uses Neo4j MENTIONS relationships created by SaveEvent when processing p-tags.
func (*N) FindMentionsByPubkeys ¶ added in v0.35.0
func (n *N) FindMentionsByPubkeys(pubkeys []string, kinds []uint16) (*GraphResult, error)
FindMentionsByPubkeys returns events that mention any of the given pubkeys. Useful for finding mentions across a set of followed accounts.
func (*N) FindMentionsFromHex ¶ added in v0.35.0
func (n *N) FindMentionsFromHex(pubkeyHex string, kinds []uint16) (*GraphResult, error)
FindMentionsFromHex is a convenience wrapper that accepts hex-encoded pubkey.
func (*N) GetAllNIP43Members ¶
GetAllNIP43Members retrieves all member pubkeys
func (*N) GetBlossomStorageQuota ¶
GetBlossomStorageQuota retrieves the storage quota for a pubkey
func (*N) GetCachedEvents ¶ added in v0.29.11
GetCachedEvents retrieves cached events (not implemented for Neo4j)
func (*N) GetCachedJSON ¶
GetCachedJSON returns cached query results (not implemented for Neo4j)
func (*N) GetFullIdPubkeyBySerial ¶
GetFullIdPubkeyBySerial retrieves ID and pubkey for a serial number
func (*N) GetFullIdPubkeyBySerials ¶
GetFullIdPubkeyBySerials retrieves IDs and pubkeys for multiple serials
func (*N) GetMarker ¶
GetMarker retrieves a metadata marker
func (*N) GetNIP43Membership ¶
func (n *N) GetNIP43Membership(pubkey []byte) (*database.NIP43Membership, error)
GetNIP43Membership retrieves membership information
func (*N) GetOrCreateRelayIdentitySecret ¶
GetOrCreateRelayIdentitySecret retrieves or creates the relay identity
func (*N) GetPaymentHistory ¶
GetPaymentHistory retrieves payment history for a pubkey
func (*N) GetRelayIdentitySecret ¶
GetRelayIdentitySecret retrieves the relay's identity secret key
func (*N) GetSerialById ¶
GetSerialById retrieves the serial number for an event ID
func (*N) GetSerialsByIds ¶
GetSerialsByIds retrieves serial numbers for multiple event IDs
func (*N) GetSerialsByIdsWithFilter ¶
func (n *N) GetSerialsByIdsWithFilter( ids *tag.T, fn func(ev *event.E, ser *types.Uint40) bool, ) (serials map[string]*types.Uint40, err error)
GetSerialsByIdsWithFilter retrieves serials with a filter function
func (*N) GetSerialsByRange ¶
GetSerialsByRange retrieves serials within a range
func (*N) GetSerialsFromFilter ¶
GetSerialsFromFilter returns event serials matching a filter
func (*N) GetSubscription ¶
func (n *N) GetSubscription(pubkey []byte) (*database.Subscription, error)
GetSubscription retrieves subscription information for a pubkey
func (*N) GetThreadParents ¶ added in v0.35.0
func (n *N) GetThreadParents(eventID []byte) (*GraphResult, error)
GetThreadParents finds events that a given event references (its parents/quotes).
func (*N) GetThreadReplies ¶ added in v0.35.0
func (n *N) GetThreadReplies(eventID []byte, kinds []uint16) (*GraphResult, error)
GetThreadReplies finds all direct replies to an event. This is a convenience method that returns events at depth 1 with inbound direction.
func (*N) Import ¶
Import imports events from a reader (JSONL format)
func (*N) ImportEventsFromReader ¶
ImportEventsFromReader imports events from a reader
func (*N) ImportEventsFromStrings ¶
func (n *N) ImportEventsFromStrings( ctx context.Context, eventJSONs []string, policyManager interface { CheckPolicy(action string, ev *event.E, pubkey []byte, remote string) (bool, error) }, ) error
ImportEventsFromStrings imports events from JSON strings
func (*N) Init ¶
Init initializes the database with a given path (no-op, path set in New)
func (*N) InvalidateQueryCache ¶
func (n *N) InvalidateQueryCache()
InvalidateQueryCache invalidates the query cache (not implemented for Neo4j)
func (*N) IsFirstTimeUser ¶
IsFirstTimeUser checks if this is the first time a user is accessing the relay
func (*N) IsNIP43Member ¶
IsNIP43Member checks if a pubkey is a member
func (*N) IsSubscriptionActive ¶
IsSubscriptionActive checks if a pubkey has an active subscription
func (*N) MaxConcurrentQueries ¶ added in v0.35.1
MaxConcurrentQueries returns the maximum concurrent query limit.
func (*N) ProcessDelete ¶
ProcessDelete processes a kind 5 deletion event
func (*N) PublishNIP43MembershipEvent ¶
PublishNIP43MembershipEvent publishes a membership event
func (*N) QueryAllVersions ¶
QueryAllVersions retrieves all versions of events matching the filter
func (*N) QueryDeleteEventsByTargetId ¶
func (n *N) QueryDeleteEventsByTargetId(c context.Context, targetEventId []byte) ( evs event.S, err error, )
QueryDeleteEventsByTargetId retrieves delete events targeting a specific event ID
func (*N) QueryEvents ¶
QueryEvents retrieves events matching the given filter
func (*N) QueryEventsWithOptions ¶
func (n *N) QueryEventsWithOptions( c context.Context, f *filter.F, includeDeleteEvents bool, showAllVersions bool, ) (evs event.S, err error)
QueryEventsWithOptions retrieves events with specific options
func (*N) QueryForIds ¶
QueryForIds retrieves event IDs matching a filter
func (*N) QueryForSerials ¶
QueryForSerials retrieves event serials matching a filter
func (*N) QuerySem ¶ added in v0.35.1
func (n *N) QuerySem() chan struct{}
QuerySem returns the query semaphore for use in rate limiting.
func (*N) Ready ¶
func (n *N) Ready() <-chan struct{}
Ready returns a channel that closes when the database is ready to serve requests. This allows callers to wait for database warmup to complete.
func (*N) RecordPayment ¶
RecordPayment records a payment for subscription extension
func (*N) RemoveNIP43Member ¶
RemoveNIP43Member removes a member
func (*N) SaveEvent ¶
SaveEvent stores a Nostr event in the Neo4j database. It creates event nodes and relationships for authors, tags, and references. This method leverages Neo4j's graph capabilities to model Nostr's social graph naturally.
For social graph events (kinds 0, 3, 1984, 10000), it additionally processes them to maintain NostrUser nodes and FOLLOWS/MUTES/REPORTS relationships with event traceability.
To prevent Neo4j stack overflow errors with events containing thousands of tags, tags are processed in batches using UNWIND instead of generating inline Cypher.
func (*N) SetMarker ¶
SetMarker sets a metadata marker
func (*N) SetRelayIdentitySecret ¶
SetRelayIdentitySecret sets the relay's identity secret key
func (*N) StoreInviteCode ¶
StoreInviteCode stores an invite code with expiration
func (*N) Sync ¶
Sync flushes pending writes (Neo4j handles persistence automatically)
func (*N) TraverseFollowers ¶ added in v0.35.0
TraverseFollowers performs BFS traversal to find who follows the seed pubkey. This is the reverse of TraverseFollows - it finds users whose kind-3 lists contain the target pubkey(s).
Uses Neo4j's native path queries, but in reverse direction:
- Depth 1: Users who directly follow the seed (follower)-[:FOLLOWS]->(seed)
- Depth 2: Users who follow anyone at depth 1 (followers of followers)
- etc.
func (*N) TraverseFollowersFromHex ¶ added in v0.35.0
func (n *N) TraverseFollowersFromHex(seedPubkeyHex string, maxDepth int) (*GraphResult, error)
TraverseFollowersFromHex is a convenience wrapper that accepts hex-encoded pubkey.
func (*N) TraverseFollows ¶ added in v0.35.0
TraverseFollows performs BFS traversal of the follow graph starting from a seed pubkey. Returns pubkeys grouped by first-discovered depth (no duplicates across depths).
Uses Neo4j's native path queries with FOLLOWS relationships created by the social event processor from kind 3 contact list events.
The traversal works by using variable-length path patterns:
- Depth 1: Direct follows (seed)-[:FOLLOWS]->(followed)
- Depth 2: Follows of follows (seed)-[:FOLLOWS*2]->(followed)
- etc.
Each pubkey appears only at the depth where it was first discovered.
func (*N) TraverseFollowsFromHex ¶ added in v0.35.0
func (n *N) TraverseFollowsFromHex(seedPubkeyHex string, maxDepth int) (*GraphResult, error)
TraverseFollowsFromHex is a convenience wrapper that accepts hex-encoded pubkey.
func (*N) TraverseThread ¶ added in v0.35.0
func (n *N) TraverseThread(seedEventID []byte, maxDepth int, direction string) (graph.GraphResultI, error)
TraverseThread performs BFS traversal of thread structure via e-tags. Starting from a seed event, it finds all replies/references at each depth.
The traversal works bidirectionally using REFERENCES relationships:
- Inbound: Events that reference the seed (replies, reactions, reposts)
- Outbound: Events that the seed references (parents, quoted posts)
Note: REFERENCES relationships are only created if the referenced event exists in the database at the time of saving. This means some references may be missing if events were stored out of order.
Parameters:
- seedEventID: The event ID to start traversal from
- maxDepth: Maximum depth to traverse
- direction: "both" (default), "inbound" (replies to seed), "outbound" (seed's references)
func (*N) TraverseThreadFromHex ¶ added in v0.35.0
func (n *N) TraverseThreadFromHex(seedEventIDHex string, maxDepth int, direction string) (*GraphResult, error)
TraverseThreadFromHex is a convenience wrapper that accepts hex-encoded event ID.
func (*N) ValidateInviteCode ¶
ValidateInviteCode checks if an invite code is valid
type ProcessedSocialEvent ¶ added in v0.30.0
type ProcessedSocialEvent struct {
EventID string
EventKind int
Pubkey string
CreatedAt int64
ProcessedAt int64
RelationshipCount int
SupersededBy *string // nil if still active
}
ProcessedSocialEvent represents a processed social graph event in Neo4j
type SocialEventProcessor ¶ added in v0.30.0
type SocialEventProcessor struct {
// contains filtered or unexported fields
}
SocialEventProcessor handles kind 0, 3, 1984, 10000 events for social graph management
func NewSocialEventProcessor ¶ added in v0.30.0
func NewSocialEventProcessor(db *N) *SocialEventProcessor
NewSocialEventProcessor creates a new social event processor
Source Files
¶
- delete.go
- fetch-event.go
- graph-adapter.go
- graph-follows.go
- graph-mentions.go
- graph-result.go
- graph-thread.go
- hex_utils.go
- identity.go
- import-export.go
- logger.go
- markers.go
- migrations.go
- neo4j.go
- nip43.go
- query-events.go
- save-event.go
- schema.go
- serial.go
- social-event-processor.go
- subscriptions.go