Files
realy/basic/query.go

87 lines
2.0 KiB
Go

package main
import (
"database/sql"
"encoding/hex"
"errors"
"fmt"
"strings"
"github.com/fiatjaf/go-nostr/event"
"github.com/fiatjaf/go-nostr/filter"
"github.com/rs/zerolog/log"
)
func (b *BasicRelay) QueryEvents(
filter *filter.EventFilter,
) (events []event.Event, err error) {
var conditions []string
var params []interface{}
if filter == nil {
err = errors.New("filter cannot be null")
return
}
if filter.ID != "" {
conditions = append(conditions, "id = ?")
params = append(params, filter.ID)
}
if filter.Kind != nil && *filter.Kind != 0 {
conditions = append(conditions, "kind = ?")
params = append(params, filter.Kind)
}
if filter.Authors != nil {
if len(filter.Authors) == 0 {
// authors being [] means you won't get anything
return
} else {
inkeys := make([]string, 0, len(filter.Authors))
for _, key := range filter.Authors {
// to prevent sql attack here we will check if
// these keys are valid 32byte hex
parsed, err := hex.DecodeString(key)
if err != nil || len(parsed) != 32 {
continue
}
inkeys = append(inkeys, fmt.Sprintf("'%x'", parsed))
}
conditions = append(conditions, `pubkey IN (`+strings.Join(inkeys, ",")+`)`)
}
}
if filter.TagEvent != "" {
conditions = append(conditions, tagConditions)
params = append(params, filter.TagEvent)
}
if filter.TagProfile != "" {
conditions = append(conditions, tagConditions)
params = append(params, filter.TagProfile)
}
if filter.Since != 0 {
conditions = append(conditions, "created_at > ?")
params = append(params, filter.Since)
}
if len(conditions) == 0 {
// fallback
conditions = append(conditions, "true")
}
query := b.DB.Rebind("SELECT * FROM event WHERE " +
strings.Join(conditions, " AND ") +
" ORDER BY created_at LIMIT 100")
err = b.DB.Select(&events, query, params...)
if err != nil && err != sql.ErrNoRows {
log.Warn().Err(err).Interface("filter", filter).Msg("failed to fetch events")
err = fmt.Errorf("failed to fetch events: %w", err)
}
return
}