This commit is contained in:
Eccentric 2024-02-10 00:34:12 +00:00
parent 69e30bf10f
commit b0d2d6fd2c
12 changed files with 318 additions and 198 deletions

View File

@ -42,4 +42,14 @@ func ReverseString(input string) string {
str = string(char) + str
}
return str
}
func ToHex(number int) string {
inta := strconv.FormatInt(int64(number), 16)
if len(inta) == 1 {
return "0" + inta
}
return inta
}

View File

@ -1,9 +1,11 @@
[accounts]
; comma separated list of usernames that are considered administrators or server accounts
; comma separated list of usernames that are considered server accounts
; these accounts will be created upon the first run of snow
; they will have max permissions with snow
; to disable this, remove the line
; they will have max permissions with snow and will have no discord account linked
gods=god,snow
; comma separated list of usernames that are considered owner accounts
; these accounts will have max permissions with snow and can have a discord account linked
owners=ectrc
[database]
; connect string
@ -56,15 +58,15 @@ host="127.0.0.1"
secret="secret"
[fortnite]
; used for account creation + lobby
; fortnite build version
build=5.41
; own every cosmetic in the game. this applies to all accounts
; on every account creation, all cosmetics will be added to the account
; if you want to disable this, set this to false
everything=true
; enable or disable the requirement of password to login to an account
; if this is set to false, you can login to any account with just the username
; if this is true you must login using an exchange code given by the bot
password=true
disable_password=true
; if you recieve lots of /account/api/oauth/token requests, set this to true
; this will disable the client credentials grant type
; however this will also disable a user to get the hotfixes before login

View File

