Browse Source

feat: trigger when pair success

pull/33/head
Aldino Kemal 3 years ago
parent
commit
280a9b09f0
  1. 53
      src/cmd/root.go
  2. 1
      src/config/settings.go
  3. 13
      src/internal/rest/helpers/common.go
  4. 45
      src/internal/rest/helpers/websocket.go
  5. 5
      src/services/app_service.go
  6. 14
      src/utils/whatsapp.go
  7. 27
      src/views/index.html

53
src/cmd/root.go

@ -2,7 +2,6 @@ package cmd
import ( import (
"encoding/base64" "encoding/base64"
"encoding/json"
"fmt" "fmt"
"github.com/aldinokemal/go-whatsapp-web-multidevice/config" "github.com/aldinokemal/go-whatsapp-web-multidevice/config"
"github.com/aldinokemal/go-whatsapp-web-multidevice/internal/rest" "github.com/aldinokemal/go-whatsapp-web-multidevice/internal/rest"
@ -16,16 +15,12 @@ import (
"github.com/gofiber/fiber/v2/middleware/cors" "github.com/gofiber/fiber/v2/middleware/cors"
"github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/fiber/v2/middleware/logger"
"github.com/gofiber/template/html" "github.com/gofiber/template/html"
"github.com/gofiber/websocket/v2"
"github.com/markbates/pkger" "github.com/markbates/pkger"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
"github.com/spf13/cobra"
"log" "log"
"net/http"
"os" "os"
"strings" "strings"
"time"
"github.com/spf13/cobra"
) )
// rootCmd represents the base command when called without any subcommands // rootCmd represents the base command when called without any subcommands
@ -107,59 +102,17 @@ func runRest(_ *cobra.Command, _ []string) {
return ctx.Render("index", fiber.Map{ return ctx.Render("index", fiber.Map{
"AppHost": fmt.Sprintf("%s://%s", ctx.Protocol(), ctx.Hostname()), "AppHost": fmt.Sprintf("%s://%s", ctx.Protocol(), ctx.Hostname()),
"AppVersion": config.AppVersion, "AppVersion": config.AppVersion,
"QRRefreshSeconds": config.AppRefreshQRCodeSeconds * 1000,
"BasicAuthToken": base64.StdEncoding.EncodeToString([]byte(config.AppBasicAuthCredential)), "BasicAuthToken": base64.StdEncoding.EncodeToString([]byte(config.AppBasicAuthCredential)),
"MaxFileSize": humanize.Bytes(uint64(config.WhatsappSettingMaxFileSize)), "MaxFileSize": humanize.Bytes(uint64(config.WhatsappSettingMaxFileSize)),
"MaxVideoSize": humanize.Bytes(uint64(config.WhatsappSettingMaxVideoSize)), "MaxVideoSize": humanize.Bytes(uint64(config.WhatsappSettingMaxVideoSize)),
}) })
}) })
app.Use("/ws", func(c *fiber.Ctx) error {
if websocket.IsWebSocketUpgrade(c) { // Returns true if the client requested upgrade to the WebSocket protocol
return c.Next()
}
return c.SendStatus(fiber.StatusUpgradeRequired)
})
helpers.WsRegisterRoutes(app, cli)
go helpers.WsRunHub() go helpers.WsRunHub()
app.Get("/ws", websocket.New(func(c *websocket.Conn) {
// When the function returns, unregister the client and close the connection
defer func() {
helpers.WsUnregister <- c
c.Close()
}()
// Register the client
helpers.WsRegister <- c
for {
messageType, message, err := c.ReadMessage()
if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
log.Println("read error:", err)
}
return // Calls the deferred function, i.e. closes the connection on error
}
if messageType == websocket.TextMessage {
// Broadcast the received message
var messageData helpers.WsBroadcastMessage
err := json.Unmarshal(message, &messageData)
if err != nil {
log.Println("error unmarshal message:", err)
return
}
helpers.WsBroadcast <- messageData
} else {
log.Println("websocket message received of type", messageType)
}
}
}))
// Set auto reconnect to whatsapp server after booting // Set auto reconnect to whatsapp server after booting
go func() {
time.Sleep(2 * time.Second)
_, _ = http.Get(fmt.Sprintf("http://localhost:%s/app/reconnect", config.AppPort))
}()
go helpers.SetAutoConnectAfterBooting()
err = app.Listen(":" + config.AppPort) err = app.Listen(":" + config.AppPort)
if err != nil { if err != nil {
log.Fatalln("Failed to start: ", err.Error()) log.Fatalln("Failed to start: ", err.Error())

1
src/config/settings.go

@ -14,7 +14,6 @@ var (
AppSelectedDeviceKey = "deviceID" AppSelectedDeviceKey = "deviceID"
AppDefaultDevice = "default" AppDefaultDevice = "default"
AppBasicAuthCredential string AppBasicAuthCredential string
AppRefreshQRCodeSeconds = 10
PathQrCode = "statics/qrcode" PathQrCode = "statics/qrcode"
PathSendItems = "statics/senditems" PathSendItems = "statics/senditems"

13
src/internal/rest/helpers/common.go

@ -0,0 +1,13 @@
package helpers
import (
"fmt"
"github.com/aldinokemal/go-whatsapp-web-multidevice/config"
"net/http"
"time"
)
func SetAutoConnectAfterBooting() {
time.Sleep(2 * time.Second)
_, _ = http.Get(fmt.Sprintf("http://localhost:%s/app/reconnect", config.AppPort))
}

45
src/internal/rest/helpers/websocket.go

@ -2,7 +2,9 @@ package helpers
import ( import (
"encoding/json" "encoding/json"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/websocket/v2" "github.com/gofiber/websocket/v2"
"go.mau.fi/whatsmeow"
"log" "log"
) )
@ -59,3 +61,46 @@ func WsRunHub() {
} }
} }
} }
func WsRegisterRoutes(app *fiber.App, cli *whatsmeow.Client) {
app.Use("/ws", func(c *fiber.Ctx) error {
if websocket.IsWebSocketUpgrade(c) { // Returns true if the client requested upgrade to the WebSocket protocol
return c.Next()
}
return c.SendStatus(fiber.StatusUpgradeRequired)
})
app.Get("/ws", websocket.New(func(c *websocket.Conn) {
// When the function returns, unregister the client and close the connection
defer func() {
WsUnregister <- c
_ = c.Close()
}()
// Register the client
WsRegister <- c
for {
messageType, message, err := c.ReadMessage()
if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
log.Println("read error:", err)
}
return // Calls the deferred function, i.e. closes the connection on error
}
if messageType == websocket.TextMessage {
// Broadcast the received message
var messageData WsBroadcastMessage
err := json.Unmarshal(message, &messageData)
if err != nil {
log.Println("error unmarshal message:", err)
return
}
WsBroadcast <- messageData
} else {
log.Println("websocket message received of type", messageType)
}
}
}))
}

