init
This commit is contained in:
@@ -1,391 +1,391 @@
|
||||
import { Channel, pinus } from "pinus";
|
||||
import { CHANNEL_PREFIX, PUSH_BATCH, PUSH_INTERVAL, PUSH_ROUTE, SDK_PUSH_MSG_PLAYER_TYPE, SDK_PUSH_MSG_TYPE, SDK_PUSH_TARGET_TYPE, 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, needPushMsg } from "../pubUtils/sdkUtil";
|
||||
import { isDevelopEnv } from "./utilService";
|
||||
import { gameData } from "../pubUtils/data";
|
||||
import { pushMsg37 } from "./sdkService";
|
||||
import { RoleModel, RoleType } from "../db/Role";
|
||||
import { GVGLeagueModel } from "../db/GVGLeague";
|
||||
|
||||
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);
|
||||
if(channel) addUserToChannel(channel, roleId, sid);
|
||||
return channel
|
||||
}
|
||||
|
||||
export function addUserToChannel(channel: Channel, roleId: string, sid: string) {
|
||||
let member = channel.getMember(roleId);
|
||||
if(member && member.sid != sid) channel.removeMember(roleId);
|
||||
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);
|
||||
pinus.app.rpc.comBattle.comBattleRemote.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 队伍在地图上受到攻击
|
||||
PUSH_ROUTE.GVG_SPINE_AREA_ADD,
|
||||
PUSH_ROUTE.GVG_SPINE_AREA_LEAVE,
|
||||
PUSH_ROUTE.GVG_SPINE_POINT_CHANGE,
|
||||
].indexOf(event) != -1
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送客户端下拉消息
|
||||
* @param type SDK_PUSH_MSG_TYPE
|
||||
* @returns
|
||||
*/
|
||||
|
||||
export async function pushClientMsg(type: SDK_PUSH_MSG_TYPE) {
|
||||
let dicPushMessage = gameData.dicPushMessage.get(type);
|
||||
if(!dicPushMessage) return;
|
||||
let targetObj = await getPushTarget(dicPushMessage.playerType);
|
||||
if(!targetObj) return;
|
||||
if(!needPushMsg(pinus.app.get('env'))) return;
|
||||
let { target, audiences } = targetObj;
|
||||
let t = Date.now();
|
||||
for(let i = 0; i < audiences.length; i++) {
|
||||
let audience = audiences[i];
|
||||
// console.log(target, audience)
|
||||
if(audience || target == SDK_PUSH_TARGET_TYPE.ALL ) {
|
||||
await timeoutAsync(i * 10)
|
||||
await pushMsg37(t.toString(), dicPushMessage, target, audience);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function timeoutAsync(time: number) {
|
||||
return new Promise<void>((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, time);
|
||||
})
|
||||
}
|
||||
|
||||
// 只推送all
|
||||
async function getPushTarget(playerType: number): Promise<{ target: SDK_PUSH_TARGET_TYPE, audiences: string[] }> {
|
||||
return { target: SDK_PUSH_TARGET_TYPE.ALL, audiences: [''] }
|
||||
|
||||
// let uids: number[] = [];
|
||||
// switch(playerType) {
|
||||
// case SDK_PUSH_MSG_PLAYER_TYPE.HAS_GUILD:
|
||||
// { uids = await getHasGuildPlayers(); break; }
|
||||
// case SDK_PUSH_MSG_PLAYER_TYPE.HAS_LEAGUE:
|
||||
// { uids = await getHasLeaguePlayers(); break; }
|
||||
// case SDK_PUSH_MSG_PLAYER_TYPE.AFK:
|
||||
// { uids = await getAfkPlayers(); break; }
|
||||
// case SDK_PUSH_MSG_PLAYER_TYPE.ACTIVE_PLAYER:
|
||||
// { uids = await getActivePlayers(); break; }
|
||||
// }
|
||||
// let len = uids.length;
|
||||
// if(len == 0) return null;
|
||||
// if(len == 1) return { target: SDK_PUSH_TARGET_TYPE.SINGLE, audiences: [uids.join()] };
|
||||
// let audiences: string[] = [];
|
||||
// for(let i = 0; i < Math.ceil(len/200); i++) {
|
||||
// audiences.push(uids.slice(i * 200, i * 200 + 200).join())
|
||||
// }
|
||||
// return { target: SDK_PUSH_TARGET_TYPE.LIST, audiences };
|
||||
}
|
||||
|
||||
// 有军团且24小时内登录过但当前未在线的玩家
|
||||
async function getHasGuildPlayers() {
|
||||
let uids: number[] = [], players: RoleType[] = [];
|
||||
let createdAt: Date;
|
||||
while(!createdAt || players.length > 0) {
|
||||
players = await RoleModel.findHasGuildPlayers(createdAt);
|
||||
if(players.length == 0) break;
|
||||
createdAt = players[players.length -1].createdAt;
|
||||
players.forEach(player => {
|
||||
if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime && !player.isClosePush) uids.push(player.userInfo.channelInfo.uid);
|
||||
});
|
||||
}
|
||||
return uids;
|
||||
}
|
||||
|
||||
// 有联军且48小时内登录过但当前未在线的玩家
|
||||
async function getHasLeaguePlayers() {
|
||||
let leagues = await GVGLeagueModel.findActiveLeagueMembers();
|
||||
let uids: number[] = [], roleIds: string[] = [];
|
||||
for(let { members } of leagues) roleIds.push(...members.map(member => member.roleId));
|
||||
let len = roleIds.length;
|
||||
for(let i = 0; i < Math.ceil(len/1000); i++) {
|
||||
let curRoleIds = roleIds.slice(i * 1000, i * 1000 + 1000);
|
||||
let players = await RoleModel.findByRoleIds(curRoleIds, 'userInfo.channelInfo isClosePush');
|
||||
players.forEach(player => {
|
||||
if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime && !player.isClosePush) uids.push(player.userInfo.channelInfo.uid);
|
||||
});
|
||||
}
|
||||
return uids;
|
||||
}
|
||||
|
||||
// 至少48小时未上线且等级>=20级的玩家
|
||||
async function getAfkPlayers() {
|
||||
let uids: number[] = [], players: RoleType[] = [];
|
||||
let createdAt: Date;
|
||||
while(!createdAt || players.length > 0) {
|
||||
players = await RoleModel.findAfkPlayers(createdAt);
|
||||
if(players.length == 0) break;
|
||||
createdAt = players[players.length -1].createdAt;
|
||||
players.forEach(player => {
|
||||
if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime && !player.isClosePush) uids.push(player.userInfo.channelInfo.uid);
|
||||
});
|
||||
}
|
||||
return uids;
|
||||
}
|
||||
|
||||
// 24小时内登录过但当前未在线的玩家
|
||||
async function getActivePlayers() {
|
||||
let uids: number[] = [], players: RoleType[] = [];
|
||||
let createdAt: Date;
|
||||
while(!createdAt || players.length > 0) {
|
||||
players = await RoleModel.findActivePlayers(createdAt);
|
||||
if(players.length == 0) break;
|
||||
createdAt = players[players.length -1].createdAt;
|
||||
players.forEach(player => {
|
||||
if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime) uids.push(player.userInfo.channelInfo.uid);
|
||||
});
|
||||
}
|
||||
return uids;
|
||||
}
|
||||
import { Channel, pinus } from "pinus";
|
||||
import { CHANNEL_PREFIX, PUSH_BATCH, PUSH_INTERVAL, PUSH_ROUTE, SDK_PUSH_MSG_PLAYER_TYPE, SDK_PUSH_MSG_TYPE, SDK_PUSH_TARGET_TYPE, 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, needPushMsg } from "@pubUtils/sdkUtil";
|
||||
import { isDevelopEnv } from "./utilService";
|
||||
import { gameData } from "@pubUtils/data";
|
||||
import { pushMsg37 } from "./sdkService";
|
||||
import { RoleModel, RoleType } from "@db/Role";
|
||||
import { GVGLeagueModel } from "@db/GVGLeague";
|
||||
|
||||
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);
|
||||
if(channel) addUserToChannel(channel, roleId, sid);
|
||||
return channel
|
||||
}
|
||||
|
||||
export function addUserToChannel(channel: Channel, roleId: string, sid: string) {
|
||||
let member = channel.getMember(roleId);
|
||||
if(member && member.sid != sid) channel.removeMember(roleId);
|
||||
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);
|
||||
pinus.app.rpc.comBattle.comBattleRemote.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 队伍在地图上受到攻击
|
||||
PUSH_ROUTE.GVG_SPINE_AREA_ADD,
|
||||
PUSH_ROUTE.GVG_SPINE_AREA_LEAVE,
|
||||
PUSH_ROUTE.GVG_SPINE_POINT_CHANGE,
|
||||
].indexOf(event) != -1
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送客户端下拉消息
|
||||
* @param type SDK_PUSH_MSG_TYPE
|
||||
* @returns
|
||||
*/
|
||||
|
||||
export async function pushClientMsg(type: SDK_PUSH_MSG_TYPE) {
|
||||
let dicPushMessage = gameData.dicPushMessage.get(type);
|
||||
if(!dicPushMessage) return;
|
||||
let targetObj = await getPushTarget(dicPushMessage.playerType);
|
||||
if(!targetObj) return;
|
||||
if(!needPushMsg(pinus.app.get('env'))) return;
|
||||
let { target, audiences } = targetObj;
|
||||
let t = Date.now();
|
||||
for(let i = 0; i < audiences.length; i++) {
|
||||
let audience = audiences[i];
|
||||
// console.log(target, audience)
|
||||
if(audience || target == SDK_PUSH_TARGET_TYPE.ALL ) {
|
||||
await timeoutAsync(i * 10)
|
||||
await pushMsg37(t.toString(), dicPushMessage, target, audience);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function timeoutAsync(time: number) {
|
||||
return new Promise<void>((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, time);
|
||||
})
|
||||
}
|
||||
|
||||
// 只推送all
|
||||
async function getPushTarget(playerType: number): Promise<{ target: SDK_PUSH_TARGET_TYPE, audiences: string[] }> {
|
||||
return { target: SDK_PUSH_TARGET_TYPE.ALL, audiences: [''] }
|
||||
|
||||
// let uids: number[] = [];
|
||||
// switch(playerType) {
|
||||
// case SDK_PUSH_MSG_PLAYER_TYPE.HAS_GUILD:
|
||||
// { uids = await getHasGuildPlayers(); break; }
|
||||
// case SDK_PUSH_MSG_PLAYER_TYPE.HAS_LEAGUE:
|
||||
// { uids = await getHasLeaguePlayers(); break; }
|
||||
// case SDK_PUSH_MSG_PLAYER_TYPE.AFK:
|
||||
// { uids = await getAfkPlayers(); break; }
|
||||
// case SDK_PUSH_MSG_PLAYER_TYPE.ACTIVE_PLAYER:
|
||||
// { uids = await getActivePlayers(); break; }
|
||||
// }
|
||||
// let len = uids.length;
|
||||
// if(len == 0) return null;
|
||||
// if(len == 1) return { target: SDK_PUSH_TARGET_TYPE.SINGLE, audiences: [uids.join()] };
|
||||
// let audiences: string[] = [];
|
||||
// for(let i = 0; i < Math.ceil(len/200); i++) {
|
||||
// audiences.push(uids.slice(i * 200, i * 200 + 200).join())
|
||||
// }
|
||||
// return { target: SDK_PUSH_TARGET_TYPE.LIST, audiences };
|
||||
}
|
||||
|
||||
// 有军团且24小时内登录过但当前未在线的玩家
|
||||
async function getHasGuildPlayers() {
|
||||
let uids: number[] = [], players: RoleType[] = [];
|
||||
let createdAt: Date;
|
||||
while(!createdAt || players.length > 0) {
|
||||
players = await RoleModel.findHasGuildPlayers(createdAt);
|
||||
if(players.length == 0) break;
|
||||
createdAt = players[players.length -1].createdAt;
|
||||
players.forEach(player => {
|
||||
if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime && !player.isClosePush) uids.push(player.userInfo.channelInfo.uid);
|
||||
});
|
||||
}
|
||||
return uids;
|
||||
}
|
||||
|
||||
// 有联军且48小时内登录过但当前未在线的玩家
|
||||
async function getHasLeaguePlayers() {
|
||||
let leagues = await GVGLeagueModel.findActiveLeagueMembers();
|
||||
let uids: number[] = [], roleIds: string[] = [];
|
||||
for(let { members } of leagues) roleIds.push(...members.map(member => member.roleId));
|
||||
let len = roleIds.length;
|
||||
for(let i = 0; i < Math.ceil(len/1000); i++) {
|
||||
let curRoleIds = roleIds.slice(i * 1000, i * 1000 + 1000);
|
||||
let players = await RoleModel.findByRoleIds(curRoleIds, 'userInfo.channelInfo isClosePush');
|
||||
players.forEach(player => {
|
||||
if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime && !player.isClosePush) uids.push(player.userInfo.channelInfo.uid);
|
||||
});
|
||||
}
|
||||
return uids;
|
||||
}
|
||||
|
||||
// 至少48小时未上线且等级>=20级的玩家
|
||||
async function getAfkPlayers() {
|
||||
let uids: number[] = [], players: RoleType[] = [];
|
||||
let createdAt: Date;
|
||||
while(!createdAt || players.length > 0) {
|
||||
players = await RoleModel.findAfkPlayers(createdAt);
|
||||
if(players.length == 0) break;
|
||||
createdAt = players[players.length -1].createdAt;
|
||||
players.forEach(player => {
|
||||
if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime && !player.isClosePush) uids.push(player.userInfo.channelInfo.uid);
|
||||
});
|
||||
}
|
||||
return uids;
|
||||
}
|
||||
|
||||
// 24小时内登录过但当前未在线的玩家
|
||||
async function getActivePlayers() {
|
||||
let uids: number[] = [], players: RoleType[] = [];
|
||||
let createdAt: Date;
|
||||
while(!createdAt || players.length > 0) {
|
||||
players = await RoleModel.findActivePlayers(createdAt);
|
||||
if(players.length == 0) break;
|
||||
createdAt = players[players.length -1].createdAt;
|
||||
players.forEach(player => {
|
||||
if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime) uids.push(player.userInfo.channelInfo.uid);
|
||||
});
|
||||
}
|
||||
return uids;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user