go_dreamfactory/modules/chat/module.go
2023-07-05 19:45:41 +08:00

416 lines
11 KiB
Go

package chat
import (
"context"
"go_dreamfactory/comm"
"go_dreamfactory/lego/base"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/sys/event"
"go_dreamfactory/lego/sys/log"
"go_dreamfactory/lego/utils/codec/json"
"go_dreamfactory/modules"
"go_dreamfactory/pb"
"go_dreamfactory/sys/configure"
"time"
"google.golang.org/protobuf/types/known/anypb"
)
const moduleName = "聊天"
/*
模块名:论坛
描述:处理跨服社交论坛相关业务
开发:李伟
*/
func NewModule() core.IModule {
m := new(Chat)
return m
}
type Chat struct {
modules.ModuleBase
service base.IRPCXService //rpc服务对象 通过这个对象可以发布服务和调用其他服务的接口
options *Options
gm comm.IGm //gm模块
sociaty comm.ISociaty //工会模块
api_comp *apiComp
configure *configureComp
modelChat *modelChatComp
}
// 重构模块配置对象
func (this *Chat) NewOptions() (options core.IModuleOptions) {
return new(Options)
}
// 模块名
func (this *Chat) GetType() core.M_Modules {
return comm.ModuleChat
}
// 模块初始化接口 注册用户创建角色事件
func (this *Chat) Init(service core.IService, module core.IModule, options core.IModuleOptions) (err error) {
err = this.ModuleBase.Init(service, module, options)
this.service = service.(base.IRPCXService)
this.options = options.(*Options)
return
}
func (this *Chat) Start() (err error) {
err = this.ModuleBase.Start()
var module core.IModule
if module, err = this.service.GetModule(comm.ModuleGM); err != nil {
return
}
this.gm = module.(comm.IGm)
if module, err = this.service.GetModule(comm.ModuleSociaty); err != nil {
return
}
this.sociaty = module.(comm.ISociaty)
event.RegisterGO(comm.EventUserOffline, this.EventUserOffline)
this.service.RegisterFunctionName(string(comm.Rpc_ModuleChatPushChat), this.Rpc_ModuleChatPushChat)
return
}
// 装备组件
func (this *Chat) OnInstallComp() {
this.ModuleBase.OnInstallComp()
this.api_comp = this.RegisterComp(new(apiComp)).(*apiComp)
this.modelChat = this.RegisterComp(new(modelChatComp)).(*modelChatComp)
this.configure = this.RegisterComp(new(configureComp)).(*configureComp)
}
// Event------------------------------------------------------------------------------------------------------------
func (this *Chat) EventUserOffline(uid, sessionid string) {
if err := this.modelChat.removeCrossChannelMember(uid); err != nil {
this.Error("EventUserOffline", log.Field{Key: "uid", Value: uid}, log.Field{Key: "err", Value: err.Error()})
}
}
// RPC--------------------------------------------------------------------------------------------------------------
// 推送聊天消息
func (this *Chat) Rpc_ModuleChatPushChat(ctx context.Context, args *pb.DBChat, reply *pb.EmptyResp) (err error) {
var (
max_chat int32
)
if max_chat, err = this.configure.GetChannelRecordMax(); err != nil {
this.Errorln(err)
return
}
switch args.Channel {
case pb.ChatChannel_World:
if err = this.modelChat.sendChatToWorld(args, max_chat); err != nil {
this.Errorln(err)
return
}
break
case pb.ChatChannel_Union:
if err = this.modelChat.sendChatToUnion(args, max_chat); err != nil {
this.Errorln(err)
return
}
break
case pb.ChatChannel_Private:
if err = this.modelChat.sendChatToPrivate(args); err != nil {
this.Errorln(err)
return
}
break
case pb.ChatChannel_CrossServer:
if err = this.modelChat.sendChatToCrossServer(args, max_chat); err != nil {
this.Errorln(err)
return
}
break
case pb.ChatChannel_System:
if err = this.modelChat.sendChatToSystem(args); err != nil {
this.Errorln(err)
return
}
break
}
return
}
// 对外接口----------------------------------------------------------------------------------------------------------
// 向世界频道发送聊天消息
func (this *Chat) SendWorldChat(msg *pb.DBChat) (errdata *pb.ErrorData) {
var (
max_chat int32
err error
)
if max_chat, err = this.configure.GetChannelRecordMax(); err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_ConfigNoFound,
Title: pb.ErrorCode_ConfigNoFound.ToString(),
Message: err.Error(),
}
this.Errorln(err)
return
}
if this.IsCross() {
if err = this.modelChat.sendChatToWorld(msg, max_chat); err != nil {
this.Errorln(err)
return
}
} else {
if _, err = this.service.AcrossClusterRpcGo(
context.Background(),
this.GetCrossTag(),
comm.Service_Worker,
string(comm.Rpc_ModuleChatPushChat),
msg,
nil); err != nil {
this.Errorln(err)
errdata = &pb.ErrorData{
Code: pb.ErrorCode_RpcFuncExecutionError,
Title: pb.ErrorCode_RpcFuncExecutionError.ToString(),
Message: err.Error(),
}
}
}
return
}
// 向工会发送聊天消息
func (this *Chat) SendUnionChat(msg *pb.DBChat) (errdata *pb.ErrorData) {
var (
max_chat int32
err error
)
if max_chat, err = this.configure.GetChannelRecordMax(); err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_ConfigNoFound,
Title: pb.ErrorCode_ConfigNoFound.ToString(),
Message: err.Error(),
}
this.Errorln(err)
return
}
if this.IsCross() {
if err = this.modelChat.sendChatToUnion(msg, max_chat); err != nil {
this.Errorln(err)
return
}
} else {
if _, err = this.service.AcrossClusterRpcGo(
context.Background(),
this.GetCrossTag(),
comm.Service_Worker,
string(comm.Rpc_ModuleChatPushChat),
msg,
nil); err != nil {
this.Errorln(err)
errdata = &pb.ErrorData{
Code: pb.ErrorCode_RpcFuncExecutionError,
Title: pb.ErrorCode_RpcFuncExecutionError.ToString(),
Message: err.Error(),
}
}
}
return
}
// 向个人发送聊天消息
func (this *Chat) SendUserChat(msg *pb.DBChat) (errdata *pb.ErrorData) {
var (
err error
session comm.IUserSession
ok bool
)
defer func() {
this.PutUserSession(session)
}()
if session, ok = this.GetUserSession(msg.Ruid); ok {
session.SendMsg(string(this.GetType()), "message", &pb.ChatMessagePush{Chat: msg})
if err = session.Push(); err != nil {
this.Errorf("err:%v", err)
errdata = &pb.ErrorData{
Code: pb.ErrorCode_SystemError,
Title: pb.ErrorCode_SystemError.ToString(),
Message: err.Error(),
}
return
}
} else {
if err = this.modelChat.saveUserMsg(msg); err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_DBError,
Title: pb.ErrorCode_DBError.ToString(),
Message: err.Error(),
}
return
}
}
return
}
// 广播系统消息
func (this *Chat) SendSysChatToWorld(ctype comm.ChatSystemType, appenddata interface{}, value0 int32, value1 int32, agrs ...string) (errdata *pb.ErrorData) {
var (
jsonStr []byte
err error
)
if st, ok := this.configure.GetCheckChatSystem(int32(ctype), value0, value1); ok {
msg := &pb.DBChat{
Channel: pb.ChatChannel_System,
Ctype: pb.ChatType_Text,
Stag: this.service.GetTag(),
Ctime: configure.Now().Unix(),
Content: "",
Display: st.Display,
AppendInt: int64(st.Key),
AppendStrs: agrs,
}
switch ctype {
case comm.ChatSystem3:
msg.Ctype = pb.ChatType_Share
if appenddata != nil {
if jsonStr, err = json.Marshal(appenddata); err != nil {
this.Errorf("err:%v", err)
} else {
data := map[string]interface{}{
agrs[1]: map[string]interface{}{
"key": agrs[1],
"appendStr": string(jsonStr),
"itemType": pb.ChatType_EquipmentShare,
},
}
jsonStr, _ = json.Marshal(data)
msg.AppendStr = string(jsonStr)
}
}
case comm.ChatSystem7, comm.ChatSystem8, comm.ChatSystem9, comm.ChatSystem10, comm.ChatSystem11:
msg.Ctype = pb.ChatType_Share
if appenddata != nil {
if jsonStr, err = json.Marshal(appenddata); err != nil {
this.Errorf("err:%v", err)
} else {
data := map[string]interface{}{
agrs[1]: map[string]interface{}{
"key": agrs[1],
"appendStr": string(jsonStr),
"itemType": pb.ChatType_HeroShare,
},
}
jsonStr, _ = json.Marshal(data)
msg.AppendStr = string(jsonStr)
}
}
}
if this.IsCross() {
if err = this.modelChat.sendChatToSystem(msg); err != nil {
this.Errorln(err)
return
}
} else {
if _, err = this.service.AcrossClusterRpcGo(
context.Background(),
this.GetCrossTag(),
comm.Service_Worker,
string(comm.Rpc_ModuleChatPushChat),
msg,
nil); err != nil {
this.Errorln(err)
errdata = &pb.ErrorData{
Code: pb.ErrorCode_RpcFuncExecutionError,
Title: pb.ErrorCode_RpcFuncExecutionError.ToString(),
Message: err.Error(),
}
}
}
}
return
}
// 广播系统消息
func (this *Chat) SendSysChatToUser(session comm.IUserSession, ctype comm.ChatSystemType, value0, value1 int32, agrs ...string) (errdata *pb.ErrorData) {
if st, ok := this.configure.GetCheckChatSystem(int32(ctype), value0, value1); ok {
msg := &pb.DBChat{
Channel: pb.ChatChannel_System,
Ctime: time.Now().Unix(),
AppendInt: int64(st.Key),
}
session.SendMsg(string(this.GetType()), "message", &pb.ChatMessagePush{Chat: msg})
}
return
}
// Push--------------------------------------------------------------------------------------------------------------
// 推送消息到世界
func (this *Chat) pushChatToWorld(msg *pb.DBChat) (err error) {
data, _ := anypb.New(&pb.ChatMessagePush{Chat: msg})
if err = this.service.AcrossClusterBroadcast(context.Background(), msg.Stag, comm.Service_Gateway, string(comm.Rpc_GatewaySendRadioMsg), pb.UserMessage{
MainType: string(this.GetType()),
SubType: "message",
Data: data,
}, nil); err != nil {
this.Errorf("err:%v", err)
}
return
}
// 推送消息到工会
func (this *Chat) pushChatToUnion(msg *pb.DBChat) (err error) {
if members := this.sociaty.MembersBySociatyId(msg.UnionId); members != nil {
users := make([]string, 0, len(members))
for _, v := range members {
if v.OfflineTime == 0 { //离线时间为0 表示在线
users = append(users, v.Uid)
}
}
this.SendMsgToUsers(string(this.GetType()), "message", &pb.ChatMessagePush{Chat: msg}, users...)
}
return
}
// 推送私聊消息
func (this *Chat) pushChatToPrivate(msg *pb.DBChat) (err error) {
var (
session comm.IUserSession
ok bool
)
defer func() {
this.PutUserSession(session)
}()
if session, ok = this.GetUserSession(msg.Ruid); ok {
session.SendMsg(string(this.GetType()), "message", &pb.ChatMessagePush{Chat: msg})
if err = session.Push(); err != nil {
this.Errorf("err:%v", err)
}
} else {
err = this.modelChat.saveUserMsg(msg)
}
return
}
// 推送跨服频道消息
func (this *Chat) pushChatToCross(msg *pb.DBChat) (err error) {
var (
users []*pb.CacheUser
)
if users, err = this.modelChat.getCrossChannelMember(msg.ChannelId); err == nil {
if err = this.SendMsgToCUsers(string(this.GetType()), "message", &pb.ChatMessagePush{Chat: msg}, users...); err != nil {
this.Errorf("err:%v", err)
return
}
}
return
}
// 推送系统消息
func (this *Chat) pushChatToSystem(msg *pb.DBChat) (err error) {
data, _ := anypb.New(&pb.ChatMessagePush{Chat: msg})
if err = this.service.ClusterBroadcast(context.Background(), comm.Service_Gateway, string(comm.Rpc_GatewaySendRadioMsg), pb.UserMessage{
MainType: string(this.GetType()),
SubType: "message",
Data: data,
}, nil); err != nil {
this.Errorf("err:%v", err)
}
return
}