Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions hoot.go
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,8 @@ func getDMs(privateKey string) ([]tui.FeedPost, error) {
}

// Decrypt the DM content
decrypted, err := nip04.Decrypt(ev.Content, []byte(privateKey))
ss, _ := nip04.ComputeSharedSecret(ev.PubKey, privateKey)
decrypted, err := nip04.Decrypt(ev.Content, ss)
if err != nil {
continue // Skip if we can't decrypt
}
Expand Down Expand Up @@ -787,6 +788,7 @@ func getReactions(eventID string) ([]tui.FeedPost, error) {
// publishPostTUI publishes a note using either NIP-46 or local key
func publishPostTUI(content string) error {
var event nostr.Event
var err error
event.Kind = 1
event.Content = content
event.CreatedAt = nostr.Now()
Expand All @@ -807,22 +809,28 @@ func publishPostTUI(content string) error {
if localPrivateKey == "" {
return fmt.Errorf("no active session or local key")
}
event.PubKey, _ = nostr.GetPublicKey(localPrivateKey)
event.Sign(localPrivateKey)
event.PubKey, err = nostr.GetPublicKey(localPrivateKey)
if err != nil {
return fmt.Errorf("failed to get public key: %w", err)
}
if err := event.Sign(localPrivateKey); err != nil {
return fmt.Errorf("failed to sign event: %w", err)
}
}

success := 0
for _, url := range relays {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
relay, err := nostr.RelayConnect(ctx, url)
if err != nil {
cancel()
continue
}
if err := relay.Publish(ctx, event); err == nil {
success++
}
relay.Close()
cancel()
}

if success == 0 {
Expand Down Expand Up @@ -904,12 +912,12 @@ func editProfile(privateKey, newContent, pubKey string, relays []string) {

// registerAsHandler registers the app as a handler for specific kinds.
func registerAsHandler(privateKey, publicKey string, kinds []int, platforms map[string]string) error {
// Create a kind 1984 event for handler registration
// Create a kind 31990 event for handler registration (NIP-89)
event := nostr.Event{
PubKey: publicKey,
CreatedAt: nostr.Timestamp(time.Now().Unix()),
Kind: 1984,
Tags: nostr.Tags{},
Kind: 31990,
Tags: nostr.Tags{{"d", "hoot"}},
Content: "",
}

Expand Down Expand Up @@ -955,7 +963,7 @@ func recommendApp(privateKey, publicKey, handlerPubKey, handlerDIdentifier strin
CreatedAt: nostr.Timestamp(time.Now().Unix()),
Kind: 1985,
Tags: nostr.Tags{
{"a", fmt.Sprintf("%s:%s:%d", handlerPubKey, handlerDIdentifier, kind)},
{"a", fmt.Sprintf("%d:%s:%s", kind, handlerPubKey, handlerDIdentifier)},
{"p", platform},
},
Content: relayHint,
Expand Down Expand Up @@ -996,7 +1004,7 @@ func findHandlers(kind int) ([]struct {
// Use relay list from file or default
relays := getRelayList()
filter := nostr.Filter{
Kinds: []int{1984},
Kinds: []int{31990},
Tags: nostr.TagMap{"k": []string{fmt.Sprintf("%d", kind)}},
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
Expand Down Expand Up @@ -1033,7 +1041,7 @@ func findHandlers(kind int) ([]struct {
}

for _, tag := range ev.Tags {
if tag[0] == "k" {
if len(tag) > 1 && tag[0] == "k" {
kind, err := strconv.Atoi(tag[1])
if err == nil {
handler.SupportedKinds = append(handler.SupportedKinds, kind)
Expand Down Expand Up @@ -1303,7 +1311,8 @@ func extractLud16(pubKey string, relays []string) (string, error) {
func main() {
// Initialize cache for improved performance
configDir := getConfigDir()
eventCache, err := cache.New(configDir)
var err error
eventCache, err = cache.New(configDir)
if err != nil {
log.Printf("Warning: failed to initialize cache: %v", err)
} else {
Expand Down Expand Up @@ -1769,7 +1778,7 @@ func main() {

// Handle DMs action with loading.
if *dmsPtr {
_ = withLoading("Loading DMs", func() error {
err = withLoading("Loading DMs", func() error {
dms, err := getDMs(sk)
if err != nil {
return fmt.Errorf("failed to load DMs: %w", err)
Expand All @@ -1788,7 +1797,7 @@ func main() {

// Handle replies action with loading.
if *repliesPtr != "" {
_ = withLoading("Loading replies", func() error {
err = withLoading("Loading replies", func() error {
replies, err := getReactions(*repliesPtr)
if err != nil {
return fmt.Errorf("failed to load replies: %w", err)
Expand Down
9 changes: 8 additions & 1 deletion nip46/nip46.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,11 +405,18 @@ func (s *Session) publishToAllRelays(ctx context.Context, event *nostr.Event) er
}
wg.Wait()
close(errCh)
successes := 0
var lastErr error
for err := range errCh {
if err != nil {
return err
lastErr = err
} else {
successes++
}
}
if successes == 0 {
return fmt.Errorf("failed to publish to any relay: %w", lastErr)
}
return nil
}

Expand Down
8 changes: 6 additions & 2 deletions tui/tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,10 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if m.cursor < limit {
m.cursor++
}
case ScreenHome:
if m.cursor < 7 {
m.cursor++
}
default:
m.cursor++
}
Expand Down Expand Up @@ -343,7 +347,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}

// Update text input
if (m.screen == ScreenLogin && (m.cursor == 50 || m.cursor == 100)) || m.screen == ScreenPost || m.screen == ScreenTip || m.screen == ScreenReplies || (m.screen == ScreenRelays && m.addingRelay) {
if (m.screen == ScreenLogin && (m.cursor == 50 || m.cursor == 51 || m.cursor == 100 || m.cursor == 200)) || m.screen == ScreenPost || m.screen == ScreenTip || m.screen == ScreenReplies || (m.screen == ScreenRelays && m.addingRelay) {
// Only update input if we are in input mode (not menu selection mode)
// For Login: if hasKey (Input mode) OR if !hasKey and cursor=0 (Nsec Entry? No, cursor 0 is menu choice)
// Wait, if !hasKey:
Expand Down Expand Up @@ -378,7 +382,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
// The previous code reused cursor=0 for menu. This is confusing.

// Using cursor=50 for Nsec Entry, 100 for Password/Save choice.
if m.cursor == 50 || m.cursor == 100 {
if m.cursor == 50 || m.cursor == 51 || m.cursor == 100 || m.cursor == 200 {
m.textInput, cmd = m.textInput.Update(msg)
}
}
Expand Down
Loading