feat(whatsapp): add proxy support for native and bridge modes

This commit is contained in:
dtapps 2026-04-03 00:05:48 +08:00
parent dad5dcc30f
commit 9e2b6fda72
5 changed files with 28 additions and 0 deletions

View file

@ -127,6 +127,7 @@
"whatsapp": { "whatsapp": {
"enabled": false, "enabled": false,
"bridge_url": "ws://localhost:3001", "bridge_url": "ws://localhost:3001",
"proxy": "",
"use_native": false, "use_native": false,
"session_store_path": "", "session_store_path": "",
"allow_from": [], "allow_from": [],

View file

@ -4,6 +4,9 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http"
"net/url"
"os"
"sync" "sync"
"time" "time"
@ -56,6 +59,16 @@ func (c *WhatsAppChannel) Start(ctx context.Context) error {
dialer := websocket.DefaultDialer dialer := websocket.DefaultDialer
dialer.HandshakeTimeout = 10 * time.Second dialer.HandshakeTimeout = 10 * time.Second
if c.config.Proxy != "" {
proxyURL, parseErr := url.Parse(c.config.Proxy)
if parseErr != nil {
return fmt.Errorf("invalid proxy URL %q: %w", c.config.Proxy, parseErr)
}
dialer.Proxy = http.ProxyURL(proxyURL)
} else if os.Getenv("HTTP_PROXY") != "" || os.Getenv("HTTPS_PROXY") != "" {
dialer.Proxy = http.ProxyFromEnvironment
}
conn, resp, err := dialer.Dial(c.url, nil) conn, resp, err := dialer.Dial(c.url, nil)
if resp != nil { if resp != nil {
resp.Body.Close() resp.Body.Close()

View file

@ -11,6 +11,8 @@ import (
"context" "context"
"database/sql" "database/sql"
"fmt" "fmt"
"net/http"
"net/url"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -124,6 +126,16 @@ func (c *WhatsAppNativeChannel) Start(ctx context.Context) error {
client := whatsmeow.NewClient(deviceStore, waLogger) client := whatsmeow.NewClient(deviceStore, waLogger)
if c.config.Proxy != "" {
proxyURL, parseErr := url.Parse(c.config.Proxy)
if parseErr != nil {
return fmt.Errorf("invalid proxy URL %q: %w", c.config.Proxy, parseErr)
}
client.SetProxy(http.ProxyURL(proxyURL))
} else if os.Getenv("HTTP_PROXY") != "" || os.Getenv("HTTPS_PROXY") != "" {
client.SetProxy(http.ProxyFromEnvironment)
}
// Create runCtx/runCancel BEFORE registering event handler and starting // Create runCtx/runCancel BEFORE registering event handler and starting
// goroutines so that Stop() can cancel them at any time, including during // goroutines so that Stop() can cancel them at any time, including during
// the QR-login flow. // the QR-login flow.

View file

@ -336,6 +336,7 @@ type StreamingConfig struct {
type WhatsAppConfig struct { type WhatsAppConfig struct {
Enabled bool `json:"enabled" yaml:"-" env:"PICOCLAW_CHANNELS_WHATSAPP_ENABLED"` Enabled bool `json:"enabled" yaml:"-" env:"PICOCLAW_CHANNELS_WHATSAPP_ENABLED"`
BridgeURL string `json:"bridge_url" yaml:"-" env:"PICOCLAW_CHANNELS_WHATSAPP_BRIDGE_URL"` BridgeURL string `json:"bridge_url" yaml:"-" env:"PICOCLAW_CHANNELS_WHATSAPP_BRIDGE_URL"`
Proxy string `json:"proxy" yaml:"-" env:"PICOCLAW_CHANNELS_WHATSAPP_PROXY"`
UseNative bool `json:"use_native" yaml:"-" env:"PICOCLAW_CHANNELS_WHATSAPP_USE_NATIVE"` UseNative bool `json:"use_native" yaml:"-" env:"PICOCLAW_CHANNELS_WHATSAPP_USE_NATIVE"`
SessionStorePath string `json:"session_store_path" yaml:"-" env:"PICOCLAW_CHANNELS_WHATSAPP_SESSION_STORE_PATH"` SessionStorePath string `json:"session_store_path" yaml:"-" env:"PICOCLAW_CHANNELS_WHATSAPP_SESSION_STORE_PATH"`
AllowFrom FlexibleStringSlice `json:"allow_from" yaml:"-" env:"PICOCLAW_CHANNELS_WHATSAPP_ALLOW_FROM"` AllowFrom FlexibleStringSlice `json:"allow_from" yaml:"-" env:"PICOCLAW_CHANNELS_WHATSAPP_ALLOW_FROM"`

View file

@ -642,6 +642,7 @@ type ChannelsConfig struct {
type WhatsAppConfig struct { type WhatsAppConfig struct {
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
BridgeURL string `json:"bridge_url"` BridgeURL string `json:"bridge_url"`
Proxy string `json:"proxy"`
AllowFrom []string `json:"allow_from"` AllowFrom []string `json:"allow_from"`
} }