Browse Source

update

master
DengBiao 2 years ago
parent
commit
db7a580b28
47 changed files with 2797 additions and 127 deletions
  1. +3
    -0
      go.mod
  2. +5
    -0
      go.sum
  3. +21
    -0
      internal/business/api/business_ext.go
  4. +20
    -0
      internal/business/comm/cloud_upload.go
  5. +119
    -0
      internal/business/comm/db/db_sys_cfg.go
  6. +8
    -0
      internal/business/comm/db/model/sys_cfg.go
  7. +7
    -0
      internal/business/comm/md/app_redis_key.go
  8. +17
    -0
      internal/business/comm/md/cfg_key.go
  9. +33
    -0
      internal/business/comm/md/file.go
  10. +16
    -0
      internal/business/comm/service/qiniu/bucket_create.go
  11. +18
    -0
      internal/business/comm/service/qiniu/bucket_delete.go
  12. +18
    -0
      internal/business/comm/service/qiniu/bucket_get_domain.go
  13. +22
    -0
      internal/business/comm/service/qiniu/init.go
  14. +42
    -0
      internal/business/comm/service/qiniu/req_img_upload.go
  15. +92
    -0
      internal/business/comm/service/svc_file_upload.go
  16. +106
    -0
      internal/business/comm/service/svc_sys_cfg_get.go
  17. +117
    -0
      internal/business/comm/utils/base64.go
  18. +369
    -0
      internal/business/comm/utils/convert.go
  19. +209
    -0
      internal/business/comm/utils/curl.go
  20. +22
    -0
      internal/business/comm/utils/file.go
  21. +245
    -0
      internal/business/comm/utils/logx/log.go
  22. +105
    -0
      internal/business/comm/utils/logx/output.go
  23. +192
    -0
      internal/business/comm/utils/logx/sugar.go
  24. +12
    -0
      internal/business/comm/utils/md5.go
  25. +46
    -0
      internal/business/comm/utils/rand.go
  26. +29
    -0
      internal/business/comm/utils/reply.go
  27. +23
    -0
      internal/business/comm/utils/serialize.go
  28. +208
    -0
      internal/business/comm/utils/time.go
  29. +24
    -0
      internal/business/domain/user/model/im_package.go
  30. +17
    -0
      internal/business/domain/user/model/master.go
  31. +25
    -0
      internal/business/domain/user/repo/im_package_dao.go
  32. +18
    -0
      internal/business/domain/user/repo/im_package_repo.go
  33. +51
    -0
      internal/business/domain/user/repo/master_cache.go
  34. +38
    -0
      internal/business/domain/user/repo/master_dao.go
  35. +37
    -0
      internal/business/domain/user/repo/master_repo.go
  36. +17
    -3
      internal/logic/api/logic_ext_test.go
  37. +16
    -0
      pkg/grpclib/ctx.go
  38. +335
    -116
      pkg/pb/business.ext.pb.go
  39. +1
    -1
      pkg/pb/business.int.pb.go
  40. +1
    -1
      pkg/pb/connect.int.pb.go
  41. +1
    -1
      pkg/pb/logic.ext.pb.go
  42. +1
    -1
      pkg/pb/logic.int.pb.go
  43. +14
    -1
      pkg/proto/business.ext.proto
  44. +2
    -0
      pkg/rpc/rpc.go
  45. +9
    -2
      pkg/util/json.go
  46. +61
    -0
      pkg/util/redis.go
  47. +5
    -1
      test/tcp_conn/main.go

+ 3
- 0
go.mod View File

@@ -38,6 +38,7 @@ require (
github.com/golang/glog v1.0.0 // indirect github.com/golang/glog v1.0.0 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/gofuzz v1.1.0 // indirect github.com/google/gofuzz v1.1.0 // indirect
github.com/gookit/color v1.3.6 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
@@ -48,12 +49,14 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect github.com/onsi/ginkgo v1.16.5 // indirect
github.com/qiniu/api.v7/v7 v7.8.2 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect github.com/ugorji/go/codec v1.1.7 // indirect
go.uber.org/atomic v1.7.0 // indirect go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect go.uber.org/multierr v1.6.0 // indirect
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
golang.org/x/net v0.1.0 // indirect golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.1.0 // indirect golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect golang.org/x/text v0.4.0 // indirect


+ 5
- 0
go.sum View File

@@ -235,6 +235,8 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/gookit/color v1.3.6 h1:Rgbazd4JO5AgSTVGS3o0nvaSdwdrS8bzvIXwtK6OiMk=
github.com/gookit/color v1.3.6/go.mod h1:R3ogXq2B9rTbXoSHJ1HyUVAZ3poOJHpd9nQmyGZsfvQ=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@@ -320,6 +322,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/qiniu/api.v7/v7 v7.8.2 h1:f08kI0MmsJNzK4sUS8bG3HDH67ktwd/ji23Gkiy2ra4=
github.com/qiniu/api.v7/v7 v7.8.2/go.mod h1:FPsIqxh1Ym3X01sANE5ZwXfLZSWoCUp5+jNI8cLo3l0=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
@@ -486,6 +490,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=


+ 21
- 0
internal/business/api/business_ext.go View File

@@ -3,8 +3,11 @@ package api
import ( import (
"context" "context"
"gim/internal/business/app" "gim/internal/business/app"
comm "gim/internal/business/comm"
"gim/internal/business/comm/utils"
"gim/pkg/grpclib" "gim/pkg/grpclib"
"gim/pkg/pb" "gim/pkg/pb"
"strconv"
) )


type BusinessExtServer struct{} type BusinessExtServer struct{}
@@ -45,3 +48,21 @@ func (s *BusinessExtServer) SearchUser(ctx context.Context, req *pb.SearchUserRe
users, err := app.UserApp.Search(ctx, req.Key, req.MasterId) users, err := app.UserApp.Search(ctx, req.Key, req.MasterId)
return &pb.SearchUserResp{Users: users}, err return &pb.SearchUserResp{Users: users}, err
} }

func (s *BusinessExtServer) CloudUploadFile(ctx context.Context, req *pb.CloudUploadFileReq) (*pb.CloudUploadFileResp, error) {
userId, _, err := grpclib.GetCtxData(ctx)
if err != nil {
return nil, err
}
upload, err := comm.CloudUpload.FileReqUpload(ctx, strconv.FormatInt(userId, 10), req.Dir, req.FileName, utils.StrToInt64(req.FileSize))
data := utils.SerializeStr(upload)
var result map[string]string
utils.Unserialize([]byte(data), &result)

return &pb.CloudUploadFileResp{
Method: result["method"],
Host: result["host"],
Key: result["key"],
Token: result["token"],
}, err
}

+ 20
- 0
internal/business/comm/cloud_upload.go View File

@@ -0,0 +1,20 @@
package app

import (
"context"
svc "gim/internal/business/comm/service"
"gim/pkg/grpclib"
)

type cloudUpload struct{}

var CloudUpload = new(cloudUpload)

// FileReqUpload 请求文件上传
func (*cloudUpload) FileReqUpload(ctx context.Context, uid, dirName, fName string, fSize int64) (interface{}, error) {
masterId, _ := grpclib.GetCtxMasterId(ctx)

callbackUrl := svc.SysCfgGet("-1", "cloud_file_upload_call_back_url")
callbackUrl = callbackUrl + masterId
return svc.FileReqUpload(ctx, uid, dirName, fName, callbackUrl, fSize)
}

+ 119
- 0
internal/business/comm/db/db_sys_cfg.go View File

@@ -0,0 +1,119 @@
package db

import (
"fmt"
"gim/internal/business/comm/db/model"
"gim/internal/business/comm/md"
"gim/internal/business/comm/utils"
"gim/internal/business/comm/utils/logx"
"gim/pkg/db"
"gim/pkg/gerrors"
)

type dbSysCfg struct{}

var DbSysCfg = new(dbSysCfg)

// SysCfgGetAll 获取系统配置
func (*dbSysCfg) SysCfgGetAll(masterId int64) (*[]model.SysCfg, error) {
var cfgList []model.SysCfg
if err := db.DB.Where("`master_id`=?", masterId).Find(&cfgList).Error; err != nil {
return nil, gerrors.WrapError(err)
}
return &cfgList, nil
}

// SysCfgGetOne 获取一条记录
func (*dbSysCfg) SysCfgGetOne(key string, masterId int64) (*model.SysCfg, error) {
var cfgList model.SysCfg
if err := db.DB.Where("`key` = ? and `master_id` = ?", key, masterId).First(&cfgList).Error; err != nil {
return nil, gerrors.WrapError(err)
}
return &cfgList, nil
}

// SysCfgInsert 插入一条配置信息
func (*dbSysCfg) SysCfgInsert(key, val, memo string, masterId int64) bool {
cfg := model.SysCfg{Key: key, Val: val, Memo: memo, MasterId: masterId}
err := db.DB.Create(&cfg).Error
if err != nil {
logx.Error(err)
return false
}
return true
}

// SysCfgUpdate 修改某条配置信息
func (*dbSysCfg) SysCfgUpdate(key, val, memo string, masterId int64) bool {
cfg := model.SysCfg{Key: key, Val: val, Memo: memo}
err := db.DB.Where("`key` = ? and `master_id` = ?", key, masterId).Update(&cfg).Error
if err != nil {
logx.Error(err)
return false
}
return true
}

// SysCfgGetWithDb 单条记录获取
func (*dbSysCfg) SysCfgGetWithDb(masterId string, HKey string) string {
cacheKey := fmt.Sprintf(md.AppCfgCacheKey, masterId, HKey[0:1])
get, err := db.RedisUtil.HGetString(cacheKey, HKey)
if err != nil || get == "" {
cfg, err := DbSysCfg.SysCfgGetOne(HKey, utils.StrToInt64(masterId))
if err != nil || cfg == nil {
_ = logx.Error(err)
return ""
}

// key是否存在
cacheKeyExist := false
if db.RedisUtil.Exists(cacheKey) {
cacheKeyExist = true
}

// 设置缓存
_, err = db.RedisUtil.HSet(cacheKey, HKey, cfg.Val)
if err != nil {
_ = logx.Error(err)
return ""
}
if !cacheKeyExist { // 如果是首次设置 设置过期时间
_, err := db.RedisUtil.Expire(cacheKey, md.CfgCacheTime)
if err != nil {
_ = logx.Error(err)
return ""
}
}
return cfg.Val
}
return get
}

// SysCfgFindWithDb 多条记录获取
func (*dbSysCfg) SysCfgFindWithDb(masterId string, keys ...string) map[string]string {
res := map[string]string{}
cacheKey := fmt.Sprintf(md.AppCfgCacheKey, masterId)
err := db.RedisUtil.GetJson(cacheKey, &res)
if err != nil || len(res) == 0 {
cfgList, _ := DbSysCfg.SysCfgGetAll(utils.StrToInt64(masterId))
if cfgList == nil {
return nil
}
for _, v := range *cfgList {
res[v.Key] = v.Val
}
db.RedisUtil.SetJson(cacheKey, res, md.CfgCacheTime)
}
if len(keys) == 0 {
return res
}
tmp := map[string]string{}
for _, v := range keys {
if val, ok := res[v]; ok {
tmp[v] = val
} else {
tmp[v] = ""
}
}
return tmp
}

+ 8
- 0
internal/business/comm/db/model/sys_cfg.go View File

@@ -0,0 +1,8 @@
package model

type SysCfg struct {
Key string // 键
Val string // 值
Memo string // 备注
MasterId int64 // 站长id
}

+ 7
- 0
internal/business/comm/md/app_redis_key.go View File

@@ -0,0 +1,7 @@
package md

// 缓存key统一管理, %s格式化为masterId
const (
AppCfgCacheKey = "%s:gim_cfg_cache:%s" // 占位符: masterId, key的第一个字母
CfgCacheTime = 86400
)

+ 17
- 0
internal/business/comm/md/cfg_key.go View File

@@ -0,0 +1,17 @@
package md

// 获取用户的缓存key
const (
KEY_SYS_CFG_CACHE = "gim_sys_cfg_cache"

// 文件缓存的key
KEY_CFG_FILE_PVD = "file_provider" // 文件供应商
KEY_CFG_FILE_BUCKET = "file_bucket"
KEY_CFG_FILE_REGION = "file_bucket_region"
KEY_CFG_FILE_HOST = "file_bucket_host"
KEY_CFG_FILE_SCHEME = "file_bucket_scheme"
KEY_CFG_FILE_AK = "file_access_key"
KEY_CFG_FILE_SK = "file_secret_key"
KEY_CFG_FILE_MAX_SIZE = "file_user_upload_max_size"
KEY_CFG_FILE_EXT = "file_ext"
)

+ 33
- 0
internal/business/comm/md/file.go View File

@@ -0,0 +1,33 @@
package md

// 用户拥有上传权限的目录, 目录ID

const (
FILE_DIR_IMAGE = "image"
FILE_DIR_VIDEO = "video"
FILE_DIR_FILE = "file"
)

var (
FileUserDir = map[string]string{
FILE_DIR_IMAGE: "1", // 图片上传
FILE_DIR_VIDEO: "2", // 视频上传
FILE_DIR_FILE: "3", // 文件上传
}
)

// 文件回调信息
type FileCallback struct {
Uid string `json:"uid"`
DirId string `json:"dir_id"`
Provider string `json:"provider"` // 供应商
FileName string `json:"fname"` // 原文件名
FileSize string `json:"fsize"`
Hash string `json:"hash"`
Bucket string `json:"bucket"`
Mime string `json:"mime"`
Width string `json:"w,omitempty"`
Height string `json:"h,omitempty"`
Time string `json:"time"` // 默认一个小时内要上传完毕,否则超时
Sign string `json:"sign"` // 签名
}

+ 16
- 0
internal/business/comm/service/qiniu/bucket_create.go View File

@@ -0,0 +1,16 @@
package qiniu

import (
"github.com/qiniu/api.v7/v7/auth"
"github.com/qiniu/api.v7/v7/storage"
)

func BucketCreate() error {
mac := auth.New(AK, SK)
cfg := storage.Config{
// 是否使用https域名进行资源管理
UseHTTPS: false,
}
bucketManager := storage.NewBucketManager(mac, &cfg)
return bucketManager.CreateBucket("", storage.RIDHuanan)
}

