package chat import ( "context" "fmt" "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" ) /* 模块名:论坛 描述:处理跨服社交论坛相关业务 开发:李伟 */ 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(session comm.IUserSession) { if err := this.modelChat.removeCrossChannelMember(session); err != nil { this.Debug("EventUserOffline:", log.Fields{"uid": session.GetUserId(), "err": 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) (code pb.ErrorCode) { var ( max_chat int32 err error ) if max_chat, err = this.configure.GetChannelRecordMax(); err != nil { code = pb.ErrorCode_ConfigNoFound 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) code = pb.ErrorCode_RpcFuncExecutionError } } return } //向工会发送聊天消息 func (this *Chat) SendUnionChat(msg *pb.DBChat) (code pb.ErrorCode) { var ( max_chat int32 err error ) if max_chat, err = this.configure.GetChannelRecordMax(); err != nil { code = pb.ErrorCode_ConfigNoFound 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) code = pb.ErrorCode_RpcFuncExecutionError } } return } //向个人发送聊天消息 func (this *Chat) SendUserChat(msg *pb.DBChat) (code pb.ErrorCode) { var ( err error ) 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) code = pb.ErrorCode_SystemError } return } else { if err = this.modelChat.saveUserMsg(msg); err != nil { code = pb.ErrorCode_DBError return } } return } //广播系统消息 func (this *Chat) SendSysChatToWorld(ctype comm.ChatSystemType, appenddata interface{}, value int32, agrs ...string) (code pb.ErrorCode) { var ( jsonStr []byte err error ) if st, ok := this.configure.GetCheckChatSystem(int32(ctype), value); 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, } if ctype == comm.EquipmentUpgradeNotice { //装备分享 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) } } } 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) code = pb.ErrorCode_RpcFuncExecutionError } } } return } //广播系统消息 func (this *Chat) SendSysChatToUser(session comm.IUserSession, ctype comm.ChatSystemType, value int32, agrs ...interface{}) (code pb.ErrorCode) { if st, ok := this.configure.GetCheckChatSystem(int32(ctype), value); ok { msg := &pb.DBChat{ Channel: pb.ChatChannel_System, Ctime: time.Now().Unix(), Content: fmt.Sprintf(st.Text, agrs...), } 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) { 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) } return } 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 }