Compare commits
30 Commits
Author | SHA1 | Date | |
---|---|---|---|
00067dd390 | |||
b54c86ea6c | |||
73995ba91e | |||
bbd839da44 | |||
8577dcea56 | |||
f472f363b6 | |||
6613cfe23e | |||
ac872c1681 | |||
e31652d481 | |||
42a82d3e97 | |||
f345fe3b2c | |||
8b8b818651 | |||
06740b6b86 | |||
6d5c00653b | |||
ead6298a55 | |||
454419abec | |||
b53357aad7 | |||
fee92259b1 | |||
c964c73824 | |||
c2882857a4 | |||
f207f57536 | |||
30fbf1b611 | |||
70900ea2c7 | |||
322e908147 | |||
308f853b81 | |||
d5de8568dd | |||
8b80a73452 | |||
20366ed3e4 | |||
1c52aae429 | |||
c0bd927903 |
60
.drone.yml
60
.drone.yml
@ -3,48 +3,56 @@ name: default
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: build
|
- name: build
|
||||||
image: golang:latest
|
image: tystuyfzand/goc
|
||||||
group: build
|
group: build
|
||||||
volumes:
|
volumes:
|
||||||
- name: build
|
- name: build
|
||||||
path: /build
|
path: /build
|
||||||
commands:
|
commands:
|
||||||
- mkdir -p /build/i386 /build/amd64 /build/armv7 /build/arm64
|
- GOOS=linux,windows GOARCH=386,arm,arm64,amd64 goc -o /build/owapi
|
||||||
- GOOS=linux GOARCH=386 go build -o /build/i386/owapi_i386
|
|
||||||
- go build -o /build/amd64/owapi_amd64
|
|
||||||
- GOOS=linux GOARCH=arm GOARM=7 go build -o /build/armv7/owapi_armv7
|
|
||||||
- GOOS=linux GOARCH=arm64 go build -o /build/arm64/owapi_arm64
|
|
||||||
- name: package
|
- name: package
|
||||||
image: tystuyfzand/fpm
|
image: tystuyfzand/fpm
|
||||||
commands:
|
commands:
|
||||||
- export VERSION=`grep "Version" main.go | head -n 1 | awk '{print $3}' | sed -e 's/^"//' -e 's/"$//' | tr -d '\n'`
|
- export VERSION=`grep "Version" main.go | head -n 1 | awk '{print $3}' | sed -e 's/^"//' -e 's/"$//' | tr -d '\n'`
|
||||||
- echo "v$VERSION" > /build/version.txt
|
- echo "v$VERSION" > /build/version.txt
|
||||||
- chmod +x packaging/build-package.sh packaging/package-upload.sh
|
- chmod +x packaging/build-package.sh
|
||||||
- ARCH=i386 packaging/build-package.sh
|
- ARCH=386,amd64,arm,arm64 packaging/build-package.sh
|
||||||
- ARCH=amd64 packaging/build-package.sh
|
|
||||||
- ARCH=armv7 packaging/build-package.sh
|
|
||||||
- ARCH=arm64 packaging/build-package.sh
|
|
||||||
- packaging/package-upload.sh
|
|
||||||
volumes:
|
volumes:
|
||||||
- name: build
|
- name: build
|
||||||
path: /build
|
path: /build
|
||||||
environment:
|
environment:
|
||||||
UPLOAD_URL:
|
UPLOAD_URL:
|
||||||
from_secret: upload_url
|
from_secret: upload_url
|
||||||
- name: release
|
# - name: release
|
||||||
image: tystuyfzand/drone-gitea-release
|
# image: tystuyfzand/drone-gitea-release
|
||||||
volumes:
|
# volumes:
|
||||||
- name: build
|
# - name: build
|
||||||
path: /build
|
# path: /build
|
||||||
|
# settings:
|
||||||
|
# gitea_server: https://git.meow.tf
|
||||||
|
# tag_file: /build/version.txt
|
||||||
|
# title_file: /build/version.txt
|
||||||
|
# files: [ '/build/owapi_*' ]
|
||||||
|
# environment:
|
||||||
|
# PLUGIN_API_KEY:
|
||||||
|
# from_secret: gitea_token
|
||||||
|
- name: docker
|
||||||
|
image: plugins/docker
|
||||||
settings:
|
settings:
|
||||||
gitea_server: https://git.meow.tf
|
username:
|
||||||
tag_file: /build/version.txt
|
from_secret: docker_username
|
||||||
title_file: /build/version.txt
|
password:
|
||||||
files: [ '/build/*/owapi_*' ]
|
from_secret: docker_password
|
||||||
environment:
|
repo: registry.meow.tf/ow-api/ow-api
|
||||||
PLUGIN_API_KEY:
|
registry: registry.meow.tf
|
||||||
from_secret: gitea_token
|
tags:
|
||||||
|
- latest
|
||||||
volumes:
|
volumes:
|
||||||
- name: build
|
- name: build
|
||||||
temp: {}
|
temp: {}
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
branch:
|
||||||
|
- master
|
||||||
|
event:
|
||||||
|
- push
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
vendor/
|
*.iml
|
||||||
|
.idea/
|
11
Dockerfile
Normal file
11
Dockerfile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
ADD . /build
|
||||||
|
|
||||||
|
RUN cd /build && go build -o ow-api
|
||||||
|
|
||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
COPY --from=builder /build/ow-api /usr/bin/ow-api
|
||||||
|
|
||||||
|
CMD [ "/usr/bin/ow-api" ]
|
5
LICENSE
Normal file
5
LICENSE
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Copyright 2020 Tyler Stuyfzand <admin@meow.tf>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
10
endpoints.go
10
endpoints.go
@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func stats(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
func stats(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
data, err := statsResponse(w, ps, nil)
|
data, err := statsResponse(w, r, ps, nil)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeError(w, err)
|
writeError(w, err)
|
||||||
@ -25,7 +25,7 @@ func stats(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func profile(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
func profile(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
cacheKey := generateCacheKey(ps) + "-profile"
|
cacheKey := generateCacheKey(r, ps) + "-profile"
|
||||||
|
|
||||||
res, err := cacheProvider.Get(cacheKey)
|
res, err := cacheProvider.Get(cacheKey)
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ func profile(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cache result for profile specifically
|
// Cache result for profile specifically
|
||||||
data, err := statsResponse(w, ps, profilePatch)
|
data, err := statsResponse(w, r, ps, profilePatch)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeError(w, err)
|
writeError(w, err)
|
||||||
@ -63,7 +63,7 @@ func heroes(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|||||||
|
|
||||||
sort.Strings(names)
|
sort.Strings(names)
|
||||||
|
|
||||||
cacheKey := generateCacheKey(ps) + "-heroes-" + hex.EncodeToString(md5.New().Sum([]byte(strings.Join(names, ","))))
|
cacheKey := generateCacheKey(r, ps) + "-heroes-" + hex.EncodeToString(md5.New().Sum([]byte(strings.Join(names, ","))))
|
||||||
|
|
||||||
res, err := cacheProvider.Get(cacheKey)
|
res, err := cacheProvider.Get(cacheKey)
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ func heroes(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a patch to remove all but specified heroes
|
// Create a patch to remove all but specified heroes
|
||||||
data, err := statsResponse(w, ps, patch)
|
data, err := statsResponse(w, r, ps, patch)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeError(w, err)
|
writeError(w, err)
|
||||||
|
38
go.mod
38
go.mod
@ -1,22 +1,28 @@
|
|||||||
module git.meow.tf/ow-api/ow-api
|
module git.meow.tf/ow-api/ow-api
|
||||||
|
|
||||||
go 1.12
|
go 1.21
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/PuerkitoBio/goquery v1.5.1-0.20190109230704-3dcf72e6c17f
|
github.com/PuerkitoBio/goquery v1.8.1
|
||||||
github.com/andybalholm/cascadia v1.1.0 // indirect
|
github.com/bluele/gcache v0.0.2
|
||||||
github.com/bluele/gcache v0.0.0-20190518031135-bc40bd653833
|
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b
|
github.com/go-redis/redis v6.15.9+incompatible
|
||||||
github.com/go-redis/redis v6.15.6+incompatible
|
|
||||||
github.com/julienschmidt/httprouter v1.3.0
|
github.com/julienschmidt/httprouter v1.3.0
|
||||||
github.com/kr/pretty v0.1.0 // indirect
|
github.com/miekg/dns v1.1.57
|
||||||
github.com/miekg/dns v1.1.26
|
github.com/ow-api/ovrstat v0.0.0-20240114101623-f548f90469ce
|
||||||
github.com/onsi/ginkgo v1.8.0 // indirect
|
github.com/rs/cors v1.10.1
|
||||||
github.com/onsi/gomega v1.5.0 // indirect
|
github.com/stoewer/go-strcase v1.3.0
|
||||||
github.com/rs/cors v1.7.0
|
golang.org/x/net v0.20.0
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 // indirect
|
)
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
|
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
require (
|
||||||
gopkg.in/yaml.v2 v2.2.2 // indirect
|
github.com/andybalholm/cascadia v1.3.2 // indirect
|
||||||
s32x.com/ovrstat v0.0.0-20191125185405-f48c0d280dc1
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
|
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||||
|
github.com/onsi/gomega v1.20.0 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/stretchr/testify v1.8.4 // indirect
|
||||||
|
golang.org/x/mod v0.14.0 // indirect
|
||||||
|
golang.org/x/sys v0.16.0 // indirect
|
||||||
|
golang.org/x/tools v0.17.0 // indirect
|
||||||
)
|
)
|
||||||
|
205
go.sum
205
go.sum
@ -1,108 +1,155 @@
|
|||||||
github.com/PuerkitoBio/goquery v1.5.1-0.20190109230704-3dcf72e6c17f h1:cWOyRTtBcTBjB0c+GyaQaXgP3g1HVM1KbvZL/Q5QNAM=
|
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
|
||||||
github.com/PuerkitoBio/goquery v1.5.1-0.20190109230704-3dcf72e6c17f/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
|
github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
|
||||||
github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o=
|
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
|
||||||
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
|
||||||
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
|
||||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
||||||
github.com/bluele/gcache v0.0.0-20190518031135-bc40bd653833 h1:yCfXxYaelOyqnia8F/Yng47qhmfC9nKTRIbYRrRueq4=
|
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
|
||||||
github.com/bluele/gcache v0.0.0-20190518031135-bc40bd653833/go.mod h1:8c4/i2VlovMO2gBnHGQPN5EJw+H0lx1u/5p+cgsXtCk=
|
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0=
|
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
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/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/go-redis/redis v6.15.6+incompatible h1:H9evprGPLI8+ci7fxQx6WNZHJSb7be8FqJQRhdQZ5Sg=
|
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
github.com/go-redis/redis v6.15.6+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
|
||||||
|
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||||
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||||
|
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
|
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
|
||||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||||
github.com/labstack/echo/v4 v4.1.7-0.20190725203903-8cabd1e123d6/go.mod h1:kU/7PwzgNxZH4das4XNsSpBSOD09XIF5YEPzjpkGnGE=
|
|
||||||
github.com/labstack/gommon v0.2.9/go.mod h1:E8ZTmW9vw5az5/ZyHWCp0Lw4OH2ecsaBP1C/NKavGG4=
|
|
||||||
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
|
||||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
|
||||||
github.com/miekg/dns v1.1.26 h1:gPxPSwALAeHJSjarOs00QjVdV9QoBvc1D2ujQUr5BzU=
|
|
||||||
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
|
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q=
|
||||||
|
github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
|
||||||
|
github.com/ow-api/ovrstat v0.0.0-20240114101623-f548f90469ce h1:lsCA1fRmpwUXB3C57oGT/EBXuoKL0cQ7fpQzxCq/Zwg=
|
||||||
|
github.com/ow-api/ovrstat v0.0.0-20240114101623-f548f90469ce/go.mod h1:3LSzrUHphNkAVC65H14Nrpsk6mw6KTxTggfD4MtrSQA=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
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/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo=
|
||||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||||
|
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
|
||||||
|
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||||
|
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a h1:gOpx8G595UYyvj8UK4+OFyY4rx037g3fmfhe5SasG3U=
|
|
||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190607181551-461777fb6f67/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.6.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.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||||
|
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||||
|
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||||
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=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||||
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20190222072716-a9d3bda3a223/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=
|
||||||
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190609082536-301114b31cce/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||||
|
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
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.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
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-20190608022120-eacb66d2a7c3/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
|
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||||
|
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||||
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=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
s32x.com/ovrstat v0.0.0-20191125185405-f48c0d280dc1 h1:q5zjrLdxx3oo3i49aBKMMdppFoLCEEq6cSD8lWNCoAY=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
s32x.com/ovrstat v0.0.0-20191125185405-f48c0d280dc1/go.mod h1:UzsLSEoY8B4FByz4e+5GGKebJio+H+axo3RxLr7d7Mw=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
203
main.go
203
main.go
@ -2,27 +2,38 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"git.meow.tf/ow-api/ow-api/cache"
|
"git.meow.tf/ow-api/ow-api/cache"
|
||||||
"git.meow.tf/ow-api/ow-api/json-patch"
|
"git.meow.tf/ow-api/ow-api/json-patch"
|
||||||
|
"github.com/PuerkitoBio/goquery"
|
||||||
"github.com/julienschmidt/httprouter"
|
"github.com/julienschmidt/httprouter"
|
||||||
|
"github.com/ow-api/ovrstat/ovrstat"
|
||||||
"github.com/rs/cors"
|
"github.com/rs/cors"
|
||||||
|
"github.com/stoewer/go-strcase"
|
||||||
|
"golang.org/x/net/context"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"s32x.com/ovrstat/ovrstat"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version = "2.3.1"
|
Version = "2.4.7"
|
||||||
|
|
||||||
OpAdd = "add"
|
OpAdd = "add"
|
||||||
OpRemove = "remove"
|
OpRemove = "remove"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ApiVersion int
|
||||||
|
|
||||||
|
const (
|
||||||
|
VersionOne ApiVersion = iota
|
||||||
|
VersionTwo
|
||||||
|
VersionThree
|
||||||
|
)
|
||||||
|
|
||||||
type gamesStats struct {
|
type gamesStats struct {
|
||||||
Played int64 `json:"played"`
|
Played int64 `json:"played"`
|
||||||
Won int64 `json:"won"`
|
Won int64 `json:"won"`
|
||||||
@ -49,7 +60,7 @@ var (
|
|||||||
|
|
||||||
heroNames []string
|
heroNames []string
|
||||||
|
|
||||||
platforms = []string{ovrstat.PlatformPC, ovrstat.PlatformXBL, ovrstat.PlatformPSN, ovrstat.PlatformNS}
|
platforms = []string{ovrstat.PlatformPC, ovrstat.PlatformConsole}
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -115,72 +126,100 @@ func registerVersionTwo(router *httprouter.Router) {
|
|||||||
router.GET("/v2/stats/"+platform+"/:tag/heroes/:heroes", injectPlatform(platform, heroes))
|
router.GET("/v2/stats/"+platform+"/:tag/heroes/:heroes", injectPlatform(platform, heroes))
|
||||||
router.GET("/v2/stats/"+platform+"/:tag/profile", injectPlatform(platform, profile))
|
router.GET("/v2/stats/"+platform+"/:tag/profile", injectPlatform(platform, profile))
|
||||||
router.GET("/v2/stats/"+platform+"/:tag/complete", injectPlatform(platform, stats))
|
router.GET("/v2/stats/"+platform+"/:tag/complete", injectPlatform(platform, stats))
|
||||||
|
router.GET("/v3/stats/"+platform+"/:tag/heroes/:heroes", injectPlatform(platform, heroes))
|
||||||
|
router.GET("/v3/stats/"+platform+"/:tag/profile", injectPlatform(platform, profile))
|
||||||
|
router.GET("/v3/stats/"+platform+"/:tag/complete", injectPlatform(platform, stats))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version
|
// Version
|
||||||
router.GET("/v2/version", versionHandler)
|
router.GET("/v2/version", versionHandler)
|
||||||
|
router.GET("/v3/version", versionHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadHeroNames() {
|
func loadHeroNames() {
|
||||||
stats, err := ovrstat.PCStats("cats-11481")
|
res, err := http.Get("https://overwatch.blizzard.com/en-us/heroes/")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
m := make(map[string]bool)
|
defer res.Body.Close()
|
||||||
|
|
||||||
for k := range stats.QuickPlayStats.TopHeroes {
|
doc, err := goquery.NewDocumentFromReader(res.Body)
|
||||||
m[k] = true
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range stats.QuickPlayStats.CareerStats {
|
links := doc.Find(".heroCard")
|
||||||
m[k] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
heroNames = make([]string, 0)
|
heroNames = make([]string, 0)
|
||||||
|
|
||||||
for k := range m {
|
links.Each(func(_ int, s *goquery.Selection) {
|
||||||
heroNames = append(heroNames, k)
|
val, exists := s.Attr("data-hero-id")
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func injectPlatform(platform string, handler httprouter.Handle) httprouter.Handle {
|
if !exists {
|
||||||
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
return
|
||||||
ps = append(ps, httprouter.Param{Key: "platform", Value: platform})
|
}
|
||||||
|
|
||||||
handler(w, r, ps)
|
heroNames = append(heroNames, strcase.LowerCamelCase(val))
|
||||||
}
|
})
|
||||||
|
|
||||||
|
log.Println("Loaded heroes", heroNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
tagRegexp = regexp.MustCompile("-(\\d+)$")
|
versionRegexp = regexp.MustCompile("^/(v\\d+)/")
|
||||||
)
|
)
|
||||||
|
|
||||||
func statsResponse(w http.ResponseWriter, ps httprouter.Params, patch *jsonpatch.Patch) ([]byte, error) {
|
func injectPlatform(platform string, handler httprouter.Handle) httprouter.Handle {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
|
if platform == "psn" || platform == "xbl" || platform == "nintendo-switch" {
|
||||||
|
platform = ovrstat.PlatformConsole
|
||||||
|
}
|
||||||
|
|
||||||
|
ps = append(ps, httprouter.Param{Key: "platform", Value: platform})
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
m := versionRegexp.FindStringSubmatch(r.RequestURI)
|
||||||
|
|
||||||
|
if m != nil {
|
||||||
|
version := VersionOne
|
||||||
|
|
||||||
|
switch m[1] {
|
||||||
|
case "v2":
|
||||||
|
version = VersionTwo
|
||||||
|
case "v3":
|
||||||
|
version = VersionThree
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = context.WithValue(ctx, "version", version)
|
||||||
|
}
|
||||||
|
|
||||||
|
handler(w, r.WithContext(ctx), ps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func statsResponse(w http.ResponseWriter, r *http.Request, ps httprouter.Params, patch *jsonpatch.Patch) ([]byte, error) {
|
||||||
var stats *ovrstat.PlayerStats
|
var stats *ovrstat.PlayerStats
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
version := VersionOne
|
||||||
|
|
||||||
|
if v := r.Context().Value("version"); v != nil {
|
||||||
|
version = v.(ApiVersion)
|
||||||
|
}
|
||||||
|
|
||||||
tag := ps.ByName("tag")
|
tag := ps.ByName("tag")
|
||||||
|
|
||||||
tag = strings.Replace(tag, "#", "-", -1)
|
tag = strings.Replace(tag, "#", "-", -1)
|
||||||
|
|
||||||
cacheKey := generateCacheKey(ps)
|
cacheKey := generateCacheKey(r, ps)
|
||||||
|
|
||||||
platform := ps.ByName("platform")
|
platform := ps.ByName("platform")
|
||||||
|
|
||||||
switch platform {
|
stats, err = ovrstat.Stats(platform, strings.Replace(tag, "-", "#", -1))
|
||||||
case ovrstat.PlatformPC:
|
|
||||||
if !tagRegexp.MatchString(tag) {
|
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
|
||||||
return nil, errors.New("bad tag")
|
|
||||||
}
|
|
||||||
stats, err = ovrstat.PCStats(tag)
|
|
||||||
case ovrstat.PlatformPSN, ovrstat.PlatformXBL, ovrstat.PlatformNS:
|
|
||||||
stats, err = ovrstat.ConsoleStats(platform, tag)
|
|
||||||
default:
|
|
||||||
return nil, errors.New("unknown platform")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -206,22 +245,10 @@ func statsResponse(w http.ResponseWriter, ps httprouter.Params, patch *jsonpatch
|
|||||||
games.Played = valueOrDefault(hs.Game, "gamesPlayed", 0)
|
games.Played = valueOrDefault(hs.Game, "gamesPlayed", 0)
|
||||||
games.Won = valueOrDefault(hs.Game, "gamesWon", 0)
|
games.Won = valueOrDefault(hs.Game, "gamesWon", 0)
|
||||||
|
|
||||||
awards := &awardsStats{}
|
|
||||||
|
|
||||||
awards.Cards = valueOrDefault(hs.MatchAwards, "cards", 0)
|
|
||||||
awards.Medals = valueOrDefault(hs.MatchAwards, "medals", 0)
|
|
||||||
awards.Bronze = valueOrDefault(hs.MatchAwards, "medalsBronze", 0)
|
|
||||||
awards.Silver = valueOrDefault(hs.MatchAwards, "medalsSilver", 0)
|
|
||||||
awards.Gold = valueOrDefault(hs.MatchAwards, "medalsGold", 0)
|
|
||||||
|
|
||||||
extra = append(extra, patchOperation{
|
extra = append(extra, patchOperation{
|
||||||
Op: OpAdd,
|
Op: OpAdd,
|
||||||
Path: "/quickPlayStats/games",
|
Path: "/quickPlayStats/games",
|
||||||
Value: games,
|
Value: games,
|
||||||
}, patchOperation{
|
|
||||||
Op: OpAdd,
|
|
||||||
Path: "/quickPlayStats/awards",
|
|
||||||
Value: awards,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,54 +258,40 @@ func statsResponse(w http.ResponseWriter, ps httprouter.Params, patch *jsonpatch
|
|||||||
games.Played = valueOrDefault(hs.Game, "gamesPlayed", 0)
|
games.Played = valueOrDefault(hs.Game, "gamesPlayed", 0)
|
||||||
games.Won = valueOrDefault(hs.Game, "gamesWon", 0)
|
games.Won = valueOrDefault(hs.Game, "gamesWon", 0)
|
||||||
|
|
||||||
awards := &awardsStats{}
|
|
||||||
|
|
||||||
awards.Cards = valueOrDefault(hs.MatchAwards, "cards", 0)
|
|
||||||
awards.Medals = valueOrDefault(hs.MatchAwards, "medals", 0)
|
|
||||||
awards.Bronze = valueOrDefault(hs.MatchAwards, "medalsBronze", 0)
|
|
||||||
awards.Silver = valueOrDefault(hs.MatchAwards, "medalsSilver", 0)
|
|
||||||
awards.Gold = valueOrDefault(hs.MatchAwards, "medalsGold", 0)
|
|
||||||
|
|
||||||
extra = append(extra, patchOperation{
|
extra = append(extra, patchOperation{
|
||||||
Op: OpAdd,
|
Op: OpAdd,
|
||||||
Path: "/competitiveStats/games",
|
Path: "/competitiveStats/games",
|
||||||
Value: games,
|
Value: games,
|
||||||
}, patchOperation{
|
|
||||||
Op: OpAdd,
|
|
||||||
Path: "/competitiveStats/awards",
|
|
||||||
Value: awards,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
rating := 0
|
|
||||||
var ratingIcon string
|
|
||||||
|
|
||||||
if len(stats.Ratings) > 0 {
|
if len(stats.Ratings) > 0 {
|
||||||
totalRating := 0
|
if version == VersionThree {
|
||||||
iconUrl := ""
|
m := make(map[string]ovrstat.Rating)
|
||||||
|
|
||||||
for _, rating := range stats.Ratings {
|
ratingsPatches := make([]patchOperation, len(stats.Ratings))
|
||||||
totalRating += rating.Level
|
|
||||||
iconUrl = rating.RankIcon
|
for i, rating := range stats.Ratings {
|
||||||
|
m[rating.Role] = rating
|
||||||
|
ratingsPatches[i] = patchOperation{
|
||||||
|
Op: OpRemove,
|
||||||
|
Path: "/ratings/" + rating.Role + "/role",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extra = append(extra, patchOperation{
|
||||||
|
Op: OpRemove,
|
||||||
|
Path: "/ratings",
|
||||||
|
}, patchOperation{
|
||||||
|
Op: OpAdd,
|
||||||
|
Path: "/ratings",
|
||||||
|
Value: m,
|
||||||
|
})
|
||||||
|
|
||||||
|
extra = append(extra, ratingsPatches...)
|
||||||
}
|
}
|
||||||
|
|
||||||
rating = int(totalRating / len(stats.Ratings))
|
|
||||||
|
|
||||||
urlBase := iconUrl[0 : strings.Index(iconUrl, "rank-icons/")+11]
|
|
||||||
|
|
||||||
ratingIcon = urlBase + iconFor(rating)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extra = append(extra, patchOperation{
|
|
||||||
Op: OpAdd,
|
|
||||||
Path: "/rating",
|
|
||||||
Value: rating,
|
|
||||||
}, patchOperation{
|
|
||||||
Op: OpAdd,
|
|
||||||
Path: "/ratingIcon",
|
|
||||||
Value: ratingIcon,
|
|
||||||
})
|
|
||||||
|
|
||||||
b, err := json.Marshal(stats)
|
b, err := json.Marshal(stats)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -312,24 +325,16 @@ func statsResponse(w http.ResponseWriter, ps httprouter.Params, patch *jsonpatch
|
|||||||
return b, err
|
return b, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func iconFor(rating int) string {
|
func generateCacheKey(r *http.Request, ps httprouter.Params) string {
|
||||||
if rating >= 4000 {
|
version := VersionOne
|
||||||
return "rank-GrandmasterTier.png"
|
|
||||||
} else if rating >= 3500 {
|
if v := r.Context().Value("version"); v != nil {
|
||||||
return "rank-MasterTier.png"
|
version = v.(ApiVersion)
|
||||||
} else if rating >= 3000 {
|
|
||||||
return "rank-DiamondTier.png"
|
|
||||||
} else if rating >= 2500 {
|
|
||||||
return "rank-PlatinumTier.png"
|
|
||||||
} else if rating >= 2000 {
|
|
||||||
return "rank-GoldTier.png"
|
|
||||||
} else if rating >= 1500 {
|
|
||||||
return "rank-SilverTier.png"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "rank-BronzeTier.png"
|
return versionToString(version) + "-" + ps.ByName("platform") + "-" + ps.ByName("tag")
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateCacheKey(ps httprouter.Params) string {
|
func versionToString(version ApiVersion) string {
|
||||||
return ps.ByName("platform") + "-" + ps.ByName("tag")
|
return fmt.Sprintf("v%d", version)
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,12 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"s32x.com/ovrstat/ovrstat"
|
"github.com/ow-api/ovrstat/ovrstat"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_Stats(t *testing.T) {
|
func Test_Stats(t *testing.T) {
|
||||||
stats, err := ovrstat.PCStats("cats-11481")
|
stats, err := ovrstat.Stats(ovrstat.PlatformPC, "cats-11481")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
fpm -s dir -t deb -p /build/$ARCH/owapi_${VERSION}_${ARCH}.deb \
|
for arch in $(echo $ARCH | sed "s/,/ /g"); do
|
||||||
-n ow-api -v $VERSION \
|
fpm -s dir -t deb -p /build/owapi_${VERSION}_${arch}.deb \
|
||||||
--deb-priority optional --force \
|
-n ow-api -v $VERSION -a $arch \
|
||||||
--deb-compression bzip2 \
|
--deb-priority optional --force \
|
||||||
--description "Overwatch API Server" \
|
--deb-compression gz \
|
||||||
-m "Tyler Stuyfzand <admin@meow.tf>" --vendor "Meow.tf" \
|
--description "Overwatch API Server" \
|
||||||
--before-install packaging/scripts/preinst.deb \
|
-m "Tyler Stuyfzand <admin@meow.tf>" --vendor "Meow.tf" \
|
||||||
--after-install packaging/scripts/postinst.deb \
|
--before-install packaging/scripts/preinst.deb \
|
||||||
-a $ARCH /build/$ARCH/owapi_${ARCH}=/usr/bin/owapi \
|
--after-install packaging/scripts/postinst.deb \
|
||||||
packaging/owapi.service=/lib/systemd/system/owapi.service
|
/build/owapi_linux_${arch}=/usr/bin/owapi \
|
||||||
|
packaging/owapi.service=/lib/systemd/system/owapi.service
|
||||||
|
done
|
@ -1 +1,3 @@
|
|||||||
curl -X POST "$UPLOAD_URL" -F "file_i386=@/build/i386/owapi_${VERSION}_i386.deb" -F "file_amd64=@/build/amd64/owapi_${VERSION}_amd64.deb" -F "file_armv7=@/build/armv7/owapi_${VERSION}_armv7.deb"
|
curl -X POST "$UPLOAD_URL" -F "file_i386=@/build/i386/owapi_${VERSION}_i386.deb" \
|
||||||
|
-F "file_amd64=@/build/amd64/owapi_${VERSION}_amd64.deb" \
|
||||||
|
-F "file_armv7=@/build/armv7/owapi_${VERSION}_armv7.deb"
|
268
pro/main.go
Normal file
268
pro/main.go
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/PuerkitoBio/goquery"
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
"github.com/ow-api/ovrstat/ovrstat"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cloudfrontUrl, err := lookupCloudfrontURL()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Unable to find url:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("URL:", cloudfrontUrl)
|
||||||
|
|
||||||
|
ips, err := lookupIpv6Dns(cloudfrontUrl)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Unable to find ips:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("IPs:", ips)
|
||||||
|
|
||||||
|
localIps, err := checkIpv6Local()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Unable to get local ips")
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Local IPs:", localIps)
|
||||||
|
|
||||||
|
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
|
||||||
|
localAddr, err := net.ResolveIPAddr("ip", "")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// You also need to do this to make it work and not give you a
|
||||||
|
// "mismatched local address type ip"
|
||||||
|
// This will make the ResolveIPAddr a TCPAddr without needing to
|
||||||
|
// say what SRC port number to use.
|
||||||
|
localTCPAddr := net.TCPAddr{
|
||||||
|
IP: localAddr.IP,
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultDialer := &net.Dialer{
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
KeepAlive: 30 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
dialer := &net.Dialer{
|
||||||
|
LocalAddr: &localTCPAddr,
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
KeepAlive: 30 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
transport := &http.Transport{
|
||||||
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
|
oldNetwork := network
|
||||||
|
oldAddr := addr
|
||||||
|
|
||||||
|
if addr == "playoverwatch.com:443" {
|
||||||
|
network = "tcp6"
|
||||||
|
addr = "[" + ips[r.Intn(len(ips))] + "]:443"
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Dial using", addr)
|
||||||
|
|
||||||
|
c, err := dialer.DialContext(ctx, network, addr)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Fallback")
|
||||||
|
c, err = defaultDialer.DialContext(ctx, oldNetwork, oldAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, err
|
||||||
|
},
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
ServerName: "playoverwatch.com",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
http.DefaultClient = &http.Client{
|
||||||
|
Transport: transport,
|
||||||
|
}
|
||||||
|
|
||||||
|
stats, err := ovrstat.Stats(ovrstat.PlatformPC, "cats-11481")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error retrieving:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println(stats.Name+" is level", stats.Endorsement)
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupCloudfrontURL() (string, error) {
|
||||||
|
res, err := http.Get("https://playoverwatch.com/en-us/")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
doc, err := goquery.NewDocumentFromReader(res.Body)
|
||||||
|
|
||||||
|
links := doc.Find("link").Map(func(i int, s *goquery.Selection) string {
|
||||||
|
v, exists := s.Attr("href")
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, link := range links {
|
||||||
|
u, err := url.Parse(link)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasSuffix(u.Host, "cloudfront.net") {
|
||||||
|
return u.Host, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", errors.New("no cloudfront url")
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupIpv6Dns(host string) ([]string, error) {
|
||||||
|
c := &dns.Client{
|
||||||
|
Net: "udp",
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := new(dns.Msg)
|
||||||
|
msg.Id = dns.Id()
|
||||||
|
msg.RecursionDesired = true
|
||||||
|
msg.Question = make([]dns.Question, 1)
|
||||||
|
msg.Question[0] = dns.Question{Name: dns.Fqdn(host), Qtype: dns.TypeAAAA, Qclass: dns.ClassINET}
|
||||||
|
|
||||||
|
in, _, err := c.Exchange(msg, "8.8.8.8:53")
|
||||||
|
|
||||||
|
result := make([]string, 0)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if in != nil && in.Rcode != dns.RcodeSuccess {
|
||||||
|
return result, errors.New(dns.RcodeToString[in.Rcode])
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, record := range in.Answer {
|
||||||
|
if t, ok := record.(*dns.AAAA); ok {
|
||||||
|
result = append(result, t.AAAA.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkIpv6Local() ([]string, error) {
|
||||||
|
ifaces, err := net.Interfaces()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := make([]string, 0)
|
||||||
|
|
||||||
|
for _, i := range ifaces {
|
||||||
|
addrs, err := i.Addrs()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, addr := range addrs {
|
||||||
|
var ip net.IP
|
||||||
|
|
||||||
|
switch v := addr.(type) {
|
||||||
|
case *net.IPNet:
|
||||||
|
ip = v.IP
|
||||||
|
case *net.IPAddr:
|
||||||
|
ip = v.IP
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Check", ip.String())
|
||||||
|
|
||||||
|
if ip == nil || ip.To4() == nil || isPrivateIP(ip) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Checking", ip.String())
|
||||||
|
|
||||||
|
if ipnet, ok := addr.(*net.IPNet); ok {
|
||||||
|
for ip := ipnet.IP.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
|
||||||
|
ret = append(ret, ip.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, ip.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func inc(ip net.IP) {
|
||||||
|
for j := len(ip) - 1; j >= 0; j-- {
|
||||||
|
ip[j]++
|
||||||
|
if ip[j] > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var privateIPBlocks []*net.IPNet
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
for _, cidr := range []string{
|
||||||
|
"127.0.0.0/8", // IPv4 loopback
|
||||||
|
"10.0.0.0/8", // RFC1918
|
||||||
|
"172.16.0.0/12", // RFC1918
|
||||||
|
"192.168.0.0/16", // RFC1918
|
||||||
|
"169.254.0.0/16", // RFC3927 link-local
|
||||||
|
"::1/128", // IPv6 loopback
|
||||||
|
"fe80::/10", // IPv6 link-local
|
||||||
|
"fc00::/7", // IPv6 unique local addr
|
||||||
|
} {
|
||||||
|
_, block, err := net.ParseCIDR(cidr)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("parse error on %q: %v", cidr, err))
|
||||||
|
}
|
||||||
|
privateIPBlocks = append(privateIPBlocks, block)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isPrivateIP(ip net.IP) bool {
|
||||||
|
if ip.IsLoopback() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, block := range privateIPBlocks {
|
||||||
|
if block.Contains(ip) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
2
util.go
2
util.go
@ -3,8 +3,8 @@ package main
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
jsonpatch "git.meow.tf/ow-api/ow-api/json-patch"
|
jsonpatch "git.meow.tf/ow-api/ow-api/json-patch"
|
||||||
|
"github.com/ow-api/ovrstat/ovrstat"
|
||||||
"net/http"
|
"net/http"
|
||||||
"s32x.com/ovrstat/ovrstat"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func valueOrDefault(m map[string]interface{}, key string, d int64) int64 {
|
func valueOrDefault(m map[string]interface{}, key string, d int64) int64 {
|
||||||
|
@ -7,12 +7,13 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
baseURL = "https://playoverwatch.com/en-us/career"
|
baseURL = "https://playoverwatch.com/en-us/career"
|
||||||
|
|
||||||
apiURL = "https://playoverwatch.com/en-us/career/platforms/"
|
apiURL = "https://playoverwatch.com/en-us/search/account-by-name/"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Platform struct {
|
type Platform struct {
|
||||||
@ -86,20 +87,12 @@ func ValidateEndpoint() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
code, err := pd.Html()
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
split := careerInitRegexp.FindStringSubmatch(code)
|
|
||||||
|
|
||||||
if split == nil || len(split) < 2 {
|
|
||||||
return errNoCareerInit
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate API response
|
// Validate API response
|
||||||
if err := validateApi(split[1]); err != nil {
|
if err := validateApi(strings.Replace(url[strings.LastIndex(url, "/")+1:], "-", "%23", -1)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,13 +147,13 @@ func validateCareerStats(careerStatsSelector *goquery.Selection, parent string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectors := []string{
|
selectors := []string{
|
||||||
"div.row div.js-stats", // Top level
|
"div.row div.js-stats", // Top level
|
||||||
"div.row div.js-stats div.column.xs-12", // stat boxes
|
"div.row div.js-stats div.column", // stat boxes
|
||||||
"div.row div.js-stats div.column.xs-12 .stat-title", // stat boxes
|
"div.row div.js-stats div.column .stat-title", // stat boxes
|
||||||
"div.row div.js-stats div.column.xs-12 table.DataTable", // data table
|
"div.row div.js-stats div.column table.DataTable", // data table
|
||||||
"div.row div.js-stats div.column.xs-12 table.DataTable tbody", // data table tbody
|
"div.row div.js-stats div.column table.DataTable tbody", // data table tbody
|
||||||
"div.row div.js-stats div.column.xs-12 table.DataTable tbody tr", // data table tbody tr
|
"div.row div.js-stats div.column table.DataTable tbody tr", // data table tbody tr
|
||||||
"div.row div.js-stats div.column.xs-12 table.DataTable tbody tr td", // data table tbody tr td
|
"div.row div.js-stats div.column table.DataTable tbody tr td", // data table tbody tr td
|
||||||
}
|
}
|
||||||
|
|
||||||
return validateElementsExist(careerStatsSelector, parent, selectors...)
|
return validateElementsExist(careerStatsSelector, parent, selectors...)
|
||||||
|
Reference in New Issue
Block a user