Gitter migration: Setup redirects (rollout pt. 3)
[gitter.git] / modules / spam-detection / lib / chat-spam-detection.js
blobd762e70ebe6c13714857948dcff8151c0a3ae785
1 'use strict';
3 const assert = require('assert');
4 const env = require('gitter-web-env');
5 const logger = env.logger.get('spam-detection');
6 const Promise = require('bluebird');
7 const mongoUtils = require('gitter-web-persistence-utils/lib/mongo-utils');
8 const duplicateChatDetector = require('./duplicate-chat-detector');
9 const detectEthereumSpam = require('./detect-ethereum-spam');
10 const userService = require('gitter-web-users');
11 const chatService = require('gitter-web-chats');
12 const stats = env.stats;
13 const config = env.config;
15 const ETHEREUM_DIRTY_GROUP_LIST = config.get('spam-detection:ethereum-dirty-group-list');
17 const ONE_DAY_TIME = 24 * 60 * 60 * 1000; // One day
18 const PROBATION_PERIOD = 14 * ONE_DAY_TIME;
20 /**
21  * Super basic spam detection
22  */
23 async function detect({ room, user, parsedMessage }) {
24   assert(room);
25   assert(user);
26   assert(parsedMessage);
28   // Once a spammer, always a spammer....
29   if (user.hellbanned) return true;
31   const roomId = room.id || room._id;
32   const userId = user.id || user._id;
33   const userCreated = mongoUtils.getTimestampFromObjectId(userId);
35   // Outside of the probation period? For now, let them do anything
36   if (Date.now() - userCreated > PROBATION_PERIOD) {
37     return false;
38   }
40   const spamResults = await Promise.all([
41     duplicateChatDetector(userId, parsedMessage.text),
42     detectEthereumSpam({
43       groupId: room && room.groupId,
44       dirtyGroupList: ETHEREUM_DIRTY_GROUP_LIST,
45       user,
46       text: parsedMessage.text
47     })
48   ]);
50   const [isBulkSpammer, isEthereumSpammer] = spamResults;
52   if (isBulkSpammer) {
53     stats.event('spam_detection.bulk_spam_detected', {
54       userId: userId
55     });
56   }
58   if (isEthereumSpammer) {
59     stats.event('spam_detection.ethereum_spam_detected', {
60       userId: userId
61     });
63     // Clean up all of their messages in the room
64     // as it is probably just them begging for Ethereum in different ways
65     await chatService.removeAllMessagesForUserIdInRoomId(userId, roomId);
66   }
68   const isSpamming = spamResults.some(result => {
69     return result;
70   });
72   if (isSpamming) {
73     logger.warn('Auto spam detector to hellban user for suspicious activity', {
74       userId,
75       username: user.username,
76       text: parsedMessage.text
77     });
79     stats.event('auto_hellban_user', {
80       userId: userId
81     });
83     await userService.hellbanUser(userId);
84   }
86   return isSpamming;
89 module.exports = {
90   detect: Promise.method(detect)