Compare commits

...

4 Commits

5 changed files with 89 additions and 51 deletions

View File

@ -4,6 +4,9 @@ mongodb:
server: server:
port: ":8080" # Port for the server to listen on port: ":8080" # Port for the server to listen on
read_timeout: 10 # Read timeout in seconds
write_timeout: 10 # Write timeout in seconds
idle_timeout: 120 # Idle timeout in seconds
pubkey_whitelist: pubkey_whitelist:
enabled: false enabled: false
pubkeys: #["3fe0ab6cbdb7ee27148202249e3fb3b89423c6f6cda6ef43ea5057c3d93088e4", pubkeys: #["3fe0ab6cbdb7ee27148202249e3fb3b89423c6f6cda6ef43ea5057c3d93088e4",

View File

@ -10,35 +10,39 @@
hx-target="#result" hx-target="#result"
hx-indicator="#spinner" hx-indicator="#spinner"
> >
<div class="content-right"> <div>
<div> <label for="pubkey">Pubkey:</label>
<label for="pubkey">Pubkey:</label> <input
<input class="p-2 m-2 text-black rounded-md"
class="p-2 m-2 text-black rounded-md" type="text"
type="text" id="pubkey"
id="pubkey" name="pubkey"
name="pubkey" required
required maxlength="64"
maxlength="64" />
/>
</div>
<div>
<label for="relayUrls">Relay URLs (comma separated):</label>
<input
class="p-2 m-2 text-black rounded-md"
type="text"
id="relayUrls"
name="relayUrls"
required
/>
</div>
</div> </div>
<button <div>
class="p-2 m-2 font-bold bg-green-500 rounded-md font-xl" <label for="relayUrls">Relay URLs (comma separated):</label>
type="submit" <input
> class="p-2 m-2 text-black rounded-md"
Import Events type="text"
</button> id="relayUrls"
name="relayUrls"
required
/>
</div>
<div class="flex items-center justify-center" style="height: 32px">
<!-- Adjust height as needed -->
<button
id="import-button"
class="p-2 m-2 font-bold bg-green-500 rounded-md font-xl"
type="submit"
>
Import Events
</button>
<div id="spinner" class="spinner"></div>
</div>
<div id="result" class="p-2 m-2 text-xl font-bold"></div>
<div class="font-bold text-md"> <div class="font-bold text-md">
⚠️ This Feature is Experimental<br /> ⚠️ This Feature is Experimental<br />
If you are whitelisted, this SHOULD capture all of your events<br /> If you are whitelisted, this SHOULD capture all of your events<br />
@ -46,12 +50,7 @@
</div> </div>
</form> </form>
</div> </div>
<div
id="spinner"
class="m-4 text-lg font-bold text-center spinner"
style="display: none"
></div>
<div id="result" class="p-2 m-2 text-xl font-bold"></div>
<button <button
hx-get="/" hx-get="/"
hx-swap="outerHTML" hx-swap="outerHTML"
@ -60,19 +59,23 @@
> >
Return to Dashboard Return to Dashboard
</button> </button>
<script> <script>
document document
.getElementById("import-form") .getElementById("import-form")
.addEventListener("submit", function () { .addEventListener("submit", function () {
document.getElementById("import-button").style.display = "none";
document.getElementById("spinner").style.display = "block"; document.getElementById("spinner").style.display = "block";
}); });
document.addEventListener("htmx:afterRequest", function () { document.addEventListener("htmx:afterRequest", function () {
document.getElementById("spinner").style.display = "none"; document.getElementById("spinner").style.display = "none";
// No need to bring back the import button
}); });
document.addEventListener("htmx:requestError", function () { document.addEventListener("htmx:requestError", function () {
document.getElementById("spinner").style.display = "none"; document.getElementById("spinner").style.display = "none";
document.getElementById("import-button").style.display = "block"; // Bring back the button only on error
}); });
</script> </script>
</main> </main>

View File

@ -6,7 +6,10 @@ type ServerConfig struct {
Database string `yaml:"database"` Database string `yaml:"database"`
} `yaml:"mongodb"` } `yaml:"mongodb"`
Server struct { Server struct {
Port string `yaml:"port"` Port string `yaml:"port"`
ReadTimeout int `yaml:"read_timeout"` // Timeout in seconds
WriteTimeout int `yaml:"write_timeout"` // Timeout in seconds
IdleTimeout int `yaml:"idle_timeout"` // Timeout in seconds
} `yaml:"server"` } `yaml:"server"`
RateLimit RateLimitConfig `yaml:"rate_limit"` RateLimit RateLimitConfig `yaml:"rate_limit"`
PubkeyWhitelist PubkeyWhitelistConfig `yaml:"pubkey_whitelist"` PubkeyWhitelist PubkeyWhitelistConfig `yaml:"pubkey_whitelist"`

