From 7833a2234caed86b849f53b009d2083f07303e27 Mon Sep 17 00:00:00 2001 From: kenneth <1185230223@qq.com> Date: Fri, 17 Sep 2021 11:16:38 +0800 Subject: [PATCH] commit --- .gitignore | 3 + go.mod | 28 +++ go.sum | 92 +++++++++ pkg/cache/manager.go | 17 ++ pkg/cache/memory_manager.go | 70 +++++++ pkg/cache/redis_manager.go | 135 ++++++++++++ pkg/ip2region/ip2Region.go | 349 ++++++++++++++++++++++++++++++++ pkg/ip2region/ip2Region_test.go | 49 +++++ pkg/token/jwt_maker.go | 62 ++++++ pkg/token/maker.go | 14 ++ pkg/token/paseto_maker.go | 56 +++++ pkg/token/payload.go | 46 +++++ pkg/util/cache.go | 33 +++ pkg/util/encrypt/aes.go | 75 +++++++ pkg/util/encrypt/base64.go | 15 ++ pkg/util/encrypt/des.go | 93 +++++++++ pkg/util/encrypt/md5.go | 27 +++ pkg/util/encrypt/rsa.go | 64 ++++++ pkg/util/encrypt/sha.go | 33 +++ pkg/util/fetcher.go | 195 ++++++++++++++++++ pkg/util/file.go | 34 ++++ pkg/util/location.go | 140 +++++++++++++ pkg/util/log.go | 33 +++ pkg/util/md5.go | 17 ++ pkg/util/pager.go | 20 ++ pkg/util/password.go | 21 ++ pkg/util/random.go | 51 +++++ pkg/util/string.go | 59 ++++++ 28 files changed, 1831 insertions(+) create mode 100644 go.mod create mode 100644 go.sum create mode 100644 pkg/cache/manager.go create mode 100644 pkg/cache/memory_manager.go create mode 100644 pkg/cache/redis_manager.go create mode 100644 pkg/ip2region/ip2Region.go create mode 100644 pkg/ip2region/ip2Region_test.go create mode 100644 pkg/token/jwt_maker.go create mode 100644 pkg/token/maker.go create mode 100644 pkg/token/paseto_maker.go create mode 100644 pkg/token/payload.go create mode 100644 pkg/util/cache.go create mode 100644 pkg/util/encrypt/aes.go create mode 100644 pkg/util/encrypt/base64.go create mode 100644 pkg/util/encrypt/des.go create mode 100644 pkg/util/encrypt/md5.go create mode 100644 pkg/util/encrypt/rsa.go create mode 100644 pkg/util/encrypt/sha.go create mode 100644 pkg/util/fetcher.go create mode 100644 pkg/util/file.go create mode 100644 pkg/util/location.go create mode 100644 pkg/util/log.go create mode 100644 pkg/util/md5.go create mode 100644 pkg/util/pager.go create mode 100644 pkg/util/password.go create mode 100644 pkg/util/random.go create mode 100644 pkg/util/string.go diff --git a/.gitignore b/.gitignore index 66fd13c..61aa98f 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ # Dependency directories (remove the comment below to include it) # vendor/ + +.vscode +.idea \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..75905f1 --- /dev/null +++ b/go.mod @@ -0,0 +1,28 @@ +module github.com/lyydhl-zhang/common-module + +go 1.17 + +require ( + github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect + github.com/aead/chacha20poly1305 v0.0.0-20201124145622-1a5aba2a8b29 // indirect + github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect + github.com/gomodule/redigo v1.8.5 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/matoous/go-nanoid v1.5.0 // indirect + github.com/natefinch/lumberjack v2.0.0+incompatible // indirect + github.com/o1egl/paseto v1.0.0 // indirect + github.com/patrickmn/go-cache v2.1.0+incompatible // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.7.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.7.0 // indirect + go.uber.org/zap v1.19.1 // indirect + golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 // indirect + golang.org/x/net v0.0.0-20210916014120-12bc252f5db8 // indirect + golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 // indirect + golang.org/x/text v0.3.7 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..420cb8d --- /dev/null +++ b/go.sum @@ -0,0 +1,92 @@ +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= +github.com/aead/chacha20poly1305 v0.0.0-20170617001512-233f39982aeb/go.mod h1:UzH9IX1MMqOcwhoNOIjmTQeAxrFgzs50j4golQtXXxU= +github.com/aead/chacha20poly1305 v0.0.0-20201124145622-1a5aba2a8b29 h1:1DcvRPZOdbQRg5nAHt2jrc5QbV0AGuhDdfQI6gXjiFE= +github.com/aead/chacha20poly1305 v0.0.0-20201124145622-1a5aba2a8b29/go.mod h1:UzH9IX1MMqOcwhoNOIjmTQeAxrFgzs50j4golQtXXxU= +github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw= +github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +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/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc= +github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/matoous/go-nanoid v1.5.0 h1:VRorl6uCngneC4oUQqOYtO3S0H5QKFtKuKycFG3euek= +github.com/matoous/go-nanoid v1.5.0/go.mod h1:zyD2a71IubI24efhpvkJz+ZwfwagzgSO6UNiFsZKN7U= +github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= +github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= +github.com/o1egl/paseto v1.0.0 h1:bwpvPu2au176w4IBlhbyUv/S5VPptERIA99Oap5qUd0= +github.com/o1egl/paseto v1.0.0/go.mod h1:5HxsZPmw/3RI2pAwGo1HhOOwSdvBpcuVzO7uDkm+CLU= +github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= +github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= +go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= +golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 h1:3erb+vDS8lU1sxfDHF4/hhWyaXnhIaO+7RgL4fDZORA= +golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210916014120-12bc252f5db8 h1:/6y1LfuqNuQdHAm0jjtPtgRcxIxjVZgm5OTu8/QhZvk= +golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 h1:7ZDGnxgHAMw7thfC5bEos0RDAccZKxioiWBhfIe+tvw= +golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +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-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +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/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/cache/manager.go b/pkg/cache/manager.go new file mode 100644 index 0000000..f4d0f00 --- /dev/null +++ b/pkg/cache/manager.go @@ -0,0 +1,17 @@ +package cache + +// Manager 管理缓存的接口定义 +type Manager interface { + // Set 设置缓存 + Set(key string, value interface{}) error + // SetDefault 设置缓存 + SetDefault(key string, value interface{}, expire int64) error + // Get 获取缓存 + Get(key string) (interface{}, error) + // GetString 获取缓存 + GetString(key string) (string, error) + // Exists key是否存在 + Exists(key string) bool + // Delete 删除key + Delete(key string) error +} diff --git a/pkg/cache/memory_manager.go b/pkg/cache/memory_manager.go new file mode 100644 index 0000000..33c6aa7 --- /dev/null +++ b/pkg/cache/memory_manager.go @@ -0,0 +1,70 @@ +package cache + +import ( + "errors" + "fmt" + "time" + + "github.com/patrickmn/go-cache" +) + +// MemoryManager memory缓存管理 +type MemoryManager struct { + cache *cache.Cache +} + +// NewMemoryManager 获取一个新的内存管理对象 +// defaultExpiration 缓存过期时间 +// cleanupInterval 缓存清理时间 +func NewMemoryManager(defaultExpiration, cleanupInterval time.Duration) Manager { + return &MemoryManager{cache: cache.New(defaultExpiration, cleanupInterval)} +} + +// Set 设置缓存 +// key 键 +// value 值 +func (manager *MemoryManager) Set(key string, value interface{}) error { + manager.cache.Set(key, value, time.Hour*24*365*100) // 10年 + return nil +} + +// SetDefault 设置缓存 +// key 键 +// value 值 +// expire 过期时间 (秒) +func (manager *MemoryManager) SetDefault(key string, value interface{}, expire int64) error { + manager.cache.Set(key, value, time.Second*time.Duration(expire)) + return nil +} + +// Get 获取缓存 +func (manager *MemoryManager) Get(key string) (interface{}, error) { + value, found := manager.cache.Get(key) + if found { + return value, nil + } + return nil, errors.New("no found data with key") +} + +// GetString 获取缓存 +func (manager *MemoryManager) GetString(key string) (string, error) { + value, found := manager.cache.Get(key) + if found { + return fmt.Sprintf("%v", value), nil + } + return "", errors.New("no found data with key") +} + +// Exists key是否存在 +func (manager *MemoryManager) Exists(key string) bool { + if _, found := manager.cache.Get(key); found { + return true + } + return false +} + +// Delete 删除key +func (manager *MemoryManager) Delete(key string) error { + manager.cache.Delete(key) + return nil +} diff --git a/pkg/cache/redis_manager.go b/pkg/cache/redis_manager.go new file mode 100644 index 0000000..4c608ea --- /dev/null +++ b/pkg/cache/redis_manager.go @@ -0,0 +1,135 @@ +package cache + +import ( + "fmt" + "time" + + "github.com/gomodule/redigo/redis" +) + +// RedisManager redis缓存管理 +type RedisManager struct { + pool *redis.Pool +} + +// NewRedisManager 获取一个新的redis管理对象 +func NewRedisManager(address string) Manager { + pool := &redis.Pool{ + // 连接方法 + Dial: func() (redis.Conn, error) { + c, err := redis.Dial("tcp", address) + if err != nil { + return nil, err + } + c.Do("SELECT", 0) + return c, nil + }, + //DialContext: nil, + //TestOnBorrow: nil, + MaxIdle: 10, // 最大的空闲连接数,表示即使没有redis连接时依然可以保持N个空闲的连接,而不被清除,随时处于待命状态。 + MaxActive: 10, // 最大的激活连接数,表示同时最多有N个连接 + IdleTimeout: 360 * time.Second, // 最大的空闲连接等待时间,超过此时间后,空闲连接将被关闭 + //Wait: false, + //MaxConnLifetime: 0, + } + return &RedisManager{pool} +} + +// Set 设置缓存 +// key 键 +// value 值 +func (manager *RedisManager) Set(key string, value interface{}) error { + conn := manager.pool.Get() + defer conn.Close() + + _, err := conn.Do("Set", key, value) + if err != nil { + return fmt.Errorf("set cache error: %v", err) + } + return nil +} + +// SetDefault 设置缓存 +// key 键 +// value 值 +// expire 过期时间 (秒) +func (manager *RedisManager) SetDefault(key string, value interface{}, expire int64) error { + conn := manager.pool.Get() + defer conn.Close() + + //_, err := conn.Do("set", key, value) + //if err != nil { + // return fmt.Errorf("set default cache error: %v", err) + //} + // + //// 设置过期时间 + //conn.Do("expire", key, expire) + //return nil + + _, err := conn.Do("set", key, value, "ex", expire) + if err != nil { + return fmt.Errorf("set default cache error: %v", err) + } + return nil +} + +// Get 获取缓存 +func (manager *RedisManager) Get(key string) (interface{}, error) { + conn := manager.pool.Get() + defer conn.Close() + + // 检查key是否存在 + exit, err := redis.Bool(conn.Do("exists", key)) + if err != nil || !exit { + return nil, fmt.Errorf("key is not exists") + } + + value, err := conn.Do("get", key) + if err != nil { + return nil, fmt.Errorf("get cache error: %v", err) + } + return value, nil +} + +// GetString 获取缓存 +func (manager *RedisManager) GetString(key string) (string, error) { + conn := manager.pool.Get() + defer conn.Close() + + // 检查key是否存在 + exit, err := redis.Bool(conn.Do("exists", key)) + if err != nil || !exit { + return "", fmt.Errorf("key is not exists") + } + + value, err := redis.String(conn.Do("get", key)) + if err != nil { + return "", fmt.Errorf("get cache error: %v", err) + } + return value, nil +} + +// Exists key是否存在 +func (manager *RedisManager) Exists(key string) bool { + conn := manager.pool.Get() + defer conn.Close() + + // 检查key是否存在 + exit, err := redis.Bool(conn.Do("expire", key)) + if err != nil { + return false + } + return exit +} + +// Delete 删除key +func (manager *RedisManager) Delete(key string) error { + conn := manager.pool.Get() + defer conn.Close() + + _, err := conn.Do("del", key) + if err != nil { + return fmt.Errorf("删除key:[%s]异常:%v", key, err) + } + return nil +} diff --git a/pkg/ip2region/ip2Region.go b/pkg/ip2region/ip2Region.go new file mode 100644 index 0000000..de32f83 --- /dev/null +++ b/pkg/ip2region/ip2Region.go @@ -0,0 +1,349 @@ +package ip2region + +import ( + "errors" + "io/ioutil" + "os" + "strconv" + "strings" +) + +const ( + INDEX_BLOCK_LENGTH = 12 + TOTAL_HEADER_LENGTH = 8192 +) + +var err error +var ipInfo IpInfo + +type Ip2Region struct { + // db file handler + dbFileHandler *os.File + + + //header block info + + headerSip []int64 + headerPtr []int64 + headerLen int64 + + // super block index info + firstIndexPtr int64 + lastIndexPtr int64 + totalBlocks int64 + + // for memory mode only + // the original db binary string + + dbBinStr []byte + dbFile string +} + +type IpInfo struct { + CityId int64 + Country string + Region string + Province string + City string + ISP string +} + +func (ip IpInfo)String() string { + return strconv.FormatInt(ip.CityId, 10) + "|" + ip.Country + "|" + ip.Region + "|" + ip.Province + "|" + ip.City + "|" + ip.ISP +} + +func getIpInfo(cityId int64, line []byte) IpInfo { + + lineSlice := strings.Split(string(line), "|") + ipInfo := IpInfo{} + length := len(lineSlice) + ipInfo.CityId = cityId + if length < 5 { + for i := 0; i <= 5 - length; i++ { + lineSlice = append(lineSlice, "") + } + } + + ipInfo.Country = lineSlice[0] + ipInfo.Region = lineSlice[1] + ipInfo.Province = lineSlice[2] + ipInfo.City = lineSlice[3] + ipInfo.ISP = lineSlice[4] + return ipInfo +} + +func New(path string) (*Ip2Region, error) { + + file, err := os.Open(path) + if err != nil { + return nil, err + } + + return &Ip2Region{ + dbFile:path, + dbFileHandler:file, + }, nil +} + +func (this *Ip2Region) Close() { + this.dbFileHandler.Close() +} + +func (this *Ip2Region) MemorySearch(ipStr string) (ipInfo IpInfo, err error) { + ipInfo = IpInfo{} + + if this.totalBlocks == 0 { + this.dbBinStr, err = ioutil.ReadFile(this.dbFile) + + if err != nil { + + return ipInfo, err + } + + this.firstIndexPtr = getLong(this.dbBinStr, 0) + this.lastIndexPtr = getLong(this.dbBinStr, 4) + this.totalBlocks = (this.lastIndexPtr - this.firstIndexPtr) /INDEX_BLOCK_LENGTH + 1 + } + + ip, err := ip2long(ipStr) + if err != nil { + return ipInfo, err + } + + h := this.totalBlocks + var dataPtr, l int64; + for (l <= h) { + + m := (l + h) >> 1 + p := this.firstIndexPtr + m *INDEX_BLOCK_LENGTH + sip := getLong(this.dbBinStr, p) + if ip < sip { + h = m - 1 + } else { + eip := getLong(this.dbBinStr, p + 4) + if ip > eip { + l = m + 1 + } else { + dataPtr = getLong(this.dbBinStr, p + 8) + break; + } + } + } + if dataPtr == 0 { + return ipInfo, errors.New("not found") + } + + dataLen := ((dataPtr >> 24) & 0xFF) + dataPtr = (dataPtr & 0x00FFFFFF); + ipInfo = getIpInfo(getLong(this.dbBinStr, dataPtr), this.dbBinStr[(dataPtr) + 4:dataPtr + dataLen]) + return ipInfo, nil + +} + +func (this *Ip2Region)BinarySearch(ipStr string) (ipInfo IpInfo, err error) { + ipInfo = IpInfo{} + if this.totalBlocks == 0 { + this.dbFileHandler.Seek(0, 0) + superBlock := make([]byte, 8) + this.dbFileHandler.Read(superBlock) + this.firstIndexPtr = getLong(superBlock, 0) + this.lastIndexPtr = getLong(superBlock, 4) + this.totalBlocks = (this.lastIndexPtr - this.firstIndexPtr) /INDEX_BLOCK_LENGTH + 1 + } + + var l, dataPtr, p int64 + + h := this.totalBlocks + + ip, err := ip2long(ipStr) + + if err != nil { + return + } + + for (l <= h) { + m := (l + h) >> 1 + + p = m * INDEX_BLOCK_LENGTH + + _, err = this.dbFileHandler.Seek(this.firstIndexPtr + p, 0) + if err != nil { + return + } + + buffer := make([]byte, INDEX_BLOCK_LENGTH) + _, err = this.dbFileHandler.Read(buffer) + + if err != nil { + + } + sip := getLong(buffer, 0) + if ip < sip { + h = m - 1 + } else { + eip := getLong(buffer, 4) + if ip > eip { + l = m + 1 + } else { + dataPtr = getLong(buffer, 8) + break; + } + } + + } + + if dataPtr == 0 { + err = errors.New("not found") + return + } + + dataLen := ((dataPtr >> 24) & 0xFF) + dataPtr = (dataPtr & 0x00FFFFFF); + + this.dbFileHandler.Seek(dataPtr, 0) + data := make([]byte, dataLen) + this.dbFileHandler.Read(data) + ipInfo = getIpInfo(getLong(data, 0), data[4:dataLen]) + err = nil + return +} + +func (this *Ip2Region) BtreeSearch(ipStr string) (ipInfo IpInfo, err error) { + ipInfo = IpInfo{} + ip, err := ip2long(ipStr) + + if this.headerLen == 0 { + this.dbFileHandler.Seek(8, 0) + + buffer := make([]byte, TOTAL_HEADER_LENGTH) + this.dbFileHandler.Read(buffer) + var idx int64; + for i := 0; i < TOTAL_HEADER_LENGTH; i += 8 { + startIp := getLong(buffer, int64(i)) + dataPar := getLong(buffer, int64(i + 4)) + if dataPar == 0 { + break + } + + this.headerSip = append(this.headerSip, startIp) + this.headerPtr = append(this.headerPtr, dataPar) + idx ++; + } + + this.headerLen = idx + } + + var l, sptr, eptr int64 + h := this.headerLen + + for l <= h { + m := int64(l + h) >> 1 + if m < this.headerLen { + if ip == this.headerSip[m] { + if m > 0 { + sptr = this.headerPtr[m - 1] + eptr = this.headerPtr[m] + } else { + sptr = this.headerPtr[m] + eptr = this.headerPtr[m + 1] + } + break + } + if ip < this.headerSip[m] { + if m == 0 { + sptr = this.headerPtr[m] + eptr = this.headerPtr[m + 1] + break + } else if ip > this.headerSip[m - 1] { + sptr = this.headerPtr[m - 1] + eptr = this.headerPtr[m] + break + } + h = m - 1 + } else { + if m == this.headerLen - 1 { + sptr = this.headerPtr[m - 1] + eptr = this.headerPtr[m] + break + } else if ip <= this.headerSip[m + 1] { + sptr = this.headerPtr[m ] + eptr = this.headerPtr[m + 1] + break + } + l = m + 1 + } + } + + } + + if sptr == 0 { + err = errors.New("not found") + return + } + + blockLen := eptr - sptr + this.dbFileHandler.Seek(sptr, 0) + index := make([]byte, blockLen +INDEX_BLOCK_LENGTH) + this.dbFileHandler.Read(index) + var dataptr int64 + h = blockLen / INDEX_BLOCK_LENGTH + l = 0 + + for l <= h { + m := int64(l + h) >> 1 + p := m * INDEX_BLOCK_LENGTH + sip := getLong(index, p) + if ip < sip { + h = m - 1; + } else { + eip := getLong(index, p + 4) + if ip > eip { + l = m + 1 + } else { + dataptr = getLong(index, p + 8) + break + } + } + } + + if dataptr == 0 { + err = errors.New("not found") + return + } + + dataLen := (dataptr >> 24) & 0xFF + dataPtr := dataptr & 0x00FFFFFF + + this.dbFileHandler.Seek(dataPtr, 0) + data := make([]byte, dataLen) + this.dbFileHandler.Read(data) + ipInfo = getIpInfo(getLong(data, 0), data[4:]) + return +} + +func getLong(b []byte, offset int64) int64 { + + val := (int64(b[offset ]) | + int64(b[offset + 1]) << 8 | + int64(b[offset + 2]) << 16 | + int64(b[offset + 3]) << 24) + + return val + +} + +func ip2long(IpStr string) (int64, error) { + bits := strings.Split(IpStr, ".") + if len(bits) != 4 { + return 0, errors.New("ip format error") + } + + var sum int64 + for i, n := range bits { + bit, _ := strconv.ParseInt(n, 10, 64) + sum += bit << uint(24 - 8 * i) + } + + return sum, nil +} + diff --git a/pkg/ip2region/ip2Region_test.go b/pkg/ip2region/ip2Region_test.go new file mode 100644 index 0000000..5fb717c --- /dev/null +++ b/pkg/ip2region/ip2Region_test.go @@ -0,0 +1,49 @@ +package ip2region + +import ( + "testing" +) + +func BenchmarkBtreeSearch(B *testing.B) { + region, err := New("../../data/ip2region.db ") + if err != nil { + B.Error(err) + } + for i:=0;i 20 { + pageSize = 20 + } + return pageSize +} diff --git a/pkg/util/password.go b/pkg/util/password.go new file mode 100644 index 0000000..8237e44 --- /dev/null +++ b/pkg/util/password.go @@ -0,0 +1,21 @@ +package util + +import ( + "fmt" + + "golang.org/x/crypto/bcrypt" +) + +// HashPassword returns the bcrypt hash of the password +func HashPassword(password string) (string, error) { + hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + if err != nil { + return "", fmt.Errorf("failed to hash password: %w", err) + } + return string(hashedPassword), nil +} + +// CheckPassword checks if the provided password is correct or not +func CheckPassword(password string, hashedPassword string) error { + return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)) +} diff --git a/pkg/util/random.go b/pkg/util/random.go new file mode 100644 index 0000000..e3477dc --- /dev/null +++ b/pkg/util/random.go @@ -0,0 +1,51 @@ +package util + +import ( + "fmt" + "math/rand" + "strings" + "time" + + gonanoid "github.com/matoous/go-nanoid" +) + +const alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + +func init() { + rand.Seed(time.Now().UnixNano()) +} + +func RandomString(n int) string { + var sb strings.Builder + k := len(alphabet) + + for i := 0; i < n; i++ { + c := alphabet[rand.Intn(k)] + sb.WriteByte(c) + } + + return sb.String() +} + +func RandomInt(n int) string { + var letters = []byte("0123456789") + result := make([]byte, n) + for i := range result { + result[i] = letters[rand.Intn(len(letters))] + } + return string(result) +} + +func RandomLevel() string { + levels := []string{"DEBUG", "INFO", "ERROR", "WARNING", "FAIL"} + n := len(levels) + return levels[rand.Intn(n)] +} + +func GenerateFilename() (string, error) { + filename, err := gonanoid.Nanoid() + if err != nil { + return "", fmt.Errorf("could not generate avatar filename: %v", err) + } + return filename, nil +} diff --git a/pkg/util/string.go b/pkg/util/string.go new file mode 100644 index 0000000..ef80aff --- /dev/null +++ b/pkg/util/string.go @@ -0,0 +1,59 @@ +package util + +import ( + "regexp" + "strconv" + "strings" +) + +func RemoveHTML(str string) string { + if len(str) > 0 { + //删除脚本 + reg := regexp.MustCompile(`([\r\n])[\s]+`) + str = reg.ReplaceAllString(str, "") + reg = regexp.MustCompile(`]*?>.*?`) + str = reg.ReplaceAllString(str, "") + //删除HTML + reg = regexp.MustCompile(`<(.[^>]*)>`) + str = reg.ReplaceAllString(str, "") + reg = regexp.MustCompile(`([\r\n])[\s]+`) + str = reg.ReplaceAllString(str, "") + reg = regexp.MustCompile(`-->`) + str = reg.ReplaceAllString(str, "") + reg = regexp.MustCompile(`