Compare commits

...

8 Commits
master ... tidy

Author SHA1 Message Date
85c8835e64 delete unused code 2024-11-26 15:18:04 -08:00
09ae8b4b38 extreme gorm 2024-11-26 15:14:06 -08:00
d11ee978dc gorming 2024-11-26 15:08:40 -08:00
ee7790dd39 delete everything that won't compile 2024-11-26 15:08:31 -08:00
103ae75640 submissions.Get no red underlines 2024-11-26 14:48:31 -08:00
d85a5a0669 run generate 2024-11-26 14:47:56 -08:00
6e2e95abaf extend submission object 2024-11-26 14:42:22 -08:00
a5009998a8 renaming and fixing red underlines 2024-11-26 14:37:18 -08:00
11 changed files with 365 additions and 493 deletions

View File

@ -125,6 +125,41 @@ func (s *Error) UnmarshalJSON(data []byte) error {
return s.Decode(d) return s.Decode(d)
} }
// Encode encodes bool as json.
func (o OptBool) Encode(e *jx.Encoder) {
if !o.Set {
return
}
e.Bool(bool(o.Value))
}
// Decode decodes bool from json.
func (o *OptBool) Decode(d *jx.Decoder) error {
if o == nil {
return errors.New("invalid: unable to decode OptBool to nil")
}
o.Set = true
v, err := d.Bool()
if err != nil {
return err
}
o.Value = bool(v)
return nil
}
// MarshalJSON implements stdjson.Marshaler.
func (s OptBool) MarshalJSON() ([]byte, error) {
e := jx.Encoder{}
s.Encode(&e)
return e.Bytes(), nil
}
// UnmarshalJSON implements stdjson.Unmarshaler.
func (s *OptBool) UnmarshalJSON(data []byte) error {
d := jx.DecodeBytes(data)
return s.Decode(d)
}
// Encode encodes int32 as json. // Encode encodes int32 as json.
func (o OptInt32) Encode(e *jx.Encoder) { func (o OptInt32) Encode(e *jx.Encoder) {
if !o.Set { if !o.Set {
@ -269,14 +304,63 @@ func (s *Submission) encodeFields(e *jx.Encoder) {
s.Date.Encode(e) s.Date.Encode(e)
} }
} }
{
if s.Submitter.Set {
e.FieldStart("Submitter")
s.Submitter.Encode(e)
}
}
{
if s.AssetID.Set {
e.FieldStart("AssetID")
s.AssetID.Encode(e)
}
}
{
if s.AssetVersion.Set {
e.FieldStart("AssetVersion")
s.AssetVersion.Encode(e)
}
}
{
if s.Completed.Set {
e.FieldStart("Completed")
s.Completed.Encode(e)
}
}
{
if s.SubmissionType.Set {
e.FieldStart("SubmissionType")
s.SubmissionType.Encode(e)
}
}
{
if s.TargetAssetID.Set {
e.FieldStart("TargetAssetID")
s.TargetAssetID.Encode(e)
}
}
{
if s.StatusID.Set {
e.FieldStart("StatusID")
s.StatusID.Encode(e)
}
}
} }
var jsonFieldsNameOfSubmission = [5]string{ var jsonFieldsNameOfSubmission = [12]string{
0: "ID", 0: "ID",
1: "DisplayName", 1: "DisplayName",
2: "Creator", 2: "Creator",
3: "GameID", 3: "GameID",
4: "Date", 4: "Date",
5: "Submitter",
6: "AssetID",
7: "AssetVersion",
8: "Completed",
9: "SubmissionType",
10: "TargetAssetID",
11: "StatusID",
} }
// Decode decodes Submission from json. // Decode decodes Submission from json.
@ -337,6 +421,76 @@ func (s *Submission) Decode(d *jx.Decoder) error {
}(); err != nil { }(); err != nil {
return errors.Wrap(err, "decode field \"Date\"") return errors.Wrap(err, "decode field \"Date\"")
} }
case "Submitter":
if err := func() error {
s.Submitter.Reset()
if err := s.Submitter.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"Submitter\"")
}
case "AssetID":
if err := func() error {
s.AssetID.Reset()
if err := s.AssetID.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"AssetID\"")
}
case "AssetVersion":
if err := func() error {
s.AssetVersion.Reset()
if err := s.AssetVersion.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"AssetVersion\"")
}
case "Completed":
if err := func() error {
s.Completed.Reset()
if err := s.Completed.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"Completed\"")
}
case "SubmissionType":
if err := func() error {
s.SubmissionType.Reset()
if err := s.SubmissionType.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"SubmissionType\"")
}
case "TargetAssetID":
if err := func() error {
s.TargetAssetID.Reset()
if err := s.TargetAssetID.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"TargetAssetID\"")
}
case "StatusID":
if err := func() error {
s.StatusID.Reset()
if err := s.StatusID.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"StatusID\"")
}
default: default:
return d.Skip() return d.Skip()
} }

