mirror of
https://github.com/fiatjaf/nak.git
synced 2025-12-09 00:58:50 +00:00
Compare commits
1 Commits
v0.17.1
...
2de3ff78ee
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2de3ff78ee |
1
main.go
1
main.go
@@ -49,6 +49,7 @@ var app = &cli.Command{
|
||||
fsCmd,
|
||||
publish,
|
||||
git,
|
||||
nip,
|
||||
},
|
||||
Version: version,
|
||||
Flags: []cli.Flag{
|
||||
|
||||
186
nip.go
Normal file
186
nip.go
Normal file
@@ -0,0 +1,186 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var nip = &cli.Command{
|
||||
Name: "nip",
|
||||
Usage: "get the description of a NIP from its number",
|
||||
Description: `fetches the NIPs README from GitHub and parses it to find the description of the given NIP number.
|
||||
|
||||
example:
|
||||
nak nip 1
|
||||
nak nip list
|
||||
nak nip open 1`,
|
||||
ArgsUsage: "<NIP number>",
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "list",
|
||||
Usage: "list all NIPs",
|
||||
Action: func(ctx context.Context, c *cli.Command) error {
|
||||
return iterateNips(func(nip, desc, link string) bool {
|
||||
stdout(nip + ": " + desc)
|
||||
return true
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "open",
|
||||
Usage: "open the NIP page in the browser",
|
||||
Action: func(ctx context.Context, c *cli.Command) error {
|
||||
reqNum := c.Args().First()
|
||||
if reqNum == "" {
|
||||
return fmt.Errorf("missing NIP number")
|
||||
}
|
||||
|
||||
normalize := func(s string) string {
|
||||
s = strings.ToLower(s)
|
||||
s = strings.TrimPrefix(s, "nip-")
|
||||
s = strings.TrimLeft(s, "0")
|
||||
if s == "" {
|
||||
s = "0"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
reqNum = normalize(reqNum)
|
||||
|
||||
foundLink := ""
|
||||
err := iterateNips(func(nip, desc, link string) bool {
|
||||
nipNum := normalize(nip)
|
||||
if nipNum == reqNum {
|
||||
foundLink = link
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if foundLink == "" {
|
||||
return fmt.Errorf("NIP-%s not found", strings.ToUpper(reqNum))
|
||||
}
|
||||
|
||||
url := "https://github.com/nostr-protocol/nips/blob/master/" + foundLink
|
||||
fmt.Println("Opening " + url)
|
||||
|
||||
var cmd *exec.Cmd
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
cmd = exec.Command("open", url)
|
||||
case "windows":
|
||||
cmd = exec.Command("cmd", "/c", "start", url)
|
||||
default:
|
||||
cmd = exec.Command("xdg-open", url)
|
||||
}
|
||||
|
||||
return cmd.Start()
|
||||
},
|
||||
},
|
||||
},
|
||||
Action: func(ctx context.Context, c *cli.Command) error {
|
||||
reqNum := c.Args().First()
|
||||
if reqNum == "" {
|
||||
return fmt.Errorf("missing NIP number")
|
||||
}
|
||||
|
||||
normalize := func(s string) string {
|
||||
s = strings.ToLower(s)
|
||||
s = strings.TrimPrefix(s, "nip-")
|
||||
s = strings.TrimLeft(s, "0")
|
||||
if s == "" {
|
||||
s = "0"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
reqNum = normalize(reqNum)
|
||||
|
||||
found := false
|
||||
err := iterateNips(func(nip, desc, link string) bool {
|
||||
nipNum := normalize(nip)
|
||||
|
||||
if nipNum == reqNum {
|
||||
stdout(strings.TrimSpace(desc))
|
||||
found = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !found {
|
||||
return fmt.Errorf("NIP-%s not found", strings.ToUpper(reqNum))
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func iterateNips(yield func(nip, desc, link string) bool) error {
|
||||
resp, err := http.Get("https://raw.githubusercontent.com/nostr-protocol/nips/master/README.md")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch NIPs README: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read NIPs README: %w", err)
|
||||
}
|
||||
bodyStr := string(body)
|
||||
epoch := strings.Index(bodyStr, "## List")
|
||||
|
||||
lines := strings.SplitSeq(bodyStr[epoch+8:], "\n")
|
||||
for line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if strings.HasPrefix(line, "##") {
|
||||
break
|
||||
}
|
||||
if !strings.HasPrefix(line, "- [NIP-") {
|
||||
continue
|
||||
}
|
||||
|
||||
start := strings.Index(line, "[")
|
||||
end := strings.Index(line, "]")
|
||||
if start == -1 || end == -1 || end < start {
|
||||
continue
|
||||
}
|
||||
|
||||
content := line[start+1 : end]
|
||||
|
||||
parts := strings.SplitN(content, ":", 2)
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
nipPart := parts[0]
|
||||
descPart := parts[1]
|
||||
|
||||
rest := line[end+1:]
|
||||
linkStart := strings.Index(rest, "(")
|
||||
linkEnd := strings.Index(rest, ")")
|
||||
link := ""
|
||||
if linkStart != -1 && linkEnd != -1 && linkEnd > linkStart {
|
||||
link = rest[linkStart+1 : linkEnd]
|
||||
}
|
||||
|
||||
if !yield(nipPart, strings.TrimSpace(descPart), link) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user