@yrpri/api 9.0.231 → 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.
Files changed (68) hide show
  1. package/controllers/allOurIdeas.js +1 -1
  2. package/controllers/communities.cjs +282 -91
  3. package/controllers/domains.cjs +54 -8
  4. package/controllers/groups.cjs +51 -6
  5. package/controllers/points.cjs +4 -9
  6. package/controllers/posts.cjs +7 -9
  7. package/controllers/ratings.cjs +3 -6
  8. package/models/point.cjs +31 -3
  9. package/models/post.cjs +2 -3
  10. package/package.json +2 -2
  11. package/services/engine/allOurIdeas/aiHelper.d.ts +7 -4
  12. package/services/engine/allOurIdeas/aiHelper.js +34 -19
  13. package/services/engine/allOurIdeas/explainAnswersAssistant.d.ts +1 -1
  14. package/services/engine/allOurIdeas/explainAnswersAssistant.js +3 -9
  15. package/services/engine/moderation/fraud/CreateFraudAuditReport.cjs +35 -11
  16. package/services/engine/moderation/fraud/CreateFraudAuditReport.d.cts +21 -0
  17. package/services/engine/moderation/fraud/FraudBase.cjs +38 -18
  18. package/services/engine/moderation/fraud/FraudBase.d.cts +2 -0
  19. package/services/engine/moderation/fraud/FraudDeleteBase.cjs +48 -29
  20. package/services/engine/moderation/fraud/FraudDeleteBase.d.cts +8 -6
  21. package/services/engine/moderation/fraud/FraudDeleteEndorsements.cjs +5 -4
  22. package/services/engine/moderation/fraud/FraudDeleteEndorsements.d.cts +2 -2
  23. package/services/engine/moderation/fraud/FraudDeletePointQualities.cjs +3 -2
  24. package/services/engine/moderation/fraud/FraudDeletePointQualities.d.cts +1 -1
  25. package/services/engine/moderation/fraud/FraudDeletePoints.cjs +3 -2
  26. package/services/engine/moderation/fraud/FraudDeletePoints.d.cts +1 -1
  27. package/services/engine/moderation/fraud/FraudDeletePosts.cjs +3 -2
  28. package/services/engine/moderation/fraud/FraudDeleteRatings.cjs +61 -4
  29. package/services/engine/moderation/fraud/FraudGetBase.cjs +44 -20
  30. package/services/engine/moderation/fraud/FraudGetBase.d.cts +5 -0
  31. package/services/engine/moderation/fraud/FraudGetEndorsements.cjs +4 -13
  32. package/services/engine/moderation/fraud/FraudGetEndorsements.d.cts +1 -1
  33. package/services/engine/moderation/fraud/FraudGetPointQualities.cjs +3 -0
  34. package/services/engine/moderation/fraud/FraudGetPointQualities.d.cts +1 -1
  35. package/services/engine/moderation/fraud/FraudGetPoints.cjs +3 -0
  36. package/services/engine/moderation/fraud/FraudGetPoints.d.cts +1 -1
  37. package/services/engine/moderation/fraud/FraudGetPosts.cjs +17 -16
  38. package/services/engine/moderation/fraud/FraudGetPosts.d.cts +3 -3
  39. package/services/engine/moderation/fraud/FraudGetRatings.cjs +62 -30
  40. package/services/engine/moderation/fraud/FraudGetRatings.d.cts +4 -1
  41. package/services/engine/moderation/fraud/FraudRequestValidation.cjs +143 -0
  42. package/services/engine/moderation/fraud/FraudRequestValidation.d.cts +21 -0
  43. package/services/engine/moderation/fraud/FraudScannerNotifier.cjs +59 -35
  44. package/services/engine/moderation/fraud/FraudScannerNotifier.d.cts +20 -1
  45. package/services/llms/baseChatBot.d.ts +2 -0
  46. package/services/llms/baseChatBot.js +25 -9
  47. package/services/llms/imageGeneration/chatGptImageGenerator.d.ts +2 -2
  48. package/services/llms/imageGeneration/chatGptImageGenerator.js +13 -10
  49. package/services/llms/imageGeneration/collectionImageGenerator.js +31 -13
  50. package/services/llms/imageGeneration/dalleImageGenerator.d.ts +2 -2
  51. package/services/llms/imageGeneration/dalleImageGenerator.js +28 -16
  52. package/services/llms/imageGeneration/fluxImageGenerator.d.ts +2 -2
  53. package/services/llms/imageGeneration/fluxImageGenerator.js +9 -3
  54. package/services/llms/imageGeneration/iImageGenerator.d.ts +8 -1
  55. package/services/llms/imageGeneration/imageModelConfig.cjs +319 -0
  56. package/services/llms/imageGeneration/imageModelConfig.d.cts +79 -0
  57. package/services/llms/imageGeneration/imagenImageGenerator.d.ts +2 -3
  58. package/services/llms/imageGeneration/imagenImageGenerator.js +10 -10
  59. package/tests/fraudManagement.test.cjs +470 -0
  60. package/tests/fraudManagement.test.d.cts +1 -0
  61. package/tests/imageModelConfig.test.cjs +144 -0
  62. package/tests/imageModelConfig.test.d.cts +1 -0
  63. package/utils/ai_image_generation_guard.cjs +268 -0
  64. package/utils/ai_image_generation_guard.d.cts +34 -0
  65. package/utils/fingerprint_data.cjs +32 -0
  66. package/utils/fingerprint_data.d.cts +6 -0
  67. package/utils/recount_utils.cjs +53 -37
  68. package/utils/recount_utils.d.cts +7 -7
