2024-09-14 11:02:22 +08:00

131 lines
3.0 KiB
Go

package main
import (
"context"
"encoding/json"
"io"
"log"
"os"
"path/filepath"
"time"
"github.com/fiatjaf/eventstore/strfry"
"github.com/fiatjaf/relay29"
"github.com/nbd-wtf/go-nostr"
)
var (
state *relay29.State
ctx = context.Background()
strfrydb strfry.StrfryBackend
)
func main() {
incoming := json.NewDecoder(os.Stdin)
outgoing := json.NewEncoder(os.Stdout)
curr, _ := os.Getwd()
path := filepath.Join(curr, "strfry29.json")
confb, err := os.ReadFile(path)
if err != nil {
log.Fatalf("couldn't open config file at %s: %s", path, err)
return
}
var conf struct {
Domain string `json:"domain"`
RelaySecretKey string `json:"relay_secret_key"`
StrfryConfig string `json:"strfry_config_path"`
StrfryExecutable string `json:"strfry_executable_path"`
}
if err := json.Unmarshal(confb, &conf); err != nil {
log.Fatalf("invalid json config at %s: %s", path, err)
return
}
strfrydb = strfry.StrfryBackend{
ConfigPath: conf.StrfryConfig,
ExecutablePath: conf.StrfryExecutable,
}
strfrydb.Init()
defer strfrydb.Close()
state = relay29.New(relay29.Options{
Domain: conf.Domain,
DB: &strfrydb,
SecretKey: conf.RelaySecretKey,
})
state.AllowPrivateGroups = false
state.GetAuthed = func(ctx context.Context) string { return "" }
state.Relay = protoRelay{}
// rebuild metadata events (replaceable) for all groups and make them available
filter := nostr.Filter{Kinds: []int{nostr.KindSimpleGroupMetadata, nostr.KindSimpleGroupAdmins, nostr.KindSimpleGroupMembers}}
if err := republishMetadataEvents(filter); err != nil {
log.Fatalf("failed to republish metadata events on startup: %s", err)
return
}
for {
var msg StrfryMessage
err := incoming.Decode(&msg)
if err == io.EOF {
return
}
if err != nil {
log.Print("[strfry29] failed to decode request. killing: " + err.Error())
return
}
// message, _ := json.Marshal(msg)
// log.Print("[strfry29] got event: ", string(message))
if reject, rejectMsg := accept(msg.Event); reject {
outgoing.Encode(StrfryResponse{
ID: msg.Event.ID,
Action: "reject",
Msg: rejectMsg,
})
} else {
outgoing.Encode(StrfryResponse{
ID: msg.Event.ID,
Action: "accept",
})
go func() {
time.Sleep(time.Millisecond * 200)
state.ApplyModerationAction(ctx, msg.Event)
state.ReactToJoinRequest(ctx, msg.Event)
state.ReactToLeaveRequest(ctx, msg.Event)
}()
}
}
}
type StrfryMessage struct {
Type string `json:"type"`
Event *nostr.Event `json:"event"`
SourceType string `json:"sourceType"`
}
type StrfryResponse struct {
ID string `json:"id"`
Action string `json:"action"`
Msg string `json:"msg"`
}
type protoRelay struct{}
func (p protoRelay) AddEvent(ctx context.Context, evt *nostr.Event) (skipBroadcast bool, writeError error) {
err := strfrydb.SaveEvent(ctx, evt)
return false, err
}
func (p protoRelay) BroadcastEvent(evt *nostr.Event) {
strfrydb.SaveEvent(ctx, evt)
}