feat(main): extract testable runCommand and add debug log for blocked WhatsApp senders
- Extract runCommand(w, args) from main() so the command tree can be tested without spawning a subprocess; fatal errors are printed to w so they surface even when stderr is redirected (e.g. docker). - Add TestRunCommandFatalPrintsToStdout to verify the FATAL message reaches stdout on cobra errors. - Log a DebugCF message when an incoming WhatsApp message is silently dropped because the sender is not in allow_from. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d392ef8da9
commit
32433f85d2
3 changed files with 32 additions and 2 deletions
|
|
@ -8,6 +8,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -67,6 +68,21 @@ const (
|
||||||
"\033[0m\r\n"
|
"\033[0m\r\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// runCommand executes picoclaw with the given args, writing output to w.
|
||||||
|
// On failure it prints a prominent error to w so the message is visible
|
||||||
|
// even when os.Stderr has been redirected (e.g. to a panic-log file).
|
||||||
|
func runCommand(w io.Writer, args []string) error {
|
||||||
|
cmd := NewPicoclawCommand()
|
||||||
|
cmd.SetOut(w)
|
||||||
|
cmd.SetErr(w)
|
||||||
|
cmd.SetArgs(args)
|
||||||
|
if err := cmd.Execute(); err != nil {
|
||||||
|
fmt.Fprintf(w, "\n\033[1;31m✗ FATAL: %v\033[0m\n", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Printf("%s", banner)
|
fmt.Printf("%s", banner)
|
||||||
|
|
||||||
|
|
@ -84,8 +100,7 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := NewPicoclawCommand()
|
if err := runCommand(os.Stdout, os.Args[1:]); err != nil {
|
||||||
if err := cmd.Execute(); err != nil {
|
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -12,6 +13,19 @@ import (
|
||||||
"github.com/sipeed/picoclaw/pkg/config"
|
"github.com/sipeed/picoclaw/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TestRunCommandFatalPrintsToStdout verifies that when a subcommand fails,
|
||||||
|
// runCommand prints a prominent error to the provided writer (stdout in production),
|
||||||
|
// so the error is visible in environments where stderr is redirected (e.g. docker).
|
||||||
|
func TestRunCommandFatalPrintsToStdout(t *testing.T) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
// Pass an unknown flag to trigger a cobra error without any real I/O.
|
||||||
|
err := runCommand(&buf, []string{"gateway", "--no-such-flag"})
|
||||||
|
require.Error(t, err)
|
||||||
|
out := buf.String()
|
||||||
|
assert.Contains(t, out, "FATAL", "fatal error must be printed to stdout")
|
||||||
|
assert.Contains(t, out, err.Error(), "error message must appear in stdout output")
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewPicoclawCommand(t *testing.T) {
|
func TestNewPicoclawCommand(t *testing.T) {
|
||||||
cmd := NewPicoclawCommand()
|
cmd := NewPicoclawCommand()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -385,6 +385,7 @@ func (c *WhatsAppNativeChannel) handleIncoming(evt *events.Message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.IsAllowedSender(sender) {
|
if !c.IsAllowedSender(sender) {
|
||||||
|
logger.DebugCF("whatsapp", "WhatsApp message blocked (not in allow_from)", map[string]any{"sender_id": senderID})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue