@bprotsyk/aso-core 2.1.198 → 2.1.224

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/app/app.d.ts CHANGED
@@ -177,7 +177,8 @@ export interface IDomainParams {
177
177
  export declare enum AppStatus {
178
178
  ARCHIVED = "ARCHIVED",
179
179
  IN_DEVELOPMENT = "IN_DEVELOPMENT",
180
- READY = "READY"
180
+ READY = "READY",
181
+ DISABLED = "DISABLED"
181
182
  }
182
183
  export interface IKeitaroDirectTrackingParams {
183
184
  naming: string;
package/lib/app/app.js CHANGED
@@ -78,6 +78,7 @@ var AppStatus;
78
78
  AppStatus["ARCHIVED"] = "ARCHIVED";
79
79
  AppStatus["IN_DEVELOPMENT"] = "IN_DEVELOPMENT";
80
80
  AppStatus["READY"] = "READY";
81
+ AppStatus["DISABLED"] = "DISABLED";
81
82
  })(AppStatus = exports.AppStatus || (exports.AppStatus = {}));
82
83
  exports.AppSchema = new mongoose_1.Schema({
83
84
  id: {
@@ -1,7 +1,18 @@
1
1
  export interface IKeitaroOffer {
2
2
  id: number;
3
- campaign_id: number;
3
+ campaign_id?: number;
4
4
  name: string;
5
- url: string;
6
- country: string;
5
+ url?: string;
6
+ country?: string | string[];
7
+ group_id?: number;
8
+ action_type?: string;
9
+ action_payload?: string;
10
+ affiliate_network_id?: number;
11
+ payout_value?: number;
12
+ payout_currency?: string;
13
+ payout_type?: string;
14
+ state?: string;
15
+ offer_type?: string;
16
+ payout_auto?: boolean;
17
+ payout_upsell?: boolean;
7
18
  }
@@ -1,4 +1,5 @@
1
1
  import { IKeitaroStream } from "../../keitaro/keitaro-stream";
2
+ import { IOffer } from "../../offers/offer";
2
3
  import { IKeitaroCampaign } from "../../keitaro/keitaro-campaign";
3
4
  import { IKeitaroDomain } from "../../keitaro/keitaro-domain";
4
5
  import { IApp, IAppKeitaroData, IntegrationType } from "../../app/app";
@@ -15,6 +16,28 @@ declare function updateCampaign(id: number, payload: Partial<IKeitaroCampaign>):
15
16
  declare function createCampaign(campaignData: Partial<IKeitaroCampaign>): Promise<IKeitaroCampaign>;
16
17
  declare function getDomains(onlyActive?: boolean): Promise<IKeitaroDomain[]>;
17
18
  declare function getAllOffers(): Promise<IKeitaroOffer[]>;
19
+ /**
20
+ * Create offer in Keitaro from our IOffer
21
+ * @param offer - Our internal IOffer object
22
+ * @returns Keitaro offer with ID
23
+ */
24
+ declare function createOfferInKeitaro(offer: IOffer): Promise<IKeitaroOffer>;
25
+ declare function createStream(campaignId: number, streamData: Partial<IKeitaroStream>): Promise<IKeitaroStream>;
26
+ /**
27
+ * Get all offerwall campaigns (campaigns with [◈] prefix in group 106)
28
+ */
29
+ declare function getOfferwallCampaigns(): Promise<IKeitaroCampaign[]>;
30
+ /**
31
+ * Add our IOffer to Keitaro and distribute to all offerwall campaigns
32
+ * @param offer - Our internal IOffer object
33
+ * @returns Result with Keitaro offer ID and distribution stats
34
+ */
35
+ declare function addOfferToKeitaro(offer: IOffer): Promise<{
36
+ keitaroOfferId: number;
37
+ success: number;
38
+ failed: number;
39
+ campaigns: string[];
40
+ }>;
18
41
  declare function generateAlias(): string;
19
42
  /**
20
43
  * Clone a campaign for an app based on integration type
@@ -33,9 +56,13 @@ export declare const KeitaroService: {
33
56
  createCampaign: typeof createCampaign;
34
57
  updateCampaign: typeof updateCampaign;
35
58
  cloneCampaignForApp: typeof cloneCampaignForApp;
59
+ getOfferwallCampaigns: typeof getOfferwallCampaigns;
36
60
  getStreamsByCampaignId: typeof getStreamsByCampaignId;
61
+ createStream: typeof createStream;
37
62
  getDomains: typeof getDomains;
38
63
  getAllOffers: typeof getAllOffers;
64
+ createOfferInKeitaro: typeof createOfferInKeitaro;
65
+ addOfferToKeitaro: typeof addOfferToKeitaro;
39
66
  generateAlias: typeof generateAlias;
40
67
  campaignToKeitaroData: typeof campaignToKeitaroData;
41
68
  };
@@ -39,6 +39,97 @@ async function getAllOffers() {
39
39
  const { data: offers } = await http_1.default.get('offers');
40
40
  return offers;
41
41
  }
42
+ /**
43
+ * Create offer in Keitaro from our IOffer
44
+ * @param offer - Our internal IOffer object
45
+ * @returns Keitaro offer with ID
46
+ */
47
+ async function createOfferInKeitaro(offer) {
48
+ const payload = {
49
+ name: `${offer.caption} ${offer.geo} (${offer.name})`,
50
+ group_id: DEFAULT_OFFERS_GROUP_ID,
51
+ action_type: 'http',
52
+ action_payload: offer.link,
53
+ affiliate_network_id: 0,
54
+ payout_value: 0,
55
+ payout_currency: 'USD',
56
+ payout_type: 'CPA',
57
+ state: offer.hidden ? 'disabled' : 'active',
58
+ country: [offer.geo],
59
+ offer_type: 'external',
60
+ payout_auto: true,
61
+ payout_upsell: true,
62
+ };
63
+ const { data: keitaroOffer } = await http_1.default.post('offers', payload);
64
+ return keitaroOffer;
65
+ }
66
+ // Stream operations
67
+ async function createStream(campaignId, streamData) {
68
+ const { data: stream } = await http_1.default.post('streams', {
69
+ ...streamData,
70
+ campaign_id: campaignId
71
+ });
72
+ return stream;
73
+ }
74
+ /**
75
+ * Get all offerwall campaigns (campaigns with [◈] prefix in group 106)
76
+ */
77
+ async function getOfferwallCampaigns() {
78
+ const allCampaigns = await getAllCampaigns();
79
+ // Offerwall campaigns have [◈] in their name and are in group 106
80
+ return allCampaigns.filter(c => c.name.includes('[◈]') && c.group_id === DEFAULT_CAMPAIGNS_GROUP_ID);
81
+ }
82
+ /**
83
+ * Add our IOffer to Keitaro and distribute to all offerwall campaigns
84
+ * @param offer - Our internal IOffer object
85
+ * @returns Result with Keitaro offer ID and distribution stats
86
+ */
87
+ async function addOfferToKeitaro(offer) {
88
+ // First, create the offer in Keitaro
89
+ const keitaroOffer = await createOfferInKeitaro(offer);
90
+ console.log(`Created Keitaro offer #${keitaroOffer.id}: ${keitaroOffer.name}`);
91
+ // Then distribute to all offerwall campaigns
92
+ const offerwallCampaigns = await getOfferwallCampaigns();
93
+ let success = 0;
94
+ let failed = 0;
95
+ const campaignNames = [];
96
+ for (const campaign of offerwallCampaigns) {
97
+ try {
98
+ // Check if stream with this offer already exists
99
+ const existingStreams = await getStreamsByCampaignId(campaign.id);
100
+ const streamExists = existingStreams.some(stream => stream.offers?.some(o => o.offer_id === keitaroOffer.id));
101
+ if (streamExists) {
102
+ console.log(`Stream with offer ${keitaroOffer.id} already exists in campaign ${campaign.name}`);
103
+ continue;
104
+ }
105
+ // Create a new stream with the offer
106
+ await createStream(campaign.id, {
107
+ name: `${offer.geo} - ${offer.caption} (${offer.name})`,
108
+ type: 'regular',
109
+ action_type: 'http',
110
+ weight: 100,
111
+ state: offer.hidden ? 'disabled' : 'active',
112
+ offers: [{
113
+ offer_id: keitaroOffer.id,
114
+ share: 100,
115
+ state: 'active'
116
+ }],
117
+ filters: [{
118
+ name: 'country',
119
+ mode: 'accept',
120
+ payload: [offer.geo]
121
+ }]
122
+ });
123
+ success++;
124
+ campaignNames.push(campaign.name);
125
+ }
126
+ catch (error) {
127
+ console.error(`Failed to add offer to campaign ${campaign.name}:`, error);
128
+ failed++;
129
+ }
130
+ }
131
+ return { keitaroOfferId: keitaroOffer.id, success, failed, campaigns: campaignNames };
132
+ }
42
133
  // Generate random alias for campaigns
43
134
  function generateAlias() {
44
135
  const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
@@ -152,12 +243,16 @@ exports.KeitaroService = {
152
243
  createCampaign,
153
244
  updateCampaign,
154
245
  cloneCampaignForApp,
246
+ getOfferwallCampaigns,
155
247
  // Stream operations
156
248
  getStreamsByCampaignId,
249
+ createStream,
157
250
  // Domain operations
158
251
  getDomains,
159
252
  // Offer operations
160
253
  getAllOffers,
254
+ createOfferInKeitaro,
255
+ addOfferToKeitaro,
161
256
  // Utilities
162
257
  generateAlias,
163
258
  campaignToKeitaroData,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bprotsyk/aso-core",
3
- "version": "2.1.198",
3
+ "version": "2.1.224",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "scripts": {
package/src/app/app.ts CHANGED
@@ -178,7 +178,8 @@ export interface IDomainParams {
178
178
  export enum AppStatus {
179
179
  ARCHIVED = "ARCHIVED",
180
180
  IN_DEVELOPMENT = "IN_DEVELOPMENT",
181
- READY = "READY"
181
+ READY = "READY",
182
+ DISABLED = "DISABLED"
182
183
  }
183
184
 
184
185
  export interface IKeitaroDirectTrackingParams {
@@ -1,7 +1,18 @@
1
1
  export interface IKeitaroOffer {
2
2
  id: number;
3
- campaign_id: number;
3
+ campaign_id?: number;
4
4
  name: string;
5
- url: string;
6
- country: string
5
+ url?: string;
6
+ country?: string | string[];
7
+ group_id?: number;
8
+ action_type?: string;
9
+ action_payload?: string;
10
+ affiliate_network_id?: number;
11
+ payout_value?: number;
12
+ payout_currency?: string;
13
+ payout_type?: string;
14
+ state?: string;
15
+ offer_type?: string;
16
+ payout_auto?: boolean;
17
+ payout_upsell?: boolean;
7
18
  }
@@ -1,5 +1,5 @@
1
1
  import { IKeitaroStream } from "../../keitaro/keitaro-stream";
2
- import { IOffer } from "../../offers/offer"
2
+ import { IOffer } from "../../offers/offer";
3
3
  import keitaroApi from "./http"
4
4
  import { IKeitaroCampaign } from "../../keitaro/keitaro-campaign";
5
5
  import { IKeitaroDomain } from "../../keitaro/keitaro-domain";
@@ -59,6 +59,115 @@ async function getAllOffers(): Promise<IKeitaroOffer[]> {
59
59
  return offers
60
60
  }
61
61
 
62
+ /**
63
+ * Create offer in Keitaro from our IOffer
64
+ * @param offer - Our internal IOffer object
65
+ * @returns Keitaro offer with ID
66
+ */
67
+ async function createOfferInKeitaro(offer: IOffer): Promise<IKeitaroOffer> {
68
+ const payload = {
69
+ name: `${offer.caption} ${offer.geo} (${offer.name})`,
70
+ group_id: DEFAULT_OFFERS_GROUP_ID,
71
+ action_type: 'http',
72
+ action_payload: offer.link,
73
+ affiliate_network_id: 0, // Can be set if we have partner mapping
74
+ payout_value: 0,
75
+ payout_currency: 'USD',
76
+ payout_type: 'CPA',
77
+ state: offer.hidden ? 'disabled' : 'active',
78
+ country: [offer.geo],
79
+ offer_type: 'external',
80
+ payout_auto: true,
81
+ payout_upsell: true,
82
+ };
83
+ const { data: keitaroOffer } = await keitaroApi.post<IKeitaroOffer>('offers', payload);
84
+ return keitaroOffer;
85
+ }
86
+
87
+ // Stream operations
88
+ async function createStream(campaignId: number, streamData: Partial<IKeitaroStream>): Promise<IKeitaroStream> {
89
+ const { data: stream } = await keitaroApi.post<IKeitaroStream>('streams', {
90
+ ...streamData,
91
+ campaign_id: campaignId
92
+ });
93
+ return stream;
94
+ }
95
+
96
+ /**
97
+ * Get all offerwall campaigns (campaigns with [◈] prefix in group 106)
98
+ */
99
+ async function getOfferwallCampaigns(): Promise<IKeitaroCampaign[]> {
100
+ const allCampaigns = await getAllCampaigns();
101
+ // Offerwall campaigns have [◈] in their name and are in group 106
102
+ return allCampaigns.filter(c =>
103
+ c.name.includes('[◈]') && c.group_id === DEFAULT_CAMPAIGNS_GROUP_ID
104
+ );
105
+ }
106
+
107
+ /**
108
+ * Add our IOffer to Keitaro and distribute to all offerwall campaigns
109
+ * @param offer - Our internal IOffer object
110
+ * @returns Result with Keitaro offer ID and distribution stats
111
+ */
112
+ async function addOfferToKeitaro(offer: IOffer): Promise<{
113
+ keitaroOfferId: number;
114
+ success: number;
115
+ failed: number;
116
+ campaigns: string[]
117
+ }> {
118
+ // First, create the offer in Keitaro
119
+ const keitaroOffer = await createOfferInKeitaro(offer);
120
+ console.log(`Created Keitaro offer #${keitaroOffer.id}: ${keitaroOffer.name}`);
121
+
122
+ // Then distribute to all offerwall campaigns
123
+ const offerwallCampaigns = await getOfferwallCampaigns();
124
+ let success = 0;
125
+ let failed = 0;
126
+ const campaignNames: string[] = [];
127
+
128
+ for (const campaign of offerwallCampaigns) {
129
+ try {
130
+ // Check if stream with this offer already exists
131
+ const existingStreams = await getStreamsByCampaignId(campaign.id);
132
+ const streamExists = existingStreams.some(stream =>
133
+ stream.offers?.some(o => o.offer_id === keitaroOffer.id)
134
+ );
135
+
136
+ if (streamExists) {
137
+ console.log(`Stream with offer ${keitaroOffer.id} already exists in campaign ${campaign.name}`);
138
+ continue;
139
+ }
140
+
141
+ // Create a new stream with the offer
142
+ await createStream(campaign.id, {
143
+ name: `${offer.geo} - ${offer.caption} (${offer.name})`,
144
+ type: 'regular',
145
+ action_type: 'http',
146
+ weight: 100,
147
+ state: offer.hidden ? 'disabled' : 'active',
148
+ offers: [{
149
+ offer_id: keitaroOffer.id,
150
+ share: 100,
151
+ state: 'active'
152
+ }],
153
+ filters: [{
154
+ name: 'country',
155
+ mode: 'accept',
156
+ payload: [offer.geo]
157
+ }]
158
+ });
159
+
160
+ success++;
161
+ campaignNames.push(campaign.name);
162
+ } catch (error) {
163
+ console.error(`Failed to add offer to campaign ${campaign.name}:`, error);
164
+ failed++;
165
+ }
166
+ }
167
+
168
+ return { keitaroOfferId: keitaroOffer.id, success, failed, campaigns: campaignNames };
169
+ }
170
+
62
171
  // Generate random alias for campaigns
63
172
  function generateAlias(): string {
64
173
  const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
@@ -191,15 +300,19 @@ export const KeitaroService = {
191
300
  createCampaign,
192
301
  updateCampaign,
193
302
  cloneCampaignForApp,
303
+ getOfferwallCampaigns,
194
304
 
195
305
  // Stream operations
196
306
  getStreamsByCampaignId,
307
+ createStream,
197
308
 
198
309
  // Domain operations
199
310
  getDomains,
200
311
 
201
312
  // Offer operations
202
313
  getAllOffers,
314
+ createOfferInKeitaro,
315
+ addOfferToKeitaro,
203
316
 
204
317
  // Utilities
205
318
  generateAlias,