+ 18
- 0
internal/business/comm/service/qiniu/bucket_delete.go View File

@@ -0,0 +1,18 @@
package qiniu

import (
"github.com/qiniu/api.v7/v7/auth"
"github.com/qiniu/api.v7/v7/storage"
)

func BucketDelete(bucketName string) error {
mac := auth.New(AK, SK)

cfg := storage.Config{
// 是否使用https域名进行资源管理
UseHTTPS: false,
}

bucketManager := storage.NewBucketManager(mac, &cfg)
return bucketManager.DropBucket(bucketName)
}

+ 18
- 0
internal/business/comm/service/qiniu/bucket_get_domain.go View File

@@ -0,0 +1,18 @@
package qiniu

import (
"github.com/qiniu/api.v7/v7/auth"
"github.com/qiniu/api.v7/v7/storage"
)

func BucketGetDomain(bucketName string) (string, error) {
mac := auth.New(AK, SK)

cfg := storage.Config{UseHTTPS: false}
bucketManager := storage.NewBucketManager(mac, &cfg)
b, err := bucketManager.ListBucketDomains(bucketName)
if err != nil {
return "", err
}
return b[0].Domain, nil
}

+ 22
- 0
internal/business/comm/service/qiniu/init.go View File

@@ -0,0 +1,22 @@
package qiniu

import (
"gim/internal/business/comm/utils"
)

var (
AK = "MmxNdai23egjNUHjdzEVaTPdPCIbWzENz9BQuak3"
SK = "mElaFlM9O16rXp-ihoQdJ9KOH56naKm3MoyQBA59"
BUCKET = "dev-fnuoos" // 桶子名称
BUCKET_SCHEME = "http"
BUCKET_REGION = "up-z2.qiniup.com"
Expires uint64 = 3600
)

func Init(ak, sk, bucket, region, scheme string) {
AK, SK, BUCKET, BUCKET_REGION, BUCKET_SCHEME = ak, sk, bucket, region, scheme
}

func Sign(t string) string {
return utils.Md5(AK + SK + t)
}

+ 42
- 0
internal/business/comm/service/qiniu/req_img_upload.go View File

@@ -0,0 +1,42 @@
package qiniu

import (
"gim/internal/business/comm/md"
"gim/internal/business/comm/utils"
"time"

"github.com/qiniu/api.v7/v7/auth/qbox"
_ "github.com/qiniu/api.v7/v7/conf"
"github.com/qiniu/api.v7/v7/storage"
)

// 请求图片上传地址信息
func ReqImgUpload(f *md.FileCallback, callbackUrl string) interface{} {
if ext := utils.FileExt(f.FileName); ext == "png" || ext == "jpg" || ext == "jpeg" || ext == "gif" || ext == "bmp" || ext == "webp" {
f.Width = "$(imageInfo.width)"
f.Height = "$(imageInfo.height)"
}
f.Provider = "qiniu"
f.FileSize = "$(fsize)"
f.Hash = "$(etag)"
f.Bucket = "$(bucket)"
f.Mime = "$(mimeType)"
f.Time = utils.Int64ToStr(time.Now().Unix())
f.Sign = Sign(f.Time)
putPolicy := storage.PutPolicy{
Scope: BUCKET + ":" + f.FileName, // 使用覆盖方式时候必须请求里面有key,否则报错
Expires: Expires,
ForceSaveKey: true,
SaveKey: f.FileName,
//MimeLimit: "image/*", // 只允许上传图片
CallbackURL: callbackUrl,
CallbackBody: utils.SerializeStr(f),
CallbackBodyType: "application/json",
}
return &struct {
Method string `json:"method"`
Key string `json:"key"`
Host string `json:"host"`
Token string `json:"token"`
}{Key: f.FileName, Method: "POST", Host: BUCKET_SCHEME + "://" + BUCKET_REGION, Token: putPolicy.UploadToken(qbox.NewMac(AK, SK))}
}

+ 92
- 0
internal/business/comm/service/svc_file_upload.go View File

@@ -0,0 +1,92 @@
package svc

import (
"context"
"errors"
"fmt"
"gim/internal/business/comm/md"
"gim/internal/business/comm/service/qiniu"
"gim/internal/business/comm/utils"
"gim/internal/business/comm/utils/logx"
"strings"
)

// 请求文件上传
func FileReqUpload(ctx context.Context, uid, dirName, fName, callbackUrl string, fSize int64) (interface{}, error) {
ext := utils.FileExt(fName)
if err := initStg(ctx, fSize, ext); err != nil {
return nil, err
}
newName := dirName + "_" + fmt.Sprintf("%010s", uid)

// 默认都加时间戳
newName += "_" + utils.FormatNanoUnix() + utils.RandString(4, "0123456789")
newName += "." + ext

f := &md.FileCallback{
Uid: uid,
DirId: md.FileUserDir[dirName],
FileName: newName,
}
return qiniu.ReqImgUpload(f, callbackUrl), nil
}

func initStg(ctx context.Context, fSize int64, ext string) error {
// 获取上传配置
stgInfo := SysCfgFind(
ctx,
md.KEY_CFG_FILE_BUCKET,
md.KEY_CFG_FILE_HOST,
md.KEY_CFG_FILE_AK,
md.KEY_CFG_FILE_SK,
md.KEY_CFG_FILE_PVD,
md.KEY_CFG_FILE_REGION,
md.KEY_CFG_FILE_MAX_SIZE,
md.KEY_CFG_FILE_EXT,
md.KEY_CFG_FILE_SCHEME,
)

if stgInfo == nil {
return errors.New("获取配置信息出错")
}
// todo 目前仅支持七牛
if v, ok := stgInfo[md.KEY_CFG_FILE_PVD]; !ok || v != "qiniu" {
return errors.New("file_provider error")
}
if v, ok := stgInfo[md.KEY_CFG_FILE_REGION]; !ok || v == "" {
return errors.New("file_bucket_region error")
}
if v, ok := stgInfo[md.KEY_CFG_FILE_AK]; !ok || v == "" {
return errors.New("file_access_key error")
}
if v, ok := stgInfo[md.KEY_CFG_FILE_SK]; !ok || v == "" {
return errors.New("file_secret_key error")
}
if v, ok := stgInfo[md.KEY_CFG_FILE_BUCKET]; !ok || v == "" {
return errors.New("file_bucket error")
}
if v, ok := stgInfo[md.KEY_CFG_FILE_SCHEME]; !ok || v == "" {
stgInfo[md.KEY_CFG_FILE_SCHEME] = "http"
SysCfgSet(ctx, md.KEY_CFG_FILE_SCHEME, stgInfo[md.KEY_CFG_FILE_SCHEME], "文件域名HTTP协议")
}
qiniu.Init(stgInfo[md.KEY_CFG_FILE_AK], stgInfo[md.KEY_CFG_FILE_SK], stgInfo[md.KEY_CFG_FILE_BUCKET], stgInfo[md.KEY_CFG_FILE_REGION], stgInfo[md.KEY_CFG_FILE_SCHEME])
if v, ok := stgInfo[md.KEY_CFG_FILE_HOST]; !ok || v == "" {
var err error
stgInfo[md.KEY_CFG_FILE_HOST], err = qiniu.BucketGetDomain(stgInfo[md.KEY_CFG_FILE_BUCKET])
if err != nil {
logx.Error(err)
return errors.New("服务器配置错误")
}
SysCfgSet(ctx, md.KEY_CFG_FILE_HOST, stgInfo[md.KEY_CFG_FILE_HOST], "文件域名地址")
}

// 检查文件大小限制
if v, ok := stgInfo[md.KEY_CFG_FILE_MAX_SIZE]; ok && v != "" && utils.StrToInt64(v) < fSize {
return errors.New("file_user_upload_max_size error")
}
// 检查文件后缀
if v, ok := stgInfo[md.KEY_CFG_FILE_EXT]; ok && v != "" && !strings.Contains(v, ext) {
return errors.New("file_ext error")
}
return nil
}

+ 106
- 0
internal/business/comm/service/svc_sys_cfg_get.go View File

@@ -0,0 +1,106 @@
package svc

import (
"context"
"fmt"
"gim/internal/business/comm/db"
"gim/internal/business/comm/md"
"gim/internal/business/comm/utils"
db2 "gim/pkg/db"
"gim/pkg/grpclib"
)

// 单挑记录获取
func SysCfgGet(masterId, key string) string {
return db.DbSysCfg.SysCfgGetWithDb(masterId, key)
}

// 多条记录获取
func SysCfgFind(ctx context.Context, keys ...string) map[string]string {
masterId, _ := grpclib.GetCtxMasterId(ctx)
tmp := SysCfgFindComm(masterId, keys...)
return tmp
}

// SysCfgGetByMasterId get one config by master id
func SysCfgGetByMasterId(masterId, key string) string {
res := SysCfgFindComm(masterId, key)
if _, ok := res[key]; !ok {
return ""
}
return res[key]
}

// SysCfgFindComm get cfg by master id
func SysCfgFindComm(masterId string, keys ...string) map[string]string {
res := map[string]string{}
cfgKey := fmt.Sprintf("%s:gim_cfg_cache", masterId)
err := db2.RedisUtil.GetJson(cfgKey, &res)
if err != nil || len(res) == 0 {
cfgList, _ := db.DbSysCfg.SysCfgGetAll(utils.StrToInt64(masterId))
if cfgList == nil {
return nil
}
for _, v := range *cfgList {
res[v.Key] = v.Val
}
db2.RedisUtil.SetJson(cfgKey, res, 1800)
}
if len(keys) == 0 {
return res
}
tmp := map[string]string{}
for _, v := range keys {
if val, ok := res[v]; ok {
tmp[v] = val
} else {
tmp[v] = ""
}
}
return tmp
}

// EgSysCfgFind 多条记录获取
func EgSysCfgFind(masterId string, keys ...string) map[string]string {
res := map[string]string{}
if len(res) == 0 {
cfgList, _ := db.DbSysCfg.SysCfgGetAll(utils.StrToInt64(masterId))
if cfgList == nil {
return nil
}
for _, v := range *cfgList {
res[v.Key] = v.Val
}
}
if len(keys) == 0 {
return res
}
tmp := map[string]string{}
for _, v := range keys {
if val, ok := res[v]; ok {
tmp[v] = val
} else {
tmp[v] = ""
}
}
return tmp
}

// SysCfgCleanCache 清理系统配置信息
func SysCfgCleanCache() {
db2.RedisUtil.Del(md.KEY_SYS_CFG_CACHE)
}

// SysCfgSet 写入系统设置
func SysCfgSet(ctx context.Context, key, val, memo string) bool {
masterId, _ := grpclib.GetCtxMasterId(ctx)
cfg, err := db.DbSysCfg.SysCfgGetOne(key, utils.StrToInt64(masterId))
if err != nil || cfg == nil {
return db.DbSysCfg.SysCfgInsert(key, val, memo, utils.StrToInt64(masterId))
}
if memo != "" && cfg.Memo != memo {
cfg.Memo = memo
}
SysCfgCleanCache()
return db.DbSysCfg.SysCfgUpdate(key, val, cfg.Memo, utils.StrToInt64(masterId))
}

+ 117
- 0
internal/business/comm/utils/base64.go View File

@@ -0,0 +1,117 @@
package utils

import (
"encoding/base64"
"fmt"
"regexp"
)

const (
Base64Std = iota
Base64Url
Base64RawStd
Base64RawUrl
)

func Base64StdEncode(str interface{}) string {
return Base64Encode(str, Base64Std)
}

func Base64StdDecode(str interface{}) string {
return Base64Decode(str, Base64Std)
}

func Base64UrlEncode(str interface{}) string {
return Base64Encode(str, Base64Url)
}

func Base64UrlDecode(str interface{}) string {
return Base64Decode(str, Base64Url)
}

func Base64RawStdEncode(str interface{}) string {
return Base64Encode(str, Base64RawStd)
}

func Base64RawStdDecode(str interface{}) string {
return Base64Decode(str, Base64RawStd)
}

func Base64RawUrlEncode(str interface{}) string {
return Base64Encode(str, Base64RawUrl)
}

func Base64RawUrlDecode(str interface{}) string {
return Base64Decode(str, Base64RawUrl)
}

func Base64Encode(str interface{}, encode int) string {
newEncode := base64Encode(encode)
if newEncode == nil {
return ""
}
switch v := str.(type) {
case string:
return newEncode.EncodeToString([]byte(v))
case []byte:
return newEncode.EncodeToString(v)
}
return newEncode.EncodeToString([]byte(fmt.Sprint(str)))
}

func Base64Decode(str interface{}, encode int) string {
var err error
var b []byte
newEncode := base64Encode(encode)
if newEncode == nil {
return ""
}
switch v := str.(type) {
case string:
b, err = newEncode.DecodeString(v)
case []byte:
b, err = newEncode.DecodeString(string(v))
default:
return ""
}
if err != nil {
return ""
}
return string(b)
}

func base64Encode(encode int) *base64.Encoding {
switch encode {
case Base64Std:
return base64.StdEncoding
case Base64Url:
return base64.URLEncoding
case Base64RawStd:
return base64.RawStdEncoding
case Base64RawUrl:
return base64.RawURLEncoding
default:
return nil
}
}

func JudgeBase64(str string) bool {
pattern := "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$"
matched, err := regexp.MatchString(pattern, str)
if err != nil {
return false
}
if !(len(str)%4 == 0 && matched) {
return false
}
unCodeStr, err := base64.StdEncoding.DecodeString(str)
if err != nil {
return false
}
tranStr := base64.StdEncoding.EncodeToString(unCodeStr)
//return str==base64.StdEncoding.EncodeToString(unCodeStr)
if str == tranStr {
return true
}
return false
}

+ 369
- 0
internal/business/comm/utils/convert.go View File

@@ -0,0 +1,369 @@
package utils

import (
"encoding/binary"
"encoding/json"
"fmt"
"math"
"strconv"
"strings"
)

func ToString(raw interface{}, e error) (res string) {
if e != nil {
return ""
}
return AnyToString(raw)
}