31
main.go
View File

@ -62,9 +62,9 @@ func startServer(config *configTypes.ServerConfig, mux *http.ServeMux) {
server := &http.Server{ server := &http.Server{
Addr: config.Server.Port, Addr: config.Server.Port,
Handler: mux, Handler: mux,
ReadTimeout: 10 * time.Second, ReadTimeout: time.Duration(config.Server.ReadTimeout) * time.Second,
WriteTimeout: 10 * time.Second, WriteTimeout: time.Duration(config.Server.WriteTimeout) * time.Second,
IdleTimeout: 120 * time.Second, IdleTimeout: time.Duration(config.Server.IdleTimeout) * time.Second,
} }
fmt.Printf("Server is running on http://localhost%s\n", config.Server.Port) fmt.Printf("Server is running on http://localhost%s\n", config.Server.Port)
err := server.ListenAndServe() err := server.ListenAndServe()
@ -72,20 +72,21 @@ func startServer(config *configTypes.ServerConfig, mux *http.ServeMux) {
fmt.Println("Error starting server:", err) fmt.Println("Error starting server:", err)
} }
} }
var wsServer = &websocket.Server{ var wsServer = &websocket.Server{
Handshake: func(config *websocket.Config, r *http.Request) error { Handshake: func(config *websocket.Config, r *http.Request) error {
// Skip origin check // Skip origin check
return nil return nil
}, },
Handler: websocket.Handler(relay.WebSocketHandler), Handler: websocket.Handler(relay.WebSocketHandler),
} }
func ListenAndServe(w http.ResponseWriter, r *http.Request) { func ListenAndServe(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Upgrade") == "websocket" { if r.Header.Get("Upgrade") == "websocket" {
wsServer.ServeHTTP(w, r) wsServer.ServeHTTP(w, r)
} else if r.Header.Get("Accept") == "application/nostr+json" { } else if r.Header.Get("Accept") == "application/nostr+json" {
nip.RelayInfoHandler(w, r) nip.RelayInfoHandler(w, r)
} else { } else {
app.RootHandler(w, r) app.RootHandler(w, r)
} }
} }

View File

@ -29,6 +29,14 @@ func HandleKind5(ctx context.Context, evt relay.Event, dbClient *mongo.Client, w
kind := parts[0] kind := parts[0]
pubKey := parts[1] pubKey := parts[1]
dID := parts[2] dID := parts[2]
// Delete previous kind 5 events with the same "a" tag if they exist
if err := deletePreviousKind5Events(ctx, kind, pubKey, dID, dbClient); err != nil {
response.SendOK(ws, evt.ID, false, fmt.Sprintf("error: %v", err))
return fmt.Errorf("error deleting previous kind 5 events: %v", err)
}
// Delete target events by kind, pubKey, and dID
if err := deleteEventByKindPubKeyDID(ctx, kind, pubKey, dID, evt.CreatedAt, dbClient); err != nil { if err := deleteEventByKindPubKeyDID(ctx, kind, pubKey, dID, evt.CreatedAt, dbClient); err != nil {
response.SendOK(ws, evt.ID, false, fmt.Sprintf("error: %v", err)) response.SendOK(ws, evt.ID, false, fmt.Sprintf("error: %v", err))
return fmt.Errorf("error deleting events with kind %s, pubkey %s, and dID %s: %v", kind, pubKey, dID, err) return fmt.Errorf("error deleting events with kind %s, pubkey %s, and dID %s: %v", kind, pubKey, dID, err)
@ -47,6 +55,26 @@ func HandleKind5(ctx context.Context, evt relay.Event, dbClient *mongo.Client, w
return nil return nil
} }
func deletePreviousKind5Events(ctx context.Context, kind string, pubKey string, dID string, dbClient *mongo.Client) error {
collection := dbClient.Database("grain").Collection("event-kind5")
filter := bson.M{
"tags": bson.M{
"$elemMatch": bson.M{
"0": "a",
"1": fmt.Sprintf("%s:%s:%s", kind, pubKey, dID),
},
},
}
_, err := collection.DeleteMany(ctx, filter)
if err != nil {
return fmt.Errorf("error deleting previous kind 5 events from collection event-kind5: %v", err)
}
fmt.Printf("Deleted previous kind 5 events for kind %s, pubkey %s, and dID %s\n", kind, pubKey, dID)
return nil
}
func deleteEventByID(ctx context.Context, eventID string, pubKey string, dbClient *mongo.Client) error { func deleteEventByID(ctx context.Context, eventID string, pubKey string, dbClient *mongo.Client) error {
collections, err := dbClient.Database("grain").ListCollectionNames(ctx, bson.M{}) collections, err := dbClient.Database("grain").ListCollectionNames(ctx, bson.M{})
if err != nil { if err != nil {