@ -54,7 +54,7 @@ func whoHandler(s *discordgo.Session, i *discordgo.InteractionCreate) {
return
}
player := getPersonFromOptions(i.ApplicationCommandData(), s)
player := getPersonFromOptions(i.ApplicationCommandData().Options, s)
if player == nil {
s.InteractionRespond(i.Interaction, &ErrorInvalidDisplayOrDiscord)
return
@ -119,7 +119,7 @@ func banHandler(s *discordgo.Session, i *discordgo.InteractionCreate) {
return
}
player := getPersonFromOptions(i.ApplicationCommandData(), s)
player := getPersonFromOptions(i.ApplicationCommandData().Options, s)
if player == nil {
s.InteractionRespond(i.Interaction, &ErrorInvalidDisplayOrDiscord)
return
@ -146,7 +146,7 @@ func unbanHandler(s *discordgo.Session, i *discordgo.InteractionCreate) {
return
}
player := getPersonFromOptions(i.ApplicationCommandData(), s)
player := getPersonFromOptions(i.ApplicationCommandData().Options, s)
if player == nil {
s.InteractionRespond(i.Interaction, &ErrorInvalidDisplayOrDiscord)
return
@ -168,12 +168,12 @@ func giveItemHandler(s *discordgo.Session, i *discordgo.InteractionCreate) {
return
}
if !looker.HasPermission(person.PermissionGiveItem) {
if !looker.HasPermission(person.PermissionItemControl) {
s.InteractionRespond(i.Interaction, &ErrorNoPermission)
return
}
player := getPersonFromOptions(i.ApplicationCommandData(), s)
player := getPersonFromOptions(i.ApplicationCommandData().Options, s)
if player == nil {
s.InteractionRespond(i.Interaction, &ErrorInvalidDisplayOrDiscord)
return
@ -229,12 +229,12 @@ func takeItemHandler(s *discordgo.Session, i *discordgo.InteractionCreate) {
return
}
if !looker.HasPermission(person.PermissionTakeItem) {
if !looker.HasPermission(person.PermissionItemControl) {
s.InteractionRespond(i.Interaction, &ErrorNoPermission)
return
}
player := getPersonFromOptions(i.ApplicationCommandData(), s)
player := getPersonFromOptions(i.ApplicationCommandData().Options, s)
if player == nil {
s.InteractionRespond(i.Interaction, &ErrorInvalidDisplayOrDiscord)
return
@ -301,21 +301,16 @@ func giveEverythingHandler(s *discordgo.Session, i *discordgo.InteractionCreate)
return
}
if !looker.HasPermission(person.PermissionGiveItem) {
if !looker.HasPermission(person.PermissionItemControl) || !looker.HasPermission(person.PermissionLockerControl) {
s.InteractionRespond(i.Interaction, &ErrorNoPermission)
return
}
player := getPersonFromOptions(i.ApplicationCommandData(), s)
player := getPersonFromOptions(i.ApplicationCommandData().Options, s)
if player == nil {
s.InteractionRespond(i.Interaction, &ErrorInvalidDisplayOrDiscord)
return
}
if !player.HasPermission(person.PermissionFullLocker) {
s.InteractionRespond(i.Interaction, &ErrorNoPermission)
return
}
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseDeferredChannelMessageWithSource,
@ -327,4 +322,79 @@ func giveEverythingHandler(s *discordgo.Session, i *discordgo.InteractionCreate)
s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{
Content: &str,
})
}
func permissionHandler(s *discordgo.Session, i *discordgo.InteractionCreate) {
looker := person.FindByDiscord(i.Member.User.ID)
if looker == nil {
s.InteractionRespond(i.Interaction, &ErrorNoPermission)
return
}
if !looker.HasPermission(person.PermissionPermissionControl) {
s.InteractionRespond(i.Interaction, &ErrorNoPermission)
return
}
if len(i.ApplicationCommandData().Options) <= 0 {
s.InteractionRespond(i.Interaction, &ErrorInvalidArguments)
return
}
subCommand := i.ApplicationCommandData().Options[0]
if len(subCommand.Options) <= 0 {
s.InteractionRespond(i.Interaction, &ErrorInvalidArguments)
return
}
player := getPersonFromOptions(subCommand.Options, s)
if player == nil {
s.InteractionRespond(i.Interaction, &ErrorInvalidDisplayOrDiscord)
return
}
permission := person.IntToPermission(subCommand.Options[0].IntValue())
if permission == 0 {
s.InteractionRespond(i.Interaction, &ErrorInvalidArguments)
return
}
if permission == person.PermissionAll && !looker.HasPermission(person.PermissionOwner) {
s.InteractionRespond(i.Interaction, &ErrorNoPermission)
return
}
if player.HasPermission(person.PermissionOwner) && !looker.HasPermission(person.PermissionOwner) {
s.InteractionRespond(i.Interaction, &ErrorNoPermission)
return
}
if player.HasPermission(person.PermissionAll) && !looker.HasPermission(person.PermissionOwner) {
s.InteractionRespond(i.Interaction, &ErrorNoPermission)
return
}
switch subCommand.Name {
case "add":
player.AddPermission(permission)
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: player.DisplayName + " has been given permission `" + permission.GetName() + "`.",
},
})
case "remove":
player.RemovePermission(permission)
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: player.DisplayName + " has had permission `" + permission.GetName() + "` removed.",
},
})
default:
s.InteractionRespond(i.Interaction, &ErrorInvalidArguments)
return
}
s.InteractionRespond(i.Interaction, &ErrorInvalidArguments)
}

View File

