2023-10-18 11:58:09 -03:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
2023-11-02 20:59:50 -03:00
|
|
|
"github.com/nbd-wtf/go-nostr"
|
2023-10-18 11:58:09 -03:00
|
|
|
. "github.com/theplant/htmlgo"
|
|
|
|
)
|
|
|
|
|
2023-10-28 21:40:54 -03:00
|
|
|
const buttonClass = "rounded-md text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300"
|
2023-10-28 20:21:15 -03:00
|
|
|
|
2023-10-18 11:58:09 -03:00
|
|
|
func baseHTML(inside HTMLComponent) HTMLComponent {
|
2023-10-28 20:21:15 -03:00
|
|
|
navItemClass := "text-gray-600 hover:bg-gray-200 rounded-md px-3 py-2 font-medium"
|
2023-10-18 11:58:09 -03:00
|
|
|
|
|
|
|
return HTML(
|
|
|
|
Head(
|
|
|
|
Meta().Charset("utf-8"),
|
|
|
|
Meta().Name("viewport").Content("width=device-width, initial-scale=1"),
|
|
|
|
Title(s.RelayName),
|
|
|
|
Script("").Src("https://cdn.tailwindcss.com"),
|
2023-10-28 20:21:15 -03:00
|
|
|
Script("").Src("https://unpkg.com/htmx.org@1.9.6"),
|
|
|
|
Script("").Src("https://unpkg.com/hyperscript.org@0.9.12"),
|
2023-10-18 11:58:09 -03:00
|
|
|
),
|
|
|
|
Body(
|
|
|
|
Div(
|
|
|
|
H1(s.RelayName).Class("font-bold text-2xl"),
|
|
|
|
P().Text(s.RelayDescription).Class("text-lg"),
|
|
|
|
).Class("mx-auto my-6 text-center"),
|
|
|
|
Nav(
|
2024-02-01 12:51:05 -03:00
|
|
|
A().Text("invite tree").Href("/").Class(navItemClass).Attr("hx-boost", "true", "hx-target", "main", "hx-select", "main"),
|
2023-10-28 20:21:15 -03:00
|
|
|
A().Text("reports").Href("/reports").Class(navItemClass).Attr("hx-boost", "true", "hx-target", "main", "hx-select", "main"),
|
2023-11-02 16:08:53 -03:00
|
|
|
A().Text("").Href("#").Class(navItemClass).
|
|
|
|
Attr("_", `
|
2023-11-02 16:15:59 -03:00
|
|
|
on click if my innerText is equal to "login" get window.nostr.signEvent({created_at: Math.round(Date.now()/1000), kind: 27235, tags: [['domain', "`+s.Domain+`"]], content: ''}) then get JSON.stringify(it) then set cookies['nip98'] to it otherwise call cookies.clear('nip98') end then call location.reload()
|
2023-11-02 16:08:53 -03:00
|
|
|
|
|
|
|
on load get cookies['nip98'] then if it is undefined set my innerText to "login" otherwise set my innerText to "logout"`),
|
2023-10-18 11:58:09 -03:00
|
|
|
).Class("flex flex-1 items-center justify-center"),
|
2023-10-28 20:21:15 -03:00
|
|
|
Main(inside).Class("m-4"),
|
2024-02-01 13:11:10 -03:00
|
|
|
P(
|
|
|
|
Text("powered by "),
|
|
|
|
A().Href("https://github.com/github-tijlxyz/khatru-invite").Text("khatru-invite").Class("hover:underline cursor-pointer text-blue-500"),
|
|
|
|
).Class("text-end my-4 text-sm"),
|
|
|
|
).Class("my-6 mx-auto max-w-min min-w-96"),
|
2023-10-18 11:58:09 -03:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-10-28 21:40:54 -03:00
|
|
|
type InviteTreePageParams struct {
|
2023-11-02 16:08:53 -03:00
|
|
|
loggedUser string
|
2023-10-28 21:40:54 -03:00
|
|
|
}
|
2023-10-18 11:58:09 -03:00
|
|
|
|
|
|
|
func inviteTreePageHTML(ctx context.Context, params InviteTreePageParams) HTMLComponent {
|
2023-11-02 16:08:53 -03:00
|
|
|
inviteForm := Div()
|
|
|
|
|
2024-02-05 11:32:41 -03:00
|
|
|
if params.loggedUser != "" && (params.loggedUser == s.RelayPubkey || !hasInvitedAtLeast(params.loggedUser, s.MaxInvitesPerPerson)) {
|
2023-11-02 16:08:53 -03:00
|
|
|
inviteForm = Form(
|
|
|
|
Input("pubkey").Type("text").Placeholder("npub1...").Class("w-96 rounded-md border-0 p-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600"),
|
2024-02-01 13:11:10 -03:00
|
|
|
Button("invite").Class(buttonClass+" ml-2 p-2 bg-white hover:bg-gray-50"),
|
2023-11-02 16:08:53 -03:00
|
|
|
).Attr(
|
|
|
|
"hx-post", "/add-to-whitelist",
|
|
|
|
"hx-trigger", "submit",
|
|
|
|
"hx-target", "#tree",
|
|
|
|
"_", "on htmx:afterRequest(elt, successful) if successful and elt is I call I.reset()",
|
2024-02-01 13:11:10 -03:00
|
|
|
).Class("flex")
|
2023-11-02 16:08:53 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
return Div(
|
|
|
|
inviteForm,
|
2023-10-28 20:21:15 -03:00
|
|
|
Div(
|
2023-11-02 16:08:53 -03:00
|
|
|
inviteTreeComponent(ctx, "", params.loggedUser),
|
2023-10-28 20:21:15 -03:00
|
|
|
).Id("tree").Class("mt-3"),
|
2023-10-29 13:45:46 -03:00
|
|
|
)
|
2023-10-18 11:58:09 -03:00
|
|
|
}
|
2023-11-02 20:59:50 -03:00
|
|
|
|
|
|
|
type ReportsPageParams struct {
|
|
|
|
reports chan *nostr.Event
|
|
|
|
loggedUser string
|
|
|
|
}
|
|
|
|
|
|
|
|
func reportsPageHTML(ctx context.Context, params ReportsPageParams) HTMLComponent {
|
|
|
|
items := make([]HTMLComponent, 0, 52)
|
|
|
|
for report := range params.reports {
|
|
|
|
var primaryType string
|
|
|
|
var secondaryType string
|
|
|
|
var relatedContent HTMLComponent
|
|
|
|
|
|
|
|
if e := report.Tags.GetFirst([]string{"e", ""}); e != nil {
|
|
|
|
// event report
|
|
|
|
res, _ := sys.StoreRelay().QuerySync(ctx, nostr.Filter{IDs: []string{(*e)[1]}})
|
|
|
|
if len(res) == 0 {
|
|
|
|
sys.Store.DeleteEvent(ctx, report)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(*e) >= 3 {
|
|
|
|
primaryType = (*e)[2]
|
|
|
|
}
|
|
|
|
|
|
|
|
relatedEvent := res[0]
|
|
|
|
relatedContent = Div(
|
|
|
|
Text("event reported: "),
|
|
|
|
Div().Text(relatedEvent.String()).Class("text-mono"),
|
|
|
|
)
|
|
|
|
} else if p := report.Tags.GetFirst([]string{"p", ""}); p != nil {
|
|
|
|
// pubkey report
|
|
|
|
if !isPublicKeyInWhitelist((*p)[1]) {
|
|
|
|
sys.Store.DeleteEvent(ctx, report)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(*p) >= 3 {
|
|
|
|
primaryType = (*p)[2]
|
|
|
|
}
|
|
|
|
|
2023-11-07 14:33:01 -03:00
|
|
|
relatedProfile := sys.FetchOrStoreProfileMetadata(ctx, (*p)[1])
|
2023-11-02 20:59:50 -03:00
|
|
|
relatedContent = Div(
|
|
|
|
Text("profile reported: "),
|
|
|
|
userNameComponent(relatedProfile),
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
reporter := sys.FetchProfileMetadata(ctx, report.PubKey)
|
|
|
|
report := Div(
|
|
|
|
Div(Span(primaryType).Class("font-semibold"), Text(" report")).Class("font-lg"),
|
|
|
|
Div().Text(secondaryType),
|
|
|
|
Div(Text("by "), userNameComponent(reporter)),
|
|
|
|
Div().Text(report.Content).Class("p-3"),
|
|
|
|
relatedContent,
|
|
|
|
)
|
|
|
|
|
|
|
|
items = append(items, report)
|
|
|
|
}
|
|
|
|
return baseHTML(
|
|
|
|
Div(
|
|
|
|
H1("reports received").Class("text-xl p-4"),
|
|
|
|
Div(items...),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
}
|