From 9e691170f6d9210f82908b8e6c1e80d6fb38dfe7 Mon Sep 17 00:00:00 2001 From: Eccentric Date: Sun, 4 Feb 2024 19:49:31 +0000 Subject: [PATCH] Add amazon s3 cloud settings --- aid/config.go | 28 ++++++++++++ default.config.ini | 13 +++++- fortnite/interact.go | 2 +- go.mod | 24 ++++++++-- go.sum | 66 ++++++++++++++++++++++++--- handlers/snow.go | 8 ++++ handlers/storage.go | 103 ++++++++++++++++++++++++++++++++----------- main.go | 15 +++++-- readme.md | 3 +- storage/amazon.go | 92 ++++++++++++++++++++++++++++++++++++++ storage/storage.go | 1 + 11 files changed, 313 insertions(+), 42 deletions(-) create mode 100644 storage/amazon.go diff --git a/aid/config.go b/aid/config.go index ee2a360..849d6d6 100644 --- a/aid/config.go +++ b/aid/config.go @@ -22,6 +22,13 @@ type CS struct { Token string Guild string } + Amazon struct { + Enabled bool + BucketURI string + AccessKeyID string + SecretAccessKey string + ClientSettingsBucket string + } Output struct { Level string } @@ -94,6 +101,27 @@ func LoadConfig(file []byte) { panic("Discord Guild ID is empty") } + Config.Amazon.Enabled = true + Config.Amazon.BucketURI = cfg.Section("amazon").Key("uri").String() + if Config.Amazon.BucketURI == "" { + Config.Amazon.Enabled = false + } + + Config.Amazon.AccessKeyID = cfg.Section("amazon").Key("id").String() + if Config.Amazon.AccessKeyID == "" { + Config.Amazon.Enabled = false + } + + Config.Amazon.SecretAccessKey = cfg.Section("amazon").Key("key").String() + if Config.Amazon.SecretAccessKey == "" { + Config.Amazon.Enabled = false + } + + Config.Amazon.ClientSettingsBucket = cfg.Section("amazon").Key("bucket").String() + if Config.Amazon.ClientSettingsBucket == "" { + Config.Amazon.Enabled = false + } + Config.API.Host = cfg.Section("api").Key("host").String() if Config.API.Host == "" { panic("API Host is empty") diff --git a/default.config.ini b/default.config.ini index 5ba2547..7926190 100644 --- a/default.config.ini +++ b/default.config.ini @@ -14,6 +14,17 @@ type="postgres" ; deletes and resets the entire database on startup drop=false +[amazon] +; bucket uri of your s3 storage +; leave blank to disable s3 storage +uri="" +; access key id for the amazon s3 bucket +id="36a3297c08..." +; secret access key for the amazon s3 bucket +key="4e5274c62b7b8c3..." +; path to the bucket in the s3 storage that will store the client settings +bucket="snow" + [discord] ; discord id of the bot id="1234567890..." @@ -28,7 +39,7 @@ guild="1234567890..." ; level of logging ; info = backend logs ; time = backend logs + time taken for database queries -; prod = only errors +; prod = only errors // this will also disable the risky endpoints level="info" [api] diff --git a/fortnite/interact.go b/fortnite/interact.go index 5588d65..52490ec 100644 --- a/fortnite/interact.go +++ b/fortnite/interact.go @@ -264,7 +264,7 @@ func (f *FortniteAPI) GetPlaylistImage(playlist string) (any, error) { } func PreloadCosmetics(max int) error { - aid.Print("(snow) assets from", StaticAPI.URL) + aid.Print("(external) assets from", StaticAPI.URL) list, err := StaticAPI.GetAllCosmetics() if err != nil { diff --git a/go.mod b/go.mod index 90c8f74..d4a5702 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,17 @@ module github.com/ectrc/snow go 1.21.3 require ( + github.com/aws/aws-sdk-go-v2 v1.18.0 + github.com/aws/aws-sdk-go-v2/config v1.18.18 + github.com/aws/aws-sdk-go-v2/credentials v1.13.24 + github.com/aws/aws-sdk-go-v2/service/s3 v1.29.0 github.com/beevik/etree v1.3.0 github.com/bwmarrin/discordgo v0.27.1 github.com/goccy/go-json v0.10.2 github.com/gofiber/contrib/websocket v1.3.0 github.com/gofiber/fiber/v2 v2.51.0 github.com/golang-jwt/jwt/v5 v5.2.0 - github.com/google/uuid v1.4.0 + github.com/google/uuid v1.5.0 github.com/lib/pq v1.10.9 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/r3labs/diff/v3 v3.0.1 @@ -19,7 +23,21 @@ require ( ) require ( - github.com/andybalholm/brotli v1.0.6 // indirect + github.com/andybalholm/brotli v1.0.5 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.8 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.31 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.15 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.19 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.18 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.12.10 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.19.0 // indirect + github.com/aws/smithy-go v1.13.5 // indirect github.com/fasthttp/websocket v1.5.7 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect @@ -32,7 +50,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/philhofer/fwd v1.1.2 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.2.0 // indirect github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect github.com/tinylib/msgp v1.1.8 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect diff --git a/go.sum b/go.sum index 4d8a81e..8f2eec5 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,55 @@ -github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= -github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/aws/aws-sdk-go-v2 v1.17.0/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= +github.com/aws/aws-sdk-go-v2 v1.17.6/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= +github.com/aws/aws-sdk-go-v2 v1.18.0 h1:882kkTpSFhdgYRKVZ/VCgf7sd0ru57p2JCxz4/oN5RY= +github.com/aws/aws-sdk-go-v2 v1.18.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.8 h1:tcFliCWne+zOuUfKNRn8JdFBuWPDuISDH08wD2ULkhk= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.8/go.mod h1:JTnlBSot91steJeti4ryyu/tLd4Sk84O5W22L7O2EQU= +github.com/aws/aws-sdk-go-v2/config v1.18.18 h1:/ePABXvXl3ESlzUGnkkvvNnRFw3Gh13dyqaq0Qo3JcU= +github.com/aws/aws-sdk-go-v2/config v1.18.18/go.mod h1:Lj3E7XcxJnxMa+AYo89YiL68s1cFJRGduChynYU67VA= +github.com/aws/aws-sdk-go-v2/credentials v1.13.17/go.mod h1:K9xeFo1g/YPMguMUD69YpwB4Nyi6W/5wn706xIInJFg= +github.com/aws/aws-sdk-go-v2/credentials v1.13.24 h1:PjiYyls3QdCrzqUN35jMWtUK1vqVZ+zLfdOa/UPFDp0= +github.com/aws/aws-sdk-go-v2/credentials v1.13.24/go.mod h1:jYPYi99wUOPIFi0rhiOvXeSEReVOzBqFNOX5bXYoG2o= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.0/go.mod h1:neYVaeKr5eT7BzwULuG2YbLhzWZ22lpjKdCybR7AXrQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 h1:jJPgroehGvjrde3XufFIJUZVK5A2L9a3KwSFgKy9n8w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3/go.mod h1:4Q0UFP0YJf0NrsEuEYHpM9fTSEVnD16Z3uyEF7J9JGM= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.24/go.mod h1:ghMzB/j2wRbPx5/4jPYxJdOtCG2ggrtY01j8K7FMBDA= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.30/go.mod h1:LUBAO3zNXQjoONBKn/kR1y0Q4cj/D02Ts0uHYjcCQLM= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 h1:kG5eQilShqmJbv11XL1VpyDbaEJzWxd4zRiCG30GSn4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33/go.mod h1:7i0PF1ME/2eUPFcjkVIwq+DOygHEoK92t5cDqNgYbIw= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.18/go.mod h1:fkQKYK/jUhCL/wNS1tOPrlYhr9vqutjCz4zZC1wBE1s= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.24/go.mod h1:gAuCezX/gob6BSMbItsSlMb6WZGV7K2+fWOvk8xBSto= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 h1:vFQlirhuM8lLlpI7imKOMsjdQLuN9CPi+k44F/OFVsk= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27/go.mod h1:UrHnn3QV/d0pBZ6QBAEQcqFLf8FAzLmoUfPVIueOvoM= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.31 h1:hf+Vhp5WtTdcSdE+yEcUz8L73sAzN0R+0jQv+Z51/mI= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.31/go.mod h1:5zUjguZfG5qjhG9/wqmuyHRyUftl2B5Cp6NNxNC6kRA= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.15 h1:15q0OjFjny5qjCC8nI+4DH+MZFDC2/BtXxONBNnVZR8= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.15/go.mod h1:t7/Pw0mlxveHXyfzEkGjzQ59Xu9xUmzOfxe1S52TJ8Q= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.9 h1:Lh1AShsuIJTwMkoxVCAYPJgNG5H+eN6SmoUn8nOZ5wE= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.9/go.mod h1:a9j48l6yL5XINLHLcOKInjdvknN+vWqPBxqeIDw7ktw= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.19 h1:jrV+VRNrUuzcwTZxdZMi1JtKMk71FN1H7VaF8XjGl44= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.19/go.mod h1:HGDDjLf/IyINXk4PcEZSEviZulqnePG76iq9/rC5qqo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.18/go.mod h1:QtCDHDOXunxeihz7iU15e09u9gRIeaa5WeE6FZVnGUo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.24/go.mod h1:HMA4FZG6fyib+NDo5bpIxX1EhYjrAOveZJY2YR0xrNE= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 h1:0iKliEXAcCa2qVtRs7Ot5hItA2MsufrphbRFlz1Owxo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27/go.mod h1:EOwBD4J4S5qYszS5/3DpkejfuK+Z5/1uzICfPaZLtqw= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.18 h1:sk9Z5ZwZpLGq3q8ZhOsw8bORT2t8raWPsFrq/yMMbZ0= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.18/go.mod h1:O1mfO/JzWKUNujOAqD39r7BXqlvhjh/JiPnQ97tvQMc= +github.com/aws/aws-sdk-go-v2/service/s3 v1.29.0 h1:wmROdhyusq7m7HJgSB9Jm955XU4Kvz0FknIbr1dJTjA= +github.com/aws/aws-sdk-go-v2/service/s3 v1.29.0/go.mod h1:syhASH3D6eA1PCga49mGfvISJh/E2QYaooSIqir3pIM= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.5/go.mod h1:vuWiaDB30M/QTC+lI3Wj6S/zb7tpUK2MSYgy3Guh2L0= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.10 h1:UBQjaMTCKwyUYwiVnUt6toEJwGXsLBI6al083tpjJzY= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.10/go.mod h1:ouy2P4z6sJN70fR3ka3wD3Ro3KezSxU6eKGQI2+2fjI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.5/go.mod h1:QjxpHmCwAg0ESGtPQnLIVp7SedTOBMYy+Slr3IfMKeI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10 h1:PkHIIJs8qvq0e5QybnZoG1K/9QTrLr9OsqCIo59jOBA= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10/go.mod h1:AFvkxc8xfBe8XA+5St5XIHHrQQtkxqrRincx4hmMHOk= +github.com/aws/aws-sdk-go-v2/service/sts v1.18.6/go.mod h1:48WJ9l3dwP0GSHWGc5sFGGlCkuA82Mc2xnw+T6Q8aDw= +github.com/aws/aws-sdk-go-v2/service/sts v1.19.0 h1:2DQLAKDteoEDI8zpCzqBMaZlJuoE9iTYD0gFmXVax9E= +github.com/aws/aws-sdk-go-v2/service/sts v1.19.0/go.mod h1:BgQOMsg8av8jset59jelyPW7NoZcZXLVpDsXunGDrk8= +github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= +github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/beevik/etree v1.3.0 h1:hQTc+pylzIKDb23yYprodCWWTt+ojFfUZyzU09a/hmU= github.com/beevik/etree v1.3.0/go.mod h1:aiPf89g/1k3AShMVAzriilpcE4R/Vuor90y83zVZWFc= github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY= @@ -17,8 +67,10 @@ github.com/gofiber/fiber/v2 v2.51.0 h1:JNACcZy5e2tGApWB2QrRpenTWn0fq0hkFm6k0C86g github.com/gofiber/fiber/v2 v2.51.0/go.mod h1:xaQRZQJGqnKOQnbQw+ltvku3/h8QxvNi8o6JiJ7Ll0U= github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -31,6 +83,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= @@ -50,9 +104,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/r3labs/diff/v3 v3.0.1 h1:CBKqf3XmNRHXKmdU7mZP1w7TV0pDyVCis1AUHtA4Xtg= github.com/r3labs/diff/v3 v3.0.1/go.mod h1:f1S9bourRbiM66NskseyUdo0fTmEE0qKrikYJX63dgo= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk= github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -117,6 +170,7 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/handlers/snow.go b/handlers/snow.go index 7a4876e..9e061ef 100644 --- a/handlers/snow.go +++ b/handlers/snow.go @@ -6,6 +6,7 @@ import ( "github.com/ectrc/snow/aid" "github.com/ectrc/snow/fortnite" p "github.com/ectrc/snow/person" + "github.com/ectrc/snow/storage" "github.com/gofiber/fiber/v2" ) @@ -60,4 +61,11 @@ func GetCachedPlayers(c *fiber.Ctx) error { } return c.JSON(players) +} + +func GetSnowConfig(c *fiber.Ctx) error { + return c.JSON(aid.JSON{ + "basic": aid.Config, + "amazon": storage.Repo.Amazon, + }) } \ No newline at end of file diff --git a/handlers/storage.go b/handlers/storage.go index c4f6494..8a3cef3 100644 --- a/handlers/storage.go +++ b/handlers/storage.go @@ -6,39 +6,57 @@ import ( "encoding/hex" "github.com/ectrc/snow/aid" + "github.com/ectrc/snow/person" "github.com/ectrc/snow/storage" "github.com/gofiber/fiber/v2" ) +type cloudstorage struct { + f []aid.JSON +} + +func (c *cloudstorage) Add(name string, bytes []byte) error { + sumation1 := sha1.Sum(bytes) + sumation256 := sha256.Sum256(bytes) + + c.f = append(c.f, aid.JSON{ + "uniqueFilename": name, + "filename": name, + "hash": hex.EncodeToString(sumation1[:]), + "hash256": hex.EncodeToString(sumation256[:]), + "length": len(bytes), + "contentType": "application/octet-stream", + "uploaded": aid.TimeStartOfDay(), + "storageType": "S3", + "storageIds": aid.JSON{ + "primary": "primary", + }, + "doNotCache": false, + }) + + return nil +} + +func (c *cloudstorage) Get() []aid.JSON { + if c.f == nil { + c.f = []aid.JSON{} + } + return c.f +} + func GetCloudStorageFiles(c *fiber.Ctx) error { - files := map[string][]byte { + lookup := map[string][]byte { "DefaultEngine.ini": storage.GetDefaultEngine(), "DefaultGame.ini": storage.GetDefaultGame(), "DefaultRuntimeOptions.ini": storage.GetDefaultRuntime(), } - result := []aid.JSON{} - - for name, data := range files { - sumation1 := sha1.Sum(data) - sumation256 := sha256.Sum256(data) - - result = append(result, aid.JSON{ - "uniqueFilename": name, - "filename": name, - "hash": hex.EncodeToString(sumation1[:]), - "hash256": hex.EncodeToString(sumation256[:]), - "length": len(data), - "contentType": "application/octet-stream", - "uploaded": aid.TimeStartOfDay(), - "storageType": "S3", - "storageIds": aid.JSON{ - "primary": "primary", - }, - "doNotCache": false, - }) + + files := cloudstorage{} + for name, bytes := range lookup { + files.Add(name, bytes) } - return c.Status(200).JSON(result) + return c.Status(200).JSON(files.Get()) } func GetCloudStorageConfig(c *fiber.Ctx) error { @@ -69,13 +87,48 @@ func GetCloudStorageFile(c *fiber.Ctx) error { } func GetUserStorageFiles(c *fiber.Ctx) error { - return c.Status(200).JSON([]aid.JSON{}) + if !aid.Config.Amazon.Enabled { + return c.Status(200).JSON([]aid.JSON{}) + } + person := c.Locals("person").(*person.Person) + files := cloudstorage{} + + file, err := storage.Repo.Amazon.GetUserFile(person.ID) + if err == nil { + files.Add("ClientSettings.sav", file) + } + + return c.Status(200).JSON(files.Get()) } func GetUserStorageFile(c *fiber.Ctx) error { - return c.Status(200).JSON(aid.JSON{}) + if !aid.Config.Amazon.Enabled { + return c.SendStatus(204) + } + person := c.Locals("person").(*person.Person) + + file, err := storage.Repo.Amazon.GetUserFile(person.ID) + if err != nil { + aid.Print("(amazon)", err.Error()) + return c.Status(500).JSON(aid.ErrorBadRequest("Failed to retrieve user file")) + } + + c.Set("Content-Type", "application/octet-stream") + return c.Status(200).Send(file) } func PutUserStorageFile(c *fiber.Ctx) error { - return c.Status(200).JSON(aid.JSON{}) + if !aid.Config.Amazon.Enabled { + return c.SendStatus(204) + } + person := c.Locals("person").(*person.Person) + body := c.Body() + + err := storage.Repo.Amazon.CreateUserFile(person.ID, body) + if err != nil { + aid.Print("(amazon)", err.Error()) + return c.Status(500).JSON(aid.ErrorBadRequest("Failed to create user file")) + } + + return c.SendStatus(204) } diff --git a/main.go b/main.go index 00791ff..f0a89e6 100644 --- a/main.go +++ b/main.go @@ -37,6 +37,10 @@ func init() { } storage.Repo = storage.NewStorage(device) + + if aid.Config.Amazon.Enabled { + storage.Repo.Amazon = storage.NewAmazonClient(aid.Config.Amazon.BucketURI, aid.Config.Amazon.AccessKeyID, aid.Config.Amazon.SecretAccessKey, aid.Config.Amazon.ClientSettingsBucket) + } } func init() { @@ -55,7 +59,7 @@ func init() { found.RemovePermission(perm) } - found.AddPermission("asdasdasdasa") + found.AddPermission("all") aid.Print("(snow) max account " + username + " loaded") } } @@ -139,10 +143,13 @@ func main() { lightswitch.Get("/service/bulk/status", handlers.GetLightswitchBulkStatus) snow := r.Group("/snow") - snow.Get("/sockets", handlers.GetConnectedSockets) - snow.Get("/cache", handlers.GetCachedPlayers) - snow.Get("/cosmetics", handlers.GetPreloadedCosmetics) snow.Get("/image/:playlist", handlers.GetPlaylistImage) + if aid.Config.Output.Level != "prod" { + snow.Get("/cache", handlers.GetCachedPlayers) + snow.Get("/config", handlers.GetSnowConfig) + snow.Get("/sockets", handlers.GetConnectedSockets) + snow.Get("/cosmetics", handlers.GetPreloadedCosmetics) + } discord := snow.Group("/discord") discord.Get("/", handlers.GetDiscordOAuthURL) diff --git a/readme.md b/readme.md index 6ce3a42..a78142a 100644 --- a/readme.md +++ b/readme.md @@ -15,9 +15,8 @@ Performance first, universal Fortnite private server backend written in Go. > The backend is very feature rich and is constantly being updated. Below are the features that are not yet implemented, but are coming soon. -- **Party System V2** Currently it relies on the automatic XMPP solution which is very hard to keep track of. -- Niche profile actions like `RefundMtxPurchase`, `SetAffiliateName` and more. These are barely used however they contribute to the full experience. - Amazon S3 integration to store the **Player Settings** externally. Using the bucket will allow for horizontal scaling which may be required for very large player counts. +- **Party System V2** Currently it relies on the automatic XMPP solution which is very hard to keep track of. - Purchasing the **Battle Pass**. This will require the Battle Pass Storefront ID for every build. I am yet to think of a solution for this. - Seeded randomization for the **Item Shop** instead of a random number generator. This will ensure that even if the backend is restarted, the same random items will be in the shop during that day. - 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. diff --git a/storage/amazon.go b/storage/amazon.go new file mode 100644 index 0000000..d6a51da --- /dev/null +++ b/storage/amazon.go @@ -0,0 +1,92 @@ +package storage + +import ( + "bytes" + "context" + "encoding/base64" + "fmt" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/credentials" + "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/ectrc/snow/aid" +) + +type AmazonClient struct { + client *s3.Client + ClientSettingsBucket string +} + +func NewAmazonClient(bucketURI, accessKeyID, secretAccessKey, clientSettingsBucket string) *AmazonClient { + s := &AmazonClient{} + + r2Resolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) { + return aws.Endpoint{ + URL: bucketURI, + }, nil + }) + + cfg, err := config.LoadDefaultConfig(context.TODO(), + config.WithEndpointResolverWithOptions(r2Resolver), + config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accessKeyID, secretAccessKey, "")), + ) + if err != nil { + panic(err.Error()) + } + + s.client = s3.NewFromConfig(cfg) + s.ClientSettingsBucket = clientSettingsBucket + aid.Print("(amazon) client is ready") + + return s +} + +func (a *AmazonClient) GetAllUserFiles() ([]string, error) { + listObjectsOutput, err := a.client.ListObjectsV2(context.TODO(), &s3.ListObjectsV2Input{ + Bucket: aws.String(a.ClientSettingsBucket), + }) + if err != nil { + return nil, err + } + + var files []string + for _, object := range listObjectsOutput.Contents { + fmt.Println(*object.Key) + files = append(files, *object.Key) + } + + return files, nil +} + +func (a *AmazonClient) CreateUserFile(fileName string, data []byte) error { + _, err := a.client.PutObject(context.TODO(), &s3.PutObjectInput{ + Bucket: aws.String(a.ClientSettingsBucket), + Key: aws.String(fileName), + Body: bytes.NewReader(data), + }) + if err != nil { + return err + } + + return nil +} + +func (a *AmazonClient) GetUserFile(fileName string) ([]byte, error) { + getObjectOutput, err := a.client.GetObject(context.TODO(), &s3.GetObjectInput{ + Bucket: aws.String(a.ClientSettingsBucket), + Key: aws.String(fileName), + }) + if err != nil { + return nil, err + } + + buf := new(bytes.Buffer) + buf.ReadFrom(getObjectOutput.Body) + + bytes := buf.Bytes() + decoded := make([]byte, base64.StdEncoding.DecodedLen(len(bytes))) + base64.StdEncoding.Decode(decoded, bytes) + + return buf.Bytes(), nil +} \ No newline at end of file diff --git a/storage/storage.go b/storage/storage.go index e9b5a07..34af125 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -58,6 +58,7 @@ type Storage interface { type Repository struct { Storage Storage + Amazon *AmazonClient } func NewStorage(s Storage) *Repository {