From 93af6e9c08b9fae316641c73c1ce19a5a084495d Mon Sep 17 00:00:00 2001 From: Laurent Le Houerou Date: Thu, 21 Mar 2024 05:34:38 +0000 Subject: [PATCH] initial commit --- .gitignore | 19 +++ cmd/common/init.go | 217 +++++++++++++++++++++++++++ cmd/common/main.go | 47 ++++++ cmd/console/root.go | 281 +++++++++++++++++++++++++++++++++++ db/migrations/00001_init.sql | 205 +++++++++++++++++++++++++ go.mod | 55 +++++++ go.sum | 191 ++++++++++++++++++++++++ model/competition.sql.go | 151 +++++++++++++++++++ model/copyfrom.go | 175 ++++++++++++++++++++++ model/country.sql.go | 69 +++++++++ model/db.go | 33 ++++ model/fixture.sql.go | 116 +++++++++++++++ model/game.sql.go | 32 ++++ model/models.go | 164 ++++++++++++++++++++ model/sql/competition.sql | 39 +++++ model/sql/country.sql | 34 +++++ model/sql/fixture.sql | 23 +++ model/sql/game.sql | 4 + model/sql/team.sql | 3 + model/sql/test.sql | 2 + model/sql/zone.sql | 2 + model/team.sql.go | 18 +++ model/zone.sql.go | 21 +++ sqlc.yml | 25 ++++ 24 files changed, 1926 insertions(+) create mode 100644 .gitignore create mode 100644 cmd/common/init.go create mode 100644 cmd/common/main.go create mode 100644 cmd/console/root.go create mode 100644 db/migrations/00001_init.sql create mode 100644 go.mod create mode 100644 go.sum create mode 100644 model/competition.sql.go create mode 100644 model/copyfrom.go create mode 100644 model/country.sql.go create mode 100644 model/db.go create mode 100644 model/fixture.sql.go create mode 100644 model/game.sql.go create mode 100644 model/models.go create mode 100644 model/sql/competition.sql create mode 100644 model/sql/country.sql create mode 100644 model/sql/fixture.sql create mode 100644 model/sql/game.sql create mode 100644 model/sql/team.sql create mode 100644 model/sql/test.sql create mode 100644 model/sql/zone.sql create mode 100644 model/team.sql.go create mode 100644 model/zone.sql.go create mode 100644 sqlc.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..494e767 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work +go.work.sum diff --git a/cmd/common/init.go b/cmd/common/init.go new file mode 100644 index 0000000..888f6b1 --- /dev/null +++ b/cmd/common/init.go @@ -0,0 +1,217 @@ +package common + +import ( + "context" + "fmt" + "os" + "strings" + "time" + + "git.lehouerou.net/laurent/sorare" + "git.lehouerou.net/laurent/sorare/graphql" + "github.com/jackc/pgx/v5" + "github.com/pkg/errors" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "git.lehouerou.net/laurent/sorarebuddy/model" +) + +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) (*model.Queries, 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") + } + + conn, err := pgx.Connect( + ctx, + fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", + host, + port, + user, + password, + dbname, + ), + ) + if err != nil { + return nil, errors.Wrap(err, "connecting to database") + } + + queries := model.New(conn) + + log.Info().Msgf("connected to database %s@%s:%s/%s", user, host, port, dbname) + + return queries, 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 +} diff --git a/cmd/common/main.go b/cmd/common/main.go new file mode 100644 index 0000000..c0121fa --- /dev/null +++ b/cmd/common/main.go @@ -0,0 +1,47 @@ +package common + +import ( + "context" + "os" + "os/signal" + "syscall" + "time" + + "github.com/rs/zerolog/log" + "github.com/spf13/cobra" +) + +func Start(cmd *cobra.Command) { + ctx, cancel := context.WithCancel(context.Background()) + returnCode := make(chan int) + terminated := make(chan interface{}) + go trapSignals(cancel, terminated, returnCode) + + if err := cmd.ExecuteContext(ctx); err != nil { + log.Error().Err(err).Send() + sendReturnCode(returnCode, -2) + } else { + sendReturnCode(returnCode, 0) + } + close(terminated) + os.Exit(<-returnCode) +} + +func sendReturnCode(returnCode chan<- int, code int) { + go func(returnCode chan<- int) { returnCode <- code }(returnCode) +} + +func trapSignals(cancel context.CancelFunc, terminated chan interface{}, returnCode chan int) { + stopSignal := make(chan os.Signal, 1) + signal.Notify(stopSignal, syscall.SIGTERM, syscall.SIGINT) + <-stopSignal + log.Info().Msg("received stop signal. shutting down...") + cancel() + select { + case <-time.After(30 * time.Second): + log.Warn().Msg("app shutdown sequence timed out") + returnCode <- 1 + case <-terminated: + returnCode <- 0 + } +} diff --git a/cmd/console/root.go b/cmd/console/root.go new file mode 100644 index 0000000..8010d57 --- /dev/null +++ b/cmd/console/root.go @@ -0,0 +1,281 @@ +package main + +import ( + "git.lehouerou.net/laurent/sorare" + "git.lehouerou.net/laurent/sorare/football" + "git.lehouerou.net/laurent/sorare/graphql" + "github.com/jackc/pgx/v5/pgtype" + "github.com/pkg/errors" + "github.com/rs/zerolog/log" + "github.com/samber/lo" + "github.com/spf13/cobra" + + "git.lehouerou.net/laurent/sorarebuddy/cmd/common" + "git.lehouerou.net/laurent/sorarebuddy/model" +) + +var Cmd = &cobra.Command{ + Use: "console", + Short: "console", + Long: `console`, + RunE: run, + PersistentPreRunE: common.CmdPreRunE, +} + +func main() { + common.Start(Cmd) +} + +func init() { + common.InitParams(Cmd) +} + +func run(cmd *cobra.Command, _ []string) error { + //var wg conc.WaitGroup + + ctx := cmd.Context() + s, ok := ctx.Value(common.SorareContextKey).(*sorare.Sorare) + if !ok { + return errors.New("sorare not found in context") + } + + db, ok := ctx.Value(common.DbContextKey).(*model.Queries) + if !ok { + return errors.New("db not found in context") + } + + sfixtures, err := s.Football.So5.So5Fixtures.Get(ctx, football.So5FixturesParams{}) + if err != nil { + return err + } + log.Debug().Msgf("fixtures: %v", sfixtures) + + cnt, err := db.CreateFixtures( + ctx, + lo.Map(sfixtures, func(fixture football.So5Fixture, index int) model.CreateFixturesParams { + return model.CreateFixturesParams{ + Slug: fixture.Slug, + DisplayName: fixture.DisplayName, + State: fixture.AasmState, + StartDate: pgtype.Timestamptz{Time: fixture.StartDate, Valid: true}, + EndDate: pgtype.Timestamptz{Time: fixture.EndDate, Valid: true}, + GameWeek: int32(fixture.GameWeek), + } + }), + ) + if err != nil { + return err + } + + log.Debug().Msgf("created %d fixtures", cnt) + + fixtures, err := db.GetAllFixtures(ctx) + if err != nil { + return err + } + + var games []football.Game + for _, fixture := range fixtures { + log.Debug().Msgf("fixture: %v", fixture) + g, err := s.Football.So5.FixtureGames(fixture.Slug).Get(ctx, graphql.EmptyParams{}) + if err != nil { + return err + } + log.Debug().Msgf("games: %d", len(g)) + games = append(games, g...) + } + log.Debug().Msgf("games: %d", len(games)) + + var teamSlugs []string + teamSlugs = lo.Map(games, func(game football.Game, index int) string { + return game.AwayTeam.Team.Slug + }) + teamSlugs = append(teamSlugs, lo.Map(games, func(game football.Game, index int) string { + return game.HomeTeam.Team.Slug + })...) + teamSlugs = lo.Filter(teamSlugs, func(slug string, index int) bool { + return slug != "" + }) + teamSlugs = lo.Uniq(teamSlugs) + + var clubs []football.Club + for _, chunk := range lo.Chunk(teamSlugs, 100) { + t, err := s.Football.Clubs.Get(ctx, graphql.SlugsParams{Slugs: chunk}) + if err != nil { + return err + } + clubs = append(clubs, t...) + } + + var nationalTeams []football.NationalTeam + for _, chunk := range lo.Chunk(lo.Without(teamSlugs, lo.Map(clubs, func(club football.Club, index int) string { + return club.Slug + })...), 100) { + t, err := s.Football.NationalTeams.Get(ctx, graphql.SlugsParams{Slugs: chunk}) + if err != nil { + return err + } + nationalTeams = append(nationalTeams, t...) + } + + var teamsToInsert []model.CreateTeamsParams + teamsToInsert = append(teamsToInsert, lo.Map(clubs, func(club football.Club, index int) model.CreateTeamsParams { + return model.CreateTeamsParams{ + Slug: club.Slug, + DisplayName: club.Name, + CountrySlug: club.Country.Slug, + DomesticLeagueSlug: func() *string { + if club.DomesticLeague.Slug == "" { + return nil + } + return &club.DomesticLeague.Slug + }(), + ShortName: club.ShortName, + PictureUrl: club.PictureUrl, + TeamType: "club", + } + })...) + teamsToInsert = append( + teamsToInsert, + lo.Map(nationalTeams, func(nationalTeam football.NationalTeam, index int) model.CreateTeamsParams { + return model.CreateTeamsParams{ + Slug: nationalTeam.Slug, + DisplayName: nationalTeam.Name, + CountrySlug: nationalTeam.Country.Slug, + DomesticLeagueSlug: nil, + ShortName: nationalTeam.ShortName, + PictureUrl: nationalTeam.PictureUrl, + TeamType: "national", + } + })...) + + competitionSlugs := lo.Map(games, func(game football.Game, index int) string { + return game.Competition.Slug + }) + competitionSlugs = append( + competitionSlugs, + lo.Map(teamsToInsert, func(team model.CreateTeamsParams, index int) string { + if team.DomesticLeagueSlug == nil { + return "" + } + return *team.DomesticLeagueSlug + })...) + competitionSlugs = lo.Filter(competitionSlugs, func(slug string, index int) bool { + return slug != "" + }) + competitionSlugs = lo.Uniq(competitionSlugs) + + var competitions []football.Competition + for _, slug := range competitionSlugs { + log.Debug().Msgf("competition: %s", slug) + c, err := s.Football.Competition.Get(ctx, graphql.SlugParams{Slug: slug}) + if err != nil { + return err + } + competitions = append(competitions, c) + } + + var countrySlugs []string + countrySlugs = append(countrySlugs, lo.Map(teamsToInsert, func(team model.CreateTeamsParams, index int) string { + return team.CountrySlug + })...) + countrySlugs = append(countrySlugs, lo.Map(competitions, func(competition football.Competition, index int) string { + return competition.Country.Slug + })...) + countrySlugs = lo.Filter(countrySlugs, func(slug string, index int) bool { + return slug != "" + }) + countrySlugs = lo.Uniq(countrySlugs) + + var countries []sorare.Country + for _, chunk := range lo.Chunk(countrySlugs, 100) { + c, err := s.Countries.Get(ctx, graphql.SlugsParams{Slugs: chunk}) + if err != nil { + return err + } + countries = append(countries, c...) + } + + cnt, err = db.CreateCountries( + ctx, + lo.Map(countries, func(country sorare.Country, index int) model.CreateCountriesParams { + return model.CreateCountriesParams{ + Slug: country.Slug, + Code: country.Code, + DisplayName: country.Name, + ThreeLetterCode: country.ThreeLetterCode, + FlagFlat64Url: country.FlagFlat64Url, + FlagFlat32Url: country.FlagFlat32Url, + FlagRound64Url: country.FlagRound64Url, + FlagRound32Url: country.FlagRound32Url, + } + }), + ) + if err != nil { + return err + } + log.Debug().Msgf("created %d countries", cnt) + + log.Debug().Msgf("competitions: %d", len(competitions)) + for _, competition := range competitions { + + err := db.CreateOrUpdateCompetition(ctx, model.CreateOrUpdateCompetitionParams{ + Slug: competition.Slug, + CompetitionFormat: competition.Format, + CompetitionType: competition.Type, + DisplayName: competition.DisplayName, + PictureUrl: competition.PictureUrl, + LogoUrl: competition.LogoUrl, + CountrySlug: competition.Country.Slug, + }) + if err != nil { + return err + } + } + + cnt, err = db.CreateTeams(ctx, teamsToInsert) + if err != nil { + return err + } + log.Debug().Msgf("created %d teams", cnt) + + cnt, err = db.CreateGames(ctx, lo.Map(games, func(game football.Game, index int) model.CreateGamesParams { + return model.CreateGamesParams{ + CoverageStatus: game.CoverageStatus, + LowCoverage: game.LowCoverage, + Minutes: int32(game.Minute), + PeriodType: game.PeriodType, + Scored: game.Scored, + Status: game.Status, + CompetitionSlug: game.Competition.Slug, + FixtureSlug: game.So5Fixture.Slug, + AwayTeamSlug: game.AwayTeam.Team.Slug, + AwayGoals: int32(game.AwayGoals), + AwayExtraTimeScore: int32(game.ExtraTimeScoreAway), + AwayPenaltyScore: int32(game.PenaltyScoreAway), + HomeTeamSlug: game.HomeTeam.Team.Slug, + HomeGoals: int32(game.HomeGoals), + HomeExtraTimeScore: int32(game.ExtraTimeScoreHome), + HomePenaltyScore: int32(game.PenaltyScoreHome), + WinnerTeamSlug: func() *string { + if game.Winner.Team.Slug == "" { + return nil + } + return &game.Winner.Team.Slug + }(), + } + })) + if err != nil { + return err + } + + log.Debug().Msgf("created %d games", cnt) + + // log.Debug().Msg("start sequence completed. waiting for shutdown request") + // <-ctx.Done() + // log.Debug().Msg("shutdown requested") + // wg.Wait() + // log.Debug().Msg("shutdown complete") + return nil + +} diff --git a/db/migrations/00001_init.sql b/db/migrations/00001_init.sql new file mode 100644 index 0000000..22df959 --- /dev/null +++ b/db/migrations/00001_init.sql @@ -0,0 +1,205 @@ +-- +goose Up + BEGIN; + + CREATE TABLE IF NOT EXISTS zones (id SERIAL PRIMARY KEY, display_name TEXT NOT NULL); + + INSERT INTO zones (display_name) + VALUES ('Champions'); + + INSERT INTO zones (display_name) + VALUES ('Contenders'); + + INSERT INTO zones (display_name) + VALUES ('Challengers'); + + CREATE TABLE IF NOT EXISTS countries ( + slug TEXT PRIMARY KEY, + code TEXT NOT NULL, + display_name TEXT NOT NULL, + three_letter_code TEXT NOT NULL, + flag_flat_64_url TEXT NOT NULL, + flag_flat_32_url TEXT NOT NULL, + flag_round_64_url TEXT NOT NULL, + flag_round_32_url TEXT NOT NULL + ); + + CREATE TABLE IF NOT EXISTS competitions ( + slug TEXT PRIMARY KEY, + display_name TEXT NOT NULL, + country_slug TEXT NOT NULL, + FOREIGN KEY (country_slug) REFERENCES countries (slug), + competition_format TEXT NOT NULL, + competition_type TEXT NOT NULL, + picture_url TEXT NOT NULL, + logo_url TEXT NOT NULL, + zone_id INTEGER, + FOREIGN KEY (zone_id) REFERENCES zones (id) + ); + + CREATE TABLE IF NOT EXISTS fixtures ( + slug TEXT PRIMARY KEY, + display_name TEXT NOT NULL, + state TEXT NOT NULL, + start_date TIMESTAMPTZ NOT NULL, + end_date TIMESTAMPTZ NOT NULL, + game_week INTEGER NOT NULL UNIQUE + ); + + CREATE TABLE IF NOT EXISTS teams ( + slug TEXT PRIMARY KEY, + display_name TEXT NOT NULL, + country_slug TEXT NOT NULL, + FOREIGN KEY (country_slug) REFERENCES countries (slug), + domestic_league_slug TEXT, + FOREIGN KEY (domestic_league_slug) REFERENCES competitions (slug), + short_name TEXT NOT NULL, + picture_url TEXT NOT NULL, + team_type TEXT NOT NULL + ); + + CREATE TABLE IF NOT EXISTS games ( + id TEXT PRIMARY KEY, + date TIMESTAMPTZ, + coverage_status TEXT NOT NULL, + low_coverage BOOLEAN NOT NULL, + minutes INTEGER NOT NULL, + period_type TEXT NOT NULL, + scored BOOLEAN NOT NULL, + status TEXT NOT NULL, + competition_slug TEXT NOT NULL, + FOREIGN KEY (competition_slug) REFERENCES competitions (slug), + fixture_slug TEXT NOT NULL, + FOREIGN KEY (fixture_slug) REFERENCES fixtures (slug), + away_team_slug TEXT NOT NULL, + FOREIGN KEY (away_team_slug) REFERENCES teams (slug), + away_goals INTEGER NOT NULL, + away_extra_time_score INTEGER NOT NULL, + away_penalty_score INTEGER NOT NULL, + home_team_slug TEXT NOT NULL, + FOREIGN KEY (home_team_slug) REFERENCES teams (slug), + home_goals INTEGER NOT NULL, + home_extra_time_score INTEGER NOT NULL, + home_penalty_score INTEGER NOT NULL, + winner_team_slug TEXT, + FOREIGN KEY (winner_team_slug) REFERENCES teams (slug) + ); + + CREATE TABLE IF NOT EXISTS players ( + slug TEXT PRIMARY KEY, + display_name TEXT NOT NULL, + birth_date DATE NOT NULL, + country_slug TEXT NOT NULL, + FOREIGN KEY (country_slug) REFERENCES countries (slug), + team_slug TEXT NOT NULL, + FOREIGN KEY (team_slug) REFERENCES teams (slug), + domestic_league_slug TEXT NOT NULL, + FOREIGN KEY (domestic_league_slug) REFERENCES competitions (slug), + avatar_url TEXT NOT NULL, + field_position TEXT NOT NULL, + status TEXT NOT NULL, + shirt_number INTEGER NOT NULL + ); + + CREATE TABLE IF NOT EXISTS game_players ( + game_id TEXT NOT NULL, + FOREIGN KEY (game_id) REFERENCES games (id), + player_slug TEXT NOT NULL, + FOREIGN KEY (player_slug) REFERENCES players (slug), + status TEXT NOT NULL, + team_slug TEXT NOT NULL, + FOREIGN KEY (team_slug) REFERENCES teams (slug), + PRIMARY KEY (game_id, player_slug) + ); + + CREATE INDEX idx_game_players_game_id_team_slug ON game_players (game_id, team_slug); + + CREATE TABLE IF NOT EXISTS game_player_scores ( + game_id TEXT NOT NULL, + FOREIGN KEY (game_id) REFERENCES games (id), + player_slug TEXT NOT NULL, + FOREIGN KEY (player_slug) REFERENCES players (slug), + FOREIGN KEY (game_id, player_slug) REFERENCES game_players (game_id, player_slug), + PRIMARY KEY (game_id, player_slug), + score NUMERIC NOT NULL, + decisive_score NUMERIC NOT NULL, + all_around_score NUMERIC NOT NULL, + minutes_played INTEGER NOT NULL, + game_started BOOLEAN NOT NULL, + formation_place INTEGER NOT NULL, + live BOOLEAN NOT NULL, + on_game_sheet BOOLEAN NOT NULL, + reviewed BOOLEAN NOT NULL, + goal INTEGER NOT NULL, + assist INTEGER NOT NULL, + penalty_won INTEGER NOT NULL, + clearance_off_line INTEGER NOT NULL, + last_man_tackle INTEGER NOT NULL, + penalty_save INTEGER NOT NULL, + own_goal INTEGER NOT NULL, + red_card BOOLEAN NOT NULL, + error_lead_to_goal INTEGER NOT NULL, + penalty_conceded INTEGER NOT NULL, + yellow_card INTEGER NOT NULL, + fouls INTEGER NOT NULL, + fouled INTEGER NOT NULL, + clean_sheet BOOLEAN NOT NULL, + double_double BOOLEAN NOT NULL, + triple_double BOOLEAN NOT NULL, + triple_triple BOOLEAN NOT NULL, + error_lead_to_shot INTEGER NOT NULL, + saves INTEGER NOT NULL, + saved_shot_from_inside_box INTEGER NOT NULL, + good_high_claim INTEGER NOT NULL, + punches INTEGER NOT NULL, + diving_save INTEGER NOT NULL, + diving_catch INTEGER NOT NULL, + cross_not_claimed INTEGER NOT NULL, + goalkeeper_smother INTEGER NOT NULL, + six_second_violation INTEGER NOT NULL, + keeper_sweeper INTEGER NOT NULL, + goals_conceded INTEGER NOT NULL, + effective_clearance INTEGER NOT NULL, + won_tackle INTEGER NOT NULL, + blocked_cross INTEGER NOT NULL, + block INTEGER NOT NULL, + possession_lost INTEGER NOT NULL, + possession_won INTEGER NOT NULL, + duel_lost INTEGER NOT NULL, + duel_won INTEGER NOT NULL, + interception INTEGER NOT NULL, + accurate_pass INTEGER NOT NULL, + accurate_final_third_pass INTEGER NOT NULL, + accurate_long_ball INTEGER NOT NULL, + long_pass_into_opposition INTEGER NOT NULL, + missed_pass INTEGER NOT NULL, + shot_on_target INTEGER NOT NULL, + won_contest INTEGER NOT NULL, + big_chance_created INTEGER NOT NULL, + attempted_assist INTEGER NOT NULL, + penalty_area_entries INTEGER NOT NULL, + penalty_kick_missed INTEGER NOT NULL, + big_chance_missed INTEGER NOT NULL + ); + + COMMIT; + +-- +goose Down + DROP TABLE IF EXISTS game_player_scores; + + DROP INDEX IF EXISTS idx_game_players_game_id_team_slug; + + DROP TABLE IF EXISTS game_players; + + DROP TABLE IF EXISTS players; + + DROP TABLE IF EXISTS games; + + DROP TABLE IF EXISTS teams; + + DROP TABLE IF EXISTS fixtures; + + DROP TABLE IF EXISTS competitions; + + DROP TABLE IF EXISTS countries; + + DROP TABLE IF EXISTS zones; \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..bb9c320 --- /dev/null +++ b/go.mod @@ -0,0 +1,55 @@ +module git.lehouerou.net/laurent/sorarebuddy + +go 1.22.1 + +require ( + github.com/jackc/pgx/v5 v5.5.5 + github.com/shopspring/decimal v1.3.1 + github.com/spf13/cobra v1.8.0 + github.com/spf13/viper v1.18.2 +) + +require ( + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-retryablehttp v0.7.5 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/klauspost/compress v1.17.0 // indirect + github.com/llehouerou/go-graphql-client v0.9.6 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/xlzd/gotp v0.1.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/time v0.5.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + nhooyr.io/websocket v1.8.7 // indirect +) + +require ( + git.lehouerou.net/laurent/sorare v0.0.0-20240308104821-b99d85580526 + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect + github.com/pkg/errors v0.9.1 + github.com/rs/zerolog v1.32.0 + github.com/samber/lo v1.39.0 + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/text v0.14.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..70cf21a --- /dev/null +++ b/go.sum @@ -0,0 +1,191 @@ +git.lehouerou.net/laurent/sorare v0.0.0-20240308104821-b99d85580526 h1:/qgeHqVliEYKynyyDEnS45e6I8uS7bAFkw1ucpQ3D8I= +git.lehouerou.net/laurent/sorare v0.0.0-20240308104821-b99d85580526/go.mod h1:s/kVH8wu+esjAd1Zw+8+UGovg5hVClZp+9lFu7ZXsbI= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMNMPSVXA1yc= +github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= +github.com/graph-gophers/graphql-transport-ws v0.0.2 h1:DbmSkbIGzj8SvHei6n8Mh9eLQin8PtA8xY9eCzjRpvo= +github.com/graph-gophers/graphql-transport-ws v0.0.2/go.mod h1:5BVKvFzOd2BalVIBFfnfmHjpJi/MZ5rOj8G55mXvZ8g= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= +github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= +github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/llehouerou/go-graphql-client v0.9.6 h1:tZdCHrBz8p044KoxXwmEur9L4VNZ3luYeJmQZpLodPY= +github.com/llehouerou/go-graphql-client v0.9.6/go.mod h1:hyvnfe3diGLxMelSKF+cFPyAfxZLa1CGGBogmix4SyM= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA= +github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/xlzd/gotp v0.1.0 h1:37blvlKCh38s+fkem+fFh7sMnceltoIEBYTVXyoa5Po= +github.com/xlzd/gotp v0.1.0/go.mod h1:ndLJ3JKzi3xLmUProq4LLxCuECL93dG9WASNLpHz8qg= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= diff --git a/model/competition.sql.go b/model/competition.sql.go new file mode 100644 index 0000000..2deb2fc --- /dev/null +++ b/model/competition.sql.go @@ -0,0 +1,151 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.25.0 +// source: competition.sql + +package model + +import ( + "context" +) + +const createOrUpdateCompetition = `-- name: CreateOrUpdateCompetition :exec + INSERT INTO competitions ( + slug, + display_name, + country_slug, + competition_format, + competition_type, + picture_url, + logo_url + ) + VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT (slug) + DO + UPDATE + SET display_name = EXCLUDED.display_name, + competition_format = EXCLUDED.competition_format, + competition_type = EXCLUDED.competition_type, + picture_url = EXCLUDED.picture_url, + logo_url = EXCLUDED.logo_url, + country_slug = EXCLUDED.country_slug +` + +type CreateOrUpdateCompetitionParams struct { + Slug string + DisplayName string + CountrySlug string + CompetitionFormat string + CompetitionType string + PictureUrl string + LogoUrl string +} + +// Active: 1709890109198@@192.168.1.250@5436@sorare +func (q *Queries) CreateOrUpdateCompetition(ctx context.Context, arg CreateOrUpdateCompetitionParams) error { + _, err := q.db.Exec(ctx, createOrUpdateCompetition, + arg.Slug, + arg.DisplayName, + arg.CountrySlug, + arg.CompetitionFormat, + arg.CompetitionType, + arg.PictureUrl, + arg.LogoUrl, + ) + return err +} + +const getAllCompetitions = `-- name: GetAllCompetitions :many + SELECT competitions.slug, competitions.display_name, competitions.country_slug, competitions.competition_format, competitions.competition_type, competitions.picture_url, competitions.logo_url, competitions.zone_id, + zones.id, zones.display_name, + countries.slug, countries.code, countries.display_name, countries.three_letter_code, countries.flag_flat_64_url, countries.flag_flat_32_url, countries.flag_round_64_url, countries.flag_round_32_url + FROM competitions + LEFT JOIN zones ON competitions.zone_id = zones.id + LEFT JOIN countries ON competitions.country_slug = countries.slug +` + +type GetAllCompetitionsRow struct { + Competition Competition + Zone Zone + Country Country +} + +func (q *Queries) GetAllCompetitions(ctx context.Context) ([]GetAllCompetitionsRow, error) { + rows, err := q.db.Query(ctx, getAllCompetitions) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetAllCompetitionsRow + for rows.Next() { + var i GetAllCompetitionsRow + if err := rows.Scan( + &i.Competition.Slug, + &i.Competition.DisplayName, + &i.Competition.CountrySlug, + &i.Competition.CompetitionFormat, + &i.Competition.CompetitionType, + &i.Competition.PictureUrl, + &i.Competition.LogoUrl, + &i.Competition.ZoneID, + &i.Zone.ID, + &i.Zone.DisplayName, + &i.Country.Slug, + &i.Country.Code, + &i.Country.DisplayName, + &i.Country.ThreeLetterCode, + &i.Country.FlagFlat64Url, + &i.Country.FlagFlat32Url, + &i.Country.FlagRound64Url, + &i.Country.FlagRound32Url, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getCompetitionBySlug = `-- name: GetCompetitionBySlug :one + SELECT competitions.slug, competitions.display_name, competitions.country_slug, competitions.competition_format, competitions.competition_type, competitions.picture_url, competitions.logo_url, competitions.zone_id, + zones.id, zones.display_name, + countries.slug, countries.code, countries.display_name, countries.three_letter_code, countries.flag_flat_64_url, countries.flag_flat_32_url, countries.flag_round_64_url, countries.flag_round_32_url + FROM competitions + LEFT JOIN zones ON competitions.zone_id = zones.id + LEFT JOIN countries ON competitions.country_slug = countries.slug + WHERE competitions.slug = $1 +` + +type GetCompetitionBySlugRow struct { + Competition Competition + Zone Zone + Country Country +} + +func (q *Queries) GetCompetitionBySlug(ctx context.Context, slug string) (GetCompetitionBySlugRow, error) { + row := q.db.QueryRow(ctx, getCompetitionBySlug, slug) + var i GetCompetitionBySlugRow + err := row.Scan( + &i.Competition.Slug, + &i.Competition.DisplayName, + &i.Competition.CountrySlug, + &i.Competition.CompetitionFormat, + &i.Competition.CompetitionType, + &i.Competition.PictureUrl, + &i.Competition.LogoUrl, + &i.Competition.ZoneID, + &i.Zone.ID, + &i.Zone.DisplayName, + &i.Country.Slug, + &i.Country.Code, + &i.Country.DisplayName, + &i.Country.ThreeLetterCode, + &i.Country.FlagFlat64Url, + &i.Country.FlagFlat32Url, + &i.Country.FlagRound64Url, + &i.Country.FlagRound32Url, + ) + return i, err +} diff --git a/model/copyfrom.go b/model/copyfrom.go new file mode 100644 index 0000000..a4da5b9 --- /dev/null +++ b/model/copyfrom.go @@ -0,0 +1,175 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.25.0 +// source: copyfrom.go + +package model + +import ( + "context" +) + +// iteratorForCreateCountries implements pgx.CopyFromSource. +type iteratorForCreateCountries struct { + rows []CreateCountriesParams + skippedFirstNextCall bool +} + +func (r *iteratorForCreateCountries) Next() bool { + if len(r.rows) == 0 { + return false + } + if !r.skippedFirstNextCall { + r.skippedFirstNextCall = true + return true + } + r.rows = r.rows[1:] + return len(r.rows) > 0 +} + +func (r iteratorForCreateCountries) Values() ([]interface{}, error) { + return []interface{}{ + r.rows[0].Slug, + r.rows[0].Code, + r.rows[0].DisplayName, + r.rows[0].ThreeLetterCode, + r.rows[0].FlagFlat64Url, + r.rows[0].FlagFlat32Url, + r.rows[0].FlagRound64Url, + r.rows[0].FlagRound32Url, + }, nil +} + +func (r iteratorForCreateCountries) Err() error { + return nil +} + +func (q *Queries) CreateCountries(ctx context.Context, arg []CreateCountriesParams) (int64, error) { + return q.db.CopyFrom(ctx, []string{"countries"}, []string{"slug", "code", "display_name", "three_letter_code", "flag_flat_64_url", "flag_flat_32_url", "flag_round_64_url", "flag_round_32_url"}, &iteratorForCreateCountries{rows: arg}) +} + +// iteratorForCreateFixtures implements pgx.CopyFromSource. +type iteratorForCreateFixtures struct { + rows []CreateFixturesParams + skippedFirstNextCall bool +} + +func (r *iteratorForCreateFixtures) Next() bool { + if len(r.rows) == 0 { + return false + } + if !r.skippedFirstNextCall { + r.skippedFirstNextCall = true + return true + } + r.rows = r.rows[1:] + return len(r.rows) > 0 +} + +func (r iteratorForCreateFixtures) Values() ([]interface{}, error) { + return []interface{}{ + r.rows[0].Slug, + r.rows[0].DisplayName, + r.rows[0].State, + r.rows[0].StartDate, + r.rows[0].EndDate, + r.rows[0].GameWeek, + }, nil +} + +func (r iteratorForCreateFixtures) Err() error { + return nil +} + +// Active: 1709890109198@@192.168.1.250@5436@sorare +func (q *Queries) CreateFixtures(ctx context.Context, arg []CreateFixturesParams) (int64, error) { + return q.db.CopyFrom(ctx, []string{"fixtures"}, []string{"slug", "display_name", "state", "start_date", "end_date", "game_week"}, &iteratorForCreateFixtures{rows: arg}) +} + +// iteratorForCreateGames implements pgx.CopyFromSource. +type iteratorForCreateGames struct { + rows []CreateGamesParams + skippedFirstNextCall bool +} + +func (r *iteratorForCreateGames) Next() bool { + if len(r.rows) == 0 { + return false + } + if !r.skippedFirstNextCall { + r.skippedFirstNextCall = true + return true + } + r.rows = r.rows[1:] + return len(r.rows) > 0 +} + +func (r iteratorForCreateGames) Values() ([]interface{}, error) { + return []interface{}{ + r.rows[0].ID, + r.rows[0].Date, + r.rows[0].CoverageStatus, + r.rows[0].LowCoverage, + r.rows[0].Minutes, + r.rows[0].PeriodType, + r.rows[0].Scored, + r.rows[0].Status, + r.rows[0].CompetitionSlug, + r.rows[0].FixtureSlug, + r.rows[0].AwayTeamSlug, + r.rows[0].AwayGoals, + r.rows[0].AwayExtraTimeScore, + r.rows[0].AwayPenaltyScore, + r.rows[0].HomeTeamSlug, + r.rows[0].HomeGoals, + r.rows[0].HomeExtraTimeScore, + r.rows[0].HomePenaltyScore, + r.rows[0].WinnerTeamSlug, + }, nil +} + +func (r iteratorForCreateGames) Err() error { + return nil +} + +func (q *Queries) CreateGames(ctx context.Context, arg []CreateGamesParams) (int64, error) { + return q.db.CopyFrom(ctx, []string{"games"}, []string{"id", "date", "coverage_status", "low_coverage", "minutes", "period_type", "scored", "status", "competition_slug", "fixture_slug", "away_team_slug", "away_goals", "away_extra_time_score", "away_penalty_score", "home_team_slug", "home_goals", "home_extra_time_score", "home_penalty_score", "winner_team_slug"}, &iteratorForCreateGames{rows: arg}) +} + +// iteratorForCreateTeams implements pgx.CopyFromSource. +type iteratorForCreateTeams struct { + rows []CreateTeamsParams + skippedFirstNextCall bool +} + +func (r *iteratorForCreateTeams) Next() bool { + if len(r.rows) == 0 { + return false + } + if !r.skippedFirstNextCall { + r.skippedFirstNextCall = true + return true + } + r.rows = r.rows[1:] + return len(r.rows) > 0 +} + +func (r iteratorForCreateTeams) Values() ([]interface{}, error) { + return []interface{}{ + r.rows[0].Slug, + r.rows[0].DisplayName, + r.rows[0].CountrySlug, + r.rows[0].DomesticLeagueSlug, + r.rows[0].ShortName, + r.rows[0].PictureUrl, + r.rows[0].TeamType, + }, nil +} + +func (r iteratorForCreateTeams) Err() error { + return nil +} + +func (q *Queries) CreateTeams(ctx context.Context, arg []CreateTeamsParams) (int64, error) { + return q.db.CopyFrom(ctx, []string{"teams"}, []string{"slug", "display_name", "country_slug", "domestic_league_slug", "short_name", "picture_url", "team_type"}, &iteratorForCreateTeams{rows: arg}) +} diff --git a/model/country.sql.go b/model/country.sql.go new file mode 100644 index 0000000..e6ad665 --- /dev/null +++ b/model/country.sql.go @@ -0,0 +1,69 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.25.0 +// source: country.sql + +package model + +import ( + "context" +) + +type CreateCountriesParams struct { + Slug string + Code string + DisplayName string + ThreeLetterCode string + FlagFlat64Url string + FlagFlat32Url string + FlagRound64Url string + FlagRound32Url string +} + +const createOrUpdateCountry = `-- name: CreateOrUpdateCountry :exec + INSERT INTO countries ( + slug, + code, + display_name, + three_letter_code, + flag_flat_64_url, + flag_flat_32_url, + flag_round_64_url, + flag_round_32_url + ) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) ON CONFLICT (slug) + DO + UPDATE + SET code = EXCLUDED.code, + display_name = EXCLUDED.display_name, + three_letter_code = EXCLUDED.three_letter_code, + flag_flat_64_url = EXCLUDED.flag_flat_64_url, + flag_flat_32_url = EXCLUDED.flag_flat_32_url, + flag_round_64_url = EXCLUDED.flag_round_64_url, + flag_round_32_url = EXCLUDED.flag_round_32_url +` + +type CreateOrUpdateCountryParams struct { + Slug string + Code string + DisplayName string + ThreeLetterCode string + FlagFlat64Url string + FlagFlat32Url string + FlagRound64Url string + FlagRound32Url string +} + +func (q *Queries) CreateOrUpdateCountry(ctx context.Context, arg CreateOrUpdateCountryParams) error { + _, err := q.db.Exec(ctx, createOrUpdateCountry, + arg.Slug, + arg.Code, + arg.DisplayName, + arg.ThreeLetterCode, + arg.FlagFlat64Url, + arg.FlagFlat32Url, + arg.FlagRound64Url, + arg.FlagRound32Url, + ) + return err +} diff --git a/model/db.go b/model/db.go new file mode 100644 index 0000000..38ffa40 --- /dev/null +++ b/model/db.go @@ -0,0 +1,33 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.25.0 + +package model + +import ( + "context" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" +) + +type DBTX interface { + Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) + Query(context.Context, string, ...interface{}) (pgx.Rows, error) + QueryRow(context.Context, string, ...interface{}) pgx.Row + CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error) +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx pgx.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/model/fixture.sql.go b/model/fixture.sql.go new file mode 100644 index 0000000..112f019 --- /dev/null +++ b/model/fixture.sql.go @@ -0,0 +1,116 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.25.0 +// source: fixture.sql + +package model + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +type CreateFixturesParams struct { + Slug string + DisplayName string + State string + StartDate pgtype.Timestamptz + EndDate pgtype.Timestamptz + GameWeek int32 +} + +const createOrUpdateFixture = `-- name: CreateOrUpdateFixture :exec +INSERT INTO fixtures (slug, display_name, state, start_date, end_date, game_week) +VALUES ($1, $2, $3, $4, $5, $6) +ON CONFLICT (slug) DO UPDATE +SET display_name = $2, state = $3, start_date = $4, end_date = $5, game_week = $6 +` + +type CreateOrUpdateFixtureParams struct { + Slug string + DisplayName string + State string + StartDate pgtype.Timestamptz + EndDate pgtype.Timestamptz + GameWeek int32 +} + +func (q *Queries) CreateOrUpdateFixture(ctx context.Context, arg CreateOrUpdateFixtureParams) error { + _, err := q.db.Exec(ctx, createOrUpdateFixture, + arg.Slug, + arg.DisplayName, + arg.State, + arg.StartDate, + arg.EndDate, + arg.GameWeek, + ) + return err +} + +const getAllFixtures = `-- name: GetAllFixtures :many +SELECT slug, display_name, state, start_date, end_date, game_week FROM fixtures +` + +func (q *Queries) GetAllFixtures(ctx context.Context) ([]Fixture, error) { + rows, err := q.db.Query(ctx, getAllFixtures) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Fixture + for rows.Next() { + var i Fixture + if err := rows.Scan( + &i.Slug, + &i.DisplayName, + &i.State, + &i.StartDate, + &i.EndDate, + &i.GameWeek, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getFixtureByGameWeek = `-- name: GetFixtureByGameWeek :one +SELECT slug, display_name, state, start_date, end_date, game_week FROM fixtures WHERE game_week = $1 +` + +func (q *Queries) GetFixtureByGameWeek(ctx context.Context, gameWeek int32) (Fixture, error) { + row := q.db.QueryRow(ctx, getFixtureByGameWeek, gameWeek) + var i Fixture + err := row.Scan( + &i.Slug, + &i.DisplayName, + &i.State, + &i.StartDate, + &i.EndDate, + &i.GameWeek, + ) + return i, err +} + +const getFixtureBySlug = `-- name: GetFixtureBySlug :one +SELECT slug, display_name, state, start_date, end_date, game_week FROM fixtures WHERE slug = $1 +` + +func (q *Queries) GetFixtureBySlug(ctx context.Context, slug string) (Fixture, error) { + row := q.db.QueryRow(ctx, getFixtureBySlug, slug) + var i Fixture + err := row.Scan( + &i.Slug, + &i.DisplayName, + &i.State, + &i.StartDate, + &i.EndDate, + &i.GameWeek, + ) + return i, err +} diff --git a/model/game.sql.go b/model/game.sql.go new file mode 100644 index 0000000..c082fad --- /dev/null +++ b/model/game.sql.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.25.0 +// source: game.sql + +package model + +import ( + "github.com/jackc/pgx/v5/pgtype" +) + +type CreateGamesParams struct { + ID string + Date pgtype.Timestamptz + CoverageStatus string + LowCoverage bool + Minutes int32 + PeriodType string + Scored bool + Status string + CompetitionSlug string + FixtureSlug string + AwayTeamSlug string + AwayGoals int32 + AwayExtraTimeScore int32 + AwayPenaltyScore int32 + HomeTeamSlug string + HomeGoals int32 + HomeExtraTimeScore int32 + HomePenaltyScore int32 + WinnerTeamSlug *string +} diff --git a/model/models.go b/model/models.go new file mode 100644 index 0000000..61dfd7f --- /dev/null +++ b/model/models.go @@ -0,0 +1,164 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.25.0 + +package model + +import ( + "time" + + "github.com/jackc/pgx/v5/pgtype" + "github.com/shopspring/decimal" +) + +type Competition struct { + Slug string + DisplayName string + CountrySlug string + CompetitionFormat string + CompetitionType string + PictureUrl string + LogoUrl string + ZoneID *int32 +} + +type Country struct { + Slug string + Code string + DisplayName string + ThreeLetterCode string + FlagFlat64Url string + FlagFlat32Url string + FlagRound64Url string + FlagRound32Url string +} + +type Fixture struct { + Slug string + DisplayName string + State string + StartDate time.Time + EndDate time.Time + GameWeek int32 +} + +type Game struct { + ID string + Date pgtype.Timestamptz + CoverageStatus string + LowCoverage bool + Minutes int32 + PeriodType string + Scored bool + Status string + CompetitionSlug string + FixtureSlug string + AwayTeamSlug string + AwayGoals int32 + AwayExtraTimeScore int32 + AwayPenaltyScore int32 + HomeTeamSlug string + HomeGoals int32 + HomeExtraTimeScore int32 + HomePenaltyScore int32 + WinnerTeamSlug *string +} + +type GamePlayer struct { + GameID string + PlayerSlug string + Status string + TeamSlug string +} + +type GamePlayerScore struct { + GameID string + PlayerSlug string + Score decimal.Decimal + DecisiveScore decimal.Decimal + AllAroundScore decimal.Decimal + MinutesPlayed int32 + GameStarted bool + FormationPlace int32 + Live bool + OnGameSheet bool + Reviewed bool + Goal int32 + Assist int32 + PenaltyWon int32 + ClearanceOffLine int32 + LastManTackle int32 + PenaltySave int32 + OwnGoal int32 + RedCard bool + ErrorLeadToGoal int32 + PenaltyConceded int32 + YellowCard int32 + Fouls int32 + Fouled int32 + CleanSheet bool + DoubleDouble bool + TripleDouble bool + TripleTriple bool + ErrorLeadToShot int32 + Saves int32 + SavedShotFromInsideBox int32 + GoodHighClaim int32 + Punches int32 + DivingSave int32 + DivingCatch int32 + CrossNotClaimed int32 + GoalkeeperSmother int32 + SixSecondViolation int32 + KeeperSweeper int32 + GoalsConceded int32 + EffectiveClearance int32 + WonTackle int32 + BlockedCross int32 + Block int32 + PossessionLost int32 + PossessionWon int32 + DuelLost int32 + DuelWon int32 + Interception int32 + AccuratePass int32 + AccurateFinalThirdPass int32 + AccurateLongBall int32 + LongPassIntoOpposition int32 + MissedPass int32 + ShotOnTarget int32 + WonContest int32 + BigChanceCreated int32 + AttemptedAssist int32 + PenaltyAreaEntries int32 + PenaltyKickMissed int32 + BigChanceMissed int32 +} + +type Player struct { + Slug string + DisplayName string + BirthDate time.Time + CountrySlug string + TeamSlug string + DomesticLeagueSlug string + AvatarUrl string + FieldPosition string + Status string + ShirtNumber int32 +} + +type Team struct { + Slug string + DisplayName string + CountrySlug string + DomesticLeagueSlug *string + ShortName string + PictureUrl string + TeamType string +} + +type Zone struct { + ID int32 + DisplayName string +} diff --git a/model/sql/competition.sql b/model/sql/competition.sql new file mode 100644 index 0000000..d020a67 --- /dev/null +++ b/model/sql/competition.sql @@ -0,0 +1,39 @@ +-- name: CreateOrUpdateCompetition :exec + INSERT INTO competitions ( + slug, + display_name, + country_slug, + competition_format, + competition_type, + picture_url, + logo_url + ) + VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT (slug) + DO + UPDATE + SET display_name = EXCLUDED.display_name, + competition_format = EXCLUDED.competition_format, + competition_type = EXCLUDED.competition_type, + picture_url = EXCLUDED.picture_url, + logo_url = EXCLUDED.logo_url, + country_slug = EXCLUDED.country_slug; + +-- name: GetCompetitionBySlug :one + SELECT sqlc.embed(competitions), + sqlc.embed(zones), + sqlc.embed(countries) + FROM competitions + LEFT JOIN zones ON competitions.zone_id = zones.id + LEFT JOIN countries ON competitions.country_slug = countries.slug + WHERE competitions.slug = $1; + + +-- name: GetAllCompetitions :many + SELECT sqlc.embed(competitions), + sqlc.embed(zones), + sqlc.embed(countries) + FROM competitions + LEFT JOIN zones ON competitions.zone_id = zones.id + LEFT JOIN countries ON competitions.country_slug = countries.slug; + + diff --git a/model/sql/country.sql b/model/sql/country.sql new file mode 100644 index 0000000..77514b8 --- /dev/null +++ b/model/sql/country.sql @@ -0,0 +1,34 @@ +-- name: CreateCountries :copyfrom +INSERT INTO countries ( + slug, + code, + display_name, + three_letter_code, + flag_flat_64_url, + flag_flat_32_url, + flag_round_64_url, + flag_round_32_url + ) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8); + +-- name: CreateOrUpdateCountry :exec + INSERT INTO countries ( + slug, + code, + display_name, + three_letter_code, + flag_flat_64_url, + flag_flat_32_url, + flag_round_64_url, + flag_round_32_url + ) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) ON CONFLICT (slug) + DO + UPDATE + SET code = EXCLUDED.code, + display_name = EXCLUDED.display_name, + three_letter_code = EXCLUDED.three_letter_code, + flag_flat_64_url = EXCLUDED.flag_flat_64_url, + flag_flat_32_url = EXCLUDED.flag_flat_32_url, + flag_round_64_url = EXCLUDED.flag_round_64_url, + flag_round_32_url = EXCLUDED.flag_round_32_url; diff --git a/model/sql/fixture.sql b/model/sql/fixture.sql new file mode 100644 index 0000000..a1f5980 --- /dev/null +++ b/model/sql/fixture.sql @@ -0,0 +1,23 @@ +-- Active: 1709890109198@@192.168.1.250@5436@sorare +-- name: CreateFixtures :copyfrom +INSERT INTO fixtures (slug, display_name, state, start_date, end_date, game_week) +VALUES ($1, $2, $3, $4, $5, $6); + +-- name: CreateOrUpdateFixture :exec +INSERT INTO fixtures (slug, display_name, state, start_date, end_date, game_week) +VALUES ($1, $2, $3, $4, $5, $6) +ON CONFLICT (slug) DO UPDATE +SET display_name = $2, state = $3, start_date = $4, end_date = $5, game_week = $6; + +-- name: GetFixtureBySlug :one +SELECT * FROM fixtures WHERE slug = $1; + +-- name: GetFixtureByGameWeek :one +SELECT * FROM fixtures WHERE game_week = $1; + +-- name: GetAllFixtures :many +SELECT * FROM fixtures; + + + + diff --git a/model/sql/game.sql b/model/sql/game.sql new file mode 100644 index 0000000..60d07f0 --- /dev/null +++ b/model/sql/game.sql @@ -0,0 +1,4 @@ +-- name: CreateGames :copyfrom +INSERT INTO games (id, date, coverage_status, low_coverage, minutes, period_type, scored, status, competition_slug, fixture_slug, away_team_slug, away_goals, away_extra_time_score, away_penalty_score, home_team_slug, home_goals, home_extra_time_score, home_penalty_score, winner_team_slug) +VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19); + diff --git a/model/sql/team.sql b/model/sql/team.sql new file mode 100644 index 0000000..c82c820 --- /dev/null +++ b/model/sql/team.sql @@ -0,0 +1,3 @@ +-- name: CreateTeams :copyfrom +INSERT INTO teams (slug, display_name, country_slug, domestic_league_slug, short_name, picture_url, team_type) +VALUES ($1, $2, $3, $4, $5, $6, $7); diff --git a/model/sql/test.sql b/model/sql/test.sql new file mode 100644 index 0000000..c9fedec --- /dev/null +++ b/model/sql/test.sql @@ -0,0 +1,2 @@ +select * from competitions +join games on games.id = competitions.game_id diff --git a/model/sql/zone.sql b/model/sql/zone.sql new file mode 100644 index 0000000..d844a2d --- /dev/null +++ b/model/sql/zone.sql @@ -0,0 +1,2 @@ +-- name: CountZones :one +SELECT COUNT(*) FROM zones; \ No newline at end of file diff --git a/model/team.sql.go b/model/team.sql.go new file mode 100644 index 0000000..11ffca3 --- /dev/null +++ b/model/team.sql.go @@ -0,0 +1,18 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.25.0 +// source: team.sql + +package model + +import () + +type CreateTeamsParams struct { + Slug string + DisplayName string + CountrySlug string + DomesticLeagueSlug *string + ShortName string + PictureUrl string + TeamType string +} diff --git a/model/zone.sql.go b/model/zone.sql.go new file mode 100644 index 0000000..c110f6d --- /dev/null +++ b/model/zone.sql.go @@ -0,0 +1,21 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.25.0 +// source: zone.sql + +package model + +import ( + "context" +) + +const countZones = `-- name: CountZones :one +SELECT COUNT(*) FROM zones +` + +func (q *Queries) CountZones(ctx context.Context) (int64, error) { + row := q.db.QueryRow(ctx, countZones) + var count int64 + err := row.Scan(&count) + return count, err +} diff --git a/sqlc.yml b/sqlc.yml new file mode 100644 index 0000000..dda9f27 --- /dev/null +++ b/sqlc.yml @@ -0,0 +1,25 @@ +version: "2" +sql: + - engine: "postgresql" + queries: "model/sql/*.sql" + schema: "db/migrations" + database: + uri: postgresql://sorare:sorare@192.168.1.250:5436/sorare?sslmode=disable + gen: + go: + package: "model" + out: "model" + sql_package: "pgx/v5" + emit_pointers_for_null_types: true + overrides: + - db_type: "timestamptz" + go_type: "time.Time" + - db_type: "date" + go_type: "time.Time" + - db_type: "pg_catalog.numeric" + go_type: + import: "github.com/shopspring/decimal" + type: "Decimal" + + +