Update profiles to add MultiUpdates and Notifications;
Add purchasing form storefront!
This commit is contained in:
parent
4336da2e4d
commit
f4fa7866fd
|
@ -28,7 +28,9 @@ func NewFortnitePerson(displayName string, key string) *p.Person {
|
|||
person.AccessKey = key
|
||||
|
||||
for _, item := range defaultAthenaItems {
|
||||
person.AthenaProfile.Items.AddItem(p.NewItem(item, 1))
|
||||
item := p.NewItem(item, 1)
|
||||
item.HasSeen = true
|
||||
person.AthenaProfile.Items.AddItem(item)
|
||||
}
|
||||
|
||||
for _, item := range defaultCommonCoreItems {
|
||||
|
@ -51,10 +53,8 @@ func NewFortnitePerson(displayName string, key string) *p.Person {
|
|||
}
|
||||
|
||||
if item == "Currency:MtxPurchased" {
|
||||
item := p.NewItem(item, 0)
|
||||
item.HasSeen = true
|
||||
person.CommonCoreProfile.Items.AddItem(item).Save()
|
||||
person.Profile0Profile.Items.AddItem(item).Save()
|
||||
person.CommonCoreProfile.Items.AddItem(p.NewItem(item, 9999)).Save()
|
||||
person.Profile0Profile.Items.AddItem(p.NewItem(item, 9999)).Save()
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ func (c *Catalog) GenerateFortniteCatalog(p *person.Person) aid.JSON {
|
|||
return json
|
||||
}
|
||||
|
||||
func (c *Catalog) IsDuplicate(entry Entry) bool {
|
||||
func (c *Catalog) CheckIfOfferIsDuplicate(entry Entry) bool {
|
||||
for _, storefront := range c.Storefronts {
|
||||
for _, catalogEntry := range storefront.CatalogEntries {
|
||||
if catalogEntry.Grants[0] == entry.Grants[0] {
|
||||
|
@ -70,6 +70,18 @@ func (c *Catalog) IsDuplicate(entry Entry) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (c *Catalog) GetOfferById(id string) *Entry {
|
||||
for _, storefront := range c.Storefronts {
|
||||
for _, catalogEntry := range storefront.CatalogEntries {
|
||||
if catalogEntry.ID == id {
|
||||
return &catalogEntry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Storefront struct {
|
||||
Name string `json:"name"`
|
||||
CatalogEntries []Entry `json:"catalogEntries"`
|
||||
|
@ -111,12 +123,14 @@ type Entry struct {
|
|||
NewDisplayAssetPath string
|
||||
Title string
|
||||
ShortDescription string
|
||||
ProfileType string
|
||||
}
|
||||
|
||||
func NewCatalogEntry(meta ...aid.JSON) *Entry {
|
||||
func NewCatalogEntry(profile string, meta ...aid.JSON) *Entry {
|
||||
return &Entry{
|
||||
ID: uuid.New().String(),
|
||||
Meta: meta,
|
||||
ProfileType: profile,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -305,7 +319,7 @@ func GenerateStorefront() {
|
|||
}
|
||||
|
||||
item := Cosmetics.GetRandomItemByType("AthenaCharacter")
|
||||
entry := NewCatalogEntry()
|
||||
entry := NewCatalogEntry("athena")
|
||||
entry.SetSection("Daily")
|
||||
|
||||
if !entry.IsNewDisplayAssetValid(item.ID) {
|
||||
|
@ -322,7 +336,11 @@ func GenerateStorefront() {
|
|||
entry.SetTileSize("Normal")
|
||||
entry.Priority = 1
|
||||
|
||||
if storefront.IsDuplicate(*entry) {
|
||||
if item.Backpack != "" {
|
||||
entry.AddGrant("AthenaBackpack:" + item.Backpack)
|
||||
}
|
||||
|
||||
if storefront.CheckIfOfferIsDuplicate(*entry) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -331,7 +349,7 @@ func GenerateStorefront() {
|
|||
|
||||
for i := 0; i < 6; i++ {
|
||||
item := Cosmetics.GetRandomItemByNotType("AthenaCharacter")
|
||||
entry := NewCatalogEntry()
|
||||
entry := NewCatalogEntry("athena")
|
||||
entry.SetSection("Daily")
|
||||
|
||||
if !entry.IsNewDisplayAssetValid(item.ID) {
|
||||
|
@ -347,7 +365,7 @@ func GenerateStorefront() {
|
|||
entry.AddGrant(item.Type.BackendValue + ":" + item.ID)
|
||||
entry.SetTileSize("Small")
|
||||
|
||||
if storefront.IsDuplicate(*entry) {
|
||||
if storefront.CheckIfOfferIsDuplicate(*entry) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -366,7 +384,7 @@ func GenerateStorefront() {
|
|||
itemsAdded := 0
|
||||
itemsToAdd := []*Entry{}
|
||||
for _, item := range set.Items {
|
||||
entry := NewCatalogEntry()
|
||||
entry := NewCatalogEntry("athena")
|
||||
entry.SetSection("Featured")
|
||||
entry.SetPanel(set.BackendName)
|
||||
|
||||
|
@ -402,7 +420,7 @@ func GenerateStorefront() {
|
|||
}
|
||||
|
||||
for _, entry := range itemsToAdd {
|
||||
if storefront.IsDuplicate(*entry) {
|
||||
if storefront.CheckIfOfferIsDuplicate(*entry) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -416,4 +434,5 @@ func GenerateStorefront() {
|
|||
storefront.Add(weekly)
|
||||
|
||||
StaticCatalog = storefront
|
||||
aid.Print("Generated new random storefront")
|
||||
}
|
|
@ -7,13 +7,14 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/ectrc/snow/aid"
|
||||
"github.com/ectrc/snow/fortnite"
|
||||
p "github.com/ectrc/snow/person"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
profileActions = map[string]func(c *fiber.Ctx, person *p.Person, profile *p.Profile) error {
|
||||
profileActions = map[string]func(c *fiber.Ctx, person *p.Person, profile *p.Profile, notifications *[]aid.JSON) error {
|
||||
"QueryProfile": PostQueryProfileAction,
|
||||
"ClientQuestLogin": PostQueryProfileAction,
|
||||
"MarkItemSeen": PostMarkItemSeenAction,
|
||||
|
@ -22,6 +23,7 @@ var (
|
|||
"SetBattleRoyaleBanner": PostSetBattleRoyaleBannerAction,
|
||||
"SetCosmeticLockerSlot": PostSetCosmeticLockerSlotAction,
|
||||
"SetCosmeticLockerBanner": PostSetCosmeticLockerBannerAction,
|
||||
"PurchaseCatalogEntry": PostPurchaseCatalogEntryAction,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -32,27 +34,74 @@ func PostProfileAction(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
profile := person.GetProfileFromType(c.Query("profileId"))
|
||||
if action, ok := profileActions[c.Params("action")]; ok && profile != nil {
|
||||
if profile == nil {
|
||||
return c.Status(404).JSON(aid.ErrorBadRequest("No Profile Found"))
|
||||
}
|
||||
defer profile.ClearProfileChanges()
|
||||
before := profile.Snapshot()
|
||||
if err := action(c, person, profile); err != nil {
|
||||
|
||||
profileSnapshots := map[string]*p.ProfileSnapshot{
|
||||
"athena": nil,
|
||||
"common_core": nil,
|
||||
"common_public": nil,
|
||||
}
|
||||
|
||||
for key := range profileSnapshots {
|
||||
profileSnapshots[key] = person.GetProfileFromType(key).Snapshot()
|
||||
}
|
||||
|
||||
notifications := []aid.JSON{}
|
||||
|
||||
action, ok := profileActions[c.Params("action")];
|
||||
if ok && profile != nil {
|
||||
if err := action(c, person, profile, ¬ifications); err != nil {
|
||||
return c.Status(400).JSON(aid.ErrorBadRequest(err.Error()))
|
||||
}
|
||||
profile.Diff(before)
|
||||
}
|
||||
|
||||
for key, profileSnapshot := range profileSnapshots {
|
||||
profile := person.GetProfileFromType(key)
|
||||
if profile == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if profileSnapshot == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
profile.Diff(profileSnapshot)
|
||||
}
|
||||
|
||||
revision, _ := strconv.Atoi(c.Query("rvn"))
|
||||
if revision == -1 && profile == nil {
|
||||
revision = 1
|
||||
}
|
||||
if revision == -1 && profile != nil {
|
||||
if revision == -1 {
|
||||
revision = profile.Revision
|
||||
}
|
||||
revision++
|
||||
profile.Revision = revision
|
||||
profile.Save()
|
||||
delete(profileSnapshots, profile.Type)
|
||||
|
||||
changes := []interface{}{}
|
||||
if profile != nil {
|
||||
changes = profile.Changes
|
||||
multiUpdate := []aid.JSON{}
|
||||
for key := range profileSnapshots {
|
||||
profile := person.GetProfileFromType(key)
|
||||
if profile == nil {
|
||||
continue
|
||||
}
|
||||
profile.Revision++
|
||||
|
||||
if len(profile.Changes) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
multiUpdate = append(multiUpdate, aid.JSON{
|
||||
"profileId": profile.Type,
|
||||
"profileRevision": profile.Revision,
|
||||
"profileCommandRevision": profile.Revision,
|
||||
"profileChangesBaseRevision": profile.Revision - 1,
|
||||
"profileChanges": profile.Changes,
|
||||
})
|
||||
|
||||
profile.ClearProfileChanges()
|
||||
profile.Save()
|
||||
}
|
||||
|
||||
return c.Status(200).JSON(aid.JSON{
|
||||
|
@ -60,20 +109,20 @@ func PostProfileAction(c *fiber.Ctx) error {
|
|||
"profileRevision": revision,
|
||||
"profileCommandRevision": revision,
|
||||
"profileChangesBaseRevision": revision - 1,
|
||||
"profileChanges": changes,
|
||||
"multiUpdate": []aid.JSON{},
|
||||
"notifications": []aid.JSON{},
|
||||
"profileChanges": profile.Changes,
|
||||
"multiUpdate": multiUpdate,
|
||||
"notifications": notifications,
|
||||
"responseVersion": 1,
|
||||
"serverTime": time.Now().Format("2006-01-02T15:04:05.999Z"),
|
||||
})
|
||||
}
|
||||
|
||||
func PostQueryProfileAction(c *fiber.Ctx, person *p.Person, profile *p.Profile) error {
|
||||
func PostQueryProfileAction(c *fiber.Ctx, person *p.Person, profile *p.Profile, notifications *[]aid.JSON) error {
|
||||
profile.CreateFullProfileUpdateChange()
|
||||
return nil
|
||||
}
|
||||
|
||||
func PostMarkItemSeenAction(c *fiber.Ctx, person *p.Person, profile *p.Profile) error {
|
||||
func PostMarkItemSeenAction(c *fiber.Ctx, person *p.Person, profile *p.Profile, notifications *[]aid.JSON) error {
|
||||
var body struct {
|
||||
ItemIds []string `json:"itemIds"`
|
||||
}
|
||||
|
@ -96,7 +145,7 @@ func PostMarkItemSeenAction(c *fiber.Ctx, person *p.Person, profile *p.Profile)
|
|||
return nil
|
||||
}
|
||||
|
||||
func PostEquipBattleRoyaleCustomizationAction(c *fiber.Ctx, person *p.Person, profile *p.Profile) error {
|
||||
func PostEquipBattleRoyaleCustomizationAction(c *fiber.Ctx, person *p.Person, profile *p.Profile, notifications *[]aid.JSON) error {
|
||||
var body struct {
|
||||
SlotName string `json:"slotName" binding:"required"`
|
||||
ItemToSlot string `json:"itemToSlot"`
|
||||
|
@ -141,7 +190,7 @@ func PostEquipBattleRoyaleCustomizationAction(c *fiber.Ctx, person *p.Person, pr
|
|||
return nil
|
||||
}
|
||||
|
||||
func PostSetBattleRoyaleBannerAction(c *fiber.Ctx, person *p.Person, profile *p.Profile) error {
|
||||
func PostSetBattleRoyaleBannerAction(c *fiber.Ctx, person *p.Person, profile *p.Profile, notifications *[]aid.JSON) error {
|
||||
var body struct {
|
||||
HomebaseBannerColorID string `json:"homebaseBannerColorId" binding:"required"`
|
||||
HomebaseBannerIconID string `json:"homebaseBannerIconId" binding:"required"`
|
||||
|
@ -182,7 +231,7 @@ func PostSetBattleRoyaleBannerAction(c *fiber.Ctx, person *p.Person, profile *p.
|
|||
return nil
|
||||
}
|
||||
|
||||
func PostSetItemFavoriteStatusBatchAction(c *fiber.Ctx, person *p.Person, profile *p.Profile) error {
|
||||
func PostSetItemFavoriteStatusBatchAction(c *fiber.Ctx, person *p.Person, profile *p.Profile, notifications *[]aid.JSON) error {
|
||||
var body struct {
|
||||
ItemIds []string `json:"itemIds" binding:"required"`
|
||||
Favorite []bool `json:"itemFavStatus" binding:"required"`
|
||||
|
@ -206,7 +255,7 @@ func PostSetItemFavoriteStatusBatchAction(c *fiber.Ctx, person *p.Person, profil
|
|||
return nil
|
||||
}
|
||||
|
||||
func PostSetCosmeticLockerSlotAction(c *fiber.Ctx, person *p.Person, profile *p.Profile) error {
|
||||
func PostSetCosmeticLockerSlotAction(c *fiber.Ctx, person *p.Person, profile *p.Profile, notifications *[]aid.JSON) error {
|
||||
var body struct {
|
||||
Category string `json:"category" binding:"required"` // item type e.g. Character
|
||||
ItemToSlot string `json:"itemToSlot" binding:"required"` // template id
|
||||
|
@ -275,7 +324,7 @@ func PostSetCosmeticLockerSlotAction(c *fiber.Ctx, person *p.Person, profile *p.
|
|||
return nil
|
||||
}
|
||||
|
||||
func PostSetCosmeticLockerBannerAction(c *fiber.Ctx, person *p.Person, profile *p.Profile) error {
|
||||
func PostSetCosmeticLockerBannerAction(c *fiber.Ctx, person *p.Person, profile *p.Profile, notifications *[]aid.JSON) error {
|
||||
var body struct {
|
||||
LockerItem string `json:"lockerItem" binding:"required"` // locker id
|
||||
BannerColorTemplateName string `json:"bannerColorTemplateName" binding:"required"` // template id
|
||||
|
@ -294,7 +343,6 @@ func PostSetCosmeticLockerBannerAction(c *fiber.Ctx, person *p.Person, profile *
|
|||
|
||||
icon := profile.Items.GetItemByTemplateID("HomebaseBannerIcon:" + body.BannerIconTemplateName)
|
||||
if icon == nil {
|
||||
// return fmt.Errorf("icon item not found")
|
||||
icon = &p.Item{
|
||||
ID: body.BannerIconTemplateName,
|
||||
}
|
||||
|
@ -311,3 +359,80 @@ func PostSetCosmeticLockerBannerAction(c *fiber.Ctx, person *p.Person, profile *
|
|||
go currentLocker.Save()
|
||||
return nil
|
||||
}
|
||||
|
||||
func PostPurchaseCatalogEntryAction(c *fiber.Ctx, person *p.Person, profile *p.Profile, notifications *[]aid.JSON) error {
|
||||
var body struct{
|
||||
OfferID string `json:"offerId" binding:"required"`
|
||||
PurchaseQuantity int `json:"purchaseQuantity" binding:"required"`
|
||||
ExpectedTotalPrice int `json:"expectedTotalPrice" binding:"required"`
|
||||
}
|
||||
|
||||
err := c.BodyParser(&body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid Body")
|
||||
}
|
||||
|
||||
offer := fortnite.StaticCatalog.GetOfferById(body.OfferID)
|
||||
if offer == nil {
|
||||
return fmt.Errorf("offer not found")
|
||||
}
|
||||
|
||||
if offer.Price != body.ExpectedTotalPrice {
|
||||
return fmt.Errorf("invalid price")
|
||||
}
|
||||
|
||||
vbucks := profile.Items.GetItemByTemplateID("Currency:MtxPurchased")
|
||||
if vbucks == nil {
|
||||
return fmt.Errorf("vbucks not found")
|
||||
}
|
||||
|
||||
profile0Vbucks := person.Profile0Profile.Items.GetItemByTemplateID("Currency:MtxPurchased")
|
||||
if profile0Vbucks == nil {
|
||||
return fmt.Errorf("profile0vbucks not found")
|
||||
}
|
||||
|
||||
if vbucks.Quantity < body.ExpectedTotalPrice {
|
||||
return fmt.Errorf("not enough vbucks")
|
||||
}
|
||||
|
||||
vbucks.Quantity -= body.ExpectedTotalPrice
|
||||
|
||||
go func() {
|
||||
profile0Vbucks.Quantity = vbucks.Quantity // for season 2 and lower
|
||||
vbucks.Save()
|
||||
profile0Vbucks.Save()
|
||||
}()
|
||||
|
||||
if offer.ProfileType != "athena" {
|
||||
return fmt.Errorf("save the world not implemeted yet!")
|
||||
}
|
||||
|
||||
loot := []aid.JSON{}
|
||||
for i := 0; i < body.PurchaseQuantity; i++ {
|
||||
for _, grant := range offer.Grants {
|
||||
if profile.Items.GetItemByTemplateID(grant) != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
item := p.NewItem(grant, 1)
|
||||
person.AthenaProfile.Items.AddItem(item)
|
||||
|
||||
loot = append(loot, aid.JSON{
|
||||
"itemType": item.TemplateID,
|
||||
"itemGuid": item.ID,
|
||||
"quantity": item.Quantity,
|
||||
"itemProfile": offer.ProfileType,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
*notifications = append(*notifications, aid.JSON{
|
||||
"type": "CatalogPurchase",
|
||||
"lootResult": aid.JSON{
|
||||
"items": loot,
|
||||
},
|
||||
"primary": true,
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
|
@ -13,6 +13,7 @@ type Person struct {
|
|||
CommonCoreProfile *Profile
|
||||
CommonPublicProfile *Profile
|
||||
Profile0Profile *Profile
|
||||
CollectionsProfile *Profile
|
||||
}
|
||||
|
||||
type Option struct {
|
||||
|
@ -29,6 +30,7 @@ func NewPerson() *Person {
|
|||
CommonCoreProfile: NewProfile("common_core"),
|
||||
CommonPublicProfile: NewProfile("common_public"),
|
||||
Profile0Profile: NewProfile("profile0"),
|
||||
CollectionsProfile: NewProfile("collections"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,6 +75,7 @@ func findHelper(databasePerson *storage.DB_Person) *Person {
|
|||
commonCoreProfile := NewProfile("common_core")
|
||||
commonPublicProfile := NewProfile("common_public")
|
||||
profile0 := NewProfile("profile0")
|
||||
collectionsProfile := NewProfile("collections")
|
||||
|
||||
for _, profile := range databasePerson.Profiles {
|
||||
if profile.Type == "athena" {
|
||||
|
@ -94,6 +97,11 @@ func findHelper(databasePerson *storage.DB_Person) *Person {
|
|||
profile0.ID = profile.ID
|
||||
profile0 = FromDatabaseProfile(&profile)
|
||||
}
|
||||
|
||||
if profile.Type == "collections" {
|
||||
collectionsProfile.ID = profile.ID
|
||||
collectionsProfile = FromDatabaseProfile(&profile)
|
||||
}
|
||||
}
|
||||
|
||||
person := &Person{
|
||||
|
@ -104,6 +112,7 @@ func findHelper(databasePerson *storage.DB_Person) *Person {
|
|||
CommonCoreProfile: commonCoreProfile,
|
||||
CommonPublicProfile: commonPublicProfile,
|
||||
Profile0Profile: profile0,
|
||||
CollectionsProfile: collectionsProfile,
|
||||
}
|
||||
|
||||
cache.SavePerson(person)
|
||||
|
@ -144,6 +153,8 @@ func (p *Person) GetProfileFromType(profileType string) *Profile {
|
|||
return p.CommonPublicProfile
|
||||
case "profile0":
|
||||
return p.Profile0Profile
|
||||
case "collections":
|
||||
return p.CollectionsProfile
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -167,6 +178,7 @@ func (p *Person) ToDatabase() *storage.DB_Person {
|
|||
"athena": p.AthenaProfile,
|
||||
"common_public": p.CommonPublicProfile,
|
||||
"profile0": p.Profile0Profile,
|
||||
"collections": p.CollectionsProfile,
|
||||
}
|
||||
|
||||
for profileType, profile := range profilesToConvert {
|
||||
|
@ -234,5 +246,6 @@ func (p *Person) Snapshot() *PersonSnapshot {
|
|||
CommonCoreProfile: *p.CommonCoreProfile.Snapshot(),
|
||||
CommonPublicProfile: *p.CommonPublicProfile.Snapshot(),
|
||||
Profile0Profile: *p.Profile0Profile.Snapshot(),
|
||||
CollectionsProfile: *p.CollectionsProfile.Snapshot(),
|
||||
}
|
||||
}
|
|
@ -129,7 +129,7 @@ func (p *Profile) GenerateFortniteProfileEntry() aid.JSON {
|
|||
}
|
||||
|
||||
func (p *Profile) Save() {
|
||||
// storage.Repo.SaveProfile(p.ToDatabase())
|
||||
storage.Repo.SaveProfile(p.ToDatabase())
|
||||
}
|
||||
|
||||
func (p *Profile) Snapshot() *ProfileSnapshot {
|
||||
|
@ -399,3 +399,44 @@ func (p *Profile) CreateFullProfileUpdateChange() {
|
|||
func (p *Profile) ClearProfileChanges() {
|
||||
p.Changes = []interface{}{}
|
||||
}
|
||||
|
||||
func (p *Profile) ToDatabase() *storage.DB_Profile {
|
||||
dbProfile := storage.DB_Profile{
|
||||
ID: p.ID,
|
||||
PersonID: p.PersonID,
|
||||
Type: p.Type,
|
||||
Items: []storage.DB_Item{},
|
||||
Gifts: []storage.DB_Gift{},
|
||||
Quests: []storage.DB_Quest{},
|
||||
Loadouts: []storage.DB_Loadout{},
|
||||
Attributes: []storage.DB_PAttribute{},
|
||||
Revision: p.Revision,
|
||||
}
|
||||
|
||||
// p.Items.RangeItems(func(id string, item *Item) bool {
|
||||
// dbProfile.Items = append(dbProfile.Items, *item.ToDatabase(dbProfile.PersonID))
|
||||
// return true
|
||||
// })
|
||||
|
||||
p.Gifts.RangeGifts(func(id string, gift *Gift) bool {
|
||||
dbProfile.Gifts = append(dbProfile.Gifts, *gift.ToDatabase(dbProfile.PersonID))
|
||||
return true
|
||||
})
|
||||
|
||||
p.Quests.RangeQuests(func(id string, quest *Quest) bool {
|
||||
dbProfile.Quests = append(dbProfile.Quests, *quest.ToDatabase(dbProfile.PersonID))
|
||||
return true
|
||||
})
|
||||
|
||||
p.Attributes.RangeAttributes(func(key string, value *Attribute) bool {
|
||||
dbProfile.Attributes = append(dbProfile.Attributes, *value.ToDatabase(dbProfile.PersonID))
|
||||
return true
|
||||
})
|
||||
|
||||
p.Loadouts.RangeLoadouts(func(id string, loadout *Loadout) bool {
|
||||
dbProfile.Loadouts = append(dbProfile.Loadouts, *loadout.ToDatabase(dbProfile.PersonID))
|
||||
return true
|
||||
})
|
||||
|
||||
return &dbProfile
|
||||
}
|
|
@ -7,6 +7,7 @@ type PersonSnapshot struct {
|
|||
CommonCoreProfile ProfileSnapshot
|
||||
CommonPublicProfile ProfileSnapshot
|
||||
Profile0Profile ProfileSnapshot
|
||||
CollectionsProfile ProfileSnapshot
|
||||
}
|
||||
|
||||
type ProfileSnapshot struct {
|
||||
|
|
Loading…
Reference in New Issue
Block a user