Refactor external data to improve startup time
This commit is contained in:
parent
7ae70063b4
commit
6af8610fe6
15
aid/aid.go
15
aid/aid.go
|
@ -4,6 +4,7 @@ import (
|
||||||
m "math/rand"
|
m "math/rand"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
@ -24,6 +25,10 @@ func RandomString(n int) string {
|
||||||
return string(s)
|
return string(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RandomInt(min, max int) int {
|
||||||
|
return m.Intn(max - min) + min
|
||||||
|
}
|
||||||
|
|
||||||
func FormatNumber(number int) string {
|
func FormatNumber(number int) string {
|
||||||
str := ""
|
str := ""
|
||||||
for i, char := range ReverseString(strconv.Itoa(number)) {
|
for i, char := range ReverseString(strconv.Itoa(number)) {
|
||||||
|
@ -53,3 +58,13 @@ func ToHex(number int) string {
|
||||||
|
|
||||||
return inta
|
return inta
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Regex(str, regex string) *string {
|
||||||
|
// reg := regexp.MustCompile(`(?:CID_)(\d+|A_\d+)(?:_.+)`).FindStringSubmatch(strings.Join(split[:], "_"))
|
||||||
|
reg := regexp.MustCompile(regex).FindStringSubmatch(str)
|
||||||
|
if len(reg) > 1 {
|
||||||
|
return ®[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -376,6 +376,7 @@ func fillItemsHandler(s *discordgo.Session, i *discordgo.InteractionCreate, look
|
||||||
|
|
||||||
fortnite.GiveEverything(player)
|
fortnite.GiveEverything(player)
|
||||||
str := player.DisplayName + " has been granted all items."
|
str := player.DisplayName + " has been granted all items."
|
||||||
|
|
||||||
s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{
|
s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{
|
||||||
Content: &str,
|
Content: &str,
|
||||||
})
|
})
|
||||||
|
|
248
fortnite/external.go
Normal file
248
fortnite/external.go
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
package fortnite
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ectrc/snow/aid"
|
||||||
|
"github.com/ectrc/snow/storage"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
External *ExternalDataClient
|
||||||
|
assetRegex = regexp.MustCompile(`DAv2_([A-Za-z]+)_`)
|
||||||
|
)
|
||||||
|
|
||||||
|
type ExternalDataClient struct {
|
||||||
|
h *http.Client
|
||||||
|
FortniteSets map[string]*FortniteSet
|
||||||
|
FortniteItems map[string]*FortniteItem
|
||||||
|
FortniteItemsWithDisplayAssets map[string]*FortniteItem
|
||||||
|
FortniteItemsWithFeaturedImage []*FortniteItem
|
||||||
|
TypedFortniteItems map[string][]*FortniteItem
|
||||||
|
TypedFortniteItemsWithDisplayAssets map[string][]*FortniteItem
|
||||||
|
SnowVariantTokens map[string]SnowCosmeticVariantToken
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewExternalDataClient() *ExternalDataClient {
|
||||||
|
return &ExternalDataClient{
|
||||||
|
h: &http.Client{},
|
||||||
|
FortniteItems: make(map[string]*FortniteItem),
|
||||||
|
FortniteSets: make(map[string]*FortniteSet),
|
||||||
|
FortniteItemsWithDisplayAssets: make(map[string]*FortniteItem),
|
||||||
|
FortniteItemsWithFeaturedImage: []*FortniteItem{},
|
||||||
|
TypedFortniteItems: make(map[string][]*FortniteItem),
|
||||||
|
TypedFortniteItemsWithDisplayAssets: make(map[string][]*FortniteItem),
|
||||||
|
SnowVariantTokens: make(map[string]SnowCosmeticVariantToken),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ExternalDataClient) LoadExternalData() {
|
||||||
|
req, err := http.NewRequest("GET", "https://fortnite-api.com/v2/cosmetics/br", nil)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := c.h.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyBytes, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
content := &FortniteCosmeticsResponse{}
|
||||||
|
err = json.Unmarshal(bodyBytes, content)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range content.Data {
|
||||||
|
c.LoadItem(&item)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range c.TypedFortniteItems["AthenaBackpack"] {
|
||||||
|
c.AddBackpackToItem(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
displayAssets := storage.HttpAsset[[]string]("QKnwROGzQjYm1W9xu9uL3VrbSA0tnVj6NJJtEChUdAb3DF8uN.json")
|
||||||
|
if displayAssets == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, displayAsset := range *displayAssets {
|
||||||
|
c.AddDisplayAssetToItem(displayAsset)
|
||||||
|
}
|
||||||
|
|
||||||
|
variantTokens := storage.HttpAsset[map[string]SnowCosmeticVariantToken]("QF3nHCFt1vhELoU4q1VKTmpxnk20c2iAiBEBzlbzQAY.json")
|
||||||
|
if variantTokens == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.SnowVariantTokens = *variantTokens
|
||||||
|
|
||||||
|
addNumericStylesToSets := []string{"Soccer", "Football", "ScaryBall"}
|
||||||
|
for _, setValue := range addNumericStylesToSets {
|
||||||
|
set, found := c.FortniteSets[setValue]
|
||||||
|
if !found {
|
||||||
|
aid.Print("set not found: " + setValue)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range set.Items {
|
||||||
|
c.AddNumericStylesToItem(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ExternalDataClient) LoadItem(item *FortniteItem) {
|
||||||
|
if item.Introduction.BackendValue > aid.Config.Fortnite.Season || item.Introduction.BackendValue == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.FortniteSets[item.Set.BackendValue] == nil {
|
||||||
|
c.FortniteSets[item.Set.BackendValue] = &FortniteSet{
|
||||||
|
BackendName: item.Set.Value,
|
||||||
|
DisplayName: item.Set.Text,
|
||||||
|
Items: []*FortniteItem{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.TypedFortniteItems[item.Type.BackendValue] == nil {
|
||||||
|
c.TypedFortniteItems[item.Type.BackendValue] = []*FortniteItem{}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.FortniteItems[item.ID] = item
|
||||||
|
c.FortniteSets[item.Set.BackendValue].Items = append(c.FortniteSets[item.Set.BackendValue].Items, item)
|
||||||
|
c.TypedFortniteItems[item.Type.BackendValue] = append(c.TypedFortniteItems[item.Type.BackendValue], item)
|
||||||
|
|
||||||
|
if item.Type.BackendValue != "AthenaCharacter" || item.Images.Featured == "" || slices.Contains[[]string]([]string{
|
||||||
|
"Soccer",
|
||||||
|
"Football",
|
||||||
|
"Waypoint",
|
||||||
|
}, item.Set.BackendValue) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tag := range item.GameplayTags {
|
||||||
|
if strings.Contains(tag, "StarterPack") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.FortniteItemsWithFeaturedImage = append(c.FortniteItemsWithFeaturedImage, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ExternalDataClient) AddBackpackToItem(backpack *FortniteItem) {
|
||||||
|
if backpack.ItemPreviewHeroPath == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
splitter := strings.Split(backpack.ItemPreviewHeroPath, "/")
|
||||||
|
character, found := c.FortniteItems[splitter[len(splitter) - 1]]
|
||||||
|
if !found {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
character.Backpack = backpack
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ExternalDataClient) AddDisplayAssetToItem(displayAsset string) {
|
||||||
|
split := strings.Split(displayAsset, "_")[1:]
|
||||||
|
found := c.FortniteItems[strings.Join(split[:], "_")]
|
||||||
|
|
||||||
|
if found == nil && split[0] == "CID" {
|
||||||
|
r := aid.Regex(strings.Join(split[:], "_"), `(?:CID_)(\d+|A_\d+)(?:_.+)`)
|
||||||
|
if r != nil {
|
||||||
|
found = ItemByShallowID(*r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if found == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
found.DisplayAssetPath2 = displayAsset
|
||||||
|
c.FortniteItemsWithDisplayAssets[found.ID] = found
|
||||||
|
c.TypedFortniteItemsWithDisplayAssets[found.Type.BackendValue] = append(c.TypedFortniteItemsWithDisplayAssets[found.Type.BackendValue], found)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ExternalDataClient) AddNumericStylesToItem(item *FortniteItem) {
|
||||||
|
ownedStyles := []FortniteVariantChannel{}
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
ownedStyles = append(ownedStyles, FortniteVariantChannel{
|
||||||
|
Tag: fmt.Sprint(i),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
item.Variants = append(item.Variants, FortniteVariant{
|
||||||
|
Channel: "Numeric",
|
||||||
|
Type: "int",
|
||||||
|
Options: ownedStyles,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func PreloadCosmetics() error {
|
||||||
|
External = NewExternalDataClient()
|
||||||
|
External.LoadExternalData()
|
||||||
|
|
||||||
|
aid.Print("(snow) " + fmt.Sprint(len(External.FortniteItems)) + " cosmetics loaded from fortnite-api.com")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ItemByShallowID(shallowID string) *FortniteItem {
|
||||||
|
for _, item := range External.TypedFortniteItems["AthenaCharacter"] {
|
||||||
|
if strings.Contains(item.ID, shallowID) {
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandomItemByType(itemType string) *FortniteItem {
|
||||||
|
items := External.TypedFortniteItemsWithDisplayAssets[itemType]
|
||||||
|
if len(items) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return items[aid.RandomInt(0, len(items))]
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandomItemByNotType(notItemType string) *FortniteItem {
|
||||||
|
allItems := []*FortniteItem{}
|
||||||
|
|
||||||
|
for key, items := range External.TypedFortniteItemsWithDisplayAssets {
|
||||||
|
if key == notItemType {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
allItems = append(allItems, items...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return allItems[aid.RandomInt(0, len(allItems))]
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandomItemWithFeaturedImage() *FortniteItem {
|
||||||
|
items := External.FortniteItemsWithFeaturedImage
|
||||||
|
if len(items) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return items[aid.RandomInt(0, len(items))]
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandomSet() *FortniteSet {
|
||||||
|
sets := []*FortniteSet{}
|
||||||
|
for _, set := range External.FortniteSets {
|
||||||
|
sets = append(sets, set)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sets[aid.RandomInt(0, len(sets))]
|
||||||
|
}
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/ectrc/snow/aid"
|
"github.com/ectrc/snow/aid"
|
||||||
"github.com/ectrc/snow/storage"
|
"github.com/ectrc/snow/storage"
|
||||||
|
@ -71,70 +70,8 @@ func colorDifference(c1, c2 colours) float64 {
|
||||||
return math.Sqrt(float64(diffRed*diffRed + diffGreen*diffGreen + diffBlue*diffBlue))
|
return math.Sqrt(float64(diffRed*diffRed + diffGreen*diffGreen + diffBlue*diffBlue))
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCharacterImage(characterId string) image.Image {
|
|
||||||
character, ok := Cosmetics.Items[characterId]
|
|
||||||
if !ok {
|
|
||||||
return getRandomCharacterImage()
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := http.Get(character.Images.Featured)
|
|
||||||
if err != nil {
|
|
||||||
return getRandomCharacterImage()
|
|
||||||
}
|
|
||||||
defer response.Body.Close()
|
|
||||||
|
|
||||||
b, err := io.ReadAll(response.Body)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
image, _, err := image.Decode(bytes.NewReader(b))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return image
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRandomCharacterImage() image.Image {
|
func getRandomCharacterImage() image.Image {
|
||||||
found := false
|
character := RandomItemWithFeaturedImage()
|
||||||
var character FAPI_Cosmetic
|
|
||||||
for !found {
|
|
||||||
character = Cosmetics.GetRandomItemByType("AthenaCharacter")
|
|
||||||
|
|
||||||
if character.Images.Featured == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
continueLoop := false
|
|
||||||
for _, set := range SETS_NOT_ALLOWED {
|
|
||||||
if strings.Contains(character.Set.Value, set) {
|
|
||||||
continueLoop = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if continueLoop {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if character.Introduction.BackendValue < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tag := range character.GameplayTags {
|
|
||||||
if strings.Contains(tag, "StarterPack") {
|
|
||||||
continueLoop = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if continueLoop {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := http.Get(character.Images.Featured)
|
response, err := http.Get(character.Images.Featured)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -168,32 +105,12 @@ func getRandomCharacterImageWithSimilarColour(colour colours) image.Image {
|
||||||
func GenerateSoloImage() {
|
func GenerateSoloImage() {
|
||||||
background := *storage.Asset("background.png")
|
background := *storage.Asset("background.png")
|
||||||
|
|
||||||
itemFound := Cosmetics.GetRandomItemByType("AthenaCharacter")
|
soloPlayer := getRandomCharacterImage()
|
||||||
for itemFound.Images.Featured == "" {
|
|
||||||
itemFound = Cosmetics.GetRandomItemByType("AthenaCharacter")
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err := http.Get(itemFound.Images.Featured)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
|
|
||||||
data, err := io.ReadAll(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
bg, _, err := image.Decode(bytes.NewReader(background))
|
bg, _, err := image.Decode(bytes.NewReader(background))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
soloPlayer, _, err := image.Decode(bytes.NewReader(data))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
m := image.NewRGBA(bg.Bounds())
|
m := image.NewRGBA(bg.Bounds())
|
||||||
draw.Draw(m, m.Bounds(), bg, image.Point{0, 0}, draw.Src)
|
draw.Draw(m, m.Bounds(), bg, image.Point{0, 0}, draw.Src)
|
||||||
|
|
||||||
|
@ -224,7 +141,6 @@ func GenerateDuoImage() {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
m := image.NewRGBA(bg.Bounds())
|
m := image.NewRGBA(bg.Bounds())
|
||||||
draw.Draw(m, m.Bounds(), bg, image.Point{0, 0}, draw.Src)
|
draw.Draw(m, m.Bounds(), bg, image.Point{0, 0}, draw.Src)
|
||||||
|
|
||||||
|
@ -378,6 +294,5 @@ func GeneratePlaylistImages() {
|
||||||
GenerateDuoImage()
|
GenerateDuoImage()
|
||||||
GenerateTrioImage()
|
GenerateTrioImage()
|
||||||
GenerateSquadImage()
|
GenerateSquadImage()
|
||||||
|
|
||||||
aid.Print("(snow) generated playlist images")
|
aid.Print("(snow) generated playlist images")
|
||||||
}
|
}
|
|
@ -1,595 +0,0 @@
|
||||||
package fortnite
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"math/rand"
|
|
||||||
"net/http"
|
|
||||||
"slices"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/ectrc/snow/aid"
|
|
||||||
"github.com/ectrc/snow/storage"
|
|
||||||
)
|
|
||||||
|
|
||||||
type FortniteAPI struct {
|
|
||||||
URL string
|
|
||||||
C *http.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
type FAPI_Response struct {
|
|
||||||
Status int `json:"status"`
|
|
||||||
Data []FAPI_Cosmetic `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type FAPI_Error struct {
|
|
||||||
Status int `json:"status"`
|
|
||||||
Error string `json:"error"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type FAPI_Cosmetic_Variant struct {
|
|
||||||
Channel string `json:"channel"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
Options []FAPI_Cosmetic_VariantChannel `json:"options"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type FAPI_Cosmetic_VariantChannel struct {
|
|
||||||
Tag string `json:"tag"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Image string `json:"image"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type FAPI_Cosmetic struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Type struct {
|
|
||||||
Value string `json:"value"`
|
|
||||||
DisplayValue string `json:"displayValue"`
|
|
||||||
BackendValue string `json:"backendValue"`
|
|
||||||
} `json:"type"`
|
|
||||||
Rarity struct {
|
|
||||||
Value string `json:"value"`
|
|
||||||
DisplayValue string `json:"displayValue"`
|
|
||||||
BackendValue string `json:"backendValue"`
|
|
||||||
} `json:"rarity"`
|
|
||||||
Series struct {
|
|
||||||
Value string `json:"value"`
|
|
||||||
Image string `json:"image"`
|
|
||||||
BackendValue string `json:"backendValue"`
|
|
||||||
} `json:"series"`
|
|
||||||
Set struct {
|
|
||||||
Value string `json:"value"`
|
|
||||||
Text string `json:"text"`
|
|
||||||
BackendValue string `json:"backendValue"`
|
|
||||||
} `json:"set"`
|
|
||||||
Introduction struct {
|
|
||||||
Chapter string `json:"chapter"`
|
|
||||||
Season string `json:"season"`
|
|
||||||
Text string `json:"text"`
|
|
||||||
BackendValue int `json:"backendValue"`
|
|
||||||
} `json:"introduction"`
|
|
||||||
Images struct {
|
|
||||||
Icon string `json:"icon"`
|
|
||||||
Featured string `json:"featured"`
|
|
||||||
SmallIcon string `json:"smallIcon"`
|
|
||||||
Other map[string]string `json:"other"`
|
|
||||||
} `json:"images"`
|
|
||||||
Variants []FAPI_Cosmetic_Variant `json:"variants"`
|
|
||||||
GameplayTags []string `json:"gameplayTags"`
|
|
||||||
SearchTags []string `json:"searchTags"`
|
|
||||||
MetaTags []string `json:"metaTags"`
|
|
||||||
ShowcaseVideo string `json:"showcaseVideo"`
|
|
||||||
DynamicPakID string `json:"dynamicPakId"`
|
|
||||||
DisplayAssetPath string `json:"displayAssetPath"`
|
|
||||||
DisplayAssetPath2 string
|
|
||||||
ItemPreviewHeroPath string `json:"itemPreviewHeroPath"`
|
|
||||||
Backpack string `json:"backpack"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Added string `json:"added"`
|
|
||||||
ShopHistory []string `json:"shopHistory"`
|
|
||||||
BattlePass bool `json:"battlePass"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SnowVariantGrant struct {
|
|
||||||
Channel string `json:"channel"`
|
|
||||||
Value string `json:"value"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SnowVariant struct {
|
|
||||||
Grants []SnowVariantGrant `json:"grants"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Gift bool `json:"gift"`
|
|
||||||
Equip bool `json:"equip"`
|
|
||||||
Unseen bool `json:"unseen"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Set struct {
|
|
||||||
Items map[string]FAPI_Cosmetic `json:"items"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
BackendName string `json:"backendName"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CosmeticData struct {
|
|
||||||
Items map[string]FAPI_Cosmetic `json:"items"`
|
|
||||||
Sets map[string]Set `json:"sets"`
|
|
||||||
VariantTokens map[string]SnowVariant `json:"variantTokens"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CosmeticData) GetRandomItem() FAPI_Cosmetic {
|
|
||||||
randomInt := rand.Intn(len(c.Items))
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for _, item := range c.Items {
|
|
||||||
if strings.Contains(item.Description, "TBD") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if i == randomInt {
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.GetRandomItem()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CosmeticData) GetRandomItemByType(itemType string) FAPI_Cosmetic {
|
|
||||||
randomInt := rand.Intn(len(c.Items))
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for _, item := range c.Items {
|
|
||||||
if item.Type.BackendValue != itemType {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(item.Description, "TBD") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if i == randomInt {
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.GetRandomItemByType(itemType)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CosmeticData) GetRandomItemByNotType(itemType string) FAPI_Cosmetic {
|
|
||||||
randomInt := rand.Intn(len(c.Items))
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for _, item := range c.Items {
|
|
||||||
if item.Type.BackendValue == itemType {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(item.Description, "TBD") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if i == randomInt {
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.GetRandomItemByNotType(itemType)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CosmeticData) GetRandomSet() Set {
|
|
||||||
randomInt := rand.Intn(len(c.Sets))
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for _, set := range c.Sets {
|
|
||||||
if i == randomInt {
|
|
||||||
return set
|
|
||||||
}
|
|
||||||
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.GetRandomSet()
|
|
||||||
}
|
|
||||||
|
|
||||||
var EXTRA_NUMERIC_STYLES = []string{"Soccer", "Football", "ScaryBall"}
|
|
||||||
|
|
||||||
func (c *CosmeticData) AddItem(item FAPI_Cosmetic) {
|
|
||||||
if slices.Contains(EXTRA_NUMERIC_STYLES, item.Set.BackendValue) {
|
|
||||||
item = c.AddNumericVariantChannelToItem(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Items[item.ID] = item
|
|
||||||
|
|
||||||
if item.Set.BackendValue != "" {
|
|
||||||
if _, ok := Cosmetics.Sets[item.Set.BackendValue]; !ok {
|
|
||||||
Cosmetics.Sets[item.Set.BackendValue] = Set{
|
|
||||||
Items: make(map[string]FAPI_Cosmetic),
|
|
||||||
Name: item.Set.Value,
|
|
||||||
BackendName: item.Set.BackendValue,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Cosmetics.Sets[item.Set.BackendValue].Items[item.ID] = item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CosmeticData) AddNumericVariantChannelToItem(item FAPI_Cosmetic) FAPI_Cosmetic {
|
|
||||||
owned := []FAPI_Cosmetic_VariantChannel{}
|
|
||||||
for i := 0; i < 100; i++ {
|
|
||||||
owned = append(owned, FAPI_Cosmetic_VariantChannel{
|
|
||||||
Tag: fmt.Sprint(i),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
item.Variants = append(item.Variants, FAPI_Cosmetic_Variant{
|
|
||||||
Channel: "Numeric",
|
|
||||||
Type: "int",
|
|
||||||
Options: owned,
|
|
||||||
})
|
|
||||||
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
StaticAPI = NewFortniteAPI()
|
|
||||||
Cosmetics = CosmeticData{
|
|
||||||
Items: make(map[string]FAPI_Cosmetic),
|
|
||||||
Sets: make(map[string]Set),
|
|
||||||
VariantTokens: make(map[string]SnowVariant),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewFortniteAPI() *FortniteAPI {
|
|
||||||
return &FortniteAPI{
|
|
||||||
URL: "https://fortnite-api.com",
|
|
||||||
C: &http.Client{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FortniteAPI) Get(path string) (*FAPI_Response, error) {
|
|
||||||
req, err := http.NewRequest("GET", f.URL + path, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := f.C.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
bodyBytes, err := io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var data FAPI_Response
|
|
||||||
err = json.Unmarshal(bodyBytes, &data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FortniteAPI) GetAllCosmetics() ([]FAPI_Cosmetic, error) {
|
|
||||||
resp, err := f.Get("/v2/cosmetics/br")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp.Data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FortniteAPI) GetPlaylistImage(playlist string) (any, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func PreloadCosmetics(max int) error {
|
|
||||||
aid.Print("(external) assets from", StaticAPI.URL)
|
|
||||||
|
|
||||||
list, err := StaticAPI.GetAllCosmetics()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, item := range list {
|
|
||||||
if item.Introduction.BackendValue == 0 || item.Introduction.BackendValue > max {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(item.ShopHistory) == 0 && item.Type.Value == "outfit" {
|
|
||||||
item.BattlePass = true
|
|
||||||
}
|
|
||||||
|
|
||||||
Cosmetics.AddItem(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
for id, item := range Cosmetics.Items {
|
|
||||||
if item.Type.Value != "backpack" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if item.ItemPreviewHeroPath == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
previewHeroPath := strings.Split(item.ItemPreviewHeroPath, "/")
|
|
||||||
characterId := previewHeroPath[len(previewHeroPath)-1]
|
|
||||||
|
|
||||||
character, ok := Cosmetics.Items[characterId]
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
character.Backpack = id
|
|
||||||
Cosmetics.AddItem(character)
|
|
||||||
}
|
|
||||||
|
|
||||||
assets := storage.HttpAsset("QKnwROGzQjYm1W9xu9uL3VrbSA0tnVj6NJJtEChUdAb3DF8uN.json")
|
|
||||||
if assets == nil {
|
|
||||||
panic("Failed to load assets")
|
|
||||||
}
|
|
||||||
|
|
||||||
var assetData []string
|
|
||||||
err = json.Unmarshal(*assets, &assetData)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
withDisplayAssets := 0
|
|
||||||
|
|
||||||
for _, asset := range assetData {
|
|
||||||
asset := strings.ReplaceAll(asset, "DAv2_", "")
|
|
||||||
parts := strings.Split(asset, "_")
|
|
||||||
|
|
||||||
if strings.Contains(asset, "Bundle") {
|
|
||||||
withDisplayAssets++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case parts[0] == "CID":
|
|
||||||
addCharacterAsset(parts)
|
|
||||||
case parts[0] == "Character":
|
|
||||||
addCharacterAsset(parts)
|
|
||||||
case parts[0] == "BID":
|
|
||||||
addBackpackAsset(parts)
|
|
||||||
case parts[0] == "EID":
|
|
||||||
addEmoteAsset(parts)
|
|
||||||
case parts[0] == "Emote":
|
|
||||||
addEmoteAsset(parts)
|
|
||||||
case parts[0] == "Pickaxe":
|
|
||||||
addPickaxeAsset(parts)
|
|
||||||
case parts[0] == "Wrap":
|
|
||||||
addWrapAsset(parts)
|
|
||||||
case parts[0] == "Glider":
|
|
||||||
addGliderAsset(parts)
|
|
||||||
case parts[0] == "MusicPack":
|
|
||||||
addMusicAsset(parts)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, item := range Cosmetics.Items {
|
|
||||||
if item.DisplayAssetPath2 == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
withDisplayAssets++
|
|
||||||
}
|
|
||||||
|
|
||||||
variants := storage.HttpAsset("QF3nHCFt1vhELoU4q1VKTmpxnk20c2iAiBEBzlbzQAY.json")
|
|
||||||
if variants == nil {
|
|
||||||
panic("Failed to load variants")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(*variants, &Cosmetics.VariantTokens)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
aid.Print("(snow) preloaded", len(Cosmetics.Items), "cosmetics")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func addCharacterAsset(parts []string) {
|
|
||||||
character := FAPI_Cosmetic{}
|
|
||||||
|
|
||||||
for _, item := range Cosmetics.Items {
|
|
||||||
if item.Type.Value != "outfit" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if parts[0] == "CID" {
|
|
||||||
cid := ""
|
|
||||||
if parts[1] != "A" {
|
|
||||||
cid = parts[0] + "_" + parts[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
if parts[1] == "A" {
|
|
||||||
cid = parts[0] + "_A_" + parts[2]
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(item.ID, cid) {
|
|
||||||
character = item
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if parts[0] == "Character" {
|
|
||||||
if strings.Contains(item.ID, parts[1]) {
|
|
||||||
character = item
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if character.ID == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
character.DisplayAssetPath2 = "DAv2_" + strings.Join(parts, "_")
|
|
||||||
Cosmetics.AddItem(character)
|
|
||||||
}
|
|
||||||
|
|
||||||
func addBackpackAsset(parts []string) {
|
|
||||||
backpack := FAPI_Cosmetic{}
|
|
||||||
|
|
||||||
for _, item := range Cosmetics.Items {
|
|
||||||
if item.Type.Value != "backpack" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
bid := ""
|
|
||||||
if parts[1] != "A" {
|
|
||||||
bid = parts[0] + "_" + parts[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
if parts[1] == "A" {
|
|
||||||
bid = parts[0] + "_A_" + parts[2]
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(item.ID, bid) {
|
|
||||||
backpack = item
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if backpack.ID == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
backpack.DisplayAssetPath2 = "DAv2_" + strings.Join(parts, "_")
|
|
||||||
Cosmetics.AddItem(backpack)
|
|
||||||
}
|
|
||||||
|
|
||||||
func addEmoteAsset(parts []string) {
|
|
||||||
emote := FAPI_Cosmetic{}
|
|
||||||
|
|
||||||
for _, item := range Cosmetics.Items {
|
|
||||||
if item.Type.Value != "emote" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(item.ID, parts[1]) {
|
|
||||||
emote = item
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if emote.ID == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
emote.DisplayAssetPath2 = "DAv2_" + strings.Join(parts, "_")
|
|
||||||
Cosmetics.AddItem(emote)
|
|
||||||
}
|
|
||||||
|
|
||||||
func addPickaxeAsset(parts []string) {
|
|
||||||
pickaxe := FAPI_Cosmetic{}
|
|
||||||
|
|
||||||
for _, item := range Cosmetics.Items {
|
|
||||||
if item.Type.Value != "pickaxe" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
pickaxeId := ""
|
|
||||||
if parts[1] != "ID" {
|
|
||||||
pickaxeId = parts[0] + "_" + parts[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
if parts[1] == "ID" {
|
|
||||||
pickaxeId = parts[0] + "_ID_" + parts[2]
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(item.ID, pickaxeId) {
|
|
||||||
pickaxe = item
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if pickaxe.ID == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pickaxe.DisplayAssetPath2 = "DAv2_" + strings.Join(parts, "_")
|
|
||||||
Cosmetics.AddItem(pickaxe)
|
|
||||||
}
|
|
||||||
|
|
||||||
func addGliderAsset(parts []string) {
|
|
||||||
glider := FAPI_Cosmetic{}
|
|
||||||
|
|
||||||
for _, item := range Cosmetics.Items {
|
|
||||||
if item.Type.Value != "glider" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
gliderId := ""
|
|
||||||
if parts[1] != "ID" {
|
|
||||||
gliderId = parts[0] + "_" + parts[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
if parts[1] == "ID" {
|
|
||||||
gliderId = parts[0] + "_ID_" + parts[2]
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(item.ID, gliderId) {
|
|
||||||
glider = item
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if glider.ID == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
glider.DisplayAssetPath2 = "DAv2_" + strings.Join(parts, "_")
|
|
||||||
Cosmetics.AddItem(glider)
|
|
||||||
}
|
|
||||||
|
|
||||||
func addWrapAsset(parts []string) {
|
|
||||||
wrap := FAPI_Cosmetic{}
|
|
||||||
|
|
||||||
for _, item := range Cosmetics.Items {
|
|
||||||
if item.Type.Value != "wrap" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(item.ID, parts[1]) {
|
|
||||||
wrap = item
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if wrap.ID == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
wrap.DisplayAssetPath2 = "DAv2_" + strings.Join(parts, "_")
|
|
||||||
Cosmetics.AddItem(wrap)
|
|
||||||
}
|
|
||||||
|
|
||||||
func addMusicAsset(parts []string) {
|
|
||||||
music := FAPI_Cosmetic{}
|
|
||||||
|
|
||||||
for _, item := range Cosmetics.Items {
|
|
||||||
if item.Type.Value != "music" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(item.ID, parts[1]) {
|
|
||||||
music = item
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if music.ID == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
music.DisplayAssetPath2 = "DAv2_" + strings.Join(parts, "_")
|
|
||||||
Cosmetics.AddItem(music)
|
|
||||||
}
|
|
|
@ -31,7 +31,7 @@ func NewFortnitePerson(displayName string, everything bool) *p.Person {
|
||||||
func GiveEverything(person *p.Person) {
|
func GiveEverything(person *p.Person) {
|
||||||
items := make([]storage.DB_Item, 0)
|
items := make([]storage.DB_Item, 0)
|
||||||
|
|
||||||
for _, item := range Cosmetics.Items {
|
for _, item := range External.FortniteItems {
|
||||||
if strings.Contains(strings.ToLower(item.ID), "random") {
|
if strings.Contains(strings.ToLower(item.ID), "random") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -360,14 +360,9 @@ func GenerateRandomStorefront() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
item := Cosmetics.GetRandomItemByType("AthenaCharacter")
|
item := RandomItemByType("AthenaCharacter")
|
||||||
entry := NewCatalogEntry("athena")
|
entry := NewCatalogEntry("athena")
|
||||||
entry.SetSection("Daily")
|
entry.SetSection("Daily")
|
||||||
|
|
||||||
if item.DisplayAssetPath2 == "" {
|
|
||||||
i--
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
entry.SetNewDisplayAsset(item.DisplayAssetPath2)
|
entry.SetNewDisplayAsset(item.DisplayAssetPath2)
|
||||||
|
|
||||||
if item.DisplayAssetPath != "" {
|
if item.DisplayAssetPath != "" {
|
||||||
|
@ -378,8 +373,8 @@ func GenerateRandomStorefront() {
|
||||||
entry.SetTileSize("Normal")
|
entry.SetTileSize("Normal")
|
||||||
entry.Priority = 1
|
entry.Priority = 1
|
||||||
|
|
||||||
if item.Backpack != "" {
|
if item.Backpack != nil {
|
||||||
entry.AddGrant("AthenaBackpack:" + item.Backpack)
|
entry.AddGrant("AthenaBackpack:" + item.Backpack.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if storefront.CheckIfOfferIsDuplicate(*entry) {
|
if storefront.CheckIfOfferIsDuplicate(*entry) {
|
||||||
|
@ -390,7 +385,7 @@ func GenerateRandomStorefront() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < 6; i++ {
|
for i := 0; i < 6; i++ {
|
||||||
item := Cosmetics.GetRandomItemByNotType("AthenaCharacter")
|
item := RandomItemByNotType("AthenaCharacter")
|
||||||
entry := NewCatalogEntry("athena")
|
entry := NewCatalogEntry("athena")
|
||||||
entry.SetSection("Daily")
|
entry.SetSection("Daily")
|
||||||
|
|
||||||
|
@ -426,7 +421,7 @@ func GenerateRandomStorefront() {
|
||||||
|
|
||||||
setsAdded := 0
|
setsAdded := 0
|
||||||
for len(weekly.CatalogEntries) < minimumItems || setsAdded < minimumSets {
|
for len(weekly.CatalogEntries) < minimumItems || setsAdded < minimumSets {
|
||||||
set := Cosmetics.GetRandomSet()
|
set := RandomSet()
|
||||||
|
|
||||||
itemsAdded := 0
|
itemsAdded := 0
|
||||||
itemsToAdd := []*Entry{}
|
itemsToAdd := []*Entry{}
|
||||||
|
@ -434,10 +429,6 @@ func GenerateRandomStorefront() {
|
||||||
entry := NewCatalogEntry("athena")
|
entry := NewCatalogEntry("athena")
|
||||||
entry.SetSection("Featured")
|
entry.SetSection("Featured")
|
||||||
entry.SetPanel(set.BackendName)
|
entry.SetPanel(set.BackendName)
|
||||||
|
|
||||||
if item.DisplayAssetPath2 == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
entry.SetNewDisplayAsset(item.DisplayAssetPath2)
|
entry.SetNewDisplayAsset(item.DisplayAssetPath2)
|
||||||
|
|
||||||
if item.Type.BackendValue == "AthenaCharacter" {
|
if item.Type.BackendValue == "AthenaCharacter" {
|
||||||
|
|
87
fortnite/types.go
Normal file
87
fortnite/types.go
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
package fortnite
|
||||||
|
|
||||||
|
type FortniteVariantChannel struct {
|
||||||
|
Tag string `json:"tag"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Image string `json:"image"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FortniteVariant struct {
|
||||||
|
Channel string `json:"channel"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Options []FortniteVariantChannel `json:"options"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FortniteItem struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Type struct {
|
||||||
|
Value string `json:"value"`
|
||||||
|
DisplayValue string `json:"displayValue"`
|
||||||
|
BackendValue string `json:"backendValue"`
|
||||||
|
} `json:"type"`
|
||||||
|
Rarity struct {
|
||||||
|
Value string `json:"value"`
|
||||||
|
DisplayValue string `json:"displayValue"`
|
||||||
|
BackendValue string `json:"backendValue"`
|
||||||
|
} `json:"rarity"`
|
||||||
|
Series struct {
|
||||||
|
Value string `json:"value"`
|
||||||
|
Image string `json:"image"`
|
||||||
|
BackendValue string `json:"backendValue"`
|
||||||
|
} `json:"series"`
|
||||||
|
Set struct {
|
||||||
|
Value string `json:"value"`
|
||||||
|
Text string `json:"text"`
|
||||||
|
BackendValue string `json:"backendValue"`
|
||||||
|
} `json:"set"`
|
||||||
|
Introduction struct {
|
||||||
|
Chapter string `json:"chapter"`
|
||||||
|
Season string `json:"season"`
|
||||||
|
Text string `json:"text"`
|
||||||
|
BackendValue int `json:"backendValue"`
|
||||||
|
} `json:"introduction"`
|
||||||
|
Images struct {
|
||||||
|
Icon string `json:"icon"`
|
||||||
|
Featured string `json:"featured"`
|
||||||
|
SmallIcon string `json:"smallIcon"`
|
||||||
|
Other map[string]string `json:"other"`
|
||||||
|
} `json:"images"`
|
||||||
|
Variants []FortniteVariant `json:"variants"`
|
||||||
|
GameplayTags []string `json:"gameplayTags"`
|
||||||
|
SearchTags []string `json:"searchTags"`
|
||||||
|
MetaTags []string `json:"metaTags"`
|
||||||
|
ShowcaseVideo string `json:"showcaseVideo"`
|
||||||
|
DynamicPakID string `json:"dynamicPakId"`
|
||||||
|
DisplayAssetPath string `json:"displayAssetPath"`
|
||||||
|
DisplayAssetPath2 string
|
||||||
|
ItemPreviewHeroPath string `json:"itemPreviewHeroPath"`
|
||||||
|
Backpack *FortniteItem `json:"backpack"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
Added string `json:"added"`
|
||||||
|
ShopHistory []string `json:"shopHistory"`
|
||||||
|
BattlePass bool `json:"battlePass"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FortniteSet struct {
|
||||||
|
BackendName string `json:"backendName"`
|
||||||
|
DisplayName string `json:"displayName"`
|
||||||
|
Items []*FortniteItem `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FortniteCosmeticsResponse struct {
|
||||||
|
Status int `json:"status"`
|
||||||
|
Data []FortniteItem `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SnowCosmeticVariantToken struct {
|
||||||
|
Grants []struct {
|
||||||
|
Channel string `json:"channel"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
} `json:"grants"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Gift bool `json:"gift"`
|
||||||
|
Equip bool `json:"equip"`
|
||||||
|
Unseen bool `json:"unseen"`
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetPreloadedCosmetics(c *fiber.Ctx) error {
|
func GetPreloadedCosmetics(c *fiber.Ctx) error {
|
||||||
return c.JSON(fortnite.Cosmetics)
|
return c.JSON(fortnite.External)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPlaylistImage(c *fiber.Ctx) error {
|
func GetPlaylistImage(c *fiber.Ctx) error {
|
||||||
|
|
3
main.go
3
main.go
|
@ -45,10 +45,11 @@ func init() {
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
discord.IntialiseClient()
|
discord.IntialiseClient()
|
||||||
fortnite.PreloadCosmetics(aid.Config.Fortnite.Season)
|
fortnite.PreloadCosmetics()
|
||||||
fortnite.GenerateRandomStorefront()
|
fortnite.GenerateRandomStorefront()
|
||||||
fortnite.GeneratePlaylistImages()
|
fortnite.GeneratePlaylistImages()
|
||||||
|
|
||||||
|
|
||||||
for _, username := range aid.Config.Accounts.Gods {
|
for _, username := range aid.Config.Accounts.Gods {
|
||||||
found := person.FindByDisplay(username)
|
found := person.FindByDisplay(username)
|
||||||
if found == nil {
|
if found == nil {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -21,7 +22,7 @@ func Asset(file string) (*[]byte) {
|
||||||
return &data
|
return &data
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpAsset(file string) (*[]byte) {
|
func HttpAsset[T interface{}](file string) (*T) {
|
||||||
client := http.Client{}
|
client := http.Client{}
|
||||||
|
|
||||||
resp, err := client.Get("https://raw.githubusercontent.com/ectrc/ectrc/main/" + file)
|
resp, err := client.Get("https://raw.githubusercontent.com/ectrc/ectrc/main/" + file)
|
||||||
|
@ -34,5 +35,11 @@ func HttpAsset(file string) (*[]byte) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &data
|
var assetData T
|
||||||
|
err = json.Unmarshal(data, &assetData)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &assetData
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user