135 lines
3.6 KiB
Go
135 lines
3.6 KiB
Go
package bundb
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
|
|
"gitea.dwysokinski.me/twhelp/core/internal/domain"
|
|
"github.com/uptrace/bun"
|
|
)
|
|
|
|
var (
|
|
villageMetaColumns = []string{"id", "name", "x", "y", "continent", "profile_url"}
|
|
villageOrders = []string{"village.server_key ASC", "village.id ASC"}
|
|
)
|
|
|
|
type Village struct {
|
|
db *bun.DB
|
|
}
|
|
|
|
func NewVillage(db *bun.DB) *Village {
|
|
return &Village{db: db}
|
|
}
|
|
|
|
func (v *Village) CreateOrUpdate(ctx context.Context, params ...domain.CreateVillageParams) error {
|
|
if len(params) == 0 {
|
|
return nil
|
|
}
|
|
|
|
villages := make([]model.Village, 0, len(params))
|
|
for _, p := range params {
|
|
villages = append(villages, model.NewVillage(p))
|
|
}
|
|
if _, err := v.db.NewInsert().
|
|
Model(&villages).
|
|
On("CONFLICT ON CONSTRAINT villages_pkey DO UPDATE").
|
|
Set("name = EXCLUDED.name").
|
|
Set("points = EXCLUDED.points").
|
|
Set("x = EXCLUDED.x").
|
|
Set("y = EXCLUDED.y").
|
|
Set("continent = EXCLUDED.continent").
|
|
Set("bonus = EXCLUDED.bonus").
|
|
Set("player_id = EXCLUDED.player_id").
|
|
Set("profile_url = EXCLUDED.profile_url").
|
|
Returning("NULL").
|
|
Exec(ctx); err != nil {
|
|
return fmt.Errorf("something went wrong while inserting villages into the db: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (v *Village) List(ctx context.Context, params domain.ListVillagesParams) ([]domain.Village, error) {
|
|
var villages []model.Village
|
|
|
|
err := v.db.NewSelect().
|
|
Model(&villages).
|
|
Order(villageOrders...).
|
|
Apply(listVillagesParamsApplier{params}.apply).
|
|
Scan(ctx)
|
|
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
|
return nil, fmt.Errorf("couldn't select villages from the db: %w", err)
|
|
}
|
|
|
|
result := make([]domain.Village, 0, len(villages))
|
|
for _, village := range villages {
|
|
result = append(result, village.ToDomain())
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (v *Village) ListCountWithRelations(ctx context.Context, params domain.ListVillagesParams) ([]domain.VillageWithRelations, int64, error) {
|
|
var villages []model.Village
|
|
|
|
paramsApplier := listVillagesParamsApplier{params}
|
|
|
|
cntQ := v.db.NewSelect().
|
|
Model(&model.Village{}).
|
|
Apply(paramsApplier.applyFilters)
|
|
|
|
q := v.db.NewSelect().
|
|
Model(&villages).
|
|
Where("(village.id, village.server_key) IN (?)", v.db.NewSelect().
|
|
Column("id", "server_key").
|
|
Model(&model.Village{}).
|
|
Order(villageOrders...).
|
|
Apply(paramsApplier.apply)).
|
|
Order(villageOrders...).
|
|
Relation("Player", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.Column(playerMetaColumns...)
|
|
}).
|
|
Relation("Player.Tribe", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.Column(tribeMetaColumns...)
|
|
})
|
|
|
|
count, err := scanAndCount(ctx, cntQ, q)
|
|
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
|
return nil, 0, fmt.Errorf("couldn't select villages from the db: %w", err)
|
|
}
|
|
|
|
result := make([]domain.VillageWithRelations, 0, len(villages))
|
|
for _, village := range villages {
|
|
result = append(result, village.ToDomainWithRelations())
|
|
}
|
|
|
|
return result, int64(count), nil
|
|
}
|
|
|
|
type listVillagesParamsApplier struct {
|
|
params domain.ListVillagesParams
|
|
}
|
|
|
|
func (l listVillagesParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.Apply(l.applyPagination).Apply(l.applyFilters)
|
|
}
|
|
|
|
func (l listVillagesParamsApplier) applyFilters(q *bun.SelectQuery) *bun.SelectQuery {
|
|
if len(l.params.IDs) > 0 {
|
|
q = q.Where("village.id IN (?)", bun.In(l.params.IDs))
|
|
}
|
|
|
|
if len(l.params.ServerKeys) > 0 {
|
|
q = q.Where("village.server_key IN (?)", bun.In(l.params.ServerKeys))
|
|
}
|
|
|
|
return q
|
|
}
|
|
|
|
func (l listVillagesParamsApplier) applyPagination(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return (paginationApplier{pagination: l.params.Pagination}).apply(q)
|
|
}
|