You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

238 lines
4.7 KiB

  1. const roles = require('../../config/roles');
  2. const events = require('../../misc/events');
  3. const profanities = require('../../misc/profanities');
  4. const canChat = require('./canChat');
  5. const sendRegularMessage = ({ obj }, messageInfo) => {
  6. const { source, msg, item } = messageInfo;
  7. const prefix = roles.getRoleMessagePrefix(obj) || '';
  8. const prefixClass = roles.getRoleMessageStyle(obj) || 'color-grayB';
  9. const msgClass = item ? `q${item.quality}` : 'color-grayB';
  10. const msgData = {
  11. type: 'chat',
  12. source,
  13. prefix,
  14. prefixClass,
  15. msg,
  16. msgClass,
  17. item
  18. };
  19. cons.emit('event', {
  20. event: 'onGetMessages',
  21. data: { messages: [msgData] }
  22. });
  23. };
  24. const sendPartyMessage = ({ party, obj }, msg) => {
  25. if (!party) {
  26. obj.socket.emit('events', {
  27. onGetMessages: [{
  28. messages: [{
  29. class: 'color-redA',
  30. message: 'you are not in a party',
  31. type: 'info'
  32. }]
  33. }]
  34. });
  35. return;
  36. }
  37. let charname = obj.auth.charname;
  38. let message = msg.data.message;
  39. party.forEach(p => {
  40. let player = cons.players.find(c => c.id === p);
  41. player.socket.emit('events', {
  42. onGetMessages: [{
  43. messages: [{
  44. class: 'color-tealC',
  45. message: '(party: ' + charname + '): ' + message,
  46. type: 'chat',
  47. source: obj.name
  48. }]
  49. }]
  50. });
  51. });
  52. };
  53. const sendCustomChannelMessage = (cpnSocial, msg) => {
  54. const { obj } = cpnSocial;
  55. const { data: { message, subType: channel } } = msg;
  56. if (!channel)
  57. return;
  58. if (!cpnSocial.isInChannel(obj, channel)) {
  59. obj.socket.emit('events', {
  60. onGetMessages: [{
  61. messages: [{
  62. class: 'color-redA',
  63. message: 'You are not currently in that channel',
  64. type: 'info'
  65. }]
  66. }]
  67. });
  68. return;
  69. }
  70. const sendMessage = `[${channel}] ${obj.auth.charname}: ${message}`;
  71. const eventData = {
  72. onGetMessages: [{
  73. messages: [{
  74. class: 'color-grayB',
  75. message: sendMessage,
  76. type: 'chat',
  77. subType: 'custom',
  78. channel: channel.trim(),
  79. source: obj.name
  80. }]
  81. }]
  82. };
  83. cons.players.forEach(p => {
  84. if (!cpnSocial.isInChannel(p, channel))
  85. return;
  86. p.socket.emit('events', eventData);
  87. });
  88. };
  89. const sendPrivateMessage = ({ obj: { name: sourceName, socket } }, msg) => {
  90. const { data: { message, subType: targetName } } = msg;
  91. if (targetName === sourceName)
  92. return;
  93. let target = cons.players.find(p => p.name === targetName);
  94. if (!target)
  95. return;
  96. socket.emit('event', {
  97. event: 'onGetMessages',
  98. data: {
  99. messages: [{
  100. class: 'color-yellowB',
  101. message: '(you to ' + targetName + '): ' + message,
  102. type: 'chat',
  103. subType: 'privateOut',
  104. target: targetName
  105. }]
  106. }
  107. });
  108. target.socket.emit('event', {
  109. event: 'onGetMessages',
  110. data: {
  111. messages: [{
  112. class: 'color-yellowB',
  113. message: '(' + sourceName + ' to you): ' + message,
  114. type: 'chat',
  115. subType: 'privateIn',
  116. source: sourceName
  117. }]
  118. }
  119. });
  120. };
  121. const sendErrorMsg = (cpnSocial, msgString) => {
  122. cpnSocial.sendMessage(msgString, 'color-redA');
  123. };
  124. module.exports = (cpnSocial, msg) => {
  125. const { data: msgData } = msg;
  126. if (!msgData.message)
  127. return;
  128. const { obj, maxChatLength, messageHistory } = cpnSocial;
  129. const sendError = sendErrorMsg.bind(null, cpnSocial);
  130. msgData.message = msgData.message
  131. .split('<')
  132. .join('&lt;')
  133. .split('>')
  134. .join('&gt;');
  135. if (!msgData.message)
  136. return;
  137. if (msgData.message.trim() === '')
  138. return;
  139. let messageString = msgData.message;
  140. if (messageString.length > maxChatLength)
  141. return;
  142. let time = +new Date();
  143. messageHistory.spliceWhere(h => ((time - h.time) > 5000));
  144. if (messageHistory.length) {
  145. if (messageHistory[messageHistory.length - 1].msg === messageString) {
  146. sendError('You have already sent that message');
  147. return;
  148. } else if (messageHistory.length >= 3) {
  149. sendError('You are sending too many messages');
  150. return;
  151. }
  152. }
  153. cpnSocial.onBeforeChat(msgData);
  154. if (msgData.ignore)
  155. return;
  156. if (!msgData.item && !profanities.isClean(messageString)) {
  157. sendError('Profanities detected in message. Blocked.');
  158. return;
  159. }
  160. if (!canChat(obj, time)) {
  161. sendError('Your character needs to be played for at least 3 minutes or be at least level 3 to be able to send messages in chat.');
  162. return;
  163. }
  164. const msgEvent = {
  165. source: obj.auth.charname,
  166. sourceObj: obj,
  167. msg: messageString,
  168. ignore: false,
  169. item: msg.data.item,
  170. error: null
  171. };
  172. events.emit('onBeforeSendMessage', msgEvent);
  173. if (msgEvent.ignore) {
  174. if (msgEvent.error)
  175. sendError(msgEvent.error);
  176. return;
  177. }
  178. messageHistory.push({
  179. msg: msgEvent.msg,
  180. time: time
  181. });
  182. const messageHandler = {
  183. global: sendRegularMessage,
  184. custom: sendCustomChannelMessage,
  185. direct: sendPrivateMessage,
  186. party: sendPartyMessage
  187. }[msgData.type];
  188. if (!messageHandler)
  189. return;
  190. messageHandler(cpnSocial, msgEvent);
  191. };