@bprotsyk/aso-core 2.1.42 → 2.1.44

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.
@@ -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 addOfferToKeitaro(offer: IOffer, affiliateId: number, link: string, avoidGroup?: number, groupId?: number): Promise<void>;
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
- addOfferToKeitaro: typeof addOfferToKeitaro;
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,26 +55,28 @@ 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(streamPartialPayload, offerId, campaignRegExp, avoidGroup) {
59
- // Get a list of all campaigns
58
+ async function createStreamForMatchingCampaigns(streamPayloads, campaignRegExp, avoidGroup) {
59
+ // Get all campaigns once
60
60
  const allCampaigns = await getAllCampaigns();
61
- // Filter the campaigns by the given RegExp
62
- const matchingCampaigns = allCampaigns.filter(campaign => (avoidGroup ? campaign.group_id != avoidGroup : true) && campaignRegExp.exec(campaign.name));
63
- // console.log(matchingCampaigns)
64
- // For each matching campaign, clone the streams
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
- let streams = await getStreamsByCampaignId(matchingCampaign.id);
67
- let identicalStream = streams.find((stream) => stream.name.includes(offerId));
68
- if (identicalStream) {
69
- await http_1.default.put(`streams/${identicalStream.id}`, {
70
- campaign_id: matchingCampaign.id,
71
- ...streamPartialPayload
72
- });
73
- }
74
- else {
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.delete(`streams/${identicalStream.id}`);
76
+ }
75
77
  await http_1.default.post('streams', {
76
78
  campaign_id: matchingCampaign.id,
77
- ...streamPartialPayload
79
+ ...payload
78
80
  });
79
81
  }
80
82
  }
@@ -120,31 +122,38 @@ function createStreamPartialPayload(keitaroOfferId, offerName, offerId, offerGeo
120
122
  }],
121
123
  };
122
124
  }
