2023-06-23 04:08:00 +03:00
package cmd
import (
2023-06-30 22:49:58 +03:00
"errors"
2023-06-23 04:08:00 +03:00
"fmt"
2023-06-30 22:49:58 +03:00
"strings"
2023-06-23 04:08:00 +03:00
2023-06-23 04:16:45 +03:00
"github.com/karust/openserp/core"
2023-06-23 04:08:00 +03:00
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
)
const (
2023-06-30 22:49:58 +03:00
version = "0.2.1"
defaultConfigFilename = "config"
envPrefix = "OPENSERP"
2023-06-23 04:08:00 +03:00
)
2023-06-30 22:49:58 +03:00
type Config struct {
App AppConfig ` mapstructure:"app" `
GoogleConfig core . SearchEngineOptions ` mapstructure:"google" `
YandexConfig core . SearchEngineOptions ` mapstructure:"yandex" `
BaiduConfig core . SearchEngineOptions ` mapstructure:"baidu" `
}
2023-06-23 04:08:00 +03:00
type AppConfig struct {
2023-06-30 22:49:58 +03:00
Host string ` mapstructure:"host" `
Port int ` mapstructure:"port" `
Timeout int ` mapstructure:"timeout" `
ConfigPath string ` mapstructure:"config_path" `
IsBrowserHead bool ` mapstructure:"head" `
IsLeaveHead bool ` mapstructure:"leave_head" `
IsLeakless bool ` mapstructure:"leakless" `
IsDebug bool ` mapstructure:"debug" `
IsVerbose bool ` mapstructure:"verbose" `
IsRawRequests bool ` mapstructure:"raw_requests" `
2023-06-23 04:08:00 +03:00
}
2023-06-30 22:49:58 +03:00
var config = Config { }
2023-06-23 04:08:00 +03:00
var RootCmd = & cobra . Command {
2023-06-30 22:49:58 +03:00
Use : "openserp" ,
Short : "Open SERP" ,
Long : ` Get [Google, Yandex, Baidu] search engine results via API or CLI. ` ,
Version : version ,
SilenceUsage : true ,
2023-06-23 04:08:00 +03:00
PersistentPreRunE : func ( cmd * cobra . Command , args [ ] string ) error {
2023-06-30 22:49:58 +03:00
core . InitLogger ( config . App . IsVerbose , config . App . IsDebug )
2023-06-24 22:26:36 +03:00
err := initializeConfig ( cmd )
2023-06-30 22:49:58 +03:00
if err != nil {
return err
}
logrus . Debugf ( "Final config: %+v" , config )
return nil
2023-06-23 04:08:00 +03:00
} ,
2023-06-30 22:49:58 +03:00
2023-06-23 04:08:00 +03:00
// Run: func(cmd *cobra.Command, args []string) {
// // Working with OutOrStdout/OutOrStderr allows us to unit test our command easier
// //out := cmd.OutOrStdout()
2023-06-30 22:49:58 +03:00
// logrus.Trace("Config:", config)
2023-06-23 04:08:00 +03:00
// },
}
// Bind each cobra flag to its associated viper configuration (config file and environment variable)
func bindFlags ( cmd * cobra . Command , vpr * viper . Viper ) {
cmd . Flags ( ) . VisitAll ( func ( flg * pflag . Flag ) {
configName := "app." + flg . Name
// Apply viper config value to the flag if viper has a value
2023-06-30 22:49:58 +03:00
if flg . Changed {
vpr . Set ( configName , flg . Value )
2023-06-23 04:08:00 +03:00
}
} )
}
// Initialize Viper
func initializeConfig ( cmd * cobra . Command ) error {
v := viper . New ( )
// Base name of the config file, without the file extension
v . SetConfigName ( defaultConfigFilename )
v . AddConfigPath ( "." )
2023-06-30 22:49:58 +03:00
// 1. Config. Return an error if we cannot parse the config file.
err := v . ReadInConfig ( )
if err != nil {
err = errors . New ( fmt . Sprintf ( "Cannot read config: %v" , err ) )
logrus . Warn ( err )
2023-06-23 04:08:00 +03:00
}
2023-06-30 22:49:58 +03:00
// 2. Env. Bind environment variables to their equivalent keys with underscores
for _ , key := range v . AllKeys ( ) {
envKey := envPrefix + "_" + strings . ToUpper ( strings . ReplaceAll ( key , "." , "_" ) )
err := v . BindEnv ( key , envKey )
if err != nil {
logrus . Errorf ( "Unable to bind ENV valye: %v" , err )
}
}
2023-06-23 04:08:00 +03:00
2023-06-30 22:49:58 +03:00
// 3. Cmd flags. Bind the current command's flags to viper
2023-06-23 04:08:00 +03:00
bindFlags ( cmd , v )
2023-06-30 22:49:58 +03:00
// Dump Viper values to config struct
err = v . Unmarshal ( & config )
if err != nil {
return errors . New ( fmt . Sprintf ( "Cannot unmarshall config: %v" , err ) )
}
if config . App . IsDebug {
logrus . Debug ( "Viper config:" )
v . Debug ( )
}
2023-06-23 04:08:00 +03:00
return nil
}
func init ( ) {
2023-06-30 22:49:58 +03:00
RootCmd . PersistentFlags ( ) . IntVarP ( & config . App . Port , "port" , "p" , 7070 , "Port number to run server" )
RootCmd . PersistentFlags ( ) . StringVarP ( & config . App . Host , "host" , "a" , "127.0.0.1" , "Host address to run server" )
RootCmd . PersistentFlags ( ) . IntVarP ( & config . App . Timeout , "timeout" , "t" , 30 , "Timeout to fail request" )
RootCmd . PersistentFlags ( ) . StringVarP ( & config . App . ConfigPath , "config" , "c" , "" , "Configuration file path" )
RootCmd . PersistentFlags ( ) . BoolVarP ( & config . App . IsVerbose , "verbose" , "v" , false , "Use verbose output" )
RootCmd . PersistentFlags ( ) . BoolVarP ( & config . App . IsDebug , "debug" , "d" , false , "Use debug output. Disable headless browser" )
RootCmd . PersistentFlags ( ) . BoolVarP ( & config . App . IsBrowserHead , "head" , "" , false , "Enable browser UI" )
RootCmd . PersistentFlags ( ) . BoolVarP ( & config . App . IsLeakless , "leakless" , "l" , false , "Use leakless mode to insure browser instances are closed after search" )
RootCmd . PersistentFlags ( ) . BoolVarP ( & config . App . IsRawRequests , "raw" , "r" , false , "Disable browser usage, use HTTP requests" )
RootCmd . PersistentFlags ( ) . BoolVarP ( & config . App . IsLeaveHead , "leave" , "" , false , "Leave browser and tabs opened after search is made" )
2023-06-23 04:08:00 +03:00
}