You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
176 lines
4.3 KiB
176 lines
4.3 KiB
package whatsapp
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
|
|
_ "github.com/mattn/go-sqlite3"
|
|
qrCode "github.com/skip2/go-qrcode"
|
|
"google.golang.org/protobuf/proto"
|
|
|
|
"go.mau.fi/whatsmeow"
|
|
waproto "go.mau.fi/whatsmeow/binary/proto"
|
|
"go.mau.fi/whatsmeow/store"
|
|
"go.mau.fi/whatsmeow/store/sqlstore"
|
|
"go.mau.fi/whatsmeow/types"
|
|
)
|
|
|
|
var WhatsAppClient = make(map[string]*whatsmeow.Client)
|
|
|
|
func WhatsAppInit(jid string) (*whatsmeow.Client, error) {
|
|
// Prepare SQLite Database File and Connection Address
|
|
dbFileName := "dbs/" + jid + ".db"
|
|
dbAddress := fmt.Sprintf("file:%s?_foreign_keys=on", dbFileName)
|
|
|
|
// Create and Connect to SQLite Database
|
|
datastore, err := sqlstore.New("sqlite3", dbAddress, nil)
|
|
if err != nil {
|
|
return nil, errors.New("Failed to Connect SQLite Database")
|
|
}
|
|
|
|
// Get First WhatsApp Device from SQLite Database
|
|
device, err := datastore.GetFirstDevice()
|
|
if err != nil {
|
|
return nil, errors.New("Failed to Load WhatsApp Device")
|
|
}
|
|
|
|
// Set Client Properties
|
|
store.CompanionProps.Os = proto.String("Go WhatsApp MultiDevice REST")
|
|
store.CompanionProps.PlatformType = waproto.CompanionProps_DESKTOP.Enum()
|
|
|
|
// Create New Client Connection
|
|
client := whatsmeow.NewClient(device, nil)
|
|
|
|
// Return Client Connection
|
|
return client, nil
|
|
}
|
|
|
|
func WhatAppConnect(jid string) error {
|
|
if WhatsAppClient[jid] == nil {
|
|
// Initialize New WhatsApp Client
|
|
client, err := WhatsAppInit(jid)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Set Created WhatsApp Client to Map
|
|
WhatsAppClient[jid] = client
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func WhatsAppGenerateQR(qrChan <-chan whatsmeow.QRChannelItem) (string, string) {
|
|
qrChanCode := make(chan string)
|
|
qrChanTimeout := make(chan string)
|
|
qrChanBase64 := make(chan string)
|
|
|
|
// Get QR Code Data and Timeout
|
|
go func() {
|
|
for evt := range qrChan {
|
|
if evt.Event == "code" {
|
|
qrChanCode <- evt.Code
|
|
qrChanTimeout <- evt.Timeout.String()
|
|
}
|
|
}
|
|
}()
|
|
|
|
// Generate QR Code Data to PNG Base64 Format
|
|
go func() {
|
|
select {
|
|
case tmp := <-qrChanCode:
|
|
png, _ := qrCode.Encode(tmp, qrCode.Medium, 256)
|
|
qrChanBase64 <- base64.StdEncoding.EncodeToString(png)
|
|
}
|
|
}()
|
|
|
|
// Return QR Code and Timeout Information
|
|
return <-qrChanBase64, <-qrChanTimeout
|
|
}
|
|
|
|
func WhatsAppLogin(jid string) (string, string, error) {
|
|
if WhatsAppClient[jid] != nil {
|
|
// Make Sure WebSocket Connection is Disconnected
|
|
WhatsAppClient[jid].Disconnect()
|
|
|
|
if WhatsAppClient[jid].Store.ID == nil {
|
|
// Device ID is not Exist
|
|
// Generate QR Code
|
|
qrChanGenerate, _ := WhatsAppClient[jid].GetQRChannel(context.Background())
|
|
|
|
// Connect WebSocket while Initialize QR Code Data to be Sent
|
|
err := WhatsAppClient[jid].Connect()
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
// Get Generated QR Code and Timeout Information
|
|
qrImage, qrTimeout := WhatsAppGenerateQR(qrChanGenerate)
|
|
|
|
// Return QR Code in Base64 Format and Timeout Information
|
|
return "data:image/png;base64," + qrImage, qrTimeout, nil
|
|
} else {
|
|
// Device ID is Exist
|
|
// Reconnect WebSocket
|
|
err := WhatsAppClient[jid].Connect()
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
}
|
|
}
|
|
|
|
// Return Error WhatsApp Client is Not Valid
|
|
return "", "", errors.New("WhatsApp Client is not Valid")
|
|
}
|
|
|
|
func WhatsAppLogout(jid string) error {
|
|
if WhatsAppClient[jid] != nil {
|
|
// Logout WhatsApp Client and Disconnect from WebSocket
|
|
err := WhatsAppClient[jid].Logout()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Remove SQLite Database File
|
|
_ = os.Remove("dbs/" + jid + ".db")
|
|
|
|
// Free WhatsApp Client Map
|
|
WhatsAppClient[jid] = nil
|
|
delete(WhatsAppClient, jid)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Return Error WhatsApp Client is Not Valid
|
|
return errors.New("WhatsApp Client is not Valid")
|
|
}
|
|
|
|
func WhatsAppCreateUserJID(jid string) types.JID {
|
|
return types.NewJID(jid, types.DefaultUserServer)
|
|
}
|
|
|
|
func WhatsAppCreateGroupJID(gjid string) types.JID {
|
|
return types.NewJID(gjid, types.GroupServer)
|
|
}
|
|
|
|
func WhatsAppSendText(jid string, rjid string, message string) error {
|
|
if WhatsAppClient[jid] != nil {
|
|
if WhatsAppClient[jid].IsConnected() && WhatsAppClient[jid].IsLoggedIn() {
|
|
_, err := WhatsAppClient[jid].SendMessage(WhatsAppCreateUserJID(rjid), "", &waproto.Message{
|
|
Conversation: proto.String(message),
|
|
})
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Return Error WhatsApp Client is Not Valid
|
|
return errors.New("WhatsApp Client is not Valid")
|
|
}
|