package deploy
import (
"bufio"
"bytes"
"fmt"
"net/url"
"os"
"path/filepath"
"strings"
"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/keystore"
"github.com/studiokaiji/nostr-webhost/hostr/cmd/relays"
"golang.org/x/net/html"
)
func isExternalURL(urlStr string) bool {
u, err := url.Parse(urlStr)
return err == nil && u.Scheme != "" && u.Host != ""
}
func Deploy(basePath string, replaceable bool, htmlIdentifier string) (string, 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 "", "", "", err
}
// 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
}
// htmlIdentifierの存在チェック
if replaceable && len(htmlIdentifier) < 1 {
// htmlIdentifierが指定されていない場合はユーザー入力を受け取る
reader := bufio.NewReader(os.Stdin)
fmt.Print("⌨️ Please type identifier: ")
htmlIdentifier, _ = reader.ReadString('\n')
// 改行タグを削除
htmlIdentifier = strings.TrimSpace(htmlIdentifier)
fmt.Printf("Identifier: %s\n", htmlIdentifier)
}
// リレーを取得
allRelays, err = relays.GetAllRelays()
if err != nil {
fmt.Println("❌ Failed to get all relays:", err)
return "", "", "", err
}
// basePath以下のText Fileのパスをすべて羅列する
err = generateEventsAndAddQueueAllValidStaticTextFiles(
priKey,
pubKey,
htmlIdentifier,
basePath,
replaceable,
)
if err != nil {
fmt.Println("❌ Failed to convert text files:", err)
return "", "", "", err
}
// basePath以下のMedia Fileのパスを全て羅列しアップロード
err = uploadAllValidStaticMediaFiles(priKey, pubKey, basePath)
if err != nil {
fmt.Println("❌ Failed to upload media:", err)
return "", "", "", err
}
// リンクの解析と変換
convertLinks(priKey, pubKey, basePath, replaceable, htmlIdentifier, doc)
// 更新されたHTML
var buf bytes.Buffer
html.Render(&buf, doc)
strHtml := buf.String()
// index.htmlのkindを設定
indexHtmlKind := consts.KindWebhostHTML
if replaceable {
indexHtmlKind = consts.KindWebhostReplaceableHTML
}
// Tagsを追加
tags := nostr.Tags{}
if replaceable {
tags = tags.AppendUnique(nostr.Tag{"d", htmlIdentifier})
}
// Eventを生成しキューに追加
event, err := getEvent(priKey, pubKey, strHtml, indexHtmlKind, tags)
if err != nil {
fmt.Println("❌ Failed to get public key:", err)
return "", "", "", err
}
addNostrEventQueue(event, filePath)
eventId, encoded := publishEventsFromQueue(replaceable)
return eventId, encoded, htmlIdentifier, err
}
func convertLinks(
priKey, pubKey, basePath string,
replaceable bool,
indexHtmlIdentifier string,
n *html.Node,
) {
if n.Type == html.ElementNode {
if n.Data == "link" || n.Data == "script" {
// と