Compare commits

...

9 Commits

1
.gitignore vendored

@ -0,0 +1 @@
/.idea

@ -4,70 +4,103 @@ import (
"bytes" "bytes"
"crypto/aes" "crypto/aes"
"crypto/cipher" "crypto/cipher"
"fmt"
"github.com/Luzifer/go-openssl/v3" "github.com/Luzifer/go-openssl/v3"
) )
func paddingPKCS7(ciphertext []byte, blockSize int) []byte { func addPKCS7Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding) padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...) return append(ciphertext, padText...)
} }
func unpaddingPKCS7(origData []byte) []byte { func removePKCS7Padding(data []byte) ([]byte, error) {
length := len(origData) if len(data) == 0 {
unpadding := int(origData[length-1]) return nil, fmt.Errorf("data cannot be empty")
return origData[:(length - unpadding)] }
padding := int(data[len(data)-1])
if padding > len(data) {
return nil, fmt.Errorf("invalid padding size")
}
return data[:len(data)-padding], nil
} }
//EncryptAES 加密函式 // EncryptAES 加密函式
func EncryptAES(plaintext, key, iv []byte) ([]byte, error) { func EncryptAES(plaintext, key, iv []byte) ([]byte, error) {
// 驗證密鑰長度是否符合 AES 的要求
if len(key) != aes.BlockSize && len(key) != 16 && len(key) != 24 && len(key) != 32 {
return nil, fmt.Errorf("invalid key size: %d, expected 16, 24, or 32", len(key))
}
// 創建 AES 密碼器
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("failed to create AES cipher: %w", err)
} }
// 確保輸入的資料長度符合 block size並進行填充
blockSize := block.BlockSize() blockSize := block.BlockSize()
plaintext = paddingPKCS7(plaintext, blockSize) plaintext = addPKCS7Padding(plaintext, blockSize)
// 創建 CBC 模式加密器
blockMode := cipher.NewCBCEncrypter(block, iv) blockMode := cipher.NewCBCEncrypter(block, iv)
crypted := make([]byte, len(plaintext))
blockMode.CryptBlocks(crypted, plaintext) // 用來保存加密結果的緩衝區
return crypted, nil enc := make([]byte, len(plaintext))
blockMode.CryptBlocks(enc, plaintext)
return enc, nil
} }
// DecryptAES 解密函式 // DecryptAES 使用 AES CBC 模式進行解密
func DecryptAES(ciphertext, key, iv []byte) ([]byte, error) { func DecryptAES(ciphertext, key, iv []byte) ([]byte, error) {
// 驗證密鑰長度是否符合 AES 的要求
if len(key) != aes.BlockSize && len(key) != 16 && len(key) != 24 && len(key) != 32 {
return nil, fmt.Errorf("invalid key size: %d, expected 16, 24, or 32", len(key))
}
// 創建 AES 密碼器
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("failed to create AES cipher: %w", err)
} }
// 確保輸入的資料長度符合 block size並進行解密
blockSize := block.BlockSize() blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, iv[:blockSize]) blockMode := cipher.NewCBCDecrypter(block, iv[:blockSize])
// 用來保存解密結果的緩衝區
origData := make([]byte, len(ciphertext)) origData := make([]byte, len(ciphertext))
blockMode.CryptBlocks(origData, ciphertext) blockMode.CryptBlocks(origData, ciphertext)
origData = unpaddingPKCS7(origData)
return origData, nil // 去除 PKCS7 填充
return removePKCS7Padding(origData)
} }
// DecryptAESWithOpenSSL 使用Openssl 解密AES // EncryptAESWithOpenSSL 使用Openssl 加密AES
func DecryptAESWithOpenSSL(value, key string) ([]byte, error) { func EncryptAESWithOpenSSL(value, key string) ([]byte, error) {
o := openssl.New() o := openssl.New()
dec, err := o.DecryptBytes(key, []byte(value), openssl.DigestMD5Sum) enc, err := o.EncryptBytes(key, []byte(value), openssl.DigestMD5Sum)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("failed to encrypt with OpenSSL: %w", err)
} }
return dec, nil return enc, nil
} }
// EncryptAESWithOpenSSL 使用Openssl 加密AES // DecryptAESWithOpenSSL 使用Openssl 解密AES
func EncryptAESWithOpenSSL(value, key string) ([]byte, error) { func DecryptAESWithOpenSSL(value, key string) ([]byte, error) {
o := openssl.New() o := openssl.New()
enc, err := o.EncryptBytes(key, []byte(value), openssl.DigestMD5Sum) dec, err := o.DecryptBytes(key, []byte(value), openssl.DigestMD5Sum)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("failed to decrypt with OpenSSL: %w", err)
} }
return enc, nil return dec, nil
} }

