commit
d609cc25d9
@ -0,0 +1,125 @@
|
|||||||
|
linters-settings:
|
||||||
|
depguard:
|
||||||
|
list-type: blacklist
|
||||||
|
packages:
|
||||||
|
# logging is allowed only by logutils.Log, logrus
|
||||||
|
# is allowed to use only in logutils package
|
||||||
|
- github.com/sirupsen/logrus
|
||||||
|
packages-with-error-message:
|
||||||
|
- github.com/sirupsen/logrus: "logging is allowed only by logutils.Log"
|
||||||
|
dupl:
|
||||||
|
threshold: 100
|
||||||
|
funlen:
|
||||||
|
lines: 100
|
||||||
|
statements: 50
|
||||||
|
goconst:
|
||||||
|
min-len: 2
|
||||||
|
min-occurrences: 2
|
||||||
|
gocritic:
|
||||||
|
enabled-tags:
|
||||||
|
- diagnostic
|
||||||
|
- experimental
|
||||||
|
- opinionated
|
||||||
|
- performance
|
||||||
|
- style
|
||||||
|
disabled-checks:
|
||||||
|
- dupImport # https://github.com/go-critic/go-critic/issues/845
|
||||||
|
- ifElseChain
|
||||||
|
- octalLiteral
|
||||||
|
- whyNoLint
|
||||||
|
- wrapperFunc
|
||||||
|
gocyclo:
|
||||||
|
min-complexity: 15
|
||||||
|
goimports:
|
||||||
|
local-prefixes: github.com/golangci/golangci-lint
|
||||||
|
golint:
|
||||||
|
min-confidence: 0
|
||||||
|
gomnd:
|
||||||
|
settings:
|
||||||
|
mnd:
|
||||||
|
# don't include the "operation" and "assign"
|
||||||
|
checks: argument,case,condition,return
|
||||||
|
govet:
|
||||||
|
check-shadowing: true
|
||||||
|
settings:
|
||||||
|
printf:
|
||||||
|
funcs:
|
||||||
|
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
|
||||||
|
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
||||||
|
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
||||||
|
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
||||||
|
lll:
|
||||||
|
line-length: 140
|
||||||
|
maligned:
|
||||||
|
suggest-new: true
|
||||||
|
misspell:
|
||||||
|
locale: US
|
||||||
|
|
||||||
|
linters:
|
||||||
|
# please, do not use `enable-all`: it's deprecated and will be removed soon.
|
||||||
|
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- bodyclose
|
||||||
|
- deadcode
|
||||||
|
- depguard
|
||||||
|
- dogsled
|
||||||
|
- dupl
|
||||||
|
- errcheck
|
||||||
|
- funlen
|
||||||
|
- gochecknoinits
|
||||||
|
- goconst
|
||||||
|
- gocritic
|
||||||
|
- gocyclo
|
||||||
|
- gofmt
|
||||||
|
- goimports
|
||||||
|
- golint
|
||||||
|
- gomnd
|
||||||
|
- goprintffuncname
|
||||||
|
- gosec
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- interfacer
|
||||||
|
- lll
|
||||||
|
- misspell
|
||||||
|
- nakedret
|
||||||
|
- rowserrcheck
|
||||||
|
- scopelint
|
||||||
|
- staticcheck
|
||||||
|
- structcheck
|
||||||
|
- stylecheck
|
||||||
|
- typecheck
|
||||||
|
- unconvert
|
||||||
|
- unparam
|
||||||
|
- unused
|
||||||
|
- varcheck
|
||||||
|
- whitespace
|
||||||
|
|
||||||
|
# don't enable:
|
||||||
|
# - gochecknoglobals
|
||||||
|
# - gocognit
|
||||||
|
# - godox
|
||||||
|
# - maligned
|
||||||
|
# - prealloc
|
||||||
|
|
||||||
|
issues:
|
||||||
|
# Excluding configuration per-path, per-linter, per-text and per-source
|
||||||
|
exclude-rules:
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- gomnd
|
||||||
|
|
||||||
|
run:
|
||||||
|
skip-dirs:
|
||||||
|
- test/testdata_etc
|
||||||
|
- internal/cache
|
||||||
|
- internal/renameio
|
||||||
|
- internal/robustio
|
||||||
|
|
||||||
|
# golangci.com configuration
|
||||||
|
# https://github.com/golangci/golangci/wiki/Configuration
|
||||||
|
service:
|
||||||
|
golangci-lint-version: 1.23.x # use the fixed version to not introduce new linters unexpectedly
|
||||||
|
prepare:
|
||||||
|
- echo "here I can run custom commands, but no preparation needed for this repo"
|
@ -0,0 +1,14 @@
|
|||||||
|
package captcha
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mojocn/base64Captcha"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Generate() (string, string, error) {
|
||||||
|
driver := base64Captcha.NewDriverDigit(80, 160, 4, 0.1, 4)
|
||||||
|
return base64Captcha.NewCaptcha(driver, base64Captcha.DefaultMemStore).Generate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Verify(id, code string) bool {
|
||||||
|
return base64Captcha.DefaultMemStore.Verify(id, code, true)
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha1"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go-openssl/v3"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SHA1 回傳sha1加密
|
||||||
|
func SHA1(v string) string {
|
||||||
|
h := sha1.New()
|
||||||
|
h.Write([]byte(v))
|
||||||
|
bs := h.Sum(nil)
|
||||||
|
return fmt.Sprintf("%x", bs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncryptPassword(pwd string) (string, error) {
|
||||||
|
hash, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(hash), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckPassword(pwd, hash string) error {
|
||||||
|
return bcrypt.CompareHashAndPassword([]byte(hash), []byte(pwd))
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecryptAES(value, key string) ([]byte, error) {
|
||||||
|
o := openssl.New()
|
||||||
|
|
||||||
|
dec, err := o.DecryptBytes(key, []byte(value), openssl.DigestMD5Sum)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return dec, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncryptAES(value, key string) ([]byte, error) {
|
||||||
|
o := openssl.New()
|
||||||
|
|
||||||
|
enc, err := o.EncryptBytes(key, []byte(value), openssl.DigestMD5Sum)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return enc, nil
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package generate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetRandomString 取得隨機字串
|
||||||
|
func GetRandomString(n int) (string, error) {
|
||||||
|
const alphaNum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
buffer := make([]byte, n)
|
||||||
|
max := big.NewInt(int64(len(alphaNum)))
|
||||||
|
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
index, err := randomInt(max)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[i] = alphaNum[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(buffer), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func randomInt(max *big.Int) (int, error) {
|
||||||
|
random, err := rand.Int(rand.Reader, max)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(random.Int64()), nil
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
module git.simts.cc/common/lib
|
||||||
|
|
||||||
|
go 1.14
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/Luzifer/go-openssl/v3 v3.1.0
|
||||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
|
github.com/mojocn/base64Captcha v1.3.1
|
||||||
|
go.uber.org/zap v1.15.0
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
||||||
|
)
|
@ -0,0 +1,68 @@
|
|||||||
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/Luzifer/go-openssl/v3 v3.1.0 h1:QqKqo6kYXGGUsvtUoCpRZm8lHw+jDfhbzr36gVj+/gw=
|
||||||
|
github.com/Luzifer/go-openssl/v3 v3.1.0/go.mod h1:liy3FXuuS8hfDlYh1T+l78AwQ/NjZflJz0NDvjKhwDs=
|
||||||
|
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/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||||
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||||
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
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=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/mojocn/base64Captcha v1.3.1 h1:2Wbkt8Oc8qjmNJ5GyOfSo4tgVQPsbKMftqASnq8GlT0=
|
||||||
|
github.com/mojocn/base64Captcha v1.3.1/go.mod h1:wAQCKEc5bDujxKRmbT6/vTnTt5CjStQ8bRfPWUuz/iY=
|
||||||
|
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
|
||||||
|
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
|
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
|
||||||
|
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||||
|
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
|
||||||
|
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||||
|
go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM=
|
||||||
|
go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
|
||||||
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75 h1:TbGuee8sSq15Iguxu4deQ7+Bqq/d2rsQejGcEtADAMQ=
|
||||||
|
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
|
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/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/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
|
||||||
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/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 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||||
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
@ -0,0 +1,89 @@
|
|||||||
|
package image
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"image/gif"
|
||||||
|
"image/jpeg"
|
||||||
|
"image/png"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"mime/multipart"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CompressImage(input interface{}, output string) (err error) {
|
||||||
|
var file io.Reader
|
||||||
|
switch input.(type) {
|
||||||
|
case string:
|
||||||
|
if file, err = os.Open(input.(string)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.(*os.File).Close()
|
||||||
|
defer os.Remove(input.(string))
|
||||||
|
|
||||||
|
case *multipart.FileHeader:
|
||||||
|
fileHeader := input.(*multipart.FileHeader)
|
||||||
|
file, err = fileHeader.Open()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.(multipart.File).Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
bs, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var ext string
|
||||||
|
if _, err = jpeg.Decode(bytes.NewReader(bs)); err == nil {
|
||||||
|
ext = "jpg"
|
||||||
|
} else if _, err = png.Decode(bytes.NewReader(bs)); err == nil {
|
||||||
|
ext = "png"
|
||||||
|
} else if _, err = gif.Decode(bytes.NewReader(bs)); err == nil {
|
||||||
|
ext = "gif"
|
||||||
|
}
|
||||||
|
|
||||||
|
outputFile, err := os.Create(output)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer outputFile.Close()
|
||||||
|
|
||||||
|
switch ext {
|
||||||
|
case "jpg":
|
||||||
|
img, err := jpeg.Decode(bytes.NewReader(bs))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = jpeg.Encode(outputFile, img, &jpeg.Options{Quality: 70}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
case "png":
|
||||||
|
img, err := png.Decode(bytes.NewReader(bs))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
encoder := png.Encoder{CompressionLevel: png.BestCompression}
|
||||||
|
if err = encoder.Encode(outputFile, img); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
case "gif":
|
||||||
|
img, err := gif.DecodeAll(bytes.NewReader(bs))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = gif.EncodeAll(outputFile, img); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if _, err = outputFile.Write(bs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package jwt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
. "git.simts.cc/common/lib/types"
|
||||||
|
|
||||||
|
"github.com/dgrijalva/jwt-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Encode jwt編碼
|
||||||
|
func Encode(values Data, key string) (string, error) {
|
||||||
|
claims := jwt.MapClaims{}
|
||||||
|
for key, value := range values {
|
||||||
|
claims[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenString, err := jwt.
|
||||||
|
NewWithClaims(jwt.SigningMethodHS256, claims).
|
||||||
|
SignedString([]byte(key))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tokenString, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode jwt解碼
|
||||||
|
func Decode(tokenString string, key string) (Data, error) {
|
||||||
|
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||||
|
return nil, fmt.Errorf("Unexpected error: %v. ", token.Header["alg"])
|
||||||
|
}
|
||||||
|
return []byte(key), nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
claims, ok := token.Claims.(jwt.MapClaims)
|
||||||
|
if !ok || !token.Valid {
|
||||||
|
return nil, fmt.Errorf("Token error. ")
|
||||||
|
}
|
||||||
|
|
||||||
|
return Data(claims), nil
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewLoggerProduction() (*zap.SugaredLogger, error) {
|
||||||
|
logger, err := zap.NewProduction()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return logger.Sugar(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLoggerDevelopment() (*zap.SugaredLogger, error) {
|
||||||
|
logger, err := zap.NewDevelopment()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return logger.Sugar(), nil
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package mail
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"net/smtp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Send(host string, port int, username, password, mailto, subject, content string) error {
|
||||||
|
conn, err := tls.Dial("tcp", fmt.Sprintf("%s:%d", host, port), &tls.Config{InsecureSkipVerify: true, ServerName: "smtp.gmail.com"})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := smtp.NewClient(conn, "smtp.gmail.com")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = client.Auth(smtp.PlainAuth("", username, password, host)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = client.Mail(username); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = client.Rcpt(mailto); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
w, err := client.Data()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
messages := []string{
|
||||||
|
"Content-Type: text/html; charset=\"UTF-8\";",
|
||||||
|
fmt.Sprintf("From: %s", username),
|
||||||
|
fmt.Sprintf("To: %s", mailto),
|
||||||
|
fmt.Sprintf("Subject: %s", subject),
|
||||||
|
content,
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = w.Write([]byte(strings.Join(messages, "\r\n"))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = w.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.Quit()
|
||||||
|
}
|
@ -0,0 +1,207 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrExistKey = errors.New("not exist.")
|
||||||
|
ErrFormat = errors.New("error format.")
|
||||||
|
)
|
||||||
|
|
||||||
|
type Data map[string]interface{}
|
||||||
|
|
||||||
|
func (data Data) Get(key string) (interface{}, error) {
|
||||||
|
value, exist := data[key]
|
||||||
|
if !exist {
|
||||||
|
return "", ErrExistKey
|
||||||
|
}
|
||||||
|
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data Data) GetString(key string) (string, error) {
|
||||||
|
value, err := data.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch value.(type) {
|
||||||
|
case string:
|
||||||
|
return value.(string), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", ErrFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data Data) GetSlice(key string) (res []interface{}, err error) {
|
||||||
|
value, err := data.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch value.(type) {
|
||||||
|
case []interface{}:
|
||||||
|
return value.([]interface{}), nil
|
||||||
|
default:
|
||||||
|
return nil, ErrFormat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data Data) GetStringSlice(key string) (res []string, err error) {
|
||||||
|
values, err := data.GetSlice(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range values {
|
||||||
|
switch v.(type) {
|
||||||
|
case string:
|
||||||
|
res = append(res, v.(string))
|
||||||
|
default:
|
||||||
|
return nil, ErrFormat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data Data) GetIntSlice(key string) (res []int, err error) {
|
||||||
|
values, err := data.GetSlice(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range values {
|
||||||
|
switch v.(type) {
|
||||||
|
case float64:
|
||||||
|
res = append(res, int(v.(float64)))
|
||||||
|
default:
|
||||||
|
return nil, ErrFormat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data Data) GetInt64(key string) (int64, error) {
|
||||||
|
value, err := data.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch value.(type) {
|
||||||
|
case int:
|
||||||
|
return int64(value.(int)), nil
|
||||||
|
|
||||||
|
case int64:
|
||||||
|
return value.(int64), nil
|
||||||
|
|
||||||
|
case float64:
|
||||||
|
return int64(value.(float64)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, ErrFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data Data) GetUint64(key string) (uint64, error) {
|
||||||
|
value, err := data.GetInt64(key)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if value < 0 {
|
||||||
|
return 0, ErrFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
return uint64(value), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data Data) GetInt(key string) (int, error) {
|
||||||
|
value, err := data.GetInt64(key)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(value), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data Data) GetUint(key string) (uint, error) {
|
||||||
|
value, err := data.GetInt64(key)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if value < 0 {
|
||||||
|
return 0, ErrFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
return uint(value), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data Data) GetInt16(key string) (int16, error) {
|
||||||
|
value, err := data.GetInt64(key)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return int16(value), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data Data) GetUint16(key string) (uint16, error) {
|
||||||
|
value, err := data.GetInt64(key)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if value < 0 {
|
||||||
|
return 0, ErrFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
return uint16(value), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data Data) GetInt8(key string) (int8, error) {
|
||||||
|
value, err := data.GetInt64(key)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return int8(value), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data Data) GetUint8(key string) (uint8, error) {
|
||||||
|
value, err := data.GetInt64(key)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if value < 0 {
|
||||||
|
return 0, ErrFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
return uint8(value), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data Data) GetBool(key string) (bool, error) {
|
||||||
|
value, err := data.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch value.(type) {
|
||||||
|
case bool:
|
||||||
|
return value.(bool), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, ErrFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
func (data Data) GetTimestamp(key string) (Timestamp, error) {
|
||||||
|
value, err := data.GetInt64(key)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Timestamp(value), nil
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
// Page 頁數
|
||||||
|
type Page struct {
|
||||||
|
Current, Size int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Page) Take() int {
|
||||||
|
return p.Size
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Page) Skip() int {
|
||||||
|
return (p.Current - 1) * p.Size
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 格式化
|
||||||
|
const (
|
||||||
|
FormatDatetime = "2006-01-02 15:04:05"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Local = time.Local
|
||||||
|
|
||||||
|
func SetLocation(name string) {
|
||||||
|
Local, _ = time.LoadLocation(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timestamp 時間戳
|
||||||
|
type Timestamp int
|
||||||
|
|
||||||
|
func GetUnixNow() Timestamp {
|
||||||
|
return Timestamp(time.Now().Unix())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Timestamp) Int64() int64 {
|
||||||
|
return int64(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Timestamp) Time() time.Time {
|
||||||
|
return time.Unix(t.Int64(), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Datetime 回傳時間字串
|
||||||
|
func (t Timestamp) Datetime() string {
|
||||||
|
return time.
|
||||||
|
Unix(t.Int64(), 0).
|
||||||
|
In(Local).
|
||||||
|
Format(FormatDatetime)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 與現在的時間差
|
||||||
|
func (t Timestamp) NowSub() time.Duration {
|
||||||
|
return time.Since(t.Time())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 時間差
|
||||||
|
func (t Timestamp) Sub(t2 time.Time) time.Duration {
|
||||||
|
return t2.Sub(t.Time())
|
||||||
|
}
|
Loading…
Reference in New Issue