207 lines
5.5 KiB
Go
207 lines
5.5 KiB
Go
//go:build !(js && wasm)
|
|
|
|
package database
|
|
|
|
import (
|
|
"lol.mleku.dev/log"
|
|
"next.orly.dev/pkg/database/indexes/types"
|
|
)
|
|
|
|
// AddInboundRefsToResult collects inbound references (events that reference discovered items)
|
|
// for events at a specific depth in the result.
|
|
//
|
|
// For example, if you have a follows graph result and want to find all kind-7 reactions
|
|
// to posts by users at depth 1, this collects those reactions and adds them to result.InboundRefs.
|
|
//
|
|
// Parameters:
|
|
// - result: The graph result to augment with ref data
|
|
// - depth: The depth at which to collect refs (0 = all depths)
|
|
// - kinds: Event kinds to collect (e.g., [7] for reactions, [6] for reposts)
|
|
func (d *D) AddInboundRefsToResult(result *GraphResult, depth int, kinds []uint16) error {
|
|
// Determine which events to find refs for
|
|
var targetEventIDs []string
|
|
|
|
if depth == 0 {
|
|
// Collect for all depths
|
|
targetEventIDs = result.GetAllEvents()
|
|
} else {
|
|
targetEventIDs = result.GetEventsAtDepth(depth)
|
|
}
|
|
|
|
// Also collect refs for events authored by pubkeys in the result
|
|
// This is common for "find reactions to posts by my follows" queries
|
|
pubkeys := result.GetAllPubkeys()
|
|
for _, pubkeyHex := range pubkeys {
|
|
pubkeySerial, err := d.PubkeyHexToSerial(pubkeyHex)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
// Get events authored by this pubkey
|
|
// For efficiency, limit to relevant event kinds that might have reactions
|
|
authoredEvents, err := d.GetEventsByAuthor(pubkeySerial, []uint16{1, 30023}) // notes and articles
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
for _, eventSerial := range authoredEvents {
|
|
eventIDHex, err := d.GetEventIDFromSerial(eventSerial)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
// Add to target list if not already tracking
|
|
if !result.HasEvent(eventIDHex) {
|
|
targetEventIDs = append(targetEventIDs, eventIDHex)
|
|
}
|
|
}
|
|
}
|
|
|
|
// For each target event, find referencing events
|
|
for _, eventIDHex := range targetEventIDs {
|
|
eventSerial, err := d.EventIDHexToSerial(eventIDHex)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
refSerials, err := d.GetReferencingEvents(eventSerial, kinds)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
for _, refSerial := range refSerials {
|
|
refEventIDHex, err := d.GetEventIDFromSerial(refSerial)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
// Get the kind of the referencing event
|
|
// For now, use the first kind in the filter (assumes single kind queries)
|
|
// TODO: Look up actual event kind from index if needed
|
|
if len(kinds) > 0 {
|
|
result.AddInboundRef(kinds[0], eventIDHex, refEventIDHex)
|
|
}
|
|
}
|
|
}
|
|
|
|
log.D.F("AddInboundRefsToResult: collected refs for %d target events", len(targetEventIDs))
|
|
|
|
return nil
|
|
}
|
|
|
|
// AddOutboundRefsToResult collects outbound references (events referenced by discovered items).
|
|
//
|
|
// For example, find all events that posts by users at depth 1 reference (quoted posts, replied-to posts).
|
|
func (d *D) AddOutboundRefsToResult(result *GraphResult, depth int, kinds []uint16) error {
|
|
// Determine source events
|
|
var sourceEventIDs []string
|
|
|
|
if depth == 0 {
|
|
sourceEventIDs = result.GetAllEvents()
|
|
} else {
|
|
sourceEventIDs = result.GetEventsAtDepth(depth)
|
|
}
|
|
|
|
// Also include events authored by pubkeys in result
|
|
pubkeys := result.GetAllPubkeys()
|
|
for _, pubkeyHex := range pubkeys {
|
|
pubkeySerial, err := d.PubkeyHexToSerial(pubkeyHex)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
authoredEvents, err := d.GetEventsByAuthor(pubkeySerial, kinds)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
for _, eventSerial := range authoredEvents {
|
|
eventIDHex, err := d.GetEventIDFromSerial(eventSerial)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if !result.HasEvent(eventIDHex) {
|
|
sourceEventIDs = append(sourceEventIDs, eventIDHex)
|
|
}
|
|
}
|
|
}
|
|
|
|
// For each source event, find referenced events
|
|
for _, eventIDHex := range sourceEventIDs {
|
|
eventSerial, err := d.EventIDHexToSerial(eventIDHex)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
refSerials, err := d.GetETagsFromEventSerial(eventSerial)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
for _, refSerial := range refSerials {
|
|
refEventIDHex, err := d.GetEventIDFromSerial(refSerial)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
// Use first kind for categorization
|
|
if len(kinds) > 0 {
|
|
result.AddOutboundRef(kinds[0], eventIDHex, refEventIDHex)
|
|
}
|
|
}
|
|
}
|
|
|
|
log.D.F("AddOutboundRefsToResult: collected refs from %d source events", len(sourceEventIDs))
|
|
|
|
return nil
|
|
}
|
|
|
|
// CollectRefsForPubkeys collects inbound references to events by specific pubkeys.
|
|
// This is useful for "find all reactions to posts by these users" queries.
|
|
//
|
|
// Parameters:
|
|
// - pubkeySerials: The pubkeys whose events should be checked for refs
|
|
// - refKinds: Event kinds to collect (e.g., [7] for reactions)
|
|
// - eventKinds: Event kinds to check for refs (e.g., [1] for notes)
|
|
func (d *D) CollectRefsForPubkeys(
|
|
pubkeySerials []*types.Uint40,
|
|
refKinds []uint16,
|
|
eventKinds []uint16,
|
|
) (*GraphResult, error) {
|
|
result := NewGraphResult()
|
|
|
|
for _, pubkeySerial := range pubkeySerials {
|
|
// Get events by this author
|
|
authoredEvents, err := d.GetEventsByAuthor(pubkeySerial, eventKinds)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
for _, eventSerial := range authoredEvents {
|
|
eventIDHex, err := d.GetEventIDFromSerial(eventSerial)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
// Find refs to this event
|
|
refSerials, err := d.GetReferencingEvents(eventSerial, refKinds)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
for _, refSerial := range refSerials {
|
|
refEventIDHex, err := d.GetEventIDFromSerial(refSerial)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
// Add to result
|
|
if len(refKinds) > 0 {
|
|
result.AddInboundRef(refKinds[0], eventIDHex, refEventIDHex)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
}
|