5
src/services/app_service.go

@ -6,7 +6,6 @@ import (
"fmt" "fmt"
"github.com/aldinokemal/go-whatsapp-web-multidevice/config" "github.com/aldinokemal/go-whatsapp-web-multidevice/config"
domainApp "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/app" domainApp "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/app"
"github.com/aldinokemal/go-whatsapp-web-multidevice/utils"
fiberUtils "github.com/gofiber/fiber/v2/utils" fiberUtils "github.com/gofiber/fiber/v2/utils"
"github.com/skip2/go-qrcode" "github.com/skip2/go-qrcode"
"go.mau.fi/whatsmeow" "go.mau.fi/whatsmeow"
@ -82,10 +81,6 @@ func (service serviceApp) Login(_ context.Context) (response domainApp.LoginResp
} }
response.ImagePath = <-chImage response.ImagePath = <-chImage
// Set in event
utils.LoginTime = time.Now()
utils.LoginIsNotified = false
return response, nil return response, nil
} }

14
src/utils/whatsapp.go

@ -28,8 +28,6 @@ var (
cli *whatsmeow.Client cli *whatsmeow.Client
log waLog.Logger log waLog.Logger
historySyncID int32 historySyncID int32
LoginTime time.Time
LoginIsNotified bool
startupTime = time.Now().Unix() startupTime = time.Now().Unix()
) )
@ -137,16 +135,14 @@ func handler(rawEvt interface{}) {
log.Infof("Marked self as available") log.Infof("Marked self as available")
} }
} }
case *events.Connected, *events.PushNameSetting:
if len(cli.Store.PushName) == 0 {
return
}
if cli.LastSuccessfulConnect.Before(LoginTime.Add(time.Duration(config.AppRefreshQRCodeSeconds)*time.Second)) && !LoginIsNotified {
LoginIsNotified = true
case *events.PairSuccess:
helpers.WsBroadcast <- helpers.WsBroadcastMessage{ helpers.WsBroadcast <- helpers.WsBroadcastMessage{
Code: "LOGIN_SUCCESS", Code: "LOGIN_SUCCESS",
Message: "Login Success",
Message: fmt.Sprintf("Successfully pair with %s", evt.ID.String()),
} }
case *events.Connected, *events.PushNameSetting:
if len(cli.Store.PushName) == 0 {
return
} }
// Send presence available when connecting and when the pushname is changed. // Send presence available when connecting and when the pushname is changed.

