124 lines
3.6 KiB
Go
124 lines
3.6 KiB
Go
package db
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/uptrace/bun"
|
|
)
|
|
|
|
type Player struct {
|
|
bun.BaseModel `bun:"table:players,alias:p"`
|
|
|
|
ID int `bun:"id,pk,autoincrement" json:"id"`
|
|
SlapID *uint32 `bun:"slap_id,unique" json:"slap_id"`
|
|
DiscordID string `bun:"discord_id,unique,notnull" json:"discord_id"`
|
|
UserID *int `bun:"user_id,unique" json:"user_id"`
|
|
Name string `bun:"name,notnull" json:"name"`
|
|
|
|
User *User `bun:"rel:belongs-to,join:user_id=id" json:"-"`
|
|
}
|
|
|
|
func (p *Player) DisplayName() string {
|
|
if p.User != nil {
|
|
return p.User.Username
|
|
}
|
|
return p.Name
|
|
}
|
|
|
|
// NewPlayer creates a new player in the database. If there is an existing user with the same
|
|
// discordID, it will automatically link that user to the player
|
|
func NewPlayer(ctx context.Context, tx bun.Tx, name, discordID string, audit *AuditMeta) (*Player, error) {
|
|
player := &Player{DiscordID: discordID, Name: name}
|
|
user, err := GetUserByDiscordID(ctx, tx, discordID)
|
|
if err != nil && !IsBadRequest(err) {
|
|
return nil, errors.Wrap(err, "GetUserByDiscordID")
|
|
}
|
|
if user != nil {
|
|
player.UserID = &user.ID
|
|
player.Name = user.Username
|
|
}
|
|
err = Insert(tx, player).
|
|
WithAudit(audit, nil).Exec(ctx)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "Insert")
|
|
}
|
|
return player, nil
|
|
}
|
|
|
|
func NewPlayerFromLog(ctx context.Context, tx bun.Tx, name string, slapID uint32, audit *AuditMeta) (*Player, error) {
|
|
player := &Player{Name: name, SlapID: &slapID}
|
|
err := Insert(tx, player).
|
|
WithAudit(audit, nil).Exec(ctx)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "Insert")
|
|
}
|
|
return player, nil
|
|
}
|
|
|
|
// ConnectPlayer links the user to an existing player, or creates a new player to link if not found
|
|
// Populates User.Player on success
|
|
func (u *User) ConnectPlayer(ctx context.Context, tx bun.Tx, audit *AuditMeta) error {
|
|
player, err := GetByField[Player](tx, "p.discord_id", u.DiscordID).
|
|
Relation("User").Get(ctx)
|
|
if err != nil {
|
|
if !IsBadRequest(err) {
|
|
// Unexpected error occured
|
|
return errors.Wrap(err, "GetByField")
|
|
}
|
|
// Player doesn't exist, create a new one
|
|
player, err = NewPlayer(ctx, tx, u.Username, u.DiscordID, audit)
|
|
if err != nil {
|
|
return errors.Wrap(err, "NewPlayer")
|
|
}
|
|
// New player should automatically get linked to the user
|
|
u.Player = player
|
|
return nil
|
|
}
|
|
// Player was found
|
|
if player.UserID != nil {
|
|
if player.UserID == &u.ID {
|
|
return nil
|
|
}
|
|
return errors.New("player with that discord_id already linked to a user")
|
|
}
|
|
player.UserID = &u.ID
|
|
err = UpdateByID(tx, player.ID, player).Column("user_id").Exec(ctx)
|
|
if err != nil {
|
|
return errors.Wrap(err, "UpdateByID")
|
|
}
|
|
u.Player = player
|
|
return nil
|
|
}
|
|
|
|
func GetPlayer(ctx context.Context, tx bun.Tx, playerID int) (*Player, error) {
|
|
return GetByID[Player](tx, playerID).Relation("User").Get(ctx)
|
|
}
|
|
|
|
func UpdatePlayerSlapID(ctx context.Context, tx bun.Tx, playerID int, slapID uint32, audit *AuditMeta) error {
|
|
player, err := GetPlayer(ctx, tx, playerID)
|
|
if err != nil {
|
|
return errors.Wrap(err, "GetPlayer")
|
|
}
|
|
player.SlapID = &slapID
|
|
err = UpdateByID(tx, player.ID, player).Column("slap_id").
|
|
WithAudit(audit, nil).Exec(ctx)
|
|
if err != nil {
|
|
return errors.Wrap(err, "UpdateByID")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func GetPlayersNotOnTeam(ctx context.Context, tx bun.Tx, seasonID, leagueID int) ([]*Player, error) {
|
|
players, err := GetList[Player](tx).Relation("User").
|
|
Join("LEFT JOIN team_rosters tr ON tr.player_id = p.id").
|
|
Where("NOT (tr.season_id = ? and tr.league_id = ?) OR (tr.season_id IS NULL and tr.league_id IS NULL)",
|
|
seasonID, leagueID).
|
|
Order("p.name ASC").
|
|
GetAll(ctx)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "GetList")
|
|
}
|
|
return players, nil
|
|
}
|