@bprotsyk/aso-core 2.1.87 → 2.1.96

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.
@@ -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,2 @@
1
+ import { ConversionComparison } from '../utils/comparing';
2
+ export declare function displayComparisonResults(comparison: ConversionComparison): void;
@@ -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,2 @@
1
+ import { ConversionComparison } from './utils/comparing';
2
+ export declare function displayComparisonResults(comparison: ConversionComparison): void;
@@ -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,2 @@
1
+ declare const _default: import("axios").AxiosInstance;
2
+ export default _default;
@@ -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,5 @@
1
+ declare function requestOpenAI(data: any): Promise<string | undefined>;
2
+ export declare const OpenAI: {
3
+ requestOpenAI: typeof requestOpenAI;
4
+ };
5
+ export {};
@@ -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
+ };
@@ -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: {
@@ -8,5 +8,9 @@ exports.SectionsListSchema = new mongoose_1.Schema({
8
8
  unique: true,
9
9
  required: true
10
10
  },
11
+ name: {
12
+ type: String,
13
+ required: true
14
+ },
11
15
  content: [Object],
12
16
  });
@@ -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;
@@ -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;
@@ -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;
@@ -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.87",
3
+ "version": "2.1.96",
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,8 @@
1
+ import axios from "axios";
2
+
3
+ export default axios.create({
4
+ baseURL: 'https://traffle-tech.com/admin_api/v1/',
5
+ headers: {
6
+ "Api-Key": `3e80a8fcf1ceb01a761457d017e43a0a`,
7
+ },
8
+ });
@@ -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
+ }
@@ -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
  })
@@ -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 }