diff --git a/default.config.ini b/default.config.ini index 6d4fd3c..4c1e59a 100644 --- a/default.config.ini +++ b/default.config.ini @@ -16,9 +16,10 @@ level="info" [api] ; port to listen on port=":3000" -; host to listen on -; only change if you know what you're doing -host="0.0.0.0" +; host that the api is running on +; e.g. if you are running the api on your local machine, you would set this to 127.0.0.1 +; if you are running the api on a server, you would set this to the ip of the server or the domain name +host="127.0.0.1" [jwt] ; secret for jwt signing diff --git a/fortnite/image.go b/fortnite/image.go new file mode 100644 index 0000000..e1a9a7f --- /dev/null +++ b/fortnite/image.go @@ -0,0 +1,71 @@ +package fortnite + +import ( + "bytes" + "image" + "image/draw" + "image/png" + "io" + "net/http" + + "github.com/ectrc/snow/aid" + "github.com/ectrc/snow/storage" + "github.com/nfnt/resize" +) + +var ( + PlaylistImages = map[string][]byte{ + "Playlist_DefaultSolo": {}, + // "Playlist_DefaultDuo": {}, + // "Playlist_DefaultSquad": {}, + } +) + +func GenerateSoloImage() { + background := *storage.Asset("background.png") + + itemFound := Cosmetics.GetRandomItemByType("AthenaCharacter") + for itemFound.Images.Featured == "" { + itemFound = Cosmetics.GetRandomItemByType("AthenaCharacter") + } + aid.Print(itemFound.Images.Featured) + + 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)) + if err != nil { + panic(err) + } + + soloPlayer, _, err := image.Decode(bytes.NewReader(data)) + if err != nil { + panic(err) + } + + m := image.NewRGBA(bg.Bounds()) + draw.Draw(m, m.Bounds(), bg, image.Point{0, 0}, draw.Src) + + resized := resize.Resize(0, uint(float64(m.Bounds().Dy()) * 1.4), soloPlayer, resize.Lanczos3) + centre := image.Point{ + m.Bounds().Dx()/2 - resized.Bounds().Dx()/2, + (m.Bounds().Dy()/2 - resized.Bounds().Dy()/2) + 200, + } + draw.Draw(m, resized.Bounds().Add(centre), resized, image.Point{0, 0}, draw.Over) + + var bytes bytes.Buffer + err = png.Encode(&bytes, m) + if err != nil { + panic(err) + } + + PlaylistImages["Playlist_DefaultSolo"] = bytes.Bytes() +} \ No newline at end of file diff --git a/fortnite/interact.go b/fortnite/interact.go index f8ca586..565466a 100644 --- a/fortnite/interact.go +++ b/fortnite/interact.go @@ -214,6 +214,10 @@ func (f *FortniteAPI) GetAllCosmetics() ([]FAPI_Cosmetic, error) { return resp.Data, nil } +func (f *FortniteAPI) GetPlaylistImage(playlist string) (any, error) { + return nil, nil +} + func PreloadCosmetics(max int) error { aid.Print("Fortnite Assets from", StaticAPI.URL) diff --git a/go.mod b/go.mod index 625c6b7..06f176e 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,7 @@ require ( github.com/mattn/go-runewidth v0.0.15 // indirect github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/philhofer/fwd v1.1.2 // indirect github.com/rivo/uniseg v0.4.4 // indirect diff --git a/go.sum b/go.sum index ee24add..30c77b8 100644 --- a/go.sum +++ b/go.sum @@ -218,6 +218,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= diff --git a/handlers/common.go b/handlers/common.go index 68c6b82..7c263b8 100644 --- a/handlers/common.go +++ b/handlers/common.go @@ -1,8 +1,6 @@ package handlers import ( - "strconv" - "github.com/ectrc/snow/aid" "github.com/gofiber/fiber/v2" ) @@ -51,119 +49,4 @@ func GetRegion(c *fiber.Ctx) error { }, "subdivisions": []aid.JSON{}, }) -} - -func GetContentPages(c *fiber.Ctx) error { - seasonString := strconv.Itoa(aid.Config.Fortnite.Season) - - return c.Status(fiber.StatusOK).JSON(aid.JSON{ - // "battlepassaboutmessages": aid.JSON{ - // "news": aid.JSON{ - // "messages": []aid.JSON{}, - // }, - // "lastModified": "0000-00-00T00:00:00.000Z", - // }, - "subgameselectdata": aid.JSON{ - "saveTheWorldUnowned": aid.JSON{ - "message": aid.JSON{ - "title": "Co-op PvE", - "body": "Cooperative PvE storm-fighting adventure!", - "spotlight": false, - "hidden": true, - "messagetype": "normal", - }, - }, - "battleRoyale": aid.JSON{ - "message": aid.JSON{ - "title": "100 Player PvP", - "body": "100 Player PvP Battle Royale.\n\nPvE progress does not affect Battle Royale.", - "spotlight": false, - "hidden": true, - "messagetype": "normal", - }, - }, - "creative": aid.JSON{ - "message": aid.JSON{ - "title": "New Featured Islands!", - "body": "Your Island. Your Friends. Your Rules.\n\nDiscover new ways to play Fortnite, play community made games with friends and build your dream island.", - "spotlight": false, - "hidden": true, - "messagetype": "normal", - }, - }, - "lastModified": "0000-00-00T00:00:00.000Z", - }, - "dynamicbackgrounds": aid.JSON{ - "backgrounds": aid.JSON{"backgrounds": []aid.JSON{ - { - "key": "lobby", - "stage": "season" + seasonString, - }, - { - "key": "vault", - "stage": "season" + seasonString, - }, - }}, - "lastModified": "0000-00-00T00:00:00.000Z", - }, - "shopSections": aid.JSON{ - "sectionList": aid.JSON{ - "sections": []aid.JSON{ - { - "bSortOffersByOwnership": false, - "bShowIneligibleOffersIfGiftable": false, - "bEnableToastNotification": true, - "background": aid.JSON{ - "stage": "default", - "_type": "DynamicBackground", - "key": "vault", - }, - "_type": "ShopSection", - "landingPriority": 0, - "bHidden": false, - "sectionId": "Featured", - "bShowTimer": true, - "sectionDisplayName": "Featured", - "bShowIneligibleOffers": true, - }, - { - "bSortOffersByOwnership": false, - "bShowIneligibleOffersIfGiftable": false, - "bEnableToastNotification": true, - "background": aid.JSON{ - "stage": "default", - "_type": "DynamicBackground", - "key": "vault", - }, - "_type": "ShopSection", - "landingPriority": 1, - "bHidden": false, - "sectionId": "Daily", - "bShowTimer": true, - "sectionDisplayName": "Daily", - "bShowIneligibleOffers": true, - }, - { - "bSortOffersByOwnership": false, - "bShowIneligibleOffersIfGiftable": false, - "bEnableToastNotification": false, - "background": aid.JSON{ - "stage": "default", - "_type": "DynamicBackground", - "key": "vault", - }, - "_type": "ShopSection", - "landingPriority": 2, - "bHidden": false, - "sectionId": "Battlepass", - "bShowTimer": false, - "sectionDisplayName": "Battle Pass", - "bShowIneligibleOffers": false, - }, - }, - }, - "lastModified": "0000-00-00T00:00:00.000Z", - }, - "lastModified": "0000-00-00T00:00:00.000Z", - }) } \ No newline at end of file diff --git a/handlers/discovery.go b/handlers/discovery.go index 18a22a9..8258d51 100644 --- a/handlers/discovery.go +++ b/handlers/discovery.go @@ -1,7 +1,10 @@ package handlers import ( + "strconv" + "github.com/ectrc/snow/aid" + "github.com/ectrc/snow/fortnite" "github.com/gofiber/fiber/v2" ) @@ -70,17 +73,18 @@ func createPlaylist(mnemonic string, image string) aid.JSON { } func PostDiscovery(c *fiber.Ctx) error { + results := []aid.JSON{} + for playlist := range fortnite.PlaylistImages { + results = append(results, createPlaylist(playlist, "http://" + aid.Config.API.Host + aid.Config.API.Port + "/snow/image/" + playlist + ".png")) + } + results = append(results, createPlaylist("Playlist_DefaultSolo", "http://bucket.retrac.site/55737fa15677cd57fab9e7f4499d62f89cfde320.png")) + return c.Status(200).JSON(aid.JSON{ "Panels": []aid.JSON{ { "PanelName": "1", "Pages": []aid.JSON{{ - "results": []aid.JSON{ - createPlaylist("playlist_defaultsolo", "https://cdn2.unrealengine.com/solo-1920x1080-1920x1080-bc0a5455ce20.jpg"), - createPlaylist("playlist_defaultduo", "https://cdn2.unrealengine.com/duos-1920x1080-1920x1080-5a411fe07b21.jpg"), - createPlaylist("playlist_trios", "https://cdn2.unrealengine.com/trios-1920x1080-1920x1080-d5054bb9691a.jpg"), - createPlaylist("playlist_defaultsquad", "https://cdn2.unrealengine.com/squads-1920x1080-1920x1080-095c0732502e.jpg"), - }, + "results": results, "hasMore": false, }}, }, @@ -145,4 +149,137 @@ func PostAssets(c *fiber.Ctx) error { }, }, }) +} + +func GetContentPages(c *fiber.Ctx) error { + seasonString := strconv.Itoa(aid.Config.Fortnite.Season) + playlists := []aid.JSON{} + for playlist := range fortnite.PlaylistImages { + playlists = append(playlists, aid.JSON{ + "image": "http://" + aid.Config.API.Host + aid.Config.API.Port + "/snow/image/" + playlist + ".png", + "playlist_name": playlist, + "hidden": false, + }) + } + + return c.Status(fiber.StatusOK).JSON(aid.JSON{ + "subgameselectdata": aid.JSON{ + "saveTheWorldUnowned": aid.JSON{ + "message": aid.JSON{ + "title": "Co-op PvE", + "body": "Cooperative PvE storm-fighting adventure!", + "spotlight": false, + "hidden": true, + "messagetype": "normal", + }, + }, + "battleRoyale": aid.JSON{ + "message": aid.JSON{ + "title": "100 Player PvP", + "body": "100 Player PvP Battle Royale.\n\nPvE progress does not affect Battle Royale.", + "spotlight": false, + "hidden": true, + "messagetype": "normal", + }, + }, + "creative": aid.JSON{ + "message": aid.JSON{ + "title": "New Featured Islands!", + "body": "Your Island. Your Friends. Your Rules.\n\nDiscover new ways to play Fortnite, play community made games with friends and build your dream island.", + "spotlight": false, + "hidden": true, + "messagetype": "normal", + }, + }, + "lastModified": "0000-00-00T00:00:00.000Z", + }, + "dynamicbackgrounds": aid.JSON{ + "backgrounds": aid.JSON{"backgrounds": []aid.JSON{ + { + "key": "lobby", + "stage": "season" + seasonString, + }, + { + "key": "vault", + "stage": "season" + seasonString, + }, + }}, + "lastModified": "0000-00-00T00:00:00.000Z", + }, + "shopSections": aid.JSON{ + "sectionList": aid.JSON{ + "sections": []aid.JSON{ + { + "bSortOffersByOwnership": false, + "bShowIneligibleOffersIfGiftable": false, + "bEnableToastNotification": true, + "background": aid.JSON{ + "stage": "default", + "_type": "DynamicBackground", + "key": "vault", + }, + "_type": "ShopSection", + "landingPriority": 0, + "bHidden": false, + "sectionId": "Featured", + "bShowTimer": true, + "sectionDisplayName": "Featured", + "bShowIneligibleOffers": true, + }, + { + "bSortOffersByOwnership": false, + "bShowIneligibleOffersIfGiftable": false, + "bEnableToastNotification": true, + "background": aid.JSON{ + "stage": "default", + "_type": "DynamicBackground", + "key": "vault", + }, + "_type": "ShopSection", + "landingPriority": 1, + "bHidden": false, + "sectionId": "Daily", + "bShowTimer": true, + "sectionDisplayName": "Daily", + "bShowIneligibleOffers": true, + }, + { + "bSortOffersByOwnership": false, + "bShowIneligibleOffersIfGiftable": false, + "bEnableToastNotification": false, + "background": aid.JSON{ + "stage": "default", + "_type": "DynamicBackground", + "key": "vault", + }, + "_type": "ShopSection", + "landingPriority": 2, + "bHidden": false, + "sectionId": "Battlepass", + "bShowTimer": false, + "sectionDisplayName": "Battle Pass", + "bShowIneligibleOffers": false, + }, + }, + }, + "lastModified": "0000-00-00T00:00:00.000Z", + }, + "playlistinformation": aid.JSON{ + "conversion_config": aid.JSON{ + "enableReferences": true, + "containerName": "playlist_info", + "contentName": "playlists", + }, + "playlist_info": aid.JSON{ + "playlists": playlists, + }, + "is_tile_hidden": false, + "show_ad_violator": false, + "frontend_matchmaking_header_style": "Basic", + "frontend_matchmaking_header_text_description": "Watch @ 3PM EST", + "frontend_matchmaking_header_text": "ECS Qualifiers", + "lastModified": "0000-00-00T00:00:00.000Z", + }, + "lastModified": "0000-00-00T00:00:00.000Z", + }) } \ No newline at end of file diff --git a/handlers/snow.go b/handlers/snow.go index df2d3ef..e55b26a 100644 --- a/handlers/snow.go +++ b/handlers/snow.go @@ -1,10 +1,28 @@ package handlers import ( + "strings" + "github.com/ectrc/snow/fortnite" "github.com/gofiber/fiber/v2" ) -func GetPrelaodedCosmetics(c *fiber.Ctx) error { +func GetPreloadedCosmetics(c *fiber.Ctx) error { return c.JSON(fortnite.Cosmetics) -} \ No newline at end of file +} + +func GetPlaylistImage(c *fiber.Ctx) error { + playlist := c.Params("playlist") + if playlist == "" { + return c.SendStatus(404) + } + playlist = strings.Split(playlist, ".")[0] + + image, ok := fortnite.PlaylistImages[playlist] + if !ok { + return c.SendStatus(404) + } + + c.Set("Content-Type", "image/png") + return c.Send(image) +} diff --git a/main.go b/main.go index 99efe33..900fcb8 100644 --- a/main.go +++ b/main.go @@ -38,6 +38,8 @@ func init() { if aid.Config.Database.DropAllTables { fortnite.NewFortnitePerson("ac", "1") } + + fortnite.GenerateSoloImage() } func main() { @@ -105,10 +107,11 @@ func main() { lightswitch.Get("/service/bulk/status", handlers.GetLightswitchBulkStatus) snow := r.Group("/snow") - snow.Get("/cosmetics", handlers.GetPrelaodedCosmetics) + snow.Get("/cosmetics", handlers.GetPreloadedCosmetics) + snow.Get("/image/:playlist", handlers.GetPlaylistImage) r.Hooks().OnListen(func(ld fiber.ListenData) error { - aid.Print("Listening on " + ld.Host + ":" + ld.Port) + aid.Print("Listening on " + "0.0.0.0:" + ld.Port) return nil }) diff --git a/storage/mem/background.png b/storage/mem/background.png new file mode 100644 index 0000000..b873be8 Binary files /dev/null and b/storage/mem/background.png differ