feat(whatsapp): align with other channels code; handle reconnects

This commit is contained in:
fipso 2026-02-20 16:49:48 +01:00
parent 60c12072d0
commit 49076fdfe8
3 changed files with 42 additions and 16 deletions

View file

@ -45,12 +45,17 @@ func (c *WhatsmeowChannel) Start(ctx context.Context) error {
dbPath := expandHomePath(c.config.DBPath) dbPath := expandHomePath(c.config.DBPath)
// Ensure directory exists // Ensure directory exists
if err := os.MkdirAll(filepath.Dir(dbPath), 0755); err != nil { if err := os.MkdirAll(filepath.Dir(dbPath), 0o755); err != nil {
return fmt.Errorf("failed to create db directory: %w", err) return fmt.Errorf("failed to create db directory: %w", err)
} }
dbLog := waLog.Noop dbLog := waLog.Noop
container, err := sqlstore.New(ctx, "sqlite", fmt.Sprintf("file:%s?_pragma=foreign_keys(1)&_pragma=journal_mode(WAL)", dbPath), dbLog) container, err := sqlstore.New(
ctx,
"sqlite",
fmt.Sprintf("file:%s?_pragma=foreign_keys(1)&_pragma=journal_mode(WAL)", dbPath),
dbLog,
)
if err != nil { if err != nil {
return fmt.Errorf("failed to open whatsmeow db: %w", err) return fmt.Errorf("failed to open whatsmeow db: %w", err)
} }
@ -129,16 +134,18 @@ func (c *WhatsmeowChannel) Send(ctx context.Context, msg bus.OutboundMessage) er
return nil return nil
} }
func (c *WhatsmeowChannel) eventHandler(evt interface{}) { func (c *WhatsmeowChannel) eventHandler(evt any) {
switch v := evt.(type) { switch v := evt.(type) {
case *events.Message: case *events.Message:
c.handleIncomingMessage(v) c.handleIncomingMessage(v)
case *events.Connected: case *events.Connected:
logger.InfoC("whatsmeow", "WhatsApp connected") logger.InfoC("whatsmeow", "WhatsApp connected")
c.setRunning(true)
case *events.Disconnected: case *events.Disconnected:
logger.WarnC("whatsmeow", "WhatsApp disconnected") logger.WarnC("whatsmeow", "WhatsApp disconnected")
c.setRunning(false)
case *events.LoggedOut: case *events.LoggedOut:
logger.ErrorCF("whatsmeow", "WhatsApp logged out", map[string]interface{}{ logger.ErrorCF("whatsmeow", "WhatsApp logged out", map[string]any{
"reason": v.Reason, "reason": v.Reason,
}) })
c.setRunning(false) c.setRunning(false)
@ -177,6 +184,16 @@ func (c *WhatsmeowChannel) handleIncomingMessage(msg *events.Message) {
// Handle media // Handle media
var mediaPaths []string var mediaPaths []string
defer func() {
for _, file := range mediaPaths {
if err := os.Remove(file); err != nil {
logger.DebugCF("whatsmeow", "Failed to cleanup temp file", map[string]any{
"file": file,
"error": err.Error(),
})
}
}
}()
if img := msg.Message.GetImageMessage(); img != nil { if img := msg.Message.GetImageMessage(); img != nil {
if path, err := c.downloadMedia(img, ".jpg"); err == nil { if path, err := c.downloadMedia(img, ".jpg"); err == nil {
@ -225,11 +242,11 @@ func (c *WhatsmeowChannel) handleIncomingMessage(msg *events.Message) {
metadata["peer_kind"] = "group" metadata["peer_kind"] = "group"
metadata["peer_id"] = msg.Info.Chat.User metadata["peer_id"] = msg.Info.Chat.User
} else { } else {
metadata["peer_kind"] = "dm" metadata["peer_kind"] = "direct"
metadata["peer_id"] = msg.Info.Sender.User metadata["peer_id"] = msg.Info.Sender.User
} }
logger.InfoCF("whatsmeow", "Message received", map[string]interface{}{ logger.InfoCF("whatsmeow", "Message received", map[string]any{
"sender": senderID, "sender": senderID,
"chat": chatID, "chat": chatID,
"len": len(content), "len": len(content),
@ -250,21 +267,21 @@ func (c *WhatsmeowChannel) downloadMedia(msg whatsmeow.DownloadableMessage, ext
data, err := client.Download(c.ctx, msg) data, err := client.Download(c.ctx, msg)
if err != nil { if err != nil {
logger.ErrorCF("whatsmeow", "Failed to download media", map[string]interface{}{ logger.ErrorCF("whatsmeow", "Failed to download media", map[string]any{
"error": err.Error(), "error": err.Error(),
}) })
return "", err return "", err
} }
dir := filepath.Join(os.TempDir(), "picoclaw_media") dir := filepath.Join(os.TempDir(), "picoclaw_media")
if err := os.MkdirAll(dir, 0700); err != nil { if err := os.MkdirAll(dir, 0o700); err != nil {
return "", err return "", err
} }
filename := fmt.Sprintf("wa_%d%s", time.Now().UnixNano(), ext) filename := fmt.Sprintf("wa_%d%s", time.Now().UnixNano(), ext)
path := filepath.Join(dir, filename) path := filepath.Join(dir, filename)
if err := os.WriteFile(path, data, 0600); err != nil { if err := os.WriteFile(path, data, 0o600); err != nil {
return "", err return "", err
} }

View file

@ -13,7 +13,6 @@ import (
"go.mau.fi/whatsmeow/store/sqlstore" "go.mau.fi/whatsmeow/store/sqlstore"
"go.mau.fi/whatsmeow/types/events" "go.mau.fi/whatsmeow/types/events"
waLog "go.mau.fi/whatsmeow/util/log" waLog "go.mau.fi/whatsmeow/util/log"
_ "modernc.org/sqlite" _ "modernc.org/sqlite"
) )
@ -23,12 +22,17 @@ func LinkWhatsmeow(dbPath string, mode string) error {
dbPath = expandHomePath(dbPath) dbPath = expandHomePath(dbPath)
ctx := context.Background() ctx := context.Background()
if err := os.MkdirAll(filepath.Dir(dbPath), 0755); err != nil { if err := os.MkdirAll(filepath.Dir(dbPath), 0o755); err != nil {
return fmt.Errorf("failed to create db directory: %w", err) return fmt.Errorf("failed to create db directory: %w", err)
} }
dbLog := waLog.Noop dbLog := waLog.Noop
container, err := sqlstore.New(ctx, "sqlite", fmt.Sprintf("file:%s?_pragma=foreign_keys(1)&_pragma=journal_mode(WAL)", dbPath), dbLog) container, err := sqlstore.New(
ctx,
"sqlite",
fmt.Sprintf("file:%s?_pragma=foreign_keys(1)&_pragma=journal_mode(WAL)", dbPath),
dbLog,
)
if err != nil { if err != nil {
return fmt.Errorf("failed to open whatsmeow db: %w", err) return fmt.Errorf("failed to open whatsmeow db: %w", err)
} }
@ -49,7 +53,7 @@ func LinkWhatsmeow(dbPath string, mode string) error {
// Listen for Connected event to know when initial sync is done // Listen for Connected event to know when initial sync is done
connected := make(chan struct{}, 1) connected := make(chan struct{}, 1)
client.AddEventHandler(func(evt interface{}) { client.AddEventHandler(func(evt any) {
switch evt.(type) { switch evt.(type) {
case *events.Connected: case *events.Connected:
select { select {
@ -120,7 +124,12 @@ func WhatsmeowStatus(dbPath string) error {
} }
ctx := context.Background() ctx := context.Background()
container, err := sqlstore.New(ctx, "sqlite", fmt.Sprintf("file:%s?_pragma=foreign_keys(1)&_pragma=journal_mode(WAL)", dbPath), waLog.Noop) container, err := sqlstore.New(
ctx,
"sqlite",
fmt.Sprintf("file:%s?_pragma=foreign_keys(1)&_pragma=journal_mode(WAL)", dbPath),
waLog.Noop,
)
if err != nil { if err != nil {
return fmt.Errorf("failed to open db: %w", err) return fmt.Errorf("failed to open db: %w", err)
} }