package main import ( "context" "encoding/hex" "encoding/json" "strings" "github.com/fiatjaf/cli/v3" "github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr/nip19" "github.com/nbd-wtf/go-nostr/sdk" ) var decode = &cli.Command{ Name: "decode", Usage: "decodes nip19, nip21, nip05 or hex entities", Description: `example usage: nak decode npub1uescmd5krhrmj9rcura833xpke5eqzvcz5nxjw74ufeewf2sscxq4g7chm nak decode nevent1qqs29yet5tp0qq5xu5qgkeehkzqh5qu46739axzezcxpj4tjlkx9j7gpr4mhxue69uhkummnw3ez6ur4vgh8wetvd3hhyer9wghxuet5sh59ud nak decode nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpz4mhxue69uhk2er9dchxummnw3ezumrpdejqz8thwden5te0dehhxarj94c82c3wwajkcmr0wfjx2u3wdejhgqgcwaehxw309aex2mrp0yhxummnw3exzarf9e3k7mgnp0sh5 nak decode nsec1jrmyhtjhgd9yqalps8hf9mayvd58852gtz66m7tqpacjedkp6kxq4dyxsr`, DisableSliceFlagSeparator: true, Flags: []cli.Flag{ &cli.BoolFlag{ Name: "id", Aliases: []string{"e"}, Usage: "return just the event id, if applicable", }, &cli.BoolFlag{ Name: "pubkey", Aliases: []string{"p"}, Usage: "return just the pubkey, if applicable", }, }, ArgsUsage: "", Action: func(ctx context.Context, c *cli.Command) error { for input := range getStdinLinesOrArguments(c.Args()) { if strings.HasPrefix(input, "nostr:") { input = input[6:] } var decodeResult DecodeResult if b, err := hex.DecodeString(input); err == nil { if len(b) == 64 { decodeResult.HexResult.PossibleTypes = []string{"sig"} decodeResult.HexResult.Signature = hex.EncodeToString(b) } else if len(b) == 32 { decodeResult.HexResult.PossibleTypes = []string{"pubkey", "private_key", "event_id"} decodeResult.HexResult.ID = hex.EncodeToString(b) decodeResult.HexResult.PrivateKey = hex.EncodeToString(b) decodeResult.HexResult.PublicKey = hex.EncodeToString(b) } else { ctx = lineProcessingError(ctx, "hex string with invalid number of bytes: %d", len(b)) continue } } else if evp := sdk.InputToEventPointer(input); evp != nil { decodeResult = DecodeResult{EventPointer: evp} if c.Bool("id") { stdout(evp.ID) continue } } else if pp := sdk.InputToProfile(ctx, input); pp != nil { decodeResult = DecodeResult{ProfilePointer: pp} if c.Bool("pubkey") { stdout(pp.PublicKey) continue } } else if prefix, value, err := nip19.Decode(input); err == nil && prefix == "naddr" { if ep, ok := value.(nostr.EntityPointer); ok { decodeResult = DecodeResult{EntityPointer: &ep} } else { ctx = lineProcessingError(ctx, "couldn't decode naddr: %s", err) } } else if prefix, value, err := nip19.Decode(input); err == nil && prefix == "nsec" { decodeResult.PrivateKey.PrivateKey = value.(string) decodeResult.PrivateKey.PublicKey, _ = nostr.GetPublicKey(value.(string)) } else { ctx = lineProcessingError(ctx, "couldn't decode input '%s': %s", input, err) continue } if c.Bool("pubkey") || c.Bool("id") { return nil } stdout(decodeResult.JSON()) } exitIfLineProcessingError(ctx) return nil }, } type DecodeResult struct { *nostr.EventPointer *nostr.ProfilePointer *nostr.EntityPointer HexResult struct { PossibleTypes []string `json:"possible_types"` PublicKey string `json:"pubkey,omitempty"` ID string `json:"event_id,omitempty"` PrivateKey string `json:"private_key,omitempty"` Signature string `json:"sig,omitempty"` } PrivateKey struct { nostr.ProfilePointer PrivateKey string `json:"private_key"` } } func (d DecodeResult) JSON() string { var j []byte if d.EventPointer != nil { j, _ = json.MarshalIndent(d.EventPointer, "", " ") } else if d.ProfilePointer != nil { j, _ = json.MarshalIndent(d.ProfilePointer, "", " ") } else if d.EntityPointer != nil { j, _ = json.MarshalIndent(d.EntityPointer, "", " ") } else if len(d.HexResult.PossibleTypes) > 0 { j, _ = json.MarshalIndent(d.HexResult, "", " ") } else if d.PrivateKey.PrivateKey != "" { j, _ = json.MarshalIndent(d.PrivateKey, "", " ") } return string(j) }