Better
This commit is contained in:
parent
69e30bf10f
commit
b0d2d6fd2c
10
aid/aid.go
10
aid/aid.go
|
@ -43,3 +43,13 @@ func ReverseString(input string) string {
|
|||
}
|
||||
return str
|
||||
}
|
||||
|
||||
func ToHex(number int) string {
|
||||
inta := strconv.FormatInt(int64(number), 16)
|
||||
|
||||
if len(inta) == 1 {
|
||||
return "0" + inta
|
||||
}
|
||||
|
||||
return inta
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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,22 +301,17 @@ 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,
|
||||
})
|
||||
|
@ -328,3 +323,78 @@ func giveEverythingHandler(s *discordgo.Session, i *discordgo.InteractionCreate)
|
|||
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)
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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,40 +103,23 @@ 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,
|
||||
})
|
||||
|
||||
addCommand(&DiscordCommand{
|
||||
Command: &discordgo.ApplicationCommand{
|
||||
Name: "give",
|
||||
Description: "Grant a player an item in the game.",
|
||||
Options: []*discordgo.ApplicationCommandOption{
|
||||
grantOptions := append([]*discordgo.ApplicationCommandOption{
|
||||
{
|
||||
Type: discordgo.ApplicationCommandOptionString,
|
||||
Name: "template_id",
|
||||
Description: "The item id of the cosmetic to give.",
|
||||
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.",
|
||||
Description: "The amount of the item to give/take.",
|
||||
Required: true,
|
||||
},
|
||||
{
|
||||
|
@ -156,19 +128,13 @@ func addCommands() {
|
|||
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,
|
||||
},
|
||||
},
|
||||
}, personOptions...)
|
||||
|
||||
addCommand(&DiscordCommand{
|
||||
Command: &discordgo.ApplicationCommand{
|
||||
Name: "give",
|
||||
Description: "Grant a player an item in the game.",
|
||||
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" {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
})
|
||||
}
|
|
@ -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
23
main.go
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user