2023-09-06 20:49:18 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2023-10-11 00:19:33 +02:00
|
|
|
"context"
|
2023-09-07 13:06:58 +02:00
|
|
|
"embed"
|
2023-10-11 00:19:33 +02:00
|
|
|
"fmt"
|
|
|
|
"html/template"
|
2023-09-06 20:49:18 +02:00
|
|
|
"net/http"
|
2023-09-07 13:06:58 +02:00
|
|
|
"strings"
|
2023-10-11 00:19:33 +02:00
|
|
|
|
|
|
|
"github.com/nbd-wtf/go-nostr"
|
2023-09-06 20:49:18 +02:00
|
|
|
)
|
|
|
|
|
2023-09-07 13:06:58 +02:00
|
|
|
// embed ui files
|
2023-10-11 00:19:33 +02:00
|
|
|
|
2023-09-07 13:06:58 +02:00
|
|
|
//go:embed ui/dist/*
|
2023-10-11 00:19:33 +02:00
|
|
|
var dist embed.FS
|
2023-09-07 13:06:58 +02:00
|
|
|
|
2023-10-11 00:19:33 +02:00
|
|
|
func inviteTreeHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
formattedInviteData := buildHTMLTree(whitelist, "")
|
2023-09-07 13:06:58 +02:00
|
|
|
|
2023-10-11 00:19:33 +02:00
|
|
|
data := map[string]interface{}{
|
2023-10-16 23:09:12 -03:00
|
|
|
"Relayname": s.RelayName,
|
|
|
|
"Relaydescription": s.RelayDescription,
|
2023-10-11 00:19:33 +02:00
|
|
|
"Pagetitle": "Invite Hierarchy",
|
|
|
|
"Pagecontent": `
|
|
|
|
<input type="text" id="inviteuser-input" placeholder="npub1..." /><button class="inviteuser">Invite!</button>
|
|
|
|
` + formattedInviteData,
|
2023-09-07 13:06:58 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 00:19:33 +02:00
|
|
|
tmpl, err := template.ParseFS(dist, "ui/dist/index.html")
|
2023-09-07 13:06:58 +02:00
|
|
|
if err != nil {
|
2023-10-11 00:19:33 +02:00
|
|
|
http.Error(w, "Error parsing template: "+err.Error(), http.StatusInternalServerError)
|
2023-09-07 13:06:58 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-10-11 00:19:33 +02:00
|
|
|
err = tmpl.Execute(w, data)
|
|
|
|
if err != nil {
|
|
|
|
http.Error(w, "Error executing template: "+err.Error(), http.StatusInternalServerError)
|
|
|
|
return
|
2023-09-07 13:06:58 +02:00
|
|
|
}
|
2023-10-11 00:19:33 +02:00
|
|
|
}
|
2023-09-07 13:06:58 +02:00
|
|
|
|
2023-10-11 00:19:33 +02:00
|
|
|
func reportsViewerHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
var formattedReportsData template.HTML = ""
|
2023-09-07 13:06:58 +02:00
|
|
|
|
2023-10-11 00:19:33 +02:00
|
|
|
events, _ := db.QueryEvents(context.Background(), nostr.Filter{
|
|
|
|
Kinds: []int{1984},
|
|
|
|
Limit: 52,
|
|
|
|
})
|
|
|
|
|
|
|
|
type Report struct {
|
|
|
|
ID string
|
|
|
|
ByUser string
|
|
|
|
AboutUser string
|
|
|
|
AboutEvent string
|
|
|
|
Type string
|
|
|
|
Content string
|
|
|
|
}
|
|
|
|
|
|
|
|
for ev := range events {
|
|
|
|
pTag := ev.Tags.GetFirst([]string{"p"})
|
|
|
|
|
|
|
|
eTag := ev.Tags.GetFirst([]string{"e"})
|
|
|
|
if pTag != nil {
|
2023-10-16 23:09:12 -03:00
|
|
|
typeReport := eTag.Relay()[6:]
|
2023-10-11 00:19:33 +02:00
|
|
|
if typeReport == "" {
|
|
|
|
typeReport = pTag.Relay()[6:]
|
|
|
|
}
|
|
|
|
report := Report{
|
|
|
|
ID: ev.ID,
|
|
|
|
ByUser: ev.PubKey,
|
|
|
|
AboutUser: pTag.Value(),
|
|
|
|
AboutEvent: eTag.Value(),
|
|
|
|
Type: typeReport,
|
|
|
|
Content: ev.Content,
|
|
|
|
}
|
|
|
|
// get AboutEvent content, note1 ect
|
|
|
|
formattedReportsData += template.HTML(fmt.Sprintf(`
|
|
|
|
<div>
|
|
|
|
<p><b>Report %v</b></p>
|
|
|
|
<p>By User: <a class="user" href="nostr:%v">%v</a></p>
|
|
|
|
<p>About User: <a class="user" href="nostr:%v">%v</a></p>`,
|
|
|
|
report.ID,
|
|
|
|
getUserInfo(context.Background(), report.ByUser).Npub,
|
|
|
|
getUserInfo(context.Background(), report.ByUser).Name,
|
|
|
|
getUserInfo(context.Background(), report.AboutUser).Npub,
|
|
|
|
getUserInfo(context.Background(), report.AboutUser).Name,
|
|
|
|
))
|
|
|
|
if report.AboutEvent != "" {
|
|
|
|
// fetch event data
|
|
|
|
aboutEvents, _ := db.QueryEvents(context.TODO(), nostr.Filter{
|
|
|
|
IDs: []string{report.AboutEvent},
|
|
|
|
})
|
|
|
|
for aboutEvent := range aboutEvents {
|
|
|
|
formattedReportsData += template.HTML(fmt.Sprintf(`
|
|
|
|
<p>
|
|
|
|
About Event: <ul>
|
|
|
|
<p>Kind: %v</p>
|
|
|
|
<p>Tags: %v</p>
|
|
|
|
<p>Content: %v</p>
|
|
|
|
</ul>
|
|
|
|
</p>`,
|
|
|
|
template.HTMLEscaper(aboutEvent.Kind),
|
|
|
|
template.HTMLEscaper(aboutEvent.Tags),
|
|
|
|
template.HTMLEscaper(aboutEvent.Content),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
formattedReportsData += template.HTML(fmt.Sprintf(`
|
|
|
|
<p>Type: %v</p>`,
|
|
|
|
report.Type,
|
|
|
|
))
|
|
|
|
if report.Content != "" {
|
|
|
|
formattedReportsData += template.HTML(fmt.Sprintf(`
|
|
|
|
<p>Content: %v</p>
|
|
|
|
<div>
|
|
|
|
<button data-actionarg='[["e", "%v"],["p", "%v"]]' class="removefromrelay">Ban Reported User and Remove Report</button>
|
|
|
|
<button data-actionarg='[["e", "%v"]]' class="removefromrelay">Remove This Report</button>
|
|
|
|
<button data-actionarg='[["p", "%v"]]' class="removefromrelay">Ban User who wrote report</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<hr />`,
|
|
|
|
template.HTMLEscaper(report.Content),
|
|
|
|
template.HTMLEscaper(report.ID),
|
|
|
|
template.HTMLEscaper(report.AboutUser),
|
|
|
|
template.HTMLEscaper(report.ID),
|
|
|
|
template.HTMLEscaper(report.ByUser),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
data := map[string]interface{}{
|
2023-10-16 23:09:12 -03:00
|
|
|
"Relayname": s.RelayName,
|
|
|
|
"Relaydescription": s.RelayDescription,
|
2023-10-11 00:19:33 +02:00
|
|
|
"Pagetitle": "Reports Viewer",
|
|
|
|
"Pagecontent": formattedReportsData,
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpl, err := template.ParseFS(dist, "ui/dist/index.html")
|
|
|
|
if err != nil {
|
|
|
|
http.Error(w, "Error parsing template: "+err.Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Execute the template with the provided data and write it to the response
|
|
|
|
err = tmpl.Execute(w, data)
|
|
|
|
if err != nil {
|
|
|
|
http.Error(w, "Error executing template: "+err.Error(), http.StatusInternalServerError)
|
2023-09-07 13:06:58 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2023-09-18 19:18:24 +00:00
|
|
|
|
2023-10-11 00:19:33 +02:00
|
|
|
func homePageHandler(w http.ResponseWriter, r *http.Request) {
|
2023-10-16 23:09:12 -03:00
|
|
|
relayOwnerInfo := getUserInfo(context.Background(), s.RelayPubkey)
|
2023-10-11 00:19:33 +02:00
|
|
|
|
|
|
|
data := map[string]interface{}{
|
2023-10-16 23:09:12 -03:00
|
|
|
"Relayname": s.RelayName,
|
|
|
|
"Relaydescription": s.RelayDescription,
|
2023-10-11 00:19:33 +02:00
|
|
|
"Pagetitle": "Info",
|
|
|
|
"Pagecontent": template.HTML(fmt.Sprintf(`
|
|
|
|
<div>Relay Name: %v</div>
|
|
|
|
<div>Relay Description: %v</div>
|
|
|
|
<div>Relay Owner: <a class="user" href="nostr:%v">%v</a></div>
|
|
|
|
<div>Relay Alternative Contact: %v</div>
|
|
|
|
<br />
|
|
|
|
<div><sub>This relay uses <a target="_blank" rel="noopener noreferrer" href="https://github.com/github-tijlxyz/khatru-invite">Khatru Invite</a>, which is build with <a target="_blank" rel="noopener noreferrer" href="https://github.com/fiatjaf/khatru">Khatru</a></sub></div>
|
2023-10-16 23:09:12 -03:00
|
|
|
`, s.RelayName, s.RelayDescription, relayOwnerInfo.Npub, relayOwnerInfo.Name, s.RelayContact)),
|
2023-10-11 00:19:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
tmpl, err := template.ParseFS(dist, "ui/dist/index.html")
|
|
|
|
if err != nil {
|
|
|
|
http.Error(w, "Error parsing template: "+err.Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
err = tmpl.Execute(w, data)
|
2023-09-18 19:18:24 +00:00
|
|
|
if err != nil {
|
2023-10-11 00:19:33 +02:00
|
|
|
http.Error(w, "Error executing template: "+err.Error(), http.StatusInternalServerError)
|
2023-09-18 19:18:24 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-11 00:19:33 +02:00
|
|
|
func redirectHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if strings.HasPrefix(r.URL.Path, "/assets") {
|
|
|
|
staticHandler("ui/dist", w, r)
|
|
|
|
} else if r.URL.Path == "/" {
|
|
|
|
homePageHandler(w, r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func staticHandler(prefix string, w http.ResponseWriter, r *http.Request) {
|
|
|
|
path := prefix + r.URL.Path
|
|
|
|
|
|
|
|
data, err := dist.ReadFile(path)
|
2023-09-18 19:18:24 +00:00
|
|
|
if err != nil {
|
2023-10-11 00:19:33 +02:00
|
|
|
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
contentType := http.DetectContentType(data)
|
|
|
|
if strings.HasSuffix(r.URL.Path, ".js") {
|
|
|
|
contentType = "application/javascript"
|
|
|
|
} else if strings.HasSuffix(r.URL.Path, ".css") {
|
|
|
|
contentType = "text/css"
|
|
|
|
}
|
|
|
|
|
|
|
|
w.Header().Set("Content-Type", contentType)
|
|
|
|
|
|
|
|
if _, err := w.Write(data); err != nil {
|
|
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
2023-09-18 19:18:24 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|