@@ -363,6 +363,10 @@ func parseJID(arg string) (types.JID, bool) {
363363func (s * server ) startClient (userID string , textjid string , token string , subscriptions []string ) {
364364 log .Info ().Str ("userid" , userID ).Str ("jid" , textjid ).Msg ("Starting websocket connection to Whatsapp" )
365365
366+ // Connection retry constants
367+ const maxConnectionRetries = 3
368+ const connectionRetryBaseWait = 5 * time .Second
369+
366370 var deviceStore * store.Device
367371 var err error
368372
@@ -396,25 +400,14 @@ func (s *server) startClient(userID string, textjid string, token string, subscr
396400
397401 // Now we can use the client with the manager
398402 clientManager .SetWhatsmeowClient (userID , client )
399- if textjid != "" {
400- jid , _ := parseJID (textjid )
401- deviceStore , err = container .GetDevice (context .Background (), jid )
402- if err != nil {
403- panic (err )
404- }
405- } else {
406- log .Warn ().Msg ("No jid found. Creating new device" )
407- deviceStore = container .NewDevice ()
408- }
409403
410404 store .DeviceProps .PlatformType = waCompanionReg .DeviceProps_UNKNOWN .Enum ()
411405 store .DeviceProps .Os = osName
412406
413- clientManager .SetWhatsmeowClient (userID , client )
414407 mycli := MyClient {client , 1 , userID , token , subscriptions , s .db , s }
415408 mycli .eventHandlerID = mycli .WAClient .AddEventHandler (mycli .myEventHandler )
416409
417- // CORREÇÃO: Armazenar o MyClient no clientManager
410+ // Store the MyClient in clientManager
418411 clientManager .SetMyClient (userID , & mycli )
419412
420413 httpClient := resty .New ()
@@ -433,32 +426,32 @@ func (s *server) startClient(userID string, textjid string, token string, subscr
433426 }
434427 })
435428
436- // NEW: set proxy if defined in DB (assumes users table contains proxy_url column)
429+ // Set proxy if defined in DB (assumes users table contains proxy_url column)
437430 var proxyURL string
438431 err = s .db .Get (& proxyURL , "SELECT proxy_url FROM users WHERE id=$1" , userID )
439432 if err == nil && proxyURL != "" {
440-
441433 parsed , perr := url .Parse (proxyURL )
442434 if perr != nil {
443435 log .Warn ().Err (perr ).Str ("proxy" , proxyURL ).Msg ("Invalid proxy URL, skipping proxy setup" )
444436 } else {
437+
438+ log .Info ().Str ("proxy" , proxyURL ).Msg ("Configuring proxy" )
439+
445440 if parsed .Scheme == "socks5" || parsed .Scheme == "socks5h" {
446- // Build SOCKS dialer from URL (supports user:pass in URL)
447441 dialer , derr := proxy .FromURL (parsed , nil )
448442 if derr != nil {
449443 log .Warn ().Err (derr ).Str ("proxy" , proxyURL ).Msg ("Failed to build SOCKS proxy dialer, skipping proxy setup" )
450444 } else {
451- // Apply proxy to both clients now that we know it's valid.
452445 httpClient .SetProxy (proxyURL )
453446 client .SetSOCKSProxy (dialer , whatsmeow.SetProxyOptions {})
447+ log .Info ().Msg ("SOCKS proxy configured successfully" )
454448 }
455449 } else {
456- // For http/https, apply to both clients.
457450 httpClient .SetProxy (proxyURL )
458451 client .SetProxyAddress (parsed .String (), whatsmeow.SetProxyOptions {})
452+ log .Info ().Msg ("HTTP/HTTPS proxy configured successfully" )
459453 }
460454 }
461-
462455 }
463456 clientManager .SetHTTPClient (userID , httpClient )
464457
@@ -472,7 +465,7 @@ func (s *server) startClient(userID string, textjid string, token string, subscr
472465 return
473466 }
474467 } else {
475- err = client .Connect () // Si no conectamos no se puede generar QR
468+ err = client .Connect () // Must connect to generate QR code
476469 if err != nil {
477470 log .Error ().Err (err ).Msg ("Failed to connect client" )
478471 return
@@ -555,9 +548,64 @@ func (s *server) startClient(userID string, textjid string, token string, subscr
555548 } else {
556549 // Already logged in, just connect
557550 log .Info ().Msg ("Already logged in, just connect" )
558- err = client .Connect ()
559- if err != nil {
560- panic (err )
551+
552+ // Retry logic with linear backoff
553+ var lastErr error
554+
555+ for attempt := 0 ; attempt < maxConnectionRetries ; attempt ++ {
556+ if attempt > 0 {
557+ waitTime := time .Duration (attempt ) * connectionRetryBaseWait
558+ log .Warn ().
559+ Int ("attempt" , attempt + 1 ).
560+ Int ("max_retries" , maxConnectionRetries ).
561+ Dur ("wait_time" , waitTime ).
562+ Msg ("Retrying connection after delay" )
563+ time .Sleep (waitTime )
564+ }
565+
566+ err = client .Connect ()
567+ if err == nil {
568+ log .Info ().
569+ Int ("attempt" , attempt + 1 ).
570+ Msg ("Successfully connected to WhatsApp" )
571+ break
572+ }
573+
574+ lastErr = err
575+ log .Warn ().
576+ Err (err ).
577+ Int ("attempt" , attempt + 1 ).
578+ Int ("max_retries" , maxConnectionRetries ).
579+ Msg ("Failed to connect to WhatsApp" )
580+ }
581+
582+ if lastErr != nil {
583+ log .Error ().
584+ Err (lastErr ).
585+ Str ("userid" , userID ).
586+ Int ("attempts" , maxConnectionRetries ).
587+ Msg ("Failed to connect to WhatsApp after all retry attempts" )
588+
589+ clientManager .DeleteWhatsmeowClient (userID )
590+ clientManager .DeleteMyClient (userID )
591+ clientManager .DeleteHTTPClient (userID )
592+
593+ sqlStmt := `UPDATE users SET qrcode='', connected=0 WHERE id=$1`
594+ _ , dbErr := s .db .Exec (sqlStmt , userID )
595+ if dbErr != nil {
596+ log .Error ().Err (dbErr ).Msg ("Failed to update user status after connection error" )
597+ }
598+
599+ // Use the existing mycli instance from outer scope
600+ postmap := make (map [string ]interface {})
601+ postmap ["event" ] = "ConnectFailure"
602+ postmap ["error" ] = lastErr .Error ()
603+ postmap ["type" ] = "ConnectFailure"
604+ postmap ["attempts" ] = maxConnectionRetries
605+ postmap ["reason" ] = "Failed to connect after retry attempts"
606+ sendEventWithWebHook (& mycli , postmap , "" )
607+
608+ return
561609 }
562610 }
563611
0 commit comments