|
1 | 1 | import time |
2 | | -import json |
| 2 | +import os |
3 | 3 |
|
4 | 4 | from singleton_decorator import singleton |
5 | 5 |
|
|
11 | 11 | class FraudChecks: |
12 | 12 |
|
13 | 13 | def __init__(self): |
14 | | - pass |
| 14 | + self.click_spam_window_in_sec = int(os.getenv("CLICK_SPAM_WINDOW_IN_SEC", Constants.CLICK_SPAM_WINDOW_IN_SEC)) * 1000 |
| 15 | + self.click_spam_threshold = int(os.getenv("CLICK_SPAM_THRESHOLD", Constants.CLICK_SPAM_THRESHOLD)) |
15 | 16 |
|
16 | 17 | def check_fraud(self, data): |
17 | | - if self.ip_fraud(data): |
18 | | - return 'Fraud IP' |
19 | | - if self.ad_stack(data): |
20 | | - return 'Ad Stacked' |
21 | | - return 'Clean Event' |
| 18 | + data['status'] = Constants.CLEAN |
| 19 | + data['fraud_type'] = Constants.CLEAN |
| 20 | + data['ts'] = int(time.time()*1000) |
| 21 | + if self.ip_fraud(data) or self.click_spam(data): |
| 22 | + pass |
| 23 | + self.publish(data) |
| 24 | + return data['fraud_type'] |
22 | 25 |
|
23 | 26 | def ip_fraud(self, data): |
24 | 27 | exists = RedisConn().bloom().cfExists(Constants.IP_CUCKOO_FILTER_NAME, data['ip']) |
25 | | - self.publish(data, "Clean" if not exists else "Fraud") |
| 28 | + if exists: |
| 29 | + data['fraud_type'] = Constants.IP_BLACKLIST |
| 30 | + data['status'] = Constants.FRAUD |
| 31 | + |
26 | 32 | return exists |
27 | 33 |
|
28 | | - def ad_stack(self, data): |
| 34 | + def click_spam(self, data): |
29 | 35 | ## |
30 | 36 | # 'key' of each sorted is the device_id received. |
31 | | - # Ad stacked is True if the count in the range of scores (which is timestamp of event) - |
| 37 | + # click spam is True if the count in the range of scores (which is timestamp of event) - |
32 | 38 | # - is greater than a threshold. |
33 | 39 | # |
34 | 40 | ## |
35 | | - ts = int(time.time() * 1000) |
36 | | - is_ad_stacked = False |
37 | | - member = json.dumps({'device_id': data['device_id'], 'transaction_id': data['transaction_id'], 'ts': ts}) |
38 | | - RedisConn().redis().zadd(data.get('device_id'), {member: ts}) |
39 | | - count = RedisConn().redis().zcount(data.get('device_id'), ts - Constants.AD_STACK_WINDOW, ts) |
40 | | - if count > Constants.AD_STACK_THRESHOLD: |
41 | | - is_ad_stacked = True |
42 | | - self.publish(data, "Fraud" if is_ad_stacked else "Clean") |
43 | | - return is_ad_stacked |
44 | | - |
45 | | - def publish(self, data, status): |
46 | | - data['status'] = status |
47 | | - stream = Constants.CLEAN_STREAM_NAME if status == 'Clean' else Constants.FRAUD_STREAM_NAME |
48 | | - RedisConn().redis().xadd(stream, data, id='*') |
| 41 | + is_click_spammed = False |
| 42 | + count = RedisConn().redis().zcount(data.get('device_id'), data['ts'] - self.click_spam_window_in_sec, data['ts']) |
| 43 | + if count >= self.click_spam_threshold: |
| 44 | + is_click_spammed = True |
| 45 | + data['fraud_type'] = Constants.CLICK_SPAM |
| 46 | + data['status'] = Constants.FRAUD |
| 47 | + return is_click_spammed |
| 48 | + |
| 49 | + def publish(self, data): |
| 50 | + RedisConn().redis().xadd(Constants.STREAM_NAME, data, id='*') |
0 commit comments