add 2 new queries - SearchTribe and SearchPlayer + bump github.com/tribalwarshelp/shared
This commit is contained in:
parent
5aae1ca92f
commit
4bccaab85d
2
go.mod
2
go.mod
|
@ -16,7 +16,7 @@ require (
|
|||
github.com/pkg/errors v0.9.1
|
||||
github.com/segmentio/encoding v0.1.14 // indirect
|
||||
github.com/tribalwarshelp/map-generator v0.0.0-20200801113621-fb8892ceb243
|
||||
github.com/tribalwarshelp/shared v0.0.0-20201107073846-5e8e2d44d75c
|
||||
github.com/tribalwarshelp/shared v0.0.0-20201225102309-31dd9dda110c
|
||||
github.com/vektah/gqlparser/v2 v2.1.0
|
||||
go.opentelemetry.io/otel v0.9.0 // indirect
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
|
||||
|
|
2
go.sum
2
go.sum
|
@ -204,6 +204,8 @@ github.com/tribalwarshelp/shared v0.0.0-20201106181031-7c5891c02013 h1:6KWK3MWsT
|
|||
github.com/tribalwarshelp/shared v0.0.0-20201106181031-7c5891c02013/go.mod h1:Lxk6zaQhPTPrgz9ksMgg51m8XgflrCo/kRBx2cM3yfk=
|
||||
github.com/tribalwarshelp/shared v0.0.0-20201107073846-5e8e2d44d75c h1:Lgqaf1a5zBpCGlA3O0k/jTChI0nvYlXj882iQK2fFT4=
|
||||
github.com/tribalwarshelp/shared v0.0.0-20201107073846-5e8e2d44d75c/go.mod h1:Lxk6zaQhPTPrgz9ksMgg51m8XgflrCo/kRBx2cM3yfk=
|
||||
github.com/tribalwarshelp/shared v0.0.0-20201225102309-31dd9dda110c h1:ArwHE/mF3yaOhM/XMYnlh8bCOcsQeOwOfA3SJWOIlhM=
|
||||
github.com/tribalwarshelp/shared v0.0.0-20201225102309-31dd9dda110c/go.mod h1:Lxk6zaQhPTPrgz9ksMgg51m8XgflrCo/kRBx2cM3yfk=
|
||||
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=
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -21,6 +21,16 @@ type EnnoblementList struct {
|
|||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
type FoundPlayerList struct {
|
||||
Items []*models.FoundPlayer `json:"items"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
type FoundTribeList struct {
|
||||
Items []*models.FoundTribe `json:"items"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
type PlayerHistory struct {
|
||||
Total int `json:"total"`
|
||||
Items []*models.PlayerHistory `json:"items"`
|
||||
|
|
|
@ -67,10 +67,14 @@ models:
|
|||
model: github.com/tribalwarshelp/shared/models.Player
|
||||
PlayerFilter:
|
||||
model: github.com/tribalwarshelp/shared/models.PlayerFilter
|
||||
FoundPlayer:
|
||||
model: github.com/tribalwarshelp/shared/models.FoundPlayer
|
||||
Tribe:
|
||||
model: github.com/tribalwarshelp/shared/models.Tribe
|
||||
TribeFilter:
|
||||
model: github.com/tribalwarshelp/shared/models.TribeFilter
|
||||
FoundTribe:
|
||||
model: github.com/tribalwarshelp/shared/models.FoundTribe
|
||||
Village:
|
||||
model: github.com/tribalwarshelp/shared/models.Village
|
||||
VillageFilter:
|
||||
|
|
|
@ -66,3 +66,28 @@ func getTribe(ctx context.Context, id int) *models.Tribe {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func shouldCount(ctx context.Context) bool {
|
||||
count := false
|
||||
for _, field := range graphql.CollectFieldsCtx(ctx, nil) {
|
||||
if field.Name == countField {
|
||||
count = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func safeStrPointer(s *string, def string) string {
|
||||
if s == nil {
|
||||
return def
|
||||
}
|
||||
return *s
|
||||
}
|
||||
|
||||
func safeIntPointer(s *int, def int) int {
|
||||
if s == nil {
|
||||
return def
|
||||
}
|
||||
return *s
|
||||
}
|
||||
|
|
|
@ -77,3 +77,24 @@ func (r *queryResolver) Players(ctx context.Context,
|
|||
func (r *queryResolver) Player(ctx context.Context, server string, id int) (*models.Player, error) {
|
||||
return r.PlayerUcase.GetByID(ctx, server, id)
|
||||
}
|
||||
|
||||
func (r *queryResolver) SearchPlayer(ctx context.Context,
|
||||
version string,
|
||||
name *string,
|
||||
id *int,
|
||||
limit *int,
|
||||
offset *int,
|
||||
sort []string) (*generated.FoundPlayerList, error) {
|
||||
var err error
|
||||
list := &generated.FoundPlayerList{}
|
||||
list.Items, list.Total, err = r.PlayerUcase.SearchPlayer(ctx, player.SearchPlayerConfig{
|
||||
Sort: sort,
|
||||
Limit: safeIntPointer(limit, 0),
|
||||
Offset: safeIntPointer(offset, 0),
|
||||
Version: version,
|
||||
Name: safeStrPointer(name, ""),
|
||||
ID: safeIntPointer(id, 0),
|
||||
Count: shouldCount(ctx),
|
||||
})
|
||||
return list, err
|
||||
}
|
||||
|
|
|
@ -17,6 +17,10 @@ import (
|
|||
"github.com/tribalwarshelp/api/village"
|
||||
)
|
||||
|
||||
const (
|
||||
countField = "total"
|
||||
)
|
||||
|
||||
type Resolver struct {
|
||||
VersionUcase version.Usecase
|
||||
ServerUcase server.Usecase
|
||||
|
|
|
@ -39,3 +39,22 @@ func (r *queryResolver) Tribes(ctx context.Context,
|
|||
func (r *queryResolver) Tribe(ctx context.Context, server string, id int) (*models.Tribe, error) {
|
||||
return r.TribeUcase.GetByID(ctx, server, id)
|
||||
}
|
||||
|
||||
func (r *queryResolver) SearchTribe(ctx context.Context,
|
||||
version string,
|
||||
query string,
|
||||
limit *int,
|
||||
offset *int,
|
||||
sort []string) (*generated.FoundTribeList, error) {
|
||||
var err error
|
||||
list := &generated.FoundTribeList{}
|
||||
list.Items, list.Total, err = r.TribeUcase.SearchTribe(ctx, tribe.SearchTribeConfig{
|
||||
Sort: sort,
|
||||
Limit: safeIntPointer(limit, 0),
|
||||
Offset: safeIntPointer(offset, 0),
|
||||
Version: version,
|
||||
Query: query,
|
||||
Count: shouldCount(ctx),
|
||||
})
|
||||
return list, err
|
||||
}
|
||||
|
|
|
@ -150,6 +150,22 @@ input PlayerFilter {
|
|||
)
|
||||
}
|
||||
|
||||
type FoundPlayer {
|
||||
server: String!
|
||||
id: Int!
|
||||
name: String!
|
||||
bestRank: Int!
|
||||
mostPoints: Int!
|
||||
mostVillages: Int!
|
||||
tribeID: Int!
|
||||
tribeTag: String!
|
||||
}
|
||||
|
||||
type FoundPlayerList {
|
||||
items: [FoundPlayer!]
|
||||
total: Int!
|
||||
}
|
||||
|
||||
extend type Query {
|
||||
players(
|
||||
server: String!
|
||||
|
@ -159,4 +175,12 @@ extend type Query {
|
|||
sort: [String!]
|
||||
): PlayerList!
|
||||
player(server: String!, id: Int!): Player
|
||||
searchPlayer(
|
||||
version: String!
|
||||
name: String
|
||||
id: Int
|
||||
limit: Int
|
||||
offset: Int
|
||||
sort: [String!]
|
||||
): FoundPlayerList!
|
||||
}
|
||||
|
|
|
@ -144,6 +144,21 @@ input TribeFilter {
|
|||
)
|
||||
}
|
||||
|
||||
type FoundTribe {
|
||||
server: String!
|
||||
id: Int!
|
||||
tag: String!
|
||||
name: String!
|
||||
bestRank: Int!
|
||||
mostPoints: Int!
|
||||
mostVillages: Int!
|
||||
}
|
||||
|
||||
type FoundTribeList {
|
||||
items: [FoundTribe!]
|
||||
total: Int!
|
||||
}
|
||||
|
||||
extend type Query {
|
||||
tribes(
|
||||
server: String!
|
||||
|
@ -153,4 +168,11 @@ extend type Query {
|
|||
sort: [String!]
|
||||
): TribeList!
|
||||
tribe(server: String!, id: Int!): Tribe
|
||||
searchTribe(
|
||||
version: String!
|
||||
query: String!
|
||||
limit: Int
|
||||
offset: Int
|
||||
sort: [String!]
|
||||
): FoundTribeList!
|
||||
}
|
||||
|
|
|
@ -15,8 +15,19 @@ type FetchConfig struct {
|
|||
Offset int
|
||||
}
|
||||
|
||||
type SearchPlayerConfig struct {
|
||||
Version string
|
||||
Name string
|
||||
ID int
|
||||
Count bool
|
||||
Sort []string
|
||||
Limit int
|
||||
Offset int
|
||||
}
|
||||
|
||||
type Repository interface {
|
||||
Fetch(ctx context.Context, cfg FetchConfig) ([]*models.Player, int, error)
|
||||
FetchNameChanges(ctx context.Context, code models.VersionCode, playerID ...int) (map[int][]*models.PlayerNameChange, error)
|
||||
FetchPlayerServers(ctx context.Context, code models.VersionCode, playerID ...int) (map[int][]string, error)
|
||||
SearchPlayer(ctx context.Context, cfg SearchPlayerConfig) ([]*models.FoundPlayer, int, error)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
"github.com/go-pg/pg/v10/orm"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tribalwarshelp/api/player"
|
||||
"github.com/tribalwarshelp/api/utils"
|
||||
|
@ -107,3 +108,63 @@ func (repo *pgRepository) FetchPlayerServers(ctx context.Context, code models.Ve
|
|||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (repo *pgRepository) SearchPlayer(ctx context.Context, cfg player.SearchPlayerConfig) ([]*models.FoundPlayer, int, error) {
|
||||
servers := []*models.Server{}
|
||||
if err := repo.
|
||||
Model(&servers).
|
||||
Context(ctx).
|
||||
Column("key").
|
||||
Where("version_code = ?", cfg.Version).
|
||||
Select(); err != nil {
|
||||
return nil, 0, errors.Wrap(err, "Internal server error")
|
||||
}
|
||||
|
||||
var query *orm.Query
|
||||
res := []*models.FoundPlayer{}
|
||||
whereClause := "player.id = ?1 OR player.name ILIKE ?0"
|
||||
if cfg.ID <= 0 {
|
||||
whereClause = "player.name ILIKE ?0"
|
||||
} else if cfg.Name == "" {
|
||||
whereClause = "player.id = ?1"
|
||||
}
|
||||
for _, server := range servers {
|
||||
safeKey := pg.Safe(server.Key)
|
||||
otherQuery := repo.
|
||||
Model().
|
||||
Context(ctx).
|
||||
ColumnExpr("? AS server", server.Key).
|
||||
ColumnExpr("tribe.tag as tribe_tag").
|
||||
Column("player.id", "player.name", "player.most_points", "player.best_rank", "player.most_villages", "player.tribe_id").
|
||||
TableExpr("?0.players as player", safeKey).
|
||||
Join("LEFT JOIN ?0.tribes as tribe ON player.tribe_id = tribe.id", safeKey).
|
||||
Where(whereClause, cfg.Name, cfg.ID)
|
||||
if query == nil {
|
||||
query = otherQuery
|
||||
} else {
|
||||
query = query.UnionAll(otherQuery)
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
count := 0
|
||||
if query != nil {
|
||||
base := repo.
|
||||
Model().
|
||||
With("union_q", query).
|
||||
Table("union_q").
|
||||
Limit(cfg.Limit).
|
||||
Offset(cfg.Offset).
|
||||
Order(cfg.Sort...)
|
||||
if cfg.Count {
|
||||
count, err = base.SelectAndCount(&res)
|
||||
} else {
|
||||
err = base.Select(&res)
|
||||
}
|
||||
if err != nil && err != pg.ErrNoRows {
|
||||
return nil, 0, errors.Wrap(err, "Internal server error")
|
||||
}
|
||||
}
|
||||
|
||||
return res, count, nil
|
||||
}
|
||||
|
|
|
@ -9,4 +9,5 @@ import (
|
|||
type Usecase interface {
|
||||
Fetch(ctx context.Context, cfg FetchConfig) ([]*models.Player, int, error)
|
||||
GetByID(ctx context.Context, server string, id int) (*models.Player, error)
|
||||
SearchPlayer(ctx context.Context, cfg SearchPlayerConfig) ([]*models.FoundPlayer, int, error)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package usecase
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/tribalwarshelp/api/middleware"
|
||||
"github.com/tribalwarshelp/api/player"
|
||||
|
@ -59,3 +60,17 @@ func (ucase *usecase) GetByID(ctx context.Context, server string, id int) (*mode
|
|||
}
|
||||
return players[0], nil
|
||||
}
|
||||
|
||||
func (ucase *usecase) SearchPlayer(ctx context.Context, cfg player.SearchPlayerConfig) ([]*models.FoundPlayer, int, error) {
|
||||
if "" == strings.TrimSpace(cfg.Version) {
|
||||
return nil, 0, fmt.Errorf("Version is required.")
|
||||
}
|
||||
if "" == strings.TrimSpace(cfg.Name) && cfg.ID <= 0 {
|
||||
return nil, 0, fmt.Errorf("Your search is ambiguous. You must specify the variable 'name' or 'id'.")
|
||||
}
|
||||
if !middleware.CanExceedLimit(ctx) && (cfg.Limit > player.PaginationLimit || cfg.Limit <= 0) {
|
||||
cfg.Limit = player.PaginationLimit
|
||||
}
|
||||
cfg.Sort = utils.SanitizeSortExpressions(cfg.Sort)
|
||||
return ucase.repo.SearchPlayer(ctx, cfg)
|
||||
}
|
||||
|
|
|
@ -15,6 +15,16 @@ type FetchConfig struct {
|
|||
Offset int
|
||||
}
|
||||
|
||||
type SearchTribeConfig struct {
|
||||
Version string
|
||||
Query string
|
||||
Count bool
|
||||
Sort []string
|
||||
Limit int
|
||||
Offset int
|
||||
}
|
||||
|
||||
type Repository interface {
|
||||
Fetch(ctx context.Context, cfg FetchConfig) ([]*models.Tribe, int, error)
|
||||
SearchTribe(ctx context.Context, cfg SearchTribeConfig) ([]*models.FoundTribe, int, error)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
"github.com/go-pg/pg/v10/orm"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tribalwarshelp/api/tribe"
|
||||
"github.com/tribalwarshelp/shared/models"
|
||||
|
@ -53,3 +54,55 @@ func (repo *pgRepository) Fetch(ctx context.Context, cfg tribe.FetchConfig) ([]*
|
|||
|
||||
return data, total, nil
|
||||
}
|
||||
|
||||
func (repo *pgRepository) SearchTribe(ctx context.Context, cfg tribe.SearchTribeConfig) ([]*models.FoundTribe, int, error) {
|
||||
servers := []*models.Server{}
|
||||
if err := repo.
|
||||
Model(&servers).
|
||||
Context(ctx).
|
||||
Column("key").
|
||||
Where("version_code = ?", cfg.Version).
|
||||
Select(); err != nil {
|
||||
return nil, 0, errors.Wrap(err, "Internal server error")
|
||||
}
|
||||
|
||||
var query *orm.Query
|
||||
res := []*models.FoundTribe{}
|
||||
for _, server := range servers {
|
||||
safeKey := pg.Safe(server.Key)
|
||||
otherQuery := repo.
|
||||
Model().
|
||||
Context(ctx).
|
||||
ColumnExpr("? AS server", server.Key).
|
||||
Column("tribe.id", "tribe.name", "tribe.most_points", "tribe.best_rank", "tribe.most_villages").
|
||||
TableExpr("?0.tribes as tribe", safeKey).
|
||||
Where("tribe.tag ILIKE ?0 OR tribe.name ILIKE ?0", cfg.Query)
|
||||
if query == nil {
|
||||
query = otherQuery
|
||||
} else {
|
||||
query = query.UnionAll(otherQuery)
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
count := 0
|
||||
if query != nil {
|
||||
base := repo.
|
||||
Model().
|
||||
With("union_q", query).
|
||||
Table("union_q").
|
||||
Limit(cfg.Limit).
|
||||
Offset(cfg.Offset).
|
||||
Order(cfg.Sort...)
|
||||
if cfg.Count {
|
||||
count, err = base.SelectAndCount(&res)
|
||||
} else {
|
||||
err = base.Select(&res)
|
||||
}
|
||||
if err != nil && err != pg.ErrNoRows {
|
||||
return nil, 0, errors.Wrap(err, "Internal server error")
|
||||
}
|
||||
}
|
||||
|
||||
return res, count, nil
|
||||
}
|
||||
|
|
|
@ -9,4 +9,5 @@ import (
|
|||
type Usecase interface {
|
||||
Fetch(ctx context.Context, cfg FetchConfig) ([]*models.Tribe, int, error)
|
||||
GetByID(ctx context.Context, server string, id int) (*models.Tribe, error)
|
||||
SearchTribe(ctx context.Context, cfg SearchTribeConfig) ([]*models.FoundTribe, int, error)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package usecase
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/tribalwarshelp/api/middleware"
|
||||
"github.com/tribalwarshelp/api/tribe"
|
||||
|
@ -55,3 +56,17 @@ func (ucase *usecase) GetByID(ctx context.Context, server string, id int) (*mode
|
|||
}
|
||||
return tribes[0], nil
|
||||
}
|
||||
|
||||
func (ucase *usecase) SearchTribe(ctx context.Context, cfg tribe.SearchTribeConfig) ([]*models.FoundTribe, int, error) {
|
||||
if "" == strings.TrimSpace(cfg.Version) {
|
||||
return nil, 0, fmt.Errorf("Version is required.")
|
||||
}
|
||||
if "" == strings.TrimSpace(cfg.Query) {
|
||||
return nil, 0, fmt.Errorf("Your search is ambiguous. You must specify the variable 'query'.")
|
||||
}
|
||||
if !middleware.CanExceedLimit(ctx) && (cfg.Limit > tribe.PaginationLimit || cfg.Limit <= 0) {
|
||||
cfg.Limit = tribe.PaginationLimit
|
||||
}
|
||||
cfg.Sort = utils.SanitizeSortExpressions(cfg.Sort)
|
||||
return ucase.repo.SearchTribe(ctx, cfg)
|
||||
}
|
||||
|
|
Reference in New Issue