You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
5.5 KiB
206 lines
5.5 KiB
//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 |
|
}
|
|
|