@bprotsyk/aso-core 2.1.99 → 2.1.101
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 +11 -2
- package/lib/app/app.js +2 -0
- package/lib/general/domain.d.ts +1 -0
- package/lib/general/namecheap-domain.d.ts +1 -0
- package/lib/index.d.ts +1 -1
- package/lib/keitaro/keitaro-campaign.d.ts +1 -0
- package/lib/network/keitaro/traffle/http.js +2 -1
- package/lib/network/keitaro/traffle/traffle-keitaro-service.d.ts +4 -0
- package/lib/network/keitaro/traffle/traffle-keitaro-service.js +255 -1
- package/lib/offers/list.d.ts +1 -0
- package/lib/offers/offer.d.ts +1 -0
- package/lib/offers/section.d.ts +1 -0
- package/lib/panel/user.d.ts +1 -0
- package/package.json +1 -1
- package/src/app/app.ts +8 -3
- package/src/index.ts +1 -1
- package/src/keitaro/keitaro-campaign.ts +1 -0
- package/src/network/keitaro/keitaro-service.ts +6 -0
- package/src/network/keitaro/traffle/http.ts +2 -1
- package/src/network/keitaro/traffle/traffle-keitaro-service.ts +304 -1
- package/test-keitaro.js +27 -2
- package/tsc +0 -0
- package/lib/keitaro/keitaro-conversions.d.ts +0 -52
- package/lib/keitaro/keitaro-conversions.js +0 -27
- package/lib/keitaro/keitaro-utils.d.ts +0 -2
- package/lib/keitaro/keitaro-utils.js +0 -108
- package/lib/keitaro-utils.d.ts +0 -2
- package/lib/keitaro-utils.js +0 -136
- package/lib/utils/comparing.d.ts +0 -31
- package/lib/utils/comparing.js +0 -104
package/lib/app/app.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export interface IApp extends Document {
|
|
|
26
26
|
platforms: {
|
|
27
27
|
[key: string]: IPlatformParams;
|
|
28
28
|
};
|
|
29
|
+
publicationHistory: IPublicationHistory;
|
|
29
30
|
offersListId: number;
|
|
30
31
|
externalParams?: IExternalParams;
|
|
31
32
|
proxied: boolean;
|
|
@@ -49,7 +50,12 @@ export declare enum EPlatform {
|
|
|
49
50
|
}
|
|
50
51
|
export declare enum EDirectType {
|
|
51
52
|
KEITARO_OFFER = "keitaroOffer",
|
|
52
|
-
OFFER_DIRECT = "offerDirect"
|
|
53
|
+
OFFER_DIRECT = "offerDirect",
|
|
54
|
+
TRAFFLE = "traffle"
|
|
55
|
+
}
|
|
56
|
+
export interface IPublicationHistory {
|
|
57
|
+
publications: number[];
|
|
58
|
+
removals: IRemovalInfo[];
|
|
53
59
|
}
|
|
54
60
|
export declare const getPlatformName: (platform: EPlatform | undefined) => string | false;
|
|
55
61
|
export interface IPlatformParams {
|
|
@@ -132,7 +138,7 @@ export interface IRemoveDataParams {
|
|
|
132
138
|
callbackFunctionName: string;
|
|
133
139
|
toSplashAfterSuccess: boolean;
|
|
134
140
|
}
|
|
135
|
-
export interface
|
|
141
|
+
export interface IRemovalInfo {
|
|
136
142
|
reason: string;
|
|
137
143
|
date: number;
|
|
138
144
|
status: string;
|
|
@@ -188,6 +194,7 @@ export declare const AppSchema: mongoose.Schema<any, mongoose.Model<any, any, an
|
|
|
188
194
|
removeInfo: any;
|
|
189
195
|
name?: string | null | undefined;
|
|
190
196
|
pushesEnabled?: boolean | null | undefined;
|
|
197
|
+
publicationHistory?: any;
|
|
191
198
|
removeDataParams?: any;
|
|
192
199
|
privacyPolicyParams?: any;
|
|
193
200
|
offersStubParams?: any;
|
|
@@ -229,6 +236,7 @@ export declare const AppSchema: mongoose.Schema<any, mongoose.Model<any, any, an
|
|
|
229
236
|
removeInfo: any;
|
|
230
237
|
name?: string | null | undefined;
|
|
231
238
|
pushesEnabled?: boolean | null | undefined;
|
|
239
|
+
publicationHistory?: any;
|
|
232
240
|
removeDataParams?: any;
|
|
233
241
|
privacyPolicyParams?: any;
|
|
234
242
|
offersStubParams?: any;
|
|
@@ -270,6 +278,7 @@ export declare const AppSchema: mongoose.Schema<any, mongoose.Model<any, any, an
|
|
|
270
278
|
removeInfo: any;
|
|
271
279
|
name?: string | null | undefined;
|
|
272
280
|
pushesEnabled?: boolean | null | undefined;
|
|
281
|
+
publicationHistory?: any;
|
|
273
282
|
removeDataParams?: any;
|
|
274
283
|
privacyPolicyParams?: any;
|
|
275
284
|
offersStubParams?: any;
|
package/lib/app/app.js
CHANGED
|
@@ -25,6 +25,7 @@ var EDirectType;
|
|
|
25
25
|
(function (EDirectType) {
|
|
26
26
|
EDirectType["KEITARO_OFFER"] = "keitaroOffer";
|
|
27
27
|
EDirectType["OFFER_DIRECT"] = "offerDirect";
|
|
28
|
+
EDirectType["TRAFFLE"] = "traffle";
|
|
28
29
|
})(EDirectType = exports.EDirectType || (exports.EDirectType = {}));
|
|
29
30
|
const getPlatformName = (platform) => {
|
|
30
31
|
switch (platform) {
|
|
@@ -178,6 +179,7 @@ exports.AppSchema = new mongoose_1.Schema({
|
|
|
178
179
|
default: "none"
|
|
179
180
|
},
|
|
180
181
|
},
|
|
182
|
+
publicationHistory: Object,
|
|
181
183
|
removeDataParams: Object,
|
|
182
184
|
removeInfo: {
|
|
183
185
|
type: Object,
|
package/lib/general/domain.d.ts
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
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" />
|
|
25
26
|
import { ICloudflareDomainType } from "general/cloudflare-domain";
|
|
26
27
|
import { Document, Model, Schema } from "mongoose";
|
|
27
28
|
export interface IDomain extends Document {
|
|
@@ -22,6 +22,7 @@
|
|
|
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" />
|
|
25
26
|
import { Schema, Document } from "mongoose";
|
|
26
27
|
export interface INamecheapDomain {
|
|
27
28
|
ID: string;
|
package/lib/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { IPush } from "./general/push";
|
|
|
2
2
|
export { IOffer, IPartner, IOfferType } from "./offers/offer";
|
|
3
3
|
export { IOffersSection, OffersSectionSchema, DefaultSectionId } from "./offers/section";
|
|
4
4
|
export { IAppOffersSection, ISectionsList, SectionsListSchema, IOfferState } from "./offers/list";
|
|
5
|
-
export { IAdjustEventIds, IntegrationVersion, IApp, AppSchema, PlugType, IAppKeitaroData, IExternalParams, IPlatformParams, EPlatform, AppStatus } from "./app/app";
|
|
5
|
+
export { IAdjustEventIds, IntegrationVersion, IApp, AppSchema, PlugType, IAppKeitaroData, IExternalParams, IPlatformParams, EPlatform, AppStatus, IPublicationHistory, IRemovalInfo } from "./app/app";
|
|
6
6
|
export { IAppListItem } from "./app/app-list-item";
|
|
7
7
|
export { AppType } from "./app/app-type";
|
|
8
8
|
export { AlternativeLayoutType, AlternativeSourceType, AlternativeLogicType, AlternativeNetworkTool, AlternativeStorageType, AlternativeNavigation, AlternativeOnBackPressed, AlternativeOnActivityResult, IAppIntegration as IFlashIntegration } from "./app/app-integration";
|
|
@@ -7,6 +7,7 @@ const axios_1 = __importDefault(require("axios"));
|
|
|
7
7
|
exports.default = axios_1.default.create({
|
|
8
8
|
baseURL: 'https://traffle-tech.com/admin_api/v1/',
|
|
9
9
|
headers: {
|
|
10
|
-
"Api-Key": `3e80a8fcf1ceb01a761457d017e43a0a`,
|
|
10
|
+
// "Api-Key": `3e80a8fcf1ceb01a761457d017e43a0a`,
|
|
11
|
+
"Api-Key": `778a14c0730abe2629e88101cb88d573`,
|
|
11
12
|
},
|
|
12
13
|
});
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { IOffer } from "../../../offers/offer";
|
|
2
|
+
import { IKeitaroCampaign } from "../../../keitaro/keitaro-campaign";
|
|
3
|
+
import { EPlatform, IApp } from "../../../app/app";
|
|
2
4
|
import { IKeitaroOffer } from "index";
|
|
3
5
|
declare function getAllOffers(): Promise<IKeitaroOffer[]>;
|
|
4
6
|
export declare enum ITraffleTrafficType {
|
|
@@ -35,6 +37,7 @@ declare function getTraffleAffiliateNetworks(): Promise<IAffiliateNetwork[]>;
|
|
|
35
37
|
declare function deleteOfferById(id: number): Promise<any>;
|
|
36
38
|
declare function addOffersToTraffleKeitaro(offers: ITraffleOffer[]): Promise<void>;
|
|
37
39
|
declare function updateOfferLinkById(id: number, action_payload: string | object): Promise<any>;
|
|
40
|
+
declare function cloneTraffleCampaign(app: IApp, platform: EPlatform, addDefaultStreams?: boolean): Promise<IKeitaroCampaign | any>;
|
|
38
41
|
export declare const TraffleKeitaroService: {
|
|
39
42
|
addOffersToTraffleKeitaro: typeof addOffersToTraffleKeitaro;
|
|
40
43
|
getTraffleOffersGroups: typeof getTraffleOffersGroups;
|
|
@@ -43,5 +46,6 @@ export declare const TraffleKeitaroService: {
|
|
|
43
46
|
deleteOfferById: typeof deleteOfferById;
|
|
44
47
|
getAllOffers: typeof getAllOffers;
|
|
45
48
|
updateOfferLinkById: typeof updateOfferLinkById;
|
|
49
|
+
cloneTraffleCampaign: typeof cloneTraffleCampaign;
|
|
46
50
|
};
|
|
47
51
|
export {};
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.TraffleKeitaroService = exports.ITraffleTrafficType = void 0;
|
|
7
7
|
const http_1 = __importDefault(require("./http"));
|
|
8
|
+
const app_1 = require("../../../app/app");
|
|
8
9
|
const openai_1 = require("../../../network/openai/openai");
|
|
9
10
|
async function getAllOffers() {
|
|
10
11
|
const { data: offers } = await http_1.default.get('offers');
|
|
@@ -102,6 +103,259 @@ async function updateOfferLinkById(id, action_payload) {
|
|
|
102
103
|
const response = await http_1.default.put(`/offers/${id}`, updateData);
|
|
103
104
|
return response.data;
|
|
104
105
|
}
|
|
106
|
+
async function getCampaignById(id) {
|
|
107
|
+
const { data: campaign } = await http_1.default.get(`/campaigns/${id}`);
|
|
108
|
+
return campaign;
|
|
109
|
+
}
|
|
110
|
+
async function getAllCampaigns() {
|
|
111
|
+
const { data: campaigns } = await http_1.default.get('campaigns');
|
|
112
|
+
return campaigns;
|
|
113
|
+
}
|
|
114
|
+
async function getDomains(onlyActive) {
|
|
115
|
+
const { data: domains } = await http_1.default.get(`/domains`);
|
|
116
|
+
return onlyActive ? domains.filter((d) => d.network_status == "active") : domains;
|
|
117
|
+
}
|
|
118
|
+
async function getStreamsByCampaignId(campaignId) {
|
|
119
|
+
const { data: streams } = await http_1.default.get(`campaigns/${campaignId}/streams`);
|
|
120
|
+
return streams;
|
|
121
|
+
}
|
|
122
|
+
async function createCampaign(campaignData) {
|
|
123
|
+
let { data: campaign } = await http_1.default.post(`/campaigns`, campaignData);
|
|
124
|
+
return campaign;
|
|
125
|
+
}
|
|
126
|
+
async function TrafleKeitaroParameters(parameters) {
|
|
127
|
+
const { bundle, appsflyerDevKey, name } = parameters;
|
|
128
|
+
let openAIResponse = await openai_1.OpenAI.requestOpenAI({
|
|
129
|
+
model: "o3-mini",
|
|
130
|
+
messages: [
|
|
131
|
+
{ role: "user", content: `sid for ${bundle} ${name} generations Generate **one** random English word in full lowercase (still lowercase, no numbers or special characters) for the parameters "naming", "advertisingid", "appsflyerDeviceID". Return **ONLY** an JSON object: { "naming": "word", "advertisingid": "word", "appsflyerDeviceID": "word"}` },
|
|
132
|
+
]
|
|
133
|
+
});
|
|
134
|
+
if (!openAIResponse) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
let ParamsGenerationsOpenAIResponse = null;
|
|
138
|
+
try {
|
|
139
|
+
ParamsGenerationsOpenAIResponse = JSON.parse(openAIResponse);
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
console.error("Failed to parse OpenAI response:", error);
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
console.log(`ParamsGenerationsOpenAIResponse: ${JSON.stringify(ParamsGenerationsOpenAIResponse)}`);
|
|
146
|
+
return {
|
|
147
|
+
parameters: {
|
|
148
|
+
keyword: { name: 'keyword', placeholder: '', alias: '' },
|
|
149
|
+
cost: { name: 'cost', placeholder: '', alias: '' },
|
|
150
|
+
currency: { name: 'currency', placeholder: '', alias: '' },
|
|
151
|
+
external_id: { name: 'external_id', placeholder: '', alias: '' },
|
|
152
|
+
creative_id: { name: 'creative_id', placeholder: '', alias: '' },
|
|
153
|
+
ad_campaign_id: { name: 'ad_campaign_id', placeholder: '', alias: '' },
|
|
154
|
+
source: { name: 'source', placeholder: '', alias: '' },
|
|
155
|
+
sub_id_1: { name: 'uqID', placeholder: '', alias: '' },
|
|
156
|
+
sub_id_2: { name: 'AD_ID', placeholder: '', alias: '' },
|
|
157
|
+
sub_id_3: { name: 'USB', placeholder: '', alias: '' },
|
|
158
|
+
sub_id_4: { name: 'DEV', placeholder: '', alias: '' },
|
|
159
|
+
sub_id_5: { name: 'LANG', placeholder: '', alias: '' },
|
|
160
|
+
sub_id_10: { name: 'market', placeholder: '', alias: '' },
|
|
161
|
+
sub_id_15: { name: ParamsGenerationsOpenAIResponse?.naming, placeholder: '{naming}', alias: 'Naming' },
|
|
162
|
+
sub_id_16: {
|
|
163
|
+
name: 'bundle_id',
|
|
164
|
+
placeholder: bundle,
|
|
165
|
+
alias: 'Bundle ID'
|
|
166
|
+
},
|
|
167
|
+
sub_id_17: {
|
|
168
|
+
name: ParamsGenerationsOpenAIResponse?.advertisingid,
|
|
169
|
+
placeholder: '{advertising_id}',
|
|
170
|
+
alias: 'Advertising ID'
|
|
171
|
+
},
|
|
172
|
+
sub_id_18: {
|
|
173
|
+
name: ParamsGenerationsOpenAIResponse?.appsflyerDeviceID,
|
|
174
|
+
placeholder: '{appsflyer_device_id}',
|
|
175
|
+
alias: 'Appsflyer Device ID'
|
|
176
|
+
},
|
|
177
|
+
sub_id_19: {
|
|
178
|
+
name: 'appsflyer_dev_key',
|
|
179
|
+
placeholder: appsflyerDevKey,
|
|
180
|
+
alias: 'Appsflyer Dev Key'
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
async function cloneTraffleCampaign(app, platform, addDefaultStreams) {
|
|
186
|
+
const ORIGINAL_CLONE_CAMPAIGN_ID = 1925;
|
|
187
|
+
const appsflyerAvailability = app.platforms[platform].appsflyerParams?.apiToken ? "[AF]" : "";
|
|
188
|
+
let name = `[${app.id}] ${app.name} ET [${app.bundle}] [Android] ${appsflyerAvailability} ${app.domainParams.name}`;
|
|
189
|
+
let platformName = platform ? (0, app_1.getPlatformName)(platform) : null;
|
|
190
|
+
const platformCampaignName = `#${app.id} [➥] (${platformName})`;
|
|
191
|
+
const generateAlias = () => {
|
|
192
|
+
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
193
|
+
return Array.from({ length: 8 }, () => chars.charAt(Math.floor(Math.random() * chars.length))).join('');
|
|
194
|
+
};
|
|
195
|
+
let allCampaigns = await getAllCampaigns();
|
|
196
|
+
let matchingCampaign = [];
|
|
197
|
+
if (platform && platform !== app_1.EPlatform.GENERAL) {
|
|
198
|
+
// Для конкретної платформи
|
|
199
|
+
const platformName = (0, app_1.getPlatformName)(platform);
|
|
200
|
+
matchingCampaign = allCampaigns.filter((c) => {
|
|
201
|
+
// Точна перевірка ID з межами слів
|
|
202
|
+
const idPattern = new RegExp(`${app.id}\\b`);
|
|
203
|
+
const hasId = idPattern.test(c.name);
|
|
204
|
+
const hasBundle = c.name.includes(`[${app.bundle}]`);
|
|
205
|
+
// Перевіряємо наявність платформи в дужках в кінці назви
|
|
206
|
+
const platformPattern = new RegExp(`\\(.*${platformName}.*\\)\\s*$`);
|
|
207
|
+
const hasPlatform = platformPattern.test(c.name);
|
|
208
|
+
return hasId && hasBundle && hasPlatform;
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
// Для General платформи
|
|
213
|
+
matchingCampaign = allCampaigns.filter((c) => {
|
|
214
|
+
// Точна перевірка ID з межами слів
|
|
215
|
+
const idPattern = new RegExp(`${app.id}\\b`);
|
|
216
|
+
const hasId = idPattern.test(c.name);
|
|
217
|
+
const hasBundle = c.name.includes(`[${app.bundle}]`);
|
|
218
|
+
// Перевіряємо відсутність платформи в дужках в кінці
|
|
219
|
+
// Дозволяємо будь-які інші дужки (як для гео або опису)
|
|
220
|
+
const noPlatformAtEnd = !/\(.*(?:iOS|Android|Desktop|Mobile).*\)\s*$/.test(c.name);
|
|
221
|
+
return hasId && hasBundle && noPlatformAtEnd;
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
const originalCampaign = await getCampaignById(ORIGINAL_CLONE_CAMPAIGN_ID);
|
|
225
|
+
const maxPosition = Math.max(...allCampaigns.map(c => c.position || 0));
|
|
226
|
+
let allDomains = await getDomains(true);
|
|
227
|
+
if (!allDomains) {
|
|
228
|
+
throw Error(`Failed to get all domains list`);
|
|
229
|
+
}
|
|
230
|
+
const maxGroupId = Math.max(...allCampaigns.map(c => c.group_id || 0));
|
|
231
|
+
const originalStreams = await getStreamsByCampaignId(ORIGINAL_CLONE_CAMPAIGN_ID);
|
|
232
|
+
let parameters = await TrafleKeitaroParameters({ bundle: app.bundle, appsflyerDevKey: app.platforms[platform].appsflyerParams?.apiToken, name: name });
|
|
233
|
+
const createStreamWithoutIds = async (stream, campaignId) => {
|
|
234
|
+
// Створюємо базовий об'єкт потоку без ID
|
|
235
|
+
const newStream = {
|
|
236
|
+
type: stream.type,
|
|
237
|
+
name: stream.name,
|
|
238
|
+
campaign_id: campaignId,
|
|
239
|
+
position: stream.position,
|
|
240
|
+
state: stream.state,
|
|
241
|
+
action_type: stream.action_type,
|
|
242
|
+
action_payload: stream.action_payload || "",
|
|
243
|
+
schema: stream.schema,
|
|
244
|
+
collect_clicks: stream.collect_clicks,
|
|
245
|
+
filter_or: stream.filter_or,
|
|
246
|
+
weight: stream.weight,
|
|
247
|
+
filters: stream.filters.map(filter => ({
|
|
248
|
+
name: filter.name,
|
|
249
|
+
mode: filter.mode,
|
|
250
|
+
payload: filter.payload
|
|
251
|
+
})),
|
|
252
|
+
offers: stream.offers.map(offer => ({
|
|
253
|
+
offer_id: offer.offer_id,
|
|
254
|
+
state: offer.state,
|
|
255
|
+
share: offer.share
|
|
256
|
+
}))
|
|
257
|
+
};
|
|
258
|
+
// Створюємо новий потік
|
|
259
|
+
await http_1.default.post('streams', newStream);
|
|
260
|
+
};
|
|
261
|
+
const updateOrCreateCLOStream = async (campaignId, existingStreams) => {
|
|
262
|
+
const cloTemplate = originalStreams.find(s => s.name === "CLO");
|
|
263
|
+
if (!cloTemplate)
|
|
264
|
+
return;
|
|
265
|
+
const cloStream = {
|
|
266
|
+
type: cloTemplate.type,
|
|
267
|
+
name: "CLO",
|
|
268
|
+
campaign_id: campaignId,
|
|
269
|
+
position: cloTemplate.position,
|
|
270
|
+
state: cloTemplate.state,
|
|
271
|
+
action_type: cloTemplate.action_type,
|
|
272
|
+
action_payload: cloTemplate.action_payload || "",
|
|
273
|
+
schema: cloTemplate.schema,
|
|
274
|
+
collect_clicks: cloTemplate.collect_clicks,
|
|
275
|
+
filter_or: cloTemplate.filter_or,
|
|
276
|
+
weight: cloTemplate.weight,
|
|
277
|
+
filters: [
|
|
278
|
+
{
|
|
279
|
+
name: "country",
|
|
280
|
+
mode: "reject",
|
|
281
|
+
payload: app.platforms[platform].geo || []
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
name: "bot",
|
|
285
|
+
mode: "accept",
|
|
286
|
+
payload: null
|
|
287
|
+
}
|
|
288
|
+
],
|
|
289
|
+
offers: []
|
|
290
|
+
};
|
|
291
|
+
if (existingStreams) {
|
|
292
|
+
const existingCLO = existingStreams.find(s => s.name === "CLO");
|
|
293
|
+
if (existingCLO) {
|
|
294
|
+
await http_1.default.put(`streams/${existingCLO.id}`, cloStream);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
await http_1.default.post('streams', cloStream);
|
|
299
|
+
};
|
|
300
|
+
// Якщо знайдена існуюча кампанія
|
|
301
|
+
if (matchingCampaign.length > 0) {
|
|
302
|
+
const existingCampaign = matchingCampaign[0];
|
|
303
|
+
const existingStreams = await getStreamsByCampaignId(existingCampaign.id);
|
|
304
|
+
// Завжди оновлюємо CLO потік
|
|
305
|
+
await updateOrCreateCLOStream(existingCampaign.id, existingStreams);
|
|
306
|
+
// Для інших потоків
|
|
307
|
+
if (addDefaultStreams) {
|
|
308
|
+
for (const stream of originalStreams) {
|
|
309
|
+
if (stream.name === "CLO")
|
|
310
|
+
continue; // Пропускаємо CLO
|
|
311
|
+
const existingStream = existingStreams.find(s => s.name === stream.name);
|
|
312
|
+
if (!existingStream) {
|
|
313
|
+
await createStreamWithoutIds(stream, existingCampaign.id);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return existingCampaign;
|
|
318
|
+
}
|
|
319
|
+
// Створення нової кампанії
|
|
320
|
+
let alias = generateAlias();
|
|
321
|
+
let payload = {
|
|
322
|
+
// Унікальні поля
|
|
323
|
+
name: platformName ? platformCampaignName : name,
|
|
324
|
+
alias: alias,
|
|
325
|
+
domain_id: originalCampaign.domain_id,
|
|
326
|
+
position: [maxPosition + 100],
|
|
327
|
+
group_id: maxGroupId + 1,
|
|
328
|
+
traffic_source_id: 17,
|
|
329
|
+
parameters: (parameters ? parameters.parameters : originalCampaign.parameters),
|
|
330
|
+
source: originalCampaign.source,
|
|
331
|
+
bind_visitors: "slo",
|
|
332
|
+
// Неунікальні поля з оригінальної кампанії
|
|
333
|
+
type: originalCampaign.type,
|
|
334
|
+
state: originalCampaign.state,
|
|
335
|
+
cost_type: originalCampaign.cost_type,
|
|
336
|
+
cost_value: originalCampaign.cost_value,
|
|
337
|
+
cost_currency: originalCampaign.cost_currency,
|
|
338
|
+
uniqueness_period: originalCampaign.uniqueness_period,
|
|
339
|
+
cookies_ttl: originalCampaign.cookies_ttl,
|
|
340
|
+
notes: originalCampaign.notes,
|
|
341
|
+
collect_clicks: originalCampaign.collect_clicks,
|
|
342
|
+
uniqueness_type: originalCampaign.uniqueness_type,
|
|
343
|
+
};
|
|
344
|
+
const newCampaign = await createCampaign(payload);
|
|
345
|
+
// Спочатку створюємо CLO потік з оновленими гео
|
|
346
|
+
await updateOrCreateCLOStream(newCampaign.id);
|
|
347
|
+
// Потім клонуємо всі інші потоки
|
|
348
|
+
for (const stream of originalStreams) {
|
|
349
|
+
if (stream.name === "CLO")
|
|
350
|
+
continue; // Пропускаємо CLO потік
|
|
351
|
+
await createStreamWithoutIds(stream, newCampaign.id);
|
|
352
|
+
}
|
|
353
|
+
await http_1.default.put(`/campaigns/${newCampaign.id}`, {
|
|
354
|
+
group_id: originalCampaign.group_id
|
|
355
|
+
});
|
|
356
|
+
const updatedCampaign = await getCampaignById(newCampaign.id);
|
|
357
|
+
return updatedCampaign;
|
|
358
|
+
}
|
|
105
359
|
exports.TraffleKeitaroService = {
|
|
106
|
-
addOffersToTraffleKeitaro, getTraffleOffersGroups, getTraffleAffiliateNetworks, createGroup, deleteOfferById, getAllOffers, updateOfferLinkById
|
|
360
|
+
addOffersToTraffleKeitaro, getTraffleOffersGroups, getTraffleAffiliateNetworks, createGroup, deleteOfferById, getAllOffers, updateOfferLinkById, cloneTraffleCampaign
|
|
107
361
|
};
|
package/lib/offers/list.d.ts
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
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" />
|
|
25
26
|
import { Schema } from "mongoose";
|
|
26
27
|
export interface ISectionsList {
|
|
27
28
|
id: number;
|
package/lib/offers/offer.d.ts
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
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" />
|
|
25
26
|
import { Document, Model, Schema } from "mongoose";
|
|
26
27
|
export interface IOffer extends Document {
|
|
27
28
|
id: number;
|
package/lib/offers/section.d.ts
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
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" />
|
|
25
26
|
import { Schema } from "mongoose";
|
|
26
27
|
export interface IOffersSection {
|
|
27
28
|
id: number;
|
package/lib/panel/user.d.ts
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
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" />
|
|
25
26
|
import { Document, Schema } from "mongoose";
|
|
26
27
|
export declare enum PanelUserAccessScope {
|
|
27
28
|
ADMIN = 0,
|
package/package.json
CHANGED
package/src/app/app.ts
CHANGED
|
@@ -34,6 +34,7 @@ export interface IApp extends Document {
|
|
|
34
34
|
remoteServerParams?: IRemoteServerParams,
|
|
35
35
|
domainParams: IDomainParams
|
|
36
36
|
platforms: { [key: string]: IPlatformParams },
|
|
37
|
+
publicationHistory: IPublicationHistory,
|
|
37
38
|
|
|
38
39
|
offersListId: number,
|
|
39
40
|
externalParams?: IExternalParams,
|
|
@@ -62,10 +63,13 @@ export enum EPlatform {
|
|
|
62
63
|
export enum EDirectType{
|
|
63
64
|
KEITARO_OFFER = 'keitaroOffer',
|
|
64
65
|
OFFER_DIRECT = 'offerDirect',
|
|
66
|
+
TRAFFLE = 'traffle'
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
export interface IPublicationHistory {
|
|
70
|
+
publications: number[],
|
|
71
|
+
removals: IRemovalInfo[]
|
|
72
|
+
}
|
|
69
73
|
|
|
70
74
|
export const getPlatformName = (platform: EPlatform | undefined): string | false => {
|
|
71
75
|
switch (platform) {
|
|
@@ -183,7 +187,7 @@ export interface IRemoveDataParams {
|
|
|
183
187
|
toSplashAfterSuccess: boolean
|
|
184
188
|
}
|
|
185
189
|
|
|
186
|
-
export interface
|
|
190
|
+
export interface IRemovalInfo {
|
|
187
191
|
reason: string,
|
|
188
192
|
date: number,
|
|
189
193
|
status: string,
|
|
@@ -340,6 +344,7 @@ export const AppSchema = new Schema({
|
|
|
340
344
|
default: "none"
|
|
341
345
|
},
|
|
342
346
|
},
|
|
347
|
+
publicationHistory: Object,
|
|
343
348
|
removeDataParams: Object,
|
|
344
349
|
removeInfo: {
|
|
345
350
|
type: Object,
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { IOffer, IPartner, IOfferType } from "./offers/offer"
|
|
|
4
4
|
export { IOffersSection, OffersSectionSchema, DefaultSectionId } from "./offers/section"
|
|
5
5
|
export { IAppOffersSection, ISectionsList, SectionsListSchema, IOfferState } from "./offers/list"
|
|
6
6
|
|
|
7
|
-
export { IAdjustEventIds, IntegrationVersion, IApp, AppSchema, PlugType, IAppKeitaroData, IExternalParams, IPlatformParams, EPlatform, AppStatus } from "./app/app"
|
|
7
|
+
export { IAdjustEventIds, IntegrationVersion, IApp, AppSchema, PlugType, IAppKeitaroData, IExternalParams, IPlatformParams, EPlatform, AppStatus, IPublicationHistory, IRemovalInfo } from "./app/app"
|
|
8
8
|
export { IAppListItem } from "./app/app-list-item"
|
|
9
9
|
export { AppType } from "./app/app-type"
|
|
10
10
|
export { AlternativeLayoutType, AlternativeSourceType, AlternativeLogicType, AlternativeNetworkTool, AlternativeStorageType, AlternativeNavigation, AlternativeOnBackPressed, AlternativeOnActivityResult, IAppIntegration as IFlashIntegration } from "./app/app-integration"
|
|
@@ -26,6 +26,8 @@ async function getAllCampaigns(): Promise<IKeitaroCampaign[]> {
|
|
|
26
26
|
return campaigns
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
|
|
30
|
+
|
|
29
31
|
async function cloneStreams(originalCampaignId: number, streamPositionsToClone: number[], campaignRegExp: RegExp): Promise<void> {
|
|
30
32
|
// Get the original campaign's streams
|
|
31
33
|
const originalStreams = await getStreamsByCampaignId(originalCampaignId)
|
|
@@ -498,6 +500,10 @@ async function cloneDirectCampaign(app: IApp, platform?: EPlatform, addDefaultSt
|
|
|
498
500
|
|
|
499
501
|
}
|
|
500
502
|
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
|
|
501
507
|
async function cloneDCampaign(app: IApp): Promise<IKeitaroCampaign> {
|
|
502
508
|
let name = `D #${app.id} (${app.bundle})`
|
|
503
509
|
|
|
@@ -3,6 +3,7 @@ import axios from "axios";
|
|
|
3
3
|
export default axios.create({
|
|
4
4
|
baseURL: 'https://traffle-tech.com/admin_api/v1/',
|
|
5
5
|
headers: {
|
|
6
|
-
"Api-Key": `3e80a8fcf1ceb01a761457d017e43a0a`,
|
|
6
|
+
// "Api-Key": `3e80a8fcf1ceb01a761457d017e43a0a`,
|
|
7
|
+
"Api-Key": `778a14c0730abe2629e88101cb88d573`,
|
|
7
8
|
},
|
|
8
9
|
});
|