Compare commits

..

No commits in common. "master" and "v1.0.2" have entirely different histories.

21 changed files with 152 additions and 275 deletions

View File

@ -19,8 +19,6 @@ func parseArgs(cmd string) {
switch cmd { switch cmd {
case "-v", "--v", "-version", "--version": case "-v", "--v", "-version", "--version":
versionCmd() versionCmd()
case "--json":
versionCmdJson()
} }
os.Exit(0) os.Exit(0)
@ -30,7 +28,3 @@ func versionCmd() {
fmt.Printf("[Blocks Service: %s] Version: %s \n", vars.ServiceKey, vars.VERSION) fmt.Printf("[Blocks Service: %s] Version: %s \n", vars.ServiceKey, vars.VERSION)
fmt.Printf("[Blocks Service: %s] Compile: %s by %s build.\n", vars.ServiceKey, vars.GO_VERSION, vars.BUILD_TIME) fmt.Printf("[Blocks Service: %s] Compile: %s by %s build.\n", vars.ServiceKey, vars.GO_VERSION, vars.BUILD_TIME)
} }
func versionCmdJson() {
fmt.Printf("{\"version\":\"%s\",\"build_time\":\"%s\"}\n", vars.VERSION, vars.BUILD_TIME)
}

View File

@ -1,30 +0,0 @@
package sql
import "strings"
// key,value To like sql
func Like(key, val string) string {
if val == "" {
return ""
}
key = strings.TrimSpace(key)
val = strings.TrimSpace(val)
return key + " LIKE '%" + val + "%'"
}
// map strings to like sqls
func Likes(in map[string]string) string {
var ar []string
for key, val := range in {
sql := Like(key, val)
if sql != "" {
ar = append(ar, sql)
}
}
if len(ar) == 0 {
return ""
}
return strings.Join(ar, " AND ")
}

View File

@ -24,15 +24,14 @@ func NewPostgreSql(dsn string, options *types.SqlOptions) (*gorm.DB, error) {
} }
//控制台和文件同时输出日志 //控制台和文件同时输出日志
//var newLogger = setLogger(vars.ServiceKey, options.LogStdout) var newLogger = setLogger(vars.ServiceKey, options.LogStdout)
gormDb, err := gorm.Open(postgres.New(postgres.Config{ gormDb, err := gorm.Open(postgres.New(postgres.Config{
DSN: dsn, DSN: dsn,
// PreferSimpleProtocol: true, disables implicit prepared statement usage // PreferSimpleProtocol: true, disables implicit prepared statement usage
}), &gorm.Config{ }), &gorm.Config{
//Logger:newLogger, Logger: newLogger,
DisableForeignKeyConstraintWhenMigrating: true,
NamingStrategy: schema.NamingStrategy{ NamingStrategy: schema.NamingStrategy{
SingularTable: true, // 使用单数表名,启用该选项,此时,`User` 的表名应该是 `t_user` SingularTable: true, // 使用单数表名,启用该选项,此时,`User` 的表名应该是 `t_user`
}}) }})

View File

