diff --git a/src/.env.example b/src/.env.example index 80a226a..14d3a34 100644 --- a/src/.env.example +++ b/src/.env.example @@ -7,6 +7,7 @@ APP_CHAT_FLUSH_INTERVAL=7 # Database Settings DB_URI="file:storages/whatsapp.db?_foreign_keys=on" +DB_KEYS_URI="file::memory:?cache=shared" # WhatsApp Settings WHATSAPP_AUTO_REPLY="Auto reply message" diff --git a/src/cmd/root.go b/src/cmd/root.go index 1f76819..7a005be 100644 --- a/src/cmd/root.go +++ b/src/cmd/root.go @@ -3,6 +3,7 @@ package cmd import ( "context" "embed" + "go.mau.fi/whatsmeow/store/sqlstore" "os" "strings" "time" @@ -17,14 +18,12 @@ import ( "github.com/aldinokemal/go-whatsapp-web-multidevice/infrastructure/whatsapp" "github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/utils" "github.com/aldinokemal/go-whatsapp-web-multidevice/usecase" + _ "github.com/lib/pq" + _ "github.com/mattn/go-sqlite3" "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" "go.mau.fi/whatsmeow" - "go.mau.fi/whatsmeow/store/sqlstore" - - _ "github.com/lib/pq" - _ "github.com/mattn/go-sqlite3" ) var ( @@ -90,6 +89,9 @@ func initEnvConfig() { if envDBURI := viper.GetString("DB_URI"); envDBURI != "" { config.DBURI = envDBURI } + if envDBKEYSURI := viper.GetString("DB_KEYS_URI"); envDBKEYSURI != "" { + config.DBKeysURI = envDBKEYSURI + } // WhatsApp settings if envAutoReply := viper.GetString("WHATSAPP_AUTO_REPLY"); envAutoReply != "" { @@ -151,6 +153,12 @@ func initFlags() { config.DBURI, `the database uri to store the connection data database uri (by default, we'll use sqlite3 under storages/whatsapp.db). database uri --db-uri | example: --db-uri="file:storages/whatsapp.db?_foreign_keys=on or postgres://user:password@localhost:5432/whatsapp"`, ) + rootCmd.PersistentFlags().StringVarP( + &config.DBKeysURI, + "db-keys-uri", "", + config.DBKeysURI, + `the database uri to store the keys database uri (by default, we'll use the same database uri). database uri --db-keys-uri | example: --db-keys-uri="file::memory:?cache=shared"`, + ) // WhatsApp flags rootCmd.PersistentFlags().StringVarP( @@ -196,8 +204,13 @@ func initApp() { } ctx := context.Background() - whatsappDB = whatsapp.InitWaDB(ctx) - whatsappCli = whatsapp.InitWaCLI(ctx, whatsappDB) + whatsappDB = whatsapp.InitWaDB(ctx, config.DBURI) + var dbKeys *sqlstore.Container + if config.DBKeysURI != "" { + dbKeys = whatsapp.InitWaDB(ctx, config.DBKeysURI) + } + + whatsappCli = whatsapp.InitWaCLI(ctx, whatsappDB, dbKeys) // Usecase appUsecase = usecase.NewAppService(whatsappCli, whatsappDB) diff --git a/src/config/settings.go b/src/config/settings.go index 50252e3..0f77070 100644 --- a/src/config/settings.go +++ b/src/config/settings.go @@ -23,6 +23,7 @@ var ( PathChatStorage = "storages/chat.csv" DBURI = "file:storages/whatsapp.db?_foreign_keys=on" + DBKeysURI = "" WhatsappAutoReplyMessage string WhatsappWebhook []string diff --git a/src/infrastructure/whatsapp/init.go b/src/infrastructure/whatsapp/init.go index 1190798..21c483c 100644 --- a/src/infrastructure/whatsapp/init.go +++ b/src/infrastructure/whatsapp/init.go @@ -53,11 +53,11 @@ var ( ) // InitWaDB initializes the WhatsApp database connection -func InitWaDB(ctx context.Context) *sqlstore.Container { +func InitWaDB(ctx context.Context, DBURI string) *sqlstore.Container { log = waLog.Stdout("Main", config.WhatsappLogLevel, true) dbLog := waLog.Stdout("Database", config.WhatsappLogLevel, true) - storeContainer, err := initDatabase(ctx, dbLog) + storeContainer, err := initDatabase(ctx, dbLog, DBURI) if err != nil { log.Errorf("Database initialization error: %v", err) panic(pkgError.InternalServerError(fmt.Sprintf("Database initialization error: %v", err))) @@ -67,18 +67,18 @@ func InitWaDB(ctx context.Context) *sqlstore.Container { } // initDatabase creates and returns a database store container based on the configured URI -func initDatabase(ctx context.Context, dbLog waLog.Logger) (*sqlstore.Container, error) { +func initDatabase(ctx context.Context, dbLog waLog.Logger, DBURI string) (*sqlstore.Container, error) { if strings.HasPrefix(config.DBURI, "file:") { - return sqlstore.New(ctx, "sqlite3", config.DBURI, dbLog) - } else if strings.HasPrefix(config.DBURI, "postgres:") { - return sqlstore.New(ctx, "postgres", config.DBURI, dbLog) + return sqlstore.New(ctx, "sqlite3", DBURI, dbLog) + } else if strings.HasPrefix(DBURI, "postgres:") { + return sqlstore.New(ctx, "postgres", DBURI, dbLog) } - return nil, fmt.Errorf("unknown database type: %s. Currently only sqlite3(file:) and postgres are supported", config.DBURI) + return nil, fmt.Errorf("unknown database type: %s. Currently only sqlite3(file:) and postgres are supported", DBURI) } // InitWaCLI initializes the WhatsApp client -func InitWaCLI(ctx context.Context, storeContainer *sqlstore.Container) *whatsmeow.Client { +func InitWaCLI(ctx context.Context, storeContainer *sqlstore.Container, keysStoreContainer *sqlstore.Container) *whatsmeow.Client { device, err := storeContainer.GetFirstDevice(ctx) if err != nil { log.Errorf("Failed to get device: %v", err) @@ -95,6 +95,17 @@ func InitWaCLI(ctx context.Context, storeContainer *sqlstore.Container) *whatsme store.DeviceProps.PlatformType = &config.AppPlatform store.DeviceProps.Os = &osName + // Configure a separated database for accelerating encryption caching + if keysStoreContainer != nil && device.ID != nil { + innerStore := sqlstore.NewSQLStore(keysStoreContainer, *device.ID) + device.Identities = innerStore + device.Sessions = innerStore + device.PreKeys = innerStore + device.SenderKeys = innerStore + device.MsgSecrets = innerStore + device.PrivacyTokens = innerStore + } + // Create and configure the client cli = whatsmeow.NewClient(device, waLog.Stdout("Client", config.WhatsappLogLevel, true)) cli.EnableAutoReconnect = true