聊天:加入玩家发起的群聊和测试用例
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import {Application, BackendSession} from 'pinus';
|
||||
import { resResult } from '../../../pubUtils/util';
|
||||
import { DEFAULT_MSG_PER_PAGE, STATUS } from '../../../consts';
|
||||
import { createPrivateMsg, getPrivateMessages, pushMsgToRole } from '../../../services/chatService';
|
||||
import { createGroupMsg, createPrivateMsg, getPrivateMessages, groupRoomId, pushGroupMsgToRoom, pushMsgToRole } from '../../../services/chatService';
|
||||
|
||||
|
||||
export default function(app: Application) {
|
||||
@@ -79,6 +79,12 @@ export class ChatHandler {
|
||||
*/
|
||||
async sendGroupMessage(msg: { channel: string, channelId: string, type: number, content: string, targetRoleId: string, targetMsgCode: string }, session: BackendSession) {
|
||||
const { channel, channelId, type, content, targetRoleId, targetMsgCode } = msg;
|
||||
const roleId = session.get('roleId');
|
||||
const roleName = session.get('roleName');
|
||||
const msgData = await createGroupMsg(roleId, roleName, channel, channelId, type, content, targetRoleId, targetMsgCode);
|
||||
await pushGroupMsgToRoom(groupRoomId(channel, channelId), msgData);
|
||||
if (!msgData) return resResult(STATUS.WRONG_PARMS);
|
||||
return resResult(STATUS.SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { GroupMessageType } from './../../../db/GroupMessage';
|
||||
import { Application, ChannelService, FrontendSession, RemoterClass, pinus } from 'pinus';
|
||||
import { Application, ChannelService } from 'pinus';
|
||||
import { resResult } from '../../../pubUtils/util';
|
||||
import { STATUS } from '../../../consts';
|
||||
import { ON_ADD_CHANNEL_ROUTE, ON_GROUP_MSG_ROUTE, STATUS } from '../../../consts';
|
||||
import { PrivateMessageType } from '../../../db/PrivateMessage';
|
||||
import { addUserToChannel } from '../../../services/roleService';
|
||||
import { ChannelUser } from '../../../domain/ChannelUser';
|
||||
|
||||
export default function (app: Application) {
|
||||
return new ChatRemote(app);
|
||||
@@ -40,15 +42,13 @@ export class ChatRemote {
|
||||
public async addWorldChannel(roleId: string, serverId: number, sid: string, flag: boolean = true) {
|
||||
const name = `world${serverId}`;
|
||||
let channel = this.channelService.getChannel(name, flag);
|
||||
if (!channel) return;
|
||||
channel.add(roleId, sid);
|
||||
let param = {
|
||||
roleId
|
||||
};
|
||||
channel.pushMessage('onWorldAdd', resResult(STATUS.SUCCESS, param));
|
||||
|
||||
if (!!channel) {
|
||||
channel.add(roleId, sid);
|
||||
}
|
||||
|
||||
return this.getWorldChannel(name);
|
||||
}
|
||||
|
||||
@@ -86,10 +86,8 @@ export class ChatRemote {
|
||||
|
||||
let channel = this.channelService.getChannel(name, false);
|
||||
// leave channel
|
||||
if (!!channel) {
|
||||
channel.leave(roleId, sid);
|
||||
}
|
||||
|
||||
if (!channel) return;
|
||||
channel.leave(roleId, sid);
|
||||
let param = {
|
||||
roleId
|
||||
};
|
||||
@@ -120,7 +118,10 @@ export class ChatRemote {
|
||||
* @memberof ChatRemote
|
||||
*/
|
||||
public async addChannel(channelName: string, roleId: string, sid: string) {
|
||||
|
||||
let channel = this.channelService.getChannel(channelName, true);
|
||||
if (!channel) return;
|
||||
addUserToChannel(channel, new ChannelUser(roleId, sid));
|
||||
channel.pushMessage(ON_ADD_CHANNEL_ROUTE, resResult(STATUS.SUCCESS, { roleId, channelName }));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,7 +132,15 @@ export class ChatRemote {
|
||||
* @memberof ChatRemote
|
||||
*/
|
||||
public async leaveChannel(channelName: string, roleId: string, sid: string) {
|
||||
|
||||
let channel = this.channelService.getChannel(channelName, false);
|
||||
// leave channel
|
||||
if (!channel) return;
|
||||
channel.leave(roleId, sid);
|
||||
let param = {
|
||||
roleId,
|
||||
channelName
|
||||
};
|
||||
channel.pushMessage('onLeave', resResult(STATUS.SUCCESS, param));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,8 +148,10 @@ export class ChatRemote {
|
||||
* @param {Partial<GroupMessageType>} msg
|
||||
* @memberof ChatRemote
|
||||
*/
|
||||
public async sendGroupMsg(msg: Partial<GroupMessageType>) {
|
||||
|
||||
public async sendGroupMsg(roomId: string, msg: Partial<GroupMessageType>) {
|
||||
let channel = this.channelService.getChannel(roomId, false);
|
||||
if (!channel) return;
|
||||
channel.pushMessage(ON_GROUP_MSG_ROUTE, resResult(STATUS.SUCCESS, msg));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,5 +162,4 @@ export class ChatRemote {
|
||||
public async sendPrivateMsg(msg: Partial<PrivateMessageType>) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import { GuildModel } from '../../../db/Guild';
|
||||
import { gameData } from '../../../pubUtils/data';
|
||||
|
||||
import { getMails } from '../../../services/mailService';
|
||||
import { addRoleToGuildChannel, addRoleToSysChannel, addRoleToWorldChannel, leaveGuildChannel, leaveSysChannel, leaveWorldChannel } from '../../../services/chatService';
|
||||
export default function (app: Application) {
|
||||
return new EntryHandler(app);
|
||||
}
|
||||
@@ -88,7 +89,8 @@ export class EntryHandler {
|
||||
// put user into channel
|
||||
// console.log(JSON.stringify(self.app.rpc.battle))
|
||||
// await self.app.rpc.battle.battleRemote.add.route(session)(role.roleId, self.app.get('serverId'), role.serverId, true);
|
||||
|
||||
addRoleToSysChannel(role.roleId, self.app.get('serverId'), role.serverId);
|
||||
addRoleToWorldChannel(role.roleId, self.app.get('serverId'), role.serverId);
|
||||
await self.app.rpc.chat.chatRemote.addWorldChannel.route(session)(role.roleId, serverId, self.app.get('serverId'));
|
||||
await self.app.rpc.chat.guildRemote.enterMyChannel.route(session)(role.roleId, self.app.get('serverId'));
|
||||
let heros = await HeroModel.findByRole(role.roleId, [], HERO_SELECT.ENTRY, true);
|
||||
@@ -110,6 +112,7 @@ export class EntryHandler {
|
||||
if(userGuild) {
|
||||
let guild = await GuildModel.findGuild(userGuild.guildCode, role.serverId, GUILD_SELECT.ENTRY);
|
||||
if(guild) {
|
||||
addRoleToGuildChannel(role.roleId, self.app.get('serverId'), guild.code);
|
||||
role['guildAuth'] = userGuild.auth;
|
||||
let {lv: guildLv, memberCnt} = guild;
|
||||
let dicGuild = gameData.centerBase.get(guildLv);
|
||||
@@ -132,7 +135,7 @@ export class EntryHandler {
|
||||
* @param {Object} session current session object
|
||||
*
|
||||
*/
|
||||
onUserLeave(session: FrontendSession, reason: string) {
|
||||
async onUserLeave(session: FrontendSession, reason: string) {
|
||||
if (!session || !session.uid) {
|
||||
return;
|
||||
}
|
||||
@@ -148,6 +151,9 @@ export class EntryHandler {
|
||||
// this.app.rpc.battle.battleRemote.kick.route(session)(roleId, this.app.get('serverId'), serverId);
|
||||
this.app.rpc.chat.chatRemote.kickWorldChannel.route(session, true)(roleId, sid, serverId);
|
||||
this.app.rpc.chat.guildRemote.leaveMyChannel.route(session)(roleId, sid);
|
||||
await leaveSysChannel(roleId, sid, serverId);
|
||||
await leaveWorldChannel(roleId, sid, serverId);
|
||||
await leaveGuildChannel(roleId, sid);
|
||||
RoleModel.updateRoleInfo(roleId, { quitTime: nowSeconds() });
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { RoleModel } from './../db/Role';
|
||||
import { GroupMessageModel } from './../db/GroupMessage';
|
||||
import { CounterModel } from './../db/Counter';
|
||||
import { STATUS } from './../consts/statusCode';
|
||||
import { PrivateMessageModel, PrivateMessageParam, PrivateMessageType } from './../db/PrivateMessage';
|
||||
@@ -5,7 +7,8 @@ import { GroupMessageParam, GroupMessageType } from '../db/GroupMessage';
|
||||
import { genCode, resResult } from '../pubUtils/util';
|
||||
import { pinus } from 'pinus';
|
||||
import { MSG_CODE_LEN, MSG_STATUS, ON_MSG_ROUTE } from '../consts';
|
||||
import { getRoleOnlineInfo } from './redisService';
|
||||
import { addRedisChannel, getRoleOnlineInfo, redisChannelServer } from './redisService';
|
||||
import { crc32 } from 'crc';
|
||||
|
||||
/**
|
||||
* @description 生成私聊房间号
|
||||
@@ -63,6 +66,13 @@ async function createPrivateMsgData(roleId: string, roleName: string, type: numb
|
||||
return result;
|
||||
}
|
||||
|
||||
async function createGroupMsgData(roleId: string, roleName: string, channel: string, channelId: string, type: number, content: string, targetRoleId: string, targetMsgCode: string) {
|
||||
const result: GroupMessageParam = {roleId, roleName, channel, channelId, type, content, targetRoleId, targetMsgCode};
|
||||
result.roomId = groupRoomId(channel, channelId);
|
||||
await setupBaseMsgParm(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 数据库中创建私聊数据
|
||||
* @export
|
||||
@@ -105,4 +115,72 @@ export async function pushMsgToRole(targetRoleId: string, msg: PrivateMessageTyp
|
||||
export async function getPrivateMessages(roleId: string, targetRoleId: string, fromSeqId: number, count: number) {
|
||||
const result = await PrivateMessageModel.getMsgs(privateRoomId(roleId, targetRoleId), fromSeqId, count);
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function createGroupMsg(roleId: string, roleName: string, channel: string, channelId: string, type: number, content: string, targetRoleId: string, targetMsgCode: string) {
|
||||
const msgData: GroupMessageParam = await createGroupMsgData(roleId, roleName, channel, channelId, type, content, targetRoleId, targetMsgCode);
|
||||
const result: GroupMessageType = await GroupMessageModel.createMsg(msgData);
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function pushGroupMsgToRoom(roomId: string, msg: GroupMessageType) {
|
||||
const channelSid = await channelServer(roomId);
|
||||
await pinus.app.rpc.chat.chatRemote.sendGroupMsg.toServer(channelSid, roomId, msg);
|
||||
}
|
||||
|
||||
export async function channelServer(roomId: string) {
|
||||
const existSid = await redisChannelServer(roomId);
|
||||
if (existSid) {
|
||||
return existSid;
|
||||
}
|
||||
const servers = pinus.app.getServersByType('chat');
|
||||
if (!servers || !servers.length) return null;
|
||||
|
||||
let index = Math.abs(crc32(roomId)) % servers.length;
|
||||
const newSid = servers[index].id;
|
||||
const addResult = await addRedisChannel(roomId, newSid);
|
||||
if (!addResult) return null;
|
||||
return newSid;
|
||||
}
|
||||
|
||||
async function addRoleToChannel(roomId: string, roleId: string, sid: string) {
|
||||
const channelSid = await channelServer(roomId);
|
||||
await pinus.app.rpc.chat.chatRemote.addChannel.toServer(channelSid, roomId, roleId, sid);
|
||||
}
|
||||
|
||||
export async function addRoleToSysChannel(roleId: string, sid: string, serverId: number) {
|
||||
const roomId = groupRoomId('sys', `${serverId}`);
|
||||
await addRoleToChannel(roomId, roleId, sid);
|
||||
}
|
||||
|
||||
export async function addRoleToWorldChannel(roleId: string, sid: string, serverId: number) {
|
||||
const roomId = groupRoomId('new_world', `${serverId}`);
|
||||
await addRoleToChannel(roomId, roleId, sid);
|
||||
}
|
||||
|
||||
export async function addRoleToGuildChannel(roleId: string, sid: string, guildCode: string) {
|
||||
const roomId = groupRoomId('new_guild', guildCode);
|
||||
await addRoleToChannel(roomId, roleId, sid);
|
||||
}
|
||||
|
||||
async function leaveChannel(roomId: string, roleId: string, sid: string) {
|
||||
const channelSid = await channelServer(roomId);
|
||||
await pinus.app.rpc.chat.chatRemote.leaveChannel.toServer(channelSid, roomId, roleId, sid);
|
||||
}
|
||||
|
||||
export async function leaveSysChannel(roleId: string, sid: string, serverId: number) {
|
||||
const roomId = groupRoomId('sys', `${serverId}`);
|
||||
await leaveChannel(roomId, roleId, sid);
|
||||
}
|
||||
|
||||
export async function leaveWorldChannel(roleId: string, sid: string, serverId: number) {
|
||||
const roomId = groupRoomId('new_world', `${serverId}`);
|
||||
await leaveChannel(roomId, roleId, sid);
|
||||
}
|
||||
|
||||
export async function leaveGuildChannel(roleId: string, sid: string) {
|
||||
const { guildCode } = await RoleModel.findByRoleId(roleId, 'guildCode');
|
||||
if (!guildCode) return;
|
||||
const roomId = groupRoomId('new_guild', guildCode);
|
||||
await leaveChannel(roomId, roleId, sid);
|
||||
}
|
||||
@@ -346,12 +346,12 @@ export function redisSidKey(roleId: string) {
|
||||
}
|
||||
|
||||
export async function redisChannelServer(roomId: string) {
|
||||
const sid = await redisClient().hgetAsync(REDIS_KEY.ONLINE_USERS, roomId);
|
||||
const sid = await redisClient().hgetAsync(REDIS_KEY.CHANNEL_SERVERS, roomId);
|
||||
return sid;
|
||||
}
|
||||
|
||||
export async function addRedisChannel(roomId: string, sid: string) {
|
||||
const result = await redisClient().hsetAsync(REDIS_KEY.ONLINE_USERS, roomId, sid);
|
||||
const result = await redisClient().hsetAsync(REDIS_KEY.CHANNEL_SERVERS, roomId, sid);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { PinusWSClient } from 'pinus-robot-plugin';
|
||||
import { expect } from 'chai';
|
||||
import { checkSuccessResponse } from './CheckPatten';
|
||||
import { ON_ADD_CHANNEL_ROUTE } from '../app/consts';
|
||||
|
||||
export class Client {
|
||||
private _client;
|
||||
@@ -19,6 +20,11 @@ export class Client {
|
||||
this._client.request('connector.entryHandler.debugQueryToken', {tel, magicWord: 'zyz666server518'}, (res) => {
|
||||
checkSuccessResponse(res);
|
||||
expect(res.data.token).to.be.an('string');
|
||||
this._client.on(ON_ADD_CHANNEL_ROUTE, (msg) => {
|
||||
checkSuccessResponse(msg);
|
||||
expect(msg.data.roleId).to.be.a('string');
|
||||
expect(msg.data.channelName).to.be.a('string');
|
||||
});
|
||||
this._client.request('connector.entryHandler.enter', {serverId: 1, ...res.data}, (enterRes) => {
|
||||
// 消息回调
|
||||
// console.log('connector返回');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DEFAULT_MSG_PER_PAGE, MSG_TYPE, ON_MSG_ROUTE } from './../app/consts';
|
||||
import { DEFAULT_MSG_PER_PAGE, MSG_TYPE, ON_MSG_ROUTE, ON_GROUP_MSG_ROUTE, CHANNEL_PREFIX } from './../app/consts';
|
||||
import { Client } from './Client';
|
||||
import 'mocha';
|
||||
import { PinusWSClient } from 'pinus-robot-plugin';
|
||||
@@ -13,6 +13,40 @@ function sendPrivateMessageParm(targetRoleInfo, msg) {
|
||||
return result;
|
||||
}
|
||||
|
||||
function sendGroupMessageParm(channel, channelId, msg) {
|
||||
const result = {channel, channelId, ...msg};
|
||||
return result;
|
||||
}
|
||||
|
||||
function checkGroupMsg(msg, roleId, roomId, content) {
|
||||
expect(msg.content).to.equal(TEXT_MSG.content);
|
||||
expect(msg.roleId).to.equal(roleId);
|
||||
expect(msg.content).to.equal(content);
|
||||
expect(msg.roomId).to.equal(roomId);
|
||||
}
|
||||
|
||||
function testGroupMsg(pinusClient: PinusWSClient, roleInfo: any, pinusClientT: PinusWSClient, channel: string, channelId: string, done: Mocha.Done) {
|
||||
let msgReceiveCnt = 0;
|
||||
const roomId = `${channel}_${channelId}`;
|
||||
pinusClientT.on(ON_GROUP_MSG_ROUTE, (res) => {
|
||||
checkSuccessResponse(res);
|
||||
checkGroupMsg(res.data, roleInfo.roleId, roomId, TEXT_MSG.content);
|
||||
msgReceiveCnt += 1;
|
||||
});
|
||||
pinusClient.on(ON_GROUP_MSG_ROUTE, (res) => {
|
||||
checkSuccessResponse(res);
|
||||
checkGroupMsg(res.data, roleInfo.roleId, roomId, TEXT_MSG.content);
|
||||
msgReceiveCnt += 1;
|
||||
});
|
||||
pinusClient.request('chat.chatHandler.sendGroupMessage', sendGroupMessageParm(channel, channelId, TEXT_MSG), (res) => {
|
||||
checkSuccessResponse(res, false);
|
||||
setTimeout(() => {
|
||||
expect(msgReceiveCnt).to.be.equal(2);
|
||||
done();
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
|
||||
describe('聊天测试', function() {
|
||||
let pinusClient: PinusWSClient;
|
||||
let pinusClientT: PinusWSClient; // 用做测试队友
|
||||
@@ -72,4 +106,12 @@ describe('聊天测试', function() {
|
||||
})
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
it('测试系统频道消息', function(done) {
|
||||
testGroupMsg(pinusClient, roleInfo, pinusClientT, CHANNEL_PREFIX.SYS, roleInfo.serverId, done);
|
||||
});
|
||||
|
||||
it('测试世界频道消息', function(done) {
|
||||
testGroupMsg(pinusClient, roleInfo, pinusClientT, CHANNEL_PREFIX.WORLD, roleInfo.serverId, done);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,6 +11,14 @@ export const MSG_TYPE = {
|
||||
IMG: 2
|
||||
}
|
||||
|
||||
export const CHANNEL_PREFIX = {
|
||||
SYS: 'sys',
|
||||
WORLD: 'new_world',
|
||||
GUILD: 'new_guild',
|
||||
}
|
||||
|
||||
export const ON_MSG_ROUTE = 'onMessage';
|
||||
export const ON_GROUP_MSG_ROUTE = 'onGroupMessage';
|
||||
export const ON_ADD_CHANNEL_ROUTE = 'onAddChannel';
|
||||
|
||||
export const DEFAULT_MSG_PER_PAGE = 10;
|
||||
@@ -225,6 +225,7 @@ export const REDIS_KEY = {
|
||||
GUILD_ACTIVE_RANK: "guildActiveRank", // 公会周活跃排行榜
|
||||
DB_GAME: 'db_game', // 服务器列表
|
||||
ONLINE_USERS: 'onlineUsers', // 在线用户情况
|
||||
CHANNEL_SERVERS: 'chat:channelServers', // 渠道对应的 chat 服务器 Id
|
||||
}
|
||||
|
||||
// 各排行榜对应hash的key
|
||||
|
||||
@@ -39,6 +39,21 @@ export default class GroupMessage extends BaseModel {
|
||||
|
||||
@prop({ required: true, default: '' })
|
||||
content: string; // 消息内容
|
||||
|
||||
public static async createMsg(data: GroupMessageParam) {
|
||||
const result = await GroupMessageModel.findOneAndUpdate({ msgCode: data.msgCode }, {...data}, {upsert: true, new: true}).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async findOneMsg(query: GroupMessageParam) {
|
||||
const result = await GroupMessageModel.findOne(query).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async getMsgs(roomId: string, fromSeqId: number, count: number) {
|
||||
const result = await GroupMessageModel.find({ roomId, seqId: { $lt: fromSeqId } }).sort({ seqId: -1 }).limit(count).lean();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user