@bprotsyk/aso-core 2.1.112 → 2.1.114
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.
|
@@ -253,29 +253,122 @@ async function cloneTraffleCampaign(app, platform, addDefaultStreams) {
|
|
|
253
253
|
// Для конкретної платформи
|
|
254
254
|
const platformName = (0, app_1.getPlatformName)(platform);
|
|
255
255
|
matchingCampaign = allCampaigns.filter((c) => {
|
|
256
|
-
|
|
257
|
-
const
|
|
258
|
-
const hasId = idPattern.test(c.name);
|
|
259
|
-
const hasBundle = c.name.includes(`[${app.bundle}]`);
|
|
256
|
+
const hasDomain = c.name.includes(app.domainParams.name);
|
|
257
|
+
const hasGroup = c.group == app.id.toString();
|
|
260
258
|
// Перевіряємо наявність платформи в дужках в кінці назви
|
|
261
259
|
const platformPattern = new RegExp(`\\(.*${platformName}.*\\)\\s*$`);
|
|
262
260
|
const hasPlatform = platformPattern.test(c.name);
|
|
263
|
-
return
|
|
261
|
+
return hasGroup && hasDomain && hasPlatform;
|
|
264
262
|
});
|
|
265
263
|
}
|
|
266
264
|
else {
|
|
267
265
|
// Для General платформи
|
|
268
266
|
matchingCampaign = allCampaigns.filter((c) => {
|
|
269
|
-
// Точна перевірка ID з межами слів
|
|
270
|
-
const idPattern = new RegExp(`${app.id}\\b`);
|
|
271
|
-
const hasId = idPattern.test(c.name);
|
|
272
267
|
const hasBundle = c.name.includes(`[${app.bundle}]`);
|
|
268
|
+
const hasDomain = c.name.includes(app.domainParams.name);
|
|
273
269
|
// Перевіряємо відсутність платформи в дужках в кінці
|
|
274
270
|
// Дозволяємо будь-які інші дужки (як для гео або опису)
|
|
275
271
|
const noPlatformAtEnd = !/\(.*(?:iOS|Android|Desktop|Mobile).*\)\s*$/.test(c.name);
|
|
276
|
-
return
|
|
272
|
+
return hasBundle && hasDomain && noPlatformAtEnd;
|
|
277
273
|
});
|
|
278
274
|
}
|
|
275
|
+
// Якщо знайдена існуюча кампанія - повертаємо її без генерації параметрів
|
|
276
|
+
if (matchingCampaign.length > 0) {
|
|
277
|
+
const existingCampaign = matchingCampaign[0];
|
|
278
|
+
// Отримуємо потоки тільки якщо потрібно щось робити з ними
|
|
279
|
+
const originalStreams = await getStreamsByCampaignId(ORIGINAL_CLONE_CAMPAIGN_ID);
|
|
280
|
+
const existingStreams = await getStreamsByCampaignId(existingCampaign.id);
|
|
281
|
+
const updateOrCreateCLOStream = async (campaignId, existingStreams) => {
|
|
282
|
+
const cloTemplate = originalStreams.find(s => s.name === "CLO");
|
|
283
|
+
if (!cloTemplate)
|
|
284
|
+
return;
|
|
285
|
+
const cloStream = {
|
|
286
|
+
type: cloTemplate.type,
|
|
287
|
+
name: "CLO",
|
|
288
|
+
campaign_id: campaignId,
|
|
289
|
+
position: cloTemplate.position,
|
|
290
|
+
state: cloTemplate.state,
|
|
291
|
+
action_type: cloTemplate.action_type,
|
|
292
|
+
action_payload: cloTemplate.action_payload || "",
|
|
293
|
+
schema: cloTemplate.schema,
|
|
294
|
+
collect_clicks: cloTemplate.collect_clicks,
|
|
295
|
+
filter_or: cloTemplate.filter_or,
|
|
296
|
+
weight: cloTemplate.weight,
|
|
297
|
+
filters: [
|
|
298
|
+
{
|
|
299
|
+
name: "country",
|
|
300
|
+
mode: "reject",
|
|
301
|
+
payload: app.platforms[platform].geo || []
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
name: "bot",
|
|
305
|
+
mode: "accept",
|
|
306
|
+
payload: null
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
name: 'proxy',
|
|
310
|
+
mode: 'accept',
|
|
311
|
+
payload: null
|
|
312
|
+
}
|
|
313
|
+
],
|
|
314
|
+
offers: []
|
|
315
|
+
};
|
|
316
|
+
if (existingStreams) {
|
|
317
|
+
console.log(`existingStreams`, existingStreams);
|
|
318
|
+
const existingCLO = existingStreams.find(s => s.name === "CLO");
|
|
319
|
+
if (existingCLO) {
|
|
320
|
+
await http_1.default.put(`streams/${existingCLO.id}`, cloStream);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
await http_1.default.post('streams', cloStream);
|
|
325
|
+
};
|
|
326
|
+
const createStreamWithoutIds = async (stream, campaignId) => {
|
|
327
|
+
// Створюємо базовий об'єкт потоку без ID
|
|
328
|
+
const newStream = {
|
|
329
|
+
type: stream.type,
|
|
330
|
+
name: stream.name,
|
|
331
|
+
campaign_id: campaignId,
|
|
332
|
+
position: stream.position,
|
|
333
|
+
state: stream.state,
|
|
334
|
+
action_type: stream.action_type,
|
|
335
|
+
action_payload: stream.action_payload || "",
|
|
336
|
+
schema: stream.schema,
|
|
337
|
+
collect_clicks: stream.collect_clicks,
|
|
338
|
+
filter_or: stream.filter_or,
|
|
339
|
+
weight: stream.weight,
|
|
340
|
+
filters: stream.filters.map(filter => ({
|
|
341
|
+
name: filter.name,
|
|
342
|
+
mode: filter.mode,
|
|
343
|
+
payload: filter.payload
|
|
344
|
+
})),
|
|
345
|
+
offers: stream.offers.map(offer => ({
|
|
346
|
+
offer_id: offer.offer_id,
|
|
347
|
+
state: offer.state,
|
|
348
|
+
share: offer.share
|
|
349
|
+
}))
|
|
350
|
+
};
|
|
351
|
+
// Створюємо новий потік
|
|
352
|
+
await http_1.default.post('streams', newStream);
|
|
353
|
+
};
|
|
354
|
+
// Завжди оновлюємо CLO потік
|
|
355
|
+
await updateOrCreateCLOStream(existingCampaign.id, existingStreams);
|
|
356
|
+
// Для інших потоків
|
|
357
|
+
if (addDefaultStreams) {
|
|
358
|
+
for (const stream of originalStreams) {
|
|
359
|
+
if (stream.name === "CLO")
|
|
360
|
+
continue; // Пропускаємо CLO
|
|
361
|
+
const existingStream = existingStreams.find(s => s.name === stream.name);
|
|
362
|
+
if (!existingStream) {
|
|
363
|
+
await createStreamWithoutIds(stream, existingCampaign.id);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
console.log(existingCampaign);
|
|
368
|
+
return existingCampaign;
|
|
369
|
+
}
|
|
370
|
+
// Створення нової кампанії - тільки тепер генеруємо параметри
|
|
371
|
+
console.log("Creating new campaign, generating parameters...");
|
|
279
372
|
const group = await createGroup(app.id.toString(), "campaigns");
|
|
280
373
|
const originalCampaign = await getCampaignById(ORIGINAL_CLONE_CAMPAIGN_ID);
|
|
281
374
|
const maxPosition = Math.max(...allCampaigns.map(c => c.position || 0));
|
|
@@ -286,6 +379,7 @@ async function cloneTraffleCampaign(app, platform, addDefaultStreams) {
|
|
|
286
379
|
}
|
|
287
380
|
const maxGroupId = Math.max(...allCampaigns.map(c => c.group_id || 0));
|
|
288
381
|
const originalStreams = await getStreamsByCampaignId(ORIGINAL_CLONE_CAMPAIGN_ID);
|
|
382
|
+
// Параметри генеруються тільки для нових кампаній
|
|
289
383
|
let parameters = await TrafleKeitaroParameters({ bundle: app.bundle, appsflyerDevKey: app.platforms[platform].appsflyerParams?.devKey, name: name, originalParameters: originalCampaign.parameters });
|
|
290
384
|
const createStreamWithoutIds = async (stream, campaignId) => {
|
|
291
385
|
// Створюємо базовий об'єкт потоку без ID
|
|
@@ -359,26 +453,6 @@ async function cloneTraffleCampaign(app, platform, addDefaultStreams) {
|
|
|
359
453
|
}
|
|
360
454
|
await http_1.default.post('streams', cloStream);
|
|
361
455
|
};
|
|
362
|
-
// Якщо знайдена існуюча кампанія
|
|
363
|
-
if (matchingCampaign.length > 0) {
|
|
364
|
-
const existingCampaign = matchingCampaign[0];
|
|
365
|
-
const existingStreams = await getStreamsByCampaignId(existingCampaign.id);
|
|
366
|
-
// Завжди оновлюємо CLO потік
|
|
367
|
-
await updateOrCreateCLOStream(existingCampaign.id, existingStreams);
|
|
368
|
-
// Для інших потоків
|
|
369
|
-
if (addDefaultStreams) {
|
|
370
|
-
for (const stream of originalStreams) {
|
|
371
|
-
if (stream.name === "CLO")
|
|
372
|
-
continue; // Пропускаємо CLO
|
|
373
|
-
const existingStream = existingStreams.find(s => s.name === stream.name);
|
|
374
|
-
if (!existingStream) {
|
|
375
|
-
await createStreamWithoutIds(stream, existingCampaign.id);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
console.log(existingCampaign);
|
|
380
|
-
return existingCampaign;
|
|
381
|
-
}
|
|
382
456
|
// Створення нової кампанії
|
|
383
457
|
let alias = generateAlias();
|
|
384
458
|
console.log(group);
|
package/package.json
CHANGED
|
@@ -337,33 +337,137 @@ async function cloneTraffleCampaign(app: IApp, platform: EPlatform, addDefaultSt
|
|
|
337
337
|
// Для конкретної платформи
|
|
338
338
|
const platformName = getPlatformName(platform);
|
|
339
339
|
matchingCampaign = allCampaigns.filter((c) => {
|
|
340
|
-
|
|
341
|
-
const
|
|
342
|
-
const
|
|
343
|
-
const hasBundle = c.name.includes(`[${app.bundle}]`);
|
|
340
|
+
|
|
341
|
+
const hasDomain = c.name.includes(app.domainParams.name);
|
|
342
|
+
const hasGroup = c.group == app.id.toString()
|
|
344
343
|
|
|
345
344
|
// Перевіряємо наявність платформи в дужках в кінці назви
|
|
346
345
|
const platformPattern = new RegExp(`\\(.*${platformName}.*\\)\\s*$`);
|
|
347
346
|
const hasPlatform = platformPattern.test(c.name);
|
|
348
|
-
return
|
|
347
|
+
return hasGroup && hasDomain && hasPlatform;
|
|
349
348
|
});
|
|
350
349
|
} else {
|
|
351
350
|
// Для General платформи
|
|
352
351
|
matchingCampaign = allCampaigns.filter((c) => {
|
|
353
|
-
// Точна перевірка ID з межами слів
|
|
354
|
-
const idPattern = new RegExp(`${app.id}\\b`);
|
|
355
|
-
const hasId = idPattern.test(c.name);
|
|
356
352
|
const hasBundle = c.name.includes(`[${app.bundle}]`);
|
|
353
|
+
const hasDomain = c.name.includes(app.domainParams.name);
|
|
357
354
|
|
|
358
355
|
// Перевіряємо відсутність платформи в дужках в кінці
|
|
359
356
|
// Дозволяємо будь-які інші дужки (як для гео або опису)
|
|
360
357
|
const noPlatformAtEnd = !/\(.*(?:iOS|Android|Desktop|Mobile).*\)\s*$/.test(c.name);
|
|
361
|
-
return
|
|
358
|
+
return hasBundle && hasDomain && noPlatformAtEnd;
|
|
362
359
|
});
|
|
363
360
|
}
|
|
364
361
|
|
|
362
|
+
// Якщо знайдена існуюча кампанія - повертаємо її без генерації параметрів
|
|
363
|
+
if (matchingCampaign.length > 0) {
|
|
364
|
+
const existingCampaign = matchingCampaign[0];
|
|
365
|
+
|
|
366
|
+
// Отримуємо потоки тільки якщо потрібно щось робити з ними
|
|
367
|
+
const originalStreams = await getStreamsByCampaignId(ORIGINAL_CLONE_CAMPAIGN_ID);
|
|
368
|
+
const existingStreams = await getStreamsByCampaignId(existingCampaign.id);
|
|
369
|
+
|
|
370
|
+
const updateOrCreateCLOStream = async (campaignId: number, existingStreams?: IKeitaroStream[]) => {
|
|
371
|
+
const cloTemplate = originalStreams.find(s => s.name === "CLO");
|
|
372
|
+
if (!cloTemplate) return;
|
|
373
|
+
|
|
374
|
+
const cloStream = {
|
|
375
|
+
type: cloTemplate.type,
|
|
376
|
+
name: "CLO",
|
|
377
|
+
campaign_id: campaignId,
|
|
378
|
+
position: cloTemplate.position,
|
|
379
|
+
state: cloTemplate.state,
|
|
380
|
+
action_type: cloTemplate.action_type,
|
|
381
|
+
action_payload: cloTemplate.action_payload || "",
|
|
382
|
+
schema: cloTemplate.schema,
|
|
383
|
+
collect_clicks: cloTemplate.collect_clicks,
|
|
384
|
+
filter_or: cloTemplate.filter_or,
|
|
385
|
+
weight: cloTemplate.weight,
|
|
386
|
+
filters: [
|
|
387
|
+
{
|
|
388
|
+
name: "country",
|
|
389
|
+
mode: "reject",
|
|
390
|
+
payload: app.platforms[platform].geo || []
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
name: "bot",
|
|
394
|
+
mode: "accept",
|
|
395
|
+
payload: null
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
name: 'proxy',
|
|
399
|
+
mode: 'accept',
|
|
400
|
+
payload: null
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
],
|
|
404
|
+
offers: []
|
|
405
|
+
};
|
|
365
406
|
|
|
407
|
+
if (existingStreams) {
|
|
408
|
+
console.log(`existingStreams`,existingStreams)
|
|
409
|
+
const existingCLO = existingStreams.find(s => s.name === "CLO");
|
|
410
|
+
if (existingCLO) {
|
|
411
|
+
await keitaroApi.put(`streams/${existingCLO.id}`, cloStream);
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
await keitaroApi.post('streams', cloStream);
|
|
417
|
+
};
|
|
366
418
|
|
|
419
|
+
const createStreamWithoutIds = async (stream: IKeitaroStream, campaignId: number) => {
|
|
420
|
+
// Створюємо базовий об'єкт потоку без ID
|
|
421
|
+
const newStream = {
|
|
422
|
+
type: stream.type,
|
|
423
|
+
name: stream.name,
|
|
424
|
+
campaign_id: campaignId,
|
|
425
|
+
position: stream.position,
|
|
426
|
+
state: stream.state,
|
|
427
|
+
action_type: stream.action_type,
|
|
428
|
+
action_payload: stream.action_payload || "",
|
|
429
|
+
schema: stream.schema,
|
|
430
|
+
collect_clicks: stream.collect_clicks,
|
|
431
|
+
filter_or: stream.filter_or,
|
|
432
|
+
weight: stream.weight,
|
|
433
|
+
filters: stream.filters.map(filter => ({
|
|
434
|
+
name: filter.name,
|
|
435
|
+
mode: filter.mode,
|
|
436
|
+
payload: filter.payload
|
|
437
|
+
})),
|
|
438
|
+
offers: stream.offers.map(offer => ({
|
|
439
|
+
offer_id: offer.offer_id,
|
|
440
|
+
state: offer.state,
|
|
441
|
+
share: offer.share
|
|
442
|
+
}))
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
// Створюємо новий потік
|
|
446
|
+
await keitaroApi.post('streams', newStream);
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
// Завжди оновлюємо CLO потік
|
|
450
|
+
await updateOrCreateCLOStream(existingCampaign.id, existingStreams);
|
|
451
|
+
|
|
452
|
+
// Для інших потоків
|
|
453
|
+
if (addDefaultStreams) {
|
|
454
|
+
for (const stream of originalStreams) {
|
|
455
|
+
if (stream.name === "CLO") continue; // Пропускаємо CLO
|
|
456
|
+
|
|
457
|
+
const existingStream = existingStreams.find(s => s.name === stream.name);
|
|
458
|
+
if (!existingStream) {
|
|
459
|
+
await createStreamWithoutIds(stream, existingCampaign.id);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
console.log(existingCampaign)
|
|
465
|
+
return existingCampaign;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Створення нової кампанії - тільки тепер генеруємо параметри
|
|
469
|
+
console.log("Creating new campaign, generating parameters...");
|
|
470
|
+
|
|
367
471
|
const group = await createGroup(app.id.toString(), "campaigns")
|
|
368
472
|
|
|
369
473
|
const originalCampaign: IKeitaroCampaign = await getCampaignById(ORIGINAL_CLONE_CAMPAIGN_ID);
|
|
@@ -376,11 +480,10 @@ async function cloneTraffleCampaign(app: IApp, platform: EPlatform, addDefaultSt
|
|
|
376
480
|
throw Error(`Failed to get all domains list`);
|
|
377
481
|
}
|
|
378
482
|
|
|
379
|
-
|
|
380
483
|
const maxGroupId = Math.max(...allCampaigns.map(c => c.group_id || 0));
|
|
381
484
|
const originalStreams = await getStreamsByCampaignId(ORIGINAL_CLONE_CAMPAIGN_ID);
|
|
382
485
|
|
|
383
|
-
|
|
486
|
+
// Параметри генеруються тільки для нових кампаній
|
|
384
487
|
let parameters = await TrafleKeitaroParameters({bundle: app.bundle, appsflyerDevKey: app.platforms[platform].appsflyerParams?.devKey, name: name, originalParameters: originalCampaign.parameters})
|
|
385
488
|
|
|
386
489
|
const createStreamWithoutIds = async (stream: IKeitaroStream, campaignId: number) => {
|
|
@@ -461,37 +564,9 @@ async function cloneTraffleCampaign(app: IApp, platform: EPlatform, addDefaultSt
|
|
|
461
564
|
await keitaroApi.post('streams', cloStream);
|
|
462
565
|
};
|
|
463
566
|
|
|
464
|
-
// Якщо знайдена існуюча кампанія
|
|
465
|
-
if (matchingCampaign.length > 0) {
|
|
466
|
-
const existingCampaign = matchingCampaign[0];
|
|
467
|
-
const existingStreams = await getStreamsByCampaignId(existingCampaign.id);
|
|
468
|
-
|
|
469
|
-
// Завжди оновлюємо CLO потік
|
|
470
|
-
await updateOrCreateCLOStream(existingCampaign.id, existingStreams);
|
|
471
|
-
|
|
472
|
-
// Для інших потоків
|
|
473
|
-
if (addDefaultStreams) {
|
|
474
|
-
for (const stream of originalStreams) {
|
|
475
|
-
if (stream.name === "CLO") continue; // Пропускаємо CLO
|
|
476
|
-
|
|
477
|
-
const existingStream = existingStreams.find(s => s.name === stream.name);
|
|
478
|
-
if (!existingStream) {
|
|
479
|
-
await createStreamWithoutIds(stream, existingCampaign.id);
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
console.log(existingCampaign)
|
|
485
|
-
return existingCampaign;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
567
|
// Створення нової кампанії
|
|
491
568
|
let alias = generateAlias();
|
|
492
569
|
|
|
493
|
-
|
|
494
|
-
|
|
495
570
|
console.log(group)
|
|
496
571
|
|
|
497
572
|
let payload: Partial<IKeitaroCampaign> = {
|
package/test-keitaro.js
CHANGED
|
@@ -1,49 +1,43 @@
|
|
|
1
1
|
const { TraffleKeitaroService } = require('./lib/network/keitaro/traffle/traffle-keitaro-service');
|
|
2
2
|
const { EPlatform } = require('./lib/app/app');
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
//
|
|
4
|
+
async function testClone() {
|
|
5
|
+
try {
|
|
6
|
+
// Тестові дані для створення кампанії
|
|
7
|
+
const testApp = {
|
|
8
|
+
id: 901,
|
|
9
|
+
bundle: "com.test.app",
|
|
10
|
+
name: "Test App",
|
|
11
|
+
platforms: {
|
|
12
|
+
'@': {
|
|
13
|
+
geo: ["UA", "RU", "US"],
|
|
14
|
+
appsflyerParams: {
|
|
15
|
+
apiToken: "test_token",
|
|
16
|
+
devKey: "test_dev_key"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
domainParams: {
|
|
21
|
+
name: "test.com"
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Створюємо Traffle кампанію
|
|
26
|
+
const result = await TraffleKeitaroService.cloneTraffleCampaign(
|
|
27
|
+
testApp,
|
|
28
|
+
EPlatform.GENERAL,
|
|
29
|
+
true // addDefaultStreams
|
|
30
|
+
);
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
// testClone();
|
|
39
|
-
|
|
32
|
+
console.log('Cloned campaign:', result);
|
|
33
|
+
console.log(`domain`, result.domain.split('/')[2])
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.error('Error:', error);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
40
38
|
|
|
39
|
+
testClone();
|
|
41
40
|
|
|
42
41
|
|
|
43
|
-
async function testC() {
|
|
44
42
|
|
|
45
|
-
const createGroup = await TraffleKeitaroService.createGroup("727", "campaigns")
|
|
46
|
-
console.log(`createGroup`, createGroup)
|
|
47
|
-
}
|
|
48
43
|
|
|
49
|
-
testC()
|