Skip to content

Commit

Permalink
Whatsapp BUILD Completed
Browse files Browse the repository at this point in the history
  • Loading branch information
keyurboss committed Apr 20, 2024
1 parent 1282ab4 commit 8bd67a2
Show file tree
Hide file tree
Showing 12 changed files with 179 additions and 44 deletions.
3 changes: 2 additions & 1 deletion .env_template
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ APP_ENV="LOCAL"
# "LOCAL" || "PRODUCTION" || "CI"
PORT="4000"
ALLOW_LOCAL_NO_AUTH="true"
DO_NOT_AUTO_CONNECT_TO_WHATSAPP="true"
AUTO_CONNECT_TO_WHATSAPP="true"
OPEN_BROWSER_FOR_SCAN="true"
18 changes: 7 additions & 11 deletions apis/index.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package apis

import (
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
Expand All @@ -11,6 +12,7 @@ import (
"github.com/rpsoftech/whatsapp-http-api/middleware"
"github.com/rpsoftech/whatsapp-http-api/utility"
"github.com/rpsoftech/whatsapp-http-api/whatsapp"
"github.com/skip2/go-qrcode"
)

type (
Expand All @@ -36,16 +38,6 @@ func AddApis(app fiber.Router) {
}
}

func QrScan(c *fiber.Ctx) error {
id := c.Params("id")
if id == "" {
return c.SendStatus(http.StatusBadRequest)
}
return c.JSON(fiber.Map{
id: id,
})
}

func SendMediaFile(c *fiber.Ctx) error {
body := new(apiSendMessage)
c.BodyParser(body)
Expand Down Expand Up @@ -231,6 +223,7 @@ func GetQrCode(c *fiber.Ctx) error {
if err != nil {
return err
}

connection, ok := whatsapp.ConnectionMap[number]
if !ok || connection == nil {
return &interfaces.RequestError{
Expand All @@ -241,9 +234,12 @@ func GetQrCode(c *fiber.Ctx) error {
}
}
err = connection.ReturnStatusError()

if err != nil {
png, _ := qrcode.Encode(connection.QrCodeString, qrcode.High, 512)
return c.JSON(fiber.Map{
"qrCode": connection.QrCodeString,
"qrCode": base64.StdEncoding.EncodeToString(png),
"qrCodeData": connection.QrCodeString,
})
}
return c.JSON(fiber.Map{
Expand Down
65 changes: 65 additions & 0 deletions apis/qr-browser.api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package apis

import (
"fmt"

"github.com/gofiber/fiber/v2"
)

const index = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>QR Code Scanner For</title>
</head>
<body>
<h1>Scan The QR Code to Log into whatsapp web account</h1>
<img height="512" width="512" />
<script>
// get host url for api calling
const id = "%s";
// const url = window.location.href
const url = ` + "`${window.location.protocol}//${window.location.host}/v1/qr_code/`;" +
` function hexToBase64(str) {
return btoa(
String.fromCharCode.apply(
null,
str
.replace(/\r|\n/g, '')
.replace(/([\da-fA-F]{2}) ?/g, '0x$1 ')
.replace(/ +$/, '')
.split(' ')
)
);
}
async function CallAPIAndSetImage() {
const res = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'X-Api-Token': id,
},
});
try {
const data = await res.json();
if(data.qrCode){
const img = document.querySelector('img');
img.src = 'data:image/png;base64,' + data.qrCode;
}
} catch (error) {}
}
CallAPIAndSetImage();
setInterval(() => CallAPIAndSetImage(), 5000);
// const img = document.querySelector('img')
// const url = window.location.href
</script>
</body>
</html>`

func OpenBrowserWithQr(c *fiber.Ctx) error {
id := c.Params("id")
// println(c.Hostname())
c.Set("Content-Type", "text/html; charset=utf-8")
return c.Send([]byte(fmt.Sprintf(index, id)))
}
24 changes: 15 additions & 9 deletions env/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ import (

type (
EnvInterface struct {
APP_ENV AppEnv `json:"APP_ENV" validate:"required,enum=AppEnv"`
PORT int `json:"PORT" validate:"required,port"`
ALLOW_LOCAL_NO_AUTH bool `json:"ALLOW_LOCAL_NO_AUTH" validate:"boolean"`
DO_NOT_AUTO_CONNECT_TO_WHATSAPP bool `json:"DO_NOT_AUTO_CONNECT_TO_WHATSAPP" validate:"boolean"`
APP_ENV AppEnv `json:"APP_ENV" validate:"required,enum=AppEnv"`
PORT int `json:"PORT" validate:"required,port"`
ALLOW_LOCAL_NO_AUTH bool `json:"ALLOW_LOCAL_NO_AUTH" validate:"boolean"`
AUTO_CONNECT_TO_WHATSAPP bool `json:"AUTO_CONNECT_TO_WHATSAPP" validate:"boolean"`
OPEN_BROWSER_FOR_SCAN bool `json:"OPEN_BROWSER_FOR_SCAN" validate:"boolean"`
// DB_URL string `json:"DB_URL" validate:"required,url"`
// DB_NAME string `json:"DB_NAME_KEY" validate:"required,min=3"`
// REDIS_DB_HOST string `json:"REDIS_DB_HOST" validate:"required"`
Expand Down Expand Up @@ -56,16 +57,21 @@ func init() {
log.Fatal(err)
}

do_not_auto_connect_to_whatsapp, err := strconv.ParseBool(os.Getenv(do_Not_Auto_Connect_To_Whatsapp_KEY))
auto_connect_to_whatsapp, err := strconv.ParseBool(os.Getenv(Auto_Connect_To_Whatsapp_KEY))
if err != nil {
log.Fatal(err)
}
open_browser_for_scan_KEY, err := strconv.ParseBool(os.Getenv(open_browser_for_scan_KEY))
if err != nil {
log.Fatal(err)
}

Env = &EnvInterface{
APP_ENV: appEnv,
PORT: PORT,
ALLOW_LOCAL_NO_AUTH: allow_local_no_Auth,
DO_NOT_AUTO_CONNECT_TO_WHATSAPP: do_not_auto_connect_to_whatsapp,
APP_ENV: appEnv,
PORT: PORT,
ALLOW_LOCAL_NO_AUTH: allow_local_no_Auth,
AUTO_CONNECT_TO_WHATSAPP: auto_connect_to_whatsapp,
OPEN_BROWSER_FOR_SCAN: open_browser_for_scan_KEY,
}
errs := validator.Validator.Validate(Env)
if len(errs) > 0 {
Expand Down
3 changes: 2 additions & 1 deletion env/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package env
const app_ENV_KEY = "APP_ENV"
const port_KEY = "PORT"
const allow_local_no_auth_KEY = "ALLOW_LOCAL_NO_AUTH"
const do_Not_Auto_Connect_To_Whatsapp_KEY = "DO_NOT_AUTO_CONNECT_TO_WHATSAPP"
const Auto_Connect_To_Whatsapp_KEY = "AUTO_CONNECT_TO_WHATSAPP"
const open_browser_for_scan_KEY = "OPEN_BROWSER_FOR_SCAN"

// const db_URL_KEY = "DB_URL"
// const db_NAME_KEY = "DB_NAME"
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ require (
github.com/rs/zerolog v1.32.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
github.com/swaggo/swag v1.16.3 // indirect
github.com/urfave/cli/v2 v2.27.1 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down
7 changes: 4 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,10 @@ func main() {
env.ServerConfig = ReadConfigFileAndReturnIt(env.CurrentDirectory)
whatsapp.OutPutFilePath = ReturnOutPutFilePath(env.CurrentDirectory)
whatsapp.InitSqlContainer()
if !env.Env.DO_NOT_AUTO_CONNECT_TO_WHATSAPP {

if env.Env.AUTO_CONNECT_TO_WHATSAPP {
go func() {
for k, v := range env.ServerConfig.Tokens {
jidString := env.ServerConfig.JID[v]
jidString := env.ServerConfig.JID[k]
whatsapp.ConnectToNumber(v, jidString, k)
}
}()
Expand All @@ -71,6 +70,8 @@ func InitFiberServer() {
app.Use(logger.New())
app.Static("/swagger", "./swagger")
apis.AddApis(app.Group("/v1", middleware.TokenDecrypter, middleware.AllowOnlyValidTokenMiddleWare))

app.Get("/scan/:id", apis.OpenBrowserWithQr)
app.Use(func(c *fiber.Ctx) error {
return c.Status(fiber.StatusNotFound).SendString("Sorry can't find that!")
})
Expand Down
62 changes: 46 additions & 16 deletions qrcode-web/index.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,51 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.rawgit.com/davidshimjs/qrcodejs/gh-pages/qrcode.min.js"></script>
<title>QR Code Scanner For </title>
</head>
<body>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>QR Code Scanner For</title>
</head>
<body>
<h1>Scan The QR Code to Log into whatsapp web account</h1>
<img height="512" width="512">
<img height="512" width="512" />
<script>
// get host url for api calling
const url = window.location.href

// const img = document.querySelector('img')
// const url = window.location.href

// get host url for api calling
const id = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
// const url = window.location.href
const url = `${window.location.protocol}//${window.location.host}/v1/qr_code/`;
function hexToBase64(str) {
return btoa(
String.fromCharCode.apply(
null,
str
.replace(/\r|\n/g, '')
.replace(/([\da-fA-F]{2}) ?/g, '0x$1 ')
.replace(/ +$/, '')
.split(' ')
)
);
}
async function CallAPIAndSetImage() {
const res = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Token': id,
},
});
try {
const data = await res.json();
if(data.qrCode){
const img = document.querySelector('img');
img.src = 'data:image/png;base64,' + hexToBase64(data.qrCode);
}
} catch (error) {}
}
CallAPIAndSetImage();
setInterval(() => CallAPIAndSetImage(), 5000);

// const img = document.querySelector('img')
// const url = window.location.href
</script>
</body>
</html>
</body>
</html>
23 changes: 23 additions & 0 deletions utility/mime.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package utility

import (
"fmt"
"log"
"os/exec"
"path/filepath"
"runtime"
"strings"
)

Expand All @@ -12,3 +16,22 @@ func GetMime(fileName string) string {
fileExt = strings.Replace(fileExt, ".", "", 1)
return mimeList[fileExt]
}

func OpenBrowser(url string) {
var err error

switch runtime.GOOS {
case "linux":
err = exec.Command("xdg-open", url).Start()
case "windows":
err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
case "darwin":
err = exec.Command("open", url).Start()
default:
err = fmt.Errorf("unsupported platform")
}
if err != nil {
log.Fatal(err)
}

}
5 changes: 3 additions & 2 deletions whatsapp/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ func ConnectToNumber(number string, jidString string, token string) {
// BaseURL: "https://web.whatsapp.com",
// }
// client.PairPhone()
connection := &WhatsappConnection{Client: client, Number: number, ConnectionStatus: 0, SyncFinished: false}
ConnectionMap[number] = connection
connection := &WhatsappConnection{Client: client, Number: number, ConnectionStatus: 0, SyncFinished: false, Token: token}
ConnectionMap[token] = connection
client.AddEventHandler(connection.eventHandler)

connection.ConnectAndGetQRCode()
}
10 changes: 9 additions & 1 deletion whatsapp/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ func (connection *WhatsappConnection) ReturnStatusError() error {
func (connection *WhatsappConnection) ConnectAndGetQRCode() {
if connection.Client.Store.ID == nil {
// No ID stored, new login
if env.Env.OPEN_BROWSER_FOR_SCAN {
go func(token string) {
utility.OpenBrowser(fmt.Sprintf("http://127.0.0.1:%d/scan/%s", env.Env.PORT, token))
}(connection.Token)
}
qrChan, _ := connection.Client.GetQRChannel(context.Background())
err := connection.Client.Connect()
if err != nil {
Expand All @@ -69,7 +74,10 @@ func (connection *WhatsappConnection) ConnectAndGetQRCode() {
if evt.Event == "code" {
fmt.Printf("QR code for %s\n", connection.Token)
connection.QrCodeString = evt.Code
qrterminal.GenerateHalfBlock(evt.Code, qrterminal.L, os.Stdout)
// env.ServerConfig.Tokens[connection.Token] = "Something"
if !env.Env.OPEN_BROWSER_FOR_SCAN {
qrterminal.GenerateHalfBlock(evt.Code, qrterminal.L, os.Stdout)
}
} else {
fmt.Println("Login event:", evt.Event)
}
Expand Down

0 comments on commit 8bd67a2

Please sign in to comment.