import { Channel, pinus } from "pinus"; import { CHANNEL_PREFIX, PUSH_BATCH, PUSH_INTERVAL, PUSH_ROUTE, STATUS } from "../consts"; import { genCode, resResult } from "../pubUtils/util"; import { getCityChannelSid, getGuildChannelSid, getWorldChannelSid, groupRoomId, getGroupShopSid, getGVGAreaChannelSid, getGVGAreaTeamChannelSid, getGVGCityTeamChannelSid } from "./chatService"; import { getAllOnlineRoles, getAllServers, getRoleOnlineInfo } from "./redisService"; import { errlogger, infologger } from '../util/logger'; import { MsgEncrypt } from "../pubUtils/sysUtil"; import { isSkipEncode } from "../pubUtils/sdkUtil"; import { isDevelopEnv } from "./utilService"; export async function sendMessageToAllWithSuc(route: string, data: any, filterCb?: ({ lv, topLineupCe }) => boolean) { await sendMessageToAll(route, resResult(STATUS.SUCCESS, data), filterCb); } export async function sendMessageToAll(route: string, data: any, filterCb?: ({ lv, topLineupCe }) => boolean) { let allOnlineUsers = await getAllOnlineRoles(); if(filterCb) { allOnlineUsers = allOnlineUsers.filter(filterCb); } let n = Math.ceil(allOnlineUsers.length / PUSH_BATCH); // 一共多少批 let sendToUser = (i: number) => { let users = allOnlineUsers.slice(i * PUSH_BATCH, (i + 1) * PUSH_BATCH - 1); let uids = users.map(cur => ({ uid: cur.roleId, sid: cur.sid })); sendMessageToUsers(route, data, uids); } let i = -1; sendToUser(++i); let interval = setInterval(() => { if (++i < n) { sendToUser(i); } else { clearInterval(interval); } }, PUSH_INTERVAL); } export async function sendMessageToAllServersWithSuc(route: string, data: any) { let servers = await getAllServers(); for(let serverId of servers) { await sendMessageToServerWithSuc(serverId, route, data); } } export async function sendMessageToServerWithSuc(serverId: number, route: string, data: any, isBatch = false) { await sendMessageToServer(serverId, route, resResult(STATUS.SUCCESS, data), isBatch); } export async function sendMessageToServer(serverId: number, route: string, data: any, isBatch = false) { let channelSid = await getWorldChannelSid(serverId); let roomId = groupRoomId(CHANNEL_PREFIX.WORLD, serverId); await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, data, isBatch); } export async function sendMessageToGuildWithSuc(guildCode: string, route: string, data: any) { await sendMessageToGuild(guildCode, route, resResult(STATUS.SUCCESS, data)); } export async function sendMessageToGuild(guildCode: string, route: string, data: any) { let channelSid = await getGuildChannelSid(guildCode); let roomId = groupRoomId(CHANNEL_PREFIX.GUILD, guildCode); await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, data); } export async function sendMessageToGVGAreaWithSuc(groupKey: string, areaId: number, route: string, data: any) { let channelSid = await getGVGAreaChannelSid(groupKey, areaId); let roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREAS, `${groupKey}_${areaId}`); await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, resResult(STATUS.SUCCESS, data)); } export async function sendMessageToGVGAreaByTeamWithSuc(groupKey: string, areaId: number, route: string, data: any) { let channelSid = await getGVGAreaTeamChannelSid(groupKey, areaId); let roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREA_BY_TEAM, `${groupKey}_${areaId}`); await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, resResult(STATUS.SUCCESS, data)); } export async function sendMessageToGVGCityWithSuc(groupKey: string, cityId: number, route: string, data: any) { let channelSid = await getGVGCityTeamChannelSid(groupKey, cityId); let roomId = groupRoomId(CHANNEL_PREFIX.GVG_CITY, `${groupKey}_${cityId}`); await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, resResult(STATUS.SUCCESS, data)); } export async function sendMessageToCityWithSuc(serverId: number, cityId: number, route: string, data: any) { await sendMessageToCity(serverId, cityId, route, resResult(STATUS.SUCCESS, data)); } export async function sendMessageToCity(serverId: number, cityId: number, route: string, data: any) { let channelSid = await getCityChannelSid(serverId, cityId); let roomId = groupRoomId(CHANNEL_PREFIX.CITY, `${serverId}_${cityId}`); await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, data); } export async function sendMessageToGroupShopWithSuc(route: string, data: any) { let channelSid = await getGroupShopSid(); let roomId = groupRoomId(CHANNEL_PREFIX.GROUP_SHOP); await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, resResult(STATUS.SUCCESS, data)); } export async function sendMessageToUserWithSuc(roleId: string, route: string, data: any, sid?: string) { await sendMessageToUser(roleId, route, resResult(STATUS.SUCCESS, data), sid); } export async function sendMessageToUser(roleId: string, route: string, data: any, sid?: string) { let uids = []; if (!sid) { let onlineUser = await getRoleOnlineInfo(roleId); sid = onlineUser.sid; } if (!!sid) { uids.push({ uid: roleId, sid }); sendMessageToUsers(route, data, uids); } } export async function sendMessageToUsersWithSuc(route: string, data: any, uids: { uid: string, sid: string }[]) { await sendMessageToUsers(route, resResult(STATUS.SUCCESS, data), uids); } // 推送给个人的方法收束于这个函数 export async function sendMessageToUsers(route: string, data: any, uids: { uid: string, sid: string }[]) { if(uids.length > 0) { pinus.app.get('channelService').pushMessageByUids(route, encryptMsg(route, data), uids); infologger.debug(`pushMessage route: ${route} data: ${JSON.stringify(data)} members: ${uids.map(obj => obj.uid).join()}`); } } export async function sendMessageToTeam(teamCode: string, route: string, data: any) { const channel = pinus.app.get('channelService').getChannel(teamCode); sendMessageToChannel(channel, route, resResult(STATUS.SUCCESS, data)); } /** * * @param user */ export function addUserToTeamChannel(teamCode: string, isCreate: boolean, roleId: string, sid: string) { let channel = pinus.app.get('channelService').getChannel(teamCode, isCreate); addUserToChannel(channel, roleId, sid); return channel } export function addUserToChannel(channel: Channel, roleId: string, sid: string) { const users = channel.getMembers(); if (users.indexOf(roleId) === -1) { channel.add(roleId, sid); } } export function sendMessgeToChannelByBatch(channel: Channel, route: string, data: any) { let members = channel.getMembers(); if(members.length > PUSH_BATCH) { let n = Math.ceil(members.length / PUSH_BATCH); // 一共多少批 // console.log(n) let i = -1; let interval = setInterval(() => { if (++i < n) { let uidlist = members.slice(i * PUSH_BATCH, (i + 1) * PUSH_BATCH - 1); let uids: { uid: string, sid: string }[] = []; for (let uid of uidlist) { uids.push(channel.getMember(uid)); } sendMessageToUsers(route, data, uids); } else { clearInterval(interval); } }, PUSH_INTERVAL); } else { sendMessageToChannel(channel, route, data); } } // 抽下下来pushMessage收束 export function sendMessageToChannel(channel: Channel, route: string, data: any) { if(channel.getMembers().length <= 0) return; channel.pushMessage(route, encryptMsg(route, data)); infologger.debug(`pushMessage route: ${route} data: ${JSON.stringify(data)} members: ${channel.getMembers().join()}`); } export function delTeamChannel(teamCode: string) { let channel = pinus.app.get('channelService').getChannel(teamCode); if(!!channel) channel.destroy(); } export function removeFromTeamChannel(teamCode: string, roleId: string) { let channel = pinus.app.get('channelService').getChannel(teamCode); if(!channel) return null; let users: string[] = channel.getMembers(); if (users.indexOf(roleId) !== -1) { channel.removeMember(roleId); } } function getKvFromMemory() { let aesKey = pinus.app.get('aesKey'); let aesIV = pinus.app.get('aesIV'); let originK = pinus.app.get('originK'); let originV = pinus.app.get('originV'); let kvRefTime = pinus.app.get('kvRefTime'); let now = new Date().setMinutes(0, 0, 0); if(!kvRefTime || now - kvRefTime >= 60 * 60 * 1000) { originK = genCode(24); originV = genCode(16); let msgEncrypt = new MsgEncrypt({ k: originK, v: originV }); ({ aesKey, aesIV } = msgEncrypt.getEncodeKv()); setKvToRemote(originK, originV, aesKey, aesIV, now); } return { aesKey, aesIV, originK, originV, now } } function setKvToRemote(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { pinus.app.rpc.activity.activityRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); pinus.app.rpc.battle.battleRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); pinus.app.rpc.chat.chatRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); pinus.app.rpc.connector.connectorRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); pinus.app.rpc.guild.guildRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); pinus.app.rpc.order.orderRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); pinus.app.rpc.role.roleRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); pinus.app.rpc.systimer.systimerRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); } export function setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { pinus.app.set('originK', originK); pinus.app.set('originV', originV); pinus.app.set('aesKey', aesKey); pinus.app.set('aesIV', aesIV); pinus.app.set('kvRefTime', now); } function encryptMsg(event: string, json: any) { if(checkNotEncryptRoute(event)) return json let { aesKey, aesIV, originK, originV } = getKvFromMemory(); let msgEncrypt = new MsgEncrypt({ originK, originV }); let data = msgEncrypt.encryptMsg(json); return { data, k: aesKey, v: aesIV } } function checkNotEncryptRoute(event: string) { return isSkipEncode(isDevelopEnv()) || [ PUSH_ROUTE.PUSH_CURRENT_TIME, // onPushCurrentTime 推送时间 PUSH_ROUTE.RACE_START, // onRaceStart 粮草先行开始 PUSH_ROUTE.GUILD_ACTIVITY_END, // onGuildActivityEnd 军团活动结束 PUSH_ROUTE.GUILD_RACE_UPDATE, // onRaceHorseUpdate 粮草先行状态 PUSH_ROUTE.GUILD_RACE_EVENT, // onRaceEventUpdate 更新木马事件 PUSH_ROUTE.TEAMMATE_ACT, // onTeammateAct 寻宝队友行动 PUSH_ROUTE.CITY_ACT_RANK, // onGuildCityRankUpdate 诸侯混战排行榜 PUSH_ROUTE.GUILD_CITY_ACT_HP, // onGuildCityGateHpUpdate 诸侯混战城门血条 PUSH_ROUTE.GUILD_GATE_ACT_HP, // onGuildGateHpUpdate 蛮夷入侵城门血条 PUSH_ROUTE.GATE_ACT_RANK, // onGuildGateRankUpdate 蛮夷入侵排行榜 PUSH_ROUTE.BOSS_HP_UPDATE, // onBossHpUpdate 演武台更新 PUSH_ROUTE.DIVIDEND_UPDATE, // onDividendsUpdate 拍卖行分红更新 PUSH_ROUTE.AUCTION_OVER, // onAuctionOver 拍卖价格超过 PUSH_ROUTE.GUILD_BOSS_ENCOURAGE, // onGuildBossEncourage 鼓舞 PUSH_ROUTE.GVG_TEAM_ATTACKED, // onTeamAttacked 当队伍受到攻击 PUSH_ROUTE.GVG_MY_TEAM_ATTACKED, // onMyTeamAttacked 当队伍受到攻击 PUSH_ROUTE.GVG_AREA_SPINE_CHANGE, // onAreaSpinesChange 可见区域内spine的变动,每隔5秒会下发 PUSH_ROUTE.GVG_AREA_POINT_CHANGE, // onMyAreaPointChange 积分点上的驻守人变更 PUSH_ROUTE.GVG_PLAYER_AREA_ADD, // onPlayerAddToArea 积分点上的驻守人变更 PUSH_ROUTE.GVG_PLAYER_LEAVE_AREA, // onPlayerLeaveArea 积分点上的驻守人变更 PUSH_ROUTE.GVG_CITY_RANK_UPDATE, // onGVGCityRankUpdate 城池积分排名 PUSH_ROUTE.GVG_SPINE_ATTACKED, // onSpinesAttacked 队伍在地图上受到攻击 ].indexOf(event) != -1 }