@@ -2,6 +2,7 @@
2
2
  const _ = require("lodash");
3
3
  const moment = require("moment");
4
4
  const log = require("../../../../utils/logger.cjs");
5
+ const { normalizeFingerprintValue, } = require("../../../../utils/fingerprint_data.cjs");
5
6
  class FraudBase {
6
7
  constructor(workPackage) {
7
8
  this.workPackage = workPackage;
@@ -38,6 +39,21 @@ class FraudBase {
38
39
  return -item.count;
39
40
  });
40
41
  }
42
+ isDebugFraudDetectionCountAll() {
43
+ return process.env.DEBUG_FRAUD_DETECTION_COUNT_ALL === "true" &&
44
+ this.workPackage.type === "get-items";
45
+ }
46
+ getDebugTopItems(topItems) {
47
+ _.forEach(topItems, topItem => {
48
+ _.forEach(topItem.items, item => {
49
+ item.dataValues = item.dataValues || {};
50
+ if (!item.dataValues.confidenceScore) {
51
+ item.dataValues.confidenceScore = "0%";
52
+ }
53
+ });
54
+ });
55
+ return topItems;
56
+ }
41
57
  getTopDataByIp() {
42
58
  return this.getTopItems(this.groupTopDataByIp(), "byIpAddress");
43
59
  }