func ToInt64(raw interface{}, e error) int64 {
if e != nil {
return 0
}
return AnyToInt64(raw)
}

func Float64ToStrPrec4(f float64) string {
return strconv.FormatFloat(f, 'f', 4, 64)
}
func AnyToBool(raw interface{}) bool {
switch i := raw.(type) {
case float32, float64, int, int64, uint, uint8, uint16, uint32, uint64, int8, int16, int32:
return i != 0
case []byte:
return i != nil
case string:
if i == "false" {
return false
}
return i != ""
case error:
return false
case nil:
return true
}
val := fmt.Sprint(raw)
val = strings.TrimLeft(val, "&")
if strings.TrimLeft(val, "{}") == "" {
return false
}
if strings.TrimLeft(val, "[]") == "" {
return false
}
// ptr type
b, err := json.Marshal(raw)
if err != nil {
return false
}
if strings.TrimLeft(string(b), "\"\"") == "" {
return false
}
if strings.TrimLeft(string(b), "{}") == "" {
return false
}
return true
}

func AnyToInt64(raw interface{}) int64 {
switch i := raw.(type) {
case string:
res, _ := strconv.ParseInt(i, 10, 64)
return res
case []byte:
return BytesToInt64(i)
case int:
return int64(i)
case int64:
return i
case uint:
return int64(i)
case uint8:
return int64(i)
case uint16:
return int64(i)
case uint32:
return int64(i)
case uint64:
return int64(i)
case int8:
return int64(i)
case int16:
return int64(i)
case int32:
return int64(i)
case float32:
return int64(i)
case float64:
return int64(i)
case error:
return 0
case bool:
if i {
return 1
}
return 0
}
return 0
}

func AnyToString(raw interface{}) string {
switch i := raw.(type) {
case []byte:
return string(i)
case int:
return strconv.FormatInt(int64(i), 10)
case int64:
return strconv.FormatInt(i, 10)
case float32:
return Float64ToStr(float64(i))
case float64:
return Float64ToStr(i)
case uint:
return strconv.FormatInt(int64(i), 10)
case uint8:
return strconv.FormatInt(int64(i), 10)
case uint16:
return strconv.FormatInt(int64(i), 10)
case uint32:
return strconv.FormatInt(int64(i), 10)
case uint64:
return strconv.FormatInt(int64(i), 10)
case int8:
return strconv.FormatInt(int64(i), 10)
case int16:
return strconv.FormatInt(int64(i), 10)
case int32:
return strconv.FormatInt(int64(i), 10)
case string:
return i
case error:
return i.Error()
case bool:
return strconv.FormatBool(i)
}
return fmt.Sprintf("%#v", raw)
}

func AnyToFloat64(raw interface{}) float64 {
switch i := raw.(type) {
case []byte:
f, _ := strconv.ParseFloat(string(i), 64)
return f
case int:
return float64(i)
case int64:
return float64(i)
case float32:
return float64(i)
case float64:
return i
case uint:
return float64(i)
case uint8:
return float64(i)
case uint16:
return float64(i)
case uint32:
return float64(i)
case uint64:
return float64(i)
case int8:
return float64(i)
case int16:
return float64(i)
case int32:
return float64(i)
case string:
f, _ := strconv.ParseFloat(i, 64)
return f
case bool:
if i {
return 1
}
}
return 0
}

func ToByte(raw interface{}, e error) []byte {
if e != nil {
return []byte{}
}
switch i := raw.(type) {
case string:
return []byte(i)
case int:
return Int64ToBytes(int64(i))
case int64:
return Int64ToBytes(i)
case float32:
return Float32ToByte(i)
case float64:
return Float64ToByte(i)
case uint:
return Int64ToBytes(int64(i))
case uint8:
return Int64ToBytes(int64(i))
case uint16:
return Int64ToBytes(int64(i))
case uint32:
return Int64ToBytes(int64(i))
case uint64:
return Int64ToBytes(int64(i))
case int8:
return Int64ToBytes(int64(i))
case int16:
return Int64ToBytes(int64(i))
case int32:
return Int64ToBytes(int64(i))
case []byte:
return i
case error:
return []byte(i.Error())
case bool:
if i {
return []byte("true")
}
return []byte("false")
}
return []byte(fmt.Sprintf("%#v", raw))
}

func Int64ToBytes(i int64) []byte {
var buf = make([]byte, 8)
binary.BigEndian.PutUint64(buf, uint64(i))
return buf
}

func BytesToInt64(buf []byte) int64 {
return int64(binary.BigEndian.Uint64(buf))
}

func StrToInt(s string) int {
res, _ := strconv.Atoi(s)
return res
}

func StrToInt64(s string) int64 {
res, _ := strconv.ParseInt(s, 10, 64)
return res
}

func Float32ToByte(float float32) []byte {
bits := math.Float32bits(float)
bytes := make([]byte, 4)
binary.LittleEndian.PutUint32(bytes, bits)

return bytes
}

func ByteToFloat32(bytes []byte) float32 {
bits := binary.LittleEndian.Uint32(bytes)
return math.Float32frombits(bits)
}

func Float64ToByte(float float64) []byte {
bits := math.Float64bits(float)
bytes := make([]byte, 8)
binary.LittleEndian.PutUint64(bytes, bits)
return bytes
}

func ByteToFloat64(bytes []byte) float64 {
bits := binary.LittleEndian.Uint64(bytes)
return math.Float64frombits(bits)
}

func Float64ToStr(f float64) string {
return strconv.FormatFloat(f, 'f', 2, 64)
}
func Float64ToStrPrec1(f float64) string {
return strconv.FormatFloat(f, 'f', 1, 64)
}
func Float64ToStrByPrec(f float64, prec int) string {
return strconv.FormatFloat(f, 'f', prec, 64)
}

func Float32ToStr(f float32) string {
return Float64ToStr(float64(f))
}

func StrToFloat64(s string) float64 {
res, err := strconv.ParseFloat(s, 64)
if err != nil {
return 0
}
return res
}
func StrToFormat(s string, prec int) string {
ex := strings.Split(s, ".")
if len(ex) == 2 {
if StrToFloat64(ex[1]) == 0 { //小数点后面为空就是不要小数点了
return ex[0]
}
//看取多少位
str := ex[1]
str1 := str
if prec < len(str) {
str1 = str[0:prec]
} else {
for i := 0; i < prec-len(str); i++ {
str1 += "0"
}
}
if prec > 0 {
return ex[0] + "." + str1
} else {
return ex[0]
}
}
return s
}

func StrToFloat32(s string) float32 {
res, err := strconv.ParseFloat(s, 32)
if err != nil {
return 0
}
return float32(res)
}

func StrToBool(s string) bool {
b, _ := strconv.ParseBool(s)
return b
}

func BoolToStr(b bool) string {
if b {
return "true"
}
return "false"
}

func FloatToInt64(f float64) int64 {
return int64(f)
}

func IntToStr(i int) string {
return strconv.Itoa(i)
}

func Int64ToStr(i int64) string {
return strconv.FormatInt(i, 10)
}

func IntToFloat64(i int) float64 {
s := strconv.Itoa(i)
res, err := strconv.ParseFloat(s, 64)
if err != nil {
return 0
}
return res
}
func Int64ToFloat64(i int64) float64 {
s := strconv.FormatInt(i, 10)
res, err := strconv.ParseFloat(s, 64)
if err != nil {
return 0
}
return res
}

+ 209
- 0
internal/business/comm/utils/curl.go View File

@@ -0,0 +1,209 @@
package utils

import (
"bytes"
"crypto/tls"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"sort"
"strings"
"time"
)

var CurlDebug bool

func CurlGet(router string, header map[string]string) ([]byte, error) {
return curl(http.MethodGet, router, nil, header)
}
func CurlGetJson(router string, body interface{}, header map[string]string) ([]byte, error) {
return curl_new(http.MethodGet, router, body, header)
}

// 只支持form 与json 提交, 请留意body的类型, 支持string, []byte, map[string]string
func CurlPost(router string, body interface{}, header map[string]string) ([]byte, error) {
return curl(http.MethodPost, router, body, header)
}

func CurlPut(router string, body interface{}, header map[string]string) ([]byte, error) {
return curl(http.MethodPut, router, body, header)
}

// 只支持form 与json 提交, 请留意body的类型, 支持string, []byte, map[string]string
func CurlPatch(router string, body interface{}, header map[string]string) ([]byte, error) {
return curl(http.MethodPatch, router, body, header)
}

// CurlDelete is curl delete
func CurlDelete(router string, body interface{}, header map[string]string) ([]byte, error) {
return curl(http.MethodDelete, router, body, header)
}

func curl(method, router string, body interface{}, header map[string]string) ([]byte, error) {
var reqBody io.Reader
contentType := "application/json"
switch v := body.(type) {
case string:
reqBody = strings.NewReader(v)
case []byte:
reqBody = bytes.NewReader(v)
case map[string]string:
val := url.Values{}
for k, v := range v {
val.Set(k, v)
}
reqBody = strings.NewReader(val.Encode())
contentType = "application/x-www-form-urlencoded"
case map[string]interface{}:
val := url.Values{}
for k, v := range v {
val.Set(k, v.(string))
}
reqBody = strings.NewReader(val.Encode())
contentType = "application/x-www-form-urlencoded"
}
if header == nil {
header = map[string]string{"Content-Type": contentType}
}
if _, ok := header["Content-Type"]; !ok {
header["Content-Type"] = contentType
}
resp, er := CurlReq(method, router, reqBody, header)
if er != nil {
return nil, er
}
res, err := ioutil.ReadAll(resp.Body)
if CurlDebug {
blob := SerializeStr(body)
if contentType != "application/json" {
blob = HttpBuild(body)
}
fmt.Printf("\n\n=====================\n[url]: %s\n[time]: %s\n[method]: %s\n[content-type]: %v\n[req_header]: %s\n[req_body]: %#v\n[resp_err]: %v\n[resp_header]: %v\n[resp_body]: %v\n=====================\n\n",
router,
time.Now().Format("2006-01-02 15:04:05.000"),
method,
contentType,
HttpBuildQuery(header),
blob,
err,
SerializeStr(resp.Header),
string(res),
)
}
resp.Body.Close()
return res, err
}

func curl_new(method, router string, body interface{}, header map[string]string) ([]byte, error) {
var reqBody io.Reader
contentType := "application/json"

if header == nil {
header = map[string]string{"Content-Type": contentType}
}
if _, ok := header["Content-Type"]; !ok {
header["Content-Type"] = contentType
}
resp, er := CurlReq(method, router, reqBody, header)
if er != nil {
return nil, er
}
res, err := ioutil.ReadAll(resp.Body)
if CurlDebug {
blob := SerializeStr(body)
if contentType != "application/json" {
blob = HttpBuild(body)
}
fmt.Printf("\n\n=====================\n[url]: %s\n[time]: %s\n[method]: %s\n[content-type]: %v\n[req_header]: %s\n[req_body]: %#v\n[resp_err]: %v\n[resp_header]: %v\n[resp_body]: %v\n=====================\n\n",
router,
time.Now().Format("2006-01-02 15:04:05.000"),
method,
contentType,
HttpBuildQuery(header),
blob,
err,
SerializeStr(resp.Header),
string(res),
)
}
resp.Body.Close()
return res, err
}

func CurlReq(method, router string, reqBody io.Reader, header map[string]string) (*http.Response, error) {
req, _ := http.NewRequest(method, router, reqBody)
if header != nil {
for k, v := range header {
req.Header.Set(k, v)
}
}
// 绕过github等可能因为特征码返回503问题
// https://www.imwzk.com/posts/2021-03-14-why-i-always-get-503-with-golang/
defaultCipherSuites := []uint16{0xc02f, 0xc030, 0xc02b, 0xc02c, 0xcca8, 0xcca9, 0xc013, 0xc009,
0xc014, 0xc00a, 0x009c, 0x009d, 0x002f, 0x0035, 0xc012, 0x000a}
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
CipherSuites: append(defaultCipherSuites[8:], defaultCipherSuites[:8]...),
},
},
// 获取301重定向
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
return client.Do(req)
}

// 组建get请求参数,sortAsc true为小到大,false为大到小,nil不排序 a=123&b=321
func HttpBuildQuery(args map[string]string, sortAsc ...bool) string {
str := ""
if len(args) == 0 {
return str
}
if len(sortAsc) > 0 {
keys := make([]string, 0, len(args))
for k := range args {
keys = append(keys, k)
}
if sortAsc[0] {
sort.Strings(keys)
} else {
sort.Sort(sort.Reverse(sort.StringSlice(keys)))
}
for _, k := range keys {
str += "&" + k + "=" + args[k]
}
} else {
for k, v := range args {
str += "&" + k + "=" + v
}
}
return str[1:]
}

func HttpBuild(body interface{}, sortAsc ...bool) string {
params := map[string]string{}
if args, ok := body.(map[string]interface{}); ok {
for k, v := range args {
params[k] = AnyToString(v)
}
return HttpBuildQuery(params, sortAsc...)
}
if args, ok := body.(map[string]string); ok {
for k, v := range args {
params[k] = AnyToString(v)
}
return HttpBuildQuery(params, sortAsc...)
}
if args, ok := body.(map[string]int); ok {
for k, v := range args {
params[k] = AnyToString(v)
}
return HttpBuildQuery(params, sortAsc...)
}
return AnyToString(body)
}

+ 22
- 0
internal/business/comm/utils/file.go View File

@@ -0,0 +1,22 @@
package utils

import (
"os"
"path"
"strings"
"time"
)

// 获取文件后缀
func FileExt(fname string) string {
return strings.ToLower(strings.TrimLeft(path.Ext(fname), "."))
}