View File

@ -63,6 +63,52 @@ func (s *ErrorStatusCode) SetResponse(val Error) {
s.Response = val s.Response = val
} }
// NewOptBool returns new OptBool with value set to v.
func NewOptBool(v bool) OptBool {
return OptBool{
Value: v,
Set: true,
}
}
// OptBool is optional bool.
type OptBool struct {
Value bool
Set bool
}
// IsSet returns true if OptBool was set.
func (o OptBool) IsSet() bool { return o.Set }
// Reset unsets value.
func (o *OptBool) Reset() {
var v bool
o.Value = v
o.Set = false
}
// SetTo sets value to v.
func (o *OptBool) SetTo(v bool) {
o.Set = true
o.Value = v
}
// Get returns value and boolean that denotes whether value was set.
func (o OptBool) Get() (v bool, ok bool) {
if !o.Set {
return v, false
}
return o.Value, true
}
// Or returns value if set, or given parameter if does not.
func (o OptBool) Or(d bool) bool {
if v, ok := o.Get(); ok {
return v
}
return d
}
// NewOptInt32 returns new OptInt32 with value set to v. // NewOptInt32 returns new OptInt32 with value set to v.
func NewOptInt32(v int32) OptInt32 { func NewOptInt32(v int32) OptInt32 {
return OptInt32{ return OptInt32{
@ -284,11 +330,18 @@ type PatchSubmissionStatusOK struct{}
// Ref: #/components/schemas/Submission // Ref: #/components/schemas/Submission
type Submission struct { type Submission struct {
ID OptInt64 `json:"ID"` ID OptInt64 `json:"ID"`
DisplayName OptString `json:"DisplayName"` DisplayName OptString `json:"DisplayName"`
Creator OptString `json:"Creator"` Creator OptString `json:"Creator"`
GameID OptInt32 `json:"GameID"` GameID OptInt32 `json:"GameID"`
Date OptInt64 `json:"Date"` Date OptInt64 `json:"Date"`
Submitter OptInt64 `json:"Submitter"`
AssetID OptInt64 `json:"AssetID"`
AssetVersion OptInt64 `json:"AssetVersion"`
Completed OptBool `json:"Completed"`
SubmissionType OptInt32 `json:"SubmissionType"`
TargetAssetID OptInt64 `json:"TargetAssetID"`
StatusID OptInt32 `json:"StatusID"`
} }
// GetID returns the value of ID. // GetID returns the value of ID.
@ -316,6 +369,41 @@ func (s *Submission) GetDate() OptInt64 {
return s.Date return s.Date
} }
// GetSubmitter returns the value of Submitter.
func (s *Submission) GetSubmitter() OptInt64 {
return s.Submitter
}
// GetAssetID returns the value of AssetID.
func (s *Submission) GetAssetID() OptInt64 {
return s.AssetID
}
// GetAssetVersion returns the value of AssetVersion.
func (s *Submission) GetAssetVersion() OptInt64 {
return s.AssetVersion
}
// GetCompleted returns the value of Completed.
func (s *Submission) GetCompleted() OptBool {
return s.Completed
}
// GetSubmissionType returns the value of SubmissionType.
func (s *Submission) GetSubmissionType() OptInt32 {
return s.SubmissionType
}
// GetTargetAssetID returns the value of TargetAssetID.
func (s *Submission) GetTargetAssetID() OptInt64 {
return s.TargetAssetID
}
// GetStatusID returns the value of StatusID.
func (s *Submission) GetStatusID() OptInt32 {
return s.StatusID
}
// SetID sets the value of ID. // SetID sets the value of ID.
func (s *Submission) SetID(val OptInt64) { func (s *Submission) SetID(val OptInt64) {
s.ID = val s.ID = val
@ -341,6 +429,41 @@ func (s *Submission) SetDate(val OptInt64) {
s.Date = val s.Date = val
} }
// SetSubmitter sets the value of Submitter.
func (s *Submission) SetSubmitter(val OptInt64) {
s.Submitter = val
}
// SetAssetID sets the value of AssetID.
func (s *Submission) SetAssetID(val OptInt64) {
s.AssetID = val
}
// SetAssetVersion sets the value of AssetVersion.
func (s *Submission) SetAssetVersion(val OptInt64) {
s.AssetVersion = val
}
// SetCompleted sets the value of Completed.
func (s *Submission) SetCompleted(val OptBool) {
s.Completed = val
}
// SetSubmissionType sets the value of SubmissionType.
func (s *Submission) SetSubmissionType(val OptInt32) {
s.SubmissionType = val
}
// SetTargetAssetID sets the value of TargetAssetID.
func (s *Submission) SetTargetAssetID(val OptInt64) {
s.TargetAssetID = val
}
// SetStatusID sets the value of StatusID.
func (s *Submission) SetStatusID(val OptInt32) {
s.StatusID = val
}
// Ref: #/components/schemas/SubmissionFilter // Ref: #/components/schemas/SubmissionFilter
type SubmissionFilter struct { type SubmissionFilter struct {
ID OptInt64 `json:"ID"` ID OptInt64 `json:"ID"`

View File

@ -2,129 +2,32 @@ package controller
import ( import (
"context" "context"
"fmt"
"git.itzana.me/strafesnet/maps-service/internal/datastore" "git.itzana.me/strafesnet/maps-service/internal/datastore"
"git.itzana.me/strafesnet/maps-service/internal/model"
"git.itzana.me/strafesnet/maps-service/api" "git.itzana.me/strafesnet/maps-service/api"
"github.com/pkg/errors"
"time"
) )
type Maps struct { type Submissions struct {
*maps.UnimplementedMapsServiceServer
Store datastore.Datastore Store datastore.Datastore
} }
func (m Maps) Get(ctx context.Context, params *api.GetSubmissionParams) (*api.Submission, error) { func (m Submissions) Get(ctx context.Context, params *api.GetSubmissionParams) (*api.Submission, error) {
item, err := m.Store.Maps().Get(ctx, params.SubmissionID) item, err := m.Store.Submissions().Get(ctx, params.SubmissionID)
if err != nil { if err != nil {
if err == datastore.ErrNotExist { return nil, err
return nil, status.Error(codes.NotFound, "map does not exit")
}
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to get map:").Error())
} }
return &maps.MapResponse{ return &api.Submission{
ID: item.ID, ID: api.NewOptInt64(item.ID),
DisplayName: item.DisplayName, DisplayName: api.NewOptString(item.DisplayName),
Creator: item.Creator, Creator: api.NewOptString(item.Creator),
GameID: item.GameID, GameID: api.NewOptInt32(item.GameID),
Date: item.Date.Unix(), Date: api.NewOptInt64(item.Date.Unix()),
Submitter: api.NewOptInt64(item.Submitter),
AssetID: api.NewOptInt64(item.AssetID),
AssetVersion: api.NewOptInt64(item.AssetVersion),
Completed: api.NewOptBool(item.Completed),
SubmissionType: api.NewOptInt32(item.SubmissionType),
TargetAssetID: api.NewOptInt64(item.TargetAssetID),
StatusID: api.NewOptInt32(item.StatusID),
}, nil }, nil
} }
func (m Maps) GetList(ctx context.Context, list *maps.IdList) (*maps.MapList, error) {
items, err := m.Store.Maps().GetList(ctx, list.ID)
if err != nil {
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to get maps").Error())
}
var resp maps.MapList
for i := 0; i < len(items); i++ {
resp.Maps = append(resp.Maps, &maps.MapResponse{
ID: items[i].ID,
DisplayName: items[i].DisplayName,
Creator: items[i].Creator,
GameID: items[i].GameID,
Date: items[i].Date.Unix(),
})
}
return &resp, nil
}
func (m Maps) Update(ctx context.Context, request *maps.MapRequest) (*maps.NullResponse, error) {
updates := datastore.Optional()
updates.AddNotNil("display_name", request.DisplayName)
updates.AddNotNil("creator", request.Creator)
updates.AddNotNil("game_id", request.GameID)
if request.Date != nil {
updates.AddNotNil("date", time.Unix(request.GetDate(), 0))
}
if err := m.Store.Maps().Update(ctx, request.GetID(), updates); err != nil {
if err == datastore.ErrNotExist {
return nil, status.Error(codes.NotFound, "map does not exit")
}
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to update map:").Error())
}
return &maps.NullResponse{}, nil
}
func (m Maps) Create(ctx context.Context, request *maps.MapRequest) (*maps.IdMessage, error) {
item, err := m.Store.Maps().Create(ctx, model.Map{
ID: request.GetID(),
DisplayName: request.GetDisplayName(),
Creator: request.GetCreator(),
GameID: request.GetGameID(),
Date: time.Unix(request.GetDate(), 0),
})
if err != nil {
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to create map:").Error())
}
return &maps.IdMessage{ID: item.ID}, nil
}
func (m Maps) Delete(ctx context.Context, message *maps.IdMessage) (*maps.NullResponse, error) {
if err := m.Store.Maps().Delete(ctx, message.GetID()); err != nil {
if err == datastore.ErrNotExist {
return nil, status.Error(codes.NotFound, "map does not exit")
}
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to delete map:").Error())
}
return &maps.NullResponse{}, nil
}
func (m Maps) List(ctx context.Context, request *maps.ListRequest) (*maps.MapList, error) {
filter := datastore.Optional()
fmt.Println(request)
if request.Filter != nil {
filter.AddNotNil("display_name", request.GetFilter().DisplayName)
filter.AddNotNil("creator", request.GetFilter().Creator)
filter.AddNotNil("game_id", request.GetFilter().GameID)
}
items, err := m.Store.Maps().List(ctx, filter, model.Page{
Number: request.GetPage().GetNumber(),
Size: request.GetPage().GetSize(),
})
if err != nil {
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to get maps:").Error())
}
var resp maps.MapList
for i := 0; i < len(items); i++ {
resp.Maps = append(resp.Maps, &maps.MapResponse{
ID: items[i].ID,
DisplayName: items[i].DisplayName,
Creator: items[i].Creator,
GameID: items[i].GameID,
Date: items[i].Date.Unix(),
})
}
return &resp, nil
}

View File

@ -1,117 +1,9 @@
package controller package controller
import ( import (
"context"
"git.itzana.me/strafesnet/maps-service/internal/datastore" "git.itzana.me/strafesnet/maps-service/internal/datastore"
"git.itzana.me/strafesnet/maps-service/internal/model"
"git.itzana.me/strafesnet/go-grpc/users"
"github.com/pkg/errors"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
) )
type Users struct { type Users struct {
*users.UnimplementedUsersServiceServer
Store datastore.Datastore Store datastore.Datastore
} }
func (u Users) Get(ctx context.Context, request *users.IdMessage) (*users.UserResponse, error) {
ur, err := u.Store.Users().Get(ctx, request.ID)
if err != nil {
if err == datastore.ErrNotExist {
return nil, status.Error(codes.NotFound, err.Error())
}
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to get user").Error())
}
return &users.UserResponse{
ID: ur.ID,
Username: ur.Username,
StateID: ur.StateID,
}, nil
}
func (u Users) GetList(ctx context.Context, list *users.IdList) (*users.UserList, error) {
uList, err := u.Store.Users().GetList(ctx, list.ID)
if err != nil {
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to get users").Error())
}
var resp users.UserList
for i := 0; i < len(uList); i++ {
resp.Users = append(resp.Users, &users.UserResponse{
ID: uList[i].ID,
Username: uList[i].Username,
StateID: uList[i].StateID,
})
}
return &resp, nil
}
func (u Users) Update(ctx context.Context, request *users.UserRequest) (*users.NullResponse, error) {
updates := datastore.Optional()
updates.AddNotNil("state_id", request.StateID)
updates.AddNotNil("username", request.Username)
if err := u.Store.Users().Update(ctx, request.GetID(), updates); err != nil {
if err == datastore.ErrNotExist {
return nil, status.Error(codes.NotFound, err.Error())
}
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to update user").Error())
}
return &users.NullResponse{}, nil
}
func (u Users) Create(ctx context.Context, request *users.UserRequest) (*users.IdMessage, error) {
us, err := u.Store.Users().Create(ctx, model.User{
ID: request.GetID(),
Username: request.GetUsername(),
StateID: request.GetStateID(),
})
if err != nil {
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to create user").Error())
}
return &users.IdMessage{ID: us.ID}, nil
}
func (u Users) Delete(ctx context.Context, request *users.IdMessage) (*users.NullResponse, error) {
if err := u.Store.Users().Delete(ctx, request.GetID()); err != nil {
if err == datastore.ErrNotExist {
return nil, status.Error(codes.NotFound, err.Error())
}
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to delete user").Error())
}
return &users.NullResponse{}, nil
}
func (u Users) List(ctx context.Context, request *users.ListRequest) (*users.UserList, error) {
filters := datastore.Optional()
if request.Filter != nil {
filters.AddNotNil("id", request.GetFilter().ID)
filters.AddNotNil("state_id", request.GetFilter().StateID)
filters.AddNotNil("username", request.GetFilter().Username)
}
uList, err := u.Store.Users().List(ctx, filters, model.Page{
Number: request.GetPage().GetNumber(),
Size: request.GetPage().GetSize(),
})
if err != nil {
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to get filtered users").Error())
}
var uResp users.UserList
for i := 0; i < len(uList); i++ {
uResp.Users = append(uResp.Users, &users.UserResponse{
ID: uList[i].ID,
Username: uList[i].Username,
StateID: uList[i].StateID,
})
}
return &uResp, nil
}

View File

@ -3,7 +3,6 @@ package datastore
import ( import (
"context" "context"
"errors" "errors"
"time"
"git.itzana.me/strafesnet/maps-service/internal/model" "git.itzana.me/strafesnet/maps-service/internal/model"
) )
@ -13,25 +12,10 @@ var (
) )
type Datastore interface { type Datastore interface {
Times() Times
Users() Users Users() Users
Bots() Bots Submissions() Submissions
Maps() Maps
Events() Events
Servers() Servers
Transactions() Transactions
Ranks() Ranks
} }
type Times interface {
Get(ctx context.Context, id int64) (model.Time, error)
Create(ctx context.Context, time model.Time) (model.Time, error)
Update(ctx context.Context, id int64, values OptionalMap) error
Delete(ctx context.Context, id int64) error
List(ctx context.Context, filters OptionalMap, blacklisted bool, page model.Page, sort uint32) (int64, []model.Time, error)
Rank(ctx context.Context, id int64) (int64, error)
DistinctStylePairs(ctx context.Context) ([]model.Time, error)
}
type Users interface { type Users interface {
Get(ctx context.Context, id int64) (model.User, error) Get(ctx context.Context, id int64) (model.User, error)
@ -42,53 +26,11 @@ type Users interface {
List(ctx context.Context, filters OptionalMap, page model.Page) ([]model.User, error) List(ctx context.Context, filters OptionalMap, page model.Page) ([]model.User, error)
} }
type Bots interface { type Submissions interface {
Get(ctx context.Context, id int64) (model.Bot, error) Get(ctx context.Context, id int64) (model.Submission, error)
GetList(ctx context.Context, id []int64) ([]model.Bot, error) GetList(ctx context.Context, id []int64) ([]model.Submission, error)
Create(ctx context.Context, bot model.Bot) (model.Bot, error) Create(ctx context.Context, time model.Submission) (model.Submission, error)
Update(ctx context.Context, id int64, values OptionalMap) error Update(ctx context.Context, id int64, values OptionalMap) error
Delete(ctx context.Context, id int64) error Delete(ctx context.Context, id int64) error
List(ctx context.Context, filters OptionalMap, page model.Page) ([]model.Bot, error) List(ctx context.Context, filters OptionalMap, page model.Page) ([]model.Submission, error)
}
type Maps interface {
Get(ctx context.Context, id int64) (model.Map, error)
GetList(ctx context.Context, id []int64) ([]model.Map, error)
Create(ctx context.Context, time model.Map) (model.Map, error)
Update(ctx context.Context, id int64, values OptionalMap) error
Delete(ctx context.Context, id int64) error
List(ctx context.Context, filters OptionalMap, page model.Page) ([]model.Map, error)
}
type Events interface {
Latest(ctx context.Context, date int64, page model.Page) ([]model.Event, error)
Create(ctx context.Context, event model.Event) (model.Event, error)
Clean(ctx context.Context) error
}
type Servers interface {
Get(ctx context.Context, id string) (model.Server, error)
Create(ctx context.Context, server model.Server) (model.Server, error)
Update(ctx context.Context, id string, values OptionalMap) error
Delete(ctx context.Context, id string) error
DeleteByLastUpdated(ctx context.Context, date time.Time) error
List(ctx context.Context, filters OptionalMap, page model.Page) ([]model.Server, error)
}
type Transactions interface {
Balance(ctx context.Context, user int64) (int64, error)
Get(ctx context.Context, id string) (model.Transaction, error)
Create(ctx context.Context, transaction model.Transaction) (model.Transaction, error)
Update(ctx context.Context, id string, values OptionalMap) error
Delete(ctx context.Context, id string) error
List(ctx context.Context, filters OptionalMap, page model.Page) ([]model.Transaction, error)
}
type Ranks interface {
Delete(ctx context.Context, id int64) error
Get(ctx context.Context, user int64, style, game, mode int32, state []int32) (model.Rank, error)
List(ctx context.Context, style, game, mode int32, sort int64, state []int32, page model.Page) ([]model.Rank, error)
UpdateRankCalc(ctx context.Context) error
UpdateAll(ctx context.Context, style, game, mode int32) error
UpdateUsers(ctx context.Context, style, game, mode int32, users []int) error
} }

View File

@ -38,7 +38,7 @@ func New(migrate bool) (datastore.Datastore, error) {
sqlDB.SetMaxOpenConns(25) sqlDB.SetMaxOpenConns(25)
if migrate { if migrate {
if err := db.AutoMigrate(&model.Time{}, &model.User{}, &model.Bot{}, &model.Map{}, &model.Event{}, &model.Server{}, &model.Transaction{}, &model.Rank{}, &model.RankCalc{}); err != nil { if err := db.AutoMigrate(&model.User{}, &model.Submission{}); err != nil {
log.WithField("error", err).Errorln("database migration failed") log.WithField("error", err).Errorln("database migration failed")
return nil, err return nil, err
} }

View File

@ -11,34 +11,10 @@ type Gormstore struct {
cache *cache.Cache[[]byte] cache *cache.Cache[[]byte]
} }
func (g Gormstore) Times() datastore.Times {
return &Times{db: g.db}
}
func (g Gormstore) Users() datastore.Users { func (g Gormstore) Users() datastore.Users {
return &Users{db: g.db} return &Users{db: g.db}
} }
func (g Gormstore) Bots() datastore.Bots { func (g Gormstore) Submissions() datastore.Submissions {
return &Bots{db: g.db} return &Submissions{db: g.db}
}
func (g Gormstore) Maps() datastore.Maps {
return &Maps{db: g.db}
}
func (g Gormstore) Events() datastore.Events {
return &Events{db: g.db}
}
func (g Gormstore) Servers() datastore.Servers {
return &Servers{db: g.db}
}
func (g Gormstore) Transactions() datastore.Transactions {
return &Transactions{db: g.db}
}
func (g Gormstore) Ranks() datastore.Ranks {
return &Ranks{db: g.db, cache: g.cache}
} }

View File

@ -7,12 +7,12 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
) )
type Maps struct { type Submissions struct {
db *gorm.DB db *gorm.DB
} }
func (m Maps) Get(ctx context.Context, id int64) (model.Map, error) { func (m Submissions) Get(ctx context.Context, id int64) (model.Submission, error) {
var smap model.Map var smap model.Submission
if err := m.db.WithContext(ctx).First(&smap, id).Error; err != nil { if err := m.db.WithContext(ctx).First(&smap, id).Error; err != nil {
if err == gorm.ErrRecordNotFound { if err == gorm.ErrRecordNotFound {
return smap, datastore.ErrNotExist return smap, datastore.ErrNotExist
@ -23,8 +23,8 @@ func (m Maps) Get(ctx context.Context, id int64) (model.Map, error) {
return smap, nil return smap, nil
} }
func (m Maps) GetList(ctx context.Context, id []int64) ([]model.Map, error) { func (m Submissions) GetList(ctx context.Context, id []int64) ([]model.Submission, error) {
var mapList []model.Map var mapList []model.Submission
if err := m.db.WithContext(ctx).Find(&mapList, "id IN ?", id).Error; err != nil { if err := m.db.WithContext(ctx).Find(&mapList, "id IN ?", id).Error; err != nil {
return mapList, err return mapList, err
} }
@ -32,7 +32,7 @@ func (m Maps) GetList(ctx context.Context, id []int64) ([]model.Map, error) {
return mapList, nil return mapList, nil
} }
func (m Maps) Create(ctx context.Context, smap model.Map) (model.Map, error) { func (m Submissions) Create(ctx context.Context, smap model.Submission) (model.Submission, error) {
if err := m.db.WithContext(ctx).Create(&smap).Error; err != nil { if err := m.db.WithContext(ctx).Create(&smap).Error; err != nil {
return smap, err return smap, err
} }
@ -40,8 +40,8 @@ func (m Maps) Create(ctx context.Context, smap model.Map) (model.Map, error) {
return smap, nil return smap, nil
} }
func (m Maps) Update(ctx context.Context, id int64, values datastore.OptionalMap) error { func (m Submissions) Update(ctx context.Context, id int64, values datastore.OptionalMap) error {
if err := m.db.WithContext(ctx).Model(&model.Map{}).Where("id = ?", id).Updates(values.Map()).Error; err != nil { if err := m.db.WithContext(ctx).Model(&model.Submission{}).Where("id = ?", id).Updates(values.Map()).Error; err != nil {
if err == gorm.ErrRecordNotFound { if err == gorm.ErrRecordNotFound {
return datastore.ErrNotExist return datastore.ErrNotExist
} }
@ -51,8 +51,8 @@ func (m Maps) Update(ctx context.Context, id int64, values datastore.OptionalMap
return nil return nil
} }
func (m Maps) Delete(ctx context.Context, id int64) error { func (m Submissions) Delete(ctx context.Context, id int64) error {
if err := m.db.WithContext(ctx).Delete(&model.Map{}, id).Error; err != nil { if err := m.db.WithContext(ctx).Delete(&model.Submission{}, id).Error; err != nil {
if err == gorm.ErrRecordNotFound { if err == gorm.ErrRecordNotFound {
return datastore.ErrNotExist return datastore.ErrNotExist
} }
@ -62,8 +62,8 @@ func (m Maps) Delete(ctx context.Context, id int64) error {
return nil return nil
} }
func (m Maps) List(ctx context.Context, filters datastore.OptionalMap, page model.Page) ([]model.Map, error) { func (m Submissions) List(ctx context.Context, filters datastore.OptionalMap, page model.Page) ([]model.Submission, error) {
var maps []model.Map var maps []model.Submission
if err := m.db.WithContext(ctx).Where(filters.Map()).Offset(int((page.Number - 1) * page.Size)).Limit(int(page.Size)).Find(&maps).Error; err != nil { if err := m.db.WithContext(ctx).Where(filters.Map()).Offset(int((page.Number - 1) * page.Size)).Limit(int(page.Size)).Find(&maps).Error; err != nil {
return nil, err return nil, err
} }

View File

@ -2,10 +2,17 @@ package model
import "time" import "time"
type Map struct { type Submission struct {
ID int64 ID int64
DisplayName string DisplayName string
Creator string Creator string
GameID int32 GameID int32
Date time.Time Date time.Time
Submitter int64 // UserID
AssetID int64
AssetVersion int64
Completed bool
SubmissionType int32 // 1=New 2=Fix
TargetAssetID int64 // where to upload map fix
StatusID int32
} }

View File

@ -213,6 +213,26 @@ components:
Date: Date:
type: integer type: integer
format: int64 format: int64
Submitter:
type: integer
format: int64
AssetID:
type: integer
format: int64
AssetVersion:
type: integer
format: int64
Completed:
type: boolean
SubmissionType:
type: integer
format: int32
TargetAssetID:
type: integer
format: int64
StatusID:
type: integer
format: int32
SubmissionFilter: SubmissionFilter:
type: object type: object
properties: properties:

157
server.go
View File

@ -8,6 +8,7 @@ import (
"git.itzana.me/strafesnet/maps-service/api" "git.itzana.me/strafesnet/maps-service/api"
"git.itzana.me/strafesnet/maps-service/internal/controller/submissions" "git.itzana.me/strafesnet/maps-service/internal/controller/submissions"
"git.itzana.me/strafesnet/maps-service/internal/controller/users" "git.itzana.me/strafesnet/maps-service/internal/controller/users"
"git.itzana.me/strafesnet/maps-service/internal/datastore/gormstore"
) )
type apiServer struct { type apiServer struct {
@ -28,132 +29,16 @@ func (m *apiServer) NewError(ctx context.Context, err error) *api.ErrorStatusCod
} }
} }
// GetTimes implements api.Handler.
func (m *apiServer) ListTimes(ctx context.Context, params api.ListTimesParams) ([]api.Time, error) {
client := times.NewTimesServiceClient(m.client)
// Call the List method using params
req := &times.ListRequest{
Page: &times.Pagination{
Number: params.Page.GetPage(),
Size: params.Page.GetLimit(),
},
}
if filter, ok := params.Filter.Get(); ok {
if id := filter.GetID(); id.IsSet() {
req.Filter.ID = &id.Value
}
if time := filter.GetTime(); time.IsSet() {
req.Filter.Time = &time.Value
}
if userID := filter.GetUserID(); userID.IsSet() {
req.Filter.UserID = &userID.Value
}
if mapID := filter.GetMapID(); mapID.IsSet() {
req.Filter.MapID = &mapID.Value
}
if styleID := filter.GetStyleID(); styleID.IsSet() {
req.Filter.StyleID = &styleID.Value
}
if modeID := filter.GetModeID(); modeID.IsSet() {
req.Filter.ModeID = &modeID.Value
}
if gameID := filter.GetGameID(); gameID.IsSet() {
req.Filter.GameID = &gameID.Value
}
}
response, err := client.List(ctx, req)
if err != nil {
return nil, err
}
return convertTimes(response.Times), nil
}
// GetUser implements api.Handler.
func (m *apiServer) GetUser(ctx context.Context, params api.GetUserParams) (*api.User, error) {
client := users.NewUsersServiceClient(m.client)
response, err := client.Get(ctx, &users.IdMessage{
ID: params.UserID,
})
if err != nil {
return nil, err
}
return &api.User{
ID: api.NewOptInt64(response.ID),
Username: api.NewOptString(response.Username),
StateID: api.NewOptInt32(response.StateID),
}, nil
}
// ListRanks implements api.Handler.
func (m *apiServer) ListRanks(ctx context.Context, params api.ListRanksParams) ([]api.Rank, error) {
client := ranks.NewRanksServiceClient(m.client)
req := &ranks.ListRequest{
Page: &ranks.Pagination{
Number: params.Page.GetPage(),
Size: params.Page.GetLimit(),
},
}
if filter, ok := params.Filter.Get(); ok {
if gameID, ok := filter.GetGameID().Get(); ok {
req.GameID = gameID
}
if modeID, ok := filter.GetModeID().Get(); ok {
req.ModeID = modeID
}
if styleID, ok := filter.GetStyleID().Get(); ok {
req.StyleID = styleID
}
if sort, ok := filter.GetSort().Get(); ok {
req.Sort = sort
}
}
response, err := client.List(ctx, req)
if err != nil {
return nil, err
}
ranks := make([]api.Rank, len(response.Ranks))
for i, r := range response.Ranks {
ranks[i] = api.Rank{
ID: api.NewOptInt64(r.ID),
User: api.NewOptUser(api.User{
ID: api.NewOptInt64(r.User.ID),
Username: api.NewOptString(r.User.Username),
StateID: api.NewOptInt32(r.User.StateID),
}),
StyleID: api.NewOptInt32(r.StyleID),
ModeID: api.NewOptInt32(r.ModeID),
GameID: api.NewOptInt32(r.GameID),
Rank: api.NewOptFloat64(r.Rank),
Skill: api.NewOptFloat64(r.Skill),
UpdatedAt: api.NewOptInt64(r.UpdatedAt),
}
}
return ranks, nil
}
func main() { func main() {
// new grpc client db, err := gormstore.New(true)
conn, err := grpc.Dial("localhost:9000", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil { if err != nil {
log.Fatal(err) log.WithField("error", err).Fatalln("database startup failed")
return
} }
svc := &apiServer{ svc := &apiServer{
client: conn, submissions: db.Submissions(),
users: db.Users(),
} }
srv, err := api.NewServer( srv, err := api.NewServer(
@ -168,33 +53,3 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
} }
func convertTime(t *times.TimeResponse) api.Time {
return api.Time{
ID: api.NewOptInt64(t.ID),
Time: api.NewOptInt64(t.Time),
User: api.NewOptUser(api.User{
ID: api.NewOptInt64(t.User.ID),
Username: api.NewOptString(t.User.Username),
StateID: api.NewOptInt32(t.User.StateID),
}),
Map: api.NewOptMap(api.Map{
ID: api.NewOptInt64(t.Map.ID),
DisplayName: api.NewOptString(t.Map.DisplayName),
Creator: api.NewOptString(t.Map.Creator),
Date: api.NewOptInt64(t.Map.Date),
}),
Date: api.NewOptInt64(t.Date),
StyleID: api.NewOptInt32(t.StyleID),
ModeID: api.NewOptInt32(t.ModeID),
GameID: api.NewOptInt32(t.GameID),
}
}
func convertTimes(timeList []*times.TimeResponse) []api.Time {
times := make([]api.Time, len(timeList))
for i, t := range timeList {
times[i] = convertTime(t)
}
return times
}