'use strict'; var quick = require('quick-pomelo'); var P = quick.Promise; var _ = require('lodash'); var url = require('url'); var md5 = require('md5'); var util = require('util'); var http = require('http'); var qs = require('querystring'); var logger = quick.logger.getLogger('server', __filename); // 构造方法 var Controller = function (app) { this.app = app; this.uptime = Date.now(); this.port = app.getCurServer().httpPort; this.server = http.createServer((req, res) => this.handleAsync(req, res)); this.server.listen(this.port); }; // 导出方法 module.exports = function (app) { return new Controller(app); }; // 原型对象 var proto = Controller.prototype; // 路由函数 proto.route = function (pathname) { switch (pathname) { case '/getGameRoomCount': return (query, method, res) => this.getGameRoomCountAsync(query, method, res); case '/select.nd': return (query, method, res) => this.select(query, method, res); case '/diamond.nd': return (query, method, res) => this.diamondAsync(query, method, res); case '/nnluck.nd': return (query, method, res) => this.nnluckAsync(query, method, res); case '/broadcast.nd': return (query, method, res) => this.broadcastAsync(query, method, res); case '/getUserList': return (query, method, res) => this.getUserListAsync(query, method, res); case '/getUserCount': return (query, method, res) => this.getUserCountAsync(query, method, res); case '/getUserCharge': return (query, method, res) => this.getUserChargeAsync(query, method, res); case '/getSpreaderList': return (query, method, res) => this.getSpreaderListAsync(query, method, res); case '/getChargeList': return (query, method, res) => this.getChargeListAsync(query, method, res); } }; // 写出数据 proto.writeOut = function (query, res) { if (typeof query != 'object') { return res.end(String(query)); } return res.end(JSON.stringify(query)); }; // 跨域选项 const ACCESS = { "Content-Type": "text/plain;charset=utf-8", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "X-Requested-With", "Access-Control-Allow-Methods": "PUT,POST,GET,DELETE,OPTIONS" }; // 入口函数 proto.handleAsync = P.coroutine(function* (req, res) { var pathname = url.parse(req.url).pathname; var phandler = this.route(pathname); if (!phandler) { res.writeHead(404, ACCESS); return res.end('WARNING: Not Found!'); } else { res.writeHead(200, ACCESS); if (req.method.toLowerCase() == 'get') { let query = url.parse(req.url, true).query; return phandler(query, req.method, res); } else if (req.method.toLowerCase() == 'post') { let data = ''; req.on('data', (d) => { data += d; }); req.on('end', () => { let query = { __post__: data }; let regexp = /^\s*{(\s*?".*?":.*\s*)*}\s*$/; if (regexp.test(data)) try { query = JSON.parse(data); } catch (e) { } else if (data.indexOf('=') != -1) query = qs.parse(data); return phandler(query, req.method, res); }); } } }); // 单页记录数 const PAGE_SIZE = 20; // 查询条件 var genCondition = function (query) { var result = { limit: PAGE_SIZE }; var account = query.account; if (!account) { let page = parseInt(query.p) || 1; page = page > 0 ? page : 1; result.skip = (page - 1) * PAGE_SIZE; } return result; }; // 查询接口 proto.select = function (query, method, res) { var method = query['method']; switch (method) { case 'all': return this.allPlayerdAsync(res, query); case 'add': return this.addPlayerAsync(res, query); case 'again': return this.againPlayerAsync(res, query); case 'online': return this.onlinePlayerAsync(res, query); case 'recharge': return this.rechargePlayerAsync(res, query); } return this.writeOut('fail', res); }; // 所有玩家 proto.allPlayerdAsync = P.coroutine(function* (res, query) { var opts = (query.account && { account: query.account }) || {}; var userId = Number(query.userid); if (userId) opts.userId = userId; var count = yield this.app.models.Player.countMongoAsync(opts); var cond = genCondition(query); cond.sort = ['-registerTime']; var players = yield this.app.models.Player.findMongoAsync(opts, 'account userId name diamond totalMoney lastLoginTime registerTime registerIp lastLoginIp', cond); return this.writeOut({ count: count, list: players }, res); }); // 今日新增 proto.addPlayerAsync = P.coroutine(function* (res, query) { var today = new Date(); today.setMilliseconds(0); today.setSeconds(0); today.setMinutes(0); today.setHours(0); var opts = { registerTime: { $gte: today.getTime() } }; if (query.account) opts.account = query.account; var userId = Number(query.userid); if (userId) opts.userId = userId; var cond = genCondition(query); cond.sort = ['-registerTime']; var count = yield this.app.models.Player.countMongoAsync(opts); var players = yield this.app.models.Player.findMongoAsync(opts, 'account userId name diamond totalMoney lastLoginTime registerTime registerIp lastLoginIp', cond); return this.writeOut({ count: count, list: players }, res); }); // 昨日留存 proto.againPlayerAsync = P.coroutine(function* (res, query) { var today = new Date(); today.setMilliseconds(0); today.setSeconds(0); today.setMinutes(0); today.setHours(0); var yest = new Date(today.getTime() - 86400000); var opts = { registerTime: { $gte: yest.getTime(), $lt: today.getTime() }, lastLoginTime: { $gte: today.getTime() } }; if (query.account) opts.account = query.account; var userId = Number(query.userid); if (userId) opts.userId = userId; var cond = genCondition(query); cond.sort = ['-lastLoginTime']; var count = yield this.app.models.Player.countMongoAsync(opts); var players = yield this.app.models.Player.findMongoAsync(opts, 'account userId name diamond totalMoney lastLoginTime registerTime registerIp lastLoginIp', cond); return this.writeOut({ count: count, list: players }, res); }); // 在线玩家 proto.onlinePlayerAsync = P.coroutine(function* (res, query) { var opts = { connectorId: { $ne: '' }, lastLoginTime: { $gt: this.uptime } }; if (query.account) opts.account = query.account; var userId = Number(query.userid); if (userId) opts.userId = userId; var cond = genCondition(query); cond.sort = ['-lastLoginTime']; var count = yield this.app.models.Player.countMongoAsync(opts); var players = yield this.app.models.Player.findMongoAsync(opts, 'account userId name diamond totalMoney lastLoginTime registerTime registerIp lastLoginIp', cond); return this.writeOut({ count: count, list: players }, res); }); // 充值玩家 proto.rechargePlayerAsync = P.coroutine(function* (res, query) { var opts = { totalMoney: { $gt: 0 } }; if (query.account) opts.account = query.account; var userId = Number(query.userid); if (userId) opts.userId = userId; var cond = genCondition(query); cond.sort = ['-lastLoginTime']; var count = yield this.app.models.Player.countMongoAsync(opts); var players = yield this.app.models.Player.findMongoAsync(opts, 'account userId name diamond totalMoney lastLoginTime registerTime registerIp lastLoginIp', cond); return this.writeOut({ count: count, list: players }, res); }); // 添加钻石 proto.diamondAsync = P.coroutine(function* (query, method, res) { var account = query.account; if (!account) return this.writeOut('fail', res); var diamond = parseInt(query.diamond) || 0; if (!diamond) return this.writeOut('fail', res); var self = this; var app = self.app; return app.memdb.goose.transactionAsync(P.coroutine(function* () { var player = yield app.models.Player.findOneAsync({ account: account }, 'diamond'); if (player) { player.diamond += diamond; return player.saveAsync() .then(() => self.writeOut('success', res)); } return self.writeOut('fail', res); }), app.getServerId()) .then(() => app.event.emit('transactionSuccess'), () => app.event.emit('transactionFail')); }); // 牛牛运气 proto.nnluckAsync = P.coroutine(function* (query, method, res) { var account = query.account; if (!account) return this.writeOut('fail', res); var nn_luck = parseInt(query.nnluck) || 0; if (nn_luck < 0) nn_luck = 0; if (nn_luck > 100) nn_luck = 100; var self = this; var app = self.app; return app.memdb.goose.transactionAsync(P.coroutine(function* () { var player = yield app.models.Player.findOneAsync({ account: account }, 'nnLuck'); if (player) { player.nnLuck = nn_luck; return player.saveAsync() .then(() => self.writeOut('success', res)); } return self.writeOut('fail', res); }), app.getServerId()) .then(() => app.event.emit('transactionSuccess'), () => app.event.emit('transactionFail')); }); // 发送广播 proto.broadcastAsync = P.coroutine(function* (query, method, res) { var msg = query.msg; if (msg) { yield this.app.controllers.push.broadcastAsync('broadcast', msg); return this.writeOut('success', res); } return this.writeOut('fail', res); }); // 查找玩家 proto.getUserListAsync = P.coroutine(function* (query, method, res) { var list = []; var page = Number(query.p) || 1; var limit = Number(query.limit) || 30; if (page > 0 && limit > 0) { let skip = (page - 1) * limit; let opts = {}; if (query.search) opts.name = new RegExp('.*' + query.search + '.*'); let platform = query.platform; if (platform) opts._id = new RegExp('.+@' + platform + '$'); let fields = 'account userId name diamond nnLuck totalMoney lastLoginTime registerTime registerIp lastLoginIp'; list = yield this.app.models.Player.findMongoAsync(opts, fields, { sort: { userId: 1 }, skip: skip, limit: limit }); } return this.writeOut(list, res); }); // 统计玩家 proto.getUserCountAsync = P.coroutine(function* (query, method, res) { var result = {}; var start = new Date(query.start); start.setHours(0); var end = new Date((new Date(query.end)).setHours(0) + 86400000); var opts = {}; var type = query.type; var byTime = '$registerTime'; if (type == 'register') { opts.registerTime = { $gte: start.getTime(), $lt: end.getTime() }; } else { byTime = '$lastLoginTime'; opts.lastLoginTime = { $gte: start.getTime(), $lt: end.getTime() }; } var platform = query.platform; if (platform) opts._id = new RegExp('.+@' + platform + '$'); var list = yield this.app.models.Player.aggregateAsync([ { $match: opts }, { $project: { utime: { $add: [byTime, 28800000] } } }, { $project: { xtime: { $subtract: ['$utime', { $mod: ['$utime', 86400000] }] } } }, { $group: { _id: '$xtime', count: { $sum: 1 } } }, { $sort: { _id: 1 } } ]); if (list.length > 0) { list.forEach((o) => { var time = new Date(o._id); var date = util.format('%d-%d-%d', time.getFullYear(), time.getMonth() + 1, time.getDate()); if (result.hasOwnProperty(date)) { result[date] += o.count; } else result[date] = o.count; }); } return this.writeOut(result, res); }); // 统计充值 proto.getUserChargeAsync = P.coroutine(function* (query, method, res) { var result = {}; var start = new Date(query.start); start.setHours(0); var end = new Date((new Date(query.end)).setHours(0) + 86400000); var opts = { time: { $gte: start.getTime(), $lt: end.getTime() } }; var platform = query.platform; if (platform) opts.playerId = new RegExp('.+@' + platform + '$'); var list = yield this.app.models.PayRecord.aggregateAsync([ { $match: opts }, { $project: { utime: { $add: ['$time', 28800000] }, total_fee: 1 } }, { $project: { xtime: { $subtract: ['$utime', { $mod: ['$utime', 86400000] }] }, total_fee: 1 } }, { $group: { _id: '$xtime', count: { $sum: '$total_fee' } } }, { $sort: { _id: 1 } } ]); if (list.length > 0) { list.forEach((o) => { var time = new Date(o._id); var date = util.format('%d-%d-%d', time.getFullYear(), time.getMonth() + 1, time.getDate()); if (result.hasOwnProperty(date)) { result[date] += o.count; } else result[date] = o.count; }); } return this.writeOut(result, res); }); // 推广人信息 proto.getSpreaderListAsync = P.coroutine(function* (query, method, res) { var result = []; var startTime = Number(query.start); if (startTime > 0) startTime *= 1000; else startTime = 0; var endTime = Number(query.end); if (endTime > 0) endTime *= 1000; else endTime = Date.now(); var opts = { time: { $gte: startTime, $lt: endTime } }; var platform = query.platform; var regexp = platform ? new RegExp('.+@' + platform + '$') : undefined; if (regexp) opts['users._id'] = regexp; var list = yield this.app.models.Record.findMongoAsync(opts, 'gameId tableId users._id users.spreader users.cost time', { sort: { time: 1 } }); for (let i = 0; i < list.length; ++i) { let record = list[i]; let users = record.users; for (let user of users) { if ((!regexp || regexp.test(user._id)) && user.spreader) { let item = _.find(result, { gameId: record.gameId, tableId: record.tableId, spreader: user.spreader }); if (item) { item.cost += user.cost; } else result.push({ id: record._id, gameId: record.gameId, tableId: record.tableId, spreader: user.spreader, cost: user.cost, time: record.time }); } } } return this.writeOut(result, res); }); // 场数信息 proto.getGameRoomCountAsync = P.coroutine(function* (query, method, res) { var startTime = Number(query.start); if (startTime > 0) startTime *= 1000; else startTime = 0; var endTime = Number(query.end); if (endTime > 0) endTime *= 1000; else endTime = Date.now(); var opts = { time: { $gte: startTime, $lt: endTime } }; var platform = query.platform; if (platform) opts['users._id'] = new RegExp('.+@' + platform + '$'); var list = yield this.app.models.Record.aggregateAsync([{ $match: opts }, { $group: { _id: '$gameId', count: { $sum: 1 } } }]); var result = _.map(list, (o) => ({ gameId: o._id, count: o.count })); return this.writeOut(result, res); }); // 充值查询 proto.getChargeListAsync = P.coroutine(function* (query, method, res) { var startTime = Number(query.start); if (startTime > 0) startTime *= 1000; else startTime = 0; var endTime = Number(query.end); if (endTime > 0) endTime *= 1000; else endTime = Date.now(); var opts = { time: { $gte: startTime, $lt: endTime } }; var platform = query.platform; if (platform) opts.playerId = new RegExp('.+@' + platform + '$'); var list = yield this.app.models.PayRecord.aggregateAsync([ { $match: opts }, { $lookup: { from: 'player', localField: 'playerId', foreignField: '_id', as: 'player' } }, { $project: { 'playerId': 1, 'total_fee': 1, 'time': 1, 'player.name': 1, 'player.diamond': 1 } }, { $sort: { time: 1 } } ]); var result = _.map(list, (o) => ( { Id: o._id, playerId: o.playerId, name: o.player[0].name, total_fee: o.total_fee, diamond: o.player[0].diamond, time: o.time } )); return this.writeOut(result, res); }); //////下面全是加密解密的逻辑代码,用于用户id随机化显示 // this.logic.checkJiaJieMi(); proto.checkJiaJieMi = function () { let oldList = this.getOldList(); // let oldList = [191151,958658,138757,869158,312757,822951,151552,217851,432457,110959,704255] console.warn("原数组 "+oldList.length+" "+JSON.stringify(oldList)); let jiamiAfterList = []; for (var i = 0; i < oldList.length; i++) { jiamiAfterList[i] = this.jiami(oldList[i]) } console.warn("加密后 "+jiamiAfterList.length+" "+JSON.stringify(jiamiAfterList)); let jiemiAfterList = []; for (var i = 0; i < jiamiAfterList.length; i++) { jiemiAfterList[i] = this.jiemi(jiamiAfterList[i]) } console.warn("解密后 "+jiemiAfterList.length+" "+JSON.stringify(jiemiAfterList)); if(oldList.length == jiemiAfterList.length){ let ismc = true; for (var i = 0; i < oldList.length; i++) { if(oldList[i] != jiemiAfterList[i]) { ismc = false; console.warn("出错了 oldList[i] "+oldList[i]+" jiemiAfterList[i] "+jiemiAfterList[i]); } } if(ismc) console.warn("解密原数组没有问题 ") } else{ console.warn("解密原数组和揭秘数组长度不一致 ") } }; proto.getOldList = function () { let res = [] for (let i = 0; i < 10000; ++i) { let item = _.random(100000, 999999); let pos = res.indexOf(item); if (pos == -1) res[res.length] = item; if(res.length >= 1000) break; } return res; }; proto.jiami = function (_oldid) { let oldid = String(_oldid); // console.warn("111 加密参数 oldid "+oldid); let numList = []; for (var i = 0; i < oldid.length; i++) { numList[i] = (parseInt(oldid[i])+i+1)%10; // console.warn("222 numList[i] "+numList[i]); } // console.warn("333 "+JSON.stringify(numList)); let jh1 = numList[0]; numList[0] = numList[4]; numList[4] = jh1; // console.warn("444 [0]和[4]交换 "+JSON.stringify(numList)); let jh2 = numList[2]; numList[2] = numList[5]; numList[5] = jh2; let newid = ""; // console.warn("555 [2]和[5]交换 "+JSON.stringify(numList)); for (var i = 0; i < numList.length; i++) { newid+=numList[i]; } // console.warn("666 加密最终的 "+newid); return newid; // return parseInt(newid); }; proto.jiemi = function (_oldid) { let oldid = String(_oldid); // console.warn("111 解密参数 oldid "+oldid); let numList = []; for (var i = 0; i < oldid.length; i++) { numList[i] = parseInt(oldid[i]); // console.warn("222 numList[i] "+numList[i]); } // console.warn("333 "+JSON.stringify(numList)); let jh1 = numList[0]; numList[0] = numList[4]; numList[4] = jh1; // console.warn("444 [0]和[4]交换 "+JSON.stringify(numList)); let jh2 = numList[2]; numList[2] = numList[5]; numList[5] = jh2; let numList2 = [] for (var i = 0; i < oldid.length; i++) { numList2[i] = (numList[i]+9-i)%10; // console.warn("2 numList[i] "+numList[i]); } // console.warn("555 [2]和[5]交换 "+JSON.stringify(numList)); let newid = ""; for (var i = 0; i < numList2.length; i++) { newid+=numList2[i]; } // console.warn("666 解密最终的 "+newid); return parseInt(newid); };