diff --git a/.gitignore b/.gitignore index 3b20866..628a2f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /tmp -config.yml \ No newline at end of file +config.yml +relay_metadata.json \ No newline at end of file diff --git a/main.go b/main.go index 0cbc035..367ce56 100644 --- a/main.go +++ b/main.go @@ -49,11 +49,17 @@ func main() { for _, kindSizeLimit := range config.RateLimit.KindSizeLimits { sizeLimiter.AddKindSizeLimit(kindSizeLimit.Kind, kindSizeLimit.MaxSize) } - + utils.SetSizeLimiter(sizeLimiter) + err = web.LoadRelayMetadata("relay_metadata.json") + if err != nil { + log.Fatalf("Failed to load relay metadata: %v", err) + } + mux := http.NewServeMux() mux.HandleFunc("/", ListenAndServe) + mux.HandleFunc("/relay-info", web.RelayInfoHandler) mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("web/static")))) mux.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "web/static/img/favicon.ico") diff --git a/readme.md b/readme.md index 56cbce1..fa5cdaa 100644 --- a/readme.md +++ b/readme.md @@ -22,11 +22,14 @@ There is an example config in this repo. Copy the example config to config.yml t cp config.example.yml config.yml ``` +Additionally, you may set metadata Information for your relay with `relay_matadata.json` + +```bash +cp relay_metadata.example.json relay_metadata.json +``` + ### TODO -- Handle Kind 5 explicitely to delete Events from the Database -- Handle Ephemeral event - - configurable amount of time to keep ephemeral notes - configurable event purging - by category - by kind diff --git a/relay_metadata.example.json b/relay_metadata.example.json new file mode 100644 index 0000000..765936c --- /dev/null +++ b/relay_metadata.example.json @@ -0,0 +1,9 @@ +{ + "name": "GRAIN Relay", + "description": "Go Relay Archetecture for Implementing Nostr", + "pubkey": "16f1a0100d4cfffbcc4230e8e0e4290cc5849c1adc64d6653fda07c031b1074b", + "contact": "oceanslim@gmx.com", + "supported_nips": [1, 2, 9, 11], + "software": "https://forge.happytavern.co/oceanslim/grain", + "version": "0.1.0" +} diff --git a/web/http.go b/web/http.go index 3195be5..1f5548c 100644 --- a/web/http.go +++ b/web/http.go @@ -2,6 +2,7 @@ package web import ( "context" + "encoding/json" "grain/relay/db" relay "grain/relay/types" "html/template" @@ -35,6 +36,20 @@ func RootHandler(w http.ResponseWriter, r *http.Request) { RenderTemplate(w, data, "index.html") } +func RelayInfoHandler(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("Accept") != "application/nostr+json" { + http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType) + return + } + + w.Header().Set("Content-Type", "application/nostr+json") + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + w.Header().Set("Access-Control-Allow-Methods", "GET") + + json.NewEncoder(w).Encode(relayMetadata) +} + // Define the base directories for views and templates const ( viewsDir = "web/views/" @@ -43,7 +58,7 @@ const ( // Define the common layout templates filenames var templateFiles = []string{ - "#layout.html", + "layout.html", "header.html", "footer.html", } @@ -52,7 +67,6 @@ var templateFiles = []string{ var layout = PrependDir(templatesDir, templateFiles) func RenderTemplate(w http.ResponseWriter, data PageData, view string) { - // Append the specific template for the route templates := append(layout, viewsDir+view) @@ -83,33 +97,26 @@ func PrependDir(dir string, files []string) []string { func FetchTopTenRecentEvents(client *mongo.Client) ([]relay.Event, error) { var results []relay.Event - collections, err := client.Database("grain").ListCollectionNames(context.TODO(), bson.M{}) + collection := client.Database("grain").Collection("events") + filter := bson.D{} + opts := options.Find().SetSort(bson.D{{Key: "createdat", Value: -1}}).SetLimit(10) + + cursor, err := collection.Find(context.TODO(), filter, opts) if err != nil { return nil, err } + defer cursor.Close(context.TODO()) - for _, collectionName := range collections { - collection := client.Database("grain").Collection(collectionName) - filter := bson.D{} - opts := options.Find().SetSort(bson.D{{Key: "createdat", Value: -1}}).SetLimit(10) - - cursor, err := collection.Find(context.TODO(), filter, opts) - if err != nil { + for cursor.Next(context.TODO()) { + var event relay.Event + if err := cursor.Decode(&event); err != nil { return nil, err } - defer cursor.Close(context.TODO()) + results = append(results, event) + } - for cursor.Next(context.TODO()) { - var event relay.Event - if err := cursor.Decode(&event); err != nil { - return nil, err - } - results = append(results, event) - } - - if err := cursor.Err(); err != nil { - return nil, err - } + if err := cursor.Err(); err != nil { + return nil, err } return results, nil diff --git a/web/relay_metadata.go b/web/relay_metadata.go new file mode 100644 index 0000000..43d592e --- /dev/null +++ b/web/relay_metadata.go @@ -0,0 +1,32 @@ +package web + +import ( + "encoding/json" + "os" +) + +type RelayMetadata struct { + Name string `json:"name"` + Description string `json:"description"` + Pubkey string `json:"pubkey"` + Contact string `json:"contact"` + SupportedNIPs []int `json:"supported_nips"` + Software string `json:"software"` + Version string `json:"version"` +} + +var relayMetadata RelayMetadata + +func LoadRelayMetadata(filename string) error { + data, err := os.ReadFile(filename) + if err != nil { + return err + } + + err = json.Unmarshal(data, &relayMetadata) + if err != nil { + return err + } + + return nil +}