@bprotsyk/aso-core 2.1.42 → 2.1.43
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 +1 -1
- package/lib/keitaro/keitaro-clicks.d.ts +26 -0
- package/lib/keitaro/keitaro-clicks.js +15 -0
- package/lib/network/keitaro/keitaro-service.d.ts +5 -2
- package/lib/network/keitaro/keitaro-service.js +68 -45
- package/lib/utils/keitaro-utils.d.ts +3 -3
- package/lib/utils/keitaro-utils.js +75 -21
- package/package.json +1 -1
- package/src/keitaro/keitaro-clicks.ts +29 -0
- package/src/network/keitaro/keitaro-service.ts +87 -52
- package/src/utils/keitaro-utils.ts +93 -30
package/lib/general/domain.d.ts
CHANGED
|
@@ -91,6 +91,7 @@ export declare const DomainSchema: Schema<any, Model<any, any, any, any, any>, {
|
|
|
91
91
|
caption?: string | undefined;
|
|
92
92
|
title?: string | undefined;
|
|
93
93
|
proxied?: boolean | undefined;
|
|
94
|
+
ip?: string | undefined;
|
|
94
95
|
namecheapId?: string | undefined;
|
|
95
96
|
status?: string | undefined;
|
|
96
97
|
isUpdating?: boolean | undefined;
|
|
@@ -100,7 +101,6 @@ export declare const DomainSchema: Schema<any, Model<any, any, any, any, any>, {
|
|
|
100
101
|
originalDNSHost?: string | undefined;
|
|
101
102
|
createdAt?: number | undefined;
|
|
102
103
|
expiresAt?: number | undefined;
|
|
103
|
-
ip?: string | undefined;
|
|
104
104
|
subdomain?: string | undefined;
|
|
105
105
|
mxRecord?: string | undefined;
|
|
106
106
|
target?: string | undefined;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare enum KeitaroClicksInterval {
|
|
2
|
+
TODAY = "today",
|
|
3
|
+
YESTERDAY = "yesterday",
|
|
4
|
+
SEVEN_DAYS_AGO = "7_days_ago",
|
|
5
|
+
FIRST_DAY_OF_THIS_WEEK = "first_day_of_this_week",
|
|
6
|
+
ONE_MONTH_AGO = "1_month_ago",
|
|
7
|
+
FIRST_DAY_OF_THIS_MONTH = "first_day_of_this_month",
|
|
8
|
+
ONE_YEAR_AGO = "1_year_ago",
|
|
9
|
+
FIRST_DAY_OF_THIS_YEAR = "first_day_of_this_year",
|
|
10
|
+
ALL_TIME = "all_time"
|
|
11
|
+
}
|
|
12
|
+
export interface IKeitaroClicksRangeRequest {
|
|
13
|
+
interval: KeitaroClicksInterval;
|
|
14
|
+
}
|
|
15
|
+
export interface IKeitaroClicksFilterRequest {
|
|
16
|
+
name: string;
|
|
17
|
+
operator: string;
|
|
18
|
+
expression: string | number;
|
|
19
|
+
}
|
|
20
|
+
export interface IKeitaroClicksRequest {
|
|
21
|
+
range: IKeitaroClicksRangeRequest;
|
|
22
|
+
limit?: number;
|
|
23
|
+
offset?: number;
|
|
24
|
+
columns?: string[];
|
|
25
|
+
filters?: IKeitaroClicksFilterRequest[];
|
|
26
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KeitaroClicksInterval = void 0;
|
|
4
|
+
var KeitaroClicksInterval;
|
|
5
|
+
(function (KeitaroClicksInterval) {
|
|
6
|
+
KeitaroClicksInterval["TODAY"] = "today";
|
|
7
|
+
KeitaroClicksInterval["YESTERDAY"] = "yesterday";
|
|
8
|
+
KeitaroClicksInterval["SEVEN_DAYS_AGO"] = "7_days_ago";
|
|
9
|
+
KeitaroClicksInterval["FIRST_DAY_OF_THIS_WEEK"] = "first_day_of_this_week";
|
|
10
|
+
KeitaroClicksInterval["ONE_MONTH_AGO"] = "1_month_ago";
|
|
11
|
+
KeitaroClicksInterval["FIRST_DAY_OF_THIS_MONTH"] = "first_day_of_this_month";
|
|
12
|
+
KeitaroClicksInterval["ONE_YEAR_AGO"] = "1_year_ago";
|
|
13
|
+
KeitaroClicksInterval["FIRST_DAY_OF_THIS_YEAR"] = "first_day_of_this_year";
|
|
14
|
+
KeitaroClicksInterval["ALL_TIME"] = "all_time";
|
|
15
|
+
})(KeitaroClicksInterval = exports.KeitaroClicksInterval || (exports.KeitaroClicksInterval = {}));
|
|
@@ -4,6 +4,7 @@ import { IKeitaroCampaign } from "../../keitaro/keitaro-campaign";
|
|
|
4
4
|
import { IKeitaroDomain } from "../../keitaro/keitaro-domain";
|
|
5
5
|
import { IApp } from "../../app/app";
|
|
6
6
|
import { IKeitaroOffer } from "index";
|
|
7
|
+
import { IKeitaroClicksRequest, KeitaroClicksInterval } from "../../keitaro/keitaro-clicks";
|
|
7
8
|
export interface IKeitaroOffersFilter {
|
|
8
9
|
keitaroId?: number;
|
|
9
10
|
name?: string;
|
|
@@ -17,7 +18,7 @@ declare function getAllOffers(): Promise<IKeitaroOffer[]>;
|
|
|
17
18
|
declare function findKeitaroOffers(filter: IKeitaroOffersFilter): Promise<IKeitaroOffer[]>;
|
|
18
19
|
declare function getOfferByKeitaroId(id: number): Promise<IKeitaroOffer>;
|
|
19
20
|
declare function updateOffer(offer: any): Promise<IKeitaroOffer>;
|
|
20
|
-
declare function
|
|
21
|
+
declare function addOffersToKeitaro(offers: IOffer[], affiliateId: number, links: string[], avoidGroup?: number, groupId?: number): Promise<void>;
|
|
21
22
|
declare function createCampaign(campaignData: Partial<IKeitaroCampaign>): Promise<IKeitaroCampaign>;
|
|
22
23
|
declare function getCampaignById(id: number): Promise<IKeitaroCampaign>;
|
|
23
24
|
export declare function upsertStreamToCampaign(campaign: IKeitaroCampaign, stream: Partial<IKeitaroStream>): Promise<void>;
|
|
@@ -27,13 +28,14 @@ declare function changeCampaignsGroup(fromId: number, toId: number, exceptForCam
|
|
|
27
28
|
declare function getDomains(onlyActive?: boolean): Promise<IKeitaroDomain[]>;
|
|
28
29
|
declare function getProfitForTimeRange(from: number, to: number): Promise<number>;
|
|
29
30
|
declare function fixBrokenClickCosts(startDate: string, endDate: string): Promise<void>;
|
|
31
|
+
declare function getClicks(request: IKeitaroClicksRequest | KeitaroClicksInterval): Promise<any>;
|
|
30
32
|
export declare const KeitaroService: {
|
|
31
33
|
getStreamsByCampaignId: typeof getStreamsByCampaignId;
|
|
32
34
|
updateCampaign: typeof updateCampaign;
|
|
33
35
|
getAllCampaigns: typeof getAllCampaigns;
|
|
34
36
|
getAllOffers: typeof getAllOffers;
|
|
35
37
|
cloneStreams: typeof cloneStreams;
|
|
36
|
-
|
|
38
|
+
addOffersToKeitaro: typeof addOffersToKeitaro;
|
|
37
39
|
getOfferByKeitaroId: typeof getOfferByKeitaroId;
|
|
38
40
|
getDomains: typeof getDomains;
|
|
39
41
|
createCampaign: typeof createCampaign;
|
|
@@ -43,6 +45,7 @@ export declare const KeitaroService: {
|
|
|
43
45
|
updateOffer: typeof updateOffer;
|
|
44
46
|
changeCampaignsGroup: typeof changeCampaignsGroup;
|
|
45
47
|
getProfitForTimeRange: typeof getProfitForTimeRange;
|
|
48
|
+
getClicks: typeof getClicks;
|
|
46
49
|
cloneDCampaign: typeof cloneDCampaign;
|
|
47
50
|
findKeitaroOffers: typeof findKeitaroOffers;
|
|
48
51
|
fixBrokenClickCosts: typeof fixBrokenClickCosts;
|
|
@@ -55,27 +55,34 @@ async function cloneStreams(originalCampaignId, streamPositionsToClone, campaign
|
|
|
55
55
|
async function updateCampaign(id, payload) {
|
|
56
56
|
await http_1.default.put(`campaigns/${id}`, payload);
|
|
57
57
|
}
|
|
58
|
-
async function createStreamForMatchingCampaigns(
|
|
59
|
-
// Get
|
|
58
|
+
async function createStreamForMatchingCampaigns(streamPayloads, campaignRegExp, avoidGroup) {
|
|
59
|
+
// Get all campaigns once
|
|
60
60
|
const allCampaigns = await getAllCampaigns();
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
//
|
|
64
|
-
|
|
61
|
+
const matchingCampaigns = allCampaigns.filter(campaign => (avoidGroup ? campaign.group_id != avoidGroup : true) &&
|
|
62
|
+
campaignRegExp.exec(campaign.name));
|
|
63
|
+
// Get all streams for matching campaigns once
|
|
64
|
+
const campaignStreams = new Map();
|
|
65
|
+
for (const campaign of matchingCampaigns) {
|
|
66
|
+
campaignStreams.set(campaign.id, await getStreamsByCampaignId(campaign.id));
|
|
67
|
+
}
|
|
68
|
+
// Process each campaign
|
|
65
69
|
for (const matchingCampaign of matchingCampaigns) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
70
|
+
const streams = campaignStreams.get(matchingCampaign.id) || [];
|
|
71
|
+
// Process each stream payload
|
|
72
|
+
for (const { payload, offerId } of streamPayloads) {
|
|
73
|
+
const identicalStream = streams.find(stream => stream.name.includes(offerId));
|
|
74
|
+
if (identicalStream) {
|
|
75
|
+
await http_1.default.put(`streams/${identicalStream.id}`, {
|
|
76
|
+
campaign_id: matchingCampaign.id,
|
|
77
|
+
...payload
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
await http_1.default.post('streams', {
|
|
82
|
+
campaign_id: matchingCampaign.id,
|
|
83
|
+
...payload
|
|
84
|
+
});
|
|
85
|
+
}
|
|
79
86
|
}
|
|
80
87
|
}
|
|
81
88
|
}
|
|
@@ -120,31 +127,38 @@ function createStreamPartialPayload(keitaroOfferId, offerName, offerId, offerGeo
|
|
|
120
127
|
}],
|
|
121
128
|
};
|
|
122
129
|
}
|
|
123
|
-
async function
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
let
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
130
|
+
async function addOffersToKeitaro(offers, affiliateId, links, avoidGroup, groupId) {
|
|
131
|
+
const allOffers = await getAllOffers();
|
|
132
|
+
const streamPayloads = [];
|
|
133
|
+
for (let i = 0; i < offers.length; i++) {
|
|
134
|
+
const offer = offers[i];
|
|
135
|
+
const link = links[i];
|
|
136
|
+
const identicalOffer = allOffers.find(o => o.name.includes(offer.name));
|
|
137
|
+
let keitaroOfferId;
|
|
138
|
+
if (identicalOffer) {
|
|
139
|
+
keitaroOfferId = identicalOffer.id;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const offerPayload = {
|
|
143
|
+
name: `${offer.caption} ${offer.geo} (${offer.name})`,
|
|
144
|
+
group_id: groupId || 1,
|
|
145
|
+
action_payload: link,
|
|
146
|
+
affiliate_network_id: affiliateId,
|
|
147
|
+
country: [offer.geo],
|
|
148
|
+
action_type: "http",
|
|
149
|
+
offer_type: "external",
|
|
150
|
+
payout_auto: true,
|
|
151
|
+
payout_upsell: true,
|
|
152
|
+
};
|
|
153
|
+
const { data: keitaroOffer } = await http_1.default.post('offers', offerPayload);
|
|
154
|
+
keitaroOfferId = keitaroOffer.id;
|
|
155
|
+
}
|
|
156
|
+
streamPayloads.push({
|
|
157
|
+
payload: createStreamPartialPayload(keitaroOfferId, offer.caption, offer.name, offer.geo),
|
|
158
|
+
offerId: offer.name
|
|
159
|
+
});
|
|
145
160
|
}
|
|
146
|
-
|
|
147
|
-
await createStreamForMatchingCampaigns(streamPartialPayload, offer.name, /◈/, avoidGroup);
|
|
161
|
+
await createStreamForMatchingCampaigns(streamPayloads, /◈/, avoidGroup);
|
|
148
162
|
}
|
|
149
163
|
async function createCampaign(campaignData) {
|
|
150
164
|
let { data: campaign } = await http_1.default.post(`/campaigns`, campaignData);
|
|
@@ -275,9 +289,18 @@ async function fixBrokenClickCosts(startDate, endDate) {
|
|
|
275
289
|
// Make the API request to update costs
|
|
276
290
|
await http_1.default.post('/clicks/update_costs', payload);
|
|
277
291
|
}
|
|
292
|
+
async function getClicks(request) {
|
|
293
|
+
const defaultRequest = typeof request === 'string' ? {
|
|
294
|
+
range: { interval: request }
|
|
295
|
+
} : {
|
|
296
|
+
...request
|
|
297
|
+
};
|
|
298
|
+
const { data } = await http_1.default.post('/clicks/log', defaultRequest);
|
|
299
|
+
return data.rows;
|
|
300
|
+
}
|
|
278
301
|
exports.KeitaroService = {
|
|
279
|
-
getStreamsByCampaignId, updateCampaign, getAllCampaigns, getAllOffers, cloneStreams,
|
|
280
|
-
updateOffer, changeCampaignsGroup, getProfitForTimeRange,
|
|
302
|
+
getStreamsByCampaignId, updateCampaign, getAllCampaigns, getAllOffers, cloneStreams, addOffersToKeitaro, getOfferByKeitaroId, getDomains, createCampaign, getCampaignById, upsertStreamToCampaign, cloneOWCampaign,
|
|
303
|
+
updateOffer, changeCampaignsGroup, getProfitForTimeRange, getClicks,
|
|
281
304
|
// getProfitForTodayAndYesterday,
|
|
282
305
|
cloneDCampaign, findKeitaroOffers, fixBrokenClickCosts
|
|
283
306
|
};
|
|
@@ -6,8 +6,8 @@ export declare let addGeosToAllRedirectCampaigns: (geosToAdd: string) => Promise
|
|
|
6
6
|
export declare let removeGeosFromAllRedirectCampaigns: (geoToRemove: string) => Promise<void>;
|
|
7
7
|
export declare let prepareOWCampaignParameters: (app: IApp) => IKeitaroCampaignParameters;
|
|
8
8
|
export declare function createOWStreamPartialPayload(app: IApp): Partial<IKeitaroStream>;
|
|
9
|
-
export declare function createFlashCampaigns(app: IApp): Promise<{
|
|
10
|
-
tracking: IKeitaroCampaign;
|
|
11
|
-
}>;
|
|
12
9
|
export declare function createDirectCampaign(app: IApp): Promise<IKeitaroCampaign>;
|
|
13
10
|
export declare function createOWCampaign(app: IApp): Promise<IKeitaroCampaign>;
|
|
11
|
+
type PostbackStatus = 'lead' | 'sale' | 'rejected';
|
|
12
|
+
export declare function sendPostbacks(subids: string[], status: PostbackStatus, payout?: number): Promise<void>;
|
|
13
|
+
export {};
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
6
|
+
exports.sendPostbacks = exports.createOWCampaign = exports.createDirectCampaign = exports.createOWStreamPartialPayload = exports.prepareOWCampaignParameters = exports.removeGeosFromAllRedirectCampaigns = exports.addGeosToAllRedirectCampaigns = exports.TRAFFIC_SOURCE_ID_FLASH_AI = void 0;
|
|
4
7
|
const keitaro_service_1 = require("../network/keitaro/keitaro-service");
|
|
5
8
|
const sleep = require('sleep-promise');
|
|
9
|
+
const axios_1 = __importDefault(require("axios"));
|
|
10
|
+
const keitaro_clicks_1 = require("../keitaro/keitaro-clicks");
|
|
6
11
|
const FLASH_REDIRECT_GROUP_ID = 82;
|
|
7
12
|
exports.TRAFFIC_SOURCE_ID_FLASH_AI = 22;
|
|
8
13
|
const UNIQUENESS_METHOD = "ip_ua";
|
|
@@ -356,25 +361,6 @@ function createOWStreamPartialPayload(app) {
|
|
|
356
361
|
};
|
|
357
362
|
}
|
|
358
363
|
exports.createOWStreamPartialPayload = createOWStreamPartialPayload;
|
|
359
|
-
async function createFlashCampaigns(app) {
|
|
360
|
-
// Upserting Flash Redirect campaign
|
|
361
|
-
// let redirectCampaign = await createOrFindFlashRedirectCampaign(app)
|
|
362
|
-
// console.log(`Redirect campaign name:`)
|
|
363
|
-
// console.log(`${redirectCampaign.domain}/${redirectCampaign.alias}?uid=`)
|
|
364
|
-
// Upserting necessary streams
|
|
365
|
-
// let botProtectionStream = createBPStreamPartialPayload(app)
|
|
366
|
-
// let owStream = createOWStreamPartialPayload(app)
|
|
367
|
-
// for (let stream of [botProtectionStream, owStream]) {
|
|
368
|
-
// await KeitaroService.upsertStreamToCampaign(redirectCampaign, stream)
|
|
369
|
-
// }
|
|
370
|
-
// Upserting OW campaign
|
|
371
|
-
let owCampaign = await keitaro_service_1.KeitaroService.cloneOWCampaign(app);
|
|
372
|
-
return {
|
|
373
|
-
tracking: owCampaign,
|
|
374
|
-
// redirect: redirectCampaign
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
exports.createFlashCampaigns = createFlashCampaigns;
|
|
378
364
|
async function createDirectCampaign(app) {
|
|
379
365
|
let campaign = await keitaro_service_1.KeitaroService.cloneDCampaign(app);
|
|
380
366
|
let stream = createDefenceMainStreamPartialPayload(app);
|
|
@@ -611,4 +597,72 @@ async function disableAutoCost() {
|
|
|
611
597
|
throw error;
|
|
612
598
|
}
|
|
613
599
|
}
|
|
614
|
-
|
|
600
|
+
async function getClicksByIp(ip, campaignId, interval = keitaro_clicks_1.KeitaroClicksInterval.ONE_MONTH_AGO, limit = 100) {
|
|
601
|
+
const request = {
|
|
602
|
+
range: {
|
|
603
|
+
interval
|
|
604
|
+
},
|
|
605
|
+
columns: ['sub_id'],
|
|
606
|
+
filters: [
|
|
607
|
+
{
|
|
608
|
+
name: 'ip',
|
|
609
|
+
operator: 'BEGINS_WITH',
|
|
610
|
+
expression: ip
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
name: 'campaign_id',
|
|
614
|
+
operator: 'EQUALS',
|
|
615
|
+
expression: campaignId
|
|
616
|
+
}
|
|
617
|
+
],
|
|
618
|
+
limit
|
|
619
|
+
};
|
|
620
|
+
return keitaro_service_1.KeitaroService.getClicks(request);
|
|
621
|
+
}
|
|
622
|
+
async function checkMultipleIPs() {
|
|
623
|
+
const ips = [
|
|
624
|
+
"88.155.31.196",
|
|
625
|
+
"176.120.63.205"
|
|
626
|
+
];
|
|
627
|
+
let subids = [];
|
|
628
|
+
for (const ip of ips) {
|
|
629
|
+
// console.log(`\nChecking IP: ${ip}`);
|
|
630
|
+
try {
|
|
631
|
+
const clicks = await getClicksByIp(ip, 2832, keitaro_clicks_1.KeitaroClicksInterval.SEVEN_DAYS_AGO);
|
|
632
|
+
subids.push(clicks[clicks.length - 1].sub_id);
|
|
633
|
+
}
|
|
634
|
+
catch (error) { }
|
|
635
|
+
await sleep(300); // Delay to avoid rate limiting
|
|
636
|
+
}
|
|
637
|
+
return subids;
|
|
638
|
+
}
|
|
639
|
+
async function sendPostbacks(subids, status, payout) {
|
|
640
|
+
const baseUrl = 'https://aibprtsk.com/bab2832/postback';
|
|
641
|
+
const sendPostback = async (subid) => {
|
|
642
|
+
try {
|
|
643
|
+
let url = `${baseUrl}?subid=${subid}&status=${status}`;
|
|
644
|
+
if (payout !== undefined) {
|
|
645
|
+
url += `&payout=${payout}`;
|
|
646
|
+
}
|
|
647
|
+
const response = await axios_1.default.get(url);
|
|
648
|
+
if (response.status !== 200) {
|
|
649
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
650
|
+
}
|
|
651
|
+
console.log(`Postback sent successfully for subid: ${subid}`);
|
|
652
|
+
}
|
|
653
|
+
catch (error) {
|
|
654
|
+
console.error(`Failed to send postback for subid: ${subid}`, error);
|
|
655
|
+
}
|
|
656
|
+
// Add delay between requests to prevent overwhelming the server
|
|
657
|
+
await sleep(300);
|
|
658
|
+
};
|
|
659
|
+
// Process postbacks sequentially to avoid rate limiting
|
|
660
|
+
for (const subid of subids) {
|
|
661
|
+
await sendPostback(subid);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
exports.sendPostbacks = sendPostbacks;
|
|
665
|
+
(async () => {
|
|
666
|
+
let subids = await checkMultipleIPs();
|
|
667
|
+
await sendPostbacks(subids, 'sale', 125);
|
|
668
|
+
})();
|
package/package.json
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export enum KeitaroClicksInterval {
|
|
2
|
+
TODAY = 'today',
|
|
3
|
+
YESTERDAY = 'yesterday',
|
|
4
|
+
SEVEN_DAYS_AGO = '7_days_ago',
|
|
5
|
+
FIRST_DAY_OF_THIS_WEEK = 'first_day_of_this_week',
|
|
6
|
+
ONE_MONTH_AGO = '1_month_ago',
|
|
7
|
+
FIRST_DAY_OF_THIS_MONTH = 'first_day_of_this_month',
|
|
8
|
+
ONE_YEAR_AGO = '1_year_ago',
|
|
9
|
+
FIRST_DAY_OF_THIS_YEAR = 'first_day_of_this_year',
|
|
10
|
+
ALL_TIME = 'all_time'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface IKeitaroClicksRangeRequest {
|
|
14
|
+
interval: KeitaroClicksInterval;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface IKeitaroClicksFilterRequest {
|
|
18
|
+
name: string;
|
|
19
|
+
operator: string;
|
|
20
|
+
expression: string | number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface IKeitaroClicksRequest {
|
|
24
|
+
range: IKeitaroClicksRangeRequest;
|
|
25
|
+
limit?: number;
|
|
26
|
+
offset?: number;
|
|
27
|
+
columns?: string[];
|
|
28
|
+
filters?: IKeitaroClicksFilterRequest[];
|
|
29
|
+
}
|
|
@@ -7,6 +7,7 @@ import { IApp } from "../../app/app";
|
|
|
7
7
|
import { TRAFFIC_SOURCE_ID_FLASH_AI, prepareOWCampaignParameters } from "../../utils/keitaro-utils";
|
|
8
8
|
import { convertMillisToDate, getTimestampsForTodayAndYesterday } from "../../utils/general";
|
|
9
9
|
import { IKeitaroOffer } from "index";
|
|
10
|
+
import { IKeitaroClicksRequest, IKeitaroClicksRangeRequest, KeitaroClicksInterval } from "../../keitaro/keitaro-clicks";
|
|
10
11
|
|
|
11
12
|
export interface IKeitaroOffersFilter {
|
|
12
13
|
keitaroId?: number,
|
|
@@ -71,31 +72,39 @@ async function updateCampaign(id: number, payload: Partial<IKeitaroCampaign>) {
|
|
|
71
72
|
await keitaroApi.put(`campaigns/${id}`, payload)
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
async function createStreamForMatchingCampaigns(
|
|
75
|
-
// Get
|
|
76
|
-
const allCampaigns = await getAllCampaigns()
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
async function createStreamForMatchingCampaigns(streamPayloads: { payload: any, offerId: string }[], campaignRegExp: RegExp, avoidGroup?: number) {
|
|
76
|
+
// Get all campaigns once
|
|
77
|
+
const allCampaigns = await getAllCampaigns();
|
|
78
|
+
const matchingCampaigns = allCampaigns.filter(campaign =>
|
|
79
|
+
(avoidGroup ? campaign.group_id != avoidGroup : true) &&
|
|
80
|
+
campaignRegExp.exec(campaign.name)
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// Get all streams for matching campaigns once
|
|
84
|
+
const campaignStreams = new Map<number, IKeitaroStream[]>();
|
|
85
|
+
for (const campaign of matchingCampaigns) {
|
|
86
|
+
campaignStreams.set(campaign.id, await getStreamsByCampaignId(campaign.id));
|
|
87
|
+
}
|
|
82
88
|
|
|
83
|
-
//
|
|
89
|
+
// Process each campaign
|
|
84
90
|
for (const matchingCampaign of matchingCampaigns) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
91
|
+
const streams = campaignStreams.get(matchingCampaign.id) || [];
|
|
92
|
+
|
|
93
|
+
// Process each stream payload
|
|
94
|
+
for (const { payload, offerId } of streamPayloads) {
|
|
95
|
+
const identicalStream = streams.find(stream => stream.name.includes(offerId));
|
|
96
|
+
|
|
97
|
+
if (identicalStream) {
|
|
98
|
+
await keitaroApi.put(`streams/${identicalStream.id}`, {
|
|
99
|
+
campaign_id: matchingCampaign.id,
|
|
100
|
+
...payload
|
|
101
|
+
});
|
|
102
|
+
} else {
|
|
103
|
+
await keitaroApi.post('streams', {
|
|
104
|
+
campaign_id: matchingCampaign.id,
|
|
105
|
+
...payload
|
|
106
|
+
});
|
|
107
|
+
}
|
|
99
108
|
}
|
|
100
109
|
}
|
|
101
110
|
}
|
|
@@ -149,35 +158,49 @@ function createStreamPartialPayload(keitaroOfferId: number, offerName: string, o
|
|
|
149
158
|
}
|
|
150
159
|
}
|
|
151
160
|
|
|
152
|
-
async function
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
let
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
161
|
+
async function addOffersToKeitaro(offers: IOffer[], affiliateId: number, links: string[], avoidGroup?: number, groupId?: number) {
|
|
162
|
+
const allOffers = await getAllOffers();
|
|
163
|
+
|
|
164
|
+
const streamPayloads = [];
|
|
165
|
+
|
|
166
|
+
for (let i = 0; i < offers.length; i++) {
|
|
167
|
+
const offer = offers[i];
|
|
168
|
+
const link = links[i];
|
|
169
|
+
|
|
170
|
+
const identicalOffer = allOffers.find(o => o.name.includes(offer.name));
|
|
171
|
+
|
|
172
|
+
let keitaroOfferId;
|
|
173
|
+
if (identicalOffer) {
|
|
174
|
+
keitaroOfferId = identicalOffer.id;
|
|
175
|
+
} else {
|
|
176
|
+
const offerPayload = {
|
|
177
|
+
name: `${offer.caption} ${offer.geo} (${offer.name})`,
|
|
178
|
+
group_id: groupId || 1,
|
|
179
|
+
action_payload: link,
|
|
180
|
+
affiliate_network_id: affiliateId,
|
|
181
|
+
country: [offer.geo],
|
|
182
|
+
action_type: "http",
|
|
183
|
+
offer_type: "external",
|
|
184
|
+
payout_auto: true,
|
|
185
|
+
payout_upsell: true,
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const { data: keitaroOffer } = await keitaroApi.post('offers', offerPayload);
|
|
189
|
+
keitaroOfferId = keitaroOffer.id;
|
|
171
190
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
191
|
+
|
|
192
|
+
streamPayloads.push({
|
|
193
|
+
payload: createStreamPartialPayload(
|
|
194
|
+
keitaroOfferId,
|
|
195
|
+
offer.caption,
|
|
196
|
+
offer.name,
|
|
197
|
+
offer.geo
|
|
198
|
+
),
|
|
199
|
+
offerId: offer.name
|
|
200
|
+
});
|
|
176
201
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
await createStreamForMatchingCampaigns(streamPartialPayload, offer.name, /◈/, avoidGroup)
|
|
202
|
+
|
|
203
|
+
await createStreamForMatchingCampaigns(streamPayloads, /◈/, avoidGroup);
|
|
181
204
|
}
|
|
182
205
|
|
|
183
206
|
async function createCampaign(campaignData: Partial<IKeitaroCampaign>): Promise<IKeitaroCampaign> {
|
|
@@ -340,9 +363,21 @@ async function fixBrokenClickCosts(startDate: string, endDate: string): Promise<
|
|
|
340
363
|
await keitaroApi.post('/clicks/update_costs', payload);
|
|
341
364
|
}
|
|
342
365
|
|
|
366
|
+
async function getClicks(request: IKeitaroClicksRequest | KeitaroClicksInterval) {
|
|
367
|
+
const defaultRequest: IKeitaroClicksRequest = typeof request === 'string' ? {
|
|
368
|
+
range: { interval: request }
|
|
369
|
+
} : {
|
|
370
|
+
...request
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
const { data } = await keitaroApi.post('/clicks/log', defaultRequest);
|
|
374
|
+
return data.rows;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
|
|
343
378
|
export const KeitaroService = {
|
|
344
|
-
getStreamsByCampaignId, updateCampaign, getAllCampaigns, getAllOffers, cloneStreams,
|
|
345
|
-
updateOffer, changeCampaignsGroup, getProfitForTimeRange,
|
|
379
|
+
getStreamsByCampaignId, updateCampaign, getAllCampaigns, getAllOffers, cloneStreams, addOffersToKeitaro, getOfferByKeitaroId, getDomains, createCampaign, getCampaignById, upsertStreamToCampaign, cloneOWCampaign,
|
|
380
|
+
updateOffer, changeCampaignsGroup, getProfitForTimeRange, getClicks,
|
|
346
381
|
// getProfitForTodayAndYesterday,
|
|
347
382
|
cloneDCampaign, findKeitaroOffers, fixBrokenClickCosts
|
|
348
383
|
}
|
|
@@ -10,6 +10,8 @@ import axios from "axios"
|
|
|
10
10
|
import { getTimestampsForTodayAndYesterday } from "../utils/general"
|
|
11
11
|
import { KeitaroUtils } from "index"
|
|
12
12
|
import { rename } from "fs"
|
|
13
|
+
import { IKeitaroClicksRequest, KeitaroClicksInterval } from "../keitaro/keitaro-clicks"
|
|
14
|
+
import { IKeitaroClicksRangeRequest } from "../keitaro/keitaro-clicks"
|
|
13
15
|
|
|
14
16
|
const FLASH_REDIRECT_GROUP_ID = 82
|
|
15
17
|
export const TRAFFIC_SOURCE_ID_FLASH_AI = 22
|
|
@@ -396,29 +398,6 @@ export function createOWStreamPartialPayload(app: IApp): Partial<IKeitaroStream>
|
|
|
396
398
|
}
|
|
397
399
|
}
|
|
398
400
|
|
|
399
|
-
export async function createFlashCampaigns(app: IApp) {
|
|
400
|
-
// Upserting Flash Redirect campaign
|
|
401
|
-
// let redirectCampaign = await createOrFindFlashRedirectCampaign(app)
|
|
402
|
-
// console.log(`Redirect campaign name:`)
|
|
403
|
-
// console.log(`${redirectCampaign.domain}/${redirectCampaign.alias}?uid=`)
|
|
404
|
-
|
|
405
|
-
// Upserting necessary streams
|
|
406
|
-
// let botProtectionStream = createBPStreamPartialPayload(app)
|
|
407
|
-
// let owStream = createOWStreamPartialPayload(app)
|
|
408
|
-
|
|
409
|
-
// for (let stream of [botProtectionStream, owStream]) {
|
|
410
|
-
// await KeitaroService.upsertStreamToCampaign(redirectCampaign, stream)
|
|
411
|
-
// }
|
|
412
|
-
|
|
413
|
-
// Upserting OW campaign
|
|
414
|
-
let owCampaign = await KeitaroService.cloneOWCampaign(app)
|
|
415
|
-
|
|
416
|
-
return {
|
|
417
|
-
tracking: owCampaign,
|
|
418
|
-
// redirect: redirectCampaign
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
|
|
422
401
|
export async function createDirectCampaign(app: IApp) {
|
|
423
402
|
let campaign = await KeitaroService.cloneDCampaign(app)
|
|
424
403
|
|
|
@@ -666,17 +645,17 @@ let renameCampaigns = async () => {
|
|
|
666
645
|
async function fixLastThreeMonthsClickCosts(): Promise<void> {
|
|
667
646
|
// Get current date
|
|
668
647
|
const now = new Date();
|
|
669
|
-
|
|
648
|
+
|
|
670
649
|
// Calculate date 3 months ago
|
|
671
650
|
const threeMonthsAgo = new Date();
|
|
672
651
|
threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3);
|
|
673
|
-
|
|
652
|
+
|
|
674
653
|
// Format dates to required format "YYYY-MM-DD HH:MM"
|
|
675
654
|
const startDate = threeMonthsAgo.toISOString().slice(0, 10) + " 00:00";
|
|
676
655
|
const endDate = now.toISOString().slice(0, 10) + " 23:59";
|
|
677
656
|
|
|
678
657
|
console.log(`Fixing click costs from ${startDate} to ${endDate}`);
|
|
679
|
-
|
|
658
|
+
|
|
680
659
|
try {
|
|
681
660
|
await KeitaroService.fixBrokenClickCosts(startDate, endDate);
|
|
682
661
|
console.log("Successfully fixed click costs");
|
|
@@ -693,20 +672,20 @@ async function disableAutoCost(): Promise<void> {
|
|
|
693
672
|
// Get all campaigns
|
|
694
673
|
const campaigns = await KeitaroService.getAllCampaigns();
|
|
695
674
|
console.log(`Disabling auto cost for ${campaigns.length} campaigns...`);
|
|
696
|
-
|
|
675
|
+
|
|
697
676
|
// Update each campaign
|
|
698
677
|
for (const campaign of campaigns) {
|
|
699
678
|
try {
|
|
700
679
|
await KeitaroService.updateCampaign(campaign.id, { cost_auto: false });
|
|
701
680
|
console.log(`Disabled auto cost for campaign: ${campaign.name} (ID: ${campaign.id})`);
|
|
702
|
-
|
|
681
|
+
|
|
703
682
|
// Add a small delay to avoid overwhelming the API
|
|
704
683
|
await sleep(500);
|
|
705
684
|
} catch (error) {
|
|
706
685
|
console.error(`Failed to update campaign ${campaign.name} (ID: ${campaign.id}):`, error);
|
|
707
686
|
}
|
|
708
687
|
}
|
|
709
|
-
|
|
688
|
+
|
|
710
689
|
console.log('Successfully disabled auto cost for all campaigns');
|
|
711
690
|
} catch (error) {
|
|
712
691
|
console.error('Failed to disable auto cost:', error);
|
|
@@ -714,4 +693,88 @@ async function disableAutoCost(): Promise<void> {
|
|
|
714
693
|
}
|
|
715
694
|
}
|
|
716
695
|
|
|
717
|
-
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
async function getClicksByIp(ip: string, campaignId: number, interval: KeitaroClicksInterval = KeitaroClicksInterval.ONE_MONTH_AGO, limit: number = 100): Promise<any> {
|
|
699
|
+
const request: IKeitaroClicksRequest = {
|
|
700
|
+
range: {
|
|
701
|
+
interval
|
|
702
|
+
},
|
|
703
|
+
columns: ['sub_id'],
|
|
704
|
+
filters: [
|
|
705
|
+
{
|
|
706
|
+
name: 'ip',
|
|
707
|
+
operator: 'BEGINS_WITH',
|
|
708
|
+
expression: ip
|
|
709
|
+
},
|
|
710
|
+
{
|
|
711
|
+
name: 'campaign_id',
|
|
712
|
+
operator: 'EQUALS',
|
|
713
|
+
expression: campaignId
|
|
714
|
+
}
|
|
715
|
+
],
|
|
716
|
+
|
|
717
|
+
limit
|
|
718
|
+
};
|
|
719
|
+
|
|
720
|
+
return KeitaroService.getClicks(request);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
async function checkMultipleIPs() {
|
|
724
|
+
const ips = [
|
|
725
|
+
"88.155.31.196",
|
|
726
|
+
"176.120.63.205"
|
|
727
|
+
];
|
|
728
|
+
let subids = []
|
|
729
|
+
for (const ip of ips) {
|
|
730
|
+
// console.log(`\nChecking IP: ${ip}`);
|
|
731
|
+
try {
|
|
732
|
+
const clicks = await getClicksByIp(ip, 2832, KeitaroClicksInterval.SEVEN_DAYS_AGO);
|
|
733
|
+
subids.push(clicks[clicks.length - 1].sub_id)
|
|
734
|
+
} catch (error) { }
|
|
735
|
+
await sleep(300); // Delay to avoid rate limiting
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
return subids
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
// disableAutoCost();
|
|
743
|
+
|
|
744
|
+
type PostbackStatus = 'lead' | 'sale' | 'rejected';
|
|
745
|
+
|
|
746
|
+
export async function sendPostbacks(subids: string[], status: PostbackStatus, payout?: number): Promise<void> {
|
|
747
|
+
const baseUrl = 'https://aibprtsk.com/bab2832/postback';
|
|
748
|
+
|
|
749
|
+
const sendPostback = async (subid: string) => {
|
|
750
|
+
try {
|
|
751
|
+
let url = `${baseUrl}?subid=${subid}&status=${status}`;
|
|
752
|
+
if (payout !== undefined) {
|
|
753
|
+
url += `&payout=${payout}`;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
const response = await axios.get(url);
|
|
757
|
+
if (response.status !== 200) {
|
|
758
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
console.log(`Postback sent successfully for subid: ${subid}`);
|
|
762
|
+
} catch (error) {
|
|
763
|
+
console.error(`Failed to send postback for subid: ${subid}`, error);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// Add delay between requests to prevent overwhelming the server
|
|
767
|
+
await sleep(300);
|
|
768
|
+
};
|
|
769
|
+
|
|
770
|
+
// Process postbacks sequentially to avoid rate limiting
|
|
771
|
+
for (const subid of subids) {
|
|
772
|
+
await sendPostback(subid);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
(async () => {
|
|
778
|
+
let subids = await checkMultipleIPs();
|
|
779
|
+
await sendPostbacks(subids, 'sale', 125)
|
|
780
|
+
})();
|