@yrpri/api 9.0.230 → 9.0.232
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/controllers/allOurIdeas.js +1 -1
- package/controllers/communities.cjs +282 -91
- package/controllers/domains.cjs +54 -8
- package/controllers/groups.cjs +51 -6
- package/controllers/points.cjs +4 -9
- package/controllers/posts.cjs +7 -9
- package/controllers/ratings.cjs +3 -6
- package/models/point.cjs +31 -3
- package/models/post.cjs +2 -3
- package/package.json +3 -3
- package/services/engine/allOurIdeas/aiHelper.d.ts +7 -4
- package/services/engine/allOurIdeas/aiHelper.js +34 -19
- package/services/engine/allOurIdeas/explainAnswersAssistant.d.ts +1 -1
- package/services/engine/allOurIdeas/explainAnswersAssistant.js +3 -9
- package/services/engine/moderation/fraud/CreateFraudAuditReport.cjs +35 -11
- package/services/engine/moderation/fraud/CreateFraudAuditReport.d.cts +21 -0
- package/services/engine/moderation/fraud/FraudBase.cjs +38 -18
- package/services/engine/moderation/fraud/FraudBase.d.cts +2 -0
- package/services/engine/moderation/fraud/FraudDeleteBase.cjs +48 -29
- package/services/engine/moderation/fraud/FraudDeleteBase.d.cts +8 -6
- package/services/engine/moderation/fraud/FraudDeleteEndorsements.cjs +5 -4
- package/services/engine/moderation/fraud/FraudDeleteEndorsements.d.cts +2 -2
- package/services/engine/moderation/fraud/FraudDeletePointQualities.cjs +3 -2
- package/services/engine/moderation/fraud/FraudDeletePointQualities.d.cts +1 -1
- package/services/engine/moderation/fraud/FraudDeletePoints.cjs +3 -2
- package/services/engine/moderation/fraud/FraudDeletePoints.d.cts +1 -1
- package/services/engine/moderation/fraud/FraudDeletePosts.cjs +3 -2
- package/services/engine/moderation/fraud/FraudDeleteRatings.cjs +61 -4
- package/services/engine/moderation/fraud/FraudGetBase.cjs +44 -20
- package/services/engine/moderation/fraud/FraudGetBase.d.cts +5 -0
- package/services/engine/moderation/fraud/FraudGetEndorsements.cjs +4 -13
- package/services/engine/moderation/fraud/FraudGetEndorsements.d.cts +1 -1
- package/services/engine/moderation/fraud/FraudGetPointQualities.cjs +3 -0
- package/services/engine/moderation/fraud/FraudGetPointQualities.d.cts +1 -1
- package/services/engine/moderation/fraud/FraudGetPoints.cjs +3 -0
- package/services/engine/moderation/fraud/FraudGetPoints.d.cts +1 -1
- package/services/engine/moderation/fraud/FraudGetPosts.cjs +17 -16
- package/services/engine/moderation/fraud/FraudGetPosts.d.cts +3 -3
- package/services/engine/moderation/fraud/FraudGetRatings.cjs +62 -30
- package/services/engine/moderation/fraud/FraudGetRatings.d.cts +4 -1
- package/services/engine/moderation/fraud/FraudRequestValidation.cjs +143 -0
- package/services/engine/moderation/fraud/FraudRequestValidation.d.cts +21 -0
- package/services/engine/moderation/fraud/FraudScannerNotifier.cjs +59 -35
- package/services/engine/moderation/fraud/FraudScannerNotifier.d.cts +20 -1
- package/services/llms/baseChatBot.d.ts +2 -0
- package/services/llms/baseChatBot.js +25 -9
- package/services/llms/imageGeneration/chatGptImageGenerator.d.ts +2 -2
- package/services/llms/imageGeneration/chatGptImageGenerator.js +13 -10
- package/services/llms/imageGeneration/collectionImageGenerator.js +31 -13
- package/services/llms/imageGeneration/dalleImageGenerator.d.ts +2 -2
- package/services/llms/imageGeneration/dalleImageGenerator.js +28 -16
- package/services/llms/imageGeneration/fluxImageGenerator.d.ts +2 -2
- package/services/llms/imageGeneration/fluxImageGenerator.js +9 -3
- package/services/llms/imageGeneration/iImageGenerator.d.ts +8 -1
- package/services/llms/imageGeneration/imageModelConfig.cjs +319 -0
- package/services/llms/imageGeneration/imageModelConfig.d.cts +79 -0
- package/services/llms/imageGeneration/imagenImageGenerator.d.ts +2 -3
- package/services/llms/imageGeneration/imagenImageGenerator.js +10 -10
- package/tests/fraudManagement.test.cjs +470 -0
- package/tests/fraudManagement.test.d.cts +1 -0
- package/tests/imageModelConfig.test.cjs +144 -0
- package/tests/imageModelConfig.test.d.cts +1 -0
- package/utils/ai_image_generation_guard.cjs +268 -0
- package/utils/ai_image_generation_guard.d.cts +34 -0
- package/utils/fingerprint_data.cjs +32 -0
- package/utils/fingerprint_data.d.cts +6 -0
- package/utils/recount_utils.cjs +53 -37
- package/utils/recount_utils.d.cts +7 -7
|
@@ -39,19 +39,7 @@ class FraudGetEndorsements extends FraudGetBase {
|
|
|
39
39
|
const itemsToAnalyse = _.sortBy(items, function (item) {
|
|
40
40
|
return [item.post_id, item.user_agent];
|
|
41
41
|
});
|
|
42
|
-
|
|
43
|
-
if (getGroup && items.length > 0) {
|
|
44
|
-
const group = await models.Group.findOne({
|
|
45
|
-
where: {
|
|
46
|
-
id: itemsToAnalyse[0].Post.Group.id
|
|
47
|
-
},
|
|
48
|
-
attributes: ['configuration']
|
|
49
|
-
});
|
|
50
|
-
if (group) {
|
|
51
|
-
groupConfiguration = group.configuration;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
resolve({ itemsToAnalyse, groupConfiguration });
|
|
42
|
+
resolve({ itemsToAnalyse });
|
|
55
43
|
}
|
|
56
44
|
catch (error) {
|
|
57
45
|
reject(error);
|
|
@@ -66,6 +54,9 @@ class FraudGetEndorsements extends FraudGetBase {
|
|
|
66
54
|
let topItems = this.setupTopItems(items);
|
|
67
55
|
const postIds = this.getPostIdsFromItems(topItems);
|
|
68
56
|
const postCount = _.uniq(postIds).length;
|
|
57
|
+
if (this.isDebugFraudDetectionCountAll()) {
|
|
58
|
+
return this.getDebugTopItems(topItems);
|
|
59
|
+
}
|
|
69
60
|
if (type === "byIpUserAgentPostId") {
|
|
70
61
|
let out = [];
|
|
71
62
|
_.each(topItems, function (item) {
|
|
@@ -2,6 +2,6 @@ export = FraudGetEndorsements;
|
|
|
2
2
|
declare class FraudGetEndorsements extends FraudGetBase {
|
|
3
3
|
getAllModelItems(model: any, getGroup: any): Promise<any>;
|
|
4
4
|
getAllItems(): Promise<any>;
|
|
5
|
-
getTopItems(items: any, type: any): any
|
|
5
|
+
getTopItems(items: any, type: any): any;
|
|
6
6
|
}
|
|
7
7
|
import FraudGetBase = require("./FraudGetBase.cjs");
|
|
@@ -65,6 +65,9 @@ class FraudGetPointQualities extends FraudGetBase {
|
|
|
65
65
|
let topItems = this.setupTopItems(items);
|
|
66
66
|
const pointIds = this.getPointIdsFromItems(topItems);
|
|
67
67
|
const pointCount = _.uniq(pointIds).length;
|
|
68
|
+
if (this.isDebugFraudDetectionCountAll()) {
|
|
69
|
+
return this.getDebugTopItems(topItems);
|
|
70
|
+
}
|
|
68
71
|
if (type === "byIpUserAgentPointId") {
|
|
69
72
|
let out = [];
|
|
70
73
|
_.each(topItems, function (item) {
|
|
@@ -2,6 +2,6 @@ export = FraudGetPointQualities;
|
|
|
2
2
|
declare class FraudGetPointQualities extends FraudGetBase {
|
|
3
3
|
getAllItems(): Promise<any>;
|
|
4
4
|
getPointIdsFromItems(topItems: any): any[];
|
|
5
|
-
getTopItems(items: any, type: any): any
|
|
5
|
+
getTopItems(items: any, type: any): any;
|
|
6
6
|
}
|
|
7
7
|
import FraudGetBase = require("./FraudGetBase.cjs");
|
|
@@ -51,6 +51,9 @@ class FraudGetPointQualities extends FraudGetBase {
|
|
|
51
51
|
const postIds = this.getPostIdsFromItems(topItems);
|
|
52
52
|
const postCount = _.uniq(postIds).length;
|
|
53
53
|
const pointMultiplier = 10;
|
|
54
|
+
if (this.isDebugFraudDetectionCountAll()) {
|
|
55
|
+
return this.getDebugTopItems(topItems);
|
|
56
|
+
}
|
|
54
57
|
if (type === "byIpUserAgentPostId") {
|
|
55
58
|
let out = [];
|
|
56
59
|
_.each(topItems, function (item) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export = FraudGetPointQualities;
|
|
2
2
|
declare class FraudGetPointQualities extends FraudGetBase {
|
|
3
3
|
getAllItems(): Promise<any>;
|
|
4
|
-
getTopItems(items: any, type: any): any
|
|
4
|
+
getTopItems(items: any, type: any): any;
|
|
5
5
|
}
|
|
6
6
|
import FraudGetBase = require("./FraudGetBase.cjs");
|
|
@@ -3,7 +3,7 @@ const _ = require("lodash");
|
|
|
3
3
|
const FraudGetBase = require('./FraudGetBase.cjs');
|
|
4
4
|
const models = require("../../../../models/index.cjs");
|
|
5
5
|
const log = require("../../../../utils/logger.cjs");
|
|
6
|
-
class
|
|
6
|
+
class FraudGetPosts extends FraudGetBase {
|
|
7
7
|
async getAllItems() {
|
|
8
8
|
return await new Promise(async (resolve, reject) => {
|
|
9
9
|
try {
|
|
@@ -41,23 +41,24 @@ class FraudGetPoints extends FraudGetBase {
|
|
|
41
41
|
}
|
|
42
42
|
getTopItems(items, type) {
|
|
43
43
|
let topItems = this.setupTopItems(items);
|
|
44
|
-
const postIds = this.getPostIdsFromItems(topItems);
|
|
45
|
-
const postCount = _.uniq(postIds).length;
|
|
46
44
|
const pointMultiplier = 10;
|
|
45
|
+
if (this.isDebugFraudDetectionCountAll()) {
|
|
46
|
+
return this.getDebugTopItems(topItems);
|
|
47
|
+
}
|
|
47
48
|
if (type === "byIpFingerprint") {
|
|
48
49
|
let out = [];
|
|
49
50
|
_.each(topItems, function (item) {
|
|
50
|
-
if (
|
|
51
|
-
if (
|
|
51
|
+
if (item.count > pointMultiplier) {
|
|
52
|
+
if (item.count > 5 * pointMultiplier) {
|
|
52
53
|
this.setWeightedConfidenceScore(item.items, 70);
|
|
53
54
|
}
|
|
54
|
-
else if (
|
|
55
|
+
else if (item.count > 4 * pointMultiplier) {
|
|
55
56
|
this.setWeightedConfidenceScore(item.items, 60);
|
|
56
57
|
}
|
|
57
|
-
else if (
|
|
58
|
+
else if (item.count > 3 * pointMultiplier) {
|
|
58
59
|
this.setWeightedConfidenceScore(item.items, 40);
|
|
59
60
|
}
|
|
60
|
-
else if (
|
|
61
|
+
else if (item.count > 2 * pointMultiplier) {
|
|
61
62
|
this.setWeightedConfidenceScore(item.items, 20);
|
|
62
63
|
}
|
|
63
64
|
else {
|
|
@@ -74,23 +75,23 @@ class FraudGetPoints extends FraudGetBase {
|
|
|
74
75
|
else if (type === "byIpAddress") {
|
|
75
76
|
let out = [];
|
|
76
77
|
_.each(topItems, function (item) {
|
|
77
|
-
if (
|
|
78
|
-
if (
|
|
78
|
+
if (item.count > pointMultiplier) {
|
|
79
|
+
if (item.count > 100 * pointMultiplier) {
|
|
79
80
|
this.setWeightedConfidenceScore(item.items, 70);
|
|
80
81
|
}
|
|
81
|
-
else if (
|
|
82
|
+
else if (item.count > 50 * pointMultiplier) {
|
|
82
83
|
this.setWeightedConfidenceScore(item.items, 65);
|
|
83
84
|
}
|
|
84
|
-
else if (
|
|
85
|
+
else if (item.count > 25 * pointMultiplier) {
|
|
85
86
|
this.setWeightedConfidenceScore(item.items, 40);
|
|
86
87
|
}
|
|
87
|
-
else if (
|
|
88
|
+
else if (item.count > 10 * pointMultiplier) {
|
|
88
89
|
this.setWeightedConfidenceScore(item.items, 35);
|
|
89
90
|
}
|
|
90
|
-
else if (
|
|
91
|
+
else if (item.count > 5 * pointMultiplier) {
|
|
91
92
|
this.setWeightedConfidenceScore(item.items, 20);
|
|
92
93
|
}
|
|
93
|
-
else if (
|
|
94
|
+
else if (item.count > 2 * pointMultiplier) {
|
|
94
95
|
this.setWeightedConfidenceScore(item.items, 15);
|
|
95
96
|
}
|
|
96
97
|
else {
|
|
@@ -107,4 +108,4 @@ class FraudGetPoints extends FraudGetBase {
|
|
|
107
108
|
}
|
|
108
109
|
}
|
|
109
110
|
}
|
|
110
|
-
module.exports =
|
|
111
|
+
module.exports = FraudGetPosts;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export =
|
|
2
|
-
declare class
|
|
1
|
+
export = FraudGetPosts;
|
|
2
|
+
declare class FraudGetPosts extends FraudGetBase {
|
|
3
3
|
getAllItems(): Promise<any>;
|
|
4
|
-
getTopItems(items: any, type: any): any
|
|
4
|
+
getTopItems(items: any, type: any): any;
|
|
5
5
|
}
|
|
6
6
|
import FraudGetBase = require("./FraudGetBase.cjs");
|
|
@@ -6,38 +6,67 @@ const log = require("../../../../utils/logger.cjs");
|
|
|
6
6
|
class FraudGetRatings extends FraudGetEndorsements {
|
|
7
7
|
constructor(workPackage) {
|
|
8
8
|
super(workPackage);
|
|
9
|
-
this.
|
|
9
|
+
this.ratingDimensionCountsByGroupId = {};
|
|
10
10
|
}
|
|
11
11
|
async getAllItems() {
|
|
12
12
|
const itemsContainer = await this.getAllModelItems(models.Rating, true);
|
|
13
|
-
this.
|
|
13
|
+
this.ratingDimensionCountsByGroupId = await this.getRatingDimensionCountsByGroupId(itemsContainer.itemsToAnalyse);
|
|
14
14
|
return itemsContainer.itemsToAnalyse;
|
|
15
15
|
}
|
|
16
|
+
async getRatingDimensionCountsByGroupId(items) {
|
|
17
|
+
const groupIds = _.uniq(items.map(item => {
|
|
18
|
+
return item.Post && item.Post.Group && item.Post.Group.id;
|
|
19
|
+
}).filter(groupId => groupId));
|
|
20
|
+
if (groupIds.length === 0) {
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
23
|
+
const groups = await models.Group.findAll({
|
|
24
|
+
where: {
|
|
25
|
+
id: groupIds
|
|
26
|
+
},
|
|
27
|
+
attributes: ['id', 'configuration']
|
|
28
|
+
});
|
|
29
|
+
return groups.reduce((countsByGroupId, group) => {
|
|
30
|
+
const customRatings = group.configuration && group.configuration.customRatings;
|
|
31
|
+
countsByGroupId[group.id] =
|
|
32
|
+
customRatings && typeof customRatings === "object"
|
|
33
|
+
? Math.max(Object.keys(customRatings).length, 1)
|
|
34
|
+
: 1;
|
|
35
|
+
return countsByGroupId;
|
|
36
|
+
}, {});
|
|
37
|
+
}
|
|
38
|
+
getRatingDimensionsForItem(item) {
|
|
39
|
+
const groupId = item.Post && item.Post.Group && item.Post.Group.id;
|
|
40
|
+
return this.ratingDimensionCountsByGroupId[groupId] || 1;
|
|
41
|
+
}
|
|
42
|
+
getNormalizedRatingCount(items) {
|
|
43
|
+
return _.sumBy(items, item => 1 / this.getRatingDimensionsForItem(item));
|
|
44
|
+
}
|
|
16
45
|
getTopItems(items, type) {
|
|
17
46
|
let topItems = this.setupTopItems(items);
|
|
18
47
|
const postIds = this.getPostIdsFromItems(topItems);
|
|
19
|
-
const postCount = _.uniq(postIds).length;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
ratingsCount = Object.keys(this.groupConfiguration.customRatings).length;
|
|
48
|
+
const postCount = Math.max(_.uniq(postIds).length, 1);
|
|
49
|
+
if (this.isDebugFraudDetectionCountAll()) {
|
|
50
|
+
return this.getDebugTopItems(topItems);
|
|
23
51
|
}
|
|
24
52
|
if (type === "byIpUserAgentPostId") {
|
|
25
53
|
let out = [];
|
|
26
54
|
_.each(topItems, function (item) {
|
|
27
|
-
|
|
28
|
-
|
|
55
|
+
const ratingRatio = this.getNormalizedRatingCount(item.items);
|
|
56
|
+
if (ratingRatio > 1) {
|
|
57
|
+
if (ratingRatio > 10) {
|
|
29
58
|
this.setWeightedConfidenceScore(item.items, 95);
|
|
30
59
|
}
|
|
31
|
-
else if (
|
|
60
|
+
else if (ratingRatio > 5) {
|
|
32
61
|
this.setWeightedConfidenceScore(item.items, 90);
|
|
33
62
|
}
|
|
34
|
-
else if (
|
|
63
|
+
else if (ratingRatio > 4) {
|
|
35
64
|
this.setWeightedConfidenceScore(item.items, 85);
|
|
36
65
|
}
|
|
37
|
-
else if (
|
|
66
|
+
else if (ratingRatio > 3) {
|
|
38
67
|
this.setWeightedConfidenceScore(item.items, 80);
|
|
39
68
|
}
|
|
40
|
-
else if (
|
|
69
|
+
else if (ratingRatio > 2) {
|
|
41
70
|
this.setWeightedConfidenceScore(item.items, 75);
|
|
42
71
|
}
|
|
43
72
|
else {
|
|
@@ -51,17 +80,18 @@ class FraudGetRatings extends FraudGetEndorsements {
|
|
|
51
80
|
else if (type === "byIpFingerprint") {
|
|
52
81
|
let out = [];
|
|
53
82
|
_.each(topItems, function (item) {
|
|
54
|
-
|
|
55
|
-
|
|
83
|
+
const ratingRatio = this.getNormalizedRatingCount(item.items) / postCount;
|
|
84
|
+
if (ratingRatio > 1) {
|
|
85
|
+
if (ratingRatio > 5) {
|
|
56
86
|
this.setWeightedConfidenceScore(item.items, 99);
|
|
57
87
|
}
|
|
58
|
-
else if (
|
|
88
|
+
else if (ratingRatio > 4) {
|
|
59
89
|
this.setWeightedConfidenceScore(item.items, 95);
|
|
60
90
|
}
|
|
61
|
-
else if (
|
|
91
|
+
else if (ratingRatio > 3) {
|
|
62
92
|
this.setWeightedConfidenceScore(item.items, 90);
|
|
63
93
|
}
|
|
64
|
-
else if (
|
|
94
|
+
else if (ratingRatio > 2) {
|
|
65
95
|
this.setWeightedConfidenceScore(item.items, 85);
|
|
66
96
|
}
|
|
67
97
|
else {
|
|
@@ -78,20 +108,21 @@ class FraudGetRatings extends FraudGetEndorsements {
|
|
|
78
108
|
else if (type === "byIpFingerprintPostId") {
|
|
79
109
|
let out = [];
|
|
80
110
|
_.each(topItems, function (item) {
|
|
81
|
-
|
|
82
|
-
|
|
111
|
+
const ratingRatio = this.getNormalizedRatingCount(item.items);
|
|
112
|
+
if (ratingRatio > 1) {
|
|
113
|
+
if (ratingRatio > 10) {
|
|
83
114
|
this.setWeightedConfidenceScore(item.items, 100);
|
|
84
115
|
}
|
|
85
|
-
else if (
|
|
116
|
+
else if (ratingRatio > 5) {
|
|
86
117
|
this.setWeightedConfidenceScore(item.items, 98);
|
|
87
118
|
}
|
|
88
|
-
else if (
|
|
119
|
+
else if (ratingRatio > 4) {
|
|
89
120
|
this.setWeightedConfidenceScore(item.items, 95);
|
|
90
121
|
}
|
|
91
|
-
else if (
|
|
122
|
+
else if (ratingRatio > 3) {
|
|
92
123
|
this.setWeightedConfidenceScore(item.items, 90);
|
|
93
124
|
}
|
|
94
|
-
else if (
|
|
125
|
+
else if (ratingRatio > 2) {
|
|
95
126
|
this.setWeightedConfidenceScore(item.items, 85);
|
|
96
127
|
}
|
|
97
128
|
else {
|
|
@@ -105,23 +136,24 @@ class FraudGetRatings extends FraudGetEndorsements {
|
|
|
105
136
|
else if (type === "byIpAddress") {
|
|
106
137
|
let out = [];
|
|
107
138
|
_.each(topItems, function (item) {
|
|
108
|
-
|
|
109
|
-
|
|
139
|
+
const ratingRatio = this.getNormalizedRatingCount(item.items) / postCount;
|
|
140
|
+
if (ratingRatio > 1) {
|
|
141
|
+
if (ratingRatio > 100) {
|
|
110
142
|
this.setWeightedConfidenceScore(item.items, 90);
|
|
111
143
|
}
|
|
112
|
-
else if (
|
|
144
|
+
else if (ratingRatio > 50) {
|
|
113
145
|
this.setWeightedConfidenceScore(item.items, 85);
|
|
114
146
|
}
|
|
115
|
-
else if (
|
|
147
|
+
else if (ratingRatio > 25) {
|
|
116
148
|
this.setWeightedConfidenceScore(item.items, 80);
|
|
117
149
|
}
|
|
118
|
-
else if (
|
|
150
|
+
else if (ratingRatio > 10) {
|
|
119
151
|
this.setWeightedConfidenceScore(item.items, 75);
|
|
120
152
|
}
|
|
121
|
-
else if (
|
|
153
|
+
else if (ratingRatio > 5) {
|
|
122
154
|
this.setWeightedConfidenceScore(item.items, 70);
|
|
123
155
|
}
|
|
124
|
-
else if (
|
|
156
|
+
else if (ratingRatio > 2) {
|
|
125
157
|
this.setWeightedConfidenceScore(item.items, 65);
|
|
126
158
|
}
|
|
127
159
|
else {
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export = FraudGetRatings;
|
|
2
2
|
declare class FraudGetRatings extends FraudGetEndorsements {
|
|
3
|
-
|
|
3
|
+
ratingDimensionCountsByGroupId: {};
|
|
4
|
+
getRatingDimensionCountsByGroupId(items: any): Promise<{}>;
|
|
5
|
+
getRatingDimensionsForItem(item: any): any;
|
|
6
|
+
getNormalizedRatingCount(items: any): number;
|
|
4
7
|
}
|
|
5
8
|
import FraudGetEndorsements = require("./FraudGetEndorsements.cjs");
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const MAX_FRAUD_IDS_TO_DELETE = 1000;
|
|
3
|
+
const validActionTypes = new Set(["get-items", "delete-one-item", "delete-items"]);
|
|
4
|
+
const validCollectionTypes = new Set([
|
|
5
|
+
"endorsements",
|
|
6
|
+
"ratings",
|
|
7
|
+
"pointQualities",
|
|
8
|
+
"points",
|
|
9
|
+
"posts",
|
|
10
|
+
]);
|
|
11
|
+
const commonMethods = new Set([
|
|
12
|
+
"byIpFingerprint",
|
|
13
|
+
"byMissingBrowserFingerprint",
|
|
14
|
+
"byIpAddress",
|
|
15
|
+
]);
|
|
16
|
+
const postMethods = new Set([
|
|
17
|
+
...commonMethods,
|
|
18
|
+
"byIpFingerprintPostId",
|
|
19
|
+
"byIpUserAgentPostId",
|
|
20
|
+
]);
|
|
21
|
+
const pointMethods = new Set([
|
|
22
|
+
...commonMethods,
|
|
23
|
+
"byIpFingerprintPointId",
|
|
24
|
+
"byIpUserAgentPointId",
|
|
25
|
+
]);
|
|
26
|
+
const normalizeIdValue = (value) => {
|
|
27
|
+
if (typeof value === "number") {
|
|
28
|
+
return Number.isSafeInteger(value) && value > 0 ? value : null;
|
|
29
|
+
}
|
|
30
|
+
else if (typeof value === "string") {
|
|
31
|
+
const trimmedValue = value.trim();
|
|
32
|
+
if (!/^[1-9]\d*$/.test(trimmedValue)) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const parsedValue = Number(trimmedValue);
|
|
36
|
+
return Number.isSafeInteger(parsedValue) ? parsedValue : null;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const validateIdsToDelete = (idsToDelete) => {
|
|
43
|
+
if (idsToDelete === undefined || idsToDelete === null) {
|
|
44
|
+
return { idsToDelete: [] };
|
|
45
|
+
}
|
|
46
|
+
if (!Array.isArray(idsToDelete)) {
|
|
47
|
+
return {
|
|
48
|
+
error: "invalid_ids_to_delete",
|
|
49
|
+
idsToDelete: [],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (idsToDelete.length > MAX_FRAUD_IDS_TO_DELETE) {
|
|
53
|
+
return {
|
|
54
|
+
error: "too_many_ids_to_delete",
|
|
55
|
+
idsToDelete: [],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const seenIds = new Set();
|
|
59
|
+
const normalizedIds = [];
|
|
60
|
+
for (let i = 0; i < idsToDelete.length; i++) {
|
|
61
|
+
const normalizedId = normalizeIdValue(idsToDelete[i]);
|
|
62
|
+
if (!normalizedId) {
|
|
63
|
+
return {
|
|
64
|
+
error: "invalid_ids_to_delete",
|
|
65
|
+
idsToDelete: [],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (!seenIds.has(normalizedId)) {
|
|
69
|
+
seenIds.add(normalizedId);
|
|
70
|
+
normalizedIds.push(normalizedId);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return { idsToDelete: normalizedIds };
|
|
74
|
+
};
|
|
75
|
+
const normalizeIdsToDelete = (idsToDelete) => {
|
|
76
|
+
return validateIdsToDelete(idsToDelete).idsToDelete;
|
|
77
|
+
};
|
|
78
|
+
const getValidMethodsForCollectionType = (collectionType) => {
|
|
79
|
+
if (collectionType === "pointQualities") {
|
|
80
|
+
return pointMethods;
|
|
81
|
+
}
|
|
82
|
+
else if (collectionType === "posts") {
|
|
83
|
+
return commonMethods;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
return postMethods;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const validateFraudActionRequest = ({ type, selectedMethod, collectionType, idsToDelete, }) => {
|
|
90
|
+
if (!validActionTypes.has(type)) {
|
|
91
|
+
return {
|
|
92
|
+
error: "invalid_fraud_action_type",
|
|
93
|
+
idsToDelete: [],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (!validCollectionTypes.has(collectionType)) {
|
|
97
|
+
return {
|
|
98
|
+
error: "invalid_fraud_collection_type",
|
|
99
|
+
idsToDelete: [],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
const validMethods = getValidMethodsForCollectionType(collectionType);
|
|
103
|
+
if (!validMethods.has(selectedMethod)) {
|
|
104
|
+
return {
|
|
105
|
+
error: "invalid_fraud_detection_method",
|
|
106
|
+
idsToDelete: [],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
const idsValidation = validateIdsToDelete(idsToDelete);
|
|
110
|
+
const normalizedIdsToDelete = idsValidation.idsToDelete;
|
|
111
|
+
if (idsValidation.error) {
|
|
112
|
+
return idsValidation;
|
|
113
|
+
}
|
|
114
|
+
if ((type === "delete-one-item" || type === "delete-items") &&
|
|
115
|
+
normalizedIdsToDelete.length === 0) {
|
|
116
|
+
return {
|
|
117
|
+
error: "delete_requires_ids",
|
|
118
|
+
idsToDelete: normalizedIdsToDelete,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (type === "delete-one-item" && normalizedIdsToDelete.length !== 1) {
|
|
122
|
+
return {
|
|
123
|
+
error: "single_delete_requires_one_id",
|
|
124
|
+
idsToDelete: normalizedIdsToDelete,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
if (selectedMethod === "byMissingBrowserFingerprint" &&
|
|
128
|
+
(type === "delete-items" || normalizedIdsToDelete.length > 1)) {
|
|
129
|
+
return {
|
|
130
|
+
error: "bulk_delete_missing_fingerprint_disabled",
|
|
131
|
+
idsToDelete: normalizedIdsToDelete,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
idsToDelete: normalizedIdsToDelete,
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
module.exports = {
|
|
139
|
+
MAX_FRAUD_IDS_TO_DELETE,
|
|
140
|
+
normalizeIdsToDelete,
|
|
141
|
+
validateFraudActionRequest,
|
|
142
|
+
validateIdsToDelete,
|
|
143
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const MAX_FRAUD_IDS_TO_DELETE: 1000;
|
|
2
|
+
export function normalizeIdsToDelete(idsToDelete: any): number[] | never[];
|
|
3
|
+
export function validateFraudActionRequest({ type, selectedMethod, collectionType, idsToDelete, }: {
|
|
4
|
+
type: any;
|
|
5
|
+
selectedMethod: any;
|
|
6
|
+
collectionType: any;
|
|
7
|
+
idsToDelete: any;
|
|
8
|
+
}): {
|
|
9
|
+
error: string;
|
|
10
|
+
idsToDelete: number[] | never[];
|
|
11
|
+
} | {
|
|
12
|
+
idsToDelete: number[] | never[];
|
|
13
|
+
error?: undefined;
|
|
14
|
+
};
|
|
15
|
+
export function validateIdsToDelete(idsToDelete: any): {
|
|
16
|
+
error: string;
|
|
17
|
+
idsToDelete: never[];
|
|
18
|
+
} | {
|
|
19
|
+
idsToDelete: number[];
|
|
20
|
+
error?: undefined;
|
|
21
|
+
};
|
|
@@ -4,9 +4,11 @@ const models = require("../../../../models/index.cjs");
|
|
|
4
4
|
const i18n = require('../../../utils/i18n.cjs');
|
|
5
5
|
const deepEqual = require('deep-equal');
|
|
6
6
|
const log = require("../../../../utils/logger.cjs");
|
|
7
|
-
const FraudGetEndorsements = require("./FraudGetEndorsements");
|
|
8
|
-
const FraudGetPointQualities = require("./FraudGetPointQualities");
|
|
9
|
-
const FraudGetRatings = require("./FraudGetRatings");
|
|
7
|
+
const FraudGetEndorsements = require("./FraudGetEndorsements.cjs");
|
|
8
|
+
const FraudGetPointQualities = require("./FraudGetPointQualities.cjs");
|
|
9
|
+
const FraudGetRatings = require("./FraudGetRatings.cjs");
|
|
10
|
+
const FraudGetPoints = require("./FraudGetPoints.cjs");
|
|
11
|
+
const FraudGetPosts = require("./FraudGetPosts.cjs");
|
|
10
12
|
const queue = require("../../../workers/queue.cjs");
|
|
11
13
|
const Backend = require("i18next-fs-backend");
|
|
12
14
|
const path = require("path");
|
|
@@ -15,8 +17,17 @@ class FraudScannerNotifier {
|
|
|
15
17
|
constructor() {
|
|
16
18
|
this.currentCommunity = null;
|
|
17
19
|
this.uniqueCollectionItemsIds = {};
|
|
18
|
-
this.collectionsToScan = ['endorsements', 'ratings', 'pointQualities'];
|
|
19
|
-
this.scannerModels = [
|
|
20
|
+
this.collectionsToScan = ['endorsements', 'ratings', 'pointQualities', 'points', 'posts'];
|
|
21
|
+
this.scannerModels = [
|
|
22
|
+
FraudGetEndorsements,
|
|
23
|
+
FraudGetRatings,
|
|
24
|
+
FraudGetPointQualities,
|
|
25
|
+
FraudGetPoints,
|
|
26
|
+
FraudGetPosts
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
resetCounts() {
|
|
30
|
+
this.uniqueCollectionItemsIds = {};
|
|
20
31
|
}
|
|
21
32
|
getCommunityURL() {
|
|
22
33
|
if (this.currentCommunity && this.currentCommunity.Domain && this.currentCommunity.Domain.domain_name) {
|
|
@@ -134,7 +145,7 @@ class FraudScannerNotifier {
|
|
|
134
145
|
}
|
|
135
146
|
getContainerOldCount(collectionType) {
|
|
136
147
|
let foundCollection;
|
|
137
|
-
if (this.currentCommunity.data.lastFraudScanResults) {
|
|
148
|
+
if (this.currentCommunity.data && this.currentCommunity.data.lastFraudScanResults) {
|
|
138
149
|
for (let i = 0; i < this.currentCommunity.data.lastFraudScanResults.length; i++) {
|
|
139
150
|
if (this.currentCommunity.data.lastFraudScanResults[i].collectionType &&
|
|
140
151
|
this.currentCommunity.data.lastFraudScanResults[i].collectionType === collectionType) {
|
|
@@ -187,7 +198,7 @@ class FraudScannerNotifier {
|
|
|
187
198
|
if (this.collectionsToScan[c] === "pointQualities") {
|
|
188
199
|
methodsToScan = methodsToScan.concat(['byIpFingerprintPointId', 'byIpUserAgentPointId']);
|
|
189
200
|
}
|
|
190
|
-
else {
|
|
201
|
+
else if (this.collectionsToScan[c] !== "posts") {
|
|
191
202
|
methodsToScan = methodsToScan.concat(['byIpFingerprintPostId', 'byIpUserAgentPostId']);
|
|
192
203
|
}
|
|
193
204
|
for (let m = 0; m < methodsToScan.length; m++) {
|
|
@@ -230,6 +241,7 @@ class FraudScannerNotifier {
|
|
|
230
241
|
for (let i = 0; i < communities.length; i++) {
|
|
231
242
|
log.info("Processing community: " + communities[i].name);
|
|
232
243
|
this.currentCommunity = communities[i];
|
|
244
|
+
this.resetCounts();
|
|
233
245
|
try {
|
|
234
246
|
await this.scan();
|
|
235
247
|
await this.notify();
|
|
@@ -249,32 +261,44 @@ class FraudScannerNotifier {
|
|
|
249
261
|
});
|
|
250
262
|
}
|
|
251
263
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
'
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}, function (err, t) {
|
|
268
|
-
(async () => {
|
|
269
|
-
try {
|
|
270
|
-
const scanner = new FraudScannerNotifier();
|
|
271
|
-
await scanner.scanAndNotify();
|
|
272
|
-
log.info("Fraud Scanning Complete");
|
|
273
|
-
process.exit();
|
|
274
|
-
}
|
|
275
|
-
catch (error) {
|
|
276
|
-
log.error(error);
|
|
277
|
-
process.exit();
|
|
264
|
+
const runFraudScannerNotifier = () => {
|
|
265
|
+
i18n
|
|
266
|
+
.use(Backend)
|
|
267
|
+
.init({
|
|
268
|
+
preload: ['en', 'fr', 'sk', 'bg', 'cs', 'it', 'da', 'kl', 'es', 'sv', 'sq', 'uz', 'uk', 'ca', 'hr', 'ro', 'ru',
|
|
269
|
+
'ro_md', 'pt_br', 'hu', 'tr', 'is', 'nl', 'no', 'pl', 'zh_tw', 'ky'],
|
|
270
|
+
fallbackLng: 'en',
|
|
271
|
+
// this is the defaults
|
|
272
|
+
backend: {
|
|
273
|
+
// path where resources get loaded from
|
|
274
|
+
loadPath: localesPath + '/{{lng}}/translation.json',
|
|
275
|
+
// path to post missing resources
|
|
276
|
+
addPath: localesPath + '/{{lng}}/translation.missing.json',
|
|
277
|
+
// jsonIndent to use when storing json files
|
|
278
|
+
jsonIndent: 2
|
|
278
279
|
}
|
|
279
|
-
}
|
|
280
|
-
|
|
280
|
+
}, function (err, t) {
|
|
281
|
+
(async () => {
|
|
282
|
+
try {
|
|
283
|
+
if (err) {
|
|
284
|
+
throw err;
|
|
285
|
+
}
|
|
286
|
+
const scanner = new FraudScannerNotifier();
|
|
287
|
+
await scanner.scanAndNotify();
|
|
288
|
+
log.info("Fraud Scanning Complete");
|
|
289
|
+
process.exit(0);
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
log.error(error);
|
|
293
|
+
process.exit(1);
|
|
294
|
+
}
|
|
295
|
+
})();
|
|
296
|
+
});
|
|
297
|
+
};
|
|
298
|
+
if (require.main === module) {
|
|
299
|
+
runFraudScannerNotifier();
|
|
300
|
+
}
|
|
301
|
+
module.exports = {
|
|
302
|
+
FraudScannerNotifier,
|
|
303
|
+
runFraudScannerNotifier
|
|
304
|
+
};
|