diff --git a/.env.default b/.env.default index 7ca51af..33c9528 100644 --- a/.env.default +++ b/.env.default @@ -21,3 +21,9 @@ # AUTH_JWT_SECRET=secret # AUTH_JWT_EXPIRED_HOUR=24 + +# ----------------------------------- +# WhatsApp Configuration +# ----------------------------------- +# WHATSAPP_DB_TYPE=sqlite3 +# WHATSAPP_DB_URI=file:dbs/WhatsApp.db?_foreign_keys=on diff --git a/.env.development b/.env.development index fc59c7c..507b0d8 100644 --- a/.env.development +++ b/.env.development @@ -21,3 +21,9 @@ AUTH_BASIC_PASSWORD=83e4060e-78e1-4fe5-9977-aeeccd46a2b8 AUTH_JWT_SECRET=9e4eb4cf-be25-4a29-bba3-fefb5a30f6ab AUTH_JWT_EXPIRED_HOUR=24 + +# ----------------------------------- +# WhatsApp Configuration +# ----------------------------------- +WHATSAPP_DB_TYPE=sqlite3 +WHATSAPP_DB_URI=file:dbs/WhatsApp.db?_foreign_keys=on diff --git a/.env.production b/.env.production index 02a263a..ff18fea 100644 --- a/.env.production +++ b/.env.production @@ -21,3 +21,9 @@ AUTH_BASIC_PASSWORD=83e4060e-78e1-4fe5-9977-aeeccd46a2b8 AUTH_JWT_SECRET=9e4eb4cf-be25-4a29-bba3-fefb5a30f6ab AUTH_JWT_EXPIRED_HOUR=24 + +# ----------------------------------- +# WhatsApp Configuration +# ----------------------------------- +WHATSAPP_DB_TYPE=sqlite3 +WHATSAPP_DB_URI=file:dbs/WhatsApp.db?_foreign_keys=on diff --git a/internal/startup.go b/internal/startup.go index 3feae45..b1a3360 100644 --- a/internal/startup.go +++ b/internal/startup.go @@ -1,10 +1,6 @@ package internal import ( - "path" - "path/filepath" - "strings" - "github.com/dimaskiddo/go-whatsapp-multidevice-rest/pkg/log" pkgWhatsApp "github.com/dimaskiddo/go-whatsapp-multidevice-rest/pkg/whatsapp" ) @@ -12,18 +8,18 @@ import ( func Startup() { log.Print(nil).Info("Running Startup Tasks") - dbs, err := filepath.Glob("./dbs/*.db") + devices, err := pkgWhatsApp.WhatsAppDatastore.GetAllDevices() if err != nil { - log.Print(nil).Error("Error to Get Existing SQLite Database Files") + log.Print(nil).Error("Failed to Load WhatsApp Client Devices from Database") } - for _, db := range dbs { - jid := strings.TrimSuffix(filepath.Base(db), path.Ext(db)) + for _, device := range devices { + jid := pkgWhatsApp.WhatsAppDecomposeJID(device.ID.String()) maskJID := jid[0:len(jid)-4] + "xxxx" log.Print(nil).Info("Restoring WhatsApp Client for " + maskJID) - err := pkgWhatsApp.WhatsAppInitClient(jid) + err := pkgWhatsApp.WhatsAppInitClient(device, jid) if err != nil { log.Print(nil).Error(err.Error()) } diff --git a/internal/whatsapp/whatsapp.go b/internal/whatsapp/whatsapp.go index af23308..ff78e0e 100644 --- a/internal/whatsapp/whatsapp.go +++ b/internal/whatsapp/whatsapp.go @@ -125,7 +125,7 @@ func Login(c echo.Context) error { } // Initialize WhatsApp Client - err = pkgWhatsApp.WhatsAppInitClient(jid) + err = pkgWhatsApp.WhatsAppInitClient(nil, jid) if err != nil { return router.ResponseInternalError(c, err.Error()) } diff --git a/pkg/whatsapp/drivers.go b/pkg/whatsapp/drivers.go new file mode 100644 index 0000000..fe49e76 --- /dev/null +++ b/pkg/whatsapp/drivers.go @@ -0,0 +1,5 @@ +package whatsapp + +import ( + _ "github.com/mattn/go-sqlite3" +) diff --git a/pkg/whatsapp/whatsapp.go b/pkg/whatsapp/whatsapp.go index 26bfaa9..03fa8fc 100644 --- a/pkg/whatsapp/whatsapp.go +++ b/pkg/whatsapp/whatsapp.go @@ -4,10 +4,8 @@ import ( "context" "encoding/base64" "errors" - "fmt" "strings" - _ "github.com/mattn/go-sqlite3" qrCode "github.com/skip2/go-qrcode" "google.golang.org/protobuf/proto" @@ -16,66 +14,53 @@ import ( "go.mau.fi/whatsmeow/store" "go.mau.fi/whatsmeow/store/sqlstore" "go.mau.fi/whatsmeow/types" + + "github.com/dimaskiddo/go-whatsapp-multidevice-rest/pkg/env" + "github.com/dimaskiddo/go-whatsapp-multidevice-rest/pkg/log" ) +var WhatsAppDatastore *sqlstore.Container var WhatsAppClient = make(map[string]*whatsmeow.Client) -func WhatsAppDB(dbType string) (*sqlstore.Container, error) { - var dbName, dbURI string +func init() { + WhatsAppInitDB() +} - switch dbType { - case "sqlite3": - // Prepare SQLite Database and Connection URI - dbName = "dbs/WhatsApp.db" - dbURI = fmt.Sprintf("file:%s?_foreign_keys=on", dbName) +func WhatsAppInitDB() { + var err error - default: - return nil, errors.New("Unknown WhstaApp Client Database Type") - } - - // Create and Connect to Database - datastore, err := sqlstore.New(dbType, dbURI, nil) + dbType, err := env.GetEnvString("WHATSAPP_DB_TYPE") if err != nil { - return nil, errors.New("Failed to Connect WhatsApp Client Database") + log.Print(nil).Fatal("Error Parse Environment Variable for WhatsApp Client Datastore Type") } - return datastore, nil -} - -func WhatsAppInitDB(jid string) (*whatsmeow.Client, error) { - // Connect to WhatsApp Client Datastore - datastore, err := WhatsAppDB("sqlite3") + dbURI, err := env.GetEnvString("WHATSAPP_DB_URI") if err != nil { - return nil, err + log.Print(nil).Fatal("Error Parse Environment Variable for WhatsApp Client Datastore URI") } - // Get WhatsApp Device Based on JID from Datastore - device, err := datastore.GetDevice(WhatsAppComposeJID(jid)) + datastore, err := sqlstore.New(dbType, dbURI, nil) if err != nil { - return nil, errors.New("Failed to Load WhatsApp Client Device from Database") + log.Print(nil).Fatal("Error Connect WhatsApp Client Datastore") } - // Set Client Properties - store.CompanionProps.Os = proto.String("Go WhatsApp Multi-Device REST") - store.CompanionProps.PlatformType = waproto.CompanionProps_DESKTOP.Enum() - - // Create New Client Connection - client := whatsmeow.NewClient(device, nil) - - // Return Client Connection - return client, nil + WhatsAppDatastore = datastore } -func WhatsAppInitClient(jid string) error { +func WhatsAppInitClient(device *store.Device, jid string) error { if WhatsAppClient[jid] == nil { - // Initialize New WhatsApp Client - client, err := WhatsAppInitDB(jid) - if err != nil { - return err + if device == nil { + // Initialize New WhatsApp Client Device in Datastore + device = WhatsAppDatastore.NewDevice() } - // Set Created WhatsApp Client to Map - WhatsAppClient[jid] = client + // Set Client Properties + store.CompanionProps.Os = proto.String("Go WhatsApp Multi-Device REST") + store.CompanionProps.PlatformType = waproto.CompanionProps_DESKTOP.Enum() + + // Initialize New WhatsApp Client + // And Save it to The Map + WhatsAppClient[jid] = whatsmeow.NewClient(device, nil) } return nil @@ -176,7 +161,7 @@ func WhatsAppLogout(jid string) error { // Force Disconnect WhatsAppClient[jid].Disconnect() - // Manually Delete Device from Database Store + // Manually Delete Device from Datastore Store err = WhatsAppClient[jid].Store.Delete() if err != nil { return err @@ -209,6 +194,23 @@ func WhatsAppClientIsOK(jid string) error { } func WhatsAppComposeJID(jid string) types.JID { + // Decompose JID First Before Recomposing + jid = WhatsAppDecomposeJID(jid) + + // Check if JID Contains '-' Symbol + if strings.ContainsRune(jid, '-') { + // Check if the JID is a Group ID + if len(strings.SplitN(jid, "-", 2)) == 2 { + // Return JID as Group Server (@g.us) + return types.NewJID(jid, types.GroupServer) + } + } + + // Return JID as Default User Server (@s.whatsapp.net) + return types.NewJID(jid, types.DefaultUserServer) +} + +func WhatsAppDecomposeJID(jid string) string { // Check if JID Contains '@' Symbol if strings.ContainsRune(jid, '@') { // Split JID Based on '@' Symbol @@ -223,17 +225,7 @@ func WhatsAppComposeJID(jid string) types.JID { jid = jid[1:] } - // Check if JID Contains '-' Symbol - if strings.ContainsRune(jid, '-') { - // Check if the JID is a Group ID - if len(strings.SplitN(jid, "-", 2)) == 2 { - // Return JID as Group Server (@g.us) - return types.NewJID(jid, types.GroupServer) - } - } - - // Return JID as Default User Server (@s.whatsapp.net) - return types.NewJID(jid, types.DefaultUserServer) + return jid } func WhatsAppSendText(jid string, rjid string, message string) error {