@ -6,6 +6,7 @@ import (
"crypto/cipher" "crypto/cipher"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"errors"
"strings" "strings"
"time" "time"
@ -21,29 +22,25 @@ var (
JwtSecretLen int JwtSecretLen int
) )
func New(token string) { func New() {
JwtSecret = []byte(token) JwtSecret = []byte(env.MeshEnv.JwtSecretKey)
JwtSecretLen = len(env.MeshEnv.JwtSecretKey) JwtSecretLen = len(env.MeshEnv.JwtSecretKey)
} }
func GenerateTokenAes(id uint, identity, client, role string, owner any, extend map[string]string) (string, error) { func GenerateTokenAes(id uint, identity, client, role string, extend map[string]string) (string, error) {
if (JwtSecretLen == 16 || JwtSecretLen == 24 || JwtSecretLen == 32) == false {
return "", exception.ErrAuthSecret
}
expireTime := time.Now().Add(vars.JwtExpireDay) expireTime := time.Now().Add(vars.JwtExpireDay)
claims := types.JwtClaims{ claims := types.JwtClaims{
ID: id, ID: id,
Identity: identity, Identity: identity,
Client: client,
Extend: extend, Extend: extend,
Owner: owner, Client: client,
Role: role, Role: role,
ExpiresAt: expireTime.Unix(), ExpiresAt: expireTime.Unix(),
} }
byte, err := json.Marshal(claims) byte, err := json.Marshal(claims)
if err != nil { if err != nil {
return "", exception.ErrJsonEncode return "", err
} }
token, err := AesEncryptCBC(byte) token, err := AesEncryptCBC(byte)
@ -54,13 +51,12 @@ func GenerateTokenAes(id uint, identity, client, role string, owner any, extend
} }
func AesEncryptCBC(plan []byte) (string, error) { func AesEncryptCBC(plan []byte) (string, error) {
if (JwtSecretLen == 16 || JwtSecretLen == 24 || JwtSecretLen == 32) == false {
return "", errors.New("JwtSecret lenght must 16/24/32.")
}
// 分组秘钥 // 分组秘钥
// NewCipher该函数限制了输入k的长度必须为16, 24或者32 // NewCipher该函数限制了输入k的长度必须为16, 24或者32
block, err := aes.NewCipher(JwtSecret) block, _ := aes.NewCipher(JwtSecret)
if err != nil {
return "", exception.ErrAuthSecret
}
// 获取秘钥块的长度 // 获取秘钥块的长度
blockSize := block.BlockSize() blockSize := block.BlockSize()
// 补全码 // 补全码
@ -76,17 +72,17 @@ func AesEncryptCBC(plan []byte) (string, error) {
func AesDecryptCBC(cryted string) (b []byte, err error) { func AesDecryptCBC(cryted string) (b []byte, err error) {
if (JwtSecretLen == 16 || JwtSecretLen == 24 || JwtSecretLen == 32) == false { if (JwtSecretLen == 16 || JwtSecretLen == 24 || JwtSecretLen == 32) == false {
return nil, exception.ErrAuthSecret return b, errors.New("JwtSecret lenght must 16/24/32.")
} }
// 转成字节数组 // 转成字节数组
crytedByte, err := base64.StdEncoding.DecodeString(cryted) crytedByte, err := base64.StdEncoding.DecodeString(cryted)
if err != nil { if err != nil {
return nil, exception.ErrBase64Decode return
} }
// 分组秘钥 // 分组秘钥
block, err := aes.NewCipher(JwtSecret) block, err := aes.NewCipher(JwtSecret)
if err != nil { if err != nil {
return nil, exception.ErrAuthSecret return
} }
// 获取秘钥块的长度 // 获取秘钥块的长度
blockSize := block.BlockSize() blockSize := block.BlockSize()
@ -125,10 +121,6 @@ func PKCS7UnPadding(origData []byte, blocksize int) []byte {
length := len(origData) length := len(origData)
unpadding := int(origData[length-1]) unpadding := int(origData[length-1])
if length-unpadding <= 0 {
return nil
}
return origData[:(length - unpadding)] return origData[:(length - unpadding)]
} }

25
env/env.go vendored
View File

@ -14,32 +14,11 @@ var MeshEnv *types.MeshEnv = nil
func NewEnv() *types.MeshEnv { func NewEnv() *types.MeshEnv {
if MeshEnv == nil { if MeshEnv == nil {
MeshEnv = &types.MeshEnv{ MeshEnv = &types.MeshEnv{
Workspace: GetEnvDefault("BlocksMesh_Workspace", "def"), Workspace: GetEnvDefault("BlocksMesh_Workspace", "bsm"),
Prefix: GetEnvDefault("BlocksMesh_Prefix", utils.GetCurrentPath()),
JwtSecretKey: GetEnvDefault("BlocksMesh_JwtSecretKey", "Cblocksmesh2022C"), JwtSecretKey: GetEnvDefault("BlocksMesh_JwtSecretKey", "Cblocksmesh2022C"),
RuntimeMode: strings.ToLower(GetEnvDefault("BlocksMesh_RuntimeMode", "dev")), RuntimeMode: strings.ToLower(GetEnvDefault("BlocksMesh_RuntimeMode", "dev")),
} }
if MeshEnv.RuntimeMode == "dev" {
MeshEnv.Prefix = GetEnvDefault("BlocksMesh_Prefix", utils.GetCurrentPath())
} else {
MeshEnv.Prefix = GetEnvDefault("BlocksMesh_Prefix", "/usr/local/bsm")
}
}
return MeshEnv
}
// get system base env.
func NewBaseEnv() *types.MeshEnv {
if MeshEnv == nil {
MeshEnv = &types.MeshEnv{
RuntimeMode: strings.ToLower(GetEnvDefault("BlocksMesh_RuntimeMode", "dev")),
}
if MeshEnv.RuntimeMode == "dev" {
MeshEnv.Prefix = GetEnvDefault("BlocksMesh_Prefix", utils.GetCurrentPath())
} else {
MeshEnv.Prefix = GetEnvDefault("BlocksMesh_Prefix", "/usr/local/bsm")
}
} }
return MeshEnv return MeshEnv
} }

View File

@ -2,17 +2,13 @@ package exception
// jwt custom error code ,begin:200 // jwt custom error code ,begin:200
var ( var (
ErrAuthSecret = Errorf(200, "Auth JwtSecret Error") ErrAuthPasswd = ErrorJson(201, "Password Error")
ErrBase64Decode = Errorf(201, "Auth Token Base64 Decode Error") ErrAuthNotFound = ErrorJson(202, "Auth Token Not Found")
ErrAuthNotFound = Errorf(202, "Auth Token Not Found") ErrAuthParseFail = ErrorJson(203, "Auth Parse Fail")
ErrAuthParseFail = Errorf(203, "Auth Parse Fail") ErrAuthId = ErrorJson(204, "Auth Id Not Passed")
ErrAuthId = Errorf(204, "Auth Id Not Passed") ErrAuthIdentity = ErrorJson(205, "Auth Identity Not Passed")
ErrAuthIdentity = Errorf(205, "Auth Identity Not Passed") ErrAuthTokenChanged = ErrorJson(206, "Auth Token Changed")
ErrAuthTokenChanged = Errorf(206, "Auth Token Changed") ErrAuthIdType = ErrorJson(207, "Auth Id Type Error")
ErrAuthIdType = Errorf(207, "Auth Id Type Error") ErrAuthExpire = ErrorJson(208, "Auth Token Expire")
ErrAuthExpire = Errorf(208, "Auth Token Expire") ErrAuthClient = ErrorJson(208, "Auth Token Client Not Passed")
ErrAuthClient = Errorf(209, "Auth Token Client Not Passed")
ErrJsonDecode = Errorf(210, "Auth JSON Decode Error")
ErrJsonEncode = Errorf(211, "Auth JSON Encode Error")
ErrAccountNotFound = Errorf(202, "Account Not Found")
) )

View File

@ -2,9 +2,9 @@ package exception
// db custom error code ,begin:300 // db custom error code ,begin:300
var ( var (
ErrDBFatal = Errorf(300, "DB Fatal error") ErrDBFatal = ErrorJson(300, "DB Fatal error")
ErrCacheFatal = Errorf(301, "Cache Fatal error") ErrCacheFatal = ErrorJson(301, "Cache Fatal error")
ErrEtcdFatal = Errorf(302, "Etcd Fatal error") ErrEtcdFatal = ErrorJson(302, "Etcd Fatal error")
ErrElasticFatal = Errorf(303, "Elastic Fatal error") ErrElasticFatal = ErrorJson(303, "Elastic Fatal error")
ErrBlocksMQFatal = Errorf(304, "BlocksMQ Fatal error") ErrBlocksMQFatal = ErrorJson(304, "BlocksMQ Fatal error")
) )

View File

@ -9,30 +9,27 @@ import (
var ( var (
// google grpc error status. // google grpc error status.
OK = Errorf(0, "OK") OK = ErrorJson(0, "OK")
ErrCanceled = Errorf(1, "Canceled") ErrCanceled = ErrorJson(1, "Canceled")
ErrUnknown = Errorf(2, "Unknown") ErrUnknown = ErrorJson(2, "Unknown")
ErrInvalidArgument = Errorf(3, "Invalid Argument") ErrInvalidArgument = ErrorJson(3, "Invalid Argument")
ErrDeadlineExceeded = Errorf(4, "Deadline Exceeded") ErrDeadlineExceeded = ErrorJson(4, "Deadline Exceeded")
ErrNotFound = Errorf(5, "Not Found") ErrNotFound = ErrorJson(5, "Not Found")
ErrAlreadyExists = Errorf(6, "Already Exists") ErrAlreadyExists = ErrorJson(6, "Already Exists")
ErrPermissionDenied = Errorf(7, "Permission Denied") ErrPermissionDenied = ErrorJson(7, "Permission Denied")
ErrResourceExhausted = Errorf(8, "Resource Exhausted") ErrResourceExhausted = ErrorJson(8, "Resource Exhausted")
ErrFailedPrecondition = Errorf(9, "Failed Precondition") ErrFailedPrecondition = ErrorJson(9, "Failed Precondition")
ErrAborted = Errorf(10, "Aborted") ErrAborted = ErrorJson(10, "Aborted")
ErrOutOfRange = Errorf(11, "Out Of Range") ErrOutOfRange = ErrorJson(11, "Out Of Range")
ErrUnimplemented = Errorf(12, "Unimplemented") ErrUnimplemented = ErrorJson(12, "Unimplemented")
ErrInternal = Errorf(13, "Internal") ErrInternal = ErrorJson(13, "Internal")
ErrUnavailable = Errorf(14, "Unavailable") ErrUnavailable = ErrorJson(14, "Unavailable")
ErrDataLoss = Errorf(15, "Data Loss") ErrDataLoss = ErrorJson(15, "Data Loss")
ErrUnauthenticated = Errorf(16, "Unauthenticated") ErrUnauthenticated = ErrorJson(16, "Unauthenticated")
ErrJSONMarshal = Errorf(17, "Marshal JSON") ErrJSONMarshal = ErrorJson(17, "Marshal JSON")
ErrJSONUnmarshal = Errorf(18, "Unmarshal JSON") ErrJSONUnmarshal = ErrorJson(18, "Unmarshal JSON")
ErrPasswd = Errorf(19, "Password Error")
ErrSmsCode = Errorf(20, "SMS Code Invalid") ErrSmsCode = ErrorJson(20, "SMS Code Invalid")
ErrIdArgument = Errorf(30, "ID Invalid Argument")
ErrIdentityArgument = Errorf(31, "Identity Invalid Argument")
// coustom error status // coustom error status
) )
@ -44,3 +41,7 @@ func Error(c uint32, msg string) error {
func Errorf(c uint32, format string, a ...interface{}) error { func Errorf(c uint32, format string, a ...interface{}) error {
return status.New(codes.Code(c), fmt.Sprintf(format, a...)).Err() return status.New(codes.Code(c), fmt.Sprintf(format, a...)).Err()
} }
func ErrorJson(c uint32, msg string) error {
return status.New(codes.Code(c), fmt.Sprintf(`{ "Code": %d, "Msg": "%s" }`, c, msg)).Err()
}

View File

@ -2,10 +2,10 @@ package exception
// mq custom error code ,begin:900 // mq custom error code ,begin:900
var ( var (
ErrMQClient = Errorf(900, "MQ Connect Error") ErrMQClient = ErrorJson(900, "MQ Connect Error")
ErrMQDispatch = Errorf(901, "MQ Dispatch Error") ErrMQDispatch = ErrorJson(901, "MQ Dispatch Error")
ErrMQProducer = Errorf(902, "MQ Producer Error") ErrMQProducer = ErrorJson(902, "MQ Producer Error")
ErrMQConsumer = Errorf(902, "MQ Consumer Error") ErrMQConsumer = ErrorJson(902, "MQ Consumer Error")
ErrMQInternal = Errorf(903, "MQ Internal Error") ErrMQInternal = ErrorJson(903, "MQ Internal Error")
ErrMQStorage = Errorf(904, "MQ Storage Error") ErrMQStorage = ErrorJson(904, "MQ Storage Error")
) )

2
go.mod
View File

@ -1,3 +1,3 @@
module git.apinb.com/bsm-sdk/engine module git.apinb.com/bsm-sdk/engine
go 1.23.3 go 1.21

View File

@ -2,11 +2,12 @@ package service
import ( import (
"context" "context"
"encoding/json"
"strings" "strings"
"git.apinb.com/bsm-sdk/engine/encipher"
"git.apinb.com/bsm-sdk/engine/exception" "git.apinb.com/bsm-sdk/engine/exception"
"git.apinb.com/bsm-sdk/engine/types" "git.apinb.com/bsm-sdk/engine/types"
"git.apinb.com/bsm-sdk/engine/utils"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
) )
@ -23,23 +24,27 @@ func ParseMetaCtx(ctx context.Context, opts *ParseOptions) (*types.JwtClaims, er
return nil, exception.ErrAuthNotFound return nil, exception.ErrAuthNotFound
} }
var Authorizations []string = md.Get("authorization_claims") var Authorizations []string = md.Get("authorization")
if len(Authorizations) == 0 || Authorizations[0] == "" { if len(Authorizations) == 0 || Authorizations[0] == "" {
return nil, exception.ErrAuthNotFound return nil, exception.ErrAuthNotFound
} }
var claims types.JwtClaims claims, err := encipher.ParseTokenAes(Authorizations[0])
err := json.Unmarshal([]byte(Authorizations[0]), &claims)
if err != nil { if err != nil {
return nil, exception.ErrAuthParseFail return nil, err
} }
if opts != nil { if opts != nil {
if !strings.Contains(claims.Role, opts.RoleValue) { if !strings.Contains(claims.Role, opts.RoleValue) {
return nil, exception.ErrPermissionDenied return nil, exception.ErrPermissionDenied
} }
if opts.MustPrivateAllow {
if utils.IsPublicIP(claims.Client) {
return nil, exception.ErrPermissionDenied
}
}
} }
return &claims, nil return claims, nil
} }

View File

@ -34,7 +34,7 @@ func Register(srvKey string, cfg any) {
// get config file. // get config file.
cf := fmt.Sprintf("%s_%s.yaml", srvKey, env.MeshEnv.RuntimeMode) cf := fmt.Sprintf("%s_%s.yaml", srvKey, env.MeshEnv.RuntimeMode)
cf = filepath.Join(env.MeshEnv.Prefix, "etc", cf) cf = filepath.Join(env.MeshEnv.Prefix, "etc", cf)
print.Info("[Blocks Service] %s Config File: %s", vars.ServiceKey, cf)
configure.LoadYamlFile(cf, args, cfg) configure.LoadYamlFile(cf, args, cfg)
return return

View File

@ -18,54 +18,48 @@ type (
Debug bool Debug bool
} }
// standard ID,Identity definition.
Std_IDIdentity struct {
ID uint `gorm:"primarykey;" json:"id"`
Identity string `gorm:"column:identity;type:varchar(36);uniqueIndex;" json:"identity"` // 唯一标识24位NanoID,36位为ULID
}
// standard ID,Created,Updated,Deleted definition. // standard ID,Created,Updated,Deleted definition.
Std_IICUDS struct { Std_IICUDS struct {
ID uint `gorm:"primarykey;" json:"id"` ID uint `gorm:"primarykey;"`
Identity string `gorm:"column:identity;type:varchar(36);uniqueIndex;" json:"identity"` // 唯一标识24位NanoID,36位为ULID Identity string `gorm:"column:identity;type:varchar(36);uniqueIndex;"` // 唯一标识24位NanoID,36位为UUID
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index;" json:"deleted_at"` DeletedAt gorm.DeletedAt `gorm:"index";`
Status int8 `gorm:"default:0;index;" json:"status"` // 状态默认为0-1禁止1为正常 Status int8 `gorm:"default:0;index;"` // 状态默认为0-1禁止1为正常
} }
// standard ID,Identity,Created,Updated,Deleted,Status definition. // standard ID,Identity,Created,Updated,Deleted,Status definition.
Std_ICUD struct { Std_ICUD struct {
ID uint `gorm:"primarykey;" json:"id"` ID uint `gorm:"primarykey;"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index;" json:"deleted_at"` DeletedAt gorm.DeletedAt `gorm:"index"`
} }
// standard ID,Created definition. // standard ID,Created definition.
Std_IdCreated struct { Std_IdCreated struct {
ID uint `gorm:"primarykey;" json:"id"` ID uint `gorm:"primarykey;"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time
} }
// standard PassportID,PassportIdentity definition. // standard PassportID,PassportIdentity definition.
Std_Passport struct { Std_Passport struct {
PassportID uint `gorm:"column:passport_id;Index;" json:"passport_id"` PassportID uint `gorm:"column:passport_id;Index;"`
PassportIdentity string `gorm:"column:passport_identity;type:varchar(36);Index;" json:"passport_identity"` // 用户唯一标识24位NanoID,36位为ULID PassportIdentity string `gorm:"column:passport_identity;type:varchar(36);Index;"` // 用户唯一标识24位NanoID,36位为UUID
} }
// standard ID definition. // standard ID definition.
Std_ID struct { Std_ID struct {
ID uint `gorm:"primarykey;" json:"id"` ID uint `gorm:"primarykey;"`
} }
// standard Identity definition. // standard Identity definition.
Std_Identity struct { Std_Identity struct {
Identity string `gorm:"column:identity;type:varchar(36);uniqueIndex;" json:"identity"` // 唯一标识24位NanoID,36位为ULID Identity string `gorm:"column:identity;type:varchar(36);uniqueIndex;"` // 唯一标识24位NanoID,36位为UUID
} }
// standard Status definition. // standard Status definition.
Std_Status struct { Std_Status struct {
Status int8 `gorm:"default:0;index;" json:"status"` // 状态默认为0-1禁止1为正常 Status int8 `gorm:"default:0;index;"` // 状态默认为0-1禁止1为正常
} }
) )

View File

@ -10,7 +10,6 @@ type JwtClaims struct {
Identity string `json:"identity"` Identity string `json:"identity"`
Extend map[string]string `json:"extend"` Extend map[string]string `json:"extend"`
Client string `json:"client"` Client string `json:"client"`
Owner any `json:"owner"`
Role string `json:"role"` Role string `json:"role"`
ExpiresAt int64 `json:"exp"` ExpiresAt int64 `json:"exp"`
} }

View File

@ -1,12 +1,12 @@
package types package types
type Etcd struct { type Etcd struct {
Endpoints []string `json:"Endpoints"` Endpoints []string `json:"endpoints"`
Tls EtcdTls `json:"Tls,optional"` Tls EtcdTls `json:",optional"`
} }
type EtcdTls struct { type EtcdTls struct {
Ca string `json:"Ca,optional"` Ca string `json:"ca,optional"`
Cert string `json:"Cert,optional"` Cert string `json:"cert,optional"`
CertKey string `json:"CertKey,optional" ` CertKey string `json:"cert_key,optional" `
} }

View File

@ -1,56 +0,0 @@
package types
type Message struct {
TimeSequence int64 //消息创建的时间戳
SessionIdent string // 会话唯一标识
SenderId int64
SenderIdentity string
TargetId int64
TargetIdentity string
GroupId int64 //群组唯一ID在群聊消息的时候使用到。不使用时则为空
GroupIdentity string //群组唯一码,在群聊消息的时候使用到。不使用时则为空
MsgType int32 //0异常提示1单聊2群聊3系统
BodyType int32 //正文类型0文本1图片2视频3.....
Body string
Status int32 //消息状态:0待续1存储成功2送达确认3已读确认-1撤回
}
type ChatMessage struct {
TimeSequence int64 //消息创建的时间戳
SessionIdent string // 会话唯一标识
SenderId int64
SenderIdentity string
TargetId int64
TargetIdentity string
BodyType int32 //正文类型0文本1图片2视频3.....
Body string
Status int32 //消息状态:0待续1存储成功2送达确认3已读确认-1撤回
}
type GroupMessage struct {
TimeSequence int64 //消息创建的时间戳
GroupId int64 //群组唯一ID在群聊消息的时候使用到。不使用时则为空
GroupIdentity string //群组唯一标识,在群聊消息的时候使用到。不使用时则为空
SenderId int64
SenderIdentity string
BodyType int32 //正文类型0文本1图片2视频3.....
Body string
Status int32 //消息状态:0待续1存储成功2送达确认3已读确认-1撤回
}
type SystemMessage struct {
TimeSequence int64 //消息创建的时间戳
TargetId int64
TargetIdentity string
BodyType int32 //正文类型0文本1图片2视频3.....
Body string
Status int32 //消息状态:0待续1存储成功2送达确认3已读确认-1撤回
}
type EventMessage struct {
TimeSequence int64 //消息创建的时间戳
TargetId int64
TargetIdentity string
EventType int32 //事件类型0 正在输入,已送达...
Status int32 //消息状态:0待续1存储成功2送达确认3已读确认-1撤回
}

View File

@ -2,21 +2,21 @@ package utils
import ( import (
"math" "math"
"reflect"
"strconv" "strconv"
"strings" "strings"
"unsafe"
) )
// 字符串转Int // 字符串转Int
// // intStr数字的字符串
// intStr数字的字符串
func String2Int(intStr string) (intNum int) { func String2Int(intStr string) (intNum int) {
intNum, _ = strconv.Atoi(intStr) intNum, _ = strconv.Atoi(intStr)
return return
} }
// 字符串转Int64 // 字符串转Int64
// // intStr数字的字符串
// intStr数字的字符串
func String2Int64(intStr string) (int64Num int64) { func String2Int64(intStr string) (int64Num int64) {
intNum, _ := strconv.Atoi(intStr) intNum, _ := strconv.Atoi(intStr)
int64Num = int64(intNum) int64Num = int64(intNum)
@ -24,16 +24,14 @@ func String2Int64(intStr string) (int64Num int64) {
} }
// 字符串转Float64 // 字符串转Float64
// // floatStr小数点数字的字符串
// floatStr小数点数字的字符串
func String2Float64(floatStr string) (floatNum float64) { func String2Float64(floatStr string) (floatNum float64) {
floatNum, _ = strconv.ParseFloat(floatStr, 64) floatNum, _ = strconv.ParseFloat(floatStr, 64)
return return
} }
// 字符串转Float32 // 字符串转Float32
// // floatStr小数点数字的字符串
// floatStr小数点数字的字符串
func String2Float32(floatStr string) (floatNum float32) { func String2Float32(floatStr string) (floatNum float32) {
floatNum64, _ := strconv.ParseFloat(floatStr, 32) floatNum64, _ := strconv.ParseFloat(floatStr, 32)
floatNum = float32(floatNum64) floatNum = float32(floatNum64)
@ -41,16 +39,14 @@ func String2Float32(floatStr string) (floatNum float32) {
} }
// Int转字符串 // Int转字符串
// // intNum数字字符串
// intNum数字字符串
func Int2String(intNum int) (intStr string) { func Int2String(intNum int) (intStr string) {
intStr = strconv.Itoa(intNum) intStr = strconv.Itoa(intNum)
return return
} }
// Int64转字符串 // Int64转字符串
// // intNum数字字符串
// intNum数字字符串
func Int642String(intNum int64) (int64Str string) { func Int642String(intNum int64) (int64Str string) {
//10, 代表10进制 //10, 代表10进制
int64Str = strconv.FormatInt(intNum, 10) int64Str = strconv.FormatInt(intNum, 10)
@ -58,9 +54,8 @@ func Int642String(intNum int64) (int64Str string) {
} }
// Float64转字符串 // Float64转字符串
// // floatNumfloat64数字
// floatNumfloat64数字 // prec精度位数不传则默认float数字精度
// prec精度位数不传则默认float数字精度
func Float64ToString(floatNum float64, prec ...int) (floatStr string) { func Float64ToString(floatNum float64, prec ...int) (floatStr string) {
if len(prec) > 0 { if len(prec) > 0 {
floatStr = strconv.FormatFloat(floatNum, 'f', prec[0], 64) floatStr = strconv.FormatFloat(floatNum, 'f', prec[0], 64)
@ -71,9 +66,8 @@ func Float64ToString(floatNum float64, prec ...int) (floatStr string) {
} }
// Float32转字符串 // Float32转字符串
// // floatNumfloat32数字
// floatNumfloat32数字 // prec精度位数不传则默认float数字精度
// prec精度位数不传则默认float数字精度
func Float32ToString(floatNum float32, prec ...int) (floatStr string) { func Float32ToString(floatNum float32, prec ...int) (floatStr string) {
if len(prec) > 0 { if len(prec) > 0 {
floatStr = strconv.FormatFloat(float64(floatNum), 'f', prec[0], 32) floatStr = strconv.FormatFloat(float64(floatNum), 'f', prec[0], 32)
@ -96,6 +90,15 @@ func BinaryToDecimal(bit string) (num int) {
return return
} }
// BytesToString 0 拷贝转换 slice byte 为 string
func BytesToString(b []byte) (s string) {
_bptr := (*reflect.SliceHeader)(unsafe.Pointer(&b))
_sptr := (*reflect.StringHeader)(unsafe.Pointer(&s))
_sptr.Data = _bptr.Data
_sptr.Len = _bptr.Len
return s
}
// interface to string // interface to string
func AnyToString(in any) (s string) { func AnyToString(in any) (s string) {
if in == nil { if in == nil {

View File

@ -1,10 +1,26 @@
package utils package utils
import ( import (
ulid "github.com/oklog/ulid/v2" "strconv"
"github.com/google/uuid"
"github.com/jaevor/go-nanoid"
) )
// remove nanoid,uuid,replace to ulid func NanoID() string {
func ULID() string { nanoid, _ := nanoid.CustomASCII("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 21)
return ulid.Make().String() return nanoid()
}
func NanoIDInt() (id int64, err error) {
decenaryID, err := nanoid.CustomASCII("0123456789", 20)
if err != nil {
return
}
id, err = strconv.ParseInt(decenaryID(), 10, 64)
return
}
func UUID() string {
return uuid.NewString()
} }

View File

@ -99,7 +99,7 @@ func HttpPost(url string, header map[string]string, data []byte) ([]byte, error)
} }
request.Header.Set("Content-Type", "application/json;charset=UTF-8") request.Header.Set("Content-Type", "application/json;charset=UTF-8")
request.Header.Set("Request-Id", ULID()) request.Header.Set("Request-Id", NanoID())
for key, val := range header { for key, val := range header {
request.Header.Set(key, val) request.Header.Set(key, val)

View File

@ -1,49 +1,42 @@
package utils package utils
import ( import (
"math/rand/v2" "math/rand"
"time"
) )
// 随机生成字符串 //随机生成字符串
func RandomString(l int) string { func RandomString(l int) string {
str := "0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz" str := "0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
bytes := []byte(str) bytes := []byte(str)
var result []byte = make([]byte, 0, l) var result []byte = make([]byte, 0, l)
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < l; i++ { for i := 0; i < l; i++ {
result = append(result, bytes[rand.IntN(len(bytes))]) result = append(result, bytes[r.Intn(len(bytes))])
} }
return string(result) return BytesToString(result)
} }
// 随机生成纯字符串 //随机生成纯字符串
func RandomPureString(l int) string { func RandomPureString(l int) string {
str := "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz" str := "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
bytes := []byte(str) bytes := []byte(str)
var result []byte = make([]byte, 0, l) var result []byte = make([]byte, 0, l)
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < l; i++ { for i := 0; i < l; i++ {
result = append(result, bytes[rand.IntN(len(bytes))]) result = append(result, bytes[r.Intn(len(bytes))])
} }
return string(result) return BytesToString(result)
} }
// 随机生成纯大写字符串 //随机生成数字字符串
func RandomPureUpString(l int) string {
str := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
bytes := []byte(str)
var result []byte = make([]byte, 0, l)
for i := 0; i < l; i++ {
result = append(result, bytes[rand.IntN(len(bytes))])
}
return string(result)
}
// 随机生成数字字符串
func RandomNumber(l int) string { func RandomNumber(l int) string {
str := "0123456789" str := "0123456789"
bytes := []byte(str) bytes := []byte(str)
var result []byte var result []byte
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < l; i++ { for i := 0; i < l; i++ {
result = append(result, bytes[rand.IntN(len(bytes))]) result = append(result, bytes[r.Intn(len(bytes))])
} }
return string(result) return BytesToString(result)
} }

View File

@ -1,8 +0,0 @@
package vars
const (
// NormalStatus .
NormalStatus = 1
// DisabledStatus .
DisabledStatus = -1
)