mirror of
https://github.com/studiokaiji/nostr-webhost.git
synced 2025-12-17 06:44:28 +01:00
first commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/nostr-rs-relay/data
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Haruki Nazawa
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
5
cli/.gitignore
vendored
Normal file
5
cli/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
main
|
||||
dist/
|
||||
|
||||
.nostr_account_secret
|
||||
.nostr_relays
|
||||
45
cli/.goreleaser.yaml
Normal file
45
cli/.goreleaser.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
# This is an example .goreleaser.yml file with some sensible defaults.
|
||||
# Make sure to check the documentation at https://goreleaser.com
|
||||
before:
|
||||
hooks:
|
||||
# You may remove this if you don't use go modules.
|
||||
- go mod tidy
|
||||
# you may remove this if you don't need go generate
|
||||
- go generate ./...
|
||||
builds:
|
||||
- env:
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- linux
|
||||
- windows
|
||||
- darwin
|
||||
|
||||
archives:
|
||||
- format: tar.gz
|
||||
# this name template makes the OS and Arch compatible with the results of uname.
|
||||
name_template: >-
|
||||
{{ .ProjectName }}_
|
||||
{{- title .Os }}_
|
||||
{{- if eq .Arch "amd64" }}x86_64
|
||||
{{- else if eq .Arch "386" }}i386
|
||||
{{- else }}{{ .Arch }}{{ end }}
|
||||
{{- if .Arm }}v{{ .Arm }}{{ end }}
|
||||
# use zip for windows archives
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
checksum:
|
||||
name_template: 'checksums.txt'
|
||||
snapshot:
|
||||
name_template: "{{ incpatch .Version }}-next"
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
exclude:
|
||||
- '^docs:'
|
||||
- '^test:'
|
||||
|
||||
# The lines beneath this are called `modelines`. See `:help modeline`
|
||||
# Feel free to remove those if you don't want/use them.
|
||||
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
|
||||
# vim: set ts=2 sw=2 tw=0 fo=cnqoj
|
||||
8
cli/cmd/consts/consts.go
Normal file
8
cli/cmd/consts/consts.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package consts
|
||||
|
||||
const (
|
||||
KindWebhostPicture = 1965
|
||||
KindWebhostHTML = 5392
|
||||
KindWebhostCSS = 5393
|
||||
KindWebhostJS = 5394
|
||||
)
|
||||
229
cli/cmd/deploy/deploy.go
Normal file
229
cli/cmd/deploy/deploy.go
Normal file
@@ -0,0 +1,229 @@
|
||||
package deploy
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/studiokaiji/nostr-webhost/cmd/consts"
|
||||
"github.com/studiokaiji/nostr-webhost/cmd/keystore"
|
||||
"github.com/studiokaiji/nostr-webhost/cmd/relays"
|
||||
"github.com/studiokaiji/nostr-webhost/cmd/tools"
|
||||
"golang.org/x/net/html"
|
||||
)
|
||||
|
||||
func pathToKind(path string) (int, error) {
|
||||
splittedPath := strings.Split(path, ".")
|
||||
ex := splittedPath[len(splittedPath)-1]
|
||||
switch ex {
|
||||
case "html":
|
||||
return consts.KindWebhostHTML, nil
|
||||
case "css":
|
||||
return consts.KindWebhostCSS, nil
|
||||
case "js":
|
||||
return consts.KindWebhostJS, nil
|
||||
default:
|
||||
return 0, nil
|
||||
}
|
||||
}
|
||||
|
||||
var nostrEventsQueue []*nostr.Event
|
||||
|
||||
func addNostrEventQueue(event *nostr.Event) {
|
||||
nostrEventsQueue = append(nostrEventsQueue, event)
|
||||
}
|
||||
|
||||
func publishEventsFromQueue() (string, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
fmt.Println("Publishing...")
|
||||
|
||||
// リレーを取得
|
||||
allRelays, err := relays.GetAllRelays()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 各リレーに接続
|
||||
var relays []*nostr.Relay
|
||||
|
||||
for _, url := range allRelays {
|
||||
relay, err := nostr.RelayConnect(ctx, url)
|
||||
if err != nil {
|
||||
fmt.Println("❌ Failed to connect to:", url)
|
||||
continue
|
||||
}
|
||||
relays = append(relays, relay)
|
||||
}
|
||||
|
||||
// Publishの進捗状況を表示
|
||||
allEventsCount := len(nostrEventsQueue)
|
||||
uploadedFilesCount := 0
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
go func() {
|
||||
wg.Add(1)
|
||||
tools.DisplayProgressBar(&uploadedFilesCount, &allEventsCount)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
var mutex sync.Mutex
|
||||
|
||||
// リレーへpublish
|
||||
for _, ev := range nostrEventsQueue {
|
||||
wg.Add(1)
|
||||
go func(event *nostr.Event) {
|
||||
for _, relay := range relays {
|
||||
_, err := relay.Publish(ctx, *event)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
mutex.Lock() // ロックして排他制御
|
||||
uploadedFilesCount++ // カウントアップ
|
||||
mutex.Unlock() // ロック解除
|
||||
wg.Done() // ゴルーチンの終了を通知
|
||||
}(ev)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
if uploadedFilesCount < allEventsCount {
|
||||
fmt.Println("Failed to deploy", allEventsCount-uploadedFilesCount, "files.")
|
||||
}
|
||||
|
||||
indexEventId := nostrEventsQueue[len(nostrEventsQueue)-1].ID
|
||||
|
||||
return indexEventId, err
|
||||
}
|
||||
|
||||
func isExternalURL(urlStr string) bool {
|
||||
_, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isValidFileType(str string) bool {
|
||||
return strings.HasSuffix(str, ".html") || strings.HasSuffix(str, ".css") || strings.HasSuffix(str, ".js")
|
||||
}
|
||||
|
||||
func Deploy(basePath string) (string, error) {
|
||||
// 引数からデプロイしたいサイトのパスを受け取る。
|
||||
filePath := filepath.Join(basePath, "index.html")
|
||||
|
||||
// パスのディレクトリ内のファイルからindex.htmlファイルを取得
|
||||
content, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
fmt.Println("❌ Failed to read index.html:", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// HTMLの解析
|
||||
doc, err := html.Parse(bytes.NewReader(content))
|
||||
if err != nil {
|
||||
fmt.Println("❌ Failed to parse index.html:", err)
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Eventの取得に必要になるキーペアを取得
|
||||
priKey, err := keystore.GetSecret()
|
||||
if err != nil {
|
||||
fmt.Println("❌ Failed to get private key:", err)
|
||||
return "", err
|
||||
}
|
||||
pubKey, err := nostr.GetPublicKey(priKey)
|
||||
if err != nil {
|
||||
fmt.Println("❌ Failed to get public key:", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// index.htmlファイル内に記述されている他Assetのパスから実際のデータを取得。
|
||||
// 取得してきたデータをeventにしてIDを取得。
|
||||
// リンクの解析と変換
|
||||
convertLinks(priKey, pubKey, basePath, doc)
|
||||
|
||||
// 更新されたHTML
|
||||
var buf bytes.Buffer
|
||||
html.Render(&buf, doc)
|
||||
|
||||
strHtml := buf.String()
|
||||
|
||||
// Eventを生成しキューに追加
|
||||
event, err := getEvent(priKey, pubKey, strHtml, consts.KindWebhostHTML)
|
||||
if err != nil {
|
||||
fmt.Println("❌ Failed to get public key:", err)
|
||||
return "", err
|
||||
}
|
||||
addNostrEventQueue(event)
|
||||
fmt.Println("Added", filePath, "event to publish queue")
|
||||
|
||||
return publishEventsFromQueue()
|
||||
}
|
||||
|
||||
func convertLinks(priKey, pubKey, basePath string, n *html.Node) {
|
||||
// <link> と <script> タグを対象とする
|
||||
if n.Type == html.ElementNode && (n.Data == "link" || n.Data == "script") {
|
||||
for i, a := range n.Attr {
|
||||
// href,srcのうち、外部URLでないものかつ. html, .css, .js のみ変換する
|
||||
if (a.Key == "href" || a.Key == "src") && !isExternalURL(a.Val) && isValidFileType(a.Val) {
|
||||
filePath := filepath.Join(basePath, a.Val)
|
||||
// kindを取得
|
||||
kind, err := pathToKind(filePath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// contentを取得
|
||||
bytesContent, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
fmt.Println("❌ Failed to read", filePath, ":", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Eventを生成し、キューに追加
|
||||
event, err := getEvent(priKey, pubKey, string(bytesContent), kind)
|
||||
if err != nil {
|
||||
fmt.Println("❌ Failed to get event for", filePath, ":", err)
|
||||
break
|
||||
}
|
||||
|
||||
addNostrEventQueue(event)
|
||||
fmt.Println("Added", filePath, "event to publish queue")
|
||||
|
||||
// 元のパスをEvent[.]IDに変更
|
||||
n.Attr[i].Val = event.ID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 子ノードに対して再帰的に処理
|
||||
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||
convertLinks(priKey, pubKey, basePath, c)
|
||||
}
|
||||
}
|
||||
|
||||
func getEvent(priKey, pubKey, content string, kind int) (*nostr.Event, error) {
|
||||
ev := nostr.Event{
|
||||
PubKey: pubKey,
|
||||
CreatedAt: nostr.Now(),
|
||||
Kind: kind,
|
||||
Content: content,
|
||||
}
|
||||
|
||||
err := ev.Sign(priKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ev, err
|
||||
}
|
||||
52
cli/cmd/keystore/keystore.go
Normal file
52
cli/cmd/keystore/keystore.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package keystore
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
)
|
||||
|
||||
const PATH = ".nostr_account_secret"
|
||||
|
||||
func SetSecret(key string) error {
|
||||
// nsecから始まる場合はデコードする
|
||||
if key[0:4] == "nsec" {
|
||||
_, v, err := nip19.Decode(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
key = v.(string)
|
||||
}
|
||||
// キーをファイルに書き込み
|
||||
return os.WriteFile(PATH, []byte(key), 0644)
|
||||
}
|
||||
|
||||
func ShowPublic() (string, string, error) {
|
||||
hex, err := GetPublic()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
npub, err := nip19.EncodePublicKey(hex)
|
||||
fmt.Printf("npub: %s\nhex: %s\n", npub, hex)
|
||||
return hex, npub, nil
|
||||
}
|
||||
|
||||
func GetPublic() (string, error) {
|
||||
secret, err := GetSecret()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
hex, err := nostr.GetPublicKey(secret)
|
||||
return hex, err
|
||||
}
|
||||
|
||||
func GetSecret() (string, error) {
|
||||
secretBytes, err := os.ReadFile(PATH)
|
||||
if err != nil {
|
||||
return "", errors.New("Could not read secret")
|
||||
}
|
||||
return string(secretBytes), nil
|
||||
}
|
||||
56
cli/cmd/relays/relays.go
Normal file
56
cli/cmd/relays/relays.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package relays
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const PATH = ".nostr_relays"
|
||||
|
||||
func AddRelay(relayURL string) error {
|
||||
file, err := os.OpenFile(PATH, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
_, err = file.WriteString(relayURL + "\n")
|
||||
return err
|
||||
}
|
||||
|
||||
func RemoveRelay(targetURL string) error {
|
||||
content, err := os.ReadFile(PATH)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lines := strings.Split(string(content), "\n")
|
||||
var newLines []string
|
||||
|
||||
for _, line := range lines {
|
||||
if line != targetURL {
|
||||
newLines = append(newLines, line)
|
||||
}
|
||||
}
|
||||
|
||||
newContent := strings.Join(newLines, "\n")
|
||||
err = os.WriteFile(PATH, []byte(newContent), 0644)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func GetAllRelays() ([]string, error) {
|
||||
content, err := os.ReadFile(PATH)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := strings.Split(string(content), "\n")
|
||||
lines := []string{}
|
||||
for _, line := range data {
|
||||
if len(line) > 1 {
|
||||
lines = append(lines, line)
|
||||
}
|
||||
}
|
||||
return lines, nil
|
||||
}
|
||||
80
cli/cmd/server/server.go
Normal file
80
cli/cmd/server/server.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/studiokaiji/nostr-webhost/cmd/consts"
|
||||
"github.com/studiokaiji/nostr-webhost/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/:idHex", func(ctx *gin.Context) {
|
||||
// IDを取得
|
||||
id := ctx.Param("idHex")
|
||||
|
||||
// Poolからデータを取得する
|
||||
ev := pool.QuerySingle(ctx, allRelays, nostr.Filter{
|
||||
Kinds: []int{consts.KindWebhostHTML, consts.KindWebhostCSS, consts.KindWebhostJS, consts.KindWebhostPicture},
|
||||
IDs: []string{id},
|
||||
})
|
||||
if ev != nil {
|
||||
switch ev.Kind {
|
||||
case consts.KindWebhostHTML:
|
||||
ctx.Data(http.StatusOK, "text/html", []byte(ev.Content))
|
||||
case consts.KindWebhostCSS:
|
||||
ctx.Data(http.StatusOK, "text/css", []byte(ev.Content))
|
||||
case consts.KindWebhostJS:
|
||||
ctx.Data(http.StatusOK, "text/javascript", []byte(ev.Content))
|
||||
case consts.KindWebhostPicture:
|
||||
{
|
||||
eTag := ev.Tags.GetFirst([]string{"e"})
|
||||
mTag := ev.Tags.GetFirst([]string{"e"})
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return
|
||||
})
|
||||
|
||||
r.Run(":" + port)
|
||||
}
|
||||
47
cli/cmd/tools/displayPercent.go
Normal file
47
cli/cmd/tools/displayPercent.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
func DisplayProgressBar(current, total *int) {
|
||||
// ターミナルのサイズを取得
|
||||
terminalWidth, _, err := term.GetSize(0)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
width := terminalWidth - 12
|
||||
|
||||
// ターミナルの幅を最大100として調整
|
||||
if width > 100 {
|
||||
width = 100
|
||||
}
|
||||
|
||||
for true {
|
||||
progress := int(float64(*current) / float64(*total) * float64(width))
|
||||
|
||||
// バーの描画
|
||||
bar := ""
|
||||
for j := 0; j < width; j++ {
|
||||
if j < progress {
|
||||
bar += "="
|
||||
} else {
|
||||
bar += " "
|
||||
}
|
||||
}
|
||||
|
||||
// カーソルを行の先頭に戻して上書き
|
||||
fmt.Printf("\r[%s] %d/%d", bar, *current, *total)
|
||||
|
||||
if *current >= *total {
|
||||
fmt.Println("")
|
||||
break
|
||||
}
|
||||
|
||||
time.Sleep(20 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
24
cli/cute-ostrich.txt
Normal file
24
cli/cute-ostrich.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
`MMMMMMMMMMMMMMMMMMMMMMN,
|
||||
MMMMMMMMMMMMMH"""""HMMMMMMMMMMk.
|
||||
MMMMM"` ` ` ?WMMMMMMMb
|
||||
MMMM ` MMMMMMM[
|
||||
MMM\ (MMMMm, MMMM#
|
||||
MMM] ` (MMMMMM# dMMMM_
|
||||
MMMb ` ,MMMMMMF TMMM)
|
||||
MMMN. .TWH9^ _?
|
||||
MMMM[ ` ` JMM]MMMM
|
||||
MMMN .MMM]
|
||||
MMMMN; ` ` .(ggNNNNNNNNMMMM]
|
||||
MMMMM .MMMMMMMMMMMMMMMMM]
|
||||
MMMM_ ` MMMMMMMMMMMMMMMMMM]
|
||||
MMMMM] dMMMMMMMMMMMMMMMM]
|
||||
MMM# .MMMMMMMMMMMMMMMM]
|
||||
MMMFF `dMMMMMMMMMMMMMMMM]
|
||||
MMMbF dMMMMMMMMMMMMMMMM]
|
||||
_ _ _ _ _ _
|
||||
| \ | | ___ ___| |_ _ __ __ _____| |__ | |__ ___ ___| |_
|
||||
| \| |/ _ \/ __| __| '__| \ \ /\ / / _ \ '_ \| '_ \ / _ \/ __| __|
|
||||
| |\ | (_) \__ \ |_| | \ V V / __/ |_) | | | | (_) \__ \ |_
|
||||
|_| \_|\___/|___/\__|_| \_/\_/ \___|_.__/|_| |_|\___/|___/\__|
|
||||
|
||||
60
cli/go.mod
Normal file
60
cli/go.mod
Normal file
@@ -0,0 +1,60 @@
|
||||
module github.com/studiokaiji/nostr-webhost
|
||||
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
|
||||
github.com/btcsuite/btcd/btcutil v1.1.3 // indirect
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
|
||||
github.com/bytedance/sonic v1.10.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
||||
github.com/chenzhuoyu/iasm v0.9.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.1 // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/gin-gonic/gin v1.9.1 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.15.0 // indirect
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.2.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/nbd-wtf/go-nostr v0.20.0 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.9 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/puzpuzpuz/xsync v1.5.2 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/tidwall/gjson v1.14.4 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
github.com/urfave/cli/v2 v2.25.7 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
golang.org/x/arch v0.4.0 // indirect
|
||||
golang.org/x/crypto v0.12.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20221106115401-f9659909a136 // indirect
|
||||
golang.org/x/net v0.14.0 // indirect
|
||||
golang.org/x/sys v0.11.0 // indirect
|
||||
golang.org/x/term v0.11.0 // indirect
|
||||
golang.org/x/text v0.12.0 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
227
cli/go.sum
Normal file
227
cli/go.sum
Normal file
@@ -0,0 +1,227 @@
|
||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
||||
github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M=
|
||||
github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
|
||||
github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A=
|
||||
github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE=
|
||||
github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ=
|
||||
github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0=
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
||||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
|
||||
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
|
||||
github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I=
|
||||
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
|
||||
github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
|
||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
||||
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
|
||||
github.com/bytedance/sonic v1.10.0 h1:qtNZduETEIWJVIyDl01BeNxur2rW9OwTQ/yBqFRkKEk=
|
||||
github.com/bytedance/sonic v1.10.0/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
|
||||
github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
|
||||
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
|
||||
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
|
||||
github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8=
|
||||
github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.15.0 h1:nDU5XeOKtB3GEa+uB7GNYwhVKsgjAR7VgKoNB6ryXfw=
|
||||
github.com/go-playground/validator/v10 v10.15.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.2.0 h1:u0p9s3xLYpZCA1z5JgCkMeB34CKCMMQbM+G8Ii7YD0I=
|
||||
github.com/gobwas/ws v1.2.0/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/nbd-wtf/go-nostr v0.20.0 h1:97SYhg68jWh5G1bW1g454hA0dTV7btwtPg836n4no0o=
|
||||
github.com/nbd-wtf/go-nostr v0.20.0/go.mod h1:iFfiZr8YYSC1vmdUei0VfDB7GH/RjS3cbmiD1I5BKyo=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=
|
||||
github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/puzpuzpuz/xsync v1.5.2 h1:yRAP4wqSOZG+/4pxJ08fPTwrfL0IzE/LKQ/cw509qGY=
|
||||
github.com/puzpuzpuz/xsync v1.5.2/go.mod h1:K98BYhX3k1dQ2M63t1YNVDanbwUPmBCAhNmVrrxfiGg=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
||||
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
|
||||
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
|
||||
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc=
|
||||
golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/exp v0.0.0-20221106115401-f9659909a136 h1:Fq7F/w7MAa1KJ5bt2aJ62ihqp9HDcRuyILskkpIAurw=
|
||||
golang.org/x/exp v0.0.0-20221106115401-f9659909a136/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
|
||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
165
cli/main.go
Normal file
165
cli/main.go
Normal file
@@ -0,0 +1,165 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/studiokaiji/nostr-webhost/cmd/deploy"
|
||||
"github.com/studiokaiji/nostr-webhost/cmd/keystore"
|
||||
"github.com/studiokaiji/nostr-webhost/cmd/relays"
|
||||
"github.com/studiokaiji/nostr-webhost/cmd/server"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var (
|
||||
port string
|
||||
)
|
||||
|
||||
app := &cli.App{
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "deploy",
|
||||
Usage: "🌐 Deploy nostr website",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "path",
|
||||
Aliases: []string{"p"},
|
||||
Value: "./",
|
||||
Usage: "Site directory",
|
||||
},
|
||||
},
|
||||
Action: func(ctx *cli.Context) error {
|
||||
fmt.Println("🌐 Deploying...")
|
||||
path := ctx.String("path")
|
||||
indexEventId, err := deploy.Deploy(path)
|
||||
if err == nil {
|
||||
fmt.Println("🌐 Deploy Complete!")
|
||||
fmt.Println("🌐 index.html Event ID:", indexEventId)
|
||||
}
|
||||
return err
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "add-relay",
|
||||
Usage: "📌 Add nostr relay",
|
||||
Action: func(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
relay := args.Get(args.Len() - 1)
|
||||
err := relays.AddRelay(relay)
|
||||
if err == nil {
|
||||
fmt.Println("📌 Added relay:", relay)
|
||||
}
|
||||
return err
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "remove-relay",
|
||||
Usage: "🗑 Remove nostr relay",
|
||||
Action: func(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
relay := args.Get(args.Len() - 1)
|
||||
err := relays.RemoveRelay(relay)
|
||||
if err == nil {
|
||||
fmt.Println("🗑 Removed relay:", relay)
|
||||
}
|
||||
return err
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "list-relays",
|
||||
Usage: "📝 List added nostr relays",
|
||||
Action: func(ctx *cli.Context) error {
|
||||
relays, err := relays.GetAllRelays()
|
||||
fmt.Println("===========================")
|
||||
for _, relay := range relays {
|
||||
fmt.Println(relay)
|
||||
}
|
||||
fmt.Println("===========================")
|
||||
return err
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "set-private",
|
||||
Usage: "🔐 Set private key",
|
||||
Action: func(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
key := args.Get(args.Len() - 1)
|
||||
err := keystore.SetSecret(key)
|
||||
if err == nil {
|
||||
fmt.Println("🔐 Secret is recorded")
|
||||
}
|
||||
return err
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "show-public",
|
||||
Usage: "📛 Show public key",
|
||||
Action: func(ctx *cli.Context) error {
|
||||
_, _, err := keystore.ShowPublic()
|
||||
return err
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "generate-key",
|
||||
Usage: "🗝 Generate key",
|
||||
Action: func(ctx *cli.Context) error {
|
||||
key := nostr.GeneratePrivateKey()
|
||||
err := keystore.SetSecret(key)
|
||||
if err == nil {
|
||||
fmt.Print("🗝 Generated key\n🗝 You can check the public key with 'noshost show-public'\n")
|
||||
}
|
||||
return err
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "start",
|
||||
Usage: "🕺 Wake up web server",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "port",
|
||||
Aliases: []string{"p"},
|
||||
Value: "3000",
|
||||
Usage: "Web server port",
|
||||
Destination: &port,
|
||||
},
|
||||
},
|
||||
Action: func(ctx *cli.Context) error {
|
||||
server.Start(port)
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if len(os.Args) < 2 || os.Args[1] == "help" || os.Args[1] == "h" {
|
||||
// Display ostrich
|
||||
file, err := os.Open("./cute-ostrich.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
for {
|
||||
n, err := buf.ReadFrom(file)
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(buf.String())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Start app
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
11
docker-compose.yml
Normal file
11
docker-compose.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
version: "3.9"
|
||||
services:
|
||||
relay:
|
||||
image: "scsibug/nostr-rs-relay"
|
||||
ports:
|
||||
- "7001:8080"
|
||||
volumes:
|
||||
- ./nostr-rs-relay/data:/usr/src/app/db
|
||||
- ./nostr-rs-relay/config.toml:/usr/src/app/config.toml
|
||||
user: root
|
||||
container_name: nostr-webhost-relay
|
||||
18
example/.eslintrc.cjs
Normal file
18
example/.eslintrc.cjs
Normal file
@@ -0,0 +1,18 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: { browser: true, es2020: true },
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
],
|
||||
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['react-refresh'],
|
||||
rules: {
|
||||
'react-refresh/only-export-components': [
|
||||
'warn',
|
||||
{ allowConstantExport: true },
|
||||
],
|
||||
},
|
||||
}
|
||||
24
example/.gitignore
vendored
Normal file
24
example/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
27
example/README.md
Normal file
27
example/README.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# React + TypeScript + Vite
|
||||
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||
|
||||
Currently, two official plugins are available:
|
||||
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||
|
||||
## Expanding the ESLint configuration
|
||||
|
||||
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
|
||||
|
||||
- Configure the top-level `parserOptions` property like this:
|
||||
|
||||
```js
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
project: ['./tsconfig.json', './tsconfig.node.json'],
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
```
|
||||
|
||||
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
|
||||
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
|
||||
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
|
||||
13
example/index.html
Normal file
13
example/index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + React + TS</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
33
example/package.json
Normal file
33
example/package.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "example",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/josefin-sans": "^5.0.9",
|
||||
"@fontsource/poppins": "^5.0.8",
|
||||
"autoprefixer": "^10.4.15",
|
||||
"postcss": "^8.4.28",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"tailwindcss": "^3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.15",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||
"@typescript-eslint/parser": "^6.0.0",
|
||||
"@vitejs/plugin-react": "^4.0.3",
|
||||
"eslint": "^8.45.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.3",
|
||||
"typescript": "^5.0.2",
|
||||
"vite": "^4.4.5"
|
||||
}
|
||||
}
|
||||
6
example/postcss.config.js
Normal file
6
example/postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
1
example/public/vite.svg
Normal file
1
example/public/vite.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
0
example/src/App.css
Normal file
0
example/src/App.css
Normal file
68
example/src/App.tsx
Normal file
68
example/src/App.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { H1 } from "./components/H1";
|
||||
import { Link } from "./components/Link";
|
||||
|
||||
function App() {
|
||||
const htmlId = useMemo(() => window.location.pathname.split("/")[2], []);
|
||||
const cssId = useMemo(
|
||||
() => Array.from(document.styleSheets)[0].href?.split("/").slice(-1)[0],
|
||||
[]
|
||||
);
|
||||
const jsId = useMemo(
|
||||
() => Array.from(document.scripts)[0].src?.split("/").slice(-1)[0],
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
console.log(Array.from(document.styleSheets));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="font-body font-medium">
|
||||
<div className="h-screen relative w-full bg-primary text-white space-y-7 p-7">
|
||||
<H1 className="!leading-[0.8]">
|
||||
Nostr
|
||||
<br />
|
||||
WebHost
|
||||
</H1>
|
||||
<div>
|
||||
<p>
|
||||
Relay URL:{" "}
|
||||
<Link href="wss://nostrwebhost.studiokaiji.com">
|
||||
wss://nostrwebhost.studiokaiji.com
|
||||
</Link>
|
||||
</p>
|
||||
<p>HTML ID: {htmlId}</p>
|
||||
<p>CSS ID: {cssId}</p>
|
||||
<p>Javascript ID: {jsId}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
GitHub:{" "}
|
||||
<Link href="https://github.com/studiokaiji/nostr-webhost">
|
||||
https://github.com/studiokaiji/nostr-webhost
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>Created By @studiokaiji</p>
|
||||
<p>
|
||||
Nostr:
|
||||
npub194qhhn5vzzyrsqaugfms8c7ycqjyvhyguurra450nhlweatfzxkqy8tgkd
|
||||
</p>
|
||||
<p>
|
||||
GitHub:{" "}
|
||||
<Link href="https://github.com/studiokaiji">
|
||||
https://github.com/studiokaiji
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
<p className="absolute right-7 bottom-7">
|
||||
😩{"<"}Hmmm... I want to ride an ostrich...
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
1
example/src/assets/react.svg
Normal file
1
example/src/assets/react.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
5
example/src/components/H1.tsx
Normal file
5
example/src/components/H1.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
export const H1 = (props: JSX.IntrinsicElements["h1"]) => (
|
||||
<h1 {...props} className={`text-7xl font-bold ${props.className || ""}`}>
|
||||
{props.children}
|
||||
</h1>
|
||||
);
|
||||
10
example/src/components/Link.tsx
Normal file
10
example/src/components/Link.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
export const Link = (props: JSX.IntrinsicElements["a"]) => (
|
||||
<a
|
||||
{...props}
|
||||
className={`border-b-2 cursor-pointer border-white hover:opacity-70 transition-opacity ${
|
||||
props.className || ""
|
||||
}`}
|
||||
>
|
||||
{props.children}
|
||||
</a>
|
||||
);
|
||||
8
example/src/index.css
Normal file
8
example/src/index.css
Normal file
@@ -0,0 +1,8 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
body {
|
||||
cursor: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGNpcmNsZSBjeD0iMjAiIGN5PSIyMCIgcj0iMjAiIGZpbGw9IiM4RTMwRUIiLz4KPC9zdmc+Cg==, auto);
|
||||
height: 100vh;
|
||||
}
|
||||
12
example/src/main.tsx
Normal file
12
example/src/main.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import App from "./App.tsx";
|
||||
import "./index.css";
|
||||
import "@fontsource/poppins/500.css";
|
||||
import "@fontsource/poppins/700.css";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
);
|
||||
1
example/src/vite-env.d.ts
vendored
Normal file
1
example/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
15
example/tailwind.config.js
Normal file
15
example/tailwind.config.js
Normal file
@@ -0,0 +1,15 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
|
||||
theme: {
|
||||
fontFamily: {
|
||||
body: ["Josefin Sans", "ui-sans-serif", "system-ui"],
|
||||
},
|
||||
extend: {
|
||||
colors: {
|
||||
primary: "#8e30eb",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
25
example/tsconfig.json
Normal file
25
example/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
10
example/tsconfig.node.json
Normal file
10
example/tsconfig.node.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
7
example/vite.config.ts
Normal file
7
example/vite.config.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
})
|
||||
1863
example/yarn.lock
Normal file
1863
example/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
249
nostr-rs-relay/config.toml
Normal file
249
nostr-rs-relay/config.toml
Normal file
@@ -0,0 +1,249 @@
|
||||
# Nostr-rs-relay configuration
|
||||
|
||||
[info]
|
||||
# The advertised URL for the Nostr websocket.
|
||||
relay_url = "wss://nostr.example.com/"
|
||||
|
||||
# Relay information for clients. Put your unique server name here.
|
||||
name = "nostr-rs-relay"
|
||||
|
||||
# Description
|
||||
description = "A newly created nostr-rs-relay.\n\nCustomize this with your own info."
|
||||
|
||||
# Administrative contact pubkey
|
||||
#pubkey = "0c2d168a4ae8ca58c9f1ab237b5df682599c6c7ab74307ea8b05684b60405d41"
|
||||
|
||||
# Administrative contact URI
|
||||
#contact = "mailto:contact@example.com"
|
||||
|
||||
# Favicon location. Relative to the current directory. Assumes an
|
||||
# ICO format.
|
||||
#favicon = "favicon.ico"
|
||||
|
||||
# URL of Relay's icon.
|
||||
#relay_icon = "https://example.test/img.png"
|
||||
|
||||
[diagnostics]
|
||||
# Enable tokio tracing (for use with tokio-console)
|
||||
#tracing = false
|
||||
|
||||
[database]
|
||||
# Database engine (sqlite/postgres). Defaults to sqlite.
|
||||
# Support for postgres is currently experimental.
|
||||
#engine = "sqlite"
|
||||
|
||||
# Directory for SQLite files. Defaults to the current directory. Can
|
||||
# also be specified (and overriden) with the "--db dirname" command
|
||||
# line option.
|
||||
#data_directory = "."
|
||||
|
||||
# Use an in-memory database instead of 'nostr.db'.
|
||||
# Requires sqlite engine.
|
||||
# Caution; this will not survive a process restart!
|
||||
#in_memory = false
|
||||
|
||||
# Database connection pool settings for subscribers:
|
||||
|
||||
# Minimum number of SQLite reader connections
|
||||
#min_conn = 0
|
||||
|
||||
# Maximum number of SQLite reader connections. Recommend setting this
|
||||
# to approx the number of cores.
|
||||
#max_conn = 8
|
||||
|
||||
# Database connection string. Required for postgres; not used for
|
||||
# sqlite.
|
||||
#connection = "postgresql://postgres:nostr@localhost:7500/nostr"
|
||||
|
||||
# Optional database connection string for writing. Use this for
|
||||
# postgres clusters where you want to separate reads and writes to
|
||||
# different nodes. Ignore for single-database instances.
|
||||
#connection_write = "postgresql://postgres:nostr@localhost:7500/nostr"
|
||||
|
||||
[logging]
|
||||
# Directory to store log files. Log files roll over daily.
|
||||
#folder_path = "./log"
|
||||
#file_prefix = "nostr-relay"
|
||||
|
||||
[grpc]
|
||||
# gRPC interfaces for externalized decisions and other extensions to
|
||||
# functionality.
|
||||
#
|
||||
# Events can be authorized through an external service, by providing
|
||||
# the URL below. In the event the server is not accessible, events
|
||||
# will be permitted. The protobuf3 schema used is available in
|
||||
# `proto/nauthz.proto`.
|
||||
# event_admission_server = "http://[::1]:50051"
|
||||
|
||||
[network]
|
||||
# Bind to this network address
|
||||
address = "0.0.0.0"
|
||||
|
||||
# Listen on this port
|
||||
port = 8080
|
||||
|
||||
# If present, read this HTTP header for logging client IP addresses.
|
||||
# Examples for common proxies, cloudflare:
|
||||
#remote_ip_header = "x-forwarded-for"
|
||||
#remote_ip_header = "cf-connecting-ip"
|
||||
|
||||
# Websocket ping interval in seconds, defaults to 5 minutes
|
||||
#ping_interval = 300
|
||||
|
||||
[options]
|
||||
# Reject events that have timestamps greater than this many seconds in
|
||||
# the future. Recommended to reject anything greater than 30 minutes
|
||||
# from the current time, but the default is to allow any date.
|
||||
reject_future_seconds = 1800
|
||||
|
||||
[limits]
|
||||
# Limit events created per second, averaged over one minute. Must be
|
||||
# an integer. If not set (or set to 0), there is no limit. Note:
|
||||
# this is for the server as a whole, not per-connection.
|
||||
#
|
||||
# Limiting event creation is highly recommended if your relay is
|
||||
# public!
|
||||
#
|
||||
#messages_per_sec = 5
|
||||
|
||||
# Limit client subscriptions created, averaged over one minute. Must
|
||||
# be an integer. If not set (or set to 0), defaults to unlimited.
|
||||
# Strongly recommended to set this to a low value such as 10 to ensure
|
||||
# fair service.
|
||||
#subscriptions_per_min = 0
|
||||
|
||||
# UNIMPLEMENTED...
|
||||
# Limit how many concurrent database connections a client can have.
|
||||
# This prevents a single client from starting too many expensive
|
||||
# database queries. Must be an integer. If not set (or set to 0),
|
||||
# defaults to unlimited (subject to subscription limits).
|
||||
#db_conns_per_client = 0
|
||||
|
||||
# Limit blocking threads used for database connections. Defaults to 16.
|
||||
#max_blocking_threads = 16
|
||||
|
||||
# Limit the maximum size of an EVENT message. Defaults to 128 KB.
|
||||
# Set to 0 for unlimited.
|
||||
max_event_bytes = 1024000
|
||||
|
||||
# Maximum WebSocket message in bytes. Defaults to 128 KB.
|
||||
max_ws_message_bytes = 1024000
|
||||
|
||||
# Maximum WebSocket frame size in bytes. Defaults to 128 KB.
|
||||
max_ws_frame_bytes = 1024000
|
||||
|
||||
# Broadcast buffer size, in number of events. This prevents slow
|
||||
# readers from consuming memory.
|
||||
#broadcast_buffer = 16384
|
||||
|
||||
# Event persistence buffer size, in number of events. This provides
|
||||
# backpressure to senders if writes are slow.
|
||||
#event_persist_buffer = 4096
|
||||
|
||||
# Event kind blacklist. Events with these kinds will be discarded.
|
||||
#event_kind_blacklist = [
|
||||
# 70202,
|
||||
#]
|
||||
|
||||
# Event kind allowlist. Events other than these kinds will be discarded.
|
||||
event_kind_allowlist = [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
7,
|
||||
40,
|
||||
41,
|
||||
42,
|
||||
43,
|
||||
44,
|
||||
30023,
|
||||
1964,
|
||||
1965,
|
||||
5392,
|
||||
5393,
|
||||
5394,
|
||||
]
|
||||
|
||||
[authorization]
|
||||
# Pubkey addresses in this array are whitelisted for event publishing.
|
||||
# Only valid events by these authors will be accepted, if the variable
|
||||
# is set.
|
||||
#pubkey_whitelist = [
|
||||
# "35d26e4690cbe1a898af61cc3515661eb5fa763b57bd0b42e45099c8b32fd50f",
|
||||
# "887645fef0ce0c3c1218d2f5d8e6132a19304cdc57cd20281d082f38cfea0072",
|
||||
#]
|
||||
# Enable NIP-42 authentication
|
||||
#nip42_auth = false
|
||||
# Send DMs (kind 4 and 44) and gift wraps (kind 1059) only to their authenticated recipients
|
||||
#nip42_dms = false
|
||||
|
||||
[verified_users]
|
||||
# NIP-05 verification of users. Can be "enabled" to require NIP-05
|
||||
# metadata for event authors, "passive" to perform validation but
|
||||
# never block publishing, or "disabled" to do nothing.
|
||||
#mode = "disabled"
|
||||
|
||||
# Domain names that will be prevented from publishing events.
|
||||
#domain_blacklist = ["wellorder.net"]
|
||||
|
||||
# Domain names that are allowed to publish events. If defined, only
|
||||
# events NIP-05 verified authors at these domains are persisted.
|
||||
#domain_whitelist = ["example.com"]
|
||||
|
||||
# Consider an pubkey "verified" if we have a successful validation
|
||||
# from the NIP-05 domain within this amount of time. Note, if the
|
||||
# domain provides a successful response that omits the account,
|
||||
# verification is immediately revoked.
|
||||
#verify_expiration = "1 week"
|
||||
|
||||
# How long to wait between verification attempts for a specific author.
|
||||
#verify_update_frequency = "24 hours"
|
||||
|
||||
# How many consecutive failed checks before we give up on verifying
|
||||
# this author.
|
||||
#max_consecutive_failures = 20
|
||||
|
||||
[pay_to_relay]
|
||||
# Enable pay to relay
|
||||
#enabled = false
|
||||
|
||||
# The cost to be admitted to relay
|
||||
#admission_cost = 4200
|
||||
|
||||
# The cost in sats per post
|
||||
#cost_per_event = 0
|
||||
|
||||
# Url of lnbits api
|
||||
#node_url = "<node url>"
|
||||
|
||||
# LNBits api secret
|
||||
#api_secret = "<ln bits api>"
|
||||
|
||||
# Nostr direct message on signup
|
||||
#direct_message=true
|
||||
|
||||
# Terms of service
|
||||
#terms_message = """
|
||||
#This service (and supporting services) are provided "as is", without warranty of any kind, express or implied.
|
||||
#
|
||||
#By using this service, you agree:
|
||||
#* Not to engage in spam or abuse the relay service
|
||||
#* Not to disseminate illegal content
|
||||
#* That requests to delete content cannot be guaranteed
|
||||
#* To use the service in compliance with all applicable laws
|
||||
#* To grant necessary rights to your content for unlimited time
|
||||
#* To be of legal age and have capacity to use this service
|
||||
#* That the service may be terminated at any time without notice
|
||||
#* That the content you publish may be removed at any time without notice
|
||||
#* To have your IP address collected to detect abuse or misuse
|
||||
#* To cooperate with the relay to combat abuse or misuse
|
||||
#* You may be exposed to content that you might find triggering or distasteful
|
||||
#* The relay operator is not liable for content produced by users of the relay
|
||||
#"""
|
||||
|
||||
# Whether or not new sign ups should be allowed
|
||||
#sign_ups = false
|
||||
|
||||
# optional if `direct_message=false`
|
||||
#secret_key = "<nostr nsec>"
|
||||
53
readme.md
Normal file
53
readme.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Nostr Webhost
|
||||
|
||||
## Overview
|
||||
|
||||
Nostr Webhost is a command-line tool designed for hosting Single Page Applications (SPAs) using the Nostr protocol and its distributed network of relay servers. This tool provides a seamless way to deploy and access your SPA on the Nostr network.
|
||||
|
||||
### Installation
|
||||
|
||||
To get started with Nostr Webhost, follow these steps:
|
||||
|
||||
1. Install the tool using the following command:
|
||||
|
||||
2. Ensure you have Node.js and npm installed on your machine.
|
||||
|
||||
### Commands
|
||||
|
||||
```bash
|
||||
COMMANDS:
|
||||
deploy 🌐 Deploy nostr website
|
||||
add-relay 📌 Add nostr relay
|
||||
remove-relay 🗑 Remove nostr relay
|
||||
list-relay 📝 List added nostr relays
|
||||
set-private 🔐 Set private key
|
||||
show-public 📛 Show public key
|
||||
generate-key 🗝 Generate key
|
||||
start 🕺 Wake up web server
|
||||
help, h Shows a list of commands or help for one command
|
||||
```
|
||||
|
||||
### Getting Started
|
||||
|
||||
1. Install Nostr Webhost as mentioned above.
|
||||
2. Set or generate private key
|
||||
If you set private key: `nostrh set-private "nsec or hex private key"`
|
||||
Or if you want to generate private key: `nostrh generate-key`
|
||||
3. Add relay
|
||||
`nostrh add-relay wss://nostrwebhost.studiokaiji.com`
|
||||
4. Deploy
|
||||
`nostrh deploy /BUILT/SPA/DIR/PATH`
|
||||
The event id of index.html will be output after deploy. Please make a copy of it.
|
||||
5. Start test web server
|
||||
`nostrh start`
|
||||
6. Access the `http://localhost:3000/e/{event-id-of-index.html}`
|
||||
|
||||
For detailed information on how to use each command, you can use the `help` command followed by the specific command name.
|
||||
|
||||
## Feedback and Contributions
|
||||
|
||||
If you encounter any issues or have suggestions for improvement, feel free to contribute to the project on GitHub [link to GitHub repository].
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT. See the LICENSE file for more details.
|
||||
Reference in New Issue
Block a user