229 lines
6.9 KiB
Go
229 lines
6.9 KiB
Go
package common
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"runtime"
|
|
"strings"
|
|
"time"
|
|
|
|
"git.lehouerou.net/laurent/sorare"
|
|
"git.lehouerou.net/laurent/sorare/graphql"
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/jackc/pgx/v5/stdlib"
|
|
"github.com/pkg/errors"
|
|
"github.com/rs/zerolog"
|
|
"github.com/rs/zerolog/log"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/viper"
|
|
"github.com/uptrace/bun"
|
|
"github.com/uptrace/bun/dialect/pgdialect"
|
|
"github.com/uptrace/bun/extra/bundebug"
|
|
)
|
|
|
|
func InitParams(cmd *cobra.Command) {
|
|
cobra.OnInitialize(InitLog)
|
|
|
|
viper.AutomaticEnv()
|
|
viper.SetEnvPrefix("sorare")
|
|
|
|
cmd.PersistentFlags().BoolP("verbose", "v", false, "Verbose output")
|
|
_ = viper.BindPFlag("verbose", cmd.PersistentFlags().Lookup("verbose"))
|
|
viper.SetDefault("verbose", false)
|
|
|
|
cmd.PersistentFlags().String("jwttoken", "", "Sorare JWT Token")
|
|
_ = viper.BindPFlag("jwttoken", cmd.PersistentFlags().Lookup("jwttoken"))
|
|
viper.SetDefault("jwttoken", "")
|
|
|
|
cmd.PersistentFlags().String("jwtaudience", "", "Sorare JWT Audience")
|
|
_ = viper.BindPFlag("jwtaudience", cmd.PersistentFlags().Lookup("jwtaudience"))
|
|
viper.SetDefault("jwtaudience", "")
|
|
|
|
cmd.PersistentFlags().String("email", "", "Sorare Email")
|
|
_ = viper.BindPFlag("email", cmd.PersistentFlags().Lookup("email"))
|
|
viper.SetDefault("email", "")
|
|
|
|
cmd.PersistentFlags().String("password", "", "Sorare Password")
|
|
_ = viper.BindPFlag("password", cmd.PersistentFlags().Lookup("password"))
|
|
viper.SetDefault("password", "")
|
|
|
|
cmd.PersistentFlags().String("otp", "", "Sorare OTP")
|
|
_ = viper.BindPFlag("otp", cmd.PersistentFlags().Lookup("otp"))
|
|
viper.SetDefault("otp", "")
|
|
|
|
cmd.PersistentFlags().String("dbhost", "", "Database Host")
|
|
_ = viper.BindPFlag("dbhost", cmd.PersistentFlags().Lookup("dbhost"))
|
|
viper.SetDefault("dbhost", "192.168.1.250")
|
|
|
|
cmd.PersistentFlags().String("dbport", "", "Database Port")
|
|
_ = viper.BindPFlag("dbport", cmd.PersistentFlags().Lookup("dbport"))
|
|
viper.SetDefault("dbport", "5436")
|
|
|
|
cmd.PersistentFlags().String("dbuser", "", "Database User")
|
|
_ = viper.BindPFlag("dbuser", cmd.PersistentFlags().Lookup("dbuser"))
|
|
viper.SetDefault("dbuser", "sorare")
|
|
|
|
cmd.PersistentFlags().String("dbpass", "", "Database Password")
|
|
_ = viper.BindPFlag("dbpass", cmd.PersistentFlags().Lookup("dbpass"))
|
|
viper.SetDefault("dbpass", "sorare")
|
|
|
|
cmd.PersistentFlags().String("dbname", "", "Database Name")
|
|
_ = viper.BindPFlag("dbname", cmd.PersistentFlags().Lookup("dbname"))
|
|
viper.SetDefault("dbname", "sorare")
|
|
|
|
cmd.PersistentFlags().String("privatekey", "", "Sorare Private Key")
|
|
_ = viper.BindPFlag("privatekey", cmd.PersistentFlags().Lookup("privatekey"))
|
|
viper.SetDefault("privatekey", "")
|
|
|
|
cmd.PersistentFlags().Bool("tracedb", false, "Trace Database Queries")
|
|
_ = viper.BindPFlag("tracedb", cmd.PersistentFlags().Lookup("tracedb"))
|
|
viper.SetDefault("tracedb", false)
|
|
|
|
cmd.PersistentFlags().Bool("tracesorare", false, "Trace Sorare API Calls")
|
|
_ = viper.BindPFlag("tracesorare", cmd.PersistentFlags().Lookup("tracesorare"))
|
|
viper.SetDefault("tracesorare", false)
|
|
|
|
cmd.PersistentFlags().String("cryptkey", "", "Crypt Key")
|
|
_ = viper.BindPFlag("cryptkey", cmd.PersistentFlags().Lookup("cryptkey"))
|
|
viper.SetDefault("cryptkey", "")
|
|
|
|
cmd.PersistentFlags().String("jwtkey", "", "JWT Key")
|
|
_ = viper.BindPFlag("jwtkey", cmd.PersistentFlags().Lookup("jwtkey"))
|
|
viper.SetDefault("jwtkey", "")
|
|
}
|
|
|
|
func InitLog() {
|
|
log.Logger = zerolog.New(zerolog.ConsoleWriter{
|
|
Out: os.Stdout,
|
|
|
|
TimeFormat: "2006-01-02 | 15:04:05.000",
|
|
FormatLevel: func(i interface{}) string {
|
|
return strings.ToUpper(fmt.Sprintf("| %-6s|", i))
|
|
},
|
|
FormatFieldName: func(i interface{}) string {
|
|
return fmt.Sprintf("%s:", i)
|
|
},
|
|
FormatFieldValue: func(i interface{}) string {
|
|
return strings.ToUpper(fmt.Sprintf("%s", i))
|
|
},
|
|
}).With().Timestamp().Logger()
|
|
zerolog.TimeFieldFormat = zerolog.TimeFormatUnixMicro
|
|
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
|
|
|
verbose := viper.GetBool("verbose")
|
|
if verbose {
|
|
log.Info().Msg("Verbose output enabled")
|
|
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
|
}
|
|
}
|
|
|
|
func InitSorare(ctx context.Context) (*sorare.Sorare, error) {
|
|
|
|
audience := viper.GetString("jwtaudience")
|
|
if audience == "" {
|
|
return nil, errors.New("jwtaudience is required")
|
|
}
|
|
|
|
jwttoken := viper.GetString("jwttoken")
|
|
s := sorare.New()
|
|
tracesorare := viper.GetBool("tracesorare")
|
|
if tracesorare {
|
|
s.Debug()
|
|
}
|
|
if jwttoken != "" {
|
|
s.SetJWTToken(graphql.JwtToken{
|
|
Token: jwttoken,
|
|
ExpiredAt: time.Time{},
|
|
}, audience)
|
|
} else {
|
|
email := viper.GetString("email")
|
|
password := viper.GetString("password")
|
|
otp := viper.GetString("otp")
|
|
err := s.Authenticate(ctx, email, password, audience, otp)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "authenticating to sorare")
|
|
}
|
|
log.Info().Msgf("authentication to sorare successful. new token: %s", s.GetCurrentToken().Token)
|
|
}
|
|
cu, err := s.Users.CurrentUser.Get(ctx, graphql.EmptyParams{})
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "getting current user")
|
|
}
|
|
log.Info().Msgf("authenticated on Sorare as %s (%s)", cu.Nickname, cu.Profile.ClubName)
|
|
return s, nil
|
|
}
|
|
|
|
func InitDb(ctx context.Context) (*bun.DB, error) {
|
|
host := viper.GetString("dbhost")
|
|
if host == "" {
|
|
return nil, errors.New("dbhost is required")
|
|
}
|
|
port := viper.GetString("dbport")
|
|
if port == "" {
|
|
return nil, errors.New("dbport is required")
|
|
}
|
|
user := viper.GetString("dbuser")
|
|
if user == "" {
|
|
return nil, errors.New("dbuser is required")
|
|
}
|
|
password := viper.GetString("dbpass")
|
|
if password == "" {
|
|
return nil, errors.New("dbpass is required")
|
|
}
|
|
dbname := viper.GetString("dbname")
|
|
if dbname == "" {
|
|
return nil, errors.New("dbname is required")
|
|
}
|
|
|
|
maxOpenConns := 4 * runtime.GOMAXPROCS(0)
|
|
pgxconfig, err := pgx.ParseConfig(
|
|
fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable", user, password, host, port, dbname),
|
|
)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "parsing pgx config")
|
|
}
|
|
sqldb := stdlib.OpenDB(*pgxconfig)
|
|
db := bun.NewDB(sqldb, pgdialect.New())
|
|
db.SetMaxOpenConns(maxOpenConns)
|
|
|
|
tracedb := viper.GetBool("tracedb")
|
|
if tracedb {
|
|
db.AddQueryHook(bundebug.NewQueryHook(bundebug.WithVerbose(true)))
|
|
}
|
|
|
|
// Test the connection
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
if err := db.DB.PingContext(ctx); err != nil {
|
|
return nil, errors.Wrap(err, "pinging database")
|
|
}
|
|
|
|
log.Info().Msgf("connected to database %s@%s:%s/%s", user, host, port, dbname)
|
|
|
|
return db, nil
|
|
}
|
|
|
|
type contextKey string
|
|
|
|
const (
|
|
SorareContextKey contextKey = "sorare"
|
|
DbContextKey contextKey = "db"
|
|
)
|
|
|
|
func CmdPreRunE(cmd *cobra.Command, _ []string) error {
|
|
s, err := InitSorare(cmd.Context())
|
|
if err != nil {
|
|
return errors.Wrap(err, "initializing sorare client")
|
|
}
|
|
cmd.SetContext(context.WithValue(cmd.Context(), SorareContextKey, s))
|
|
|
|
db, err := InitDb(cmd.Context())
|
|
if err != nil {
|
|
return errors.Wrap(err, "initializing database")
|
|
}
|
|
cmd.SetContext(context.WithValue(cmd.Context(), DbContextKey, db))
|
|
|
|
return nil
|
|
}
|