@ -9,24 +9,15 @@ import (
// MD5 回傳md5加密 // MD5 回傳md5加密
func MD5(v string) string { func MD5(v string) string {
h := md5.New() return fmt.Sprintf("%x", md5.Sum([]byte(v)))
h.Write([]byte(v))
bs := h.Sum(nil)
return fmt.Sprintf("%x", bs)
} }
// SHA1 回傳sha1加密 // SHA1 回傳sha1加密
func SHA1(v string) string { func SHA1(v string) string {
h := sha1.New() return fmt.Sprintf("%x", sha1.Sum([]byte(v)))
h.Write([]byte(v))
bs := h.Sum(nil)
return fmt.Sprintf("%x", bs)
} }
// SHA256 回傳sha256加密 // SHA256 回傳sha256加密
func SHA256(v string) string { func SHA256(v string) string {
h := sha256.New() return fmt.Sprintf("%x", sha256.Sum256([]byte(v)))
h.Write([]byte(v))
bs := h.Sum(nil)
return fmt.Sprintf("%x", bs)
} }

@ -1,6 +1,8 @@
package crypto package crypto
import ( import (
"fmt"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )
@ -8,7 +10,7 @@ import (
func EncryptPassword(pwd string) (string, error) { func EncryptPassword(pwd string) (string, error) {
hash, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost) hash, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost)
if err != nil { if err != nil {
return "", err return "", fmt.Errorf("failed to encrypt password: %w", err)
} }
return string(hash), nil return string(hash), nil
@ -16,5 +18,12 @@ func EncryptPassword(pwd string) (string, error) {
// CheckPassword 檢查密碼 // CheckPassword 檢查密碼
func CheckPassword(pwd, hash string) error { func CheckPassword(pwd, hash string) error {
return bcrypt.CompareHashAndPassword([]byte(hash), []byte(pwd)) err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(pwd))
if err != nil {
// 返回帶有更多上下文信息的錯誤
return fmt.Errorf("password does not match: %w", err)
}
// 如果密碼正確,返回 nil
return nil
} }

@ -6,19 +6,20 @@ import (
"crypto/x509" "crypto/x509"
"encoding/pem" "encoding/pem"
"errors" "errors"
"fmt"
) )
func NewKeyRSA(bitSize int) (pubPEM []byte, keyPEM []byte, err error) { func NewKeyRSA(bitSize int) (pubPEM []byte, keyPEM []byte, err error) {
// Generate RSA key. // 生成 RSA 密鑰對
key, err := rsa.GenerateKey(rand.Reader, bitSize) key, err := rsa.GenerateKey(rand.Reader, bitSize)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, fmt.Errorf("failed to generate RSA key: %w", err)
} }
// Extract public component. // 提取公鑰部分並轉換為 PEM 格式
pubBytes, err := x509.MarshalPKIXPublicKey(key.Public()) pubBytes, err := x509.MarshalPKIXPublicKey(key.Public())
if err != nil { if err != nil {
return nil, nil, err return nil, nil, fmt.Errorf("failed to marshal public key: %w", err)
} }
pubPEM = pem.EncodeToMemory( pubPEM = pem.EncodeToMemory(
&pem.Block{ &pem.Block{
@ -27,7 +28,7 @@ func NewKeyRSA(bitSize int) (pubPEM []byte, keyPEM []byte, err error) {
}, },
) )
// Encode private key to PKCS#1 ASN.1 PEM. // 編碼私鑰為 PKCS#1 ASN.1 PEM 格式
keyPEM = pem.EncodeToMemory( keyPEM = pem.EncodeToMemory(
&pem.Block{ &pem.Block{
Type: "RSA PRIVATE KEY", Type: "RSA PRIVATE KEY",
@ -42,29 +43,44 @@ func NewKeyRSA(bitSize int) (pubPEM []byte, keyPEM []byte, err error) {
func EncryptRSA(value, publicKey []byte) ([]byte, error) { func EncryptRSA(value, publicKey []byte) ([]byte, error) {
block, _ := pem.Decode(publicKey) block, _ := pem.Decode(publicKey)
if block == nil { if block == nil {
return nil, errors.New("public key error") return nil, errors.New("failed to decode public key PEM")
} }
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes) pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("failed to parse public key: %w", err)
} }
pub := pubInterface.(*rsa.PublicKey) pub, ok := pubInterface.(*rsa.PublicKey)
return rsa.EncryptPKCS1v15(rand.Reader, pub, value) if !ok {
return nil, errors.New("invalid public key type")
}
// 使用公鑰進行加密
enc, err := rsa.EncryptPKCS1v15(rand.Reader, pub, value)
if err != nil {
return nil, fmt.Errorf("failed to encrypt with RSA: %w", err)
}
return enc, nil
} }
// DecryptRSA rsa解密 // DecryptRSA rsa解密
func DecryptRSA(ciphertext, privateKey []byte) ([]byte, error) { func DecryptRSA(ciphertext, privateKey []byte) ([]byte, error) {
block, _ := pem.Decode(privateKey) block, _ := pem.Decode(privateKey)
if block == nil { if block == nil {
return nil, errors.New("private key error") return nil, errors.New("failed to decode private key PEM")
} }
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("failed to parse private key: %w", err)
}
dec, err := rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
if err != nil {
return nil, fmt.Errorf("failed to decrypt with RSA: %w", err)
} }
return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext) return dec, nil
} }

@ -2,52 +2,37 @@ package generate
import ( import (
"crypto/rand" "crypto/rand"
"math/big" "fmt"
) )
// GetRandomString 取得隨機字串 // GetRandomString 取得隨機字串
func GetRandomString(n int) (string, error) { func GetRandomString(n int) (string, error) {
const alphaNum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" const alphaNum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
return getRandomFromCharset(n, alphaNum)
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
} }
// GetRandomKey 取得隨機金鑰 // GetRandomKey 取得隨機金鑰
func GetRandomKey(n int) (string, error) { func GetRandomKey(n int) (string, error) {
const alphaNum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@#$%^&*()-_=+" const alphaNum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@#$%^&*()-_=+"
return getRandomFromCharset(n, alphaNum)
}
// getRandomFromCharset 通用隨機字串生成器
func getRandomFromCharset(n int, charset string) (string, error) {
// 預先計算字符集的長度
charsLen := len(charset)
buffer := make([]byte, n) buffer := make([]byte, n)
max := big.NewInt(int64(len(alphaNum)))
for i := 0; i < n; i++ { // 使用 crypto/rand 生成隨機數據
index, err := randomInt(max) _, err := rand.Read(buffer)
if err != nil { if err != nil {
return "", err return "", fmt.Errorf("failed to generate random data: %w", err)
}
buffer[i] = alphaNum[index]
} }
return string(buffer), nil // 從字元集選擇字符
} for i := 0; i < n; i++ {
buffer[i] = charset[int(buffer[i])%charsLen]
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 return string(buffer), nil
} }

@ -1,18 +1,18 @@
module git.simts.cc/common/lib module git.simts.cc/common/lib
go 1.17 go 1.19
require ( require (
github.com/Luzifer/go-openssl/v3 v3.1.0 github.com/Luzifer/go-openssl/v3 v3.1.0
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/golang-jwt/jwt/v5 v5.0.0-rc.2
github.com/mojocn/base64Captcha v1.3.1 github.com/mojocn/base64Captcha v1.3.1
go.uber.org/zap v1.15.0 go.uber.org/zap v1.15.0
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 golang.org/x/crypto v0.8.0
) )
require ( require (
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
go.uber.org/atomic v1.6.0 // indirect go.uber.org/atomic v1.6.0 // indirect
go.uber.org/multierr v1.5.0 // indirect go.uber.org/multierr v1.5.0 // indirect
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75 // indirect golang.org/x/image v0.7.0 // indirect
) )

@ -5,8 +5,8 @@ github.com/Luzifer/go-openssl/v3 v3.1.0/go.mod h1:liy3FXuuS8hfDlYh1T+l78AwQ/NjZf
github.com/davecgh/go-spew v1.1.0/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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/golang-jwt/jwt/v5 v5.0.0-rc.2 h1:hXPcSazn8wKOfSb9y2m1bdgUMlDxVDarxh3lJVbC6JE=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/golang-jwt/jwt/v5 v5.0.0-rc.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= 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/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/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
@ -25,6 +25,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 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 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 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 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
@ -35,25 +36,52 @@ go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM=
go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= 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-20190308221718-c2843e01d9a2/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75 h1:TbGuee8sSq15Iguxu4deQ7+Bqq/d2rsQejGcEtADAMQ= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.7.0 h1:gzS29xtG1J5ybQlv0PuyfE3nmc6R4qB73m6LUUmvFuw=
golang.org/x/image v0.7.0/go.mod h1:nd/q4ef1AKKYl/4kft7g+6UyGbdiqWqTP1ZAbRoV7Rg=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= 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/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.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 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-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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/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-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-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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
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-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-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-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/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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 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-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

@ -6,7 +6,6 @@ import (
"image/jpeg" "image/jpeg"
"image/png" "image/png"
"io" "io"
"io/ioutil"
"mime/multipart" "mime/multipart"
"os" "os"
) )
@ -14,31 +13,42 @@ import (
// CompressImage 壓縮圖片至指定位置 // CompressImage 壓縮圖片至指定位置
func CompressImage(input interface{}, output string) (err error) { func CompressImage(input interface{}, output string) (err error) {
var file io.Reader var file io.Reader
switch input.(type) { var fileToClose io.Closer
switch v := input.(type) {
case string: case string:
if file, err = os.Open(input.(string)); err != nil { f, err := os.Open(v)
if err != nil {
return err return err
} }
file = f
fileToClose = f
defer func() { defer func() {
_ = file.(*os.File).Close() if fileToClose != nil {
_ = fileToClose.Close()
}
_ = os.Remove(v)
}() }()
defer os.Remove(input.(string))
case *multipart.FileHeader: case *multipart.FileHeader:
fileHeader := input.(*multipart.FileHeader) f, err := v.Open()
file, err = fileHeader.Open()
if err != nil { if err != nil {
return err return err
} }
file = f
fileToClose = f
defer func() { defer func() {
_ = file.(multipart.File).Close() if fileToClose != nil {
_ = fileToClose.Close()
}
}() }()
} }
bs, err := ioutil.ReadAll(file) var buf bytes.Buffer
if err != nil { if _, err = io.Copy(&buf, file); err != nil {
return err return err
} }
bs := buf.Bytes()
var ext string var ext string
if _, err = jpeg.Decode(bytes.NewReader(bs)); err == nil { if _, err = jpeg.Decode(bytes.NewReader(bs)); err == nil {
@ -53,7 +63,11 @@ func CompressImage(input interface{}, output string) (err error) {
if err != nil { if err != nil {
return err return err
} }
defer outputFile.Close() defer func() {
if outputFile != nil {
_ = outputFile.Close()
}
}()
switch ext { switch ext {
case "jpg": case "jpg":
@ -61,34 +75,22 @@ func CompressImage(input interface{}, output string) (err error) {
if err != nil { if err != nil {
return err return err
} }
if err = jpeg.Encode(outputFile, img, &jpeg.Options{Quality: 70}); err != nil { return jpeg.Encode(outputFile, img, &jpeg.Options{Quality: 70})
return err
}
case "png": case "png":
img, err := png.Decode(bytes.NewReader(bs)) img, err := png.Decode(bytes.NewReader(bs))
if err != nil { if err != nil {
return err return err
} }
encoder := png.Encoder{CompressionLevel: png.BestCompression} encoder := png.Encoder{CompressionLevel: png.BestCompression}
if err = encoder.Encode(outputFile, img); err != nil { return encoder.Encode(outputFile, img)
return err
}
case "gif": case "gif":
img, err := gif.DecodeAll(bytes.NewReader(bs)) img, err := gif.DecodeAll(bytes.NewReader(bs))
if err != nil { if err != nil {
return err return err
} }
if err = gif.EncodeAll(outputFile, img); err != nil { return gif.EncodeAll(outputFile, img)
return err
}
default: default:
if _, err = outputFile.Write(bs); err != nil { _, err = outputFile.Write(bs)
return err return err
}
} }
return nil
} }

@ -2,25 +2,24 @@ package jwt
import ( import (
"crypto/rsa" "crypto/rsa"
"errors"
"fmt" "fmt"
"git.simts.cc/common/lib/types" "git.simts.cc/common/lib/types"
"github.com/golang-jwt/jwt/v5"
"github.com/dgrijalva/jwt-go"
) )
// Encode jwt編碼 // Encode jwt編碼
func Encode(values types.Data, key string) (string, error) { func Encode(values types.Data, key string) (string, error) {
claims := jwt.MapClaims{} claims := jwt.MapClaims{}
for key, value := range values { for k, v := range values {
claims[key] = value claims[k] = v
} }
tokenString, err := jwt. tokenString, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).
NewWithClaims(jwt.SigningMethodHS256, claims).
SignedString([]byte(key)) SignedString([]byte(key))
if err != nil { if err != nil {
return "", err return "", fmt.Errorf("failed to sign JWT with HS256: %w", err)
} }
return tokenString, nil return tokenString, nil
@ -29,15 +28,14 @@ func Encode(values types.Data, key string) (string, error) {
// EncodeRS256 jwt編碼 // EncodeRS256 jwt編碼
func EncodeRS256(values types.Data, key *rsa.PrivateKey) (string, error) { func EncodeRS256(values types.Data, key *rsa.PrivateKey) (string, error) {
claims := jwt.MapClaims{} claims := jwt.MapClaims{}
for key, value := range values { for k, v := range values {
claims[key] = value claims[k] = v
} }
tokenString, err := jwt. tokenString, err := jwt.NewWithClaims(jwt.SigningMethodRS256, claims).
NewWithClaims(jwt.SigningMethodRS256, claims).
SignedString(key) SignedString(key)
if err != nil { if err != nil {
return "", err return "", fmt.Errorf("failed to sign JWT with RS256: %w", err)
} }
return tokenString, nil return tokenString, nil
@ -47,18 +45,27 @@ func EncodeRS256(values types.Data, key *rsa.PrivateKey) (string, error) {
func Decode(tokenString string, key string) (types.Data, error) { func Decode(tokenString string, key string) (types.Data, error) {
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected error: %v. ", token.Header["alg"]) return nil, fmt.Errorf("unexpected signing method: %w", token.Header["alg"])
} }
return []byte(key), nil return []byte(key), nil
}) })
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("failed to parse JWT: %w", err)
}
if token == nil || !token.Valid {
return nil, fmt.Errorf("invalid token or claims")
} }
claims, ok := token.Claims.(jwt.MapClaims) claims, ok := token.Claims.(jwt.MapClaims)
if !ok || !token.Valid { if !ok {
return nil, fmt.Errorf("Token error. ") return nil, fmt.Errorf("failed to parse token claims")
} }
return types.Data(claims), nil return types.Data(claims), nil
} }
// IsExpired 檢查 token 是否過期
func IsExpired(err error) bool {
return errors.Is(err, jwt.ErrTokenExpired)
}

@ -1,25 +0,0 @@
package logger
import (
"go.uber.org/zap"
)
// NewLoggerProduction 正式版紀錄
func NewLoggerProduction() (*zap.SugaredLogger, error) {
logger, err := zap.NewProduction()
if err != nil {
return nil, err
}
return logger.Sugar(), nil
}
// NewLoggerDevelopment 開發版紀錄
func NewLoggerDevelopment() (*zap.SugaredLogger, error) {
logger, err := zap.NewDevelopment()
if err != nil {
return nil, err
}
return logger.Sugar(), nil
}

@ -24,73 +24,48 @@ func (data Data) Get(key string) (interface{}, error) {
return value, nil return value, nil
} }
// GetString 取得字串 // GetSlice 取得切片
func (data Data) GetString(key string) (string, error) { func (data Data) GetSlice(key string) (res Slice, err error) {
value, err := data.Get(key)
if err != nil {
return "", err
}
switch value := value.(type) {
case []byte:
return string(value), nil
case string:
return value, nil
default:
return "", ErrFormat
}
}
// MustGetString 強制取得字串
func (data Data) MustGetString(key string) string {
value, _ := data.GetString(key)
return value
}
// GetBytes 取得字串
func (data Data) GetBytes(key string) ([]byte, error) {
value, err := data.Get(key) value, err := data.Get(key)
if err != nil { if err != nil {
return nil, err return nil, err
} }
switch value := value.(type) { switch v := value.(type) {
case []byte: case []interface{}:
return value, nil return v, nil
case string:
return []byte(value), nil
default: default:
return nil, ErrFormat return nil, ErrFormat
} }
} }
// MustGetBytes 強制取得字串 // MustGetSlice 強制取得切片
func (data Data) MustGetBytes(key string) []byte { func (data Data) MustGetSlice(key string) Slice {
value, _ := data.GetBytes(key) values, _ := data.GetSlice(key)
return value return values
} }
// GetSlice 取得切片 // GetString 取得字串
func (data Data) GetSlice(key string) (res Slice, err error) { func (data Data) GetString(key string) (string, error) {
value, err := data.Get(key) value, err := data.Get(key)
if err != nil { if err != nil {
return nil, err return "", err
} }
switch value := value.(type) { switch value := value.(type) {
case []interface{}: case []byte:
return Slice(value), nil return string(value), nil
case Slice: case string:
return value, nil return value, nil
default: default:
return nil, ErrFormat return "", ErrFormat
} }
} }
// MustGetSlice 強制取得切片 // MustGetString 強制取得字串
func (data Data) MustGetSlice(key string) Slice { func (data Data) MustGetString(key string) string {
values, _ := data.GetSlice(key) value, _ := data.GetString(key)
return values return value
} }
// GetStringSlice 取得字串切片 // GetStringSlice 取得字串切片
@ -118,51 +93,27 @@ func (data Data) MustGetStringSlice(key string) []string {
return values return values
} }
// GetIntSlice 取得整數切片 // GetBytes 取得字串
func (data Data) GetIntSlice(key string) (res []int, err error) { func (data Data) GetBytes(key string) ([]byte, error) {
values, err := data.GetSlice(key) value, err := data.Get(key)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, v := range values { switch value := value.(type) {
switch v := v.(type) { case []byte:
case int: return value, nil
res = append(res, int(v)) case string:
case uint: return []byte(value), nil
res = append(res, int(v)) default:
case int8: return nil, ErrFormat
res = append(res, int(v))
case uint8:
res = append(res, int(v))
case int16:
res = append(res, int(v))
case uint16:
res = append(res, int(v))
case int32:
res = append(res, int(v))
case uint32:
res = append(res, int(v))
case int64:
res = append(res, int(v))
case uint64:
res = append(res, int(v))
case float32:
res = append(res, int(v))
case float64:
res = append(res, int(v))
default:
return nil, ErrFormat
}
} }
return res, nil
} }
// MustGetIntSlice 強制取得整數切片 // MustGetBytes 強制取得字串
func (data Data) MustGetIntSlice(key string) []int { func (data Data) MustGetBytes(key string) []byte {
values, _ := data.GetIntSlice(key) value, _ := data.GetBytes(key)
return values return value
} }
// GetData 取得資料 // GetData 取得資料
@ -172,11 +123,9 @@ func (data Data) GetData(key string) (Data, error) {
return nil, err return nil, err
} }
switch value := value.(type) { switch v := value.(type) {
case map[string]interface{}: case map[string]interface{}:
return Data(value), nil return v, nil
case Data:
return value, nil
default: default:
return nil, ErrFormat return nil, ErrFormat
} }
@ -195,17 +144,17 @@ func (data Data) GetDataSlice(key string) ([]Data, error) {
return nil, err return nil, err
} }
var vals []Data var list []Data
for _, v := range values { for _, value := range values {
switch v := v.(type) { switch v := value.(type) {
case map[string]interface{}: case map[string]interface{}:
vals = append(vals, Data(v)) list = append(list, v)
default: default:
return nil, ErrFormat return nil, ErrFormat
} }
} }
return vals, nil return list, nil
} }
// MustGetDataSlice 強制取得資料切片 // MustGetDataSlice 強制取得資料切片
@ -237,6 +186,53 @@ func (data Data) MustGetFloat64(key string) float64 {
return value return value
} }
// GetFloat64Slice 取得64位元浮點數切片
func (data Data) GetFloat64Slice(key string) (res []float64, err error) {
values, err := data.GetSlice(key)
if err != nil {
return nil, err
}
for _, v := range values {
switch v := v.(type) {
case int:
res = append(res, float64(v))
case uint:
res = append(res, float64(v))
case int8:
res = append(res, float64(v))
case uint8:
res = append(res, float64(v))
case int16:
res = append(res, float64(v))
case uint16:
res = append(res, float64(v))
case int32:
res = append(res, float64(v))
case uint32:
res = append(res, float64(v))
case int64:
res = append(res, float64(v))
case uint64:
res = append(res, float64(v))
case float32:
res = append(res, float64(v))
case float64:
res = append(res, v)
default:
return nil, ErrFormat
}
}
return res, nil
}
// MustGetFloat64Slice 強制取得64位元浮點數切片
func (data Data) MustGetFloat64Slice(key string) []float64 {
values, _ := data.GetFloat64Slice(key)
return values
}
// GetInt64 取得64位元整數 // GetInt64 取得64位元整數
func (data Data) GetInt64(key string) (int64, error) { func (data Data) GetInt64(key string) (int64, error) {
value, err := data.Get(key) value, err := data.Get(key)
@ -276,6 +272,53 @@ func (data Data) MustGetInt64(key string) int64 {
return value return value
} }
// GetInt64Slice 取得64位元整數切片
func (data Data) GetInt64Slice(key string) (res []int64, err error) {
values, err := data.GetSlice(key)
if err != nil {
return nil, err
}
for _, v := range values {
switch v := v.(type) {
case int:
res = append(res, int64(v))
case uint:
res = append(res, int64(v))
case int8:
res = append(res, int64(v))
case uint8:
res = append(res, int64(v))
case int16:
res = append(res, int64(v))
case uint16:
res = append(res, int64(v))
case int32:
res = append(res, int64(v))
case uint32:
res = append(res, int64(v))
case int64:
res = append(res, v)
case uint64:
res = append(res, int64(v))
case float32:
res = append(res, int64(v))
case float64:
res = append(res, int64(v))
default:
return nil, ErrFormat
}
}
return res, nil
}
// MustGetInt64Slice 強制取得64位元整數切片
func (data Data) MustGetInt64Slice(key string) []int64 {
values, _ := data.GetInt64Slice(key)
return values
}
// GetUint64 取得64位元正整數 // GetUint64 取得64位元正整數
func (data Data) GetUint64(key string) (uint64, error) { func (data Data) GetUint64(key string) (uint64, error) {
value, err := data.GetInt64(key) value, err := data.GetInt64(key)
@ -296,6 +339,53 @@ func (data Data) MustGetUint64(key string) uint64 {
return value return value
} }
// GetUint64Slice 取得64位元正整數切片
func (data Data) GetUint64Slice(key string) (res []uint64, err error) {
values, err := data.GetSlice(key)
if err != nil {
return nil, err
}
for _, v := range values {
switch v := v.(type) {
case int:
res = append(res, uint64(v))
case uint:
res = append(res, uint64(v))
case int8:
res = append(res, uint64(v))
case uint8:
res = append(res, uint64(v))
case int16:
res = append(res, uint64(v))
case uint16:
res = append(res, uint64(v))
case int32:
res = append(res, uint64(v))
case uint32:
res = append(res, uint64(v))
case int64:
res = append(res, uint64(v))
case uint64:
res = append(res, v)
case float32:
res = append(res, uint64(v))
case float64:
res = append(res, uint64(v))
default:
return nil, ErrFormat
}
}
return res, nil
}
// MustGetUint64Slice 強制取得64位元正整數切片
func (data Data) MustGetUint64Slice(key string) []uint64 {
values, _ := data.GetUint64Slice(key)
return values
}
// GetInt 取得整數 // GetInt 取得整數
func (data Data) GetInt(key string) (int, error) { func (data Data) GetInt(key string) (int, error) {
value, err := data.GetInt64(key) value, err := data.GetInt64(key)
@ -312,6 +402,53 @@ func (data Data) MustGetInt(key string) int {
return value return value
} }
// GetIntSlice 取得整數切片
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 := v.(type) {
case int:
res = append(res, v)
case uint:
res = append(res, int(v))
case int8:
res = append(res, int(v))
case uint8:
res = append(res, int(v))
case int16:
res = append(res, int(v))
case uint16:
res = append(res, int(v))
case int32:
res = append(res, int(v))
case uint32:
res = append(res, int(v))
case int64:
res = append(res, int(v))
case uint64:
res = append(res, int(v))
case float32:
res = append(res, int(v))
case float64:
res = append(res, int(v))
default:
return nil, ErrFormat
}
}
return res, nil
}
// MustGetIntSlice 強制取得整數切片
func (data Data) MustGetIntSlice(key string) []int {
values, _ := data.GetIntSlice(key)
return values
}
// GetUint 取得正整數 // GetUint 取得正整數
func (data Data) GetUint(key string) (uint, error) { func (data Data) GetUint(key string) (uint, error) {
value, err := data.GetInt64(key) value, err := data.GetInt64(key)
@ -332,6 +469,53 @@ func (data Data) MustGetUint(key string) uint {
return value return value
} }
// GetUintSlice 取得正整數切片
func (data Data) GetUintSlice(key string) (res []uint, err error) {
values, err := data.GetSlice(key)
if err != nil {
return nil, err
}
for _, v := range values {
switch v := v.(type) {
case int:
res = append(res, uint(v))
case uint:
res = append(res, v)
case int8:
res = append(res, uint(v))
case uint8:
res = append(res, uint(v))
case int16:
res = append(res, uint(v))
case uint16:
res = append(res, uint(v))
case int32:
res = append(res, uint(v))
case uint32:
res = append(res, uint(v))
case int64:
res = append(res, uint(v))
case uint64:
res = append(res, uint(v))
case float32:
res = append(res, uint(v))
case float64:
res = append(res, uint(v))
default:
return nil, ErrFormat
}
}
return res, nil
}
// MustGetUintSlice 強制取得正整數切片
func (data Data) MustGetUintSlice(key string) []uint {
values, _ := data.GetUintSlice(key)
return values
}
// GetInt16 取得16位元整數 // GetInt16 取得16位元整數
func (data Data) GetInt16(key string) (int16, error) { func (data Data) GetInt16(key string) (int16, error) {
value, err := data.GetInt64(key) value, err := data.GetInt64(key)
@ -348,6 +532,53 @@ func (data Data) MustGetInt16(key string) uint16 {
return value return value
} }
// GetInt16Slice 取得16位元整數切片
func (data Data) GetInt16Slice(key string) (res []int16, err error) {
values, err := data.GetSlice(key)
if err != nil {
return nil, err
}
for _, v := range values {
switch v := v.(type) {
case int:
res = append(res, int16(v))
case uint:
res = append(res, int16(v))
case int8:
res = append(res, int16(v))
case uint8:
res = append(res, int16(v))
case int16:
res = append(res, v)
case uint16:
res = append(res, int16(v))
case int32:
res = append(res, int16(v))
case uint32:
res = append(res, int16(v))
case int64:
res = append(res, int16(v))
case uint64:
res = append(res, int16(v))
case float32:
res = append(res, int16(v))
case float64:
res = append(res, int16(v))
default:
return nil, ErrFormat
}
}
return res, nil
}
// MustGetInt16Slice 強制取得16位元整數切片
func (data Data) MustGetInt16Slice(key string) []int16 {
values, _ := data.GetInt16Slice(key)
return values
}
// GetUint16 取得16位元正整數 // GetUint16 取得16位元正整數
func (data Data) GetUint16(key string) (uint16, error) { func (data Data) GetUint16(key string) (uint16, error) {
value, err := data.GetInt64(key) value, err := data.GetInt64(key)
@ -368,6 +599,53 @@ func (data Data) MustGetUint16(key string) uint16 {
return value return value
} }
// GetUint16Slice 取得16位元正整數切片
func (data Data) GetUint16Slice(key string) (res []uint16, err error) {
values, err := data.GetSlice(key)
if err != nil {
return nil, err
}
for _, v := range values {
switch v := v.(type) {
case int:
res = append(res, uint16(v))
case uint:
res = append(res, uint16(v))
case int8:
res = append(res, uint16(v))
case uint8:
res = append(res, uint16(v))
case int16:
res = append(res, uint16(v))
case uint16:
res = append(res, v)
case int32:
res = append(res, uint16(v))
case uint32:
res = append(res, uint16(v))
case int64:
res = append(res, uint16(v))
case uint64:
res = append(res, uint16(v))
case float32:
res = append(res, uint16(v))
case float64:
res = append(res, uint16(v))
default:
return nil, ErrFormat
}
}
return res, nil
}
// MustGetUint16Slice 強制取得16位元正整數切片
func (data Data) MustGetUint16Slice(key string) []uint16 {
values, _ := data.GetUint16Slice(key)
return values
}
// GetInt8 取得8位元整數 // GetInt8 取得8位元整數
func (data Data) GetInt8(key string) (int8, error) { func (data Data) GetInt8(key string) (int8, error) {
value, err := data.GetInt64(key) value, err := data.GetInt64(key)
@ -384,6 +662,53 @@ func (data Data) MustGetInt8(key string) int8 {
return value return value
} }
// GetInt8Slice 取得8位元整數切片
func (data Data) GetInt8Slice(key string) (res []int8, err error) {
values, err := data.GetSlice(key)
if err != nil {
return nil, err
}
for _, v := range values {
switch v := v.(type) {
case int:
res = append(res, int8(v))
case uint:
res = append(res, int8(v))
case int8:
res = append(res, v)
case uint8:
res = append(res, int8(v))
case int16:
res = append(res, int8(v))
case uint16:
res = append(res, int8(v))
case int32:
res = append(res, int8(v))
case uint32:
res = append(res, int8(v))
case int64:
res = append(res, int8(v))
case uint64:
res = append(res, int8(v))
case float32:
res = append(res, int8(v))
case float64:
res = append(res, int8(v))
default:
return nil, ErrFormat
}
}
return res, nil
}
// MustGetInt8Slice 強制取得8位元整數切片
func (data Data) MustGetInt8Slice(key string) []int8 {
values, _ := data.GetInt8Slice(key)
return values
}
// GetUint8 取得8位元正整數 // GetUint8 取得8位元正整數
func (data Data) GetUint8(key string) (uint8, error) { func (data Data) GetUint8(key string) (uint8, error) {
value, err := data.GetInt64(key) value, err := data.GetInt64(key)
@ -404,6 +729,53 @@ func (data Data) MustGetUint8(key string) uint8 {
return value return value
} }
// GetUint8Slice 取得8位元正整數切片
func (data Data) GetUint8Slice(key string) (res []uint8, err error) {
values, err := data.GetSlice(key)
if err != nil {
return nil, err
}
for _, v := range values {
switch v := v.(type) {
case int:
res = append(res, uint8(v))
case uint:
res = append(res, uint8(v))
case int8:
res = append(res, uint8(v))
case uint8:
res = append(res, v)
case int16:
res = append(res, uint8(v))
case uint16:
res = append(res, uint8(v))
case int32:
res = append(res, uint8(v))
case uint32:
res = append(res, uint8(v))
case int64:
res = append(res, uint8(v))
case uint64:
res = append(res, uint8(v))
case float32:
res = append(res, uint8(v))
case float64:
res = append(res, uint8(v))
default:
return nil, ErrFormat
}
}
return res, nil
}
// MustGetUint8Slice 強制取得8位元正整數切片
func (data Data) MustGetUint8Slice(key string) []uint8 {
values, _ := data.GetUint8Slice(key)
return values
}
// GetBool 取得布林值 // GetBool 取得布林值
func (data Data) GetBool(key string) (bool, error) { func (data Data) GetBool(key string) (bool, error) {
value, err := data.Get(key) value, err := data.Get(key)
@ -479,7 +851,7 @@ func (data Data) MustJSON() []byte {
return bs return bs
} }
// Get 取得資料 // GetPage 取得頁數
func (data Data) GetPage(key string) (*Page, error) { func (data Data) GetPage(key string) (*Page, error) {
value, err := data.Get(key) value, err := data.Get(key)
if err != nil { if err != nil {
@ -494,7 +866,7 @@ func (data Data) GetPage(key string) (*Page, error) {
return nil, ErrFormat return nil, ErrFormat
} }
// Get 取得資料 // MustGetPage 強制取得頁數
func (data Data) MustGetPage(key string) *Page { func (data Data) MustGetPage(key string) *Page {
value, _ := data.GetPage(key) value, _ := data.GetPage(key)

@ -10,12 +10,12 @@ const (
FormatDatetime = "2006-01-02 15:04:05" FormatDatetime = "2006-01-02 15:04:05"
) )
// Local 本地時區 // Location 本地時區
var Local = time.Local var Location = time.Local
// SetLocation 設定時區 // SetLocation 設定時區
func SetLocation(name string) { func SetLocation(name string) {
Local, _ = time.LoadLocation(name) Location, _ = time.LoadLocation(name)
} }
// Timestamp 時間戳 // Timestamp 時間戳
@ -26,9 +26,14 @@ func GetUnixNow() Timestamp {
return Timestamp(time.Now().Unix()) return Timestamp(time.Now().Unix())
} }
// GetUnixMilliNow 取得現在時間戳記
func GetUnixMilliNow() Timestamp {
return Timestamp(time.Now().UnixMilli())
}
// GetUnix 嘗試取得時間戳記 // GetUnix 嘗試取得時間戳記
func GetUnix(format, datetime string) (Timestamp, error) { func GetUnix(format, datetime string) (Timestamp, error) {
t, err := time.ParseInLocation(format, datetime, Local) t, err := time.ParseInLocation(format, datetime, Location)
return Timestamp(t.Unix()), err return Timestamp(t.Unix()), err
} }
@ -48,38 +53,69 @@ func (t Timestamp) Time() time.Time {
return time.Unix(t.Int64(), 0) return time.Unix(t.Int64(), 0)
} }
// TimeMilli 轉為time類型
func (t Timestamp) TimeMilli() time.Time {
return time.UnixMilli(t.Int64())
}
// Date 回傳日期字串 // Date 回傳日期字串
func (t Timestamp) Date() string { func (t Timestamp) Date() string {
if t == 0 {
return ""
}
return time. return time.
Unix(t.Int64(), 0). Unix(t.Int64(), 0).
In(Local). In(Location).
Format(FormatDate) Format(FormatDate)
} }
// Datetime 回傳時間字串 // Datetime 回傳時間字串
func (t Timestamp) Datetime() string { func (t Timestamp) Datetime() string {
if t == 0 {
return ""
}
return time. return time.
Unix(t.Int64(), 0). Unix(t.Int64(), 0).
In(Local). In(Location).
Format(FormatDatetime) Format(FormatDatetime)
} }
// NowSub 與現在的時間差 // Since 與現在的時間差
func (t Timestamp) NowSub() time.Duration { func (t Timestamp) Since() time.Duration {
return time.Since(t.Time()) return time.Since(t.Time())
} }
// SinceMilli 與現在的時間差
func (t Timestamp) SinceMilli() time.Duration {
return time.Since(t.TimeMilli())
}
// Sub 時間差 // Sub 時間差
func (t Timestamp) Sub(t2 time.Time) time.Duration { func (t Timestamp) Sub(t2 time.Time) time.Duration {
return t2.Sub(t.Time()) return t2.Sub(t.Time())
} }
// SubMilli 時間差
func (t Timestamp) SubMilli(t2 time.Time) time.Duration {
return t2.Sub(t.TimeMilli())
}
// After 是否在指定時間後 // After 是否在指定時間後
func (t Timestamp) After(t2 time.Time) bool { func (t Timestamp) After(t2 time.Time) bool {
return t.Time().After(t2) return t.Time().After(t2)
} }
// AfterMilli 是否在指定時間後
func (t Timestamp) AfterMilli(t2 time.Time) bool {
return t.TimeMilli().After(t2)
}
// AfterNow 是否在目前時間後 // AfterNow 是否在目前時間後
func (t Timestamp) AfterNow() bool { func (t Timestamp) AfterNow() bool {
return t.After(time.Now()) return t.After(time.Now())
} }
// AfterMilliNow 是否在目前時間後
func (t Timestamp) AfterMilliNow() bool {
return t.AfterMilli(time.Now())
}

Loading…
Cancel
Save