27
src/views/index.html

@ -228,12 +228,15 @@
<div class="description"> <div class="description">
<div class="ui header">Please scan to connect</div> <div class="ui header">Please scan to connect</div>
<p>Open Setting > Linked Devices > Link Device</p> <p>Open Setting > Linked Devices > Link Device</p>
<div style="padding-top: 50px;">
<i>Refresh QR Code in [[ login_duration_sec ]] seconds to avoid link expiration</i>
</div>
</div> </div>
</div> </div>
<div class="actions"> <div class="actions">
<div class="ui positive right labeled icon button">
Done
<i class="checkmark icon"></i>
<div class="ui approve positive right labeled icon button" @click="loginApiGetQrCode">
Refresh QR Code
<i class="refresh icon"></i>
</div> </div>
</div> </div>
</div> </div>
@ -583,10 +586,11 @@
async loginModal() { async loginModal() {
try { try {
await this.loginApiGetQrCode(); await this.loginApiGetQrCode();
$('#modalLogin').modal('show');
this.autoUpdateQRCode = setInterval(async () => {
await this.loginApiGetQrCode();
}, {{.QRRefreshSeconds}} );
$('#modalLogin').modal({
onApprove: function () {
return false;
}
}).modal('show');
} catch (err) { } catch (err) {
showErrorInfo(err) showErrorInfo(err)
} }
@ -1113,13 +1117,18 @@
if (window["WebSocket"]) { if (window["WebSocket"]) {
let wsType = location.protocol !== 'https:' ? 'ws://' : 'wss://'; let wsType = location.protocol !== 'https:' ? 'ws://' : 'wss://';
let conn = new WebSocket(wsType + document.location.host + "/ws"); let conn = new WebSocket(wsType + document.location.host + "/ws");
conn.onmessage = function (evt) {
conn.onclose = (evt) => {
console.log(evt)
};
conn.onmessage = (evt) => {
console.log(evt)
const message = JSON.parse(evt.data) const message = JSON.parse(evt.data)
switch (message.code) { switch (message.code) {
case 'LOGIN_SUCCESS': case 'LOGIN_SUCCESS':
showSuccessInfo(message.message) showSuccessInfo(message.message)
$('#modalLogin').modal('hide'); $('#modalLogin').modal('hide');
location.reload()
break; break;
default: default:
console.log(message) console.log(message)

Loading…
Cancel
Save