func FilePutContents(fileName string, content string) {
fd, _ := os.OpenFile("./tmp/"+fileName+".log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
fd_time := time.Now().Format("2006-01-02 15:04:05")
fd_content := strings.Join([]string{"[", fd_time, "] ", content, "\n"}, "")
buf := []byte(fd_content)
fd.Write(buf)
fd.Close()
}

+ 245
- 0
internal/business/comm/utils/logx/log.go View File

@@ -0,0 +1,245 @@
package logx

import (
"os"
"strings"
"time"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

type LogConfig struct {
AppName string `yaml:"app_name" json:"app_name" toml:"app_name"`
Level string `yaml:"level" json:"level" toml:"level"`
StacktraceLevel string `yaml:"stacktrace_level" json:"stacktrace_level" toml:"stacktrace_level"`
IsStdOut bool `yaml:"is_stdout" json:"is_stdout" toml:"is_stdout"`
TimeFormat string `yaml:"time_format" json:"time_format" toml:"time_format"` // second, milli, nano, standard, iso,
Encoding string `yaml:"encoding" json:"encoding" toml:"encoding"` // console, json
Skip int `yaml:"skip" json:"skip" toml:"skip"`

IsFileOut bool `yaml:"is_file_out" json:"is_file_out" toml:"is_file_out"`
FileDir string `yaml:"file_dir" json:"file_dir" toml:"file_dir"`
FileName string `yaml:"file_name" json:"file_name" toml:"file_name"`
FileMaxSize int `yaml:"file_max_size" json:"file_max_size" toml:"file_max_size"`
FileMaxAge int `yaml:"file_max_age" json:"file_max_age" toml:"file_max_age"`
}

var (
l *LogX = defaultLogger()
conf *LogConfig
)

// default logger setting
func defaultLogger() *LogX {
conf = &LogConfig{
Level: "debug",
StacktraceLevel: "error",
IsStdOut: true,
TimeFormat: "standard",
Encoding: "console",
Skip: 2,
}
writers := []zapcore.WriteSyncer{os.Stdout}
lg, lv := newZapLogger(setLogLevel(conf.Level), setLogLevel(conf.StacktraceLevel), conf.Encoding, conf.TimeFormat, conf.Skip, zapcore.NewMultiWriteSyncer(writers...))
zap.RedirectStdLog(lg)
return &LogX{logger: lg, atomLevel: lv}
}

// initial standard log, if you don't init, it will use default logger setting
func InitDefaultLogger(cfg *LogConfig) {
var writers []zapcore.WriteSyncer
if cfg.IsStdOut || (!cfg.IsStdOut && !cfg.IsFileOut) {
writers = append(writers, os.Stdout)
}
if cfg.IsFileOut {
writers = append(writers, NewRollingFile(cfg.FileDir, cfg.FileName, cfg.FileMaxSize, cfg.FileMaxAge))
}

lg, lv := newZapLogger(setLogLevel(cfg.Level), setLogLevel(cfg.StacktraceLevel), cfg.Encoding, cfg.TimeFormat, cfg.Skip, zapcore.NewMultiWriteSyncer(writers...))
zap.RedirectStdLog(lg)
if cfg.AppName != "" {
lg = lg.With(zap.String("app", cfg.AppName)) // 加上应用名称
}
l = &LogX{logger: lg, atomLevel: lv}
}

// create a new logger
func NewLogger(cfg *LogConfig) *LogX {
var writers []zapcore.WriteSyncer
if cfg.IsStdOut || (!cfg.IsStdOut && !cfg.IsFileOut) {
writers = append(writers, os.Stdout)
}
if cfg.IsFileOut {
writers = append(writers, NewRollingFile(cfg.FileDir, cfg.FileName, cfg.FileMaxSize, cfg.FileMaxAge))
}

lg, lv := newZapLogger(setLogLevel(cfg.Level), setLogLevel(cfg.StacktraceLevel), cfg.Encoding, cfg.TimeFormat, cfg.Skip, zapcore.NewMultiWriteSyncer(writers...))
zap.RedirectStdLog(lg)
if cfg.AppName != "" {
lg = lg.With(zap.String("app", cfg.AppName)) // 加上应用名称
}
return &LogX{logger: lg, atomLevel: lv}
}

// create a new zaplog logger
func newZapLogger(level, stacktrace zapcore.Level, encoding, timeType string, skip int, output zapcore.WriteSyncer) (*zap.Logger, *zap.AtomicLevel) {
encCfg := zapcore.EncoderConfig{
TimeKey: "T",
LevelKey: "L",
NameKey: "N",
CallerKey: "C",
MessageKey: "M",
StacktraceKey: "S",
LineEnding: zapcore.DefaultLineEnding,
EncodeCaller: zapcore.ShortCallerEncoder,
EncodeDuration: zapcore.NanosDurationEncoder,
EncodeLevel: zapcore.LowercaseLevelEncoder,
}
setTimeFormat(timeType, &encCfg) // set time type
atmLvl := zap.NewAtomicLevel() // set level
atmLvl.SetLevel(level)
encoder := zapcore.NewJSONEncoder(encCfg) // 确定encoder格式
if encoding == "console" {
encoder = zapcore.NewConsoleEncoder(encCfg)
}
return zap.New(zapcore.NewCore(encoder, output, atmLvl), zap.AddCaller(), zap.AddStacktrace(stacktrace), zap.AddCallerSkip(skip)), &atmLvl
}

// set log level
func setLogLevel(lvl string) zapcore.Level {
switch strings.ToLower(lvl) {
case "panic":
return zapcore.PanicLevel
case "fatal":
return zapcore.FatalLevel
case "error":
return zapcore.ErrorLevel
case "warn", "warning":
return zapcore.WarnLevel
case "info":
return zapcore.InfoLevel
default:
return zapcore.DebugLevel
}
}

// set time format
func setTimeFormat(timeType string, z *zapcore.EncoderConfig) {
switch strings.ToLower(timeType) {
case "iso": // iso8601 standard
z.EncodeTime = zapcore.ISO8601TimeEncoder
case "sec": // only for unix second, without millisecond
z.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendInt64(t.Unix())
}
case "second": // unix second, with millisecond
z.EncodeTime = zapcore.EpochTimeEncoder
case "milli", "millisecond": // millisecond
z.EncodeTime = zapcore.EpochMillisTimeEncoder
case "nano", "nanosecond": // nanosecond
z.EncodeTime = zapcore.EpochNanosTimeEncoder
default: // standard format
z.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
}
}
}

func GetLevel() string {
switch l.atomLevel.Level() {
case zapcore.PanicLevel:
return "panic"
case zapcore.FatalLevel:
return "fatal"
case zapcore.ErrorLevel:
return "error"
case zapcore.WarnLevel:
return "warn"
case zapcore.InfoLevel:
return "info"
default:
return "debug"
}
}

func SetLevel(lvl string) {
l.atomLevel.SetLevel(setLogLevel(lvl))
}

// temporary add call skip
func AddCallerSkip(skip int) *LogX {
l.logger.WithOptions(zap.AddCallerSkip(skip))
return l
}

// permanent add call skip
func AddDepth(skip int) *LogX {
l.logger = l.logger.WithOptions(zap.AddCallerSkip(skip))
return l
}

// permanent add options
func AddOptions(opts ...zap.Option) *LogX {
l.logger = l.logger.WithOptions(opts...)
return l
}

func AddField(k string, v interface{}) {
l.logger.With(zap.Any(k, v))
}

func AddFields(fields map[string]interface{}) *LogX {
for k, v := range fields {
l.logger.With(zap.Any(k, v))
}
return l
}

// Normal log
func Debug(e interface{}, args ...interface{}) error {
return l.Debug(e, args...)
}
func Info(e interface{}, args ...interface{}) error {
return l.Info(e, args...)
}
func Warn(e interface{}, args ...interface{}) error {
return l.Warn(e, args...)
}
func Error(e interface{}, args ...interface{}) error {
return l.Error(e, args...)
}
func Panic(e interface{}, args ...interface{}) error {
return l.Panic(e, args...)
}
func Fatal(e interface{}, args ...interface{}) error {
return l.Fatal(e, args...)
}

// Format logs
func Debugf(format string, args ...interface{}) error {
return l.Debugf(format, args...)
}
func Infof(format string, args ...interface{}) error {
return l.Infof(format, args...)
}
func Warnf(format string, args ...interface{}) error {
return l.Warnf(format, args...)
}
func Errorf(format string, args ...interface{}) error {
return l.Errorf(format, args...)
}
func Panicf(format string, args ...interface{}) error {
return l.Panicf(format, args...)
}
func Fatalf(format string, args ...interface{}) error {
return l.Fatalf(format, args...)
}

func formatFieldMap(m FieldMap) []Field {
var res []Field
for k, v := range m {
res = append(res, zap.Any(k, v))
}
return res
}

+ 105
- 0
internal/business/comm/utils/logx/output.go View File

@@ -0,0 +1,105 @@
package logx

import (
"bytes"
"io"
"os"
"path/filepath"
"time"

"gopkg.in/natefinch/lumberjack.v2"
)

// output interface
type WriteSyncer interface {
io.Writer
Sync() error
}

// split writer
func NewRollingFile(dir, filename string, maxSize, MaxAge int) WriteSyncer {
s, err := os.Stat(dir)
if err != nil || !s.IsDir() {
os.RemoveAll(dir)
if err := os.MkdirAll(dir, 0766); err != nil {
panic(err)
}
}
return newLumberjackWriteSyncer(&lumberjack.Logger{
Filename: filepath.Join(dir, filename),
MaxSize: maxSize, // megabytes, MB
MaxAge: MaxAge, // days
LocalTime: true,
Compress: false,
})
}

type lumberjackWriteSyncer struct {
*lumberjack.Logger
buf *bytes.Buffer
logChan chan []byte
closeChan chan interface{}
maxSize int
}

func newLumberjackWriteSyncer(l *lumberjack.Logger) *lumberjackWriteSyncer {
ws := &lumberjackWriteSyncer{
Logger: l,
buf: bytes.NewBuffer([]byte{}),
logChan: make(chan []byte, 5000),
closeChan: make(chan interface{}),
maxSize: 1024,
}
go ws.run()
return ws
}

func (l *lumberjackWriteSyncer) run() {
ticker := time.NewTicker(1 * time.Second)

for {
select {
case <-ticker.C:
if l.buf.Len() > 0 {
l.sync()
}
case bs := <-l.logChan:
_, err := l.buf.Write(bs)
if err != nil {
continue
}
if l.buf.Len() > l.maxSize {
l.sync()
}
case <-l.closeChan:
l.sync()
return
}
}
}

func (l *lumberjackWriteSyncer) Stop() {
close(l.closeChan)
}

func (l *lumberjackWriteSyncer) Write(bs []byte) (int, error) {
b := make([]byte, len(bs))
for i, c := range bs {
b[i] = c
}
l.logChan <- b
return 0, nil
}

func (l *lumberjackWriteSyncer) Sync() error {
return nil
}

func (l *lumberjackWriteSyncer) sync() error {
defer l.buf.Reset()
_, err := l.Logger.Write(l.buf.Bytes())
if err != nil {
return err
}
return nil
}

+ 192
- 0
internal/business/comm/utils/logx/sugar.go View File

@@ -0,0 +1,192 @@
package logx

import (
"errors"
"fmt"
"strconv"

"go.uber.org/zap"
)

type LogX struct {
logger *zap.Logger
atomLevel *zap.AtomicLevel
}

type Field = zap.Field
type FieldMap map[string]interface{}

// 判断其他类型--start
func getFields(msg string, format bool, args ...interface{}) (string, []Field) {
var str []interface{}
var fields []zap.Field
if len(args) > 0 {
for _, v := range args {
if f, ok := v.(Field); ok {
fields = append(fields, f)
} else if f, ok := v.(FieldMap); ok {
fields = append(fields, formatFieldMap(f)...)
} else {
str = append(str, AnyToString(v))
}
}
if format {
return fmt.Sprintf(msg, str...), fields
}
str = append([]interface{}{msg}, str...)
return fmt.Sprintln(str...), fields
}
return msg, []Field{}
}

func (l *LogX) Debug(s interface{}, args ...interface{}) error {
es, e := checkErr(s)
if es != "" {
msg, field := getFields(es, false, args...)
l.logger.Debug(msg, field...)
}
return e
}
func (l *LogX) Info(s interface{}, args ...interface{}) error {
es, e := checkErr(s)
if es != "" {
msg, field := getFields(es, false, args...)
l.logger.Info(msg, field...)
}
return e
}
func (l *LogX) Warn(s interface{}, args ...interface{}) error {
es, e := checkErr(s)
if es != "" {
msg, field := getFields(es, false, args...)
l.logger.Warn(msg, field...)
}
return e
}
func (l *LogX) Error(s interface{}, args ...interface{}) error {
es, e := checkErr(s)
if es != "" {
msg, field := getFields(es, false, args...)
l.logger.Error(msg, field...)
}
return e
}
func (l *LogX) DPanic(s interface{}, args ...interface{}) error {
es, e := checkErr(s)
if es != "" {
msg, field := getFields(es, false, args...)
l.logger.DPanic(msg, field...)
}
return e
}
func (l *LogX) Panic(s interface{}, args ...interface{}) error {
es, e := checkErr(s)
if es != "" {
msg, field := getFields(es, false, args...)
l.logger.Panic(msg, field...)
}
return e
}
func (l *LogX) Fatal(s interface{}, args ...interface{}) error {
es, e := checkErr(s)
if es != "" {
msg, field := getFields(es, false, args...)
l.logger.Fatal(msg, field...)
}
return e
}

func checkErr(s interface{}) (string, error) {
switch e := s.(type) {
case error:
return e.Error(), e
case string:
return e, errors.New(e)
case []byte:
return string(e), nil
default:
return "", nil
}
}

func (l *LogX) LogError(err error) error {
return l.Error(err.Error())
}

func (l *LogX) Debugf(msg string, args ...interface{}) error {
s, f := getFields(msg, true, args...)
l.logger.Debug(s, f...)
return errors.New(s)
}

func (l *LogX) Infof(msg string, args ...interface{}) error {
s, f := getFields(msg, true, args...)
l.logger.Info(s, f...)
return errors.New(s)
}

func (l *LogX) Warnf(msg string, args ...interface{}) error {
s, f := getFields(msg, true, args...)
l.logger.Warn(s, f...)
return errors.New(s)
}

func (l *LogX) Errorf(msg string, args ...interface{}) error {
s, f := getFields(msg, true, args...)
l.logger.Error(s, f...)
return errors.New(s)
}