@@ -141,7 +157,7 @@ class FraudBase {
141
157
  for (let i = 0; i < items.length; i++) {
142
158
  const item = items[i];
143
159
  const hasData = item.data ? Object.keys(item.data).length === 0 : false;
144
- if (hasData && !item.data.browserId && moment(item.created_at) > this.getStartFingerprintMoment()) {
160
+ if (hasData && !normalizeFingerprintValue(item.data.browserId) && moment(item.created_at) > this.getStartFingerprintMoment()) {
145
161
  if (["posts", "points"].indexOf(this.workPackage.collectionType) > -1) {
146
162
  item.dataValues.confidenceScore = `50%`;
147
163
  }
@@ -180,50 +196,54 @@ class FraudBase {
180
196
  groupTopDataByIpFingerprintPostId() {
181
197
  const filtered = _.filter(this.items, (item) => {
182
198
  return item.data &&
183
- item.data.browserFingerprint &&
184
- item.data.browserFingerprint !== "undefined";
199
+ normalizeFingerprintValue(item.data.browserFingerprint);
185
200
  });
186
201
  return _.groupBy(filtered, (item) => {
187
- return item.ip_address + ":" + item.post_id + ":" + item.data.browserFingerprint;
202
+ return item.ip_address + ":" + item.post_id + ":" + normalizeFingerprintValue(item.data.browserFingerprint);
188
203
  });
189
204
  }
190
205
  groupTopDataByIpFingerprintPointId() {
191
206
  const filtered = _.filter(this.items, (item) => {
192
207
  return item.data &&
193
- item.data.browserFingerprint &&
194
- item.data.browserFingerprint !== "undefined";
208
+ normalizeFingerprintValue(item.data.browserFingerprint);
195
209
  });
196
210
  return _.groupBy(filtered, (item) => {
197
- return item.ip_address + ":" + item.point_id + ":" + item.data.browserFingerprint;
211
+ return item.ip_address + ":" + item.point_id + ":" + normalizeFingerprintValue(item.data.browserFingerprint);
198
212
  });
199
213
  }
200
214
  groupTopDataByIpFingerprint() {
201
215
  const filtered = _.filter(this.items, (item) => {
202
216
  return item.data &&
203
- item.data.browserFingerprint &&
204
- item.data.browserFingerprint !== "undefined";
217
+ normalizeFingerprintValue(item.data.browserFingerprint);
205
218
  });
206
219
  return _.groupBy(filtered, (item) => {
207
- return item.ip_address + ":" + item.data.browserFingerprint;
220
+ return item.ip_address + ":" + normalizeFingerprintValue(item.data.browserFingerprint);
208
221
  });
209
222
  }
210
223
  groupTopDataByNoFingerprints() {
211
224
  const filtered = _.filter(this.items, item => {
212
- return item.data &&
213
- (!item.data.browserFingerprint ||
214
- !item.data.browserId) &&
215
- moment(item.created_at).valueOf() > this.getStartFingerprintMoment();
225
+ item.data = item.data || {};
226
+ const missingFingerprint = !normalizeFingerprintValue(item.data.browserFingerprint) ||
227
+ !normalizeFingerprintValue(item.data.browserId);
228
+ if (this.isDebugFraudDetectionCountAll()) {
229
+ return missingFingerprint;
230
+ }
231
+ else {
232
+ return missingFingerprint &&
233
+ moment(item.created_at).valueOf() > this.getStartFingerprintMoment();
234
+ }
216
235
  });
217
236
  const scoreHundred = (["posts", "points"].indexOf(this.workPackage.collectionType) > -1) ? "50%" : "100%";
218
237
  const scoreNinety = (["posts", "points"].indexOf(this.workPackage.collectionType) > -1) ? "45%" : "90%";
219
238
  const scoreSeventy = (["posts", "points"].indexOf(this.workPackage.collectionType) > -1) ? "60%" : "70%";
220
239
  _.forEach(filtered, item => {
221
- if (!item.data.browserFingerprint &&
222
- !item.data.browserId) {
240
+ const browserFingerprint = normalizeFingerprintValue(item.data.browserFingerprint);
241
+ const browserId = normalizeFingerprintValue(item.data.browserId);
242
+ if (!browserFingerprint && !browserId) {
223
243
  item.dataValues.confidenceScore = scoreHundred;
224
244
  item.dataValues.key = "bothUndefined";
225
245
  }
226
- else if (!item.data.browserId) {
246
+ else if (!browserId) {
227
247
  item.dataValues.confidenceScore = scoreNinety;
228
248
  item.dataValues.key = "browserIdUndefined";
229
249
  }
@@ -233,7 +253,7 @@ class FraudBase {
233
253
  }
234
254
  });
235
255
  return _.groupBy(filtered, item => {
236
- return item.key;
256
+ return item.dataValues.key;
237
257
  });
238
258
  }
239
259
  }
@@ -9,6 +9,8 @@ declare class FraudBase {
9
9
  getAllItems(): Promise<null>;
10
10
  getPostIdsFromItems(topItems: any): any[];
11
11
  setupTopItems(items: any): any[];
12
+ isDebugFraudDetectionCountAll(): boolean;
13
+ getDebugTopItems(topItems: any): any;
12
14
  getTopDataByIp(): null;
13
15
  getTopDataByIpUserAgentPostId(): null;
14
16
  getTopDataByIpUserAgentPointId(): null;
@@ -12,6 +12,7 @@ class FraudDeleteBase extends FraudBase {
12
12
  super(workPackage);
13
13
  this.postsToRecount = [];
14
14
  this.pointsToRecount = [];
15
+ this.deletedItemIds = [];
15
16
  this.job = null;
16
17
  }
17
18
  sliceIntoChunks(arr, chunkSize) {
@@ -30,18 +31,22 @@ class FraudDeleteBase extends FraudBase {
30
31
  async destroyChunkItems(chunks) {
31
32
  log.error("Should be implemented in a sub class");
32
33
  }
34
+ getUserEmail(item) {
35
+ return item.User && item.User.email ? item.User.email : "";
36
+ }
33
37
  getAllItemsExceptOne(items) {
34
38
  if (items.length === 1 && this.getAllowedSingleDelete()) {
35
39
  return items;
36
40
  }
37
41
  else {
38
42
  const sortedItems = _.sortBy(items, function (item) {
39
- return item.date;
43
+ return moment(item.created_at || item.date).valueOf();
40
44
  });
41
45
  const finalItems = [];
42
46
  let foundEmail = false;
43
47
  for (let i = 0; i < sortedItems.length; i++) {
44
- if (!foundEmail && sortedItems[i].User.email && sortedItems[i].User.email.indexOf("_anonymous@citizens.i") === -1) {
48
+ const userEmail = this.getUserEmail(sortedItems[i]);
49
+ if (!foundEmail && userEmail && userEmail.indexOf("_anonymous@citizens.i") === -1) {
45
50
  foundEmail = true;
46
51
  }
47
52
  else {
@@ -54,27 +59,38 @@ class FraudDeleteBase extends FraudBase {
54
59
  return finalItems;
55
60
  }
56
61
  }
57
- async createAuditLog() {
62
+ async createAuditLog(transaction) {
58
63
  return await new Promise(async (resolve, reject) => {
59
64
  try {
60
65
  const user = await models.User.findOne({
61
66
  where: {
62
67
  id: this.workPackage.userId,
63
68
  },
64
- attributes: ['name']
69
+ attributes: ['name'],
70
+ transaction
65
71
  });
72
+ const userName = user && user.name ? user.name : "Unknown";
73
+ const deleteData = {
74
+ ...this.job.internal_data,
75
+ requestedIdsToDelete: this.job.internal_data.idsToDelete,
76
+ idsToDelete: this.deletedItemIds,
77
+ };
66
78
  const fraudAuditLog = await models.GeneralDataStore.create({ data: {
67
79
  date: new Date(),
68
- userName: user.name,
80
+ userName,
69
81
  workPackage: this.workPackage,
70
- deleteData: this.job.internal_data
71
- } });
82
+ deleteData
83
+ } }, { transaction });
72
84
  const community = await models.Community.findOne({
73
85
  where: {
74
86
  id: this.workPackage.communityId
75
87
  },
76
- attributes: ['data', 'id']
88
+ attributes: ['data', 'id'],
89
+ transaction
77
90
  });
91
+ if (!community) {
92
+ throw new Error("Community not found for fraud audit log");
93
+ }
78
94
  if (!community.data) {
79
95
  community.data = {};
80
96
  }
@@ -84,10 +100,10 @@ class FraudDeleteBase extends FraudBase {
84
100
  community.data.fraudDeletionsAuditLogs.push({
85
101
  logId: fraudAuditLog.id,
86
102
  date: fraudAuditLog.data.date,
87
- userName: user.name
103
+ userName
88
104
  });
89
105
  community.changed('data', true);
90
- await community.save();
106
+ await community.save({ transaction });
91
107
  resolve();
92
108
  }
93
109
  catch (error) {
@@ -109,13 +125,13 @@ class FraudDeleteBase extends FraudBase {
109
125
  getTopItems(items, type) {
110
126
  return this.setupTopItems(items);
111
127
  }
112
- async destroyAllItems(chunks) {
128
+ async destroyAllItems(chunks, transaction) {
113
129
  return await new Promise(async (resolve, reject) => {
114
130
  try {
115
131
  const progressAdvanceForChunk = 75 / 10;
116
132
  let progress = 25;
117
133
  for (let c = 0; c < chunks.length; c++) {
118
- await this.destroyChunkItems(chunks[c]);
134
+ await this.destroyChunkItems(chunks[c], transaction);
119
135
  progress = Math.round(Math.min(80, progress += progressAdvanceForChunk));
120
136
  await models.AcBackgroundJob.updateProgressAsync(this.workPackage.jobId, progress);
121
137
  }
@@ -126,7 +142,7 @@ class FraudDeleteBase extends FraudBase {
126
142
  }
127
143
  });
128
144
  }
129
- async deleteData() {
145
+ async deleteData(transaction) {
130
146
  return await new Promise(async (resolve, reject) => {
131
147
  try {
132
148
  const keys = Object.keys(this.dataToProcess);
@@ -134,7 +150,8 @@ class FraudDeleteBase extends FraudBase {
134
150
  for (let c = 0; c < keys.length; c++) {
135
151
  itemsToDelete = itemsToDelete.concat(this.getAllItemsExceptOne(this.dataToProcess[keys[c]].items));
136
152
  }
137
- await this.destroyAllItems(this.sliceIntoChunks(itemsToDelete, 100));
153
+ this.deletedItemIds = itemsToDelete.map(item => item.id);
154
+ await this.destroyAllItems(this.sliceIntoChunks(itemsToDelete, 100), transaction);
138
155
  resolve();
139
156
  }
140
157
  catch (error) {
@@ -142,7 +159,7 @@ class FraudDeleteBase extends FraudBase {
142
159
  }
143
160
  });
144
161
  }
145
- async recountPosts() {
162
+ async recountPosts(transaction) {
146
163
  return await new Promise(async (resolve, reject) => {
147
164
  recountPosts(this.postsToRecount, error => {
148
165
  if (error) {
@@ -151,10 +168,10 @@ class FraudDeleteBase extends FraudBase {
151
168
  else {
152
169
  resolve();
153
170
  }
154
- });
171
+ }, transaction);
155
172
  });
156
173
  }
157
- async recountPoints() {
174
+ async recountPoints(transaction) {
158
175
  return await new Promise(async (resolve, reject) => {
159
176
  recountPoints(this.pointsToRecount, error => {
160
177
  if (error) {
@@ -163,10 +180,10 @@ class FraudDeleteBase extends FraudBase {
163
180
  else {
164
181
  resolve();
165
182
  }
166
- });
183
+ }, transaction);
167
184
  });
168
185
  }
169
- async recountCommunity() {
186
+ async recountCommunity(transaction) {
170
187
  return await new Promise(async (resolve, reject) => {
171
188
  recountCommunity(this.workPackage.communityId, error => {
172
189
  if (error) {
@@ -175,7 +192,7 @@ class FraudDeleteBase extends FraudBase {
175
192
  else {
176
193
  resolve();
177
194
  }
178
- });
195
+ }, transaction);
179
196
  });
180
197
  }
181
198
  async deleteItems() {
@@ -189,15 +206,17 @@ class FraudDeleteBase extends FraudBase {
189
206
  });
190
207
  this.items = await this.getItemsById();
191
208
  this.setupDataToProcess();
192
- await this.deleteData();
193
- await this.createAuditLog();
194
- if (this.postsToRecount.length > 0) {
195
- await this.recountPosts();
196
- }
197
- if (this.pointsToRecount.length > 0) {
198
- await this.recountPoints();
199
- }
200
- await this.recountCommunity();
209
+ await models.sequelize.transaction(async (transaction) => {
210
+ await this.deleteData(transaction);
211
+ await this.createAuditLog(transaction);
212
+ if (this.postsToRecount.length > 0) {
213
+ await this.recountPosts(transaction);
214
+ }
215
+ if (this.pointsToRecount.length > 0) {
216
+ await this.recountPoints(transaction);
217
+ }
218
+ await this.recountCommunity(transaction);
219
+ });
201
220
  await models.AcBackgroundJob.updateProgressAsync(this.workPackage.jobId, 100);
202
221
  resolve();
203
222
  }
@@ -2,20 +2,22 @@ export = FraudDeleteBase;
2
2
  declare class FraudDeleteBase extends FraudBase {
3
3
  postsToRecount: any[];
4
4
  pointsToRecount: any[];
5
+ deletedItemIds: any[];
5
6
  job: any;
6
7
  sliceIntoChunks(arr: any, chunkSize: any): any[];
7
8
  getItemsById(): Promise<null>;
8
9
  destroyChunkItems(chunks: any): Promise<void>;
10
+ getUserEmail(item: any): any;
9
11
  getAllItemsExceptOne(items: any): any;
10
- createAuditLog(): Promise<any>;
12
+ createAuditLog(transaction: any): Promise<any>;
11
13
  getAllowedSingleDelete(): boolean;
12
14
  getMomentInYourPriorities(): number;
13
15
  getTopItems(items: any, type: any): any[];
14
- destroyAllItems(chunks: any): Promise<any>;
15
- deleteData(): Promise<any>;
16
- recountPosts(): Promise<any>;
17
- recountPoints(): Promise<any>;
18
- recountCommunity(): Promise<any>;
16
+ destroyAllItems(chunks: any, transaction: any): Promise<any>;
17
+ deleteData(transaction: any): Promise<any>;
18
+ recountPosts(transaction: any): Promise<any>;
19
+ recountPoints(transaction: any): Promise<any>;
20
+ recountCommunity(transaction: any): Promise<any>;
19
21
  deleteItems(): Promise<any>;
20
22
  }
21
23
  import FraudBase = require("./FraudBase.cjs");
@@ -3,7 +3,7 @@ const _ = require("lodash");
3
3
  const FraudDeleteBase = require('./FraudDeleteBase.cjs');
4
4
  const models = require("../../../../models/index.cjs");
5
5
  class FraudDeleteEndorsements extends FraudDeleteBase {
6
- async destroyChunkItemsByModel(model, items) {
6
+ async destroyChunkItemsByModel(model, items, transaction) {
7
7
  return await new Promise(async (resolve, reject) => {
8
8
  const idsToDestroy = items.map(i => i.id);
9
9
  try {
@@ -37,7 +37,8 @@ class FraudDeleteEndorsements extends FraudDeleteBase {
37
37
  ]
38
38
  }
39
39
  ],
40
- attributes: ['id']
40
+ attributes: ['id'],
41
+ transaction
41
42
  });
42
43
  for (let i = 0; i < items.length; i++) {
43
44
  if (this.postsToRecount.indexOf(items[i].post_id) === -1) {
@@ -51,8 +52,8 @@ class FraudDeleteEndorsements extends FraudDeleteBase {
51
52
  }
52
53
  });
53
54
  }
54
- async destroyChunkItems(items) {
55
- return this.destroyChunkItemsByModel(models.Endorsement, items);
55
+ async destroyChunkItems(items, transaction) {
56
+ return this.destroyChunkItemsByModel(models.Endorsement, items, transaction);
56
57
  }
57
58
  async getModelItemsById(model, getGroup) {
58
59
  return await new Promise(async (resolve, reject) => {
@@ -1,7 +1,7 @@
1
1
  export = FraudDeleteEndorsements;
2
2
  declare class FraudDeleteEndorsements extends FraudDeleteBase {
3
- destroyChunkItemsByModel(model: any, items: any): Promise<any>;
4
- destroyChunkItems(items: any): Promise<any>;
3
+ destroyChunkItemsByModel(model: any, items: any, transaction: any): Promise<any>;
4
+ destroyChunkItems(items: any, transaction: any): Promise<any>;
5
5
  getModelItemsById(model: any, getGroup: any): Promise<any>;
6
6
  getItemsById(): Promise<any>;
7
7
  }
@@ -4,7 +4,7 @@ const FraudDeleteBase = require('./FraudDeleteBase.cjs');
4
4
  const models = require("../../../../models/index.cjs");
5
5
  //TODO: Change to native JS instead of lodash
6
6
  class FraudDeletePointQualities extends FraudDeleteBase {
7
- async destroyChunkItems(items) {
7
+ async destroyChunkItems(items, transaction) {
8
8
  return await new Promise(async (resolve, reject) => {
9
9
  const idsToDestroy = items.map(i => i.id);
10
10
  try {
@@ -44,7 +44,8 @@ class FraudDeletePointQualities extends FraudDeleteBase {
44
44
  ]
45
45
  },
46
46
  ],
47
- attributes: ['id']
47
+ attributes: ['id'],
48
+ transaction
48
49
  });
49
50
  for (let i = 0; i < items.length; i++) {
50
51
  if (this.pointsToRecount.indexOf(items[i].Point.id) === -1) {
@@ -1,6 +1,6 @@
1
1
  export = FraudDeletePointQualities;
2
2
  declare class FraudDeletePointQualities extends FraudDeleteBase {
3
- destroyChunkItems(items: any): Promise<any>;
3
+ destroyChunkItems(items: any, transaction: any): Promise<any>;
4
4
  getItemsById(): Promise<any>;
5
5
  }
6
6
  import FraudDeleteBase = require("./FraudDeleteBase.cjs");
@@ -3,7 +3,7 @@ const _ = require("lodash");
3
3
  const FraudDeleteBase = require('./FraudDeleteBase.cjs');
4
4
  const models = require("../../../../models/index.cjs");
5
5
  class FraudDeletePointQualities extends FraudDeleteBase {
6
- async destroyChunkItems(items) {
6
+ async destroyChunkItems(items, transaction) {
7
7
  return await new Promise(async (resolve, reject) => {
8
8
  const idsToDestroy = items.map(i => i.id);
9
9
  try {
@@ -37,7 +37,8 @@ class FraudDeletePointQualities extends FraudDeleteBase {
37
37
  ]
38
38
  }
39
39
  ],
40
- attributes: ['id']
40
+ attributes: ['id'],
41
+ transaction
41
42
  });
42
43
  for (let i = 0; i < items.length; i++) {
43
44
  if (this.postsToRecount.indexOf(items[i].Post.id) === -1) {
@@ -1,6 +1,6 @@
1
1
  export = FraudDeletePointQualities;
2
2
  declare class FraudDeletePointQualities extends FraudDeleteBase {
3
- destroyChunkItems(items: any): Promise<any>;
3
+ destroyChunkItems(items: any, transaction: any): Promise<any>;
4
4
  getItemsById(): Promise<any>;
5
5
  }
6
6
  import FraudDeleteBase = require("./FraudDeleteBase.cjs");
@@ -3,7 +3,7 @@ const _ = require("lodash");
3
3
  const FraudDeleteEndorsements = require('./FraudDeleteEndorsements.cjs');
4
4
  const models = require("../../../../models/index.cjs");
5
5
  class FraudDeletePosts extends FraudDeleteEndorsements {
6
- async destroyChunkItems(items) {
6
+ async destroyChunkItems(items, transaction) {
7
7
  return await new Promise(async (resolve, reject) => {
8
8
  const idsToDestroy = items.map(i => i.id);
9
9
  try {
@@ -31,7 +31,8 @@ class FraudDeletePosts extends FraudDeleteEndorsements {
31
31
  ]
32
32
  }
33
33
  ],
34
- attributes: ['id']
34
+ attributes: ['id'],
35
+ transaction
35
36
  });
36
37
  resolve();
37
38
  }
@@ -4,12 +4,69 @@ const FraudDeleteEndorsements = require('./FraudDeleteEndorsements.cjs');
4
4
  const models = require("../../../../models/index.cjs");
5
5
  //TODO: Change to native JS instead of lodash
6
6
  class FraudDeleteRatings extends FraudDeleteEndorsements {
7
- async destroyChunkItems(items) {
8
- return this.destroyChunkItemsByModel(models.Rating, items);
7
+ getAllItemsExceptOne(items) {
8
+ if (items.length === 1 && this.getAllowedSingleDelete()) {
9
+ return items;
10
+ }
11
+ const itemsByTypeIndex = _.groupBy(items, item => {
12
+ return item.type_index === undefined || item.type_index === null
13
+ ? "default"
14
+ : item.type_index;
15
+ });
16
+ let itemsToDelete = [];
17
+ _.each(itemsByTypeIndex, innerItems => {
18
+ itemsToDelete = itemsToDelete.concat(super.getAllItemsExceptOne(innerItems));
19
+ });
20
+ return itemsToDelete;
21
+ }
22
+ async destroyChunkItems(items, transaction) {
23
+ return this.destroyChunkItemsByModel(models.Rating, items, transaction);
9
24
  }
10
25
  async getItemsById() {
11
- const itemsContainer = await this.getModelItemsById(models.Rating);
12
- return itemsContainer.itemsToAnalyse;
26
+ return await new Promise(async (resolve, reject) => {
27
+ try {
28
+ const items = await models.Rating.findAll({
29
+ where: {
30
+ id: {
31
+ $in: this.job.internal_data.idsToDelete
32
+ }
33
+ },
34
+ attributes: ["id", "created_at", "value", "type_index", "post_id", "user_id", "user_agent", "ip_address", "data"],
35
+ include: [
36
+ {
37
+ model: models.User,
38
+ attributes: ['id', 'email'],
39
+ },
40
+ {
41
+ model: models.Post,
42
+ attributes: ['id', 'name'],
43
+ include: [
44
+ {
45
+ model: models.Group,
46
+ attributes: ['id'],
47
+ include: [
48
+ {
49
+ model: models.Community,
50
+ attributes: [],
51
+ where: {
52
+ id: this.workPackage.communityId
53
+ }
54
+ }
55
+ ]
56
+ }
57
+ ]
58
+ }
59
+ ]
60
+ });
61
+ const itemsToAnalyse = _.sortBy(items, function (item) {
62
+ return [item.post_id, item.type_index, item.user_agent];
63
+ });
64
+ resolve(itemsToAnalyse);
65
+ }
66
+ catch (error) {
67
+ reject(error);
68
+ }
69
+ });
13
70
  }
14
71
  }
15
72
  module.exports = FraudDeleteRatings;
@@ -26,6 +26,21 @@ class FraudGetBase extends FraudBase {
26
26
  }
27
27
  });
28
28
  }
29
+ getUserEmail(item) {
30
+ return item.User && item.User.email ? item.User.email : "";
31
+ }
32
+ getUserName(item) {
33
+ return item.User && item.User.name ? item.User.name : "";
34
+ }
35
+ getPostName(item) {
36
+ return item.Post && item.Post.name ? item.Post.name : "";
37
+ }
38
+ getPointQualityPostName(item) {
39
+ return item.Point && item.Point.Post && item.Point.Post.name ? item.Point.Post.name : "";
40
+ }
41
+ getItemName(item) {
42
+ return item && item.name ? item.name : "";
43
+ }
29
44
  customCompress() {
30
45
  const flatData = [];
31
46
  _.forEach(this.dataToProcess, item => {
@@ -71,43 +86,52 @@ class FraudGetBase extends FraudBase {
71
86
  cDoneUserAgents[item.user_agent] = true;
72
87
  outData.cUserAgents.push(item.user_agent);
73
88
  }
74
- if (!cDoneEmails[item.User.email]) {
75
- cDoneEmails[item.User.email] = true;
76
- outData.cEmails.push(item.User.email);
89
+ const userEmail = this.getUserEmail(item);
90
+ const userName = this.getUserName(item);
91
+ item.User = item.User || {};
92
+ if (!cDoneEmails[userEmail]) {
93
+ cDoneEmails[userEmail] = true;
94
+ outData.cEmails.push(userEmail);
77
95
  }
78
- if (!cDoneNames[item.User.name]) {
79
- cDoneNames[item.User.name] = true;
80
- outData.cNames.push(item.User.name);
96
+ if (!cDoneNames[userName]) {
97
+ cDoneNames[userName] = true;
98
+ outData.cNames.push(userName);
81
99
  }
82
100
  if (this.workPackage.collectionType === "endorsements" ||
83
101
  this.workPackage.collectionType === "ratings" ||
84
102
  this.workPackage.collectionType === "points") {
85
- if (!cDonePostNames[item.Post.name]) {
86
- cDonePostNames[item.Post.name] = true;
87
- outData.cPostNames.push(item.Post.name);
103
+ const postName = this.getPostName(item);
104
+ item.Post = item.Post || {};
105
+ if (!cDonePostNames[postName]) {
106
+ cDonePostNames[postName] = true;
107
+ outData.cPostNames.push(postName);
88
108
  }
89
- item.Post.name = outData.cPostNames.indexOf(item.Post.name);
109
+ item.Post.name = outData.cPostNames.indexOf(postName);
90
110
  }
91
111
  if (this.workPackage.collectionType === "posts") {
92
- if (!cDonePostNames[item.name]) {
93
- cDonePostNames[item.name] = true;
94
- outData.cPostNames.push(item.name);
112
+ const postName = this.getItemName(item);
113
+ if (!cDonePostNames[postName]) {
114
+ cDonePostNames[postName] = true;
115
+ outData.cPostNames.push(postName);
95
116
  }
96
- item.name = outData.cPostNames.indexOf(item.name);
117
+ item.name = outData.cPostNames.indexOf(postName);
97
118
  }
98
119
  if (this.workPackage.collectionType === "pointQualities") {
99
- if (!cDonePostNames[item.Point.Post.name]) {
100
- cDonePostNames[item.Point.Post.name] = true;
101
- outData.cPostNames.push(item.Point.Post.name);
120
+ const postName = this.getPointQualityPostName(item);
121
+ item.Point = item.Point || {};
122
+ item.Point.Post = item.Point.Post || {};
123
+ if (!cDonePostNames[postName]) {
124
+ cDonePostNames[postName] = true;
125
+ outData.cPostNames.push(postName);
102
126
  }
103
- item.Point.Post.name = outData.cPostNames.indexOf(item.Point.Post.name);
127
+ item.Point.Post.name = outData.cPostNames.indexOf(postName);
104
128
  }
105
129
  item.dataValues.backgroundColor = outData.cBackgroundColors.indexOf(item.dataValues.backgroundColor);
106
130
  item.dataValues.confidenceScoreSort = parseInt(item.dataValues.confidenceScore.replace("%", ''));
107
131
  item.ip_address = outData.cIpAddresses.indexOf(item.ip_address);
108
132
  item.user_agent = outData.cUserAgents.indexOf(item.user_agent);
109
- item.User.email = outData.cEmails.indexOf(item.User.email);
110
- item.User.name = outData.cEmails.indexOf(item.User.name);
133
+ item.User.email = outData.cEmails.indexOf(userEmail);
134
+ item.User.name = outData.cNames.indexOf(userName);
111
135
  outData.items.push(item);
112
136
  });
113
137
  this.dataToProcess = outData;
@@ -2,6 +2,11 @@ export = FraudGetBase;
2
2
  declare class FraudGetBase extends FraudBase {
3
3
  formatTime(): void;
4
4
  setBackgroundColorsFromKey(): void;
5
+ getUserEmail(item: any): any;
6
+ getUserName(item: any): any;
7
+ getPostName(item: any): any;
8
+ getPointQualityPostName(item: any): any;
9
+ getItemName(item: any): any;
5
10
  customCompress(): void;
6
11
  processAndGetFraudItems(): Promise<any>;
7
12
  }