123
- async function addOfferToKeitaro(offer, affiliateId, link, avoidGroup, groupId) {
124
- // TODO look if offer already exists by offer.name
125
- let allOffers = await getAllOffers();
126
- let identicalOffer = allOffers.find((o) => { return o.name.includes(offer.name); });
127
- let keitaroOfferId;
128
- if (identicalOffer) {
129
- keitaroOfferId = identicalOffer.id;
130
- }
131
- else {
132
- let offerPayload = {
133
- name: `${offer.caption} ${offer.geo} (${offer.name})`,
134
- group_id: groupId || 1,
135
- action_payload: link,
136
- affiliate_network_id: affiliateId,
137
- country: [offer.geo],
138
- action_type: "http",
139
- offer_type: "external",
140
- payout_auto: true,
141
- payout_upsell: true,
142
- };
143
- const { data: keitaroOffer } = await http_1.default.post(`offers`, offerPayload);
144
- keitaroOfferId = keitaroOffer.id;
125
+ async function addOffersToKeitaro(offers, affiliateId, links, avoidGroup, groupId) {
126
+ const allOffers = await getAllOffers();
127
+ const streamPayloads = [];
128
+ for (let i = 0; i < offers.length; i++) {
129
+ const offer = offers[i];
130
+ const link = links[i];
131
+ const identicalOffer = allOffers.find(o => o.name.includes(offer.name));
132
+ let keitaroOfferId;
133
+ if (identicalOffer) {
134
+ keitaroOfferId = identicalOffer.id;
135
+ }
136
+ else {
137
+ const offerPayload = {
138
+ name: `${offer.caption} ${offer.geo} (${offer.name})`,
139
+ group_id: groupId || 1,
140
+ action_payload: link,
141
+ affiliate_network_id: affiliateId,
142
+ country: [offer.geo],
143
+ action_type: "http",
144
+ offer_type: "external",
145
+ payout_auto: true,
146
+ payout_upsell: true,
147
+ };
148
+ const { data: keitaroOffer } = await http_1.default.post('offers', offerPayload);
149
+ keitaroOfferId = keitaroOffer.id;
150
+ }
151
+ streamPayloads.push({
152
+ payload: createStreamPartialPayload(keitaroOfferId, offer.caption, offer.name, offer.geo),
153
+ offerId: offer.name
154
+ });
145
155
  }
146
- let streamPartialPayload = createStreamPartialPayload(keitaroOfferId, offer.caption, offer.name, offer.geo);
147
- await createStreamForMatchingCampaigns(streamPartialPayload, offer.name, /◈/, avoidGroup);
156
+ await createStreamForMatchingCampaigns(streamPayloads, /◈/, avoidGroup);
148
157
  }
149
158
  async function createCampaign(campaignData) {
150
159
  let { data: campaign } = await http_1.default.post(`/campaigns`, campaignData);
@@ -275,9 +284,18 @@ async function fixBrokenClickCosts(startDate, endDate) {
275
284
  // Make the API request to update costs
276
285
  await http_1.default.post('/clicks/update_costs', payload);
277
286
  }
287
+ async function getClicks(request) {
288
+ const defaultRequest = typeof request === 'string' ? {
289
+ range: { interval: request }
290
+ } : {
291
+ ...request
292
+ };
293
+ const { data } = await http_1.default.post('/clicks/log', defaultRequest);
294
+ return data.rows;
295
+ }
278
296
  exports.KeitaroService = {
279
- getStreamsByCampaignId, updateCampaign, getAllCampaigns, getAllOffers, cloneStreams, addOfferToKeitaro, getOfferByKeitaroId, getDomains, createCampaign, getCampaignById, upsertStreamToCampaign, cloneOWCampaign,
280
- updateOffer, changeCampaignsGroup, getProfitForTimeRange,
297
+ getStreamsByCampaignId, updateCampaign, getAllCampaigns, getAllOffers, cloneStreams, addOffersToKeitaro, getOfferByKeitaroId, getDomains, createCampaign, getCampaignById, upsertStreamToCampaign, cloneOWCampaign,
298
+ updateOffer, changeCampaignsGroup, getProfitForTimeRange, getClicks,
281
299
  // getProfitForTodayAndYesterday,
282
300
  cloneDCampaign, findKeitaroOffers, fixBrokenClickCosts
283
301
  };
@@ -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.createOWCampaign = exports.createDirectCampaign = exports.createFlashCampaigns = exports.createOWStreamPartialPayload = exports.prepareOWCampaignParameters = exports.removeGeosFromAllRedirectCampaigns = exports.addGeosToAllRedirectCampaigns = exports.TRAFFIC_SOURCE_ID_FLASH_AI = void 0;
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
- // disableAutoCost();
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bprotsyk/aso-core",
3
- "version": "2.1.42",
3
+ "version": "2.1.44",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "scripts": {
@@ -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,30 +72,35 @@ async function updateCampaign(id: number, payload: Partial<IKeitaroCampaign>) {
71
72
  await keitaroApi.put(`campaigns/${id}`, payload)
72
73
  }
73
74
 
74
- async function createStreamForMatchingCampaigns(streamPartialPayload: any, offerId: string, campaignRegExp: RegExp, avoidGroup?: number) {
75
- // Get a list of all campaigns
76
- const allCampaigns = await getAllCampaigns()
77
-
78
- // Filter the campaigns by the given RegExp
79
- const matchingCampaigns = allCampaigns.filter(campaign => (avoidGroup ? campaign.group_id != avoidGroup : true) && campaignRegExp.exec(campaign.name));
80
- // console.log(matchingCampaigns)
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
- // For each matching campaign, clone the streams
89
+ // Process each campaign
84
90
  for (const matchingCampaign of matchingCampaigns) {
85
- let streams = await getStreamsByCampaignId(matchingCampaign.id)
91
+ const streams = campaignStreams.get(matchingCampaign.id) || [];
86
92
 
87
- let identicalStream = streams.find((stream) => stream.name.includes(offerId))
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.delete(`streams/${identicalStream.id}`);
99
+ }
88
100
 
89
- if (identicalStream) {
90
- await keitaroApi.put(`streams/${identicalStream.id}`, {
91
- campaign_id: matchingCampaign.id,
92
- ...streamPartialPayload
93
- });
94
- } else {
95
101
  await keitaroApi.post('streams', {
96
102
  campaign_id: matchingCampaign.id,
97
- ...streamPartialPayload
103
+ ...payload
98
104
  });
99
105
  }
100
106
  }
@@ -149,35 +155,49 @@ function createStreamPartialPayload(keitaroOfferId: number, offerName: string, o
149
155
  }
150
156
  }
151
157
 
152
- async function addOfferToKeitaro(offer: IOffer, affiliateId: number, link: string, avoidGroup?: number, groupId?: number) {
153
- // TODO look if offer already exists by offer.name
154
- let allOffers = await getAllOffers()
155
- let identicalOffer = allOffers.find((o) => { return o.name.includes(offer.name) })
158
+ async function addOffersToKeitaro(offers: IOffer[], affiliateId: number, links: string[], avoidGroup?: number, groupId?: number) {
159
+ const allOffers = await getAllOffers();
156
160
 
157
- let keitaroOfferId
158
- if (identicalOffer) {
159
- keitaroOfferId = identicalOffer.id
160
- } else {
161
- let offerPayload = {
162
- name: `${offer.caption} ${offer.geo} (${offer.name})`,
163
- group_id: groupId || 1,
164
- action_payload: link,
165
- affiliate_network_id: affiliateId,
166
- country: [offer.geo],
167
- action_type: "http",
168
- offer_type: "external",
169
- payout_auto: true,
170
- payout_upsell: true,
171
- }
161
+ const streamPayloads = [];
172
162
 
173
- const { data: keitaroOffer } = await keitaroApi.post(`offers`, offerPayload);
163
+ for (let i = 0; i < offers.length; i++) {
164
+ const offer = offers[i];
165
+ const link = links[i];
174
166
 
175
- keitaroOfferId = keitaroOffer.id
176
- }
167
+ const identicalOffer = allOffers.find(o => o.name.includes(offer.name));
168
+
169
+ let keitaroOfferId;
170
+ if (identicalOffer) {
171
+ keitaroOfferId = identicalOffer.id;
172
+ } else {
173
+ const offerPayload = {
174
+ name: `${offer.caption} ${offer.geo} (${offer.name})`,
175
+ group_id: groupId || 1,
176
+ action_payload: link,
177
+ affiliate_network_id: affiliateId,
178
+ country: [offer.geo],
179
+ action_type: "http",
180
+ offer_type: "external",
181
+ payout_auto: true,
182
+ payout_upsell: true,
183
+ };
184
+
185
+ const { data: keitaroOffer } = await keitaroApi.post('offers', offerPayload);
186
+ keitaroOfferId = keitaroOffer.id;
187
+ }
177
188
 
178
- let streamPartialPayload = createStreamPartialPayload(keitaroOfferId, offer.caption, offer.name, offer.geo)
189
+ streamPayloads.push({
190
+ payload: createStreamPartialPayload(
191
+ keitaroOfferId,
192
+ offer.caption,
193
+ offer.name,
194
+ offer.geo
195
+ ),
196
+ offerId: offer.name
197
+ });
198
+ }
179
199
 
180
- await createStreamForMatchingCampaigns(streamPartialPayload, offer.name, /◈/, avoidGroup)
200
+ await createStreamForMatchingCampaigns(streamPayloads, /◈/, avoidGroup);
181
201
  }
182
202
 
183
203
  async function createCampaign(campaignData: Partial<IKeitaroCampaign>): Promise<IKeitaroCampaign> {
@@ -340,9 +360,21 @@ async function fixBrokenClickCosts(startDate: string, endDate: string): Promise<
340
360
  await keitaroApi.post('/clicks/update_costs', payload);
341
361
  }
342
362
 
363
+ async function getClicks(request: IKeitaroClicksRequest | KeitaroClicksInterval) {
364
+ const defaultRequest: IKeitaroClicksRequest = typeof request === 'string' ? {
365
+ range: { interval: request }
366
+ } : {
367
+ ...request
368
+ };
369
+
370
+ const { data } = await keitaroApi.post('/clicks/log', defaultRequest);
371
+ return data.rows;
372
+ }
373
+
374
+
343
375
  export const KeitaroService = {
344
- getStreamsByCampaignId, updateCampaign, getAllCampaigns, getAllOffers, cloneStreams, addOfferToKeitaro, getOfferByKeitaroId, getDomains, createCampaign, getCampaignById, upsertStreamToCampaign, cloneOWCampaign,
345
- updateOffer, changeCampaignsGroup, getProfitForTimeRange,
376
+ getStreamsByCampaignId, updateCampaign, getAllCampaigns, getAllOffers, cloneStreams, addOffersToKeitaro, getOfferByKeitaroId, getDomains, createCampaign, getCampaignById, upsertStreamToCampaign, cloneOWCampaign,
377
+ updateOffer, changeCampaignsGroup, getProfitForTimeRange, getClicks,
346
378
  // getProfitForTodayAndYesterday,
347
379
  cloneDCampaign, findKeitaroOffers, fixBrokenClickCosts
348
380
  }
@@ -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
- // disableAutoCost();
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
+ })();