append mutelist event pubkeys to blacklist

This commit is contained in:
0ceanSlim 2024-10-17 12:31:52 -04:00
parent 3de1aeb998
commit 21c431dd22
6 changed files with 194 additions and 2 deletions

View File

@ -11,3 +11,6 @@ permanent_blacklist_pubkeys:
- db0c9b8acd6101adb9b281c5321f98f6eebb33c5719d230ed1870997538a9765
permanent_blacklist_npubs:
- npub1x0r5gflnk2mn6h3c70nvnywpy2j46gzqwg6k7uw6fxswyz0md9qqnhshtn
mute_list_event_ids:
# - 76be64157af3e00cf50fae5fda63170cd4636065adf34960a4bec84a2022610b
# mutelist Event MUST be stored in this relay for it to be retrieved.

View File

@ -1,6 +1,7 @@
package config
import (
"encoding/json"
"fmt"
types "grain/config/types"
"grain/server/utils"
@ -10,6 +11,7 @@ import (
"sync"
"time"
"github.com/gorilla/websocket"
"gopkg.in/yaml.v2"
)
@ -200,3 +202,173 @@ func saveBlacklistConfig(blacklistConfig types.BlacklistConfig) error {
return nil
}
// FetchPubkeysFromLocalMuteList sends a REQ to the local relay for mute list events.
func FetchPubkeysFromLocalMuteList(localRelayURL string, muteListEventIDs []string) ([]string, error) {
var wg sync.WaitGroup
var mu sync.Mutex
var allPubkeys []string
results := make(chan []string, 1)
wg.Add(1)
go func() {
defer wg.Done()
conn, _, err := websocket.DefaultDialer.Dial(localRelayURL, nil)
if err != nil {
log.Printf("Failed to connect to local relay %s: %v", localRelayURL, err)
return
}
defer conn.Close()
subscriptionID := "mutelist-fetch"
// Create the REQ message to fetch the mute list events by IDs.
req := []interface{}{"REQ", subscriptionID, map[string]interface{}{
"ids": muteListEventIDs,
"kinds": []int{10000}, // Mute list events kind.
}}
reqJSON, err := json.Marshal(req)
if err != nil {
log.Printf("Failed to marshal request: %v", err)
return
}
err = conn.WriteMessage(websocket.TextMessage, reqJSON)
if err != nil {
log.Printf("Failed to send request to local relay %s: %v", localRelayURL, err)
return
}
// Listen for messages from the local relay.
for {
_, message, err := conn.ReadMessage()
if err != nil {
log.Printf("Error reading message from local relay %s: %v", localRelayURL, err)
break
}
// Log the raw message for debugging.
log.Printf("Received raw message: %s", message)
var response []interface{}
err = json.Unmarshal(message, &response)
if err != nil || len(response) < 2 {
log.Printf("Invalid message format or failed to unmarshal: %v", err)
continue
}
// Check for "EVENT" type messages.
eventType, ok := response[0].(string)
if !ok {
log.Printf("Unexpected event type: %v", response[0])
continue
}
if eventType == "EOSE" {
// End of subscription events; send a "CLOSE" message to the relay.
closeReq := []interface{}{"CLOSE", subscriptionID}
closeReqJSON, err := json.Marshal(closeReq)
if err != nil {
log.Printf("Failed to marshal close request: %v", err)
} else {
err = conn.WriteMessage(websocket.TextMessage, closeReqJSON)
if err != nil {
log.Printf("Failed to send close request to relay %s: %v", localRelayURL, err)
} else {
log.Println("Sent CLOSE request to end subscription.")
}
}
break
}
if eventType == "EVENT" {
// Safely cast the event data from the third element.
if len(response) < 3 {
log.Printf("Unexpected event format with insufficient data: %v", response)
continue
}
eventData, ok := response[2].(map[string]interface{})
if !ok {
log.Printf("Expected event data to be a map, got: %T", response[2])
continue
}
// Log event data for debugging.
log.Printf("Event data received: %+v", eventData)
pubkeys := extractPubkeysFromMuteListEvent(eventData)
results <- pubkeys
}
}
}()
go func() {
wg.Wait()
close(results)
}()
// Collect results from the relay.
for pubkeys := range results {
mu.Lock()
allPubkeys = append(allPubkeys, pubkeys...)
mu.Unlock()
}
return allPubkeys, nil
}
// extractPubkeysFromMuteListEvent extracts pubkeys from a mute list event.
func extractPubkeysFromMuteListEvent(eventData map[string]interface{}) []string {
var pubkeys []string
tags, ok := eventData["tags"].([]interface{})
if !ok {
log.Println("Tags field is missing or not an array")
return pubkeys
}
for _, tag := range tags {
tagArray, ok := tag.([]interface{})
if ok && len(tagArray) > 1 && tagArray[0] == "p" {
pubkey, ok := tagArray[1].(string)
if ok {
pubkeys = append(pubkeys, pubkey)
}
}
}
log.Printf("Extracted pubkeys: %v", pubkeys)
return pubkeys
}
// AppendFetchedPubkeysToBlacklist fetches pubkeys from the local relay and appends them to the blacklist.
func AppendFetchedPubkeysToBlacklist() error {
// Get the server configuration to determine the local relay URL.
cfg := GetConfig()
if cfg == nil {
return fmt.Errorf("server configuration is not loaded")
}
blacklistCfg := GetBlacklistConfig()
if blacklistCfg == nil {
return fmt.Errorf("blacklist configuration is not loaded")
}
// Construct the local relay WebSocket URL using the configured port.
localRelayURL := fmt.Sprintf("ws://localhost%s", cfg.Server.Port)
// Fetch pubkeys from the mute list events.
pubkeys, err := FetchPubkeysFromLocalMuteList(localRelayURL, blacklistCfg.MuteListEventIDs)
if err != nil {
return fmt.Errorf("failed to fetch pubkeys from mute list: %v", err)
}
// Add the fetched pubkeys to the permanent blacklist.
blacklistCfg.PermanentBlacklistPubkeys = append(blacklistCfg.PermanentBlacklistPubkeys, pubkeys...)
// Save the updated blacklist configuration.
return saveBlacklistConfig(*blacklistCfg)
}

View File

@ -8,4 +8,5 @@ type BlacklistConfig struct {
TempBanDuration int `yaml:"temp_ban_duration"`
PermanentBlacklistPubkeys []string `yaml:"permanent_blacklist_pubkeys"`
PermanentBlacklistNpubs []string `yaml:"permanent_blacklist_npubs"`
MuteListEventIDs []string `yaml:"mute_list_event_ids"`
}

1
go.mod
View File

@ -4,6 +4,7 @@ go 1.22.2
require (
github.com/btcsuite/btcd/btcec/v2 v2.3.4
github.com/gorilla/websocket v1.5.3
go.mongodb.org/mongo-driver v1.16.0
golang.org/x/net v0.27.0
gopkg.in/yaml.v2 v2.4.0

2
go.sum
View File

@ -28,6 +28,8 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=

17
main.go
View File

@ -23,7 +23,7 @@ import (
func main() {
utils.EnsureFileExists("config.yml", "app/static/examples/config.example.yml")
utils.EnsureFileExists("whitelist.yml", "app/static/examples/whitelist.example.yml")
utils.EnsureFileExists("blacklist.yml", "app/static/examples/blacklist.example.yml")
utils.EnsureFileExists("blacklist.yml", "app/static/examples/blacklist.example.yml")
utils.EnsureFileExists("relay_metadata.json", "app/static/examples/relay_metadata.example.json")
restartChan := make(chan struct{})
@ -46,11 +46,12 @@ func main() {
log.Fatal("Error loading whitelist config: ", err)
}
_, err = config.LoadBlacklistConfig("blacklist.yml")
_, err = config.LoadBlacklistConfig("blacklist.yml")
if err != nil {
log.Fatal("Error loading blacklist config: ", err)
}
// Start event purging in the background.
go mongo.ScheduleEventPurging(cfg)
config.SetResourceLimit(&cfg.ResourceLimits)
@ -71,6 +72,18 @@ func main() {
mux := setupRoutes()
server := startServer(cfg, mux, &wg)
// Append pubkeys from mute list events to the blacklist after the server starts.
go func() {
// Sleep for a short time to ensure the server is fully up.
time.Sleep(2 * time.Second)
err := config.AppendFetchedPubkeysToBlacklist()
if err != nil {
log.Printf("Failed to update blacklist: %v", err)
}
}()
// Monitor for server restart or shutdown signals.
select {
case <-restartChan:
log.Println("Restarting server...")