func (l *LogX) DPanicf(msg string, args ...interface{}) error {
s, f := getFields(msg, true, args...)
l.logger.DPanic(s, f...)
return errors.New(s)
}

func (l *LogX) Panicf(msg string, args ...interface{}) error {
s, f := getFields(msg, true, args...)
l.logger.Panic(s, f...)
return errors.New(s)
}

func (l *LogX) Fatalf(msg string, args ...interface{}) error {
s, f := getFields(msg, true, args...)
l.logger.Fatal(s, f...)
return errors.New(s)
}

func AnyToString(raw interface{}) string {
switch i := raw.(type) {
case []byte:
return string(i)
case int:
return strconv.FormatInt(int64(i), 10)
case int64:
return strconv.FormatInt(i, 10)
case float32:
return strconv.FormatFloat(float64(i), 'f', 2, 64)
case float64:
return strconv.FormatFloat(i, 'f', 2, 64)
case uint:
return strconv.FormatInt(int64(i), 10)
case uint8:
return strconv.FormatInt(int64(i), 10)
case uint16:
return strconv.FormatInt(int64(i), 10)
case uint32:
return strconv.FormatInt(int64(i), 10)
case uint64:
return strconv.FormatInt(int64(i), 10)
case int8:
return strconv.FormatInt(int64(i), 10)
case int16:
return strconv.FormatInt(int64(i), 10)
case int32:
return strconv.FormatInt(int64(i), 10)
case string:
return i
case error:
return i.Error()
}
return fmt.Sprintf("%#v", raw)
}

+ 12
- 0
internal/business/comm/utils/md5.go View File

@@ -0,0 +1,12 @@
package utils

import (
"crypto/md5"
"encoding/hex"
)

func Md5(str string) string {
h := md5.New()
h.Write([]byte(str))
return hex.EncodeToString(h.Sum(nil))
}

+ 46
- 0
internal/business/comm/utils/rand.go View File

@@ -0,0 +1,46 @@
package utils

import (
crand "crypto/rand"
"fmt"
"math/big"
"math/rand"
"time"
)

func RandString(l int, c ...string) string {
var (
chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
str string
num *big.Int
)
if len(c) > 0 {
chars = c[0]
}
chrLen := int64(len(chars))
for len(str) < l {
num, _ = crand.Int(crand.Reader, big.NewInt(chrLen))
str += string(chars[num.Int64()])
}
return str
}

func RandNum() string {
seed := time.Now().UnixNano() + rand.Int63()
return fmt.Sprintf("%05v", rand.New(rand.NewSource(seed)).Int31n(1000000))
}

//x的y次方
func RandPow(l int) string {
var i = "1"
for j := 0; j < l; j++ {
i += "0"
}
k := StrToInt64(i)
n := rand.New(rand.NewSource(time.Now().UnixNano())).Int63n(k)
ls := "%0" + IntToStr(l) + "v"
str := fmt.Sprintf(ls, n)
//min := int(math.Pow10(l - 1))
//max := int(math.Pow10(l) - 1)
return str
}

+ 29
- 0
internal/business/comm/utils/reply.go View File

@@ -0,0 +1,29 @@
package utils

import (
"errors"
"fmt"
)

type Error string

func (err Error) Error() string { return string(err) }

var ErrNil = errors.New("redigo: nil returned")

func Bytes(reply interface{}, err error) ([]byte, error) {
if err != nil {
return nil, err
}
switch reply := reply.(type) {
case []byte:
return reply, nil
case string:
return []byte(reply), nil
case nil:
return nil, ErrNil
case Error:
return nil, reply
}
return nil, fmt.Errorf("redigo: unexpected type for Bytes, got type %T", reply)
}

+ 23
- 0
internal/business/comm/utils/serialize.go View File

@@ -0,0 +1,23 @@
package utils

import (
"encoding/json"
)

func Serialize(data interface{}) []byte {
res, err := json.Marshal(data)
if err != nil {
return []byte{}
}
return res
}

func Unserialize(b []byte, dst interface{}) {
if err := json.Unmarshal(b, dst); err != nil {
dst = nil
}
}

func SerializeStr(data interface{}, arg ...interface{}) string {
return string(Serialize(data))
}

+ 208
- 0
internal/business/comm/utils/time.go View File

@@ -0,0 +1,208 @@
package utils

import (
"errors"
"fmt"
"strconv"
"strings"
"time"
)

func StrToTime(s string) (int64, error) {
// delete all not int characters
if s == "" {
return time.Now().Unix(), nil
}
r := make([]rune, 14)
l := 0
// 过滤除数字以外的字符
for _, v := range s {
if '0' <= v && v <= '9' {
r[l] = v
l++
if l == 14 {
break
}
}
}
for l < 14 {
r[l] = '0' // 补0
l++
}
t, err := time.Parse("20060102150405", string(r))
if err != nil {
return 0, err
}
return t.Unix(), nil
}

func TimeToStr(unixSecTime interface{}, layout ...string) string {
i := AnyToInt64(unixSecTime)
if i == 0 {
return ""
}
f := "2006-01-02 15:04:05"
if len(layout) > 0 {
f = layout[0]
}
return time.Unix(i, 0).Format(f)
}

func FormatNanoUnix() string {
return strings.Replace(time.Now().Format("20060102150405.0000000"), ".", "", 1)
}

func TimeParse(format, src string) (time.Time, error) {
return time.ParseInLocation(format, src, time.Local)
}

func TimeParseStd(src string) time.Time {
t, _ := TimeParse("2006-01-02 15:04:05", src)
return t
}

func TimeStdParseUnix(src string) int64 {
t, err := TimeParse("2006-01-02 15:04:05", src)
if err != nil {
return 0
}
return t.Unix()
}

// 获取一个当前时间 时间间隔 时间戳
func GetTimeInterval(unit string, amount int) (startTime, endTime int64) {
t := time.Now()
nowTime := t.Unix()
tmpTime := int64(0)
switch unit {
case "years":
tmpTime = time.Date(t.Year()+amount, t.Month(), t.Day(), t.Hour(), 0, 0, 0, t.Location()).Unix()
case "months":
tmpTime = time.Date(t.Year(), t.Month()+time.Month(amount), t.Day(), t.Hour(), 0, 0, 0, t.Location()).Unix()
case "days":
tmpTime = time.Date(t.Year(), t.Month(), t.Day()+amount, t.Hour(), 0, 0, 0, t.Location()).Unix()
case "hours":
tmpTime = time.Date(t.Year(), t.Month(), t.Day(), t.Hour()+amount, 0, 0, 0, t.Location()).Unix()
}
if amount > 0 {
startTime = nowTime
endTime = tmpTime
} else {
startTime = tmpTime
endTime = nowTime
}
return
}

// 几天前
func TimeInterval(newTime int) string {
now := time.Now().Unix()
newTime64 := AnyToInt64(newTime)
if newTime64 >= now {
return "刚刚"
}
interval := now - newTime64
switch {
case interval < 60:
return AnyToString(interval) + "秒前"
case interval < 60*60:
return AnyToString(interval/60) + "分前"
case interval < 60*60*24:
return AnyToString(interval/60/60) + "小时前"
case interval < 60*60*24*30:
return AnyToString(interval/60/60/24) + "天前"
case interval < 60*60*24*30*12:
return AnyToString(interval/60/60/24/30) + "月前"
default:
return AnyToString(interval/60/60/24/30/12) + "年前"
}
}

// 时分秒字符串转时间戳,传入示例:8:40 or 8:40:10
func HmsToUnix(str string) (int64, error) {
t := time.Now()
arr := strings.Split(str, ":")
if len(arr) < 2 {
return 0, errors.New("Time format error")
}
h, _ := strconv.Atoi(arr[0])
m, _ := strconv.Atoi(arr[1])
s := 0
if len(arr) == 3 {
s, _ = strconv.Atoi(arr[3])
}
formatted1 := fmt.Sprintf("%d%02d%02d%02d%02d%02d", t.Year(), t.Month(), t.Day(), h, m, s)
res, err := time.ParseInLocation("20060102150405", formatted1, time.Local)
if err != nil {
return 0, err
} else {
return res.Unix(), nil
}
}

// 获取特定时间范围
func GetTimeRange(s string) map[string]int64 {
t := time.Now()
var stime, etime time.Time
switch s {
case "today":
stime = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
etime = time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, t.Location())
case "yesterday":
stime = time.Date(t.Year(), t.Month(), t.Day()-1, 0, 0, 0, 0, t.Location())
etime = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
case "within_seven_days":
// 前6天0点
stime = time.Date(t.Year(), t.Month(), t.Day()-6, 0, 0, 0, 0, t.Location())
// 明天 0点
etime = time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, t.Location())
case "current_month":
stime = GetFirstDateOfMonth(t)
etime = time.Now()
case "last_month":
etime = GetFirstDateOfMonth(t)
monthTimes := TimeStdParseUnix(etime.Format("2006-01-02 15:04:05")) - 86400
times, _ := UnixToTime(Int64ToStr(monthTimes))
stime = GetFirstDateOfMonth(times)

}

return map[string]int64{
"start": stime.Unix(),
"end": etime.Unix(),
}
}

//时间戳转时间格式
func UnixToTime(e string) (datatime time.Time, err error) {
data, err := strconv.ParseInt(e, 10, 64)
datatime = time.Unix(data, 0)
return
}

//获取传入的时间所在月份的第一天,即某月第一天的0点。如传入time.Now(), 返回当前月份的第一天0点时间。
func GetFirstDateOfMonth(d time.Time) time.Time {
d = d.AddDate(0, 0, -d.Day()+1)
return GetZeroTime(d)
}

//获取传入的时间所在月份的最后一天,即某月最后一天的0点。如传入time.Now(), 返回当前月份的最后一天0点时间。
func GetLastDateOfMonth(d time.Time) time.Time {
return GetFirstDateOfMonth(d).AddDate(0, 1, -1)
}

//获取某一天的0点时间
func GetZeroTime(d time.Time) time.Time {
return time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 0, 0, d.Location())
}

//获取当月某天的某个时间的时间
func GetDayToTime(day, timeStr string) string {
if timeStr == "" {
timeStr = "00:00:00"
}
year := time.Now().Year()
month := time.Now().Format("01")
times := fmt.Sprintf("%s-%s-%s %s", IntToStr(year), month, day, timeStr)
return times
}

+ 24
- 0
internal/business/domain/user/model/im_package.go View File

@@ -0,0 +1,24 @@
package model

import "time"

type ImPackage struct {
Id int64 // 自增主键
Name string // 套餐名
Price string // 价格
ValidityDay int64 // 有效期(天/月/年)
ValidityDayType int32 // 有效期类型(1:天 2:月 3:年)
FriendsTotalNum int64 // 好友总数
FriendsSingleNum int64 // 单用户可添加好友数
GroupTotalNum int64 // 群组总数
GroupSingleNum int64 // 单用户可创建群组总数
GroupNum int64 // 群人员数量
SingleChatNumsEveryDay int64 // 每日单聊消息数
GroupChatNumsEveryDay int64 // 每日群聊消息数
LivingNumsEveryDay int64 // 日活数
MessageCloudStorageDay int64 // 消息云端存储(天)
Sort int64 // 排序(天)
isUse int32 // 是否启用(1:启用 2:禁用)
CreateTime time.Time // 创建时间
UpdateTime time.Time // 更新时间
}

+ 17
- 0
internal/business/domain/user/model/master.go View File

@@ -0,0 +1,17 @@
package model

import "time"

type Master struct {
Id int64 // 自增主键
Phone string // 手机号
MasterId int64 // 站长id
MasterName string // 站长名称
AvatarUrl string // 站长头像链接
Extra string // 附加属性
PackageId int64 // 套餐id(0:未购买套餐)
PackageExpireTime string // 套餐到期时间
IsUse int32 // 是否可用(1:可用 2:禁用)
CreateTime time.Time // 创建时间
UpdateTime time.Time // 更新时间
}

+ 25
- 0
internal/business/domain/user/repo/im_package_dao.go View File

@@ -0,0 +1,25 @@
package repo

import (
"gim/internal/business/domain/user/model"
"gim/pkg/db"
"gim/pkg/gerrors"
"github.com/jinzhu/gorm"
)

type imPackageDao struct{}

var ImPackageDao = new(imPackageDao)

// Get 获取套餐包详情
func (*imPackageDao) Get(id int64) (*model.ImPackage, error) {
var imPackage = model.ImPackage{Id: id}
err := db.DB.First(&imPackage).Error
if err != nil && err != gorm.ErrRecordNotFound {
return nil, gerrors.WrapError(err)
}
if err == gorm.ErrRecordNotFound {
return nil, nil
}
return &imPackage, err
}

+ 18
- 0
internal/business/domain/user/repo/im_package_repo.go View File

@@ -0,0 +1,18 @@
package repo

import (
"gim/internal/business/domain/user/model"
)

type imPackageRepo struct{}

var ImPackageRepo = new(imPackageRepo)

// Get 获取单个套餐包
func (*imPackageRepo) Get(masterId int64) (*model.ImPackage, error) {
imPackage, err := ImPackageDao.Get(masterId)
if err != nil {
return nil, err
}
return imPackage, err
}

+ 51
- 0
internal/business/domain/user/repo/master_cache.go View File

@@ -0,0 +1,51 @@
package repo

import (
"gim/internal/business/domain/user/model"
"gim/pkg/db"
"gim/pkg/gerrors"
"strconv"
"time"

"github.com/go-redis/redis"
)

const (
MasterKey = "master:"
MasterExpire = 24 * time.Hour
)

type masterCache struct{}

var MasterCache = new(masterCache)

// Get 获取用户缓存
func (c *masterCache) Get(masterId int64) (*model.Master, error) {
var master model.Master
err := db.RedisUtil.Get(MasterKey+strconv.FormatInt(masterId, 10), &master)
if err != nil && err != redis.Nil {
return nil, gerrors.WrapError(err)
}
if err == redis.Nil {
return nil, nil
}
return &master, nil
}

// Set 设置用户缓存
func (c *masterCache) Set(master model.Master) error {
err := db.RedisUtil.Set(MasterKey+strconv.FormatInt(master.MasterId, 10), master, MasterExpire)
if err != nil {
return gerrors.WrapError(err)
}
return nil
}

