Bladeren bron

Merge branch 'feature/v1.2.7_wky' of moapp/MessageCenter into feature/v1.2.7

wangkaiyue 2 jaren geleden
bovenliggende
commit
1dea0cc3d7

+ 3 - 0
entity/message.go

@@ -1,6 +1,7 @@
 package entity
 
 import (
+	m "app.yhyue.com/moapp/jybase/mongodb"
 	"app.yhyue.com/moapp/jybase/mysql"
 	"database/sql"
 	clientv3 "go.etcd.io/etcd/client/v3"
@@ -15,6 +16,8 @@ var EtcdCli *clientv3.Client
 var Mysql *mysql.Mysql
 var MessageColumn []map[string]interface{}
 var Mysql11 *sql.DB
+var MQFW m.MongodbSim
+
 var SurvivalTime int
 var SaveConcurrencyChan chan int //  定义保存消息并发
 

+ 27 - 1
rpc/etc/message.yaml

@@ -7,6 +7,15 @@ Etcd:
   Key: message.rpc
 Timeout: 10000
 Mysql: root:=PDT49#80Z!RVv52_z@tcp(192.168.3.217:4000)/messagetest?charset=utf8mb4&parseTime=true&loc=Local
+Mongodb:
+  Address: 192.168.3.206:27080
+  Size: 10
+  DbName: qfw
+  ReplSet:
+  UserName:
+  Password:
+  Collection:
+  Collection_back:
 DataSource:
     DbName: messagetest
     Address: 192.168.3.217:4000
@@ -24,4 +33,21 @@ FileSystemConf:
       - 127.0.0.1:2379
     Key: message.rpc
 SurvivalTime: 86400
-SaveConcurrency: 10
+SaveConcurrency: 10
+
+#发送微信模版消息
+WxTmplConfig:
+  rpcAddr: 127.0.0.1:8201 #微信rpc地址
+  tmplSetting: #模版消息配置
+    jySchool: "BD_wh9LRkDzt3etWMoVq811X4x4bwaApmH8REgojt8o" #剑鱼课堂消息模版
+    system: "oN_GXBBzYnrOTxL0KNWut3sK9tQQ1_vvX_SV-3QmUgw" #系统消息模版(包含服务通知、私信)
+    closeNotice: "如不再接收此类信息,请在我的-设置-推送设置关闭设置。"
+  limit:
+    total: 300000 # 每日发送信息数量限制
+    privateMessage: #私信
+      oneDayLimit: 5 #每天私信数量限制
+      duringMine: 60 #间隔时间单位分钟
+    alert: #告警
+      nums: [ 150000,250000 ] #告警数量
+      mail: [ "wangkaiyue@topnet.net.cn" ] #告警人邮箱
+

+ 1 - 1
service/getBuoyMsg.go → rpc/internal/common/getBuoyMsg.go

@@ -1,4 +1,4 @@
-package service
+package common
 
 import (
 	"app.yhyue.com/moapp/MessageCenter/entity"

+ 2 - 2
service/messageService.go → rpc/internal/common/messageService.go

@@ -1,4 +1,4 @@
-package service
+package common
 
 import (
 	"app.yhyue.com/moapp/MessageCenter/entity"
@@ -114,7 +114,7 @@ func (service *MessageService) LastMessage(userId string, appId string, msgType
 
 }
 
-//查询消息详情
+// 查询消息详情
 func FindMessageDetail(id string) (entity.Message, error) {
 	orm := entity.Engine.NewSession()
 	defer orm.Close()

+ 1 - 1
service/sendMsg.go → rpc/internal/common/sendMsg.go

@@ -1,4 +1,4 @@
-package service
+package common
 
 import (
 	"app.yhyue.com/moapp/MessageCenter/entity"

+ 105 - 0
rpc/internal/common/sendWxTmplMsg.go

@@ -0,0 +1,105 @@
+package common
+
+import (
+	"app.yhyue.com/moapp/MessageCenter/entity"
+	"app.yhyue.com/moapp/MessageCenter/rpc/internal/config"
+	"app.yhyue.com/moapp/jybase/common"
+	m "app.yhyue.com/moapp/jybase/mongodb"
+	qrpc "app.yhyue.com/moapp/jybase/rpc"
+	"fmt"
+)
+
+// GetUserOpenIdAndWxPushState 查询微信openid微信消息通知状态
+// mId mongoUserid、oId 用户openid、pId positionId 用户职位id
+func GetUserOpenIdAndWxPushState(mId, oId, pId, settingKey string) (openId string, wxPushOpen bool) {
+	uData := func() map[string]interface{} {
+		query := map[string]interface{}{}
+		if oId != "" {
+			query["s_m_openid"] = oId
+		} else if mId != "" {
+			query["_id"] = m.StringTOBsonId(mId)
+		} else if pId != "" {
+			uInfo := entity.Mysql.SelectBySql("SELECT user_id FROM base_service.base_position WHERE id = ? ", pId)
+			if uInfo != nil && len(*uInfo) > 0 {
+				fmt.Println((*uInfo)[0]["user_id"])
+				base_user_id := common.Int64All((*uInfo)[0]["user_id"])
+				if base_user_id != 0 {
+					query["base_user_id"] = base_user_id
+				}
+			}
+		}
+		if len(query) > 0 {
+			rData, _ := entity.MQFW.FindOneByField("user", query, fmt.Sprintf(`{"s_m_openid":1,"o_pushset.%s.i_wxpush":1}`, settingKey))
+			if rData != nil && len(*rData) > 0 {
+				return *rData
+			}
+		}
+		return nil
+	}()
+	if uData == nil {
+		return openId, false
+	}
+	openId = common.ObjToString(uData["s_m_openid"])
+	if pushsetMap := common.ObjToMap(uData["o_pushset"]); pushsetMap != nil && len(*pushsetMap) > 0 {
+		if pushkeyMap := common.ObjToMap((*pushsetMap)[settingKey]); pushkeyMap != nil && len(*pushkeyMap) > 0 {
+			wxPushOpen = common.Int64All((*pushkeyMap)["i_wxpush"]) == 1
+		}
+	}
+	return
+}
+
+// sendWxTmplMsg 发送微信模版消息
+func sendWxTmplMsg(openId, tplId, link string, msg map[string]*qrpc.TmplItem) (pushOk bool) {
+	pushOk, _ = qrpc.WxSendTmplMsg(config.ConfigJson.WxTmplConfig.RpcAddr, &qrpc.WxTmplMsg{
+		OpenId:   openId,
+		TplId:    tplId,
+		TmplData: msg,
+		Url:      link,
+		//Url:      Config.WebDomain + "/front/sess/" + util.Se_Topnet.EncodeString(s_m_openid+",uid,"+strconv.Itoa(int(time.Now().Unix()))+",msgremind") + "__" + hex.EncodeToString([]byte(fmt.Sprintf("type=%s&advertcode=%s", tp, wtmc.AdvertCode))),
+	})
+	return
+}
+
+// SendJySchoolMsg 发送剑鱼学堂类型消息
+// 标题 课程报名成功通知
+// 消息模版 课程名称 {{thing1.DATA}} 课程时间 {{time7.DATA}} 课程地点 {{thing6.DATA}} 课程类型 {{const11.DATA}}
+func SendJySchoolMsg(openId, title, date, address, class, link string) bool {
+	msg := map[string]*qrpc.TmplItem{
+		"thing1": &qrpc.TmplItem{
+			Value: title,
+		},
+		"time7": &qrpc.TmplItem{
+			Value: date,
+		},
+		"thing6": &qrpc.TmplItem{
+			Value: address,
+		},
+		"const11": &qrpc.TmplItem{
+			Value: class,
+		},
+	}
+	return sendWxTmplMsg(openId, "配置文件获取", link, msg)
+}
+
+// SendSystemMsg 系统消息模版(包含服务通知、私信)
+// 消息模版 工单类型 {{thing19.DATA}} 工单标题 {{thing6.DATA}} 项目名称 {{thing13.DATA}} 服务时间 {{time25.DATA}} 服务地址 {{thing26.DATA}}
+func SendSystemMsg(openId, msgClass, title, context, date, link string) bool {
+	msg := map[string]*qrpc.TmplItem{
+		"thing19": &qrpc.TmplItem{
+			Value: msgClass,
+		},
+		"thing6": &qrpc.TmplItem{
+			Value: title,
+		},
+		"thing13": &qrpc.TmplItem{
+			Value: context,
+		},
+		"time25": &qrpc.TmplItem{
+			Value: date,
+		},
+		"thing26": &qrpc.TmplItem{
+			Value: "如不再接收此类信息,请在我的-设置-推送设置关闭设置。",
+		},
+	}
+	return sendWxTmplMsg(openId, "配置文件获取", link, msg)
+}

+ 34 - 1
rpc/internal/config/config.go

@@ -9,8 +9,10 @@ type Config struct {
 	DataSource      *mysqlConfig // 手动代码
 	Mysql           string
 	Redis           *RedisConfig
+	Mongodb         *mgoConf
 	SurvivalTime    int
-	SaveConcurrency int // 消息保存并发数
+	SaveConcurrency int       // 消息保存并发数
+	WxTmplConfig    WxTmplMsg `json:"WxTmplConfig"`
 }
 
 type RedisConfig struct {
@@ -28,4 +30,35 @@ type mysqlConfig struct {
 	MaxIdleConns int
 }
 
+type mgoConf struct {
+	Address         string
+	Size            int
+	DbName          string
+	ReplSet         string
+	UserName        string
+	Password        string
+	Collection      string
+	Collection_back string
+}
+
 var ConfigJson Config
+
+type WxTmplMsg struct {
+	RpcAddr     string `json:"rpcAddr"`
+	TmplSetting struct {
+		JySchool    string `json:"jySchool"`
+		System      string `json:"system"`
+		CloseNotice string `json:"closeNotice"`
+	} `json:"tmplSetting"`
+	Limit struct {
+		Total          int `json:"total"`
+		PrivateMessage struct {
+			OneDayLimit int `json:"oneDayLimit"`
+			DuringMine  int `json:"duringMine"`
+		} `json:"privateMessage"`
+		Alert struct {
+			Nums []int    `json:"nums"`
+			Mail []string `json:"mail"`
+		} `json:"alert"`
+	} `json:"limit"`
+}

+ 1 - 1
rpc/internal/logic/changereadstatuslogic.go

@@ -1,9 +1,9 @@
 package logic
 
 import (
+	service "app.yhyue.com/moapp/MessageCenter/rpc/internal/common"
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
 	"app.yhyue.com/moapp/MessageCenter/rpc/messageclient"
-	"app.yhyue.com/moapp/MessageCenter/service"
 	"context"
 
 	"github.com/zeromicro/go-zero/core/logx"

+ 1 - 1
rpc/internal/logic/clearunreadmsglogic.go

@@ -1,7 +1,7 @@
 package logic
 
 import (
-	"app.yhyue.com/moapp/MessageCenter/service"
+	service "app.yhyue.com/moapp/MessageCenter/rpc/internal/common"
 	"context"
 
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"

+ 42 - 0
rpc/internal/logic/deletemultiplemessagelogic.go

@@ -0,0 +1,42 @@
+package logic
+
+import (
+	"app.yhyue.com/moapp/MessageCenter/rpc/messageclient"
+	"app.yhyue.com/moapp/MessageCenter/rpc/type/message"
+	"app.yhyue.com/moapp/MessageCenter/service"
+	"context"
+	"strings"
+
+	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type DeleteMultipleMessageLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewDeleteMultipleMessageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteMultipleMessageLogic {
+	return &DeleteMultipleMessageLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+//  删除多条消息
+func (l *DeleteMultipleMessageLogic) DeleteMultipleMessage(in *messageclient.DeleteMultipleMessageRequest) (*messageclient.Response, error) {
+	// todo: add your logic here and delete this line
+	m := &service.MessageService{}
+	var idSlice []string
+	tmpList := strings.Split(in.Id, ",")
+	for _, v := range tmpList {
+		idSlice = append(idSlice, v)
+	}
+	code, msg := m.DeleteMessage(idSlice, in.Appid)
+	return &message.Response{
+		Code:    code,
+		Message: msg,
+	}, nil
+}

+ 38 - 0
rpc/internal/logic/deletesinglemessagelogic.go

@@ -0,0 +1,38 @@
+package logic
+
+import (
+	"app.yhyue.com/moapp/MessageCenter/rpc/messageclient"
+	"app.yhyue.com/moapp/MessageCenter/service"
+	"context"
+
+	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type DeleteSingleMessageLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewDeleteSingleMessageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteSingleMessageLogic {
+	return &DeleteSingleMessageLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+//  删除单一消息
+func (l *DeleteSingleMessageLogic) DeleteSingleMessage(in *messageclient.DeleteSingleMessageRequest) (*messageclient.Response, error) {
+	// todo: add your logic here and delete this line
+
+	m := &service.MessageService{}
+	var idSlice []string
+	idSlice = append(idSlice, in.Id)
+	code, msg := m.DeleteMessage(idSlice, in.Appid)
+	return &messageclient.Response{
+		Code:    code,
+		Message: msg,
+	}, nil
+}

+ 1 - 1
rpc/internal/logic/findmessagedetaillogic.go

@@ -1,9 +1,9 @@
 package logic
 
 import (
+	service "app.yhyue.com/moapp/MessageCenter/rpc/internal/common"
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
 	"app.yhyue.com/moapp/MessageCenter/rpc/messageclient"
-	"app.yhyue.com/moapp/MessageCenter/service"
 	"context"
 
 	"github.com/zeromicro/go-zero/core/logx"

+ 1 - 1
rpc/internal/logic/finduserbuoymsglogic.go

@@ -1,8 +1,8 @@
 package logic
 
 import (
+	service "app.yhyue.com/moapp/MessageCenter/rpc/internal/common"
 	"app.yhyue.com/moapp/MessageCenter/rpc/type/message"
-	"app.yhyue.com/moapp/MessageCenter/service"
 	"context"
 
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"

+ 1 - 1
rpc/internal/logic/findusermsglogic.go

@@ -4,8 +4,8 @@ import (
 	"app.yhyue.com/moapp/MessageCenter/rpc/messageclient"
 	"context"
 
+	service "app.yhyue.com/moapp/MessageCenter/rpc/internal/common"
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
-	"app.yhyue.com/moapp/MessageCenter/service"
 	"github.com/zeromicro/go-zero/core/logx"
 )
 

+ 2 - 2
rpc/internal/logic/getclassunreadcountlogic.go

@@ -4,8 +4,8 @@ import (
 	"app.yhyue.com/moapp/MessageCenter/rpc/messageclient"
 	"context"
 
+	service "app.yhyue.com/moapp/MessageCenter/rpc/internal/common"
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
-	"app.yhyue.com/moapp/MessageCenter/service"
 	"github.com/zeromicro/go-zero/core/logx"
 )
 
@@ -23,7 +23,7 @@ func NewGetClassUnreadCountLogic(ctx context.Context, svcCtx *svc.ServiceContext
 	}
 }
 
-//   查询指定用户指定分类的未读消息合计
+// 查询指定用户指定分类的未读消息合计
 func (l *GetClassUnreadCountLogic) GetClassUnreadCount(in *messageclient.GetClassUnreadCountReq) (*messageclient.GetUnreadCountResponse, error) {
 	// todo: add your logic here and delete this line
 	code, msg, count := service.ClassCountUnread(int(in.MsgType), in.UserId, in.Appid)

+ 2 - 2
rpc/internal/logic/getlastmessagelogic.go

@@ -1,9 +1,9 @@
 package logic
 
 import (
+	service "app.yhyue.com/moapp/MessageCenter/rpc/internal/common"
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
 	"app.yhyue.com/moapp/MessageCenter/rpc/messageclient"
-	"app.yhyue.com/moapp/MessageCenter/service"
 	"context"
 
 	"github.com/zeromicro/go-zero/core/logx"
@@ -23,7 +23,7 @@ func NewGetLastMessageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Ge
 	}
 }
 
-//   获取指定分类的最新一条未读消息
+// 获取指定分类的最新一条未读消息
 func (l *GetLastMessageLogic) GetLastMessage(in *messageclient.GetLastMessageReq) (*messageclient.GetLastMessageRes, error) {
 	// todo: add your logic here and delete this line
 	m := service.MessageService{}

+ 2 - 2
rpc/internal/logic/getmsgtypelogic.go

@@ -1,8 +1,8 @@
 package logic
 
 import (
+	service "app.yhyue.com/moapp/MessageCenter/rpc/internal/common"
 	"app.yhyue.com/moapp/MessageCenter/rpc/messageclient"
-	"app.yhyue.com/moapp/MessageCenter/service"
 	"context"
 
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
@@ -23,7 +23,7 @@ func NewGetMsgTypeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetMsg
 	}
 }
 
-//   获取指定用户收到消息的分类
+// 获取指定用户收到消息的分类
 func (l *GetMsgTypeLogic) GetMsgType(in *messageclient.GetMsgTypeReq) (*messageclient.GetMsgTypeRes, error) {
 	// todo: add your logic here and delete this line
 	m := service.MessageService{}

+ 2 - 2
rpc/internal/logic/getunreadclasscountlogic.go

@@ -1,8 +1,8 @@
 package logic
 
 import (
+	service "app.yhyue.com/moapp/MessageCenter/rpc/internal/common"
 	"app.yhyue.com/moapp/MessageCenter/rpc/messageclient"
-	"app.yhyue.com/moapp/MessageCenter/service"
 	"context"
 
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
@@ -23,7 +23,7 @@ func NewGetUnreadClassCountLogic(ctx context.Context, svcCtx *svc.ServiceContext
 	}
 }
 
-//   获取指定用户的分类及未读消息的数量
+// 获取指定用户的分类及未读消息的数量
 func (l *GetUnreadClassCountLogic) GetUnreadClassCount(in *messageclient.GetUnreadClassCountReq) (*messageclient.GetUnreadClassCountRes, error) {
 	// todo: add your logic here and delete this line
 	m := service.MessageService{}

+ 2 - 2
rpc/internal/logic/getunreadcountlogic.go

@@ -1,8 +1,8 @@
 package logic
 
 import (
+	service "app.yhyue.com/moapp/MessageCenter/rpc/internal/common"
 	"app.yhyue.com/moapp/MessageCenter/rpc/messageclient"
-	"app.yhyue.com/moapp/MessageCenter/service"
 	"context"
 
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
@@ -23,7 +23,7 @@ func NewGetUnreadCountLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Ge
 	}
 }
 
-//   查询指定用户未读消息合计
+// 查询指定用户未读消息合计
 func (l *GetUnreadCountLogic) GetUnreadCount(in *messageclient.GetUnreadCountRequest) (*messageclient.GetUnreadCountResponse, error) {
 
 	m := &service.MessageService{}

+ 1 - 1
rpc/internal/logic/multiplesavemsglogic.go

@@ -1,8 +1,8 @@
 package logic
 
 import (
+	service "app.yhyue.com/moapp/MessageCenter/rpc/internal/common"
 	"app.yhyue.com/moapp/MessageCenter/rpc/messageclient"
-	"app.yhyue.com/moapp/MessageCenter/service"
 	"context"
 
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"

+ 1 - 1
rpc/internal/logic/sendusermsglogic.go

@@ -4,8 +4,8 @@ import (
 	"app.yhyue.com/moapp/MessageCenter/rpc/messageclient"
 	"context"
 
+	service "app.yhyue.com/moapp/MessageCenter/rpc/internal/common"
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
-	"app.yhyue.com/moapp/MessageCenter/service"
 	"github.com/zeromicro/go-zero/core/logx"
 )
 

+ 31 - 0
rpc/internal/logic/sendwxtmplmsglogic.go

@@ -0,0 +1,31 @@
+package logic
+
+import (
+	"context"
+
+	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
+	"app.yhyue.com/moapp/MessageCenter/rpc/type/message"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type SendWxTmplMsgLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewSendWxTmplMsgLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SendWxTmplMsgLogic {
+	return &SendWxTmplMsgLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+// 发送微信模版消息
+func (l *SendWxTmplMsgLogic) SendWxTmplMsg(in *message.WxTmplMsg) (*message.Response, error) {
+	// todo: add your logic here and delete this line
+
+	return &message.Response{}, nil
+}

+ 1 - 1
rpc/internal/logic/updatemessagereadlogic.go

@@ -1,9 +1,9 @@
 package logic
 
 import (
+	service "app.yhyue.com/moapp/MessageCenter/rpc/internal/common"
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
 	"app.yhyue.com/moapp/MessageCenter/rpc/messageclient"
-	"app.yhyue.com/moapp/MessageCenter/service"
 	"context"
 
 	"github.com/zeromicro/go-zero/core/logx"

+ 1 - 1
rpc/internal/logic/usermsglistlogic.go

@@ -1,7 +1,7 @@
 package logic
 
 import (
-	"app.yhyue.com/moapp/MessageCenter/service"
+	service "app.yhyue.com/moapp/MessageCenter/rpc/internal/common"
 	"app.yhyue.com/moapp/MessageCenter/util"
 	"context"
 

+ 37 - 13
rpc/internal/server/messageserver.go

@@ -1,4 +1,4 @@
-// Code generated by goctl. DO NOT EDIT!
+// Code generated by goctl. DO NOT EDIT.
 // Source: message.proto
 
 package server
@@ -8,7 +8,7 @@ import (
 
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/logic"
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
-	"app.yhyue.com/moapp/MessageCenter/rpc/pb/message"
+	"app.yhyue.com/moapp/MessageCenter/rpc/type/message"
 )
 
 type MessageServer struct {
@@ -28,8 +28,8 @@ func (s *MessageServer) MultipleSaveMsg(ctx context.Context, in *message.Multipl
 	return l.MultipleSaveMsg(in)
 }
 
-//  修改消息阅读状态
-func (s *MessageServer) ChangeReadStatus(ctx context.Context, in *message.ChangeReadStatusReq) (*message.Response, error) {
+// 修改消息阅读状态
+func (s *MessageServer) ChangeReadStatus(ctx context.Context, in *message.ChangeReadStatusRequest) (*message.Response, error) {
 	l := logic.NewChangeReadStatusLogic(ctx, s.svcCtx)
 	return l.ChangeReadStatus(in)
 }
@@ -40,25 +40,37 @@ func (s *MessageServer) SendUserMsg(ctx context.Context, in *message.SendMsgRequ
 	return l.SendUserMsg(in)
 }
 
-//   查询指定用户未读消息合计
+// 删除单一消息
+func (s *MessageServer) DeleteSingleMessage(ctx context.Context, in *message.DeleteSingleMessageRequest) (*message.Response, error) {
+	l := logic.NewDeleteSingleMessageLogic(ctx, s.svcCtx)
+	return l.DeleteSingleMessage(in)
+}
+
+// 删除多条消息
+func (s *MessageServer) DeleteMultipleMessage(ctx context.Context, in *message.DeleteMultipleMessageRequest) (*message.Response, error) {
+	l := logic.NewDeleteMultipleMessageLogic(ctx, s.svcCtx)
+	return l.DeleteMultipleMessage(in)
+}
+
+// 查询指定用户未读消息合计
 func (s *MessageServer) GetUnreadCount(ctx context.Context, in *message.GetUnreadCountRequest) (*message.GetUnreadCountResponse, error) {
 	l := logic.NewGetUnreadCountLogic(ctx, s.svcCtx)
 	return l.GetUnreadCount(in)
 }
 
-//   查询指定用户的历史消息记录
+// 查询指定用户的历史消息记录
 func (s *MessageServer) FindUserMsg(ctx context.Context, in *message.FindUserMsgReq) (*message.FindUserMsgRes, error) {
 	l := logic.NewFindUserMsgLogic(ctx, s.svcCtx)
 	return l.FindUserMsg(in)
 }
 
-//   查询指定用户指定分类的未读消息合计
+// 查询指定用户指定分类的未读消息合计
 func (s *MessageServer) GetClassUnreadCount(ctx context.Context, in *message.GetClassUnreadCountReq) (*message.GetUnreadCountResponse, error) {
 	l := logic.NewGetClassUnreadCountLogic(ctx, s.svcCtx)
 	return l.GetClassUnreadCount(in)
 }
 
-//   获取指定用户指定分类的最新一条消息
+// 获取指定用户指定分类的最新一条消息
 func (s *MessageServer) GetLastMessage(ctx context.Context, in *message.GetLastMessageReq) (*message.GetLastMessageRes, error) {
 	l := logic.NewGetLastMessageLogic(ctx, s.svcCtx)
 	return l.GetLastMessage(in)
@@ -70,32 +82,44 @@ func (s *MessageServer) FindMessageDetail(ctx context.Context, in *message.Messa
 	return l.FindMessageDetail(in)
 }
 
-//   获取指定用户的分类及未读消息数量
+// 获取指定用户的分类及未读消息数量
 func (s *MessageServer) GetUnreadClassCount(ctx context.Context, in *message.GetUnreadClassCountReq) (*message.GetUnreadClassCountRes, error) {
 	l := logic.NewGetUnreadClassCountLogic(ctx, s.svcCtx)
 	return l.GetUnreadClassCount(in)
 }
 
-//   获取指定用户收到消息的分类
+// 获取指定用户收到消息的分类
 func (s *MessageServer) GetMsgType(ctx context.Context, in *message.GetMsgTypeReq) (*message.GetMsgTypeRes, error) {
 	l := logic.NewGetMsgTypeLogic(ctx, s.svcCtx)
 	return l.GetMsgType(in)
 }
 
-//   查询指定用户的浮标消息
+// 修改用户指定分类下的消息已读未读
+func (s *MessageServer) UpdateMessageRead(ctx context.Context, in *message.UpdateMessageReadReq) (*message.UpdateMessageReadResp, error) {
+	l := logic.NewUpdateMessageReadLogic(ctx, s.svcCtx)
+	return l.UpdateMessageRead(in)
+}
+
+// 查询指定用户的浮标消息
 func (s *MessageServer) FindUserBuoyMsg(ctx context.Context, in *message.FindUserBuoyMsgReq) (*message.FindUserBuoyMsgRes, error) {
 	l := logic.NewFindUserBuoyMsgLogic(ctx, s.svcCtx)
 	return l.FindUserBuoyMsg(in)
 }
 
-//    一键清空未读消息
+// 一键清空未读消息
 func (s *MessageServer) ClearUnreadMsg(ctx context.Context, in *message.ClearUnreadMsgReq) (*message.Response, error) {
 	l := logic.NewClearUnreadMsgLogic(ctx, s.svcCtx)
 	return l.ClearUnreadMsg(in)
 }
 
-//    new用户消息列表
+// new用户消息列表
 func (s *MessageServer) UserMsgList(ctx context.Context, in *message.UserMsgListReq) (*message.UserMsgListRes, error) {
 	l := logic.NewUserMsgListLogic(ctx, s.svcCtx)
 	return l.UserMsgList(in)
 }
+
+// 发送微信模版消息
+func (s *MessageServer) SendWxTmplMsg(ctx context.Context, in *message.WxTmplMsg) (*message.Response, error) {
+	l := logic.NewSendWxTmplMsgLogic(ctx, s.svcCtx)
+	return l.SendWxTmplMsg(in)
+}

+ 12 - 0
rpc/message.go

@@ -9,6 +9,7 @@ import (
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/server"
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
 	"app.yhyue.com/moapp/MessageCenter/rpc/type/message"
+	m "app.yhyue.com/moapp/jybase/mongodb"
 	"app.yhyue.com/moapp/jybase/mysql"
 	"app.yhyue.com/moapp/jybase/redis"
 	"flag"
@@ -69,6 +70,17 @@ func init() {
 		log.Println("--初始化 redis--")
 		redis.InitRedisBySize(fmt.Sprintf("%s=%s", config.ConfigJson.Redis.Modules, config.ConfigJson.Redis.Addr), 20, 30, 300)
 	}
+	// 初始化mongo
+	if config.ConfigJson.Mongodb != nil {
+		log.Println("初始化 mongodb main")
+		entity.MQFW = m.MongodbSim{
+			MongodbAddr: config.ConfigJson.Mongodb.Address,
+			Size:        config.ConfigJson.Mongodb.Size,
+			DbName:      config.ConfigJson.Mongodb.DbName,
+			ReplSet:     config.ConfigJson.Mongodb.ReplSet,
+		}
+		entity.MQFW.InitPool()
+	}
 	// 初始化消息保存并发通道
 	entity.SaveConcurrencyChan = make(chan int, config.ConfigJson.SaveConcurrency)
 	//初始化日志信息

+ 21 - 0
rpc/message.proto

@@ -207,6 +207,18 @@ message UserMsgList {
     int64 count = 3; //总数
 }
 
+
+// 发送微信模版消息
+message WxTmplMsg {
+    string appid = 1;     //应用标识
+    string userIds = 2;   //接受人 mongo_userId(多个用,分割)
+    string openIds = 3;    //接受人 openid(多个用,分割)
+    string positionIds = 4; //接受人 职位id
+    string url = 5;       //消息跳转连接
+    int64 msgType = 6;    //信息类型 附件、图片、链接类型
+    string tmplId = 7;     //消息模版id 根据此字段判断发送模版
+}
+
 message AllSortData {
     int64 unreadMessages =1 ;
    string name =2;
@@ -215,6 +227,13 @@ message AllSortData {
    repeated Messages data = 5; //
 }
 
+
+message WxTmplResponse {
+    int64 sendTotal = 1; //发送数量
+    string message = 2; //信息
+}
+
+
 service Message {
     //批量保存消息
     rpc multipleSaveMsg (multipleSaveMsgReq) returns (multipleSaveMsgResp);
@@ -244,4 +263,6 @@ service Message {
 
     //   new用户消息列表
     rpc UserMsgList (UserMsgListReq) returns (UserMsgListRes);
+    //  发送微信模版消息
+    rpc SendWxTmplMsg (WxTmplMsg) returns(Response);
 }

+ 23 - 13
rpc/messageclient/message.go

@@ -1,4 +1,4 @@
-// Code generated by goctl. DO NOT EDIT!
+// Code generated by goctl. DO NOT EDIT.
 // Source: message.proto
 
 package messageclient
@@ -46,40 +46,44 @@ type (
 	UserMsgList                  = message.UserMsgList
 	UserMsgListReq               = message.UserMsgListReq
 	UserMsgListRes               = message.UserMsgListRes
+	WxTmplMsg                    = message.WxTmplMsg
+	WxTmplResponse               = message.WxTmplResponse
 
 	Message interface {
 		// 批量保存消息
 		MultipleSaveMsg(ctx context.Context, in *MultipleSaveMsgReq, opts ...grpc.CallOption) (*MultipleSaveMsgResp, error)
-		//  修改消息阅读状态
+		// 修改消息阅读状态
 		ChangeReadStatus(ctx context.Context, in *ChangeReadStatusRequest, opts ...grpc.CallOption) (*Response, error)
 		// 指定用户发消息
 		SendUserMsg(ctx context.Context, in *SendMsgRequest, opts ...grpc.CallOption) (*Response, error)
-		//  删除单一消息
+		// 删除单一消息
 		DeleteSingleMessage(ctx context.Context, in *DeleteSingleMessageRequest, opts ...grpc.CallOption) (*Response, error)
-		//  删除多条消息
+		// 删除多条消息
 		DeleteMultipleMessage(ctx context.Context, in *DeleteMultipleMessageRequest, opts ...grpc.CallOption) (*Response, error)
-		//   查询指定用户未读消息合计
+		// 查询指定用户未读消息合计
 		GetUnreadCount(ctx context.Context, in *GetUnreadCountRequest, opts ...grpc.CallOption) (*GetUnreadCountResponse, error)
-		//   查询指定用户的历史消息记录
+		// 查询指定用户的历史消息记录
 		FindUserMsg(ctx context.Context, in *FindUserMsgReq, opts ...grpc.CallOption) (*FindUserMsgRes, error)
-		//   查询指定用户指定分类的未读消息合计
+		// 查询指定用户指定分类的未读消息合计
 		GetClassUnreadCount(ctx context.Context, in *GetClassUnreadCountReq, opts ...grpc.CallOption) (*GetUnreadCountResponse, error)
-		//   获取指定用户指定分类的最新一条消息
+		// 获取指定用户指定分类的最新一条消息
 		GetLastMessage(ctx context.Context, in *GetLastMessageReq, opts ...grpc.CallOption) (*GetLastMessageRes, error)
 		// 查看详细详情
 		FindMessageDetail(ctx context.Context, in *MessageDetailReq, opts ...grpc.CallOption) (*MessageDetailResp, error)
-		//   获取指定用户的分类及未读消息数量
+		// 获取指定用户的分类及未读消息数量
 		GetUnreadClassCount(ctx context.Context, in *GetUnreadClassCountReq, opts ...grpc.CallOption) (*GetUnreadClassCountRes, error)
-		//   获取指定用户收到消息的分类
+		// 获取指定用户收到消息的分类
 		GetMsgType(ctx context.Context, in *GetMsgTypeReq, opts ...grpc.CallOption) (*GetMsgTypeRes, error)
 		// 修改用户指定分类下的消息已读未读
 		UpdateMessageRead(ctx context.Context, in *UpdateMessageReadReq, opts ...grpc.CallOption) (*UpdateMessageReadResp, error)
-		//   查询指定用户的浮标消息
+		// 查询指定用户的浮标消息
 		FindUserBuoyMsg(ctx context.Context, in *FindUserBuoyMsgReq, opts ...grpc.CallOption) (*FindUserBuoyMsgRes, error)
-		//    一键清空未读消息
+		// 一键清空未读消息
 		ClearUnreadMsg(ctx context.Context, in *ClearUnreadMsgReq, opts ...grpc.CallOption) (*Response, error)
-		//    new用户消息列表
+		// new用户消息列表
 		UserMsgList(ctx context.Context, in *UserMsgListReq, opts ...grpc.CallOption) (*UserMsgListRes, error)
+		// 发送微信模版消息
+		SendWxTmplMsg(ctx context.Context, in *WxTmplMsg, opts ...grpc.CallOption) (*Response, error)
 	}
 
 	defaultMessage struct {
@@ -188,3 +192,9 @@ func (m *defaultMessage) UserMsgList(ctx context.Context, in *UserMsgListReq, op
 	client := message.NewMessageClient(m.cli.Conn())
 	return client.UserMsgList(ctx, in, opts...)
 }
+
+// 发送微信模版消息
+func (m *defaultMessage) SendWxTmplMsg(ctx context.Context, in *WxTmplMsg, opts ...grpc.CallOption) (*Response, error) {
+	client := message.NewMessageClient(m.cli.Conn())
+	return client.SendWxTmplMsg(ctx, in, opts...)
+}

+ 315 - 116
rpc/type/message/message.pb.go

@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.28.1
-// 	protoc        v3.19.4
+// 	protoc-gen-go v1.30.0
+// 	protoc        v3.21.12
 // source: message.proto
 
 package message
@@ -2370,6 +2370,102 @@ func (x *UserMsgList) GetCount() int64 {
 	return 0
 }
 
+// 发送微信模版消息
+type WxTmplMsg struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Appid       string `protobuf:"bytes,1,opt,name=appid,proto3" json:"appid,omitempty"`             //应用标识
+	UserIds     string `protobuf:"bytes,2,opt,name=userIds,proto3" json:"userIds,omitempty"`         //接受人 mongo_userId(多个用,分割)
+	OpenIds     string `protobuf:"bytes,3,opt,name=openIds,proto3" json:"openIds,omitempty"`         //接受人 openid(多个用,分割)
+	PositionIds string `protobuf:"bytes,4,opt,name=positionIds,proto3" json:"positionIds,omitempty"` //接受人 职位id
+	Url         string `protobuf:"bytes,5,opt,name=url,proto3" json:"url,omitempty"`                 //消息跳转连接
+	MsgType     int64  `protobuf:"varint,6,opt,name=msgType,proto3" json:"msgType,omitempty"`        //信息类型 附件、图片、链接类型
+	TmplId      string `protobuf:"bytes,7,opt,name=tmplId,proto3" json:"tmplId,omitempty"`           //消息模版id 根据此字段判断发送模版
+}
+
+func (x *WxTmplMsg) Reset() {
+	*x = WxTmplMsg{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_message_proto_msgTypes[32]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *WxTmplMsg) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*WxTmplMsg) ProtoMessage() {}
+
+func (x *WxTmplMsg) ProtoReflect() protoreflect.Message {
+	mi := &file_message_proto_msgTypes[32]
+	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 WxTmplMsg.ProtoReflect.Descriptor instead.
+func (*WxTmplMsg) Descriptor() ([]byte, []int) {
+	return file_message_proto_rawDescGZIP(), []int{32}
+}
+
+func (x *WxTmplMsg) GetAppid() string {
+	if x != nil {
+		return x.Appid
+	}
+	return ""
+}
+
+func (x *WxTmplMsg) GetUserIds() string {
+	if x != nil {
+		return x.UserIds
+	}
+	return ""
+}
+
+func (x *WxTmplMsg) GetOpenIds() string {
+	if x != nil {
+		return x.OpenIds
+	}
+	return ""
+}
+
+func (x *WxTmplMsg) GetPositionIds() string {
+	if x != nil {
+		return x.PositionIds
+	}
+	return ""
+}
+
+func (x *WxTmplMsg) GetUrl() string {
+	if x != nil {
+		return x.Url
+	}
+	return ""
+}
+
+func (x *WxTmplMsg) GetMsgType() int64 {
+	if x != nil {
+		return x.MsgType
+	}
+	return 0
+}
+
+func (x *WxTmplMsg) GetTmplId() string {
+	if x != nil {
+		return x.TmplId
+	}
+	return ""
+}
+
 type AllSortData struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -2385,7 +2481,7 @@ type AllSortData struct {
 func (x *AllSortData) Reset() {
 	*x = AllSortData{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_message_proto_msgTypes[32]
+		mi := &file_message_proto_msgTypes[33]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -2398,7 +2494,7 @@ func (x *AllSortData) String() string {
 func (*AllSortData) ProtoMessage() {}
 
 func (x *AllSortData) ProtoReflect() protoreflect.Message {
-	mi := &file_message_proto_msgTypes[32]
+	mi := &file_message_proto_msgTypes[33]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -2411,7 +2507,7 @@ func (x *AllSortData) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use AllSortData.ProtoReflect.Descriptor instead.
 func (*AllSortData) Descriptor() ([]byte, []int) {
-	return file_message_proto_rawDescGZIP(), []int{32}
+	return file_message_proto_rawDescGZIP(), []int{33}
 }
 
 func (x *AllSortData) GetUnreadMessages() int64 {
@@ -2449,6 +2545,61 @@ func (x *AllSortData) GetData() []*Messages {
 	return nil
 }
 
+type WxTmplResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	SendTotal int64  `protobuf:"varint,1,opt,name=sendTotal,proto3" json:"sendTotal,omitempty"` //发送数量
+	Message   string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`      //信息
+}
+
+func (x *WxTmplResponse) Reset() {
+	*x = WxTmplResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_message_proto_msgTypes[34]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *WxTmplResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*WxTmplResponse) ProtoMessage() {}
+
+func (x *WxTmplResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_message_proto_msgTypes[34]
+	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 WxTmplResponse.ProtoReflect.Descriptor instead.
+func (*WxTmplResponse) Descriptor() ([]byte, []int) {
+	return file_message_proto_rawDescGZIP(), []int{34}
+}
+
+func (x *WxTmplResponse) GetSendTotal() int64 {
+	if x != nil {
+		return x.SendTotal
+	}
+	return 0
+}
+
+func (x *WxTmplResponse) GetMessage() string {
+	if x != nil {
+		return x.Message
+	}
+	return ""
+}
+
 var File_message_proto protoreflect.FileDescriptor
 
 var file_message_proto_rawDesc = []byte{
@@ -2724,92 +2875,112 @@ var file_message_proto_rawDesc = []byte{
 	0x61, 0x67, 0x65, 0x2e, 0x41, 0x6c, 0x6c, 0x53, 0x6f, 0x72, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52,
 	0x08, 0x73, 0x6f, 0x72, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75,
 	0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22,
-	0x9c, 0x01, 0x0a, 0x0b, 0x41, 0x6c, 0x6c, 0x53, 0x6f, 0x72, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12,
-	0x26, 0x0a, 0x0e, 0x75, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
-	0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x75, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x4d,
-	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69,
-	0x6d, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x69, 0x6d, 0x67, 0x12, 0x18, 0x0a,
-	0x07, 0x6d, 0x73, 0x67, 0x54, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07,
-	0x6d, 0x73, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18,
-	0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e,
-	0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0xba,
-	0x09, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x4c, 0x0a, 0x0f, 0x6d, 0x75,
-	0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, 0x4d, 0x73, 0x67, 0x12, 0x1b, 0x2e,
-	0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65,
-	0x53, 0x61, 0x76, 0x65, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x6d, 0x65, 0x73,
-	0x73, 0x61, 0x67, 0x65, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x53, 0x61, 0x76,
-	0x65, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x73, 0x70, 0x12, 0x47, 0x0a, 0x10, 0x43, 0x68, 0x61, 0x6e,
-	0x67, 0x65, 0x52, 0x65, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x2e, 0x6d,
-	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x61,
-	0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11,
-	0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x12, 0x39, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x73, 0x67,
-	0x12, 0x17, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4d,
-	0x73, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x6d, 0x65, 0x73, 0x73,
-	0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x13,
-	0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73,
-	0x61, 0x67, 0x65, 0x12, 0x23, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x44, 0x65,
-	0x6c, 0x65, 0x74, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
-	0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61,
-	0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x15, 0x44,
-	0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x4d, 0x65, 0x73,
-	0x73, 0x61, 0x67, 0x65, 0x12, 0x25, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x44,
-	0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x4d, 0x65, 0x73,
-	0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x6d, 0x65,
-	0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51,
-	0x0a, 0x0e, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74,
-	0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x6e,
-	0x72, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x6e,
-	0x72, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x12, 0x3f, 0x0a, 0x0b, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x73, 0x67,
-	0x12, 0x17, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55,
-	0x73, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x6d, 0x65, 0x73, 0x73,
-	0x61, 0x67, 0x65, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x52,
-	0x65, 0x73, 0x12, 0x57, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x55, 0x6e,
-	0x72, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x73, 0x73,
-	0x61, 0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x55, 0x6e, 0x72, 0x65,
-	0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x73,
-	0x73, 0x61, 0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6f,
-	0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0e, 0x47,
-	0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x2e,
-	0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x4d,
-	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x1a, 0x2e, 0x6d, 0x65, 0x73, 0x73,
-	0x61, 0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61,
-	0x67, 0x65, 0x52, 0x65, 0x73, 0x12, 0x4a, 0x0a, 0x11, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x65, 0x73,
-	0x73, 0x61, 0x67, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x19, 0x2e, 0x6d, 0x65, 0x73,
-	0x73, 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x44, 0x65, 0x74, 0x61,
-	0x69, 0x6c, 0x52, 0x65, 0x71, 0x1a, 0x1a, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e,
-	0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73,
-	0x70, 0x12, 0x57, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6c,
-	0x61, 0x73, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61,
-	0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6c, 0x61, 0x73,
-	0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x73, 0x73,
-	0x61, 0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6c, 0x61,
-	0x73, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x12, 0x3c, 0x0a, 0x0a, 0x47, 0x65,
-	0x74, 0x4d, 0x73, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61,
-	0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x73, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65, 0x71,
-	0x1a, 0x16, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x73,
-	0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65, 0x73, 0x12, 0x52, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61,
-	0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x61, 0x64, 0x12, 0x1d, 0x2e,
-	0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65,
-	0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x1e, 0x2e, 0x6d,
-	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x73,
-	0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4b, 0x0a, 0x0f,
-	0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x42, 0x75, 0x6f, 0x79, 0x4d, 0x73, 0x67, 0x12,
-	0x1b, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73,
-	0x65, 0x72, 0x42, 0x75, 0x6f, 0x79, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x1a, 0x1b, 0x2e, 0x6d,
-	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x42,
-	0x75, 0x6f, 0x79, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x73, 0x12, 0x3f, 0x0a, 0x0e, 0x43, 0x6c, 0x65,
-	0x61, 0x72, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x4d, 0x73, 0x67, 0x12, 0x1a, 0x2e, 0x6d, 0x65,
-	0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x55, 0x6e, 0x72, 0x65, 0x61,
-	0x64, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
-	0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0b, 0x55, 0x73,
-	0x65, 0x72, 0x4d, 0x73, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x17, 0x2e, 0x6d, 0x65, 0x73, 0x73,
-	0x61, 0x67, 0x65, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52,
-	0x65, 0x71, 0x1a, 0x17, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x55, 0x73, 0x65,
-	0x72, 0x4d, 0x73, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x42, 0x0a, 0x5a, 0x08, 0x6d,
+	0xbb, 0x01, 0x0a, 0x09, 0x57, 0x78, 0x54, 0x6d, 0x70, 0x6c, 0x4d, 0x73, 0x67, 0x12, 0x14, 0x0a,
+	0x05, 0x61, 0x70, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70,
+	0x70, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x18, 0x0a,
+	0x07, 0x6f, 0x70, 0x65, 0x6e, 0x49, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
+	0x6f, 0x70, 0x65, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x6f, 0x73, 0x69, 0x74,
+	0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x6f,
+	0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c,
+	0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x6d,
+	0x73, 0x67, 0x54, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x73,
+	0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x6d, 0x70, 0x6c, 0x49, 0x64, 0x18,
+	0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x6d, 0x70, 0x6c, 0x49, 0x64, 0x22, 0x9c, 0x01,
+	0x0a, 0x0b, 0x41, 0x6c, 0x6c, 0x53, 0x6f, 0x72, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x26, 0x0a,
+	0x0e, 0x75, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x75, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x4d, 0x65, 0x73,
+	0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x6d, 0x67,
+	0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x69, 0x6d, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x6d,
+	0x73, 0x67, 0x54, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x73,
+	0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20,
+	0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x65,
+	0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x48, 0x0a, 0x0e,
+	0x57, 0x78, 0x54, 0x6d, 0x70, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c,
+	0x0a, 0x09, 0x73, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x03, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07,
+	0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d,
+	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0xf2, 0x09, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61,
+	0x67, 0x65, 0x12, 0x4c, 0x0a, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x53, 0x61,
+	0x76, 0x65, 0x4d, 0x73, 0x67, 0x12, 0x1b, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e,
+	0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, 0x4d, 0x73, 0x67, 0x52,
+	0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x6d, 0x75, 0x6c,
+	0x74, 0x69, 0x70, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x73, 0x70,
+	0x12, 0x47, 0x0a, 0x10, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x61, 0x64, 0x53, 0x74,
+	0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43,
+	0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+	0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x53, 0x65, 0x6e,
+	0x64, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x17, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61,
+	0x67, 0x65, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x11, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x69,
+	0x6e, 0x67, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x23, 0x2e, 0x6d, 0x65,
+	0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x69, 0x6e, 0x67,
+	0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x11, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x75, 0x6c,
+	0x74, 0x69, 0x70, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x25, 0x2e, 0x6d,
+	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x75, 0x6c,
+	0x74, 0x69, 0x70, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x72,
+	0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61,
+	0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e,
+	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61,
+	0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e,
+	0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0b, 0x46, 0x69, 0x6e,
+	0x64, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x17, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61,
+	0x67, 0x65, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x52, 0x65,
+	0x71, 0x1a, 0x17, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x46, 0x69, 0x6e, 0x64,
+	0x55, 0x73, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x73, 0x12, 0x57, 0x0a, 0x13, 0x47, 0x65,
+	0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e,
+	0x74, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x43,
+	0x6c, 0x61, 0x73, 0x73, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52,
+	0x65, 0x71, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x47, 0x65, 0x74,
+	0x55, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x4d, 0x65,
+	0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e,
+	0x47, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65,
+	0x71, 0x1a, 0x1a, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4c,
+	0x61, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x12, 0x4a, 0x0a,
+	0x11, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x44, 0x65, 0x74, 0x61,
+	0x69, 0x6c, 0x12, 0x19, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x65, 0x73,
+	0x73, 0x61, 0x67, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x1a, 0x1a, 0x2e,
+	0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x44,
+	0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x12, 0x57, 0x0a, 0x13, 0x47, 0x65, 0x74,
+	0x55, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+	0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x6e,
+	0x72, 0x65, 0x61, 0x64, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65,
+	0x71, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x55,
+	0x6e, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52,
+	0x65, 0x73, 0x12, 0x3c, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4d, 0x73, 0x67, 0x54, 0x79, 0x70, 0x65,
+	0x12, 0x16, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x73,
+	0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61,
+	0x67, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x73, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65, 0x73,
+	0x12, 0x52, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+	0x65, 0x52, 0x65, 0x61, 0x64, 0x12, 0x1d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e,
+	0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x61,
+	0x64, 0x52, 0x65, 0x71, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x55,
+	0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x61, 0x64,
+	0x52, 0x65, 0x73, 0x70, 0x12, 0x4b, 0x0a, 0x0f, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72,
+	0x42, 0x75, 0x6f, 0x79, 0x4d, 0x73, 0x67, 0x12, 0x1b, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+	0x65, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x42, 0x75, 0x6f, 0x79, 0x4d, 0x73,
+	0x67, 0x52, 0x65, 0x71, 0x1a, 0x1b, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x46,
+	0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x42, 0x75, 0x6f, 0x79, 0x4d, 0x73, 0x67, 0x52, 0x65,
+	0x73, 0x12, 0x3f, 0x0a, 0x0e, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x64,
+	0x4d, 0x73, 0x67, 0x12, 0x1a, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, 0x6c,
+	0x65, 0x61, 0x72, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x64, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x1a,
+	0x11, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x4c, 0x69, 0x73,
+	0x74, 0x12, 0x17, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x55, 0x73, 0x65, 0x72,
+	0x4d, 0x73, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x6d, 0x65, 0x73,
+	0x73, 0x61, 0x67, 0x65, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x4c, 0x69, 0x73, 0x74,
+	0x52, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x0d, 0x53, 0x65, 0x6e, 0x64, 0x57, 0x78, 0x54, 0x6d, 0x70,
+	0x6c, 0x4d, 0x73, 0x67, 0x12, 0x12, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x57,
+	0x78, 0x54, 0x6d, 0x70, 0x6c, 0x4d, 0x73, 0x67, 0x1a, 0x11, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61,
+	0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0a, 0x5a, 0x08, 0x6d,
 	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
@@ -2825,7 +2996,7 @@ func file_message_proto_rawDescGZIP() []byte {
 	return file_message_proto_rawDescData
 }
 
-var file_message_proto_msgTypes = make([]protoimpl.MessageInfo, 34)
+var file_message_proto_msgTypes = make([]protoimpl.MessageInfo, 36)
 var file_message_proto_goTypes = []interface{}{
 	(*SendMsgRequest)(nil),               // 0: message.SendMsgRequest
 	(*ChangeReadStatusRequest)(nil),      // 1: message.ChangeReadStatusRequest
@@ -2859,11 +3030,13 @@ var file_message_proto_goTypes = []interface{}{
 	(*UserMsgListReq)(nil),               // 29: message.UserMsgListReq
 	(*UserMsgListRes)(nil),               // 30: message.UserMsgListRes
 	(*UserMsgList)(nil),                  // 31: message.UserMsgList
-	(*AllSortData)(nil),                  // 32: message.AllSortData
-	nil,                                  // 33: message.Messages.UrlEntry
+	(*WxTmplMsg)(nil),                    // 32: message.WxTmplMsg
+	(*AllSortData)(nil),                  // 33: message.AllSortData
+	(*WxTmplResponse)(nil),               // 34: message.WxTmplResponse
+	nil,                                  // 35: message.Messages.UrlEntry
 }
 var file_message_proto_depIdxs = []int32{
-	33, // 0: message.Messages.url:type_name -> message.Messages.UrlEntry
+	35, // 0: message.Messages.url:type_name -> message.Messages.UrlEntry
 	9,  // 1: message.FindUserMsgRes.data:type_name -> message.Messages
 	9,  // 2: message.MessageDetailResp.data:type_name -> message.Messages
 	9,  // 3: message.GetLastMessageRes.data:type_name -> message.Messages
@@ -2872,9 +3045,9 @@ var file_message_proto_depIdxs = []int32{
 	27, // 6: message.FindUserBuoyMsgRes.data:type_name -> message.BuoyMessages
 	9,  // 7: message.UserMsgListRes.list:type_name -> message.Messages
 	9,  // 8: message.UserMsgListRes.last:type_name -> message.Messages
-	32, // 9: message.UserMsgListRes.column:type_name -> message.AllSortData
+	33, // 9: message.UserMsgListRes.column:type_name -> message.AllSortData
 	9,  // 10: message.UserMsgList.data:type_name -> message.Messages
-	32, // 11: message.UserMsgList.sortData:type_name -> message.AllSortData
+	33, // 11: message.UserMsgList.sortData:type_name -> message.AllSortData
 	9,  // 12: message.AllSortData.data:type_name -> message.Messages
 	23, // 13: message.Message.multipleSaveMsg:input_type -> message.multipleSaveMsgReq
 	1,  // 14: message.Message.ChangeReadStatus:input_type -> message.ChangeReadStatusRequest
@@ -2892,24 +3065,26 @@ var file_message_proto_depIdxs = []int32{
 	25, // 26: message.Message.FindUserBuoyMsg:input_type -> message.FindUserBuoyMsgReq
 	28, // 27: message.Message.ClearUnreadMsg:input_type -> message.ClearUnreadMsgReq
 	29, // 28: message.Message.UserMsgList:input_type -> message.UserMsgListReq
-	24, // 29: message.Message.multipleSaveMsg:output_type -> message.multipleSaveMsgResp
-	6,  // 30: message.Message.ChangeReadStatus:output_type -> message.Response
-	6,  // 31: message.Message.SendUserMsg:output_type -> message.Response
-	6,  // 32: message.Message.DeleteSingleMessage:output_type -> message.Response
-	6,  // 33: message.Message.DeleteMultipleMessage:output_type -> message.Response
-	7,  // 34: message.Message.GetUnreadCount:output_type -> message.GetUnreadCountResponse
-	10, // 35: message.Message.FindUserMsg:output_type -> message.FindUserMsgRes
-	7,  // 36: message.Message.GetClassUnreadCount:output_type -> message.GetUnreadCountResponse
-	15, // 37: message.Message.GetLastMessage:output_type -> message.GetLastMessageRes
-	13, // 38: message.Message.FindMessageDetail:output_type -> message.MessageDetailResp
-	17, // 39: message.Message.GetUnreadClassCount:output_type -> message.GetUnreadClassCountRes
-	19, // 40: message.Message.GetMsgType:output_type -> message.GetMsgTypeRes
-	21, // 41: message.Message.UpdateMessageRead:output_type -> message.UpdateMessageReadResp
-	26, // 42: message.Message.FindUserBuoyMsg:output_type -> message.FindUserBuoyMsgRes
-	6,  // 43: message.Message.ClearUnreadMsg:output_type -> message.Response
-	30, // 44: message.Message.UserMsgList:output_type -> message.UserMsgListRes
-	29, // [29:45] is the sub-list for method output_type
-	13, // [13:29] is the sub-list for method input_type
+	32, // 29: message.Message.SendWxTmplMsg:input_type -> message.WxTmplMsg
+	24, // 30: message.Message.multipleSaveMsg:output_type -> message.multipleSaveMsgResp
+	6,  // 31: message.Message.ChangeReadStatus:output_type -> message.Response
+	6,  // 32: message.Message.SendUserMsg:output_type -> message.Response
+	6,  // 33: message.Message.DeleteSingleMessage:output_type -> message.Response
+	6,  // 34: message.Message.DeleteMultipleMessage:output_type -> message.Response
+	7,  // 35: message.Message.GetUnreadCount:output_type -> message.GetUnreadCountResponse
+	10, // 36: message.Message.FindUserMsg:output_type -> message.FindUserMsgRes
+	7,  // 37: message.Message.GetClassUnreadCount:output_type -> message.GetUnreadCountResponse
+	15, // 38: message.Message.GetLastMessage:output_type -> message.GetLastMessageRes
+	13, // 39: message.Message.FindMessageDetail:output_type -> message.MessageDetailResp
+	17, // 40: message.Message.GetUnreadClassCount:output_type -> message.GetUnreadClassCountRes
+	19, // 41: message.Message.GetMsgType:output_type -> message.GetMsgTypeRes
+	21, // 42: message.Message.UpdateMessageRead:output_type -> message.UpdateMessageReadResp
+	26, // 43: message.Message.FindUserBuoyMsg:output_type -> message.FindUserBuoyMsgRes
+	6,  // 44: message.Message.ClearUnreadMsg:output_type -> message.Response
+	30, // 45: message.Message.UserMsgList:output_type -> message.UserMsgListRes
+	6,  // 46: message.Message.SendWxTmplMsg:output_type -> message.Response
+	30, // [30:47] is the sub-list for method output_type
+	13, // [13:30] is the sub-list for method input_type
 	13, // [13:13] is the sub-list for extension type_name
 	13, // [13:13] is the sub-list for extension extendee
 	0,  // [0:13] is the sub-list for field type_name
@@ -3306,6 +3481,18 @@ func file_message_proto_init() {
 			}
 		}
 		file_message_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*WxTmplMsg); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_message_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*AllSortData); i {
 			case 0:
 				return &v.state
@@ -3317,6 +3504,18 @@ func file_message_proto_init() {
 				return nil
 			}
 		}
+		file_message_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*WxTmplResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
 	}
 	type x struct{}
 	out := protoimpl.TypeBuilder{
@@ -3324,7 +3523,7 @@ func file_message_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_message_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   34,
+			NumMessages:   36,
 			NumExtensions: 0,
 			NumServices:   1,
 		},

+ 92 - 34
rpc/type/message/message_grpc.pb.go

@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
 // versions:
-// - protoc-gen-go-grpc v1.2.0
-// - protoc             v3.19.4
+// - protoc-gen-go-grpc v1.3.0
+// - protoc             v3.21.12
 // source: message.proto
 
 package message
@@ -18,6 +18,26 @@ import (
 // Requires gRPC-Go v1.32.0 or later.
 const _ = grpc.SupportPackageIsVersion7
 
+const (
+	Message_MultipleSaveMsg_FullMethodName       = "/message.Message/multipleSaveMsg"
+	Message_ChangeReadStatus_FullMethodName      = "/message.Message/ChangeReadStatus"
+	Message_SendUserMsg_FullMethodName           = "/message.Message/SendUserMsg"
+	Message_DeleteSingleMessage_FullMethodName   = "/message.Message/DeleteSingleMessage"
+	Message_DeleteMultipleMessage_FullMethodName = "/message.Message/DeleteMultipleMessage"
+	Message_GetUnreadCount_FullMethodName        = "/message.Message/GetUnreadCount"
+	Message_FindUserMsg_FullMethodName           = "/message.Message/FindUserMsg"
+	Message_GetClassUnreadCount_FullMethodName   = "/message.Message/GetClassUnreadCount"
+	Message_GetLastMessage_FullMethodName        = "/message.Message/GetLastMessage"
+	Message_FindMessageDetail_FullMethodName     = "/message.Message/FindMessageDetail"
+	Message_GetUnreadClassCount_FullMethodName   = "/message.Message/GetUnreadClassCount"
+	Message_GetMsgType_FullMethodName            = "/message.Message/GetMsgType"
+	Message_UpdateMessageRead_FullMethodName     = "/message.Message/UpdateMessageRead"
+	Message_FindUserBuoyMsg_FullMethodName       = "/message.Message/FindUserBuoyMsg"
+	Message_ClearUnreadMsg_FullMethodName        = "/message.Message/ClearUnreadMsg"
+	Message_UserMsgList_FullMethodName           = "/message.Message/UserMsgList"
+	Message_SendWxTmplMsg_FullMethodName         = "/message.Message/SendWxTmplMsg"
+)
+
 // MessageClient is the client API for Message service.
 //
 // 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.
@@ -54,6 +74,8 @@ type MessageClient interface {
 	ClearUnreadMsg(ctx context.Context, in *ClearUnreadMsgReq, opts ...grpc.CallOption) (*Response, error)
 	// new用户消息列表
 	UserMsgList(ctx context.Context, in *UserMsgListReq, opts ...grpc.CallOption) (*UserMsgListRes, error)
+	// 发送微信模版消息
+	SendWxTmplMsg(ctx context.Context, in *WxTmplMsg, opts ...grpc.CallOption) (*Response, error)
 }
 
 type messageClient struct {
@@ -66,7 +88,7 @@ func NewMessageClient(cc grpc.ClientConnInterface) MessageClient {
 
 func (c *messageClient) MultipleSaveMsg(ctx context.Context, in *MultipleSaveMsgReq, opts ...grpc.CallOption) (*MultipleSaveMsgResp, error) {
 	out := new(MultipleSaveMsgResp)
-	err := c.cc.Invoke(ctx, "/message.Message/multipleSaveMsg", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_MultipleSaveMsg_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -75,7 +97,7 @@ func (c *messageClient) MultipleSaveMsg(ctx context.Context, in *MultipleSaveMsg
 
 func (c *messageClient) ChangeReadStatus(ctx context.Context, in *ChangeReadStatusRequest, opts ...grpc.CallOption) (*Response, error) {
 	out := new(Response)
-	err := c.cc.Invoke(ctx, "/message.Message/ChangeReadStatus", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_ChangeReadStatus_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -84,7 +106,7 @@ func (c *messageClient) ChangeReadStatus(ctx context.Context, in *ChangeReadStat
 
 func (c *messageClient) SendUserMsg(ctx context.Context, in *SendMsgRequest, opts ...grpc.CallOption) (*Response, error) {
 	out := new(Response)
-	err := c.cc.Invoke(ctx, "/message.Message/SendUserMsg", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_SendUserMsg_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -93,7 +115,7 @@ func (c *messageClient) SendUserMsg(ctx context.Context, in *SendMsgRequest, opt
 
 func (c *messageClient) DeleteSingleMessage(ctx context.Context, in *DeleteSingleMessageRequest, opts ...grpc.CallOption) (*Response, error) {
 	out := new(Response)
-	err := c.cc.Invoke(ctx, "/message.Message/DeleteSingleMessage", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_DeleteSingleMessage_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -102,7 +124,7 @@ func (c *messageClient) DeleteSingleMessage(ctx context.Context, in *DeleteSingl
 
 func (c *messageClient) DeleteMultipleMessage(ctx context.Context, in *DeleteMultipleMessageRequest, opts ...grpc.CallOption) (*Response, error) {
 	out := new(Response)
-	err := c.cc.Invoke(ctx, "/message.Message/DeleteMultipleMessage", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_DeleteMultipleMessage_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -111,7 +133,7 @@ func (c *messageClient) DeleteMultipleMessage(ctx context.Context, in *DeleteMul
 
 func (c *messageClient) GetUnreadCount(ctx context.Context, in *GetUnreadCountRequest, opts ...grpc.CallOption) (*GetUnreadCountResponse, error) {
 	out := new(GetUnreadCountResponse)
-	err := c.cc.Invoke(ctx, "/message.Message/GetUnreadCount", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_GetUnreadCount_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -120,7 +142,7 @@ func (c *messageClient) GetUnreadCount(ctx context.Context, in *GetUnreadCountRe
 
 func (c *messageClient) FindUserMsg(ctx context.Context, in *FindUserMsgReq, opts ...grpc.CallOption) (*FindUserMsgRes, error) {
 	out := new(FindUserMsgRes)
-	err := c.cc.Invoke(ctx, "/message.Message/FindUserMsg", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_FindUserMsg_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -129,7 +151,7 @@ func (c *messageClient) FindUserMsg(ctx context.Context, in *FindUserMsgReq, opt
 
 func (c *messageClient) GetClassUnreadCount(ctx context.Context, in *GetClassUnreadCountReq, opts ...grpc.CallOption) (*GetUnreadCountResponse, error) {
 	out := new(GetUnreadCountResponse)
-	err := c.cc.Invoke(ctx, "/message.Message/GetClassUnreadCount", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_GetClassUnreadCount_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -138,7 +160,7 @@ func (c *messageClient) GetClassUnreadCount(ctx context.Context, in *GetClassUnr
 
 func (c *messageClient) GetLastMessage(ctx context.Context, in *GetLastMessageReq, opts ...grpc.CallOption) (*GetLastMessageRes, error) {
 	out := new(GetLastMessageRes)
-	err := c.cc.Invoke(ctx, "/message.Message/GetLastMessage", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_GetLastMessage_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -147,7 +169,7 @@ func (c *messageClient) GetLastMessage(ctx context.Context, in *GetLastMessageRe
 
 func (c *messageClient) FindMessageDetail(ctx context.Context, in *MessageDetailReq, opts ...grpc.CallOption) (*MessageDetailResp, error) {
 	out := new(MessageDetailResp)
-	err := c.cc.Invoke(ctx, "/message.Message/FindMessageDetail", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_FindMessageDetail_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -156,7 +178,7 @@ func (c *messageClient) FindMessageDetail(ctx context.Context, in *MessageDetail
 
 func (c *messageClient) GetUnreadClassCount(ctx context.Context, in *GetUnreadClassCountReq, opts ...grpc.CallOption) (*GetUnreadClassCountRes, error) {
 	out := new(GetUnreadClassCountRes)
-	err := c.cc.Invoke(ctx, "/message.Message/GetUnreadClassCount", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_GetUnreadClassCount_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -165,7 +187,7 @@ func (c *messageClient) GetUnreadClassCount(ctx context.Context, in *GetUnreadCl
 
 func (c *messageClient) GetMsgType(ctx context.Context, in *GetMsgTypeReq, opts ...grpc.CallOption) (*GetMsgTypeRes, error) {
 	out := new(GetMsgTypeRes)
-	err := c.cc.Invoke(ctx, "/message.Message/GetMsgType", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_GetMsgType_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -174,7 +196,7 @@ func (c *messageClient) GetMsgType(ctx context.Context, in *GetMsgTypeReq, opts
 
 func (c *messageClient) UpdateMessageRead(ctx context.Context, in *UpdateMessageReadReq, opts ...grpc.CallOption) (*UpdateMessageReadResp, error) {
 	out := new(UpdateMessageReadResp)
-	err := c.cc.Invoke(ctx, "/message.Message/UpdateMessageRead", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_UpdateMessageRead_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -183,7 +205,7 @@ func (c *messageClient) UpdateMessageRead(ctx context.Context, in *UpdateMessage
 
 func (c *messageClient) FindUserBuoyMsg(ctx context.Context, in *FindUserBuoyMsgReq, opts ...grpc.CallOption) (*FindUserBuoyMsgRes, error) {
 	out := new(FindUserBuoyMsgRes)
-	err := c.cc.Invoke(ctx, "/message.Message/FindUserBuoyMsg", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_FindUserBuoyMsg_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -192,7 +214,7 @@ func (c *messageClient) FindUserBuoyMsg(ctx context.Context, in *FindUserBuoyMsg
 
 func (c *messageClient) ClearUnreadMsg(ctx context.Context, in *ClearUnreadMsgReq, opts ...grpc.CallOption) (*Response, error) {
 	out := new(Response)
-	err := c.cc.Invoke(ctx, "/message.Message/ClearUnreadMsg", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_ClearUnreadMsg_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -201,7 +223,16 @@ func (c *messageClient) ClearUnreadMsg(ctx context.Context, in *ClearUnreadMsgRe
 
 func (c *messageClient) UserMsgList(ctx context.Context, in *UserMsgListReq, opts ...grpc.CallOption) (*UserMsgListRes, error) {
 	out := new(UserMsgListRes)
-	err := c.cc.Invoke(ctx, "/message.Message/UserMsgList", in, out, opts...)
+	err := c.cc.Invoke(ctx, Message_UserMsgList_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *messageClient) SendWxTmplMsg(ctx context.Context, in *WxTmplMsg, opts ...grpc.CallOption) (*Response, error) {
+	out := new(Response)
+	err := c.cc.Invoke(ctx, Message_SendWxTmplMsg_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -244,6 +275,8 @@ type MessageServer interface {
 	ClearUnreadMsg(context.Context, *ClearUnreadMsgReq) (*Response, error)
 	// new用户消息列表
 	UserMsgList(context.Context, *UserMsgListReq) (*UserMsgListRes, error)
+	// 发送微信模版消息
+	SendWxTmplMsg(context.Context, *WxTmplMsg) (*Response, error)
 	mustEmbedUnimplementedMessageServer()
 }
 
@@ -299,6 +332,9 @@ func (UnimplementedMessageServer) ClearUnreadMsg(context.Context, *ClearUnreadMs
 func (UnimplementedMessageServer) UserMsgList(context.Context, *UserMsgListReq) (*UserMsgListRes, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method UserMsgList not implemented")
 }
+func (UnimplementedMessageServer) SendWxTmplMsg(context.Context, *WxTmplMsg) (*Response, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method SendWxTmplMsg not implemented")
+}
 func (UnimplementedMessageServer) mustEmbedUnimplementedMessageServer() {}
 
 // UnsafeMessageServer may be embedded to opt out of forward compatibility for this service.
@@ -322,7 +358,7 @@ func _Message_MultipleSaveMsg_Handler(srv interface{}, ctx context.Context, dec
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/multipleSaveMsg",
+		FullMethod: Message_MultipleSaveMsg_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).MultipleSaveMsg(ctx, req.(*MultipleSaveMsgReq))
@@ -340,7 +376,7 @@ func _Message_ChangeReadStatus_Handler(srv interface{}, ctx context.Context, dec
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/ChangeReadStatus",
+		FullMethod: Message_ChangeReadStatus_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).ChangeReadStatus(ctx, req.(*ChangeReadStatusRequest))
@@ -358,7 +394,7 @@ func _Message_SendUserMsg_Handler(srv interface{}, ctx context.Context, dec func
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/SendUserMsg",
+		FullMethod: Message_SendUserMsg_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).SendUserMsg(ctx, req.(*SendMsgRequest))
@@ -376,7 +412,7 @@ func _Message_DeleteSingleMessage_Handler(srv interface{}, ctx context.Context,
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/DeleteSingleMessage",
+		FullMethod: Message_DeleteSingleMessage_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).DeleteSingleMessage(ctx, req.(*DeleteSingleMessageRequest))
@@ -394,7 +430,7 @@ func _Message_DeleteMultipleMessage_Handler(srv interface{}, ctx context.Context
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/DeleteMultipleMessage",
+		FullMethod: Message_DeleteMultipleMessage_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).DeleteMultipleMessage(ctx, req.(*DeleteMultipleMessageRequest))
@@ -412,7 +448,7 @@ func _Message_GetUnreadCount_Handler(srv interface{}, ctx context.Context, dec f
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/GetUnreadCount",
+		FullMethod: Message_GetUnreadCount_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).GetUnreadCount(ctx, req.(*GetUnreadCountRequest))
@@ -430,7 +466,7 @@ func _Message_FindUserMsg_Handler(srv interface{}, ctx context.Context, dec func
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/FindUserMsg",
+		FullMethod: Message_FindUserMsg_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).FindUserMsg(ctx, req.(*FindUserMsgReq))
@@ -448,7 +484,7 @@ func _Message_GetClassUnreadCount_Handler(srv interface{}, ctx context.Context,
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/GetClassUnreadCount",
+		FullMethod: Message_GetClassUnreadCount_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).GetClassUnreadCount(ctx, req.(*GetClassUnreadCountReq))
@@ -466,7 +502,7 @@ func _Message_GetLastMessage_Handler(srv interface{}, ctx context.Context, dec f
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/GetLastMessage",
+		FullMethod: Message_GetLastMessage_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).GetLastMessage(ctx, req.(*GetLastMessageReq))
@@ -484,7 +520,7 @@ func _Message_FindMessageDetail_Handler(srv interface{}, ctx context.Context, de
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/FindMessageDetail",
+		FullMethod: Message_FindMessageDetail_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).FindMessageDetail(ctx, req.(*MessageDetailReq))
@@ -502,7 +538,7 @@ func _Message_GetUnreadClassCount_Handler(srv interface{}, ctx context.Context,
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/GetUnreadClassCount",
+		FullMethod: Message_GetUnreadClassCount_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).GetUnreadClassCount(ctx, req.(*GetUnreadClassCountReq))
@@ -520,7 +556,7 @@ func _Message_GetMsgType_Handler(srv interface{}, ctx context.Context, dec func(
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/GetMsgType",
+		FullMethod: Message_GetMsgType_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).GetMsgType(ctx, req.(*GetMsgTypeReq))
@@ -538,7 +574,7 @@ func _Message_UpdateMessageRead_Handler(srv interface{}, ctx context.Context, de
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/UpdateMessageRead",
+		FullMethod: Message_UpdateMessageRead_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).UpdateMessageRead(ctx, req.(*UpdateMessageReadReq))
@@ -556,7 +592,7 @@ func _Message_FindUserBuoyMsg_Handler(srv interface{}, ctx context.Context, dec
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/FindUserBuoyMsg",
+		FullMethod: Message_FindUserBuoyMsg_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).FindUserBuoyMsg(ctx, req.(*FindUserBuoyMsgReq))
@@ -574,7 +610,7 @@ func _Message_ClearUnreadMsg_Handler(srv interface{}, ctx context.Context, dec f
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/ClearUnreadMsg",
+		FullMethod: Message_ClearUnreadMsg_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).ClearUnreadMsg(ctx, req.(*ClearUnreadMsgReq))
@@ -592,7 +628,7 @@ func _Message_UserMsgList_Handler(srv interface{}, ctx context.Context, dec func
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/message.Message/UserMsgList",
+		FullMethod: Message_UserMsgList_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(MessageServer).UserMsgList(ctx, req.(*UserMsgListReq))
@@ -600,6 +636,24 @@ func _Message_UserMsgList_Handler(srv interface{}, ctx context.Context, dec func
 	return interceptor(ctx, in, info, handler)
 }
 
+func _Message_SendWxTmplMsg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(WxTmplMsg)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(MessageServer).SendWxTmplMsg(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: Message_SendWxTmplMsg_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(MessageServer).SendWxTmplMsg(ctx, req.(*WxTmplMsg))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 // Message_ServiceDesc is the grpc.ServiceDesc for Message service.
 // It's only intended for direct use with grpc.RegisterService,
 // and not to be introspected or modified (even as a copy)
@@ -671,6 +725,10 @@ var Message_ServiceDesc = grpc.ServiceDesc{
 			MethodName: "UserMsgList",
 			Handler:    _Message_UserMsgList_Handler,
 		},
+		{
+			MethodName: "SendWxTmplMsg",
+			Handler:    _Message_SendWxTmplMsg_Handler,
+		},
 	},
 	Streams:  []grpc.StreamDesc{},
 	Metadata: "message.proto",