diff --git a/code/rest/bridge_dao.go b/code/rest/bridge_dao.go index 2dda6b5..8c7ca39 100644 --- a/code/rest/bridge_dao.go +++ b/code/rest/bridge_dao.go @@ -4,9 +4,8 @@ import ( "github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/tool/builder" "github.com/eyebluecn/tank/code/tool/result" + "github.com/eyebluecn/tank/code/tool/uuid" "github.com/jinzhu/gorm" - - "github.com/nu7hatch/gouuid" "time" ) diff --git a/code/rest/dashboard_dao.go b/code/rest/dashboard_dao.go index 706aba2..572a427 100644 --- a/code/rest/dashboard_dao.go +++ b/code/rest/dashboard_dao.go @@ -3,8 +3,8 @@ package rest import ( "github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/tool/builder" + "github.com/eyebluecn/tank/code/tool/uuid" "github.com/jinzhu/gorm" - "github.com/nu7hatch/gouuid" "time" ) diff --git a/code/rest/download_token_dao.go b/code/rest/download_token_dao.go index 3e51d71..8b1cf0a 100644 --- a/code/rest/download_token_dao.go +++ b/code/rest/download_token_dao.go @@ -3,7 +3,7 @@ package rest import ( "github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/tool/result" - "github.com/nu7hatch/gouuid" + "github.com/eyebluecn/tank/code/tool/uuid" "time" ) diff --git a/code/rest/footprint_dao.go b/code/rest/footprint_dao.go index 64ab500..ca046ae 100644 --- a/code/rest/footprint_dao.go +++ b/code/rest/footprint_dao.go @@ -6,7 +6,7 @@ import ( "github.com/eyebluecn/tank/code/tool/result" "github.com/jinzhu/gorm" - "github.com/nu7hatch/gouuid" + "github.com/eyebluecn/tank/code/tool/uuid" "time" ) diff --git a/code/rest/image_cache_dao.go b/code/rest/image_cache_dao.go index a03b5c7..63192aa 100644 --- a/code/rest/image_cache_dao.go +++ b/code/rest/image_cache_dao.go @@ -6,8 +6,8 @@ import ( "github.com/eyebluecn/tank/code/tool/builder" "github.com/eyebluecn/tank/code/tool/result" "github.com/eyebluecn/tank/code/tool/util" + "github.com/eyebluecn/tank/code/tool/uuid" "github.com/jinzhu/gorm" - "github.com/nu7hatch/gouuid" "os" "path/filepath" "time" diff --git a/code/rest/install_controller.go b/code/rest/install_controller.go index ce541cb..1ea293b 100644 --- a/code/rest/install_controller.go +++ b/code/rest/install_controller.go @@ -7,8 +7,8 @@ import ( "github.com/eyebluecn/tank/code/tool/i18n" "github.com/eyebluecn/tank/code/tool/result" "github.com/eyebluecn/tank/code/tool/util" + "github.com/eyebluecn/tank/code/tool/uuid" "github.com/jinzhu/gorm" - "github.com/nu7hatch/gouuid" "net/http" "regexp" "strconv" diff --git a/code/rest/matter_dao.go b/code/rest/matter_dao.go index b26ba10..6468b9a 100644 --- a/code/rest/matter_dao.go +++ b/code/rest/matter_dao.go @@ -5,8 +5,8 @@ import ( "github.com/eyebluecn/tank/code/tool/builder" "github.com/eyebluecn/tank/code/tool/result" "github.com/eyebluecn/tank/code/tool/util" + "github.com/eyebluecn/tank/code/tool/uuid" "github.com/jinzhu/gorm" - "github.com/nu7hatch/gouuid" "os" "time" ) diff --git a/code/rest/preference_dao.go b/code/rest/preference_dao.go index 23f8660..7d3a0a4 100644 --- a/code/rest/preference_dao.go +++ b/code/rest/preference_dao.go @@ -3,7 +3,7 @@ package rest import ( "github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/tool/result" - "github.com/nu7hatch/gouuid" + "github.com/eyebluecn/tank/code/tool/uuid" "time" ) diff --git a/code/rest/session_dao.go b/code/rest/session_dao.go index 82f090f..3de9ab3 100644 --- a/code/rest/session_dao.go +++ b/code/rest/session_dao.go @@ -3,7 +3,7 @@ package rest import ( "github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/tool/result" - "github.com/nu7hatch/gouuid" + "github.com/eyebluecn/tank/code/tool/uuid" "time" ) diff --git a/code/rest/share_dao.go b/code/rest/share_dao.go index 2969c99..343a181 100644 --- a/code/rest/share_dao.go +++ b/code/rest/share_dao.go @@ -6,7 +6,7 @@ import ( "github.com/eyebluecn/tank/code/tool/result" "github.com/jinzhu/gorm" - "github.com/nu7hatch/gouuid" + "github.com/eyebluecn/tank/code/tool/uuid" "time" ) diff --git a/code/rest/upload_token_dao.go b/code/rest/upload_token_dao.go index a3641b3..3767f97 100644 --- a/code/rest/upload_token_dao.go +++ b/code/rest/upload_token_dao.go @@ -3,7 +3,7 @@ package rest import ( "github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/tool/result" - "github.com/nu7hatch/gouuid" + "github.com/eyebluecn/tank/code/tool/uuid" "time" ) diff --git a/code/rest/user_dao.go b/code/rest/user_dao.go index 5482f49..a9ab5ea 100644 --- a/code/rest/user_dao.go +++ b/code/rest/user_dao.go @@ -4,7 +4,7 @@ import ( "github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/tool/builder" "github.com/eyebluecn/tank/code/tool/result" - "github.com/nu7hatch/gouuid" + "github.com/eyebluecn/tank/code/tool/uuid" "time" ) diff --git a/code/rest/user_service.go b/code/rest/user_service.go index 641065b..6e05a08 100644 --- a/code/rest/user_service.go +++ b/code/rest/user_service.go @@ -5,7 +5,7 @@ import ( "github.com/eyebluecn/tank/code/tool/cache" "github.com/eyebluecn/tank/code/tool/result" "github.com/eyebluecn/tank/code/tool/util" - gouuid "github.com/nu7hatch/gouuid" + "github.com/eyebluecn/tank/code/tool/uuid" "net/http" "os" "time" @@ -169,7 +169,7 @@ func (this *UserService) PreHandle(writer http.ResponseWriter, request *http.Req } else { this.logger.Info("load a temp session by username and password.") - timeUUID, _ := gouuid.NewV4() + timeUUID, _ := uuid.NewV4() uuidStr := string(timeUUID.String()) request.Form[core.COOKIE_AUTH_KEY] = []string{uuidStr} diff --git a/code/tool/uuid/example_test.go b/code/tool/uuid/example_test.go new file mode 100644 index 0000000..e01597c --- /dev/null +++ b/code/tool/uuid/example_test.go @@ -0,0 +1,33 @@ +package uuid_test + +import ( + "fmt" + "github.com/eyebluecn/tank/code/tool/uuid" +) + +func ExampleNewV4() { + u4, err := uuid.NewV4() + if err != nil { + fmt.Println("error:", err) + return + } + fmt.Println(u4) +} + +func ExampleNewV5() { + u5, err := uuid.NewV5(uuid.NamespaceURL, []byte("nu7hat.ch")) + if err != nil { + fmt.Println("error:", err) + return + } + fmt.Println(u5) +} + +func ExampleParseHex() { + u, err := uuid.ParseHex("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + if err != nil { + fmt.Println("error:", err) + return + } + fmt.Println(u) +} diff --git a/code/tool/uuid/uuid.go b/code/tool/uuid/uuid.go new file mode 100644 index 0000000..ca960aa --- /dev/null +++ b/code/tool/uuid/uuid.go @@ -0,0 +1,173 @@ +// This package provides immutable UUID structs and the functions +// NewV3, NewV4, NewV5 and Parse() for generating versions 3, 4 +// and 5 UUIDs as specified in RFC 4122. +// +// Copyright (C) 2011 by Krzysztof Kowalik +package uuid + +import ( + "crypto/md5" + "crypto/rand" + "crypto/sha1" + "encoding/hex" + "errors" + "fmt" + "hash" + "regexp" +) + +// The UUID reserved variants. +const ( + ReservedNCS byte = 0x80 + ReservedRFC4122 byte = 0x40 + ReservedMicrosoft byte = 0x20 + ReservedFuture byte = 0x00 +) + +// The following standard UUIDs are for use with NewV3() or NewV5(). +var ( + NamespaceDNS, _ = ParseHex("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + NamespaceURL, _ = ParseHex("6ba7b811-9dad-11d1-80b4-00c04fd430c8") + NamespaceOID, _ = ParseHex("6ba7b812-9dad-11d1-80b4-00c04fd430c8") + NamespaceX500, _ = ParseHex("6ba7b814-9dad-11d1-80b4-00c04fd430c8") +) + +// Pattern used to parse hex string representation of the UUID. +// FIXME: do something to consider both brackets at one time, +// current one allows to parse string with only one opening +// or closing bracket. +const hexPattern = "^(urn\\:uuid\\:)?\\{?([a-z0-9]{8})-([a-z0-9]{4})-" + + "([1-5][a-z0-9]{3})-([a-z0-9]{4})-([a-z0-9]{12})\\}?$" + +var re = regexp.MustCompile(hexPattern) + +// A UUID representation compliant with specification in +// RFC 4122 document. +type UUID [16]byte + +// ParseHex creates a UUID object from given hex string +// representation. Function accepts UUID string in following +// formats: +// +// uuid.ParseHex("6ba7b814-9dad-11d1-80b4-00c04fd430c8") +// uuid.ParseHex("{6ba7b814-9dad-11d1-80b4-00c04fd430c8}") +// uuid.ParseHex("urn:uuid:6ba7b814-9dad-11d1-80b4-00c04fd430c8") +// +func ParseHex(s string) (u *UUID, err error) { + md := re.FindStringSubmatch(s) + if md == nil { + err = errors.New("Invalid UUID string") + return + } + hash := md[2] + md[3] + md[4] + md[5] + md[6] + b, err := hex.DecodeString(hash) + if err != nil { + return + } + u = new(UUID) + copy(u[:], b) + return +} + +// Parse creates a UUID object from given bytes slice. +func Parse(b []byte) (u *UUID, err error) { + if len(b) != 16 { + err = errors.New("Given slice is not valid UUID sequence") + return + } + u = new(UUID) + copy(u[:], b) + return +} + +// Generate a UUID based on the MD5 hash of a namespace identifier +// and a name. +func NewV3(ns *UUID, name []byte) (u *UUID, err error) { + if ns == nil { + err = errors.New("Invalid namespace UUID") + return + } + u = new(UUID) + // Set all bits to MD5 hash generated from namespace and name. + u.setBytesFromHash(md5.New(), ns[:], name) + u.setVariant(ReservedRFC4122) + u.setVersion(3) + return +} + +// Generate a random UUID. +func NewV4() (u *UUID, err error) { + u = new(UUID) + // Set all bits to randomly (or pseudo-randomly) chosen values. + _, err = rand.Read(u[:]) + if err != nil { + return + } + u.setVariant(ReservedRFC4122) + u.setVersion(4) + return +} + +// Generate a UUID based on the SHA-1 hash of a namespace identifier +// and a name. +func NewV5(ns *UUID, name []byte) (u *UUID, err error) { + u = new(UUID) + // Set all bits to truncated SHA1 hash generated from namespace + // and name. + u.setBytesFromHash(sha1.New(), ns[:], name) + u.setVariant(ReservedRFC4122) + u.setVersion(5) + return +} + +// Generate a MD5 hash of a namespace and a name, and copy it to the +// UUID slice. +func (u *UUID) setBytesFromHash(hash hash.Hash, ns, name []byte) { + hash.Write(ns[:]) + hash.Write(name) + copy(u[:], hash.Sum([]byte{})[:16]) +} + +// Set the two most significant bits (bits 6 and 7) of the +// clock_seq_hi_and_reserved to zero and one, respectively. +func (u *UUID) setVariant(v byte) { + switch v { + case ReservedNCS: + u[8] = (u[8] | ReservedNCS) & 0xBF + case ReservedRFC4122: + u[8] = (u[8] | ReservedRFC4122) & 0x7F + case ReservedMicrosoft: + u[8] = (u[8] | ReservedMicrosoft) & 0x3F + } +} + +// Variant returns the UUID Variant, which determines the internal +// layout of the UUID. This will be one of the constants: RESERVED_NCS, +// RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE. +func (u *UUID) Variant() byte { + if u[8]&ReservedNCS == ReservedNCS { + return ReservedNCS + } else if u[8]&ReservedRFC4122 == ReservedRFC4122 { + return ReservedRFC4122 + } else if u[8]&ReservedMicrosoft == ReservedMicrosoft { + return ReservedMicrosoft + } + return ReservedFuture +} + +// Set the four most significant bits (bits 12 through 15) of the +// time_hi_and_version field to the 4-bit version number. +func (u *UUID) setVersion(v byte) { + u[6] = (u[6] & 0xF) | (v << 4) +} + +// Version returns a version number of the algorithm used to +// generate the UUID sequence. +func (u *UUID) Version() uint { + return uint(u[6] >> 4) +} + +// Returns unparsed version of the generated UUID sequence. +func (u *UUID) String() string { + return fmt.Sprintf("%x-%x-%x-%x-%x", u[0:4], u[4:6], u[6:8], u[8:10], u[10:]) +} diff --git a/code/tool/uuid/uuid_test.go b/code/tool/uuid/uuid_test.go new file mode 100644 index 0000000..70ed346 --- /dev/null +++ b/code/tool/uuid/uuid_test.go @@ -0,0 +1,135 @@ +// This package provides immutable UUID structs and the functions +// NewV3, NewV4, NewV5 and Parse() for generating versions 3, 4 +// and 5 UUIDs as specified in RFC 4122. +// +// Copyright (C) 2011 by Krzysztof Kowalik +package uuid + +import ( + "regexp" + "testing" +) + +const format = "^[a-z0-9]{8}-[a-z0-9]{4}-[1-5][a-z0-9]{3}-[a-z0-9]{4}-[a-z0-9]{12}$" + +func TestParse(t *testing.T) { + _, err := Parse([]byte{1, 2, 3, 4, 5}) + if err == nil { + t.Errorf("Expected error due to invalid UUID sequence") + } + base, _ := NewV4() + u, err := Parse(base[:]) + if err != nil { + t.Errorf("Expected to parse UUID sequence without problems") + return + } + if u.String() != base.String() { + t.Errorf("Expected parsed UUID to be the same as base, %s != %s", u.String(), base.String()) + } +} + +func TestParseString(t *testing.T) { + _, err := ParseHex("foo") + if err == nil { + t.Errorf("Expected error due to invalid UUID string") + } + base, _ := NewV4() + u, err := ParseHex(base.String()) + if err != nil { + t.Errorf("Expected to parse UUID sequence without problems") + return + } + if u.String() != base.String() { + t.Errorf("Expected parsed UUID to be the same as base, %s != %s", u.String(), base.String()) + } +} + +func TestNewV3(t *testing.T) { + u, err := NewV3(NamespaceURL, []byte("golang.org")) + if err != nil { + t.Errorf("Expected to generate UUID without problems, error thrown: %d", err.Error()) + return + } + if u.Version() != 3 { + t.Errorf("Expected to generate UUIDv3, given %d", u.Version()) + } + if u.Variant() != ReservedRFC4122 { + t.Errorf("Expected to generate UUIDv3 RFC4122 variant, given %x", u.Variant()) + } + re := regexp.MustCompile(format) + if !re.MatchString(u.String()) { + t.Errorf("Expected string representation to be valid, given %s", u.String()) + } + u2, _ := NewV3(NamespaceURL, []byte("golang.org")) + if u2.String() != u.String() { + t.Errorf("Expected UUIDs generated of the same namespace and name to be the same") + } + u3, _ := NewV3(NamespaceDNS, []byte("golang.org")) + if u3.String() == u.String() { + t.Errorf("Expected UUIDs generated of different namespace and the same name to be different") + } + u4, _ := NewV3(NamespaceURL, []byte("code.google.com")) + if u4.String() == u.String() { + t.Errorf("Expected UUIDs generated of the same namespace and different names to be different") + } +} + +func TestNewV4(t *testing.T) { + u, err := NewV4() + if err != nil { + t.Errorf("Expected to generate UUID without problems, error thrown: %s", err.Error()) + return + } + if u.Version() != 4 { + t.Errorf("Expected to generate UUIDv4, given %d", u.Version()) + } + if u.Variant() != ReservedRFC4122 { + t.Errorf("Expected to generate UUIDv4 RFC4122 variant, given %x", u.Variant()) + } + re := regexp.MustCompile(format) + if !re.MatchString(u.String()) { + t.Errorf("Expected string representation to be valid, given %s", u.String()) + } +} + +func TestNewV5(t *testing.T) { + u, err := NewV5(NamespaceURL, []byte("golang.org")) + if err != nil { + t.Errorf("Expected to generate UUID without problems, error thrown: %d", err.Error()) + return + } + if u.Version() != 5 { + t.Errorf("Expected to generate UUIDv5, given %d", u.Version()) + } + if u.Variant() != ReservedRFC4122 { + t.Errorf("Expected to generate UUIDv5 RFC4122 variant, given %x", u.Variant()) + } + re := regexp.MustCompile(format) + if !re.MatchString(u.String()) { + t.Errorf("Expected string representation to be valid, given %s", u.String()) + } + u2, _ := NewV5(NamespaceURL, []byte("golang.org")) + if u2.String() != u.String() { + t.Errorf("Expected UUIDs generated of the same namespace and name to be the same") + } + u3, _ := NewV5(NamespaceDNS, []byte("golang.org")) + if u3.String() == u.String() { + t.Errorf("Expected UUIDs generated of different namespace and the same name to be different") + } + u4, _ := NewV5(NamespaceURL, []byte("code.google.com")) + if u4.String() == u.String() { + t.Errorf("Expected UUIDs generated of the same namespace and different names to be different") + } +} + +func BenchmarkParseHex(b *testing.B) { + s := "f3593cff-ee92-40df-4086-87825b523f13" + for i := 0; i < b.N; i++ { + _, err := ParseHex(s) + if err != nil { + b.Fatal(err) + } + } + b.StopTimer() + b.ReportAllocs() +} diff --git a/go.mod b/go.mod index 9f4697c..5396e15 100644 --- a/go.mod +++ b/go.mod @@ -5,14 +5,9 @@ go 1.14 require ( github.com/disintegration/imaging v1.6.2 github.com/go-sql-driver/mysql v1.5.0 - github.com/jinzhu/gorm v1.9.12 - github.com/json-iterator/go v1.1.9 - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect - github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d + github.com/jinzhu/gorm v1.9.14 + github.com/json-iterator/go v1.1.10 github.com/robfig/cron/v3 v3.0.1 - golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 - golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // indirect - golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 // indirect - golang.org/x/text v0.3.2 + golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 + golang.org/x/text v0.3.3 ) diff --git a/go.sum b/go.sum index e34605d..eefda03 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= +github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= 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= @@ -7,34 +9,27 @@ github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1 github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= -github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= -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/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q= -github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs= +github.com/jinzhu/gorm v1.9.14 h1:Kg3ShyTPcM6nzVo148fRrcMO6MNKuqtOUwnzqMgVniM= +github.com/jinzhu/gorm v1.9.14/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M= github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -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/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/mattn/go-sqlite3 v2.0.1+incompatible h1:xQ15muvnzGBHpIpdrNi1DA5x0+TcBZzsIDwmw9uTHzw= -github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA= +github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= +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/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ= -github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= 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/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= @@ -46,22 +41,20 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg= +golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200119044424-58c23975cae1 h1:5h3ngYt7+vXCDZCup/HkCQgW5XwmSvR/nA2JmJ0RErg= -golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= 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-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/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/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=