mirror of
https://github.com/studiokaiji/nostr-webhost.git
synced 2025-12-17 06:44:28 +01:00
152 lines
3.9 KiB
Go
152 lines
3.9 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/nbd-wtf/go-nostr"
|
|
"github.com/nbd-wtf/go-nostr/nip19"
|
|
"github.com/studiokaiji/nostr-webhost/hostr/cmd/consts"
|
|
"github.com/studiokaiji/nostr-webhost/hostr/cmd/relays"
|
|
)
|
|
|
|
func Start(port string) {
|
|
ctx := context.Background()
|
|
|
|
allRelays, err := relays.GetAllRelays()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
pool := nostr.NewSimplePool(ctx)
|
|
|
|
r := gin.Default()
|
|
|
|
r.GET("/e/:hex_or_nevent", func(ctx *gin.Context) {
|
|
hexOrNevent := ctx.Param("hex_or_nevent")
|
|
|
|
ids := []string{}
|
|
|
|
// neventからIDを取得
|
|
if hexOrNevent[0:6] == "nevent" {
|
|
_, res, err := nip19.Decode(hexOrNevent)
|
|
if err != nil {
|
|
ctx.String(http.StatusBadRequest, "Invalid nevent")
|
|
return
|
|
}
|
|
|
|
data, ok := res.(nostr.EventPointer)
|
|
if !ok {
|
|
ctx.String(http.StatusBadRequest, "Failed to decode nevent")
|
|
return
|
|
}
|
|
|
|
ids = append(ids, data.ID)
|
|
allRelays = append(allRelays, data.Relays...)
|
|
}
|
|
|
|
// Poolからデータを取得する
|
|
ev := pool.QuerySingle(ctx, allRelays, nostr.Filter{
|
|
Kinds: []int{consts.KindWebhostHTML, consts.KindWebhostCSS, consts.KindWebhostJS, consts.KindWebhostPicture},
|
|
IDs: ids,
|
|
})
|
|
if ev != nil {
|
|
switch ev.Kind {
|
|
case consts.KindWebhostHTML:
|
|
ctx.Data(http.StatusOK, "text/html; charset=utf-8", []byte(ev.Content))
|
|
case consts.KindWebhostCSS:
|
|
ctx.Data(http.StatusOK, "text/css; charset=utf-8", []byte(ev.Content))
|
|
case consts.KindWebhostJS:
|
|
ctx.Data(http.StatusOK, "text/javascript; charset=utf-8", []byte(ev.Content))
|
|
case consts.KindWebhostPicture:
|
|
{
|
|
eTag := ev.Tags.GetFirst([]string{"e"})
|
|
mTag := ev.Tags.GetFirst([]string{"m"})
|
|
|
|
if eTag == nil || mTag == nil {
|
|
ctx.String(http.StatusBadRequest, http.StatusText((http.StatusBadRequest)))
|
|
return
|
|
}
|
|
|
|
evData := pool.QuerySingle(ctx, allRelays, nostr.Filter{
|
|
IDs: []string{eTag.Value()},
|
|
})
|
|
|
|
if evData == nil {
|
|
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
|
|
return
|
|
}
|
|
|
|
data, err := base64.StdEncoding.DecodeString(evData.Content)
|
|
if err != nil {
|
|
ctx.String(http.StatusBadRequest, http.StatusText((http.StatusBadRequest)))
|
|
return
|
|
}
|
|
|
|
ctx.Data(http.StatusOK, mTag.Value(), data)
|
|
}
|
|
default:
|
|
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
|
|
}
|
|
} else {
|
|
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
|
|
}
|
|
|
|
return
|
|
})
|
|
|
|
// Replaceable Event (NIP-33)
|
|
r.GET("/p/:pubKey/d/*dTag", func(ctx *gin.Context) {
|
|
// pubKeyを取得しFilterに追加
|
|
pubKey := ctx.Param("pubKey")
|
|
// npubから始まる場合はデコードする
|
|
if pubKey[0:4] == "npub" {
|
|
_, v, err := nip19.Decode(pubKey)
|
|
if err != nil {
|
|
ctx.String(http.StatusBadRequest, "Invalid npub")
|
|
return
|
|
}
|
|
pubKey = v.(string)
|
|
}
|
|
authors := []string{pubKey}
|
|
|
|
// dTagを取得しFilterに追加
|
|
// dTagの最初は`/`ではじまるのでそれをslice
|
|
dTag := ctx.Param("dTag")[1:]
|
|
|
|
tags := nostr.TagMap{}
|
|
tags["d"] = []string{dTag}
|
|
|
|
// Poolからデータを取得する
|
|
ev := pool.QuerySingle(ctx, allRelays, nostr.Filter{
|
|
Kinds: []int{
|
|
consts.KindWebhostReplaceableHTML,
|
|
consts.KindWebhostReplaceableCSS,
|
|
consts.KindWebhostReplaceableJS,
|
|
},
|
|
Authors: authors,
|
|
Tags: tags,
|
|
})
|
|
if ev != nil {
|
|
switch ev.Kind {
|
|
case consts.KindWebhostReplaceableHTML:
|
|
ctx.Data(http.StatusOK, "text/html; charset=utf-8", []byte(ev.Content))
|
|
case consts.KindWebhostReplaceableCSS:
|
|
ctx.Data(http.StatusOK, "text/css; charset=utf-8", []byte(ev.Content))
|
|
case consts.KindWebhostReplaceableJS:
|
|
ctx.Data(http.StatusOK, "text/javascript; charset=utf-8", []byte(ev.Content))
|
|
default:
|
|
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
|
|
}
|
|
} else {
|
|
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
|
|
}
|
|
|
|
return
|
|
})
|
|
|
|
r.Run(":" + port)
|
|
}
|