Compare commits
142 Commits
compose-de
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| b31b3bed5f | |||
| 7eaa84a0ed | |||
| cf0cf9da7a | |||
| 34cd1c7c26 | |||
| 74565e567a | |||
| ea65794255 | |||
| 58706a5687 | |||
| efeb525e19 | |||
|
5a1fe60a7b
|
|||
| 01cfe67848 | |||
| a19bc4d380 | |||
| ae006565d6 | |||
| 57bca99109 | |||
| 058455efd2 | |||
| cd09c9b18e | |||
| e48cbaff72 | |||
| 140d58b808 | |||
| ba761549b8 | |||
| 86643fef8d | |||
| 96af864c5e | |||
| 7db89fd99b | |||
| f2bb1b078d | |||
| 66878fba4e | |||
| bda99550be | |||
| 8a216c7e82 | |||
| e5277c05a1 | |||
| e4af76cfd4 | |||
| 30db1cc375 | |||
| b50c84f8cf | |||
| 7589ef7df6 | |||
| 8ab8c441b0 | |||
| a26b228ebe | |||
| 3654755540 | |||
| c2b50ffab2 | |||
| 75756917b1 | |||
| 8989c08857 | |||
| b2232f4177 | |||
| 7d1c4d2b6c | |||
| ca401d4b96 | |||
|
9ab80931bf
|
|||
|
09022e7292
|
|||
|
3400056c23
|
|||
|
57501d446f
|
|||
| 47c0fff0ec | |||
|
e6ef4e33ac
|
|||
|
aeba355d6c
|
|||
|
8ad94bcdc8
|
|||
|
66f02a2f45
|
|||
|
c6a685310e
|
|||
|
72b95ae271
|
|||
|
7c04cc5c23
|
|||
|
a3bf111b4e
|
|||
|
d82f44e9d2
|
|||
|
4c5a8c39c1
|
|||
|
4e55b1d665
|
|||
|
63d7bec3a3
|
|||
| b7c28616ad | |||
|
ce9b26378c
|
|||
|
df8f6463da
|
|||
|
6ccc56cc55
|
|||
| 89ab25dfb9 | |||
|
ffa1308e73
|
|||
|
b5a367e159
|
|||
|
6b05836a56
|
|||
|
8abee39d15
|
|||
| b0b5ff0725 | |||
|
456b62104b
|
|||
|
574a05424d
|
|||
| 0532965d37 | |||
|
51ba05df69
|
|||
|
30b594b345
|
|||
|
ab361dffd1
|
|||
|
d30a94e42d
|
|||
|
dae378a188
|
|||
|
cd912d683e
|
|||
|
f5dfd5a163
|
|||
|
18d51af7ca
|
|||
|
a45aa700d8
|
|||
|
907b6d2034
|
|||
|
a454ea01b6
|
|||
|
7f8c9210a5
|
|||
| f76f8cd136 | |||
|
55b79b8f9b
|
|||
|
1ce09e3f9b
|
|||
|
2878467cbf
|
|||
|
2639abc7c8
|
|||
|
231c11632b
|
|||
|
877f5c024f
|
|||
|
18ca6de7d3
|
|||
|
6ee8816eed
|
|||
|
de6163093f
|
|||
|
d7456d500b
|
|||
|
1a558f35cf
|
|||
|
b5b07ec1ce
|
|||
|
efd60f45df
|
|||
|
10507c62ab
|
|||
|
0d18167b03
|
|||
|
e90cc425ba
|
|||
|
76512bec0d
|
|||
|
412dadfc3e
|
|||
|
31cca0d450
|
|||
|
cfb7461c5a
|
|||
|
0cb419430a
|
|||
|
807d394646
|
|||
|
3c9d04d637
|
|||
|
94ad0ff774
|
|||
|
25f6c9e086
|
|||
|
a62a231b0a
|
|||
|
468204b299
|
|||
| 63458aee09 | |||
|
8297ed165b
|
|||
|
c98c3fe47e
|
|||
|
9c1e1e4347
|
|||
|
d37a8b9030
|
|||
|
75682a2375
|
|||
|
8f6012c7ef
|
|||
| f59979987f | |||
|
295b1d842b
|
|||
|
93147060d6
|
|||
|
fe539bf190
|
|||
|
759ac08aef
|
|||
|
34bc623ce6
|
|||
|
9999d1ff87
|
|||
|
8a0cd50b68
|
|||
| a232269d54 | |||
| a7c4ca4b49 | |||
| ca9f82a5aa | |||
| e1a2f6f075 | |||
| dad904cd86 | |||
| ad7117a69c | |||
| d566591ea6 | |||
| 424ef6238b | |||
| 0f0ab4d3e0 | |||
| 3e2d782289 | |||
| dc446c545f | |||
|
e234a87d05
|
|||
| 8ab772ea81 | |||
| 9b58b1d26a | |||
| 7689001e74 | |||
| e89abed3d5 | |||
| b792d33164 | |||
| 929b5949f0 |
@@ -24,7 +24,7 @@ steps:
|
|||||||
- staging
|
- staging
|
||||||
|
|
||||||
- name: build-validator
|
- name: build-validator
|
||||||
image: clux/muslrust:1.86.0-stable
|
image: clux/muslrust:1.91.0-stable
|
||||||
commands:
|
commands:
|
||||||
- make build-validator
|
- make build-validator
|
||||||
when:
|
when:
|
||||||
@@ -33,7 +33,7 @@ steps:
|
|||||||
- staging
|
- staging
|
||||||
|
|
||||||
- name: build-frontend
|
- name: build-frontend
|
||||||
image: oven/bun:1.2.8
|
image: oven/bun:1.3.3
|
||||||
commands:
|
commands:
|
||||||
- apt-get update
|
- apt-get update
|
||||||
- apt-get install make
|
- apt-get install make
|
||||||
@@ -149,6 +149,6 @@ steps:
|
|||||||
- pull_request
|
- pull_request
|
||||||
---
|
---
|
||||||
kind: signature
|
kind: signature
|
||||||
hmac: cc7f2f8dac4285b5fa1df163bd92115f1a51a92050687cd08169e17803a2de4c
|
hmac: 6de9d4b91f14b30561856daf275d1fd523e1ce7a5a3651b660f0d8907b4692fb
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|||||||
993
Cargo.lock
generated
993
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"validation",
|
"validation",
|
||||||
"validation/api",
|
"submissions-api-rs",
|
||||||
]
|
]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|||||||
1
Makefile
1
Makefile
@@ -34,7 +34,6 @@ docker-validator:
|
|||||||
make build-validator
|
make build-validator
|
||||||
make image-validator
|
make image-validator
|
||||||
docker-frontend:
|
docker-frontend:
|
||||||
make build-frontend
|
|
||||||
make image-frontend
|
make image-frontend
|
||||||
|
|
||||||
docker: docker-backend docker-validator docker-frontend
|
docker: docker-backend docker-validator docker-frontend
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -13,11 +13,11 @@ Prerequisite: golang installed
|
|||||||
|
|
||||||
1. Run `go generate` to ensure the generated API is up-to-date. This project uses [ogen](https://github.com/ogen-go/ogen).
|
1. Run `go generate` to ensure the generated API is up-to-date. This project uses [ogen](https://github.com/ogen-go/ogen).
|
||||||
```bash
|
```bash
|
||||||
go generate -run "go run github.com/ogen-go/ogen/cmd/ogen@latest --target api --clean openapi.yaml"
|
go generate
|
||||||
```
|
```
|
||||||
2. Build the project.
|
2. Build the project.
|
||||||
```bash
|
```bash
|
||||||
go build git.itzana.me/strafesnet/maps-service
|
make build-backend
|
||||||
```
|
```
|
||||||
|
|
||||||
By default, the project opens at `localhost:8080`.
|
By default, the project opens at `localhost:8080`.
|
||||||
@@ -47,14 +47,16 @@ AUTH_HOST="http://localhost:8083/"
|
|||||||
|
|
||||||
Prerequisite: rust installed
|
Prerequisite: rust installed
|
||||||
|
|
||||||
1. `cd validation`
|
1. `cargo run --release -p maps-validation`
|
||||||
2. `cargo run --release`
|
|
||||||
|
|
||||||
Environment Variables:
|
Environment Variables:
|
||||||
- ROBLOX_GROUP_ID
|
- ROBLOX_GROUP_ID
|
||||||
- RBXCOOKIE
|
- RBXCOOKIE
|
||||||
|
- RBX_API_KEY
|
||||||
- API_HOST_INTERNAL
|
- API_HOST_INTERNAL
|
||||||
- NATS_HOST
|
- NATS_HOST
|
||||||
|
- LOAD_ASSET_VERSION_PLACE_ID
|
||||||
|
- LOAD_ASSET_VERSION_UNIVERSE_ID
|
||||||
|
|
||||||
#### License
|
#### License
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ func main() {
|
|||||||
app := cmds.NewApp()
|
app := cmds.NewApp()
|
||||||
app.Commands = []*cli.Command{
|
app.Commands = []*cli.Command{
|
||||||
cmds.NewServeCommand(),
|
cmds.NewServeCommand(),
|
||||||
|
cmds.NewApiCommand(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := app.Run(os.Args); err != nil {
|
if err := app.Run(os.Args); err != nil {
|
||||||
|
|||||||
30
compose.yaml
30
compose.yaml
@@ -34,7 +34,7 @@ services:
|
|||||||
"--data-rpc-host","dataservice:9000",
|
"--data-rpc-host","dataservice:9000",
|
||||||
]
|
]
|
||||||
env_file:
|
env_file:
|
||||||
- ../auth-compose/strafesnet_staging.env
|
- /home/quat/auth-compose/strafesnet_staging.env
|
||||||
depends_on:
|
depends_on:
|
||||||
- authrpc
|
- authrpc
|
||||||
- nats
|
- nats
|
||||||
@@ -59,11 +59,13 @@ services:
|
|||||||
maptest-validator
|
maptest-validator
|
||||||
container_name: validation
|
container_name: validation
|
||||||
env_file:
|
env_file:
|
||||||
- ../auth-compose/strafesnet_staging.env
|
- /home/quat/auth-compose/strafesnet_staging.env
|
||||||
environment:
|
environment:
|
||||||
- ROBLOX_GROUP_ID=17032139 # "None" is special case string value
|
- ROBLOX_GROUP_ID=17032139 # "None" is special case string value
|
||||||
- API_HOST_INTERNAL=http://submissions:8083/v1
|
- API_HOST_INTERNAL=http://submissions:8083/v1
|
||||||
- NATS_HOST=nats:4222
|
- NATS_HOST=nats:4222
|
||||||
|
- LOAD_ASSET_VERSION_PLACE_ID=14001440964
|
||||||
|
- LOAD_ASSET_VERSION_UNIVERSE_ID=4850603885
|
||||||
depends_on:
|
depends_on:
|
||||||
- nats
|
- nats
|
||||||
# note: this races the submissions which creates a nats stream
|
# note: this races the submissions which creates a nats stream
|
||||||
@@ -73,26 +75,6 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- maps-service-network
|
- maps-service-network
|
||||||
|
|
||||||
public_api:
|
|
||||||
image:
|
|
||||||
maptest-api
|
|
||||||
container_name: public_api
|
|
||||||
command: [
|
|
||||||
# debug
|
|
||||||
"--debug","api",
|
|
||||||
# http service port
|
|
||||||
"--port","8084",
|
|
||||||
"--dev-rpc-host","dev-service:8081",
|
|
||||||
"--maps-rpc-host","maptest-api:8081",
|
|
||||||
]
|
|
||||||
depends_on:
|
|
||||||
- submissions
|
|
||||||
- dev_service
|
|
||||||
networks:
|
|
||||||
- maps-service-network
|
|
||||||
ports:
|
|
||||||
- "8084:8084"
|
|
||||||
|
|
||||||
dataservice:
|
dataservice:
|
||||||
image: registry.itzana.me/strafesnet/data-service:master
|
image: registry.itzana.me/strafesnet/data-service:master
|
||||||
container_name: dataservice
|
container_name: dataservice
|
||||||
@@ -123,7 +105,7 @@ services:
|
|||||||
- REDIS_ADDR=authredis:6379
|
- REDIS_ADDR=authredis:6379
|
||||||
- RBX_GROUP_ID=17032139
|
- RBX_GROUP_ID=17032139
|
||||||
env_file:
|
env_file:
|
||||||
- ../auth-compose/auth-service.env
|
- /home/quat/auth-compose/auth-service.env
|
||||||
depends_on:
|
depends_on:
|
||||||
- authredis
|
- authredis
|
||||||
networks:
|
networks:
|
||||||
@@ -137,7 +119,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- REDIS_ADDR=authredis:6379
|
- REDIS_ADDR=authredis:6379
|
||||||
env_file:
|
env_file:
|
||||||
- ../auth-compose/auth-service.env
|
- /home/quat/auth-compose/auth-service.env
|
||||||
depends_on:
|
depends_on:
|
||||||
- authredis
|
- authredis
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ var SwaggerInfo = &swag.Spec{
|
|||||||
BasePath: "/public-api/v1",
|
BasePath: "/public-api/v1",
|
||||||
Schemes: []string{},
|
Schemes: []string{},
|
||||||
Title: "StrafesNET Maps API",
|
Title: "StrafesNET Maps API",
|
||||||
Description: "Obtain an api key at https://dev.strafes.net\nRequires Data:Read permission",
|
Description: "Obtain an api key at https://dev.strafes.net\nRequires Maps:Read permission",
|
||||||
InfoInstanceName: "swagger",
|
InfoInstanceName: "swagger",
|
||||||
SwaggerTemplate: docTemplate,
|
SwaggerTemplate: docTemplate,
|
||||||
LeftDelim: "{{",
|
LeftDelim: "{{",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"swagger": "2.0",
|
"swagger": "2.0",
|
||||||
"info": {
|
"info": {
|
||||||
"description": "Obtain an api key at https://dev.strafes.net\nRequires Data:Read permission",
|
"description": "Obtain an api key at https://dev.strafes.net\nRequires Maps:Read permission",
|
||||||
"title": "StrafesNET Maps API",
|
"title": "StrafesNET Maps API",
|
||||||
"contact": {},
|
"contact": {},
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ info:
|
|||||||
contact: {}
|
contact: {}
|
||||||
description: |-
|
description: |-
|
||||||
Obtain an api key at https://dev.strafes.net
|
Obtain an api key at https://dev.strafes.net
|
||||||
Requires Data:Read permission
|
Requires Maps:Read permission
|
||||||
title: StrafesNET Maps API
|
title: StrafesNET Maps API
|
||||||
version: "1.0"
|
version: "1.0"
|
||||||
paths:
|
paths:
|
||||||
|
|||||||
47
go.mod
47
go.mod
@@ -6,22 +6,23 @@ toolchain go1.24.5
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
git.itzana.me/StrafesNET/dev-service v0.0.0-20250628052121-92af8193b5ed
|
git.itzana.me/StrafesNET/dev-service v0.0.0-20250628052121-92af8193b5ed
|
||||||
git.itzana.me/strafesnet/go-grpc v0.0.0-20250807005013-301d35b914ef
|
git.itzana.me/strafesnet/go-grpc v0.0.0-20250815013325-1c84f73bdcb1
|
||||||
git.itzana.me/strafesnet/utils v0.0.0-20220716194944-d8ca164052f9
|
git.itzana.me/strafesnet/utils v0.0.0-20220716194944-d8ca164052f9
|
||||||
github.com/dchest/siphash v1.2.3
|
github.com/dchest/siphash v1.2.3
|
||||||
github.com/gin-gonic/gin v1.10.1
|
github.com/gin-gonic/gin v1.10.1
|
||||||
github.com/go-faster/errors v0.7.1
|
github.com/go-faster/errors v0.7.1
|
||||||
github.com/go-faster/jx v1.1.0
|
github.com/go-faster/jx v1.2.0
|
||||||
github.com/nats-io/nats.go v1.37.0
|
github.com/nats-io/nats.go v1.37.0
|
||||||
github.com/ogen-go/ogen v1.2.1
|
github.com/ogen-go/ogen v1.18.0
|
||||||
|
github.com/redis/go-redis/v9 v9.10.0
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/swaggo/files v1.0.1
|
github.com/swaggo/files v1.0.1
|
||||||
github.com/swaggo/gin-swagger v1.6.0
|
github.com/swaggo/gin-swagger v1.6.0
|
||||||
github.com/swaggo/swag v1.16.6
|
github.com/swaggo/swag v1.16.6
|
||||||
github.com/urfave/cli/v2 v2.27.6
|
github.com/urfave/cli/v2 v2.27.6
|
||||||
go.opentelemetry.io/otel v1.32.0
|
go.opentelemetry.io/otel v1.39.0
|
||||||
go.opentelemetry.io/otel/metric v1.32.0
|
go.opentelemetry.io/otel/metric v1.39.0
|
||||||
go.opentelemetry.io/otel/trace v1.32.0
|
go.opentelemetry.io/otel/trace v1.39.0
|
||||||
google.golang.org/grpc v1.48.0
|
google.golang.org/grpc v1.48.0
|
||||||
gorm.io/driver/postgres v1.6.0
|
gorm.io/driver/postgres v1.6.0
|
||||||
gorm.io/gorm v1.25.12
|
gorm.io/gorm v1.25.12
|
||||||
@@ -33,9 +34,11 @@ require (
|
|||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||||
github.com/bytedance/sonic v1.11.6 // indirect
|
github.com/bytedance/sonic v1.11.6 // indirect
|
||||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
@@ -55,7 +58,7 @@ require (
|
|||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/compress v1.17.6 // indirect
|
github.com/klauspost/compress v1.18.1 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/mailru/easyjson v0.7.6 // indirect
|
github.com/mailru/easyjson v0.7.6 // indirect
|
||||||
@@ -65,36 +68,38 @@ require (
|
|||||||
github.com/nats-io/nuid v1.0.1 // indirect
|
github.com/nats-io/nuid v1.0.1 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
|
github.com/shopspring/decimal v1.4.0 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||||
|
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||||
golang.org/x/arch v0.8.0 // indirect
|
golang.org/x/arch v0.8.0 // indirect
|
||||||
golang.org/x/crypto v0.32.0 // indirect
|
golang.org/x/crypto v0.46.0 // indirect
|
||||||
golang.org/x/mod v0.17.0 // indirect
|
golang.org/x/mod v0.31.0 // indirect
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
golang.org/x/tools v0.40.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
|
||||||
google.golang.org/protobuf v1.34.1 // indirect
|
google.golang.org/protobuf v1.34.1 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/dlclark/regexp2 v1.11.0 // indirect
|
github.com/dlclark/regexp2 v1.11.5 // indirect
|
||||||
github.com/fatih/color v1.17.0 // indirect
|
github.com/fatih/color v1.18.0 // indirect
|
||||||
github.com/ghodss/yaml v1.0.0 // indirect
|
github.com/ghodss/yaml v1.0.0 // indirect
|
||||||
github.com/go-faster/yaml v0.4.6 // indirect
|
github.com/go-faster/yaml v0.4.6 // indirect
|
||||||
github.com/go-logr/logr v1.4.2 // indirect
|
github.com/go-logr/logr v1.4.3 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
// github.com/golang/protobuf v1.5.4 // indirect
|
// github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/segmentio/asm v1.2.0 // indirect
|
github.com/segmentio/asm v1.2.1 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.1 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect
|
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 // indirect
|
||||||
golang.org/x/net v0.34.0 // indirect
|
golang.org/x/net v0.48.0 // indirect
|
||||||
golang.org/x/sync v0.12.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.29.0 // indirect
|
golang.org/x/sys v0.39.0 // indirect
|
||||||
golang.org/x/text v0.23.0 // indirect
|
golang.org/x/text v0.32.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
73
go.sum
73
go.sum
@@ -2,8 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
|||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
git.itzana.me/StrafesNET/dev-service v0.0.0-20250628052121-92af8193b5ed h1:eGWIQx2AOrSsLC2dieuSs8MCliRE60tvpZnmxsTBtKc=
|
git.itzana.me/StrafesNET/dev-service v0.0.0-20250628052121-92af8193b5ed h1:eGWIQx2AOrSsLC2dieuSs8MCliRE60tvpZnmxsTBtKc=
|
||||||
git.itzana.me/StrafesNET/dev-service v0.0.0-20250628052121-92af8193b5ed/go.mod h1:KJal0K++M6HEzSry6JJ2iDPZtOQn5zSstNlDbU3X4Jg=
|
git.itzana.me/StrafesNET/dev-service v0.0.0-20250628052121-92af8193b5ed/go.mod h1:KJal0K++M6HEzSry6JJ2iDPZtOQn5zSstNlDbU3X4Jg=
|
||||||
git.itzana.me/strafesnet/go-grpc v0.0.0-20250807005013-301d35b914ef h1:SJi4V4+xzScFnbMRN1gkZxcqR1xKfiT7CaXanLltEzw=
|
git.itzana.me/strafesnet/go-grpc v0.0.0-20250815013325-1c84f73bdcb1 h1:imXibfeYcae6og0TTDUFRQ3CQtstGjIoLbCn+pezD2o=
|
||||||
git.itzana.me/strafesnet/go-grpc v0.0.0-20250807005013-301d35b914ef/go.mod h1:X7XTRUScRkBWq8q8bplbeso105RPDlnY7J6Wy1IwBMs=
|
git.itzana.me/strafesnet/go-grpc v0.0.0-20250815013325-1c84f73bdcb1/go.mod h1:X7XTRUScRkBWq8q8bplbeso105RPDlnY7J6Wy1IwBMs=
|
||||||
git.itzana.me/strafesnet/utils v0.0.0-20220716194944-d8ca164052f9 h1:7lU6jyR7S7Rhh1dnUp7GyIRHUTBXZagw8F4n4hOyxLw=
|
git.itzana.me/strafesnet/utils v0.0.0-20220716194944-d8ca164052f9 h1:7lU6jyR7S7Rhh1dnUp7GyIRHUTBXZagw8F4n4hOyxLw=
|
||||||
git.itzana.me/strafesnet/utils v0.0.0-20220716194944-d8ca164052f9/go.mod h1:uyYerSieEt4v0MJCdPLppG0LtJ4Yj035vuTetWGsxjY=
|
git.itzana.me/strafesnet/utils v0.0.0-20220716194944-d8ca164052f9/go.mod h1:uyYerSieEt4v0MJCdPLppG0LtJ4Yj035vuTetWGsxjY=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
@@ -14,12 +14,18 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
|
|||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
|
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||||
|
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||||
|
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||||
|
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||||
@@ -39,8 +45,12 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA=
|
github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA=
|
||||||
github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc=
|
github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc=
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
||||||
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
|
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
|
||||||
|
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
@@ -49,6 +59,8 @@ github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.
|
|||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
|
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
|
||||||
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
|
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
|
||||||
|
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||||
|
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||||
@@ -63,11 +75,13 @@ github.com/go-faster/errors v0.7.1 h1:MkJTnDoEdi9pDabt1dpWf7AA8/BaSYZqibYyhZ20AY
|
|||||||
github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7FPGZP2quo=
|
github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7FPGZP2quo=
|
||||||
github.com/go-faster/jx v1.1.0 h1:ZsW3wD+snOdmTDy9eIVgQdjUpXRRV4rqW8NS3t+20bg=
|
github.com/go-faster/jx v1.1.0 h1:ZsW3wD+snOdmTDy9eIVgQdjUpXRRV4rqW8NS3t+20bg=
|
||||||
github.com/go-faster/jx v1.1.0/go.mod h1:vKDNikrKoyUmpzaJ0OkIkRQClNHFX/nF3dnTJZb3skg=
|
github.com/go-faster/jx v1.1.0/go.mod h1:vKDNikrKoyUmpzaJ0OkIkRQClNHFX/nF3dnTJZb3skg=
|
||||||
|
github.com/go-faster/jx v1.2.0 h1:T2YHJPrFaYu21fJtUxC9GzmluKu8rVIFDwwGBKTDseI=
|
||||||
|
github.com/go-faster/jx v1.2.0/go.mod h1:UWLOVDmMG597a5tBFPLIWJdUxz5/2emOpfsj9Neg0PE=
|
||||||
github.com/go-faster/yaml v0.4.6 h1:lOK/EhI04gCpPgPhgt0bChS6bvw7G3WwI8xxVe0sw9I=
|
github.com/go-faster/yaml v0.4.6 h1:lOK/EhI04gCpPgPhgt0bChS6bvw7G3WwI8xxVe0sw9I=
|
||||||
github.com/go-faster/yaml v0.4.6/go.mod h1:390dRIvV4zbnO7qC9FGo6YYutc+wyyUSHBgbXL52eXk=
|
github.com/go-faster/yaml v0.4.6/go.mod h1:390dRIvV4zbnO7qC9FGo6YYutc+wyyUSHBgbXL52eXk=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
@@ -113,8 +127,8 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
@@ -140,6 +154,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
|||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
|
github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
|
||||||
github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||||
|
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
|
||||||
|
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||||
@@ -159,6 +175,8 @@ github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA
|
|||||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||||
|
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
@@ -176,11 +194,15 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS
|
|||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/ogen-go/ogen v1.2.1 h1:C5A0lvUMu2wl+eWIxnpXMWnuOJ26a2FyzR1CIC2qG0M=
|
github.com/ogen-go/ogen v1.2.1 h1:C5A0lvUMu2wl+eWIxnpXMWnuOJ26a2FyzR1CIC2qG0M=
|
||||||
github.com/ogen-go/ogen v1.2.1/go.mod h1:P2zQdEu8UqaVRfD5GEFvl+9q63VjMLvDquq1wVbyInM=
|
github.com/ogen-go/ogen v1.2.1/go.mod h1:P2zQdEu8UqaVRfD5GEFvl+9q63VjMLvDquq1wVbyInM=
|
||||||
|
github.com/ogen-go/ogen v1.18.0 h1:6RQ7lFBjOeNaUWu4getfqIh4GJbEY4hqKuzDtec/g60=
|
||||||
|
github.com/ogen-go/ogen v1.18.0/go.mod h1:dHFr2Wf6cA7tSxMI+zPC21UR5hAlDw8ZYUkK3PziURY=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/redis/go-redis/v9 v9.10.0 h1:FxwK3eV8p/CQa0Ch276C7u2d0eNC9kCmAYQ7mCXCzVs=
|
||||||
|
github.com/redis/go-redis/v9 v9.10.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
|
||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
@@ -188,6 +210,10 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
|
|||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||||
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
||||||
|
github.com/segmentio/asm v1.2.1 h1:DTNbBqs57ioxAD4PrArqftgypG4/qNpXoJx8TVXxPR0=
|
||||||
|
github.com/segmentio/asm v1.2.1/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
||||||
|
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
|
||||||
|
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
@@ -204,8 +230,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
|
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
|
||||||
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
|
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
|
||||||
github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M=
|
github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M=
|
||||||
@@ -221,12 +248,14 @@ github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5
|
|||||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
|
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||||
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
|
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||||
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
|
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
|
||||||
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
|
go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=
|
||||||
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
|
go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=
|
||||||
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
|
go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=
|
||||||
|
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
|
||||||
|
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
|
||||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
@@ -234,6 +263,8 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
|||||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
|
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||||
|
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||||
@@ -242,15 +273,21 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||||
|
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||||
|
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg=
|
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg=
|
||||||
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
||||||
|
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0=
|
||||||
|
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
|
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
|
||||||
|
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@@ -266,6 +303,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
|||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||||
|
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||||
|
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@@ -275,6 +314,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
|
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -293,6 +334,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||||
|
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
@@ -303,6 +346,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||||
|
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||||
|
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
@@ -312,6 +357,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
|||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||||
|
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||||
|
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|||||||
355
openapi.yaml
355
openapi.yaml
@@ -14,15 +14,41 @@ tags:
|
|||||||
description: Long-running operations
|
description: Long-running operations
|
||||||
- name: Session
|
- name: Session
|
||||||
description: Session queries
|
description: Session queries
|
||||||
|
- name: Stats
|
||||||
|
description: Statistics queries
|
||||||
- name: Submissions
|
- name: Submissions
|
||||||
description: Submission operations
|
description: Submission operations
|
||||||
- name: Scripts
|
- name: Scripts
|
||||||
description: Script operations
|
description: Script operations
|
||||||
- name: ScriptPolicy
|
- name: ScriptPolicy
|
||||||
description: Script policy operations
|
description: Script policy operations
|
||||||
|
- name: Thumbnails
|
||||||
|
description: Thumbnail operations
|
||||||
|
- name: Users
|
||||||
|
description: User operations
|
||||||
security:
|
security:
|
||||||
- cookieAuth: []
|
- cookieAuth: []
|
||||||
paths:
|
paths:
|
||||||
|
/stats:
|
||||||
|
get:
|
||||||
|
summary: Get aggregate statistics
|
||||||
|
operationId: getStats
|
||||||
|
tags:
|
||||||
|
- Stats
|
||||||
|
security: []
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: Successful response
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Stats"
|
||||||
|
default:
|
||||||
|
description: General Error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
/session/user:
|
/session/user:
|
||||||
get:
|
get:
|
||||||
summary: Get information about the currently logged in user
|
summary: Get information about the currently logged in user
|
||||||
@@ -244,6 +270,12 @@ paths:
|
|||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
minimum: 0
|
minimum: 0
|
||||||
|
- name: AssetVersion
|
||||||
|
in: query
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
- name: TargetAssetID
|
- name: TargetAssetID
|
||||||
in: query
|
in: query
|
||||||
schema:
|
schema:
|
||||||
@@ -587,7 +619,7 @@ paths:
|
|||||||
$ref: "#/components/schemas/Error"
|
$ref: "#/components/schemas/Error"
|
||||||
/mapfixes/{MapfixID}/status/trigger-upload:
|
/mapfixes/{MapfixID}/status/trigger-upload:
|
||||||
post:
|
post:
|
||||||
summary: Role Admin changes status from Validated -> Uploading
|
summary: Role MapfixUpload changes status from Validated -> Uploading
|
||||||
operationId: actionMapfixTriggerUpload
|
operationId: actionMapfixTriggerUpload
|
||||||
tags:
|
tags:
|
||||||
- Mapfixes
|
- Mapfixes
|
||||||
@@ -604,7 +636,7 @@ paths:
|
|||||||
$ref: "#/components/schemas/Error"
|
$ref: "#/components/schemas/Error"
|
||||||
/mapfixes/{MapfixID}/status/reset-uploading:
|
/mapfixes/{MapfixID}/status/reset-uploading:
|
||||||
post:
|
post:
|
||||||
summary: Role Admin manually resets uploading softlock and changes status from Uploading -> Validated
|
summary: Role MapfixUpload manually resets uploading softlock and changes status from Uploading -> Validated
|
||||||
operationId: actionMapfixValidated
|
operationId: actionMapfixValidated
|
||||||
tags:
|
tags:
|
||||||
- Mapfixes
|
- Mapfixes
|
||||||
@@ -619,6 +651,40 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/Error"
|
$ref: "#/components/schemas/Error"
|
||||||
|
/mapfixes/{MapfixID}/status/trigger-release:
|
||||||
|
post:
|
||||||
|
summary: Role MapfixUpload changes status from Uploaded -> Releasing
|
||||||
|
operationId: actionMapfixTriggerRelease
|
||||||
|
tags:
|
||||||
|
- Mapfixes
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/MapfixID'
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: Successful response
|
||||||
|
default:
|
||||||
|
description: General Error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
/mapfixes/{MapfixID}/status/reset-releasing:
|
||||||
|
post:
|
||||||
|
summary: Role MapfixUpload manually resets releasing softlock and changes status from Releasing -> Uploaded
|
||||||
|
operationId: actionMapfixUploaded
|
||||||
|
tags:
|
||||||
|
- Mapfixes
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/MapfixID'
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: Successful response
|
||||||
|
default:
|
||||||
|
description: General Error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
/operations/{OperationID}:
|
/operations/{OperationID}:
|
||||||
get:
|
get:
|
||||||
summary: Retrieve operation with ID
|
summary: Retrieve operation with ID
|
||||||
@@ -698,6 +764,12 @@ paths:
|
|||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
minimum: 0
|
minimum: 0
|
||||||
|
- name: AssetVersion
|
||||||
|
in: query
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
- name: UploadedAssetID
|
- name: UploadedAssetID
|
||||||
in: query
|
in: query
|
||||||
schema:
|
schema:
|
||||||
@@ -1067,7 +1139,7 @@ paths:
|
|||||||
$ref: "#/components/schemas/Error"
|
$ref: "#/components/schemas/Error"
|
||||||
/submissions/{SubmissionID}/status/trigger-upload:
|
/submissions/{SubmissionID}/status/trigger-upload:
|
||||||
post:
|
post:
|
||||||
summary: Role Admin changes status from Validated -> Uploading
|
summary: Role SubmissionUpload changes status from Validated -> Uploading
|
||||||
operationId: actionSubmissionTriggerUpload
|
operationId: actionSubmissionTriggerUpload
|
||||||
tags:
|
tags:
|
||||||
- Submissions
|
- Submissions
|
||||||
@@ -1084,7 +1156,7 @@ paths:
|
|||||||
$ref: "#/components/schemas/Error"
|
$ref: "#/components/schemas/Error"
|
||||||
/submissions/{SubmissionID}/status/reset-uploading:
|
/submissions/{SubmissionID}/status/reset-uploading:
|
||||||
post:
|
post:
|
||||||
summary: Role Admin manually resets uploading softlock and changes status from Uploading -> Validated
|
summary: Role SubmissionUpload manually resets uploading softlock and changes status from Uploading -> Validated
|
||||||
operationId: actionSubmissionValidated
|
operationId: actionSubmissionValidated
|
||||||
tags:
|
tags:
|
||||||
- Submissions
|
- Submissions
|
||||||
@@ -1101,7 +1173,7 @@ paths:
|
|||||||
$ref: "#/components/schemas/Error"
|
$ref: "#/components/schemas/Error"
|
||||||
/release-submissions:
|
/release-submissions:
|
||||||
post:
|
post:
|
||||||
summary: Release a set of uploaded maps
|
summary: Release a set of uploaded maps. Role SubmissionRelease
|
||||||
operationId: releaseSubmissions
|
operationId: releaseSubmissions
|
||||||
tags:
|
tags:
|
||||||
- Submissions
|
- Submissions
|
||||||
@@ -1118,6 +1190,10 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
"201":
|
"201":
|
||||||
description: Successful response
|
description: Successful response
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/OperationID"
|
||||||
default:
|
default:
|
||||||
description: General Error
|
description: General Error
|
||||||
content:
|
content:
|
||||||
@@ -1388,6 +1464,222 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/Error"
|
$ref: "#/components/schemas/Error"
|
||||||
|
/thumbnails/assets:
|
||||||
|
post:
|
||||||
|
summary: Batch fetch asset thumbnails
|
||||||
|
operationId: batchAssetThumbnails
|
||||||
|
tags:
|
||||||
|
- Thumbnails
|
||||||
|
security: []
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- assetIds
|
||||||
|
properties:
|
||||||
|
assetIds:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: integer
|
||||||
|
format: uint64
|
||||||
|
maxItems: 100
|
||||||
|
description: Array of asset IDs (max 100)
|
||||||
|
size:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- "150x150"
|
||||||
|
- "420x420"
|
||||||
|
- "768x432"
|
||||||
|
default: "420x420"
|
||||||
|
description: Thumbnail size
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: Successful response
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
thumbnails:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
description: Map of asset ID to thumbnail URL
|
||||||
|
default:
|
||||||
|
description: General Error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
/thumbnails/asset/{AssetID}:
|
||||||
|
get:
|
||||||
|
summary: Get single asset thumbnail
|
||||||
|
operationId: getAssetThumbnail
|
||||||
|
tags:
|
||||||
|
- Thumbnails
|
||||||
|
security: []
|
||||||
|
parameters:
|
||||||
|
- name: AssetID
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: uint64
|
||||||
|
- name: size
|
||||||
|
in: query
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- "150x150"
|
||||||
|
- "420x420"
|
||||||
|
- "768x432"
|
||||||
|
default: "420x420"
|
||||||
|
responses:
|
||||||
|
"302":
|
||||||
|
description: Redirect to thumbnail URL
|
||||||
|
headers:
|
||||||
|
Location:
|
||||||
|
description: URL to redirect to
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
default:
|
||||||
|
description: General Error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
/thumbnails/users:
|
||||||
|
post:
|
||||||
|
summary: Batch fetch user avatar thumbnails
|
||||||
|
operationId: batchUserThumbnails
|
||||||
|
tags:
|
||||||
|
- Thumbnails
|
||||||
|
security: []
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- userIds
|
||||||
|
properties:
|
||||||
|
userIds:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: integer
|
||||||
|
format: uint64
|
||||||
|
maxItems: 100
|
||||||
|
description: Array of user IDs (max 100)
|
||||||
|
size:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- "150x150"
|
||||||
|
- "420x420"
|
||||||
|
- "768x432"
|
||||||
|
default: "150x150"
|
||||||
|
description: Thumbnail size
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: Successful response
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
thumbnails:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
description: Map of user ID to thumbnail URL
|
||||||
|
default:
|
||||||
|
description: General Error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
/thumbnails/user/{UserID}:
|
||||||
|
get:
|
||||||
|
summary: Get single user avatar thumbnail
|
||||||
|
operationId: getUserThumbnail
|
||||||
|
tags:
|
||||||
|
- Thumbnails
|
||||||
|
security: []
|
||||||
|
parameters:
|
||||||
|
- name: UserID
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: uint64
|
||||||
|
- name: size
|
||||||
|
in: query
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- "150x150"
|
||||||
|
- "420x420"
|
||||||
|
- "768x432"
|
||||||
|
default: "150x150"
|
||||||
|
responses:
|
||||||
|
"302":
|
||||||
|
description: Redirect to thumbnail URL
|
||||||
|
headers:
|
||||||
|
Location:
|
||||||
|
description: URL to redirect to
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
default:
|
||||||
|
description: General Error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
/usernames:
|
||||||
|
post:
|
||||||
|
summary: Batch fetch usernames
|
||||||
|
operationId: batchUsernames
|
||||||
|
tags:
|
||||||
|
- Users
|
||||||
|
security: []
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- userIds
|
||||||
|
properties:
|
||||||
|
userIds:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: integer
|
||||||
|
format: uint64
|
||||||
|
maxItems: 100
|
||||||
|
description: Array of user IDs (max 100)
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: Successful response
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
usernames:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
description: Map of user ID to username
|
||||||
|
default:
|
||||||
|
description: General Error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
components:
|
components:
|
||||||
securitySchemes:
|
securitySchemes:
|
||||||
cookieAuth:
|
cookieAuth:
|
||||||
@@ -1624,6 +1916,8 @@ components:
|
|||||||
- Submitter
|
- Submitter
|
||||||
- AssetID
|
- AssetID
|
||||||
- AssetVersion
|
- AssetVersion
|
||||||
|
# - ValidatedAssetID
|
||||||
|
# - ValidatedAssetVersion
|
||||||
- Completed
|
- Completed
|
||||||
- TargetAssetID
|
- TargetAssetID
|
||||||
- StatusID
|
- StatusID
|
||||||
@@ -1664,6 +1958,14 @@ components:
|
|||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
minimum: 0
|
minimum: 0
|
||||||
|
ValidatedAssetID:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
ValidatedAssetVersion:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
Completed:
|
Completed:
|
||||||
type: boolean
|
type: boolean
|
||||||
TargetAssetID:
|
TargetAssetID:
|
||||||
@@ -1902,7 +2204,7 @@ components:
|
|||||||
properties:
|
properties:
|
||||||
Name:
|
Name:
|
||||||
type: string
|
type: string
|
||||||
maxLength: 128
|
maxLength: 256
|
||||||
Source:
|
Source:
|
||||||
type: string
|
type: string
|
||||||
maxLength: 1048576
|
maxLength: 1048576
|
||||||
@@ -2001,6 +2303,47 @@ components:
|
|||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
minimum: 0
|
minimum: 0
|
||||||
|
Stats:
|
||||||
|
description: Aggregate statistics for submissions and mapfixes
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
TotalSubmissions:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
description: Total number of submissions
|
||||||
|
TotalMapfixes:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
description: Total number of mapfixes
|
||||||
|
ReleasedSubmissions:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
description: Number of released submissions
|
||||||
|
ReleasedMapfixes:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
description: Number of released mapfixes
|
||||||
|
SubmittedSubmissions:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
description: Number of submissions under review
|
||||||
|
SubmittedMapfixes:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
description: Number of mapfixes under review
|
||||||
|
required:
|
||||||
|
- TotalSubmissions
|
||||||
|
- TotalMapfixes
|
||||||
|
- ReleasedSubmissions
|
||||||
|
- ReleasedMapfixes
|
||||||
|
- SubmittedSubmissions
|
||||||
|
- SubmittedMapfixes
|
||||||
Error:
|
Error:
|
||||||
description: Represents error object
|
description: Represents error object
|
||||||
type: object
|
type: object
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ package api
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"go.opentelemetry.io/otel"
|
|
||||||
"go.opentelemetry.io/otel/metric"
|
|
||||||
"go.opentelemetry.io/otel/trace"
|
|
||||||
|
|
||||||
ht "github.com/ogen-go/ogen/http"
|
ht "github.com/ogen-go/ogen/http"
|
||||||
"github.com/ogen-go/ogen/middleware"
|
"github.com/ogen-go/ogen/middleware"
|
||||||
"github.com/ogen-go/ogen/ogenerrors"
|
"github.com/ogen-go/ogen/ogenerrors"
|
||||||
"github.com/ogen-go/ogen/otelogen"
|
"github.com/ogen-go/ogen/otelogen"
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/metric"
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -32,6 +32,7 @@ type otelConfig struct {
|
|||||||
Tracer trace.Tracer
|
Tracer trace.Tracer
|
||||||
MeterProvider metric.MeterProvider
|
MeterProvider metric.MeterProvider
|
||||||
Meter metric.Meter
|
Meter metric.Meter
|
||||||
|
Attributes []attribute.KeyValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *otelConfig) initOTEL() {
|
func (cfg *otelConfig) initOTEL() {
|
||||||
@@ -215,6 +216,13 @@ func WithMeterProvider(provider metric.MeterProvider) Option {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithAttributes specifies default otel attributes.
|
||||||
|
func WithAttributes(attributes ...attribute.KeyValue) Option {
|
||||||
|
return otelOptionFunc(func(cfg *otelConfig) {
|
||||||
|
cfg.Attributes = attributes
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// WithClient specifies http client to use.
|
// WithClient specifies http client to use.
|
||||||
func WithClient(client ht.Client) ClientOption {
|
func WithClient(client ht.Client) ClientOption {
|
||||||
return optionFunc[clientConfig](func(cfg *clientConfig) {
|
return optionFunc[clientConfig](func(cfg *clientConfig) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
19
pkg/api/oas_defaults_gen.go
Normal file
19
pkg/api/oas_defaults_gen.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
// setDefaults set default value of fields.
|
||||||
|
func (s *BatchAssetThumbnailsReq) setDefaults() {
|
||||||
|
{
|
||||||
|
val := BatchAssetThumbnailsReqSize("420x420")
|
||||||
|
s.Size.SetTo(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// setDefaults set default value of fields.
|
||||||
|
func (s *BatchUserThumbnailsReq) setDefaults() {
|
||||||
|
{
|
||||||
|
val := BatchUserThumbnailsReqSize("150x150")
|
||||||
|
s.Size.SetTo(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -12,10 +12,12 @@ const (
|
|||||||
ActionMapfixResetSubmittingOperation OperationName = "ActionMapfixResetSubmitting"
|
ActionMapfixResetSubmittingOperation OperationName = "ActionMapfixResetSubmitting"
|
||||||
ActionMapfixRetryValidateOperation OperationName = "ActionMapfixRetryValidate"
|
ActionMapfixRetryValidateOperation OperationName = "ActionMapfixRetryValidate"
|
||||||
ActionMapfixRevokeOperation OperationName = "ActionMapfixRevoke"
|
ActionMapfixRevokeOperation OperationName = "ActionMapfixRevoke"
|
||||||
|
ActionMapfixTriggerReleaseOperation OperationName = "ActionMapfixTriggerRelease"
|
||||||
ActionMapfixTriggerSubmitOperation OperationName = "ActionMapfixTriggerSubmit"
|
ActionMapfixTriggerSubmitOperation OperationName = "ActionMapfixTriggerSubmit"
|
||||||
ActionMapfixTriggerSubmitUncheckedOperation OperationName = "ActionMapfixTriggerSubmitUnchecked"
|
ActionMapfixTriggerSubmitUncheckedOperation OperationName = "ActionMapfixTriggerSubmitUnchecked"
|
||||||
ActionMapfixTriggerUploadOperation OperationName = "ActionMapfixTriggerUpload"
|
ActionMapfixTriggerUploadOperation OperationName = "ActionMapfixTriggerUpload"
|
||||||
ActionMapfixTriggerValidateOperation OperationName = "ActionMapfixTriggerValidate"
|
ActionMapfixTriggerValidateOperation OperationName = "ActionMapfixTriggerValidate"
|
||||||
|
ActionMapfixUploadedOperation OperationName = "ActionMapfixUploaded"
|
||||||
ActionMapfixValidatedOperation OperationName = "ActionMapfixValidated"
|
ActionMapfixValidatedOperation OperationName = "ActionMapfixValidated"
|
||||||
ActionSubmissionAcceptedOperation OperationName = "ActionSubmissionAccepted"
|
ActionSubmissionAcceptedOperation OperationName = "ActionSubmissionAccepted"
|
||||||
ActionSubmissionRejectOperation OperationName = "ActionSubmissionReject"
|
ActionSubmissionRejectOperation OperationName = "ActionSubmissionReject"
|
||||||
@@ -28,6 +30,9 @@ const (
|
|||||||
ActionSubmissionTriggerUploadOperation OperationName = "ActionSubmissionTriggerUpload"
|
ActionSubmissionTriggerUploadOperation OperationName = "ActionSubmissionTriggerUpload"
|
||||||
ActionSubmissionTriggerValidateOperation OperationName = "ActionSubmissionTriggerValidate"
|
ActionSubmissionTriggerValidateOperation OperationName = "ActionSubmissionTriggerValidate"
|
||||||
ActionSubmissionValidatedOperation OperationName = "ActionSubmissionValidated"
|
ActionSubmissionValidatedOperation OperationName = "ActionSubmissionValidated"
|
||||||
|
BatchAssetThumbnailsOperation OperationName = "BatchAssetThumbnails"
|
||||||
|
BatchUserThumbnailsOperation OperationName = "BatchUserThumbnails"
|
||||||
|
BatchUsernamesOperation OperationName = "BatchUsernames"
|
||||||
CreateMapfixOperation OperationName = "CreateMapfix"
|
CreateMapfixOperation OperationName = "CreateMapfix"
|
||||||
CreateMapfixAuditCommentOperation OperationName = "CreateMapfixAuditComment"
|
CreateMapfixAuditCommentOperation OperationName = "CreateMapfixAuditComment"
|
||||||
CreateScriptOperation OperationName = "CreateScript"
|
CreateScriptOperation OperationName = "CreateScript"
|
||||||
@@ -38,12 +43,15 @@ const (
|
|||||||
DeleteScriptOperation OperationName = "DeleteScript"
|
DeleteScriptOperation OperationName = "DeleteScript"
|
||||||
DeleteScriptPolicyOperation OperationName = "DeleteScriptPolicy"
|
DeleteScriptPolicyOperation OperationName = "DeleteScriptPolicy"
|
||||||
DownloadMapAssetOperation OperationName = "DownloadMapAsset"
|
DownloadMapAssetOperation OperationName = "DownloadMapAsset"
|
||||||
|
GetAssetThumbnailOperation OperationName = "GetAssetThumbnail"
|
||||||
GetMapOperation OperationName = "GetMap"
|
GetMapOperation OperationName = "GetMap"
|
||||||
GetMapfixOperation OperationName = "GetMapfix"
|
GetMapfixOperation OperationName = "GetMapfix"
|
||||||
GetOperationOperation OperationName = "GetOperation"
|
GetOperationOperation OperationName = "GetOperation"
|
||||||
GetScriptOperation OperationName = "GetScript"
|
GetScriptOperation OperationName = "GetScript"
|
||||||
GetScriptPolicyOperation OperationName = "GetScriptPolicy"
|
GetScriptPolicyOperation OperationName = "GetScriptPolicy"
|
||||||
|
GetStatsOperation OperationName = "GetStats"
|
||||||
GetSubmissionOperation OperationName = "GetSubmission"
|
GetSubmissionOperation OperationName = "GetSubmission"
|
||||||
|
GetUserThumbnailOperation OperationName = "GetUserThumbnail"
|
||||||
ListMapfixAuditEventsOperation OperationName = "ListMapfixAuditEvents"
|
ListMapfixAuditEventsOperation OperationName = "ListMapfixAuditEvents"
|
||||||
ListMapfixesOperation OperationName = "ListMapfixes"
|
ListMapfixesOperation OperationName = "ListMapfixes"
|
||||||
ListMapsOperation OperationName = "ListMaps"
|
ListMapsOperation OperationName = "ListMaps"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"mime"
|
"mime"
|
||||||
@@ -10,13 +11,13 @@ import (
|
|||||||
|
|
||||||
"github.com/go-faster/errors"
|
"github.com/go-faster/errors"
|
||||||
"github.com/go-faster/jx"
|
"github.com/go-faster/jx"
|
||||||
|
|
||||||
"github.com/ogen-go/ogen/ogenerrors"
|
"github.com/ogen-go/ogen/ogenerrors"
|
||||||
"github.com/ogen-go/ogen/validate"
|
"github.com/ogen-go/ogen/validate"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) decodeCreateMapfixRequest(r *http.Request) (
|
func (s *Server) decodeBatchAssetThumbnailsRequest(r *http.Request) (
|
||||||
req *MapfixTriggerCreate,
|
req *BatchAssetThumbnailsReq,
|
||||||
|
rawBody []byte,
|
||||||
close func() error,
|
close func() error,
|
||||||
rerr error,
|
rerr error,
|
||||||
) {
|
) {
|
||||||
@@ -37,22 +38,266 @@ func (s *Server) decodeCreateMapfixRequest(r *http.Request) (
|
|||||||
}()
|
}()
|
||||||
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, errors.Wrap(err, "parse media type")
|
return req, rawBody, close, errors.Wrap(err, "parse media type")
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case ct == "application/json":
|
case ct == "application/json":
|
||||||
if r.ContentLength == 0 {
|
if r.ContentLength == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
buf, err := io.ReadAll(r.Body)
|
buf, err := io.ReadAll(r.Body)
|
||||||
|
defer func() {
|
||||||
|
_ = r.Body.Close()
|
||||||
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the body to allow for downstream reading.
|
||||||
|
r.Body = io.NopCloser(bytes.NewBuffer(buf))
|
||||||
|
|
||||||
if len(buf) == 0 {
|
if len(buf) == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rawBody = append(rawBody, buf...)
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var request BatchAssetThumbnailsReq
|
||||||
|
if err := func() error {
|
||||||
|
if err := request.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return req, rawBody, close, err
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if err := request.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return req, rawBody, close, errors.Wrap(err, "validate")
|
||||||
|
}
|
||||||
|
return &request, rawBody, close, nil
|
||||||
|
default:
|
||||||
|
return req, rawBody, close, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) decodeBatchUserThumbnailsRequest(r *http.Request) (
|
||||||
|
req *BatchUserThumbnailsReq,
|
||||||
|
rawBody []byte,
|
||||||
|
close func() error,
|
||||||
|
rerr error,
|
||||||
|
) {
|
||||||
|
var closers []func() error
|
||||||
|
close = func() error {
|
||||||
|
var merr error
|
||||||
|
// Close in reverse order, to match defer behavior.
|
||||||
|
for i := len(closers) - 1; i >= 0; i-- {
|
||||||
|
c := closers[i]
|
||||||
|
merr = errors.Join(merr, c())
|
||||||
|
}
|
||||||
|
return merr
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if rerr != nil {
|
||||||
|
rerr = errors.Join(rerr, close())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return req, rawBody, close, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
if r.ContentLength == 0 {
|
||||||
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
|
}
|
||||||
|
buf, err := io.ReadAll(r.Body)
|
||||||
|
defer func() {
|
||||||
|
_ = r.Body.Close()
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return req, rawBody, close, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the body to allow for downstream reading.
|
||||||
|
r.Body = io.NopCloser(bytes.NewBuffer(buf))
|
||||||
|
|
||||||
|
if len(buf) == 0 {
|
||||||
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
rawBody = append(rawBody, buf...)
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var request BatchUserThumbnailsReq
|
||||||
|
if err := func() error {
|
||||||
|
if err := request.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return req, rawBody, close, err
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if err := request.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return req, rawBody, close, errors.Wrap(err, "validate")
|
||||||
|
}
|
||||||
|
return &request, rawBody, close, nil
|
||||||
|
default:
|
||||||
|
return req, rawBody, close, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) decodeBatchUsernamesRequest(r *http.Request) (
|
||||||
|
req *BatchUsernamesReq,
|
||||||
|
rawBody []byte,
|
||||||
|
close func() error,
|
||||||
|
rerr error,
|
||||||
|
) {
|
||||||
|
var closers []func() error
|
||||||
|
close = func() error {
|
||||||
|
var merr error
|
||||||
|
// Close in reverse order, to match defer behavior.
|
||||||
|
for i := len(closers) - 1; i >= 0; i-- {
|
||||||
|
c := closers[i]
|
||||||
|
merr = errors.Join(merr, c())
|
||||||
|
}
|
||||||
|
return merr
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if rerr != nil {
|
||||||
|
rerr = errors.Join(rerr, close())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return req, rawBody, close, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
if r.ContentLength == 0 {
|
||||||
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
|
}
|
||||||
|
buf, err := io.ReadAll(r.Body)
|
||||||
|
defer func() {
|
||||||
|
_ = r.Body.Close()
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return req, rawBody, close, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the body to allow for downstream reading.
|
||||||
|
r.Body = io.NopCloser(bytes.NewBuffer(buf))
|
||||||
|
|
||||||
|
if len(buf) == 0 {
|
||||||
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
rawBody = append(rawBody, buf...)
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var request BatchUsernamesReq
|
||||||
|
if err := func() error {
|
||||||
|
if err := request.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return req, rawBody, close, err
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if err := request.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return req, rawBody, close, errors.Wrap(err, "validate")
|
||||||
|
}
|
||||||
|
return &request, rawBody, close, nil
|
||||||
|
default:
|
||||||
|
return req, rawBody, close, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) decodeCreateMapfixRequest(r *http.Request) (
|
||||||
|
req *MapfixTriggerCreate,
|
||||||
|
rawBody []byte,
|
||||||
|
close func() error,
|
||||||
|
rerr error,
|
||||||
|
) {
|
||||||
|
var closers []func() error
|
||||||
|
close = func() error {
|
||||||
|
var merr error
|
||||||
|
// Close in reverse order, to match defer behavior.
|
||||||
|
for i := len(closers) - 1; i >= 0; i-- {
|
||||||
|
c := closers[i]
|
||||||
|
merr = errors.Join(merr, c())
|
||||||
|
}
|
||||||
|
return merr
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if rerr != nil {
|
||||||
|
rerr = errors.Join(rerr, close())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return req, rawBody, close, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
if r.ContentLength == 0 {
|
||||||
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
|
}
|
||||||
|
buf, err := io.ReadAll(r.Body)
|
||||||
|
defer func() {
|
||||||
|
_ = r.Body.Close()
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return req, rawBody, close, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the body to allow for downstream reading.
|
||||||
|
r.Body = io.NopCloser(bytes.NewBuffer(buf))
|
||||||
|
|
||||||
|
if len(buf) == 0 {
|
||||||
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
rawBody = append(rawBody, buf...)
|
||||||
d := jx.DecodeBytes(buf)
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
var request MapfixTriggerCreate
|
var request MapfixTriggerCreate
|
||||||
@@ -70,7 +315,7 @@ func (s *Server) decodeCreateMapfixRequest(r *http.Request) (
|
|||||||
Body: buf,
|
Body: buf,
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
if err := func() error {
|
if err := func() error {
|
||||||
if err := request.Validate(); err != nil {
|
if err := request.Validate(); err != nil {
|
||||||
@@ -78,16 +323,17 @@ func (s *Server) decodeCreateMapfixRequest(r *http.Request) (
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}(); err != nil {
|
}(); err != nil {
|
||||||
return req, close, errors.Wrap(err, "validate")
|
return req, rawBody, close, errors.Wrap(err, "validate")
|
||||||
}
|
}
|
||||||
return &request, close, nil
|
return &request, rawBody, close, nil
|
||||||
default:
|
default:
|
||||||
return req, close, validate.InvalidContentType(ct)
|
return req, rawBody, close, validate.InvalidContentType(ct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) decodeCreateMapfixAuditCommentRequest(r *http.Request) (
|
func (s *Server) decodeCreateMapfixAuditCommentRequest(r *http.Request) (
|
||||||
req CreateMapfixAuditCommentReq,
|
req CreateMapfixAuditCommentReq,
|
||||||
|
rawBody []byte,
|
||||||
close func() error,
|
close func() error,
|
||||||
rerr error,
|
rerr error,
|
||||||
) {
|
) {
|
||||||
@@ -108,20 +354,21 @@ func (s *Server) decodeCreateMapfixAuditCommentRequest(r *http.Request) (
|
|||||||
}()
|
}()
|
||||||
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, errors.Wrap(err, "parse media type")
|
return req, rawBody, close, errors.Wrap(err, "parse media type")
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case ct == "text/plain":
|
case ct == "text/plain":
|
||||||
reader := r.Body
|
reader := r.Body
|
||||||
request := CreateMapfixAuditCommentReq{Data: reader}
|
request := CreateMapfixAuditCommentReq{Data: reader}
|
||||||
return request, close, nil
|
return request, rawBody, close, nil
|
||||||
default:
|
default:
|
||||||
return req, close, validate.InvalidContentType(ct)
|
return req, rawBody, close, validate.InvalidContentType(ct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) decodeCreateScriptRequest(r *http.Request) (
|
func (s *Server) decodeCreateScriptRequest(r *http.Request) (
|
||||||
req *ScriptCreate,
|
req *ScriptCreate,
|
||||||
|
rawBody []byte,
|
||||||
close func() error,
|
close func() error,
|
||||||
rerr error,
|
rerr error,
|
||||||
) {
|
) {
|
||||||
@@ -142,22 +389,29 @@ func (s *Server) decodeCreateScriptRequest(r *http.Request) (
|
|||||||
}()
|
}()
|
||||||
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, errors.Wrap(err, "parse media type")
|
return req, rawBody, close, errors.Wrap(err, "parse media type")
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case ct == "application/json":
|
case ct == "application/json":
|
||||||
if r.ContentLength == 0 {
|
if r.ContentLength == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
buf, err := io.ReadAll(r.Body)
|
buf, err := io.ReadAll(r.Body)
|
||||||
|
defer func() {
|
||||||
|
_ = r.Body.Close()
|
||||||
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the body to allow for downstream reading.
|
||||||
|
r.Body = io.NopCloser(bytes.NewBuffer(buf))
|
||||||
|
|
||||||
if len(buf) == 0 {
|
if len(buf) == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rawBody = append(rawBody, buf...)
|
||||||
d := jx.DecodeBytes(buf)
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
var request ScriptCreate
|
var request ScriptCreate
|
||||||
@@ -175,7 +429,7 @@ func (s *Server) decodeCreateScriptRequest(r *http.Request) (
|
|||||||
Body: buf,
|
Body: buf,
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
if err := func() error {
|
if err := func() error {
|
||||||
if err := request.Validate(); err != nil {
|
if err := request.Validate(); err != nil {
|
||||||
@@ -183,16 +437,17 @@ func (s *Server) decodeCreateScriptRequest(r *http.Request) (
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}(); err != nil {
|
}(); err != nil {
|
||||||
return req, close, errors.Wrap(err, "validate")
|
return req, rawBody, close, errors.Wrap(err, "validate")
|
||||||
}
|
}
|
||||||
return &request, close, nil
|
return &request, rawBody, close, nil
|
||||||
default:
|
default:
|
||||||
return req, close, validate.InvalidContentType(ct)
|
return req, rawBody, close, validate.InvalidContentType(ct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) decodeCreateScriptPolicyRequest(r *http.Request) (
|
func (s *Server) decodeCreateScriptPolicyRequest(r *http.Request) (
|
||||||
req *ScriptPolicyCreate,
|
req *ScriptPolicyCreate,
|
||||||
|
rawBody []byte,
|
||||||
close func() error,
|
close func() error,
|
||||||
rerr error,
|
rerr error,
|
||||||
) {
|
) {
|
||||||
@@ -213,22 +468,29 @@ func (s *Server) decodeCreateScriptPolicyRequest(r *http.Request) (
|
|||||||
}()
|
}()
|
||||||
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, errors.Wrap(err, "parse media type")
|
return req, rawBody, close, errors.Wrap(err, "parse media type")
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case ct == "application/json":
|
case ct == "application/json":
|
||||||
if r.ContentLength == 0 {
|
if r.ContentLength == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
buf, err := io.ReadAll(r.Body)
|
buf, err := io.ReadAll(r.Body)
|
||||||
|
defer func() {
|
||||||
|
_ = r.Body.Close()
|
||||||
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the body to allow for downstream reading.
|
||||||
|
r.Body = io.NopCloser(bytes.NewBuffer(buf))
|
||||||
|
|
||||||
if len(buf) == 0 {
|
if len(buf) == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rawBody = append(rawBody, buf...)
|
||||||
d := jx.DecodeBytes(buf)
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
var request ScriptPolicyCreate
|
var request ScriptPolicyCreate
|
||||||
@@ -246,7 +508,7 @@ func (s *Server) decodeCreateScriptPolicyRequest(r *http.Request) (
|
|||||||
Body: buf,
|
Body: buf,
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
if err := func() error {
|
if err := func() error {
|
||||||
if err := request.Validate(); err != nil {
|
if err := request.Validate(); err != nil {
|
||||||
@@ -254,16 +516,17 @@ func (s *Server) decodeCreateScriptPolicyRequest(r *http.Request) (
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}(); err != nil {
|
}(); err != nil {
|
||||||
return req, close, errors.Wrap(err, "validate")
|
return req, rawBody, close, errors.Wrap(err, "validate")
|
||||||
}
|
}
|
||||||
return &request, close, nil
|
return &request, rawBody, close, nil
|
||||||
default:
|
default:
|
||||||
return req, close, validate.InvalidContentType(ct)
|
return req, rawBody, close, validate.InvalidContentType(ct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) decodeCreateSubmissionRequest(r *http.Request) (
|
func (s *Server) decodeCreateSubmissionRequest(r *http.Request) (
|
||||||
req *SubmissionTriggerCreate,
|
req *SubmissionTriggerCreate,
|
||||||
|
rawBody []byte,
|
||||||
close func() error,
|
close func() error,
|
||||||
rerr error,
|
rerr error,
|
||||||
) {
|
) {
|
||||||
@@ -284,22 +547,29 @@ func (s *Server) decodeCreateSubmissionRequest(r *http.Request) (
|
|||||||
}()
|
}()
|
||||||
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, errors.Wrap(err, "parse media type")
|
return req, rawBody, close, errors.Wrap(err, "parse media type")
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case ct == "application/json":
|
case ct == "application/json":
|
||||||
if r.ContentLength == 0 {
|
if r.ContentLength == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
buf, err := io.ReadAll(r.Body)
|
buf, err := io.ReadAll(r.Body)
|
||||||
|
defer func() {
|
||||||
|
_ = r.Body.Close()
|
||||||
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the body to allow for downstream reading.
|
||||||
|
r.Body = io.NopCloser(bytes.NewBuffer(buf))
|
||||||
|
|
||||||
if len(buf) == 0 {
|
if len(buf) == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rawBody = append(rawBody, buf...)
|
||||||
d := jx.DecodeBytes(buf)
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
var request SubmissionTriggerCreate
|
var request SubmissionTriggerCreate
|
||||||
@@ -317,7 +587,7 @@ func (s *Server) decodeCreateSubmissionRequest(r *http.Request) (
|
|||||||
Body: buf,
|
Body: buf,
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
if err := func() error {
|
if err := func() error {
|
||||||
if err := request.Validate(); err != nil {
|
if err := request.Validate(); err != nil {
|
||||||
@@ -325,16 +595,17 @@ func (s *Server) decodeCreateSubmissionRequest(r *http.Request) (
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}(); err != nil {
|
}(); err != nil {
|
||||||
return req, close, errors.Wrap(err, "validate")
|
return req, rawBody, close, errors.Wrap(err, "validate")
|
||||||
}
|
}
|
||||||
return &request, close, nil
|
return &request, rawBody, close, nil
|
||||||
default:
|
default:
|
||||||
return req, close, validate.InvalidContentType(ct)
|
return req, rawBody, close, validate.InvalidContentType(ct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) decodeCreateSubmissionAdminRequest(r *http.Request) (
|
func (s *Server) decodeCreateSubmissionAdminRequest(r *http.Request) (
|
||||||
req *SubmissionTriggerCreate,
|
req *SubmissionTriggerCreate,
|
||||||
|
rawBody []byte,
|
||||||
close func() error,
|
close func() error,
|
||||||
rerr error,
|
rerr error,
|
||||||
) {
|
) {
|
||||||
@@ -355,22 +626,29 @@ func (s *Server) decodeCreateSubmissionAdminRequest(r *http.Request) (
|
|||||||
}()
|
}()
|
||||||
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, errors.Wrap(err, "parse media type")
|
return req, rawBody, close, errors.Wrap(err, "parse media type")
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case ct == "application/json":
|
case ct == "application/json":
|
||||||
if r.ContentLength == 0 {
|
if r.ContentLength == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
buf, err := io.ReadAll(r.Body)
|
buf, err := io.ReadAll(r.Body)
|
||||||
|
defer func() {
|
||||||
|
_ = r.Body.Close()
|
||||||
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the body to allow for downstream reading.
|
||||||
|
r.Body = io.NopCloser(bytes.NewBuffer(buf))
|
||||||
|
|
||||||
if len(buf) == 0 {
|
if len(buf) == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rawBody = append(rawBody, buf...)
|
||||||
d := jx.DecodeBytes(buf)
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
var request SubmissionTriggerCreate
|
var request SubmissionTriggerCreate
|
||||||
@@ -388,7 +666,7 @@ func (s *Server) decodeCreateSubmissionAdminRequest(r *http.Request) (
|
|||||||
Body: buf,
|
Body: buf,
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
if err := func() error {
|
if err := func() error {
|
||||||
if err := request.Validate(); err != nil {
|
if err := request.Validate(); err != nil {
|
||||||
@@ -396,16 +674,17 @@ func (s *Server) decodeCreateSubmissionAdminRequest(r *http.Request) (
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}(); err != nil {
|
}(); err != nil {
|
||||||
return req, close, errors.Wrap(err, "validate")
|
return req, rawBody, close, errors.Wrap(err, "validate")
|
||||||
}
|
}
|
||||||
return &request, close, nil
|
return &request, rawBody, close, nil
|
||||||
default:
|
default:
|
||||||
return req, close, validate.InvalidContentType(ct)
|
return req, rawBody, close, validate.InvalidContentType(ct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) decodeCreateSubmissionAuditCommentRequest(r *http.Request) (
|
func (s *Server) decodeCreateSubmissionAuditCommentRequest(r *http.Request) (
|
||||||
req CreateSubmissionAuditCommentReq,
|
req CreateSubmissionAuditCommentReq,
|
||||||
|
rawBody []byte,
|
||||||
close func() error,
|
close func() error,
|
||||||
rerr error,
|
rerr error,
|
||||||
) {
|
) {
|
||||||
@@ -426,20 +705,21 @@ func (s *Server) decodeCreateSubmissionAuditCommentRequest(r *http.Request) (
|
|||||||
}()
|
}()
|
||||||
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, errors.Wrap(err, "parse media type")
|
return req, rawBody, close, errors.Wrap(err, "parse media type")
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case ct == "text/plain":
|
case ct == "text/plain":
|
||||||
reader := r.Body
|
reader := r.Body
|
||||||
request := CreateSubmissionAuditCommentReq{Data: reader}
|
request := CreateSubmissionAuditCommentReq{Data: reader}
|
||||||
return request, close, nil
|
return request, rawBody, close, nil
|
||||||
default:
|
default:
|
||||||
return req, close, validate.InvalidContentType(ct)
|
return req, rawBody, close, validate.InvalidContentType(ct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) decodeReleaseSubmissionsRequest(r *http.Request) (
|
func (s *Server) decodeReleaseSubmissionsRequest(r *http.Request) (
|
||||||
req []ReleaseInfo,
|
req []ReleaseInfo,
|
||||||
|
rawBody []byte,
|
||||||
close func() error,
|
close func() error,
|
||||||
rerr error,
|
rerr error,
|
||||||
) {
|
) {
|
||||||
@@ -460,22 +740,29 @@ func (s *Server) decodeReleaseSubmissionsRequest(r *http.Request) (
|
|||||||
}()
|
}()
|
||||||
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, errors.Wrap(err, "parse media type")
|
return req, rawBody, close, errors.Wrap(err, "parse media type")
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case ct == "application/json":
|
case ct == "application/json":
|
||||||
if r.ContentLength == 0 {
|
if r.ContentLength == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
buf, err := io.ReadAll(r.Body)
|
buf, err := io.ReadAll(r.Body)
|
||||||
|
defer func() {
|
||||||
|
_ = r.Body.Close()
|
||||||
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the body to allow for downstream reading.
|
||||||
|
r.Body = io.NopCloser(bytes.NewBuffer(buf))
|
||||||
|
|
||||||
if len(buf) == 0 {
|
if len(buf) == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rawBody = append(rawBody, buf...)
|
||||||
d := jx.DecodeBytes(buf)
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
var request []ReleaseInfo
|
var request []ReleaseInfo
|
||||||
@@ -501,7 +788,7 @@ func (s *Server) decodeReleaseSubmissionsRequest(r *http.Request) (
|
|||||||
Body: buf,
|
Body: buf,
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
if err := func() error {
|
if err := func() error {
|
||||||
if request == nil {
|
if request == nil {
|
||||||
@@ -534,16 +821,17 @@ func (s *Server) decodeReleaseSubmissionsRequest(r *http.Request) (
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}(); err != nil {
|
}(); err != nil {
|
||||||
return req, close, errors.Wrap(err, "validate")
|
return req, rawBody, close, errors.Wrap(err, "validate")
|
||||||
}
|
}
|
||||||
return request, close, nil
|
return request, rawBody, close, nil
|
||||||
default:
|
default:
|
||||||
return req, close, validate.InvalidContentType(ct)
|
return req, rawBody, close, validate.InvalidContentType(ct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) decodeUpdateScriptRequest(r *http.Request) (
|
func (s *Server) decodeUpdateScriptRequest(r *http.Request) (
|
||||||
req *ScriptUpdate,
|
req *ScriptUpdate,
|
||||||
|
rawBody []byte,
|
||||||
close func() error,
|
close func() error,
|
||||||
rerr error,
|
rerr error,
|
||||||
) {
|
) {
|
||||||
@@ -564,22 +852,29 @@ func (s *Server) decodeUpdateScriptRequest(r *http.Request) (
|
|||||||
}()
|
}()
|
||||||
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, errors.Wrap(err, "parse media type")
|
return req, rawBody, close, errors.Wrap(err, "parse media type")
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case ct == "application/json":
|
case ct == "application/json":
|
||||||
if r.ContentLength == 0 {
|
if r.ContentLength == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
buf, err := io.ReadAll(r.Body)
|
buf, err := io.ReadAll(r.Body)
|
||||||
|
defer func() {
|
||||||
|
_ = r.Body.Close()
|
||||||
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the body to allow for downstream reading.
|
||||||
|
r.Body = io.NopCloser(bytes.NewBuffer(buf))
|
||||||
|
|
||||||
if len(buf) == 0 {
|
if len(buf) == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rawBody = append(rawBody, buf...)
|
||||||
d := jx.DecodeBytes(buf)
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
var request ScriptUpdate
|
var request ScriptUpdate
|
||||||
@@ -597,7 +892,7 @@ func (s *Server) decodeUpdateScriptRequest(r *http.Request) (
|
|||||||
Body: buf,
|
Body: buf,
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
if err := func() error {
|
if err := func() error {
|
||||||
if err := request.Validate(); err != nil {
|
if err := request.Validate(); err != nil {
|
||||||
@@ -605,16 +900,17 @@ func (s *Server) decodeUpdateScriptRequest(r *http.Request) (
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}(); err != nil {
|
}(); err != nil {
|
||||||
return req, close, errors.Wrap(err, "validate")
|
return req, rawBody, close, errors.Wrap(err, "validate")
|
||||||
}
|
}
|
||||||
return &request, close, nil
|
return &request, rawBody, close, nil
|
||||||
default:
|
default:
|
||||||
return req, close, validate.InvalidContentType(ct)
|
return req, rawBody, close, validate.InvalidContentType(ct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) decodeUpdateScriptPolicyRequest(r *http.Request) (
|
func (s *Server) decodeUpdateScriptPolicyRequest(r *http.Request) (
|
||||||
req *ScriptPolicyUpdate,
|
req *ScriptPolicyUpdate,
|
||||||
|
rawBody []byte,
|
||||||
close func() error,
|
close func() error,
|
||||||
rerr error,
|
rerr error,
|
||||||
) {
|
) {
|
||||||
@@ -635,22 +931,29 @@ func (s *Server) decodeUpdateScriptPolicyRequest(r *http.Request) (
|
|||||||
}()
|
}()
|
||||||
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, errors.Wrap(err, "parse media type")
|
return req, rawBody, close, errors.Wrap(err, "parse media type")
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case ct == "application/json":
|
case ct == "application/json":
|
||||||
if r.ContentLength == 0 {
|
if r.ContentLength == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
buf, err := io.ReadAll(r.Body)
|
buf, err := io.ReadAll(r.Body)
|
||||||
|
defer func() {
|
||||||
|
_ = r.Body.Close()
|
||||||
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the body to allow for downstream reading.
|
||||||
|
r.Body = io.NopCloser(bytes.NewBuffer(buf))
|
||||||
|
|
||||||
if len(buf) == 0 {
|
if len(buf) == 0 {
|
||||||
return req, close, validate.ErrBodyRequired
|
return req, rawBody, close, validate.ErrBodyRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rawBody = append(rawBody, buf...)
|
||||||
d := jx.DecodeBytes(buf)
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
var request ScriptPolicyUpdate
|
var request ScriptPolicyUpdate
|
||||||
@@ -668,7 +971,7 @@ func (s *Server) decodeUpdateScriptPolicyRequest(r *http.Request) (
|
|||||||
Body: buf,
|
Body: buf,
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
return req, close, err
|
return req, rawBody, close, err
|
||||||
}
|
}
|
||||||
if err := func() error {
|
if err := func() error {
|
||||||
if err := request.Validate(); err != nil {
|
if err := request.Validate(); err != nil {
|
||||||
@@ -676,10 +979,10 @@ func (s *Server) decodeUpdateScriptPolicyRequest(r *http.Request) (
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}(); err != nil {
|
}(); err != nil {
|
||||||
return req, close, errors.Wrap(err, "validate")
|
return req, rawBody, close, errors.Wrap(err, "validate")
|
||||||
}
|
}
|
||||||
return &request, close, nil
|
return &request, rawBody, close, nil
|
||||||
default:
|
default:
|
||||||
return req, close, validate.InvalidContentType(ct)
|
return req, rawBody, close, validate.InvalidContentType(ct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,51 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-faster/jx"
|
"github.com/go-faster/jx"
|
||||||
|
|
||||||
ht "github.com/ogen-go/ogen/http"
|
ht "github.com/ogen-go/ogen/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func encodeBatchAssetThumbnailsRequest(
|
||||||
|
req *BatchAssetThumbnailsReq,
|
||||||
|
r *http.Request,
|
||||||
|
) error {
|
||||||
|
const contentType = "application/json"
|
||||||
|
e := new(jx.Encoder)
|
||||||
|
{
|
||||||
|
req.Encode(e)
|
||||||
|
}
|
||||||
|
encoded := e.Bytes()
|
||||||
|
ht.SetBody(r, bytes.NewReader(encoded), contentType)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeBatchUserThumbnailsRequest(
|
||||||
|
req *BatchUserThumbnailsReq,
|
||||||
|
r *http.Request,
|
||||||
|
) error {
|
||||||
|
const contentType = "application/json"
|
||||||
|
e := new(jx.Encoder)
|
||||||
|
{
|
||||||
|
req.Encode(e)
|
||||||
|
}
|
||||||
|
encoded := e.Bytes()
|
||||||
|
ht.SetBody(r, bytes.NewReader(encoded), contentType)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeBatchUsernamesRequest(
|
||||||
|
req *BatchUsernamesReq,
|
||||||
|
r *http.Request,
|
||||||
|
) error {
|
||||||
|
const contentType = "application/json"
|
||||||
|
e := new(jx.Encoder)
|
||||||
|
{
|
||||||
|
req.Encode(e)
|
||||||
|
}
|
||||||
|
encoded := e.Bytes()
|
||||||
|
ht.SetBody(r, bytes.NewReader(encoded), contentType)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func encodeCreateMapfixRequest(
|
func encodeCreateMapfixRequest(
|
||||||
req *MapfixTriggerCreate,
|
req *MapfixTriggerCreate,
|
||||||
r *http.Request,
|
r *http.Request,
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ import (
|
|||||||
|
|
||||||
"github.com/go-faster/errors"
|
"github.com/go-faster/errors"
|
||||||
"github.com/go-faster/jx"
|
"github.com/go-faster/jx"
|
||||||
|
"github.com/ogen-go/ogen/conv"
|
||||||
"github.com/ogen-go/ogen/ogenerrors"
|
"github.com/ogen-go/ogen/ogenerrors"
|
||||||
|
"github.com/ogen-go/ogen/uri"
|
||||||
"github.com/ogen-go/ogen/validate"
|
"github.com/ogen-go/ogen/validate"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -376,6 +377,66 @@ func decodeActionMapfixRevokeResponse(resp *http.Response) (res *ActionMapfixRev
|
|||||||
return res, errors.Wrap(defRes, "error")
|
return res, errors.Wrap(defRes, "error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func decodeActionMapfixTriggerReleaseResponse(resp *http.Response) (res *ActionMapfixTriggerReleaseNoContent, _ error) {
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case 204:
|
||||||
|
// Code 204.
|
||||||
|
return &ActionMapfixTriggerReleaseNoContent{}, nil
|
||||||
|
}
|
||||||
|
// Convenient error response.
|
||||||
|
defRes, err := func() (res *ErrorStatusCode, err error) {
|
||||||
|
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
buf, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var response Error
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
// Validate response.
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return res, errors.Wrap(err, "validate")
|
||||||
|
}
|
||||||
|
return &ErrorStatusCode{
|
||||||
|
StatusCode: resp.StatusCode,
|
||||||
|
Response: response,
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
return res, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode)
|
||||||
|
}
|
||||||
|
return res, errors.Wrap(defRes, "error")
|
||||||
|
}
|
||||||
|
|
||||||
func decodeActionMapfixTriggerSubmitResponse(resp *http.Response) (res *ActionMapfixTriggerSubmitNoContent, _ error) {
|
func decodeActionMapfixTriggerSubmitResponse(resp *http.Response) (res *ActionMapfixTriggerSubmitNoContent, _ error) {
|
||||||
switch resp.StatusCode {
|
switch resp.StatusCode {
|
||||||
case 204:
|
case 204:
|
||||||
@@ -616,6 +677,66 @@ func decodeActionMapfixTriggerValidateResponse(resp *http.Response) (res *Action
|
|||||||
return res, errors.Wrap(defRes, "error")
|
return res, errors.Wrap(defRes, "error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func decodeActionMapfixUploadedResponse(resp *http.Response) (res *ActionMapfixUploadedNoContent, _ error) {
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case 204:
|
||||||
|
// Code 204.
|
||||||
|
return &ActionMapfixUploadedNoContent{}, nil
|
||||||
|
}
|
||||||
|
// Convenient error response.
|
||||||
|
defRes, err := func() (res *ErrorStatusCode, err error) {
|
||||||
|
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
buf, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var response Error
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
// Validate response.
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return res, errors.Wrap(err, "validate")
|
||||||
|
}
|
||||||
|
return &ErrorStatusCode{
|
||||||
|
StatusCode: resp.StatusCode,
|
||||||
|
Response: response,
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
return res, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode)
|
||||||
|
}
|
||||||
|
return res, errors.Wrap(defRes, "error")
|
||||||
|
}
|
||||||
|
|
||||||
func decodeActionMapfixValidatedResponse(resp *http.Response) (res *ActionMapfixValidatedNoContent, _ error) {
|
func decodeActionMapfixValidatedResponse(resp *http.Response) (res *ActionMapfixValidatedNoContent, _ error) {
|
||||||
switch resp.StatusCode {
|
switch resp.StatusCode {
|
||||||
case 204:
|
case 204:
|
||||||
@@ -1336,6 +1457,282 @@ func decodeActionSubmissionValidatedResponse(resp *http.Response) (res *ActionSu
|
|||||||
return res, errors.Wrap(defRes, "error")
|
return res, errors.Wrap(defRes, "error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func decodeBatchAssetThumbnailsResponse(resp *http.Response) (res *BatchAssetThumbnailsOK, _ error) {
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case 200:
|
||||||
|
// Code 200.
|
||||||
|
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
buf, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var response BatchAssetThumbnailsOK
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return &response, nil
|
||||||
|
default:
|
||||||
|
return res, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Convenient error response.
|
||||||
|
defRes, err := func() (res *ErrorStatusCode, err error) {
|
||||||
|
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
buf, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var response Error
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
// Validate response.
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return res, errors.Wrap(err, "validate")
|
||||||
|
}
|
||||||
|
return &ErrorStatusCode{
|
||||||
|
StatusCode: resp.StatusCode,
|
||||||
|
Response: response,
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
return res, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode)
|
||||||
|
}
|
||||||
|
return res, errors.Wrap(defRes, "error")
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeBatchUserThumbnailsResponse(resp *http.Response) (res *BatchUserThumbnailsOK, _ error) {
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case 200:
|
||||||
|
// Code 200.
|
||||||
|
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
buf, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var response BatchUserThumbnailsOK
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return &response, nil
|
||||||
|
default:
|
||||||
|
return res, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Convenient error response.
|
||||||
|
defRes, err := func() (res *ErrorStatusCode, err error) {
|
||||||
|
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
buf, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var response Error
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
// Validate response.
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return res, errors.Wrap(err, "validate")
|
||||||
|
}
|
||||||
|
return &ErrorStatusCode{
|
||||||
|
StatusCode: resp.StatusCode,
|
||||||
|
Response: response,
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
return res, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode)
|
||||||
|
}
|
||||||
|
return res, errors.Wrap(defRes, "error")
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeBatchUsernamesResponse(resp *http.Response) (res *BatchUsernamesOK, _ error) {
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case 200:
|
||||||
|
// Code 200.
|
||||||
|
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
buf, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var response BatchUsernamesOK
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return &response, nil
|
||||||
|
default:
|
||||||
|
return res, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Convenient error response.
|
||||||
|
defRes, err := func() (res *ErrorStatusCode, err error) {
|
||||||
|
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
buf, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var response Error
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
// Validate response.
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return res, errors.Wrap(err, "validate")
|
||||||
|
}
|
||||||
|
return &ErrorStatusCode{
|
||||||
|
StatusCode: resp.StatusCode,
|
||||||
|
Response: response,
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
return res, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode)
|
||||||
|
}
|
||||||
|
return res, errors.Wrap(defRes, "error")
|
||||||
|
}
|
||||||
|
|
||||||
func decodeCreateMapfixResponse(resp *http.Response) (res *OperationID, _ error) {
|
func decodeCreateMapfixResponse(resp *http.Response) (res *OperationID, _ error) {
|
||||||
switch resp.StatusCode {
|
switch resp.StatusCode {
|
||||||
case 201:
|
case 201:
|
||||||
@@ -2157,6 +2554,105 @@ func decodeDownloadMapAssetResponse(resp *http.Response) (res DownloadMapAssetOK
|
|||||||
return res, errors.Wrap(defRes, "error")
|
return res, errors.Wrap(defRes, "error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func decodeGetAssetThumbnailResponse(resp *http.Response) (res *GetAssetThumbnailFound, _ error) {
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case 302:
|
||||||
|
// Code 302.
|
||||||
|
var wrapper GetAssetThumbnailFound
|
||||||
|
h := uri.NewHeaderDecoder(resp.Header)
|
||||||
|
// Parse "Location" header.
|
||||||
|
{
|
||||||
|
cfg := uri.HeaderParameterDecodingConfig{
|
||||||
|
Name: "Location",
|
||||||
|
Explode: false,
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if err := h.HasParam(cfg); err == nil {
|
||||||
|
if err := h.DecodeParam(cfg, func(d uri.Decoder) error {
|
||||||
|
var wrapperDotLocationVal string
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapperDotLocationVal = c
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
wrapper.Location.SetTo(wrapperDotLocationVal)
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse Location header")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &wrapper, nil
|
||||||
|
}
|
||||||
|
// Convenient error response.
|
||||||
|
defRes, err := func() (res *ErrorStatusCode, err error) {
|
||||||
|
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
buf, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var response Error
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
// Validate response.
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return res, errors.Wrap(err, "validate")
|
||||||
|
}
|
||||||
|
return &ErrorStatusCode{
|
||||||
|
StatusCode: resp.StatusCode,
|
||||||
|
Response: response,
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
return res, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode)
|
||||||
|
}
|
||||||
|
return res, errors.Wrap(defRes, "error")
|
||||||
|
}
|
||||||
|
|
||||||
func decodeGetMapResponse(resp *http.Response) (res *Map, _ error) {
|
func decodeGetMapResponse(resp *http.Response) (res *Map, _ error) {
|
||||||
switch resp.StatusCode {
|
switch resp.StatusCode {
|
||||||
case 200:
|
case 200:
|
||||||
@@ -2662,6 +3158,107 @@ func decodeGetScriptPolicyResponse(resp *http.Response) (res *ScriptPolicy, _ er
|
|||||||
return res, errors.Wrap(defRes, "error")
|
return res, errors.Wrap(defRes, "error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func decodeGetStatsResponse(resp *http.Response) (res *Stats, _ error) {
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case 200:
|
||||||
|
// Code 200.
|
||||||
|
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
buf, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var response Stats
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
// Validate response.
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return res, errors.Wrap(err, "validate")
|
||||||
|
}
|
||||||
|
return &response, nil
|
||||||
|
default:
|
||||||
|
return res, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Convenient error response.
|
||||||
|
defRes, err := func() (res *ErrorStatusCode, err error) {
|
||||||
|
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
buf, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var response Error
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
// Validate response.
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return res, errors.Wrap(err, "validate")
|
||||||
|
}
|
||||||
|
return &ErrorStatusCode{
|
||||||
|
StatusCode: resp.StatusCode,
|
||||||
|
Response: response,
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
return res, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode)
|
||||||
|
}
|
||||||
|
return res, errors.Wrap(defRes, "error")
|
||||||
|
}
|
||||||
|
|
||||||
func decodeGetSubmissionResponse(resp *http.Response) (res *Submission, _ error) {
|
func decodeGetSubmissionResponse(resp *http.Response) (res *Submission, _ error) {
|
||||||
switch resp.StatusCode {
|
switch resp.StatusCode {
|
||||||
case 200:
|
case 200:
|
||||||
@@ -2763,6 +3360,105 @@ func decodeGetSubmissionResponse(resp *http.Response) (res *Submission, _ error)
|
|||||||
return res, errors.Wrap(defRes, "error")
|
return res, errors.Wrap(defRes, "error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func decodeGetUserThumbnailResponse(resp *http.Response) (res *GetUserThumbnailFound, _ error) {
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case 302:
|
||||||
|
// Code 302.
|
||||||
|
var wrapper GetUserThumbnailFound
|
||||||
|
h := uri.NewHeaderDecoder(resp.Header)
|
||||||
|
// Parse "Location" header.
|
||||||
|
{
|
||||||
|
cfg := uri.HeaderParameterDecodingConfig{
|
||||||
|
Name: "Location",
|
||||||
|
Explode: false,
|
||||||
|
}
|
||||||
|
if err := func() error {
|
||||||
|
if err := h.HasParam(cfg); err == nil {
|
||||||
|
if err := h.DecodeParam(cfg, func(d uri.Decoder) error {
|
||||||
|
var wrapperDotLocationVal string
|
||||||
|
if err := func() error {
|
||||||
|
val, err := d.DecodeValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := conv.ToString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapperDotLocationVal = c
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
wrapper.Location.SetTo(wrapperDotLocationVal)
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse Location header")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &wrapper, nil
|
||||||
|
}
|
||||||
|
// Convenient error response.
|
||||||
|
defRes, err := func() (res *ErrorStatusCode, err error) {
|
||||||
|
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
buf, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var response Error
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
// Validate response.
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return res, errors.Wrap(err, "validate")
|
||||||
|
}
|
||||||
|
return &ErrorStatusCode{
|
||||||
|
StatusCode: resp.StatusCode,
|
||||||
|
Response: response,
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
return res, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode)
|
||||||
|
}
|
||||||
|
return res, errors.Wrap(defRes, "error")
|
||||||
|
}
|
||||||
|
|
||||||
func decodeListMapfixAuditEventsResponse(resp *http.Response) (res []AuditEvent, _ error) {
|
func decodeListMapfixAuditEventsResponse(resp *http.Response) (res []AuditEvent, _ error) {
|
||||||
switch resp.StatusCode {
|
switch resp.StatusCode {
|
||||||
case 200:
|
case 200:
|
||||||
@@ -3595,11 +4291,52 @@ func decodeListSubmissionsResponse(resp *http.Response) (res *Submissions, _ err
|
|||||||
return res, errors.Wrap(defRes, "error")
|
return res, errors.Wrap(defRes, "error")
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeReleaseSubmissionsResponse(resp *http.Response) (res *ReleaseSubmissionsCreated, _ error) {
|
func decodeReleaseSubmissionsResponse(resp *http.Response) (res *OperationID, _ error) {
|
||||||
switch resp.StatusCode {
|
switch resp.StatusCode {
|
||||||
case 201:
|
case 201:
|
||||||
// Code 201.
|
// Code 201.
|
||||||
return &ReleaseSubmissionsCreated{}, nil
|
ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return res, errors.Wrap(err, "parse media type")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case ct == "application/json":
|
||||||
|
buf, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
|
var response OperationID
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Decode(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Skip(); err != io.EOF {
|
||||||
|
return errors.New("unexpected trailing data")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
err = &ogenerrors.DecodeBodyError{
|
||||||
|
ContentType: ct,
|
||||||
|
Body: buf,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
// Validate response.
|
||||||
|
if err := func() error {
|
||||||
|
if err := response.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return res, errors.Wrap(err, "validate")
|
||||||
|
}
|
||||||
|
return &response, nil
|
||||||
|
default:
|
||||||
|
return res, validate.InvalidContentType(ct)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Convenient error response.
|
// Convenient error response.
|
||||||
defRes, err := func() (res *ErrorStatusCode, err error) {
|
defRes, err := func() (res *ErrorStatusCode, err error) {
|
||||||
|
|||||||
@@ -8,10 +8,11 @@ import (
|
|||||||
|
|
||||||
"github.com/go-faster/errors"
|
"github.com/go-faster/errors"
|
||||||
"github.com/go-faster/jx"
|
"github.com/go-faster/jx"
|
||||||
|
"github.com/ogen-go/ogen/conv"
|
||||||
|
ht "github.com/ogen-go/ogen/http"
|
||||||
|
"github.com/ogen-go/ogen/uri"
|
||||||
"go.opentelemetry.io/otel/codes"
|
"go.opentelemetry.io/otel/codes"
|
||||||
"go.opentelemetry.io/otel/trace"
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
|
||||||
ht "github.com/ogen-go/ogen/http"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func encodeActionMapfixAcceptedResponse(response *ActionMapfixAcceptedNoContent, w http.ResponseWriter, span trace.Span) error {
|
func encodeActionMapfixAcceptedResponse(response *ActionMapfixAcceptedNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||||
@@ -56,6 +57,13 @@ func encodeActionMapfixRevokeResponse(response *ActionMapfixRevokeNoContent, w h
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodeActionMapfixTriggerReleaseResponse(response *ActionMapfixTriggerReleaseNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||||
|
w.WriteHeader(204)
|
||||||
|
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func encodeActionMapfixTriggerSubmitResponse(response *ActionMapfixTriggerSubmitNoContent, w http.ResponseWriter, span trace.Span) error {
|
func encodeActionMapfixTriggerSubmitResponse(response *ActionMapfixTriggerSubmitNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||||
w.WriteHeader(204)
|
w.WriteHeader(204)
|
||||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||||
@@ -84,6 +92,13 @@ func encodeActionMapfixTriggerValidateResponse(response *ActionMapfixTriggerVali
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodeActionMapfixUploadedResponse(response *ActionMapfixUploadedNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||||
|
w.WriteHeader(204)
|
||||||
|
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func encodeActionMapfixValidatedResponse(response *ActionMapfixValidatedNoContent, w http.ResponseWriter, span trace.Span) error {
|
func encodeActionMapfixValidatedResponse(response *ActionMapfixValidatedNoContent, w http.ResponseWriter, span trace.Span) error {
|
||||||
w.WriteHeader(204)
|
w.WriteHeader(204)
|
||||||
span.SetStatus(codes.Ok, http.StatusText(204))
|
span.SetStatus(codes.Ok, http.StatusText(204))
|
||||||
@@ -168,6 +183,48 @@ func encodeActionSubmissionValidatedResponse(response *ActionSubmissionValidated
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodeBatchAssetThumbnailsResponse(response *BatchAssetThumbnailsOK, w http.ResponseWriter, span trace.Span) error {
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
w.WriteHeader(200)
|
||||||
|
span.SetStatus(codes.Ok, http.StatusText(200))
|
||||||
|
|
||||||
|
e := new(jx.Encoder)
|
||||||
|
response.Encode(e)
|
||||||
|
if _, err := e.WriteTo(w); err != nil {
|
||||||
|
return errors.Wrap(err, "write")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeBatchUserThumbnailsResponse(response *BatchUserThumbnailsOK, w http.ResponseWriter, span trace.Span) error {
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
w.WriteHeader(200)
|
||||||
|
span.SetStatus(codes.Ok, http.StatusText(200))
|
||||||
|
|
||||||
|
e := new(jx.Encoder)
|
||||||
|
response.Encode(e)
|
||||||
|
if _, err := e.WriteTo(w); err != nil {
|
||||||
|
return errors.Wrap(err, "write")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeBatchUsernamesResponse(response *BatchUsernamesOK, w http.ResponseWriter, span trace.Span) error {
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
w.WriteHeader(200)
|
||||||
|
span.SetStatus(codes.Ok, http.StatusText(200))
|
||||||
|
|
||||||
|
e := new(jx.Encoder)
|
||||||
|
response.Encode(e)
|
||||||
|
if _, err := e.WriteTo(w); err != nil {
|
||||||
|
return errors.Wrap(err, "write")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func encodeCreateMapfixResponse(response *OperationID, w http.ResponseWriter, span trace.Span) error {
|
func encodeCreateMapfixResponse(response *OperationID, w http.ResponseWriter, span trace.Span) error {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
w.WriteHeader(201)
|
w.WriteHeader(201)
|
||||||
@@ -282,6 +339,32 @@ func encodeDownloadMapAssetResponse(response DownloadMapAssetOK, w http.Response
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodeGetAssetThumbnailResponse(response *GetAssetThumbnailFound, w http.ResponseWriter, span trace.Span) error {
|
||||||
|
// Encoding response headers.
|
||||||
|
{
|
||||||
|
h := uri.NewHeaderEncoder(w.Header())
|
||||||
|
// Encode "Location" header.
|
||||||
|
{
|
||||||
|
cfg := uri.HeaderParameterEncodingConfig{
|
||||||
|
Name: "Location",
|
||||||
|
Explode: false,
|
||||||
|
}
|
||||||
|
if err := h.EncodeParam(cfg, func(e uri.Encoder) error {
|
||||||
|
if val, ok := response.Location.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.StringToString(val))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode Location header")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.WriteHeader(302)
|
||||||
|
span.SetStatus(codes.Ok, http.StatusText(302))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func encodeGetMapResponse(response *Map, w http.ResponseWriter, span trace.Span) error {
|
func encodeGetMapResponse(response *Map, w http.ResponseWriter, span trace.Span) error {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
w.WriteHeader(200)
|
w.WriteHeader(200)
|
||||||
@@ -352,6 +435,20 @@ func encodeGetScriptPolicyResponse(response *ScriptPolicy, w http.ResponseWriter
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodeGetStatsResponse(response *Stats, w http.ResponseWriter, span trace.Span) error {
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
w.WriteHeader(200)
|
||||||
|
span.SetStatus(codes.Ok, http.StatusText(200))
|
||||||
|
|
||||||
|
e := new(jx.Encoder)
|
||||||
|
response.Encode(e)
|
||||||
|
if _, err := e.WriteTo(w); err != nil {
|
||||||
|
return errors.Wrap(err, "write")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func encodeGetSubmissionResponse(response *Submission, w http.ResponseWriter, span trace.Span) error {
|
func encodeGetSubmissionResponse(response *Submission, w http.ResponseWriter, span trace.Span) error {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
w.WriteHeader(200)
|
w.WriteHeader(200)
|
||||||
@@ -366,6 +463,32 @@ func encodeGetSubmissionResponse(response *Submission, w http.ResponseWriter, sp
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodeGetUserThumbnailResponse(response *GetUserThumbnailFound, w http.ResponseWriter, span trace.Span) error {
|
||||||
|
// Encoding response headers.
|
||||||
|
{
|
||||||
|
h := uri.NewHeaderEncoder(w.Header())
|
||||||
|
// Encode "Location" header.
|
||||||
|
{
|
||||||
|
cfg := uri.HeaderParameterEncodingConfig{
|
||||||
|
Name: "Location",
|
||||||
|
Explode: false,
|
||||||
|
}
|
||||||
|
if err := h.EncodeParam(cfg, func(e uri.Encoder) error {
|
||||||
|
if val, ok := response.Location.Get(); ok {
|
||||||
|
return e.EncodeValue(conv.StringToString(val))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return errors.Wrap(err, "encode Location header")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.WriteHeader(302)
|
||||||
|
span.SetStatus(codes.Ok, http.StatusText(302))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func encodeListMapfixAuditEventsResponse(response []AuditEvent, w http.ResponseWriter, span trace.Span) error {
|
func encodeListMapfixAuditEventsResponse(response []AuditEvent, w http.ResponseWriter, span trace.Span) error {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
w.WriteHeader(200)
|
w.WriteHeader(200)
|
||||||
@@ -484,10 +607,17 @@ func encodeListSubmissionsResponse(response *Submissions, w http.ResponseWriter,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeReleaseSubmissionsResponse(response *ReleaseSubmissionsCreated, w http.ResponseWriter, span trace.Span) error {
|
func encodeReleaseSubmissionsResponse(response *OperationID, w http.ResponseWriter, span trace.Span) error {
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
w.WriteHeader(201)
|
w.WriteHeader(201)
|
||||||
span.SetStatus(codes.Ok, http.StatusText(201))
|
span.SetStatus(codes.Ok, http.StatusText(201))
|
||||||
|
|
||||||
|
e := new(jx.Encoder)
|
||||||
|
response.Encode(e)
|
||||||
|
if _, err := e.WriteTo(w); err != nil {
|
||||||
|
return errors.Wrap(err, "write")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -318,6 +318,28 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
switch elem[0] {
|
switch elem[0] {
|
||||||
|
case 'r': // Prefix: "releasing"
|
||||||
|
|
||||||
|
if l := len("releasing"); len(elem) >= l && elem[0:l] == "releasing" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch r.Method {
|
||||||
|
case "POST":
|
||||||
|
s.handleActionMapfixUploadedRequest([1]string{
|
||||||
|
args[0],
|
||||||
|
}, elemIsEscaped, w, r)
|
||||||
|
default:
|
||||||
|
s.notAllowed(w, r, "POST")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
case 's': // Prefix: "submitting"
|
case 's': // Prefix: "submitting"
|
||||||
|
|
||||||
if l := len("submitting"); len(elem) >= l && elem[0:l] == "submitting" {
|
if l := len("submitting"); len(elem) >= l && elem[0:l] == "submitting" {
|
||||||
@@ -444,6 +466,28 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
switch elem[0] {
|
switch elem[0] {
|
||||||
|
case 'r': // Prefix: "release"
|
||||||
|
|
||||||
|
if l := len("release"); len(elem) >= l && elem[0:l] == "release" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch r.Method {
|
||||||
|
case "POST":
|
||||||
|
s.handleActionMapfixTriggerReleaseRequest([1]string{
|
||||||
|
args[0],
|
||||||
|
}, elemIsEscaped, w, r)
|
||||||
|
default:
|
||||||
|
s.notAllowed(w, r, "POST")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
case 's': // Prefix: "submit"
|
case 's': // Prefix: "submit"
|
||||||
|
|
||||||
if l := len("submit"); len(elem) >= l && elem[0:l] == "submit" {
|
if l := len("submit"); len(elem) >= l && elem[0:l] == "submit" {
|
||||||
@@ -895,6 +939,26 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 't': // Prefix: "tats"
|
||||||
|
|
||||||
|
if l := len("tats"); len(elem) >= l && elem[0:l] == "tats" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch r.Method {
|
||||||
|
case "GET":
|
||||||
|
s.handleGetStatsRequest([0]string{}, elemIsEscaped, w, r)
|
||||||
|
default:
|
||||||
|
s.notAllowed(w, r, "GET")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
case 'u': // Prefix: "ubmissions"
|
case 'u': // Prefix: "ubmissions"
|
||||||
|
|
||||||
if l := len("ubmissions"); len(elem) >= l && elem[0:l] == "ubmissions" {
|
if l := len("ubmissions"); len(elem) >= l && elem[0:l] == "ubmissions" {
|
||||||
@@ -1387,6 +1451,170 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 't': // Prefix: "thumbnails/"
|
||||||
|
|
||||||
|
if l := len("thumbnails/"); len(elem) >= l && elem[0:l] == "thumbnails/" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch elem[0] {
|
||||||
|
case 'a': // Prefix: "asset"
|
||||||
|
|
||||||
|
if l := len("asset"); len(elem) >= l && elem[0:l] == "asset" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch elem[0] {
|
||||||
|
case '/': // Prefix: "/"
|
||||||
|
|
||||||
|
if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Param: "AssetID"
|
||||||
|
// Leaf parameter, slashes are prohibited
|
||||||
|
idx := strings.IndexByte(elem, '/')
|
||||||
|
if idx >= 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
args[0] = elem
|
||||||
|
elem = ""
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch r.Method {
|
||||||
|
case "GET":
|
||||||
|
s.handleGetAssetThumbnailRequest([1]string{
|
||||||
|
args[0],
|
||||||
|
}, elemIsEscaped, w, r)
|
||||||
|
default:
|
||||||
|
s.notAllowed(w, r, "GET")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
case 's': // Prefix: "s"
|
||||||
|
|
||||||
|
if l := len("s"); len(elem) >= l && elem[0:l] == "s" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch r.Method {
|
||||||
|
case "POST":
|
||||||
|
s.handleBatchAssetThumbnailsRequest([0]string{}, elemIsEscaped, w, r)
|
||||||
|
default:
|
||||||
|
s.notAllowed(w, r, "POST")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'u': // Prefix: "user"
|
||||||
|
|
||||||
|
if l := len("user"); len(elem) >= l && elem[0:l] == "user" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch elem[0] {
|
||||||
|
case '/': // Prefix: "/"
|
||||||
|
|
||||||
|
if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Param: "UserID"
|
||||||
|
// Leaf parameter, slashes are prohibited
|
||||||
|
idx := strings.IndexByte(elem, '/')
|
||||||
|
if idx >= 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
args[0] = elem
|
||||||
|
elem = ""
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch r.Method {
|
||||||
|
case "GET":
|
||||||
|
s.handleGetUserThumbnailRequest([1]string{
|
||||||
|
args[0],
|
||||||
|
}, elemIsEscaped, w, r)
|
||||||
|
default:
|
||||||
|
s.notAllowed(w, r, "GET")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
case 's': // Prefix: "s"
|
||||||
|
|
||||||
|
if l := len("s"); len(elem) >= l && elem[0:l] == "s" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch r.Method {
|
||||||
|
case "POST":
|
||||||
|
s.handleBatchUserThumbnailsRequest([0]string{}, elemIsEscaped, w, r)
|
||||||
|
default:
|
||||||
|
s.notAllowed(w, r, "POST")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'u': // Prefix: "usernames"
|
||||||
|
|
||||||
|
if l := len("usernames"); len(elem) >= l && elem[0:l] == "usernames" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch r.Method {
|
||||||
|
case "POST":
|
||||||
|
s.handleBatchUsernamesRequest([0]string{}, elemIsEscaped, w, r)
|
||||||
|
default:
|
||||||
|
s.notAllowed(w, r, "POST")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1396,12 +1624,13 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// Route is route object.
|
// Route is route object.
|
||||||
type Route struct {
|
type Route struct {
|
||||||
name string
|
name string
|
||||||
summary string
|
summary string
|
||||||
operationID string
|
operationID string
|
||||||
pathPattern string
|
operationGroup string
|
||||||
count int
|
pathPattern string
|
||||||
args [1]string
|
count int
|
||||||
|
args [1]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns ogen operation name.
|
// Name returns ogen operation name.
|
||||||
@@ -1421,6 +1650,11 @@ func (r Route) OperationID() string {
|
|||||||
return r.operationID
|
return r.operationID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OperationGroup returns the x-ogen-operation-group value.
|
||||||
|
func (r Route) OperationGroup() string {
|
||||||
|
return r.operationGroup
|
||||||
|
}
|
||||||
|
|
||||||
// PathPattern returns OpenAPI path.
|
// PathPattern returns OpenAPI path.
|
||||||
func (r Route) PathPattern() string {
|
func (r Route) PathPattern() string {
|
||||||
return r.pathPattern
|
return r.pathPattern
|
||||||
@@ -1507,6 +1741,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ListMapfixesOperation
|
r.name = ListMapfixesOperation
|
||||||
r.summary = "Get list of mapfixes"
|
r.summary = "Get list of mapfixes"
|
||||||
r.operationID = "listMapfixes"
|
r.operationID = "listMapfixes"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes"
|
r.pathPattern = "/mapfixes"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 0
|
r.count = 0
|
||||||
@@ -1515,6 +1750,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = CreateMapfixOperation
|
r.name = CreateMapfixOperation
|
||||||
r.summary = "Trigger the validator to create a mapfix"
|
r.summary = "Trigger the validator to create a mapfix"
|
||||||
r.operationID = "createMapfix"
|
r.operationID = "createMapfix"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes"
|
r.pathPattern = "/mapfixes"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 0
|
r.count = 0
|
||||||
@@ -1547,6 +1783,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = GetMapfixOperation
|
r.name = GetMapfixOperation
|
||||||
r.summary = "Retrieve map with ID"
|
r.summary = "Retrieve map with ID"
|
||||||
r.operationID = "getMapfix"
|
r.operationID = "getMapfix"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}"
|
r.pathPattern = "/mapfixes/{MapfixID}"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -1583,6 +1820,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ListMapfixAuditEventsOperation
|
r.name = ListMapfixAuditEventsOperation
|
||||||
r.summary = "Retrieve a list of audit events"
|
r.summary = "Retrieve a list of audit events"
|
||||||
r.operationID = "listMapfixAuditEvents"
|
r.operationID = "listMapfixAuditEvents"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}/audit-events"
|
r.pathPattern = "/mapfixes/{MapfixID}/audit-events"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -1619,6 +1857,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = CreateMapfixAuditCommentOperation
|
r.name = CreateMapfixAuditCommentOperation
|
||||||
r.summary = "Post a comment to the audit log"
|
r.summary = "Post a comment to the audit log"
|
||||||
r.operationID = "createMapfixAuditComment"
|
r.operationID = "createMapfixAuditComment"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}/comment"
|
r.pathPattern = "/mapfixes/{MapfixID}/comment"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -1643,6 +1882,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = SetMapfixCompletedOperation
|
r.name = SetMapfixCompletedOperation
|
||||||
r.summary = "Called by maptest when a player completes the map"
|
r.summary = "Called by maptest when a player completes the map"
|
||||||
r.operationID = "setMapfixCompleted"
|
r.operationID = "setMapfixCompleted"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}/completed"
|
r.pathPattern = "/mapfixes/{MapfixID}/completed"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -1669,6 +1909,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = UpdateMapfixModelOperation
|
r.name = UpdateMapfixModelOperation
|
||||||
r.summary = "Update model following role restrictions"
|
r.summary = "Update model following role restrictions"
|
||||||
r.operationID = "updateMapfixModel"
|
r.operationID = "updateMapfixModel"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}/model"
|
r.pathPattern = "/mapfixes/{MapfixID}/model"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -1717,6 +1958,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionMapfixRejectOperation
|
r.name = ActionMapfixRejectOperation
|
||||||
r.summary = "Role Reviewer changes status from Submitted -> Rejected"
|
r.summary = "Role Reviewer changes status from Submitted -> Rejected"
|
||||||
r.operationID = "actionMapfixReject"
|
r.operationID = "actionMapfixReject"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}/status/reject"
|
r.pathPattern = "/mapfixes/{MapfixID}/status/reject"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -1741,6 +1983,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionMapfixRequestChangesOperation
|
r.name = ActionMapfixRequestChangesOperation
|
||||||
r.summary = "Role Reviewer changes status from Validated|Accepted|Submitted -> ChangesRequested"
|
r.summary = "Role Reviewer changes status from Validated|Accepted|Submitted -> ChangesRequested"
|
||||||
r.operationID = "actionMapfixRequestChanges"
|
r.operationID = "actionMapfixRequestChanges"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}/status/request-changes"
|
r.pathPattern = "/mapfixes/{MapfixID}/status/request-changes"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -1762,6 +2005,31 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
switch elem[0] {
|
switch elem[0] {
|
||||||
|
case 'r': // Prefix: "releasing"
|
||||||
|
|
||||||
|
if l := len("releasing"); len(elem) >= l && elem[0:l] == "releasing" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch method {
|
||||||
|
case "POST":
|
||||||
|
r.name = ActionMapfixUploadedOperation
|
||||||
|
r.summary = "Role MapfixUpload manually resets releasing softlock and changes status from Releasing -> Uploaded"
|
||||||
|
r.operationID = "actionMapfixUploaded"
|
||||||
|
r.operationGroup = ""
|
||||||
|
r.pathPattern = "/mapfixes/{MapfixID}/status/reset-releasing"
|
||||||
|
r.args = args
|
||||||
|
r.count = 1
|
||||||
|
return r, true
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case 's': // Prefix: "submitting"
|
case 's': // Prefix: "submitting"
|
||||||
|
|
||||||
if l := len("submitting"); len(elem) >= l && elem[0:l] == "submitting" {
|
if l := len("submitting"); len(elem) >= l && elem[0:l] == "submitting" {
|
||||||
@@ -1777,6 +2045,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionMapfixResetSubmittingOperation
|
r.name = ActionMapfixResetSubmittingOperation
|
||||||
r.summary = "Role Submitter manually resets submitting softlock and changes status from Submitting -> UnderConstruction"
|
r.summary = "Role Submitter manually resets submitting softlock and changes status from Submitting -> UnderConstruction"
|
||||||
r.operationID = "actionMapfixResetSubmitting"
|
r.operationID = "actionMapfixResetSubmitting"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}/status/reset-submitting"
|
r.pathPattern = "/mapfixes/{MapfixID}/status/reset-submitting"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -1799,8 +2068,9 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
switch method {
|
switch method {
|
||||||
case "POST":
|
case "POST":
|
||||||
r.name = ActionMapfixValidatedOperation
|
r.name = ActionMapfixValidatedOperation
|
||||||
r.summary = "Role Admin manually resets uploading softlock and changes status from Uploading -> Validated"
|
r.summary = "Role MapfixUpload manually resets uploading softlock and changes status from Uploading -> Validated"
|
||||||
r.operationID = "actionMapfixValidated"
|
r.operationID = "actionMapfixValidated"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}/status/reset-uploading"
|
r.pathPattern = "/mapfixes/{MapfixID}/status/reset-uploading"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -1825,6 +2095,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionMapfixAcceptedOperation
|
r.name = ActionMapfixAcceptedOperation
|
||||||
r.summary = "Role Reviewer manually resets validating softlock and changes status from Validating -> Accepted"
|
r.summary = "Role Reviewer manually resets validating softlock and changes status from Validating -> Accepted"
|
||||||
r.operationID = "actionMapfixAccepted"
|
r.operationID = "actionMapfixAccepted"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}/status/reset-validating"
|
r.pathPattern = "/mapfixes/{MapfixID}/status/reset-validating"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -1851,6 +2122,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionMapfixRetryValidateOperation
|
r.name = ActionMapfixRetryValidateOperation
|
||||||
r.summary = "Role Reviewer re-runs validation and changes status from Accepted -> Validating"
|
r.summary = "Role Reviewer re-runs validation and changes status from Accepted -> Validating"
|
||||||
r.operationID = "actionMapfixRetryValidate"
|
r.operationID = "actionMapfixRetryValidate"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}/status/retry-validate"
|
r.pathPattern = "/mapfixes/{MapfixID}/status/retry-validate"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -1875,6 +2147,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionMapfixRevokeOperation
|
r.name = ActionMapfixRevokeOperation
|
||||||
r.summary = "Role Submitter changes status from Submitted|ChangesRequested -> UnderConstruction"
|
r.summary = "Role Submitter changes status from Submitted|ChangesRequested -> UnderConstruction"
|
||||||
r.operationID = "actionMapfixRevoke"
|
r.operationID = "actionMapfixRevoke"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}/status/revoke"
|
r.pathPattern = "/mapfixes/{MapfixID}/status/revoke"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -1898,6 +2171,31 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
switch elem[0] {
|
switch elem[0] {
|
||||||
|
case 'r': // Prefix: "release"
|
||||||
|
|
||||||
|
if l := len("release"); len(elem) >= l && elem[0:l] == "release" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch method {
|
||||||
|
case "POST":
|
||||||
|
r.name = ActionMapfixTriggerReleaseOperation
|
||||||
|
r.summary = "Role MapfixUpload changes status from Uploaded -> Releasing"
|
||||||
|
r.operationID = "actionMapfixTriggerRelease"
|
||||||
|
r.operationGroup = ""
|
||||||
|
r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-release"
|
||||||
|
r.args = args
|
||||||
|
r.count = 1
|
||||||
|
return r, true
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case 's': // Prefix: "submit"
|
case 's': // Prefix: "submit"
|
||||||
|
|
||||||
if l := len("submit"); len(elem) >= l && elem[0:l] == "submit" {
|
if l := len("submit"); len(elem) >= l && elem[0:l] == "submit" {
|
||||||
@@ -1912,6 +2210,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionMapfixTriggerSubmitOperation
|
r.name = ActionMapfixTriggerSubmitOperation
|
||||||
r.summary = "Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting"
|
r.summary = "Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting"
|
||||||
r.operationID = "actionMapfixTriggerSubmit"
|
r.operationID = "actionMapfixTriggerSubmit"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-submit"
|
r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-submit"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -1936,6 +2235,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionMapfixTriggerSubmitUncheckedOperation
|
r.name = ActionMapfixTriggerSubmitUncheckedOperation
|
||||||
r.summary = "Role Reviewer changes status from ChangesRequested -> Submitting"
|
r.summary = "Role Reviewer changes status from ChangesRequested -> Submitting"
|
||||||
r.operationID = "actionMapfixTriggerSubmitUnchecked"
|
r.operationID = "actionMapfixTriggerSubmitUnchecked"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-submit-unchecked"
|
r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-submit-unchecked"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -1960,8 +2260,9 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
switch method {
|
switch method {
|
||||||
case "POST":
|
case "POST":
|
||||||
r.name = ActionMapfixTriggerUploadOperation
|
r.name = ActionMapfixTriggerUploadOperation
|
||||||
r.summary = "Role Admin changes status from Validated -> Uploading"
|
r.summary = "Role MapfixUpload changes status from Validated -> Uploading"
|
||||||
r.operationID = "actionMapfixTriggerUpload"
|
r.operationID = "actionMapfixTriggerUpload"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-upload"
|
r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-upload"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -1986,6 +2287,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionMapfixTriggerValidateOperation
|
r.name = ActionMapfixTriggerValidateOperation
|
||||||
r.summary = "Role Reviewer triggers validation and changes status from Submitted -> Validating"
|
r.summary = "Role Reviewer triggers validation and changes status from Submitted -> Validating"
|
||||||
r.operationID = "actionMapfixTriggerValidate"
|
r.operationID = "actionMapfixTriggerValidate"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-validate"
|
r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-validate"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2019,6 +2321,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ListMapsOperation
|
r.name = ListMapsOperation
|
||||||
r.summary = "Get list of maps"
|
r.summary = "Get list of maps"
|
||||||
r.operationID = "listMaps"
|
r.operationID = "listMaps"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/maps"
|
r.pathPattern = "/maps"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 0
|
r.count = 0
|
||||||
@@ -2051,6 +2354,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = GetMapOperation
|
r.name = GetMapOperation
|
||||||
r.summary = "Retrieve map with ID"
|
r.summary = "Retrieve map with ID"
|
||||||
r.operationID = "getMap"
|
r.operationID = "getMap"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/maps/{MapID}"
|
r.pathPattern = "/maps/{MapID}"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2075,6 +2379,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = DownloadMapAssetOperation
|
r.name = DownloadMapAssetOperation
|
||||||
r.summary = "Download the map asset"
|
r.summary = "Download the map asset"
|
||||||
r.operationID = "downloadMapAsset"
|
r.operationID = "downloadMapAsset"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/maps/{MapID}/download"
|
r.pathPattern = "/maps/{MapID}/download"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2114,6 +2419,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = GetOperationOperation
|
r.name = GetOperationOperation
|
||||||
r.summary = "Retrieve operation with ID"
|
r.summary = "Retrieve operation with ID"
|
||||||
r.operationID = "getOperation"
|
r.operationID = "getOperation"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/operations/{OperationID}"
|
r.pathPattern = "/operations/{OperationID}"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2136,8 +2442,9 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
switch method {
|
switch method {
|
||||||
case "POST":
|
case "POST":
|
||||||
r.name = ReleaseSubmissionsOperation
|
r.name = ReleaseSubmissionsOperation
|
||||||
r.summary = "Release a set of uploaded maps"
|
r.summary = "Release a set of uploaded maps. Role SubmissionRelease"
|
||||||
r.operationID = "releaseSubmissions"
|
r.operationID = "releaseSubmissions"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/release-submissions"
|
r.pathPattern = "/release-submissions"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 0
|
r.count = 0
|
||||||
@@ -2185,6 +2492,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ListScriptPolicyOperation
|
r.name = ListScriptPolicyOperation
|
||||||
r.summary = "Get list of script policies"
|
r.summary = "Get list of script policies"
|
||||||
r.operationID = "listScriptPolicy"
|
r.operationID = "listScriptPolicy"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/script-policy"
|
r.pathPattern = "/script-policy"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 0
|
r.count = 0
|
||||||
@@ -2193,6 +2501,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = CreateScriptPolicyOperation
|
r.name = CreateScriptPolicyOperation
|
||||||
r.summary = "Create a new script policy"
|
r.summary = "Create a new script policy"
|
||||||
r.operationID = "createScriptPolicy"
|
r.operationID = "createScriptPolicy"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/script-policy"
|
r.pathPattern = "/script-policy"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 0
|
r.count = 0
|
||||||
@@ -2226,6 +2535,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = DeleteScriptPolicyOperation
|
r.name = DeleteScriptPolicyOperation
|
||||||
r.summary = "Delete the specified script policy by ID"
|
r.summary = "Delete the specified script policy by ID"
|
||||||
r.operationID = "deleteScriptPolicy"
|
r.operationID = "deleteScriptPolicy"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/script-policy/{ScriptPolicyID}"
|
r.pathPattern = "/script-policy/{ScriptPolicyID}"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2234,6 +2544,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = GetScriptPolicyOperation
|
r.name = GetScriptPolicyOperation
|
||||||
r.summary = "Get the specified script policy by ID"
|
r.summary = "Get the specified script policy by ID"
|
||||||
r.operationID = "getScriptPolicy"
|
r.operationID = "getScriptPolicy"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/script-policy/{ScriptPolicyID}"
|
r.pathPattern = "/script-policy/{ScriptPolicyID}"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2242,6 +2553,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = UpdateScriptPolicyOperation
|
r.name = UpdateScriptPolicyOperation
|
||||||
r.summary = "Update the specified script policy by ID"
|
r.summary = "Update the specified script policy by ID"
|
||||||
r.operationID = "updateScriptPolicy"
|
r.operationID = "updateScriptPolicy"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/script-policy/{ScriptPolicyID}"
|
r.pathPattern = "/script-policy/{ScriptPolicyID}"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2267,6 +2579,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ListScriptsOperation
|
r.name = ListScriptsOperation
|
||||||
r.summary = "Get list of scripts"
|
r.summary = "Get list of scripts"
|
||||||
r.operationID = "listScripts"
|
r.operationID = "listScripts"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/scripts"
|
r.pathPattern = "/scripts"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 0
|
r.count = 0
|
||||||
@@ -2275,6 +2588,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = CreateScriptOperation
|
r.name = CreateScriptOperation
|
||||||
r.summary = "Create a new script"
|
r.summary = "Create a new script"
|
||||||
r.operationID = "createScript"
|
r.operationID = "createScript"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/scripts"
|
r.pathPattern = "/scripts"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 0
|
r.count = 0
|
||||||
@@ -2308,6 +2622,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = DeleteScriptOperation
|
r.name = DeleteScriptOperation
|
||||||
r.summary = "Delete the specified script by ID"
|
r.summary = "Delete the specified script by ID"
|
||||||
r.operationID = "deleteScript"
|
r.operationID = "deleteScript"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/scripts/{ScriptID}"
|
r.pathPattern = "/scripts/{ScriptID}"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2316,6 +2631,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = GetScriptOperation
|
r.name = GetScriptOperation
|
||||||
r.summary = "Get the specified script by ID"
|
r.summary = "Get the specified script by ID"
|
||||||
r.operationID = "getScript"
|
r.operationID = "getScript"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/scripts/{ScriptID}"
|
r.pathPattern = "/scripts/{ScriptID}"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2324,6 +2640,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = UpdateScriptOperation
|
r.name = UpdateScriptOperation
|
||||||
r.summary = "Update the specified script by ID"
|
r.summary = "Update the specified script by ID"
|
||||||
r.operationID = "updateScript"
|
r.operationID = "updateScript"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/scripts/{ScriptID}"
|
r.pathPattern = "/scripts/{ScriptID}"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2364,6 +2681,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = SessionRolesOperation
|
r.name = SessionRolesOperation
|
||||||
r.summary = "Get list of roles for the current session"
|
r.summary = "Get list of roles for the current session"
|
||||||
r.operationID = "sessionRoles"
|
r.operationID = "sessionRoles"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/session/roles"
|
r.pathPattern = "/session/roles"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 0
|
r.count = 0
|
||||||
@@ -2388,6 +2706,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = SessionUserOperation
|
r.name = SessionUserOperation
|
||||||
r.summary = "Get information about the currently logged in user"
|
r.summary = "Get information about the currently logged in user"
|
||||||
r.operationID = "sessionUser"
|
r.operationID = "sessionUser"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/session/user"
|
r.pathPattern = "/session/user"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 0
|
r.count = 0
|
||||||
@@ -2412,6 +2731,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = SessionValidateOperation
|
r.name = SessionValidateOperation
|
||||||
r.summary = "Ask if the current session is valid"
|
r.summary = "Ask if the current session is valid"
|
||||||
r.operationID = "sessionValidate"
|
r.operationID = "sessionValidate"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/session/validate"
|
r.pathPattern = "/session/validate"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 0
|
r.count = 0
|
||||||
@@ -2423,6 +2743,31 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 't': // Prefix: "tats"
|
||||||
|
|
||||||
|
if l := len("tats"); len(elem) >= l && elem[0:l] == "tats" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch method {
|
||||||
|
case "GET":
|
||||||
|
r.name = GetStatsOperation
|
||||||
|
r.summary = "Get aggregate statistics"
|
||||||
|
r.operationID = "getStats"
|
||||||
|
r.operationGroup = ""
|
||||||
|
r.pathPattern = "/stats"
|
||||||
|
r.args = args
|
||||||
|
r.count = 0
|
||||||
|
return r, true
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case 'u': // Prefix: "ubmissions"
|
case 'u': // Prefix: "ubmissions"
|
||||||
|
|
||||||
if l := len("ubmissions"); len(elem) >= l && elem[0:l] == "ubmissions" {
|
if l := len("ubmissions"); len(elem) >= l && elem[0:l] == "ubmissions" {
|
||||||
@@ -2437,6 +2782,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ListSubmissionsOperation
|
r.name = ListSubmissionsOperation
|
||||||
r.summary = "Get list of submissions"
|
r.summary = "Get list of submissions"
|
||||||
r.operationID = "listSubmissions"
|
r.operationID = "listSubmissions"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions"
|
r.pathPattern = "/submissions"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 0
|
r.count = 0
|
||||||
@@ -2445,6 +2791,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = CreateSubmissionOperation
|
r.name = CreateSubmissionOperation
|
||||||
r.summary = "Trigger the validator to create a new submission"
|
r.summary = "Trigger the validator to create a new submission"
|
||||||
r.operationID = "createSubmission"
|
r.operationID = "createSubmission"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions"
|
r.pathPattern = "/submissions"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 0
|
r.count = 0
|
||||||
@@ -2469,6 +2816,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = CreateSubmissionAdminOperation
|
r.name = CreateSubmissionAdminOperation
|
||||||
r.summary = "Trigger the validator to create a new submission"
|
r.summary = "Trigger the validator to create a new submission"
|
||||||
r.operationID = "createSubmissionAdmin"
|
r.operationID = "createSubmissionAdmin"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions-admin"
|
r.pathPattern = "/submissions-admin"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 0
|
r.count = 0
|
||||||
@@ -2501,6 +2849,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = GetSubmissionOperation
|
r.name = GetSubmissionOperation
|
||||||
r.summary = "Retrieve map with ID"
|
r.summary = "Retrieve map with ID"
|
||||||
r.operationID = "getSubmission"
|
r.operationID = "getSubmission"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}"
|
r.pathPattern = "/submissions/{SubmissionID}"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2537,6 +2886,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ListSubmissionAuditEventsOperation
|
r.name = ListSubmissionAuditEventsOperation
|
||||||
r.summary = "Retrieve a list of audit events"
|
r.summary = "Retrieve a list of audit events"
|
||||||
r.operationID = "listSubmissionAuditEvents"
|
r.operationID = "listSubmissionAuditEvents"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}/audit-events"
|
r.pathPattern = "/submissions/{SubmissionID}/audit-events"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2573,6 +2923,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = CreateSubmissionAuditCommentOperation
|
r.name = CreateSubmissionAuditCommentOperation
|
||||||
r.summary = "Post a comment to the audit log"
|
r.summary = "Post a comment to the audit log"
|
||||||
r.operationID = "createSubmissionAuditComment"
|
r.operationID = "createSubmissionAuditComment"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}/comment"
|
r.pathPattern = "/submissions/{SubmissionID}/comment"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2597,6 +2948,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = SetSubmissionCompletedOperation
|
r.name = SetSubmissionCompletedOperation
|
||||||
r.summary = "Called by maptest when a player completes the map"
|
r.summary = "Called by maptest when a player completes the map"
|
||||||
r.operationID = "setSubmissionCompleted"
|
r.operationID = "setSubmissionCompleted"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}/completed"
|
r.pathPattern = "/submissions/{SubmissionID}/completed"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2623,6 +2975,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = UpdateSubmissionModelOperation
|
r.name = UpdateSubmissionModelOperation
|
||||||
r.summary = "Update model following role restrictions"
|
r.summary = "Update model following role restrictions"
|
||||||
r.operationID = "updateSubmissionModel"
|
r.operationID = "updateSubmissionModel"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}/model"
|
r.pathPattern = "/submissions/{SubmissionID}/model"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2671,6 +3024,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionSubmissionRejectOperation
|
r.name = ActionSubmissionRejectOperation
|
||||||
r.summary = "Role Reviewer changes status from Submitted -> Rejected"
|
r.summary = "Role Reviewer changes status from Submitted -> Rejected"
|
||||||
r.operationID = "actionSubmissionReject"
|
r.operationID = "actionSubmissionReject"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}/status/reject"
|
r.pathPattern = "/submissions/{SubmissionID}/status/reject"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2695,6 +3049,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionSubmissionRequestChangesOperation
|
r.name = ActionSubmissionRequestChangesOperation
|
||||||
r.summary = "Role Reviewer changes status from Validated|Accepted|Submitted -> ChangesRequested"
|
r.summary = "Role Reviewer changes status from Validated|Accepted|Submitted -> ChangesRequested"
|
||||||
r.operationID = "actionSubmissionRequestChanges"
|
r.operationID = "actionSubmissionRequestChanges"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}/status/request-changes"
|
r.pathPattern = "/submissions/{SubmissionID}/status/request-changes"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2731,6 +3086,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionSubmissionResetSubmittingOperation
|
r.name = ActionSubmissionResetSubmittingOperation
|
||||||
r.summary = "Role Submitter manually resets submitting softlock and changes status from Submitting -> UnderConstruction"
|
r.summary = "Role Submitter manually resets submitting softlock and changes status from Submitting -> UnderConstruction"
|
||||||
r.operationID = "actionSubmissionResetSubmitting"
|
r.operationID = "actionSubmissionResetSubmitting"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}/status/reset-submitting"
|
r.pathPattern = "/submissions/{SubmissionID}/status/reset-submitting"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2753,8 +3109,9 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
switch method {
|
switch method {
|
||||||
case "POST":
|
case "POST":
|
||||||
r.name = ActionSubmissionValidatedOperation
|
r.name = ActionSubmissionValidatedOperation
|
||||||
r.summary = "Role Admin manually resets uploading softlock and changes status from Uploading -> Validated"
|
r.summary = "Role SubmissionUpload manually resets uploading softlock and changes status from Uploading -> Validated"
|
||||||
r.operationID = "actionSubmissionValidated"
|
r.operationID = "actionSubmissionValidated"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}/status/reset-uploading"
|
r.pathPattern = "/submissions/{SubmissionID}/status/reset-uploading"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2779,6 +3136,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionSubmissionAcceptedOperation
|
r.name = ActionSubmissionAcceptedOperation
|
||||||
r.summary = "Role Reviewer manually resets validating softlock and changes status from Validating -> Accepted"
|
r.summary = "Role Reviewer manually resets validating softlock and changes status from Validating -> Accepted"
|
||||||
r.operationID = "actionSubmissionAccepted"
|
r.operationID = "actionSubmissionAccepted"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}/status/reset-validating"
|
r.pathPattern = "/submissions/{SubmissionID}/status/reset-validating"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2805,6 +3163,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionSubmissionRetryValidateOperation
|
r.name = ActionSubmissionRetryValidateOperation
|
||||||
r.summary = "Role Reviewer re-runs validation and changes status from Accepted -> Validating"
|
r.summary = "Role Reviewer re-runs validation and changes status from Accepted -> Validating"
|
||||||
r.operationID = "actionSubmissionRetryValidate"
|
r.operationID = "actionSubmissionRetryValidate"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}/status/retry-validate"
|
r.pathPattern = "/submissions/{SubmissionID}/status/retry-validate"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2829,6 +3188,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionSubmissionRevokeOperation
|
r.name = ActionSubmissionRevokeOperation
|
||||||
r.summary = "Role Submitter changes status from Submitted|ChangesRequested -> UnderConstruction"
|
r.summary = "Role Submitter changes status from Submitted|ChangesRequested -> UnderConstruction"
|
||||||
r.operationID = "actionSubmissionRevoke"
|
r.operationID = "actionSubmissionRevoke"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}/status/revoke"
|
r.pathPattern = "/submissions/{SubmissionID}/status/revoke"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2866,6 +3226,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionSubmissionTriggerSubmitOperation
|
r.name = ActionSubmissionTriggerSubmitOperation
|
||||||
r.summary = "Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting"
|
r.summary = "Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting"
|
||||||
r.operationID = "actionSubmissionTriggerSubmit"
|
r.operationID = "actionSubmissionTriggerSubmit"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}/status/trigger-submit"
|
r.pathPattern = "/submissions/{SubmissionID}/status/trigger-submit"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2890,6 +3251,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionSubmissionTriggerSubmitUncheckedOperation
|
r.name = ActionSubmissionTriggerSubmitUncheckedOperation
|
||||||
r.summary = "Role Reviewer changes status from ChangesRequested -> Submitting"
|
r.summary = "Role Reviewer changes status from ChangesRequested -> Submitting"
|
||||||
r.operationID = "actionSubmissionTriggerSubmitUnchecked"
|
r.operationID = "actionSubmissionTriggerSubmitUnchecked"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}/status/trigger-submit-unchecked"
|
r.pathPattern = "/submissions/{SubmissionID}/status/trigger-submit-unchecked"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2914,8 +3276,9 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
switch method {
|
switch method {
|
||||||
case "POST":
|
case "POST":
|
||||||
r.name = ActionSubmissionTriggerUploadOperation
|
r.name = ActionSubmissionTriggerUploadOperation
|
||||||
r.summary = "Role Admin changes status from Validated -> Uploading"
|
r.summary = "Role SubmissionUpload changes status from Validated -> Uploading"
|
||||||
r.operationID = "actionSubmissionTriggerUpload"
|
r.operationID = "actionSubmissionTriggerUpload"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}/status/trigger-upload"
|
r.pathPattern = "/submissions/{SubmissionID}/status/trigger-upload"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2940,6 +3303,7 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
r.name = ActionSubmissionTriggerValidateOperation
|
r.name = ActionSubmissionTriggerValidateOperation
|
||||||
r.summary = "Role Reviewer triggers validation and changes status from Submitted -> Validating"
|
r.summary = "Role Reviewer triggers validation and changes status from Submitted -> Validating"
|
||||||
r.operationID = "actionSubmissionTriggerValidate"
|
r.operationID = "actionSubmissionTriggerValidate"
|
||||||
|
r.operationGroup = ""
|
||||||
r.pathPattern = "/submissions/{SubmissionID}/status/trigger-validate"
|
r.pathPattern = "/submissions/{SubmissionID}/status/trigger-validate"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
@@ -2961,6 +3325,191 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 't': // Prefix: "thumbnails/"
|
||||||
|
|
||||||
|
if l := len("thumbnails/"); len(elem) >= l && elem[0:l] == "thumbnails/" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch elem[0] {
|
||||||
|
case 'a': // Prefix: "asset"
|
||||||
|
|
||||||
|
if l := len("asset"); len(elem) >= l && elem[0:l] == "asset" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch elem[0] {
|
||||||
|
case '/': // Prefix: "/"
|
||||||
|
|
||||||
|
if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Param: "AssetID"
|
||||||
|
// Leaf parameter, slashes are prohibited
|
||||||
|
idx := strings.IndexByte(elem, '/')
|
||||||
|
if idx >= 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
args[0] = elem
|
||||||
|
elem = ""
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch method {
|
||||||
|
case "GET":
|
||||||
|
r.name = GetAssetThumbnailOperation
|
||||||
|
r.summary = "Get single asset thumbnail"
|
||||||
|
r.operationID = "getAssetThumbnail"
|
||||||
|
r.operationGroup = ""
|
||||||
|
r.pathPattern = "/thumbnails/asset/{AssetID}"
|
||||||
|
r.args = args
|
||||||
|
r.count = 1
|
||||||
|
return r, true
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 's': // Prefix: "s"
|
||||||
|
|
||||||
|
if l := len("s"); len(elem) >= l && elem[0:l] == "s" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch method {
|
||||||
|
case "POST":
|
||||||
|
r.name = BatchAssetThumbnailsOperation
|
||||||
|
r.summary = "Batch fetch asset thumbnails"
|
||||||
|
r.operationID = "batchAssetThumbnails"
|
||||||
|
r.operationGroup = ""
|
||||||
|
r.pathPattern = "/thumbnails/assets"
|
||||||
|
r.args = args
|
||||||
|
r.count = 0
|
||||||
|
return r, true
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'u': // Prefix: "user"
|
||||||
|
|
||||||
|
if l := len("user"); len(elem) >= l && elem[0:l] == "user" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch elem[0] {
|
||||||
|
case '/': // Prefix: "/"
|
||||||
|
|
||||||
|
if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Param: "UserID"
|
||||||
|
// Leaf parameter, slashes are prohibited
|
||||||
|
idx := strings.IndexByte(elem, '/')
|
||||||
|
if idx >= 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
args[0] = elem
|
||||||
|
elem = ""
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch method {
|
||||||
|
case "GET":
|
||||||
|
r.name = GetUserThumbnailOperation
|
||||||
|
r.summary = "Get single user avatar thumbnail"
|
||||||
|
r.operationID = "getUserThumbnail"
|
||||||
|
r.operationGroup = ""
|
||||||
|
r.pathPattern = "/thumbnails/user/{UserID}"
|
||||||
|
r.args = args
|
||||||
|
r.count = 1
|
||||||
|
return r, true
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 's': // Prefix: "s"
|
||||||
|
|
||||||
|
if l := len("s"); len(elem) >= l && elem[0:l] == "s" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch method {
|
||||||
|
case "POST":
|
||||||
|
r.name = BatchUserThumbnailsOperation
|
||||||
|
r.summary = "Batch fetch user avatar thumbnails"
|
||||||
|
r.operationID = "batchUserThumbnails"
|
||||||
|
r.operationGroup = ""
|
||||||
|
r.pathPattern = "/thumbnails/users"
|
||||||
|
r.args = args
|
||||||
|
r.count = 0
|
||||||
|
return r, true
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'u': // Prefix: "usernames"
|
||||||
|
|
||||||
|
if l := len("usernames"); len(elem) >= l && elem[0:l] == "usernames" {
|
||||||
|
elem = elem[l:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem) == 0 {
|
||||||
|
// Leaf node.
|
||||||
|
switch method {
|
||||||
|
case "POST":
|
||||||
|
r.name = BatchUsernamesOperation
|
||||||
|
r.summary = "Batch fetch usernames"
|
||||||
|
r.operationID = "batchUsernames"
|
||||||
|
r.operationGroup = ""
|
||||||
|
r.pathPattern = "/usernames"
|
||||||
|
r.args = args
|
||||||
|
r.count = 0
|
||||||
|
return r, true
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-faster/errors"
|
||||||
"github.com/go-faster/jx"
|
"github.com/go-faster/jx"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -32,6 +33,9 @@ type ActionMapfixRetryValidateNoContent struct{}
|
|||||||
// ActionMapfixRevokeNoContent is response for ActionMapfixRevoke operation.
|
// ActionMapfixRevokeNoContent is response for ActionMapfixRevoke operation.
|
||||||
type ActionMapfixRevokeNoContent struct{}
|
type ActionMapfixRevokeNoContent struct{}
|
||||||
|
|
||||||
|
// ActionMapfixTriggerReleaseNoContent is response for ActionMapfixTriggerRelease operation.
|
||||||
|
type ActionMapfixTriggerReleaseNoContent struct{}
|
||||||
|
|
||||||
// ActionMapfixTriggerSubmitNoContent is response for ActionMapfixTriggerSubmit operation.
|
// ActionMapfixTriggerSubmitNoContent is response for ActionMapfixTriggerSubmit operation.
|
||||||
type ActionMapfixTriggerSubmitNoContent struct{}
|
type ActionMapfixTriggerSubmitNoContent struct{}
|
||||||
|
|
||||||
@@ -44,6 +48,9 @@ type ActionMapfixTriggerUploadNoContent struct{}
|
|||||||
// ActionMapfixTriggerValidateNoContent is response for ActionMapfixTriggerValidate operation.
|
// ActionMapfixTriggerValidateNoContent is response for ActionMapfixTriggerValidate operation.
|
||||||
type ActionMapfixTriggerValidateNoContent struct{}
|
type ActionMapfixTriggerValidateNoContent struct{}
|
||||||
|
|
||||||
|
// ActionMapfixUploadedNoContent is response for ActionMapfixUploaded operation.
|
||||||
|
type ActionMapfixUploadedNoContent struct{}
|
||||||
|
|
||||||
// ActionMapfixValidatedNoContent is response for ActionMapfixValidated operation.
|
// ActionMapfixValidatedNoContent is response for ActionMapfixValidated operation.
|
||||||
type ActionMapfixValidatedNoContent struct{}
|
type ActionMapfixValidatedNoContent struct{}
|
||||||
|
|
||||||
@@ -186,6 +193,254 @@ func (s *AuditEventEventData) init() AuditEventEventData {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BatchAssetThumbnailsOK struct {
|
||||||
|
// Map of asset ID to thumbnail URL.
|
||||||
|
Thumbnails OptBatchAssetThumbnailsOKThumbnails `json:"thumbnails"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetThumbnails returns the value of Thumbnails.
|
||||||
|
func (s *BatchAssetThumbnailsOK) GetThumbnails() OptBatchAssetThumbnailsOKThumbnails {
|
||||||
|
return s.Thumbnails
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetThumbnails sets the value of Thumbnails.
|
||||||
|
func (s *BatchAssetThumbnailsOK) SetThumbnails(val OptBatchAssetThumbnailsOKThumbnails) {
|
||||||
|
s.Thumbnails = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map of asset ID to thumbnail URL.
|
||||||
|
type BatchAssetThumbnailsOKThumbnails map[string]string
|
||||||
|
|
||||||
|
func (s *BatchAssetThumbnailsOKThumbnails) init() BatchAssetThumbnailsOKThumbnails {
|
||||||
|
m := *s
|
||||||
|
if m == nil {
|
||||||
|
m = map[string]string{}
|
||||||
|
*s = m
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
type BatchAssetThumbnailsReq struct {
|
||||||
|
// Array of asset IDs (max 100).
|
||||||
|
AssetIds []uint64 `json:"assetIds"`
|
||||||
|
// Thumbnail size.
|
||||||
|
Size OptBatchAssetThumbnailsReqSize `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAssetIds returns the value of AssetIds.
|
||||||
|
func (s *BatchAssetThumbnailsReq) GetAssetIds() []uint64 {
|
||||||
|
return s.AssetIds
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSize returns the value of Size.
|
||||||
|
func (s *BatchAssetThumbnailsReq) GetSize() OptBatchAssetThumbnailsReqSize {
|
||||||
|
return s.Size
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAssetIds sets the value of AssetIds.
|
||||||
|
func (s *BatchAssetThumbnailsReq) SetAssetIds(val []uint64) {
|
||||||
|
s.AssetIds = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSize sets the value of Size.
|
||||||
|
func (s *BatchAssetThumbnailsReq) SetSize(val OptBatchAssetThumbnailsReqSize) {
|
||||||
|
s.Size = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thumbnail size.
|
||||||
|
type BatchAssetThumbnailsReqSize string
|
||||||
|
|
||||||
|
const (
|
||||||
|
BatchAssetThumbnailsReqSize150x150 BatchAssetThumbnailsReqSize = "150x150"
|
||||||
|
BatchAssetThumbnailsReqSize420x420 BatchAssetThumbnailsReqSize = "420x420"
|
||||||
|
BatchAssetThumbnailsReqSize768x432 BatchAssetThumbnailsReqSize = "768x432"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AllValues returns all BatchAssetThumbnailsReqSize values.
|
||||||
|
func (BatchAssetThumbnailsReqSize) AllValues() []BatchAssetThumbnailsReqSize {
|
||||||
|
return []BatchAssetThumbnailsReqSize{
|
||||||
|
BatchAssetThumbnailsReqSize150x150,
|
||||||
|
BatchAssetThumbnailsReqSize420x420,
|
||||||
|
BatchAssetThumbnailsReqSize768x432,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
|
func (s BatchAssetThumbnailsReqSize) MarshalText() ([]byte, error) {
|
||||||
|
switch s {
|
||||||
|
case BatchAssetThumbnailsReqSize150x150:
|
||||||
|
return []byte(s), nil
|
||||||
|
case BatchAssetThumbnailsReqSize420x420:
|
||||||
|
return []byte(s), nil
|
||||||
|
case BatchAssetThumbnailsReqSize768x432:
|
||||||
|
return []byte(s), nil
|
||||||
|
default:
|
||||||
|
return nil, errors.Errorf("invalid value: %q", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||||
|
func (s *BatchAssetThumbnailsReqSize) UnmarshalText(data []byte) error {
|
||||||
|
switch BatchAssetThumbnailsReqSize(data) {
|
||||||
|
case BatchAssetThumbnailsReqSize150x150:
|
||||||
|
*s = BatchAssetThumbnailsReqSize150x150
|
||||||
|
return nil
|
||||||
|
case BatchAssetThumbnailsReqSize420x420:
|
||||||
|
*s = BatchAssetThumbnailsReqSize420x420
|
||||||
|
return nil
|
||||||
|
case BatchAssetThumbnailsReqSize768x432:
|
||||||
|
*s = BatchAssetThumbnailsReqSize768x432
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return errors.Errorf("invalid value: %q", data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type BatchUserThumbnailsOK struct {
|
||||||
|
// Map of user ID to thumbnail URL.
|
||||||
|
Thumbnails OptBatchUserThumbnailsOKThumbnails `json:"thumbnails"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetThumbnails returns the value of Thumbnails.
|
||||||
|
func (s *BatchUserThumbnailsOK) GetThumbnails() OptBatchUserThumbnailsOKThumbnails {
|
||||||
|
return s.Thumbnails
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetThumbnails sets the value of Thumbnails.
|
||||||
|
func (s *BatchUserThumbnailsOK) SetThumbnails(val OptBatchUserThumbnailsOKThumbnails) {
|
||||||
|
s.Thumbnails = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map of user ID to thumbnail URL.
|
||||||
|
type BatchUserThumbnailsOKThumbnails map[string]string
|
||||||
|
|
||||||
|
func (s *BatchUserThumbnailsOKThumbnails) init() BatchUserThumbnailsOKThumbnails {
|
||||||
|
m := *s
|
||||||
|
if m == nil {
|
||||||
|
m = map[string]string{}
|
||||||
|
*s = m
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
type BatchUserThumbnailsReq struct {
|
||||||
|
// Array of user IDs (max 100).
|
||||||
|
UserIds []uint64 `json:"userIds"`
|
||||||
|
// Thumbnail size.
|
||||||
|
Size OptBatchUserThumbnailsReqSize `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserIds returns the value of UserIds.
|
||||||
|
func (s *BatchUserThumbnailsReq) GetUserIds() []uint64 {
|
||||||
|
return s.UserIds
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSize returns the value of Size.
|
||||||
|
func (s *BatchUserThumbnailsReq) GetSize() OptBatchUserThumbnailsReqSize {
|
||||||
|
return s.Size
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUserIds sets the value of UserIds.
|
||||||
|
func (s *BatchUserThumbnailsReq) SetUserIds(val []uint64) {
|
||||||
|
s.UserIds = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSize sets the value of Size.
|
||||||
|
func (s *BatchUserThumbnailsReq) SetSize(val OptBatchUserThumbnailsReqSize) {
|
||||||
|
s.Size = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thumbnail size.
|
||||||
|
type BatchUserThumbnailsReqSize string
|
||||||
|
|
||||||
|
const (
|
||||||
|
BatchUserThumbnailsReqSize150x150 BatchUserThumbnailsReqSize = "150x150"
|
||||||
|
BatchUserThumbnailsReqSize420x420 BatchUserThumbnailsReqSize = "420x420"
|
||||||
|
BatchUserThumbnailsReqSize768x432 BatchUserThumbnailsReqSize = "768x432"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AllValues returns all BatchUserThumbnailsReqSize values.
|
||||||
|
func (BatchUserThumbnailsReqSize) AllValues() []BatchUserThumbnailsReqSize {
|
||||||
|
return []BatchUserThumbnailsReqSize{
|
||||||
|
BatchUserThumbnailsReqSize150x150,
|
||||||
|
BatchUserThumbnailsReqSize420x420,
|
||||||
|
BatchUserThumbnailsReqSize768x432,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
|
func (s BatchUserThumbnailsReqSize) MarshalText() ([]byte, error) {
|
||||||
|
switch s {
|
||||||
|
case BatchUserThumbnailsReqSize150x150:
|
||||||
|
return []byte(s), nil
|
||||||
|
case BatchUserThumbnailsReqSize420x420:
|
||||||
|
return []byte(s), nil
|
||||||
|
case BatchUserThumbnailsReqSize768x432:
|
||||||
|
return []byte(s), nil
|
||||||
|
default:
|
||||||
|
return nil, errors.Errorf("invalid value: %q", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||||
|
func (s *BatchUserThumbnailsReqSize) UnmarshalText(data []byte) error {
|
||||||
|
switch BatchUserThumbnailsReqSize(data) {
|
||||||
|
case BatchUserThumbnailsReqSize150x150:
|
||||||
|
*s = BatchUserThumbnailsReqSize150x150
|
||||||
|
return nil
|
||||||
|
case BatchUserThumbnailsReqSize420x420:
|
||||||
|
*s = BatchUserThumbnailsReqSize420x420
|
||||||
|
return nil
|
||||||
|
case BatchUserThumbnailsReqSize768x432:
|
||||||
|
*s = BatchUserThumbnailsReqSize768x432
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return errors.Errorf("invalid value: %q", data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type BatchUsernamesOK struct {
|
||||||
|
// Map of user ID to username.
|
||||||
|
Usernames OptBatchUsernamesOKUsernames `json:"usernames"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUsernames returns the value of Usernames.
|
||||||
|
func (s *BatchUsernamesOK) GetUsernames() OptBatchUsernamesOKUsernames {
|
||||||
|
return s.Usernames
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUsernames sets the value of Usernames.
|
||||||
|
func (s *BatchUsernamesOK) SetUsernames(val OptBatchUsernamesOKUsernames) {
|
||||||
|
s.Usernames = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map of user ID to username.
|
||||||
|
type BatchUsernamesOKUsernames map[string]string
|
||||||
|
|
||||||
|
func (s *BatchUsernamesOKUsernames) init() BatchUsernamesOKUsernames {
|
||||||
|
m := *s
|
||||||
|
if m == nil {
|
||||||
|
m = map[string]string{}
|
||||||
|
*s = m
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
type BatchUsernamesReq struct {
|
||||||
|
// Array of user IDs (max 100).
|
||||||
|
UserIds []uint64 `json:"userIds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserIds returns the value of UserIds.
|
||||||
|
func (s *BatchUsernamesReq) GetUserIds() []uint64 {
|
||||||
|
return s.UserIds
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUserIds sets the value of UserIds.
|
||||||
|
func (s *BatchUsernamesReq) SetUserIds(val []uint64) {
|
||||||
|
s.UserIds = val
|
||||||
|
}
|
||||||
|
|
||||||
type CookieAuth struct {
|
type CookieAuth struct {
|
||||||
APIKey string
|
APIKey string
|
||||||
Roles []string
|
Roles []string
|
||||||
@@ -318,6 +573,132 @@ func (s *ErrorStatusCode) SetResponse(val Error) {
|
|||||||
s.Response = val
|
s.Response = val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAssetThumbnailFound is response for GetAssetThumbnail operation.
|
||||||
|
type GetAssetThumbnailFound struct {
|
||||||
|
Location OptString
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLocation returns the value of Location.
|
||||||
|
func (s *GetAssetThumbnailFound) GetLocation() OptString {
|
||||||
|
return s.Location
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLocation sets the value of Location.
|
||||||
|
func (s *GetAssetThumbnailFound) SetLocation(val OptString) {
|
||||||
|
s.Location = val
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetAssetThumbnailSize string
|
||||||
|
|
||||||
|
const (
|
||||||
|
GetAssetThumbnailSize150x150 GetAssetThumbnailSize = "150x150"
|
||||||
|
GetAssetThumbnailSize420x420 GetAssetThumbnailSize = "420x420"
|
||||||
|
GetAssetThumbnailSize768x432 GetAssetThumbnailSize = "768x432"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AllValues returns all GetAssetThumbnailSize values.
|
||||||
|
func (GetAssetThumbnailSize) AllValues() []GetAssetThumbnailSize {
|
||||||
|
return []GetAssetThumbnailSize{
|
||||||
|
GetAssetThumbnailSize150x150,
|
||||||
|
GetAssetThumbnailSize420x420,
|
||||||
|
GetAssetThumbnailSize768x432,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
|
func (s GetAssetThumbnailSize) MarshalText() ([]byte, error) {
|
||||||
|
switch s {
|
||||||
|
case GetAssetThumbnailSize150x150:
|
||||||
|
return []byte(s), nil
|
||||||
|
case GetAssetThumbnailSize420x420:
|
||||||
|
return []byte(s), nil
|
||||||
|
case GetAssetThumbnailSize768x432:
|
||||||
|
return []byte(s), nil
|
||||||
|
default:
|
||||||
|
return nil, errors.Errorf("invalid value: %q", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||||
|
func (s *GetAssetThumbnailSize) UnmarshalText(data []byte) error {
|
||||||
|
switch GetAssetThumbnailSize(data) {
|
||||||
|
case GetAssetThumbnailSize150x150:
|
||||||
|
*s = GetAssetThumbnailSize150x150
|
||||||
|
return nil
|
||||||
|
case GetAssetThumbnailSize420x420:
|
||||||
|
*s = GetAssetThumbnailSize420x420
|
||||||
|
return nil
|
||||||
|
case GetAssetThumbnailSize768x432:
|
||||||
|
*s = GetAssetThumbnailSize768x432
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return errors.Errorf("invalid value: %q", data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserThumbnailFound is response for GetUserThumbnail operation.
|
||||||
|
type GetUserThumbnailFound struct {
|
||||||
|
Location OptString
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLocation returns the value of Location.
|
||||||
|
func (s *GetUserThumbnailFound) GetLocation() OptString {
|
||||||
|
return s.Location
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLocation sets the value of Location.
|
||||||
|
func (s *GetUserThumbnailFound) SetLocation(val OptString) {
|
||||||
|
s.Location = val
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetUserThumbnailSize string
|
||||||
|
|
||||||
|
const (
|
||||||
|
GetUserThumbnailSize150x150 GetUserThumbnailSize = "150x150"
|
||||||
|
GetUserThumbnailSize420x420 GetUserThumbnailSize = "420x420"
|
||||||
|
GetUserThumbnailSize768x432 GetUserThumbnailSize = "768x432"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AllValues returns all GetUserThumbnailSize values.
|
||||||
|
func (GetUserThumbnailSize) AllValues() []GetUserThumbnailSize {
|
||||||
|
return []GetUserThumbnailSize{
|
||||||
|
GetUserThumbnailSize150x150,
|
||||||
|
GetUserThumbnailSize420x420,
|
||||||
|
GetUserThumbnailSize768x432,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
|
func (s GetUserThumbnailSize) MarshalText() ([]byte, error) {
|
||||||
|
switch s {
|
||||||
|
case GetUserThumbnailSize150x150:
|
||||||
|
return []byte(s), nil
|
||||||
|
case GetUserThumbnailSize420x420:
|
||||||
|
return []byte(s), nil
|
||||||
|
case GetUserThumbnailSize768x432:
|
||||||
|
return []byte(s), nil
|
||||||
|
default:
|
||||||
|
return nil, errors.Errorf("invalid value: %q", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||||
|
func (s *GetUserThumbnailSize) UnmarshalText(data []byte) error {
|
||||||
|
switch GetUserThumbnailSize(data) {
|
||||||
|
case GetUserThumbnailSize150x150:
|
||||||
|
*s = GetUserThumbnailSize150x150
|
||||||
|
return nil
|
||||||
|
case GetUserThumbnailSize420x420:
|
||||||
|
*s = GetUserThumbnailSize420x420
|
||||||
|
return nil
|
||||||
|
case GetUserThumbnailSize768x432:
|
||||||
|
*s = GetUserThumbnailSize768x432
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return errors.Errorf("invalid value: %q", data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Ref: #/components/schemas/Map
|
// Ref: #/components/schemas/Map
|
||||||
type Map struct {
|
type Map struct {
|
||||||
ID int64 `json:"ID"`
|
ID int64 `json:"ID"`
|
||||||
@@ -456,19 +837,21 @@ func (s *Map) SetModes(val uint32) {
|
|||||||
|
|
||||||
// Ref: #/components/schemas/Mapfix
|
// Ref: #/components/schemas/Mapfix
|
||||||
type Mapfix struct {
|
type Mapfix struct {
|
||||||
ID int64 `json:"ID"`
|
ID int64 `json:"ID"`
|
||||||
DisplayName string `json:"DisplayName"`
|
DisplayName string `json:"DisplayName"`
|
||||||
Creator string `json:"Creator"`
|
Creator string `json:"Creator"`
|
||||||
GameID int32 `json:"GameID"`
|
GameID int32 `json:"GameID"`
|
||||||
CreatedAt int64 `json:"CreatedAt"`
|
CreatedAt int64 `json:"CreatedAt"`
|
||||||
UpdatedAt int64 `json:"UpdatedAt"`
|
UpdatedAt int64 `json:"UpdatedAt"`
|
||||||
Submitter int64 `json:"Submitter"`
|
Submitter int64 `json:"Submitter"`
|
||||||
AssetID int64 `json:"AssetID"`
|
AssetID int64 `json:"AssetID"`
|
||||||
AssetVersion int64 `json:"AssetVersion"`
|
AssetVersion int64 `json:"AssetVersion"`
|
||||||
Completed bool `json:"Completed"`
|
ValidatedAssetID OptInt64 `json:"ValidatedAssetID"`
|
||||||
TargetAssetID int64 `json:"TargetAssetID"`
|
ValidatedAssetVersion OptInt64 `json:"ValidatedAssetVersion"`
|
||||||
StatusID int32 `json:"StatusID"`
|
Completed bool `json:"Completed"`
|
||||||
Description string `json:"Description"`
|
TargetAssetID int64 `json:"TargetAssetID"`
|
||||||
|
StatusID int32 `json:"StatusID"`
|
||||||
|
Description string `json:"Description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetID returns the value of ID.
|
// GetID returns the value of ID.
|
||||||
@@ -516,6 +899,16 @@ func (s *Mapfix) GetAssetVersion() int64 {
|
|||||||
return s.AssetVersion
|
return s.AssetVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetValidatedAssetID returns the value of ValidatedAssetID.
|
||||||
|
func (s *Mapfix) GetValidatedAssetID() OptInt64 {
|
||||||
|
return s.ValidatedAssetID
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetValidatedAssetVersion returns the value of ValidatedAssetVersion.
|
||||||
|
func (s *Mapfix) GetValidatedAssetVersion() OptInt64 {
|
||||||
|
return s.ValidatedAssetVersion
|
||||||
|
}
|
||||||
|
|
||||||
// GetCompleted returns the value of Completed.
|
// GetCompleted returns the value of Completed.
|
||||||
func (s *Mapfix) GetCompleted() bool {
|
func (s *Mapfix) GetCompleted() bool {
|
||||||
return s.Completed
|
return s.Completed
|
||||||
@@ -581,6 +974,16 @@ func (s *Mapfix) SetAssetVersion(val int64) {
|
|||||||
s.AssetVersion = val
|
s.AssetVersion = val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetValidatedAssetID sets the value of ValidatedAssetID.
|
||||||
|
func (s *Mapfix) SetValidatedAssetID(val OptInt64) {
|
||||||
|
s.ValidatedAssetID = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetValidatedAssetVersion sets the value of ValidatedAssetVersion.
|
||||||
|
func (s *Mapfix) SetValidatedAssetVersion(val OptInt64) {
|
||||||
|
s.ValidatedAssetVersion = val
|
||||||
|
}
|
||||||
|
|
||||||
// SetCompleted sets the value of Completed.
|
// SetCompleted sets the value of Completed.
|
||||||
func (s *Mapfix) SetCompleted(val bool) {
|
func (s *Mapfix) SetCompleted(val bool) {
|
||||||
s.Completed = val
|
s.Completed = val
|
||||||
@@ -749,6 +1152,328 @@ func (s *OperationID) SetOperationID(val int32) {
|
|||||||
s.OperationID = val
|
s.OperationID = val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewOptBatchAssetThumbnailsOKThumbnails returns new OptBatchAssetThumbnailsOKThumbnails with value set to v.
|
||||||
|
func NewOptBatchAssetThumbnailsOKThumbnails(v BatchAssetThumbnailsOKThumbnails) OptBatchAssetThumbnailsOKThumbnails {
|
||||||
|
return OptBatchAssetThumbnailsOKThumbnails{
|
||||||
|
Value: v,
|
||||||
|
Set: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptBatchAssetThumbnailsOKThumbnails is optional BatchAssetThumbnailsOKThumbnails.
|
||||||
|
type OptBatchAssetThumbnailsOKThumbnails struct {
|
||||||
|
Value BatchAssetThumbnailsOKThumbnails
|
||||||
|
Set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns true if OptBatchAssetThumbnailsOKThumbnails was set.
|
||||||
|
func (o OptBatchAssetThumbnailsOKThumbnails) IsSet() bool { return o.Set }
|
||||||
|
|
||||||
|
// Reset unsets value.
|
||||||
|
func (o *OptBatchAssetThumbnailsOKThumbnails) Reset() {
|
||||||
|
var v BatchAssetThumbnailsOKThumbnails
|
||||||
|
o.Value = v
|
||||||
|
o.Set = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo sets value to v.
|
||||||
|
func (o *OptBatchAssetThumbnailsOKThumbnails) SetTo(v BatchAssetThumbnailsOKThumbnails) {
|
||||||
|
o.Set = true
|
||||||
|
o.Value = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns value and boolean that denotes whether value was set.
|
||||||
|
func (o OptBatchAssetThumbnailsOKThumbnails) Get() (v BatchAssetThumbnailsOKThumbnails, ok bool) {
|
||||||
|
if !o.Set {
|
||||||
|
return v, false
|
||||||
|
}
|
||||||
|
return o.Value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns value if set, or given parameter if does not.
|
||||||
|
func (o OptBatchAssetThumbnailsOKThumbnails) Or(d BatchAssetThumbnailsOKThumbnails) BatchAssetThumbnailsOKThumbnails {
|
||||||
|
if v, ok := o.Get(); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOptBatchAssetThumbnailsReqSize returns new OptBatchAssetThumbnailsReqSize with value set to v.
|
||||||
|
func NewOptBatchAssetThumbnailsReqSize(v BatchAssetThumbnailsReqSize) OptBatchAssetThumbnailsReqSize {
|
||||||
|
return OptBatchAssetThumbnailsReqSize{
|
||||||
|
Value: v,
|
||||||
|
Set: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptBatchAssetThumbnailsReqSize is optional BatchAssetThumbnailsReqSize.
|
||||||
|
type OptBatchAssetThumbnailsReqSize struct {
|
||||||
|
Value BatchAssetThumbnailsReqSize
|
||||||
|
Set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns true if OptBatchAssetThumbnailsReqSize was set.
|
||||||
|
func (o OptBatchAssetThumbnailsReqSize) IsSet() bool { return o.Set }
|
||||||
|
|
||||||
|
// Reset unsets value.
|
||||||
|
func (o *OptBatchAssetThumbnailsReqSize) Reset() {
|
||||||
|
var v BatchAssetThumbnailsReqSize
|
||||||
|
o.Value = v
|
||||||
|
o.Set = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo sets value to v.
|
||||||
|
func (o *OptBatchAssetThumbnailsReqSize) SetTo(v BatchAssetThumbnailsReqSize) {
|
||||||
|
o.Set = true
|
||||||
|
o.Value = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns value and boolean that denotes whether value was set.
|
||||||
|
func (o OptBatchAssetThumbnailsReqSize) Get() (v BatchAssetThumbnailsReqSize, ok bool) {
|
||||||
|
if !o.Set {
|
||||||
|
return v, false
|
||||||
|
}
|
||||||
|
return o.Value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns value if set, or given parameter if does not.
|
||||||
|
func (o OptBatchAssetThumbnailsReqSize) Or(d BatchAssetThumbnailsReqSize) BatchAssetThumbnailsReqSize {
|
||||||
|
if v, ok := o.Get(); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOptBatchUserThumbnailsOKThumbnails returns new OptBatchUserThumbnailsOKThumbnails with value set to v.
|
||||||
|
func NewOptBatchUserThumbnailsOKThumbnails(v BatchUserThumbnailsOKThumbnails) OptBatchUserThumbnailsOKThumbnails {
|
||||||
|
return OptBatchUserThumbnailsOKThumbnails{
|
||||||
|
Value: v,
|
||||||
|
Set: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptBatchUserThumbnailsOKThumbnails is optional BatchUserThumbnailsOKThumbnails.
|
||||||
|
type OptBatchUserThumbnailsOKThumbnails struct {
|
||||||
|
Value BatchUserThumbnailsOKThumbnails
|
||||||
|
Set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns true if OptBatchUserThumbnailsOKThumbnails was set.
|
||||||
|
func (o OptBatchUserThumbnailsOKThumbnails) IsSet() bool { return o.Set }
|
||||||
|
|
||||||
|
// Reset unsets value.
|
||||||
|
func (o *OptBatchUserThumbnailsOKThumbnails) Reset() {
|
||||||
|
var v BatchUserThumbnailsOKThumbnails
|
||||||
|
o.Value = v
|
||||||
|
o.Set = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo sets value to v.
|
||||||
|
func (o *OptBatchUserThumbnailsOKThumbnails) SetTo(v BatchUserThumbnailsOKThumbnails) {
|
||||||
|
o.Set = true
|
||||||
|
o.Value = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns value and boolean that denotes whether value was set.
|
||||||
|
func (o OptBatchUserThumbnailsOKThumbnails) Get() (v BatchUserThumbnailsOKThumbnails, ok bool) {
|
||||||
|
if !o.Set {
|
||||||
|
return v, false
|
||||||
|
}
|
||||||
|
return o.Value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns value if set, or given parameter if does not.
|
||||||
|
func (o OptBatchUserThumbnailsOKThumbnails) Or(d BatchUserThumbnailsOKThumbnails) BatchUserThumbnailsOKThumbnails {
|
||||||
|
if v, ok := o.Get(); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOptBatchUserThumbnailsReqSize returns new OptBatchUserThumbnailsReqSize with value set to v.
|
||||||
|
func NewOptBatchUserThumbnailsReqSize(v BatchUserThumbnailsReqSize) OptBatchUserThumbnailsReqSize {
|
||||||
|
return OptBatchUserThumbnailsReqSize{
|
||||||
|
Value: v,
|
||||||
|
Set: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptBatchUserThumbnailsReqSize is optional BatchUserThumbnailsReqSize.
|
||||||
|
type OptBatchUserThumbnailsReqSize struct {
|
||||||
|
Value BatchUserThumbnailsReqSize
|
||||||
|
Set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns true if OptBatchUserThumbnailsReqSize was set.
|
||||||
|
func (o OptBatchUserThumbnailsReqSize) IsSet() bool { return o.Set }
|
||||||
|
|
||||||
|
// Reset unsets value.
|
||||||
|
func (o *OptBatchUserThumbnailsReqSize) Reset() {
|
||||||
|
var v BatchUserThumbnailsReqSize
|
||||||
|
o.Value = v
|
||||||
|
o.Set = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo sets value to v.
|
||||||
|
func (o *OptBatchUserThumbnailsReqSize) SetTo(v BatchUserThumbnailsReqSize) {
|
||||||
|
o.Set = true
|
||||||
|
o.Value = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns value and boolean that denotes whether value was set.
|
||||||
|
func (o OptBatchUserThumbnailsReqSize) Get() (v BatchUserThumbnailsReqSize, ok bool) {
|
||||||
|
if !o.Set {
|
||||||
|
return v, false
|
||||||
|
}
|
||||||
|
return o.Value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns value if set, or given parameter if does not.
|
||||||
|
func (o OptBatchUserThumbnailsReqSize) Or(d BatchUserThumbnailsReqSize) BatchUserThumbnailsReqSize {
|
||||||
|
if v, ok := o.Get(); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOptBatchUsernamesOKUsernames returns new OptBatchUsernamesOKUsernames with value set to v.
|
||||||
|
func NewOptBatchUsernamesOKUsernames(v BatchUsernamesOKUsernames) OptBatchUsernamesOKUsernames {
|
||||||
|
return OptBatchUsernamesOKUsernames{
|
||||||
|
Value: v,
|
||||||
|
Set: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptBatchUsernamesOKUsernames is optional BatchUsernamesOKUsernames.
|
||||||
|
type OptBatchUsernamesOKUsernames struct {
|
||||||
|
Value BatchUsernamesOKUsernames
|
||||||
|
Set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns true if OptBatchUsernamesOKUsernames was set.
|
||||||
|
func (o OptBatchUsernamesOKUsernames) IsSet() bool { return o.Set }
|
||||||
|
|
||||||
|
// Reset unsets value.
|
||||||
|
func (o *OptBatchUsernamesOKUsernames) Reset() {
|
||||||
|
var v BatchUsernamesOKUsernames
|
||||||
|
o.Value = v
|
||||||
|
o.Set = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo sets value to v.
|
||||||
|
func (o *OptBatchUsernamesOKUsernames) SetTo(v BatchUsernamesOKUsernames) {
|
||||||
|
o.Set = true
|
||||||
|
o.Value = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns value and boolean that denotes whether value was set.
|
||||||
|
func (o OptBatchUsernamesOKUsernames) Get() (v BatchUsernamesOKUsernames, ok bool) {
|
||||||
|
if !o.Set {
|
||||||
|
return v, false
|
||||||
|
}
|
||||||
|
return o.Value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns value if set, or given parameter if does not.
|
||||||
|
func (o OptBatchUsernamesOKUsernames) Or(d BatchUsernamesOKUsernames) BatchUsernamesOKUsernames {
|
||||||
|
if v, ok := o.Get(); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOptGetAssetThumbnailSize returns new OptGetAssetThumbnailSize with value set to v.
|
||||||
|
func NewOptGetAssetThumbnailSize(v GetAssetThumbnailSize) OptGetAssetThumbnailSize {
|
||||||
|
return OptGetAssetThumbnailSize{
|
||||||
|
Value: v,
|
||||||
|
Set: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptGetAssetThumbnailSize is optional GetAssetThumbnailSize.
|
||||||
|
type OptGetAssetThumbnailSize struct {
|
||||||
|
Value GetAssetThumbnailSize
|
||||||
|
Set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns true if OptGetAssetThumbnailSize was set.
|
||||||
|
func (o OptGetAssetThumbnailSize) IsSet() bool { return o.Set }
|
||||||
|
|
||||||
|
// Reset unsets value.
|
||||||
|
func (o *OptGetAssetThumbnailSize) Reset() {
|
||||||
|
var v GetAssetThumbnailSize
|
||||||
|
o.Value = v
|
||||||
|
o.Set = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo sets value to v.
|
||||||
|
func (o *OptGetAssetThumbnailSize) SetTo(v GetAssetThumbnailSize) {
|
||||||
|
o.Set = true
|
||||||
|
o.Value = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns value and boolean that denotes whether value was set.
|
||||||
|
func (o OptGetAssetThumbnailSize) Get() (v GetAssetThumbnailSize, ok bool) {
|
||||||
|
if !o.Set {
|
||||||
|
return v, false
|
||||||
|
}
|
||||||
|
return o.Value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns value if set, or given parameter if does not.
|
||||||
|
func (o OptGetAssetThumbnailSize) Or(d GetAssetThumbnailSize) GetAssetThumbnailSize {
|
||||||
|
if v, ok := o.Get(); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOptGetUserThumbnailSize returns new OptGetUserThumbnailSize with value set to v.
|
||||||
|
func NewOptGetUserThumbnailSize(v GetUserThumbnailSize) OptGetUserThumbnailSize {
|
||||||
|
return OptGetUserThumbnailSize{
|
||||||
|
Value: v,
|
||||||
|
Set: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptGetUserThumbnailSize is optional GetUserThumbnailSize.
|
||||||
|
type OptGetUserThumbnailSize struct {
|
||||||
|
Value GetUserThumbnailSize
|
||||||
|
Set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns true if OptGetUserThumbnailSize was set.
|
||||||
|
func (o OptGetUserThumbnailSize) IsSet() bool { return o.Set }
|
||||||
|
|
||||||
|
// Reset unsets value.
|
||||||
|
func (o *OptGetUserThumbnailSize) Reset() {
|
||||||
|
var v GetUserThumbnailSize
|
||||||
|
o.Value = v
|
||||||
|
o.Set = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo sets value to v.
|
||||||
|
func (o *OptGetUserThumbnailSize) SetTo(v GetUserThumbnailSize) {
|
||||||
|
o.Set = true
|
||||||
|
o.Value = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns value and boolean that denotes whether value was set.
|
||||||
|
func (o OptGetUserThumbnailSize) Get() (v GetUserThumbnailSize, ok bool) {
|
||||||
|
if !o.Set {
|
||||||
|
return v, false
|
||||||
|
}
|
||||||
|
return o.Value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns value if set, or given parameter if does not.
|
||||||
|
func (o OptGetUserThumbnailSize) Or(d GetUserThumbnailSize) GetUserThumbnailSize {
|
||||||
|
if v, ok := o.Get(); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
// NewOptInt32 returns new OptInt32 with value set to v.
|
// NewOptInt32 returns new OptInt32 with value set to v.
|
||||||
func NewOptInt32(v int32) OptInt32 {
|
func NewOptInt32(v int32) OptInt32 {
|
||||||
return OptInt32{
|
return OptInt32{
|
||||||
@@ -913,9 +1638,6 @@ func (s *ReleaseInfo) SetDate(val time.Time) {
|
|||||||
s.Date = val
|
s.Date = val
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReleaseSubmissionsCreated is response for ReleaseSubmissions operation.
|
|
||||||
type ReleaseSubmissionsCreated struct{}
|
|
||||||
|
|
||||||
// Ref: #/components/schemas/Roles
|
// Ref: #/components/schemas/Roles
|
||||||
type Roles struct {
|
type Roles struct {
|
||||||
Roles int32 `json:"Roles"`
|
Roles int32 `json:"Roles"`
|
||||||
@@ -1277,6 +1999,83 @@ type SetMapfixCompletedNoContent struct{}
|
|||||||
// SetSubmissionCompletedNoContent is response for SetSubmissionCompleted operation.
|
// SetSubmissionCompletedNoContent is response for SetSubmissionCompleted operation.
|
||||||
type SetSubmissionCompletedNoContent struct{}
|
type SetSubmissionCompletedNoContent struct{}
|
||||||
|
|
||||||
|
// Aggregate statistics for submissions and mapfixes.
|
||||||
|
// Ref: #/components/schemas/Stats
|
||||||
|
type Stats struct {
|
||||||
|
// Total number of submissions.
|
||||||
|
TotalSubmissions int64 `json:"TotalSubmissions"`
|
||||||
|
// Total number of mapfixes.
|
||||||
|
TotalMapfixes int64 `json:"TotalMapfixes"`
|
||||||
|
// Number of released submissions.
|
||||||
|
ReleasedSubmissions int64 `json:"ReleasedSubmissions"`
|
||||||
|
// Number of released mapfixes.
|
||||||
|
ReleasedMapfixes int64 `json:"ReleasedMapfixes"`
|
||||||
|
// Number of submissions under review.
|
||||||
|
SubmittedSubmissions int64 `json:"SubmittedSubmissions"`
|
||||||
|
// Number of mapfixes under review.
|
||||||
|
SubmittedMapfixes int64 `json:"SubmittedMapfixes"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTotalSubmissions returns the value of TotalSubmissions.
|
||||||
|
func (s *Stats) GetTotalSubmissions() int64 {
|
||||||
|
return s.TotalSubmissions
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTotalMapfixes returns the value of TotalMapfixes.
|
||||||
|
func (s *Stats) GetTotalMapfixes() int64 {
|
||||||
|
return s.TotalMapfixes
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetReleasedSubmissions returns the value of ReleasedSubmissions.
|
||||||
|
func (s *Stats) GetReleasedSubmissions() int64 {
|
||||||
|
return s.ReleasedSubmissions
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetReleasedMapfixes returns the value of ReleasedMapfixes.
|
||||||
|
func (s *Stats) GetReleasedMapfixes() int64 {
|
||||||
|
return s.ReleasedMapfixes
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSubmittedSubmissions returns the value of SubmittedSubmissions.
|
||||||
|
func (s *Stats) GetSubmittedSubmissions() int64 {
|
||||||
|
return s.SubmittedSubmissions
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSubmittedMapfixes returns the value of SubmittedMapfixes.
|
||||||
|
func (s *Stats) GetSubmittedMapfixes() int64 {
|
||||||
|
return s.SubmittedMapfixes
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTotalSubmissions sets the value of TotalSubmissions.
|
||||||
|
func (s *Stats) SetTotalSubmissions(val int64) {
|
||||||
|
s.TotalSubmissions = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTotalMapfixes sets the value of TotalMapfixes.
|
||||||
|
func (s *Stats) SetTotalMapfixes(val int64) {
|
||||||
|
s.TotalMapfixes = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetReleasedSubmissions sets the value of ReleasedSubmissions.
|
||||||
|
func (s *Stats) SetReleasedSubmissions(val int64) {
|
||||||
|
s.ReleasedSubmissions = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetReleasedMapfixes sets the value of ReleasedMapfixes.
|
||||||
|
func (s *Stats) SetReleasedMapfixes(val int64) {
|
||||||
|
s.ReleasedMapfixes = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSubmittedSubmissions sets the value of SubmittedSubmissions.
|
||||||
|
func (s *Stats) SetSubmittedSubmissions(val int64) {
|
||||||
|
s.SubmittedSubmissions = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSubmittedMapfixes sets the value of SubmittedMapfixes.
|
||||||
|
func (s *Stats) SetSubmittedMapfixes(val int64) {
|
||||||
|
s.SubmittedMapfixes = val
|
||||||
|
}
|
||||||
|
|
||||||
// Ref: #/components/schemas/Submission
|
// Ref: #/components/schemas/Submission
|
||||||
type Submission struct {
|
type Submission struct {
|
||||||
ID int64 `json:"ID"`
|
ID int64 `json:"ID"`
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-faster/errors"
|
"github.com/go-faster/errors"
|
||||||
|
|
||||||
"github.com/ogen-go/ogen/ogenerrors"
|
"github.com/ogen-go/ogen/ogenerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,10 +39,12 @@ var operationRolesCookieAuth = map[string][]string{
|
|||||||
ActionMapfixResetSubmittingOperation: []string{},
|
ActionMapfixResetSubmittingOperation: []string{},
|
||||||
ActionMapfixRetryValidateOperation: []string{},
|
ActionMapfixRetryValidateOperation: []string{},
|
||||||
ActionMapfixRevokeOperation: []string{},
|
ActionMapfixRevokeOperation: []string{},
|
||||||
|
ActionMapfixTriggerReleaseOperation: []string{},
|
||||||
ActionMapfixTriggerSubmitOperation: []string{},
|
ActionMapfixTriggerSubmitOperation: []string{},
|
||||||
ActionMapfixTriggerSubmitUncheckedOperation: []string{},
|
ActionMapfixTriggerSubmitUncheckedOperation: []string{},
|
||||||
ActionMapfixTriggerUploadOperation: []string{},
|
ActionMapfixTriggerUploadOperation: []string{},
|
||||||
ActionMapfixTriggerValidateOperation: []string{},
|
ActionMapfixTriggerValidateOperation: []string{},
|
||||||
|
ActionMapfixUploadedOperation: []string{},
|
||||||
ActionMapfixValidatedOperation: []string{},
|
ActionMapfixValidatedOperation: []string{},
|
||||||
ActionSubmissionAcceptedOperation: []string{},
|
ActionSubmissionAcceptedOperation: []string{},
|
||||||
ActionSubmissionRejectOperation: []string{},
|
ActionSubmissionRejectOperation: []string{},
|
||||||
|
|||||||
@@ -45,6 +45,12 @@ type Handler interface {
|
|||||||
//
|
//
|
||||||
// POST /mapfixes/{MapfixID}/status/revoke
|
// POST /mapfixes/{MapfixID}/status/revoke
|
||||||
ActionMapfixRevoke(ctx context.Context, params ActionMapfixRevokeParams) error
|
ActionMapfixRevoke(ctx context.Context, params ActionMapfixRevokeParams) error
|
||||||
|
// ActionMapfixTriggerRelease implements actionMapfixTriggerRelease operation.
|
||||||
|
//
|
||||||
|
// Role MapfixUpload changes status from Uploaded -> Releasing.
|
||||||
|
//
|
||||||
|
// POST /mapfixes/{MapfixID}/status/trigger-release
|
||||||
|
ActionMapfixTriggerRelease(ctx context.Context, params ActionMapfixTriggerReleaseParams) error
|
||||||
// ActionMapfixTriggerSubmit implements actionMapfixTriggerSubmit operation.
|
// ActionMapfixTriggerSubmit implements actionMapfixTriggerSubmit operation.
|
||||||
//
|
//
|
||||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting.
|
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting.
|
||||||
@@ -59,7 +65,7 @@ type Handler interface {
|
|||||||
ActionMapfixTriggerSubmitUnchecked(ctx context.Context, params ActionMapfixTriggerSubmitUncheckedParams) error
|
ActionMapfixTriggerSubmitUnchecked(ctx context.Context, params ActionMapfixTriggerSubmitUncheckedParams) error
|
||||||
// ActionMapfixTriggerUpload implements actionMapfixTriggerUpload operation.
|
// ActionMapfixTriggerUpload implements actionMapfixTriggerUpload operation.
|
||||||
//
|
//
|
||||||
// Role Admin changes status from Validated -> Uploading.
|
// Role MapfixUpload changes status from Validated -> Uploading.
|
||||||
//
|
//
|
||||||
// POST /mapfixes/{MapfixID}/status/trigger-upload
|
// POST /mapfixes/{MapfixID}/status/trigger-upload
|
||||||
ActionMapfixTriggerUpload(ctx context.Context, params ActionMapfixTriggerUploadParams) error
|
ActionMapfixTriggerUpload(ctx context.Context, params ActionMapfixTriggerUploadParams) error
|
||||||
@@ -69,9 +75,15 @@ type Handler interface {
|
|||||||
//
|
//
|
||||||
// POST /mapfixes/{MapfixID}/status/trigger-validate
|
// POST /mapfixes/{MapfixID}/status/trigger-validate
|
||||||
ActionMapfixTriggerValidate(ctx context.Context, params ActionMapfixTriggerValidateParams) error
|
ActionMapfixTriggerValidate(ctx context.Context, params ActionMapfixTriggerValidateParams) error
|
||||||
|
// ActionMapfixUploaded implements actionMapfixUploaded operation.
|
||||||
|
//
|
||||||
|
// Role MapfixUpload manually resets releasing softlock and changes status from Releasing -> Uploaded.
|
||||||
|
//
|
||||||
|
// POST /mapfixes/{MapfixID}/status/reset-releasing
|
||||||
|
ActionMapfixUploaded(ctx context.Context, params ActionMapfixUploadedParams) error
|
||||||
// ActionMapfixValidated implements actionMapfixValidated operation.
|
// ActionMapfixValidated implements actionMapfixValidated operation.
|
||||||
//
|
//
|
||||||
// Role Admin manually resets uploading softlock and changes status from Uploading -> Validated.
|
// Role MapfixUpload manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||||
//
|
//
|
||||||
// POST /mapfixes/{MapfixID}/status/reset-uploading
|
// POST /mapfixes/{MapfixID}/status/reset-uploading
|
||||||
ActionMapfixValidated(ctx context.Context, params ActionMapfixValidatedParams) error
|
ActionMapfixValidated(ctx context.Context, params ActionMapfixValidatedParams) error
|
||||||
@@ -126,7 +138,7 @@ type Handler interface {
|
|||||||
ActionSubmissionTriggerSubmitUnchecked(ctx context.Context, params ActionSubmissionTriggerSubmitUncheckedParams) error
|
ActionSubmissionTriggerSubmitUnchecked(ctx context.Context, params ActionSubmissionTriggerSubmitUncheckedParams) error
|
||||||
// ActionSubmissionTriggerUpload implements actionSubmissionTriggerUpload operation.
|
// ActionSubmissionTriggerUpload implements actionSubmissionTriggerUpload operation.
|
||||||
//
|
//
|
||||||
// Role Admin changes status from Validated -> Uploading.
|
// Role SubmissionUpload changes status from Validated -> Uploading.
|
||||||
//
|
//
|
||||||
// POST /submissions/{SubmissionID}/status/trigger-upload
|
// POST /submissions/{SubmissionID}/status/trigger-upload
|
||||||
ActionSubmissionTriggerUpload(ctx context.Context, params ActionSubmissionTriggerUploadParams) error
|
ActionSubmissionTriggerUpload(ctx context.Context, params ActionSubmissionTriggerUploadParams) error
|
||||||
@@ -138,10 +150,29 @@ type Handler interface {
|
|||||||
ActionSubmissionTriggerValidate(ctx context.Context, params ActionSubmissionTriggerValidateParams) error
|
ActionSubmissionTriggerValidate(ctx context.Context, params ActionSubmissionTriggerValidateParams) error
|
||||||
// ActionSubmissionValidated implements actionSubmissionValidated operation.
|
// ActionSubmissionValidated implements actionSubmissionValidated operation.
|
||||||
//
|
//
|
||||||
// Role Admin manually resets uploading softlock and changes status from Uploading -> Validated.
|
// Role SubmissionUpload manually resets uploading softlock and changes status from Uploading ->
|
||||||
|
// Validated.
|
||||||
//
|
//
|
||||||
// POST /submissions/{SubmissionID}/status/reset-uploading
|
// POST /submissions/{SubmissionID}/status/reset-uploading
|
||||||
ActionSubmissionValidated(ctx context.Context, params ActionSubmissionValidatedParams) error
|
ActionSubmissionValidated(ctx context.Context, params ActionSubmissionValidatedParams) error
|
||||||
|
// BatchAssetThumbnails implements batchAssetThumbnails operation.
|
||||||
|
//
|
||||||
|
// Batch fetch asset thumbnails.
|
||||||
|
//
|
||||||
|
// POST /thumbnails/assets
|
||||||
|
BatchAssetThumbnails(ctx context.Context, req *BatchAssetThumbnailsReq) (*BatchAssetThumbnailsOK, error)
|
||||||
|
// BatchUserThumbnails implements batchUserThumbnails operation.
|
||||||
|
//
|
||||||
|
// Batch fetch user avatar thumbnails.
|
||||||
|
//
|
||||||
|
// POST /thumbnails/users
|
||||||
|
BatchUserThumbnails(ctx context.Context, req *BatchUserThumbnailsReq) (*BatchUserThumbnailsOK, error)
|
||||||
|
// BatchUsernames implements batchUsernames operation.
|
||||||
|
//
|
||||||
|
// Batch fetch usernames.
|
||||||
|
//
|
||||||
|
// POST /usernames
|
||||||
|
BatchUsernames(ctx context.Context, req *BatchUsernamesReq) (*BatchUsernamesOK, error)
|
||||||
// CreateMapfix implements createMapfix operation.
|
// CreateMapfix implements createMapfix operation.
|
||||||
//
|
//
|
||||||
// Trigger the validator to create a mapfix.
|
// Trigger the validator to create a mapfix.
|
||||||
@@ -202,6 +233,12 @@ type Handler interface {
|
|||||||
//
|
//
|
||||||
// GET /maps/{MapID}/download
|
// GET /maps/{MapID}/download
|
||||||
DownloadMapAsset(ctx context.Context, params DownloadMapAssetParams) (DownloadMapAssetOK, error)
|
DownloadMapAsset(ctx context.Context, params DownloadMapAssetParams) (DownloadMapAssetOK, error)
|
||||||
|
// GetAssetThumbnail implements getAssetThumbnail operation.
|
||||||
|
//
|
||||||
|
// Get single asset thumbnail.
|
||||||
|
//
|
||||||
|
// GET /thumbnails/asset/{AssetID}
|
||||||
|
GetAssetThumbnail(ctx context.Context, params GetAssetThumbnailParams) (*GetAssetThumbnailFound, error)
|
||||||
// GetMap implements getMap operation.
|
// GetMap implements getMap operation.
|
||||||
//
|
//
|
||||||
// Retrieve map with ID.
|
// Retrieve map with ID.
|
||||||
@@ -232,12 +269,24 @@ type Handler interface {
|
|||||||
//
|
//
|
||||||
// GET /script-policy/{ScriptPolicyID}
|
// GET /script-policy/{ScriptPolicyID}
|
||||||
GetScriptPolicy(ctx context.Context, params GetScriptPolicyParams) (*ScriptPolicy, error)
|
GetScriptPolicy(ctx context.Context, params GetScriptPolicyParams) (*ScriptPolicy, error)
|
||||||
|
// GetStats implements getStats operation.
|
||||||
|
//
|
||||||
|
// Get aggregate statistics.
|
||||||
|
//
|
||||||
|
// GET /stats
|
||||||
|
GetStats(ctx context.Context) (*Stats, error)
|
||||||
// GetSubmission implements getSubmission operation.
|
// GetSubmission implements getSubmission operation.
|
||||||
//
|
//
|
||||||
// Retrieve map with ID.
|
// Retrieve map with ID.
|
||||||
//
|
//
|
||||||
// GET /submissions/{SubmissionID}
|
// GET /submissions/{SubmissionID}
|
||||||
GetSubmission(ctx context.Context, params GetSubmissionParams) (*Submission, error)
|
GetSubmission(ctx context.Context, params GetSubmissionParams) (*Submission, error)
|
||||||
|
// GetUserThumbnail implements getUserThumbnail operation.
|
||||||
|
//
|
||||||
|
// Get single user avatar thumbnail.
|
||||||
|
//
|
||||||
|
// GET /thumbnails/user/{UserID}
|
||||||
|
GetUserThumbnail(ctx context.Context, params GetUserThumbnailParams) (*GetUserThumbnailFound, error)
|
||||||
// ListMapfixAuditEvents implements listMapfixAuditEvents operation.
|
// ListMapfixAuditEvents implements listMapfixAuditEvents operation.
|
||||||
//
|
//
|
||||||
// Retrieve a list of audit events.
|
// Retrieve a list of audit events.
|
||||||
@@ -282,10 +331,10 @@ type Handler interface {
|
|||||||
ListSubmissions(ctx context.Context, params ListSubmissionsParams) (*Submissions, error)
|
ListSubmissions(ctx context.Context, params ListSubmissionsParams) (*Submissions, error)
|
||||||
// ReleaseSubmissions implements releaseSubmissions operation.
|
// ReleaseSubmissions implements releaseSubmissions operation.
|
||||||
//
|
//
|
||||||
// Release a set of uploaded maps.
|
// Release a set of uploaded maps. Role SubmissionRelease.
|
||||||
//
|
//
|
||||||
// POST /release-submissions
|
// POST /release-submissions
|
||||||
ReleaseSubmissions(ctx context.Context, req []ReleaseInfo) error
|
ReleaseSubmissions(ctx context.Context, req []ReleaseInfo) (*OperationID, error)
|
||||||
// SessionRoles implements sessionRoles operation.
|
// SessionRoles implements sessionRoles operation.
|
||||||
//
|
//
|
||||||
// Get list of roles for the current session.
|
// Get list of roles for the current session.
|
||||||
|
|||||||
@@ -68,6 +68,15 @@ func (UnimplementedHandler) ActionMapfixRevoke(ctx context.Context, params Actio
|
|||||||
return ht.ErrNotImplemented
|
return ht.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActionMapfixTriggerRelease implements actionMapfixTriggerRelease operation.
|
||||||
|
//
|
||||||
|
// Role MapfixUpload changes status from Uploaded -> Releasing.
|
||||||
|
//
|
||||||
|
// POST /mapfixes/{MapfixID}/status/trigger-release
|
||||||
|
func (UnimplementedHandler) ActionMapfixTriggerRelease(ctx context.Context, params ActionMapfixTriggerReleaseParams) error {
|
||||||
|
return ht.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
// ActionMapfixTriggerSubmit implements actionMapfixTriggerSubmit operation.
|
// ActionMapfixTriggerSubmit implements actionMapfixTriggerSubmit operation.
|
||||||
//
|
//
|
||||||
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting.
|
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitting.
|
||||||
@@ -88,7 +97,7 @@ func (UnimplementedHandler) ActionMapfixTriggerSubmitUnchecked(ctx context.Conte
|
|||||||
|
|
||||||
// ActionMapfixTriggerUpload implements actionMapfixTriggerUpload operation.
|
// ActionMapfixTriggerUpload implements actionMapfixTriggerUpload operation.
|
||||||
//
|
//
|
||||||
// Role Admin changes status from Validated -> Uploading.
|
// Role MapfixUpload changes status from Validated -> Uploading.
|
||||||
//
|
//
|
||||||
// POST /mapfixes/{MapfixID}/status/trigger-upload
|
// POST /mapfixes/{MapfixID}/status/trigger-upload
|
||||||
func (UnimplementedHandler) ActionMapfixTriggerUpload(ctx context.Context, params ActionMapfixTriggerUploadParams) error {
|
func (UnimplementedHandler) ActionMapfixTriggerUpload(ctx context.Context, params ActionMapfixTriggerUploadParams) error {
|
||||||
@@ -104,9 +113,18 @@ func (UnimplementedHandler) ActionMapfixTriggerValidate(ctx context.Context, par
|
|||||||
return ht.ErrNotImplemented
|
return ht.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActionMapfixUploaded implements actionMapfixUploaded operation.
|
||||||
|
//
|
||||||
|
// Role MapfixUpload manually resets releasing softlock and changes status from Releasing -> Uploaded.
|
||||||
|
//
|
||||||
|
// POST /mapfixes/{MapfixID}/status/reset-releasing
|
||||||
|
func (UnimplementedHandler) ActionMapfixUploaded(ctx context.Context, params ActionMapfixUploadedParams) error {
|
||||||
|
return ht.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
// ActionMapfixValidated implements actionMapfixValidated operation.
|
// ActionMapfixValidated implements actionMapfixValidated operation.
|
||||||
//
|
//
|
||||||
// Role Admin manually resets uploading softlock and changes status from Uploading -> Validated.
|
// Role MapfixUpload manually resets uploading softlock and changes status from Uploading -> Validated.
|
||||||
//
|
//
|
||||||
// POST /mapfixes/{MapfixID}/status/reset-uploading
|
// POST /mapfixes/{MapfixID}/status/reset-uploading
|
||||||
func (UnimplementedHandler) ActionMapfixValidated(ctx context.Context, params ActionMapfixValidatedParams) error {
|
func (UnimplementedHandler) ActionMapfixValidated(ctx context.Context, params ActionMapfixValidatedParams) error {
|
||||||
@@ -188,7 +206,7 @@ func (UnimplementedHandler) ActionSubmissionTriggerSubmitUnchecked(ctx context.C
|
|||||||
|
|
||||||
// ActionSubmissionTriggerUpload implements actionSubmissionTriggerUpload operation.
|
// ActionSubmissionTriggerUpload implements actionSubmissionTriggerUpload operation.
|
||||||
//
|
//
|
||||||
// Role Admin changes status from Validated -> Uploading.
|
// Role SubmissionUpload changes status from Validated -> Uploading.
|
||||||
//
|
//
|
||||||
// POST /submissions/{SubmissionID}/status/trigger-upload
|
// POST /submissions/{SubmissionID}/status/trigger-upload
|
||||||
func (UnimplementedHandler) ActionSubmissionTriggerUpload(ctx context.Context, params ActionSubmissionTriggerUploadParams) error {
|
func (UnimplementedHandler) ActionSubmissionTriggerUpload(ctx context.Context, params ActionSubmissionTriggerUploadParams) error {
|
||||||
@@ -206,13 +224,41 @@ func (UnimplementedHandler) ActionSubmissionTriggerValidate(ctx context.Context,
|
|||||||
|
|
||||||
// ActionSubmissionValidated implements actionSubmissionValidated operation.
|
// ActionSubmissionValidated implements actionSubmissionValidated operation.
|
||||||
//
|
//
|
||||||
// Role Admin manually resets uploading softlock and changes status from Uploading -> Validated.
|
// Role SubmissionUpload manually resets uploading softlock and changes status from Uploading ->
|
||||||
|
// Validated.
|
||||||
//
|
//
|
||||||
// POST /submissions/{SubmissionID}/status/reset-uploading
|
// POST /submissions/{SubmissionID}/status/reset-uploading
|
||||||
func (UnimplementedHandler) ActionSubmissionValidated(ctx context.Context, params ActionSubmissionValidatedParams) error {
|
func (UnimplementedHandler) ActionSubmissionValidated(ctx context.Context, params ActionSubmissionValidatedParams) error {
|
||||||
return ht.ErrNotImplemented
|
return ht.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BatchAssetThumbnails implements batchAssetThumbnails operation.
|
||||||
|
//
|
||||||
|
// Batch fetch asset thumbnails.
|
||||||
|
//
|
||||||
|
// POST /thumbnails/assets
|
||||||
|
func (UnimplementedHandler) BatchAssetThumbnails(ctx context.Context, req *BatchAssetThumbnailsReq) (r *BatchAssetThumbnailsOK, _ error) {
|
||||||
|
return r, ht.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
// BatchUserThumbnails implements batchUserThumbnails operation.
|
||||||
|
//
|
||||||
|
// Batch fetch user avatar thumbnails.
|
||||||
|
//
|
||||||
|
// POST /thumbnails/users
|
||||||
|
func (UnimplementedHandler) BatchUserThumbnails(ctx context.Context, req *BatchUserThumbnailsReq) (r *BatchUserThumbnailsOK, _ error) {
|
||||||
|
return r, ht.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
// BatchUsernames implements batchUsernames operation.
|
||||||
|
//
|
||||||
|
// Batch fetch usernames.
|
||||||
|
//
|
||||||
|
// POST /usernames
|
||||||
|
func (UnimplementedHandler) BatchUsernames(ctx context.Context, req *BatchUsernamesReq) (r *BatchUsernamesOK, _ error) {
|
||||||
|
return r, ht.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
// CreateMapfix implements createMapfix operation.
|
// CreateMapfix implements createMapfix operation.
|
||||||
//
|
//
|
||||||
// Trigger the validator to create a mapfix.
|
// Trigger the validator to create a mapfix.
|
||||||
@@ -303,6 +349,15 @@ func (UnimplementedHandler) DownloadMapAsset(ctx context.Context, params Downloa
|
|||||||
return r, ht.ErrNotImplemented
|
return r, ht.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAssetThumbnail implements getAssetThumbnail operation.
|
||||||
|
//
|
||||||
|
// Get single asset thumbnail.
|
||||||
|
//
|
||||||
|
// GET /thumbnails/asset/{AssetID}
|
||||||
|
func (UnimplementedHandler) GetAssetThumbnail(ctx context.Context, params GetAssetThumbnailParams) (r *GetAssetThumbnailFound, _ error) {
|
||||||
|
return r, ht.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
// GetMap implements getMap operation.
|
// GetMap implements getMap operation.
|
||||||
//
|
//
|
||||||
// Retrieve map with ID.
|
// Retrieve map with ID.
|
||||||
@@ -348,6 +403,15 @@ func (UnimplementedHandler) GetScriptPolicy(ctx context.Context, params GetScrip
|
|||||||
return r, ht.ErrNotImplemented
|
return r, ht.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetStats implements getStats operation.
|
||||||
|
//
|
||||||
|
// Get aggregate statistics.
|
||||||
|
//
|
||||||
|
// GET /stats
|
||||||
|
func (UnimplementedHandler) GetStats(ctx context.Context) (r *Stats, _ error) {
|
||||||
|
return r, ht.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
// GetSubmission implements getSubmission operation.
|
// GetSubmission implements getSubmission operation.
|
||||||
//
|
//
|
||||||
// Retrieve map with ID.
|
// Retrieve map with ID.
|
||||||
@@ -357,6 +421,15 @@ func (UnimplementedHandler) GetSubmission(ctx context.Context, params GetSubmiss
|
|||||||
return r, ht.ErrNotImplemented
|
return r, ht.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUserThumbnail implements getUserThumbnail operation.
|
||||||
|
//
|
||||||
|
// Get single user avatar thumbnail.
|
||||||
|
//
|
||||||
|
// GET /thumbnails/user/{UserID}
|
||||||
|
func (UnimplementedHandler) GetUserThumbnail(ctx context.Context, params GetUserThumbnailParams) (r *GetUserThumbnailFound, _ error) {
|
||||||
|
return r, ht.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
// ListMapfixAuditEvents implements listMapfixAuditEvents operation.
|
// ListMapfixAuditEvents implements listMapfixAuditEvents operation.
|
||||||
//
|
//
|
||||||
// Retrieve a list of audit events.
|
// Retrieve a list of audit events.
|
||||||
@@ -422,11 +495,11 @@ func (UnimplementedHandler) ListSubmissions(ctx context.Context, params ListSubm
|
|||||||
|
|
||||||
// ReleaseSubmissions implements releaseSubmissions operation.
|
// ReleaseSubmissions implements releaseSubmissions operation.
|
||||||
//
|
//
|
||||||
// Release a set of uploaded maps.
|
// Release a set of uploaded maps. Role SubmissionRelease.
|
||||||
//
|
//
|
||||||
// POST /release-submissions
|
// POST /release-submissions
|
||||||
func (UnimplementedHandler) ReleaseSubmissions(ctx context.Context, req []ReleaseInfo) error {
|
func (UnimplementedHandler) ReleaseSubmissions(ctx context.Context, req []ReleaseInfo) (r *OperationID, _ error) {
|
||||||
return ht.ErrNotImplemented
|
return r, ht.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
// SessionRoles implements sessionRoles operation.
|
// SessionRoles implements sessionRoles operation.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,7 @@ import (
|
|||||||
"git.itzana.me/strafesnet/maps-service/pkg/validator_controller"
|
"git.itzana.me/strafesnet/maps-service/pkg/validator_controller"
|
||||||
"git.itzana.me/strafesnet/maps-service/pkg/web_api"
|
"git.itzana.me/strafesnet/maps-service/pkg/web_api"
|
||||||
"github.com/nats-io/nats.go"
|
"github.com/nats-io/nats.go"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
@@ -102,6 +103,24 @@ func NewServeCommand() *cli.Command {
|
|||||||
EnvVars: []string{"RBX_API_KEY"},
|
EnvVars: []string{"RBX_API_KEY"},
|
||||||
Required: true,
|
Required: true,
|
||||||
},
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "redis-host",
|
||||||
|
Usage: "Host of Redis cache",
|
||||||
|
EnvVars: []string{"REDIS_HOST"},
|
||||||
|
Value: "localhost:6379",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "redis-password",
|
||||||
|
Usage: "Password for Redis",
|
||||||
|
EnvVars: []string{"REDIS_PASSWORD"},
|
||||||
|
Value: "",
|
||||||
|
},
|
||||||
|
&cli.IntFlag{
|
||||||
|
Name: "redis-db",
|
||||||
|
Usage: "Redis database number",
|
||||||
|
EnvVars: []string{"REDIS_DB"},
|
||||||
|
Value: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,6 +148,24 @@ func serve(ctx *cli.Context) error {
|
|||||||
log.WithError(err).Fatal("failed to add stream")
|
log.WithError(err).Fatal("failed to add stream")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize Redis client
|
||||||
|
redisClient := redis.NewClient(&redis.Options{
|
||||||
|
Addr: ctx.String("redis-host"),
|
||||||
|
Password: ctx.String("redis-password"),
|
||||||
|
DB: ctx.Int("redis-db"),
|
||||||
|
})
|
||||||
|
|
||||||
|
// Test Redis connection
|
||||||
|
if err := redisClient.Ping(ctx.Context).Err(); err != nil {
|
||||||
|
log.WithError(err).Warn("failed to connect to Redis - thumbnails will not be cached")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize Roblox client
|
||||||
|
robloxClient := &roblox.Client{
|
||||||
|
HttpClient: http.DefaultClient,
|
||||||
|
ApiKey: ctx.String("rbx-api-key"),
|
||||||
|
}
|
||||||
|
|
||||||
// connect to main game database
|
// connect to main game database
|
||||||
conn, err := grpc.Dial(ctx.String("data-rpc-host"), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
conn, err := grpc.Dial(ctx.String("data-rpc-host"), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -139,13 +176,15 @@ func serve(ctx *cli.Context) error {
|
|||||||
js,
|
js,
|
||||||
maps.NewMapsServiceClient(conn),
|
maps.NewMapsServiceClient(conn),
|
||||||
users.NewUsersServiceClient(conn),
|
users.NewUsersServiceClient(conn),
|
||||||
|
robloxClient,
|
||||||
|
redisClient,
|
||||||
)
|
)
|
||||||
|
|
||||||
svc_external := web_api.NewService(
|
svc_external := web_api.NewService(
|
||||||
&svc_inner,
|
&svc_inner,
|
||||||
roblox.Client{
|
roblox.Client{
|
||||||
HttpClient: http.DefaultClient,
|
HttpClient: http.DefaultClient,
|
||||||
ApiKey: ctx.String("rbx-api-key"),
|
ApiKey: ctx.String("rbx-api-key"),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -18,10 +18,12 @@ const (
|
|||||||
MapfixStatusValidating MapfixStatus = 5
|
MapfixStatusValidating MapfixStatus = 5
|
||||||
MapfixStatusValidated MapfixStatus = 6
|
MapfixStatusValidated MapfixStatus = 6
|
||||||
MapfixStatusUploading MapfixStatus = 7
|
MapfixStatusUploading MapfixStatus = 7
|
||||||
|
MapfixStatusUploaded MapfixStatus = 8 // uploaded to the group, but pending release
|
||||||
|
MapfixStatusReleasing MapfixStatus = 11
|
||||||
|
|
||||||
// Phase: Final MapfixStatus
|
// Phase: Final MapfixStatus
|
||||||
MapfixStatusUploaded MapfixStatus = 8 // uploaded to the group, but pending release
|
|
||||||
MapfixStatusRejected MapfixStatus = 9
|
MapfixStatusRejected MapfixStatus = 9
|
||||||
|
MapfixStatusReleased MapfixStatus = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
type Mapfix struct {
|
type Mapfix struct {
|
||||||
|
|||||||
@@ -65,3 +65,29 @@ type UploadMapfixRequest struct {
|
|||||||
ModelVersion uint64
|
ModelVersion uint64
|
||||||
TargetAssetID uint64
|
TargetAssetID uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ReleaseSubmissionRequest struct {
|
||||||
|
// Release schedule
|
||||||
|
SubmissionID int64
|
||||||
|
ReleaseDate int64
|
||||||
|
// Model download info
|
||||||
|
ModelID uint64
|
||||||
|
ModelVersion uint64
|
||||||
|
// MapCreate
|
||||||
|
UploadedAssetID uint64
|
||||||
|
DisplayName string
|
||||||
|
Creator string
|
||||||
|
GameID uint32
|
||||||
|
Submitter uint64
|
||||||
|
}
|
||||||
|
type BatchReleaseSubmissionsRequest struct {
|
||||||
|
Submissions []ReleaseSubmissionRequest
|
||||||
|
OperationID int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReleaseMapfixRequest struct {
|
||||||
|
MapfixID int64
|
||||||
|
ModelID uint64
|
||||||
|
ModelVersion uint64
|
||||||
|
TargetAssetID uint64
|
||||||
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ func setupRoutes(cfg *RouterConfig) (*gin.Engine, error) {
|
|||||||
// Docs
|
// Docs
|
||||||
public_api.GET("/docs/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))
|
public_api.GET("/docs/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))
|
||||||
public_api.GET("/", func(ctx *gin.Context) {
|
public_api.GET("/", func(ctx *gin.Context) {
|
||||||
ctx.Redirect(http.StatusPermanentRedirect, "/docs/index.html")
|
ctx.Redirect(http.StatusPermanentRedirect, "/public-api/docs/index.html")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
160
pkg/roblox/thumbnails.go
Normal file
160
pkg/roblox/thumbnails.go
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
package roblox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ThumbnailSize represents valid Roblox thumbnail sizes
|
||||||
|
type ThumbnailSize string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Size150x150 ThumbnailSize = "150x150"
|
||||||
|
Size420x420 ThumbnailSize = "420x420"
|
||||||
|
Size768x432 ThumbnailSize = "768x432"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ThumbnailFormat represents the image format
|
||||||
|
type ThumbnailFormat string
|
||||||
|
|
||||||
|
const (
|
||||||
|
FormatPng ThumbnailFormat = "Png"
|
||||||
|
FormatJpeg ThumbnailFormat = "Jpeg"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ThumbnailRequest represents a single thumbnail request
|
||||||
|
type ThumbnailRequest struct {
|
||||||
|
RequestID string `json:"requestId,omitempty"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
TargetID uint64 `json:"targetId"`
|
||||||
|
Size string `json:"size,omitempty"`
|
||||||
|
Format string `json:"format,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ThumbnailData represents a single thumbnail response
|
||||||
|
type ThumbnailData struct {
|
||||||
|
TargetID uint64 `json:"targetId"`
|
||||||
|
State string `json:"state"` // "Completed", "Error", "Pending"
|
||||||
|
ImageURL string `json:"imageUrl"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BatchThumbnailsResponse represents the API response
|
||||||
|
type BatchThumbnailsResponse struct {
|
||||||
|
Data []ThumbnailData `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAssetThumbnails fetches thumbnails for multiple assets in a single batch request
|
||||||
|
// Roblox allows up to 100 assets per batch
|
||||||
|
func (c *Client) GetAssetThumbnails(assetIDs []uint64, size ThumbnailSize, format ThumbnailFormat) ([]ThumbnailData, error) {
|
||||||
|
if len(assetIDs) == 0 {
|
||||||
|
return []ThumbnailData{}, nil
|
||||||
|
}
|
||||||
|
if len(assetIDs) > 100 {
|
||||||
|
return nil, GetError("batch size cannot exceed 100 assets")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build request payload - the API expects an array directly, not wrapped in an object
|
||||||
|
requests := make([]ThumbnailRequest, len(assetIDs))
|
||||||
|
for i, assetID := range assetIDs {
|
||||||
|
requests[i] = ThumbnailRequest{
|
||||||
|
Type: "Asset",
|
||||||
|
TargetID: assetID,
|
||||||
|
Size: string(size),
|
||||||
|
Format: string(format),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonData, err := json.Marshal(requests)
|
||||||
|
if err != nil {
|
||||||
|
return nil, GetError("JSONMarshalError: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", "https://thumbnails.roblox.com/v1/batch", bytes.NewBuffer(jsonData))
|
||||||
|
if err != nil {
|
||||||
|
return nil, GetError("RequestCreationError: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
resp, err := c.HttpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, GetError("RequestError: " + err.Error())
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
body, _ := io.ReadAll(resp.Body)
|
||||||
|
return nil, GetError(fmt.Sprintf("ResponseError: status code %d, body: %s", resp.StatusCode, string(body)))
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, GetError("ReadBodyError: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
var response BatchThumbnailsResponse
|
||||||
|
if err := json.Unmarshal(body, &response); err != nil {
|
||||||
|
return nil, GetError("JSONUnmarshalError: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserAvatarThumbnails fetches avatar thumbnails for multiple users in a single batch request
|
||||||
|
func (c *Client) GetUserAvatarThumbnails(userIDs []uint64, size ThumbnailSize, format ThumbnailFormat) ([]ThumbnailData, error) {
|
||||||
|
if len(userIDs) == 0 {
|
||||||
|
return []ThumbnailData{}, nil
|
||||||
|
}
|
||||||
|
if len(userIDs) > 100 {
|
||||||
|
return nil, GetError("batch size cannot exceed 100 users")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build request payload - the API expects an array directly, not wrapped in an object
|
||||||
|
requests := make([]ThumbnailRequest, len(userIDs))
|
||||||
|
for i, userID := range userIDs {
|
||||||
|
requests[i] = ThumbnailRequest{
|
||||||
|
Type: "AvatarHeadShot",
|
||||||
|
TargetID: userID,
|
||||||
|
Size: string(size),
|
||||||
|
Format: string(format),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonData, err := json.Marshal(requests)
|
||||||
|
if err != nil {
|
||||||
|
return nil, GetError("JSONMarshalError: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", "https://thumbnails.roblox.com/v1/batch", bytes.NewBuffer(jsonData))
|
||||||
|
if err != nil {
|
||||||
|
return nil, GetError("RequestCreationError: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
resp, err := c.HttpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, GetError("RequestError: " + err.Error())
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
body, _ := io.ReadAll(resp.Body)
|
||||||
|
return nil, GetError(fmt.Sprintf("ResponseError: status code %d, body: %s", resp.StatusCode, string(body)))
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, GetError("ReadBodyError: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
var response BatchThumbnailsResponse
|
||||||
|
if err := json.Unmarshal(body, &response); err != nil {
|
||||||
|
return nil, GetError("JSONUnmarshalError: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Data, nil
|
||||||
|
}
|
||||||
72
pkg/roblox/users.go
Normal file
72
pkg/roblox/users.go
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
package roblox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UserData represents a single user's information
|
||||||
|
type UserData struct {
|
||||||
|
ID uint64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
DisplayName string `json:"displayName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BatchUsersResponse represents the API response for batch user requests
|
||||||
|
type BatchUsersResponse struct {
|
||||||
|
Data []UserData `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUsernames fetches usernames for multiple users in a single batch request
|
||||||
|
// Roblox allows up to 100 users per batch
|
||||||
|
func (c *Client) GetUsernames(userIDs []uint64) ([]UserData, error) {
|
||||||
|
if len(userIDs) == 0 {
|
||||||
|
return []UserData{}, nil
|
||||||
|
}
|
||||||
|
if len(userIDs) > 100 {
|
||||||
|
return nil, GetError("batch size cannot exceed 100 users")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build request payload
|
||||||
|
payload := map[string][]uint64{
|
||||||
|
"userIds": userIDs,
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonData, err := json.Marshal(payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, GetError("JSONMarshalError: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", "https://users.roblox.com/v1/users", bytes.NewBuffer(jsonData))
|
||||||
|
if err != nil {
|
||||||
|
return nil, GetError("RequestCreationError: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
resp, err := c.HttpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, GetError("RequestError: " + err.Error())
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
body, _ := io.ReadAll(resp.Body)
|
||||||
|
return nil, GetError(fmt.Sprintf("ResponseError: status code %d, body: %s", resp.StatusCode, string(body)))
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, GetError("ReadBodyError: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
var response BatchUsersResponse
|
||||||
|
if err := json.Unmarshal(body, &response); err != nil {
|
||||||
|
return nil, GetError("JSONUnmarshalError: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Data, nil
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
"git.itzana.me/strafesnet/go-grpc/maps"
|
"git.itzana.me/strafesnet/go-grpc/maps"
|
||||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||||
@@ -26,7 +27,7 @@ func (update MapUpdate) SetGameID(game_id uint32) {
|
|||||||
datastore.OptionalMap(update).Add("game_id", game_id)
|
datastore.OptionalMap(update).Add("game_id", game_id)
|
||||||
}
|
}
|
||||||
func (update MapUpdate) SetDate(date int64) {
|
func (update MapUpdate) SetDate(date int64) {
|
||||||
datastore.OptionalMap(update).Add("date", date)
|
datastore.OptionalMap(update).Add("date", time.Unix(date, 0))
|
||||||
}
|
}
|
||||||
func (update MapUpdate) SetSubmitter(submitter uint64) {
|
func (update MapUpdate) SetSubmitter(submitter uint64) {
|
||||||
datastore.OptionalMap(update).Add("submitter", submitter)
|
datastore.OptionalMap(update).Add("submitter", submitter)
|
||||||
|
|||||||
@@ -112,3 +112,29 @@ func (svc *Service) NatsValidateMapfix(
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (svc *Service) NatsReleaseMapfix(
|
||||||
|
MapfixID int64,
|
||||||
|
ModelID uint64,
|
||||||
|
ModelVersion uint64,
|
||||||
|
TargetAssetID uint64,
|
||||||
|
) error {
|
||||||
|
release_fix_request := model.ReleaseMapfixRequest{
|
||||||
|
MapfixID: MapfixID,
|
||||||
|
ModelID: ModelID,
|
||||||
|
ModelVersion: ModelVersion,
|
||||||
|
TargetAssetID: TargetAssetID,
|
||||||
|
}
|
||||||
|
|
||||||
|
j, err := json.Marshal(release_fix_request)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = svc.nats.Publish("maptest.mapfixes.release", []byte(j))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -88,6 +88,28 @@ func (svc *Service) NatsUploadSubmission(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (svc *Service) NatsBatchReleaseSubmissions(
|
||||||
|
Submissions []model.ReleaseSubmissionRequest,
|
||||||
|
operation int32,
|
||||||
|
) error {
|
||||||
|
release_new_request := model.BatchReleaseSubmissionsRequest{
|
||||||
|
Submissions: Submissions,
|
||||||
|
OperationID: operation,
|
||||||
|
}
|
||||||
|
|
||||||
|
j, err := json.Marshal(release_new_request)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = svc.nats.Publish("maptest.submissions.batchrelease", []byte(j))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (svc *Service) NatsValidateSubmission(
|
func (svc *Service) NatsValidateSubmission(
|
||||||
SubmissionID int64,
|
SubmissionID int64,
|
||||||
ModelID uint64,
|
ModelID uint64,
|
||||||
|
|||||||
@@ -1,17 +1,22 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"git.itzana.me/strafesnet/go-grpc/maps"
|
"git.itzana.me/strafesnet/go-grpc/maps"
|
||||||
"git.itzana.me/strafesnet/go-grpc/users"
|
"git.itzana.me/strafesnet/go-grpc/users"
|
||||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||||
|
"git.itzana.me/strafesnet/maps-service/pkg/roblox"
|
||||||
"github.com/nats-io/nats.go"
|
"github.com/nats-io/nats.go"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
db datastore.Datastore
|
db datastore.Datastore
|
||||||
nats nats.JetStreamContext
|
nats nats.JetStreamContext
|
||||||
maps maps.MapsServiceClient
|
maps maps.MapsServiceClient
|
||||||
users users.UsersServiceClient
|
users users.UsersServiceClient
|
||||||
|
thumbnailService *ThumbnailService
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(
|
func NewService(
|
||||||
@@ -19,11 +24,44 @@ func NewService(
|
|||||||
nats nats.JetStreamContext,
|
nats nats.JetStreamContext,
|
||||||
maps maps.MapsServiceClient,
|
maps maps.MapsServiceClient,
|
||||||
users users.UsersServiceClient,
|
users users.UsersServiceClient,
|
||||||
|
robloxClient *roblox.Client,
|
||||||
|
redisClient *redis.Client,
|
||||||
) Service {
|
) Service {
|
||||||
return Service{
|
return Service{
|
||||||
db: db,
|
db: db,
|
||||||
nats: nats,
|
nats: nats,
|
||||||
maps: maps,
|
maps: maps,
|
||||||
users: users,
|
users: users,
|
||||||
|
thumbnailService: NewThumbnailService(robloxClient, redisClient),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAssetThumbnails proxies to the thumbnail service
|
||||||
|
func (s *Service) GetAssetThumbnails(ctx context.Context, assetIDs []uint64, size roblox.ThumbnailSize) (map[uint64]string, error) {
|
||||||
|
return s.thumbnailService.GetAssetThumbnails(ctx, assetIDs, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserAvatarThumbnails proxies to the thumbnail service
|
||||||
|
func (s *Service) GetUserAvatarThumbnails(ctx context.Context, userIDs []uint64, size roblox.ThumbnailSize) (map[uint64]string, error) {
|
||||||
|
return s.thumbnailService.GetUserAvatarThumbnails(ctx, userIDs, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSingleAssetThumbnail proxies to the thumbnail service
|
||||||
|
func (s *Service) GetSingleAssetThumbnail(ctx context.Context, assetID uint64, size roblox.ThumbnailSize) (string, error) {
|
||||||
|
return s.thumbnailService.GetSingleAssetThumbnail(ctx, assetID, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSingleUserAvatarThumbnail proxies to the thumbnail service
|
||||||
|
func (s *Service) GetSingleUserAvatarThumbnail(ctx context.Context, userID uint64, size roblox.ThumbnailSize) (string, error) {
|
||||||
|
return s.thumbnailService.GetSingleUserAvatarThumbnail(ctx, userID, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUsernames proxies to the thumbnail service
|
||||||
|
func (s *Service) GetUsernames(ctx context.Context, userIDs []uint64) (map[uint64]string, error) {
|
||||||
|
return s.thumbnailService.GetUsernames(ctx, userIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSingleUsername proxies to the thumbnail service
|
||||||
|
func (s *Service) GetSingleUsername(ctx context.Context, userID uint64) (string, error) {
|
||||||
|
return s.thumbnailService.GetSingleUsername(ctx, userID)
|
||||||
|
}
|
||||||
|
|||||||
218
pkg/service/thumbnails.go
Normal file
218
pkg/service/thumbnails.go
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.itzana.me/strafesnet/maps-service/pkg/roblox"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ThumbnailService struct {
|
||||||
|
robloxClient *roblox.Client
|
||||||
|
redisClient *redis.Client
|
||||||
|
cacheTTL time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewThumbnailService(robloxClient *roblox.Client, redisClient *redis.Client) *ThumbnailService {
|
||||||
|
return &ThumbnailService{
|
||||||
|
robloxClient: robloxClient,
|
||||||
|
redisClient: redisClient,
|
||||||
|
cacheTTL: 24 * time.Hour, // Cache thumbnails for 24 hours
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CachedThumbnail represents a cached thumbnail entry
|
||||||
|
type CachedThumbnail struct {
|
||||||
|
ImageURL string `json:"imageUrl"`
|
||||||
|
State string `json:"state"`
|
||||||
|
CachedAt time.Time `json:"cachedAt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAssetThumbnails fetches thumbnails with Redis caching and batching
|
||||||
|
func (s *ThumbnailService) GetAssetThumbnails(ctx context.Context, assetIDs []uint64, size roblox.ThumbnailSize) (map[uint64]string, error) {
|
||||||
|
if len(assetIDs) == 0 {
|
||||||
|
return map[uint64]string{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make(map[uint64]string)
|
||||||
|
var missingIDs []uint64
|
||||||
|
|
||||||
|
// Try to get from cache first
|
||||||
|
for _, assetID := range assetIDs {
|
||||||
|
cacheKey := fmt.Sprintf("thumbnail:asset:%d:%s", assetID, size)
|
||||||
|
cached, err := s.redisClient.Get(ctx, cacheKey).Result()
|
||||||
|
|
||||||
|
if err == redis.Nil {
|
||||||
|
// Cache miss
|
||||||
|
missingIDs = append(missingIDs, assetID)
|
||||||
|
} else if err != nil {
|
||||||
|
// Redis error - treat as cache miss
|
||||||
|
missingIDs = append(missingIDs, assetID)
|
||||||
|
} else {
|
||||||
|
// Cache hit
|
||||||
|
var thumbnail CachedThumbnail
|
||||||
|
if err := json.Unmarshal([]byte(cached), &thumbnail); err == nil && thumbnail.State == "Completed" {
|
||||||
|
result[assetID] = thumbnail.ImageURL
|
||||||
|
} else {
|
||||||
|
missingIDs = append(missingIDs, assetID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all were cached, return early
|
||||||
|
if len(missingIDs) == 0 {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Batch fetch missing thumbnails from Roblox API
|
||||||
|
// Split into batches of 100 (Roblox API limit)
|
||||||
|
for i := 0; i < len(missingIDs); i += 100 {
|
||||||
|
end := i + 100
|
||||||
|
if end > len(missingIDs) {
|
||||||
|
end = len(missingIDs)
|
||||||
|
}
|
||||||
|
batch := missingIDs[i:end]
|
||||||
|
|
||||||
|
thumbnails, err := s.robloxClient.GetAssetThumbnails(batch, size, roblox.FormatPng)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to fetch thumbnails: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process results and cache them
|
||||||
|
for _, thumb := range thumbnails {
|
||||||
|
cached := CachedThumbnail{
|
||||||
|
ImageURL: thumb.ImageURL,
|
||||||
|
State: thumb.State,
|
||||||
|
CachedAt: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if thumb.State == "Completed" && thumb.ImageURL != "" {
|
||||||
|
result[thumb.TargetID] = thumb.ImageURL
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the result (even if incomplete, to avoid repeated API calls)
|
||||||
|
cacheKey := fmt.Sprintf("thumbnail:asset:%d:%s", thumb.TargetID, size)
|
||||||
|
cachedJSON, _ := json.Marshal(cached)
|
||||||
|
|
||||||
|
// Use shorter TTL for incomplete thumbnails
|
||||||
|
ttl := s.cacheTTL
|
||||||
|
if thumb.State != "Completed" {
|
||||||
|
ttl = 5 * time.Minute
|
||||||
|
}
|
||||||
|
|
||||||
|
s.redisClient.Set(ctx, cacheKey, cachedJSON, ttl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserAvatarThumbnails fetches user avatar thumbnails with Redis caching and batching
|
||||||
|
func (s *ThumbnailService) GetUserAvatarThumbnails(ctx context.Context, userIDs []uint64, size roblox.ThumbnailSize) (map[uint64]string, error) {
|
||||||
|
if len(userIDs) == 0 {
|
||||||
|
return map[uint64]string{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make(map[uint64]string)
|
||||||
|
var missingIDs []uint64
|
||||||
|
|
||||||
|
// Try to get from cache first
|
||||||
|
for _, userID := range userIDs {
|
||||||
|
cacheKey := fmt.Sprintf("thumbnail:user:%d:%s", userID, size)
|
||||||
|
cached, err := s.redisClient.Get(ctx, cacheKey).Result()
|
||||||
|
|
||||||
|
if err == redis.Nil {
|
||||||
|
// Cache miss
|
||||||
|
missingIDs = append(missingIDs, userID)
|
||||||
|
} else if err != nil {
|
||||||
|
// Redis error - treat as cache miss
|
||||||
|
missingIDs = append(missingIDs, userID)
|
||||||
|
} else {
|
||||||
|
// Cache hit
|
||||||
|
var thumbnail CachedThumbnail
|
||||||
|
if err := json.Unmarshal([]byte(cached), &thumbnail); err == nil && thumbnail.State == "Completed" {
|
||||||
|
result[userID] = thumbnail.ImageURL
|
||||||
|
} else {
|
||||||
|
missingIDs = append(missingIDs, userID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all were cached, return early
|
||||||
|
if len(missingIDs) == 0 {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Batch fetch missing thumbnails from Roblox API
|
||||||
|
// Split into batches of 100 (Roblox API limit)
|
||||||
|
for i := 0; i < len(missingIDs); i += 100 {
|
||||||
|
end := i + 100
|
||||||
|
if end > len(missingIDs) {
|
||||||
|
end = len(missingIDs)
|
||||||
|
}
|
||||||
|
batch := missingIDs[i:end]
|
||||||
|
|
||||||
|
thumbnails, err := s.robloxClient.GetUserAvatarThumbnails(batch, size, roblox.FormatPng)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to fetch user thumbnails: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process results and cache them
|
||||||
|
for _, thumb := range thumbnails {
|
||||||
|
cached := CachedThumbnail{
|
||||||
|
ImageURL: thumb.ImageURL,
|
||||||
|
State: thumb.State,
|
||||||
|
CachedAt: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if thumb.State == "Completed" && thumb.ImageURL != "" {
|
||||||
|
result[thumb.TargetID] = thumb.ImageURL
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the result
|
||||||
|
cacheKey := fmt.Sprintf("thumbnail:user:%d:%s", thumb.TargetID, size)
|
||||||
|
cachedJSON, _ := json.Marshal(cached)
|
||||||
|
|
||||||
|
// Use shorter TTL for incomplete thumbnails
|
||||||
|
ttl := s.cacheTTL
|
||||||
|
if thumb.State != "Completed" {
|
||||||
|
ttl = 5 * time.Minute
|
||||||
|
}
|
||||||
|
|
||||||
|
s.redisClient.Set(ctx, cacheKey, cachedJSON, ttl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSingleAssetThumbnail is a convenience method for fetching a single asset thumbnail
|
||||||
|
func (s *ThumbnailService) GetSingleAssetThumbnail(ctx context.Context, assetID uint64, size roblox.ThumbnailSize) (string, error) {
|
||||||
|
results, err := s.GetAssetThumbnails(ctx, []uint64{assetID}, size)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if url, ok := results[assetID]; ok {
|
||||||
|
return url, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("thumbnail not available for asset %d", assetID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSingleUserAvatarThumbnail is a convenience method for fetching a single user avatar thumbnail
|
||||||
|
func (s *ThumbnailService) GetSingleUserAvatarThumbnail(ctx context.Context, userID uint64, size roblox.ThumbnailSize) (string, error) {
|
||||||
|
results, err := s.GetUserAvatarThumbnails(ctx, []uint64{userID}, size)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if url, ok := results[userID]; ok {
|
||||||
|
return url, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("thumbnail not available for user %d", userID)
|
||||||
|
}
|
||||||
108
pkg/service/users.go
Normal file
108
pkg/service/users.go
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.itzana.me/strafesnet/maps-service/pkg/roblox"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CachedUser represents a cached user entry
|
||||||
|
type CachedUser struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
DisplayName string `json:"displayName"`
|
||||||
|
CachedAt time.Time `json:"cachedAt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUsernames fetches usernames with Redis caching and batching
|
||||||
|
func (s *ThumbnailService) GetUsernames(ctx context.Context, userIDs []uint64) (map[uint64]string, error) {
|
||||||
|
if len(userIDs) == 0 {
|
||||||
|
return map[uint64]string{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make(map[uint64]string)
|
||||||
|
var missingIDs []uint64
|
||||||
|
|
||||||
|
// Try to get from cache first
|
||||||
|
for _, userID := range userIDs {
|
||||||
|
cacheKey := fmt.Sprintf("user:name:%d", userID)
|
||||||
|
cached, err := s.redisClient.Get(ctx, cacheKey).Result()
|
||||||
|
|
||||||
|
if err == redis.Nil {
|
||||||
|
// Cache miss
|
||||||
|
missingIDs = append(missingIDs, userID)
|
||||||
|
} else if err != nil {
|
||||||
|
// Redis error - treat as cache miss
|
||||||
|
missingIDs = append(missingIDs, userID)
|
||||||
|
} else {
|
||||||
|
// Cache hit
|
||||||
|
var user CachedUser
|
||||||
|
if err := json.Unmarshal([]byte(cached), &user); err == nil && user.Name != "" {
|
||||||
|
result[userID] = user.Name
|
||||||
|
} else {
|
||||||
|
missingIDs = append(missingIDs, userID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all were cached, return early
|
||||||
|
if len(missingIDs) == 0 {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Batch fetch missing usernames from Roblox API
|
||||||
|
// Split into batches of 100 (Roblox API limit)
|
||||||
|
for i := 0; i < len(missingIDs); i += 100 {
|
||||||
|
end := i + 100
|
||||||
|
if end > len(missingIDs) {
|
||||||
|
end = len(missingIDs)
|
||||||
|
}
|
||||||
|
batch := missingIDs[i:end]
|
||||||
|
|
||||||
|
var users []roblox.UserData
|
||||||
|
var err error
|
||||||
|
users, err = s.robloxClient.GetUsernames(batch)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to fetch usernames: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process results and cache them
|
||||||
|
for _, user := range users {
|
||||||
|
cached := CachedUser{
|
||||||
|
Name: user.Name,
|
||||||
|
DisplayName: user.DisplayName,
|
||||||
|
CachedAt: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Name != "" {
|
||||||
|
result[user.ID] = user.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the result
|
||||||
|
cacheKey := fmt.Sprintf("user:name:%d", user.ID)
|
||||||
|
cachedJSON, _ := json.Marshal(cached)
|
||||||
|
|
||||||
|
// Cache usernames for a long time (7 days) since they rarely change
|
||||||
|
s.redisClient.Set(ctx, cacheKey, cachedJSON, 7*24*time.Hour)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSingleUsername is a convenience method for fetching a single username
|
||||||
|
func (s *ThumbnailService) GetSingleUsername(ctx context.Context, userID uint64) (string, error) {
|
||||||
|
results, err := s.GetUsernames(ctx, []uint64{userID})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if name, ok := results[userID]; ok {
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("username not available for user %d", userID)
|
||||||
|
}
|
||||||
@@ -26,6 +26,8 @@ func NewMapfixesController(
|
|||||||
var(
|
var(
|
||||||
// prevent two mapfixes with same asset id
|
// prevent two mapfixes with same asset id
|
||||||
ActiveMapfixStatuses = []model.MapfixStatus{
|
ActiveMapfixStatuses = []model.MapfixStatus{
|
||||||
|
model.MapfixStatusReleasing,
|
||||||
|
model.MapfixStatusUploaded,
|
||||||
model.MapfixStatusUploading,
|
model.MapfixStatusUploading,
|
||||||
model.MapfixStatusValidated,
|
model.MapfixStatusValidated,
|
||||||
model.MapfixStatusValidating,
|
model.MapfixStatusValidating,
|
||||||
@@ -184,7 +186,7 @@ func (svc *Mapfixes) SetStatusValidated(ctx context.Context, params *validator.M
|
|||||||
// (Internal endpoint) Role Validator changes status from Validating -> Accepted.
|
// (Internal endpoint) Role Validator changes status from Validating -> Accepted.
|
||||||
//
|
//
|
||||||
// POST /mapfixes/{MapfixID}/status/validator-failed
|
// POST /mapfixes/{MapfixID}/status/validator-failed
|
||||||
func (svc *Mapfixes) SetStatusFailed(ctx context.Context, params *validator.MapfixID) (*validator.NullResponse, error) {
|
func (svc *Mapfixes) SetStatusNotValidated(ctx context.Context, params *validator.MapfixID) (*validator.NullResponse, error) {
|
||||||
MapfixID := int64(params.ID)
|
MapfixID := int64(params.ID)
|
||||||
// transaction
|
// transaction
|
||||||
target_status := model.MapfixStatusAcceptedUnvalidated
|
target_status := model.MapfixStatusAcceptedUnvalidated
|
||||||
@@ -253,6 +255,117 @@ func (svc *Mapfixes) SetStatusUploaded(ctx context.Context, params *validator.Ma
|
|||||||
|
|
||||||
return &validator.NullResponse{}, nil
|
return &validator.NullResponse{}, nil
|
||||||
}
|
}
|
||||||
|
func (svc *Mapfixes) SetStatusNotUploaded(ctx context.Context, params *validator.MapfixID) (*validator.NullResponse, error) {
|
||||||
|
MapfixID := int64(params.ID)
|
||||||
|
// transaction
|
||||||
|
target_status := model.MapfixStatusValidated
|
||||||
|
update := service.NewMapfixUpdate()
|
||||||
|
update.SetStatusID(target_status)
|
||||||
|
allow_statuses := []model.MapfixStatus{model.MapfixStatusUploading}
|
||||||
|
err := svc.inner.UpdateMapfixIfStatus(ctx, MapfixID, allow_statuses, update)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// push an action audit event
|
||||||
|
event_data := model.AuditEventDataAction{
|
||||||
|
TargetStatus: uint32(target_status),
|
||||||
|
}
|
||||||
|
|
||||||
|
err = svc.inner.CreateAuditEventAction(
|
||||||
|
ctx,
|
||||||
|
model.ValidatorUserID,
|
||||||
|
model.Resource{
|
||||||
|
ID: MapfixID,
|
||||||
|
Type: model.ResourceMapfix,
|
||||||
|
},
|
||||||
|
event_data,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &validator.NullResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ActionMapfixReleased implements actionMapfixReleased operation.
|
||||||
|
//
|
||||||
|
// (Internal endpoint) Role Validator changes status from Releasing -> Released.
|
||||||
|
//
|
||||||
|
// POST /mapfixes/{MapfixID}/status/validator-released
|
||||||
|
func (svc *Mapfixes) SetStatusReleased(ctx context.Context, params *validator.MapfixReleaseRequest) (*validator.NullResponse, error) {
|
||||||
|
MapfixID := int64(params.MapfixID)
|
||||||
|
// transaction
|
||||||
|
target_status := model.MapfixStatusReleased
|
||||||
|
update := service.NewMapfixUpdate()
|
||||||
|
update.SetStatusID(target_status)
|
||||||
|
allow_statuses := []model.MapfixStatus{model.MapfixStatusReleasing}
|
||||||
|
err := svc.inner.UpdateMapfixIfStatus(ctx, MapfixID, allow_statuses, update)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
event_data := model.AuditEventDataAction{
|
||||||
|
TargetStatus: uint32(target_status),
|
||||||
|
}
|
||||||
|
|
||||||
|
err = svc.inner.CreateAuditEventAction(
|
||||||
|
ctx,
|
||||||
|
model.ValidatorUserID,
|
||||||
|
model.Resource{
|
||||||
|
ID: MapfixID,
|
||||||
|
Type: model.ResourceMapfix,
|
||||||
|
},
|
||||||
|
event_data,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// metadata maintenance
|
||||||
|
map_update := service.NewMapUpdate()
|
||||||
|
map_update.SetAssetVersion(params.AssetVersion)
|
||||||
|
map_update.SetModes(params.Modes)
|
||||||
|
|
||||||
|
err = svc.inner.UpdateMap(ctx, int64(params.TargetAssetID), map_update)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &validator.NullResponse{}, nil
|
||||||
|
}
|
||||||
|
func (svc *Mapfixes) SetStatusNotReleased(ctx context.Context, params *validator.MapfixID) (*validator.NullResponse, error) {
|
||||||
|
MapfixID := int64(params.ID)
|
||||||
|
// transaction
|
||||||
|
target_status := model.MapfixStatusUploaded
|
||||||
|
update := service.NewMapfixUpdate()
|
||||||
|
update.SetStatusID(target_status)
|
||||||
|
allow_statuses := []model.MapfixStatus{model.MapfixStatusReleasing}
|
||||||
|
err := svc.inner.UpdateMapfixIfStatus(ctx, MapfixID, allow_statuses, update)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// push an action audit event
|
||||||
|
event_data := model.AuditEventDataAction{
|
||||||
|
TargetStatus: uint32(target_status),
|
||||||
|
}
|
||||||
|
|
||||||
|
err = svc.inner.CreateAuditEventAction(
|
||||||
|
ctx,
|
||||||
|
model.ValidatorUserID,
|
||||||
|
model.Resource{
|
||||||
|
ID: MapfixID,
|
||||||
|
Type: model.ResourceMapfix,
|
||||||
|
},
|
||||||
|
event_data,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &validator.NullResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// CreateMapfixAuditError implements createMapfixAuditError operation.
|
// CreateMapfixAuditError implements createMapfixAuditError operation.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -19,6 +19,18 @@ func NewOperationsController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (svc *Operations) Success(ctx context.Context, params *validator.OperationSuccessRequest) (*validator.NullResponse, error) {
|
||||||
|
success_params := service.NewOperationCompleteParams(
|
||||||
|
params.Path,
|
||||||
|
)
|
||||||
|
err := svc.inner.CompleteOperation(ctx, int32(params.OperationID), success_params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &validator.NullResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ActionOperationFailed implements actionOperationFailed operation.
|
// ActionOperationFailed implements actionOperationFailed operation.
|
||||||
//
|
//
|
||||||
// Fail the specified OperationID with a StatusMessage.
|
// Fail the specified OperationID with a StatusMessage.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"git.itzana.me/strafesnet/go-grpc/validator"
|
"git.itzana.me/strafesnet/go-grpc/validator"
|
||||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||||
@@ -24,7 +25,7 @@ func NewSubmissionsController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var(
|
var(
|
||||||
// prevent two mapfixes with same asset id
|
// prevent two submissions with same asset id
|
||||||
ActiveSubmissionStatuses = []model.SubmissionStatus{
|
ActiveSubmissionStatuses = []model.SubmissionStatus{
|
||||||
model.SubmissionStatusUploading,
|
model.SubmissionStatusUploading,
|
||||||
model.SubmissionStatusValidated,
|
model.SubmissionStatusValidated,
|
||||||
@@ -202,7 +203,7 @@ func (svc *Submissions) SetStatusValidated(ctx context.Context, params *validato
|
|||||||
// (Internal endpoint) Role Validator changes status from Validating -> Accepted.
|
// (Internal endpoint) Role Validator changes status from Validating -> Accepted.
|
||||||
//
|
//
|
||||||
// POST /submissions/{SubmissionID}/status/validator-failed
|
// POST /submissions/{SubmissionID}/status/validator-failed
|
||||||
func (svc *Submissions) SetStatusFailed(ctx context.Context, params *validator.SubmissionID) (*validator.NullResponse, error) {
|
func (svc *Submissions) SetStatusNotValidated(ctx context.Context, params *validator.SubmissionID) (*validator.NullResponse, error) {
|
||||||
SubmissionID := int64(params.ID)
|
SubmissionID := int64(params.ID)
|
||||||
// transaction
|
// transaction
|
||||||
target_status := model.SubmissionStatusAcceptedUnvalidated
|
target_status := model.SubmissionStatusAcceptedUnvalidated
|
||||||
@@ -273,6 +274,68 @@ func (svc *Submissions) SetStatusUploaded(ctx context.Context, params *validator
|
|||||||
return &validator.NullResponse{}, nil
|
return &validator.NullResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (svc *Submissions) SetStatusNotUploaded(ctx context.Context, params *validator.SubmissionID) (*validator.NullResponse, error) {
|
||||||
|
SubmissionID := int64(params.ID)
|
||||||
|
// transaction
|
||||||
|
target_status := model.SubmissionStatusValidated
|
||||||
|
update := service.NewSubmissionUpdate()
|
||||||
|
update.SetStatusID(target_status)
|
||||||
|
allowed_statuses :=[]model.SubmissionStatus{model.SubmissionStatusUploading}
|
||||||
|
err := svc.inner.UpdateSubmissionIfStatus(ctx, SubmissionID, allowed_statuses, update)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// push an action audit event
|
||||||
|
event_data := model.AuditEventDataAction{
|
||||||
|
TargetStatus: uint32(target_status),
|
||||||
|
}
|
||||||
|
|
||||||
|
err = svc.inner.CreateAuditEventAction(
|
||||||
|
ctx,
|
||||||
|
model.ValidatorUserID,
|
||||||
|
model.Resource{
|
||||||
|
ID: SubmissionID,
|
||||||
|
Type: model.ResourceSubmission,
|
||||||
|
},
|
||||||
|
event_data,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &validator.NullResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (svc *Submissions) SetStatusReleased(ctx context.Context, params *validator.SubmissionReleaseRequest) (*validator.NullResponse, error){
|
||||||
|
// create map with go-grpc
|
||||||
|
_, err := svc.inner.CreateMap(ctx, model.Map{
|
||||||
|
ID: params.MapCreate.ID,
|
||||||
|
DisplayName: params.MapCreate.DisplayName,
|
||||||
|
Creator: params.MapCreate.Creator,
|
||||||
|
GameID: params.MapCreate.GameID,
|
||||||
|
Date: time.Unix(params.MapCreate.Date, 0),
|
||||||
|
Submitter: params.MapCreate.Submitter,
|
||||||
|
Thumbnail: 0,
|
||||||
|
AssetVersion: params.MapCreate.AssetVersion,
|
||||||
|
LoadCount: 0,
|
||||||
|
Modes: params.MapCreate.Modes,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// update status to Released
|
||||||
|
update := service.NewSubmissionUpdate()
|
||||||
|
update.SetStatusID(model.SubmissionStatusReleased)
|
||||||
|
err = svc.inner.UpdateSubmissionIfStatus(ctx, int64(params.SubmissionID), []model.SubmissionStatus{model.SubmissionStatusUploaded}, update)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &validator.NullResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// CreateSubmissionAuditError implements createSubmissionAuditError operation.
|
// CreateSubmissionAuditError implements createSubmissionAuditError operation.
|
||||||
//
|
//
|
||||||
// Post an error to the audit log
|
// Post an error to the audit log
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ var(
|
|||||||
}
|
}
|
||||||
// limit mapfixes in the pipeline to one per target map
|
// limit mapfixes in the pipeline to one per target map
|
||||||
ActiveAcceptedMapfixStatuses = []model.MapfixStatus{
|
ActiveAcceptedMapfixStatuses = []model.MapfixStatus{
|
||||||
|
model.MapfixStatusReleasing,
|
||||||
|
model.MapfixStatusUploaded,
|
||||||
model.MapfixStatusUploading,
|
model.MapfixStatusUploading,
|
||||||
model.MapfixStatusValidated,
|
model.MapfixStatusValidated,
|
||||||
model.MapfixStatusValidating,
|
model.MapfixStatusValidating,
|
||||||
@@ -193,6 +195,9 @@ func (svc *Service) ListMapfixes(ctx context.Context, params api.ListMapfixesPar
|
|||||||
if asset_id, asset_id_ok := params.AssetID.Get(); asset_id_ok{
|
if asset_id, asset_id_ok := params.AssetID.Get(); asset_id_ok{
|
||||||
filter.SetAssetID(uint64(asset_id))
|
filter.SetAssetID(uint64(asset_id))
|
||||||
}
|
}
|
||||||
|
if asset_version, asset_version_ok := params.AssetVersion.Get(); asset_version_ok{
|
||||||
|
filter.SetAssetVersion(uint64(asset_version))
|
||||||
|
}
|
||||||
if target_asset_id, target_asset_id_ok := params.TargetAssetID.Get(); target_asset_id_ok{
|
if target_asset_id, target_asset_id_ok := params.TargetAssetID.Get(); target_asset_id_ok{
|
||||||
filter.SetTargetAssetID(uint64(target_asset_id))
|
filter.SetTargetAssetID(uint64(target_asset_id))
|
||||||
}
|
}
|
||||||
@@ -786,6 +791,127 @@ func (svc *Service) ActionMapfixValidated(ctx context.Context, params api.Action
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActionMapfixTriggerRelease invokes actionMapfixTriggerRelease operation.
|
||||||
|
//
|
||||||
|
// Role MapfixUpload changes status from Uploaded -> Releasing.
|
||||||
|
//
|
||||||
|
// POST /mapfixes/{MapfixID}/status/trigger-release
|
||||||
|
func (svc *Service) ActionMapfixTriggerRelease(ctx context.Context, params api.ActionMapfixTriggerReleaseParams) error {
|
||||||
|
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||||
|
if !ok {
|
||||||
|
return ErrUserInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
has_role, err := userInfo.HasRoleMapfixUpload()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// check if caller has required role
|
||||||
|
if !has_role {
|
||||||
|
return ErrPermissionDeniedNeedRoleMapfixUpload
|
||||||
|
}
|
||||||
|
|
||||||
|
userId, err := userInfo.GetUserID()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// transaction
|
||||||
|
target_status := model.MapfixStatusReleasing
|
||||||
|
update := service.NewMapfixUpdate()
|
||||||
|
update.SetStatusID(target_status)
|
||||||
|
allow_statuses := []model.MapfixStatus{model.MapfixStatusUploaded}
|
||||||
|
mapfix, err := svc.inner.UpdateAndGetMapfixIfStatus(ctx, params.MapfixID, allow_statuses, update)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is a map fix
|
||||||
|
err = svc.inner.NatsReleaseMapfix(
|
||||||
|
mapfix.ID,
|
||||||
|
mapfix.ValidatedAssetID,
|
||||||
|
mapfix.ValidatedAssetVersion,
|
||||||
|
mapfix.TargetAssetID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
event_data := model.AuditEventDataAction{
|
||||||
|
TargetStatus: uint32(target_status),
|
||||||
|
}
|
||||||
|
|
||||||
|
return svc.inner.CreateAuditEventAction(
|
||||||
|
ctx,
|
||||||
|
userId,
|
||||||
|
model.Resource{
|
||||||
|
ID: params.MapfixID,
|
||||||
|
Type: model.ResourceMapfix,
|
||||||
|
},
|
||||||
|
event_data,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ActionMapfixUploaded invokes actionMapfixUploaded operation.
|
||||||
|
//
|
||||||
|
// Role MapfixUpload manually resets releasing softlock and changes status from Releasing -> Uploaded.
|
||||||
|
//
|
||||||
|
// POST /mapfixes/{MapfixID}/status/reset-releasing
|
||||||
|
func (svc *Service) ActionMapfixUploaded(ctx context.Context, params api.ActionMapfixUploadedParams) error {
|
||||||
|
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||||
|
if !ok {
|
||||||
|
return ErrUserInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
has_role, err := userInfo.HasRoleMapfixUpload()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// check if caller has required role
|
||||||
|
if !has_role {
|
||||||
|
return ErrPermissionDeniedNeedRoleMapfixUpload
|
||||||
|
}
|
||||||
|
|
||||||
|
userId, err := userInfo.GetUserID()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// check when mapfix was updated
|
||||||
|
mapfix, err := svc.inner.GetMapfix(ctx, params.MapfixID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if time.Now().Before(mapfix.UpdatedAt.Add(time.Second*10)) {
|
||||||
|
// the last time the mapfix was updated must be longer than 10 seconds ago
|
||||||
|
return ErrDelayReset
|
||||||
|
}
|
||||||
|
|
||||||
|
// transaction
|
||||||
|
target_status := model.MapfixStatusUploaded
|
||||||
|
update := service.NewMapfixUpdate()
|
||||||
|
update.SetStatusID(target_status)
|
||||||
|
allow_statuses := []model.MapfixStatus{model.MapfixStatusReleasing}
|
||||||
|
err = svc.inner.UpdateMapfixIfStatus(ctx, params.MapfixID, allow_statuses, update)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
event_data := model.AuditEventDataAction{
|
||||||
|
TargetStatus: uint32(target_status),
|
||||||
|
}
|
||||||
|
|
||||||
|
return svc.inner.CreateAuditEventAction(
|
||||||
|
ctx,
|
||||||
|
userId,
|
||||||
|
model.Resource{
|
||||||
|
ID: params.MapfixID,
|
||||||
|
Type: model.ResourceMapfix,
|
||||||
|
},
|
||||||
|
event_data,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// ActionMapfixTriggerValidate invokes actionMapfixTriggerValidate operation.
|
// ActionMapfixTriggerValidate invokes actionMapfixTriggerValidate operation.
|
||||||
//
|
//
|
||||||
// Role Reviewer triggers validation and changes status from Submitted -> Validating.
|
// Role Reviewer triggers validation and changes status from Submitted -> Validating.
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ func (usr UserInfoHandle) Validate() (bool, error) {
|
|||||||
}
|
}
|
||||||
return validate.Valid, nil
|
return validate.Valid, nil
|
||||||
}
|
}
|
||||||
func (usr UserInfoHandle) hasRoles(wantRoles model.Roles) (bool, error) {
|
func (usr UserInfoHandle) HasRoles(wantRoles model.Roles) (bool, error) {
|
||||||
haveroles, err := usr.GetRoles()
|
haveroles, err := usr.GetRoles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -94,25 +94,25 @@ func (usr UserInfoHandle) GetRoles() (model.Roles, error) {
|
|||||||
|
|
||||||
// RoleThumbnail
|
// RoleThumbnail
|
||||||
func (usr UserInfoHandle) HasRoleMapfixUpload() (bool, error) {
|
func (usr UserInfoHandle) HasRoleMapfixUpload() (bool, error) {
|
||||||
return usr.hasRoles(model.RolesMapfixUpload)
|
return usr.HasRoles(model.RolesMapfixUpload)
|
||||||
}
|
}
|
||||||
func (usr UserInfoHandle) HasRoleMapfixReview() (bool, error) {
|
func (usr UserInfoHandle) HasRoleMapfixReview() (bool, error) {
|
||||||
return usr.hasRoles(model.RolesMapfixReview)
|
return usr.HasRoles(model.RolesMapfixReview)
|
||||||
}
|
}
|
||||||
func (usr UserInfoHandle) HasRoleMapDownload() (bool, error) {
|
func (usr UserInfoHandle) HasRoleMapDownload() (bool, error) {
|
||||||
return usr.hasRoles(model.RolesMapDownload)
|
return usr.HasRoles(model.RolesMapDownload)
|
||||||
}
|
}
|
||||||
func (usr UserInfoHandle) HasRoleSubmissionRelease() (bool, error) {
|
func (usr UserInfoHandle) HasRoleSubmissionRelease() (bool, error) {
|
||||||
return usr.hasRoles(model.RolesSubmissionRelease)
|
return usr.HasRoles(model.RolesSubmissionRelease)
|
||||||
}
|
}
|
||||||
func (usr UserInfoHandle) HasRoleSubmissionUpload() (bool, error) {
|
func (usr UserInfoHandle) HasRoleSubmissionUpload() (bool, error) {
|
||||||
return usr.hasRoles(model.RolesSubmissionUpload)
|
return usr.HasRoles(model.RolesSubmissionUpload)
|
||||||
}
|
}
|
||||||
func (usr UserInfoHandle) HasRoleSubmissionReview() (bool, error) {
|
func (usr UserInfoHandle) HasRoleSubmissionReview() (bool, error) {
|
||||||
return usr.hasRoles(model.RolesSubmissionReview)
|
return usr.HasRoles(model.RolesSubmissionReview)
|
||||||
}
|
}
|
||||||
func (usr UserInfoHandle) HasRoleScriptWrite() (bool, error) {
|
func (usr UserInfoHandle) HasRoleScriptWrite() (bool, error) {
|
||||||
return usr.hasRoles(model.RolesScriptWrite)
|
return usr.HasRoles(model.RolesScriptWrite)
|
||||||
}
|
}
|
||||||
/// Not implemented
|
/// Not implemented
|
||||||
func (usr UserInfoHandle) HasRoleMaptest() (bool, error) {
|
func (usr UserInfoHandle) HasRoleMaptest() (bool, error) {
|
||||||
|
|||||||
105
pkg/web_api/stats.go
Normal file
105
pkg/web_api/stats.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package web_api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||||
|
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||||
|
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||||
|
"git.itzana.me/strafesnet/maps-service/pkg/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GET /stats
|
||||||
|
func (svc *Service) GetStats(ctx context.Context) (*api.Stats, error) {
|
||||||
|
// Get total submissions count
|
||||||
|
totalSubmissions, _, err := svc.inner.ListSubmissionsWithTotal(ctx, service.NewSubmissionFilter(), model.Page{
|
||||||
|
Number: 1,
|
||||||
|
Size: 0, // We only want the count, not the items
|
||||||
|
}, datastore.ListSortDisabled)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get total mapfixes count
|
||||||
|
totalMapfixes, _, err := svc.inner.ListMapfixesWithTotal(ctx, service.NewMapfixFilter(), model.Page{
|
||||||
|
Number: 1,
|
||||||
|
Size: 0, // We only want the count, not the items
|
||||||
|
}, datastore.ListSortDisabled)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get released submissions count
|
||||||
|
releasedSubmissionsFilter := service.NewSubmissionFilter()
|
||||||
|
releasedSubmissionsFilter.SetStatuses([]model.SubmissionStatus{model.SubmissionStatusReleased})
|
||||||
|
releasedSubmissions, _, err := svc.inner.ListSubmissionsWithTotal(ctx, releasedSubmissionsFilter, model.Page{
|
||||||
|
Number: 1,
|
||||||
|
Size: 0,
|
||||||
|
}, datastore.ListSortDisabled)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get released mapfixes count
|
||||||
|
releasedMapfixesFilter := service.NewMapfixFilter()
|
||||||
|
releasedMapfixesFilter.SetStatuses([]model.MapfixStatus{model.MapfixStatusReleased})
|
||||||
|
releasedMapfixes, _, err := svc.inner.ListMapfixesWithTotal(ctx, releasedMapfixesFilter, model.Page{
|
||||||
|
Number: 1,
|
||||||
|
Size: 0,
|
||||||
|
}, datastore.ListSortDisabled)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get submitted submissions count (under review)
|
||||||
|
submittedSubmissionsFilter := service.NewSubmissionFilter()
|
||||||
|
submittedSubmissionsFilter.SetStatuses([]model.SubmissionStatus{
|
||||||
|
model.SubmissionStatusUnderConstruction,
|
||||||
|
model.SubmissionStatusChangesRequested,
|
||||||
|
model.SubmissionStatusSubmitting,
|
||||||
|
model.SubmissionStatusSubmitted,
|
||||||
|
model.SubmissionStatusAcceptedUnvalidated,
|
||||||
|
model.SubmissionStatusValidating,
|
||||||
|
model.SubmissionStatusValidated,
|
||||||
|
model.SubmissionStatusUploading,
|
||||||
|
model.SubmissionStatusUploaded,
|
||||||
|
})
|
||||||
|
submittedSubmissions, _, err := svc.inner.ListSubmissionsWithTotal(ctx, submittedSubmissionsFilter, model.Page{
|
||||||
|
Number: 1,
|
||||||
|
Size: 0,
|
||||||
|
}, datastore.ListSortDisabled)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get submitted mapfixes count (under review)
|
||||||
|
submittedMapfixesFilter := service.NewMapfixFilter()
|
||||||
|
submittedMapfixesFilter.SetStatuses([]model.MapfixStatus{
|
||||||
|
model.MapfixStatusUnderConstruction,
|
||||||
|
model.MapfixStatusChangesRequested,
|
||||||
|
model.MapfixStatusSubmitting,
|
||||||
|
model.MapfixStatusSubmitted,
|
||||||
|
model.MapfixStatusAcceptedUnvalidated,
|
||||||
|
model.MapfixStatusValidating,
|
||||||
|
model.MapfixStatusValidated,
|
||||||
|
model.MapfixStatusUploading,
|
||||||
|
model.MapfixStatusUploaded,
|
||||||
|
model.MapfixStatusReleasing,
|
||||||
|
})
|
||||||
|
submittedMapfixes, _, err := svc.inner.ListMapfixesWithTotal(ctx, submittedMapfixesFilter, model.Page{
|
||||||
|
Number: 1,
|
||||||
|
Size: 0,
|
||||||
|
}, datastore.ListSortDisabled)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.Stats{
|
||||||
|
TotalSubmissions: totalSubmissions,
|
||||||
|
TotalMapfixes: totalMapfixes,
|
||||||
|
ReleasedSubmissions: releasedSubmissions,
|
||||||
|
ReleasedMapfixes: releasedMapfixes,
|
||||||
|
SubmittedSubmissions: submittedSubmissions,
|
||||||
|
SubmittedMapfixes: submittedMapfixes,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
@@ -20,13 +20,6 @@ var(
|
|||||||
model.SubmissionStatusSubmitted,
|
model.SubmissionStatusSubmitted,
|
||||||
model.SubmissionStatusUnderConstruction,
|
model.SubmissionStatusUnderConstruction,
|
||||||
}
|
}
|
||||||
// limit submissions in the pipeline to one per target map
|
|
||||||
ActiveAcceptedSubmissionStatuses = []model.SubmissionStatus{
|
|
||||||
model.SubmissionStatusUploading,
|
|
||||||
model.SubmissionStatusValidated,
|
|
||||||
model.SubmissionStatusValidating,
|
|
||||||
model.SubmissionStatusAcceptedUnvalidated,
|
|
||||||
}
|
|
||||||
// Allow 5 submissions every 10 minutes
|
// Allow 5 submissions every 10 minutes
|
||||||
CreateSubmissionRateLimit int64 = 5
|
CreateSubmissionRateLimit int64 = 5
|
||||||
CreateSubmissionRecencyWindow = time.Second*600
|
CreateSubmissionRecencyWindow = time.Second*600
|
||||||
@@ -236,6 +229,9 @@ func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissi
|
|||||||
if asset_id, asset_id_ok := params.AssetID.Get(); asset_id_ok{
|
if asset_id, asset_id_ok := params.AssetID.Get(); asset_id_ok{
|
||||||
filter.SetAssetID(uint64(asset_id))
|
filter.SetAssetID(uint64(asset_id))
|
||||||
}
|
}
|
||||||
|
if asset_version, asset_version_ok := params.AssetVersion.Get(); asset_version_ok{
|
||||||
|
filter.SetAssetVersion(uint64(asset_version))
|
||||||
|
}
|
||||||
if uploaded_asset_id, uploaded_asset_id_ok := params.UploadedAssetID.Get(); uploaded_asset_id_ok{
|
if uploaded_asset_id, uploaded_asset_id_ok := params.UploadedAssetID.Get(); uploaded_asset_id_ok{
|
||||||
filter.SetUploadedAssetID(uint64(uploaded_asset_id))
|
filter.SetUploadedAssetID(uint64(uploaded_asset_id))
|
||||||
}
|
}
|
||||||
@@ -1038,19 +1034,24 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params api.Act
|
|||||||
// Release a set of uploaded maps.
|
// Release a set of uploaded maps.
|
||||||
//
|
//
|
||||||
// POST /release-submissions
|
// POST /release-submissions
|
||||||
func (svc *Service) ReleaseSubmissions(ctx context.Context, request []api.ReleaseInfo) error {
|
func (svc *Service) ReleaseSubmissions(ctx context.Context, request []api.ReleaseInfo) (*api.OperationID, error) {
|
||||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ErrUserInfo
|
return nil, ErrUserInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
has_role, err := userInfo.HasRoleSubmissionRelease()
|
has_role, err := userInfo.HasRoleSubmissionRelease()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
// check if caller has required role
|
// check if caller has required role
|
||||||
if !has_role {
|
if !has_role {
|
||||||
return ErrPermissionDeniedNeedRoleSubmissionRelease
|
return nil, ErrPermissionDeniedNeedRoleSubmissionRelease
|
||||||
|
}
|
||||||
|
|
||||||
|
userId, err := userInfo.GetUserID()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
idList := make([]int64, len(request))
|
idList := make([]int64, len(request))
|
||||||
@@ -1061,48 +1062,62 @@ func (svc *Service) ReleaseSubmissions(ctx context.Context, request []api.Releas
|
|||||||
// fetch submissions
|
// fetch submissions
|
||||||
submissions, err := svc.inner.GetSubmissionList(ctx, idList)
|
submissions, err := svc.inner.GetSubmissionList(ctx, idList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the submissions are not ordered the same as the idList!
|
||||||
|
id_to_submission := make(map[int64]*model.Submission, len(submissions))
|
||||||
|
|
||||||
// check each submission to make sure it is ready to release
|
// check each submission to make sure it is ready to release
|
||||||
for _,submission := range submissions{
|
for _,submission := range submissions{
|
||||||
if submission.StatusID != model.SubmissionStatusUploaded{
|
if submission.StatusID != model.SubmissionStatusUploaded{
|
||||||
return ErrReleaseInvalidStatus
|
return nil, ErrReleaseInvalidStatus
|
||||||
}
|
}
|
||||||
if submission.UploadedAssetID == 0{
|
if submission.UploadedAssetID == 0{
|
||||||
return ErrReleaseNoUploadedAssetID
|
return nil, ErrReleaseNoUploadedAssetID
|
||||||
}
|
}
|
||||||
|
id_to_submission[submission.ID] = &submission
|
||||||
}
|
}
|
||||||
|
|
||||||
for i,submission := range submissions{
|
// construct batch release nats message
|
||||||
date := request[i].Date.Unix()
|
release_submissions := make([]model.ReleaseSubmissionRequest, len(request))
|
||||||
// create each map with go-grpc
|
for i, release_info := range request {
|
||||||
_, err := svc.inner.CreateMap(ctx, model.Map{
|
// from request
|
||||||
ID: int64(submission.UploadedAssetID),
|
release_submissions[i].ReleaseDate = release_info.Date.Unix()
|
||||||
DisplayName: submission.DisplayName,
|
release_submissions[i].SubmissionID = release_info.SubmissionID
|
||||||
Creator: submission.Creator,
|
submission := id_to_submission[release_info.SubmissionID]
|
||||||
GameID: submission.GameID,
|
// from submission
|
||||||
Date: time.Unix(date, 0),
|
release_submissions[i].ModelID = submission.ValidatedAssetID
|
||||||
Submitter: submission.Submitter,
|
release_submissions[i].ModelVersion = submission.ValidatedAssetVersion
|
||||||
// Thumbnail: 0,
|
// for map create
|
||||||
// AssetVersion: 0,
|
release_submissions[i].UploadedAssetID = submission.UploadedAssetID
|
||||||
// LoadCount: 0,
|
release_submissions[i].DisplayName = submission.DisplayName
|
||||||
// Modes: 0,
|
release_submissions[i].Creator = submission.Creator
|
||||||
})
|
release_submissions[i].GameID = submission.GameID
|
||||||
if err != nil {
|
release_submissions[i].Submitter = submission.Submitter
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// update each status to Released
|
|
||||||
update := service.NewSubmissionUpdate()
|
|
||||||
update.SetStatusID(model.SubmissionStatusReleased)
|
|
||||||
err = svc.inner.UpdateSubmissionIfStatus(ctx, submission.ID, []model.SubmissionStatus{model.SubmissionStatusUploaded}, update)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
// create a trackable long-running operation
|
||||||
|
operation, err := svc.inner.CreateOperation(ctx, model.Operation{
|
||||||
|
Owner: userId,
|
||||||
|
StatusID: model.OperationStatusCreated,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is a map fix
|
||||||
|
err = svc.inner.NatsBatchReleaseSubmissions(
|
||||||
|
release_submissions,
|
||||||
|
operation.ID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.OperationID{
|
||||||
|
OperationID: operation.ID,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateSubmissionAuditComment implements createSubmissionAuditComment operation.
|
// CreateSubmissionAuditComment implements createSubmissionAuditComment operation.
|
||||||
|
|||||||
135
pkg/web_api/thumbnails.go
Normal file
135
pkg/web_api/thumbnails.go
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
package web_api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||||
|
"git.itzana.me/strafesnet/maps-service/pkg/roblox"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BatchAssetThumbnails handles batch fetching of asset thumbnails
|
||||||
|
func (svc *Service) BatchAssetThumbnails(ctx context.Context, req *api.BatchAssetThumbnailsReq) (*api.BatchAssetThumbnailsOK, error) {
|
||||||
|
if len(req.AssetIds) == 0 {
|
||||||
|
return &api.BatchAssetThumbnailsOK{
|
||||||
|
Thumbnails: api.NewOptBatchAssetThumbnailsOKThumbnails(map[string]string{}),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert size string to enum
|
||||||
|
size := roblox.Size420x420
|
||||||
|
if req.Size.IsSet() {
|
||||||
|
sizeStr := req.Size.Value
|
||||||
|
switch api.BatchAssetThumbnailsReqSize(sizeStr) {
|
||||||
|
case api.BatchAssetThumbnailsReqSize150x150:
|
||||||
|
size = roblox.Size150x150
|
||||||
|
case api.BatchAssetThumbnailsReqSize768x432:
|
||||||
|
size = roblox.Size768x432
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch thumbnails from service
|
||||||
|
thumbnails, err := svc.inner.GetAssetThumbnails(ctx, req.AssetIds, size)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert map[uint64]string to map[string]string for JSON
|
||||||
|
result := make(map[string]string, len(thumbnails))
|
||||||
|
for assetID, url := range thumbnails {
|
||||||
|
result[strconv.FormatUint(assetID, 10)] = url
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.BatchAssetThumbnailsOK{
|
||||||
|
Thumbnails: api.NewOptBatchAssetThumbnailsOKThumbnails(result),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAssetThumbnail handles single asset thumbnail fetch (with redirect)
|
||||||
|
func (svc *Service) GetAssetThumbnail(ctx context.Context, params api.GetAssetThumbnailParams) (*api.GetAssetThumbnailFound, error) {
|
||||||
|
// Convert size string to enum
|
||||||
|
size := roblox.Size420x420
|
||||||
|
if params.Size.IsSet() {
|
||||||
|
sizeStr := params.Size.Value
|
||||||
|
switch api.GetAssetThumbnailSize(sizeStr) {
|
||||||
|
case api.GetAssetThumbnailSize150x150:
|
||||||
|
size = roblox.Size150x150
|
||||||
|
case api.GetAssetThumbnailSize768x432:
|
||||||
|
size = roblox.Size768x432
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch thumbnail
|
||||||
|
thumbnailURL, err := svc.inner.GetSingleAssetThumbnail(ctx, params.AssetID, size)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return redirect response
|
||||||
|
return &api.GetAssetThumbnailFound{
|
||||||
|
Location: api.NewOptString(thumbnailURL),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BatchUserThumbnails handles batch fetching of user avatar thumbnails
|
||||||
|
func (svc *Service) BatchUserThumbnails(ctx context.Context, req *api.BatchUserThumbnailsReq) (*api.BatchUserThumbnailsOK, error) {
|
||||||
|
if len(req.UserIds) == 0 {
|
||||||
|
return &api.BatchUserThumbnailsOK{
|
||||||
|
Thumbnails: api.NewOptBatchUserThumbnailsOKThumbnails(map[string]string{}),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert size string to enum
|
||||||
|
size := roblox.Size150x150
|
||||||
|
if req.Size.IsSet() {
|
||||||
|
sizeStr := req.Size.Value
|
||||||
|
switch api.BatchUserThumbnailsReqSize(sizeStr) {
|
||||||
|
case api.BatchUserThumbnailsReqSize420x420:
|
||||||
|
size = roblox.Size420x420
|
||||||
|
case api.BatchUserThumbnailsReqSize768x432:
|
||||||
|
size = roblox.Size768x432
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch thumbnails from service
|
||||||
|
thumbnails, err := svc.inner.GetUserAvatarThumbnails(ctx, req.UserIds, size)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert map[uint64]string to map[string]string for JSON
|
||||||
|
result := make(map[string]string, len(thumbnails))
|
||||||
|
for userID, url := range thumbnails {
|
||||||
|
result[strconv.FormatUint(userID, 10)] = url
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.BatchUserThumbnailsOK{
|
||||||
|
Thumbnails: api.NewOptBatchUserThumbnailsOKThumbnails(result),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserThumbnail handles single user avatar thumbnail fetch (with redirect)
|
||||||
|
func (svc *Service) GetUserThumbnail(ctx context.Context, params api.GetUserThumbnailParams) (*api.GetUserThumbnailFound, error) {
|
||||||
|
// Convert size string to enum
|
||||||
|
size := roblox.Size150x150
|
||||||
|
if params.Size.IsSet() {
|
||||||
|
sizeStr := params.Size.Value
|
||||||
|
switch api.GetUserThumbnailSize(sizeStr) {
|
||||||
|
case api.GetUserThumbnailSize420x420:
|
||||||
|
size = roblox.Size420x420
|
||||||
|
case api.GetUserThumbnailSize768x432:
|
||||||
|
size = roblox.Size768x432
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch thumbnail
|
||||||
|
thumbnailURL, err := svc.inner.GetSingleUserAvatarThumbnail(ctx, params.UserID, size)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return redirect response
|
||||||
|
return &api.GetUserThumbnailFound{
|
||||||
|
Location: api.NewOptString(thumbnailURL),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
33
pkg/web_api/users.go
Normal file
33
pkg/web_api/users.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package web_api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BatchUsernames handles batch fetching of usernames
|
||||||
|
func (svc *Service) BatchUsernames(ctx context.Context, req *api.BatchUsernamesReq) (*api.BatchUsernamesOK, error) {
|
||||||
|
if len(req.UserIds) == 0 {
|
||||||
|
return &api.BatchUsernamesOK{
|
||||||
|
Usernames: api.NewOptBatchUsernamesOKUsernames(map[string]string{}),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch usernames from service
|
||||||
|
usernames, err := svc.inner.GetUsernames(ctx, req.UserIds)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert map[uint64]string to map[string]string for JSON
|
||||||
|
result := make(map[string]string, len(usernames))
|
||||||
|
for userID, username := range usernames {
|
||||||
|
result[strconv.FormatUint(userID, 10)] = username
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.BatchUsernamesOK{
|
||||||
|
Usernames: api.NewOptBatchUsernamesOKUsernames(result),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "submissions-api"
|
name = "submissions-api"
|
||||||
version = "0.8.2"
|
version = "0.10.1"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
publish = ["strafesnet"]
|
publish = ["strafesnet"]
|
||||||
repository = "https://git.itzana.me/StrafesNET/maps-service"
|
repository = "https://git.itzana.me/StrafesNET/maps-service"
|
||||||
@@ -152,6 +152,48 @@ impl Context{
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
pub async fn get_mapfixes(&self,config:GetMapfixesRequest<'_>)->Result<MapfixesResponse,Error>{
|
||||||
|
let url_raw=format!("{}/mapfixes",self.0.base_url);
|
||||||
|
let mut url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?;
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut query_pairs=url.query_pairs_mut();
|
||||||
|
query_pairs.append_pair("Page",config.Page.to_string().as_str());
|
||||||
|
query_pairs.append_pair("Limit",config.Limit.to_string().as_str());
|
||||||
|
if let Some(sort)=config.Sort{
|
||||||
|
query_pairs.append_pair("Sort",(sort as u8).to_string().as_str());
|
||||||
|
}
|
||||||
|
if let Some(display_name)=config.DisplayName{
|
||||||
|
query_pairs.append_pair("DisplayName",display_name);
|
||||||
|
}
|
||||||
|
if let Some(creator)=config.Creator{
|
||||||
|
query_pairs.append_pair("Creator",creator);
|
||||||
|
}
|
||||||
|
if let Some(game_id)=config.GameID{
|
||||||
|
query_pairs.append_pair("GameID",(game_id as u8).to_string().as_str());
|
||||||
|
}
|
||||||
|
if let Some(submitter)=config.Submitter{
|
||||||
|
query_pairs.append_pair("Submitter",submitter.to_string().as_str());
|
||||||
|
}
|
||||||
|
if let Some(asset_id)=config.AssetID{
|
||||||
|
query_pairs.append_pair("AssetID",asset_id.to_string().as_str());
|
||||||
|
}
|
||||||
|
if let Some(asset_version)=config.AssetVersion{
|
||||||
|
query_pairs.append_pair("AssetVersion",asset_version.to_string().as_str());
|
||||||
|
}
|
||||||
|
if let Some(uploaded_asset_id)=config.TargetAssetID{
|
||||||
|
query_pairs.append_pair("TargetAssetID",uploaded_asset_id.to_string().as_str());
|
||||||
|
}
|
||||||
|
if let Some(status_id)=config.StatusID{
|
||||||
|
query_pairs.append_pair("StatusID",(status_id as u8).to_string().as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response_ok(
|
||||||
|
self.0.get(url).await.map_err(Error::Reqwest)?
|
||||||
|
).await.map_err(Error::Response)?
|
||||||
|
.json().await.map_err(Error::ReqwestJson)
|
||||||
|
}
|
||||||
pub async fn get_submissions(&self,config:GetSubmissionsRequest<'_>)->Result<SubmissionsResponse,Error>{
|
pub async fn get_submissions(&self,config:GetSubmissionsRequest<'_>)->Result<SubmissionsResponse,Error>{
|
||||||
let url_raw=format!("{}/submissions",self.0.base_url);
|
let url_raw=format!("{}/submissions",self.0.base_url);
|
||||||
let mut url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?;
|
let mut url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?;
|
||||||
@@ -178,6 +220,9 @@ impl Context{
|
|||||||
if let Some(asset_id)=config.AssetID{
|
if let Some(asset_id)=config.AssetID{
|
||||||
query_pairs.append_pair("AssetID",asset_id.to_string().as_str());
|
query_pairs.append_pair("AssetID",asset_id.to_string().as_str());
|
||||||
}
|
}
|
||||||
|
if let Some(asset_version)=config.AssetVersion{
|
||||||
|
query_pairs.append_pair("AssetVersion",asset_version.to_string().as_str());
|
||||||
|
}
|
||||||
if let Some(uploaded_asset_id)=config.UploadedAssetID{
|
if let Some(uploaded_asset_id)=config.UploadedAssetID{
|
||||||
query_pairs.append_pair("UploadedAssetID",uploaded_asset_id.to_string().as_str());
|
query_pairs.append_pair("UploadedAssetID",uploaded_asset_id.to_string().as_str());
|
||||||
}
|
}
|
||||||
@@ -218,7 +263,37 @@ impl Context{
|
|||||||
).await.map_err(Error::Response)?
|
).await.map_err(Error::Response)?
|
||||||
.json().await.map_err(Error::ReqwestJson)
|
.json().await.map_err(Error::ReqwestJson)
|
||||||
}
|
}
|
||||||
pub async fn release_submissions(&self,config:ReleaseRequest<'_>)->Result<(),Error>{
|
pub async fn get_mapfix_audit_events(&self,config:GetMapfixAuditEventsRequest)->Result<Vec<AuditEventReponse>,Error>{
|
||||||
|
let url_raw=format!("{}/mapfixes/{}/audit-events",self.0.base_url,config.MapfixID);
|
||||||
|
let mut url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?;
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut query_pairs=url.query_pairs_mut();
|
||||||
|
query_pairs.append_pair("Page",config.Page.to_string().as_str());
|
||||||
|
query_pairs.append_pair("Limit",config.Limit.to_string().as_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
response_ok(
|
||||||
|
self.0.get(url).await.map_err(Error::Reqwest)?
|
||||||
|
).await.map_err(Error::Response)?
|
||||||
|
.json().await.map_err(Error::ReqwestJson)
|
||||||
|
}
|
||||||
|
pub async fn get_submission_audit_events(&self,config:GetSubmissionAuditEventsRequest)->Result<Vec<AuditEventReponse>,Error>{
|
||||||
|
let url_raw=format!("{}/submissions/{}/audit-events",self.0.base_url,config.SubmissionID);
|
||||||
|
let mut url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?;
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut query_pairs=url.query_pairs_mut();
|
||||||
|
query_pairs.append_pair("Page",config.Page.to_string().as_str());
|
||||||
|
query_pairs.append_pair("Limit",config.Limit.to_string().as_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
response_ok(
|
||||||
|
self.0.get(url).await.map_err(Error::Reqwest)?
|
||||||
|
).await.map_err(Error::Response)?
|
||||||
|
.json().await.map_err(Error::ReqwestJson)
|
||||||
|
}
|
||||||
|
pub async fn release_submissions(&self,config:ReleaseRequest<'_>)->Result<OperationIDResponse,Error>{
|
||||||
let url_raw=format!("{}/release-submissions",self.0.base_url);
|
let url_raw=format!("{}/release-submissions",self.0.base_url);
|
||||||
let url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?;
|
let url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?;
|
||||||
|
|
||||||
@@ -226,8 +301,7 @@ impl Context{
|
|||||||
|
|
||||||
response_ok(
|
response_ok(
|
||||||
self.0.post(url,body).await.map_err(Error::Reqwest)?
|
self.0.post(url,body).await.map_err(Error::Reqwest)?
|
||||||
).await.map_err(Error::Response)?;
|
).await.map_err(Error::Response)?
|
||||||
|
.json().await.map_err(Error::ReqwestJson)
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,6 @@ impl<Items> std::error::Error for SingleItemError<Items> where Items:std::fmt::D
|
|||||||
pub type ScriptSingleItemError=SingleItemError<Vec<ScriptID>>;
|
pub type ScriptSingleItemError=SingleItemError<Vec<ScriptID>>;
|
||||||
pub type ScriptPolicySingleItemError=SingleItemError<Vec<ScriptPolicyID>>;
|
pub type ScriptPolicySingleItemError=SingleItemError<Vec<ScriptPolicyID>>;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct UrlAndBody{
|
pub struct UrlAndBody{
|
||||||
pub url:url::Url,
|
pub url:url::Url,
|
||||||
@@ -76,7 +75,7 @@ pub enum GameID{
|
|||||||
FlyTrials=5,
|
FlyTrials=5,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Serialize)]
|
#[derive(Clone,Debug,serde::Serialize)]
|
||||||
pub struct CreateMapfixRequest<'a>{
|
pub struct CreateMapfixRequest<'a>{
|
||||||
pub OperationID:OperationID,
|
pub OperationID:OperationID,
|
||||||
@@ -89,13 +88,13 @@ pub struct CreateMapfixRequest<'a>{
|
|||||||
pub TargetAssetID:u64,
|
pub TargetAssetID:u64,
|
||||||
pub Description:&'a str,
|
pub Description:&'a str,
|
||||||
}
|
}
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Deserialize)]
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
pub struct MapfixIDResponse{
|
pub struct MapfixIDResponse{
|
||||||
pub MapfixID:MapfixID,
|
pub MapfixID:MapfixID,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Serialize)]
|
#[derive(Clone,Debug,serde::Serialize)]
|
||||||
pub struct CreateSubmissionRequest<'a>{
|
pub struct CreateSubmissionRequest<'a>{
|
||||||
pub OperationID:OperationID,
|
pub OperationID:OperationID,
|
||||||
@@ -108,7 +107,7 @@ pub struct CreateSubmissionRequest<'a>{
|
|||||||
pub Status:u32,
|
pub Status:u32,
|
||||||
pub Roles:u32,
|
pub Roles:u32,
|
||||||
}
|
}
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Deserialize)]
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
pub struct SubmissionIDResponse{
|
pub struct SubmissionIDResponse{
|
||||||
pub SubmissionID:SubmissionID,
|
pub SubmissionID:SubmissionID,
|
||||||
@@ -127,11 +126,11 @@ pub enum ResourceType{
|
|||||||
Submission=2,
|
Submission=2,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
pub struct GetScriptRequest{
|
pub struct GetScriptRequest{
|
||||||
pub ScriptID:ScriptID,
|
pub ScriptID:ScriptID,
|
||||||
}
|
}
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Serialize)]
|
#[derive(Clone,Debug,serde::Serialize)]
|
||||||
pub struct GetScriptsRequest<'a>{
|
pub struct GetScriptsRequest<'a>{
|
||||||
pub Page:u32,
|
pub Page:u32,
|
||||||
@@ -151,7 +150,7 @@ pub struct GetScriptsRequest<'a>{
|
|||||||
pub struct HashRequest<'a>{
|
pub struct HashRequest<'a>{
|
||||||
pub hash:&'a str,
|
pub hash:&'a str,
|
||||||
}
|
}
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Deserialize)]
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
pub struct ScriptResponse{
|
pub struct ScriptResponse{
|
||||||
pub ID:ScriptID,
|
pub ID:ScriptID,
|
||||||
@@ -161,7 +160,7 @@ pub struct ScriptResponse{
|
|||||||
pub ResourceType:ResourceType,
|
pub ResourceType:ResourceType,
|
||||||
pub ResourceID:ResourceID,
|
pub ResourceID:ResourceID,
|
||||||
}
|
}
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Serialize)]
|
#[derive(Clone,Debug,serde::Serialize)]
|
||||||
pub struct CreateScriptRequest<'a>{
|
pub struct CreateScriptRequest<'a>{
|
||||||
pub Name:&'a str,
|
pub Name:&'a str,
|
||||||
@@ -170,7 +169,7 @@ pub struct CreateScriptRequest<'a>{
|
|||||||
#[serde(skip_serializing_if="Option::is_none")]
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
pub ResourceID:Option<ResourceID>,
|
pub ResourceID:Option<ResourceID>,
|
||||||
}
|
}
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Deserialize)]
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
pub struct ScriptIDResponse{
|
pub struct ScriptIDResponse{
|
||||||
pub ScriptID:ScriptID,
|
pub ScriptID:ScriptID,
|
||||||
@@ -186,11 +185,11 @@ pub enum Policy{
|
|||||||
Replace=4,
|
Replace=4,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
pub struct GetScriptPolicyRequest{
|
pub struct GetScriptPolicyRequest{
|
||||||
pub ScriptPolicyID:ScriptPolicyID,
|
pub ScriptPolicyID:ScriptPolicyID,
|
||||||
}
|
}
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Serialize)]
|
#[derive(Clone,Debug,serde::Serialize)]
|
||||||
pub struct GetScriptPoliciesRequest<'a>{
|
pub struct GetScriptPoliciesRequest<'a>{
|
||||||
pub Page:u32,
|
pub Page:u32,
|
||||||
@@ -202,7 +201,7 @@ pub struct GetScriptPoliciesRequest<'a>{
|
|||||||
#[serde(skip_serializing_if="Option::is_none")]
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
pub Policy:Option<Policy>,
|
pub Policy:Option<Policy>,
|
||||||
}
|
}
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Deserialize)]
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
pub struct ScriptPolicyResponse{
|
pub struct ScriptPolicyResponse{
|
||||||
pub ID:ScriptPolicyID,
|
pub ID:ScriptPolicyID,
|
||||||
@@ -210,20 +209,20 @@ pub struct ScriptPolicyResponse{
|
|||||||
pub ToScriptID:ScriptID,
|
pub ToScriptID:ScriptID,
|
||||||
pub Policy:Policy
|
pub Policy:Policy
|
||||||
}
|
}
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Serialize)]
|
#[derive(Clone,Debug,serde::Serialize)]
|
||||||
pub struct CreateScriptPolicyRequest{
|
pub struct CreateScriptPolicyRequest{
|
||||||
pub FromScriptID:ScriptID,
|
pub FromScriptID:ScriptID,
|
||||||
pub ToScriptID:ScriptID,
|
pub ToScriptID:ScriptID,
|
||||||
pub Policy:Policy,
|
pub Policy:Policy,
|
||||||
}
|
}
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Deserialize)]
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
pub struct ScriptPolicyIDResponse{
|
pub struct ScriptPolicyIDResponse{
|
||||||
pub ScriptPolicyID:ScriptPolicyID,
|
pub ScriptPolicyID:ScriptPolicyID,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Serialize)]
|
#[derive(Clone,Debug,serde::Serialize)]
|
||||||
pub struct UpdateScriptPolicyRequest{
|
pub struct UpdateScriptPolicyRequest{
|
||||||
pub ID:ScriptPolicyID,
|
pub ID:ScriptPolicyID,
|
||||||
@@ -235,7 +234,7 @@ pub struct UpdateScriptPolicyRequest{
|
|||||||
pub Policy:Option<Policy>,
|
pub Policy:Option<Policy>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct UpdateSubmissionModelRequest{
|
pub struct UpdateSubmissionModelRequest{
|
||||||
pub SubmissionID:SubmissionID,
|
pub SubmissionID:SubmissionID,
|
||||||
@@ -252,6 +251,73 @@ pub enum Sort{
|
|||||||
DateDescending=4,
|
DateDescending=4,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Debug,serde_repr::Serialize_repr,serde_repr::Deserialize_repr)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum MapfixStatus{
|
||||||
|
// Phase: Creation
|
||||||
|
UnderConstruction=0,
|
||||||
|
ChangesRequested=1,
|
||||||
|
|
||||||
|
// Phase: Review
|
||||||
|
Submitting=2,
|
||||||
|
Submitted=3,
|
||||||
|
|
||||||
|
// Phase: Testing
|
||||||
|
AcceptedUnvalidated=4, // pending script review, can re-trigger validation
|
||||||
|
Validating=5,
|
||||||
|
Validated=6,
|
||||||
|
Uploading=7,
|
||||||
|
Uploaded=8, // uploaded to the group, but pending release
|
||||||
|
Releasing=11,
|
||||||
|
|
||||||
|
// Phase: Final MapfixStatus
|
||||||
|
Rejected=9,
|
||||||
|
Released=10,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(nonstandard_style)]
|
||||||
|
#[derive(Clone,Debug)]
|
||||||
|
pub struct GetMapfixesRequest<'a>{
|
||||||
|
pub Page:u32,
|
||||||
|
pub Limit:u32,
|
||||||
|
pub Sort:Option<Sort>,
|
||||||
|
pub DisplayName:Option<&'a str>,
|
||||||
|
pub Creator:Option<&'a str>,
|
||||||
|
pub GameID:Option<GameID>,
|
||||||
|
pub Submitter:Option<u64>,
|
||||||
|
pub AssetID:Option<u64>,
|
||||||
|
pub AssetVersion:Option<u64>,
|
||||||
|
pub TargetAssetID:Option<u64>,
|
||||||
|
pub StatusID:Option<MapfixStatus>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(nonstandard_style)]
|
||||||
|
#[derive(Clone,Debug,serde::Serialize,serde::Deserialize)]
|
||||||
|
pub struct MapfixResponse{
|
||||||
|
pub ID:MapfixID,
|
||||||
|
pub DisplayName:String,
|
||||||
|
pub Creator:String,
|
||||||
|
pub GameID:u32,
|
||||||
|
pub CreatedAt:i64,
|
||||||
|
pub UpdatedAt:i64,
|
||||||
|
pub Submitter:u64,
|
||||||
|
pub AssetID:u64,
|
||||||
|
pub AssetVersion:u64,
|
||||||
|
pub ValidatedAssetID:Option<u64>,
|
||||||
|
pub ValidatedAssetVersion:Option<u64>,
|
||||||
|
pub Completed:bool,
|
||||||
|
pub TargetAssetID:u64,
|
||||||
|
pub StatusID:MapfixStatus,
|
||||||
|
pub Description:String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(nonstandard_style)]
|
||||||
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
|
pub struct MapfixesResponse{
|
||||||
|
pub Total:u64,
|
||||||
|
pub Mapfixes:Vec<MapfixResponse>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone,Debug,serde_repr::Deserialize_repr)]
|
#[derive(Clone,Debug,serde_repr::Deserialize_repr)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum SubmissionStatus{
|
pub enum SubmissionStatus{
|
||||||
@@ -275,7 +341,7 @@ pub enum SubmissionStatus{
|
|||||||
Released=10,
|
Released=10,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct GetSubmissionsRequest<'a>{
|
pub struct GetSubmissionsRequest<'a>{
|
||||||
pub Page:u32,
|
pub Page:u32,
|
||||||
@@ -286,11 +352,12 @@ pub struct GetSubmissionsRequest<'a>{
|
|||||||
pub GameID:Option<GameID>,
|
pub GameID:Option<GameID>,
|
||||||
pub Submitter:Option<u64>,
|
pub Submitter:Option<u64>,
|
||||||
pub AssetID:Option<u64>,
|
pub AssetID:Option<u64>,
|
||||||
|
pub AssetVersion:Option<u64>,
|
||||||
pub UploadedAssetID:Option<u64>,
|
pub UploadedAssetID:Option<u64>,
|
||||||
pub StatusID:Option<SubmissionStatus>,
|
pub StatusID:Option<SubmissionStatus>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Deserialize)]
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
pub struct SubmissionResponse{
|
pub struct SubmissionResponse{
|
||||||
pub ID:SubmissionID,
|
pub ID:SubmissionID,
|
||||||
@@ -302,18 +369,20 @@ pub struct SubmissionResponse{
|
|||||||
pub Submitter:u64,
|
pub Submitter:u64,
|
||||||
pub AssetID:u64,
|
pub AssetID:u64,
|
||||||
pub AssetVersion:u64,
|
pub AssetVersion:u64,
|
||||||
|
pub ValidatedAssetID:Option<u64>,
|
||||||
|
pub ValidatedAssetVersion:Option<u64>,
|
||||||
pub UploadedAssetID:u64,
|
pub UploadedAssetID:u64,
|
||||||
pub StatusID:SubmissionStatus,
|
pub StatusID:SubmissionStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Deserialize)]
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
pub struct SubmissionsResponse{
|
pub struct SubmissionsResponse{
|
||||||
pub Total:u64,
|
pub Total:u64,
|
||||||
pub Submissions:Vec<SubmissionResponse>,
|
pub Submissions:Vec<SubmissionResponse>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct GetMapsRequest<'a>{
|
pub struct GetMapsRequest<'a>{
|
||||||
pub Page:u32,
|
pub Page:u32,
|
||||||
@@ -324,7 +393,7 @@ pub struct GetMapsRequest<'a>{
|
|||||||
pub GameID:Option<GameID>,
|
pub GameID:Option<GameID>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Deserialize)]
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
pub struct MapResponse{
|
pub struct MapResponse{
|
||||||
pub ID:i64,
|
pub ID:i64,
|
||||||
@@ -334,7 +403,119 @@ pub struct MapResponse{
|
|||||||
pub Date:i64,
|
pub Date:i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
|
#[derive(Clone,Debug)]
|
||||||
|
pub struct GetMapfixAuditEventsRequest{
|
||||||
|
pub Page:u32,
|
||||||
|
pub Limit:u32,
|
||||||
|
pub MapfixID:i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(nonstandard_style)]
|
||||||
|
#[derive(Clone,Debug)]
|
||||||
|
pub struct GetSubmissionAuditEventsRequest{
|
||||||
|
pub Page:u32,
|
||||||
|
pub Limit:u32,
|
||||||
|
pub SubmissionID:i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Debug,serde_repr::Deserialize_repr)]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum AuditEventType{
|
||||||
|
Action=0,
|
||||||
|
Comment=1,
|
||||||
|
ChangeModel=2,
|
||||||
|
ChangeValidatedModel=3,
|
||||||
|
ChangeDisplayName=4,
|
||||||
|
ChangeCreator=5,
|
||||||
|
Error=6,
|
||||||
|
CheckList=7,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
|
pub struct AuditEventAction{
|
||||||
|
pub target_status:MapfixStatus,
|
||||||
|
}
|
||||||
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
|
pub struct AuditEventComment{
|
||||||
|
pub comment:String,
|
||||||
|
}
|
||||||
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
|
pub struct AuditEventChangeModel{
|
||||||
|
pub old_model_id:u64,
|
||||||
|
pub old_model_version:u64,
|
||||||
|
pub new_model_id:u64,
|
||||||
|
pub new_model_version:u64,
|
||||||
|
}
|
||||||
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
|
pub struct AuditEventChangeValidatedModel{
|
||||||
|
pub validated_model_id:u64,
|
||||||
|
pub validated_model_version:u64,
|
||||||
|
}
|
||||||
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
|
pub struct AuditEventChangeName{
|
||||||
|
pub old_name:String,
|
||||||
|
pub new_name:String,
|
||||||
|
}
|
||||||
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
|
pub struct AuditEventError{
|
||||||
|
pub error:String,
|
||||||
|
}
|
||||||
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
|
pub struct AuditEventCheck{
|
||||||
|
pub name:String,
|
||||||
|
pub summary:String,
|
||||||
|
pub passed:bool,
|
||||||
|
}
|
||||||
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
|
pub struct AuditEventCheckList{
|
||||||
|
pub check_list:Vec<AuditEventCheck>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Debug)]
|
||||||
|
pub enum AuditEventData{
|
||||||
|
Action(AuditEventAction),
|
||||||
|
Comment(AuditEventComment),
|
||||||
|
ChangeModel(AuditEventChangeModel),
|
||||||
|
ChangeValidatedModel(AuditEventChangeValidatedModel),
|
||||||
|
ChangeDisplayName(AuditEventChangeName),
|
||||||
|
ChangeCreator(AuditEventChangeName),
|
||||||
|
Error(AuditEventError),
|
||||||
|
CheckList(AuditEventCheckList),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq,serde::Serialize,serde::Deserialize)]
|
||||||
|
pub struct AuditEventID(pub(crate)i64);
|
||||||
|
|
||||||
|
#[expect(nonstandard_style)]
|
||||||
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
|
pub struct AuditEventReponse{
|
||||||
|
pub ID:AuditEventID,
|
||||||
|
pub Date:i64,
|
||||||
|
pub User:u64,
|
||||||
|
pub Username:String,
|
||||||
|
pub ResourceType:ResourceType,
|
||||||
|
pub ResourceID:ResourceID,
|
||||||
|
pub EventType:AuditEventType,
|
||||||
|
EventData:serde_json::Value,
|
||||||
|
}
|
||||||
|
impl AuditEventReponse{
|
||||||
|
pub fn data(self)->serde_json::Result<AuditEventData>{
|
||||||
|
Ok(match self.EventType{
|
||||||
|
AuditEventType::Action=>AuditEventData::Action(serde_json::from_value(self.EventData)?),
|
||||||
|
AuditEventType::Comment=>AuditEventData::Comment(serde_json::from_value(self.EventData)?),
|
||||||
|
AuditEventType::ChangeModel=>AuditEventData::ChangeModel(serde_json::from_value(self.EventData)?),
|
||||||
|
AuditEventType::ChangeValidatedModel=>AuditEventData::ChangeValidatedModel(serde_json::from_value(self.EventData)?),
|
||||||
|
AuditEventType::ChangeDisplayName=>AuditEventData::ChangeDisplayName(serde_json::from_value(self.EventData)?),
|
||||||
|
AuditEventType::ChangeCreator=>AuditEventData::ChangeCreator(serde_json::from_value(self.EventData)?),
|
||||||
|
AuditEventType::Error=>AuditEventData::Error(serde_json::from_value(self.EventData)?),
|
||||||
|
AuditEventType::CheckList=>AuditEventData::CheckList(serde_json::from_value(self.EventData)?),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Serialize)]
|
#[derive(Clone,Debug,serde::Serialize)]
|
||||||
pub struct Check{
|
pub struct Check{
|
||||||
pub Name:&'static str,
|
pub Name:&'static str,
|
||||||
@@ -342,7 +523,7 @@ pub struct Check{
|
|||||||
pub Passed:bool,
|
pub Passed:bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct ActionSubmissionSubmittedRequest{
|
pub struct ActionSubmissionSubmittedRequest{
|
||||||
pub SubmissionID:SubmissionID,
|
pub SubmissionID:SubmissionID,
|
||||||
@@ -352,33 +533,33 @@ pub struct ActionSubmissionSubmittedRequest{
|
|||||||
pub GameID:GameID,
|
pub GameID:GameID,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct ActionSubmissionRequestChangesRequest{
|
pub struct ActionSubmissionRequestChangesRequest{
|
||||||
pub SubmissionID:SubmissionID,
|
pub SubmissionID:SubmissionID,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct ActionSubmissionUploadedRequest{
|
pub struct ActionSubmissionUploadedRequest{
|
||||||
pub SubmissionID:SubmissionID,
|
pub SubmissionID:SubmissionID,
|
||||||
pub UploadedAssetID:u64,
|
pub UploadedAssetID:u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct ActionSubmissionAcceptedRequest{
|
pub struct ActionSubmissionAcceptedRequest{
|
||||||
pub SubmissionID:SubmissionID,
|
pub SubmissionID:SubmissionID,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct CreateSubmissionAuditErrorRequest{
|
pub struct CreateSubmissionAuditErrorRequest{
|
||||||
pub SubmissionID:SubmissionID,
|
pub SubmissionID:SubmissionID,
|
||||||
pub ErrorMessage:String,
|
pub ErrorMessage:String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct CreateSubmissionAuditCheckListRequest<'a>{
|
pub struct CreateSubmissionAuditCheckListRequest<'a>{
|
||||||
pub SubmissionID:SubmissionID,
|
pub SubmissionID:SubmissionID,
|
||||||
@@ -387,8 +568,16 @@ pub struct CreateSubmissionAuditCheckListRequest<'a>{
|
|||||||
|
|
||||||
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq,serde::Serialize,serde::Deserialize)]
|
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq,serde::Serialize,serde::Deserialize)]
|
||||||
pub struct SubmissionID(pub(crate)i64);
|
pub struct SubmissionID(pub(crate)i64);
|
||||||
|
impl SubmissionID{
|
||||||
|
pub const fn new(value:i64)->Self{
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
pub const fn value(&self)->i64{
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct UpdateMapfixModelRequest{
|
pub struct UpdateMapfixModelRequest{
|
||||||
pub MapfixID:MapfixID,
|
pub MapfixID:MapfixID,
|
||||||
@@ -396,7 +585,7 @@ pub struct UpdateMapfixModelRequest{
|
|||||||
pub ModelVersion:u64,
|
pub ModelVersion:u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct ActionMapfixSubmittedRequest{
|
pub struct ActionMapfixSubmittedRequest{
|
||||||
pub MapfixID:MapfixID,
|
pub MapfixID:MapfixID,
|
||||||
@@ -406,32 +595,32 @@ pub struct ActionMapfixSubmittedRequest{
|
|||||||
pub GameID:GameID,
|
pub GameID:GameID,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct ActionMapfixRequestChangesRequest{
|
pub struct ActionMapfixRequestChangesRequest{
|
||||||
pub MapfixID:MapfixID,
|
pub MapfixID:MapfixID,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct ActionMapfixUploadedRequest{
|
pub struct ActionMapfixUploadedRequest{
|
||||||
pub MapfixID:MapfixID,
|
pub MapfixID:MapfixID,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct ActionMapfixAcceptedRequest{
|
pub struct ActionMapfixAcceptedRequest{
|
||||||
pub MapfixID:MapfixID,
|
pub MapfixID:MapfixID,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct CreateMapfixAuditErrorRequest{
|
pub struct CreateMapfixAuditErrorRequest{
|
||||||
pub MapfixID:MapfixID,
|
pub MapfixID:MapfixID,
|
||||||
pub ErrorMessage:String,
|
pub ErrorMessage:String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct CreateMapfixAuditCheckListRequest<'a>{
|
pub struct CreateMapfixAuditCheckListRequest<'a>{
|
||||||
pub MapfixID:MapfixID,
|
pub MapfixID:MapfixID,
|
||||||
@@ -440,8 +629,16 @@ pub struct CreateMapfixAuditCheckListRequest<'a>{
|
|||||||
|
|
||||||
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq,serde::Serialize,serde::Deserialize)]
|
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq,serde::Serialize,serde::Deserialize)]
|
||||||
pub struct MapfixID(pub(crate)i64);
|
pub struct MapfixID(pub(crate)i64);
|
||||||
|
impl MapfixID{
|
||||||
|
pub const fn new(value:i64)->Self{
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
pub const fn value(&self)->i64{
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub struct ActionOperationFailedRequest{
|
pub struct ActionOperationFailedRequest{
|
||||||
pub OperationID:OperationID,
|
pub OperationID:OperationID,
|
||||||
@@ -468,7 +665,7 @@ impl Resource{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(Clone,Debug,serde::Serialize)]
|
#[derive(Clone,Debug,serde::Serialize)]
|
||||||
pub struct ReleaseInfo{
|
pub struct ReleaseInfo{
|
||||||
pub SubmissionID:SubmissionID,
|
pub SubmissionID:SubmissionID,
|
||||||
@@ -478,3 +675,8 @@ pub struct ReleaseInfo{
|
|||||||
pub struct ReleaseRequest<'a>{
|
pub struct ReleaseRequest<'a>{
|
||||||
pub schedule:&'a [ReleaseInfo],
|
pub schedule:&'a [ReleaseInfo],
|
||||||
}
|
}
|
||||||
|
#[expect(nonstandard_style)]
|
||||||
|
#[derive(Clone,Debug,serde::Deserialize)]
|
||||||
|
pub struct OperationIDResponse{
|
||||||
|
pub OperationID:OperationID,
|
||||||
|
}
|
||||||
@@ -4,18 +4,18 @@ version = "0.1.1"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-nats = "0.42.0"
|
async-nats = "0.45.0"
|
||||||
futures = "0.3.31"
|
futures = "0.3.31"
|
||||||
rbx_asset = { version = "0.4.9", features = ["gzip", "rustls-tls"], default-features = false, registry = "strafesnet" }
|
rbx_asset = { version = "0.5.0", features = ["gzip", "rustls-tls"], default-features = false, registry = "strafesnet" }
|
||||||
rbx_binary = "1.0.0"
|
rbx_binary = "2.0.0"
|
||||||
rbx_dom_weak = "3.0.0"
|
rbx_dom_weak = "4.0.0"
|
||||||
rbx_reflection_database = "1.0.3"
|
rbx_reflection_database = "2.0.1"
|
||||||
rbx_xml = "1.0.0"
|
rbx_xml = "2.0.0"
|
||||||
|
regex = { version = "1.11.3", default-features = false }
|
||||||
serde = { version = "1.0.215", features = ["derive"] }
|
serde = { version = "1.0.215", features = ["derive"] }
|
||||||
serde_json = "1.0.133"
|
serde_json = "1.0.133"
|
||||||
siphasher = "1.0.1"
|
siphasher = "1.0.1"
|
||||||
tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread", "signal"] }
|
tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread", "signal"] }
|
||||||
heck = "0.5.0"
|
heck = "0.5.0"
|
||||||
lazy-regex = "3.4.1"
|
rust-grpc = { version = "1.6.1", registry = "strafesnet" }
|
||||||
rust-grpc = { version = "1.2.1", registry = "strafesnet" }
|
tonic = "0.14.1"
|
||||||
tonic = "0.13.1"
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use heck::{ToSnakeCase,ToTitleCase};
|
|||||||
use rbx_dom_weak::Instance;
|
use rbx_dom_weak::Instance;
|
||||||
use rust_grpc::validator::Check;
|
use rust_grpc::validator::Check;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[expect(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error{
|
pub enum Error{
|
||||||
ModelInfoDownload(rbx_asset::cloud::GetError),
|
ModelInfoDownload(rbx_asset::cloud::GetError),
|
||||||
@@ -24,7 +24,16 @@ impl std::fmt::Display for Error{
|
|||||||
}
|
}
|
||||||
impl std::error::Error for Error{}
|
impl std::error::Error for Error{}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
macro_rules! lazy_regex{
|
||||||
|
($r:literal)=>{{
|
||||||
|
use regex::Regex;
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
static RE:LazyLock<Regex>=LazyLock::new(||Regex::new($r).unwrap());
|
||||||
|
&RE
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(nonstandard_style)]
|
||||||
pub struct CheckRequest{
|
pub struct CheckRequest{
|
||||||
ModelID:u64,
|
ModelID:u64,
|
||||||
SkipChecks:bool,
|
SkipChecks:bool,
|
||||||
@@ -47,12 +56,20 @@ impl From<crate::nats_types::CheckSubmissionRequest> for CheckRequest{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq)]
|
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq,Ord,PartialOrd)]
|
||||||
struct ModeID(u64);
|
struct ModeID(u64);
|
||||||
impl ModeID{
|
impl ModeID{
|
||||||
const MAIN:Self=Self(0);
|
const MAIN:Self=Self(0);
|
||||||
const BONUS:Self=Self(1);
|
const BONUS:Self=Self(1);
|
||||||
}
|
}
|
||||||
|
impl std::fmt::Display for ModeID{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
match self{
|
||||||
|
&ModeID::MAIN=>write!(f,"Main"),
|
||||||
|
&ModeID(mode_id)=>write!(f,"Bonus{mode_id}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
enum Zone{
|
enum Zone{
|
||||||
Start,
|
Start,
|
||||||
Finish,
|
Finish,
|
||||||
@@ -62,7 +79,7 @@ struct ModeElement{
|
|||||||
zone:Zone,
|
zone:Zone,
|
||||||
mode_id:ModeID,
|
mode_id:ModeID,
|
||||||
}
|
}
|
||||||
#[allow(dead_code)]
|
#[expect(dead_code)]
|
||||||
pub enum IDParseError{
|
pub enum IDParseError{
|
||||||
NoCaptures,
|
NoCaptures,
|
||||||
ParseInt(core::num::ParseIntError),
|
ParseInt(core::num::ParseIntError),
|
||||||
@@ -79,7 +96,7 @@ impl std::str::FromStr for ModeElement{
|
|||||||
"BonusFinish"=>Ok(Self{zone:Zone::Finish,mode_id:ModeID::BONUS}),
|
"BonusFinish"=>Ok(Self{zone:Zone::Finish,mode_id:ModeID::BONUS}),
|
||||||
"BonusAnticheat"=>Ok(Self{zone:Zone::Anticheat,mode_id:ModeID::BONUS}),
|
"BonusAnticheat"=>Ok(Self{zone:Zone::Anticheat,mode_id:ModeID::BONUS}),
|
||||||
other=>{
|
other=>{
|
||||||
let everything_pattern=lazy_regex::lazy_regex!(r"^Bonus(\d+)Start$|^BonusStart(\d+)$|^Bonus(\d+)Finish$|^BonusFinish(\d+)$|^Bonus(\d+)Anticheat$|^BonusAnticheat(\d+)$");
|
let everything_pattern=lazy_regex!(r"^Bonus(\d+)Start$|^BonusStart(\d+)$|^Bonus(\d+)Finish$|^BonusFinish(\d+)$|^Bonus(\d+)Anticheat$|^BonusAnticheat(\d+)$");
|
||||||
if let Some(captures)=everything_pattern.captures(other){
|
if let Some(captures)=everything_pattern.captures(other){
|
||||||
if let Some(mode_id)=captures.get(1).or(captures.get(2)){
|
if let Some(mode_id)=captures.get(1).or(captures.get(2)){
|
||||||
return Ok(Self{
|
return Ok(Self{
|
||||||
@@ -139,16 +156,16 @@ impl std::str::FromStr for StageElement{
|
|||||||
type Err=IDParseError;
|
type Err=IDParseError;
|
||||||
fn from_str(s:&str)->Result<Self,Self::Err>{
|
fn from_str(s:&str)->Result<Self,Self::Err>{
|
||||||
// Trigger ForceTrigger Teleport ForceTeleport SpawnAt ForceSpawnAt
|
// Trigger ForceTrigger Teleport ForceTeleport SpawnAt ForceSpawnAt
|
||||||
let bonus_start_pattern=lazy_regex::lazy_regex!(r"^(?:Force)?(Teleport|SpawnAt|Trigger)(\d+)$");
|
let teleport_pattern=lazy_regex!(r"^(?:Force)?(Teleport|SpawnAt|Trigger)(\d+)$");
|
||||||
if let Some(captures)=bonus_start_pattern.captures(s){
|
if let Some(captures)=teleport_pattern.captures(s){
|
||||||
return Ok(StageElement{
|
return Ok(StageElement{
|
||||||
behaviour:StageElementBehaviour::Teleport,
|
behaviour:StageElementBehaviour::Teleport,
|
||||||
stage_id:StageID(captures[1].parse().map_err(IDParseError::ParseInt)?),
|
stage_id:StageID(captures[1].parse().map_err(IDParseError::ParseInt)?),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Spawn
|
// Spawn
|
||||||
let bonus_finish_pattern=lazy_regex::lazy_regex!(r"^Spawn(\d+)$");
|
let spawn_pattern=lazy_regex!(r"^Spawn(\d+)$");
|
||||||
if let Some(captures)=bonus_finish_pattern.captures(s){
|
if let Some(captures)=spawn_pattern.captures(s){
|
||||||
return Ok(StageElement{
|
return Ok(StageElement{
|
||||||
behaviour:StageElementBehaviour::Spawn,
|
behaviour:StageElementBehaviour::Spawn,
|
||||||
stage_id:StageID(captures[1].parse().map_err(IDParseError::ParseInt)?),
|
stage_id:StageID(captures[1].parse().map_err(IDParseError::ParseInt)?),
|
||||||
@@ -180,15 +197,15 @@ struct WormholeElement{
|
|||||||
impl std::str::FromStr for WormholeElement{
|
impl std::str::FromStr for WormholeElement{
|
||||||
type Err=IDParseError;
|
type Err=IDParseError;
|
||||||
fn from_str(s:&str)->Result<Self,Self::Err>{
|
fn from_str(s:&str)->Result<Self,Self::Err>{
|
||||||
let bonus_start_pattern=lazy_regex::lazy_regex!(r"^WormholeIn(\d+)$");
|
let wormhole_in_pattern=lazy_regex!(r"^WormholeIn(\d+)$");
|
||||||
if let Some(captures)=bonus_start_pattern.captures(s){
|
if let Some(captures)=wormhole_in_pattern.captures(s){
|
||||||
return Ok(Self{
|
return Ok(Self{
|
||||||
behaviour:WormholeBehaviour::In,
|
behaviour:WormholeBehaviour::In,
|
||||||
wormhole_id:WormholeID(captures[1].parse().map_err(IDParseError::ParseInt)?),
|
wormhole_id:WormholeID(captures[1].parse().map_err(IDParseError::ParseInt)?),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let bonus_finish_pattern=lazy_regex::lazy_regex!(r"^WormholeOut(\d+)$");
|
let wormhole_out_pattern=lazy_regex!(r"^WormholeOut(\d+)$");
|
||||||
if let Some(captures)=bonus_finish_pattern.captures(s){
|
if let Some(captures)=wormhole_out_pattern.captures(s){
|
||||||
return Ok(Self{
|
return Ok(Self{
|
||||||
behaviour:WormholeBehaviour::Out,
|
behaviour:WormholeBehaviour::Out,
|
||||||
wormhole_id:WormholeID(captures[1].parse().map_err(IDParseError::ParseInt)?),
|
wormhole_id:WormholeID(captures[1].parse().map_err(IDParseError::ParseInt)?),
|
||||||
@@ -206,6 +223,15 @@ impl std::fmt::Display for WormholeElement{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn count_sequential(modes:&HashMap<ModeID,Vec<&Instance>>)->usize{
|
||||||
|
for mode_id in 0..modes.len(){
|
||||||
|
if !modes.contains_key(&ModeID(mode_id as u64)){
|
||||||
|
return mode_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return modes.len();
|
||||||
|
}
|
||||||
|
|
||||||
/// Count various map elements
|
/// Count various map elements
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Counts<'a>{
|
struct Counts<'a>{
|
||||||
@@ -225,6 +251,24 @@ pub struct ModelInfo<'a>{
|
|||||||
counts:Counts<'a>,
|
counts:Counts<'a>,
|
||||||
unanchored_parts:Vec<&'a Instance>,
|
unanchored_parts:Vec<&'a Instance>,
|
||||||
}
|
}
|
||||||
|
impl ModelInfo<'_>{
|
||||||
|
pub fn count_modes(&self)->Option<usize>{
|
||||||
|
let start_zones_count=self.counts.mode_start_counts.len();
|
||||||
|
let finish_zones_count=self.counts.mode_finish_counts.len();
|
||||||
|
let sequential_start_zones=count_sequential(&self.counts.mode_start_counts);
|
||||||
|
let sequential_finish_zones=count_sequential(&self.counts.mode_finish_counts);
|
||||||
|
// all counts must match
|
||||||
|
if start_zones_count==finish_zones_count
|
||||||
|
&& sequential_start_zones==sequential_finish_zones
|
||||||
|
&& start_zones_count==sequential_start_zones
|
||||||
|
&& finish_zones_count==sequential_finish_zones
|
||||||
|
{
|
||||||
|
Some(start_zones_count)
|
||||||
|
}else{
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_model_info<'a>(dom:&'a rbx_dom_weak::WeakDom,model_instance:&'a rbx_dom_weak::Instance)->ModelInfo<'a>{
|
pub fn get_model_info<'a>(dom:&'a rbx_dom_weak::WeakDom,model_instance:&'a rbx_dom_weak::Instance)->ModelInfo<'a>{
|
||||||
// extract model info
|
// extract model info
|
||||||
@@ -237,7 +281,7 @@ pub fn get_model_info<'a>(dom:&'a rbx_dom_weak::WeakDom,model_instance:&'a rbx_d
|
|||||||
let mut unanchored_parts=Vec::new();
|
let mut unanchored_parts=Vec::new();
|
||||||
let anchored_ustr=rbx_dom_weak::ustr("Anchored");
|
let anchored_ustr=rbx_dom_weak::ustr("Anchored");
|
||||||
|
|
||||||
let db=rbx_reflection_database::get();
|
let db=rbx_reflection_database::get().unwrap();
|
||||||
let base_part=&db.classes["BasePart"];
|
let base_part=&db.classes["BasePart"];
|
||||||
let base_parts=dom.descendants_of(model_instance.referent()).filter(|&instance|
|
let base_parts=dom.descendants_of(model_instance.referent()).filter(|&instance|
|
||||||
db.classes.get(instance.class.as_str()).is_some_and(|class|
|
db.classes.get(instance.class.as_str()).is_some_and(|class|
|
||||||
@@ -398,7 +442,7 @@ pub struct MapInfoOwned{
|
|||||||
pub creator:String,
|
pub creator:String,
|
||||||
pub game_id:GameID,
|
pub game_id:GameID,
|
||||||
}
|
}
|
||||||
#[allow(dead_code)]
|
#[expect(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum IntoMapInfoOwnedError{
|
pub enum IntoMapInfoOwnedError{
|
||||||
DisplayName(StringValueError),
|
DisplayName(StringValueError),
|
||||||
@@ -446,6 +490,8 @@ struct MapCheck<'a>{
|
|||||||
mode_finish_counts:SetDifferenceCheck<SetDifferenceCheckContextAtLeastOne<ModeID,Vec<&'a Instance>>>,
|
mode_finish_counts:SetDifferenceCheck<SetDifferenceCheckContextAtLeastOne<ModeID,Vec<&'a Instance>>>,
|
||||||
// Check for dangling MapAnticheat zones (no associated MapStart)
|
// Check for dangling MapAnticheat zones (no associated MapStart)
|
||||||
mode_anticheat_counts:SetDifferenceCheck<SetDifferenceCheckContextAllowNone<ModeID,Vec<&'a Instance>>>,
|
mode_anticheat_counts:SetDifferenceCheck<SetDifferenceCheckContextAllowNone<ModeID,Vec<&'a Instance>>>,
|
||||||
|
// Check that modes are sequential
|
||||||
|
modes_sequential:Result<(),Vec<ModeID>>,
|
||||||
// Spawn1 must exist
|
// Spawn1 must exist
|
||||||
spawn1:Result<Exists,Absent>,
|
spawn1:Result<Exists,Absent>,
|
||||||
// Check for dangling Teleport# (no associated Spawn#)
|
// Check for dangling Teleport# (no associated Spawn#)
|
||||||
@@ -514,6 +560,25 @@ impl<'a> ModelInfo<'a>{
|
|||||||
let mode_anticheat_counts=SetDifferenceCheckContextAllowNone::new(self.counts.mode_anticheat_counts)
|
let mode_anticheat_counts=SetDifferenceCheckContextAllowNone::new(self.counts.mode_anticheat_counts)
|
||||||
.check(&self.counts.mode_start_counts);
|
.check(&self.counts.mode_start_counts);
|
||||||
|
|
||||||
|
// There must not be non-sequential modes. If Bonus100 exists, Bonuses 1-99 had better also exist.
|
||||||
|
let modes_sequential={
|
||||||
|
let sequential=count_sequential(&self.counts.mode_start_counts);
|
||||||
|
if sequential==self.counts.mode_start_counts.len(){
|
||||||
|
Ok(())
|
||||||
|
}else{
|
||||||
|
let mut non_sequential=Vec::with_capacity(self.counts.mode_start_counts.len()-sequential);
|
||||||
|
for (&mode_id,_) in &self.counts.mode_start_counts{
|
||||||
|
let ModeID(mode_id_u64)=mode_id;
|
||||||
|
if !(mode_id_u64<sequential as u64){
|
||||||
|
non_sequential.push(mode_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// sort so it's prettier when it prints out
|
||||||
|
non_sequential.sort();
|
||||||
|
Err(non_sequential)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// There must be exactly one start zone for every mode in the map.
|
// There must be exactly one start zone for every mode in the map.
|
||||||
let mode_start_counts=DuplicateCheckContext(self.counts.mode_start_counts).check(|c|1<c.len());
|
let mode_start_counts=DuplicateCheckContext(self.counts.mode_start_counts).check(|c|1<c.len());
|
||||||
|
|
||||||
@@ -550,6 +615,7 @@ impl<'a> ModelInfo<'a>{
|
|||||||
mode_start_counts,
|
mode_start_counts,
|
||||||
mode_finish_counts,
|
mode_finish_counts,
|
||||||
mode_anticheat_counts,
|
mode_anticheat_counts,
|
||||||
|
modes_sequential,
|
||||||
spawn1,
|
spawn1,
|
||||||
teleport_counts,
|
teleport_counts,
|
||||||
spawn_counts,
|
spawn_counts,
|
||||||
@@ -573,6 +639,7 @@ impl MapCheck<'_>{
|
|||||||
mode_start_counts:DuplicateCheck(Ok(())),
|
mode_start_counts:DuplicateCheck(Ok(())),
|
||||||
mode_finish_counts:SetDifferenceCheck(Ok(())),
|
mode_finish_counts:SetDifferenceCheck(Ok(())),
|
||||||
mode_anticheat_counts:SetDifferenceCheck(Ok(())),
|
mode_anticheat_counts:SetDifferenceCheck(Ok(())),
|
||||||
|
modes_sequential:Ok(()),
|
||||||
spawn1:Ok(Exists),
|
spawn1:Ok(Exists),
|
||||||
teleport_counts:SetDifferenceCheck(Ok(())),
|
teleport_counts:SetDifferenceCheck(Ok(())),
|
||||||
spawn_counts:DuplicateCheck(Ok(())),
|
spawn_counts:DuplicateCheck(Ok(())),
|
||||||
@@ -746,6 +813,15 @@ impl MapCheck<'_>{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let sequential_modes=match &self.modes_sequential{
|
||||||
|
Ok(())=>passed!("SequentialModes"),
|
||||||
|
Err(context)=>{
|
||||||
|
let non_sequential=context.len();
|
||||||
|
let plural_non_sequential=if non_sequential==1{"mode"}else{"modes"};
|
||||||
|
let comma_separated=Separated::new(", ",||context);
|
||||||
|
summary_format!("SequentialModes","{non_sequential} {plural_non_sequential} should use a lower ModeID (no gaps): {comma_separated}")
|
||||||
|
}
|
||||||
|
};
|
||||||
let spawn1=match &self.spawn1{
|
let spawn1=match &self.spawn1{
|
||||||
Ok(Exists)=>passed!("Spawn1"),
|
Ok(Exists)=>passed!("Spawn1"),
|
||||||
Err(Absent)=>summary_format!("Spawn1","Model has no Spawn1"),
|
Err(Absent)=>summary_format!("Spawn1","Model has no Spawn1"),
|
||||||
@@ -824,6 +900,7 @@ impl MapCheck<'_>{
|
|||||||
extra_finish,
|
extra_finish,
|
||||||
missing_finish,
|
missing_finish,
|
||||||
dangling_anticheat,
|
dangling_anticheat,
|
||||||
|
sequential_modes,
|
||||||
spawn1,
|
spawn1,
|
||||||
dangling_teleport,
|
dangling_teleport,
|
||||||
duplicate_spawns,
|
duplicate_spawns,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::check::CheckListAndVersion;
|
use crate::check::CheckListAndVersion;
|
||||||
use crate::nats_types::CheckMapfixRequest;
|
use crate::nats_types::CheckMapfixRequest;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[expect(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error{
|
pub enum Error{
|
||||||
Check(crate::check::Error),
|
Check(crate::check::Error),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::check::CheckListAndVersion;
|
use crate::check::CheckListAndVersion;
|
||||||
use crate::nats_types::CheckSubmissionRequest;
|
use crate::nats_types::CheckSubmissionRequest;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[expect(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error{
|
pub enum Error{
|
||||||
Check(crate::check::Error),
|
Check(crate::check::Error),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::download::download_asset_version;
|
use crate::download::download_asset_version;
|
||||||
use crate::rbx_util::{get_root_instance,get_mapinfo,read_dom,MapInfo,ReadDomError,GetRootInstanceError,GameID};
|
use crate::rbx_util::{get_root_instance,get_mapinfo,read_dom,MapInfo,ReadDomError,GetRootInstanceError,GameID};
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[expect(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error{
|
pub enum Error{
|
||||||
CreatorTypeMustBeUser,
|
CreatorTypeMustBeUser,
|
||||||
@@ -17,11 +17,11 @@ impl std::fmt::Display for Error{
|
|||||||
}
|
}
|
||||||
impl std::error::Error for Error{}
|
impl std::error::Error for Error{}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
pub struct CreateRequest{
|
pub struct CreateRequest{
|
||||||
pub ModelID:u64,
|
pub ModelID:u64,
|
||||||
}
|
}
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
pub struct CreateResult{
|
pub struct CreateResult{
|
||||||
pub AssetOwner:u64,
|
pub AssetOwner:u64,
|
||||||
pub DisplayName:Option<String>,
|
pub DisplayName:Option<String>,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::nats_types::CreateMapfixRequest;
|
use crate::nats_types::CreateMapfixRequest;
|
||||||
use crate::create::CreateRequest;
|
use crate::create::CreateRequest;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[expect(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error{
|
pub enum Error{
|
||||||
Create(crate::create::Error),
|
Create(crate::create::Error),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use crate::nats_types::CreateSubmissionRequest;
|
|||||||
use crate::create::CreateRequest;
|
use crate::create::CreateRequest;
|
||||||
use crate::rbx_util::GameID;
|
use crate::rbx_util::GameID;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[expect(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error{
|
pub enum Error{
|
||||||
Create(crate::create::Error),
|
Create(crate::create::Error),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#[allow(dead_code)]
|
#[expect(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error{
|
pub enum Error{
|
||||||
ModelLocationDownload(rbx_asset::cloud::GetError),
|
ModelLocationDownload(rbx_asset::cloud::GetError),
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ impl Service{
|
|||||||
endpoint!(set_status_submitted,SubmittedRequest,NullResponse);
|
endpoint!(set_status_submitted,SubmittedRequest,NullResponse);
|
||||||
endpoint!(set_status_request_changes,MapfixId,NullResponse);
|
endpoint!(set_status_request_changes,MapfixId,NullResponse);
|
||||||
endpoint!(set_status_validated,MapfixId,NullResponse);
|
endpoint!(set_status_validated,MapfixId,NullResponse);
|
||||||
endpoint!(set_status_failed,MapfixId,NullResponse);
|
endpoint!(set_status_not_validated,MapfixId,NullResponse);
|
||||||
endpoint!(set_status_uploaded,MapfixId,NullResponse);
|
endpoint!(set_status_uploaded,MapfixId,NullResponse);
|
||||||
|
endpoint!(set_status_not_uploaded,MapfixId,NullResponse);
|
||||||
|
endpoint!(set_status_released,MapfixReleaseRequest,NullResponse);
|
||||||
|
endpoint!(set_status_not_released,MapfixId,NullResponse);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,5 +11,6 @@ impl Service{
|
|||||||
)->Self{
|
)->Self{
|
||||||
Self{client}
|
Self{client}
|
||||||
}
|
}
|
||||||
|
endpoint!(success,OperationSuccessRequest,NullResponse);
|
||||||
endpoint!(fail,OperationFailRequest,NullResponse);
|
endpoint!(fail,OperationFailRequest,NullResponse);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ impl Service{
|
|||||||
endpoint!(set_status_submitted,SubmittedRequest,NullResponse);
|
endpoint!(set_status_submitted,SubmittedRequest,NullResponse);
|
||||||
endpoint!(set_status_request_changes,SubmissionId,NullResponse);
|
endpoint!(set_status_request_changes,SubmissionId,NullResponse);
|
||||||
endpoint!(set_status_validated,SubmissionId,NullResponse);
|
endpoint!(set_status_validated,SubmissionId,NullResponse);
|
||||||
endpoint!(set_status_failed,SubmissionId,NullResponse);
|
endpoint!(set_status_not_validated,SubmissionId,NullResponse);
|
||||||
endpoint!(set_status_uploaded,StatusUploadedRequest,NullResponse);
|
endpoint!(set_status_uploaded,StatusUploadedRequest,NullResponse);
|
||||||
|
endpoint!(set_status_not_uploaded,SubmissionId,NullResponse);
|
||||||
|
endpoint!(set_status_released,SubmissionReleaseRequest,NullResponse);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,13 +13,15 @@ mod check_submission;
|
|||||||
mod create;
|
mod create;
|
||||||
mod create_mapfix;
|
mod create_mapfix;
|
||||||
mod create_submission;
|
mod create_submission;
|
||||||
|
mod release;
|
||||||
|
mod release_mapfix;
|
||||||
|
mod release_submissions_batch;
|
||||||
mod upload_mapfix;
|
mod upload_mapfix;
|
||||||
mod upload_submission;
|
mod upload_submission;
|
||||||
mod validator;
|
mod validator;
|
||||||
mod validate_mapfix;
|
mod validate_mapfix;
|
||||||
mod validate_submission;
|
mod validate_submission;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum StartupError{
|
pub enum StartupError{
|
||||||
API(tonic::transport::Error),
|
API(tonic::transport::Error),
|
||||||
@@ -47,24 +49,44 @@ async fn main()->Result<(),StartupError>{
|
|||||||
},
|
},
|
||||||
Err(e)=>panic!("{e}: ROBLOX_GROUP_ID env required"),
|
Err(e)=>panic!("{e}: ROBLOX_GROUP_ID env required"),
|
||||||
};
|
};
|
||||||
|
let load_asset_version_place_id=std::env::var("LOAD_ASSET_VERSION_PLACE_ID").expect("LOAD_ASSET_VERSION_PLACE_ID env required").parse().expect("LOAD_ASSET_VERSION_PLACE_ID int parse failed");
|
||||||
|
let load_asset_version_universe_id=std::env::var("LOAD_ASSET_VERSION_UNIVERSE_ID").expect("LOAD_ASSET_VERSION_UNIVERSE_ID env required").parse().expect("LOAD_ASSET_VERSION_UNIVERSE_ID int parse failed");
|
||||||
|
|
||||||
// create / upload models through STRAFESNET_CI2 account
|
// create / upload models through STRAFESNET_CI2 account
|
||||||
let cookie=std::env::var("RBXCOOKIE").expect("RBXCOOKIE env required");
|
let cookie=std::env::var("RBXCOOKIE").expect("RBXCOOKIE env required");
|
||||||
let cookie_context=rbx_asset::cookie::Context::new(rbx_asset::cookie::Cookie::new(cookie));
|
let cookie_context=rbx_asset::cookie::Context::new(rbx_asset::cookie::Cookie::new(cookie));
|
||||||
// download models through cloud api
|
// download models through cloud api (STRAFESNET_CI2 account)
|
||||||
let api_key=std::env::var("RBX_API_KEY").expect("RBX_API_KEY env required");
|
let api_key=std::env::var("RBX_API_KEY").expect("RBX_API_KEY env required");
|
||||||
let cloud_context=rbx_asset::cloud::Context::new(rbx_asset::cloud::ApiKey::new(api_key));
|
let cloud_context=rbx_asset::cloud::Context::new(rbx_asset::cloud::ApiKey::new(api_key));
|
||||||
|
// luau execution cloud api (StrafesNET group)
|
||||||
|
let api_key=std::env::var("RBX_API_KEY_LUAU_EXECUTION").expect("RBX_API_KEY_LUAU_EXECUTION env required");
|
||||||
|
let cloud_context_luau_execution=rbx_asset::cloud::Context::new(rbx_asset::cloud::ApiKey::new(api_key));
|
||||||
|
|
||||||
// maps-service api
|
// maps-service api
|
||||||
let api_host_internal=std::env::var("API_HOST_INTERNAL").expect("API_HOST_INTERNAL env required");
|
let api_host_internal=std::env::var("API_HOST_INTERNAL").expect("API_HOST_INTERNAL env required");
|
||||||
let endpoint=tonic::transport::Endpoint::new(api_host_internal).map_err(StartupError::API)?;
|
let endpoint=tonic::transport::Endpoint::new(api_host_internal).map_err(StartupError::API)?;
|
||||||
let channel=endpoint.connect_lazy();
|
let channel=endpoint.connect_lazy();
|
||||||
let mapfixes=crate::grpc::mapfixes::ValidatorMapfixesServiceClient::new(channel.clone());
|
let mapfixes=crate::grpc::mapfixes::Service::new(crate::grpc::mapfixes::ValidatorMapfixesServiceClient::new(channel.clone()));
|
||||||
let operations=crate::grpc::operations::ValidatorOperationsServiceClient::new(channel.clone());
|
let operations=crate::grpc::operations::Service::new(crate::grpc::operations::ValidatorOperationsServiceClient::new(channel.clone()));
|
||||||
let scripts=crate::grpc::scripts::ValidatorScriptsServiceClient::new(channel.clone());
|
let scripts=crate::grpc::scripts::Service::new(crate::grpc::scripts::ValidatorScriptsServiceClient::new(channel.clone()));
|
||||||
let script_policy=crate::grpc::script_policy::ValidatorScriptPolicyServiceClient::new(channel.clone());
|
let script_policy=crate::grpc::script_policy::Service::new(crate::grpc::script_policy::ValidatorScriptPolicyServiceClient::new(channel.clone()));
|
||||||
let submissions=crate::grpc::submissions::ValidatorSubmissionsServiceClient::new(channel);
|
let submissions=crate::grpc::submissions::Service::new(crate::grpc::submissions::ValidatorSubmissionsServiceClient::new(channel.clone()));
|
||||||
let message_handler=message_handler::MessageHandler::new(cloud_context,cookie_context,group_id,mapfixes,operations,scripts,script_policy,submissions);
|
let load_asset_version_runtime=rbx_asset::cloud::LuauSessionLatestRequest{
|
||||||
|
place_id:load_asset_version_place_id,
|
||||||
|
universe_id:load_asset_version_universe_id,
|
||||||
|
};
|
||||||
|
let message_handler=message_handler::MessageHandler{
|
||||||
|
cloud_context,
|
||||||
|
cookie_context,
|
||||||
|
cloud_context_luau_execution,
|
||||||
|
group_id,
|
||||||
|
load_asset_version_runtime,
|
||||||
|
mapfixes,
|
||||||
|
operations,
|
||||||
|
scripts,
|
||||||
|
script_policy,
|
||||||
|
submissions,
|
||||||
|
};
|
||||||
|
|
||||||
// nats
|
// nats
|
||||||
let nats_host=std::env::var("NATS_HOST").expect("NATS_HOST env required");
|
let nats_host=std::env::var("NATS_HOST").expect("NATS_HOST env required");
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#[allow(dead_code)]
|
#[expect(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum HandleMessageError{
|
pub enum HandleMessageError{
|
||||||
Messages(async_nats::jetstream::consumer::pull::MessagesError),
|
Messages(async_nats::jetstream::consumer::pull::MessagesError),
|
||||||
@@ -9,6 +9,8 @@ pub enum HandleMessageError{
|
|||||||
CreateSubmission(tonic::Status),
|
CreateSubmission(tonic::Status),
|
||||||
CheckMapfix(crate::check_mapfix::Error),
|
CheckMapfix(crate::check_mapfix::Error),
|
||||||
CheckSubmission(crate::check_submission::Error),
|
CheckSubmission(crate::check_submission::Error),
|
||||||
|
ReleaseMapfix(crate::release_mapfix::Error),
|
||||||
|
ReleaseSubmissionsBatch(crate::release_submissions_batch::Error),
|
||||||
UploadMapfix(crate::upload_mapfix::Error),
|
UploadMapfix(crate::upload_mapfix::Error),
|
||||||
UploadSubmission(crate::upload_submission::Error),
|
UploadSubmission(crate::upload_submission::Error),
|
||||||
ValidateMapfix(crate::validate_mapfix::Error),
|
ValidateMapfix(crate::validate_mapfix::Error),
|
||||||
@@ -30,7 +32,9 @@ fn from_slice<'a,T:serde::de::Deserialize<'a>>(slice:&'a [u8])->Result<T,HandleM
|
|||||||
pub struct MessageHandler{
|
pub struct MessageHandler{
|
||||||
pub(crate) cloud_context:rbx_asset::cloud::Context,
|
pub(crate) cloud_context:rbx_asset::cloud::Context,
|
||||||
pub(crate) cookie_context:rbx_asset::cookie::Context,
|
pub(crate) cookie_context:rbx_asset::cookie::Context,
|
||||||
|
pub(crate) cloud_context_luau_execution:rbx_asset::cloud::Context,
|
||||||
pub(crate) group_id:Option<u64>,
|
pub(crate) group_id:Option<u64>,
|
||||||
|
pub(crate) load_asset_version_runtime:rbx_asset::cloud::LuauSessionLatestRequest,
|
||||||
pub(crate) mapfixes:crate::grpc::mapfixes::Service,
|
pub(crate) mapfixes:crate::grpc::mapfixes::Service,
|
||||||
pub(crate) operations:crate::grpc::operations::Service,
|
pub(crate) operations:crate::grpc::operations::Service,
|
||||||
pub(crate) scripts:crate::grpc::scripts::Service,
|
pub(crate) scripts:crate::grpc::scripts::Service,
|
||||||
@@ -39,27 +43,6 @@ pub struct MessageHandler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MessageHandler{
|
impl MessageHandler{
|
||||||
pub fn new(
|
|
||||||
cloud_context:rbx_asset::cloud::Context,
|
|
||||||
cookie_context:rbx_asset::cookie::Context,
|
|
||||||
group_id:Option<u64>,
|
|
||||||
mapfixes:crate::grpc::mapfixes::ValidatorMapfixesServiceClient,
|
|
||||||
operations:crate::grpc::operations::ValidatorOperationsServiceClient,
|
|
||||||
scripts:crate::grpc::scripts::ValidatorScriptsServiceClient,
|
|
||||||
script_policy:crate::grpc::script_policy::ValidatorScriptPolicyServiceClient,
|
|
||||||
submissions:crate::grpc::submissions::ValidatorSubmissionsServiceClient,
|
|
||||||
)->Self{
|
|
||||||
Self{
|
|
||||||
cloud_context,
|
|
||||||
cookie_context,
|
|
||||||
group_id,
|
|
||||||
mapfixes:crate::grpc::mapfixes::Service::new(mapfixes),
|
|
||||||
operations:crate::grpc::operations::Service::new(operations),
|
|
||||||
scripts:crate::grpc::scripts::Service::new(scripts),
|
|
||||||
script_policy:crate::grpc::script_policy::Service::new(script_policy),
|
|
||||||
submissions:crate::grpc::submissions::Service::new(submissions),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub async fn handle_message_result(&self,message_result:MessageResult)->Result<(),HandleMessageError>{
|
pub async fn handle_message_result(&self,message_result:MessageResult)->Result<(),HandleMessageError>{
|
||||||
let message=message_result.map_err(HandleMessageError::Messages)?;
|
let message=message_result.map_err(HandleMessageError::Messages)?;
|
||||||
message.double_ack().await.map_err(HandleMessageError::DoubleAck)?;
|
message.double_ack().await.map_err(HandleMessageError::DoubleAck)?;
|
||||||
@@ -68,6 +51,8 @@ impl MessageHandler{
|
|||||||
"maptest.submissions.create"=>self.create_submission(from_slice(&message.payload)?).await.map_err(HandleMessageError::CreateSubmission),
|
"maptest.submissions.create"=>self.create_submission(from_slice(&message.payload)?).await.map_err(HandleMessageError::CreateSubmission),
|
||||||
"maptest.mapfixes.check"=>self.check_mapfix(from_slice(&message.payload)?).await.map_err(HandleMessageError::CheckMapfix),
|
"maptest.mapfixes.check"=>self.check_mapfix(from_slice(&message.payload)?).await.map_err(HandleMessageError::CheckMapfix),
|
||||||
"maptest.submissions.check"=>self.check_submission(from_slice(&message.payload)?).await.map_err(HandleMessageError::CheckSubmission),
|
"maptest.submissions.check"=>self.check_submission(from_slice(&message.payload)?).await.map_err(HandleMessageError::CheckSubmission),
|
||||||
|
"maptest.mapfixes.release"=>self.release_mapfix(from_slice(&message.payload)?).await.map_err(HandleMessageError::ReleaseMapfix),
|
||||||
|
"maptest.submissions.batchrelease"=>self.release_submissions_batch(from_slice(&message.payload)?).await.map_err(HandleMessageError::ReleaseSubmissionsBatch),
|
||||||
"maptest.mapfixes.upload"=>self.upload_mapfix(from_slice(&message.payload)?).await.map_err(HandleMessageError::UploadMapfix),
|
"maptest.mapfixes.upload"=>self.upload_mapfix(from_slice(&message.payload)?).await.map_err(HandleMessageError::UploadMapfix),
|
||||||
"maptest.submissions.upload"=>self.upload_submission(from_slice(&message.payload)?).await.map_err(HandleMessageError::UploadSubmission),
|
"maptest.submissions.upload"=>self.upload_submission(from_slice(&message.payload)?).await.map_err(HandleMessageError::UploadSubmission),
|
||||||
"maptest.mapfixes.validate"=>self.validate_mapfix(from_slice(&message.payload)?).await.map_err(HandleMessageError::ValidateMapfix),
|
"maptest.mapfixes.validate"=>self.validate_mapfix(from_slice(&message.payload)?).await.map_err(HandleMessageError::ValidateMapfix),
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
// Requests are sent from maps-service to validator
|
// Requests are sent from maps-service to validator
|
||||||
// Validation invokes the REST api to update the submissions
|
// Validation invokes the REST api to update the submissions
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct CreateSubmissionRequest{
|
pub struct CreateSubmissionRequest{
|
||||||
// operation_id is passed back in the response message
|
// operation_id is passed back in the response message
|
||||||
@@ -18,7 +18,7 @@ pub struct CreateSubmissionRequest{
|
|||||||
pub Roles:u32,
|
pub Roles:u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct CreateMapfixRequest{
|
pub struct CreateMapfixRequest{
|
||||||
pub OperationID:u32,
|
pub OperationID:u32,
|
||||||
@@ -27,7 +27,7 @@ pub struct CreateMapfixRequest{
|
|||||||
pub Description:String,
|
pub Description:String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct CheckSubmissionRequest{
|
pub struct CheckSubmissionRequest{
|
||||||
pub SubmissionID:u64,
|
pub SubmissionID:u64,
|
||||||
@@ -35,7 +35,7 @@ pub struct CheckSubmissionRequest{
|
|||||||
pub SkipChecks:bool,
|
pub SkipChecks:bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct CheckMapfixRequest{
|
pub struct CheckMapfixRequest{
|
||||||
pub MapfixID:u64,
|
pub MapfixID:u64,
|
||||||
@@ -43,7 +43,7 @@ pub struct CheckMapfixRequest{
|
|||||||
pub SkipChecks:bool,
|
pub SkipChecks:bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct ValidateSubmissionRequest{
|
pub struct ValidateSubmissionRequest{
|
||||||
// submission_id is passed back in the response message
|
// submission_id is passed back in the response message
|
||||||
@@ -53,7 +53,7 @@ pub struct ValidateSubmissionRequest{
|
|||||||
pub ValidatedModelID:Option<u64>,
|
pub ValidatedModelID:Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct ValidateMapfixRequest{
|
pub struct ValidateMapfixRequest{
|
||||||
// submission_id is passed back in the response message
|
// submission_id is passed back in the response message
|
||||||
@@ -64,7 +64,7 @@ pub struct ValidateMapfixRequest{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new map
|
// Create a new map
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct UploadSubmissionRequest{
|
pub struct UploadSubmissionRequest{
|
||||||
pub SubmissionID:u64,
|
pub SubmissionID:u64,
|
||||||
@@ -73,7 +73,7 @@ pub struct UploadSubmissionRequest{
|
|||||||
pub ModelName:String,
|
pub ModelName:String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct UploadMapfixRequest{
|
pub struct UploadMapfixRequest{
|
||||||
pub MapfixID:u64,
|
pub MapfixID:u64,
|
||||||
@@ -81,3 +81,34 @@ pub struct UploadMapfixRequest{
|
|||||||
pub ModelVersion:u64,
|
pub ModelVersion:u64,
|
||||||
pub TargetAssetID:u64,
|
pub TargetAssetID:u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Release a new map
|
||||||
|
#[expect(nonstandard_style)]
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
pub struct ReleaseSubmissionRequest{
|
||||||
|
pub SubmissionID:u64,
|
||||||
|
pub ReleaseDate:i64,
|
||||||
|
pub ModelID:u64,
|
||||||
|
pub ModelVersion:u64,
|
||||||
|
pub UploadedAssetID:u64,
|
||||||
|
pub DisplayName:String,
|
||||||
|
pub Creator:String,
|
||||||
|
pub GameID:u32,
|
||||||
|
pub Submitter:u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(nonstandard_style)]
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
pub struct ReleaseSubmissionsBatchRequest{
|
||||||
|
pub Submissions:Vec<ReleaseSubmissionRequest>,
|
||||||
|
pub OperationID:u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(nonstandard_style)]
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
pub struct ReleaseMapfixRequest{
|
||||||
|
pub MapfixID:u64,
|
||||||
|
pub ModelID:u64,
|
||||||
|
pub ModelVersion:u64,
|
||||||
|
pub TargetAssetID:u64,
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
|
#[expect(dead_code)]
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ReadDomError{
|
pub enum ReadDomError{
|
||||||
Binary(rbx_binary::DecodeError),
|
Binary(rbx_binary::DecodeError),
|
||||||
@@ -112,3 +111,21 @@ pub fn get_mapinfo<'a>(dom:&'a rbx_dom_weak::WeakDom,model_instance:&rbx_dom_wea
|
|||||||
game_id:model_instance.name.parse(),
|
game_id:model_instance.name.parse(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_luau_result_exp_backoff(
|
||||||
|
context:&rbx_asset::cloud::Context,
|
||||||
|
luau_session:&rbx_asset::cloud::LuauSessionResponse
|
||||||
|
)->Result<Result<rbx_asset::cloud::LuauResults,rbx_asset::cloud::LuauError>,rbx_asset::cloud::LuauSessionError>{
|
||||||
|
const BACKOFF_MUL:f32=1.395_612_5;//exp(1/3)
|
||||||
|
let mut backoff=1000f32;
|
||||||
|
loop{
|
||||||
|
match luau_session.try_get_result(context).await{
|
||||||
|
//try again when the operation is not done
|
||||||
|
Err(rbx_asset::cloud::LuauSessionError::NotDone)=>(),
|
||||||
|
//return all other results
|
||||||
|
other_result=>return other_result,
|
||||||
|
}
|
||||||
|
tokio::time::sleep(std::time::Duration::from_millis(backoff as u64)).await;
|
||||||
|
backoff*=BACKOFF_MUL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
104
validation/src/release.rs
Normal file
104
validation/src/release.rs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
use crate::rbx_util::read_dom;
|
||||||
|
|
||||||
|
#[expect(unused)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ModesError{
|
||||||
|
ApiActionMapfixReleased(tonic::Status),
|
||||||
|
ModelFileDecode(crate::rbx_util::ReadDomError),
|
||||||
|
GetRootInstance(crate::rbx_util::GetRootInstanceError),
|
||||||
|
NonSequentialModes,
|
||||||
|
TooManyModes(usize),
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for ModesError{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
write!(f,"{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for ModesError{}
|
||||||
|
|
||||||
|
// decode and get modes function
|
||||||
|
pub fn count_modes(maybe_gzip:rbx_asset::types::MaybeGzippedBytes)->Result<u32,ModesError>{
|
||||||
|
// decode dom (slow!)
|
||||||
|
let dom=maybe_gzip.read_with(read_dom,read_dom).map_err(ModesError::ModelFileDecode)?;
|
||||||
|
|
||||||
|
// extract the root instance
|
||||||
|
let model_instance=crate::rbx_util::get_root_instance(&dom).map_err(ModesError::GetRootInstance)?;
|
||||||
|
|
||||||
|
// extract information from the model
|
||||||
|
let model_info=crate::check::get_model_info(&dom,model_instance);
|
||||||
|
|
||||||
|
// count modes
|
||||||
|
let modes=model_info.count_modes().ok_or(ModesError::NonSequentialModes)?;
|
||||||
|
|
||||||
|
// hard limit LOL
|
||||||
|
let modes=if modes<u32::MAX as usize{
|
||||||
|
modes as u32
|
||||||
|
}else{
|
||||||
|
return Err(ModesError::TooManyModes(modes));
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(modes)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(unused)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum LoadAssetVersionsError{
|
||||||
|
CreateSession(rbx_asset::cloud::CreateError),
|
||||||
|
NonPositiveNumber(serde_json::Value),
|
||||||
|
Script(rbx_asset::cloud::LuauError),
|
||||||
|
InvalidResult(Vec<serde_json::Value>),
|
||||||
|
LuauSession(rbx_asset::cloud::LuauSessionError),
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for LoadAssetVersionsError{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
write!(f,"{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for LoadAssetVersionsError{}
|
||||||
|
|
||||||
|
// get asset versions in bulk using Roblox Luau API
|
||||||
|
pub async fn load_asset_versions<I:IntoIterator<Item=u64>>(
|
||||||
|
context:&rbx_asset::cloud::Context,
|
||||||
|
runtime:&rbx_asset::cloud::LuauSessionLatestRequest,
|
||||||
|
assets:I,
|
||||||
|
)->Result<Vec<u64>,LoadAssetVersionsError>{
|
||||||
|
// construct script with inline IDs
|
||||||
|
// TODO: concurrent execution
|
||||||
|
let mut script="local InsertService=game:GetService(\"InsertService\")\nreturn\n".to_string();
|
||||||
|
for asset in assets{
|
||||||
|
use std::fmt::Write;
|
||||||
|
write!(script,"InsertService:GetLatestAssetVersionAsync({asset}),\n").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let session=rbx_asset::cloud::LuauSessionCreate{
|
||||||
|
script:&script[..script.len()-2],
|
||||||
|
user:None,
|
||||||
|
timeout:None,
|
||||||
|
binaryInput:None,
|
||||||
|
enableBinaryOutput:None,
|
||||||
|
binaryOutputUri:None,
|
||||||
|
};
|
||||||
|
let session_response=context.create_luau_session(runtime,session).await.map_err(LoadAssetVersionsError::CreateSession)?;
|
||||||
|
|
||||||
|
let result=crate::rbx_util::get_luau_result_exp_backoff(&context,&session_response).await;
|
||||||
|
|
||||||
|
// * Note that only one mapfix can be active per map
|
||||||
|
// * so it's theoretically impossible for the map to be updated unexpectedly.
|
||||||
|
// * This means that the incremental asset version does not
|
||||||
|
// * need to be checked before and after the load asset version is checked.
|
||||||
|
|
||||||
|
match result{
|
||||||
|
Ok(Ok(rbx_asset::cloud::LuauResults{results}))=>{
|
||||||
|
results.into_iter().map(|load_asset_version|
|
||||||
|
match load_asset_version.as_u64(){
|
||||||
|
Some(version)=>Ok(version),
|
||||||
|
None=>Err(LoadAssetVersionsError::NonPositiveNumber(load_asset_version))
|
||||||
|
}
|
||||||
|
).collect()
|
||||||
|
},
|
||||||
|
Ok(Err(e))=>Err(LoadAssetVersionsError::Script(e)),
|
||||||
|
Err(e)=>Err(LoadAssetVersionsError::LuauSession(e)),
|
||||||
|
}
|
||||||
|
|
||||||
|
// * Don't need to check asset version to make sure it hasn't been updated
|
||||||
|
}
|
||||||
101
validation/src/release_mapfix.rs
Normal file
101
validation/src/release_mapfix.rs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
use crate::download::download_asset_version;
|
||||||
|
use crate::nats_types::ReleaseMapfixRequest;
|
||||||
|
use crate::release::{count_modes,load_asset_versions};
|
||||||
|
|
||||||
|
#[expect(unused)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum InnerError{
|
||||||
|
Download(crate::download::Error),
|
||||||
|
Modes(crate::release::ModesError),
|
||||||
|
LoadAssetVersions(crate::release::LoadAssetVersionsError),
|
||||||
|
LoadAssetVersionsListLength,
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for InnerError{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
write!(f,"{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for InnerError{}
|
||||||
|
|
||||||
|
async fn release_inner(
|
||||||
|
cloud_context:&rbx_asset::cloud::Context,
|
||||||
|
cloud_context_luau_execution:&rbx_asset::cloud::Context,
|
||||||
|
load_asset_version_runtime:&rbx_asset::cloud::LuauSessionLatestRequest,
|
||||||
|
release_info:ReleaseMapfixRequest,
|
||||||
|
)->Result<rust_grpc::validator::MapfixReleaseRequest,InnerError>{
|
||||||
|
// download the map model
|
||||||
|
let maybe_gzip=download_asset_version(cloud_context,rbx_asset::cloud::GetAssetVersionRequest{
|
||||||
|
asset_id:release_info.ModelID,
|
||||||
|
version:release_info.ModelVersion,
|
||||||
|
}).await.map_err(InnerError::Download)?;
|
||||||
|
|
||||||
|
// count modes
|
||||||
|
let modes=count_modes(maybe_gzip).map_err(InnerError::Modes)?;
|
||||||
|
|
||||||
|
// fetch load asset version
|
||||||
|
let load_asset_versions=load_asset_versions(
|
||||||
|
cloud_context_luau_execution,
|
||||||
|
load_asset_version_runtime,
|
||||||
|
[release_info.TargetAssetID],
|
||||||
|
).await.map_err(InnerError::LoadAssetVersions)?;
|
||||||
|
|
||||||
|
// exactly one value in the results
|
||||||
|
let &[load_asset_version]=load_asset_versions.as_slice()else{
|
||||||
|
return Err(InnerError::LoadAssetVersionsListLength);
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(rust_grpc::validator::MapfixReleaseRequest{
|
||||||
|
mapfix_id:release_info.MapfixID,
|
||||||
|
target_asset_id:release_info.TargetAssetID,
|
||||||
|
asset_version:load_asset_version,
|
||||||
|
modes:modes,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(unused)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error{
|
||||||
|
ApiActionMapfixRelease(tonic::Status),
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for Error{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
write!(f,"{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for Error{}
|
||||||
|
|
||||||
|
impl crate::message_handler::MessageHandler{
|
||||||
|
pub async fn release_mapfix(&self,release_info:ReleaseMapfixRequest)->Result<(),Error>{
|
||||||
|
let mapfix_id=release_info.MapfixID;
|
||||||
|
let result=release_inner(
|
||||||
|
&self.cloud_context,
|
||||||
|
&self.cloud_context_luau_execution,
|
||||||
|
&self.load_asset_version_runtime,
|
||||||
|
release_info,
|
||||||
|
).await;
|
||||||
|
|
||||||
|
match result{
|
||||||
|
Ok(request)=>{
|
||||||
|
// update map metadata
|
||||||
|
self.mapfixes.set_status_released(request).await.map_err(Error::ApiActionMapfixRelease)?;
|
||||||
|
},
|
||||||
|
Err(e)=>{
|
||||||
|
// log error
|
||||||
|
println!("[release_mapfix] Error: {e}");
|
||||||
|
|
||||||
|
// post an error message to the audit log
|
||||||
|
self.mapfixes.create_audit_error(rust_grpc::validator::AuditErrorRequest{
|
||||||
|
id:mapfix_id,
|
||||||
|
error_message:e.to_string(),
|
||||||
|
}).await.map_err(Error::ApiActionMapfixRelease)?;
|
||||||
|
|
||||||
|
// update the mapfix model status to uploaded
|
||||||
|
self.mapfixes.set_status_not_released(rust_grpc::validator::MapfixId{
|
||||||
|
id:mapfix_id,
|
||||||
|
}).await.map_err(Error::ApiActionMapfixRelease)?;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
227
validation/src/release_submissions_batch.rs
Normal file
227
validation/src/release_submissions_batch.rs
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
use futures::StreamExt;
|
||||||
|
|
||||||
|
use crate::download::download_asset_version;
|
||||||
|
use crate::nats_types::ReleaseSubmissionsBatchRequest;
|
||||||
|
use crate::release::{count_modes,load_asset_versions};
|
||||||
|
|
||||||
|
|
||||||
|
#[expect(unused)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum DownloadFutError{
|
||||||
|
Download(crate::download::Error),
|
||||||
|
Join(tokio::task::JoinError),
|
||||||
|
Modes(crate::release::ModesError),
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for DownloadFutError{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
write!(f,"{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for DownloadFutError{}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ErrorContext<E>{
|
||||||
|
submission_id:u64,
|
||||||
|
error:E,
|
||||||
|
}
|
||||||
|
impl<E:std::fmt::Debug> std::fmt::Display for ErrorContext<E>{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
write!(f,"SubmissionID({})={:?}",self.submission_id,self.error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<E:std::fmt::Debug> std::error::Error for ErrorContext<E>{}
|
||||||
|
|
||||||
|
async fn download_fut(
|
||||||
|
cloud_context:&rbx_asset::cloud::Context,
|
||||||
|
asset_version:rbx_asset::cloud::GetAssetVersionRequest,
|
||||||
|
)->Result<u32,DownloadFutError>{
|
||||||
|
// download
|
||||||
|
let maybe_gzip=download_asset_version(cloud_context,asset_version)
|
||||||
|
.await
|
||||||
|
.map_err(DownloadFutError::Download)?;
|
||||||
|
|
||||||
|
// count modes in a green thread
|
||||||
|
let modes=tokio::task::spawn_blocking(||
|
||||||
|
count_modes(maybe_gzip)
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(DownloadFutError::Join)?
|
||||||
|
.map_err(DownloadFutError::Modes)?;
|
||||||
|
|
||||||
|
Ok::<_,DownloadFutError>(modes)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(unused)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum InnerError{
|
||||||
|
Io(std::io::Error),
|
||||||
|
LoadAssetVersions(crate::release::LoadAssetVersionsError),
|
||||||
|
LoadAssetVersionsListLength,
|
||||||
|
DownloadFutErrors(Vec<ErrorContext<DownloadFutError>>),
|
||||||
|
ReleaseErrors(Vec<ErrorContext<tonic::Status>>),
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for InnerError{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
write!(f,"{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for InnerError{}
|
||||||
|
|
||||||
|
const MAX_PARALLEL_DECODE:usize=6;
|
||||||
|
const MAX_CONCURRENT_RELEASE:usize=16;
|
||||||
|
|
||||||
|
async fn release_inner(
|
||||||
|
release_info:ReleaseSubmissionsBatchRequest,
|
||||||
|
cloud_context:&rbx_asset::cloud::Context,
|
||||||
|
cloud_context_luau_execution:&rbx_asset::cloud::Context,
|
||||||
|
load_asset_version_runtime:&rbx_asset::cloud::LuauSessionLatestRequest,
|
||||||
|
submissions:&crate::grpc::submissions::Service,
|
||||||
|
)->Result<(),InnerError>{
|
||||||
|
let available_parallelism=std::thread::available_parallelism().map_err(InnerError::Io)?.get();
|
||||||
|
// set up futures
|
||||||
|
|
||||||
|
// unnecessary allocation :(
|
||||||
|
let asset_versions:Vec<_> =release_info
|
||||||
|
.Submissions
|
||||||
|
.iter()
|
||||||
|
.map(|submission|rbx_asset::cloud::GetAssetVersionRequest{
|
||||||
|
asset_id:submission.ModelID,
|
||||||
|
version:submission.ModelVersion,
|
||||||
|
})
|
||||||
|
.enumerate()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// fut_download
|
||||||
|
let fut_download=futures::stream::iter(asset_versions)
|
||||||
|
.map(|(index,asset_version)|async move{
|
||||||
|
let modes=download_fut(cloud_context,asset_version).await;
|
||||||
|
(index,modes)
|
||||||
|
})
|
||||||
|
.buffer_unordered(available_parallelism.min(MAX_PARALLEL_DECODE))
|
||||||
|
.collect::<Vec<(usize,Result<_,DownloadFutError>)>>();
|
||||||
|
|
||||||
|
// fut_luau
|
||||||
|
let fut_load_asset_versions=load_asset_versions(
|
||||||
|
cloud_context_luau_execution,
|
||||||
|
load_asset_version_runtime,
|
||||||
|
release_info.Submissions.iter().map(|submission|submission.UploadedAssetID),
|
||||||
|
);
|
||||||
|
|
||||||
|
// execute futures
|
||||||
|
let (mut modes_unordered,load_asset_versions_result)=tokio::join!(fut_download,fut_load_asset_versions);
|
||||||
|
|
||||||
|
let load_asset_versions=load_asset_versions_result.map_err(InnerError::LoadAssetVersions)?;
|
||||||
|
|
||||||
|
// sanity check roblox output
|
||||||
|
if load_asset_versions.len()!=release_info.Submissions.len(){
|
||||||
|
return Err(InnerError::LoadAssetVersionsListLength);
|
||||||
|
};
|
||||||
|
|
||||||
|
// rip asymptotic complexity (hash map would be better)
|
||||||
|
modes_unordered.sort_by_key(|&(index,_)|index);
|
||||||
|
|
||||||
|
// check modes calculations for all success
|
||||||
|
let mut modes=Vec::with_capacity(modes_unordered.len());
|
||||||
|
let mut errors=Vec::with_capacity(modes_unordered.len());
|
||||||
|
for (index,result) in modes_unordered{
|
||||||
|
match result{
|
||||||
|
Ok(value)=>modes.push(value),
|
||||||
|
Err(error)=>errors.push(ErrorContext{
|
||||||
|
submission_id:release_info.Submissions[index].SubmissionID,
|
||||||
|
error:error,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !errors.is_empty(){
|
||||||
|
return Err(InnerError::DownloadFutErrors(errors));
|
||||||
|
}
|
||||||
|
|
||||||
|
// concurrently dispatch results
|
||||||
|
let release_results:Vec<_> =futures::stream::iter(
|
||||||
|
release_info
|
||||||
|
.Submissions
|
||||||
|
.into_iter()
|
||||||
|
.zip(modes)
|
||||||
|
.zip(load_asset_versions)
|
||||||
|
.map(|((submission,modes),asset_version)|async move{
|
||||||
|
let result=submissions.set_status_released(rust_grpc::validator::SubmissionReleaseRequest{
|
||||||
|
submission_id:submission.SubmissionID,
|
||||||
|
map_create:Some(rust_grpc::maps_extended::MapCreate{
|
||||||
|
id:submission.UploadedAssetID as i64,
|
||||||
|
display_name:submission.DisplayName,
|
||||||
|
creator:submission.Creator,
|
||||||
|
game_id:submission.GameID,
|
||||||
|
date:submission.ReleaseDate,
|
||||||
|
submitter:submission.Submitter,
|
||||||
|
thumbnail:0,
|
||||||
|
asset_version,
|
||||||
|
modes,
|
||||||
|
}),
|
||||||
|
}).await;
|
||||||
|
(submission.SubmissionID,result)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.buffer_unordered(MAX_CONCURRENT_RELEASE)
|
||||||
|
.collect().await;
|
||||||
|
|
||||||
|
// check for errors
|
||||||
|
let errors:Vec<_> =
|
||||||
|
release_results
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|(submission_id,result)|
|
||||||
|
result.err().map(|e|ErrorContext{
|
||||||
|
submission_id,
|
||||||
|
error:e,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if !errors.is_empty(){
|
||||||
|
return Err(InnerError::ReleaseErrors(errors));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(dead_code)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error{
|
||||||
|
UpdateOperation(tonic::Status),
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for Error{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
write!(f,"{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for Error{}
|
||||||
|
|
||||||
|
impl crate::message_handler::MessageHandler{
|
||||||
|
pub async fn release_submissions_batch(&self,release_info:ReleaseSubmissionsBatchRequest)->Result<(),Error>{
|
||||||
|
let operation_id=release_info.OperationID;
|
||||||
|
let result=release_inner(
|
||||||
|
release_info,
|
||||||
|
&self.cloud_context,
|
||||||
|
&self.cloud_context_luau_execution,
|
||||||
|
&self.load_asset_version_runtime,
|
||||||
|
&self.submissions,
|
||||||
|
).await;
|
||||||
|
|
||||||
|
match result{
|
||||||
|
Ok(())=>{
|
||||||
|
// operation success
|
||||||
|
self.operations.success(rust_grpc::validator::OperationSuccessRequest{
|
||||||
|
operation_id,
|
||||||
|
path:String::new(),
|
||||||
|
}).await.map_err(Error::UpdateOperation)?;
|
||||||
|
},
|
||||||
|
Err(e)=>{
|
||||||
|
// operation error
|
||||||
|
self.operations.fail(rust_grpc::validator::OperationFailRequest{
|
||||||
|
operation_id,
|
||||||
|
status_message:e.to_string(),
|
||||||
|
}).await.map_err(Error::UpdateOperation)?;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,8 +5,6 @@ pub struct MapfixID(pub(crate)u64);
|
|||||||
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq,serde::Serialize,serde::Deserialize)]
|
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq,serde::Serialize,serde::Deserialize)]
|
||||||
pub struct SubmissionID(pub(crate)u64);
|
pub struct SubmissionID(pub(crate)u64);
|
||||||
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq,serde::Serialize,serde::Deserialize)]
|
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq,serde::Serialize,serde::Deserialize)]
|
||||||
pub struct OperationID(pub(crate)u64);
|
|
||||||
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq,serde::Serialize,serde::Deserialize)]
|
|
||||||
pub struct ResourceID(pub(crate)u64);
|
pub struct ResourceID(pub(crate)u64);
|
||||||
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq,serde::Serialize,serde::Deserialize)]
|
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq,serde::Serialize,serde::Deserialize)]
|
||||||
pub struct ScriptID(pub(crate)u64);
|
pub struct ScriptID(pub(crate)u64);
|
||||||
|
|||||||
@@ -1,13 +1,51 @@
|
|||||||
use crate::download::download_asset_version;
|
use crate::download::download_asset_version;
|
||||||
use crate::nats_types::UploadMapfixRequest;
|
use crate::nats_types::UploadMapfixRequest;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[expect(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error{
|
pub enum InnerError{
|
||||||
Download(crate::download::Error),
|
Download(crate::download::Error),
|
||||||
IO(std::io::Error),
|
IO(std::io::Error),
|
||||||
Json(serde_json::Error),
|
Json(serde_json::Error),
|
||||||
Upload(rbx_asset::cookie::UploadError),
|
Upload(rbx_asset::cookie::UploadError),
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for InnerError{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
write!(f,"{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for InnerError{}
|
||||||
|
|
||||||
|
async fn upload_inner(
|
||||||
|
upload_info:UploadMapfixRequest,
|
||||||
|
cloud_context:&rbx_asset::cloud::Context,
|
||||||
|
cookie_context:&rbx_asset::cookie::Context,
|
||||||
|
group_id:Option<u64>,
|
||||||
|
)->Result<(),InnerError>{
|
||||||
|
// download the map model
|
||||||
|
let maybe_gzip=download_asset_version(cloud_context,rbx_asset::cloud::GetAssetVersionRequest{
|
||||||
|
asset_id:upload_info.ModelID,
|
||||||
|
version:upload_info.ModelVersion,
|
||||||
|
}).await.map_err(InnerError::Download)?;
|
||||||
|
|
||||||
|
// transparently handle gzipped models
|
||||||
|
let model_data=maybe_gzip.to_vec().map_err(InnerError::IO)?;
|
||||||
|
|
||||||
|
// upload the map to the strafesnet group
|
||||||
|
let _upload_response=cookie_context.upload(rbx_asset::cookie::UploadRequest{
|
||||||
|
assetid:upload_info.TargetAssetID,
|
||||||
|
groupId:group_id,
|
||||||
|
name:None,
|
||||||
|
description:None,
|
||||||
|
ispublic:None,
|
||||||
|
allowComments:None,
|
||||||
|
},model_data).await.map_err(InnerError::Upload)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
#[expect(dead_code)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error{
|
||||||
ApiActionMapfixUploaded(tonic::Status),
|
ApiActionMapfixUploaded(tonic::Status),
|
||||||
}
|
}
|
||||||
impl std::fmt::Display for Error{
|
impl std::fmt::Display for Error{
|
||||||
@@ -19,31 +57,39 @@ impl std::error::Error for Error{}
|
|||||||
|
|
||||||
impl crate::message_handler::MessageHandler{
|
impl crate::message_handler::MessageHandler{
|
||||||
pub async fn upload_mapfix(&self,upload_info:UploadMapfixRequest)->Result<(),Error>{
|
pub async fn upload_mapfix(&self,upload_info:UploadMapfixRequest)->Result<(),Error>{
|
||||||
// download the map model
|
let mapfix_id=upload_info.MapfixID;
|
||||||
let maybe_gzip=download_asset_version(&self.cloud_context,rbx_asset::cloud::GetAssetVersionRequest{
|
let result=upload_inner(
|
||||||
asset_id:upload_info.ModelID,
|
upload_info,
|
||||||
version:upload_info.ModelVersion,
|
&self.cloud_context,
|
||||||
}).await.map_err(Error::Download)?;
|
&self.cookie_context,
|
||||||
|
self.group_id,
|
||||||
|
).await;
|
||||||
|
|
||||||
// transparently handle gzipped models
|
// update the mapfix depending on the result
|
||||||
let model_data=maybe_gzip.to_vec().map_err(Error::IO)?;
|
match result{
|
||||||
|
Ok(())=>{
|
||||||
|
// mark mapfix as uploaded, TargetAssetID is unchanged
|
||||||
|
self.mapfixes.set_status_uploaded(rust_grpc::validator::MapfixId{
|
||||||
|
id:mapfix_id,
|
||||||
|
}).await.map_err(Error::ApiActionMapfixUploaded)?;
|
||||||
|
},
|
||||||
|
Err(e)=>{
|
||||||
|
// log error
|
||||||
|
println!("[upload_mapfix] Error: {e}");
|
||||||
|
|
||||||
// upload the map to the strafesnet group
|
self.mapfixes.create_audit_error(
|
||||||
let _upload_response=self.cookie_context.upload(rbx_asset::cookie::UploadRequest{
|
rust_grpc::validator::AuditErrorRequest{
|
||||||
assetid:upload_info.TargetAssetID,
|
id:mapfix_id,
|
||||||
groupId:self.group_id,
|
error_message:e.to_string(),
|
||||||
name:None,
|
}
|
||||||
description:None,
|
).await.map_err(Error::ApiActionMapfixUploaded)?;
|
||||||
ispublic:None,
|
|
||||||
allowComments:None,
|
|
||||||
},model_data).await.map_err(Error::Upload)?;
|
|
||||||
|
|
||||||
// that's it, the database entry does not need to be changed.
|
// update the mapfix model status to accepted
|
||||||
|
self.mapfixes.set_status_not_uploaded(rust_grpc::validator::MapfixId{
|
||||||
// mark mapfix as uploaded, TargetAssetID is unchanged
|
id:mapfix_id,
|
||||||
self.mapfixes.set_status_uploaded(rust_grpc::validator::MapfixId{
|
}).await.map_err(Error::ApiActionMapfixUploaded)?;
|
||||||
id:upload_info.MapfixID,
|
},
|
||||||
}).await.map_err(Error::ApiActionMapfixUploaded)?;
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,52 @@
|
|||||||
use crate::download::download_asset_version;
|
use crate::download::download_asset_version;
|
||||||
use crate::nats_types::UploadSubmissionRequest;
|
use crate::nats_types::UploadSubmissionRequest;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[expect(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error{
|
pub enum InnerError{
|
||||||
Download(crate::download::Error),
|
Download(crate::download::Error),
|
||||||
IO(std::io::Error),
|
IO(std::io::Error),
|
||||||
Json(serde_json::Error),
|
Json(serde_json::Error),
|
||||||
Create(rbx_asset::cookie::CreateError),
|
Create(rbx_asset::cookie::CreateError),
|
||||||
SystemTime(std::time::SystemTimeError),
|
SystemTime(std::time::SystemTimeError),
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for InnerError{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
write!(f,"{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for InnerError{}
|
||||||
|
|
||||||
|
async fn upload_inner(
|
||||||
|
upload_info:UploadSubmissionRequest,
|
||||||
|
cloud_context:&rbx_asset::cloud::Context,
|
||||||
|
cookie_context:&rbx_asset::cookie::Context,
|
||||||
|
group_id:Option<u64>,
|
||||||
|
)->Result<u64,InnerError>{
|
||||||
|
// download the map model
|
||||||
|
let maybe_gzip=download_asset_version(cloud_context,rbx_asset::cloud::GetAssetVersionRequest{
|
||||||
|
asset_id:upload_info.ModelID,
|
||||||
|
version:upload_info.ModelVersion,
|
||||||
|
}).await.map_err(InnerError::Download)?;
|
||||||
|
|
||||||
|
// transparently handle gzipped models
|
||||||
|
let model_data=maybe_gzip.to_vec().map_err(InnerError::IO)?;
|
||||||
|
|
||||||
|
// upload the map to the strafesnet group
|
||||||
|
let upload_response=cookie_context.create(rbx_asset::cookie::CreateRequest{
|
||||||
|
name:upload_info.ModelName.clone(),
|
||||||
|
description:"".to_owned(),
|
||||||
|
ispublic:false,
|
||||||
|
allowComments:false,
|
||||||
|
groupId:group_id,
|
||||||
|
},model_data).await.map_err(InnerError::Create)?;
|
||||||
|
|
||||||
|
Ok(upload_response.AssetId)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(dead_code)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error{
|
||||||
ApiActionSubmissionUploaded(tonic::Status),
|
ApiActionSubmissionUploaded(tonic::Status),
|
||||||
}
|
}
|
||||||
impl std::fmt::Display for Error{
|
impl std::fmt::Display for Error{
|
||||||
@@ -20,29 +58,40 @@ impl std::error::Error for Error{}
|
|||||||
|
|
||||||
impl crate::message_handler::MessageHandler{
|
impl crate::message_handler::MessageHandler{
|
||||||
pub async fn upload_submission(&self,upload_info:UploadSubmissionRequest)->Result<(),Error>{
|
pub async fn upload_submission(&self,upload_info:UploadSubmissionRequest)->Result<(),Error>{
|
||||||
// download the map model
|
let submission_id=upload_info.SubmissionID;
|
||||||
let maybe_gzip=download_asset_version(&self.cloud_context,rbx_asset::cloud::GetAssetVersionRequest{
|
let result=upload_inner(
|
||||||
asset_id:upload_info.ModelID,
|
upload_info,
|
||||||
version:upload_info.ModelVersion,
|
&self.cloud_context,
|
||||||
}).await.map_err(Error::Download)?;
|
&self.cookie_context,
|
||||||
|
self.group_id,
|
||||||
|
).await;
|
||||||
|
|
||||||
// transparently handle gzipped models
|
// update the submission depending on the result
|
||||||
let model_data=maybe_gzip.to_vec().map_err(Error::IO)?;
|
match result{
|
||||||
|
Ok(uploaded_asset_id)=>{
|
||||||
|
// note the asset id of the created model for later release, and mark the submission as uploaded
|
||||||
|
self.submissions.set_status_uploaded(rust_grpc::validator::StatusUploadedRequest{
|
||||||
|
id:submission_id,
|
||||||
|
uploaded_asset_id,
|
||||||
|
}).await.map_err(Error::ApiActionSubmissionUploaded)?;
|
||||||
|
},
|
||||||
|
Err(e)=>{
|
||||||
|
// log error
|
||||||
|
println!("[upload_submission] Error: {e}");
|
||||||
|
|
||||||
// upload the map to the strafesnet group
|
self.submissions.create_audit_error(
|
||||||
let upload_response=self.cookie_context.create(rbx_asset::cookie::CreateRequest{
|
rust_grpc::validator::AuditErrorRequest{
|
||||||
name:upload_info.ModelName.clone(),
|
id:submission_id,
|
||||||
description:"".to_owned(),
|
error_message:e.to_string(),
|
||||||
ispublic:false,
|
}
|
||||||
allowComments:false,
|
).await.map_err(Error::ApiActionSubmissionUploaded)?;
|
||||||
groupId:self.group_id,
|
|
||||||
},model_data).await.map_err(Error::Create)?;
|
|
||||||
|
|
||||||
// note the asset id of the created model for later release, and mark the submission as uploaded
|
// update the submission model status to accepted
|
||||||
self.submissions.set_status_uploaded(rust_grpc::validator::StatusUploadedRequest{
|
self.submissions.set_status_not_uploaded(rust_grpc::validator::SubmissionId{
|
||||||
id:upload_info.SubmissionID,
|
id:submission_id,
|
||||||
uploaded_asset_id:upload_response.AssetId,
|
}).await.map_err(Error::ApiActionSubmissionUploaded)?;
|
||||||
}).await.map_err(Error::ApiActionSubmissionUploaded)?;
|
},
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::nats_types::ValidateMapfixRequest;
|
use crate::nats_types::ValidateMapfixRequest;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[expect(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error{
|
pub enum Error{
|
||||||
ApiActionMapfixValidate(tonic::Status),
|
ApiActionMapfixValidate(tonic::Status),
|
||||||
@@ -37,7 +37,7 @@ impl crate::message_handler::MessageHandler{
|
|||||||
).await.map_err(Error::ApiActionMapfixValidate)?;
|
).await.map_err(Error::ApiActionMapfixValidate)?;
|
||||||
|
|
||||||
// update the mapfix model status to accepted
|
// update the mapfix model status to accepted
|
||||||
self.mapfixes.set_status_failed(rust_grpc::validator::MapfixId{
|
self.mapfixes.set_status_not_validated(rust_grpc::validator::MapfixId{
|
||||||
id:mapfix_id,
|
id:mapfix_id,
|
||||||
}).await.map_err(Error::ApiActionMapfixValidate)?;
|
}).await.map_err(Error::ApiActionMapfixValidate)?;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::nats_types::ValidateSubmissionRequest;
|
use crate::nats_types::ValidateSubmissionRequest;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[expect(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error{
|
pub enum Error{
|
||||||
ApiActionSubmissionValidate(tonic::Status),
|
ApiActionSubmissionValidate(tonic::Status),
|
||||||
@@ -37,7 +37,7 @@ impl crate::message_handler::MessageHandler{
|
|||||||
).await.map_err(Error::ApiActionSubmissionValidate)?;
|
).await.map_err(Error::ApiActionSubmissionValidate)?;
|
||||||
|
|
||||||
// update the submission model status to accepted
|
// update the submission model status to accepted
|
||||||
self.submissions.set_status_failed(rust_grpc::validator::SubmissionId{
|
self.submissions.set_status_not_validated(rust_grpc::validator::SubmissionId{
|
||||||
id:submission_id,
|
id:submission_id,
|
||||||
}).await.map_err(Error::ApiActionSubmissionValidate)?;
|
}).await.map_err(Error::ApiActionSubmissionValidate)?;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ fn hash_source(source:&str)->u64{
|
|||||||
std::hash::Hasher::finish(&hasher)
|
std::hash::Hasher::finish(&hasher)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[expect(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error{
|
pub enum Error{
|
||||||
ModelInfoDownload(rbx_asset::cloud::GetError),
|
ModelInfoDownload(rbx_asset::cloud::GetError),
|
||||||
@@ -52,7 +52,7 @@ impl std::fmt::Display for Error{
|
|||||||
}
|
}
|
||||||
impl std::error::Error for Error{}
|
impl std::error::Error for Error{}
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[expect(nonstandard_style)]
|
||||||
pub struct ValidateRequest{
|
pub struct ValidateRequest{
|
||||||
pub ModelID:u64,
|
pub ModelID:u64,
|
||||||
pub ModelVersion:u64,
|
pub ModelVersion:u64,
|
||||||
@@ -318,7 +318,7 @@ fn get_partial_path(dom:&rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_script_refs(dom:&rbx_dom_weak::WeakDom)->Vec<rbx_dom_weak::types::Ref>{
|
fn get_script_refs(dom:&rbx_dom_weak::WeakDom)->Vec<rbx_dom_weak::types::Ref>{
|
||||||
let db=rbx_reflection_database::get();
|
let db=rbx_reflection_database::get().unwrap();
|
||||||
let superclass=&db.classes["LuaSourceContainer"];
|
let superclass=&db.classes["LuaSourceContainer"];
|
||||||
dom.descendants().filter_map(|inst|{
|
dom.descendants().filter_map(|inst|{
|
||||||
let class=db.classes.get(inst.class.as_str())?;
|
let class=db.classes.get(inst.class.as_str())?;
|
||||||
|
|||||||
34
web/.gitignore
vendored
34
web/.gitignore
vendored
@@ -1,24 +1,12 @@
|
|||||||
bun.lockb
|
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
/node_modules
|
/node_modules
|
||||||
/.pnp
|
|
||||||
.pnp.*
|
|
||||||
.yarn/*
|
|
||||||
!.yarn/patches
|
|
||||||
!.yarn/plugins
|
|
||||||
!.yarn/releases
|
|
||||||
!.yarn/versions
|
|
||||||
|
|
||||||
# testing
|
# testing
|
||||||
/coverage
|
/coverage
|
||||||
|
|
||||||
# next.js
|
|
||||||
/.next/
|
|
||||||
/out/
|
|
||||||
|
|
||||||
# production
|
# production
|
||||||
/build
|
/build
|
||||||
|
/dist
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
@@ -29,12 +17,22 @@ npm-debug.log*
|
|||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
# env files (can opt-in for committing if needed)
|
# env files
|
||||||
.env*
|
.env*
|
||||||
|
.env.local
|
||||||
# vercel
|
.env.development.local
|
||||||
.vercel
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
# typescript
|
# typescript
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
next-env.d.ts
|
|
||||||
|
# editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|||||||
@@ -1,13 +1,29 @@
|
|||||||
FROM registry.itzana.me/docker-proxy/oven/bun:1.2.8
|
# Build stage
|
||||||
|
FROM registry.itzana.me/docker-proxy/oven/bun:1.3.3 AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json bun.lockb* ./
|
||||||
|
RUN bun install --frozen-lockfile
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
RUN bun run build
|
||||||
|
|
||||||
|
# Release
|
||||||
|
FROM registry.itzana.me/docker-proxy/nginx:alpine
|
||||||
|
|
||||||
|
COPY --from=builder /app/build /usr/share/nginx/html
|
||||||
|
|
||||||
|
# Add nginx configuration for SPA routing
|
||||||
|
RUN echo 'server { \
|
||||||
|
listen 3000; \
|
||||||
|
location / { \
|
||||||
|
root /usr/share/nginx/html; \
|
||||||
|
index index.html; \
|
||||||
|
try_files $uri $uri/ /index.html; \
|
||||||
|
} \
|
||||||
|
}' > /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
|
|
||||||
RUN bun install
|
|
||||||
RUN bun run build
|
|
||||||
ENTRYPOINT ["bun", "run", "start"]
|
|
||||||
|
|||||||
755
web/bun.lock
755
web/bun.lock
File diff suppressed because it is too large
Load Diff
13
web/index.html
Normal file
13
web/index.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Maps Service</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import type { NextConfig } from "next";
|
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
|
||||||
distDir: "build",
|
|
||||||
output: "standalone",
|
|
||||||
images: {
|
|
||||||
remotePatterns: [
|
|
||||||
{
|
|
||||||
protocol: "https",
|
|
||||||
hostname: "**.rbxcdn.com",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default nextConfig;
|
|
||||||
4078
web/package-lock.json
generated
Normal file
4078
web/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -2,30 +2,33 @@
|
|||||||
"name": "map-service-web",
|
"name": "map-service-web",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev -p 3000 --turbopack",
|
"dev": "vite",
|
||||||
"build": "next build",
|
"build": "tsc && vite build",
|
||||||
"start": "next start -p 3000",
|
"preview": "vite preview",
|
||||||
"lint": "next lint"
|
"lint": "eslint src --ext ts,tsx"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.14.1",
|
||||||
"@mui/icons-material": "^6.1.10",
|
"@mui/icons-material": "^7.3.6",
|
||||||
"@mui/material": "^6.1.10",
|
"@mui/material": "^7.3.6",
|
||||||
|
"@tanstack/react-query": "^5.90.12",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"next": "^15.1.0",
|
"react": "^19.2.1",
|
||||||
"react": "^19.0.0",
|
"react-dom": "^19.2.1",
|
||||||
"react-dom": "^19.0.0",
|
"react-router-dom": "^7.1.3",
|
||||||
"sass": "^1.82.0"
|
"sass": "^1.94.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.2.0",
|
"@eslint/eslintrc": "^3.3.3",
|
||||||
"@types/node": "^20.17.9",
|
"@types/node": "^24.10.1",
|
||||||
"@types/react": "^19.0.1",
|
"@types/react": "^19.2.7",
|
||||||
"@types/react-dom": "^19.0.2",
|
"@types/react-dom": "^19.2.3",
|
||||||
"eslint": "^9.16.0",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
"eslint-config-next": "15.1.0",
|
"eslint": "^9.39.1",
|
||||||
"typescript": "^5.7.2"
|
"typescript": "^5.9.3",
|
||||||
|
"vite": "^6.0.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
44
web/src/App.tsx
Normal file
44
web/src/App.tsx
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { Routes, Route } from 'react-router-dom'
|
||||||
|
import { ThemeProvider } from '@mui/material'
|
||||||
|
import { theme } from '@/app/lib/theme'
|
||||||
|
|
||||||
|
// Pages
|
||||||
|
import Home from '@/app/page'
|
||||||
|
import MapsPage from '@/app/maps/page'
|
||||||
|
import MapDetailPage from '@/app/maps/[mapId]/page'
|
||||||
|
import MapFixCreatePage from '@/app/maps/[mapId]/fix/page'
|
||||||
|
import MapfixesPage from '@/app/mapfixes/page'
|
||||||
|
import MapfixDetailPage from '@/app/mapfixes/[mapfixId]/page'
|
||||||
|
import SubmissionsPage from '@/app/submissions/page'
|
||||||
|
import SubmissionDetailPage from '@/app/submissions/[submissionId]/page'
|
||||||
|
import SubmitPage from '@/app/submit/page'
|
||||||
|
import AdminSubmitPage from '@/app/admin-submit/page'
|
||||||
|
import OperationPage from '@/app/operations/[operationId]/page'
|
||||||
|
import ReviewerDashboardPage from '@/app/reviewer-dashboard/page'
|
||||||
|
import UserDashboardPage from '@/app/user-dashboard/page'
|
||||||
|
import NotFound from '@/app/not-found/page'
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<ThemeProvider theme={theme}>
|
||||||
|
<Routes>
|
||||||
|
<Route path="/" element={<Home />} />
|
||||||
|
<Route path="/maps" element={<MapsPage />} />
|
||||||
|
<Route path="/maps/:mapId" element={<MapDetailPage />} />
|
||||||
|
<Route path="/maps/:mapId/fix" element={<MapFixCreatePage />} />
|
||||||
|
<Route path="/mapfixes" element={<MapfixesPage />} />
|
||||||
|
<Route path="/mapfixes/:mapfixId" element={<MapfixDetailPage />} />
|
||||||
|
<Route path="/submissions" element={<SubmissionsPage />} />
|
||||||
|
<Route path="/submissions/:submissionId" element={<SubmissionDetailPage />} />
|
||||||
|
<Route path="/submit" element={<SubmitPage />} />
|
||||||
|
<Route path="/admin-submit" element={<AdminSubmitPage />} />
|
||||||
|
<Route path="/operations/:operationId" element={<OperationPage />} />
|
||||||
|
<Route path="/review" element={<ReviewerDashboardPage />} />
|
||||||
|
<Route path="/dashboard" element={<UserDashboardPage />} />
|
||||||
|
<Route path="*" element={<NotFound />} />
|
||||||
|
</Routes>
|
||||||
|
</ThemeProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import {Box, IconButton, Typography} from "@mui/material";
|
import {Box, Button, IconButton, Typography} from "@mui/material";
|
||||||
import {useEffect, useRef, useState} from "react";
|
import {useEffect, useRef, useState} from "react";
|
||||||
import Link from "next/link";
|
import { Link } from "react-router-dom";
|
||||||
import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew";
|
import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew";
|
||||||
import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos";
|
import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos";
|
||||||
import {SubmissionInfo} from "@/app/ts/Submission";
|
import {SubmissionInfo} from "@/app/ts/Submission";
|
||||||
@@ -65,14 +65,22 @@ export function Carousel<T extends CarouselItem>({ title, items, renderItem, vie
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box mb={6}>
|
<Box mb={6}>
|
||||||
<Box display="flex" justifyContent="space-between" alignItems="center" mb={2}>
|
<Box display="flex" justifyContent="space-between" alignItems="center" mb={3}>
|
||||||
<Typography variant="h4" component="h2" fontWeight="bold">
|
<Typography variant="h4" component="h2" fontWeight="bold">
|
||||||
{title}
|
{title}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Link href={viewAllLink} style={{textDecoration: 'none'}}>
|
<Link to={viewAllLink} style={{textDecoration: 'none'}}>
|
||||||
<Typography component="span" color="primary">
|
<Button
|
||||||
View All →
|
endIcon={<ArrowForwardIosIcon sx={{ fontSize: '0.875rem' }} />}
|
||||||
</Typography>
|
sx={{
|
||||||
|
color: 'primary.main',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: 'rgba(99, 102, 241, 0.1)',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
View All
|
||||||
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
@@ -85,9 +93,12 @@ export function Carousel<T extends CarouselItem>({ title, items, renderItem, vie
|
|||||||
transform: 'translateY(-50%)',
|
transform: 'translateY(-50%)',
|
||||||
zIndex: 2,
|
zIndex: 2,
|
||||||
backgroundColor: 'background.paper',
|
backgroundColor: 'background.paper',
|
||||||
boxShadow: 2,
|
border: '1px solid rgba(99, 102, 241, 0.2)',
|
||||||
|
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
backgroundColor: 'action.hover',
|
backgroundColor: 'background.paper',
|
||||||
|
borderColor: 'rgba(99, 102, 241, 0.4)',
|
||||||
|
boxShadow: '0 8px 20px rgba(99, 102, 241, 0.3)',
|
||||||
},
|
},
|
||||||
visibility: scrollPosition <= 5 ? 'hidden' : 'visible',
|
visibility: scrollPosition <= 5 ? 'hidden' : 'visible',
|
||||||
}}
|
}}
|
||||||
@@ -106,7 +117,7 @@ export function Carousel<T extends CarouselItem>({ title, items, renderItem, vie
|
|||||||
'&::-webkit-scrollbar': {
|
'&::-webkit-scrollbar': {
|
||||||
display: 'none',
|
display: 'none',
|
||||||
},
|
},
|
||||||
gap: '16px', // Fixed 16px gap - using string with px unit to ensure it's absolute
|
gap: '20px',
|
||||||
padding: '8px 4px',
|
padding: '8px 4px',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -116,7 +127,7 @@ export function Carousel<T extends CarouselItem>({ title, items, renderItem, vie
|
|||||||
sx={{
|
sx={{
|
||||||
flex: '0 0 auto',
|
flex: '0 0 auto',
|
||||||
width: {
|
width: {
|
||||||
xs: '260px', // Fixed width at different breakpoints
|
xs: '260px',
|
||||||
sm: '280px',
|
sm: '280px',
|
||||||
md: '300px'
|
md: '300px'
|
||||||
}
|
}
|
||||||
@@ -135,9 +146,12 @@ export function Carousel<T extends CarouselItem>({ title, items, renderItem, vie
|
|||||||
transform: 'translateY(-50%)',
|
transform: 'translateY(-50%)',
|
||||||
zIndex: 2,
|
zIndex: 2,
|
||||||
backgroundColor: 'background.paper',
|
backgroundColor: 'background.paper',
|
||||||
boxShadow: 2,
|
border: '1px solid rgba(99, 102, 241, 0.2)',
|
||||||
|
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
backgroundColor: 'action.hover',
|
backgroundColor: 'background.paper',
|
||||||
|
borderColor: 'rgba(99, 102, 241, 0.4)',
|
||||||
|
boxShadow: '0 8px 20px rgba(99, 102, 241, 0.3)',
|
||||||
},
|
},
|
||||||
visibility: scrollPosition >= maxScroll - 5 ? 'hidden' : 'visible',
|
visibility: scrollPosition >= maxScroll - 5 ? 'hidden' : 'visible',
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import React from 'react';
|
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Avatar,
|
Avatar,
|
||||||
Typography,
|
Typography,
|
||||||
Tooltip
|
Tooltip,
|
||||||
|
Skeleton
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import PersonIcon from '@mui/icons-material/Person';
|
import PersonIcon from '@mui/icons-material/Person';
|
||||||
import { formatDistanceToNow, format } from "date-fns";
|
import { formatDistanceToNow, format } from "date-fns";
|
||||||
import { AuditEvent, decodeAuditEvent as auditEventMessage } from "@/app/ts/AuditEvent";
|
import { AuditEvent, decodeAuditEvent as auditEventMessage } from "@/app/ts/AuditEvent";
|
||||||
|
import { useUserThumbnail } from "@/app/hooks/useThumbnails";
|
||||||
|
|
||||||
interface AuditEventItemProps {
|
interface AuditEventItemProps {
|
||||||
event: AuditEvent;
|
event: AuditEvent;
|
||||||
@@ -15,17 +16,39 @@ interface AuditEventItemProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function AuditEventItem({ event, validatorUser }: AuditEventItemProps) {
|
export default function AuditEventItem({ event, validatorUser }: AuditEventItemProps) {
|
||||||
|
const isValidator = event.User === validatorUser;
|
||||||
|
const { thumbnailUrl, isLoading } = useUserThumbnail(isValidator ? undefined : event.User, '150x150');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: 'flex', gap: 2 }}>
|
<Box sx={{ display: 'flex', gap: 2 }}>
|
||||||
<Avatar
|
<Box sx={{ position: 'relative', width: 40, height: 40 }}>
|
||||||
src={event.User === validatorUser ? undefined : `/thumbnails/user/${event.User}`}
|
<Skeleton
|
||||||
>
|
variant="circular"
|
||||||
<PersonIcon />
|
sx={{
|
||||||
</Avatar>
|
position: 'absolute',
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
opacity: isLoading ? 1 : 0,
|
||||||
|
transition: 'opacity 0.3s ease-in-out',
|
||||||
|
}}
|
||||||
|
animation="wave"
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
src={isValidator ? undefined : (thumbnailUrl || undefined)}
|
||||||
|
sx={{
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
opacity: isLoading ? 0 : 1,
|
||||||
|
transition: 'opacity 0.3s ease-in-out',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PersonIcon />
|
||||||
|
</Avatar>
|
||||||
|
</Box>
|
||||||
<Box sx={{ flexGrow: 1 }}>
|
<Box sx={{ flexGrow: 1 }}>
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
<Typography variant="subtitle2">
|
<Typography variant="subtitle2">
|
||||||
{event.User === validatorUser ? "Validator" : event.Username || "Unknown"}
|
{isValidator ? "Validator" : event.Username || "Unknown"}
|
||||||
</Typography>
|
</Typography>
|
||||||
<DateDisplay date={event.Date} />
|
<DateDisplay date={event.Date} />
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Stack,
|
Stack,
|
||||||
@@ -22,18 +21,21 @@ export default function AuditEventsTabPanel({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box role="tabpanel" hidden={activeTab !== 1}>
|
<Box
|
||||||
{activeTab === 1 && (
|
role="tabpanel"
|
||||||
<Stack spacing={2}>
|
sx={{
|
||||||
{filteredEvents.map((event, index) => (
|
display: activeTab === 1 ? 'block' : 'none'
|
||||||
<AuditEventItem
|
}}
|
||||||
key={index}
|
>
|
||||||
event={event}
|
<Stack spacing={2}>
|
||||||
validatorUser={validatorUser}
|
{filteredEvents.map((event, index) => (
|
||||||
/>
|
<AuditEventItem
|
||||||
))}
|
key={index}
|
||||||
</Stack>
|
event={event}
|
||||||
)}
|
validatorUser={validatorUser}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
import React from 'react';
|
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Avatar,
|
Avatar,
|
||||||
Typography,
|
Typography,
|
||||||
Tooltip
|
Tooltip,
|
||||||
|
Skeleton
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import PersonIcon from '@mui/icons-material/Person';
|
import PersonIcon from '@mui/icons-material/Person';
|
||||||
import { formatDistanceToNow, format } from "date-fns";
|
import { formatDistanceToNow, format } from "date-fns";
|
||||||
import { AuditEvent, decodeAuditEvent } from "@/app/ts/AuditEvent";
|
import { AuditEvent, decodeAuditEvent } from "@/app/ts/AuditEvent";
|
||||||
|
import { useUserThumbnail } from "@/app/hooks/useThumbnails";
|
||||||
|
|
||||||
interface CommentItemProps {
|
interface CommentItemProps {
|
||||||
event: AuditEvent;
|
event: AuditEvent;
|
||||||
@@ -15,21 +16,43 @@ interface CommentItemProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function CommentItem({ event, validatorUser }: CommentItemProps) {
|
export default function CommentItem({ event, validatorUser }: CommentItemProps) {
|
||||||
|
const isValidator = event.User === validatorUser;
|
||||||
|
const { thumbnailUrl, isLoading } = useUserThumbnail(isValidator ? undefined : event.User, '150x150');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: 'flex', gap: 2 }}>
|
<Box sx={{ display: 'flex', gap: 2 }}>
|
||||||
<Avatar
|
<Box sx={{ position: 'relative', width: 40, height: 40 }}>
|
||||||
src={event.User === validatorUser ? undefined : `/thumbnails/user/${event.User}`}
|
<Skeleton
|
||||||
>
|
variant="circular"
|
||||||
<PersonIcon />
|
sx={{
|
||||||
</Avatar>
|
position: 'absolute',
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
opacity: isLoading ? 1 : 0,
|
||||||
|
transition: 'opacity 0.3s ease-in-out',
|
||||||
|
}}
|
||||||
|
animation="wave"
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
src={isValidator ? undefined : (thumbnailUrl || undefined)}
|
||||||
|
sx={{
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
opacity: isLoading ? 0 : 1,
|
||||||
|
transition: 'opacity 0.3s ease-in-out',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PersonIcon />
|
||||||
|
</Avatar>
|
||||||
|
</Box>
|
||||||
<Box sx={{ flexGrow: 1 }}>
|
<Box sx={{ flexGrow: 1 }}>
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
<Typography variant="subtitle2">
|
<Typography variant="subtitle2">
|
||||||
{event.User === validatorUser ? "Validator" : event.Username || "Unknown"}
|
{isValidator ? "Validator" : event.Username || "Unknown"}
|
||||||
</Typography>
|
</Typography>
|
||||||
<DateDisplay date={event.Date} />
|
<DateDisplay date={event.Date} />
|
||||||
</Box>
|
</Box>
|
||||||
<Typography variant="body2">{decodeAuditEvent(event)}</Typography>
|
<Typography variant="body2" sx={{ whiteSpace: 'pre-wrap' }}>{decodeAuditEvent(event)}</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export default function CommentsAndAuditSection({
|
|||||||
}: CommentsAndAuditSectionProps) {
|
}: CommentsAndAuditSectionProps) {
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = useState(0);
|
const [activeTab, setActiveTab] = useState(0);
|
||||||
const handleTabChange = (event: React.SyntheticEvent, newValue: number) => {
|
const handleTabChange = (_event: React.SyntheticEvent, newValue: number) => {
|
||||||
setActiveTab(newValue);
|
setActiveTab(newValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import React from 'react';
|
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Stack,
|
Stack,
|
||||||
Avatar,
|
Avatar,
|
||||||
TextField,
|
TextField,
|
||||||
IconButton
|
IconButton,
|
||||||
|
Skeleton
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import SendIcon from '@mui/icons-material/Send';
|
import SendIcon from '@mui/icons-material/Send';
|
||||||
import { AuditEvent, AuditEventType } from "@/app/ts/AuditEvent";
|
import { AuditEvent, AuditEventType } from "@/app/ts/AuditEvent";
|
||||||
import CommentItem from './CommentItem';
|
import CommentItem from './CommentItem';
|
||||||
|
import { useUserThumbnail } from "@/app/hooks/useThumbnails";
|
||||||
|
|
||||||
interface CommentsTabPanelProps {
|
interface CommentsTabPanelProps {
|
||||||
activeTab: number;
|
activeTab: number;
|
||||||
@@ -34,34 +35,35 @@ export default function CommentsTabPanel({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box role="tabpanel" hidden={activeTab !== 0}>
|
<Box
|
||||||
{activeTab === 0 && (
|
role="tabpanel"
|
||||||
<>
|
sx={{
|
||||||
<Stack spacing={2} sx={{ mb: 3 }}>
|
display: activeTab === 0 ? 'block' : 'none'
|
||||||
{commentEvents.length > 0 ? (
|
}}
|
||||||
commentEvents.map((event, index) => (
|
>
|
||||||
<CommentItem
|
<Stack spacing={2} sx={{ mb: 3 }}>
|
||||||
key={index}
|
{commentEvents.length > 0 ? (
|
||||||
event={event}
|
commentEvents.map((event, index) => (
|
||||||
validatorUser={validatorUser}
|
<CommentItem
|
||||||
/>
|
key={index}
|
||||||
))
|
event={event}
|
||||||
) : (
|
validatorUser={validatorUser}
|
||||||
<Box sx={{ textAlign: 'center', py: 2, color: 'text.secondary' }}>
|
|
||||||
No Comments
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
{userId !== null && (
|
|
||||||
<CommentInput
|
|
||||||
newComment={newComment}
|
|
||||||
setNewComment={setNewComment}
|
|
||||||
handleCommentSubmit={handleCommentSubmit}
|
|
||||||
userId={userId}
|
|
||||||
/>
|
/>
|
||||||
)}
|
))
|
||||||
</>
|
) : (
|
||||||
|
<Box sx={{ textAlign: 'center', py: 2, color: 'text.secondary' }}>
|
||||||
|
No Comments
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
{userId !== null && (
|
||||||
|
<CommentInput
|
||||||
|
newComment={newComment}
|
||||||
|
setNewComment={setNewComment}
|
||||||
|
handleCommentSubmit={handleCommentSubmit}
|
||||||
|
userId={userId}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
@@ -75,11 +77,32 @@ interface CommentInputProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function CommentInput({ newComment, setNewComment, handleCommentSubmit, userId }: CommentInputProps) {
|
function CommentInput({ newComment, setNewComment, handleCommentSubmit, userId }: CommentInputProps) {
|
||||||
|
const { thumbnailUrl, isLoading } = useUserThumbnail(userId || undefined, '150x150');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: 'flex', gap: 2, alignItems: 'flex-start' }}>
|
<Box sx={{ display: 'flex', gap: 2, alignItems: 'flex-start' }}>
|
||||||
<Avatar
|
<Box sx={{ position: 'relative', width: 40, height: 40 }}>
|
||||||
src={`/thumbnails/user/${userId}`}
|
<Skeleton
|
||||||
/>
|
variant="circular"
|
||||||
|
sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
opacity: isLoading ? 1 : 0,
|
||||||
|
transition: 'opacity 0.3s ease-in-out',
|
||||||
|
}}
|
||||||
|
animation="wave"
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
src={thumbnailUrl || undefined}
|
||||||
|
sx={{
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
opacity: isLoading ? 0 : 1,
|
||||||
|
transition: 'opacity 0.3s ease-in-out',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
multiline
|
multiline
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
"use client"
|
import { Link } from "react-router-dom"
|
||||||
|
import { useState, useRef } from "react";
|
||||||
import Link from "next/link"
|
import { useUser } from "@/app/hooks/useUser";
|
||||||
import Image from "next/image";
|
|
||||||
import { UserInfo } from "@/app/ts/User";
|
|
||||||
import { useState, useEffect } from "react";
|
|
||||||
|
|
||||||
import AppBar from "@mui/material/AppBar";
|
import AppBar from "@mui/material/AppBar";
|
||||||
import Toolbar from "@mui/material/Toolbar";
|
import Toolbar from "@mui/material/Toolbar";
|
||||||
@@ -37,7 +34,7 @@ const navItems: HeaderButton[] = [
|
|||||||
|
|
||||||
function HeaderButton(header: HeaderButton) {
|
function HeaderButton(header: HeaderButton) {
|
||||||
return (
|
return (
|
||||||
<Button color="inherit" component={Link} href={header.href}>
|
<Button color="inherit" component={Link} to={header.href}>
|
||||||
{header.name}
|
{header.name}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
@@ -47,14 +44,26 @@ export default function Header() {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
const [mobileOpen, setMobileOpen] = useState(false);
|
const [mobileOpen, setMobileOpen] = useState(false);
|
||||||
|
const hasAnimated = useRef(false);
|
||||||
|
|
||||||
const handleLoginClick = () => {
|
const getAuthUrl = () => {
|
||||||
window.location.href =
|
const hostname = window.location.hostname;
|
||||||
"/auth/oauth2/login?redirect=" + window.location.href;
|
|
||||||
|
// Production only
|
||||||
|
if (hostname === 'maps.strafes.net') {
|
||||||
|
return 'https://auth.strafes.net';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default to staging (works for staging.strafes.net and localhost)
|
||||||
|
return 'https://auth.staging.strafes.net';
|
||||||
};
|
};
|
||||||
|
|
||||||
const [valid, setValid] = useState<boolean>(false);
|
const handleLoginClick = () => {
|
||||||
const [user, setUser] = useState<UserInfo | null>(null);
|
const authUrl = getAuthUrl();
|
||||||
|
window.location.href = `${authUrl}/oauth2/login?redirect=${window.location.href}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { user, isLoggedIn } = useUser();
|
||||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||||
const [quickLinksAnchor, setQuickLinksAnchor] = useState<null | HTMLElement>(null);
|
const [quickLinksAnchor, setQuickLinksAnchor] = useState<null | HTMLElement>(null);
|
||||||
|
|
||||||
@@ -77,60 +86,34 @@ export default function Header() {
|
|||||||
setQuickLinksAnchor(null);
|
setQuickLinksAnchor(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
async function getLoginInfo() {
|
|
||||||
try {
|
|
||||||
const response = await fetch("/api/session/user");
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
setValid(false);
|
|
||||||
setUser(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const userData = await response.json();
|
|
||||||
const isLoggedIn = userData && 'UserID' in userData;
|
|
||||||
|
|
||||||
setValid(isLoggedIn);
|
|
||||||
setUser(isLoggedIn ? userData : null);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching user data:", error);
|
|
||||||
setValid(false);
|
|
||||||
setUser(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getLoginInfo();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Mobile navigation drawer content
|
// Mobile navigation drawer content
|
||||||
const drawer = (
|
const drawer = (
|
||||||
<Box onClick={handleDrawerToggle} sx={{ textAlign: 'center' }}>
|
<Box onClick={handleDrawerToggle} sx={{ textAlign: 'center' }}>
|
||||||
<List>
|
<List>
|
||||||
{navItems.map((item) => (
|
{navItems.map((item) => (
|
||||||
<ListItem key={item.name} disablePadding>
|
<ListItem key={item.name} disablePadding>
|
||||||
<ListItemButton component={Link} href={item.href} sx={{ textAlign: 'center' }}>
|
<ListItemButton component={Link} to={item.href} sx={{ textAlign: 'center' }}>
|
||||||
<ListItemText primary={item.name} />
|
<ListItemText primary={item.name} />
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
))}
|
))}
|
||||||
{valid && user && (
|
{isLoggedIn && user && (
|
||||||
<ListItem disablePadding>
|
<ListItem disablePadding>
|
||||||
<ListItemButton component={Link} href="/submit" sx={{ textAlign: 'center' }}>
|
<ListItemButton component={Link} to="/submit" sx={{ textAlign: 'center' }}>
|
||||||
<ListItemText primary="Submit Map" sx={{ color: 'success.main' }} />
|
<ListItemText primary="Submit Map" sx={{ color: 'success.main' }} />
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
)}
|
)}
|
||||||
{!valid && (
|
{!isLoggedIn && (
|
||||||
<ListItem disablePadding>
|
<ListItem disablePadding>
|
||||||
<ListItemButton onClick={handleLoginClick} sx={{ textAlign: 'center' }}>
|
<ListItemButton onClick={handleLoginClick} sx={{ textAlign: 'center' }}>
|
||||||
<ListItemText primary="Login" />
|
<ListItemText primary="Login" />
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
)}
|
)}
|
||||||
{valid && user && (
|
{isLoggedIn && user && (
|
||||||
<ListItem disablePadding>
|
<ListItem disablePadding>
|
||||||
<ListItemButton component={Link} href="/auth" sx={{ textAlign: 'center' }}>
|
<ListItemButton component="a" href={getAuthUrl()} sx={{ textAlign: 'center' }}>
|
||||||
<ListItemText primary="Manage Account" />
|
<ListItemText primary="Manage Account" />
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
@@ -150,7 +133,7 @@ export default function Header() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<AppBar position="static">
|
<AppBar position="static">
|
||||||
<Toolbar>
|
<Toolbar sx={{ py: 1 }}>
|
||||||
{isMobile && (
|
{isMobile && (
|
||||||
<IconButton
|
<IconButton
|
||||||
color="inherit"
|
color="inherit"
|
||||||
@@ -165,20 +148,144 @@ export default function Header() {
|
|||||||
|
|
||||||
{/* Desktop navigation */}
|
{/* Desktop navigation */}
|
||||||
{!isMobile && (
|
{!isMobile && (
|
||||||
<Box display="flex" flexGrow={1} gap={2} alignItems="center">
|
<Box display="flex" flexGrow={1} gap={1} alignItems="center">
|
||||||
|
{/* Logo/Brand */}
|
||||||
|
<Box
|
||||||
|
component={Link}
|
||||||
|
to="/"
|
||||||
|
sx={{
|
||||||
|
mr: 4,
|
||||||
|
textDecoration: 'none',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
position: 'relative',
|
||||||
|
overflow: 'hidden',
|
||||||
|
'@keyframes speedLine': {
|
||||||
|
'0%': {
|
||||||
|
transform: 'translateX(-50px) scaleX(0.5)',
|
||||||
|
opacity: 0,
|
||||||
|
},
|
||||||
|
'40%': {
|
||||||
|
opacity: 0.8,
|
||||||
|
transform: 'translateX(0px) scaleX(1)',
|
||||||
|
},
|
||||||
|
'100%': {
|
||||||
|
opacity: 0,
|
||||||
|
transform: 'translateX(30px) scaleX(0.7)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'@keyframes logoReveal': {
|
||||||
|
'0%': {
|
||||||
|
opacity: 0,
|
||||||
|
transform: 'translateX(-10px)',
|
||||||
|
filter: 'blur(2px)',
|
||||||
|
},
|
||||||
|
'100%': {
|
||||||
|
opacity: 1,
|
||||||
|
transform: 'translateX(0px)',
|
||||||
|
filter: 'blur(0px)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'&::before, &::after': {
|
||||||
|
content: '""',
|
||||||
|
position: 'absolute',
|
||||||
|
left: 0,
|
||||||
|
width: '100%',
|
||||||
|
height: '2px',
|
||||||
|
background: 'linear-gradient(90deg, transparent 10%, rgba(59, 130, 246, 0.8) 50%, transparent 90%)',
|
||||||
|
pointerEvents: 'none',
|
||||||
|
animation: !hasAnimated.current ? 'speedLine 0.6s ease-out forwards' : 'none',
|
||||||
|
opacity: !hasAnimated.current ? 0 : undefined,
|
||||||
|
},
|
||||||
|
'&::before': {
|
||||||
|
top: '35%',
|
||||||
|
animationDelay: !hasAnimated.current ? '0s' : undefined,
|
||||||
|
},
|
||||||
|
'&::after': {
|
||||||
|
top: '65%',
|
||||||
|
animationDelay: !hasAnimated.current ? '0.08s' : undefined,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: '50%',
|
||||||
|
left: 0,
|
||||||
|
width: '100%',
|
||||||
|
height: '1px',
|
||||||
|
background: 'linear-gradient(90deg, transparent 10%, rgba(139, 92, 246, 0.6) 50%, transparent 90%)',
|
||||||
|
animation: !hasAnimated.current ? 'speedLine 0.6s ease-out forwards' : 'none',
|
||||||
|
animationDelay: !hasAnimated.current ? '0.04s' : '0s',
|
||||||
|
opacity: !hasAnimated.current ? 0 : undefined,
|
||||||
|
pointerEvents: 'none',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Typography
|
||||||
|
variant="h6"
|
||||||
|
sx={{
|
||||||
|
color: 'text.primary',
|
||||||
|
fontWeight: 700,
|
||||||
|
letterSpacing: '-0.01em',
|
||||||
|
fontSize: '1.125rem',
|
||||||
|
position: 'relative',
|
||||||
|
zIndex: 1,
|
||||||
|
opacity: !hasAnimated.current ? 0 : 1,
|
||||||
|
animation: !hasAnimated.current ? 'logoReveal 0.5s ease-out forwards' : 'none',
|
||||||
|
animationDelay: !hasAnimated.current ? '0.5s' : '0s',
|
||||||
|
}}
|
||||||
|
onAnimationEnd={() => {
|
||||||
|
hasAnimated.current = true;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
StrafesNET
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
{navItems.map((item) => (
|
{navItems.map((item) => (
|
||||||
<HeaderButton key={item.name} name={item.name} href={item.href} />
|
<Button
|
||||||
|
key={item.name}
|
||||||
|
color="inherit"
|
||||||
|
component={Link}
|
||||||
|
to={item.href}
|
||||||
|
sx={{
|
||||||
|
px: 2,
|
||||||
|
py: 1,
|
||||||
|
borderRadius: 1.5,
|
||||||
|
fontSize: '0.9rem',
|
||||||
|
fontWeight: 500,
|
||||||
|
color: 'text.secondary',
|
||||||
|
transition: 'all 0.2s',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: 'rgba(59, 130, 246, 0.08)',
|
||||||
|
color: 'text.primary',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</Button>
|
||||||
))}
|
))}
|
||||||
<Box sx={{ flexGrow: 1 }} /> {/* Push quick links to the right */}
|
<Box sx={{ flexGrow: 1 }} />
|
||||||
{/* Quick Links Dropdown */}
|
{/* Quick Links Dropdown */}
|
||||||
<Box>
|
<Box>
|
||||||
<Button
|
<Button
|
||||||
color="inherit"
|
color="inherit"
|
||||||
endIcon={<ArrowDropDownIcon />}
|
endIcon={<ArrowDropDownIcon />}
|
||||||
onClick={handleQuickLinksOpen}
|
onClick={handleQuickLinksOpen}
|
||||||
sx={{ textTransform: 'none', fontSize: '0.95rem', px: 1 }}
|
sx={{
|
||||||
|
px: 2,
|
||||||
|
mr: 1,
|
||||||
|
borderRadius: 1.5,
|
||||||
|
fontSize: '0.9rem',
|
||||||
|
fontWeight: 500,
|
||||||
|
color: 'text.secondary',
|
||||||
|
transition: 'all 0.2s',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: 'rgba(59, 130, 246, 0.08)',
|
||||||
|
color: 'text.primary',
|
||||||
|
},
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
QUICK LINKS
|
Quick Links
|
||||||
</Button>
|
</Button>
|
||||||
<Menu
|
<Menu
|
||||||
anchorEl={quickLinksAnchor}
|
anchorEl={quickLinksAnchor}
|
||||||
@@ -186,12 +293,20 @@ export default function Header() {
|
|||||||
onClose={handleQuickLinksClose}
|
onClose={handleQuickLinksClose}
|
||||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
||||||
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
|
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
|
||||||
|
sx={{
|
||||||
|
'& .MuiMenu-paper': {
|
||||||
|
mt: 1.5,
|
||||||
|
},
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{quickLinks.map(link => (
|
{quickLinks.map(link => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={link.name}
|
key={link.name}
|
||||||
onClick={handleQuickLinksClose}
|
onClick={handleQuickLinksClose}
|
||||||
sx={{ minWidth: 180 }}
|
sx={{
|
||||||
|
minWidth: 200,
|
||||||
|
fontSize: '0.9rem',
|
||||||
|
}}
|
||||||
component="a"
|
component="a"
|
||||||
href={link.href}
|
href={link.href}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -209,30 +324,53 @@ export default function Header() {
|
|||||||
{isMobile && <Box sx={{ flexGrow: 1 }} />}
|
{isMobile && <Box sx={{ flexGrow: 1 }} />}
|
||||||
|
|
||||||
{/* Right side of nav */}
|
{/* Right side of nav */}
|
||||||
<Box display="flex" gap={2}>
|
<Box display="flex" gap={2} alignItems="center">
|
||||||
{!isMobile && valid && user && (
|
{!isMobile && isLoggedIn && user && (
|
||||||
<Button variant="outlined" color="success" component={Link} href="/submit">
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
component={Link}
|
||||||
|
to="/submit"
|
||||||
|
sx={{
|
||||||
|
px: 3,
|
||||||
|
}}
|
||||||
|
>
|
||||||
Submit Map
|
Submit Map
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{!isMobile && valid && user ? (
|
{!isMobile && isLoggedIn && user ? (
|
||||||
<Box display="flex" alignItems="center">
|
<Box display="flex" alignItems="center">
|
||||||
<Button
|
<Button
|
||||||
onClick={handleMenuOpen}
|
onClick={handleMenuOpen}
|
||||||
color="inherit"
|
color="inherit"
|
||||||
size="small"
|
size="small"
|
||||||
style={{ textTransform: "none" }}
|
sx={{
|
||||||
|
textTransform: "none",
|
||||||
|
borderRadius: 1.5,
|
||||||
|
px: 1.5,
|
||||||
|
py: 0.75,
|
||||||
|
border: '1px solid rgba(255, 255, 255, 0.08)',
|
||||||
|
transition: 'all 0.2s',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: 'rgba(59, 130, 246, 0.08)',
|
||||||
|
borderColor: 'rgba(59, 130, 246, 0.3)',
|
||||||
|
},
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Image
|
<img
|
||||||
className="avatar"
|
className="avatar"
|
||||||
width={28}
|
width={28}
|
||||||
height={28}
|
height={28}
|
||||||
priority={true}
|
|
||||||
src={user.AvatarURL}
|
src={user.AvatarURL}
|
||||||
alt={user.Username}
|
alt={user.Username}
|
||||||
style={{ marginRight: 8 }}
|
style={{
|
||||||
|
marginRight: 8,
|
||||||
|
borderRadius: '50%',
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<Typography variant="body1">{user.Username}</Typography>
|
<Typography variant="body2" sx={{ fontSize: '0.875rem', fontWeight: 500 }}>
|
||||||
|
{user.Username}
|
||||||
|
</Typography>
|
||||||
</Button>
|
</Button>
|
||||||
<Menu
|
<Menu
|
||||||
anchorEl={anchorEl}
|
anchorEl={anchorEl}
|
||||||
@@ -240,38 +378,58 @@ export default function Header() {
|
|||||||
onClose={handleMenuClose}
|
onClose={handleMenuClose}
|
||||||
anchorOrigin={{
|
anchorOrigin={{
|
||||||
vertical: "bottom",
|
vertical: "bottom",
|
||||||
horizontal: "left",
|
horizontal: "right",
|
||||||
}}
|
}}
|
||||||
transformOrigin={{
|
transformOrigin={{
|
||||||
vertical: "top",
|
vertical: "top",
|
||||||
horizontal: "left",
|
horizontal: "right",
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
'& .MuiMenu-paper': {
|
||||||
|
mt: 1.5,
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MenuItem component={Link} href="/auth">
|
<MenuItem
|
||||||
Manage
|
component="a"
|
||||||
|
href={getAuthUrl()}
|
||||||
|
sx={{
|
||||||
|
fontSize: '0.9rem',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Manage Account
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
</Box>
|
</Box>
|
||||||
) : !isMobile && (
|
) : !isMobile && (
|
||||||
<Button color="inherit" onClick={handleLoginClick}>
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
color="primary"
|
||||||
|
onClick={handleLoginClick}
|
||||||
|
sx={{
|
||||||
|
px: 3,
|
||||||
|
}}
|
||||||
|
>
|
||||||
Login
|
Login
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* In mobile view, display just the avatar if logged in */}
|
{/* In mobile view, display just the avatar if logged in */}
|
||||||
{isMobile && valid && user && (
|
{isMobile && isLoggedIn && user && (
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={handleMenuOpen}
|
onClick={handleMenuOpen}
|
||||||
color="inherit"
|
color="inherit"
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
<Image
|
<img
|
||||||
className="avatar"
|
className="avatar"
|
||||||
width={28}
|
width={32}
|
||||||
height={28}
|
height={32}
|
||||||
priority={true}
|
|
||||||
src={user.AvatarURL}
|
src={user.AvatarURL}
|
||||||
alt={user.Username}
|
alt={user.Username}
|
||||||
|
style={{
|
||||||
|
borderRadius: '50%',
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
@@ -284,10 +442,13 @@ export default function Header() {
|
|||||||
open={mobileOpen}
|
open={mobileOpen}
|
||||||
onClose={handleDrawerToggle}
|
onClose={handleDrawerToggle}
|
||||||
ModalProps={{
|
ModalProps={{
|
||||||
keepMounted: true, // Better open performance on mobile
|
keepMounted: true,
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: 240 },
|
'& .MuiDrawer-paper': {
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
width: 240,
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{drawer}
|
{drawer}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import React from "react";
|
import {Avatar, Box, Card, CardActionArea, CardContent, CardMedia, Divider, Typography, Skeleton} from "@mui/material";
|
||||||
import {Avatar, Box, Card, CardActionArea, CardContent, CardMedia, Divider, Grid, Typography} from "@mui/material";
|
import {Explore, Person2, Assignment, Build} from "@mui/icons-material";
|
||||||
import {Explore, Person2} from "@mui/icons-material";
|
|
||||||
import {StatusChip} from "@/app/_components/statusChip";
|
import {StatusChip} from "@/app/_components/statusChip";
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
import {useAssetThumbnail, useUserThumbnail} from "@/app/hooks/useThumbnails";
|
||||||
|
import {useUsername} from "@/app/hooks/useUsername";
|
||||||
|
|
||||||
interface MapCardProps {
|
interface MapCardProps {
|
||||||
displayName: string;
|
displayName: string;
|
||||||
@@ -14,173 +16,176 @@ interface MapCardProps {
|
|||||||
gameID: number;
|
gameID: number;
|
||||||
created: number;
|
created: number;
|
||||||
type: 'mapfix' | 'submission';
|
type: 'mapfix' | 'submission';
|
||||||
|
showTypeBadge?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CARD_WIDTH = 270;
|
|
||||||
|
|
||||||
export function MapCard(props: MapCardProps) {
|
export function MapCard(props: MapCardProps) {
|
||||||
|
const { thumbnailUrl: assetThumbnail, isLoading: assetLoading } = useAssetThumbnail(props.assetId);
|
||||||
|
const { thumbnailUrl: userThumbnail, isLoading: userLoading } = useUserThumbnail(props.authorId);
|
||||||
|
const { username, isLoading: usernameLoading } = useUsername(props.type === 'mapfix' ? props.authorId : undefined);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid item xs={12} sm={6} md={3} key={props.assetId}>
|
<Card sx={{ height: '100%' }}>
|
||||||
<Box sx={{
|
<CardActionArea
|
||||||
width: CARD_WIDTH,
|
component={Link}
|
||||||
mx: 'auto', // Center the card in its grid cell
|
to={`/${props.type === 'submission' ? 'submissions' : 'mapfixes'}/${props.id}`}>
|
||||||
}}>
|
<Box sx={{ position: 'relative', overflow: 'hidden' }}>
|
||||||
<Card sx={{
|
<Skeleton
|
||||||
width: CARD_WIDTH,
|
variant="rectangular"
|
||||||
height: 340, // Fixed height for all cards
|
height={180}
|
||||||
display: 'flex',
|
animation="wave"
|
||||||
flexDirection: 'column',
|
|
||||||
}}>
|
|
||||||
<CardActionArea
|
|
||||||
sx={{
|
|
||||||
height: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'stretch'
|
|
||||||
}}
|
|
||||||
href={`/${props.type === 'submission' ? 'submissions' : 'mapfixes'}/${props.id}`}>
|
|
||||||
<Box sx={{ position: 'relative' }}>
|
|
||||||
<CardMedia
|
|
||||||
component="img"
|
|
||||||
image={`/thumbnails/asset/${props.assetId}`}
|
|
||||||
alt={props.displayName}
|
|
||||||
sx={{
|
sx={{
|
||||||
height: 160, // Fixed height for all images
|
position: 'absolute',
|
||||||
objectFit: 'cover',
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
opacity: assetLoading ? 1 : 0,
|
||||||
|
transition: 'opacity 0.3s ease-in-out',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<CardMedia
|
||||||
|
component="img"
|
||||||
|
image={assetThumbnail || '/placeholder-map.png'}
|
||||||
|
alt={props.displayName}
|
||||||
|
sx={{
|
||||||
|
height: 180,
|
||||||
|
objectFit: 'cover',
|
||||||
|
opacity: assetLoading ? 0 : 1,
|
||||||
|
transition: 'opacity 0.3s ease-in-out, transform 0.3s',
|
||||||
|
'&:hover': {
|
||||||
|
transform: 'scale(1.05)',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{props.showTypeBadge && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: 12,
|
||||||
|
left: 12,
|
||||||
|
opacity: assetLoading ? 0 : 1,
|
||||||
|
transition: 'opacity 0.3s ease-in-out 0.1s',
|
||||||
|
bgcolor: props.type === 'submission' ? 'primary.main' : 'secondary.main',
|
||||||
|
color: 'white',
|
||||||
|
borderRadius: '50%',
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
boxShadow: 2
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.type === 'submission' ? <Assignment sx={{ fontSize: '1.1rem' }} /> : <Build sx={{ fontSize: '1.1rem' }} />}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: 12,
|
top: 12,
|
||||||
right: 12,
|
right: 12,
|
||||||
|
opacity: assetLoading ? 0 : 1,
|
||||||
|
transition: 'opacity 0.3s ease-in-out 0.1s',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<StatusChip status={props.statusID}/>
|
<StatusChip status={props.statusID}/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<CardContent sx={{
|
<CardContent>
|
||||||
flex: 1,
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
p: 2,
|
|
||||||
width: '100%',
|
|
||||||
}}>
|
|
||||||
<Box>
|
<Box>
|
||||||
<Typography
|
<Typography
|
||||||
variant="subtitle1"
|
variant="h6"
|
||||||
component="div"
|
component="div"
|
||||||
sx={{
|
sx={{
|
||||||
mb: 1,
|
mb: 1.5,
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
color: '#fff',
|
lineHeight: '1.4',
|
||||||
lineHeight: '1.3',
|
|
||||||
// Allow text to wrap
|
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
textOverflow: 'ellipsis',
|
textOverflow: 'ellipsis',
|
||||||
display: '-webkit-box',
|
display: '-webkit-box',
|
||||||
WebkitLineClamp: 2,
|
WebkitLineClamp: 2,
|
||||||
WebkitBoxOrient: 'vertical',
|
WebkitBoxOrient: 'vertical',
|
||||||
|
minHeight: '2.8em',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.displayName}
|
{props.displayName}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
mb: 1.5,
|
gap: 2,
|
||||||
|
mb: 2,
|
||||||
|
flexWrap: 'wrap',
|
||||||
}}>
|
}}>
|
||||||
<Explore sx={{
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
|
||||||
mr: 0.75,
|
<Explore sx={{ fontSize: '1rem', color: '#6366f1' }} />
|
||||||
mt: 0.25,
|
<Typography variant="body2" color="text.secondary" fontSize="0.875rem">
|
||||||
color: 'text.secondary',
|
{props.gameID === 1 ? 'Bhop' : props.gameID === 2 ? 'Surf' : props.gameID === 5 ? 'Fly Trials' : props.gameID === 4 ? 'Deathrun' : 'Unknown'}
|
||||||
fontSize: '0.9rem',
|
</Typography>
|
||||||
flexShrink: 0,
|
</Box>
|
||||||
}} />
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
|
||||||
<Typography
|
<Person2 sx={{ fontSize: '1rem', color: '#8b5cf6' }} />
|
||||||
variant="body2"
|
{props.type === 'mapfix' && usernameLoading ? (
|
||||||
color="text.secondary"
|
<Skeleton variant="text" width={80} />
|
||||||
sx={{
|
) : (
|
||||||
fontWeight: 500,
|
<Typography
|
||||||
// Allow text to wrap
|
variant="body2"
|
||||||
overflow: 'hidden',
|
color="text.secondary"
|
||||||
textOverflow: 'ellipsis',
|
fontSize="0.875rem"
|
||||||
display: '-webkit-box',
|
sx={{
|
||||||
WebkitLineClamp: 2,
|
overflow: 'hidden',
|
||||||
WebkitBoxOrient: 'vertical',
|
textOverflow: 'ellipsis',
|
||||||
lineHeight: '1.2',
|
whiteSpace: 'nowrap',
|
||||||
wordBreak: 'break-word',
|
}}
|
||||||
}}
|
>
|
||||||
>
|
{props.type === 'mapfix' && username ? `@${username}` : props.author}
|
||||||
{props.gameID === 1 ? 'Bhop' : props.gameID === 2 ? 'Surf' : props.gameID === 5 ? 'Fly Trials' : props.gameID === 4 ? 'Deathrun' : 'Unknown'}
|
</Typography>
|
||||||
</Typography>
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{
|
|
||||||
display: 'flex',
|
|
||||||
mb: 1.5,
|
|
||||||
}}>
|
|
||||||
<Person2 sx={{
|
|
||||||
mr: 0.75,
|
|
||||||
mt: 0.25,
|
|
||||||
color: 'text.secondary',
|
|
||||||
fontSize: '0.9rem',
|
|
||||||
flexShrink: 0,
|
|
||||||
}} />
|
|
||||||
<Typography
|
|
||||||
variant="body2"
|
|
||||||
color="text.secondary"
|
|
||||||
sx={{
|
|
||||||
fontWeight: 500,
|
|
||||||
// Allow text to wrap
|
|
||||||
overflow: 'hidden',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
display: '-webkit-box',
|
|
||||||
WebkitLineClamp: 2,
|
|
||||||
WebkitBoxOrient: 'vertical',
|
|
||||||
lineHeight: '1.2',
|
|
||||||
wordBreak: 'break-word',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{props.author}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<Box>
|
<Box>
|
||||||
<Divider sx={{ my: 1.5 }} />
|
<Divider sx={{ my: 1.5 }} />
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||||
|
<Skeleton
|
||||||
|
variant="circular"
|
||||||
|
width={28}
|
||||||
|
height={28}
|
||||||
|
sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
opacity: userLoading ? 1 : 0,
|
||||||
|
transition: 'opacity 0.3s ease-in-out',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<Avatar
|
<Avatar
|
||||||
src={`/thumbnails/user/${props.authorId}`}
|
src={userThumbnail || undefined}
|
||||||
alt={props.author}
|
alt={props.author}
|
||||||
sx={{
|
sx={{
|
||||||
width: 24,
|
width: 28,
|
||||||
height: 24,
|
height: 28,
|
||||||
border: '1px solid rgba(255, 255, 255, 0.1)',
|
opacity: userLoading ? 0 : 1,
|
||||||
|
transition: 'opacity 0.3s ease-in-out',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Typography
|
<Typography
|
||||||
variant="caption"
|
variant="caption"
|
||||||
|
color="text.secondary"
|
||||||
sx={{
|
sx={{
|
||||||
ml: 1,
|
|
||||||
color: 'text.secondary',
|
|
||||||
fontWeight: 500,
|
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
textOverflow: 'ellipsis',
|
textOverflow: 'ellipsis',
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/*In the future author should be the username of the submitter not the info from the map*/}
|
{new Date(props.created * 1000).toLocaleDateString('en-US', {
|
||||||
{props.author} - {new Date(props.created * 1000).toLocaleDateString('en-US', {
|
month: 'short',
|
||||||
year: 'numeric',
|
day: 'numeric',
|
||||||
month: 'long',
|
year: 'numeric'
|
||||||
day: 'numeric'
|
|
||||||
})}
|
})}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</CardActionArea>
|
</CardActionArea>
|
||||||
</Card>
|
</Card>
|
||||||
</Box>
|
|
||||||
</Grid>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ interface ReviewButtonsProps {
|
|||||||
|
|
||||||
const ReviewActions = {
|
const ReviewActions = {
|
||||||
Submit: {name:"Submit",action:"trigger-submit"} as ReviewAction,
|
Submit: {name:"Submit",action:"trigger-submit"} as ReviewAction,
|
||||||
|
AdminSubmit: {name:"Admin Submit",action:"trigger-submit"} as ReviewAction,
|
||||||
SubmitUnchecked: {name:"Submit Unchecked", action:"trigger-submit-unchecked"} as ReviewAction,
|
SubmitUnchecked: {name:"Submit Unchecked", action:"trigger-submit-unchecked"} as ReviewAction,
|
||||||
ResetSubmitting: {name:"Reset Submitting",action:"reset-submitting"} as ReviewAction,
|
ResetSubmitting: {name:"Reset Submitting",action:"reset-submitting"} as ReviewAction,
|
||||||
Revoke: {name:"Revoke",action:"revoke"} as ReviewAction,
|
Revoke: {name:"Revoke",action:"revoke"} as ReviewAction,
|
||||||
@@ -30,6 +31,8 @@ const ReviewActions = {
|
|||||||
RequestChanges: {name:"Request Changes",action:"request-changes"} as ReviewAction,
|
RequestChanges: {name:"Request Changes",action:"request-changes"} as ReviewAction,
|
||||||
Upload: {name:"Upload",action:"trigger-upload"} as ReviewAction,
|
Upload: {name:"Upload",action:"trigger-upload"} as ReviewAction,
|
||||||
ResetUploading: {name:"Reset Uploading",action:"reset-uploading"} as ReviewAction,
|
ResetUploading: {name:"Reset Uploading",action:"reset-uploading"} as ReviewAction,
|
||||||
|
Release: {name:"Release",action:"trigger-release"} as ReviewAction,
|
||||||
|
ResetReleasing: {name:"Reset Releasing",action:"reset-releasing"} as ReviewAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
const ReviewButtons: React.FC<ReviewButtonsProps> = ({
|
const ReviewButtons: React.FC<ReviewButtonsProps> = ({
|
||||||
@@ -54,6 +57,7 @@ const ReviewButtons: React.FC<ReviewButtonsProps> = ({
|
|||||||
|
|
||||||
const reviewRole = type === "submission" ? RolesConstants.SubmissionReview : RolesConstants.MapfixReview;
|
const reviewRole = type === "submission" ? RolesConstants.SubmissionReview : RolesConstants.MapfixReview;
|
||||||
const uploadRole = type === "submission" ? RolesConstants.SubmissionUpload : RolesConstants.MapfixUpload;
|
const uploadRole = type === "submission" ? RolesConstants.SubmissionUpload : RolesConstants.MapfixUpload;
|
||||||
|
const releaseRole = type === "submission" ? RolesConstants.SubmissionRelease : RolesConstants.MapfixRelease;
|
||||||
|
|
||||||
if (is_submitter) {
|
if (is_submitter) {
|
||||||
if (StatusMatches(status, [Status.UnderConstruction, Status.ChangesRequested])) {
|
if (StatusMatches(status, [Status.UnderConstruction, Status.ChangesRequested])) {
|
||||||
@@ -119,6 +123,14 @@ const ReviewButtons: React.FC<ReviewButtonsProps> = ({
|
|||||||
action: ReviewActions.SubmitUnchecked,
|
action: ReviewActions.SubmitUnchecked,
|
||||||
color: "warning"
|
color: "warning"
|
||||||
});
|
});
|
||||||
|
// button only exists for submissions
|
||||||
|
// submitter has normal submit button
|
||||||
|
if (type === "submission" && !is_submitter) {
|
||||||
|
buttons.push({
|
||||||
|
action: ReviewActions.AdminSubmit,
|
||||||
|
color: "primary"
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,6 +151,24 @@ const ReviewButtons: React.FC<ReviewButtonsProps> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Buttons for release role
|
||||||
|
if (hasRole(roles, releaseRole)) {
|
||||||
|
// submissions do not have a release button
|
||||||
|
if (type === "mapfix" && status === Status.Uploaded) {
|
||||||
|
buttons.push({
|
||||||
|
action: ReviewActions.Release,
|
||||||
|
color: "success"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status === Status.Releasing) {
|
||||||
|
buttons.push({
|
||||||
|
action: ReviewActions.ResetReleasing,
|
||||||
|
color: "warning"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return buttons;
|
return buttons;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user