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.
 
 
 

275 lines
5.7 KiB

  1. const events = require('../../misc/events');
  2. const profanities = require('../../misc/profanities');
  3. const canChat = require('./canChat');
  4. const sendRegularMessage = async ({ obj }, msg) => {
  5. const charname = obj.auth.charname;
  6. const msgEvent = {
  7. username: obj.account,
  8. tagPrefix: '(',
  9. tagSuffix: ')',
  10. tags: [],
  11. emojiTag: null,
  12. namePrefix: '',
  13. nameSuffix: '',
  14. msgStyle: 'color-grayB',
  15. obj
  16. };
  17. await events.emit('onBeforeGetChatStyles', msgEvent);
  18. const { emojiTag } = msgEvent;
  19. let usePrefix = '';
  20. if (emojiTag) {
  21. const imgX = (-emojiTag.sprite[0] * emojiTag.spriteSize);
  22. const imgY = (-emojiTag.sprite[1] * emojiTag.spriteSize);
  23. const backgroundPosition = `${imgX}px ${imgY}px`;
  24. usePrefix = `<div class='emojiTag' style='background: url("${emojiTag.spritesheet}") no-repeat scroll ${backgroundPosition} / auto;'></div>`;
  25. } else if (msgEvent.tags.length > 0)
  26. usePrefix = `${msgEvent.tagPrefix}${msgEvent.tags.join(' ')}${msgEvent.tagSuffix} `;
  27. let useCharName = charname;
  28. if (msgEvent.namePrefix)
  29. useCharName = `${msgEvent.namePrefix}${useCharName}`;
  30. if (msgEvent.nameSuffix)
  31. useCharName = `${useCharName}${msgEvent.nameSuffix}`;
  32. const finalMessage = `${usePrefix}${useCharName}: ${msg.data.message}`;
  33. const item = msg.data.item ? JSON.parse(JSON.stringify(msg.data.item).replace(/(<([^>]+)>)/ig, '')) : undefined;
  34. const eventMsg = {
  35. event: 'onGetMessages',
  36. data: {
  37. messages: [{
  38. class: msgEvent.msgStyle,
  39. message: finalMessage,
  40. item,
  41. type: 'chat',
  42. source: obj.name
  43. }]
  44. }
  45. };
  46. cons.emit('event', eventMsg);
  47. };
  48. const sendPartyMessage = ({ party, obj }, msg) => {
  49. if (!party) {
  50. obj.socket.emit('events', {
  51. onGetMessages: [{
  52. messages: [{
  53. class: 'color-redA',
  54. message: 'you are not in a party',
  55. type: 'info'
  56. }]
  57. }]
  58. });
  59. return;
  60. }
  61. let message = msg.data.message;
  62. const sendMessage = `(party: ${obj.auth.charname}): ${message}`;
  63. const eventData = {
  64. onGetMessages: [{
  65. messages: [{
  66. class: 'color-tealC',
  67. message: sendMessage,
  68. item: msg.data.item,
  69. type: 'chat',
  70. source: obj.name
  71. }]
  72. }]
  73. };
  74. party.forEach(p => {
  75. let player = cons.players.find(c => c.id === p);
  76. player.socket.emit('events', eventData);
  77. });
  78. };
  79. const sendCustomChannelMessage = (cpnSocial, msg) => {
  80. const { obj } = cpnSocial;
  81. const { data: { message, subType: channel } } = msg;
  82. if (!channel)
  83. return;
  84. if (!cpnSocial.isInChannel(obj, channel)) {
  85. obj.socket.emit('events', {
  86. onGetMessages: [{
  87. messages: [{
  88. class: 'color-redA',
  89. message: 'You are not currently in that channel',
  90. type: 'info'
  91. }]
  92. }]
  93. });
  94. return;
  95. }
  96. const sendMessage = `[${channel}] ${obj.auth.charname}: ${message}`;
  97. const eventData = {
  98. onGetMessages: [{
  99. messages: [{
  100. class: 'color-grayB',
  101. message: sendMessage,
  102. item: msg.data.item,
  103. type: 'chat',
  104. subType: 'custom',
  105. channel: channel.trim(),
  106. source: obj.name
  107. }]
  108. }]
  109. };
  110. cons.players.forEach(p => {
  111. if (!cpnSocial.isInChannel(p, channel))
  112. return;
  113. p.socket.emit('events', eventData);
  114. });
  115. };
  116. const sendPrivateMessage = ({ obj: { name: sourceName, socket } }, msg) => {
  117. const { data: { message, subType: targetName } } = msg;
  118. if (targetName === sourceName)
  119. return;
  120. let target = cons.players.find(p => p.name === targetName);
  121. if (!target)
  122. return;
  123. socket.emit('event', {
  124. event: 'onGetMessages',
  125. data: {
  126. messages: [{
  127. class: 'color-yellowB',
  128. message: '(you to ' + targetName + '): ' + message,
  129. item: msg.data.item,
  130. type: 'chat',
  131. subType: 'privateOut',
  132. target: targetName
  133. }]
  134. }
  135. });
  136. target.socket.emit('event', {
  137. event: 'onGetMessages',
  138. data: {
  139. messages: [{
  140. class: 'color-yellowB',
  141. message: '(' + sourceName + ' to you): ' + message,
  142. item: msg.data.item,
  143. type: 'chat',
  144. subType: 'privateIn',
  145. source: sourceName
  146. }]
  147. }
  148. });
  149. };
  150. const sendErrorMsg = (cpnSocial, msgString) => {
  151. cpnSocial.sendMessage(msgString, 'color-redA');
  152. };
  153. module.exports = async (cpnSocial, msg) => {
  154. const { data: msgData } = msg;
  155. if (!msgData.message)
  156. return;
  157. const { obj, maxChatLength, messageHistory } = cpnSocial;
  158. const sendError = sendErrorMsg.bind(null, cpnSocial);
  159. msgData.message = msgData.message
  160. .split('<')
  161. .join('&lt;')
  162. .split('>')
  163. .join('&gt;');
  164. if (!msgData.message)
  165. return;
  166. if (msgData.message.trim() === '')
  167. return;
  168. let messageString = msgData.message;
  169. if (messageString.length > maxChatLength)
  170. return;
  171. let time = +new Date();
  172. messageHistory.spliceWhere(h => ((time - h.time) > 5000));
  173. if (messageHistory.length) {
  174. if (messageHistory[messageHistory.length - 1].msg === messageString) {
  175. sendError('You have already sent that message');
  176. return;
  177. } else if (messageHistory.length >= 3) {
  178. sendError('You are sending too many messages');
  179. return;
  180. }
  181. }
  182. cpnSocial.onBeforeChat(msgData);
  183. if (msgData.ignore)
  184. return;
  185. if (!msgData.item && !profanities.isClean(messageString)) {
  186. sendError('Profanities detected in message. Blocked.');
  187. return;
  188. }
  189. if (!canChat(obj, time)) {
  190. 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.');
  191. return;
  192. }
  193. let msgEvent = {
  194. source: obj.auth.charname,
  195. sourceObj: obj,
  196. msg: messageString,
  197. type: msgData.type,
  198. subType: msgData.subType,
  199. ignore: false,
  200. error: null
  201. };
  202. events.emit('onBeforeSendMessage', msgEvent);
  203. if (msgEvent.ignore) {
  204. if (msgEvent.error)
  205. sendError(msgEvent.error);
  206. return;
  207. }
  208. messageHistory.push({
  209. msg: msgEvent.msg,
  210. time: time
  211. });
  212. const messageHandler = {
  213. global: sendRegularMessage,
  214. custom: sendCustomChannelMessage,
  215. direct: sendPrivateMessage,
  216. party: sendPartyMessage
  217. }[msgData.type];
  218. if (!messageHandler)
  219. return;
  220. await messageHandler(cpnSocial, msg);
  221. };