// Del 删除用户缓存
func (c *masterCache) Del(masterId int64) error {
_, err := db.RedisCli.Del(MasterKey + strconv.FormatInt(masterId, 10)).Result()
if err != nil {
return gerrors.WrapError(err)
}
return nil
}

+ 38
- 0
internal/business/domain/user/repo/master_dao.go View File

@@ -0,0 +1,38 @@
package repo

import (
"gim/internal/business/domain/user/model"
"gim/pkg/db"
"gim/pkg/gerrors"
"github.com/jinzhu/gorm"
)

type masterDao struct{}

var MasterDao = new(masterDao)

// Get 获取站长信息
func (*masterDao) Get(masterId int64) (*model.Master, error) {
var master = model.Master{MasterId: masterId}
err := db.DB.First(&master).Error
if err != nil && err != gorm.ErrRecordNotFound {
return nil, gerrors.WrapError(err)
}
if err == gorm.ErrRecordNotFound {
return nil, nil
}
return &master, err
}

// GetByPhone 根据手机号获取用户信息
func (*masterDao) GetByPhone(phone string) (*model.Master, error) {
var master model.Master
err := db.DB.First(&master, "phone_number = ?", phone).Error
if err != nil && err != gorm.ErrRecordNotFound {
return nil, gerrors.WrapError(err)
}
if err == gorm.ErrRecordNotFound {
return nil, nil
}
return &master, err
}

+ 37
- 0
internal/business/domain/user/repo/master_repo.go View File

@@ -0,0 +1,37 @@
package repo

import (
"gim/internal/business/domain/user/model"
)

type masterRepo struct{}

var MasterRepo = new(masterRepo)

// Get 获取单个站长
func (*masterRepo) Get(masterId int64) (*model.Master, error) {
master, err := MasterCache.Get(masterId)
if err != nil {
return nil, err
}
if master != nil {
return master, nil
}

master, err = MasterDao.Get(masterId)
if err != nil {
return nil, err
}

if master != nil {
err = MasterCache.Set(*master)
if err != nil {
return nil, err
}
}
return master, err
}

func (*masterRepo) GetByPhone(phone string, masterId int64) (*model.Master, error) {
return MasterDao.GetByPhone(phone)
}

+ 17
- 3
internal/logic/api/logic_ext_test.go View File

@@ -26,10 +26,10 @@ func getLogicExtClient() pb.LogicExtClient {
// deprecated: // deprecated:


func getCtx() context.Context { func getCtx() context.Context {
token := "VRZWQVPFXHPUCCKFOANEYOLCDSFMKEAVYVMAZQWQ"
token := "AYBVKGSIFENYDKKOPBYVONZWTCZAQEDGHLAKZLXT"
return metadata.NewOutgoingContext(context.TODO(), metadata.Pairs( return metadata.NewOutgoingContext(context.TODO(), metadata.Pairs(
"user_id", "2",
"device_id", "2",
"user_id", "13",
"device_id", "10",
"token", token, "token", token,
"request_id", strconv.FormatInt(time.Now().UnixNano(), 10))) "request_id", strconv.FormatInt(time.Now().UnixNano(), 10)))
} }
@@ -208,3 +208,17 @@ func TestLogicExtServer_GetGroupMembers(t *testing.T) {
} }
fmt.Printf("%+v\n", resp) fmt.Printf("%+v\n", resp)
} }

func TestLogicExtServer_AddFriend(t *testing.T) {
resp, err := getLogicExtClient().AddFriend(getCtx(),
&pb.AddFriendReq{
FriendId: 2,
Remarks: "weihan",
Description: "hello",
})
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v\n", resp)
}

+ 16
- 0
pkg/grpclib/ctx.go View File

@@ -13,6 +13,7 @@ const (
CtxUserId = "user_id" CtxUserId = "user_id"
CtxDeviceId = "device_id" CtxDeviceId = "device_id"
CtxToken = "token" CtxToken = "token"
CtxMasterId = "master_id"
CtxRequestId = "request_id" CtxRequestId = "request_id"
) )


@@ -107,6 +108,21 @@ func GetCtxToken(ctx context.Context) (string, error) {
return tokens[0], nil return tokens[0], nil
} }


// GetCtxMasterId 获取ctx的masterId
func GetCtxMasterId(ctx context.Context) (string, error) {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return "", gerrors.ErrUnauthorized
}

masterId, ok := md[CtxMasterId]
if !ok && len(masterId) == 0 {
return "", gerrors.ErrUnauthorized
}

return masterId[0], nil
}

// NewAndCopyRequestId 创建一个context,并且复制RequestId // NewAndCopyRequestId 创建一个context,并且复制RequestId
func NewAndCopyRequestId(ctx context.Context) context.Context { func NewAndCopyRequestId(ctx context.Context) context.Context {
newCtx := context.TODO() newCtx := context.TODO()


+ 335
- 116
pkg/pb/business.ext.pb.go View File

@@ -1,8 +1,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.26.0
// protoc v3.14.0
// source: business.ext.proto_back
// protoc-gen-go v1.28.1
// protoc v3.20.0--rc1
// source: business.ext.proto


package pb package pb


@@ -166,6 +166,140 @@ func (x *SignInResp) GetMasterId() int64 {
return 0 return 0
} }


type CloudUploadFileReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields

Dir string `protobuf:"bytes,1,opt,name=dir,proto3" json:"dir,omitempty"` // 目录名
FileName string `protobuf:"bytes,2,opt,name=file_name,json=fileName,proto3" json:"file_name,omitempty"` // 上传原文件名称
FileSize string `protobuf:"bytes,3,opt,name=file_size,json=fileSize,proto3" json:"file_size,omitempty"` // 文件大小
}

func (x *CloudUploadFileReq) Reset() {
*x = CloudUploadFileReq{}
if protoimpl.UnsafeEnabled {
mi := &file_business_ext_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}

func (x *CloudUploadFileReq) String() string {
return protoimpl.X.MessageStringOf(x)
}

func (*CloudUploadFileReq) ProtoMessage() {}

func (x *CloudUploadFileReq) ProtoReflect() protoreflect.Message {
mi := &file_business_ext_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}

// Deprecated: Use CloudUploadFileReq.ProtoReflect.Descriptor instead.
func (*CloudUploadFileReq) Descriptor() ([]byte, []int) {
return file_business_ext_proto_rawDescGZIP(), []int{2}
}

func (x *CloudUploadFileReq) GetDir() string {
if x != nil {
return x.Dir
}
return ""
}

func (x *CloudUploadFileReq) GetFileName() string {
if x != nil {
return x.FileName
}
return ""
}

func (x *CloudUploadFileReq) GetFileSize() string {
if x != nil {
return x.FileSize
}
return ""
}

type CloudUploadFileResp struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields

Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"` // 请求方式
Host string `protobuf:"bytes,2,opt,name=host,proto3" json:"host,omitempty"` // 域名
Key string `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` // key
Token string `protobuf:"bytes,4,opt,name=token,proto3" json:"token,omitempty"` // token
}

