@bprotsyk/aso-core 2.1.87 → 2.1.97
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/lib/general/domain.d.ts +0 -1
- package/lib/general/namecheap-domain.d.ts +0 -1
- package/lib/keitaro/keitaro-conversions.d.ts +52 -0
- package/lib/keitaro/keitaro-conversions.js +27 -0
- package/lib/keitaro/keitaro-utils.d.ts +2 -0
- package/lib/keitaro/keitaro-utils.js +108 -0
- package/lib/keitaro-utils.d.ts +2 -0
- package/lib/keitaro-utils.js +136 -0
- package/lib/network/keitaro/traffle/http.d.ts +2 -0
- package/lib/network/keitaro/traffle/http.js +12 -0
- package/lib/network/keitaro/traffle/traffle-keitaro-service.d.ts +47 -0
- package/lib/network/keitaro/traffle/traffle-keitaro-service.js +107 -0
- package/lib/network/openai/openai.d.ts +5 -0
- package/lib/network/openai/openai.js +27 -0
- package/lib/offers/list.d.ts +4 -1
- package/lib/offers/list.js +4 -0
- package/lib/offers/offer.d.ts +0 -1
- package/lib/offers/section.d.ts +0 -1
- package/lib/panel/user.d.ts +0 -1
- package/lib/utils/comparing.d.ts +31 -0
- package/lib/utils/comparing.js +104 -0
- package/lib/utils/keitaro-utils.js +4 -1
- package/lib/utils/traffle-keitaro-utils.d.ts +1 -0
- package/lib/utils/traffle-keitaro-utils.js +50 -0
- package/package.json +2 -1
- package/src/network/keitaro/traffle/http.ts +8 -0
- package/src/network/keitaro/traffle/traffle-keitaro-service.ts +152 -0
- package/src/network/openai/openai.ts +26 -0
- package/src/offers/list.ts +5 -0
- package/src/utils/keitaro-utils.ts +8 -5
- package/src/utils/traffle-keitaro-utils.ts +67 -0
package/lib/general/domain.d.ts
CHANGED
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
/// <reference types="mongoose/types/validation" />
|
|
23
23
|
/// <reference types="mongoose/types/virtuals" />
|
|
24
24
|
/// <reference types="mongoose/types/inferschematype" />
|
|
25
|
-
/// <reference types="mongoose/types/inferrawdoctype" />
|
|
26
25
|
import { ICloudflareDomainType } from "general/cloudflare-domain";
|
|
27
26
|
import { Document, Model, Schema } from "mongoose";
|
|
28
27
|
export interface IDomain extends Document {
|
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
/// <reference types="mongoose/types/validation" />
|
|
23
23
|
/// <reference types="mongoose/types/virtuals" />
|
|
24
24
|
/// <reference types="mongoose/types/inferschematype" />
|
|
25
|
-
/// <reference types="mongoose/types/inferrawdoctype" />
|
|
26
25
|
import { Schema, Document } from "mongoose";
|
|
27
26
|
export interface INamecheapDomain {
|
|
28
27
|
ID: string;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { KeitaroClicksInterval } from './keitaro-clicks';
|
|
2
|
+
export declare enum KeitaroOperator {
|
|
3
|
+
EQUALS = "EQUALS",
|
|
4
|
+
NOT_EQUAL = "NOT_EQUAL",
|
|
5
|
+
EQUALS_OR_GREATER_THAN = "EQUALS_OR_GREATER_THAN",
|
|
6
|
+
EQUALS_OR_LESS_THAN = "EQUALS_OR_LESS_THAN",
|
|
7
|
+
GREATER_THAN = "GREATER_THAN",
|
|
8
|
+
LESS_THAN = "LESS_THAN",
|
|
9
|
+
MATCH_REGEXP = "MATCH_REGEXP",
|
|
10
|
+
NOT_MATCH_REGEXP = "NOT_MATCH_REGEXP",
|
|
11
|
+
BEGINS_WITH = "BEGINS_WITH",
|
|
12
|
+
ENDS_WITH = "ENDS_WITH",
|
|
13
|
+
CONTAINS = "CONTAINS",
|
|
14
|
+
NOT_CONTAIN = "NOT_CONTAIN",
|
|
15
|
+
IN_LIST = "IN_LIST",
|
|
16
|
+
NOT_IN_LIST = "NOT_IN_LIST",
|
|
17
|
+
BETWEEN = "BETWEEN",
|
|
18
|
+
IS_SET = "IS_SET",
|
|
19
|
+
IS_NOT_SET = "IS_NOT_SET",
|
|
20
|
+
IS_TRUE = "IS_TRUE",
|
|
21
|
+
IS_FALSE = "IS_FALSE",
|
|
22
|
+
HAS_LABEL = "HAS_LABEL",
|
|
23
|
+
NOT_HAS_LABEL = "NOT_HAS_LABEL"
|
|
24
|
+
}
|
|
25
|
+
export interface IKeitaroConversionRangeRequest {
|
|
26
|
+
from?: string;
|
|
27
|
+
to?: string;
|
|
28
|
+
timezone?: string;
|
|
29
|
+
interval?: KeitaroClicksInterval;
|
|
30
|
+
}
|
|
31
|
+
export interface IKeitaroConversionFilterRequest {
|
|
32
|
+
name: string;
|
|
33
|
+
operator: KeitaroOperator;
|
|
34
|
+
expression?: string | number | Array<string | number>;
|
|
35
|
+
}
|
|
36
|
+
export interface IKeitaroConversionSortRequest {
|
|
37
|
+
name: string;
|
|
38
|
+
order: 'ASC' | 'DESC';
|
|
39
|
+
}
|
|
40
|
+
export interface IKeitaroConversionsRequest {
|
|
41
|
+
range: IKeitaroConversionRangeRequest;
|
|
42
|
+
limit?: number;
|
|
43
|
+
offset?: number;
|
|
44
|
+
columns?: string[];
|
|
45
|
+
filters?: IKeitaroConversionFilterRequest[];
|
|
46
|
+
sort?: IKeitaroConversionSortRequest[];
|
|
47
|
+
}
|
|
48
|
+
export interface IKeitaroConversionsResponse {
|
|
49
|
+
rows: any[];
|
|
50
|
+
total: number;
|
|
51
|
+
meta: string[];
|
|
52
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KeitaroOperator = void 0;
|
|
4
|
+
var KeitaroOperator;
|
|
5
|
+
(function (KeitaroOperator) {
|
|
6
|
+
KeitaroOperator["EQUALS"] = "EQUALS";
|
|
7
|
+
KeitaroOperator["NOT_EQUAL"] = "NOT_EQUAL";
|
|
8
|
+
KeitaroOperator["EQUALS_OR_GREATER_THAN"] = "EQUALS_OR_GREATER_THAN";
|
|
9
|
+
KeitaroOperator["EQUALS_OR_LESS_THAN"] = "EQUALS_OR_LESS_THAN";
|
|
10
|
+
KeitaroOperator["GREATER_THAN"] = "GREATER_THAN";
|
|
11
|
+
KeitaroOperator["LESS_THAN"] = "LESS_THAN";
|
|
12
|
+
KeitaroOperator["MATCH_REGEXP"] = "MATCH_REGEXP";
|
|
13
|
+
KeitaroOperator["NOT_MATCH_REGEXP"] = "NOT_MATCH_REGEXP";
|
|
14
|
+
KeitaroOperator["BEGINS_WITH"] = "BEGINS_WITH";
|
|
15
|
+
KeitaroOperator["ENDS_WITH"] = "ENDS_WITH";
|
|
16
|
+
KeitaroOperator["CONTAINS"] = "CONTAINS";
|
|
17
|
+
KeitaroOperator["NOT_CONTAIN"] = "NOT_CONTAIN";
|
|
18
|
+
KeitaroOperator["IN_LIST"] = "IN_LIST";
|
|
19
|
+
KeitaroOperator["NOT_IN_LIST"] = "NOT_IN_LIST";
|
|
20
|
+
KeitaroOperator["BETWEEN"] = "BETWEEN";
|
|
21
|
+
KeitaroOperator["IS_SET"] = "IS_SET";
|
|
22
|
+
KeitaroOperator["IS_NOT_SET"] = "IS_NOT_SET";
|
|
23
|
+
KeitaroOperator["IS_TRUE"] = "IS_TRUE";
|
|
24
|
+
KeitaroOperator["IS_FALSE"] = "IS_FALSE";
|
|
25
|
+
KeitaroOperator["HAS_LABEL"] = "HAS_LABEL";
|
|
26
|
+
KeitaroOperator["NOT_HAS_LABEL"] = "NOT_HAS_LABEL";
|
|
27
|
+
})(KeitaroOperator = exports.KeitaroOperator || (exports.KeitaroOperator = {}));
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.displayComparisonResults = void 0;
|
|
4
|
+
function displayComparisonResults(comparison) {
|
|
5
|
+
const isValidStatus = (status) => ['sale', 'rebill'].includes(status);
|
|
6
|
+
let wpTotalSum = comparison.wpConversions
|
|
7
|
+
.reduce((sum, conv) => sum + conv.sum, 0);
|
|
8
|
+
let keitaroTotalSum = comparison.keitaroConversions
|
|
9
|
+
.filter(conv => isValidStatus(conv.status))
|
|
10
|
+
.reduce((sum, conv) => sum + (parseFloat(conv.revenue) || 0), 0);
|
|
11
|
+
// Get all Keitaro rejected conversions
|
|
12
|
+
const allKeitaroRejected = [
|
|
13
|
+
...comparison.rejected.keitaro,
|
|
14
|
+
...comparison.matches
|
|
15
|
+
.filter(match => match.keitaro.status === 'rejected')
|
|
16
|
+
.map(match => match.keitaro)
|
|
17
|
+
];
|
|
18
|
+
// Group mismatches by project/offer
|
|
19
|
+
const wpMismatchesByProject = new Map();
|
|
20
|
+
const keitaroMismatchesByOffer = new Map();
|
|
21
|
+
const rejectedByOffer = new Map();
|
|
22
|
+
comparison.mismatches.onlyInWP.forEach(conv => {
|
|
23
|
+
if (!wpMismatchesByProject.has(conv.project)) {
|
|
24
|
+
wpMismatchesByProject.set(conv.project, { count: 0, sum: 0, conversions: [] });
|
|
25
|
+
}
|
|
26
|
+
const projectStats = wpMismatchesByProject.get(conv.project);
|
|
27
|
+
projectStats.count++;
|
|
28
|
+
projectStats.sum += conv.sum;
|
|
29
|
+
projectStats.conversions.push(conv);
|
|
30
|
+
});
|
|
31
|
+
// Include all conversions in mismatches, including rejected ones
|
|
32
|
+
[...comparison.mismatches.onlyInKeitaro, ...allKeitaroRejected].forEach(conv => {
|
|
33
|
+
if (!keitaroMismatchesByOffer.has(conv.offer)) {
|
|
34
|
+
keitaroMismatchesByOffer.set(conv.offer, { count: 0, sum: 0, conversions: [] });
|
|
35
|
+
}
|
|
36
|
+
const offerStats = keitaroMismatchesByOffer.get(conv.offer);
|
|
37
|
+
offerStats.count++;
|
|
38
|
+
offerStats.sum += parseFloat(conv.revenue) || 0;
|
|
39
|
+
offerStats.conversions.push(conv);
|
|
40
|
+
});
|
|
41
|
+
// Group rejected conversions by offer
|
|
42
|
+
allKeitaroRejected.forEach(conv => {
|
|
43
|
+
if (!rejectedByOffer.has(conv.offer)) {
|
|
44
|
+
rejectedByOffer.set(conv.offer, { count: 0, sum: 0, conversions: [] });
|
|
45
|
+
}
|
|
46
|
+
const offerStats = rejectedByOffer.get(conv.offer);
|
|
47
|
+
offerStats.count++;
|
|
48
|
+
offerStats.sum += parseFloat(conv.revenue) || 0;
|
|
49
|
+
offerStats.conversions.push(conv);
|
|
50
|
+
});
|
|
51
|
+
console.log('\n\x1b[1mЗагальна статистика:\x1b[0m');
|
|
52
|
+
console.log(`Всього конверсій у WP: ${comparison.wpConversions.length} (Сума: \x1b[33m$${wpTotalSum.toFixed(2)}\x1b[0m)`);
|
|
53
|
+
console.log(`Всього конверсій у Keitaro: ${comparison.keitaroConversions.filter(conv => isValidStatus(conv.status)).length} (Сума: \x1b[33m$${keitaroTotalSum.toFixed(2)}\x1b[0m)`);
|
|
54
|
+
console.log(`Співпадінь: ${comparison.matches.length}`);
|
|
55
|
+
console.log(`Відхилених конверсій: ${allKeitaroRejected.length}`);
|
|
56
|
+
const totalDiff = Math.abs(wpTotalSum - keitaroTotalSum);
|
|
57
|
+
console.log(`\x1b[1mЗагальна різниця:\x1b[0m \x1b[33m$${totalDiff.toFixed(2)}\x1b[0m`);
|
|
58
|
+
// Always show rejected conversions first if there are any
|
|
59
|
+
if (allKeitaroRejected.length > 0) {
|
|
60
|
+
const rejectedTotal = allKeitaroRejected.reduce((sum, conv) => sum + (parseFloat(conv.revenue) || 0), 0);
|
|
61
|
+
console.log('\n\x1b[1mВідхилені конверсії в Keitaro за офферами:\x1b[0m');
|
|
62
|
+
console.log(`Загальна кількість: ${allKeitaroRejected.length}`);
|
|
63
|
+
console.log(`Загальна сума: \x1b[33m$${rejectedTotal.toFixed(2)}\x1b[0m`);
|
|
64
|
+
for (const [offer, stats] of rejectedByOffer.entries()) {
|
|
65
|
+
console.log(`\n\x1b[33m${offer}:\x1b[0m`);
|
|
66
|
+
console.log(`Кількість: ${stats.count}, Сума: $${stats.sum.toFixed(2)}`);
|
|
67
|
+
stats.conversions.forEach(conv => {
|
|
68
|
+
const matchMark = comparison.matches.some(match => match.keitaro.sub_id === conv.sub_id) ? '[matched] ' : '';
|
|
69
|
+
console.log(` ${matchMark}${conv.sub_id} | ${conv.sale_datetime.split(' ')[0]} | $${conv.revenue}`);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
console.log('\n\x1b[1mВідсутні в Keitaro за проектами:\x1b[0m');
|
|
74
|
+
for (const [project, stats] of wpMismatchesByProject) {
|
|
75
|
+
console.log(`\n\x1b[31m${project}:\x1b[0m`);
|
|
76
|
+
console.log(`Кількість: ${stats.count}, Сума: $${stats.sum.toFixed(2)}`);
|
|
77
|
+
stats.conversions.forEach(conv => {
|
|
78
|
+
console.log(` ${conv.clickId} | ${conv.regDate.toISOString().split('T')[0]} | $${conv.sum}`);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
console.log('\n\x1b[1mВідсутні в WP за офферами:\x1b[0m');
|
|
82
|
+
for (const [offer, stats] of keitaroMismatchesByOffer) {
|
|
83
|
+
console.log(`\n\x1b[32m${offer}:\x1b[0m`);
|
|
84
|
+
console.log(`Кількість: ${stats.count}, Сума: $${stats.sum.toFixed(2)}`);
|
|
85
|
+
stats.conversions.forEach(conv => {
|
|
86
|
+
const statusMark = conv.status === 'rejected' ? '(rejected) ' : '';
|
|
87
|
+
const matchMark = comparison.matches.some(match => match.keitaro.sub_id === conv.sub_id) ? '[matched] ' : '';
|
|
88
|
+
console.log(` ${statusMark}${matchMark}${conv.sub_id} | ${conv.sale_datetime.split(' ')[0]} | $${conv.revenue}`);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
let mismatchWPSum = comparison.mismatches.onlyInWP
|
|
92
|
+
.reduce((sum, conv) => sum + conv.sum, 0);
|
|
93
|
+
let mismatchKeitaroSum = [...comparison.mismatches.onlyInKeitaro, ...allKeitaroRejected]
|
|
94
|
+
.reduce((sum, conv) => sum + (parseFloat(conv.revenue) || 0), 0);
|
|
95
|
+
console.log('\n\x1b[1mПідсумок розбіжностей:\x1b[0m');
|
|
96
|
+
console.log(`Сума відсутніх в Keitaro: \x1b[31m$${mismatchWPSum.toFixed(2)}\x1b[0m`);
|
|
97
|
+
console.log(`Сума відсутніх в WP: \x1b[32m$${mismatchKeitaroSum.toFixed(2)}\x1b[0m`);
|
|
98
|
+
console.log(`Різниця у відсутніх конверсіях: \x1b[33m$${Math.abs(mismatchWPSum - mismatchKeitaroSum).toFixed(2)}\x1b[0m`);
|
|
99
|
+
// Debug information
|
|
100
|
+
const matchingRejected = comparison.matches.filter(match => match.keitaro.status === 'rejected').length;
|
|
101
|
+
console.log('\n\x1b[1mДебаг інформація:\x1b[0m');
|
|
102
|
+
console.log(`Кількість конверсій відсутніх в WP: ${comparison.mismatches.onlyInKeitaro.length + comparison.rejected.keitaro.length + matchingRejected}`);
|
|
103
|
+
console.log(`З них:`);
|
|
104
|
+
console.log(`- Активних: ${comparison.mismatches.onlyInKeitaro.length}`);
|
|
105
|
+
console.log(`- Відхилених (унікальних): ${comparison.rejected.keitaro.length}`);
|
|
106
|
+
console.log(`- Відхилених (що є в WP): ${matchingRejected}`);
|
|
107
|
+
}
|
|
108
|
+
exports.displayComparisonResults = displayComparisonResults;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.displayComparisonResults = void 0;
|
|
27
|
+
const keitaro_service_1 = require("./network/keitaro/keitaro-service");
|
|
28
|
+
const keitaro_conversions_1 = require("./keitaro/keitaro-conversions");
|
|
29
|
+
const path = __importStar(require("path"));
|
|
30
|
+
const comparing_1 = require("./utils/comparing");
|
|
31
|
+
function displayComparisonResults(comparison) {
|
|
32
|
+
const isValidStatus = (status) => ['sale', 'rebill'].includes(status);
|
|
33
|
+
// Считаем общие суммы
|
|
34
|
+
let wpTotalSum = comparison.wpConversions
|
|
35
|
+
.reduce((sum, conv) => sum + conv.sum, 0);
|
|
36
|
+
let keitaroTotalSum = comparison.keitaroConversions
|
|
37
|
+
.filter((conv) => isValidStatus(conv.status))
|
|
38
|
+
.reduce((sum, conv) => sum + (parseFloat(conv.revenue) || 0), 0);
|
|
39
|
+
// Находим разницу
|
|
40
|
+
const totalDiff = keitaroTotalSum - wpTotalSum;
|
|
41
|
+
console.log('\n\x1b[1mЗагальна статистика:\x1b[0m');
|
|
42
|
+
console.log(`WP сума: $${wpTotalSum.toFixed(2)}`);
|
|
43
|
+
console.log(`Keitaro сума: $${keitaroTotalSum.toFixed(2)}`);
|
|
44
|
+
console.log(`Різниця: $${totalDiff.toFixed(2)}`);
|
|
45
|
+
// Получаем конверсии, которые есть в Keitaro, но нет в WP
|
|
46
|
+
const extraKeitaroConversions = comparison.mismatches.onlyInKeitaro
|
|
47
|
+
.filter(conv => isValidStatus(conv.status))
|
|
48
|
+
.sort((a, b) => (parseFloat(b.revenue) || 0) - (parseFloat(a.revenue) || 0));
|
|
49
|
+
// Группируем по офферам для удобства
|
|
50
|
+
const byOffer = new Map();
|
|
51
|
+
extraKeitaroConversions.forEach(conv => {
|
|
52
|
+
const offer = conv.offer || 'Unknown Offer';
|
|
53
|
+
if (!byOffer.has(offer)) {
|
|
54
|
+
byOffer.set(offer, { count: 0, sum: 0, conversions: [] });
|
|
55
|
+
}
|
|
56
|
+
const stats = byOffer.get(offer);
|
|
57
|
+
const revenue = parseFloat(conv.revenue) || 0;
|
|
58
|
+
stats.count++;
|
|
59
|
+
stats.sum += revenue;
|
|
60
|
+
stats.conversions.push(conv);
|
|
61
|
+
});
|
|
62
|
+
console.log('\n\x1b[1mКонверсії, які є в Keitaro, але відсутні в WP:\x1b[0m');
|
|
63
|
+
let totalExtraSum = 0;
|
|
64
|
+
for (const [offer, stats] of byOffer) {
|
|
65
|
+
console.log(`\n\x1b[33m${offer}:\x1b[0m`);
|
|
66
|
+
console.log(`Кількість: ${stats.count}, Сума: $${stats.sum.toFixed(2)}`);
|
|
67
|
+
stats.conversions.forEach(conv => {
|
|
68
|
+
if (conv.sub_id && conv.revenue) {
|
|
69
|
+
console.log(` ${conv.sub_id} | ${conv.revenue}`);
|
|
70
|
+
totalExtraSum += parseFloat(conv.revenue) || 0;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
console.log('\n\x1b[1mПідсумок:\x1b[0m');
|
|
75
|
+
console.log(`Загальна сума "зайвих" конверсій: \x1b[33m$${totalExtraSum.toFixed(2)}\x1b[0m`);
|
|
76
|
+
console.log('Це конверсії, які потрібно видалити з Keitaro, щоб суми співпадали з WP');
|
|
77
|
+
}
|
|
78
|
+
exports.displayComparisonResults = displayComparisonResults;
|
|
79
|
+
// Self-executing function to fetch and compare conversions
|
|
80
|
+
(async () => {
|
|
81
|
+
const request = {
|
|
82
|
+
range: {
|
|
83
|
+
from: '2025-01-01',
|
|
84
|
+
to: '2025-01-31',
|
|
85
|
+
timezone: 'Europe/Kyiv'
|
|
86
|
+
},
|
|
87
|
+
filters: [
|
|
88
|
+
{
|
|
89
|
+
name: 'status',
|
|
90
|
+
operator: keitaro_conversions_1.KeitaroOperator.IN_LIST,
|
|
91
|
+
expression: ['sale', 'rejected']
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: 'affiliate_network_id',
|
|
95
|
+
operator: keitaro_conversions_1.KeitaroOperator.EQUALS,
|
|
96
|
+
expression: 2
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
columns: [
|
|
100
|
+
'sign', 'version', 'campaign', 'campaign_group', 'landing_group', 'offer_group',
|
|
101
|
+
'landing', 'offer', 'affiliate_network', 'ts', 'stream', 'source',
|
|
102
|
+
'x_requested_with', 'referrer', 'search_engine', 'keyword', 'click_id',
|
|
103
|
+
'sub_id', 'visitor_code', 'campaign_id', 'campaign_group_id', 'offer_group_id',
|
|
104
|
+
'landing_group_id', 'landing_id', 'offer_id', 'affiliate_network_id', 'ts_id',
|
|
105
|
+
'stream_id', 'ad_campaign_id', 'external_id', 'creative_id',
|
|
106
|
+
'sub_id_1', 'sub_id_2', 'sub_id_3', 'sub_id_4', 'sub_id_5',
|
|
107
|
+
'sub_id_6', 'sub_id_7', 'sub_id_8', 'sub_id_9', 'sub_id_10',
|
|
108
|
+
'sub_id_11', 'sub_id_12', 'sub_id_13', 'sub_id_14', 'sub_id_15',
|
|
109
|
+
'sub_id_16', 'sub_id_17', 'sub_id_18', 'sub_id_19', 'sub_id_20',
|
|
110
|
+
'sub_id_21', 'sub_id_22', 'sub_id_23', 'sub_id_24', 'sub_id_25',
|
|
111
|
+
'sub_id_26', 'sub_id_27', 'sub_id_28', 'sub_id_29', 'sub_id_30',
|
|
112
|
+
'connection_type', 'operator', 'isp', 'country_code', 'country_flag',
|
|
113
|
+
'country', 'region', 'region_code', 'city', 'language', 'device_type',
|
|
114
|
+
'user_agent', 'os_icon', 'os', 'os_version', 'browser', 'browser_version',
|
|
115
|
+
'device_model', 'browser_icon', 'ip', 'ip_mask1', 'ip_mask2', 'ipv4only',
|
|
116
|
+
'ipv6only', 'cost', 'postback_datetime', 'sale_datetime', 'click_datetime',
|
|
117
|
+
'sale_period', 'status', 'previous_status', 'original_status',
|
|
118
|
+
'previous_conversion_id', 'params', 'conversion_id', 'tid',
|
|
119
|
+
'profitability', 'revenue', 'profit'
|
|
120
|
+
],
|
|
121
|
+
sort: [{
|
|
122
|
+
name: 'sale_datetime',
|
|
123
|
+
order: 'DESC'
|
|
124
|
+
}]
|
|
125
|
+
};
|
|
126
|
+
try {
|
|
127
|
+
const conversions = await keitaro_service_1.KeitaroService.getConversions(request);
|
|
128
|
+
const wpFilePath = path.join(process.cwd(), 'src', 'utils', 'wp-january.csv');
|
|
129
|
+
const comparison = await (0, comparing_1.compareConversions)(wpFilePath, conversions);
|
|
130
|
+
// Use our improved display function
|
|
131
|
+
displayComparisonResults(comparison);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
console.error('Error fetching conversions:', error);
|
|
135
|
+
}
|
|
136
|
+
})();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const axios_1 = __importDefault(require("axios"));
|
|
7
|
+
exports.default = axios_1.default.create({
|
|
8
|
+
baseURL: 'https://traffle-tech.com/admin_api/v1/',
|
|
9
|
+
headers: {
|
|
10
|
+
"Api-Key": `3e80a8fcf1ceb01a761457d017e43a0a`,
|
|
11
|
+
},
|
|
12
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { IOffer } from "../../../offers/offer";
|
|
2
|
+
import { IKeitaroOffer } from "index";
|
|
3
|
+
declare function getAllOffers(): Promise<IKeitaroOffer[]>;
|
|
4
|
+
export declare enum ITraffleTrafficType {
|
|
5
|
+
ASO = "ASO",
|
|
6
|
+
INAPP = "INAPP"
|
|
7
|
+
}
|
|
8
|
+
export interface ITraffleOffer {
|
|
9
|
+
offer: Partial<IOffer>;
|
|
10
|
+
link: string;
|
|
11
|
+
partnerName: string;
|
|
12
|
+
trafficType: ITraffleTrafficType;
|
|
13
|
+
}
|
|
14
|
+
export interface IAffiliateNetwork {
|
|
15
|
+
id: number;
|
|
16
|
+
name: string;
|
|
17
|
+
postback_url: string;
|
|
18
|
+
offer_param: string;
|
|
19
|
+
state: "active" | "deleted";
|
|
20
|
+
template_name: string;
|
|
21
|
+
notes: string;
|
|
22
|
+
pull_api_options: string;
|
|
23
|
+
created_at: string;
|
|
24
|
+
updated_at: string;
|
|
25
|
+
offers: number;
|
|
26
|
+
}
|
|
27
|
+
declare function getTraffleOffersGroups(): Promise<any[]>;
|
|
28
|
+
declare function createGroup(name: string, type: "campaigns" | "offers" | "landings" | "domains"): Promise<{
|
|
29
|
+
id: number;
|
|
30
|
+
name: string;
|
|
31
|
+
position: number;
|
|
32
|
+
type: string;
|
|
33
|
+
}>;
|
|
34
|
+
declare function getTraffleAffiliateNetworks(): Promise<IAffiliateNetwork[]>;
|
|
35
|
+
declare function deleteOfferById(id: number): Promise<any>;
|
|
36
|
+
declare function addOffersToTraffleKeitaro(offers: ITraffleOffer[]): Promise<void>;
|
|
37
|
+
declare function updateOfferLinkById(id: number, action_payload: string | object): Promise<any>;
|
|
38
|
+
export declare const TraffleKeitaroService: {
|
|
39
|
+
addOffersToTraffleKeitaro: typeof addOffersToTraffleKeitaro;
|
|
40
|
+
getTraffleOffersGroups: typeof getTraffleOffersGroups;
|
|
41
|
+
getTraffleAffiliateNetworks: typeof getTraffleAffiliateNetworks;
|
|
42
|
+
createGroup: typeof createGroup;
|
|
43
|
+
deleteOfferById: typeof deleteOfferById;
|
|
44
|
+
getAllOffers: typeof getAllOffers;
|
|
45
|
+
updateOfferLinkById: typeof updateOfferLinkById;
|
|
46
|
+
};
|
|
47
|
+
export {};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TraffleKeitaroService = exports.ITraffleTrafficType = void 0;
|
|
7
|
+
const http_1 = __importDefault(require("./http"));
|
|
8
|
+
const openai_1 = require("../../../network/openai/openai");
|
|
9
|
+
async function getAllOffers() {
|
|
10
|
+
const { data: offers } = await http_1.default.get('offers');
|
|
11
|
+
return offers;
|
|
12
|
+
}
|
|
13
|
+
var ITraffleTrafficType;
|
|
14
|
+
(function (ITraffleTrafficType) {
|
|
15
|
+
ITraffleTrafficType["ASO"] = "ASO";
|
|
16
|
+
ITraffleTrafficType["INAPP"] = "INAPP";
|
|
17
|
+
})(ITraffleTrafficType = exports.ITraffleTrafficType || (exports.ITraffleTrafficType = {}));
|
|
18
|
+
async function getTraffleOffersGroups() {
|
|
19
|
+
try {
|
|
20
|
+
const response = await http_1.default.get('/groups?type=offers');
|
|
21
|
+
console.log(response.config.url);
|
|
22
|
+
return response.data;
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
console.error("Error fetching groups:", error);
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async function createGroup(name, type) {
|
|
30
|
+
try {
|
|
31
|
+
const response = await http_1.default.post('/groups', {
|
|
32
|
+
name: name,
|
|
33
|
+
type: type
|
|
34
|
+
});
|
|
35
|
+
return response.data;
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.error("Error creating group:", error);
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function getTraffleAffiliateNetworks() {
|
|
43
|
+
try {
|
|
44
|
+
const { data: networks } = await http_1.default.get('/affiliate_networks');
|
|
45
|
+
return networks;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.error("Error fetching affiliate networks:", error);
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function findMatchingAffiliateId(affiliateNetworks, offer) {
|
|
53
|
+
let affialiateOpenAIResponse = await openai_1.OpenAI.requestOpenAI({
|
|
54
|
+
model: "o3-mini",
|
|
55
|
+
messages: [
|
|
56
|
+
{ role: "user", content: `Find id of affialiate with name [${offer.partnerName}] (can be slightly different, case or typing) in [${JSON.stringify(affiliateNetworks.map(affiliateNetwork => { return { name: affiliateNetwork.name, id: affiliateNetwork.id }; }))}]; Respond with raw JSON object of affiliate network` },
|
|
57
|
+
]
|
|
58
|
+
});
|
|
59
|
+
if (!affialiateOpenAIResponse) {
|
|
60
|
+
console.error("No response from OpenAI");
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
let network = JSON.parse(affialiateOpenAIResponse);
|
|
64
|
+
console.log(network);
|
|
65
|
+
return network.id;
|
|
66
|
+
}
|
|
67
|
+
function findMatchingOffersGroup(offersGroups, offer) {
|
|
68
|
+
return 1037;
|
|
69
|
+
}
|
|
70
|
+
async function deleteOfferById(id) {
|
|
71
|
+
const response = await http_1.default.delete(`/offers/${id}/archive`);
|
|
72
|
+
return response.data;
|
|
73
|
+
}
|
|
74
|
+
async function addOffersToTraffleKeitaro(offers) {
|
|
75
|
+
const allOffers = await getAllOffers();
|
|
76
|
+
let offersGroups = await getTraffleOffersGroups();
|
|
77
|
+
let affiliateNetworks = await getTraffleAffiliateNetworks();
|
|
78
|
+
for (let i = 0; i < offers.length; i++) {
|
|
79
|
+
const offer = offers[i];
|
|
80
|
+
let name = `${offer.offer.caption} ${offer.offer.geo} [el trafico] ${offer.trafficType}`;
|
|
81
|
+
const identicalOffer = allOffers.find(o => o.name.includes(name));
|
|
82
|
+
let offersGroupId = findMatchingOffersGroup(offersGroups, offer);
|
|
83
|
+
let affiliateId = await findMatchingAffiliateId(affiliateNetworks, offer);
|
|
84
|
+
if (!identicalOffer) {
|
|
85
|
+
const offerPayload = {
|
|
86
|
+
name: name,
|
|
87
|
+
group_id: offersGroupId || 1,
|
|
88
|
+
action_payload: offer.link,
|
|
89
|
+
affiliate_network_id: affiliateId,
|
|
90
|
+
country: [offer.offer.geo],
|
|
91
|
+
action_type: "http",
|
|
92
|
+
offer_type: "external",
|
|
93
|
+
payout_auto: true,
|
|
94
|
+
payout_upsell: true,
|
|
95
|
+
};
|
|
96
|
+
await http_1.default.post('offers', offerPayload);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function updateOfferLinkById(id, action_payload) {
|
|
101
|
+
const updateData = { action_payload };
|
|
102
|
+
const response = await http_1.default.put(`/offers/${id}`, updateData);
|
|
103
|
+
return response.data;
|
|
104
|
+
}
|
|
105
|
+
exports.TraffleKeitaroService = {
|
|
106
|
+
addOffersToTraffleKeitaro, getTraffleOffersGroups, getTraffleAffiliateNetworks, createGroup, deleteOfferById, getAllOffers, updateOfferLinkById
|
|
107
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.OpenAI = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const OPENAI_API_KEY = "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";
|
|
9
|
+
async function requestOpenAI(data) {
|
|
10
|
+
try {
|
|
11
|
+
const response = await axios_1.default.post('https://api.openai.com/v1/chat/completions', data, {
|
|
12
|
+
headers: {
|
|
13
|
+
Authorization: `Bearer ${OPENAI_API_KEY}`,
|
|
14
|
+
'Content-Type': 'application/json',
|
|
15
|
+
},
|
|
16
|
+
timeout: 120000,
|
|
17
|
+
responseType: 'json',
|
|
18
|
+
});
|
|
19
|
+
return response.data.choices[0].message.content;
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
console.error(e);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.OpenAI = {
|
|
26
|
+
requestOpenAI
|
|
27
|
+
};
|
package/lib/offers/list.d.ts
CHANGED
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
/// <reference types="mongoose/types/validation" />
|
|
23
23
|
/// <reference types="mongoose/types/virtuals" />
|
|
24
24
|
/// <reference types="mongoose/types/inferschematype" />
|
|
25
|
-
/// <reference types="mongoose/types/inferrawdoctype" />
|
|
26
25
|
import { Schema } from "mongoose";
|
|
27
26
|
export interface ISectionsList {
|
|
28
27
|
id: number;
|
|
28
|
+
name: string;
|
|
29
29
|
content: IAppOffersSection[];
|
|
30
30
|
}
|
|
31
31
|
export interface IOfferState {
|
|
@@ -40,6 +40,7 @@ export interface IAppOffersSection {
|
|
|
40
40
|
}
|
|
41
41
|
export declare const SectionsListSchema: Schema<any, import("mongoose").Model<any, any, any, any, any, any>, {}, {}, {}, {}, import("mongoose").DefaultSchemaOptions, {
|
|
42
42
|
id: number;
|
|
43
|
+
name: string;
|
|
43
44
|
content: import("mongoose").Types.DocumentArray<{
|
|
44
45
|
prototype?: {
|
|
45
46
|
constructor: {
|
|
@@ -172,6 +173,7 @@ export declare const SectionsListSchema: Schema<any, import("mongoose").Model<an
|
|
|
172
173
|
}>;
|
|
173
174
|
}, import("mongoose").Document<unknown, {}, import("mongoose").FlatRecord<{
|
|
174
175
|
id: number;
|
|
176
|
+
name: string;
|
|
175
177
|
content: import("mongoose").Types.DocumentArray<{
|
|
176
178
|
prototype?: {
|
|
177
179
|
constructor: {
|
|
@@ -304,6 +306,7 @@ export declare const SectionsListSchema: Schema<any, import("mongoose").Model<an
|
|
|
304
306
|
}>;
|
|
305
307
|
}>> & import("mongoose").FlatRecord<{
|
|
306
308
|
id: number;
|
|
309
|
+
name: string;
|
|
307
310
|
content: import("mongoose").Types.DocumentArray<{
|
|
308
311
|
prototype?: {
|
|
309
312
|
constructor: {
|
package/lib/offers/list.js
CHANGED
package/lib/offers/offer.d.ts
CHANGED
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
/// <reference types="mongoose/types/validation" />
|
|
23
23
|
/// <reference types="mongoose/types/virtuals" />
|
|
24
24
|
/// <reference types="mongoose/types/inferschematype" />
|
|
25
|
-
/// <reference types="mongoose/types/inferrawdoctype" />
|
|
26
25
|
import { Document, Model, Schema } from "mongoose";
|
|
27
26
|
export interface IOffer extends Document {
|
|
28
27
|
id: number;
|
package/lib/offers/section.d.ts
CHANGED
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
/// <reference types="mongoose/types/validation" />
|
|
23
23
|
/// <reference types="mongoose/types/virtuals" />
|
|
24
24
|
/// <reference types="mongoose/types/inferschematype" />
|
|
25
|
-
/// <reference types="mongoose/types/inferrawdoctype" />
|
|
26
25
|
import { Schema } from "mongoose";
|
|
27
26
|
export interface IOffersSection {
|
|
28
27
|
id: number;
|
package/lib/panel/user.d.ts
CHANGED
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
/// <reference types="mongoose/types/validation" />
|
|
23
23
|
/// <reference types="mongoose/types/virtuals" />
|
|
24
24
|
/// <reference types="mongoose/types/inferschematype" />
|
|
25
|
-
/// <reference types="mongoose/types/inferrawdoctype" />
|
|
26
25
|
import { Document, Schema } from "mongoose";
|
|
27
26
|
export declare enum PanelUserAccessScope {
|
|
28
27
|
ADMIN = 0,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface WPConversion {
|
|
2
|
+
status: string;
|
|
3
|
+
regDate: Date;
|
|
4
|
+
qualDate: Date;
|
|
5
|
+
approveOrRejectDate: Date;
|
|
6
|
+
project: string;
|
|
7
|
+
offerName: string;
|
|
8
|
+
sum: number;
|
|
9
|
+
currency: string;
|
|
10
|
+
geo: string;
|
|
11
|
+
subId?: string;
|
|
12
|
+
clickId: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ConversionComparison {
|
|
15
|
+
wpConversions: WPConversion[];
|
|
16
|
+
keitaroConversions: any[];
|
|
17
|
+
matches: {
|
|
18
|
+
wp: WPConversion;
|
|
19
|
+
keitaro: any;
|
|
20
|
+
}[];
|
|
21
|
+
mismatches: {
|
|
22
|
+
onlyInWP: WPConversion[];
|
|
23
|
+
onlyInKeitaro: any[];
|
|
24
|
+
};
|
|
25
|
+
rejected: {
|
|
26
|
+
wp: WPConversion[];
|
|
27
|
+
keitaro: any[];
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export declare function parseWPConversions(filePath: string): Promise<WPConversion[]>;
|
|
31
|
+
export declare function compareConversions(wpFilePath: string, keitaroConversions: any[]): Promise<ConversionComparison>;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.compareConversions = exports.parseWPConversions = void 0;
|
|
27
|
+
const sync_1 = require("csv-parse/sync");
|
|
28
|
+
const fs = __importStar(require("fs"));
|
|
29
|
+
function parseDate(dateStr) {
|
|
30
|
+
const [month, day, year] = dateStr.split('/').map(num => parseInt(num));
|
|
31
|
+
return new Date(2000 + year, month - 1, day);
|
|
32
|
+
}
|
|
33
|
+
async function parseWPConversions(filePath) {
|
|
34
|
+
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
35
|
+
const records = (0, sync_1.parse)(fileContent, {
|
|
36
|
+
delimiter: ';',
|
|
37
|
+
columns: true,
|
|
38
|
+
skip_empty_lines: true
|
|
39
|
+
});
|
|
40
|
+
return records.map((record) => ({
|
|
41
|
+
status: record.Status,
|
|
42
|
+
regDate: parseDate(record.RegDate),
|
|
43
|
+
qualDate: parseDate(record.QualDate),
|
|
44
|
+
approveOrRejectDate: parseDate(record.Approve_or_Reject_Date),
|
|
45
|
+
project: record.Project,
|
|
46
|
+
offerName: record.Offer_Name,
|
|
47
|
+
sum: parseFloat(record.Sum),
|
|
48
|
+
currency: record.Currency,
|
|
49
|
+
geo: record.Geo,
|
|
50
|
+
subId: record.Sub_ID || undefined,
|
|
51
|
+
clickId: record.Click_ID
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
exports.parseWPConversions = parseWPConversions;
|
|
55
|
+
async function compareConversions(wpFilePath, keitaroConversions) {
|
|
56
|
+
const wpConversions = await parseWPConversions(wpFilePath);
|
|
57
|
+
const matches = [];
|
|
58
|
+
const onlyInWP = [];
|
|
59
|
+
const onlyInKeitaro = [];
|
|
60
|
+
const rejectedWP = [];
|
|
61
|
+
const rejectedKeitaro = [];
|
|
62
|
+
// Create a map of Keitaro conversions by their sub_id to match with WP's Click_ID
|
|
63
|
+
const keitaroMap = new Map(keitaroConversions.map(conv => [conv.sub_id, conv]));
|
|
64
|
+
// First, find matches and conversions only in WP
|
|
65
|
+
for (const wpConv of wpConversions) {
|
|
66
|
+
// Skip rejected conversions
|
|
67
|
+
if (wpConv.status === 'Удержан') {
|
|
68
|
+
rejectedWP.push(wpConv);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const keitaroMatch = keitaroMap.get(wpConv.clickId);
|
|
72
|
+
if (keitaroMatch) {
|
|
73
|
+
matches.push({ wp: wpConv, keitaro: keitaroMatch });
|
|
74
|
+
keitaroMap.delete(wpConv.clickId);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
onlyInWP.push(wpConv);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Remaining conversions in keitaroMap are only in Keitaro
|
|
81
|
+
// We need to check their status before adding them to onlyInKeitaro
|
|
82
|
+
for (const [_, conv] of keitaroMap) {
|
|
83
|
+
if (conv.status === 'rejected') {
|
|
84
|
+
rejectedKeitaro.push(conv);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
onlyInKeitaro.push(conv);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
wpConversions: wpConversions.filter(conv => conv.status !== 'Удержан'),
|
|
92
|
+
keitaroConversions: keitaroConversions.filter(conv => conv.status !== 'rejected'),
|
|
93
|
+
matches,
|
|
94
|
+
mismatches: {
|
|
95
|
+
onlyInWP,
|
|
96
|
+
onlyInKeitaro
|
|
97
|
+
},
|
|
98
|
+
rejected: {
|
|
99
|
+
wp: rejectedWP,
|
|
100
|
+
keitaro: rejectedKeitaro
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
exports.compareConversions = compareConversions;
|
|
@@ -5,7 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.sendPostbacks = exports.createOWCampaign = exports.createDirectCampaign = exports.prepareOWCampaignParameters = exports.removeGeosFromAllRedirectCampaigns = exports.addGeosToAllRedirectCampaigns = exports.TRAFFIC_SOURCE_ID_FLASH_AI = void 0;
|
|
7
7
|
const keitaro_service_1 = require("../network/keitaro/keitaro-service");
|
|
8
|
-
const sleep = require('sleep-promise');
|
|
9
8
|
const axios_1 = __importDefault(require("axios"));
|
|
10
9
|
const keitaro_clicks_1 = require("../keitaro/keitaro-clicks");
|
|
11
10
|
const FLASH_REDIRECT_GROUP_ID = 82;
|
|
@@ -59,6 +58,10 @@ const COST_CURRENCY_USD = "USD";
|
|
|
59
58
|
// offerIdParameterName: "i",
|
|
60
59
|
// }
|
|
61
60
|
// } as IFlashApp
|
|
61
|
+
function sleep(ms) {
|
|
62
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
63
|
+
}
|
|
64
|
+
``;
|
|
62
65
|
let addGeosToAllRedirectCampaigns = async (geosToAdd) => {
|
|
63
66
|
let allCampaigns = await keitaro_service_1.KeitaroService.getAllCampaigns();
|
|
64
67
|
let regexp = new RegExp(`^F #`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const sleep = require('sleep-promise');
|
|
4
|
+
const traffle_keitaro_service_1 = require("../network/keitaro/traffle/traffle-keitaro-service");
|
|
5
|
+
(async () => {
|
|
6
|
+
await traffle_keitaro_service_1.TraffleKeitaroService.addOffersToTraffleKeitaro([
|
|
7
|
+
// {
|
|
8
|
+
// offer: {
|
|
9
|
+
// caption: "4rabet (aviator)",
|
|
10
|
+
// geo: "IN"
|
|
11
|
+
// },
|
|
12
|
+
// link: "https://click.traffprogo7.com/GUU0LPNx?landing=684&sub_id3=aviator",
|
|
13
|
+
// partnerName: "4rabet",
|
|
14
|
+
// trafficType: ITraffleTrafficType.ASO
|
|
15
|
+
// },
|
|
16
|
+
// {
|
|
17
|
+
// offer: {
|
|
18
|
+
// caption: "4rabet (regpage)",
|
|
19
|
+
// geo: "IN"
|
|
20
|
+
// },
|
|
21
|
+
// link: "https://click.traffprogo7.com/GUU0LPNx?landing=54&sub_id3=reg_form",
|
|
22
|
+
// partnerName: "4rabet",
|
|
23
|
+
// trafficType: ITraffleTrafficType.ASO
|
|
24
|
+
// },
|
|
25
|
+
// {
|
|
26
|
+
// offer: {
|
|
27
|
+
// caption: "4rabet (chicken #1)",
|
|
28
|
+
// geo: "IN"
|
|
29
|
+
// },
|
|
30
|
+
// link: "https://click.traffprogo7.com/GUU0LPNx?landing=1803&sub_id3=chicken1",
|
|
31
|
+
// partnerName: "4rabet",
|
|
32
|
+
// trafficType: ITraffleTrafficType.ASO
|
|
33
|
+
// },
|
|
34
|
+
// {
|
|
35
|
+
// offer: {
|
|
36
|
+
// caption: "4rabet (chicken #2)",
|
|
37
|
+
// geo: "IN"
|
|
38
|
+
// },
|
|
39
|
+
// link: "https://click.traffprogo7.com/GUU0LPNx?landing=2689&sub_id3=chicken2",
|
|
40
|
+
// partnerName: "4rabet",
|
|
41
|
+
// trafficType: ITraffleTrafficType.ASO
|
|
42
|
+
// }
|
|
43
|
+
]);
|
|
44
|
+
// await TraffleKeitaroService.deleteOfferById(2070)
|
|
45
|
+
await traffle_keitaro_service_1.TraffleKeitaroService.updateOfferLinkById(2074, "https://click.traffprogo7.com/GUU0LPNx?landing=2689&sub_id3=chicken");
|
|
46
|
+
// await TraffleKeitaroService.updateOfferLinkById(2073, "https://click.traffprogo7.com/GUU0LPNx?landing=1803&sub_id3=chicken")
|
|
47
|
+
let offers = await traffle_keitaro_service_1.TraffleKeitaroService.getAllOffers();
|
|
48
|
+
console.log(offers);
|
|
49
|
+
})();
|
|
50
|
+
// Offers group: { name: '[from] El Trafico', position: 79, type: 'offers', id: 1037 }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bprotsyk/aso-core",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.97",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"scripts": {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"build": "tsc",
|
|
9
9
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
10
10
|
"keitaro": "tsc; node lib/utils/keitaro-utils.js",
|
|
11
|
+
"traffle": "tsc; node lib/utils/traffle-keitaro-utils.js",
|
|
11
12
|
"server": "tsc; node lib/utils/server-util.js"
|
|
12
13
|
},
|
|
13
14
|
"author": "bprotsyk",
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { IKeitaroStream } from "../../../keitaro/keitaro-stream";
|
|
2
|
+
import { IOffer } from "../../../offers/offer"
|
|
3
|
+
import keitaroApi from "./http"
|
|
4
|
+
import { IKeitaroCampaign } from "../../../keitaro/keitaro-campaign";
|
|
5
|
+
import { IKeitaroDomain } from "../../../keitaro/keitaro-domain";
|
|
6
|
+
import { EPlatform, getPlatformName, IApp } from "../../../app/app";
|
|
7
|
+
import { TRAFFIC_SOURCE_ID_FLASH_AI, prepareOWCampaignParameters } from "../../../utils/keitaro-utils";
|
|
8
|
+
import { convertMillisToDate, getTimestampsForTodayAndYesterday } from "../../../utils/general";
|
|
9
|
+
import { IKeitaroOffer, IKeitaroOffersFilter } from "index";
|
|
10
|
+
import { IKeitaroClicksRequest, IKeitaroClicksRangeRequest, KeitaroClicksInterval } from "../../../keitaro/keitaro-clicks";
|
|
11
|
+
import { OpenAI } from "../../../network/openai/openai";
|
|
12
|
+
import { off } from "process";
|
|
13
|
+
|
|
14
|
+
async function getAllOffers(): Promise<IKeitaroOffer[]> {
|
|
15
|
+
const { data: offers } = await keitaroApi.get<IKeitaroOffer[]>('offers')
|
|
16
|
+
|
|
17
|
+
return offers
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export enum ITraffleTrafficType {
|
|
21
|
+
ASO = "ASO",
|
|
22
|
+
INAPP = "INAPP"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ITraffleOffer {
|
|
26
|
+
offer: Partial<IOffer>,
|
|
27
|
+
link: string,
|
|
28
|
+
partnerName: string,
|
|
29
|
+
trafficType: ITraffleTrafficType
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface IAffiliateNetwork {
|
|
33
|
+
id: number;
|
|
34
|
+
name: string;
|
|
35
|
+
postback_url: string;
|
|
36
|
+
offer_param: string;
|
|
37
|
+
state: "active" | "deleted";
|
|
38
|
+
template_name: string;
|
|
39
|
+
notes: string;
|
|
40
|
+
pull_api_options: string;
|
|
41
|
+
created_at: string;
|
|
42
|
+
updated_at: string;
|
|
43
|
+
offers: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function getTraffleOffersGroups(): Promise<any[]> {
|
|
47
|
+
try {
|
|
48
|
+
const response = await keitaroApi.get('/groups?type=offers');
|
|
49
|
+
console.log(response.config.url)
|
|
50
|
+
return response.data;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error("Error fetching groups:", error);
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
async function createGroup(name: string, type: "campaigns" | "offers" | "landings" | "domains"): Promise<{ id: number, name: string, position: number, type: string }> {
|
|
59
|
+
try {
|
|
60
|
+
const response = await keitaroApi.post('/groups', {
|
|
61
|
+
name: name,
|
|
62
|
+
type: type
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return response.data;
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error("Error creating group:", error);
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function getTraffleAffiliateNetworks(): Promise<IAffiliateNetwork[]> {
|
|
73
|
+
try {
|
|
74
|
+
const { data: networks } = await keitaroApi.get<IAffiliateNetwork[]>('/affiliate_networks');
|
|
75
|
+
return networks;
|
|
76
|
+
} catch (error) {
|
|
77
|
+
console.error("Error fetching affiliate networks:", error);
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function findMatchingAffiliateId(affiliateNetworks: IAffiliateNetwork[], offer: ITraffleOffer): Promise<number> {
|
|
83
|
+
let affialiateOpenAIResponse = await OpenAI.requestOpenAI({
|
|
84
|
+
model: "o3-mini",
|
|
85
|
+
messages: [
|
|
86
|
+
{ role: "user", content: `Find id of affialiate with name [${offer.partnerName}] (can be slightly different, case or typing) in [${JSON.stringify(affiliateNetworks.map(affiliateNetwork => {return {name: affiliateNetwork.name, id: affiliateNetwork.id}}))}]; Respond with raw JSON object of affiliate network`},
|
|
87
|
+
]
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
if (!affialiateOpenAIResponse){
|
|
91
|
+
console.error("No response from OpenAI")
|
|
92
|
+
return 0
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let network: { id: number, name: string } = JSON.parse(affialiateOpenAIResponse)
|
|
96
|
+
|
|
97
|
+
console.log(network)
|
|
98
|
+
return network.id
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function findMatchingOffersGroup(offersGroups: any[], offer: ITraffleOffer): number | null {
|
|
102
|
+
return 1037;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function deleteOfferById(id: number): Promise<any> {
|
|
106
|
+
const response = await keitaroApi.delete(`/offers/${id}/archive`);
|
|
107
|
+
return response.data;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function addOffersToTraffleKeitaro(offers: ITraffleOffer[]) {
|
|
111
|
+
const allOffers = await getAllOffers();
|
|
112
|
+
|
|
113
|
+
let offersGroups = await getTraffleOffersGroups()
|
|
114
|
+
let affiliateNetworks = await getTraffleAffiliateNetworks()
|
|
115
|
+
|
|
116
|
+
for (let i = 0; i < offers.length; i++) {
|
|
117
|
+
const offer = offers[i];
|
|
118
|
+
|
|
119
|
+
let name = `${offer.offer.caption} ${offer.offer.geo} [el trafico] ${offer.trafficType}`
|
|
120
|
+
|
|
121
|
+
const identicalOffer = allOffers.find(o => o.name.includes(name));
|
|
122
|
+
|
|
123
|
+
let offersGroupId = findMatchingOffersGroup(offersGroups, offer)
|
|
124
|
+
let affiliateId = await findMatchingAffiliateId(affiliateNetworks, offer)
|
|
125
|
+
if (!identicalOffer) {
|
|
126
|
+
const offerPayload = {
|
|
127
|
+
name: name,
|
|
128
|
+
group_id: offersGroupId || 1,
|
|
129
|
+
action_payload: offer.link,
|
|
130
|
+
affiliate_network_id: affiliateId,
|
|
131
|
+
country: [offer.offer.geo],
|
|
132
|
+
action_type: "http",
|
|
133
|
+
offer_type: "external",
|
|
134
|
+
payout_auto: true,
|
|
135
|
+
payout_upsell: true,
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
await keitaroApi.post('offers', offerPayload);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async function updateOfferLinkById(id: number, action_payload: string | object): Promise<any> {
|
|
144
|
+
const updateData = { action_payload };
|
|
145
|
+
const response = await keitaroApi.put(`/offers/${id}`, updateData);
|
|
146
|
+
return response.data;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
export const TraffleKeitaroService = {
|
|
151
|
+
addOffersToTraffleKeitaro, getTraffleOffersGroups, getTraffleAffiliateNetworks, createGroup, deleteOfferById, getAllOffers, updateOfferLinkById
|
|
152
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
|
|
3
|
+
const OPENAI_API_KEY = "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";
|
|
4
|
+
|
|
5
|
+
async function requestOpenAI(
|
|
6
|
+
data: any,
|
|
7
|
+
): Promise<string | undefined> {
|
|
8
|
+
try {
|
|
9
|
+
const response = await axios.post('https://api.openai.com/v1/chat/completions', data, {
|
|
10
|
+
headers: {
|
|
11
|
+
Authorization: `Bearer ${OPENAI_API_KEY}`,
|
|
12
|
+
'Content-Type': 'application/json',
|
|
13
|
+
},
|
|
14
|
+
timeout: 120000,
|
|
15
|
+
responseType: 'json',
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
return response.data.choices[0].message.content
|
|
19
|
+
} catch (e) {
|
|
20
|
+
console.error(e)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const OpenAI = {
|
|
25
|
+
requestOpenAI
|
|
26
|
+
}
|
package/src/offers/list.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Schema } from "mongoose"
|
|
|
2
2
|
|
|
3
3
|
export interface ISectionsList {
|
|
4
4
|
id: number
|
|
5
|
+
name: string
|
|
5
6
|
content: IAppOffersSection[]
|
|
6
7
|
}
|
|
7
8
|
|
|
@@ -21,5 +22,9 @@ export const SectionsListSchema = new Schema({
|
|
|
21
22
|
unique: true,
|
|
22
23
|
required: true
|
|
23
24
|
},
|
|
25
|
+
name: {
|
|
26
|
+
type: String,
|
|
27
|
+
required: true
|
|
28
|
+
},
|
|
24
29
|
content: [Object],
|
|
25
30
|
})
|
|
@@ -4,7 +4,6 @@ import { AppType } from "../app/app-type"
|
|
|
4
4
|
import { IKeitaroCampaign, IKeitaroCampaignParameters } from "../keitaro/keitaro-campaign"
|
|
5
5
|
import { IKeitaroDomain } from "../keitaro/keitaro-domain"
|
|
6
6
|
import { KeitaroService } from "../network/keitaro/keitaro-service"
|
|
7
|
-
const sleep = require('sleep-promise');
|
|
8
7
|
import * as util from 'util';
|
|
9
8
|
import axios from "axios"
|
|
10
9
|
import { getTimestampsForTodayAndYesterday } from "../utils/general"
|
|
@@ -68,6 +67,10 @@ const COST_CURRENCY_USD = "USD"
|
|
|
68
67
|
// }
|
|
69
68
|
// } as IFlashApp
|
|
70
69
|
|
|
70
|
+
function sleep(ms: number): Promise<void> {
|
|
71
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
72
|
+
}``
|
|
73
|
+
|
|
71
74
|
export let addGeosToAllRedirectCampaigns = async (geosToAdd: string) => {
|
|
72
75
|
let allCampaigns = await KeitaroService.getAllCampaigns()
|
|
73
76
|
|
|
@@ -409,8 +412,8 @@ export let prepareOWCampaignParameters = (app: IApp): IKeitaroCampaignParameters
|
|
|
409
412
|
"placeholder": "",
|
|
410
413
|
"alias": "offer_id"
|
|
411
414
|
},
|
|
412
|
-
|
|
413
|
-
|
|
415
|
+
|
|
416
|
+
|
|
414
417
|
}
|
|
415
418
|
}
|
|
416
419
|
|
|
@@ -477,7 +480,7 @@ export async function createDirectCampaign(app: IApp) {
|
|
|
477
480
|
return campaign
|
|
478
481
|
}
|
|
479
482
|
|
|
480
|
-
export async function createOWCampaign(app: IApp, platform?: EPlatform
|
|
483
|
+
export async function createOWCampaign(app: IApp, platform?: EPlatform) {
|
|
481
484
|
let owCampaign = await KeitaroService.cloneOWCampaign(app, platform)
|
|
482
485
|
|
|
483
486
|
return owCampaign
|
|
@@ -800,7 +803,7 @@ async function checkMultipleIPs() {
|
|
|
800
803
|
try {
|
|
801
804
|
const clicks = await getClicksByIp(ip, 2832, KeitaroClicksInterval.SEVEN_DAYS_AGO);
|
|
802
805
|
subids.push(clicks[clicks.length - 1].sub_id)
|
|
803
|
-
} catch (error) {
|
|
806
|
+
} catch (error) { }
|
|
804
807
|
await sleep(300); // Delay to avoid rate limiting
|
|
805
808
|
}
|
|
806
809
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { IKeitaroStream } from "../keitaro/keitaro-stream"
|
|
2
|
+
import { EPlatform, IApp, PlugType, } from "../app/app"
|
|
3
|
+
import { AppType } from "../app/app-type"
|
|
4
|
+
import { IKeitaroCampaign, IKeitaroCampaignParameters } from "../keitaro/keitaro-campaign"
|
|
5
|
+
import { IKeitaroDomain } from "../keitaro/keitaro-domain"
|
|
6
|
+
import { KeitaroService } from "../network/keitaro/keitaro-service"
|
|
7
|
+
const sleep = require('sleep-promise');
|
|
8
|
+
import * as util from 'util';
|
|
9
|
+
import axios from "axios"
|
|
10
|
+
import { getTimestampsForTodayAndYesterday } from "./general"
|
|
11
|
+
import { KeitaroUtils } from "index"
|
|
12
|
+
import { rename } from "fs"
|
|
13
|
+
import { IKeitaroClicksRequest, KeitaroClicksInterval } from "../keitaro/keitaro-clicks"
|
|
14
|
+
import { IKeitaroClicksRangeRequest } from "../keitaro/keitaro-clicks"
|
|
15
|
+
import { ITraffleTrafficType, TraffleKeitaroService } from "../network/keitaro/traffle/traffle-keitaro-service"
|
|
16
|
+
import { OpenAI } from "../network/openai/openai"
|
|
17
|
+
|
|
18
|
+
(async () => {
|
|
19
|
+
await TraffleKeitaroService.addOffersToTraffleKeitaro([
|
|
20
|
+
// {
|
|
21
|
+
// offer: {
|
|
22
|
+
// caption: "4rabet (aviator)",
|
|
23
|
+
// geo: "IN"
|
|
24
|
+
// },
|
|
25
|
+
// link: "https://click.traffprogo7.com/GUU0LPNx?landing=684&sub_id3=aviator",
|
|
26
|
+
// partnerName: "4rabet",
|
|
27
|
+
// trafficType: ITraffleTrafficType.ASO
|
|
28
|
+
// },
|
|
29
|
+
// {
|
|
30
|
+
// offer: {
|
|
31
|
+
// caption: "4rabet (regpage)",
|
|
32
|
+
// geo: "IN"
|
|
33
|
+
// },
|
|
34
|
+
// link: "https://click.traffprogo7.com/GUU0LPNx?landing=54&sub_id3=reg_form",
|
|
35
|
+
// partnerName: "4rabet",
|
|
36
|
+
// trafficType: ITraffleTrafficType.ASO
|
|
37
|
+
// },
|
|
38
|
+
// {
|
|
39
|
+
// offer: {
|
|
40
|
+
// caption: "4rabet (chicken #1)",
|
|
41
|
+
// geo: "IN"
|
|
42
|
+
// },
|
|
43
|
+
// link: "https://click.traffprogo7.com/GUU0LPNx?landing=1803&sub_id3=chicken1",
|
|
44
|
+
// partnerName: "4rabet",
|
|
45
|
+
// trafficType: ITraffleTrafficType.ASO
|
|
46
|
+
// },
|
|
47
|
+
// {
|
|
48
|
+
// offer: {
|
|
49
|
+
// caption: "4rabet (chicken #2)",
|
|
50
|
+
// geo: "IN"
|
|
51
|
+
// },
|
|
52
|
+
// link: "https://click.traffprogo7.com/GUU0LPNx?landing=2689&sub_id3=chicken2",
|
|
53
|
+
// partnerName: "4rabet",
|
|
54
|
+
// trafficType: ITraffleTrafficType.ASO
|
|
55
|
+
// }
|
|
56
|
+
])
|
|
57
|
+
|
|
58
|
+
// await TraffleKeitaroService.deleteOfferById(2070)
|
|
59
|
+
|
|
60
|
+
await TraffleKeitaroService.updateOfferLinkById(2074, "https://click.traffprogo7.com/GUU0LPNx?landing=2689&sub_id3=chicken")
|
|
61
|
+
// await TraffleKeitaroService.updateOfferLinkById(2073, "https://click.traffprogo7.com/GUU0LPNx?landing=1803&sub_id3=chicken")
|
|
62
|
+
|
|
63
|
+
let offers = await TraffleKeitaroService.getAllOffers()
|
|
64
|
+
console.log(offers)
|
|
65
|
+
})();
|
|
66
|
+
|
|
67
|
+
// Offers group: { name: '[from] El Trafico', position: 79, type: 'offers', id: 1037 }
|