s1.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. //引入http模块
  2. var socketio = require('socket.io'),
  3. fs = require('fs'),
  4. https = require('http'),
  5. domain = require('domain'),
  6. redis = require('redis'),
  7. redisio = require('socket.io-redis'),
  8. request = require('request'),
  9. md5 = require('md5-node'),
  10. config = require('./config.js');
  11. var d = domain.create();
  12. d.on("error", function(err) {
  13. //console.log(err);
  14. });
  15. var sockets = {};
  16. var chat_history={};
  17. var chat_interval={};
  18. /* 主播连麦关系 */
  19. var LiveConnect={};
  20. var LiveConnect_pull={};
  21. // redis 链接
  22. var clientRedis = redis.createClient(config['REDISPORT'],config['REDISHOST']);
  23. clientRedis.auth(config['REDISPASS']);
  24. //var server = https.createServer(options,function(req, res) {
  25. var server = https.createServer(function(req, res) {
  26. res.writeHead(200, {
  27. 'Content-type': 'text/html;charset=utf-8'
  28. });
  29. //res.write("人数: " + numscount );
  30. res.end();
  31. }).listen(config['socket_port'], function() {
  32. ////console.log('服务开启19965');
  33. });
  34. var field=[];
  35. var io = socketio.listen(server,{
  36. pingTimeout: 60000,
  37. pingInterval: 25000
  38. });
  39. io.on('connection', function(socket) {
  40. //console.log(FormatNowDate());
  41. //console.log('连接成功');
  42. //numscount++;
  43. var interval;
  44. /* 获取服务端配置 */
  45. request(config['WEBADDRESS']+"?service=Home.getFilterField",function(error, response, body){
  46. if(error){
  47. //console.log(error);
  48. return;
  49. } ;
  50. if(!body){
  51. //console.log(body);
  52. return;
  53. } ;
  54. var res = evalJson(body);
  55. //console.log(body);
  56. //console.log(res.data.info);
  57. //console.log("sssss");
  58. field = res.data.info;
  59. });
  60. //进入房间
  61. socket.on('conn', function(data) {
  62. // console.log('data');
  63. // console.log(data);
  64. if(!data || !data.token){
  65. return !1;
  66. }
  67. userid=data.uid;
  68. if(userid<0 && userid==-9999){ //app端
  69. userid=data.mobileid;
  70. data.uid=data.mobileid;
  71. data.token=data.mobileid;
  72. }
  73. old_socket = sockets[userid];
  74. if (old_socket && old_socket != socket) {
  75. if(data.uid != data.roomnum && data.uid==old_socket.roomnum){
  76. /* 进房间 但旧链接是 主播 */
  77. var data_str='{"retmsg":"ok","retcode":"000000","msg":[{"msgtype":"1","_method_":"StartEndLive","action":"19","ct":"直播关闭"}]}';
  78. old_socket.emit('broadcastingListen',[data_str]);
  79. }else if(data.uid== data.roomnum && data.stream==old_socket.stream){
  80. /* 主播重连 */
  81. old_socket.reusing = 1;
  82. //console.log("重用");
  83. }else if(data.uid== data.roomnum && data.stream!=old_socket.stream){
  84. /* 主播多端开播 */
  85. var data_str='{"retmsg":"ok","retcode":"000000","msg":[{"msgtype":"1","_method_":"StartEndLive","action":"19","ct":"直播关闭"}]}';
  86. old_socket.emit('broadcastingListen',[data_str]);
  87. }
  88. old_socket.disconnect()
  89. }
  90. clientRedis.get(data.token,function(error,res){
  91. if(error){
  92. return;
  93. }else if(res==null){
  94. console.log("[获取token失败]"+data.uid);
  95. }else{
  96. if(res != null){
  97. var userInfo = evalJson(res);
  98. // console.log("用户进入直播间-----------"+res);
  99. if(userInfo['id'] == data.uid ){
  100. //console.log("[初始化验证成功]--"+data.uid+"---"+data.roomnum+'---'+data.stream);
  101. //获取验证token
  102. socket.token = data.token;
  103. socket.roomnum = data.roomnum;
  104. socket.stream = data.stream;
  105. socket.nicename = userInfo['user_nicename'];
  106. socket.level = userInfo['level'];
  107. socket.avatar = userInfo['avatar'];
  108. socket.sign = Number(userInfo['sign']);
  109. socket.usertype = parseInt(userInfo['usertype']);
  110. socket.uid = data.uid;
  111. socket.reusing = 0;
  112. socket.join(data.roomnum);
  113. sockets[userid] = socket;
  114. socket.emit('conn',['ok']);
  115. if( socket.roomnum!=socket.uid){
  116. var data_obj={
  117. "msg":[
  118. {
  119. "_method_":"SendMsg",
  120. "action":"0",
  121. "ct":{
  122. "id":''+userInfo['id'],
  123. "user_nicename":''+userInfo['user_nicename'],
  124. "avatar":userInfo['avatar'],
  125. "avatar_thumb":userInfo['avatar_thumb'],
  126. "level":''+userInfo['level'],
  127. "usertype":''+userInfo['usertype'],
  128. },
  129. "msgtype":"0"
  130. }
  131. ],
  132. "retcode":"000000",
  133. "retmsg":"OK"
  134. };
  135. // console.log(userInfo['usertype']);
  136. process_msg(io,socket.roomnum,JSON.stringify(data_obj));
  137. if(socket.stream){
  138. clientRedis.zadd('user_'+socket.stream,socket.sign,userInfo['id']);
  139. }
  140. }
  141. // sendSystemMsg(socket,"直播内容包含任何低俗、暴露和涉黄内容,账号会被封禁;安全部门会24小时巡查哦~");
  142. sendSystemMsg(socket,"欢迎来到直播间,我们倡导绿色直播。直播内容和封面有违法违规、色情低俗、抽烟喝酒、诱导欺诈、聚众闹事等行为账号会被封禁,网警24小时在线巡查哦!");
  143. return;
  144. }else{
  145. socket.disconnect();
  146. }
  147. }
  148. }
  149. socket.emit('conn',['no']);
  150. });
  151. });
  152. socket.on('broadcast',function(data){
  153. //console.log(data);
  154. if(socket.token != undefined){
  155. var dataObj = typeof data == 'object'?data:evalJson(data);
  156. var msg = dataObj['msg'][0];
  157. var token = dataObj['token'];
  158. var method = msg['_method_'];
  159. var action = msg['action'];
  160. var data_str = typeof data == 'object'?JSON.stringify(data):data;
  161. switch(method){
  162. case 'SendMsg':{ //聊天
  163. dataObj['msg'][0]['ct']=filter(dataObj['msg'][0]['ct']);
  164. clientRedis.hget( "super",socket.uid,function(error,res){
  165. if(error) return;
  166. if(res != null){
  167. var data_str2={
  168. "msg":[
  169. {
  170. "_method_":"SystemNot",
  171. "action":"1",
  172. "ct":''+dataObj['msg'][0]['ct'],
  173. "msgtype":"4"
  174. }
  175. ],
  176. "retcode":"000000",
  177. "retmsg":"OK"
  178. };
  179. process_msg(io,socket.roomnum,JSON.stringify(data_str2));
  180. }else{
  181. data_str=JSON.stringify(dataObj);
  182. clientRedis.hget(socket.roomnum + "shutup",socket.uid,function(error,res){
  183. if(error) return;
  184. if(res != null){
  185. var newData = dataObj;
  186. newData['retcode'] = '409002';
  187. socket.emit('broadcastingListen',[JSON.stringify(newData)]);
  188. }else{
  189. process_msg(io,socket.roomnum,data_str);
  190. }
  191. });
  192. }
  193. });
  194. break;
  195. }
  196. case 'SendGift':{ //送礼物
  197. var gifToken = dataObj['msg'][0]['ct'];
  198. console.log('送礼物gifToken');
  199. console.log(gifToken);
  200. clientRedis.get(gifToken,function(error,res){
  201. console.log('get送礼物');
  202. console.log(error);
  203. console.log(res);
  204. if(!error&&res != null){
  205. var sendGiftObj = evalJson(res);
  206. console.log(sendGiftObj);
  207. var len=sendGiftObj.length;
  208. for (var i = 0; i < len; i++) {
  209. var resObj= sendGiftObj[i];
  210. dataObj['msg'][0]['ct'] = resObj;
  211. io.sockets.in(socket.roomnum).emit('broadcastingListen',[JSON.stringify(dataObj)]);
  212. }
  213. clientRedis.del(gifToken);
  214. }
  215. });
  216. break;
  217. }
  218. case 'SendBarrage':{ //弹幕
  219. var barragetoken = dataObj['msg'][0]['ct'];
  220. clientRedis.get(barragetoken,function(error,res){
  221. if(!error&&res != null){
  222. var resObj = evalJson(res);
  223. var con=resObj.content;
  224. var res = filter(con);
  225. resObj.content=res;
  226. dataObj['msg'][0]['ct'] = resObj;
  227. var data_str=JSON.stringify(dataObj);
  228. process_msg(io,socket.roomnum,data_str);
  229. clientRedis.del(barragetoken);
  230. }
  231. });
  232. break;
  233. }
  234. case 'light' :{ //点亮
  235. process_msg(io,socket.roomnum,data_str);
  236. break;
  237. }
  238. case 'updateVotes' :{//更新映票
  239. process_msg(io,socket.roomnum,data_str);
  240. break;
  241. }
  242. case 'StartEndLive':{
  243. if(socket.usertype == 50 ){
  244. socket.broadcast.to(socket.roomnum).emit('broadcastingListen',[data_str]);
  245. }else{
  246. clientRedis.get("LiveAuthority" + socket.uid,function(error,res){
  247. if(error) return;
  248. if(parseInt(res) == 5 ||parseInt(res) == 1 || parseInt(res) == 2){
  249. socket.broadcast.to(socket.roomnum).emit('broadcastingListen',[data_str]);
  250. }
  251. })
  252. }
  253. break;
  254. }
  255. case 'SystemNot':{//系统通知
  256. process_msg(io,socket.roomnum,data_str);
  257. break;
  258. }
  259. }
  260. }
  261. });
  262. socket.on('superadminaction',function(data){
  263. if(data['token'] == config['TOKEN']){
  264. io.sockets.in(data['roomnum']).emit("broadcastingListen", ['stopplay']);
  265. }
  266. });
  267. /* 系统信息 */
  268. socket.on('systemadmin',function(data){
  269. if(data['token'] == config['TOKEN']){
  270. var data_obj={
  271. "msg":[
  272. {
  273. "_method_":"SystemNot",
  274. "action":"1",
  275. "ct":''+ data.content,
  276. "msgtype":"4"
  277. }
  278. ],
  279. "retcode":"000000",
  280. "retmsg":"OK"
  281. };
  282. io.emit('broadcastingListen',[JSON.stringify(data_obj)]);
  283. }
  284. });
  285. //资源释放
  286. socket.on('disconnect', function() {
  287. if(socket.roomnum ==null || socket.token==null || socket.uid <=0){
  288. return !1;
  289. }
  290. d.run(function() {
  291. if(socket.roomnum==socket.uid){
  292. /* 主播 */
  293. if(socket.reusing==0){
  294. request(config['WEBADDRESS']+"?service=Live.stopRoom&uid="+socket.uid + "&token=" + socket.token+ "&type=1&source=socket&stream=" + socket.stream,function(error, response, body){
  295. var data_obj={
  296. "retmsg":"ok",
  297. "retcode":"000000",
  298. "msg":[
  299. {
  300. "msgtype":"1",
  301. "_method_":"StartEndLive",
  302. "action":"18",
  303. "ct":"直播关闭"
  304. }
  305. ]
  306. };
  307. process_msg(io,socket.roomnum,JSON.stringify(data_obj));
  308. // console.log('关播');
  309. // console.log(FormatNowDate());
  310. // console.log('uid---'+socket.uid);
  311. });
  312. endLiveConnect(io,socket.uid);
  313. }
  314. }else{
  315. /* 观众 */
  316. clientRedis.zrem('user_'+socket.stream,socket.uid,function(error,res){
  317. if(error) return;
  318. if(res){
  319. var data_obj={
  320. "msg":[
  321. {
  322. "_method_":"disconnect",
  323. "action":"1",
  324. "ct":{
  325. "id":''+socket.uid,
  326. "user_nicename":''+socket.nicename,
  327. "avatar":socket.avatar,
  328. "level":''+socket.level
  329. },
  330. "msgtype":"0",
  331. "uid":''+socket.uid,
  332. "uname":socket.nicename
  333. }
  334. ],
  335. "retcode":"000000",
  336. "retmsg":"OK"
  337. };
  338. process_msg(io,socket.roomnum,JSON.stringify(data_obj));
  339. }
  340. });
  341. clientRedis.del(socket.token);
  342. clientRedis.hdel('super',socket.uid);
  343. }
  344. ////console.log(socket.roomnum+"==="+socket.token+"===="+socket.uid+"======"+socket.stream);
  345. socket.leave(socket.roomnum);
  346. delete io.sockets.sockets[socket.id];
  347. sockets[socket.uid] = null;
  348. delete sockets[socket.uid];
  349. });
  350. });
  351. });
  352. function sendSystemMsg(socket,msg){
  353. var data_obj={
  354. "msg":[
  355. {
  356. "_method_":"SystemNot",
  357. "action":"1",
  358. "ct":""+ msg,
  359. "msgtype":"4"
  360. }
  361. ],
  362. "retcode":"000000",
  363. "retmsg":"OK"
  364. };
  365. socket.emit('broadcastingListen',[JSON.stringify(data_obj)]);
  366. }
  367. function evalJson(data){
  368. return eval("("+data+")");
  369. }
  370. function process_msg(io,roomnum,data){
  371. if(!chat_history[roomnum]){
  372. chat_history[roomnum]=[];
  373. }
  374. chat_history[roomnum].push(data);
  375. chat_interval[roomnum] || (chat_interval[roomnum]=setInterval(function(){
  376. if(chat_history[roomnum].length>0){
  377. send_msg(io,roomnum);
  378. }else{
  379. clearInterval(chat_interval[roomnum]);
  380. chat_interval[roomnum]=null;
  381. }
  382. },200));
  383. }
  384. function send_msg(io,roomnum){
  385. var data=chat_history[roomnum].splice(0,chat_history[roomnum].length);
  386. io.sockets.in(roomnum).emit("broadcastingListen", data);
  387. }
  388. //时间格式化
  389. function FormatNowDate(){
  390. var mDate = new Date();
  391. var Y = mDate.getFullYear();
  392. var M = mDate.getMonth()+1;
  393. var D = mDate.getDate();
  394. var H = mDate.getHours();
  395. var i = mDate.getMinutes();
  396. var s = mDate.getSeconds();
  397. return Y +'-' + M + '-' + D + ' ' + H + ':' + i + ':' + s;
  398. }
  399. /* sign加密 */
  400. function setSign(obj) {//排序的函数
  401. var str='';
  402. var newkey = Object.keys(obj).sort();
  403. //先用Object内置类的keys方法获取要排序对象的属性名,再利用Array原型上的sort方法对获取的属性名进行排序,newkey是一个数组
  404. var newObj = {};//创建一个新的对象,用于存放排好序的键值对
  405. for (var i = 0; i < newkey.length; i++) {//遍历newkey数组
  406. //newObj[newkey[i]] = obj[newkey[i]];//向新创建的对象中按照排好的顺序依次增加键值对
  407. str+=newkey[i]+'='+obj[newkey[i]]+'&';
  408. }
  409. str+=config['sign_key'];
  410. var sign=md5(str);
  411. return sign;
  412. }
  413. //过滤函数
  414. function filter(str) {
  415. // 多个敏感词,这里直接以数组的形式展示出来
  416. var arrMg = field;
  417. //console.log(arrMg);
  418. // 显示的内容--showContent
  419. var showContent = str;
  420. //console.log(showContent);
  421. // 正则表达式
  422. // \d 匹配数字
  423. for (var i = 0; i < arrMg.length; i++) {
  424. // 创建一个正则表达式
  425. var r = new RegExp(arrMg[i], "ig");
  426. var re='';
  427. for(var n=0;n<arrMg[i].length;n++){
  428. re+='*';
  429. }
  430. showContent = showContent.replace(r, re);
  431. }
  432. // 显示的内容--showInput
  433. //console.log(showContent);
  434. return showContent;
  435. }