diff --git a/.gitignore b/.gitignore index 397b4a7..2bdb3cd 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.log +*.release diff --git a/config/config.go b/config/config.go index f7abcc9..4190f8c 100644 --- a/config/config.go +++ b/config/config.go @@ -4,9 +4,11 @@ type ServerConfig struct { Listen string `yaml:"listen"` Port int `yaml:"port"` Name string `yaml:"name"` + Env string `yaml:"env"` UrlPrefix string `yaml:"urlPrefix"` LogPath string `yaml:"logPath"` MySQL MySQLConfig `yaml:"mysql"` + Redis RedisConfig `yaml:"redis"` } type MySQLConfig struct { @@ -16,3 +18,9 @@ type MySQLConfig struct { Password string `yaml:"password"` Database string `yaml:"database"` } + +type RedisConfig struct { + Host string `yaml:"host"` + Port int `yaml:"port"` + Password string `yaml:"password"` +} diff --git a/docs/docs.go b/docs/docs.go new file mode 100644 index 0000000..b0f9468 --- /dev/null +++ b/docs/docs.go @@ -0,0 +1,429 @@ +// Package docs GENERATED BY THE COMMAND ABOVE; DO NOT EDIT +// This file was generated by swaggo/swag +package docs + +import ( + "bytes" + "encoding/json" + "strings" + "text/template" + + "github.com/swaggo/swag" +) + +var doc = `{ + "schemes": {{ marshal .Schemes }}, + "swagger": "2.0", + "info": { + "description": "{{escape .Description}}", + "title": "{{.Title}}", + "contact": {}, + "version": "{{.Version}}" + }, + "host": "{{.Host}}", + "basePath": "{{.BasePath}}", + "paths": { + "/statistics/china": { + "get": { + "tags": [ + "Statistics" + ], + "summary": "china data", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/models.GinResponse" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/models.ChinaData" + } + } + } + ] + } + } + } + } + }, + "/statistics/city/{sort}": { + "get": { + "tags": [ + "Statistics" + ], + "summary": "city statistics", + "parameters": [ + { + "enum": [ + "today", + "total", + "now", + "default" + ], + "type": "string", + "description": "data sorted by", + "name": "sort", + "in": "path" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/models.GinResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/models.AreaInfo" + } + } + } + } + ] + } + } + } + } + }, + "/statistics/country": { + "get": { + "tags": [ + "Statistics" + ], + "summary": "country statistics", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/models.GinResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/models.AreaInfo" + } + } + } + } + ] + } + } + } + } + }, + "/statistics/country/child": { + "get": { + "tags": [ + "Statistics" + ], + "summary": "country statistics", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/models.GinResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/models.AreaInfo" + } + } + } + } + ] + } + } + } + } + }, + "/statistics/provience/{sort}": { + "get": { + "tags": [ + "Statistics" + ], + "summary": "provience statistics", + "parameters": [ + { + "enum": [ + "today", + "total", + "now", + "default" + ], + "type": "string", + "description": "data sorted by", + "name": "sort", + "in": "path" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/models.GinResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/models.AreaInfo" + } + } + } + } + ] + } + } + } + } + } + }, + "definitions": { + "models.AreaInfo": { + "type": "object", + "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/models.AreaInfo" + } + }, + "name": { + "type": "string" + }, + "today": { + "$ref": "#/definitions/models.AreaToday" + }, + "total": { + "$ref": "#/definitions/models.AreaTotal" + } + } + }, + "models.AreaToday": { + "type": "object", + "properties": { + "confirm": { + "type": "integer" + }, + "isUpdate": { + "type": "boolean" + } + } + }, + "models.AreaTotal": { + "type": "object", + "properties": { + "confirm": { + "type": "integer" + }, + "dead": { + "type": "integer" + }, + "heal": { + "type": "integer" + }, + "nowConfirm": { + "type": "integer" + }, + "provinceLocalConfirm": { + "type": "integer" + }, + "showHeal": { + "type": "boolean" + }, + "showRate": { + "type": "boolean" + }, + "wzz": { + "type": "integer" + } + } + }, + "models.ChinaAdd": { + "type": "object", + "properties": { + "confirm": { + "type": "integer" + }, + "dead": { + "type": "integer" + }, + "heal": { + "type": "integer" + }, + "importedCase": { + "type": "integer" + }, + "localConfirm": { + "type": "integer" + }, + "localConfirmH5": { + "type": "integer" + }, + "noInfect": { + "type": "integer" + }, + "noInfectH5": { + "type": "integer" + }, + "nowConfirm": { + "type": "integer" + }, + "nowSevere": { + "type": "integer" + }, + "suspect": { + "type": "integer" + } + } + }, + "models.ChinaData": { + "type": "object", + "properties": { + "chinaAdd": { + "$ref": "#/definitions/models.ChinaAdd" + }, + "chinaTotal": { + "$ref": "#/definitions/models.ChinaTotal" + } + } + }, + "models.ChinaTotal": { + "type": "object", + "properties": { + "confirm": { + "type": "integer" + }, + "dead": { + "type": "integer" + }, + "heal": { + "type": "integer" + }, + "importedCase": { + "type": "integer" + }, + "localConfirm": { + "type": "integer" + }, + "localConfirmH5": { + "type": "integer" + }, + "local_acc_confirm": { + "type": "integer" + }, + "noInfect": { + "type": "integer" + }, + "noInfectH5": { + "type": "integer" + }, + "nowConfirm": { + "type": "integer" + }, + "nowSevere": { + "type": "integer" + }, + "showLocalConfirm": { + "type": "integer" + }, + "showlocalinfeciton": { + "type": "integer" + }, + "suspect": { + "type": "integer" + } + } + }, + "models.GinResponse": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "data": {}, + "msg": {} + } + } + } +}` + +type swaggerInfo struct { + Version string + Host string + BasePath string + Schemes []string + Title string + Description string +} + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = swaggerInfo{ + Version: "1.0", + Host: "", + BasePath: "", + Schemes: []string{}, + Title: "nCov Tracker", + Description: "", +} + +type s struct{} + +func (s *s) ReadDoc() string { + sInfo := SwaggerInfo + sInfo.Description = strings.Replace(sInfo.Description, "\n", "\\n", -1) + + t, err := template.New("swagger_info").Funcs(template.FuncMap{ + "marshal": func(v interface{}) string { + a, _ := json.Marshal(v) + return string(a) + }, + "escape": func(v interface{}) string { + // escape tabs + str := strings.Replace(v.(string), "\t", "\\t", -1) + // replace " with \", and if that results in \\", replace that with \\\" + str = strings.Replace(str, "\"", "\\\"", -1) + return strings.Replace(str, "\\\\\"", "\\\\\\\"", -1) + }, + }).Parse(doc) + if err != nil { + return doc + } + + var tpl bytes.Buffer + if err := t.Execute(&tpl, sInfo); err != nil { + return doc + } + + return tpl.String() +} + +func init() { + swag.Register("swagger", &s{}) +} diff --git a/docs/swagger.json b/docs/swagger.json new file mode 100644 index 0000000..5566e32 --- /dev/null +++ b/docs/swagger.json @@ -0,0 +1,358 @@ +{ + "swagger": "2.0", + "info": { + "title": "nCov Tracker", + "contact": {}, + "version": "1.0" + }, + "paths": { + "/statistics/china": { + "get": { + "tags": [ + "Statistics" + ], + "summary": "china data", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/models.GinResponse" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/models.ChinaData" + } + } + } + ] + } + } + } + } + }, + "/statistics/city/{sort}": { + "get": { + "tags": [ + "Statistics" + ], + "summary": "city statistics", + "parameters": [ + { + "enum": [ + "today", + "total", + "now", + "default" + ], + "type": "string", + "description": "data sorted by", + "name": "sort", + "in": "path" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/models.GinResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/models.AreaInfo" + } + } + } + } + ] + } + } + } + } + }, + "/statistics/country": { + "get": { + "tags": [ + "Statistics" + ], + "summary": "country statistics", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/models.GinResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/models.AreaInfo" + } + } + } + } + ] + } + } + } + } + }, + "/statistics/country/child": { + "get": { + "tags": [ + "Statistics" + ], + "summary": "country statistics", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/models.GinResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/models.AreaInfo" + } + } + } + } + ] + } + } + } + } + }, + "/statistics/provience/{sort}": { + "get": { + "tags": [ + "Statistics" + ], + "summary": "provience statistics", + "parameters": [ + { + "enum": [ + "today", + "total", + "now", + "default" + ], + "type": "string", + "description": "data sorted by", + "name": "sort", + "in": "path" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/models.GinResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/models.AreaInfo" + } + } + } + } + ] + } + } + } + } + } + }, + "definitions": { + "models.AreaInfo": { + "type": "object", + "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/models.AreaInfo" + } + }, + "name": { + "type": "string" + }, + "today": { + "$ref": "#/definitions/models.AreaToday" + }, + "total": { + "$ref": "#/definitions/models.AreaTotal" + } + } + }, + "models.AreaToday": { + "type": "object", + "properties": { + "confirm": { + "type": "integer" + }, + "isUpdate": { + "type": "boolean" + } + } + }, + "models.AreaTotal": { + "type": "object", + "properties": { + "confirm": { + "type": "integer" + }, + "dead": { + "type": "integer" + }, + "heal": { + "type": "integer" + }, + "nowConfirm": { + "type": "integer" + }, + "provinceLocalConfirm": { + "type": "integer" + }, + "showHeal": { + "type": "boolean" + }, + "showRate": { + "type": "boolean" + }, + "wzz": { + "type": "integer" + } + } + }, + "models.ChinaAdd": { + "type": "object", + "properties": { + "confirm": { + "type": "integer" + }, + "dead": { + "type": "integer" + }, + "heal": { + "type": "integer" + }, + "importedCase": { + "type": "integer" + }, + "localConfirm": { + "type": "integer" + }, + "localConfirmH5": { + "type": "integer" + }, + "noInfect": { + "type": "integer" + }, + "noInfectH5": { + "type": "integer" + }, + "nowConfirm": { + "type": "integer" + }, + "nowSevere": { + "type": "integer" + }, + "suspect": { + "type": "integer" + } + } + }, + "models.ChinaData": { + "type": "object", + "properties": { + "chinaAdd": { + "$ref": "#/definitions/models.ChinaAdd" + }, + "chinaTotal": { + "$ref": "#/definitions/models.ChinaTotal" + } + } + }, + "models.ChinaTotal": { + "type": "object", + "properties": { + "confirm": { + "type": "integer" + }, + "dead": { + "type": "integer" + }, + "heal": { + "type": "integer" + }, + "importedCase": { + "type": "integer" + }, + "localConfirm": { + "type": "integer" + }, + "localConfirmH5": { + "type": "integer" + }, + "local_acc_confirm": { + "type": "integer" + }, + "noInfect": { + "type": "integer" + }, + "noInfectH5": { + "type": "integer" + }, + "nowConfirm": { + "type": "integer" + }, + "nowSevere": { + "type": "integer" + }, + "showLocalConfirm": { + "type": "integer" + }, + "showlocalinfeciton": { + "type": "integer" + }, + "suspect": { + "type": "integer" + } + } + }, + "models.GinResponse": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "data": {}, + "msg": {} + } + } + } +} \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml new file mode 100644 index 0000000..7ee4049 --- /dev/null +++ b/docs/swagger.yaml @@ -0,0 +1,219 @@ +definitions: + models.AreaInfo: + properties: + children: + items: + $ref: '#/definitions/models.AreaInfo' + type: array + name: + type: string + today: + $ref: '#/definitions/models.AreaToday' + total: + $ref: '#/definitions/models.AreaTotal' + type: object + models.AreaToday: + properties: + confirm: + type: integer + isUpdate: + type: boolean + type: object + models.AreaTotal: + properties: + confirm: + type: integer + dead: + type: integer + heal: + type: integer + nowConfirm: + type: integer + provinceLocalConfirm: + type: integer + showHeal: + type: boolean + showRate: + type: boolean + wzz: + type: integer + type: object + models.ChinaAdd: + properties: + confirm: + type: integer + dead: + type: integer + heal: + type: integer + importedCase: + type: integer + localConfirm: + type: integer + localConfirmH5: + type: integer + noInfect: + type: integer + noInfectH5: + type: integer + nowConfirm: + type: integer + nowSevere: + type: integer + suspect: + type: integer + type: object + models.ChinaData: + properties: + chinaAdd: + $ref: '#/definitions/models.ChinaAdd' + chinaTotal: + $ref: '#/definitions/models.ChinaTotal' + type: object + models.ChinaTotal: + properties: + confirm: + type: integer + dead: + type: integer + heal: + type: integer + importedCase: + type: integer + local_acc_confirm: + type: integer + localConfirm: + type: integer + localConfirmH5: + type: integer + noInfect: + type: integer + noInfectH5: + type: integer + nowConfirm: + type: integer + nowSevere: + type: integer + showLocalConfirm: + type: integer + showlocalinfeciton: + type: integer + suspect: + type: integer + type: object + models.GinResponse: + properties: + code: + type: integer + data: {} + msg: {} + type: object +info: + contact: {} + title: nCov Tracker + version: "1.0" +paths: + /statistics/china: + get: + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/models.GinResponse' + - properties: + data: + $ref: '#/definitions/models.ChinaData' + type: object + summary: china data + tags: + - Statistics + /statistics/city/{sort}: + get: + parameters: + - description: data sorted by + enum: + - today + - total + - now + - default + in: path + name: sort + type: string + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/models.GinResponse' + - properties: + data: + items: + $ref: '#/definitions/models.AreaInfo' + type: array + type: object + summary: city statistics + tags: + - Statistics + /statistics/country: + get: + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/models.GinResponse' + - properties: + data: + items: + $ref: '#/definitions/models.AreaInfo' + type: array + type: object + summary: country statistics + tags: + - Statistics + /statistics/country/child: + get: + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/models.GinResponse' + - properties: + data: + items: + $ref: '#/definitions/models.AreaInfo' + type: array + type: object + summary: country statistics + tags: + - Statistics + /statistics/provience/{sort}: + get: + parameters: + - description: data sorted by + enum: + - today + - total + - now + - default + in: path + name: sort + type: string + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/models.GinResponse' + - properties: + data: + items: + $ref: '#/definitions/models.AreaInfo' + type: array + type: object + summary: provience statistics + tags: + - Statistics +swagger: "2.0" diff --git a/global/global.go b/global/global.go index 474c617..f57a2b4 100644 --- a/global/global.go +++ b/global/global.go @@ -7,6 +7,7 @@ import ( "net/http" "github.com/gin-gonic/gin" + "github.com/go-redis/redis" "go.uber.org/zap" "gorm.io/gorm" ) @@ -17,6 +18,7 @@ var ( RootRouter *gin.RouterGroup Logger *zap.SugaredLogger HttpClient map[string]*http.Client + Redis *redis.Client ) func GetListenOn() string { @@ -33,4 +35,5 @@ func GetHttpClient(key string) (*http.Client, error) { const ( CHINA_NCOV_STATISTIC_URL = "https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5" + ENV_NOLOG = "nolog" ) diff --git a/go.mod b/go.mod index 35e0652..09a5769 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,27 @@ module nCovTrack-Backend go 1.18 require ( - github.com/fatih/color v1.13.0 // indirect + github.com/fatih/color v1.13.0 + github.com/gin-gonic/gin v1.7.7 + github.com/go-redis/redis v6.15.9+incompatible + github.com/robfig/cron/v3 v3.0.1 + github.com/spf13/viper v1.10.1 + github.com/swaggo/swag v1.7.8 + go.uber.org/zap v1.20.0 + gorm.io/driver/mysql v1.2.3 + gorm.io/gorm v1.22.4 +) + +require ( + github.com/KyleBanks/depth v1.2.1 // indirect + github.com/PuerkitoBio/purell v1.1.1 // indirect + github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/gin-contrib/sse v0.1.0 // indirect - github.com/gin-gonic/gin v1.7.7 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.19.6 // indirect + github.com/go-openapi/spec v0.20.4 // indirect + github.com/go-openapi/swag v0.19.15 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/validator/v10 v10.10.0 // indirect @@ -15,31 +32,35 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.4 // indirect + github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/magiconair/properties v1.8.5 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/onsi/ginkgo v1.16.5 // indirect + github.com/onsi/gomega v1.18.0 // indirect github.com/pelletier/go-toml v1.9.4 // indirect github.com/spf13/afero v1.8.0 // indirect github.com/spf13/cast v1.4.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.10.1 // indirect github.com/subosito/gotenv v1.2.0 // indirect + github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 // indirect + github.com/swaggo/gin-swagger v1.4.0 // indirect github.com/ugorji/go/codec v1.2.6 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.7.0 // indirect - go.uber.org/zap v1.20.0 // indirect - golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect - golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect + golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce // indirect + golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba // indirect + golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect golang.org/x/text v0.3.7 // indirect + golang.org/x/tools v0.1.8 // indirect google.golang.org/protobuf v1.27.1 // indirect gopkg.in/ini.v1 v1.66.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gorm.io/driver/mysql v1.2.3 // indirect - gorm.io/gorm v1.22.4 // indirect ) diff --git a/go.sum b/go.sum index 1c888ce..5a129ff 100644 --- a/go.sum +++ b/go.sum @@ -38,6 +38,15 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= +github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +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/agiledragon/gomonkey/v2 v2.3.1 h1:k+UnUY0EMNYUFUAQVETGY9uUTxjMdnUkP0ARyJS1zzs= +github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -47,8 +56,10 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/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= @@ -58,15 +69,31 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/gzip v0.0.3/go.mod h1:YxxswVZIqOvcHEQpsSn+QF5guQtO1dCfy0shBPy4jFc= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= +github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= +github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= +github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -74,11 +101,15 @@ github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0= github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= +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-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -119,6 +150,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/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 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -133,15 +165,18 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= @@ -149,24 +184,35 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +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.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -181,17 +227,47 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.18.0 h1:ngbYoRctxjl8SiF7XgP0NxBFbfHcg3wfHMMaFHWwMTM= +github.com/onsi/gomega v1.18.0/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= +github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE= +github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/afero v1.8.0 h1:5MmtuhAgYeU6qpa7w7bP0dv6MBYuup0vekhSpSkoq60= github.com/spf13/afero v1.8.0/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= @@ -208,20 +284,29 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 h1:+iNTcqQJy0OZ5jk6a5NLib47eqXK8uYcPX+O4+cBpEM= +github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w= +github.com/swaggo/gin-swagger v1.4.0 h1:AV1vlpiYMKUawINGVO5gtmLlGPOOJfxXxAJnxSlAROM= +github.com/swaggo/gin-swagger v1.4.0/go.mod h1:VAoX17txQZ3i/Qsbd4G/k+boFVSfWsOSSA2YTfgtUlA= +github.com/swaggo/swag v1.7.8 h1:w249t0l/kc/DKMGlS0fppNJQxKyJ8heNaUWB6nsH3zc= +github.com/swaggo/swag v1.7.8/go.mod h1:gZ+TJ2w/Ve1RwQsA2IRoSOTidHz6DX+PIG8GWvbnoLU= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E= github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -231,6 +316,7 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= @@ -247,6 +333,8 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce h1:Roh6XWxHFKrPgC/EQhVubSAGQ6Ozk6IdxHSzt1mR0EI= +golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -281,8 +369,10 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= 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-20180906233101-161cd47e91fd/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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -303,6 +393,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -313,6 +404,11 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba h1:6u6sik+bn/y7vILcYkK3iwTBWN7WtBvB0+SZswQnbf8= +golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -334,6 +430,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -342,7 +439,10 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -364,17 +464,23 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -394,6 +500,7 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -432,13 +539,18 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= +golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -534,15 +646,25 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +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/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/mysql v1.2.3 h1:cZqzlOfg5Kf1VIdLC1D9hT6Cy9BgxhExLj/2tIgUe7Y= gorm.io/driver/mysql v1.2.3/go.mod h1:qsiz+XcAyMrS6QY+X3M9R6b/lKM1imKmcuK9kac5LTo= diff --git a/handler/statistics.go b/handler/statistics.go new file mode 100644 index 0000000..f39768f --- /dev/null +++ b/handler/statistics.go @@ -0,0 +1,59 @@ +package handler + +import ( + service "nCovTrack-Backend/service/statistics" + "nCovTrack-Backend/utils" + "strings" + + "github.com/gin-gonic/gin" +) + +// Get provience statistics +// @Tags Statistics +// @Prodeuce json +// @Summary provience statistics +// @Success 200 {object} models.GinResponse{data=[]models.AreaInfo} +// @Router /statistics/provience/{sort} [get] +// @Param sort path string false "data sorted by" Enums(today, total, now, default) +func ProvienceDataHandler(c *gin.Context) { + sort := c.Param("sort") + data := service.GetAllProvienceData(sort) + utils.Succ(c, data) +} + +// Get city statistics +// @Tags Statistics +// @Prodeuce json +// @Summary city statistics +// @Success 200 {object} models.GinResponse{data=[]models.AreaInfo} +// @Router /statistics/city/{sort} [get] +// @Param sort path string false "data sorted by" Enums(today, total, now, default) +func CityDataHandler(c *gin.Context) { + sort := c.Param("sort") + data := service.GetAllCityData(sort) + utils.Succ(c, data) +} + +// Get country statistics(only china currently) +// @Tags Statistics +// @Prodeuce json +// @Summary country statistics +// @Success 200 {object} models.GinResponse{data=[]models.AreaInfo} +// @Router /statistics/country/child [get] +// @Router /statistics/country [get] +func CountryDataHandler(c *gin.Context) { + child := strings.Contains(c.Request.URL.RequestURI(), "child") + data := service.GetCountryData(child) + utils.Succ(c, data) +} + +// Get china data +// @Tags Statistics +// @Prodeuce json +// @Summary china data +// @Success 200 {object} models.GinResponse{data=models.ChinaData} +// @Router /statistics/china [get] +func ChinaDataHandler(c *gin.Context) { + data := service.GetChinaNCovStatistic() + utils.Succ(c, data) +} diff --git a/initialize/config.go b/initialize/config.go index 19920c5..ac58124 100644 --- a/initialize/config.go +++ b/initialize/config.go @@ -22,4 +22,5 @@ func initConfig() { } global.ServerSettings = serverConfig color.Blue("Already read config from %s", v.ConfigFileUsed()) + color.Blue("Env: %s", global.ServerSettings.Env) } diff --git a/initialize/cron.go b/initialize/cron.go new file mode 100644 index 0000000..adff2a0 --- /dev/null +++ b/initialize/cron.go @@ -0,0 +1,14 @@ +package initialize + +import ( + "nCovTrack-Backend/service/statistics" + + "github.com/robfig/cron/v3" +) + +func initCron() { + c := cron.New() + //c.AddFunc("@every 10s", func() { global.Redis.Set("OK", time.Now().String(), time.Duration(10*time.Hour)) }) + c.AddFunc("@every 10m", statistics.CacheNCov) + c.Start() +} diff --git a/initialize/initialize.go b/initialize/initialize.go index 08f8452..05fc1ef 100644 --- a/initialize/initialize.go +++ b/initialize/initialize.go @@ -7,5 +7,9 @@ func Initialize() *gin.Engine { initLogger() initHttpClient() initMySQL() - return initRouter() + initRedis() + initCron() + g := initRouter() + initSwagger() + return g } diff --git a/initialize/redis.go b/initialize/redis.go new file mode 100644 index 0000000..0991267 --- /dev/null +++ b/initialize/redis.go @@ -0,0 +1,21 @@ +package initialize + +import ( + "fmt" + "nCovTrack-Backend/global" + + "github.com/go-redis/redis" +) + +func initRedis() { + rds := redis.NewClient(&redis.Options{ + Addr: fmt.Sprintf("%s:%d", global.ServerSettings.Redis.Host, global.ServerSettings.Redis.Port), + Password: global.ServerSettings.Redis.Password, + DB: 0, + }) + _, err := rds.Ping().Result() + if err != nil { + panic(err) + } + global.Redis = rds +} diff --git a/initialize/router.go b/initialize/router.go index f2a62b7..b103683 100644 --- a/initialize/router.go +++ b/initialize/router.go @@ -12,7 +12,7 @@ func initRouter() *gin.Engine { r := gin.New() r.Use(middleware.Cors(), middleware.RequestLog(), middleware.GinRecovery(true)) //r.Use(middleware.Cors(), middleware.RequestLog(), gin.Recovery()) - global.RootRouter = r.Group(global.ServerSettings.UrlPrefix) + global.RootRouter = r.Group("/api" + global.ServerSettings.UrlPrefix) router.BusiRouter() return r } diff --git a/initialize/swagger.go b/initialize/swagger.go new file mode 100644 index 0000000..37d0e49 --- /dev/null +++ b/initialize/swagger.go @@ -0,0 +1,14 @@ +package initialize + +import ( + "nCovTrack-Backend/docs" + "nCovTrack-Backend/global" + + swaggerFile "github.com/swaggo/files" + swagger "github.com/swaggo/gin-swagger" +) + +func initSwagger() { + docs.SwaggerInfo.BasePath = "/api" + global.ServerSettings.UrlPrefix + global.RootRouter.GET("/swagger/*any", swagger.WrapHandler(swaggerFile.Handler)) +} diff --git a/main.go b/main.go index e3c4d76..0a2b9f9 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,8 @@ import ( "nCovTrack-Backend/initialize" ) +// @title nCov Tracker +// @version 1.0 func main() { gin := initialize.Initialize() gin.Run(global.GetListenOn()) diff --git a/middleware/gin_recovery.go b/middleware/gin_recovery.go index 6c041d9..440b377 100644 --- a/middleware/gin_recovery.go +++ b/middleware/gin_recovery.go @@ -49,6 +49,7 @@ func GinRecovery(stack bool) gin.HandlerFunc { } utils.RequestLogError(logParams...) c.AbortWithStatus(http.StatusInternalServerError) + fmt.Println(err) fmt.Printf("\n%s\n", debug.Stack()) } }() diff --git a/models/statistic.go b/models/statistic.go new file mode 100644 index 0000000..0a58282 --- /dev/null +++ b/models/statistic.go @@ -0,0 +1,60 @@ +package models + +type AreaInfo struct { + Name string `json:"name"` + Today AreaToday `json:"today"` + Total AreaTotal `json:"total"` + Children []AreaInfo `json:"children"` +} + +type AreaToday struct { + Comfirm int `json:"confirm"` + IsUpdated bool `json:"isUpdate"` +} + +type AreaTotal struct { + NowConfirm int `json:"nowConfirm"` + Confirm int `json:"confirm"` + Dead int `json:"dead"` + ShowRate bool `json:"showRate"` + Heal int `json:"heal"` + ShowHeal bool `json:"showHeal"` + Wzz int `json:"wzz"` + ProvinceLocalConfirm int `json:"provinceLocalConfirm"` +} + +type ChinaAdd struct { + Confirm int `json:"confirm"` + Dead int `json:"dead"` + Heal int `json:"heal"` + ImportedCase int `json:"importedCase"` + LocalConfirm int `json:"localConfirm"` + LocalConfirmH5 int `json:"localConfirmH5"` + NoInfect int `json:"noInfect"` + NoInfectH5 int `json:"noInfectH5"` + NowConfirm int `json:"nowConfirm"` + NowSevere int `json:"nowSevere"` + Suspect int `json:"suspect"` +} + +type ChinaTotal struct { + Confirm int `json:"confirm"` + Dead int `json:"dead"` + Heal int `json:"heal"` + ImportedCase int `json:"importedCase"` + LocalConfirm int `json:"localConfirm"` + LocalConfirmH5 int `json:"localConfirmH5"` + LocalAccConfirm int `json:"local_acc_confirm"` + NoInfect int `json:"noInfect"` + NoInfectH5 int `json:"noInfectH5"` + NowConfirm int `json:"nowConfirm"` + NowSevere int `json:"nowSevere"` + ShowLocalConfirm int `json:"showLocalConfirm"` + Showlocalinfeciton int `json:"showlocalinfeciton"` + Suspect int `json:"suspect"` +} + +type ChinaData struct { + ChinaAdd ChinaAdd `json:"chinaAdd"` + ChinaTotal ChinaTotal `json:"chinaTotal"` +} diff --git a/models/utils.go b/models/utils.go index 4dcd7e0..e837bf1 100644 --- a/models/utils.go +++ b/models/utils.go @@ -6,3 +6,9 @@ type UtilRequestInfo struct { Body string Timeout int } + +type GinResponse struct { + Code int `json:"code"` + Msg interface{} `json:"msg"` + Data interface{} `json:"data"` +} diff --git a/router/router.go b/router/router.go index fc5e2b2..f151bdf 100644 --- a/router/router.go +++ b/router/router.go @@ -2,7 +2,6 @@ package router import ( "nCovTrack-Backend/global" - "nCovTrack-Backend/service/statistics" "net/http" "time" @@ -10,14 +9,17 @@ import ( ) func BusiRouter() { - userRouter := global.RootRouter.Group("/user") + testRouter := global.RootRouter.Group("/test") { - userRouter.GET("/count", func(c *gin.Context) { + testRouter.GET("/count", func(c *gin.Context) { time.Sleep(800 * time.Millisecond) c.String(http.StatusOK, "OK") }) - userRouter.GET("/test", func(c *gin.Context) { - c.JSON(http.StatusOK, statistics.GetChinaNCovStatistic()) - }) + //testRouter.GET("/test", statistics.GetChinaNCovStatistic()) + //testRouter.GET("/redis", func(c *gin.Context) { + // data := statistics.GetAllProvienceData(statistics.SORT_NOW_CONFIRM) + // Succ(c, data) + //}) } + statisticRouter() } diff --git a/router/statistics.go b/router/statistics.go new file mode 100644 index 0000000..718309f --- /dev/null +++ b/router/statistics.go @@ -0,0 +1,17 @@ +package router + +import ( + "nCovTrack-Backend/global" + "nCovTrack-Backend/handler" +) + +func statisticRouter() { + statisticsRouter := global.RootRouter.Group("/statistics") + { + statisticsRouter.GET("/provience/:sort", handler.ProvienceDataHandler) + statisticsRouter.GET("/city/:sort", handler.CityDataHandler) + statisticsRouter.GET("/country/child", handler.CountryDataHandler) + statisticsRouter.GET("/country", handler.CountryDataHandler) + statisticsRouter.GET("/china", handler.ChinaDataHandler) + } +} diff --git a/service/statistics/cache.go b/service/statistics/cache.go new file mode 100644 index 0000000..f730665 --- /dev/null +++ b/service/statistics/cache.go @@ -0,0 +1,184 @@ +package statistics + +import ( + "encoding/json" + "fmt" + "nCovTrack-Backend/global" + "nCovTrack-Backend/models" + "nCovTrack-Backend/utils" + "sort" + "strings" + "time" +) + +const ( + rds_NCOV_STATISTIC_KEY = "nCovStatistic" + rds_CHINA_TOTAL_KEY = "chinaTotal" + rds_CHINA_ADD_KEY = "chinaAdd" + rds_COUNTRY_LEVEL_KEY = "countryLevel" + rds_COUNTRY_LEVEL_CHILD_KEY = "countryLevelChild" + rds_PROVIENCE_LEVEL_CHILD_KEY = "provienceLevelChild" + rds_PROVIENCE_LEVEL_NOW_CONFIRM_KEY = "provienceLevelNowConfirm" + rds_PROVIENCE_LEVEL_TODAY_CONFIRM_KEY = "provienceLevelTodayConfirm" + rds_PROVIENCE_LEVEL_TOTAL_CONFIRM_KEY = "provienceLevelTotalConfirm" + rds_CITY_LEVEL_CHILD_KEY = "cityLevelChild" + rds_CITY_LEVEL_NOW_CONFIRM_KEY = "cityLevelNowConfirm" + rds_CITY_LEVEL_TODAY_CONFIRM_KEY = "cityLevelTodayConfirm" + rds_CITY_LEVEL_TOTAL_CONFIRM_KEY = "cityLevelTotalConfirm" + rds_LAST_UPDATE_TIME = "statisticsLastUpdateTime" + rds_LAST_CACHE_TIME = "statisticsLastCacheTime" + + SORT_TODAY_CONFIRM = "today" + SORT_TOTAL_CONFIRM = "total" + SORT_NOW_CONFIRM = "now" + + json_FOREIGN_COUNTRY = "境外" + json_FOREIGN_CITY = "外地" + json_TO_BE_CONFIRM = "待确认" +) + +var ( + sortBy string +) + +type AreaSlice []models.AreaInfo + +func cacheNCovStatistics() { + resp := utils.GetWhioutHeader(global.CHINA_NCOV_STATISTIC_URL) + var nCovRes map[string]string + json.Unmarshal([]byte(resp), &nCovRes) + var nCovResData map[string]interface{} + json.Unmarshal([]byte(nCovRes["data"]), &nCovResData) + if !needToRecache(nCovResData) { + return + } + cacheChinaInfo(nCovResData) + cacheLevelInfo(nCovResData) + cacheLastUpdateTime(nCovResData) +} + +func cacheChinaInfo(data map[string]interface{}) { + chinaTotal, _ := json.Marshal(data["chinaTotal"]) + chinaAdd, _ := json.Marshal(data["chinaAdd"]) + global.Redis.Set(rds_CHINA_TOTAL_KEY, chinaTotal, time.Duration(12*time.Hour)) + global.Redis.Set(rds_CHINA_ADD_KEY, chinaAdd, time.Duration(12*time.Hour)) +} + +func cacheLastUpdateTime(data map[string]interface{}) { + global.Redis.Set(rds_LAST_UPDATE_TIME, data["lastUpdateTime"], time.Duration(12*time.Hour)) + global.Redis.Set(rds_LAST_CACHE_TIME, time.Now().String(), time.Duration(12*time.Hour)) +} + +func needToRecache(data map[string]interface{}) bool { + rdsLastUpdateTime := global.Redis.Get(rds_LAST_UPDATE_TIME).Val() + newestUpdateTime := fmt.Sprintf("%v", data["lastUpdateTime"]) + return rdsLastUpdateTime != newestUpdateTime +} + +func cacheLevelInfo(data map[string]interface{}) { + areaTree, _ := json.Marshal(data["areaTree"]) + + // Get Every Level's Info + var countryLevels []models.AreaInfo + json.Unmarshal(areaTree, &countryLevels) + provienceLevels := children(countryLevels) + cityLevels := children(provienceLevels) + + // Country Level Area Info With Child + cacheList(rds_COUNTRY_LEVEL_CHILD_KEY, areaInfoToJson(countryLevels)...) + // Country Level Area Info + areaInfoChildNil(&countryLevels) + cacheList(rds_COUNTRY_LEVEL_KEY, areaInfoToJson(countryLevels)...) + + // Provience Level Area Info With Child + cacheList(rds_PROVIENCE_LEVEL_CHILD_KEY, areaInfoToJson(provienceLevels)...) + areaInfoChildNil(&provienceLevels) + // City Level Area Info With Child + cacheList(rds_CITY_LEVEL_CHILD_KEY, areaInfoToJson(cityLevels)...) + areaInfoChildNil(&provienceLevels) + + // Provience Level Area Info Sorted by Now Confirm + provienceLevelsSlice := AreaSlice(provienceLevels) + sort.Sort(provienceLevelsSlice) + cacheList(rds_PROVIENCE_LEVEL_NOW_CONFIRM_KEY, areaInfoToJson(provienceLevelsSlice)...) + // City Level Area Info Sorted By Now Confirm + cityLevelsSlice := AreaSlice(cityLevels) + sort.Sort(cityLevelsSlice) + cacheList(rds_CITY_LEVEL_NOW_CONFIRM_KEY, areaInfoToJson(cityLevelsSlice)...) + + sortBy = SORT_TODAY_CONFIRM + // Provience Level Area Info Sorted by Today Confirm + sort.Sort(provienceLevelsSlice) + cacheList(rds_PROVIENCE_LEVEL_TODAY_CONFIRM_KEY, areaInfoToJson(provienceLevelsSlice)...) + // City Level Area Info Sorted by Today Confirm + sort.Sort(cityLevelsSlice) + cacheList(rds_CITY_LEVEL_TODAY_CONFIRM_KEY, areaInfoToJson(cityLevelsSlice)...) + + sortBy = SORT_TOTAL_CONFIRM + // Provience Level Area Info Sorted by Total Confirm + sort.Sort(provienceLevelsSlice) + cacheList(rds_PROVIENCE_LEVEL_TOTAL_CONFIRM_KEY, areaInfoToJson(provienceLevelsSlice)...) + // City Level Area Info Sorted by Total Confirm + sort.Sort(cityLevelsSlice) + cacheList(rds_CITY_LEVEL_TOTAL_CONFIRM_KEY, areaInfoToJson(cityLevelsSlice)...) + +} + +func cacheList(key string, values ...interface{}) { + global.Redis.Del(key) + global.Redis.RPush(key, values...) +} + +func children(parents []models.AreaInfo) []models.AreaInfo { + var areaInfos []models.AreaInfo + for _, parent := range parents { + if parent.Children == nil { + continue + } + for _, item := range parent.Children { + name := item.Name + if !strings.Contains(name, json_FOREIGN_CITY) && !strings.Contains(name, json_FOREIGN_COUNTRY) && !strings.Contains(name, json_TO_BE_CONFIRM) { + areaInfos = append(areaInfos, item) + } + } + } + return areaInfos +} + +func areaInfoToJson(areaInfos []models.AreaInfo) []interface{} { + return utils.Map(areaInfos, func(item models.AreaInfo) interface{} { + jsonByte, _ := json.Marshal(item) + return jsonByte + }) +} + +func areaInfoChildNil(areaInfos *[]models.AreaInfo) { + utils.ForEach(areaInfos, func(item *models.AreaInfo) { + item.Children = nil + }) +} + +func checkCache() { + if global.Redis.Get(rds_LAST_UPDATE_TIME).Val() == "" { + cacheNCovStatistics() + } +} + +func (s AreaSlice) Len() int { return len(s) } + +func (s AreaSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +func (s AreaSlice) Less(i, j int) bool { + if sortBy == SORT_TODAY_CONFIRM { + return s[i].Today.Comfirm > s[j].Today.Comfirm + } + if sortBy == SORT_TOTAL_CONFIRM { + return s[i].Total.Confirm > s[j].Total.Confirm + } + // Default sorted by now confirm + return s[i].Total.NowConfirm > s[j].Total.NowConfirm +} + +func CacheNCov() { + cacheNCovStatistics() +} diff --git a/service/statistics/statistics.go b/service/statistics/statistics.go index 19bed3a..1563d11 100644 --- a/service/statistics/statistics.go +++ b/service/statistics/statistics.go @@ -2,41 +2,57 @@ package statistics import ( "encoding/json" - "fmt" "nCovTrack-Backend/global" - "nCovTrack-Backend/utils" - "net/http" - - "github.com/gin-gonic/gin" + "nCovTrack-Backend/models" + "strings" ) -func GetChinaNCovStatistics() func(c *gin.Context) { - return func(c *gin.Context) { - resp := utils.GetWhioutHeader(global.CHINA_NCOV_STATISTIC_URL) - var nCovRes map[string]string - json.Unmarshal([]byte(resp), &nCovRes) - fmt.Println(nCovRes) - var nCovResData interface{} - json.Unmarshal([]byte(nCovRes["data"]), &nCovResData) - c.JSON(http.StatusOK, nCovResData) +func GetAllProvienceData(sort string) []interface{} { + checkCache() + if sort == SORT_TODAY_CONFIRM { + return getEntireRedisList(rds_PROVIENCE_LEVEL_TODAY_CONFIRM_KEY) } + if sort == SORT_TOTAL_CONFIRM { + return getEntireRedisList(rds_PROVIENCE_LEVEL_TOTAL_CONFIRM_KEY) + } + if sort == SORT_NOW_CONFIRM { + return getEntireRedisList(rds_PROVIENCE_LEVEL_NOW_CONFIRM_KEY) + } + return getEntireRedisList(rds_PROVIENCE_LEVEL_CHILD_KEY) } -func GetChinaNCovStatistic() func(c *gin.Context) { - return func(c *gin.Context) { - //resp := utils.GetWhioutHeader(global.CHINA_NCOV_STATISTIC_URL) - var nCovRes map[string]string - //err := json.Unmarshal([]byte(resp), &nCovRes) - //fmt.Println(nCovRes) - //if err != nil { - // panic(err) - //} - //var nCovResData interface{} - //err := json.Unmarshal([]byte(nCovRes["data"]), &nCovResData) - //if err != nil { - // panic(err) - //} - nCovRes["1"] = "1" - c.JSON(http.StatusOK, nCovRes) +func GetAllCityData(sort string) []interface{} { + checkCache() + if sort == SORT_TODAY_CONFIRM { + return getEntireRedisList(rds_CITY_LEVEL_TODAY_CONFIRM_KEY) } + if sort == SORT_TOTAL_CONFIRM { + return getEntireRedisList(rds_CITY_LEVEL_TOTAL_CONFIRM_KEY) + } + if sort == SORT_NOW_CONFIRM { + return getEntireRedisList(rds_CITY_LEVEL_NOW_CONFIRM_KEY) + } + return getEntireRedisList(rds_CITY_LEVEL_CHILD_KEY) +} + +func GetCountryData(child bool) []interface{} { + if child { + return getEntireRedisList(rds_COUNTRY_LEVEL_CHILD_KEY) + } + return getEntireRedisList(rds_COUNTRY_LEVEL_KEY) +} + +func GetChinaNCovStatistic() models.ChinaData { + data := models.ChinaData{} + json.Unmarshal([]byte(global.Redis.Get(rds_CHINA_ADD_KEY).Val()), &data.ChinaAdd) + json.Unmarshal([]byte(global.Redis.Get(rds_CHINA_TOTAL_KEY).Val()), &data.ChinaTotal) + return data +} + +func getEntireRedisList(key string) []interface{} { + var data []interface{} + dataStrArr := global.Redis.LRange(key, 0, -1).Val() + dataStr := "[" + strings.Join(dataStrArr[:], ",") + "]" + json.Unmarshal([]byte(dataStr), &data) + return data } diff --git a/settings-dev.yml b/settings-dev.yml index 491b56e..1aedb24 100644 --- a/settings-dev.yml +++ b/settings-dev.yml @@ -1,5 +1,6 @@ name: nConvTrack port: 8081 +env: nolog host: 0.0.0.0 urlPrefix: /v1/ logPath: ./logs/ @@ -10,3 +11,8 @@ mysql: username: root password: 13291004986@lm database: nCovTrack + +redis: + host: myhost.fallen-angle.com + port: 6379 + password: wzl20001001 diff --git a/utils/list.go b/utils/list.go new file mode 100644 index 0000000..a4b7009 --- /dev/null +++ b/utils/list.go @@ -0,0 +1,17 @@ +package utils + +type ObjectType []interface{} + +func ForEach[T any](arr *[]T, fun func(item *T)) { + for i := range *arr { + fun(&((*arr)[i])) + } +} + +func Map[T any, V any](arr []T, fun func(item T) V) []V { + res := make([]V, 0, len(arr)) + for _, item := range arr { + res = append(res, fun(item)) + } + return res +} diff --git a/utils/log.go b/utils/log.go index 0ce3164..20a3db4 100644 --- a/utils/log.go +++ b/utils/log.go @@ -40,13 +40,19 @@ func UtilLogWarn(utilName string, args ...interface{}) { } func logInfo(msg string, args ...interface{}) { - global.Logger.Infow(msg, args...) + if global.ServerSettings.Env != global.ENV_NOLOG { + global.Logger.Infow(msg, args...) + } } func logError(msg string, args ...interface{}) { - global.Logger.Errorw(msg, args...) -} + if global.ServerSettings.Env != global.ENV_NOLOG { + global.Logger.Errorw(msg, args...) -func logWarn(msg string, args ...interface{}) { - global.Logger.Warnw(msg, args...) + } +} +func logWarn(msg string, args ...interface{}) { + if global.ServerSettings.Env != global.ENV_NOLOG { + global.Logger.Warnw(msg, args...) + } } diff --git a/utils/response.go b/utils/response.go new file mode 100644 index 0000000..00a00c8 --- /dev/null +++ b/utils/response.go @@ -0,0 +1,20 @@ +package utils + +import ( + "nCovTrack-Backend/models" + "net/http" + + "github.com/gin-gonic/gin" +) + +func Success(c *gin.Context, code int, msg interface{}, data interface{}) { + c.JSON(http.StatusOK, models.GinResponse{Code: code, Msg: msg, Data: data}) +} + +func Error(c *gin.Context, status int, code int, msg interface{}, data interface{}) { + c.JSON(status, models.GinResponse{Code: code, Msg: msg, Data: data}) +} + +func Succ(c *gin.Context, data interface{}) { + Success(c, http.StatusOK, "success", data) +} diff --git a/utils/string.go b/utils/string.go new file mode 100644 index 0000000..d4b585b --- /dev/null +++ b/utils/string.go @@ -0,0 +1 @@ +package utils diff --git a/utils/struct.go b/utils/struct.go new file mode 100644 index 0000000..c8510cd --- /dev/null +++ b/utils/struct.go @@ -0,0 +1,7 @@ +package utils + +func Copy[T any](old *T) T { + T1 := *old + T2 := *&T1 + return T2 +}