func (x *CloudUploadFileResp) Reset() {
*x = CloudUploadFileResp{}
if protoimpl.UnsafeEnabled {
mi := &file_business_ext_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}

func (x *CloudUploadFileResp) String() string {
return protoimpl.X.MessageStringOf(x)
}

func (*CloudUploadFileResp) ProtoMessage() {}

func (x *CloudUploadFileResp) ProtoReflect() protoreflect.Message {
mi := &file_business_ext_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}

// Deprecated: Use CloudUploadFileResp.ProtoReflect.Descriptor instead.
func (*CloudUploadFileResp) Descriptor() ([]byte, []int) {
return file_business_ext_proto_rawDescGZIP(), []int{3}
}

func (x *CloudUploadFileResp) GetMethod() string {
if x != nil {
return x.Method
}
return ""
}

func (x *CloudUploadFileResp) GetHost() string {
if x != nil {
return x.Host
}
return ""
}

func (x *CloudUploadFileResp) GetKey() string {
if x != nil {
return x.Key
}
return ""
}

func (x *CloudUploadFileResp) GetToken() string {
if x != nil {
return x.Token
}
return ""
}

type User struct { type User struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@@ -184,7 +318,7 @@ type User struct {
func (x *User) Reset() { func (x *User) Reset() {
*x = User{} *x = User{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_business_ext_proto_msgTypes[2]
mi := &file_business_ext_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -197,7 +331,7 @@ func (x *User) String() string {
func (*User) ProtoMessage() {} func (*User) ProtoMessage() {}


func (x *User) ProtoReflect() protoreflect.Message { func (x *User) ProtoReflect() protoreflect.Message {
mi := &file_business_ext_proto_msgTypes[2]
mi := &file_business_ext_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -210,7 +344,7 @@ func (x *User) ProtoReflect() protoreflect.Message {


// Deprecated: Use User.ProtoReflect.Descriptor instead. // Deprecated: Use User.ProtoReflect.Descriptor instead.
func (*User) Descriptor() ([]byte, []int) { func (*User) Descriptor() ([]byte, []int) {
return file_business_ext_proto_rawDescGZIP(), []int{2}
return file_business_ext_proto_rawDescGZIP(), []int{4}
} }


func (x *User) GetUserId() int64 { func (x *User) GetUserId() int64 {
@@ -280,7 +414,7 @@ type GetUserReq struct {
func (x *GetUserReq) Reset() { func (x *GetUserReq) Reset() {
*x = GetUserReq{} *x = GetUserReq{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_business_ext_proto_msgTypes[3]
mi := &file_business_ext_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -293,7 +427,7 @@ func (x *GetUserReq) String() string {
func (*GetUserReq) ProtoMessage() {} func (*GetUserReq) ProtoMessage() {}


func (x *GetUserReq) ProtoReflect() protoreflect.Message { func (x *GetUserReq) ProtoReflect() protoreflect.Message {
mi := &file_business_ext_proto_msgTypes[3]
mi := &file_business_ext_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -306,7 +440,7 @@ func (x *GetUserReq) ProtoReflect() protoreflect.Message {


// Deprecated: Use GetUserReq.ProtoReflect.Descriptor instead. // Deprecated: Use GetUserReq.ProtoReflect.Descriptor instead.
func (*GetUserReq) Descriptor() ([]byte, []int) { func (*GetUserReq) Descriptor() ([]byte, []int) {
return file_business_ext_proto_rawDescGZIP(), []int{3}
return file_business_ext_proto_rawDescGZIP(), []int{5}
} }


func (x *GetUserReq) GetUserId() int64 { func (x *GetUserReq) GetUserId() int64 {
@@ -327,7 +461,7 @@ type GetUserResp struct {
func (x *GetUserResp) Reset() { func (x *GetUserResp) Reset() {
*x = GetUserResp{} *x = GetUserResp{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_business_ext_proto_msgTypes[4]
mi := &file_business_ext_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -340,7 +474,7 @@ func (x *GetUserResp) String() string {
func (*GetUserResp) ProtoMessage() {} func (*GetUserResp) ProtoMessage() {}


func (x *GetUserResp) ProtoReflect() protoreflect.Message { func (x *GetUserResp) ProtoReflect() protoreflect.Message {
mi := &file_business_ext_proto_msgTypes[4]
mi := &file_business_ext_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -353,7 +487,7 @@ func (x *GetUserResp) ProtoReflect() protoreflect.Message {


// Deprecated: Use GetUserResp.ProtoReflect.Descriptor instead. // Deprecated: Use GetUserResp.ProtoReflect.Descriptor instead.
func (*GetUserResp) Descriptor() ([]byte, []int) { func (*GetUserResp) Descriptor() ([]byte, []int) {
return file_business_ext_proto_rawDescGZIP(), []int{4}
return file_business_ext_proto_rawDescGZIP(), []int{6}
} }


func (x *GetUserResp) GetUser() *User { func (x *GetUserResp) GetUser() *User {
@@ -377,7 +511,7 @@ type UpdateUserReq struct {
func (x *UpdateUserReq) Reset() { func (x *UpdateUserReq) Reset() {
*x = UpdateUserReq{} *x = UpdateUserReq{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_business_ext_proto_msgTypes[5]
mi := &file_business_ext_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -390,7 +524,7 @@ func (x *UpdateUserReq) String() string {
func (*UpdateUserReq) ProtoMessage() {} func (*UpdateUserReq) ProtoMessage() {}


func (x *UpdateUserReq) ProtoReflect() protoreflect.Message { func (x *UpdateUserReq) ProtoReflect() protoreflect.Message {
mi := &file_business_ext_proto_msgTypes[5]
mi := &file_business_ext_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -403,7 +537,7 @@ func (x *UpdateUserReq) ProtoReflect() protoreflect.Message {


// Deprecated: Use UpdateUserReq.ProtoReflect.Descriptor instead. // Deprecated: Use UpdateUserReq.ProtoReflect.Descriptor instead.
func (*UpdateUserReq) Descriptor() ([]byte, []int) { func (*UpdateUserReq) Descriptor() ([]byte, []int) {
return file_business_ext_proto_rawDescGZIP(), []int{5}
return file_business_ext_proto_rawDescGZIP(), []int{7}
} }


func (x *UpdateUserReq) GetNickname() string { func (x *UpdateUserReq) GetNickname() string {
@@ -446,7 +580,7 @@ type SearchUserReq struct {
func (x *SearchUserReq) Reset() { func (x *SearchUserReq) Reset() {
*x = SearchUserReq{} *x = SearchUserReq{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_business_ext_proto_msgTypes[6]
mi := &file_business_ext_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -459,7 +593,7 @@ func (x *SearchUserReq) String() string {
func (*SearchUserReq) ProtoMessage() {} func (*SearchUserReq) ProtoMessage() {}


func (x *SearchUserReq) ProtoReflect() protoreflect.Message { func (x *SearchUserReq) ProtoReflect() protoreflect.Message {
mi := &file_business_ext_proto_msgTypes[6]
mi := &file_business_ext_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -472,7 +606,7 @@ func (x *SearchUserReq) ProtoReflect() protoreflect.Message {


// Deprecated: Use SearchUserReq.ProtoReflect.Descriptor instead. // Deprecated: Use SearchUserReq.ProtoReflect.Descriptor instead.
func (*SearchUserReq) Descriptor() ([]byte, []int) { func (*SearchUserReq) Descriptor() ([]byte, []int) {
return file_business_ext_proto_rawDescGZIP(), []int{6}
return file_business_ext_proto_rawDescGZIP(), []int{8}
} }


func (x *SearchUserReq) GetKey() string { func (x *SearchUserReq) GetKey() string {
@@ -500,7 +634,7 @@ type SearchUserResp struct {
func (x *SearchUserResp) Reset() { func (x *SearchUserResp) Reset() {
*x = SearchUserResp{} *x = SearchUserResp{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_business_ext_proto_msgTypes[7]
mi := &file_business_ext_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -513,7 +647,7 @@ func (x *SearchUserResp) String() string {
func (*SearchUserResp) ProtoMessage() {} func (*SearchUserResp) ProtoMessage() {}


func (x *SearchUserResp) ProtoReflect() protoreflect.Message { func (x *SearchUserResp) ProtoReflect() protoreflect.Message {
mi := &file_business_ext_proto_msgTypes[7]
mi := &file_business_ext_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -526,7 +660,7 @@ func (x *SearchUserResp) ProtoReflect() protoreflect.Message {


// Deprecated: Use SearchUserResp.ProtoReflect.Descriptor instead. // Deprecated: Use SearchUserResp.ProtoReflect.Descriptor instead.
func (*SearchUserResp) Descriptor() ([]byte, []int) { func (*SearchUserResp) Descriptor() ([]byte, []int) {
return file_business_ext_proto_rawDescGZIP(), []int{7}
return file_business_ext_proto_rawDescGZIP(), []int{9}
} }


func (x *SearchUserResp) GetUsers() []*User { func (x *SearchUserResp) GetUsers() []*User {
@@ -556,55 +690,72 @@ var file_business_ext_proto_rawDesc = []byte{
0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18,
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1b, 0x0a, 0x09,
0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52,
0x08, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22, 0xe1, 0x01, 0x0a, 0x04, 0x55, 0x73,
0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6e,
0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e,
0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x65, 0x78, 0x18, 0x03,
0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x73, 0x65, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x76, 0x61,
0x74, 0x61, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61,
0x76, 0x61, 0x74, 0x61, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x78, 0x74, 0x72,
0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x78, 0x74, 0x72, 0x61, 0x12, 0x1f,
0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20,
0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12,
0x1f, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x07,
0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65,
0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20,
0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22, 0x25, 0x0a,
0x0a, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x17, 0x0a, 0x07, 0x75,
0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73,
0x65, 0x72, 0x49, 0x64, 0x22, 0x2b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52,
0x65, 0x73, 0x70, 0x12, 0x1c, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x08, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65,
0x72, 0x22, 0x72, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52,
0x65, 0x71, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10,
0x0a, 0x03, 0x73, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x73, 0x65, 0x78,
0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03,
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x55, 0x72, 0x6c, 0x12,
0x14, 0x0a, 0x05, 0x65, 0x78, 0x74, 0x72, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
0x65, 0x78, 0x74, 0x72, 0x61, 0x22, 0x3e, 0x0a, 0x0d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55,
0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x73, 0x74,
0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x61, 0x73,
0x74, 0x65, 0x72, 0x49, 0x64, 0x22, 0x30, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55,
0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x1e, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73,
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72,
0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x32, 0xc3, 0x01, 0x0a, 0x0b, 0x42, 0x75, 0x73, 0x69,
0x6e, 0x65, 0x73, 0x73, 0x45, 0x78, 0x74, 0x12, 0x27, 0x0a, 0x06, 0x53, 0x69, 0x67, 0x6e, 0x49,
0x6e, 0x12, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x52, 0x65, 0x71,
0x1a, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70,
0x12, 0x2a, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x2e, 0x70, 0x62,
0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x70, 0x62,
0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x2a, 0x0a, 0x0a,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x11, 0x2e, 0x70, 0x62, 0x2e,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x09, 0x2e,
0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x33, 0x0a, 0x0a, 0x53, 0x65, 0x61, 0x72,
0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x12, 0x11, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x61, 0x72,
0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x53,
0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x42, 0x0d, 0x5a,
0x0b, 0x67, 0x69, 0x6d, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
0x08, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22, 0x60, 0x0a, 0x12, 0x43, 0x6c, 0x6f,
0x75, 0x64, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x12,
0x10, 0x0a, 0x03, 0x64, 0x69, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x69,
0x72, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b,
0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x69, 0x0a, 0x13, 0x43,
0x6c, 0x6f, 0x75, 0x64, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65,
0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f,
0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x10,
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xe1, 0x01, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12,
0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03,
0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x69, 0x63, 0x6b,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x69, 0x63, 0x6b,
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28,
0x05, 0x52, 0x03, 0x73, 0x65, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72,
0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x76, 0x61, 0x74,
0x61, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x78, 0x74, 0x72, 0x61, 0x18, 0x05,
0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x78, 0x74, 0x72, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x63,
0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b,
0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28,
0x03, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a,
0x09, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03,
0x52, 0x08, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22, 0x25, 0x0a, 0x0a, 0x47, 0x65,
0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72,
0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49,
0x64, 0x22, 0x2b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70,
0x12, 0x1c, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08,
0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x72,
0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12,
0x1a, 0x0a, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73,
0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x73, 0x65, 0x78, 0x12, 0x1d, 0x0a,
0x0a, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x52, 0x09, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x14, 0x0a, 0x05,
0x65, 0x78, 0x74, 0x72, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x78, 0x74,
0x72, 0x61, 0x22, 0x3e, 0x0a, 0x0d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72,
0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x5f,
0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72,
0x49, 0x64, 0x22, 0x30, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x73, 0x65, 0x72,
0x52, 0x65, 0x73, 0x70, 0x12, 0x1e, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75,
0x73, 0x65, 0x72, 0x73, 0x32, 0x87, 0x02, 0x0a, 0x0b, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73,
0x73, 0x45, 0x78, 0x74, 0x12, 0x27, 0x0a, 0x06, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x12, 0x0d,
0x2e, 0x70, 0x62, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e,
0x70, 0x62, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x2a, 0x0a,
0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65,
0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65,
0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x2a, 0x0a, 0x0a, 0x55, 0x70, 0x64,
0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x11, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64,
0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x09, 0x2e, 0x70, 0x62, 0x2e,
0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x33, 0x0a, 0x0a, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55,
0x73, 0x65, 0x72, 0x12, 0x11, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55,
0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x61, 0x72,
0x63, 0x68, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x42, 0x0a, 0x0f, 0x43, 0x6c,
0x6f, 0x75, 0x64, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x16, 0x2e,
0x70, 0x62, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69,
0x6c, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64,
0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x42, 0x0d,
0x5a, 0x0b, 0x67, 0x69, 0x6d, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
} }


var ( var (
@@ -619,34 +770,38 @@ func file_business_ext_proto_rawDescGZIP() []byte {
return file_business_ext_proto_rawDescData return file_business_ext_proto_rawDescData
} }


var file_business_ext_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_business_ext_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
var file_business_ext_proto_goTypes = []interface{}{ var file_business_ext_proto_goTypes = []interface{}{
(*SignInReq)(nil), // 0: pb.SignInReq
(*SignInResp)(nil), // 1: pb.SignInResp
(*User)(nil), // 2: pb.User
(*GetUserReq)(nil), // 3: pb.GetUserReq
(*GetUserResp)(nil), // 4: pb.GetUserResp
(*UpdateUserReq)(nil), // 5: pb.UpdateUserReq
(*SearchUserReq)(nil), // 6: pb.SearchUserReq
(*SearchUserResp)(nil), // 7: pb.SearchUserResp
(*Empty)(nil), // 8: pb.Empty
(*SignInReq)(nil), // 0: pb.SignInReq
(*SignInResp)(nil), // 1: pb.SignInResp
(*CloudUploadFileReq)(nil), // 2: pb.CloudUploadFileReq
(*CloudUploadFileResp)(nil), // 3: pb.CloudUploadFileResp
(*User)(nil), // 4: pb.User
(*GetUserReq)(nil), // 5: pb.GetUserReq
(*GetUserResp)(nil), // 6: pb.GetUserResp
(*UpdateUserReq)(nil), // 7: pb.UpdateUserReq
(*SearchUserReq)(nil), // 8: pb.SearchUserReq
(*SearchUserResp)(nil), // 9: pb.SearchUserResp
(*Empty)(nil), // 10: pb.Empty
} }
var file_business_ext_proto_depIdxs = []int32{ var file_business_ext_proto_depIdxs = []int32{
2, // 0: pb.GetUserResp.user:type_name -> pb.User
2, // 1: pb.SearchUserResp.users:type_name -> pb.User
0, // 2: pb.BusinessExt.SignIn:input_type -> pb.SignInReq
3, // 3: pb.BusinessExt.GetUser:input_type -> pb.GetUserReq
5, // 4: pb.BusinessExt.UpdateUser:input_type -> pb.UpdateUserReq
6, // 5: pb.BusinessExt.SearchUser:input_type -> pb.SearchUserReq
1, // 6: pb.BusinessExt.SignIn:output_type -> pb.SignInResp
4, // 7: pb.BusinessExt.GetUser:output_type -> pb.GetUserResp
8, // 8: pb.BusinessExt.UpdateUser:output_type -> pb.Empty
7, // 9: pb.BusinessExt.SearchUser:output_type -> pb.SearchUserResp
6, // [6:10] is the sub-list for method output_type
2, // [2:6] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
4, // 0: pb.GetUserResp.user:type_name -> pb.User
4, // 1: pb.SearchUserResp.users:type_name -> pb.User
0, // 2: pb.BusinessExt.SignIn:input_type -> pb.SignInReq
5, // 3: pb.BusinessExt.GetUser:input_type -> pb.GetUserReq
7, // 4: pb.BusinessExt.UpdateUser:input_type -> pb.UpdateUserReq
8, // 5: pb.BusinessExt.SearchUser:input_type -> pb.SearchUserReq
2, // 6: pb.BusinessExt.CloudUploadFile:input_type -> pb.CloudUploadFileReq
1, // 7: pb.BusinessExt.SignIn:output_type -> pb.SignInResp
6, // 8: pb.BusinessExt.GetUser:output_type -> pb.GetUserResp
10, // 9: pb.BusinessExt.UpdateUser:output_type -> pb.Empty
9, // 10: pb.BusinessExt.SearchUser:output_type -> pb.SearchUserResp
3, // 11: pb.BusinessExt.CloudUploadFile:output_type -> pb.CloudUploadFileResp
7, // [7:12] is the sub-list for method output_type
2, // [2:7] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
} }


func init() { file_business_ext_proto_init() } func init() { file_business_ext_proto_init() }
@@ -681,7 +836,7 @@ func file_business_ext_proto_init() {
} }
} }
file_business_ext_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { file_business_ext_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*User); i {
switch v := v.(*CloudUploadFileReq); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@@ -693,7 +848,7 @@ func file_business_ext_proto_init() {
} }
} }
file_business_ext_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { file_business_ext_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetUserReq); i {
switch v := v.(*CloudUploadFileResp); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@@ -705,7 +860,7 @@ func file_business_ext_proto_init() {
} }
} }
file_business_ext_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { file_business_ext_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetUserResp); i {
switch v := v.(*User); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@@ -717,7 +872,7 @@ func file_business_ext_proto_init() {
} }
} }
file_business_ext_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { file_business_ext_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateUserReq); i {
switch v := v.(*GetUserReq); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@@ -729,7 +884,7 @@ func file_business_ext_proto_init() {
} }
} }
file_business_ext_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { file_business_ext_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SearchUserReq); i {
switch v := v.(*GetUserResp); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@@ -741,6 +896,30 @@ func file_business_ext_proto_init() {
} }
} }
file_business_ext_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { file_business_ext_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateUserReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_business_ext_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SearchUserReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_business_ext_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SearchUserResp); i { switch v := v.(*SearchUserResp); i {
case 0: case 0:
return &v.state return &v.state
@@ -759,7 +938,7 @@ func file_business_ext_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_business_ext_proto_rawDesc, RawDescriptor: file_business_ext_proto_rawDesc,
NumEnums: 0, NumEnums: 0,
NumMessages: 8,
NumMessages: 10,
NumExtensions: 0, NumExtensions: 0,
NumServices: 1, NumServices: 1,
}, },
@@ -773,17 +952,14 @@ func file_business_ext_proto_init() {
file_business_ext_proto_depIdxs = nil file_business_ext_proto_depIdxs = nil
} }


// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConnInterface

// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against. // is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7


// BusinessExtClient is the client API for BusinessExt service. // BusinessExtClient is the client API for BusinessExt service.
// //
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type BusinessExtClient interface { type BusinessExtClient interface {
// 登录 // 登录
SignIn(ctx context.Context, in *SignInReq, opts ...grpc.CallOption) (*SignInResp, error) SignIn(ctx context.Context, in *SignInReq, opts ...grpc.CallOption) (*SignInResp, error)
@@ -793,6 +969,8 @@ type BusinessExtClient interface {
UpdateUser(ctx context.Context, in *UpdateUserReq, opts ...grpc.CallOption) (*Empty, error) UpdateUser(ctx context.Context, in *UpdateUserReq, opts ...grpc.CallOption) (*Empty, error)
// 搜索用户(这里简单数据库实现,生产环境建议使用ES) // 搜索用户(这里简单数据库实现,生产环境建议使用ES)
SearchUser(ctx context.Context, in *SearchUserReq, opts ...grpc.CallOption) (*SearchUserResp, error) SearchUser(ctx context.Context, in *SearchUserReq, opts ...grpc.CallOption) (*SearchUserResp, error)
// 上传文件至云端
CloudUploadFile(ctx context.Context, in *CloudUploadFileReq, opts ...grpc.CallOption) (*CloudUploadFileResp, error)
} }


type businessExtClient struct { type businessExtClient struct {
@@ -839,7 +1017,18 @@ func (c *businessExtClient) SearchUser(ctx context.Context, in *SearchUserReq, o
return out, nil return out, nil
} }


func (c *businessExtClient) CloudUploadFile(ctx context.Context, in *CloudUploadFileReq, opts ...grpc.CallOption) (*CloudUploadFileResp, error) {
out := new(CloudUploadFileResp)
err := c.cc.Invoke(ctx, "/pb.BusinessExt/CloudUploadFile", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}

// BusinessExtServer is the server API for BusinessExt service. // BusinessExtServer is the server API for BusinessExt service.
// All implementations must embed UnimplementedBusinessExtServer
// for forward compatibility
type BusinessExtServer interface { type BusinessExtServer interface {
// 登录 // 登录
SignIn(context.Context, *SignInReq) (*SignInResp, error) SignIn(context.Context, *SignInReq) (*SignInResp, error)
@@ -849,27 +1038,32 @@ type BusinessExtServer interface {
UpdateUser(context.Context, *UpdateUserReq) (*Empty, error) UpdateUser(context.Context, *UpdateUserReq) (*Empty, error)
// 搜索用户(这里简单数据库实现,生产环境建议使用ES) // 搜索用户(这里简单数据库实现,生产环境建议使用ES)
SearchUser(context.Context, *SearchUserReq) (*SearchUserResp, error) SearchUser(context.Context, *SearchUserReq) (*SearchUserResp, error)
// 上传文件至云端
CloudUploadFile(context.Context, *CloudUploadFileReq) (*CloudUploadFileResp, error)
} }


// UnimplementedBusinessExtServer can be embedded to have forward compatible implementations.
// UnimplementedBusinessExtServer must be embedded to have forward compatible implementations.
type UnimplementedBusinessExtServer struct { type UnimplementedBusinessExtServer struct {
} }


func (*UnimplementedBusinessExtServer) SignIn(context.Context, *SignInReq) (*SignInResp, error) {
func (UnimplementedBusinessExtServer) SignIn(context.Context, *SignInReq) (*SignInResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method SignIn not implemented") return nil, status.Errorf(codes.Unimplemented, "method SignIn not implemented")
} }
func (*UnimplementedBusinessExtServer) GetUser(context.Context, *GetUserReq) (*GetUserResp, error) {
func (UnimplementedBusinessExtServer) GetUser(context.Context, *GetUserReq) (*GetUserResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetUser not implemented") return nil, status.Errorf(codes.Unimplemented, "method GetUser not implemented")
} }
func (*UnimplementedBusinessExtServer) UpdateUser(context.Context, *UpdateUserReq) (*Empty, error) {
func (UnimplementedBusinessExtServer) UpdateUser(context.Context, *UpdateUserReq) (*Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateUser not implemented") return nil, status.Errorf(codes.Unimplemented, "method UpdateUser not implemented")
} }
func (*UnimplementedBusinessExtServer) SearchUser(context.Context, *SearchUserReq) (*SearchUserResp, error) {
func (UnimplementedBusinessExtServer) SearchUser(context.Context, *SearchUserReq) (*SearchUserResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method SearchUser not implemented") return nil, status.Errorf(codes.Unimplemented, "method SearchUser not implemented")
} }
func (UnimplementedBusinessExtServer) CloudUploadFile(context.Context, *CloudUploadFileReq) (*CloudUploadFileResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method CloudUploadFile not implemented")
}


func RegisterBusinessExtServer(s *grpc.Server, srv BusinessExtServer) {
s.RegisterService(&_BusinessExt_serviceDesc, srv)
func RegisterBusinessExtServer(s grpc.ServiceRegistrar, srv BusinessExtServer) {
s.RegisterService(&BusinessExt_ServiceDesc, srv)
} }


func _BusinessExt_SignIn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _BusinessExt_SignIn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
@@ -944,7 +1138,28 @@ func _BusinessExt_SearchUser_Handler(srv interface{}, ctx context.Context, dec f
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }


var _BusinessExt_serviceDesc = grpc.ServiceDesc{
func _BusinessExt_CloudUploadFile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CloudUploadFileReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BusinessExtServer).CloudUploadFile(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/pb.BusinessExt/CloudUploadFile",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BusinessExtServer).CloudUploadFile(ctx, req.(*CloudUploadFileReq))
}
return interceptor(ctx, in, info, handler)
}

// BusinessExt_ServiceDesc is the grpc.ServiceDesc for BusinessExt service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var BusinessExt_ServiceDesc = grpc.ServiceDesc{
ServiceName: "pb.BusinessExt", ServiceName: "pb.BusinessExt",
HandlerType: (*BusinessExtServer)(nil), HandlerType: (*BusinessExtServer)(nil),
Methods: []grpc.MethodDesc{ Methods: []grpc.MethodDesc{
@@ -964,7 +1179,11 @@ var _BusinessExt_serviceDesc = grpc.ServiceDesc{
MethodName: "SearchUser", MethodName: "SearchUser",
Handler: _BusinessExt_SearchUser_Handler, Handler: _BusinessExt_SearchUser_Handler,
}, },
{
MethodName: "CloudUploadFile",
Handler: _BusinessExt_CloudUploadFile_Handler,
},
}, },
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
Metadata: "business.ext.proto_back",
Metadata: "business.ext.proto",
} }

+ 1
- 1
pkg/pb/business.int.pb.go View File

@@ -333,7 +333,7 @@ func file_business_int_proto_init() {
var _ context.Context var _ context.Context
var _ grpc.ClientConnInterface var _ grpc.ClientConnInterface


// This is a compile-time assertion to ensure that this generated file
// This is a compile-time assertion to ensure that this generated comm
// is compatible with the grpc package it is being compiled against. // is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6 const _ = grpc.SupportPackageIsVersion6




+ 1
- 1
pkg/pb/connect.int.pb.go View File

@@ -316,7 +316,7 @@ func file_connect_int_proto_init() {
var _ context.Context var _ context.Context
var _ grpc.ClientConnInterface var _ grpc.ClientConnInterface


// This is a compile-time assertion to ensure that this generated file
// This is a compile-time assertion to ensure that this generated comm
// is compatible with the grpc package it is being compiled against. // is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6 const _ = grpc.SupportPackageIsVersion6




+ 1
- 1
pkg/pb/logic.ext.pb.go View File

@@ -2387,7 +2387,7 @@ func file_logic_ext_proto_init() {
var _ context.Context var _ context.Context
var _ grpc.ClientConnInterface var _ grpc.ClientConnInterface


// This is a compile-time assertion to ensure that this generated file
// This is a compile-time assertion to ensure that this generated comm
// is compatible with the grpc package it is being compiled against. // is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6 const _ = grpc.SupportPackageIsVersion6




+ 1
- 1
pkg/pb/logic.int.pb.go View File

@@ -1126,7 +1126,7 @@ func file_logic_int_proto_init() {
var _ context.Context var _ context.Context
var _ grpc.ClientConnInterface var _ grpc.ClientConnInterface


// This is a compile-time assertion to ensure that this generated file
// This is a compile-time assertion to ensure that this generated comm
// is compatible with the grpc package it is being compiled against. // is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6 const _ = grpc.SupportPackageIsVersion6




+ 14
- 1
pkg/proto/business.ext.proto View File

@@ -2,7 +2,7 @@ syntax = "proto3";
package pb; package pb;
option go_package = "gim/pkg/pb/"; option go_package = "gim/pkg/pb/";


import "common.ext.proto";
message Empty{}


service BusinessExt { service BusinessExt {
// 登录 // 登录
@@ -13,6 +13,8 @@ service BusinessExt {
rpc UpdateUser (UpdateUserReq) returns (Empty); rpc UpdateUser (UpdateUserReq) returns (Empty);
// 搜索用户(这里简单数据库实现,生产环境建议使用ES) // 搜索用户(这里简单数据库实现,生产环境建议使用ES)
rpc SearchUser (SearchUserReq) returns (SearchUserResp); rpc SearchUser (SearchUserReq) returns (SearchUserResp);
// 上传文件至云端
rpc CloudUploadFile (CloudUploadFileReq) returns (CloudUploadFileResp);
} }


message SignInReq { message SignInReq {
@@ -27,6 +29,17 @@ message SignInResp {
string token = 3; // token string token = 3; // token
int64 master_id = 4; // 站长id int64 master_id = 4; // 站长id
} }
message CloudUploadFileReq {
string dir = 1; // 目录名
string file_name = 2; // 上传原文件名称
string file_size = 3; // 文件大小
}
message CloudUploadFileResp {
string method = 1; // 请求方式
string host = 2; // 域名
string key = 3; // key
string token = 4; // token
}


message User { message User {
int64 user_id = 1; // 用户id int64 user_id = 1; // 用户id


+ 2
- 0
pkg/rpc/rpc.go View File

@@ -58,6 +58,8 @@ func initConnectIntClient() {
} }


func initBusinessIntClient() { func initBusinessIntClient() {
//conn, err := grpc.DialContext(context.TODO(), "127.0.0.1:8000", grpc.WithInsecure(),
// grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, roundrobin.Name)))
conn, err := grpc.DialContext(context.TODO(), k8s.GetK8STarget("gim", "business", "8000"), grpc.WithInsecure(), conn, err := grpc.DialContext(context.TODO(), k8s.GetK8STarget("gim", "business", "8000"), grpc.WithInsecure(),
grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, roundrobin.Name))) grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, roundrobin.Name)))
if err != nil { if err != nil {


+ 9
- 2
pkg/util/json.go View File

@@ -48,8 +48,15 @@ func FormatMessage(messageType pb.MessageType, messageContent []byte) string {
msg = &pb.Text{} msg = &pb.Text{}
err = proto.Unmarshal(messageContent, msg) err = proto.Unmarshal(messageContent, msg)
case pb.MessageType_MT_COMMAND: case pb.MessageType_MT_COMMAND:
msg = &pb.Text{}
err = proto.Unmarshal(messageContent, msg)
msgCmd := &pb.Command{
Code: 0,
Data: nil,
}
err = proto.Unmarshal(messageContent, msgCmd)
if msgCmd.Code == int32(pb.PushCode_PC_ADD_FRIEND) {
msg = &pb.AddFriendPush{}
err = proto.Unmarshal(messageContent, msg)
}
case pb.MessageType_MT_CUSTOM: case pb.MessageType_MT_CUSTOM:
msg = &pb.Text{} msg = &pb.Text{}
err = proto.Unmarshal(messageContent, msg) err = proto.Unmarshal(messageContent, msg)


+ 61
- 0
pkg/util/redis.go View File

@@ -1,6 +1,8 @@
package util package util


import ( import (
"encoding/json"
"gim/internal/business/comm/utils"
"gim/pkg/logger" "gim/pkg/logger"
"time" "time"


@@ -45,3 +47,62 @@ func (u *RedisUtil) Get(key string, value interface{}) error {
} }
return nil return nil
} }

func (u *RedisUtil) HGetString(key string, HKey string) (string, error) {
return u.client.Do("HGET", key, HKey).String()
}

func (u *RedisUtil) Exists(key string) bool {
count, err := u.client.Do("EXISTS", key).Int()
if count == 0 || err != nil {
return false
}
return true
}

func (u *RedisUtil) HSet(key string, HKey string, data interface{}) (interface{}, error) {
return u.client.HSet(key, HKey, data).Result()
}

func (u *RedisUtil) Expire(key string, ttl int) (interface{}, error) {
return u.client.Do("EXPIRE", key, ttl).Result()
}

func (u *RedisUtil) Del(key string) (interface{}, error) {
return u.client.Do("DEL", key).Result()
}

func (u *RedisUtil) Do(args ...interface{}) (reply interface{}, err error) {
return u.client.Do(args...).String()
}

func (u *RedisUtil) SetEx(key string, data interface{}, ttl int) (reply interface{}, err error) {
return u.client.Do("SETEX", key, ttl, data).Result()
}

func (u *RedisUtil) GetJson(key string, dst interface{}) error {
b, err := utils.Bytes(u.client.Do("GET", key).Result())
if err != nil {
return err
}
if err = json.Unmarshal(b, dst); err != nil {
return err
}
return nil
}

func (u *RedisUtil) SetJson(key string, data interface{}, ttl int) bool {
c, err := json.Marshal(data)
if err != nil {
return false
}
if ttl < 1 {
err = u.Set(key, c, time.Duration(ttl))
} else {
_, err = u.SetEx(key, c, ttl)
}
if err != nil {
return false
}
return true
}

+ 5
- 1
test/tcp_conn/main.go View File

@@ -87,7 +87,7 @@ func (c *TcpClient) SignIn() {
signIn := pb.SignInInput{ signIn := pb.SignInInput{
UserId: c.UserId, UserId: c.UserId,
DeviceId: c.DeviceId, DeviceId: c.DeviceId,
Token: "ABPIKUKGTCZZGLUSZQAGFXKCSQFEVXEMAYHNNOUZ",
Token: "GPFMVIWQKIKLLPHMDYECZJONPCAAKUWKMNGXRTSP",
} }
c.Output(pb.PackageType_PT_SIGN_IN, time.Now().UnixNano(), &signIn) c.Output(pb.PackageType_PT_SIGN_IN, time.Now().UnixNano(), &signIn)
} }
@@ -165,6 +165,10 @@ func (c *TcpClient) HandlePackage(bytes []byte) {
} }


msg := messageSend.Message msg := messageSend.Message
//if msg.Sender.SenderType == 1 {
// //系统发送的消息
//
//}
log.Printf("消息:发送者类型:%d 发送者id:%d 接收者类型:%d 接收者id:%d 消息内容:%+v seq:%d \n", log.Printf("消息:发送者类型:%d 发送者id:%d 接收者类型:%d 接收者id:%d 消息内容:%+v seq:%d \n",
msg.Sender.SenderType, msg.Sender.SenderId, msg.ReceiverType, msg.ReceiverId, util.FormatMessage(msg.MessageType, msg.MessageContent), msg.Seq) msg.Sender.SenderType, msg.Sender.SenderId, msg.ReceiverType, msg.ReceiverId, util.FormatMessage(msg.MessageType, msg.MessageContent), msg.Seq)




Loading…
Cancel
Save