Two related additions for using omarchy-send beyond the focused TUI: Headless send (no TUI / no TTY) — for scripts, cron, SSH sessions: omarchy-send --to "<alias>" --message "<text>" [--send-pin N] [--wait 15s] Resolves the peer by alias over multicast (discovery only, not the HTTP receiver, so it co-exists with a running instance), sends, prints a one-line result, and exits non-zero on not-found / failure. New discovery.FindPeer/Snapshot and client.SendMessageSync (returns the error directly, incl. ErrPinRequired). Bugfix surfaced by the above: the official LocalSend client answers a message prepare-upload with HTTP 204 No Content (the text rides in the preview field, nothing to upload). prepareUpload only accepted 200, so message sends to official peers failed with "prepare-upload status 204" in BOTH the new headless path and the existing TUI. Now treats 204 as success (empty response). Desktop notifications: a running receiver raises a notify-send notification on an incoming message or file offer, so mako shows it on Omarchy/Hyprland even when the TUI isn't focused. New internal/notify (best-effort; self-disabling on headless boxes with no notify-send / session bus). Off-switch: --no-notify flag, cfg.NoNotify, and a Settings 'n' toggle wired to a live atomic gate via Controller.SetNotify so it takes effect without a restart. Tests: discovery/find_test, client/message_sync_test, client/prepare_204_test, app/events_test. Race-clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
56 lines
1.6 KiB
Go
56 lines
1.6 KiB
Go
package discovery
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// FindPeer returns immediately for a peer already in the snapshot.
|
|
func TestFindPeerAlreadyKnown(t *testing.T) {
|
|
d := New(mkInfo("self", "selffp", 0))
|
|
d.NotePeer(mkInfo("Strong Onion", "peerfp", 53317), "192.168.1.50")
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
|
defer cancel()
|
|
// Match is case-insensitive and whitespace-trimmed, like the CLI.
|
|
got, err := d.FindPeer(ctx, func(p Peer) bool {
|
|
return p.Info.Alias == "Strong Onion"
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("FindPeer: %v", err)
|
|
}
|
|
if got.IP != "192.168.1.50" {
|
|
t.Errorf("IP = %q, want 192.168.1.50", got.IP)
|
|
}
|
|
}
|
|
|
|
// FindPeer resolves a peer that only appears after the call starts.
|
|
func TestFindPeerArrivesLater(t *testing.T) {
|
|
d := New(mkInfo("self", "selffp", 0))
|
|
|
|
go func() {
|
|
time.Sleep(50 * time.Millisecond)
|
|
d.NotePeer(mkInfo("Latecomer", "latefp", 53317), "10.0.0.9")
|
|
}()
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
|
defer cancel()
|
|
got, err := d.FindPeer(ctx, func(p Peer) bool { return p.Info.Alias == "Latecomer" })
|
|
if err != nil {
|
|
t.Fatalf("FindPeer: %v", err)
|
|
}
|
|
if got.IP != "10.0.0.9" {
|
|
t.Errorf("IP = %q, want 10.0.0.9", got.IP)
|
|
}
|
|
}
|
|
|
|
// FindPeer returns the context error when no match arrives in time.
|
|
func TestFindPeerTimeout(t *testing.T) {
|
|
d := New(mkInfo("self", "selffp", 0))
|
|
ctx, cancel := context.WithTimeout(context.Background(), 80*time.Millisecond)
|
|
defer cancel()
|
|
if _, err := d.FindPeer(ctx, func(Peer) bool { return false }); err == nil {
|
|
t.Fatal("expected a timeout error, got nil")
|
|
}
|
|
}
|