diff --git a/hostr/cmd/consts/consts.go b/hostr/cmd/consts/consts.go index da69610..31e757a 100644 --- a/hostr/cmd/consts/consts.go +++ b/hostr/cmd/consts/consts.go @@ -5,7 +5,9 @@ const ( KindWebhostHTML = 5392 KindWebhostCSS = 5393 KindWebhostJS = 5394 + KindTextFile = 1064 KindWebhostReplaceableHTML = 35392 KindWebhostReplaceableCSS = 35393 KindWebhostReplaceableJS = 35394 + KindReplaceableTextFile = 30064 ) diff --git a/hostr/cmd/deploy/media.go b/hostr/cmd/deploy/media.go index e412a30..5fad57c 100644 --- a/hostr/cmd/deploy/media.go +++ b/hostr/cmd/deploy/media.go @@ -49,7 +49,7 @@ type MediaResult struct { // [元パス]:[URL]の形で記録する var uploadedMediaFilePathToURL = map[string]string{} -func uploadMediaFiles(filePaths []string, requests []*http.Request) { +func uploadMediaFiles(basePath string, filePaths []string, requests []*http.Request) { fmt.Println("Uploading media files...") client := &http.Client{} @@ -72,7 +72,7 @@ func uploadMediaFiles(filePaths []string, requests []*http.Request) { wg.Add(1) filePath := filePaths[i] - fmt.Printf("\nAdded upload request %s", filePath) + fmt.Println("Added upload request", filePath) go func(filePath string, req *http.Request) { defer wg.Done() @@ -107,7 +107,7 @@ func uploadMediaFiles(filePaths []string, requests []*http.Request) { mutex.Lock() // ロックして排他制御 uploadedMediaFilePathToURLCount++ // カウントアップ - uploadedMediaFilePathToURL[filePath] = result.Url + uploadedMediaFilePathToURL[strings.Replace(filePath, basePath, "", 1)] = result.Url mutex.Unlock() // ロック解除 }(filePath, req) } @@ -206,7 +206,7 @@ func uploadAllValidStaticMediaFiles(priKey, pubKey, basePath string) error { requests = append(requests, request) } - uploadMediaFiles(filesPaths, requests) + uploadMediaFiles(basePath, filesPaths, requests) return nil } diff --git a/hostr/cmd/deploy/textFile.go b/hostr/cmd/deploy/textFile.go index 0202b8d..6371f2e 100644 --- a/hostr/cmd/deploy/textFile.go +++ b/hostr/cmd/deploy/textFile.go @@ -4,6 +4,7 @@ import ( "encoding/base64" "os" "path/filepath" + "strings" "github.com/nbd-wtf/go-nostr" "github.com/studiokaiji/nostr-webhost/hostr/cmd/tools" @@ -59,7 +60,11 @@ func generateEventsAndAddQueueAllValidStaticTextFiles(priKey, pubKey, indexHtmlI tags := nostr.Tags{} // 置き換え可能なイベントの場合 if replaceable { - fileIdentifier := getReplaceableIdentifier(indexHtmlIdentifier, filePath) + // filePathからbasePathを取り除く + pathForIdentifier := strings.Replace(filePath, basePath, "", 1) + // 識別子を取得 + fileIdentifier := getReplaceableIdentifier(indexHtmlIdentifier, pathForIdentifier) + tags = tags.AppendUnique(nostr.Tag{"d", fileIdentifier}) } diff --git a/hostr/cmd/server/server.go b/hostr/cmd/server/server.go index 61043d6..17be517 100644 --- a/hostr/cmd/server/server.go +++ b/hostr/cmd/server/server.go @@ -64,8 +64,13 @@ func Start(port string, mode string) { } filter := nostr.Filter{ - Kinds: []int{consts.KindWebhostHTML, consts.KindWebhostCSS, consts.KindWebhostJS, consts.KindWebhostPicture}, - IDs: ids, + Kinds: []int{ + consts.KindWebhostHTML, + consts.KindWebhostCSS, + consts.KindWebhostJS, + consts.KindTextFile, + }, + IDs: ids, } if mode == "secure" { filter.Authors = []string{subdomainPubKey} @@ -74,11 +79,16 @@ func Start(port string, mode string) { // Poolからデータを取得する ev := pool.QuerySingle(ctx, allRelays, filter) if ev != nil { - contentType, err := tools.GetContentType(ev.Kind) + contentType, isTextFile, err := tools.GetContentType(ev) if err != nil { ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound)) + } + + content, err := tools.GetResponseContent(ev.Content, isTextFile) + if err != nil { + ctx.String(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) } else { - ctx.Data(http.StatusOK, contentType, []byte(ev.Content)) + ctx.Data(http.StatusOK, contentType, content) } } else { ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound)) @@ -112,16 +122,24 @@ func Start(port string, mode string) { consts.KindWebhostReplaceableHTML, consts.KindWebhostReplaceableCSS, consts.KindWebhostReplaceableJS, + consts.KindReplaceableTextFile, }, Authors: authors, Tags: tags, }) if ev != nil { - contentType, err := tools.GetContentType(ev.Kind) + contentType, isTextFile, err := tools.GetContentType(ev) if err != nil { ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound)) } - ctx.Data(http.StatusOK, contentType, []byte(ev.Content)) + + // contentの変換 + content, err := tools.GetResponseContent(ev.Content, isTextFile) + if err != nil { + ctx.String(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) + } else { + ctx.Data(http.StatusOK, contentType, content) + } } else { ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound)) } @@ -158,16 +176,24 @@ func Start(port string, mode string) { consts.KindWebhostReplaceableHTML, consts.KindWebhostReplaceableCSS, consts.KindWebhostReplaceableJS, + consts.KindReplaceableTextFile, }, Authors: authors, Tags: tags, }) + if ev != nil { - contentType, err := tools.GetContentType(ev.Kind) + contentType, isTextFile, err := tools.GetContentType(ev) if err != nil { ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound)) } - ctx.Data(http.StatusOK, contentType, []byte(ev.Content)) + + content, err := tools.GetResponseContent(ev.Content, isTextFile) + if err != nil { + ctx.String(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) + } else { + ctx.Data(http.StatusOK, contentType, content) + } } else { ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound)) } diff --git a/hostr/cmd/tools/getContentType.go b/hostr/cmd/tools/getContentType.go index 4d25943..379ddc0 100644 --- a/hostr/cmd/tools/getContentType.go +++ b/hostr/cmd/tools/getContentType.go @@ -3,17 +3,32 @@ package tools import ( "fmt" + "github.com/nbd-wtf/go-nostr" "github.com/studiokaiji/nostr-webhost/hostr/cmd/consts" ) -func GetContentType(kind int) (string, error) { +// Content-Typeをイベントから取得する。NIP-95の場合は第二引数がtrueになる。 +func GetContentType(event *nostr.Event) (string, bool, error) { + kind := event.Kind + + if kind == consts.KindTextFile || kind == consts.KindReplaceableTextFile { + contentTypeTag := event.Tags.GetFirst([]string{"type"}) + contentType := contentTypeTag.Value() + + if len(contentType) < 1 { + return "", true, fmt.Errorf("Content-Type not specified") + } + + return contentType, true, nil + } + if kind == consts.KindWebhostHTML || kind == consts.KindWebhostReplaceableHTML { - return "text/html; charset=utf-8", nil + return "text/html; charset=utf-8", false, nil } else if kind == consts.KindWebhostCSS || kind == consts.KindWebhostReplaceableCSS { - return "text/css; charset=utf-8", nil + return "text/css; charset=utf-8", false, nil } else if kind == consts.KindWebhostJS || kind == consts.KindWebhostReplaceableJS { - return "text/javascript; charset=utf-8", nil + return "text/javascript; charset=utf-8", false, nil } else { - return "", fmt.Errorf("Invalid Kind") + return "", false, fmt.Errorf("Invalid Kind") } } diff --git a/hostr/cmd/tools/getResponseContent.go b/hostr/cmd/tools/getResponseContent.go new file mode 100644 index 0000000..d00e3f2 --- /dev/null +++ b/hostr/cmd/tools/getResponseContent.go @@ -0,0 +1,14 @@ +package tools + +import ( + "encoding/base64" +) + +func GetResponseContent(eventContent string, isTextFile bool) ([]byte, error) { + if isTextFile { + // NIP-95ファイル(Text File)の場合はbase64エンコードされているのでdecodeする + return base64.StdEncoding.DecodeString(eventContent) + } else { + return []byte(eventContent), nil + } +} diff --git a/nostr-rs-relay/config.toml b/nostr-rs-relay/config.toml index 9f992a5..6eab804 100644 --- a/nostr-rs-relay/config.toml +++ b/nostr-rs-relay/config.toml @@ -146,7 +146,18 @@ max_ws_frame_bytes = 1024000 #] # Event kind allowlist. Events other than these kinds will be discarded. -event_kind_allowlist = [1964, 1965, 5392, 5393, 5394, 35392, 35393, 35394] +event_kind_allowlist = [ + 1964, + 1965, + 5392, + 5393, + 5394, + 30064, + 30065, + 35392, + 35393, + 35394, +] [authorization] # Pubkey addresses in this array are whitelisted for event publishing.