fake-data-npm 1.0.0
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/README.md +83 -0
- package/datasets.json +1 -0
- package/dist/datasets.json +1 -0
- package/dist/index.d.ts +93 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +756 -0
- package/index.ts +963 -0
- package/package.json +23 -0
- package/tsconfig.json +16 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,756 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import datasets from './datasets.json';
|
|
4
|
+
// helper utilities
|
|
5
|
+
/**
|
|
6
|
+
* Return a random element from an array.
|
|
7
|
+
* @template T
|
|
8
|
+
* @param {T[]} arr - array to pick from
|
|
9
|
+
* @returns {T} random element
|
|
10
|
+
*/
|
|
11
|
+
export function randomItem(arr) {
|
|
12
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Generate a random phone number string with the provided country code.
|
|
16
|
+
* @param {string} countryCode
|
|
17
|
+
* @returns {string}
|
|
18
|
+
*/
|
|
19
|
+
export function generatePhoneNumber(countryCode) {
|
|
20
|
+
const numeroAleatoire = Math.floor(Math.random() * 1000000000)
|
|
21
|
+
.toString()
|
|
22
|
+
.padStart(9, '0');
|
|
23
|
+
return `${countryCode}${numeroAleatoire}`;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Generate a social media handle variant based on name, surname and base pseudo.
|
|
27
|
+
* Supported platforms include twitter, instagram, facebook, etc.
|
|
28
|
+
* @param {string} name
|
|
29
|
+
* @param {string} surname
|
|
30
|
+
* @param {string} pseudo
|
|
31
|
+
* @param {string} mediaSocial
|
|
32
|
+
* @returns {string}
|
|
33
|
+
*/
|
|
34
|
+
export function generateSocialHandleVariant(name, surname, pseudo, mediaSocial) {
|
|
35
|
+
if (!(name && surname && pseudo && mediaSocial)) {
|
|
36
|
+
throw new Error('Missing parameters');
|
|
37
|
+
}
|
|
38
|
+
const pseudoEnMinuscules = pseudo.toLowerCase();
|
|
39
|
+
const nameEnMinuscules = name.toLowerCase();
|
|
40
|
+
const surnameEnMinuscules = surname.toLowerCase();
|
|
41
|
+
const numeroRandom = Math.floor(Math.random() * 100);
|
|
42
|
+
const chiffresSuite = generateRandomDigits(5);
|
|
43
|
+
const variations = {
|
|
44
|
+
instagram: [
|
|
45
|
+
`${pseudo}_official`,
|
|
46
|
+
`${pseudo}_real`,
|
|
47
|
+
`${pseudo}_original`,
|
|
48
|
+
`${pseudo}_insta`,
|
|
49
|
+
`${pseudo}_gram`,
|
|
50
|
+
`${pseudo}_ig`,
|
|
51
|
+
],
|
|
52
|
+
facebook: [
|
|
53
|
+
`${name}.${surname}.${numeroRandom}`,
|
|
54
|
+
`${name}${surname}${numeroRandom}`,
|
|
55
|
+
`${name}-${surname}-${numeroRandom}`,
|
|
56
|
+
`${name}.${surname}${numeroRandom}`,
|
|
57
|
+
`${name}${surname}_${numeroRandom}`,
|
|
58
|
+
`${pseudo}${numeroRandom}`,
|
|
59
|
+
],
|
|
60
|
+
linkedin: [
|
|
61
|
+
`${name}-${surname}-a${chiffresSuite}`,
|
|
62
|
+
`${name}.${surname}.a${chiffresSuite}`,
|
|
63
|
+
`${name}${surname}a${chiffresSuite}`,
|
|
64
|
+
`${name}-${surname}${chiffresSuite}`,
|
|
65
|
+
`${name}.${surname}${chiffresSuite}`,
|
|
66
|
+
`${name}${surname}${chiffresSuite}`,
|
|
67
|
+
],
|
|
68
|
+
twitter: [
|
|
69
|
+
`@${pseudoEnMinuscules}`,
|
|
70
|
+
`@${pseudoEnMinuscules}_official`,
|
|
71
|
+
`@${pseudoEnMinuscules}Official`,
|
|
72
|
+
`@${pseudoEnMinuscules}Real`,
|
|
73
|
+
`@${pseudoEnMinuscules}OfficialAccount`,
|
|
74
|
+
`@${pseudoEnMinuscules}Fan`,
|
|
75
|
+
],
|
|
76
|
+
paypal: [
|
|
77
|
+
`${pseudoEnMinuscules}@paypal`,
|
|
78
|
+
`${pseudoEnMinuscules}_paypal`,
|
|
79
|
+
`paypal_${pseudo}`,
|
|
80
|
+
`paypal.${pseudoEnMinuscules}`,
|
|
81
|
+
],
|
|
82
|
+
ebay: [
|
|
83
|
+
`ebay_${pseudoEnMinuscules}`,
|
|
84
|
+
`${pseudoEnMinuscules}_ebay`,
|
|
85
|
+
`ebay${pseudoEnMinuscules}`,
|
|
86
|
+
`${pseudoEnMinuscules}_store`,
|
|
87
|
+
`ebaystore_${pseudoEnMinuscules}`,
|
|
88
|
+
],
|
|
89
|
+
playstation: [
|
|
90
|
+
`${pseudoEnMinuscules}_PSN`,
|
|
91
|
+
`${pseudoEnMinuscules}_PlayStation`,
|
|
92
|
+
`${pseudoEnMinuscules}PS`,
|
|
93
|
+
],
|
|
94
|
+
battlenet: [
|
|
95
|
+
`${pseudoEnMinuscules}#${Math.floor(9999 * Math.random())}`,
|
|
96
|
+
`${pseudoEnMinuscules}#${Math.floor(9999 * Math.random())}_${surnameEnMinuscules}`,
|
|
97
|
+
],
|
|
98
|
+
bungiecord: [
|
|
99
|
+
`${pseudoEnMinuscules}#0000`,
|
|
100
|
+
`${pseudoEnMinuscules}#0001`,
|
|
101
|
+
`${pseudoEnMinuscules}#0002`,
|
|
102
|
+
],
|
|
103
|
+
reddit: [
|
|
104
|
+
`u/${pseudoEnMinuscules}`,
|
|
105
|
+
`user_${pseudoEnMinuscules}`,
|
|
106
|
+
`${pseudoEnMinuscules}_reddit`,
|
|
107
|
+
`reddit_${pseudoEnMinuscules}`,
|
|
108
|
+
],
|
|
109
|
+
steam: [
|
|
110
|
+
`steamcommunity.com/id/${pseudoEnMinuscules}`,
|
|
111
|
+
`${pseudoEnMinuscules}_steam`,
|
|
112
|
+
`steam_${pseudoEnMinuscules}`,
|
|
113
|
+
`steam_${pseudoEnMinuscules}_id`,
|
|
114
|
+
],
|
|
115
|
+
tiktok: [
|
|
116
|
+
`@${pseudoEnMinuscules}_tiktok`,
|
|
117
|
+
`tiktok_${pseudoEnMinuscules}`,
|
|
118
|
+
`${pseudoEnMinuscules}_tiktok`,
|
|
119
|
+
],
|
|
120
|
+
xbox: [
|
|
121
|
+
`xbox_${pseudoEnMinuscules}`,
|
|
122
|
+
`${pseudoEnMinuscules}_xbox`,
|
|
123
|
+
`${pseudoEnMinuscules}_x`,
|
|
124
|
+
],
|
|
125
|
+
crunchyroll: [
|
|
126
|
+
`crunchy_${pseudoEnMinuscules}`,
|
|
127
|
+
`${pseudoEnMinuscules}_crunchy`,
|
|
128
|
+
`crunchy_${pseudoEnMinuscules}_anime`,
|
|
129
|
+
],
|
|
130
|
+
spotify: [
|
|
131
|
+
`spotify_${pseudoEnMinuscules}`,
|
|
132
|
+
`${pseudoEnMinuscules}_spotify`,
|
|
133
|
+
`music_${pseudoEnMinuscules}`,
|
|
134
|
+
],
|
|
135
|
+
epicgames: [
|
|
136
|
+
`epic_${pseudoEnMinuscules}`,
|
|
137
|
+
`${pseudoEnMinuscules}_epic`,
|
|
138
|
+
`epicgames_${pseudoEnMinuscules}`,
|
|
139
|
+
],
|
|
140
|
+
github: [
|
|
141
|
+
`${pseudoEnMinuscules}_github`,
|
|
142
|
+
`${pseudoEnMinuscules}-dev`,
|
|
143
|
+
`git_${pseudoEnMinuscules}`,
|
|
144
|
+
`github.com/${pseudoEnMinuscules}`,
|
|
145
|
+
],
|
|
146
|
+
riotgames: [
|
|
147
|
+
`${pseudoEnMinuscules}_riot`,
|
|
148
|
+
`${pseudoEnMinuscules}_games`,
|
|
149
|
+
`riot_${pseudoEnMinuscules}`,
|
|
150
|
+
`${pseudoEnMinuscules}_gg`,
|
|
151
|
+
],
|
|
152
|
+
leagueoflegends: [
|
|
153
|
+
`${pseudoEnMinuscules}_lol`,
|
|
154
|
+
`${pseudoEnMinuscules}_league`,
|
|
155
|
+
`${pseudoEnMinuscules}_legends`,
|
|
156
|
+
],
|
|
157
|
+
twitch: [
|
|
158
|
+
`${pseudoEnMinuscules}_stream`,
|
|
159
|
+
`${pseudoEnMinuscules}TV`,
|
|
160
|
+
`${pseudoEnMinuscules}_twitch`,
|
|
161
|
+
`twitch_${pseudoEnMinuscules}`,
|
|
162
|
+
],
|
|
163
|
+
youtube: [
|
|
164
|
+
`${pseudoEnMinuscules}_YT`,
|
|
165
|
+
`youtube.com/user/${pseudoEnMinuscules}`,
|
|
166
|
+
`yt_${pseudoEnMinuscules}`,
|
|
167
|
+
`${pseudoEnMinuscules}_tube`,
|
|
168
|
+
],
|
|
169
|
+
onlyfans: [
|
|
170
|
+
`${pseudoEnMinuscules}_fans`,
|
|
171
|
+
`${pseudoEnMinuscules}_exclusive`,
|
|
172
|
+
`${pseudoEnMinuscules}_content`,
|
|
173
|
+
`only_${pseudoEnMinuscules}`,
|
|
174
|
+
],
|
|
175
|
+
};
|
|
176
|
+
let pseudoVariante = pseudoEnMinuscules;
|
|
177
|
+
switch (mediaSocial.toLowerCase()) {
|
|
178
|
+
case 'twitter':
|
|
179
|
+
pseudoVariante = `@${pseudoEnMinuscules}`;
|
|
180
|
+
break;
|
|
181
|
+
case 'instagram':
|
|
182
|
+
pseudoVariante =
|
|
183
|
+
Math.random() < 0.5
|
|
184
|
+
? randomItem(variations['instagram'])
|
|
185
|
+
: pseudoEnMinuscules;
|
|
186
|
+
break;
|
|
187
|
+
case 'facebook':
|
|
188
|
+
pseudoVariante = randomItem(variations['facebook']);
|
|
189
|
+
break;
|
|
190
|
+
case 'linkedin':
|
|
191
|
+
pseudoVariante = randomItem(variations['linkedin']);
|
|
192
|
+
break;
|
|
193
|
+
case 'paypal':
|
|
194
|
+
pseudoVariante = randomItem(variations['paypal']);
|
|
195
|
+
break;
|
|
196
|
+
case 'ebay':
|
|
197
|
+
pseudoVariante = randomItem(variations['ebay']);
|
|
198
|
+
break;
|
|
199
|
+
case 'playstation':
|
|
200
|
+
pseudoVariante = randomItem(variations['playstation']);
|
|
201
|
+
break;
|
|
202
|
+
case 'battlenet':
|
|
203
|
+
pseudoVariante = randomItem(variations['battlenet']);
|
|
204
|
+
break;
|
|
205
|
+
case 'bungiecord':
|
|
206
|
+
pseudoVariante = randomItem(variations['bungiecord']);
|
|
207
|
+
break;
|
|
208
|
+
case 'reddit':
|
|
209
|
+
pseudoVariante = randomItem(variations['reddit']);
|
|
210
|
+
break;
|
|
211
|
+
case 'steam':
|
|
212
|
+
pseudoVariante = randomItem(variations['steam']);
|
|
213
|
+
break;
|
|
214
|
+
case 'tiktok':
|
|
215
|
+
pseudoVariante = randomItem(variations['tiktok']);
|
|
216
|
+
break;
|
|
217
|
+
case 'xbox':
|
|
218
|
+
pseudoVariante = randomItem(variations['xbox']);
|
|
219
|
+
break;
|
|
220
|
+
case 'crunchyroll':
|
|
221
|
+
pseudoVariante = randomItem(variations['crunchyroll']);
|
|
222
|
+
break;
|
|
223
|
+
case 'spotify':
|
|
224
|
+
pseudoVariante = randomItem(variations['spotify']);
|
|
225
|
+
break;
|
|
226
|
+
case 'epicgames':
|
|
227
|
+
pseudoVariante = randomItem(variations['epicgames']);
|
|
228
|
+
break;
|
|
229
|
+
case 'github':
|
|
230
|
+
pseudoVariante = randomItem(variations['github']);
|
|
231
|
+
break;
|
|
232
|
+
case 'riotgames':
|
|
233
|
+
pseudoVariante = randomItem(variations['riotgames']);
|
|
234
|
+
break;
|
|
235
|
+
case 'onlyfans':
|
|
236
|
+
pseudoVariante = randomItem(variations['onlyfans']);
|
|
237
|
+
break;
|
|
238
|
+
case 'twitch':
|
|
239
|
+
pseudoVariante = randomItem(variations['twitch']);
|
|
240
|
+
break;
|
|
241
|
+
case 'youtube':
|
|
242
|
+
pseudoVariante = generateYouTubeChannelID();
|
|
243
|
+
break;
|
|
244
|
+
default:
|
|
245
|
+
pseudoVariante = pseudoEnMinuscules;
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
return pseudoVariante;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Generate a string of random digits of the given length.
|
|
252
|
+
* @param {number} length
|
|
253
|
+
* @returns {string}
|
|
254
|
+
*/
|
|
255
|
+
export function generateRandomDigits(length) {
|
|
256
|
+
let chiffres = '';
|
|
257
|
+
for (let i = 0; i < length; i++) {
|
|
258
|
+
chiffres += Math.floor(Math.random() * 10);
|
|
259
|
+
}
|
|
260
|
+
return chiffres;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Construct a believable email address using first and last name and a
|
|
264
|
+
* random domain for the specified country code.
|
|
265
|
+
* @param {string} firstName
|
|
266
|
+
* @param {string} lastName
|
|
267
|
+
* @param {string} countryCode
|
|
268
|
+
* @returns {string}
|
|
269
|
+
*/
|
|
270
|
+
export function buildCredibleEmailAddress(firstName, lastName, countryCode) {
|
|
271
|
+
const domaines = datasets.mailboxes;
|
|
272
|
+
if (firstName && lastName) {
|
|
273
|
+
const firstLower = firstName.toLowerCase();
|
|
274
|
+
const lastLower = lastName.toLowerCase();
|
|
275
|
+
const domaineAleatoire = randomItem(domaines[countryCode]);
|
|
276
|
+
const choixVariante = Math.floor(Math.random() * 10);
|
|
277
|
+
let adresseEmail = '';
|
|
278
|
+
switch (choixVariante) {
|
|
279
|
+
case 0:
|
|
280
|
+
adresseEmail = `${firstLower}.${lastLower}@${domaineAleatoire}`;
|
|
281
|
+
break;
|
|
282
|
+
case 1:
|
|
283
|
+
adresseEmail = `${firstLower}${lastLower}@${domaineAleatoire}`;
|
|
284
|
+
break;
|
|
285
|
+
case 2:
|
|
286
|
+
adresseEmail = `${lastLower}.${firstLower}@${domaineAleatoire}`;
|
|
287
|
+
break;
|
|
288
|
+
case 3:
|
|
289
|
+
adresseEmail = `${lastLower}${firstLower}@${domaineAleatoire}`;
|
|
290
|
+
break;
|
|
291
|
+
case 4:
|
|
292
|
+
case 5:
|
|
293
|
+
adresseEmail = `${firstLower.charAt(0)}${lastLower}@${domaineAleatoire}`;
|
|
294
|
+
break;
|
|
295
|
+
case 6:
|
|
296
|
+
case 7:
|
|
297
|
+
adresseEmail = `${firstLower}_${lastLower}@${domaineAleatoire}`;
|
|
298
|
+
break;
|
|
299
|
+
case 8:
|
|
300
|
+
adresseEmail = `${firstLower}.${lastLower}${generateRandomDigits(3)}@${domaineAleatoire}`;
|
|
301
|
+
break;
|
|
302
|
+
case 9:
|
|
303
|
+
adresseEmail = `${lastLower}${firstLower}${generateRandomDigits(3)}@${domaineAleatoire}`;
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
return adresseEmail;
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
throw new Error('Missing first name or last name');
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Generate a fake credit card number, CVV, issuer, expiry year and month.
|
|
314
|
+
* @returns {{cc:string,cvv:string,issuer:string,exp_year:number,exp_month:number}}
|
|
315
|
+
*/
|
|
316
|
+
export function generateCreditCard() {
|
|
317
|
+
const cardNumber = [];
|
|
318
|
+
let checksum = 0;
|
|
319
|
+
let issuer;
|
|
320
|
+
let expiryMonth;
|
|
321
|
+
let expiryYear;
|
|
322
|
+
let cvv;
|
|
323
|
+
const issuers = ['Mastercard', 'Visa', 'American Express', 'Discover'];
|
|
324
|
+
const randomIssuerIndex = Math.floor(Math.random() * issuers.length);
|
|
325
|
+
issuer = issuers[randomIssuerIndex];
|
|
326
|
+
let firstDigits = (Math.floor(Math.random() * 9) + 1) +
|
|
327
|
+
'' +
|
|
328
|
+
(Math.floor(Math.random() * 10)) +
|
|
329
|
+
'' +
|
|
330
|
+
(Math.floor(Math.random() * 10));
|
|
331
|
+
expiryYear = new Date().getFullYear() + Math.floor(Math.random() * 5) + 1;
|
|
332
|
+
switch (issuer) {
|
|
333
|
+
case 'Visa':
|
|
334
|
+
cardNumber.push(4);
|
|
335
|
+
break;
|
|
336
|
+
case 'Mastercard':
|
|
337
|
+
cardNumber.push(5);
|
|
338
|
+
cardNumber.push(1 + Math.floor(Math.random() * 5));
|
|
339
|
+
break;
|
|
340
|
+
case 'American Express':
|
|
341
|
+
cardNumber.push(3);
|
|
342
|
+
cardNumber.push(4 + Math.floor(Math.random() * 4));
|
|
343
|
+
firstDigits += Math.floor(Math.random() * 10);
|
|
344
|
+
break;
|
|
345
|
+
case 'Discover':
|
|
346
|
+
cardNumber.push(6);
|
|
347
|
+
cardNumber.push(0);
|
|
348
|
+
cardNumber.push(1);
|
|
349
|
+
cardNumber.push(1);
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
const cardLength = issuer === 'American Express' ? 15 : 16;
|
|
353
|
+
for (let i = cardNumber.length; i < cardLength - 1; i++) {
|
|
354
|
+
cardNumber.push(Math.floor(Math.random() * 10));
|
|
355
|
+
}
|
|
356
|
+
for (let i = 0; i < cardLength - 1; i++) {
|
|
357
|
+
let digit = cardNumber[i];
|
|
358
|
+
if ((i + 1) % 2 === cardLength % 2) {
|
|
359
|
+
digit *= 2;
|
|
360
|
+
if (digit > 9) {
|
|
361
|
+
digit -= 9;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
checksum += digit;
|
|
365
|
+
}
|
|
366
|
+
const checksumDigit = (10 - (checksum % 10)) % 10;
|
|
367
|
+
cardNumber.push(checksumDigit);
|
|
368
|
+
const cardNumberStr = cardNumber.join('');
|
|
369
|
+
cvv =
|
|
370
|
+
Math.floor(Math.random() * 9) +
|
|
371
|
+
'' +
|
|
372
|
+
Math.floor(Math.random() * 9) +
|
|
373
|
+
'' +
|
|
374
|
+
Math.floor(Math.random() * 9);
|
|
375
|
+
expiryMonth = Math.floor(Math.random() * 12) + 1;
|
|
376
|
+
return {
|
|
377
|
+
cc: cardNumberStr,
|
|
378
|
+
cvv,
|
|
379
|
+
issuer,
|
|
380
|
+
exp_year: expiryYear,
|
|
381
|
+
exp_month: expiryMonth,
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
// usernames handling
|
|
385
|
+
const usernamesTemplate = datasets.usernames;
|
|
386
|
+
let usernames = [...usernamesTemplate];
|
|
387
|
+
export function getRandomUsername() {
|
|
388
|
+
if (usernames.length === 0)
|
|
389
|
+
usernames = [...usernamesTemplate];
|
|
390
|
+
const usernameIndex = Math.floor(Math.random() * usernames.length);
|
|
391
|
+
const username = usernames[usernameIndex];
|
|
392
|
+
return username;
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Generate a random birthdate for an adult (between 19 and 80 years ago).
|
|
396
|
+
* @returns {Date}
|
|
397
|
+
*/
|
|
398
|
+
export function generateRandomDate() {
|
|
399
|
+
const dateActuelle = new Date();
|
|
400
|
+
const dateIlYa13Ans = new Date(dateActuelle);
|
|
401
|
+
dateIlYa13Ans.setFullYear(dateIlYa13Ans.getFullYear() - 19);
|
|
402
|
+
const dateIlYa30Ans = new Date(dateActuelle);
|
|
403
|
+
dateIlYa30Ans.setFullYear(dateIlYa30Ans.getFullYear() - 80);
|
|
404
|
+
const dateAleatoire = new Date(dateIlYa13Ans.getTime() +
|
|
405
|
+
Math.random() * (dateIlYa30Ans.getTime() - dateIlYa13Ans.getTime()));
|
|
406
|
+
return dateAleatoire;
|
|
407
|
+
}
|
|
408
|
+
export function getAge(birthDate) {
|
|
409
|
+
const today = new Date();
|
|
410
|
+
let age = today.getFullYear() - birthDate.getFullYear();
|
|
411
|
+
const m = today.getMonth() - birthDate.getMonth();
|
|
412
|
+
if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
|
|
413
|
+
age--;
|
|
414
|
+
}
|
|
415
|
+
return age;
|
|
416
|
+
}
|
|
417
|
+
export const countries = datasets.countries;
|
|
418
|
+
export function getContinent(countryCode) {
|
|
419
|
+
const continentsCountries = datasets.continentsCountries;
|
|
420
|
+
for (const continent in continentsCountries) {
|
|
421
|
+
if (continentsCountries[continent].includes(countryCode)) {
|
|
422
|
+
return continent;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
return 'Unknown';
|
|
426
|
+
}
|
|
427
|
+
const preferencesPublicitaires = datasets.adChoices;
|
|
428
|
+
/**
|
|
429
|
+
* Generate a sorted map of ad preference scores based on categories and gender.
|
|
430
|
+
* @param {any[]} categories
|
|
431
|
+
* @param {'Male'|'Female'} gender
|
|
432
|
+
* @returns {Record<string, number>}
|
|
433
|
+
*/
|
|
434
|
+
export function generatePreferences(categories, gender) {
|
|
435
|
+
categories.forEach((categorie) => {
|
|
436
|
+
const categorieName = Object.keys(categorie)[0];
|
|
437
|
+
const coef = Math.random() * 1 + 0.5;
|
|
438
|
+
categorie[categorieName][gender] *= coef;
|
|
439
|
+
});
|
|
440
|
+
categories.sort((a, b) => b[Object.keys(b)[0]][gender] - a[Object.keys(a)[0]][gender]);
|
|
441
|
+
const categoriesSelectionnees = categories.slice(0, Math.floor(Math.random() * 6) + 15);
|
|
442
|
+
const preferences = {};
|
|
443
|
+
categoriesSelectionnees.forEach((categorie) => {
|
|
444
|
+
const categorieName = Object.keys(categorie)[0];
|
|
445
|
+
const score = categorie[categorieName][gender];
|
|
446
|
+
preferences[categorieName] = score;
|
|
447
|
+
});
|
|
448
|
+
return preferences;
|
|
449
|
+
}
|
|
450
|
+
export function generateYouTubeChannelID() {
|
|
451
|
+
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
|
|
452
|
+
const length = 22;
|
|
453
|
+
let channelID = 'UC';
|
|
454
|
+
for (let i = 0; i < length; i++) {
|
|
455
|
+
channelID += characters.charAt(Math.floor(Math.random() * characters.length));
|
|
456
|
+
}
|
|
457
|
+
return channelID;
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Generate a fake user profile as a JSON string.
|
|
461
|
+
* @param {{countryName?:string,birthGender?:string}} params
|
|
462
|
+
* @returns {string}
|
|
463
|
+
*/
|
|
464
|
+
export function generateFakeProfile(params) {
|
|
465
|
+
let { countryName, birthGender } = params;
|
|
466
|
+
let country;
|
|
467
|
+
if (!countryName)
|
|
468
|
+
country = countries[Math.floor(Math.random() * countries.length)];
|
|
469
|
+
else
|
|
470
|
+
country = countries.find((u) => u.name === countryName);
|
|
471
|
+
let continent = getContinent(country.abbreviation);
|
|
472
|
+
while (continent === 'Unknown') {
|
|
473
|
+
country = countries[Math.floor(Math.random() * countries.length)];
|
|
474
|
+
continent = getContinent(country.abbreviation);
|
|
475
|
+
}
|
|
476
|
+
if (!birthGender)
|
|
477
|
+
birthGender = Math.random() < 0.5 ? 'Male' : 'Female';
|
|
478
|
+
const person = {
|
|
479
|
+
name: randomItem(datasets[country.abbreviation][birthGender.toLowerCase() + '_first']),
|
|
480
|
+
surname: randomItem(datasets[country.abbreviation].last),
|
|
481
|
+
};
|
|
482
|
+
const phoneNumber = generatePhoneNumber(country.phoneCode);
|
|
483
|
+
const username = getRandomUsername();
|
|
484
|
+
const social_media = {};
|
|
485
|
+
social_media['twitter'] =
|
|
486
|
+
Math.random() < 0.3
|
|
487
|
+
? null
|
|
488
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'twitter');
|
|
489
|
+
social_media['instagram'] =
|
|
490
|
+
Math.random() < 0.1
|
|
491
|
+
? null
|
|
492
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'instagram');
|
|
493
|
+
social_media['facebook'] =
|
|
494
|
+
Math.random() < 0.4
|
|
495
|
+
? null
|
|
496
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'facebook');
|
|
497
|
+
social_media['linkedin'] =
|
|
498
|
+
Math.random() < 0.6
|
|
499
|
+
? null
|
|
500
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'linkedin');
|
|
501
|
+
social_media['paypal'] =
|
|
502
|
+
Math.random() < 0.5
|
|
503
|
+
? null
|
|
504
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'paypal');
|
|
505
|
+
social_media['ebay'] =
|
|
506
|
+
Math.random() < 0.4
|
|
507
|
+
? null
|
|
508
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'ebay');
|
|
509
|
+
social_media['playstation'] =
|
|
510
|
+
Math.random() < 0.2
|
|
511
|
+
? null
|
|
512
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'playstation');
|
|
513
|
+
social_media['battlenet'] =
|
|
514
|
+
Math.random() < 0.3
|
|
515
|
+
? null
|
|
516
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'battlenet');
|
|
517
|
+
social_media['bungiecord'] =
|
|
518
|
+
Math.random() < 0.2
|
|
519
|
+
? null
|
|
520
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'bungiecord');
|
|
521
|
+
social_media['reddit'] =
|
|
522
|
+
Math.random() < 0.4
|
|
523
|
+
? null
|
|
524
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'reddit');
|
|
525
|
+
social_media['steam'] =
|
|
526
|
+
Math.random() < 0.5
|
|
527
|
+
? null
|
|
528
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'steam');
|
|
529
|
+
social_media['tiktok'] =
|
|
530
|
+
Math.random() < 0.3
|
|
531
|
+
? null
|
|
532
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'tiktok');
|
|
533
|
+
social_media['xbox'] =
|
|
534
|
+
Math.random() < 0.4
|
|
535
|
+
? null
|
|
536
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'xbox');
|
|
537
|
+
social_media['crunchyroll'] =
|
|
538
|
+
Math.random() < 0.2
|
|
539
|
+
? null
|
|
540
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'crunchyroll');
|
|
541
|
+
social_media['spotify'] =
|
|
542
|
+
Math.random() < 0.5
|
|
543
|
+
? null
|
|
544
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'spotify');
|
|
545
|
+
social_media['epicgames'] =
|
|
546
|
+
Math.random() < 0.3
|
|
547
|
+
? null
|
|
548
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'epicgames');
|
|
549
|
+
social_media['github'] =
|
|
550
|
+
Math.random() < 0.4
|
|
551
|
+
? null
|
|
552
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'github');
|
|
553
|
+
social_media['riotgames'] =
|
|
554
|
+
Math.random() < 0.6
|
|
555
|
+
? null
|
|
556
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'riotgames');
|
|
557
|
+
if (social_media['riotgames']) {
|
|
558
|
+
social_media['leagueoflegends'] =
|
|
559
|
+
Math.random() < 0.8 ? null : social_media['riotgames'];
|
|
560
|
+
}
|
|
561
|
+
social_media['onlyfans'] =
|
|
562
|
+
Math.random() < 0.3
|
|
563
|
+
? null
|
|
564
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'onlyfans');
|
|
565
|
+
social_media['twitch'] =
|
|
566
|
+
Math.random() < 0.4 ? null : username;
|
|
567
|
+
social_media['youtube'] =
|
|
568
|
+
Math.random() < 0.3
|
|
569
|
+
? null
|
|
570
|
+
: generateSocialHandleVariant(person.name, person.surname, username, 'youtube');
|
|
571
|
+
const email = buildCredibleEmailAddress(person.name, person.surname, country.abbreviation);
|
|
572
|
+
let creditCardInfo = generateCreditCard();
|
|
573
|
+
while (creditCardInfo.cc.length !== 16) {
|
|
574
|
+
creditCardInfo = generateCreditCard();
|
|
575
|
+
}
|
|
576
|
+
const randomDate = generateRandomDate();
|
|
577
|
+
const preferences = generatePreferences(preferencesPublicitaires, birthGender);
|
|
578
|
+
const preferencesJSON = JSON.stringify(preferences);
|
|
579
|
+
const preferencesBase64 = Buffer.from(preferencesJSON).toString('base64');
|
|
580
|
+
const password = randomItem(datasets.common.passwords) +
|
|
581
|
+
randomItem(datasets.common.passwords) +
|
|
582
|
+
range(100, 999);
|
|
583
|
+
const salt = range(2, 8);
|
|
584
|
+
const street = randomItem(datasets[country.abbreviation].street);
|
|
585
|
+
const city = randomItem(datasets[country.abbreviation].cities);
|
|
586
|
+
const state = randomItem(datasets[country.abbreviation].states);
|
|
587
|
+
const sexualities = [
|
|
588
|
+
'Lesbian',
|
|
589
|
+
'Gay',
|
|
590
|
+
'Bisexual',
|
|
591
|
+
'Transgender',
|
|
592
|
+
'Queer',
|
|
593
|
+
'Intersex',
|
|
594
|
+
'Asexual',
|
|
595
|
+
'Pansexual',
|
|
596
|
+
'Non-binary',
|
|
597
|
+
'Genderqueer',
|
|
598
|
+
'Androgyne',
|
|
599
|
+
'Bigenre',
|
|
600
|
+
'Agender',
|
|
601
|
+
'Genderfluid',
|
|
602
|
+
'Demisexual',
|
|
603
|
+
'Graysexual',
|
|
604
|
+
'Skoliosexual',
|
|
605
|
+
'Homoflexible',
|
|
606
|
+
'Heteroflexible',
|
|
607
|
+
'Queerplatonic',
|
|
608
|
+
'Polyamorous',
|
|
609
|
+
'Monogamous',
|
|
610
|
+
'Pangender',
|
|
611
|
+
'Omnisexual',
|
|
612
|
+
'Questioning',
|
|
613
|
+
'Two-Spirit',
|
|
614
|
+
'Autosexual',
|
|
615
|
+
'Gynesexual',
|
|
616
|
+
'Androphilia',
|
|
617
|
+
'Gynephilia',
|
|
618
|
+
'Sapiosexual',
|
|
619
|
+
'Demiromantic',
|
|
620
|
+
'Heteroromantic',
|
|
621
|
+
'Homoromantic',
|
|
622
|
+
'Biromantic',
|
|
623
|
+
'Panromantic',
|
|
624
|
+
'Polyromantic',
|
|
625
|
+
'Aroromantic',
|
|
626
|
+
'Greyromantic',
|
|
627
|
+
'Lithromantic',
|
|
628
|
+
'Frayromantic',
|
|
629
|
+
'Quoiromantic',
|
|
630
|
+
'Akoiromantic',
|
|
631
|
+
'Cupioromantic',
|
|
632
|
+
'Platoniromantic',
|
|
633
|
+
'Demisexuality',
|
|
634
|
+
'Lithsexuality',
|
|
635
|
+
'Fraysexuality',
|
|
636
|
+
'Apollosexuality',
|
|
637
|
+
'Queerplatonic',
|
|
638
|
+
];
|
|
639
|
+
const fakeProfile = {
|
|
640
|
+
name: person.name,
|
|
641
|
+
surname: person.surname,
|
|
642
|
+
birth: randomDate.toUTCString(),
|
|
643
|
+
age: getAge(randomDate),
|
|
644
|
+
username,
|
|
645
|
+
birthGender,
|
|
646
|
+
actualGender: Math.random() < 0.3
|
|
647
|
+
? birthGender
|
|
648
|
+
: randomItem(sexualities),
|
|
649
|
+
phone_number: phoneNumber,
|
|
650
|
+
location: {
|
|
651
|
+
street: {
|
|
652
|
+
number: range(1, 100),
|
|
653
|
+
name: street,
|
|
654
|
+
},
|
|
655
|
+
city,
|
|
656
|
+
state,
|
|
657
|
+
country,
|
|
658
|
+
continent,
|
|
659
|
+
},
|
|
660
|
+
email,
|
|
661
|
+
passwords: {
|
|
662
|
+
raw: password,
|
|
663
|
+
salt,
|
|
664
|
+
md5: crypto.createHash('md5').update(password + salt).digest('hex'),
|
|
665
|
+
sha1: crypto.createHash('sha1').update(password + salt).digest('hex'),
|
|
666
|
+
sha256: crypto.createHash('sha256').update(password + salt).digest('hex'),
|
|
667
|
+
},
|
|
668
|
+
social_media,
|
|
669
|
+
credit_card: {
|
|
670
|
+
number: creditCardInfo.cc,
|
|
671
|
+
cvv: creditCardInfo.cvv,
|
|
672
|
+
issuer: creditCardInfo.issuer,
|
|
673
|
+
expiration_year: creditCardInfo.exp_year,
|
|
674
|
+
expiration_month: creditCardInfo.exp_month,
|
|
675
|
+
},
|
|
676
|
+
adChoices: preferencesBase64,
|
|
677
|
+
};
|
|
678
|
+
return JSON.stringify(fakeProfile, null, 2);
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Generate an array of fake profiles.
|
|
682
|
+
* @param {number} batchSize
|
|
683
|
+
* @param {{countryName?:string,birthGender?:string}} params
|
|
684
|
+
* @returns {any[]}
|
|
685
|
+
*/
|
|
686
|
+
export function generateFakeProfilesBatch(batchSize, params) {
|
|
687
|
+
const profiles = [];
|
|
688
|
+
for (let i = 0; i < batchSize; i++) {
|
|
689
|
+
profiles.push(JSON.parse(generateFakeProfile(params)));
|
|
690
|
+
}
|
|
691
|
+
return profiles;
|
|
692
|
+
}
|
|
693
|
+
export function range(min, max) {
|
|
694
|
+
return Math.floor(Math.random() * (max - min)) + min;
|
|
695
|
+
}
|
|
696
|
+
export function composeCSVFile(data) {
|
|
697
|
+
const header = 'name;surname;birth;age;location_street_number;location_street_name;location_city;location_state;location_country_name;location_country_abbreviation;location_country_phoneCode;location_continent;username;birthGender;actualGender;phone_number;social_media_twitter;social_media_instagram;social_media_facebook;social_media_linkedin;social_media_youtube;social_media_twitch;email;credit_card_number;credit_card_cvv;credit_card_issuer;credit_card_expiration_month;credit_card_expiration_year;passwords_raw;passwords_salt;passwords_md5;passwords_sha1;passwords_sha256;adChoices\n';
|
|
698
|
+
const rows = data
|
|
699
|
+
.map((profile) => {
|
|
700
|
+
const formattedProfile = [
|
|
701
|
+
profile.name,
|
|
702
|
+
profile.surname,
|
|
703
|
+
profile.birth.split(',').join(' '),
|
|
704
|
+
profile.age,
|
|
705
|
+
profile.location.street.number,
|
|
706
|
+
profile.location.street.name,
|
|
707
|
+
profile.location.city,
|
|
708
|
+
profile.location.state,
|
|
709
|
+
profile.location.country.name,
|
|
710
|
+
profile.location.country.abbreviation,
|
|
711
|
+
profile.location.country.phoneCode,
|
|
712
|
+
profile.location.country.continent,
|
|
713
|
+
profile.username,
|
|
714
|
+
profile.birthGender,
|
|
715
|
+
profile.actualGender,
|
|
716
|
+
profile.phone_number,
|
|
717
|
+
[
|
|
718
|
+
profile.social_media.twitter,
|
|
719
|
+
profile.social_media.instagram,
|
|
720
|
+
profile.social_media.facebook,
|
|
721
|
+
profile.social_media.linkedin,
|
|
722
|
+
profile.social_media.youtube,
|
|
723
|
+
profile.social_media.twitch,
|
|
724
|
+
].join(';'),
|
|
725
|
+
profile.email,
|
|
726
|
+
[
|
|
727
|
+
profile.credit_card.number,
|
|
728
|
+
profile.credit_card.cvv,
|
|
729
|
+
profile.credit_card.issuer,
|
|
730
|
+
profile.credit_card.expiration_month,
|
|
731
|
+
profile.credit_card.expiration_year,
|
|
732
|
+
].join(';'),
|
|
733
|
+
profile.passwords.raw,
|
|
734
|
+
profile.passwords.salt,
|
|
735
|
+
profile.passwords.md5,
|
|
736
|
+
profile.passwords.sha1,
|
|
737
|
+
profile.passwords.sha256,
|
|
738
|
+
profile.adChoices,
|
|
739
|
+
];
|
|
740
|
+
return formattedProfile.join(';');
|
|
741
|
+
})
|
|
742
|
+
.join('\n');
|
|
743
|
+
return header + rows;
|
|
744
|
+
}
|
|
745
|
+
export function generateAndComposeCSV(totalProfiles, batchSize, params) {
|
|
746
|
+
const profiles = [];
|
|
747
|
+
for (let i = 0; i < totalProfiles / batchSize; i++) {
|
|
748
|
+
console.log('Generated', i * batchSize);
|
|
749
|
+
const batch = generateFakeProfilesBatch(batchSize, params);
|
|
750
|
+
profiles.push(...batch);
|
|
751
|
+
}
|
|
752
|
+
return composeCSVFile(profiles);
|
|
753
|
+
}
|
|
754
|
+
export function writeCSVFile(filename, content) {
|
|
755
|
+
fs.writeFileSync(filename, content);
|
|
756
|
+
}
|