@ -89,6 +89,7 @@ func (c *DiscordClient) RegisterCommands() {
for _, command := range c.Commands {
if command.AdminOnly {
command.Command.DefaultMemberPermissions = &adminPermission
command.Command.Description += " (admin only)"
}
update = append(update, command.Command)

View File

@ -18,6 +18,21 @@ func addCommands() {
panic("StaticClient is nil")
}
personOptions := []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionUser,
Name: "discord",
Description: "The discord account of the player.",
Required: false,
},
{
Type: discordgo.ApplicationCommandOptionString,
Name: "display",
Description: "The display name of the player.",
Required: false,
},
}
addCommand(&DiscordCommand{
Command: &discordgo.ApplicationCommand{
Name: "create",
@ -58,7 +73,7 @@ func addCommands() {
addCommand(&DiscordCommand{
Command: &discordgo.ApplicationCommand{
Name: "information",
Description: "Useful information about this server's activity! Admin Only.",
Description: "Useful information about this server's activity!",
},
Handler: informationHandler,
AdminOnly: true,
@ -68,20 +83,7 @@ func addCommands() {
Command: &discordgo.ApplicationCommand{
Name: "who",
Description: "Lookup a player's information.",
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionString,
Name: "display",
Description: "The display name of the player.",
Required: false,
},
{
Type: discordgo.ApplicationCommandOptionUser,
Name: "discord",
Description: "The discord account of the player.",
Required: false,
},
},
Options: personOptions,
},
Handler: whoHandler,
AdminOnly: true,
@ -91,20 +93,7 @@ func addCommands() {
Command: &discordgo.ApplicationCommand{
Name: "ban",
Description: "Ban a player from using the bot.",
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionUser,
Name: "discord",
Description: "The discord account of the player.",
Required: false,
},
{
Type: discordgo.ApplicationCommandOptionString,
Name: "display",
Description: "The display name of the player.",
Required: false,
},
},
Options: personOptions,
},
Handler: banHandler,
AdminOnly: true,
@ -114,61 +103,38 @@ func addCommands() {
Command: &discordgo.ApplicationCommand{
Name: "unban",
Description: "Unban a player from using the bot.",
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionUser,
Name: "discord",
Description: "The discord account of the player.",
Required: false,
},
{
Type: discordgo.ApplicationCommandOptionString,
Name: "display",
Description: "The display name of the player.",
Required: false,
},
},
Options: personOptions,
},
Handler: unbanHandler,
AdminOnly: true,
})
grantOptions := append([]*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionString,
Name: "template_id",
Description: "The item id of the cosmetic to give/take.",
Required: true,
},
{
Type: discordgo.ApplicationCommandOptionInteger,
Name: "quantity",
Description: "The amount of the item to give/take.",
Required: true,
},
{
Type: discordgo.ApplicationCommandOptionString,
Name: "profile",
Description: "common_core, athena, common_public, profile0, collections, creative",
Required: true,
},
}, personOptions...)
addCommand(&DiscordCommand{
Command: &discordgo.ApplicationCommand{
Name: "give",
Description: "Grant a player an item in the game.",
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionString,
Name: "template_id",
Description: "The item id of the cosmetic to give.",
Required: true,
},
{
Type: discordgo.ApplicationCommandOptionInteger,
Name: "quantity",
Description: "The amount of the item to give.",
Required: true,
},
{
Type: discordgo.ApplicationCommandOptionString,
Name: "profile",
Description: "common_core, athena, common_public, profile0, collections, creative",
Required: true,
},
{
Type: discordgo.ApplicationCommandOptionUser,
Name: "discord",
Description: "The discord account of the player.",
Required: false,
},
{
Type: discordgo.ApplicationCommandOptionString,
Name: "display",
Description: "The display name of the player.",
Required: false,
},
},
Options: grantOptions,
},
Handler: giveItemHandler,
AdminOnly: true,
@ -178,38 +144,7 @@ func addCommands() {
Command: &discordgo.ApplicationCommand{
Name: "take",
Description: "Take an item from a player in the game.",
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionString,
Name: "template_id",
Description: "The item id of the cosmetic to take.",
Required: true,
},
{
Type: discordgo.ApplicationCommandOptionInteger,
Name: "quantity",
Description: "The amount of the item to take.",
Required: true,
},
{
Type: discordgo.ApplicationCommandOptionString,
Name: "profile",
Description: "common_core, athena, common_public, profile0, collections, creative",
Required: true,
},
{
Type: discordgo.ApplicationCommandOptionUser,
Name: "discord",
Description: "The discord account of the player.",
Required: false,
},
{
Type: discordgo.ApplicationCommandOptionString,
Name: "display",
Description: "The display name of the player.",
Required: false,
},
},
Options: grantOptions,
},
Handler: takeItemHandler,
AdminOnly: true,
@ -219,34 +154,89 @@ func addCommands() {
Command: &discordgo.ApplicationCommand{
Name: "everything",
Description: "Give a player full locker",
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionUser,
Name: "discord",
Description: "The discord account of the player.",
Required: false,
},
{
Type: discordgo.ApplicationCommandOptionString,
Name: "display",
Description: "The display name of the player.",
Required: false,
},
},
Options: personOptions,
},
Handler: giveEverythingHandler,
AdminOnly: true,
})
permissionOptionChoices := []*discordgo.ApplicationCommandOptionChoice{
{
Name: "All",
Value: person.PermissionAll,
},
{
Name: "Lookup",
Value: person.PermissionLookup,
},
{
Name: "Information",
Value: person.PermissionInformation,
},
{
Name: "Donator",
Value: person.PermissionDonator,
},
{
Name: "ItemControl",
Value: person.PermissionItemControl,
},
{
Name: "LockerControl",
Value: person.PermissionLockerControl,
},
{
Name: "Owner",
Value: person.PermissionOwner,
},
{
Name: "PermissionControl",
Value: person.PermissionPermissionControl,
},
}
permissionOptions := append([]*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionInteger,
Name: "permission",
Description: "The permission to add/take.",
Required: true,
Choices: permissionOptionChoices,
},
}, personOptions...)
permissionSubCommands := []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionSubCommand,
Name: "add",
Description: "Add a permission to a player.",
Options: permissionOptions,
},
{
Type: discordgo.ApplicationCommandOptionSubCommand,
Name: "remove",
Description: "Rake a permission from a player.",
Options: permissionOptions,
},
}
addCommand(&DiscordCommand{
Command: &discordgo.ApplicationCommand{
Name: "permission",
Description: "Give or take permissions from a player.",
Options: permissionSubCommands,
},
Handler: permissionHandler,
AdminOnly: true,
})
}
func getPersonFromOptions(data discordgo.ApplicationCommandInteractionData, s *discordgo.Session) *person.Person {
options := data.Options
if len(options) <= 0 {
func getPersonFromOptions(opts []*discordgo.ApplicationCommandInteractionDataOption, s *discordgo.Session) *person.Person {
if len(opts) <= 0 {
return nil
}
for _, option := range options {
for _, option := range opts {
switch option.Type {
case discordgo.ApplicationCommandOptionUser:
if option.Name != "discord" {

View File

@ -58,15 +58,44 @@ func getAverageColour(img image.Image) colours {
}
}
func GetAverageHexColour(img image.Image) string {
colour := getAverageColour(img)
return "#" + aid.ToHex(int(colour.averageRed)) + aid.ToHex(int(colour.averageGreen)) + aid.ToHex(int(colour.averageBlue))
}
func colorDifference(c1, c2 colours) float64 {
diffRed := int(c1.averageRed) - int(c2.averageRed)
diffGreen := int(c1.averageGreen) - int(c2.averageGreen)
diffBlue := int(c1.averageBlue) - int(c2.averageBlue)
// Using Euclidean distance to calculate color difference
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 {
found := false
var character FAPI_Cosmetic

View File

@ -29,22 +29,22 @@ func PostFortniteToken(c *fiber.Ctx) error {
var body FortniteTokenBody
if err := c.BodyParser(&body); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Request Body"))
return c.Status(400).JSON(aid.ErrorBadRequest("Invalid Request Body"))
}
if action, ok := oauthTokenGrantTypes[body.GrantType]; ok {
return action(c, &body)
}
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Grant Type"))
return c.Status(400).JSON(aid.ErrorBadRequest("Invalid Grant Type"))
}
func PostTokenClientCredentials(c *fiber.Ctx, body *FortniteTokenBody) error {
if aid.Config.Fortnite.DisableClientCredentials {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Client Credentials is disabled."))
return c.Status(400).JSON(aid.ErrorBadRequest("Client Credentials is disabled."))
}
return c.Status(fiber.StatusOK).JSON(aid.JSON{
return c.Status(200).JSON(aid.JSON{
"access_token": "snow",
"token_type": "bearer",
"client_id": aid.Hash([]byte(c.IP())),
@ -57,37 +57,37 @@ func PostTokenClientCredentials(c *fiber.Ctx, body *FortniteTokenBody) error {
func PostTokenExchangeCode(c *fiber.Ctx, body *FortniteTokenBody) error {
if body.ExchangeCode == "" {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Exchange Code is empty"))
return c.Status(400).JSON(aid.ErrorBadRequest("Exchange Code is empty"))
}
codeParts := strings.Split(body.ExchangeCode, ".")
if len(codeParts) != 2 {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
return c.Status(400).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
}
code, failed := aid.KeyPair.DecryptAndVerifyB64(codeParts[0], codeParts[1])
if failed {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
return c.Status(400).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
}
personParts := strings.Split(string(code), "=")
if len(personParts) != 2 {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
return c.Status(400).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
}
personId := personParts[0]
expire, err := time.Parse("2006-01-02T15:04:05.999Z", personParts[1])
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
return c.Status(400).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
}
if expire.Add(time.Hour).Before(time.Now()) {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
return c.Status(400).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
}
person := p.Find(personId)
if person == nil {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
return c.Status(400).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
}
access, err := aid.JWTSign(aid.JSON{
@ -108,7 +108,7 @@ func PostTokenExchangeCode(c *fiber.Ctx, body *FortniteTokenBody) error {
return c.Status(fiber.StatusInternalServerError).JSON(aid.ErrorInternalServer)
}
return c.Status(fiber.StatusOK).JSON(aid.JSON{
return c.Status(200).JSON(aid.JSON{
"access_token": "eg1~" + access,
"account_id": person.ID,
"client_id": c.IP(),
@ -117,9 +117,9 @@ func PostTokenExchangeCode(c *fiber.Ctx, body *FortniteTokenBody) error {
"device_id": "default",
"display_name": person.DisplayName,
"expires_at": time.Now().Add(time.Hour * 24).Format("2006-01-02T15:04:05.999Z"),
"expires_in": 86400,
"expires_in": 86200,
"internal_client": true,
"refresh_expires": 86400,
"refresh_expires": 86200,
"refresh_expires_at": time.Now().Add(time.Hour * 24).Format("2006-01-02T15:04:05.999Z"),
"refresh_token": "eg1~" + refresh,
"token_type": "bearer",
@ -130,16 +130,16 @@ func PostTokenExchangeCode(c *fiber.Ctx, body *FortniteTokenBody) error {
func PostTokenPassword(c *fiber.Ctx, body *FortniteTokenBody) error {
if aid.Config.Fortnite.Password {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Username and password authentication is disabled for security reasons. Please use an exchange code given by the discord bot."))
return c.Status(400).JSON(aid.ErrorBadRequest("Username and password authentication is disabled for security reasons. Please use an exchange code given by the discord bot."))
}
if body.Username == "" || body.Password == "" {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Username/Password is empty"))
return c.Status(400).JSON(aid.ErrorBadRequest("Username/Password is empty"))
}
person := p.FindByDisplay(strings.Split(body.Username, "@")[0])
if person == nil {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("No Account Found"))
return c.Status(400).JSON(aid.ErrorBadRequest("No Account Found"))
}
access, err := aid.JWTSign(aid.JSON{
@ -160,7 +160,7 @@ func PostTokenPassword(c *fiber.Ctx, body *FortniteTokenBody) error {
return c.Status(fiber.StatusInternalServerError).JSON(aid.ErrorInternalServer)
}
return c.Status(fiber.StatusOK).JSON(aid.JSON{
return c.Status(200).JSON(aid.JSON{
"access_token": "eg1~" + access,
"account_id": person.ID,
"client_id": c.IP(),
@ -169,9 +169,9 @@ func PostTokenPassword(c *fiber.Ctx, body *FortniteTokenBody) error {
"device_id": "default",
"display_name": person.DisplayName,
"expires_at": time.Now().Add(time.Hour * 24).Format("2006-01-02T15:04:05.999Z"),
"expires_in": 86400,
"expires_in": 86200,
"internal_client": true,
"refresh_expires": 86400,
"refresh_expires": 86200,
"refresh_expires_at": time.Now().Add(time.Hour * 24).Format("2006-01-02T15:04:05.999Z"),
"refresh_token": "eg1~" + refresh,
"token_type": "bearer",
@ -191,12 +191,12 @@ func GetTokenVerify(c *fiber.Ctx) error {
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
}
return c.Status(fiber.StatusOK).JSON(aid.JSON{
return c.Status(200).JSON(aid.JSON{
"app": "fortnite",
"token": strings.ReplaceAll(c.Get("Authorization"), "bearer eg1~", ""),
"token_type": "bearer",
"expires_at": time.Now().Add(time.Hour * 24).Format("2006-01-02T15:04:05.999Z"),
"expires_in": 86400,
"expires_in": 86200,
"client_id": c.IP(),
"session_id": "0",
"device_id": "default",
@ -211,7 +211,7 @@ func GetTokenVerify(c *fiber.Ctx) error {
}
func DeleteToken(c *fiber.Ctx) error {
return c.Status(fiber.StatusOK).JSON(aid.JSON{})
return c.Status(200).JSON(aid.JSON{})
}
func MiddlewareFortnite(c *fiber.Ctx) error {
@ -247,10 +247,10 @@ func MiddlewareWeb(c *fiber.Ctx) error {
func GetPublicAccount(c *fiber.Ctx) error {
person := p.Find(c.Params("accountId"))
if person == nil {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("No Account Found"))
return c.Status(400).JSON(aid.ErrorBadRequest("No Account Found"))
}
return c.Status(fiber.StatusOK).JSON(aid.JSON{
return c.Status(200).JSON(aid.JSON{
"id": person.ID,
"displayName": person.DisplayName,
"externalAuths": []aid.JSON{},
@ -274,27 +274,37 @@ func GetPublicAccounts(c *fiber.Ctx) error {
})
}
return c.Status(fiber.StatusOK).JSON(response)
return c.Status(200).JSON(response)
}
func GetPublicAccountExternalAuths(c *fiber.Ctx) error {
person := p.Find(c.Params("accountId"))
if person == nil {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("No Account Found"))
return c.Status(400).JSON(aid.ErrorBadRequest("No Account Found"))
}
return c.Status(fiber.StatusOK).JSON([]aid.JSON{})
return c.Status(200).JSON([]aid.JSON{})
}
func GetPublicAccountByDisplayName(c *fiber.Ctx) error {
person := p.FindByDisplay(c.Params("displayName"))
if person == nil {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("No Account Found"))
return c.Status(400).JSON(aid.ErrorBadRequest("No Account Found"))
}
return c.Status(fiber.StatusOK).JSON(aid.JSON{
return c.Status(200).JSON(aid.JSON{
"id": person.ID,
"displayName": person.DisplayName,
"externalAuths": []aid.JSON{},
})
}
func GetPrivacySettings(c *fiber.Ctx) error {
return c.Status(200).JSON(aid.JSON{
"privacySettings": aid.JSON{
"playRegion": "PUBLIC",
"badges": "PUBLIC",
"languages": "PUBLIC",
},
})
}

View File

@ -32,7 +32,6 @@ func GetLightswitchBulkStatus(c *fiber.Ctx) error {
"banned": isBanned,
"launcherInfoDTO": aid.JSON{
"appName":"Fortnite",
"catalogItemId":"4fe75bbc5a674f4f9b356b5c90567da5",
"namespace":"fn",
},
}})
@ -65,34 +64,34 @@ func GetFortniteTimeline(c *fiber.Ctx) error {
switch season {
case 2:
events = append(events, aid.JSON{
"activeUntil": "9999-12-31T23:59:59.999Z",
"activeSince": "0001-01-01T00:00:00Z",
"activeUntil": "9999-01-01T00:00:00.000Z",
"activeSince": "9999-01-01T00:00:00.000Z",
"eventType": "EventFlag.LobbyWinterDecor",
})
case 6:
events = append(events, aid.JSON{
"activeUntil": "9999-01-01T00:00:00.000Z",
"activeSince": "0001-01-01T00:00:00Z",
"activeSince": "9999-01-01T00:00:00.000Z",
"eventType": "EventFlag.LobbySeason6Halloween",
})
case 11:
events = append(events, aid.JSON{
"activeUntil": "9999-01-01T00:00:00.000Z",
"activeSince": "0001-01-01T00:00:00Z",
"activeSince": "9999-01-01T00:00:00.000Z",
"eventType": "EventFlag.LTE_WinterFest2019",
}, aid.JSON{
"activeUntil": "9999-01-01T00:00:00.000Z",
"activeSince": "0001-01-01T00:00:00Z",
"activeSince": "9999-01-01T00:00:00.000Z",
"eventType": "EventFlag.LTE_WinterFest",
}, aid.JSON{
"activeUntil": "9999-01-01T00:00:00.000Z",
"activeSince": "0001-01-01T00:00:00Z",
"activeSince": "9999-01-01T00:00:00.000Z",
"eventType": "EventFlag.Winterfest.Tree",
})
default:
events = append(events, aid.JSON{
"activeUntil": "9999-12-31T23:59:59.999Z",
"activeSince": "0001-01-01T00:00:00Z",
"activeUntil": "9999-01-01T00:00:00.000Z",
"activeSince": "9999-01-01T00:00:00.000Z",
"eventType": "EventFlag.LobbySeason" + strings.Split(build, ".")[0],
})
}

23
main.go
View File

@ -55,14 +55,21 @@ func init() {
found = fortnite.NewFortnitePersonWithId(username, username, true)
}
for _, perm := range found.Permissions {
found.RemovePermission(perm)
}
found.AddPermission("all")
found.AddPermission(person.PermissionAllWithRoles)
aid.Print("(snow) max account " + username + " loaded")
}
for _, username := range aid.Config.Accounts.Owners {
found := person.FindByDisplay(username)
if found == nil {
continue
}
found.AddPermission(person.PermissionOwner)
aid.Print("(snow) owner account " + username + " loaded")
}
}
func main() {
r := fiber.New(fiber.Config{
DisableStartupMessage: true,
@ -70,7 +77,6 @@ func main() {
JSONDecoder: json.Unmarshal,
})
r.Use(aid.FiberLogger())
r.Use(aid.FiberLimiter())
r.Use(aid.FiberCors())
@ -78,9 +84,12 @@ func main() {
r.Get("/region", handlers.GetRegion)
r.Get("/content/api/pages/fortnite-game", handlers.GetContentPages)
r.Get("/waitingroom/api/waitingroom", handlers.GetWaitingRoomStatus)
r.Get("/affiliate/api/public/affiliates/slug/:slug", handlers.GetAffiliate)
r.Get("/api/v1/search/:accountId", handlers.GetPersonSearch)
r.Post("/api/v1/assets/Fortnite/:versionId/:assetName", handlers.PostAssets)
r.Get("/affiliate/api/public/affiliates/slug/:slug", handlers.GetAffiliate)
r.Get("/profile/privacy_settings", handlers.MiddlewareFortnite, handlers.GetPrivacySettings)
r.Put("/profile/play_region", handlers.AnyNoContent)
r.Get("/", handlers.RedirectSocket)

View File

@ -8,4 +8,4 @@ run:
go run main.go
test:
go test -v ./...
go test

View File

@ -5,7 +5,7 @@ import "github.com/ectrc/snow/storage"
type PersonSnapshot struct {
ID string
DisplayName string
Permissions []string
Permissions int64
AthenaProfile ProfileSnapshot
CommonCoreProfile ProfileSnapshot
CommonPublicProfile ProfileSnapshot

View File

@ -19,9 +19,9 @@
- Interaction with a Game Server to handle **Event Tracking** for player statistics and challenges. This will be a very large task as a new specialised game server will need to be created.
- After the game server addition, a **Matchmaking System** will be added to match players together for a game. It will use a bin packing algorithm to ensure that games are filled as much as possible.
And finally, the biggest task of all...
And once battle royale is completed ...
- **Save The World**. This is a very large task and will require a lot of work. It is not a priority at the moment and might be done after the Battle Royale experience is complete.
- **Save The World**
## Supported MCP Actions