77 lines
1.9 KiB
Go
77 lines
1.9 KiB
Go
package mysql
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
|
|
"github.com/fiatjaf/eventstore"
|
|
"github.com/nbd-wtf/go-nostr"
|
|
)
|
|
|
|
func (b *MySQLBackend) SaveEvent(ctx context.Context, evt *nostr.Event) error {
|
|
deleteQuery, deleteParams, shouldDelete := deleteBeforeSaveSql(evt)
|
|
if shouldDelete {
|
|
_, _ = b.DB.ExecContext(ctx, deleteQuery, deleteParams...)
|
|
}
|
|
|
|
sql, params, _ := saveEventSql(evt)
|
|
res, err := b.DB.ExecContext(ctx, sql, params...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
nr, err := res.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if nr == 0 {
|
|
return eventstore.ErrDupEvent
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func deleteBeforeSaveSql(evt *nostr.Event) (string, []any, bool) {
|
|
// react to different kinds of events
|
|
var (
|
|
query = ""
|
|
params []any
|
|
shouldDelete bool
|
|
)
|
|
if evt.Kind == nostr.KindSetMetadata || evt.Kind == nostr.KindContactList || (10000 <= evt.Kind && evt.Kind < 20000) {
|
|
// delete past events from this user
|
|
query = `DELETE FROM event WHERE pubkey = ? AND kind = ?`
|
|
params = []any{evt.PubKey, evt.Kind}
|
|
shouldDelete = true
|
|
} else if evt.Kind == nostr.KindRecommendServer {
|
|
// delete past recommend_server events equal to this one
|
|
query = `DELETE FROM event WHERE pubkey = ? AND kind = ? AND content = ?`
|
|
params = []any{evt.PubKey, evt.Kind, evt.Content}
|
|
shouldDelete = true
|
|
} else if evt.Kind >= 30000 && evt.Kind < 40000 {
|
|
// NIP-33
|
|
d := evt.Tags.GetFirst([]string{"d"})
|
|
if d != nil {
|
|
query = `DELETE FROM event WHERE pubkey = ? AND kind = ? AND tags LIKE ?`
|
|
params = []any{evt.PubKey, evt.Kind, d.Value()}
|
|
shouldDelete = true
|
|
}
|
|
}
|
|
|
|
return query, params, shouldDelete
|
|
}
|
|
|
|
func saveEventSql(evt *nostr.Event) (string, []any, error) {
|
|
const query = `INSERT INTO event (
|
|
id, pubkey, created_at, kind, tags, content, sig)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
|
|
|
var (
|
|
tagsj, _ = json.Marshal(evt.Tags)
|
|
params = []any{evt.ID, evt.PubKey, evt.CreatedAt, evt.Kind, tagsj, evt.Content, evt.Sig}
|
|
)
|
|
|
|
return query, params, nil
|
|
}
|