Skip to main content
Glama
root.go8.98 kB
package cmd import ( "context" "database/sql" "embed" "fmt" "go.mau.fi/whatsmeow/store/sqlstore" "os" "strings" "time" "github.com/aldinokemal/go-whatsapp-web-multidevice/config" domainApp "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/app" domainChat "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/chat" domainChatStorage "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/chatstorage" domainGroup "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/group" domainMessage "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/message" domainNewsletter "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/newsletter" domainSend "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/send" domainUser "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/user" "github.com/aldinokemal/go-whatsapp-web-multidevice/infrastructure/chatstorage" "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" ) var ( EmbedIndex embed.FS EmbedViews embed.FS // Whatsapp whatsappCli *whatsmeow.Client // Chat Storage chatStorageDB *sql.DB chatStorageRepo domainChatStorage.IChatStorageRepository // Usecase appUsecase domainApp.IAppUsecase chatUsecase domainChat.IChatUsecase sendUsecase domainSend.ISendUsecase userUsecase domainUser.IUserUsecase messageUsecase domainMessage.IMessageUsecase groupUsecase domainGroup.IGroupUsecase newsletterUsecase domainNewsletter.INewsletterUsecase ) // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Short: "Send free whatsapp API", Long: `This application is from clone https://github.com/aldinokemal/go-whatsapp-web-multidevice, you can send whatsapp over http api but your whatsapp account have to be multi device version`, } func init() { // Load environment variables first utils.LoadConfig(".") time.Local = time.UTC rootCmd.CompletionOptions.DisableDefaultCmd = true // Initialize flags first, before any subcommands are added initFlags() // Then initialize other components cobra.OnInitialize(initEnvConfig, initApp) } // initEnvConfig loads configuration from environment variables func initEnvConfig() { fmt.Println(viper.AllSettings()) // Application settings if envPort := viper.GetString("app_port"); envPort != "" { config.AppPort = envPort } if envDebug := viper.GetBool("app_debug"); envDebug { config.AppDebug = envDebug } if envOs := viper.GetString("app_os"); envOs != "" { config.AppOs = envOs } if envBasicAuth := viper.GetString("app_basic_auth"); envBasicAuth != "" { credential := strings.Split(envBasicAuth, ",") config.AppBasicAuthCredential = credential } if envBasePath := viper.GetString("app_base_path"); envBasePath != "" { config.AppBasePath = envBasePath } // Database settings 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 != "" { config.WhatsappAutoReplyMessage = envAutoReply } if viper.IsSet("whatsapp_auto_mark_read") { config.WhatsappAutoMarkRead = viper.GetBool("whatsapp_auto_mark_read") } if envWebhook := viper.GetString("whatsapp_webhook"); envWebhook != "" { webhook := strings.Split(envWebhook, ",") config.WhatsappWebhook = webhook } if envWebhookSecret := viper.GetString("whatsapp_webhook_secret"); envWebhookSecret != "" { config.WhatsappWebhookSecret = envWebhookSecret } if viper.IsSet("whatsapp_account_validation") { config.WhatsappAccountValidation = viper.GetBool("whatsapp_account_validation") } } func initFlags() { // Application flags rootCmd.PersistentFlags().StringVarP( &config.AppPort, "port", "p", config.AppPort, "change port number with --port <number> | example: --port=8080", ) rootCmd.PersistentFlags().BoolVarP( &config.AppDebug, "debug", "d", config.AppDebug, "hide or displaying log with --debug <true/false> | example: --debug=true", ) rootCmd.PersistentFlags().StringVarP( &config.AppOs, "os", "", config.AppOs, `os name --os <string> | example: --os="Chrome"`, ) rootCmd.PersistentFlags().StringSliceVarP( &config.AppBasicAuthCredential, "basic-auth", "b", config.AppBasicAuthCredential, "basic auth credential | -b=yourUsername:yourPassword", ) rootCmd.PersistentFlags().StringVarP( &config.AppBasePath, "base-path", "", config.AppBasePath, `base path for subpath deployment --base-path <string> | example: --base-path="/gowa"`, ) // Database flags rootCmd.PersistentFlags().StringVarP( &config.DBURI, "db-uri", "", 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 <string> | 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 <string> | example: --db-keys-uri="file::memory:?cache=shared&_foreign_keys=on"`, ) // WhatsApp flags rootCmd.PersistentFlags().StringVarP( &config.WhatsappAutoReplyMessage, "autoreply", "", config.WhatsappAutoReplyMessage, `auto reply when received message --autoreply <string> | example: --autoreply="Don't reply this message"`, ) rootCmd.PersistentFlags().BoolVarP( &config.WhatsappAutoMarkRead, "auto-mark-read", "", config.WhatsappAutoMarkRead, `auto mark incoming messages as read --auto-mark-read <true/false> | example: --auto-mark-read=true`, ) rootCmd.PersistentFlags().StringSliceVarP( &config.WhatsappWebhook, "webhook", "w", config.WhatsappWebhook, `forward event to webhook --webhook <string> | example: --webhook="https://yourcallback.com/callback"`, ) rootCmd.PersistentFlags().StringVarP( &config.WhatsappWebhookSecret, "webhook-secret", "", config.WhatsappWebhookSecret, `secure webhook request --webhook-secret <string> | example: --webhook-secret="super-secret-key"`, ) rootCmd.PersistentFlags().BoolVarP( &config.WhatsappAccountValidation, "account-validation", "", config.WhatsappAccountValidation, `enable or disable account validation --account-validation <true/false> | example: --account-validation=true`, ) } func initChatStorage() (*sql.DB, error) { connStr := fmt.Sprintf("%s?_journal_mode=WAL", config.ChatStorageURI) if config.ChatStorageEnableForeignKeys { connStr += "&_foreign_keys=on" } db, err := sql.Open("sqlite3", connStr) if err != nil { return nil, err } // Configure connection pool db.SetMaxOpenConns(25) db.SetMaxIdleConns(5) // Test connection if err := db.Ping(); err != nil { db.Close() return nil, fmt.Errorf("failed to ping database: %w", err) } return db, nil } func initApp() { if config.AppDebug { config.WhatsappLogLevel = "DEBUG" logrus.SetLevel(logrus.DebugLevel) } //preparing folder if not exist err := utils.CreateFolder(config.PathQrCode, config.PathSendItems, config.PathStorages, config.PathMedia) if err != nil { logrus.Errorln(err) } ctx := context.Background() chatStorageDB, err = initChatStorage() if err != nil { // Terminate the application if chat storage fails to initialize to avoid nil pointer panics later. logrus.Fatalf("failed to initialize chat storage: %v", err) } chatStorageRepo = chatstorage.NewStorageRepository(chatStorageDB) chatStorageRepo.InitializeSchema() whatsappDB := whatsapp.InitWaDB(ctx, config.DBURI) var keysDB *sqlstore.Container if config.DBKeysURI != "" { keysDB = whatsapp.InitWaDB(ctx, config.DBKeysURI) } whatsapp.SetChatStorageRepository(chatStorageRepo) whatsapp.InitWaCLI(ctx, whatsappDB, keysDB, chatStorageRepo) // Usecase appUsecase = usecase.NewAppService(chatStorageRepo) chatUsecase = usecase.NewChatService(chatStorageRepo) sendUsecase = usecase.NewSendService(appUsecase, chatStorageRepo) userUsecase = usecase.NewUserService() messageUsecase = usecase.NewMessageService(chatStorageRepo) groupUsecase = usecase.NewGroupService() newsletterUsecase = usecase.NewNewsletterService() } // Execute adds all child commands to the root command and sets flags appropriately. func Execute(embedIndex embed.FS, embedViews embed.FS) { EmbedIndex = embedIndex EmbedViews = embedViews if err := rootCmd.Execute(); err != nil { os.Exit(1) } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/samihalawa/whatsapp-go-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server