From 2dc0db7210fff676d9c84600f60c8f0f2ecfe8c9 Mon Sep 17 00:00:00 2001 From: Niko Storni Date: Tue, 16 Jun 2020 05:37:51 +0200 Subject: [PATCH] add compression for gifs add database backend --- .gitignore | 1 + Makefile | 26 + compression/compression.go | 52 ++ config.json.example | 6 + configs/configs.go | 1 + db/init.go | 83 +++ db/logger.go | 142 +++++ db/tx.go | 46 ++ go.mod | 16 +- go.sum | 319 ++++++++++ main.go | 81 ++- migration/000_init_schema.sql | 23 + migration/bindata.go | 246 +++++++ model/boil_queries.go | 33 + model/boil_table_names.go | 10 + model/boil_types.go | 52 ++ model/mysql_upsert.go | 58 ++ model/thumbnail.go | 1134 +++++++++++++++++++++++++++++++++ scripts/gen_models.sh | 12 + scripts/lint.sh | 33 + speech/speech.go | 36 -- sqlboiler.toml | 13 + 22 files changed, 2370 insertions(+), 53 deletions(-) create mode 100644 Makefile create mode 100644 compression/compression.go create mode 100644 db/init.go create mode 100644 db/logger.go create mode 100644 db/tx.go create mode 100644 migration/000_init_schema.sql create mode 100644 migration/bindata.go create mode 100644 model/boil_queries.go create mode 100644 model/boil_table_names.go create mode 100644 model/boil_types.go create mode 100644 model/mysql_upsert.go create mode 100644 model/thumbnail.go create mode 100755 scripts/gen_models.sh create mode 100755 scripts/lint.sh delete mode 100644 speech/speech.go create mode 100644 sqlboiler.toml diff --git a/.gitignore b/.gitignore index af392e0..1218449 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ config.json +/bin/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..df750d6 --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +BINARY=voidwalker + +DIR = $(shell cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) +BIN_DIR = ${DIR}/bin +IMPORT_PATH = github.com/lbryio/voidwalker +GOARCH = amd64 + +VERSION = $(shell git --git-dir=${DIR}/.git describe --dirty --always --long --abbrev=7) +LDFLAGS = -ldflags "-X ${IMPORT_PATH}/meta.Version=${VERSION} -X ${IMPORT_PATH}/meta.Time=$(shell date +%s) -w" + + +.PHONY: build clean test lint +.DEFAULT_GOAL: build + + +build: + mkdir -p ${BIN_DIR} && CGO_ENABLED=1 GOOS=linux GOARCH=${GOARCH} go build ${LDFLAGS} -asmflags -trimpath=${DIR} -o ${BIN_DIR}/${BINARY} main.go + +clean: + if [ -f ${BIN_DIR}/${BINARY} ]; then rm ${BIN_DIR}/${BINARY}; fi + +test: + go test ./... -v -cover + +lint: + go get github.com/alecthomas/gometalinter && gometalinter --install && gometalinter ./... \ No newline at end of file diff --git a/compression/compression.go b/compression/compression.go new file mode 100644 index 0000000..7214e05 --- /dev/null +++ b/compression/compression.go @@ -0,0 +1,52 @@ +package compression + +import ( + "io/ioutil" + "mime" + "os" + "path/filepath" + + "github.com/lbryio/lbry.go/v2/extras/errors" + giftowebp "github.com/sizeofint/gif-to-webp" + "go.uber.org/atomic" +) + +var inUse atomic.Bool +var AlreadyInUseErr = errors.Base("already busy compressing") +var UnsupportedErr = errors.Base("unsupported compression") + +// returns a compressedPath, a mimeType or an error +func Compress(path, fileName, mimeType, storePath string) (string, string, error) { + swapped := inUse.CAS(false, true) + if !swapped { + return "", "", AlreadyInUseErr + } + defer inUse.Store(false) + file, err := ioutil.ReadFile(path) + if err != nil { + return "", "", errors.Err(err) + } + switch mimeType { + case "image/gif": + converter := giftowebp.NewConverter() + converter.LoopCompatibility = false + converter.WebPConfig.SetTargetSize(500 * 1024) + converter.WebPConfig.SetMethod(2) + webpBin, err := converter.Convert(file) + if err != nil { + return "", "", errors.Err(err) + } + compressedPath := filepath.Join(storePath, fileName+".webp") + err = ioutil.WriteFile(compressedPath, webpBin, 0600) + if err != nil { + return "", "", errors.Err(err) + } + err = os.Remove(path) + return fileName + ".webp", mime.TypeByExtension(".webp"), errors.Err(err) + case mime.TypeByExtension("png"): + case mime.TypeByExtension("jpeg"): + case mime.TypeByExtension("jpg"): + + } + return "", "", UnsupportedErr +} diff --git a/config.json.example b/config.json.example index 0bba6e8..3285151 100644 --- a/config.json.example +++ b/config.json.example @@ -11,6 +11,12 @@ "database": "lbry", "password": "password" }, + "voidwalker": { + "host": "localhost", + "user": "voidwalker", + "database": "voidwalker", + "password": "voidwalker" + }, "channel_id": "", "publish_address": "", "reflector_server": "reflector.lbry.com:5567", diff --git a/configs/configs.go b/configs/configs.go index 5da10ec..c7d7483 100644 --- a/configs/configs.go +++ b/configs/configs.go @@ -16,6 +16,7 @@ type DbConfig struct { type Configs struct { Chainquery DbConfig `json:"chainquery"` Speech DbConfig `json:"speech"` + Voidwalker DbConfig `json:"voidwalker"` ChannelID string `json:"channel_id"` PublishAddress string `json:"publish_address"` ReflectorServer string `json:"reflector_server"` diff --git a/db/init.go b/db/init.go new file mode 100644 index 0000000..62a46c0 --- /dev/null +++ b/db/init.go @@ -0,0 +1,83 @@ +package db + +import ( + "database/sql" + "fmt" + + "voidwalker/configs" + "voidwalker/migration" + + _ "github.com/go-sql-driver/mysql" // import mysql + "github.com/lbryio/lbry.go/v2/extras/errors" + migrate "github.com/rubenv/sql-migrate" + log "github.com/sirupsen/logrus" + "github.com/volatiletech/sqlboiler/boil" +) + +// Init initializes a database connection based on the dsn provided. It also sets it as the global db connection. +func Init(debug bool) (*QueryLogger, error) { + conf := configs.Configuration + dbConn, err := sql.Open("mysql", fmt.Sprintf( + "%s:%s@tcp(%s:3306)/%s?parseTime=1&collation=utf8mb4_unicode_ci", + conf.Voidwalker.User, + conf.Voidwalker.Password, + conf.Voidwalker.Host, + conf.Voidwalker.Database, + )) + if err != nil { + return nil, errors.Err(err) + } + + err = dbConn.Ping() + if err != nil { + return nil, errors.Err(err) + } + + logWrapper := &QueryLogger{DB: dbConn} + if debug { + boil.DebugMode = true + } + + boil.SetDB(dbConn) + + migrations := &migrate.AssetMigrationSource{ + Asset: migration.Asset, + AssetDir: migration.AssetDir, + Dir: "migration", + } + n, migrationErr := migrate.Exec(dbConn, "mysql", migrations, migrate.Up) + if migrationErr != nil { + return nil, errors.Err(migrationErr) + } + log.Printf("Applied %d migrations", n) + + return logWrapper, nil +} + +func dbInitConnection(dsn string, driverName string, debug bool) (*sql.DB, *QueryLogger, error) { + dsn += "?parseTime=1&collation=utf8mb4_unicode_ci" + dbConn, err := sql.Open(driverName, dsn) + if err != nil { + return nil, nil, errors.Err(err) + } + + err = dbConn.Ping() + if err != nil { + return nil, nil, errors.Err(err) + } + + logWrapper := &QueryLogger{DB: dbConn} + if debug { + logWrapper.Logger = log.StandardLogger() + //boil.DebugMode = true // this just prints everything twice + } + + return dbConn, logWrapper, nil +} + +// CloseDB is a wrapper function to allow error handle when it is usually deferred. +func CloseDB(db *QueryLogger) { + if err := db.Close(); err != nil { + log.Error("Closing DB Error: ", err) + } +} diff --git a/db/logger.go b/db/logger.go new file mode 100644 index 0000000..8a69ed7 --- /dev/null +++ b/db/logger.go @@ -0,0 +1,142 @@ +package db + +import ( + "database/sql" + "time" + + "github.com/lbryio/lbry.go/v2/extras/errors" + querytools "github.com/lbryio/lbry.go/v2/extras/query" + + log "github.com/sirupsen/logrus" + "github.com/volatiletech/sqlboiler/boil" +) + +func logQueryTime(logger *log.Logger, startTime time.Time) { + logger.Debugln("Query took " + time.Since(startTime).String()) +} + +// QueryLogger implements the Executor interface +type QueryLogger struct { + DB *sql.DB + Logger *log.Logger + Enabled bool +} + +// Query implements the Executor Query function +func (d *QueryLogger) Query(query string, args ...interface{}) (*sql.Rows, error) { + if d.Logger != nil { + q, err := querytools.InterpolateParams(query, args...) + if err != nil { + return nil, errors.Err(err) + } + d.Logger.Debugln(q) + defer logQueryTime(d.Logger, time.Now()) + } + return d.DB.Query(query, args...) +} + +// Exec implements the Executor Exec function +func (d *QueryLogger) Exec(query string, args ...interface{}) (sql.Result, error) { + if d.Logger != nil { + q, err := querytools.InterpolateParams(query, args...) + if err != nil { + return nil, errors.Err(err) + } + d.Logger.Debugln(q) + defer logQueryTime(d.Logger, time.Now()) + } + return d.DB.Exec(query, args...) +} + +// QueryRow implements the Executor QueryRow function +func (d *QueryLogger) QueryRow(query string, args ...interface{}) *sql.Row { + if d.Logger != nil { + q, err := querytools.InterpolateParams(query, args...) + if err != nil { + return nil + } + d.Logger.Debugln(q) + defer logQueryTime(d.Logger, time.Now()) + } + return d.DB.QueryRow(query, args...) +} + +// Begin implements the Executor Begin function +func (d *QueryLogger) Begin() (boil.Transactor, error) { + if d.Logger != nil { + d.Logger.Debug("-> Beginning tx") + } + tx, err := d.DB.Begin() + if err != nil { + return tx, err + } + return &queryLoggerTx{Tx: tx, logger: d.Logger}, nil +} + +// Close implements the Executor Close function +func (d *QueryLogger) Close() error { + if d.Logger != nil { + d.Logger.Print("Closing DB connection") + } + return d.DB.Close() +} + +type queryLoggerTx struct { + Tx *sql.Tx + logger *log.Logger +} + +// Query implements the Executor Query function on a transaction +func (t *queryLoggerTx) Query(query string, args ...interface{}) (*sql.Rows, error) { + if t.logger != nil { + q, err := querytools.InterpolateParams(query, args...) + if err != nil { + return nil, errors.Err(err) + } + t.logger.Debugln("-> " + q) + defer logQueryTime(t.logger, time.Now()) + } + return t.Tx.Query(query, args...) +} + +// Exec implements the Executor Exec function on a transaction +func (t *queryLoggerTx) Exec(query string, args ...interface{}) (sql.Result, error) { + if t.logger != nil { + q, err := querytools.InterpolateParams(query, args...) + if err != nil { + return nil, errors.Err(err) + } + t.logger.Debugln("-> " + q) + defer logQueryTime(t.logger, time.Now()) + } + return t.Tx.Exec(query, args...) +} + +// QueryRow implements the Executor QueryRow function on a transaction +func (t *queryLoggerTx) QueryRow(query string, args ...interface{}) *sql.Row { + if t.logger != nil { + q, err := querytools.InterpolateParams(query, args...) + if err != nil { + return nil + } + t.logger.Debugln("-> " + q) + defer logQueryTime(t.logger, time.Now()) + } + return t.Tx.QueryRow(query, args...) +} + +// Commit implements the Executor Commit function on a transaction +func (t *queryLoggerTx) Commit() error { + if t.logger != nil { + t.logger.Debug("-> Committing tx") + } + return t.Tx.Commit() +} + +// RollBack implements the Executor Rollback function on a transaction +func (t *queryLoggerTx) Rollback() error { + if t.logger != nil { + t.logger.Debug("-> Rolling back tx") + } + return t.Tx.Rollback() +} diff --git a/db/tx.go b/db/tx.go new file mode 100644 index 0000000..693bc06 --- /dev/null +++ b/db/tx.go @@ -0,0 +1,46 @@ +package db + +import ( + "context" + + "github.com/lbryio/lbry.go/v2/extras/errors" + log "github.com/sirupsen/logrus" + "github.com/volatiletech/sqlboiler/boil" +) + +// TxFunc is a function that can be wrapped in a transaction +type TxFunc func(tx boil.Transactor) error + +// WithTx wraps a function in an sql transaction. the transaction is committed if there's no error, or rolled back if there is one. +// if `currentTx` is nil, a new transaction is started. otherwise currentTx is used as the transaction +func WithTx(currentTx boil.Transactor, f TxFunc) (err error) { + var tx boil.Transactor + + if currentTx != nil { + tx = currentTx + } else { + tx, err = boil.BeginTx(context.Background(), nil) + if err != nil { + return err + } + + defer func() { + if p := recover(); p != nil { + rollbackErr := tx.Rollback() + if rollbackErr != nil { + log.Errorln(errors.Prefix("rollback failed after tx error", rollbackErr)) + } + panic(p) + } else if err != nil { + rollbackErr := tx.Rollback() + if rollbackErr != nil { + log.Errorln(errors.Prefix("rollback failed after tx error", rollbackErr)) + } + } else { + err = errors.Err(tx.Commit()) + } + }() + } + + return f(tx) +} diff --git a/go.mod b/go.mod index 1c6f1b2..551a871 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,27 @@ module voidwalker go 1.14 require ( + github.com/DATA-DOG/go-sqlmock v1.4.1 // indirect + github.com/friendsofgo/errors v0.9.2 + github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/gabriel-vasile/mimetype v1.0.5 - github.com/ghodss/yaml v1.0.0 // indirect github.com/gin-contrib/cors v1.3.1 github.com/gin-gonic/gin v1.6.2 github.com/go-sql-driver/mysql v1.5.0 + github.com/gofrs/uuid v3.3.0+incompatible // indirect + github.com/gorilla/websocket v1.4.2 // indirect github.com/lbryio/lbry.go/v2 v2.5.3 github.com/lbryio/reflector.go v1.1.2 + github.com/mitchellh/mapstructure v1.3.2 // indirect + github.com/rubenv/sql-migrate v0.0.0-20200429072036-ae26b214fa43 github.com/sirupsen/logrus v1.4.2 + github.com/sizeofint/gif-to-webp v0.0.0-20190216083302-414816b4e852 + github.com/spf13/cast v1.3.1 // indirect github.com/tkanos/gonfig v0.0.0-20181112185242-896f3d81fadf + github.com/volatiletech/inflect v0.0.1 // indirect + github.com/volatiletech/null v8.0.0+incompatible + github.com/volatiletech/sqlboiler v3.7.1+incompatible + go.uber.org/atomic v1.5.0 + golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 // indirect + gopkg.in/yaml.v2 v2.3.0 // indirect ) diff --git a/go.sum b/go.sum index 3f4f521..6195dc9 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +1,38 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DATA-DOG/go-sqlmock v1.4.1 h1:ThlnYciV1iM/V0OSF/dtkqWb6xo5qITT1TJBG1MRDJM= +github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.16.11 h1:g/c7gJeVyHoXCxM2fddS85bPGVkBF8s2q8t3fyElegc= github.com/aws/aws-sdk-go v1.16.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.27.0 h1:0xphMHGMLBrPMfxR2AmVjZKcMEESEgWF8Kru94BNByk= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 h1:qkOC5Gd33k54tobS36cXdAzJbeHaduLtnLQQwNoIi78= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= @@ -25,18 +47,49 @@ github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVa github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +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.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/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/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/friendsofgo/errors v0.9.2 h1:X6NYxef4efCBdwI7BgS820zFaN7Cphrmb+Pljdzjtgk= +github.com/friendsofgo/errors v0.9.2/go.mod h1:yCvFW5AkDIL9qn7suHVLiI/gH228n7PC4Pn44IGoTOI= 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.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gabriel-vasile/mimetype v1.0.5 h1:E/D07IzERHKrUCQV4VRvbss/OC3tPHQ+bDohTpxh4Kg= github.com/gabriel-vasile/mimetype v1.0.5/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= @@ -52,6 +105,12 @@ github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6 github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-ini/ini v1.38.2/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-ini/ini v1.48.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-ozzo/ozzo-validation v3.5.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU= github.com/go-ozzo/ozzo-validation v3.6.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= @@ -65,9 +124,31 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-sql-driver/mysql v0.0.0-20180719071942-99ff426eb706/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.1 h1:OQl5ys5MBea7OGCdvPbBJWRgnhC/fGona6QKfvFeau8= +github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= +github.com/gobuffalo/logger v1.0.1 h1:ZEgyRGgAm4ZAhAO45YXMs5Fp+bzGLESFewzAVBMKuTg= +github.com/gobuffalo/logger v1.0.1/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= +github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4= +github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= +github.com/gobuffalo/packr/v2 v2.7.1 h1:n3CIW5T17T8v4GGK5sWXLVWJhCz7b5aNLSxW6gYim4o= +github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kETFqjFoFlOc= +github.com/godror/godror v0.13.3/go.mod h1:2ouUT4kdhUBk7TAkHWD4SN0CdI0pgEQbo8FVHhbSKWg= +github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84= +github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= @@ -75,12 +156,18 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20190915194858-d3ddacdb130f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -89,23 +176,37 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/rpc v1.1.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ= github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= 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/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +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/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= @@ -113,24 +214,35 @@ github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/johntdyer/slack-go v0.0.0-20180213144715-95fac1160b22/go.mod h1:u0Jo4f2dNlTJeeOywkM6bLwxq6gC3pZ9rEFHn3AhTdk= github.com/johntdyer/slackrus v0.0.0-20180518184837-f7aae3243a07/go.mod h1:j1kV/8f3jowErEq4XyeypkCdvg5EeHkf0YCKCcq5Ybo= +github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -155,31 +267,66 @@ github.com/lbryio/types v0.0.0-20191009145016-1bb8107e04f8/go.mod h1:CG3wsDv5BiV github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5/go.mod h1:c2mYKRyMb1BPkO5St0c/ps62L4S0W2NAkaTXj9qEI+0= github.com/lusis/slack-test v0.0.0-20180109053238-3c758769bfa6/go.mod h1:sFlOUpQL1YcjhFVXhg1CG8ZASEs/Mf1oVb6H75JL/zg= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/lyoshenka/bencode v0.0.0-20180323155644-b7abd7672df5 h1:mG83tLXWSRdcXMWfkoumVwhcCbf3jHF9QKv/m37BkM0= github.com/lyoshenka/bencode v0.0.0-20180323155644-b7abd7672df5/go.mod h1:H0aPCWffGOaDcjkw1iB7W9DVLp6GXmfcJY/7YZCWPA4= +github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-oci8 v0.0.7/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-sqlite3 v1.12.0 h1:u/x3mp++qUxvYfulZ4HKOvVO0JWhk7HtE8lWhbGz/Do= +github.com/mattn/go-sqlite3 v1.12.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v0.0.0-20180511142126-bb74f1db0675/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg= +github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nlopes/slack v0.5.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM= github.com/nlopes/slack v0.6.0 h1:jt0jxVQGhssx1Ib7naAOZEZcGdtIhTzkP0nopK0AsRA= github.com/nlopes/slack v0.6.0/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.2 h1:uqH7bpe+ERSiDa34FDOF7RikN6RzXgduUF8yarlZp94= @@ -187,21 +334,65 @@ github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/phayes/freeport v0.0.0-20171002185219-e27662a4a9d6 h1:2bae6N0SZjgzk+Zg8mzTsfmpwHXY9VBNp9UdjhaElA0= github.com/phayes/freeport v0.0.0-20171002185219-e27662a4a9d6/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= 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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.4.0 h1:LUa41nrWTQNGhzdsZ5lTnkwbNjj6rXTdazA1cSdjkOY= +github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rubenv/sql-migrate v0.0.0-20200429072036-ae26b214fa43 h1:0i6uTtxUGc/jpK/CngM4T2S2NFnqYUUxH+lKDgBLw8U= +github.com/rubenv/sql-migrate v0.0.0-20200429072036-ae26b214fa43/go.mod h1:DCgfY80j8GYL7MLEfvcpSFvjD0L5yZq/aZUJmhZklyg= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sebdah/goldie v0.0.0-20180424091453-8784dd1ab561/go.mod h1:lvjGftC8oe7XPtyrOidaMi0rp5B9+XY/ZRUynGnuaxQ= github.com/sebdah/goldie v0.0.0-20190531093107-d313ffb52c77/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= @@ -210,17 +401,42 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm github.com/shopspring/decimal v0.0.0-20180607144847-19e3cb6c2930/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v0.0.0-20191009025716-f1972eb1d1f5 h1:Gojs/hac/DoYEM7WEICT45+hNWczIeuL5D21e5/HPAw= github.com/shopspring/decimal v0.0.0-20191009025716-f1972eb1d1f5/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sizeofint/gif-to-webp v0.0.0-20190216083302-414816b4e852 h1:azXPlYerbbqjO7/XY6CCCWUJnuqP5pAvrW/nol9TRZg= +github.com/sizeofint/gif-to-webp v0.0.0-20190216083302-414816b4e852/go.mod h1:IXC7KN2FEuTEISdePm37qcFyXInAh6pfW35yDjbdfOM= +github.com/sizeofint/webp-animation v0.0.0-20190207194838-b631dc900de9 h1:i3LYMwQ0zkh/BJ47vIZN+jBYqV4/f6DFoAsW8rwV490= +github.com/sizeofint/webp-animation v0.0.0-20190207194838-b631dc900de9/go.mod h1:/NQ8ciRuH+vxYhrFlnX70gvXBugMYQbBygCRocFgSZ4= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.0-20180722215644-7c4570c3ebeb/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -229,105 +445,208 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/tkanos/gonfig v0.0.0-20181112185242-896f3d81fadf h1:sepG1nOX39NO8y8E+sYMkkKSDxiAfZ0XL0l0+vogwBw= github.com/tkanos/gonfig v0.0.0-20181112185242-896f3d81fadf/go.mod h1:DaZPBuToMc2eezA9R9nDAnmS2RMwL7yEa5YD36ESQdI= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= github.com/uber-go/atomic v1.4.0 h1:yOuPqEq4ovnhEjpHmfFwsqBXDYbQeT6Nb0bwD6XnD5o= github.com/uber-go/atomic v1.4.0/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/volatiletech/inflect v0.0.1 h1:2a6FcMQyhmPZcLa+uet3VJ8gLn/9svWhJxJYwvE8KsU= +github.com/volatiletech/inflect v0.0.1/go.mod h1:IBti31tG6phkHitLlr5j7shC5SOo//x0AjDzaJU1PLA= +github.com/volatiletech/null v8.0.0+incompatible h1:7wP8m5d/gZ6kW/9GnrLtMCRre2dlEnaQ9Km5OXlK4zg= +github.com/volatiletech/null v8.0.0+incompatible/go.mod h1:0wD98JzdqB+rLyZ70fN05VDbXbafIb0KU0MdVhCzmOQ= +github.com/volatiletech/sqlboiler v3.7.1+incompatible h1:dm9/NjDskQVwAarmpeZ2UqLn1NKE8M3WHSHBS4jw2x8= +github.com/volatiletech/sqlboiler v3.7.1+incompatible/go.mod h1:jLfDkkHWPbS2cWRLkyC20vQWaIQsASEY7gM7zSo11Yw= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/ybbus/jsonrpc v0.0.0-20180411222309-2a548b7d822d h1:tQo6hjclyv3RHUgZOl6iWb2Y44A/sN9bf9LAYfuioEg= github.com/ybbus/jsonrpc v0.0.0-20180411222309-2a548b7d822d/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE= +github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= +github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190125091013-d26f9f9a57f3/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= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/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-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191009170851-d66e71096ffb h1:TR699M2v0qoKTOHxeLgp6zPqaQNs74f01a/ob9W0qko= golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 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/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190520201301-c432e742b0af/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191009170203-06d7bd2c5f4f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/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-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191004055002-72853e10c5a3/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114 h1:DnSr2mCsxyCE6ZgIkmcWUQY2R5cH/6wL7eIxEmQOMSE= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181004005441-af9cb2a35e7f/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 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-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/gorp.v1 v1.7.2 h1:j3DWlAyGVv8whO7AcIWznQ2Yj7yJkn34B8s63GViAAw= +gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= gopkg.in/ini.v1 v1.41.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.48.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/nullbio/null.v6 v6.0.0-20161116030900-40264a2e6b79 h1:FpCr9V8wuOei4BAen+93HtVJ+XSi+KPbaPKm0Vj5R64= gopkg.in/nullbio/null.v6 v6.0.0-20161116030900-40264a2e6b79/go.mod h1:gWkaRU7CoXpezCBWfWjm3999QqS+1pYPXGbqQCTMzo8= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 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/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/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.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/main.go b/main.go index 2530169..b4dc5ec 100644 --- a/main.go +++ b/main.go @@ -4,10 +4,12 @@ import ( "bufio" "bytes" "crypto/sha256" + "database/sql" "encoding/hex" "fmt" "io" "io/ioutil" + "log" "mime" "net/http" "os" @@ -19,7 +21,10 @@ import ( "voidwalker/blobsdownloader" "voidwalker/chainquery" + "voidwalker/compression" "voidwalker/configs" + "voidwalker/db" + "voidwalker/model" ml2 "voidwalker/util/ml" "github.com/gabriel-vasile/mimetype" @@ -30,22 +35,34 @@ import ( "github.com/lbryio/lbry.go/v2/extras/util" "github.com/lbryio/lbry.go/v2/stream" "github.com/sirupsen/logrus" + "github.com/volatiletech/null" + "github.com/volatiletech/sqlboiler/boil" ) var publishAddress string var channelID string var cqApi *chainquery.CQApi var downloadsDir string +var compressedDir string var uploadsDir string var blobsDir string var viewLock ml2.MultipleLock var publishLock ml2.MultipleLock +//go:generate go-bindata -nometadata -o migration/bindata.go -pkg migration -ignore bindata.go migration/ +//go:generate go fmt ./migration/bindata.go +//go:generate goimports -l ./migration/bindata.go func main() { err := configs.Init("./config.json") if err != nil { panic(err) } + //Main DB connection + dbInstance, err := db.Init(true) + if err != nil { + log.Panic(err) + } + defer db.CloseDB(dbInstance) publishAddress = configs.Configuration.PublishAddress channelID = configs.Configuration.ChannelID if publishAddress == "" || channelID == "" { @@ -62,6 +79,7 @@ func main() { } uploadsDir = usr.HomeDir + "/Uploads/" downloadsDir = usr.HomeDir + "/Downloads/" + compressedDir = usr.HomeDir + "/Compressed/" blobsDir = usr.HomeDir + "/.lbrynet/blobfiles/" viewLock = ml2.NewMultipleLock() publishLock = ml2.NewMultipleLock() @@ -111,7 +129,12 @@ func view(c *gin.Context) { } } mustDownload := !inUploads && !inDownloads - if mustDownload { + t, err := model.Thumbnails(model.ThumbnailWhere.Name.EQ(claimNameWithExt)).OneG() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + _ = c.AbortWithError(http.StatusInternalServerError, errors.Err(err)) + return + } + if mustDownload && (t == nil || !t.Compressed) { if strings.Contains(id, "@") { parts := strings.Split(id, ":") channelName = parts[0] @@ -136,9 +159,6 @@ func view(c *gin.Context) { return } contentType = claim.ContentType - } - - if mustDownload { err = downloadStream(claim.SdHash, claimNameWithExt) if err != nil { logrus.Errorln(errors.FullTrace(err)) @@ -148,20 +168,49 @@ func view(c *gin.Context) { } var reader *os.File + thumbnailPath := "" if mustDownload || inDownloads { - reader, err = os.Open(downloadsDir + claimNameWithExt) - if err != nil { - logrus.Errorln(errors.FullTrace(err)) - _ = c.AbortWithError(http.StatusInternalServerError, errors.Err(err)) - return - } + thumbnailPath = downloadsDir + claimNameWithExt } else { - reader, err = os.Open(uploadsDir + claimNameWithExt) - if err != nil { - logrus.Errorln(errors.FullTrace(err)) - _ = c.AbortWithError(http.StatusInternalServerError, errors.Err(err)) - return - } + thumbnailPath = uploadsDir + claimNameWithExt //fallback + } + if t == nil || !t.Compressed { + go func() { + cp, mt, err := compression.Compress(thumbnailPath, claimName, contentType, compressedDir) + if err != nil { + if !errors.Is(err, compression.AlreadyInUseErr) && !errors.Is(err, compression.UnsupportedErr) { + logrus.Errorln(errors.FullTrace(err)) + } else { + logrus.Infoln(err.Error()) + } + } else { + if t == nil { + t = &model.Thumbnail{ + Name: claimNameWithExt, + } + } + t.Compressed = true + t.CompressedMimeType = null.StringFrom(mt) + t.CompressedName = null.StringFrom(cp) + err = t.UpsertG(boil.Infer(), boil.Infer()) + if err != nil { + logrus.Errorln(errors.FullTrace(err)) + _ = c.AbortWithError(http.StatusInternalServerError, errors.Err(err)) + return + } + thumbnailPath = filepath.Join(compressedDir, cp) + contentType = mt + } + }() + } else { + thumbnailPath = filepath.Join(compressedDir, t.CompressedName.String) + contentType = t.CompressedMimeType.String + } + reader, err = os.Open(thumbnailPath) + if err != nil { + logrus.Errorln(errors.FullTrace(err)) + _ = c.AbortWithError(http.StatusInternalServerError, errors.Err(err)) + return } defer reader.Close() f, err := reader.Stat() diff --git a/migration/000_init_schema.sql b/migration/000_init_schema.sql new file mode 100644 index 0000000..035998d --- /dev/null +++ b/migration/000_init_schema.sql @@ -0,0 +1,23 @@ +-- +migrate Up + +-- +migrate StatementBegin +CREATE SCHEMA IF NOT EXISTS `voidwalker` DEFAULT CHARACTER SET latin1 COLLATE latin1_general_ci; +-- +migrate StatementEnd +-- +migrate StatementBegin +CREATE TABLE `thumbnail` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(150) UNIQUE NOT NULL, + `compressed_name` varchar(150) UNIQUE NULL, + `compressed_mime_type` varchar(150) NULL, + `compressed` tinyint(1) NOT NULL, + `created_at` datetime default CURRENT_TIMESTAMP not null, + `updated_at` datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP, + index (`name`), + index (`created_at`), + index (`updated_at`), + PRIMARY KEY (`id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci; +-- +migrate StatementEnd diff --git a/migration/bindata.go b/migration/bindata.go new file mode 100644 index 0000000..5009c9a --- /dev/null +++ b/migration/bindata.go @@ -0,0 +1,246 @@ +// Code generated for package migration by go-bindata DO NOT EDIT. (@generated) +// sources: +// migration/000_init_schema.sql +package migration + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +// Name return file name +func (fi bindataFileInfo) Name() string { + return fi.name +} + +// Size return file size +func (fi bindataFileInfo) Size() int64 { + return fi.size +} + +// Mode return file mode +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} + +// Mode return file modify time +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} + +// IsDir return file whether a directory +func (fi bindataFileInfo) IsDir() bool { + return fi.mode&os.ModeDir != 0 +} + +// Sys return file is sys mode +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +var _migration000_init_schemaSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x93\x4f\x6f\x9b\x40\x10\xc5\xef\x7c\x8a\x77\x04\xb5\x91\xe2\xaa\x95\x2a\x55\x39\x60\xb2\x69\x50\x01\xa7\xb0\x48\xcd\x09\xd6\xde\x09\x59\x95\x1d\x2c\xbc\xa4\xcd\xb7\xaf\x10\x56\x84\x63\xa7\xb2\x94\xb9\xcd\x1f\xfd\x66\x1e\xec\xbb\xb8\xc0\x07\x6b\x9a\x5e\x39\x42\xb9\xf5\xbc\x79\x5e\x38\xe5\xc8\x12\xbb\x25\x35\x86\xbd\x28\x17\xa1\x14\x28\xa2\x5b\x91\x86\x88\x6f\x90\xad\x24\xc4\xaf\xb8\x90\x05\xea\xa7\xce\xe8\x3f\xaa\xfd\x4d\x7d\x8d\x6b\x71\x13\x96\x89\x44\x74\x1b\xe6\x61\x24\x45\x8e\x42\x48\xb4\xca\x19\x5e\x20\x5a\x25\xc9\x88\x99\xd2\xaa\x21\xa6\x5e\xb5\xd5\xc6\x7c\x3b\xbd\x5b\xb0\x3e\xe3\x28\x19\x2e\x13\x81\xda\x3d\x0e\x76\xcd\xca\xb4\xb5\xe7\x7b\x00\x50\x1b\x5d\xe3\x38\xd6\xa6\x31\xec\xfc\x4f\x97\x01\x06\xde\x99\x86\x49\xbf\x1e\x19\xc5\x65\x65\x92\x20\x2c\xe5\xaa\x8a\xb3\x28\x17\xa9\xc8\xe4\xc7\x09\xcb\xca\xd2\x31\xf8\x49\xf5\x9b\x47\xd5\xfb\x8b\x2f\x97\x01\xca\x2c\xfe\x59\x8a\xb7\xb0\x7b\xce\xa6\xb3\xdb\x9e\x76\x3b\xd2\xd5\x0c\x79\x0e\xe7\x24\xc3\x1a\x4b\x95\x7b\xde\x52\x7d\xc8\x38\x1d\x27\x19\x73\x55\xce\xf0\xf3\xf8\x9d\x16\x6f\x11\x8e\xf5\xf4\xa4\x1c\xe9\x4a\xb9\x39\x47\x2b\x47\xce\x58\x82\xa6\x07\x35\xb4\x0e\x51\x99\xe7\x22\x93\x95\x8c\x53\x51\xc8\x30\xbd\x03\x77\x0e\x3c\xb4\xed\x9e\x33\x6c\xf5\xfb\x38\xe8\x18\x13\xe4\x78\x68\xda\x61\x58\xd3\x5f\xf8\xd3\xaf\x0c\x0e\x6b\x33\x19\xaf\x3a\xb3\xc3\xf6\x9d\xbb\x3c\x4e\xc3\xfc\x1e\x3f\xc4\x3d\xfc\xf1\xbd\x05\x5e\x00\x91\x7d\x8f\x33\x81\x2b\xc4\xcc\xdd\xf5\xd2\xc3\x81\x29\x46\x3b\x5c\x61\x70\x0f\x5f\xed\xfa\xb3\x87\x17\x4f\xbc\xd4\xaa\x81\xcd\xa6\xd3\xf4\x7f\x5b\xfc\x0b\x00\x00\xff\xff\x67\x94\x22\xa2\xbc\x03\x00\x00") + +func migration000_init_schemaSqlBytes() ([]byte, error) { + return bindataRead( + _migration000_init_schemaSql, + "migration/000_init_schema.sql", + ) +} + +func migration000_init_schemaSql() (*asset, error) { + bytes, err := migration000_init_schemaSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "migration/000_init_schema.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "migration/000_init_schema.sql": migration000_init_schemaSql, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "migration": &bintree{nil, map[string]*bintree{ + "000_init_schema.sql": &bintree{migration000_init_schemaSql, map[string]*bintree{}}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/model/boil_queries.go b/model/boil_queries.go new file mode 100644 index 0000000..c8f1ec1 --- /dev/null +++ b/model/boil_queries.go @@ -0,0 +1,33 @@ +// Code generated by SQLBoiler 3.7.1 (https://github.com/volatiletech/sqlboiler). DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package model + +import ( + "github.com/volatiletech/sqlboiler/drivers" + "github.com/volatiletech/sqlboiler/queries" + "github.com/volatiletech/sqlboiler/queries/qm" +) + +var dialect = drivers.Dialect{ + LQ: 0x60, + RQ: 0x60, + + UseIndexPlaceholders: false, + UseLastInsertID: true, + UseSchema: false, + UseDefaultKeyword: false, + UseAutoColumns: false, + UseTopClause: false, + UseOutputClause: false, + UseCaseWhenExistsClause: false, +} + +// NewQuery initializes a new Query using the passed in QueryMods +func NewQuery(mods ...qm.QueryMod) *queries.Query { + q := &queries.Query{} + queries.SetDialect(q, &dialect) + qm.Apply(q, mods...) + + return q +} diff --git a/model/boil_table_names.go b/model/boil_table_names.go new file mode 100644 index 0000000..46d2325 --- /dev/null +++ b/model/boil_table_names.go @@ -0,0 +1,10 @@ +// Code generated by SQLBoiler 3.7.1 (https://github.com/volatiletech/sqlboiler). DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package model + +var TableNames = struct { + Thumbnail string +}{ + Thumbnail: "thumbnail", +} diff --git a/model/boil_types.go b/model/boil_types.go new file mode 100644 index 0000000..121e8ee --- /dev/null +++ b/model/boil_types.go @@ -0,0 +1,52 @@ +// Code generated by SQLBoiler 3.7.1 (https://github.com/volatiletech/sqlboiler). DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package model + +import ( + "strconv" + + "github.com/friendsofgo/errors" + "github.com/volatiletech/sqlboiler/boil" + "github.com/volatiletech/sqlboiler/strmangle" +) + +// M type is for providing columns and column values to UpdateAll. +type M map[string]interface{} + +// ErrSyncFail occurs during insert when the record could not be retrieved in +// order to populate default value information. This usually happens when LastInsertId +// fails or there was a primary key configuration that was not resolvable. +var ErrSyncFail = errors.New("model: failed to synchronize data after insert") + +type insertCache struct { + query string + retQuery string + valueMapping []uint64 + retMapping []uint64 +} + +type updateCache struct { + query string + valueMapping []uint64 +} + +func makeCacheKey(cols boil.Columns, nzDefaults []string) string { + buf := strmangle.GetBuffer() + + buf.WriteString(strconv.Itoa(cols.Kind)) + for _, w := range cols.Cols { + buf.WriteString(w) + } + + if len(nzDefaults) != 0 { + buf.WriteByte('.') + } + for _, nz := range nzDefaults { + buf.WriteString(nz) + } + + str := buf.String() + strmangle.PutBuffer(buf) + return str +} diff --git a/model/mysql_upsert.go b/model/mysql_upsert.go new file mode 100644 index 0000000..d33c113 --- /dev/null +++ b/model/mysql_upsert.go @@ -0,0 +1,58 @@ +// Code generated by SQLBoiler 3.7.1 (https://github.com/volatiletech/sqlboiler). DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package model + +import ( + "fmt" + "strings" + + "github.com/volatiletech/sqlboiler/drivers" + "github.com/volatiletech/sqlboiler/strmangle" +) + +// buildUpsertQueryMySQL builds a SQL statement string using the upsertData provided. +func buildUpsertQueryMySQL(dia drivers.Dialect, tableName string, update, whitelist []string) string { + whitelist = strmangle.IdentQuoteSlice(dia.LQ, dia.RQ, whitelist) + tableName = strmangle.IdentQuote(dia.LQ, dia.RQ, tableName) + + buf := strmangle.GetBuffer() + defer strmangle.PutBuffer(buf) + + var columns string + if len(whitelist) != 0 { + columns = strings.Join(whitelist, ",") + } + + if len(update) == 0 { + fmt.Fprintf( + buf, + "INSERT IGNORE INTO %s (%s) VALUES (%s)", + tableName, + columns, + strmangle.Placeholders(dia.UseIndexPlaceholders, len(whitelist), 1, 1), + ) + return buf.String() + } + + fmt.Fprintf( + buf, + "INSERT INTO %s (%s) VALUES (%s) ON DUPLICATE KEY UPDATE ", + tableName, + columns, + strmangle.Placeholders(dia.UseIndexPlaceholders, len(whitelist), 1, 1), + ) + + for i, v := range update { + if i != 0 { + buf.WriteByte(',') + } + quoted := strmangle.IdentQuote(dia.LQ, dia.RQ, v) + buf.WriteString(quoted) + buf.WriteString(" = VALUES(") + buf.WriteString(quoted) + buf.WriteByte(')') + } + + return buf.String() +} diff --git a/model/thumbnail.go b/model/thumbnail.go new file mode 100644 index 0000000..7f9790e --- /dev/null +++ b/model/thumbnail.go @@ -0,0 +1,1134 @@ +// Code generated by SQLBoiler 3.7.1 (https://github.com/volatiletech/sqlboiler). DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package model + +import ( + "database/sql" + "fmt" + "reflect" + "strconv" + "strings" + "sync" + "time" + + "github.com/friendsofgo/errors" + "github.com/volatiletech/null" + "github.com/volatiletech/sqlboiler/boil" + "github.com/volatiletech/sqlboiler/queries" + "github.com/volatiletech/sqlboiler/queries/qm" + "github.com/volatiletech/sqlboiler/queries/qmhelper" + "github.com/volatiletech/sqlboiler/strmangle" +) + +// Thumbnail is an object representing the database table. +type Thumbnail struct { + ID uint64 `boil:"id" json:"id" toml:"id" yaml:"id"` + Name string `boil:"name" json:"name" toml:"name" yaml:"name"` + CompressedName null.String `boil:"compressed_name" json:"compressed_name,omitempty" toml:"compressed_name" yaml:"compressed_name,omitempty"` + CompressedMimeType null.String `boil:"compressed_mime_type" json:"compressed_mime_type,omitempty" toml:"compressed_mime_type" yaml:"compressed_mime_type,omitempty"` + Compressed bool `boil:"compressed" json:"compressed" toml:"compressed" yaml:"compressed"` + CreatedAt time.Time `boil:"created_at" json:"created_at" toml:"created_at" yaml:"created_at"` + UpdatedAt time.Time `boil:"updated_at" json:"updated_at" toml:"updated_at" yaml:"updated_at"` + + R *thumbnailR `boil:"-" json:"-" toml:"-" yaml:"-"` + L thumbnailL `boil:"-" json:"-" toml:"-" yaml:"-"` +} + +var ThumbnailColumns = struct { + ID string + Name string + CompressedName string + CompressedMimeType string + Compressed string + CreatedAt string + UpdatedAt string +}{ + ID: "id", + Name: "name", + CompressedName: "compressed_name", + CompressedMimeType: "compressed_mime_type", + Compressed: "compressed", + CreatedAt: "created_at", + UpdatedAt: "updated_at", +} + +// Generated where + +type whereHelperuint64 struct{ field string } + +func (w whereHelperuint64) EQ(x uint64) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.EQ, x) } +func (w whereHelperuint64) NEQ(x uint64) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.NEQ, x) } +func (w whereHelperuint64) LT(x uint64) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LT, x) } +func (w whereHelperuint64) LTE(x uint64) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LTE, x) } +func (w whereHelperuint64) GT(x uint64) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GT, x) } +func (w whereHelperuint64) GTE(x uint64) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GTE, x) } +func (w whereHelperuint64) IN(slice []uint64) qm.QueryMod { + values := make([]interface{}, 0, len(slice)) + for _, value := range slice { + values = append(values, value) + } + return qm.WhereIn(fmt.Sprintf("%s IN ?", w.field), values...) +} + +type whereHelperstring struct{ field string } + +func (w whereHelperstring) EQ(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.EQ, x) } +func (w whereHelperstring) NEQ(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.NEQ, x) } +func (w whereHelperstring) LT(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LT, x) } +func (w whereHelperstring) LTE(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LTE, x) } +func (w whereHelperstring) GT(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GT, x) } +func (w whereHelperstring) GTE(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GTE, x) } +func (w whereHelperstring) IN(slice []string) qm.QueryMod { + values := make([]interface{}, 0, len(slice)) + for _, value := range slice { + values = append(values, value) + } + return qm.WhereIn(fmt.Sprintf("%s IN ?", w.field), values...) +} + +type whereHelpernull_String struct{ field string } + +func (w whereHelpernull_String) EQ(x null.String) qm.QueryMod { + return qmhelper.WhereNullEQ(w.field, false, x) +} +func (w whereHelpernull_String) NEQ(x null.String) qm.QueryMod { + return qmhelper.WhereNullEQ(w.field, true, x) +} +func (w whereHelpernull_String) IsNull() qm.QueryMod { return qmhelper.WhereIsNull(w.field) } +func (w whereHelpernull_String) IsNotNull() qm.QueryMod { return qmhelper.WhereIsNotNull(w.field) } +func (w whereHelpernull_String) LT(x null.String) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.LT, x) +} +func (w whereHelpernull_String) LTE(x null.String) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.LTE, x) +} +func (w whereHelpernull_String) GT(x null.String) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.GT, x) +} +func (w whereHelpernull_String) GTE(x null.String) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.GTE, x) +} + +type whereHelperbool struct{ field string } + +func (w whereHelperbool) EQ(x bool) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.EQ, x) } +func (w whereHelperbool) NEQ(x bool) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.NEQ, x) } +func (w whereHelperbool) LT(x bool) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LT, x) } +func (w whereHelperbool) LTE(x bool) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LTE, x) } +func (w whereHelperbool) GT(x bool) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GT, x) } +func (w whereHelperbool) GTE(x bool) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GTE, x) } + +type whereHelpertime_Time struct{ field string } + +func (w whereHelpertime_Time) EQ(x time.Time) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.EQ, x) +} +func (w whereHelpertime_Time) NEQ(x time.Time) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.NEQ, x) +} +func (w whereHelpertime_Time) LT(x time.Time) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.LT, x) +} +func (w whereHelpertime_Time) LTE(x time.Time) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.LTE, x) +} +func (w whereHelpertime_Time) GT(x time.Time) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.GT, x) +} +func (w whereHelpertime_Time) GTE(x time.Time) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.GTE, x) +} + +var ThumbnailWhere = struct { + ID whereHelperuint64 + Name whereHelperstring + CompressedName whereHelpernull_String + CompressedMimeType whereHelpernull_String + Compressed whereHelperbool + CreatedAt whereHelpertime_Time + UpdatedAt whereHelpertime_Time +}{ + ID: whereHelperuint64{field: "`thumbnail`.`id`"}, + Name: whereHelperstring{field: "`thumbnail`.`name`"}, + CompressedName: whereHelpernull_String{field: "`thumbnail`.`compressed_name`"}, + CompressedMimeType: whereHelpernull_String{field: "`thumbnail`.`compressed_mime_type`"}, + Compressed: whereHelperbool{field: "`thumbnail`.`compressed`"}, + CreatedAt: whereHelpertime_Time{field: "`thumbnail`.`created_at`"}, + UpdatedAt: whereHelpertime_Time{field: "`thumbnail`.`updated_at`"}, +} + +// ThumbnailRels is where relationship names are stored. +var ThumbnailRels = struct { +}{} + +// thumbnailR is where relationships are stored. +type thumbnailR struct { +} + +// NewStruct creates a new relationship struct +func (*thumbnailR) NewStruct() *thumbnailR { + return &thumbnailR{} +} + +// thumbnailL is where Load methods for each relationship are stored. +type thumbnailL struct{} + +var ( + thumbnailAllColumns = []string{"id", "name", "compressed_name", "compressed_mime_type", "compressed", "created_at", "updated_at"} + thumbnailColumnsWithoutDefault = []string{"name", "compressed_name", "compressed_mime_type", "compressed"} + thumbnailColumnsWithDefault = []string{"id", "created_at", "updated_at"} + thumbnailPrimaryKeyColumns = []string{"id"} +) + +type ( + // ThumbnailSlice is an alias for a slice of pointers to Thumbnail. + // This should generally be used opposed to []Thumbnail. + ThumbnailSlice []*Thumbnail + + thumbnailQuery struct { + *queries.Query + } +) + +// Cache for insert, update and upsert +var ( + thumbnailType = reflect.TypeOf(&Thumbnail{}) + thumbnailMapping = queries.MakeStructMapping(thumbnailType) + thumbnailPrimaryKeyMapping, _ = queries.BindMapping(thumbnailType, thumbnailMapping, thumbnailPrimaryKeyColumns) + thumbnailInsertCacheMut sync.RWMutex + thumbnailInsertCache = make(map[string]insertCache) + thumbnailUpdateCacheMut sync.RWMutex + thumbnailUpdateCache = make(map[string]updateCache) + thumbnailUpsertCacheMut sync.RWMutex + thumbnailUpsertCache = make(map[string]insertCache) +) + +var ( + // Force time package dependency for automated UpdatedAt/CreatedAt. + _ = time.Second + // Force qmhelper dependency for where clause generation (which doesn't + // always happen) + _ = qmhelper.Where +) + +// OneG returns a single thumbnail record from the query using the global executor. +func (q thumbnailQuery) OneG() (*Thumbnail, error) { + return q.One(boil.GetDB()) +} + +// OneGP returns a single thumbnail record from the query using the global executor, and panics on error. +func (q thumbnailQuery) OneGP() *Thumbnail { + o, err := q.One(boil.GetDB()) + if err != nil { + panic(boil.WrapErr(err)) + } + + return o +} + +// OneP returns a single thumbnail record from the query, and panics on error. +func (q thumbnailQuery) OneP(exec boil.Executor) *Thumbnail { + o, err := q.One(exec) + if err != nil { + panic(boil.WrapErr(err)) + } + + return o +} + +// One returns a single thumbnail record from the query. +func (q thumbnailQuery) One(exec boil.Executor) (*Thumbnail, error) { + o := &Thumbnail{} + + queries.SetLimit(q.Query, 1) + + err := q.Bind(nil, exec, o) + if err != nil { + if errors.Cause(err) == sql.ErrNoRows { + return nil, sql.ErrNoRows + } + return nil, errors.Wrap(err, "model: failed to execute a one query for thumbnail") + } + + return o, nil +} + +// AllG returns all Thumbnail records from the query using the global executor. +func (q thumbnailQuery) AllG() (ThumbnailSlice, error) { + return q.All(boil.GetDB()) +} + +// AllGP returns all Thumbnail records from the query using the global executor, and panics on error. +func (q thumbnailQuery) AllGP() ThumbnailSlice { + o, err := q.All(boil.GetDB()) + if err != nil { + panic(boil.WrapErr(err)) + } + + return o +} + +// AllP returns all Thumbnail records from the query, and panics on error. +func (q thumbnailQuery) AllP(exec boil.Executor) ThumbnailSlice { + o, err := q.All(exec) + if err != nil { + panic(boil.WrapErr(err)) + } + + return o +} + +// All returns all Thumbnail records from the query. +func (q thumbnailQuery) All(exec boil.Executor) (ThumbnailSlice, error) { + var o []*Thumbnail + + err := q.Bind(nil, exec, &o) + if err != nil { + return nil, errors.Wrap(err, "model: failed to assign all query results to Thumbnail slice") + } + + return o, nil +} + +// CountG returns the count of all Thumbnail records in the query, and panics on error. +func (q thumbnailQuery) CountG() (int64, error) { + return q.Count(boil.GetDB()) +} + +// CountGP returns the count of all Thumbnail records in the query using the global executor, and panics on error. +func (q thumbnailQuery) CountGP() int64 { + c, err := q.Count(boil.GetDB()) + if err != nil { + panic(boil.WrapErr(err)) + } + + return c +} + +// CountP returns the count of all Thumbnail records in the query, and panics on error. +func (q thumbnailQuery) CountP(exec boil.Executor) int64 { + c, err := q.Count(exec) + if err != nil { + panic(boil.WrapErr(err)) + } + + return c +} + +// Count returns the count of all Thumbnail records in the query. +func (q thumbnailQuery) Count(exec boil.Executor) (int64, error) { + var count int64 + + queries.SetSelect(q.Query, nil) + queries.SetCount(q.Query) + + err := q.Query.QueryRow(exec).Scan(&count) + if err != nil { + return 0, errors.Wrap(err, "model: failed to count thumbnail rows") + } + + return count, nil +} + +// ExistsG checks if the row exists in the table, and panics on error. +func (q thumbnailQuery) ExistsG() (bool, error) { + return q.Exists(boil.GetDB()) +} + +// ExistsGP checks if the row exists in the table using the global executor, and panics on error. +func (q thumbnailQuery) ExistsGP() bool { + e, err := q.Exists(boil.GetDB()) + if err != nil { + panic(boil.WrapErr(err)) + } + + return e +} + +// ExistsP checks if the row exists in the table, and panics on error. +func (q thumbnailQuery) ExistsP(exec boil.Executor) bool { + e, err := q.Exists(exec) + if err != nil { + panic(boil.WrapErr(err)) + } + + return e +} + +// Exists checks if the row exists in the table. +func (q thumbnailQuery) Exists(exec boil.Executor) (bool, error) { + var count int64 + + queries.SetSelect(q.Query, nil) + queries.SetCount(q.Query) + queries.SetLimit(q.Query, 1) + + err := q.Query.QueryRow(exec).Scan(&count) + if err != nil { + return false, errors.Wrap(err, "model: failed to check if thumbnail exists") + } + + return count > 0, nil +} + +// Thumbnails retrieves all the records using an executor. +func Thumbnails(mods ...qm.QueryMod) thumbnailQuery { + mods = append(mods, qm.From("`thumbnail`")) + return thumbnailQuery{NewQuery(mods...)} +} + +// FindThumbnailG retrieves a single record by ID. +func FindThumbnailG(iD uint64, selectCols ...string) (*Thumbnail, error) { + return FindThumbnail(boil.GetDB(), iD, selectCols...) +} + +// FindThumbnailP retrieves a single record by ID with an executor, and panics on error. +func FindThumbnailP(exec boil.Executor, iD uint64, selectCols ...string) *Thumbnail { + retobj, err := FindThumbnail(exec, iD, selectCols...) + if err != nil { + panic(boil.WrapErr(err)) + } + + return retobj +} + +// FindThumbnailGP retrieves a single record by ID, and panics on error. +func FindThumbnailGP(iD uint64, selectCols ...string) *Thumbnail { + retobj, err := FindThumbnail(boil.GetDB(), iD, selectCols...) + if err != nil { + panic(boil.WrapErr(err)) + } + + return retobj +} + +// FindThumbnail retrieves a single record by ID with an executor. +// If selectCols is empty Find will return all columns. +func FindThumbnail(exec boil.Executor, iD uint64, selectCols ...string) (*Thumbnail, error) { + thumbnailObj := &Thumbnail{} + + sel := "*" + if len(selectCols) > 0 { + sel = strings.Join(strmangle.IdentQuoteSlice(dialect.LQ, dialect.RQ, selectCols), ",") + } + query := fmt.Sprintf( + "select %s from `thumbnail` where `id`=?", sel, + ) + + q := queries.Raw(query, iD) + + err := q.Bind(nil, exec, thumbnailObj) + if err != nil { + if errors.Cause(err) == sql.ErrNoRows { + return nil, sql.ErrNoRows + } + return nil, errors.Wrap(err, "model: unable to select from thumbnail") + } + + return thumbnailObj, nil +} + +// InsertG a single record. See Insert for whitelist behavior description. +func (o *Thumbnail) InsertG(columns boil.Columns) error { + return o.Insert(boil.GetDB(), columns) +} + +// InsertP a single record using an executor, and panics on error. See Insert +// for whitelist behavior description. +func (o *Thumbnail) InsertP(exec boil.Executor, columns boil.Columns) { + if err := o.Insert(exec, columns); err != nil { + panic(boil.WrapErr(err)) + } +} + +// InsertGP a single record, and panics on error. See Insert for whitelist +// behavior description. +func (o *Thumbnail) InsertGP(columns boil.Columns) { + if err := o.Insert(boil.GetDB(), columns); err != nil { + panic(boil.WrapErr(err)) + } +} + +// Insert a single record using an executor. +// See boil.Columns.InsertColumnSet documentation to understand column list inference for inserts. +func (o *Thumbnail) Insert(exec boil.Executor, columns boil.Columns) error { + if o == nil { + return errors.New("model: no thumbnail provided for insertion") + } + + var err error + + nzDefaults := queries.NonZeroDefaultSet(thumbnailColumnsWithDefault, o) + + key := makeCacheKey(columns, nzDefaults) + thumbnailInsertCacheMut.RLock() + cache, cached := thumbnailInsertCache[key] + thumbnailInsertCacheMut.RUnlock() + + if !cached { + wl, returnColumns := columns.InsertColumnSet( + thumbnailAllColumns, + thumbnailColumnsWithDefault, + thumbnailColumnsWithoutDefault, + nzDefaults, + ) + + cache.valueMapping, err = queries.BindMapping(thumbnailType, thumbnailMapping, wl) + if err != nil { + return err + } + cache.retMapping, err = queries.BindMapping(thumbnailType, thumbnailMapping, returnColumns) + if err != nil { + return err + } + if len(wl) != 0 { + cache.query = fmt.Sprintf("INSERT INTO `thumbnail` (`%s`) %%sVALUES (%s)%%s", strings.Join(wl, "`,`"), strmangle.Placeholders(dialect.UseIndexPlaceholders, len(wl), 1, 1)) + } else { + cache.query = "INSERT INTO `thumbnail` () VALUES ()%s%s" + } + + var queryOutput, queryReturning string + + if len(cache.retMapping) != 0 { + cache.retQuery = fmt.Sprintf("SELECT `%s` FROM `thumbnail` WHERE %s", strings.Join(returnColumns, "`,`"), strmangle.WhereClause("`", "`", 0, thumbnailPrimaryKeyColumns)) + } + + cache.query = fmt.Sprintf(cache.query, queryOutput, queryReturning) + } + + value := reflect.Indirect(reflect.ValueOf(o)) + vals := queries.ValuesFromMapping(value, cache.valueMapping) + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, cache.query) + fmt.Fprintln(boil.DebugWriter, vals) + } + result, err := exec.Exec(cache.query, vals...) + + if err != nil { + return errors.Wrap(err, "model: unable to insert into thumbnail") + } + + var lastID int64 + var identifierCols []interface{} + + if len(cache.retMapping) == 0 { + goto CacheNoHooks + } + + lastID, err = result.LastInsertId() + if err != nil { + return ErrSyncFail + } + + o.ID = uint64(lastID) + if lastID != 0 && len(cache.retMapping) == 1 && cache.retMapping[0] == thumbnailMapping["id"] { + goto CacheNoHooks + } + + identifierCols = []interface{}{ + o.ID, + } + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, cache.retQuery) + fmt.Fprintln(boil.DebugWriter, identifierCols...) + } + err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...) + if err != nil { + return errors.Wrap(err, "model: unable to populate default values for thumbnail") + } + +CacheNoHooks: + if !cached { + thumbnailInsertCacheMut.Lock() + thumbnailInsertCache[key] = cache + thumbnailInsertCacheMut.Unlock() + } + + return nil +} + +// UpdateG a single Thumbnail record using the global executor. +// See Update for more documentation. +func (o *Thumbnail) UpdateG(columns boil.Columns) error { + return o.Update(boil.GetDB(), columns) +} + +// UpdateP uses an executor to update the Thumbnail, and panics on error. +// See Update for more documentation. +func (o *Thumbnail) UpdateP(exec boil.Executor, columns boil.Columns) { + err := o.Update(exec, columns) + if err != nil { + panic(boil.WrapErr(err)) + } +} + +// UpdateGP a single Thumbnail record using the global executor. Panics on error. +// See Update for more documentation. +func (o *Thumbnail) UpdateGP(columns boil.Columns) { + err := o.Update(boil.GetDB(), columns) + if err != nil { + panic(boil.WrapErr(err)) + } +} + +// Update uses an executor to update the Thumbnail. +// See boil.Columns.UpdateColumnSet documentation to understand column list inference for updates. +// Update does not automatically update the record in case of default values. Use .Reload() to refresh the records. +func (o *Thumbnail) Update(exec boil.Executor, columns boil.Columns) error { + var err error + key := makeCacheKey(columns, nil) + thumbnailUpdateCacheMut.RLock() + cache, cached := thumbnailUpdateCache[key] + thumbnailUpdateCacheMut.RUnlock() + + if !cached { + wl := columns.UpdateColumnSet( + thumbnailAllColumns, + thumbnailPrimaryKeyColumns, + ) + + if len(wl) == 0 { + return errors.New("model: unable to update thumbnail, could not build whitelist") + } + + cache.query = fmt.Sprintf("UPDATE `thumbnail` SET %s WHERE %s", + strmangle.SetParamNames("`", "`", 0, wl), + strmangle.WhereClause("`", "`", 0, thumbnailPrimaryKeyColumns), + ) + cache.valueMapping, err = queries.BindMapping(thumbnailType, thumbnailMapping, append(wl, thumbnailPrimaryKeyColumns...)) + if err != nil { + return err + } + } + + values := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), cache.valueMapping) + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, cache.query) + fmt.Fprintln(boil.DebugWriter, values) + } + _, err = exec.Exec(cache.query, values...) + if err != nil { + return errors.Wrap(err, "model: unable to update thumbnail row") + } + + if !cached { + thumbnailUpdateCacheMut.Lock() + thumbnailUpdateCache[key] = cache + thumbnailUpdateCacheMut.Unlock() + } + + return nil +} + +// UpdateAllP updates all rows with matching column names, and panics on error. +func (q thumbnailQuery) UpdateAllP(exec boil.Executor, cols M) { + err := q.UpdateAll(exec, cols) + if err != nil { + panic(boil.WrapErr(err)) + } +} + +// UpdateAllG updates all rows with the specified column values. +func (q thumbnailQuery) UpdateAllG(cols M) error { + return q.UpdateAll(boil.GetDB(), cols) +} + +// UpdateAll updates all rows with the specified column values. +func (q thumbnailQuery) UpdateAll(exec boil.Executor, cols M) error { + queries.SetUpdate(q.Query, cols) + + _, err := q.Query.Exec(exec) + if err != nil { + return errors.Wrap(err, "model: unable to update all for thumbnail") + } + + return nil +} + +// UpdateAllG updates all rows with the specified column values. +func (o ThumbnailSlice) UpdateAllG(cols M) error { + return o.UpdateAll(boil.GetDB(), cols) +} + +// UpdateAllGP updates all rows with the specified column values, and panics on error. +func (o ThumbnailSlice) UpdateAllGP(cols M) { + err := o.UpdateAll(boil.GetDB(), cols) + if err != nil { + panic(boil.WrapErr(err)) + } +} + +// UpdateAllP updates all rows with the specified column values, and panics on error. +func (o ThumbnailSlice) UpdateAllP(exec boil.Executor, cols M) { + err := o.UpdateAll(exec, cols) + if err != nil { + panic(boil.WrapErr(err)) + } +} + +// UpdateAll updates all rows with the specified column values, using an executor. +func (o ThumbnailSlice) UpdateAll(exec boil.Executor, cols M) error { + ln := int64(len(o)) + if ln == 0 { + return nil + } + + if len(cols) == 0 { + return errors.New("model: update all requires at least one column argument") + } + + colNames := make([]string, len(cols)) + args := make([]interface{}, len(cols)) + + i := 0 + for name, value := range cols { + colNames[i] = name + args[i] = value + i++ + } + + // Append all of the primary key values for each column + for _, obj := range o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), thumbnailPrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := fmt.Sprintf("UPDATE `thumbnail` SET %s WHERE %s", + strmangle.SetParamNames("`", "`", 0, colNames), + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 0, thumbnailPrimaryKeyColumns, len(o))) + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, args...) + } + _, err := exec.Exec(sql, args...) + if err != nil { + return errors.Wrap(err, "model: unable to update all in thumbnail slice") + } + + return nil +} + +// UpsertG attempts an insert, and does an update or ignore on conflict. +func (o *Thumbnail) UpsertG(updateColumns, insertColumns boil.Columns) error { + return o.Upsert(boil.GetDB(), updateColumns, insertColumns) +} + +// UpsertGP attempts an insert, and does an update or ignore on conflict. Panics on error. +func (o *Thumbnail) UpsertGP(updateColumns, insertColumns boil.Columns) { + if err := o.Upsert(boil.GetDB(), updateColumns, insertColumns); err != nil { + panic(boil.WrapErr(err)) + } +} + +// UpsertP attempts an insert using an executor, and does an update or ignore on conflict. +// UpsertP panics on error. +func (o *Thumbnail) UpsertP(exec boil.Executor, updateColumns, insertColumns boil.Columns) { + if err := o.Upsert(exec, updateColumns, insertColumns); err != nil { + panic(boil.WrapErr(err)) + } +} + +var mySQLThumbnailUniqueColumns = []string{ + "id", + "name", + "compressed_name", +} + +// Upsert attempts an insert using an executor, and does an update or ignore on conflict. +// See boil.Columns documentation for how to properly use updateColumns and insertColumns. +func (o *Thumbnail) Upsert(exec boil.Executor, updateColumns, insertColumns boil.Columns) error { + if o == nil { + return errors.New("model: no thumbnail provided for upsert") + } + + nzDefaults := queries.NonZeroDefaultSet(thumbnailColumnsWithDefault, o) + nzUniques := queries.NonZeroDefaultSet(mySQLThumbnailUniqueColumns, o) + + if len(nzUniques) == 0 { + return errors.New("cannot upsert with a table that cannot conflict on a unique column") + } + + // Build cache key in-line uglily - mysql vs psql problems + buf := strmangle.GetBuffer() + buf.WriteString(strconv.Itoa(updateColumns.Kind)) + for _, c := range updateColumns.Cols { + buf.WriteString(c) + } + buf.WriteByte('.') + buf.WriteString(strconv.Itoa(insertColumns.Kind)) + for _, c := range insertColumns.Cols { + buf.WriteString(c) + } + buf.WriteByte('.') + for _, c := range nzDefaults { + buf.WriteString(c) + } + buf.WriteByte('.') + for _, c := range nzUniques { + buf.WriteString(c) + } + key := buf.String() + strmangle.PutBuffer(buf) + + thumbnailUpsertCacheMut.RLock() + cache, cached := thumbnailUpsertCache[key] + thumbnailUpsertCacheMut.RUnlock() + + var err error + + if !cached { + insert, ret := insertColumns.InsertColumnSet( + thumbnailAllColumns, + thumbnailColumnsWithDefault, + thumbnailColumnsWithoutDefault, + nzDefaults, + ) + update := updateColumns.UpdateColumnSet( + thumbnailAllColumns, + thumbnailPrimaryKeyColumns, + ) + + if len(update) == 0 { + return errors.New("model: unable to upsert thumbnail, could not build update column list") + } + + ret = strmangle.SetComplement(ret, nzUniques) + cache.query = buildUpsertQueryMySQL(dialect, "thumbnail", update, insert) + cache.retQuery = fmt.Sprintf( + "SELECT %s FROM `thumbnail` WHERE %s", + strings.Join(strmangle.IdentQuoteSlice(dialect.LQ, dialect.RQ, ret), ","), + strmangle.WhereClause("`", "`", 0, nzUniques), + ) + + cache.valueMapping, err = queries.BindMapping(thumbnailType, thumbnailMapping, insert) + if err != nil { + return err + } + if len(ret) != 0 { + cache.retMapping, err = queries.BindMapping(thumbnailType, thumbnailMapping, ret) + if err != nil { + return err + } + } + } + + value := reflect.Indirect(reflect.ValueOf(o)) + vals := queries.ValuesFromMapping(value, cache.valueMapping) + var returns []interface{} + if len(cache.retMapping) != 0 { + returns = queries.PtrsFromMapping(value, cache.retMapping) + } + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, cache.query) + fmt.Fprintln(boil.DebugWriter, vals) + } + result, err := exec.Exec(cache.query, vals...) + + if err != nil { + return errors.Wrap(err, "model: unable to upsert for thumbnail") + } + + var lastID int64 + var uniqueMap []uint64 + var nzUniqueCols []interface{} + + if len(cache.retMapping) == 0 { + goto CacheNoHooks + } + + lastID, err = result.LastInsertId() + if err != nil { + return ErrSyncFail + } + + o.ID = uint64(lastID) + if lastID != 0 && len(cache.retMapping) == 1 && cache.retMapping[0] == thumbnailMapping["id"] { + goto CacheNoHooks + } + + uniqueMap, err = queries.BindMapping(thumbnailType, thumbnailMapping, nzUniques) + if err != nil { + return errors.Wrap(err, "model: unable to retrieve unique values for thumbnail") + } + nzUniqueCols = queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), uniqueMap) + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, cache.retQuery) + fmt.Fprintln(boil.DebugWriter, nzUniqueCols...) + } + err = exec.QueryRow(cache.retQuery, nzUniqueCols...).Scan(returns...) + if err != nil { + return errors.Wrap(err, "model: unable to populate default values for thumbnail") + } + +CacheNoHooks: + if !cached { + thumbnailUpsertCacheMut.Lock() + thumbnailUpsertCache[key] = cache + thumbnailUpsertCacheMut.Unlock() + } + + return nil +} + +// DeleteG deletes a single Thumbnail record. +// DeleteG will match against the primary key column to find the record to delete. +func (o *Thumbnail) DeleteG() error { + return o.Delete(boil.GetDB()) +} + +// DeleteP deletes a single Thumbnail record with an executor. +// DeleteP will match against the primary key column to find the record to delete. +// Panics on error. +func (o *Thumbnail) DeleteP(exec boil.Executor) { + err := o.Delete(exec) + if err != nil { + panic(boil.WrapErr(err)) + } +} + +// DeleteGP deletes a single Thumbnail record. +// DeleteGP will match against the primary key column to find the record to delete. +// Panics on error. +func (o *Thumbnail) DeleteGP() { + err := o.Delete(boil.GetDB()) + if err != nil { + panic(boil.WrapErr(err)) + } +} + +// Delete deletes a single Thumbnail record with an executor. +// Delete will match against the primary key column to find the record to delete. +func (o *Thumbnail) Delete(exec boil.Executor) error { + if o == nil { + return errors.New("model: no Thumbnail provided for delete") + } + + args := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), thumbnailPrimaryKeyMapping) + sql := "DELETE FROM `thumbnail` WHERE `id`=?" + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, args...) + } + _, err := exec.Exec(sql, args...) + if err != nil { + return errors.Wrap(err, "model: unable to delete from thumbnail") + } + + return nil +} + +// DeleteAllP deletes all rows, and panics on error. +func (q thumbnailQuery) DeleteAllP(exec boil.Executor) { + err := q.DeleteAll(exec) + if err != nil { + panic(boil.WrapErr(err)) + } +} + +// DeleteAll deletes all matching rows. +func (q thumbnailQuery) DeleteAll(exec boil.Executor) error { + if q.Query == nil { + return errors.New("model: no thumbnailQuery provided for delete all") + } + + queries.SetDelete(q.Query) + + _, err := q.Query.Exec(exec) + if err != nil { + return errors.Wrap(err, "model: unable to delete all from thumbnail") + } + + return nil +} + +// DeleteAllG deletes all rows in the slice. +func (o ThumbnailSlice) DeleteAllG() error { + return o.DeleteAll(boil.GetDB()) +} + +// DeleteAllP deletes all rows in the slice, using an executor, and panics on error. +func (o ThumbnailSlice) DeleteAllP(exec boil.Executor) { + err := o.DeleteAll(exec) + if err != nil { + panic(boil.WrapErr(err)) + } +} + +// DeleteAllGP deletes all rows in the slice, and panics on error. +func (o ThumbnailSlice) DeleteAllGP() { + err := o.DeleteAll(boil.GetDB()) + if err != nil { + panic(boil.WrapErr(err)) + } +} + +// DeleteAll deletes all rows in the slice, using an executor. +func (o ThumbnailSlice) DeleteAll(exec boil.Executor) error { + if len(o) == 0 { + return nil + } + + var args []interface{} + for _, obj := range o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), thumbnailPrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := "DELETE FROM `thumbnail` WHERE " + + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 0, thumbnailPrimaryKeyColumns, len(o)) + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, args) + } + _, err := exec.Exec(sql, args...) + if err != nil { + return errors.Wrap(err, "model: unable to delete all from thumbnail slice") + } + + return nil +} + +// ReloadG refetches the object from the database using the primary keys. +func (o *Thumbnail) ReloadG() error { + if o == nil { + return errors.New("model: no Thumbnail provided for reload") + } + + return o.Reload(boil.GetDB()) +} + +// ReloadP refetches the object from the database with an executor. Panics on error. +func (o *Thumbnail) ReloadP(exec boil.Executor) { + if err := o.Reload(exec); err != nil { + panic(boil.WrapErr(err)) + } +} + +// ReloadGP refetches the object from the database and panics on error. +func (o *Thumbnail) ReloadGP() { + if err := o.Reload(boil.GetDB()); err != nil { + panic(boil.WrapErr(err)) + } +} + +// Reload refetches the object from the database +// using the primary keys with an executor. +func (o *Thumbnail) Reload(exec boil.Executor) error { + ret, err := FindThumbnail(exec, o.ID) + if err != nil { + return err + } + + *o = *ret + return nil +} + +// ReloadAllG refetches every row with matching primary key column values +// and overwrites the original object slice with the newly updated slice. +func (o *ThumbnailSlice) ReloadAllG() error { + if o == nil { + return errors.New("model: empty ThumbnailSlice provided for reload all") + } + + return o.ReloadAll(boil.GetDB()) +} + +// ReloadAllP refetches every row with matching primary key column values +// and overwrites the original object slice with the newly updated slice. +// Panics on error. +func (o *ThumbnailSlice) ReloadAllP(exec boil.Executor) { + if err := o.ReloadAll(exec); err != nil { + panic(boil.WrapErr(err)) + } +} + +// ReloadAllGP refetches every row with matching primary key column values +// and overwrites the original object slice with the newly updated slice. +// Panics on error. +func (o *ThumbnailSlice) ReloadAllGP() { + if err := o.ReloadAll(boil.GetDB()); err != nil { + panic(boil.WrapErr(err)) + } +} + +// ReloadAll refetches every row with matching primary key column values +// and overwrites the original object slice with the newly updated slice. +func (o *ThumbnailSlice) ReloadAll(exec boil.Executor) error { + if o == nil || len(*o) == 0 { + return nil + } + + slice := ThumbnailSlice{} + var args []interface{} + for _, obj := range *o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), thumbnailPrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := "SELECT `thumbnail`.* FROM `thumbnail` WHERE " + + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 0, thumbnailPrimaryKeyColumns, len(*o)) + + q := queries.Raw(sql, args...) + + err := q.Bind(nil, exec, &slice) + if err != nil { + return errors.Wrap(err, "model: unable to reload all in ThumbnailSlice") + } + + *o = slice + + return nil +} + +// ThumbnailExistsG checks if the Thumbnail row exists. +func ThumbnailExistsG(iD uint64) (bool, error) { + return ThumbnailExists(boil.GetDB(), iD) +} + +// ThumbnailExistsP checks if the Thumbnail row exists. Panics on error. +func ThumbnailExistsP(exec boil.Executor, iD uint64) bool { + e, err := ThumbnailExists(exec, iD) + if err != nil { + panic(boil.WrapErr(err)) + } + + return e +} + +// ThumbnailExistsGP checks if the Thumbnail row exists. Panics on error. +func ThumbnailExistsGP(iD uint64) bool { + e, err := ThumbnailExists(boil.GetDB(), iD) + if err != nil { + panic(boil.WrapErr(err)) + } + + return e +} + +// ThumbnailExists checks if the Thumbnail row exists. +func ThumbnailExists(exec boil.Executor, iD uint64) (bool, error) { + var exists bool + sql := "select exists(select 1 from `thumbnail` where `id`=? limit 1)" + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, iD) + } + row := exec.QueryRow(sql, iD) + + err := row.Scan(&exists) + if err != nil { + return false, errors.Wrap(err, "model: unable to check if thumbnail exists") + } + + return exists, nil +} diff --git a/scripts/gen_models.sh b/scripts/gen_models.sh new file mode 100755 index 0000000..b8a8855 --- /dev/null +++ b/scripts/gen_models.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "$DIR" +cd ".." +DIR="$PWD" +( + cd "$DIR" + go get -u -t github.com/volatiletech/sqlboiler@v3.7.1 + go get -u -t github.com/volatiletech/sqlboiler/drivers/sqlboiler-mysql@v3.7.1 + sqlboiler --no-rows-affected --no-auto-timestamps --no-hooks --no-tests --no-context --add-global-variants --add-panic-variants --wipe mysql +) \ No newline at end of file diff --git a/scripts/lint.sh b/scripts/lint.sh new file mode 100755 index 0000000..04ca4c6 --- /dev/null +++ b/scripts/lint.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +err=0 +trap 'err=1' ERR +# All the .go files, excluding vendor/ and model (auto generated) +GO_FILES=$(find . -iname '*.go' -type f | grep -v /vendor/ | grep -v /model/ | grep -v /swagger/ | grep -v /migration/) +( + GO111MODULE=off + go get -u golang.org/x/tools/cmd/goimports # Used in build script for generated files + go get -u golang.org/x/lint/golint # Linter + go get -u github.com/jgautheron/gocyclo # Check against high complexity + go get -u github.com/mdempsky/unconvert # Identifies unnecessary type conversions + go get -u github.com/kisielk/errcheck # Checks for unhandled errors + go get -u github.com/opennota/check/cmd/varcheck # Checks for unused vars + go get -u github.com/opennota/check/cmd/structcheck # Checks for unused fields in structs +) +echo "Running varcheck..." && varcheck $(go list ./... | grep -v /vendor/ | grep -v /model | grep -v /migration ) +echo "Running structcheck..." && structcheck $(go list ./... | grep -v /vendor/ | grep -v /model | grep -v /migration ) +# go vet is the official Go static analyzer +echo "Running go vet..." && go vet $(go list ./... | grep -v /vendor/ | grep -v /model | grep -v /migration ) +# checks for unhandled errors +echo "Running errcheck..." && errcheck $(go list ./... | grep -v /vendor/ | grep -v /model | grep -v /migration ) +# check for unnecessary conversions - ignore autogen code +echo "Running unconvert..." && unconvert -v $(go list ./... | grep -v /vendor/ | grep -v /model | grep -v /migration ) +# checks for function complexity, too big or too many returns ( 40 for now as to not get worse >> should be 19) +echo "Running gocyclo..." && gocyclo -ignore "_test" -avg -over 40 $GO_FILES + +######## COMMENTED BELOW UNTIL THEY ARE ALL FIXED ######## +# forbid code with huge functions +# "go vet on steroids" + linter - ignore autogen code +# one last linter - ignore autogen code +#echo "Running golint..." && golint -set_exit_status $(go list ./... | grep -v /vendor/ | grep -v /model/ | grep -v /migration ) +test $err = 0 # Return non-zero if any command failed \ No newline at end of file diff --git a/speech/speech.go b/speech/speech.go deleted file mode 100644 index dfd0797..0000000 --- a/speech/speech.go +++ /dev/null @@ -1,36 +0,0 @@ -package speech - -import ( - "database/sql" - "fmt" - "os" - - "github.com/lbryio/lbry.go/v2/extras/errors" - - _ "github.com/go-sql-driver/mysql" -) - -type Speech struct { - dbConn *sql.DB -} - -var instance *Speech - -func Init() (*Speech, error) { - if instance != nil { - return instance, nil - } - db, err := connect() - if err != nil { - return nil, err - } - instance = &Speech{ - dbConn: db, - } - return instance, nil -} - -func connect() (*sql.DB, error) { - db, err := sql.Open("mysql", fmt.Sprintf("lbry:%s@tcp(localhost)/lbry?parseTime=true", os.Getenv("MYSQL_LBRY_PASSWORD"))) - return db, errors.Err(err) -} diff --git a/sqlboiler.toml b/sqlboiler.toml new file mode 100644 index 0000000..afb7912 --- /dev/null +++ b/sqlboiler.toml @@ -0,0 +1,13 @@ +# this file is used for generating the models, not for connecting to the db +# so username/password are the local dev login, not the production login + +pkgname="model" +output="model" +[mysql] + blacklist=["gorp_migrations"] + dbname="voidwalker" + host="localhost" + port=3306 + user="voidwalker" + pass="voidwalker" + sslmode="false" \ No newline at end of file