@redonvn/zalo-ads-sdk 0.2.4 → 0.2.13

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/dist/index.js CHANGED
@@ -30,21 +30,28 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ ALLOWED_CTAS_PER_AD_TYPE: () => ALLOWED_CTAS_PER_AD_TYPE,
33
34
  ALL_ZALO_ADS_DOMAINS: () => ALL_ZALO_ADS_DOMAINS,
34
35
  MemoryZaloSessionStore: () => MemoryZaloSessionStore,
35
36
  RedisZaloSessionStore: () => RedisZaloSessionStore,
36
37
  TieredZaloSessionStore: () => TieredZaloSessionStore,
38
+ VALID_AD_TYPES: () => VALID_AD_TYPES,
39
+ VALID_CAMPAIGN_TYPES: () => VALID_CAMPAIGN_TYPES,
37
40
  ZaloAccountService: () => ZaloAccountService,
38
41
  ZaloAdsAccountPool: () => ZaloAdsIntegrationManager,
42
+ ZaloAdsActionType: () => ZaloAdsActionType,
43
+ ZaloAdsAgeRangeId: () => ZaloAdsAgeRangeId,
39
44
  ZaloAdsCreateFlowRequest: () => ZaloAdsCreateFlowRequest,
40
45
  ZaloAdsCreateFlowResponse: () => ZaloAdsCreateFlowResponse,
41
46
  ZaloAdsCreatePostCampaignRequest: () => ZaloAdsCreatePostCampaignRequest,
42
47
  ZaloAdsCreatePostCampaignResponse: () => ZaloAdsCreatePostCampaignResponse,
48
+ ZaloAdsDeliveryType: () => ZaloAdsDeliveryType,
43
49
  ZaloAdsFlowButtonDto: () => ZaloAdsFlowButtonDto,
44
50
  ZaloAdsFlowChildMessageDto: () => ZaloAdsFlowChildMessageDto,
45
51
  ZaloAdsFlowMessageDto: () => ZaloAdsFlowMessageDto,
46
52
  ZaloAdsIntegrationManager: () => ZaloAdsIntegrationManager,
47
53
  ZaloAdsMessageAdUpdateDataDto: () => ZaloAdsMessageAdUpdateDataDto,
54
+ ZaloAdsOsId: () => ZaloAdsOsId,
48
55
  ZaloAdsSdk: () => ZaloAdsSdk,
49
56
  ZaloAdsService: () => ZaloAdsService,
50
57
  ZaloAdsUpdateMessageAdRequest: () => ZaloAdsUpdateMessageAdRequest,
@@ -52,13 +59,17 @@ __export(index_exports, {
52
59
  ZaloAdsUpdateVideoAdRequest: () => ZaloAdsUpdateVideoAdRequest,
53
60
  ZaloAdsUpdateVideoAdResponse: () => ZaloAdsUpdateVideoAdResponse,
54
61
  ZaloAudiencesService: () => ZaloAudiencesService,
62
+ ZaloAudiencesValidator: () => ZaloAudiencesValidator,
55
63
  ZaloAuthManager: () => ZaloAuthManager,
56
64
  ZaloAutomatedRulesService: () => ZaloAutomatedRulesService,
57
65
  ZaloCampaignsService: () => ZaloCampaignsService,
66
+ ZaloCampaignsValidator: () => ZaloCampaignsValidator,
58
67
  ZaloChatWidgetService: () => ZaloChatWidgetService,
59
68
  ZaloConversionsService: () => ZaloConversionsService,
60
69
  ZaloFlowsService: () => ZaloFlowsService,
70
+ ZaloFlowsValidator: () => ZaloFlowsValidator,
61
71
  ZaloFormsService: () => ZaloFormsService,
72
+ ZaloFormsValidator: () => ZaloFormsValidator,
62
73
  ZaloInstantPageBlockType: () => ZaloInstantPageBlockType,
63
74
  ZaloInstantPagesService: () => ZaloInstantPagesService,
64
75
  ZaloInstantPagesValidator: () => ZaloInstantPagesValidator,
@@ -75,9 +86,24 @@ __export(index_exports, {
75
86
  defaultSharedMemorySessionStore: () => defaultSharedMemorySessionStore,
76
87
  deriveAccountKeyFromZpsid: () => deriveAccountKeyFromZpsid,
77
88
  parseZaloCookieInput: () => parseZaloCookieInput,
89
+ validateChangeCampaignStatusParams: () => validateChangeCampaignStatusParams,
78
90
  validateCloneInstantPageRequest: () => validateCloneInstantPageRequest,
91
+ validateCreateCampaignPayload: () => validateCreateCampaignPayload,
92
+ validateCreateFlowRequest: () => validateCreateFlowRequest,
93
+ validateCreateFormEventAudienceRequest: () => validateCreateFormEventAudienceRequest,
94
+ validateCreateFormRequest: () => validateCreateFormRequest,
95
+ validateCreateLookalikeAudienceRequest: () => validateCreateLookalikeAudienceRequest,
96
+ validateCreateMessageOaEventAudienceRequest: () => validateCreateMessageOaEventAudienceRequest,
97
+ validateCreateMessagePersonalEventAudienceRequest: () => validateCreateMessagePersonalEventAudienceRequest,
98
+ validateCreatePhoneAudienceRequest: () => validateCreatePhoneAudienceRequest,
99
+ validateCreateSavedAudienceRequest: () => validateCreateSavedAudienceRequest,
100
+ validateDuplicateAdParams: () => validateDuplicateAdParams,
101
+ validateEstimateAudienceRequest: () => validateEstimateAudienceRequest,
79
102
  validateGetInstantPageDetailRequest: () => validateGetInstantPageDetailRequest,
80
103
  validateGetInstantPageSharedUserRequest: () => validateGetInstantPageSharedUserRequest,
104
+ validateListFlowsByOfficialAccountRequest: () => validateListFlowsByOfficialAccountRequest,
105
+ validateListFormLeadsRequest: () => validateListFormLeadsRequest,
106
+ validateListFormsByOfficialAccountRequest: () => validateListFormsByOfficialAccountRequest,
81
107
  validateListInstantPageEditHistoryRequest: () => validateListInstantPageEditHistoryRequest,
82
108
  validateListInstantPageFormRecordsRequest: () => validateListInstantPageFormRecordsRequest,
83
109
  validateListInstantPageLeadsRequest: () => validateListInstantPageLeadsRequest,
@@ -85,7 +111,10 @@ __export(index_exports, {
85
111
  validateListInstantPageUsersRequest: () => validateListInstantPageUsersRequest,
86
112
  validateListMiniPageTemplatesRequest: () => validateListMiniPageTemplatesRequest,
87
113
  validateListOfficialAccountsRequest: () => validateListOfficialAccountsRequest,
114
+ validateRenameCampaignParams: () => validateRenameCampaignParams,
88
115
  validateSearchInstantPagesRequest: () => validateSearchInstantPagesRequest,
116
+ validateUpdateAdPayload: () => validateUpdateAdPayload,
117
+ validateUpdateFlowRequest: () => validateUpdateFlowRequest,
89
118
  validateUpdateInstantPageRequest: () => validateUpdateInstantPageRequest,
90
119
  validateUpsertInstantPageFormRequest: () => validateUpsertInstantPageFormRequest
91
120
  });
@@ -711,7 +740,10 @@ var ZaloAuthManager = class {
711
740
  let adsProfile;
712
741
  let formProfile;
713
742
  if (domain === "ads.zalo.me") {
714
- await this.followOAuthRedirects("https://ads.zalo.me/api/login", cookies, true);
743
+ const explicitPlaySession = this.extraCookies?.PLAY_SESSION || cookies["PLAY_SESSION"];
744
+ if (!explicitPlaySession) {
745
+ await this.followOAuthRedirects("https://ads.zalo.me/api/login", cookies, true);
746
+ }
715
747
  const whoamiRes = await this.fetchImpl("https://ads.zalo.me/api/whoami", {
716
748
  method: "GET",
717
749
  headers: {
@@ -721,12 +753,17 @@ var ZaloAuthManager = class {
721
753
  }
722
754
  });
723
755
  this.mergeSetCookies(whoamiRes, cookies);
756
+ if (explicitPlaySession) {
757
+ cookies["PLAY_SESSION"] = explicitPlaySession;
758
+ }
724
759
  const whoamiJson = await whoamiRes.json().catch(() => null);
725
760
  if (whoamiJson?.data) {
726
761
  adsProfile = whoamiJson.data;
727
762
  if (adsProfile.id) {
728
763
  cookies["ads_user_id"] = String(adsProfile.id);
729
764
  }
765
+ } else if (this.extraCookies?.ads_user_id) {
766
+ cookies["ads_user_id"] = this.extraCookies.ads_user_id;
730
767
  }
731
768
  } else if (domain === "page.ads.zalo.me") {
732
769
  await this.followOAuthRedirects("https://page.ads.zalo.me/api/login", cookies, false);
@@ -1131,6 +1168,469 @@ async function resolveCookies(auth, context) {
1131
1168
  return { ...auth?.cookies ?? {}, ...await auth?.getCookies?.(context) ?? {} };
1132
1169
  }
1133
1170
 
1171
+ // src/dtos/ads.dto.ts
1172
+ var ZaloAdsFlowChildMessageDto = class {
1173
+ /** Mẫu Zalo đã xác minh dùng 8 cho tin nhắn văn bản trong nhánh. */
1174
+ type;
1175
+ /** Nội dung phản hồi trong nhánh. */
1176
+ text;
1177
+ };
1178
+ var ZaloAdsFlowButtonDto = class {
1179
+ /** 3 = Gửi tin nhắn vào nhánh hội thoại; 10 = Mở website; 12 = Thực hiện cuộc gọi. */
1180
+ type;
1181
+ /** Nhãn nút hiển thị cho người dùng. */
1182
+ text;
1183
+ /** URL website; bắt buộc với type 10. */
1184
+ url;
1185
+ /** Cờ của nút website; dùng true với type 10. */
1186
+ editable;
1187
+ /** Số hotline, bắt buộc khi type là 12. */
1188
+ phone;
1189
+ /** Nhánh tin nhắn, bắt buộc khi type là 3. Với type 10 hoặc 12, để null hoặc bỏ qua. */
1190
+ messages;
1191
+ };
1192
+ var ZaloAdsFlowMessageDto = class {
1193
+ /** 1 = Tin nhắn văn bản; 2 = Tin nhắn kèm hình ảnh. */
1194
+ type;
1195
+ /** Nội dung tin nhắn, tối đa 1961 ký tự. Hỗ trợ biến: {{user_name}}, {{page_name}}, {{user_gender}}, {{user_id}}, {{page_id}}, {{date}}, {{datetime}}. */
1196
+ text;
1197
+ /** URL media hoặc null với tin nhắn văn bản thuần. Bắt buộc và không được null khi type = 2. */
1198
+ url;
1199
+ /** Các nút đi kèm tin nhắn. */
1200
+ buttons;
1201
+ };
1202
+ var ZaloAdsCreateFlowRequest = class {
1203
+ /** ID Official Account sở hữu kịch bản. */
1204
+ oaId;
1205
+ /** Luôn null khi tạo kịch bản mới. */
1206
+ id;
1207
+ /** Tên kịch bản, tối đa 33 ký tự theo giao diện Zalo Ads. */
1208
+ name;
1209
+ /** Các tin nhắn được gửi theo thứ tự trong kịch bản. */
1210
+ messages;
1211
+ };
1212
+ var ZaloAdsCreateFlowResponse = class {
1213
+ /** 0 khi tạo thành công; 1 khi lỗi (ví dụ: đã tới hạn mức 20 kịch bản). */
1214
+ code;
1215
+ /** Thông báo lỗi từ Zalo Ads khi code khác 0. */
1216
+ msg;
1217
+ /** ID kịch bản mới, truyền vào data.ZaloFlowId khi cập nhật quảng cáo Tin nhắn. */
1218
+ data;
1219
+ };
1220
+ var ZaloAdsActionType = {
1221
+ DAT_NGAY: 1,
1222
+ MUA_NGAY: 2,
1223
+ THU_NGAY: 3,
1224
+ TAI_NGAY: 4,
1225
+ XEM_THEM: 5,
1226
+ QUAN_TAM_OA: 6,
1227
+ NGHE_NGAY: 7,
1228
+ CHOI_NGAY: 8,
1229
+ DANG_KY: 9,
1230
+ GOI_DIEN: 10
1231
+ };
1232
+ var ZaloAdsAgeRangeId = {
1233
+ UNDER_18: 10282,
1234
+ FROM_18_TO_24: 10283,
1235
+ FROM_25_TO_34: 10284,
1236
+ FROM_35_TO_44: 10285,
1237
+ FROM_45_TO_54: 10286,
1238
+ FROM_55_TO_64: 10287,
1239
+ OVER_64: 10288
1240
+ };
1241
+ var ZaloAdsOsId = {
1242
+ ANDROID: 0,
1243
+ IOS: 1,
1244
+ PC: 3
1245
+ };
1246
+ var ZaloAdsDeliveryType = {
1247
+ STANDARD: 1,
1248
+ ACCELERATED: 2
1249
+ };
1250
+ var ZaloAdsUpdateVideoAdRequest = class {
1251
+ data;
1252
+ est;
1253
+ isBoostAd;
1254
+ stt;
1255
+ };
1256
+ var ZaloAdsUpdateVideoAdResponse = class {
1257
+ code;
1258
+ msg;
1259
+ data;
1260
+ };
1261
+ var ZaloAdsCreatePostCampaignRequest = class {
1262
+ /** Cấu hình chiến dịch Bài viết (object hoặc chuỗi JSON). */
1263
+ data;
1264
+ };
1265
+ var ZaloAdsCreatePostCampaignResponse = class {
1266
+ code;
1267
+ /** Chuỗi ID quảng cáo mới trong response Zalo Ads. */
1268
+ msg;
1269
+ data;
1270
+ };
1271
+ var ZaloAdsMessageAdUpdateDataDto = class {
1272
+ AdId;
1273
+ CampaignId;
1274
+ MemberId;
1275
+ /** Phiên bản lạc quan lấy từ bản quảng cáo hiện tại. */
1276
+ RowVersion;
1277
+ AdName;
1278
+ /** 20 (hoặc 19) là quảng cáo Tin nhắn. */
1279
+ Type;
1280
+ Settings;
1281
+ Status;
1282
+ StartDate;
1283
+ EndDate;
1284
+ /** ID kịch bản, lấy từ createFlow hoặc listFlowsByOfficialAccount. */
1285
+ ZaloFlowId;
1286
+ ZaloPageId;
1287
+ ZaloFormId;
1288
+ ConversionId;
1289
+ Report;
1290
+ };
1291
+ var ZaloAdsUpdateMessageAdRequest = class {
1292
+ /** Payload quảng cáo đầy đủ (object hoặc chuỗi JSON); service tự tuần tự hóa thành field form data. */
1293
+ data;
1294
+ /** Tham số UI phụ trợ; capture Zalo Ads có giá trị literal "undefined". */
1295
+ est;
1296
+ /** 0 là quảng cáo thông thường, 1 là boost ad. */
1297
+ isBoostAd;
1298
+ /** Trạng thái thao tác của giao diện; mẫu đã ghi nhận 0. */
1299
+ stt;
1300
+ };
1301
+ var ZaloAdsUpdateMessageAdResponse = class {
1302
+ msg;
1303
+ code;
1304
+ data;
1305
+ };
1306
+
1307
+ // src/validators/campaigns.validator.ts
1308
+ var VALID_CAMPAIGN_TYPES = {
1309
+ WEBSITE: 6,
1310
+ FORM: 17,
1311
+ MESSAGE: 18,
1312
+ OA: 3,
1313
+ VIDEO: 14,
1314
+ COMMERCE: 22,
1315
+ ARTICLE: 4,
1316
+ DISPLAY: 20
1317
+ };
1318
+ var VALID_AD_TYPES = {
1319
+ WEBSITE: 5,
1320
+ FORM: 18,
1321
+ MESSAGE: 30,
1322
+ OA: 2,
1323
+ VIDEO: 11,
1324
+ COMMERCE: 28,
1325
+ // Server trả về 28 (không phải 23)
1326
+ ARTICLE: 3,
1327
+ DISPLAY: 21
1328
+ };
1329
+ var ALLOWED_CTAS_PER_AD_TYPE = {
1330
+ // Website (Type 5): 9 CTAs
1331
+ [VALID_AD_TYPES.WEBSITE]: [
1332
+ ZaloAdsActionType.DAT_NGAY,
1333
+ ZaloAdsActionType.MUA_NGAY,
1334
+ ZaloAdsActionType.THU_NGAY,
1335
+ ZaloAdsActionType.TAI_NGAY,
1336
+ ZaloAdsActionType.XEM_THEM,
1337
+ ZaloAdsActionType.NGHE_NGAY,
1338
+ ZaloAdsActionType.CHOI_NGAY,
1339
+ ZaloAdsActionType.DANG_KY,
1340
+ ZaloAdsActionType.GOI_DIEN
1341
+ ],
1342
+ // Video (Type 11): 8 CTAs
1343
+ [VALID_AD_TYPES.VIDEO]: [
1344
+ ZaloAdsActionType.DAT_NGAY,
1345
+ ZaloAdsActionType.MUA_NGAY,
1346
+ ZaloAdsActionType.THU_NGAY,
1347
+ ZaloAdsActionType.TAI_NGAY,
1348
+ ZaloAdsActionType.XEM_THEM,
1349
+ ZaloAdsActionType.NGHE_NGAY,
1350
+ ZaloAdsActionType.CHOI_NGAY,
1351
+ ZaloAdsActionType.DANG_KY
1352
+ ],
1353
+ // Article (Type 3): 7 CTAs
1354
+ [VALID_AD_TYPES.ARTICLE]: [
1355
+ ZaloAdsActionType.DAT_NGAY,
1356
+ ZaloAdsActionType.MUA_NGAY,
1357
+ ZaloAdsActionType.THU_NGAY,
1358
+ ZaloAdsActionType.TAI_NGAY,
1359
+ ZaloAdsActionType.XEM_THEM,
1360
+ ZaloAdsActionType.CHOI_NGAY,
1361
+ ZaloAdsActionType.DANG_KY
1362
+ ],
1363
+ // Form (Type 18): 5 CTAs
1364
+ [VALID_AD_TYPES.FORM]: [
1365
+ ZaloAdsActionType.DAT_NGAY,
1366
+ ZaloAdsActionType.MUA_NGAY,
1367
+ ZaloAdsActionType.THU_NGAY,
1368
+ ZaloAdsActionType.XEM_THEM,
1369
+ ZaloAdsActionType.DANG_KY
1370
+ ],
1371
+ // Commerce (Type 28): 3 CTAs
1372
+ [VALID_AD_TYPES.COMMERCE]: [
1373
+ ZaloAdsActionType.DAT_NGAY,
1374
+ ZaloAdsActionType.MUA_NGAY,
1375
+ ZaloAdsActionType.XEM_THEM
1376
+ ],
1377
+ // OA (Type 2): Cố định Quan tâm OA (6)
1378
+ [VALID_AD_TYPES.OA]: [ZaloAdsActionType.QUAN_TAM_OA]
1379
+ };
1380
+ function validateCreateCampaignPayload(payload, options = {}) {
1381
+ const errors = [];
1382
+ const warnings = [];
1383
+ if (!payload.name || typeof payload.name !== "string" || !payload.name.trim()) {
1384
+ errors.push("name l\xE0 b\u1EAFt bu\u1ED9c v\xE0 kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
1385
+ } else if (payload.name.length > 255) {
1386
+ errors.push("name kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 255 k\xFD t\u1EF1.");
1387
+ }
1388
+ const validTypes = Object.values(VALID_CAMPAIGN_TYPES);
1389
+ if (payload.campaignType === void 0 || payload.campaignType === null) {
1390
+ errors.push("campaignType l\xE0 b\u1EAFt bu\u1ED9c.");
1391
+ } else if (!validTypes.includes(payload.campaignType)) {
1392
+ errors.push(
1393
+ `campaignType: ${payload.campaignType} kh\xF4ng h\u1EE3p l\u1EC7. C\xE1c lo\u1EA1i h\u1ED7 tr\u1EE3: 6 (Website), 17 (Form), 18 (Message), 3 (OA), 14 (Video), 22 (Commerce), 4 (Article), 20 (Display).`
1394
+ );
1395
+ }
1396
+ if (payload.campaignType !== VALID_CAMPAIGN_TYPES.DISPLAY) {
1397
+ if (!payload.pageId || payload.pageId <= 0) {
1398
+ errors.push("pageId c\u1EE7a Official Account l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi lo\u1EA1i chi\u1EBFn d\u1ECBch n\xE0y (ph\u1EA3i > 0).");
1399
+ }
1400
+ } else {
1401
+ if (payload.pageId !== -1 && payload.pageId !== 0 && !payload.pageId) {
1402
+ warnings.push("Qu\u1EA3ng c\xE1o Display th\u01B0\u1EDDng s\u1EED d\u1EE5ng pageId = -1.");
1403
+ }
1404
+ }
1405
+ switch (payload.campaignType) {
1406
+ case VALID_CAMPAIGN_TYPES.WEBSITE:
1407
+ if (!payload.targetUrl || typeof payload.targetUrl !== "string" || !payload.targetUrl.trim()) {
1408
+ errors.push("targetUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Website.");
1409
+ } else if (!/^https?:\/\/.+/i.test(payload.targetUrl)) {
1410
+ errors.push("targetUrl ph\u1EA3i l\xE0 m\u1ED9t \u0111\u01B0\u1EDDng link h\u1EE3p l\u1EC7 b\u1EAFt \u0111\u1EA7u b\u1EB1ng http:// ho\u1EB7c https://.");
1411
+ }
1412
+ break;
1413
+ case VALID_CAMPAIGN_TYPES.ARTICLE:
1414
+ if (!payload.articleId || payload.articleId <= 0) {
1415
+ errors.push("articleId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o B\xE0i Vi\u1EBFt (ph\u1EA3i > 0, l\u1EA5y t\u1EEB getOwnedArticles).");
1416
+ }
1417
+ break;
1418
+ case VALID_CAMPAIGN_TYPES.COMMERCE:
1419
+ if (payload.productId === void 0 || payload.productId === null) {
1420
+ warnings.push("Qu\u1EA3ng c\xE1o Commerce n\xEAn ch\u1EC9 \u0111\u1ECBnh productId (ho\u1EB7c -1/0 khi d\xF9ng Instant Page s\u1EA3n ph\u1EA9m).");
1421
+ }
1422
+ break;
1423
+ case VALID_CAMPAIGN_TYPES.FORM:
1424
+ case VALID_CAMPAIGN_TYPES.MESSAGE:
1425
+ break;
1426
+ }
1427
+ if (payload.budgetType !== void 0 && payload.budgetlimit !== void 0) {
1428
+ if (payload.budgetType === 2) {
1429
+ if (payload.budgetlimit > 0 && payload.budgetlimit < 6e5) {
1430
+ errors.push("Ng\xE2n s\xE1ch cho To\xE0n l\u1ECBch ch\u1EA1y t\u1ED1i thi\u1EC3u l\xE0 600,000 VN\u0110.");
1431
+ }
1432
+ } else if (payload.budgetType === 1) {
1433
+ if (payload.budgetlimit > 0 && payload.budgetlimit < 50) {
1434
+ warnings.push("S\u1ED1 l\u01B0\u1EE3ng t\u01B0\u01A1ng t\xE1c m\u1ED7i ng\xE0y t\u1ED1i thi\u1EC3u \u0111\u01B0\u1EE3c khuy\u1EBFn ngh\u1ECB t\u1EEB 50 l\u01B0\u1EE3t.");
1435
+ }
1436
+ }
1437
+ }
1438
+ if (payload.campaignId && payload.campaignId > 0) {
1439
+ if (payload.adId !== 0) {
1440
+ warnings.push("Khi th\xEAm Ad m\u1EDBi v\xE0o chi\u1EBFn d\u1ECBch hi\u1EC7n c\xF3 (Multi-Ad), adId n\xEAn \u0111\u1EC3 b\u1EB1ng 0.");
1441
+ }
1442
+ }
1443
+ return {
1444
+ isValid: errors.length === 0,
1445
+ errors,
1446
+ warnings
1447
+ };
1448
+ }
1449
+ function validateUpdateAdPayload(payload, options = {}) {
1450
+ const errors = [];
1451
+ const warnings = [];
1452
+ if (!payload.AdId || payload.AdId <= 0) {
1453
+ errors.push("AdId l\xE0 b\u1EAFt bu\u1ED9c (ph\u1EA3i > 0).");
1454
+ }
1455
+ if (!payload.CampaignId || payload.CampaignId <= 0) {
1456
+ errors.push("CampaignId l\xE0 b\u1EAFt bu\u1ED9c (ph\u1EA3i > 0).");
1457
+ }
1458
+ if (!payload.AdName || !payload.AdName.trim()) {
1459
+ errors.push("AdName l\xE0 b\u1EAFt bu\u1ED9c v\xE0 kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
1460
+ } else if (payload.AdName.length > 255) {
1461
+ errors.push(`AdName qu\xE1 d\xE0i (${payload.AdName.length}/255 k\xFD t\u1EF1).`);
1462
+ }
1463
+ const adInfo = payload.Settings?.AdInfo;
1464
+ if (!adInfo) {
1465
+ errors.push("Settings.AdInfo l\xE0 b\u1EAFt bu\u1ED9c.");
1466
+ } else {
1467
+ if (!adInfo.Caption || !adInfo.Caption.trim()) {
1468
+ errors.push("Settings.AdInfo.Caption l\xE0 b\u1EAFt bu\u1ED9c.");
1469
+ } else {
1470
+ const captionLen = adInfo.Caption.trim().length;
1471
+ if (captionLen < 35) {
1472
+ errors.push(`Settings.AdInfo.Caption qu\xE1 ng\u1EAFn (${captionLen}/35 k\xFD t\u1EF1 t\u1ED1i thi\u1EC3u).`);
1473
+ } else if (captionLen > 90) {
1474
+ errors.push(`Settings.AdInfo.Caption qu\xE1 d\xE0i (${captionLen}/90 k\xFD t\u1EF1 t\u1ED1i \u0111a).`);
1475
+ }
1476
+ }
1477
+ if (adInfo.MoreInfo && adInfo.MoreInfo.trim()) {
1478
+ const moreInfoLen = adInfo.MoreInfo.trim().length;
1479
+ if (moreInfoLen < 90) {
1480
+ warnings.push(`Ch\xFA th\xEDch m\u1EDF r\u1ED9ng n\xEAn \u0111\u1EA1t t\u1ED1i thi\u1EC3u 90 k\xFD t\u1EF1 (hi\u1EC7n t\u1EA1i: ${moreInfoLen}).`);
1481
+ } else if (moreInfoLen > 2e3) {
1482
+ errors.push(`Ch\xFA th\xEDch m\u1EDF r\u1ED9ng v\u01B0\u1EE3t qu\xE1 gi\u1EDBi h\u1EA1n t\u1ED1i \u0111a 2000 k\xFD t\u1EF1 (hi\u1EC7n t\u1EA1i: ${moreInfoLen}).`);
1483
+ }
1484
+ }
1485
+ if (adInfo.Action !== void 0 && payload.Type) {
1486
+ const allowedCtas = ALLOWED_CTAS_PER_AD_TYPE[payload.Type];
1487
+ if (allowedCtas && !allowedCtas.includes(adInfo.Action)) {
1488
+ warnings.push(
1489
+ `M\xE3 h\xE0nh \u0111\u1ED9ng Action: ${adInfo.Action} c\xF3 th\u1EC3 kh\xF4ng n\u1EB1m trong danh m\u1EE5c n\xFAt CTA h\u1ED7 tr\u1EE3 cho Ad Type ${payload.Type}.`
1490
+ );
1491
+ }
1492
+ }
1493
+ }
1494
+ const price = payload.Settings?.Price;
1495
+ if (!price) {
1496
+ errors.push("Settings.Price l\xE0 b\u1EAFt bu\u1ED9c.");
1497
+ } else {
1498
+ if (payload.Type === VALID_AD_TYPES.WEBSITE) {
1499
+ if (price.Type !== 1) {
1500
+ errors.push(
1501
+ "\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Website (Type 5), Price.Type b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 1 (CPC). N\u1EBFu truy\u1EC1n 2 s\u1EBD b\u1ECB m\xE1y ch\u1EE7 l\u1ED7i."
1502
+ );
1503
+ }
1504
+ if (price.LimitType === 1) {
1505
+ errors.push(
1506
+ "Qu\u1EA3ng c\xE1o Website kh\xF4ng h\u1ED7 tr\u1EE3 LimitType: 1 (t\u1ED5ng ng\xE2n s\xE1ch). B\u1EAFt bu\u1ED9c ph\u1EA3i d\xF9ng LimitType: 0 (ng\xE2n s\xE1ch ng\xE0y)."
1507
+ );
1508
+ }
1509
+ } else if (payload.Type === VALID_AD_TYPES.COMMERCE || payload.Type === VALID_AD_TYPES.OA || payload.Type === VALID_AD_TYPES.ARTICLE || payload.Type === VALID_AD_TYPES.VIDEO || payload.Type === VALID_AD_TYPES.FORM || payload.Type === VALID_AD_TYPES.MESSAGE) {
1510
+ if (price.Type !== 2) {
1511
+ errors.push(
1512
+ `\u0110\u1ED1i v\u1EDBi Ad Type ${payload.Type}, Price.Type b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 2. N\u1EBFu truy\u1EC1n 1, Zalo Ads s\u1EBD b\xE1o l\u1ED7i code 14 (\u0110\u1EB7t gi\xE1 theo L\u01B0\u1EE3t hi\u1EC3n th\u1ECB kh\xF4ng h\u1ED7 tr\u1EE3).`
1513
+ );
1514
+ }
1515
+ }
1516
+ if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 50) {
1517
+ warnings.push("S\u1ED1 l\u01B0\u1EE3ng l\u01B0\u1EE3t t\u01B0\u01A1ng t\xE1c \u0111\u1EB7t m\u1ED7i ng\xE0y t\u1ED1i thi\u1EC3u l\xE0 50 l\u01B0\u1EE3t.");
1518
+ }
1519
+ }
1520
+ const targeting = payload.Settings?.Targeting;
1521
+ if (targeting) {
1522
+ if (targeting.AgeRanges && targeting.AgeRanges.length > 0) {
1523
+ const validAges = Object.values(ZaloAdsAgeRangeId);
1524
+ const invalidAges = targeting.AgeRanges.filter((a) => !validAges.includes(a));
1525
+ if (invalidAges.length > 0) {
1526
+ errors.push(`M\xE3 kho\u1EA3ng tu\u1ED5i kh\xF4ng h\u1EE3p l\u1EC7: ${invalidAges.join(", ")}. H\u1EE3p l\u1EC7: ${validAges.join(", ")}.`);
1527
+ }
1528
+ }
1529
+ if (targeting.OsTypes && targeting.OsTypes.length > 0) {
1530
+ const validOs = Object.values(ZaloAdsOsId);
1531
+ const invalidOs = targeting.OsTypes.filter((os) => !validOs.includes(os));
1532
+ if (invalidOs.length > 0) {
1533
+ errors.push(`M\xE3 h\u1EC7 \u0111i\u1EC1u h\xE0nh kh\xF4ng h\u1EE3p l\u1EC7: ${invalidOs.join(", ")}. H\u1EE3p l\u1EC7: 0 (Android), 1 (iOS), 3 (PC).`);
1534
+ }
1535
+ }
1536
+ const deliveryType = payload.Settings?.DeliveryType;
1537
+ if (deliveryType !== void 0 && deliveryType !== 1 && deliveryType !== 2) {
1538
+ warnings.push("DeliveryType n\xEAn l\xE0 1 (Ti\xEAu chu\u1EA9n) ho\u1EB7c 2 (T\u0103ng t\u1ED1c).");
1539
+ }
1540
+ }
1541
+ if (payload.Type === VALID_AD_TYPES.FORM) {
1542
+ if (!payload.ZaloFormId || !payload.ZaloFormId.trim()) {
1543
+ errors.push("ZaloFormId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Form (Ad Type 18).");
1544
+ }
1545
+ } else if (payload.Type === VALID_AD_TYPES.MESSAGE) {
1546
+ if (!payload.Settings?.Image?.LogoUrl) {
1547
+ errors.push("Settings.Image.LogoUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn (Ad Type 30).");
1548
+ }
1549
+ if (!payload.ZaloFlowId && !payload.MiniPageId) {
1550
+ warnings.push("Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn n\xEAn g\u1EAFn ZaloFlowId ho\u1EB7c MiniPageId (Template 4 k\u1ECBch b\u1EA3n tin nh\u1EAFn).");
1551
+ }
1552
+ } else if (payload.Type === VALID_AD_TYPES.COMMERCE) {
1553
+ if (!payload.MiniPageId || payload.MiniPageId <= 0) {
1554
+ errors.push("MiniPageId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Commerce (Ad Type 28, Template 1/2/3).");
1555
+ }
1556
+ } else if (payload.Type === VALID_AD_TYPES.VIDEO) {
1557
+ if (!payload.ZaloVideoId && !payload.Settings?.Image?.VideoUrl) {
1558
+ errors.push("ZaloVideoId ho\u1EB7c Settings.Image.VideoUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Video (Ad Type 11).");
1559
+ }
1560
+ if (payload.Settings?.Image?.VideoUrl && !payload.Settings.Image.VideoUrl.includes("zascdn.me")) {
1561
+ warnings.push("VideoUrl n\xEAn l\xE0 \u0111\u01B0\u1EDDng d\u1EABn CDN ch\xEDnh th\u1EE9c c\u1EE7a Zalo Ads (*.zascdn.me).");
1562
+ }
1563
+ } else if (payload.Type === VALID_AD_TYPES.ARTICLE) {
1564
+ if (!payload.ZaloFeedId && !payload.articleId) {
1565
+ errors.push("ZaloFeedId ho\u1EB7c articleId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o B\xE0i Vi\u1EBFt (Ad Type 3).");
1566
+ }
1567
+ }
1568
+ return {
1569
+ isValid: errors.length === 0,
1570
+ errors,
1571
+ warnings
1572
+ };
1573
+ }
1574
+ function validateRenameCampaignParams(params) {
1575
+ const errors = [];
1576
+ const warnings = [];
1577
+ const id = params.campid || params.campaignId;
1578
+ const name = params.newname || params.newName || params.name;
1579
+ if (!id || id <= 0) {
1580
+ errors.push("ID chi\u1EBFn d\u1ECBch (campid/campaignId) l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i > 0.");
1581
+ }
1582
+ if (!name || !name.trim()) {
1583
+ errors.push("T\xEAn m\u1EDBi c\u1EE7a chi\u1EBFn d\u1ECBch (newname/name) l\xE0 b\u1EAFt bu\u1ED9c v\xE0 kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
1584
+ } else if (name.length > 255) {
1585
+ errors.push(`T\xEAn chi\u1EBFn d\u1ECBch qu\xE1 d\xE0i (${name.length}/255 k\xFD t\u1EF1).`);
1586
+ }
1587
+ return {
1588
+ isValid: errors.length === 0,
1589
+ errors,
1590
+ warnings
1591
+ };
1592
+ }
1593
+ function validateChangeCampaignStatusParams(params) {
1594
+ const errors = [];
1595
+ const warnings = [];
1596
+ if (!params.campaignId || params.campaignId <= 0) {
1597
+ errors.push("campaignId l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i > 0.");
1598
+ }
1599
+ if (![1, 2, -2].includes(params.status)) {
1600
+ errors.push(`status: ${params.status} kh\xF4ng h\u1EE3p l\u1EC7. C\xE1c tr\u1EA1ng th\xE1i h\u1EE3p l\u1EC7: 1 (B\u1EADt), 2 (T\u1EA1m d\u1EEBng), -2 (X\xF3a).`);
1601
+ }
1602
+ if (params.status === 2 && params.isDraft) {
1603
+ warnings.push(
1604
+ "Chi\u1EBFn d\u1ECBch nh\xE1p ch\u01B0a c\xF3 qu\u1EA3ng c\xE1o ho\u1EA1t \u0111\u1ED9ng khi g\u1ECDi status: 2 (T\u1EA1m d\u1EEBng) s\u1EBD b\u1ECB m\xE1y ch\u1EE7 n\xE9m l\u1ED7i HTTP 500 Internal Server Error. \u0110\u1EC3 d\u1ECDn d\u1EB9p h\xE3y d\xF9ng status: -2 (X\xF3a)."
1605
+ );
1606
+ }
1607
+ return {
1608
+ isValid: errors.length === 0,
1609
+ errors,
1610
+ warnings
1611
+ };
1612
+ }
1613
+ function validateDuplicateAdParams(params) {
1614
+ const errors = [];
1615
+ const warnings = [];
1616
+ const id = params.adid || params.adId;
1617
+ if (!id || id <= 0) {
1618
+ errors.push("ID m\u1EABu qu\u1EA3ng c\xE1o g\u1ED1c c\u1EA7n nh\xE2n b\u1EA3n (adid/adId) l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i > 0.");
1619
+ }
1620
+ return {
1621
+ isValid: errors.length === 0,
1622
+ errors,
1623
+ warnings
1624
+ };
1625
+ }
1626
+ var ZaloCampaignsValidator = {
1627
+ createCampaign: validateCreateCampaignPayload,
1628
+ updateAd: validateUpdateAdPayload,
1629
+ renameCampaign: validateRenameCampaignParams,
1630
+ changeStatus: validateChangeCampaignStatusParams,
1631
+ duplicateAd: validateDuplicateAdParams
1632
+ };
1633
+
1134
1634
  // src/services/campaigns.service.ts
1135
1635
  var OP_ZaloAdsUpdateVideoAd = {
1136
1636
  operationId: "ZaloAds_updateVideoAd",
@@ -1251,7 +1751,9 @@ var OP_ZaloAdsGetAdById = {
1251
1751
  "binaryFields": [],
1252
1752
  "pathFields": [],
1253
1753
  "queryFields": [
1254
- "adId"
1754
+ "adId",
1755
+ "v",
1756
+ "newWard"
1255
1757
  ],
1256
1758
  "headerFields": [],
1257
1759
  "cookieFields": [],
@@ -1323,7 +1825,9 @@ var OP_ZaloAdsGetZaapiGetadsfromcampaignid = {
1323
1825
  "pathFields": [],
1324
1826
  "queryFields": [
1325
1827
  "campaignId",
1326
- "campId"
1828
+ "campId",
1829
+ "dataType",
1830
+ "v"
1327
1831
  ],
1328
1832
  "headerFields": [],
1329
1833
  "cookieFields": [],
@@ -1624,10 +2128,48 @@ var OP_ZaloAdsDeleteCampaign = {
1624
2128
  "status"
1625
2129
  ]
1626
2130
  };
2131
+ var OP_ZaloAdsDuplicateAd = {
2132
+ operationId: "zalo_ads_duplicate_ad",
2133
+ method: "POST",
2134
+ endpoint: "/zaapi/DuplicateAd",
2135
+ baseUrl: "https://ads.zalo.me",
2136
+ binaryFields: [],
2137
+ pathFields: [],
2138
+ queryFields: [],
2139
+ headerFields: [],
2140
+ cookieFields: [],
2141
+ bodyFields: ["adid"]
2142
+ };
2143
+ var OP_ZaloAdsCreateSpellCheckV3Job = {
2144
+ operationId: "zalo_ads_create_spell_check_v3_job",
2145
+ method: "POST",
2146
+ endpoint: "/api/spell-check/v3",
2147
+ baseUrl: "https://ads.zalo.me",
2148
+ binaryFields: [],
2149
+ pathFields: [],
2150
+ queryFields: [],
2151
+ headerFields: [],
2152
+ cookieFields: [],
2153
+ bodyFields: ["title", "caption"]
2154
+ };
2155
+ var OP_ZaloAdsGetSpellCheckV3Job = {
2156
+ operationId: "zalo_ads_get_spell_check_v3_job",
2157
+ method: "GET",
2158
+ endpoint: "/api/spell-check/v3/{jobId}",
2159
+ baseUrl: "https://ads.zalo.me",
2160
+ binaryFields: [],
2161
+ pathFields: ["jobId"],
2162
+ queryFields: [],
2163
+ headerFields: [],
2164
+ cookieFields: [],
2165
+ bodyFields: []
2166
+ };
1627
2167
  var ZaloCampaignsService = class {
1628
2168
  constructor(client) {
1629
2169
  this.client = client;
1630
2170
  }
2171
+ validator = ZaloCampaignsValidator;
2172
+ static validator = ZaloCampaignsValidator;
1631
2173
  updateVideoAd(request, options) {
1632
2174
  return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateVideoAd, this.client.toTransportInput(OP_ZaloAdsUpdateVideoAd, request), options);
1633
2175
  }
@@ -1684,10 +2226,19 @@ var ZaloCampaignsService = class {
1684
2226
  return this.createPostCampaign(request, options);
1685
2227
  }
1686
2228
  getAdById(request = {}, options) {
1687
- return this.client.requestWithoutBody(OP_ZaloAdsGetAdById, this.client.toTransportInput(OP_ZaloAdsGetAdById, request), options);
2229
+ const normalized = {
2230
+ adId: request.adId,
2231
+ v: request.v ?? 2,
2232
+ newWard: request.newWard ?? true
2233
+ };
2234
+ return this.client.requestWithoutBody(OP_ZaloAdsGetAdById, this.client.toTransportInput(OP_ZaloAdsGetAdById, normalized), options);
1688
2235
  }
1689
2236
  getAdChangeLog(request, options) {
1690
- return this.client.requestWithoutBody(OP_ZaloAdsGetAdChangeLog, this.client.toTransportInput(OP_ZaloAdsGetAdChangeLog, request), options);
2237
+ const normalized = {
2238
+ adId: request.adId,
2239
+ type: request.type ?? 1
2240
+ };
2241
+ return this.client.requestWithoutBody(OP_ZaloAdsGetAdChangeLog, this.client.toTransportInput(OP_ZaloAdsGetAdChangeLog, normalized), options);
1691
2242
  }
1692
2243
  getApiPlaceGetalldistricts(request = {}, options) {
1693
2244
  return this.client.requestWithoutBody(OP_ZaloAdsGetApiPlaceGetalldistricts, this.client.toTransportInput(OP_ZaloAdsGetApiPlaceGetalldistricts, request), options);
@@ -1699,7 +2250,16 @@ var ZaloCampaignsService = class {
1699
2250
  return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiCheckcamphasmanyads, this.client.toTransportInput(OP_ZaloAdsGetZaapiCheckcamphasmanyads, request), options);
1700
2251
  }
1701
2252
  getZaapiGetadsfromcampaignid(request = {}, options) {
1702
- return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetadsfromcampaignid, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetadsfromcampaignid, request), options);
2253
+ const normalized = {
2254
+ campaignId: request.campaignId ?? request.campId,
2255
+ dataType: request.dataType ?? 1,
2256
+ v: request.v ?? 2
2257
+ };
2258
+ return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetadsfromcampaignid, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetadsfromcampaignid, normalized), options);
2259
+ }
2260
+ /** Alias lấy danh sách quảng cáo của chiến dịch kèm metadata extend và extra.appliedRuleInfo */
2261
+ getAdsFromCampaignId(request = {}, options) {
2262
+ return this.getZaapiGetadsfromcampaignid(request, options);
1703
2263
  }
1704
2264
  getZaapiGetallpages(request = {}, options) {
1705
2265
  return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetallpages, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetallpages, request), options);
@@ -1729,7 +2289,11 @@ var ZaloCampaignsService = class {
1729
2289
  return this.client.requestWithoutBody(OP_ZaloAdsPostZaapiDeletead, this.client.toTransportInput(OP_ZaloAdsPostZaapiDeletead, request), options);
1730
2290
  }
1731
2291
  renameCampaign(request, options) {
1732
- return this.client.requestFormUrlEncoded(OP_ZaloAdsRenameCampaign, this.client.toTransportInput(OP_ZaloAdsRenameCampaign, request), options);
2292
+ const normalized = {
2293
+ campid: request.campid ?? request.campaignId,
2294
+ newname: request.newname ?? request.campaignName ?? request.name
2295
+ };
2296
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsRenameCampaign, this.client.toTransportInput(OP_ZaloAdsRenameCampaign, normalized), options);
1733
2297
  }
1734
2298
  updateEcommerceAd(request, options) {
1735
2299
  return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateEcommerceAd, this.client.toTransportInput(OP_ZaloAdsUpdateEcommerceAd, request), options);
@@ -1773,6 +2337,62 @@ var ZaloCampaignsService = class {
1773
2337
  getSpellCheckV2(...args) {
1774
2338
  return this.getApiSpellCheckV2(...args);
1775
2339
  }
2340
+ /**
2341
+ * Khởi tạo tác vụ kiểm tra chính tả và vi phạm quy chuẩn quảng cáo AI V3 (POST /api/spell-check/v3).
2342
+ */
2343
+ createSpellCheckV3Job(request, options) {
2344
+ return this.client.requestJson(
2345
+ OP_ZaloAdsCreateSpellCheckV3Job,
2346
+ this.client.toTransportInput(OP_ZaloAdsCreateSpellCheckV3Job, request),
2347
+ options
2348
+ );
2349
+ }
2350
+ /**
2351
+ * Lấy kết quả kiểm tra chính tả AI V3 theo jobId (GET /api/spell-check/v3/{jobId}).
2352
+ */
2353
+ getSpellCheckV3Job(request, options) {
2354
+ return this.client.requestWithoutBody(
2355
+ OP_ZaloAdsGetSpellCheckV3Job,
2356
+ this.client.toTransportInput(OP_ZaloAdsGetSpellCheckV3Job, request),
2357
+ options
2358
+ );
2359
+ }
2360
+ /**
2361
+ * Helper kiểm tra chính tả AI V3 trọn gói: Gửi kiểm tra và tự động polling cho đến khi hoàn thành (hoặc timeout).
2362
+ * @param request Tiêu đề (title) và chú thích (caption) cần kiểm tra.
2363
+ * @param pollIntervalMs Chu kỳ polling kiểm tra trạng thái (mặc định: 600ms).
2364
+ * @param timeoutMs Thời gian chờ tối đa (mặc định: 15.000ms = 15 giây).
2365
+ */
2366
+ async checkSpellV3AndWait(request, pollIntervalMs = 600, timeoutMs = 15e3, options) {
2367
+ const jobRes = await this.createSpellCheckV3Job(request, options);
2368
+ const jobId = jobRes?.data?.jobId;
2369
+ if (!jobId) {
2370
+ throw new Error(`[SpellCheckV3] Kh\xF4ng nh\u1EADn \u0111\u01B0\u1EE3c jobId t\u1EEB Zalo Ads (code: ${jobRes?.code})`);
2371
+ }
2372
+ const startTime = Date.now();
2373
+ while (Date.now() - startTime < timeoutMs) {
2374
+ await new Promise((r) => setTimeout(r, pollIntervalMs));
2375
+ const res = await this.getSpellCheckV3Job({ jobId }, options);
2376
+ if (res?.data?.status === "COMPLETED") {
2377
+ return res;
2378
+ }
2379
+ }
2380
+ throw new Error(`[SpellCheckV3] Qu\xE1 th\u1EDDi gian ch\u1EDD (${timeoutMs}ms) cho t\xE1c v\u1EE5 ki\u1EC3m tra ch\xEDnh t\u1EA3 jobId: ${jobId}`);
2381
+ }
2382
+ /**
2383
+ * Nhân bản (sao chép / duplicate) một mẫu quảng cáo đã tồn tại trên Zalo Ads (POST /zaapi/DuplicateAd).
2384
+ * Giúp tạo nhanh một bản sao Ad mới trong cùng chiến dịch để thực hiện A/B testing.
2385
+ */
2386
+ duplicateAd(request, options) {
2387
+ const payload = {
2388
+ adid: request.adid ?? request.adId
2389
+ };
2390
+ return this.client.requestFormUrlEncoded(
2391
+ OP_ZaloAdsDuplicateAd,
2392
+ this.client.toTransportInput(OP_ZaloAdsDuplicateAd, payload),
2393
+ options
2394
+ );
2395
+ }
1776
2396
  };
1777
2397
 
1778
2398
  // src/services/account.service.ts
@@ -1927,6 +2547,365 @@ var ZaloAccountService = class {
1927
2547
  }
1928
2548
  };
1929
2549
 
2550
+ // src/validators/audiences.validator.ts
2551
+ function validateCreateSavedAudienceRequest(input) {
2552
+ const errors = [];
2553
+ if (!input || typeof input !== "object") {
2554
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
2555
+ }
2556
+ const raw = input;
2557
+ const name = typeof raw.name === "string" ? raw.name.trim() : "";
2558
+ if (!name) {
2559
+ errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' l\xE0 b\u1EAFt bu\u1ED9c.");
2560
+ } else if (name.length < 2 || name.length > 255) {
2561
+ errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
2562
+ }
2563
+ let targetingObj;
2564
+ if (typeof raw.targeting === "string") {
2565
+ try {
2566
+ targetingObj = JSON.parse(raw.targeting);
2567
+ } catch {
2568
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
2569
+ targetingObj = {};
2570
+ }
2571
+ } else if (raw.targeting && typeof raw.targeting === "object") {
2572
+ targetingObj = raw.targeting;
2573
+ } else {
2574
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c (chu\u1ED7i JSON ho\u1EB7c Object c\u1EA5u h\xECnh targeting).");
2575
+ targetingObj = {};
2576
+ }
2577
+ const gender = typeof targetingObj.Gender === "number" ? targetingObj.Gender : 0;
2578
+ if (![0, 1, 2].includes(gender)) {
2579
+ errors.push("Tr\u01B0\u1EDDng 'Gender' ph\u1EA3i l\xE0 0 (T\u1EA5t c\u1EA3), 1 (Nam), ho\u1EB7c 2 (N\u1EEF).");
2580
+ }
2581
+ const VALID_AGE_RANGES = [10282, 10283, 10284, 10285, 10286, 10287, 10288];
2582
+ const newAgeRanges = Array.isArray(targetingObj.NewAgeRanges) && targetingObj.NewAgeRanges.length > 0 ? targetingObj.NewAgeRanges.map(Number) : VALID_AGE_RANGES;
2583
+ for (const age of newAgeRanges) {
2584
+ if (!VALID_AGE_RANGES.includes(age)) {
2585
+ errors.push(`M\xE3 \u0111\u1ED9 tu\u1ED5i '${age}' kh\xF4ng h\u1EE3p l\u1EC7. C\xE1c m\xE3 cho ph\xE9p: ${VALID_AGE_RANGES.join(", ")}.`);
2586
+ }
2587
+ }
2588
+ const VALID_OS = [0, 1, 2, 3];
2589
+ const os = Array.isArray(targetingObj.Os) && targetingObj.Os.length > 0 ? targetingObj.Os.map(Number) : [0, 1, 3];
2590
+ for (const o of os) {
2591
+ if (!VALID_OS.includes(o)) {
2592
+ errors.push(`M\xE3 h\u1EC7 \u0111i\u1EC1u h\xE0nh '${o}' kh\xF4ng h\u1EE3p l\u1EC7 (0: Android, 1: iOS, 2: Windows Phone, 3: PC).`);
2593
+ }
2594
+ }
2595
+ let location = targetingObj.Location;
2596
+ if (!location || typeof location !== "object") {
2597
+ location = {
2598
+ Addresses: [],
2599
+ Cities: [],
2600
+ WardTargeting: { Includes: [], Excludes: [] }
2601
+ };
2602
+ } else {
2603
+ location = {
2604
+ Addresses: Array.isArray(location.Addresses) ? location.Addresses : [],
2605
+ Cities: Array.isArray(location.Cities) ? location.Cities : [],
2606
+ WardTargeting: location.WardTargeting && typeof location.WardTargeting === "object" ? location.WardTargeting : { Includes: [], Excludes: [] }
2607
+ };
2608
+ if (location.WardTargeting.Includes && !Array.isArray(location.WardTargeting.Includes)) {
2609
+ errors.push("Tr\u01B0\u1EDDng 'Location.WardTargeting.Includes' ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng khu v\u1EF1c.");
2610
+ } else if (Array.isArray(location.WardTargeting.Includes)) {
2611
+ for (const inc of location.WardTargeting.Includes) {
2612
+ if (![1, 2, 3].includes(Number(inc.Id))) {
2613
+ errors.push(`M\xE3 v\xF9ng mi\u1EC1n Id='${inc.Id}' kh\xF4ng h\u1EE3p l\u1EC7 (1: Mi\u1EC1n B\u1EAFc, 2: Mi\u1EC1n Trung, 3: Mi\u1EC1n Nam).`);
2614
+ }
2615
+ if (inc.Provinces && !Array.isArray(inc.Provinces)) {
2616
+ errors.push(`Tr\u01B0\u1EDDng 'Provinces' trong v\xF9ng mi\u1EC1n Id=${inc.Id} ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng t\u1EC9nh/th\xE0nh.`);
2617
+ }
2618
+ }
2619
+ }
2620
+ }
2621
+ const finalTargeting = {
2622
+ ...targetingObj,
2623
+ CustomAudienceId: 0,
2624
+ Gender: gender,
2625
+ NewAgeRanges: newAgeRanges,
2626
+ Os: os,
2627
+ Location: location
2628
+ };
2629
+ return {
2630
+ isValid: errors.length === 0,
2631
+ errors,
2632
+ data: errors.length === 0 ? {
2633
+ name,
2634
+ caType: 1,
2635
+ targeting: JSON.stringify(finalTargeting)
2636
+ } : void 0
2637
+ };
2638
+ }
2639
+ function validateCreatePhoneAudienceRequest(input) {
2640
+ const errors = [];
2641
+ if (!input || typeof input !== "object") {
2642
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
2643
+ }
2644
+ const raw = input;
2645
+ const name = typeof raw.name === "string" ? raw.name.trim() : "";
2646
+ if (!name || name.length < 2 || name.length > 255) {
2647
+ errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
2648
+ }
2649
+ let targetingObj = {};
2650
+ if (typeof raw.targeting === "string") {
2651
+ try {
2652
+ targetingObj = JSON.parse(raw.targeting);
2653
+ } catch {
2654
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
2655
+ }
2656
+ } else if (raw.targeting && typeof raw.targeting === "object") {
2657
+ targetingObj = raw.targeting;
2658
+ } else {
2659
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c.");
2660
+ }
2661
+ const path = typeof targetingObj.Path === "string" ? targetingObj.Path.trim() : "";
2662
+ if (!path) {
2663
+ errors.push("Tr\u01B0\u1EDDng 'Path' (URL file .txt sau khi upload) l\xE0 b\u1EAFt bu\u1ED9c.");
2664
+ }
2665
+ const total = typeof targetingObj.Total === "number" ? targetingObj.Total : 0;
2666
+ if (total <= 0) {
2667
+ errors.push("Tr\u01B0\u1EDDng 'Total' (s\u1ED1 l\u01B0\u1EE3ng S\u0110T trong file) ph\u1EA3i l\u1EDBn h\u01A1n 0.");
2668
+ }
2669
+ return {
2670
+ isValid: errors.length === 0,
2671
+ errors,
2672
+ data: errors.length === 0 ? {
2673
+ name,
2674
+ caType: 3,
2675
+ targeting: JSON.stringify({
2676
+ Name: String(targetingObj.Name || "phones.txt"),
2677
+ Path: path,
2678
+ Total: total,
2679
+ ZaloId: Number(targetingObj.ZaloId || 0),
2680
+ OriginAudience: 0
2681
+ })
2682
+ } : void 0
2683
+ };
2684
+ }
2685
+ function validateCreateLookalikeAudienceRequest(input) {
2686
+ const errors = [];
2687
+ if (!input || typeof input !== "object") {
2688
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
2689
+ }
2690
+ const raw = input;
2691
+ const name = typeof raw.name === "string" ? raw.name.trim() : "";
2692
+ if (!name || name.length < 2 || name.length > 255) {
2693
+ errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
2694
+ }
2695
+ let targetingObj = {};
2696
+ if (typeof raw.targeting === "string") {
2697
+ try {
2698
+ targetingObj = JSON.parse(raw.targeting);
2699
+ } catch {
2700
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
2701
+ }
2702
+ } else if (raw.targeting && typeof raw.targeting === "object") {
2703
+ targetingObj = raw.targeting;
2704
+ } else {
2705
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c.");
2706
+ }
2707
+ const originAudience = Number(targetingObj.OriginAudience);
2708
+ if (!originAudience || originAudience <= 0) {
2709
+ errors.push("Tr\u01B0\u1EDDng 'OriginAudience' (ID nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng S\u0110T g\u1ED1c) l\xE0 b\u1EAFt bu\u1ED9c.");
2710
+ }
2711
+ const total = Number(targetingObj.Total);
2712
+ if (![1e6, 15e5, 2e6].includes(total)) {
2713
+ errors.push("Tr\u01B0\u1EDDng 'Total' c\u1EE7a Lookalike ch\u1EC9 ch\u1EA5p nh\u1EADn c\xE1c m\u1ED1c: 1.000.000, 1.500.000 ho\u1EB7c 2.000.000.");
2714
+ }
2715
+ return {
2716
+ isValid: errors.length === 0,
2717
+ errors,
2718
+ data: errors.length === 0 ? {
2719
+ name,
2720
+ caType: 6,
2721
+ targeting: JSON.stringify({
2722
+ OriginAudience: originAudience,
2723
+ Total: total,
2724
+ Name: String(targetingObj.Name || "Lookalike Audience"),
2725
+ Path: String(targetingObj.Path || "")
2726
+ })
2727
+ } : void 0
2728
+ };
2729
+ }
2730
+ function validateCreateFormEventAudienceRequest(input) {
2731
+ const errors = [];
2732
+ if (!input || typeof input !== "object") {
2733
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
2734
+ }
2735
+ const raw = input;
2736
+ const name = typeof raw.name === "string" ? raw.name.trim() : "";
2737
+ if (!name || name.length < 2 || name.length > 255) {
2738
+ errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
2739
+ }
2740
+ let targetingObj = {};
2741
+ if (typeof raw.targeting === "string") {
2742
+ try {
2743
+ targetingObj = JSON.parse(raw.targeting);
2744
+ } catch {
2745
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
2746
+ }
2747
+ } else if (raw.targeting && typeof raw.targeting === "object") {
2748
+ targetingObj = raw.targeting;
2749
+ }
2750
+ const eventType = Number(targetingObj.EventType);
2751
+ if (![1, 2, 3, 4].includes(eventType)) {
2752
+ errors.push("Tr\u01B0\u1EDDng 'EventType' ph\u1EA3i l\xE0 1 (\u0110\xE3 xem ch\u01B0a g\u1EEDi), 2 (\u0110\xE3 xem & g\u1EEDi), 3 (\u0110\xE3 xem), ho\u1EB7c 4 (M\u1EDF chat t\u1EEB Form).");
2753
+ }
2754
+ const oaId = typeof targetingObj.OaId === "string" ? targetingObj.OaId.trim() : String(targetingObj.OaId || "");
2755
+ if (!oaId) {
2756
+ errors.push("Tr\u01B0\u1EDDng 'OaId' (d\u1EA1ng chu\u1ED7i c\u1EE7a pageId ho\u1EB7c noisedId) l\xE0 b\u1EAFt bu\u1ED9c.");
2757
+ }
2758
+ const numDays = Number(targetingObj.NumDays);
2759
+ if (isNaN(numDays) || numDays < 1 || numDays > 90) {
2760
+ errors.push("Tr\u01B0\u1EDDng 'NumDays' ph\u1EA3i n\u1EB1m trong kho\u1EA3ng t\u1EEB 1 \u0111\u1EBFn 90 ng\xE0y.");
2761
+ }
2762
+ const formIds = Array.isArray(targetingObj.FormIds) ? targetingObj.FormIds : [];
2763
+ if (formIds.length === 0) {
2764
+ errors.push("Tr\u01B0\u1EDDng 'FormIds' ph\u1EA3i ch\u1EE9a \xEDt nh\u1EA5t 1 ID Form.");
2765
+ }
2766
+ return {
2767
+ isValid: errors.length === 0,
2768
+ errors,
2769
+ data: errors.length === 0 ? {
2770
+ name,
2771
+ caType: 12,
2772
+ targeting: JSON.stringify({
2773
+ EventType: eventType,
2774
+ OaId: oaId,
2775
+ NumDays: numDays,
2776
+ FormIds: formIds
2777
+ })
2778
+ } : void 0
2779
+ };
2780
+ }
2781
+ function validateCreateMessageOaEventAudienceRequest(input) {
2782
+ const errors = [];
2783
+ if (!input || typeof input !== "object") {
2784
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
2785
+ }
2786
+ const raw = input;
2787
+ const name = typeof raw.name === "string" ? raw.name.trim() : "";
2788
+ if (!name || name.length < 2 || name.length > 255) {
2789
+ errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
2790
+ }
2791
+ let targetingObj = {};
2792
+ if (typeof raw.targeting === "string") {
2793
+ try {
2794
+ targetingObj = JSON.parse(raw.targeting);
2795
+ } catch {
2796
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
2797
+ }
2798
+ } else if (raw.targeting && typeof raw.targeting === "object") {
2799
+ targetingObj = raw.targeting;
2800
+ }
2801
+ const eventId = Number(targetingObj.EventId ?? targetingObj.EventType ?? 1);
2802
+ const oaId = typeof targetingObj.OaId === "string" ? targetingObj.OaId.trim() : String(targetingObj.OaId || "");
2803
+ if (!oaId) {
2804
+ errors.push("Tr\u01B0\u1EDDng 'OaId' (chu\u1ED7i pageId ho\u1EB7c noisedId c\u1EE7a OA) l\xE0 b\u1EAFt bu\u1ED9c.");
2805
+ }
2806
+ const numDays = Number(targetingObj.NumDays);
2807
+ if (isNaN(numDays) || numDays < 1 || numDays > 90) {
2808
+ errors.push("Tr\u01B0\u1EDDng 'NumDays' ph\u1EA3i n\u1EB1m trong kho\u1EA3ng t\u1EEB 1 \u0111\u1EBFn 90 ng\xE0y.");
2809
+ }
2810
+ return {
2811
+ isValid: errors.length === 0,
2812
+ errors,
2813
+ data: errors.length === 0 ? {
2814
+ name,
2815
+ caType: 11,
2816
+ targeting: JSON.stringify({
2817
+ EventId: eventId,
2818
+ OaId: oaId,
2819
+ NumDays: numDays
2820
+ })
2821
+ } : void 0
2822
+ };
2823
+ }
2824
+ function validateCreateMessagePersonalEventAudienceRequest(input) {
2825
+ const errors = [];
2826
+ if (!input || typeof input !== "object") {
2827
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
2828
+ }
2829
+ const raw = input;
2830
+ const name = typeof raw.name === "string" ? raw.name.trim() : "";
2831
+ if (!name || name.length < 2 || name.length > 255) {
2832
+ errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
2833
+ }
2834
+ let targetingObj = {};
2835
+ if (typeof raw.targeting === "string") {
2836
+ try {
2837
+ targetingObj = JSON.parse(raw.targeting);
2838
+ } catch {
2839
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
2840
+ }
2841
+ } else if (raw.targeting && typeof raw.targeting === "object") {
2842
+ targetingObj = raw.targeting;
2843
+ }
2844
+ const eventId = Number(targetingObj.EventId ?? targetingObj.EventType ?? 1);
2845
+ if (![1, 2, 3].includes(eventId)) {
2846
+ errors.push("Tr\u01B0\u1EDDng 'EventId' ph\u1EA3i l\xE0 1 (\u0110\xE3 li\xEAn h\u1EC7), 2 (\u0110\xE3 xem kh\xF4ng li\xEAn h\u1EC7), ho\u1EB7c 3 (Xem carousel kh\xF4ng li\xEAn h\u1EC7).");
2847
+ }
2848
+ const numDays = Number(targetingObj.NumDays);
2849
+ if (isNaN(numDays) || numDays < 1 || numDays > 90) {
2850
+ errors.push("Tr\u01B0\u1EDDng 'NumDays' ph\u1EA3i n\u1EB1m trong kho\u1EA3ng t\u1EEB 1 \u0111\u1EBFn 90 ng\xE0y.");
2851
+ }
2852
+ const pageIds = Array.isArray(targetingObj.PageIds) ? targetingObj.PageIds.map(String) : [];
2853
+ if (pageIds.length === 0) {
2854
+ errors.push("Tr\u01B0\u1EDDng 'PageIds' ph\u1EA3i ch\u1EE9a \xEDt nh\u1EA5t 1 ID trang c\xE1 nh\xE2n.");
2855
+ }
2856
+ return {
2857
+ isValid: errors.length === 0,
2858
+ errors,
2859
+ data: errors.length === 0 ? {
2860
+ name,
2861
+ caType: 14,
2862
+ targeting: JSON.stringify({
2863
+ EventId: eventId,
2864
+ NumDays: numDays,
2865
+ PageIds: pageIds
2866
+ })
2867
+ } : void 0
2868
+ };
2869
+ }
2870
+ function validateEstimateAudienceRequest(input) {
2871
+ const errors = [];
2872
+ if (!input || typeof input !== "object") {
2873
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
2874
+ }
2875
+ const raw = input;
2876
+ const gender = typeof raw.gender === "number" ? raw.gender : 0;
2877
+ if (![0, 1, 2].includes(gender)) {
2878
+ errors.push("Tr\u01B0\u1EDDng 'gender' ph\u1EA3i l\xE0 0, 1 ho\u1EB7c 2.");
2879
+ }
2880
+ const ageRanges = Array.isArray(raw.ageRanges) && raw.ageRanges.length > 0 ? raw.ageRanges.map(Number) : [10283, 10284, 10285, 10286, 10287];
2881
+ const platforms = Array.isArray(raw.platforms) && raw.platforms.length > 0 ? raw.platforms.map(Number) : [0, 1, 3];
2882
+ const priceType = typeof raw.priceType === "number" ? raw.priceType : 2;
2883
+ const wardsTargeting = typeof raw.wardsTargeting === "string" && raw.wardsTargeting.trim() ? raw.wardsTargeting.trim() : JSON.stringify({ Includes: [], Excludes: [] });
2884
+ return {
2885
+ isValid: errors.length === 0,
2886
+ errors,
2887
+ data: errors.length === 0 ? {
2888
+ gender,
2889
+ ageRanges,
2890
+ platforms,
2891
+ locations: typeof raw.locations === "string" ? raw.locations : "",
2892
+ provinces: Array.isArray(raw.provinces) ? raw.provinces.map(Number) : [],
2893
+ wardsTargeting,
2894
+ priceType,
2895
+ number: typeof raw.number === "string" ? raw.number : String(raw.number || "0")
2896
+ } : void 0
2897
+ };
2898
+ }
2899
+ var ZaloAudiencesValidator = {
2900
+ createSavedAudience: validateCreateSavedAudienceRequest,
2901
+ createPhoneAudience: validateCreatePhoneAudienceRequest,
2902
+ createLookalikeAudience: validateCreateLookalikeAudienceRequest,
2903
+ createFormEventAudience: validateCreateFormEventAudienceRequest,
2904
+ createMessageOaEventAudience: validateCreateMessageOaEventAudienceRequest,
2905
+ createMessagePersonalEventAudience: validateCreateMessagePersonalEventAudienceRequest,
2906
+ estimateAudience: validateEstimateAudienceRequest
2907
+ };
2908
+
1930
2909
  // src/services/audiences.service.ts
1931
2910
  var OP_ZaloAdsCreateCustomAudience = {
1932
2911
  "operationId": "ZaloAds_createCustomAudience",
@@ -2027,6 +3006,7 @@ var ZaloAudiencesService = class {
2027
3006
  constructor(client) {
2028
3007
  this.client = client;
2029
3008
  }
3009
+ static validator = ZaloAudiencesValidator;
2030
3010
  postApiAdEstimateaudience(request, options) {
2031
3011
  return this.client.requestJson(OP_ZaloAdsPostApiAdEstimateaudience, this.client.toTransportInput(OP_ZaloAdsPostApiAdEstimateaudience, request), options);
2032
3012
  }
@@ -2079,7 +3059,22 @@ var ZaloAudiencesService = class {
2079
3059
  }
2080
3060
  /** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Kịch bản Tin nhắn cá nhân (`caType = 14` - `MESSAGE_PERSONAL_EVENT_AUDIENCE`). */
2081
3061
  createMessagePersonalEventAudience(request, options) {
2082
- const targetingStr = typeof request.targeting === "string" ? request.targeting : JSON.stringify(request.targeting);
3062
+ let targetingObj;
3063
+ if (typeof request.targeting === "string") {
3064
+ try {
3065
+ targetingObj = JSON.parse(request.targeting);
3066
+ } catch {
3067
+ targetingObj = null;
3068
+ }
3069
+ } else if (request.targeting && typeof request.targeting === "object") {
3070
+ targetingObj = { ...request.targeting };
3071
+ }
3072
+ if (targetingObj && typeof targetingObj === "object") {
3073
+ if (targetingObj.EventId === void 0 && targetingObj.EventType !== void 0) {
3074
+ targetingObj.EventId = targetingObj.EventType;
3075
+ }
3076
+ }
3077
+ const targetingStr = targetingObj ? JSON.stringify(targetingObj) : typeof request.targeting === "string" ? request.targeting : JSON.stringify(request.targeting);
2083
3078
  return this.createCustomAudience({ name: request.name, caType: 14, targeting: targetingStr }, options);
2084
3079
  }
2085
3080
  /** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Zalo Form (`caType = 10` - `FORM_AUDIENCE`). */
@@ -2299,6 +3294,25 @@ var OP_ZaloAdsUpsertCustomReport = {
2299
3294
  "isDefault"
2300
3295
  ]
2301
3296
  };
3297
+ var OP_ZaloAdsDownloadReport = {
3298
+ operationId: "zalo_ads_download_report",
3299
+ method: "POST",
3300
+ endpoint: "/api/collect",
3301
+ baseUrl: "https://ads.zalo.me",
3302
+ binaryFields: [],
3303
+ pathFields: [],
3304
+ queryFields: [],
3305
+ headerFields: [],
3306
+ cookieFields: [],
3307
+ bodyFields: [
3308
+ "t",
3309
+ "adIds",
3310
+ "status",
3311
+ "dateFilter",
3312
+ "reportKind",
3313
+ "et"
3314
+ ]
3315
+ };
2302
3316
  var ZaloReportsService = class {
2303
3317
  constructor(client) {
2304
3318
  this.client = client;
@@ -2361,6 +3375,18 @@ var ZaloReportsService = class {
2361
3375
  getCampaignReportLegacy(...args) {
2362
3376
  return this.getZaapiCampaignReportcampaign(...args);
2363
3377
  }
3378
+ /** Xuất và tải trực tiếp tệp tin Excel (.xlsx / Blob) báo cáo hiệu quả quảng cáo (POST /api/collect) */
3379
+ downloadReport(request, options) {
3380
+ const payload = {
3381
+ t: request.t ?? "cd.download.report",
3382
+ status: request.status ?? 2,
3383
+ dateFilter: request.dateFilter ?? 0,
3384
+ reportKind: request.reportKind ?? 100001,
3385
+ et: request.et ?? Math.floor(Date.now() / 1e3),
3386
+ adIds: request.adIds
3387
+ };
3388
+ return this.client.requestJson(OP_ZaloAdsDownloadReport, this.client.toTransportInput(OP_ZaloAdsDownloadReport, payload), options);
3389
+ }
2364
3390
  };
2365
3391
 
2366
3392
  // src/services/conversions.service.ts
@@ -2627,12 +3653,242 @@ var ZaloAutomatedRulesService = class {
2627
3653
  changeAutomatedRuleStatus(request, options) {
2628
3654
  return this.client.requestJson(OP_ZaloAdsChangeAutomatedRuleStatus, this.client.toTransportInput(OP_ZaloAdsChangeAutomatedRuleStatus, request), options);
2629
3655
  }
2630
- getAutomatedRuleHistory(request, options) {
2631
- return this.client.requestWithoutBody(OP_ZaloAdsGetAutomatedRuleHistory, this.client.toTransportInput(OP_ZaloAdsGetAutomatedRuleHistory, request), options);
3656
+ getAutomatedRuleHistory(request, options) {
3657
+ return this.client.requestWithoutBody(OP_ZaloAdsGetAutomatedRuleHistory, this.client.toTransportInput(OP_ZaloAdsGetAutomatedRuleHistory, request), options);
3658
+ }
3659
+ deleteAutomatedRule(request, options) {
3660
+ return this.client.requestJson(OP_ZaloAdsDeleteAutomatedRule, this.client.toTransportInput(OP_ZaloAdsDeleteAutomatedRule, request), options);
3661
+ }
3662
+ };
3663
+
3664
+ // src/validators/flows.validator.ts
3665
+ var MAX_INT_32 = 2147483647;
3666
+ function is32BitPositiveInteger(val) {
3667
+ if (typeof val === "number") {
3668
+ return Number.isInteger(val) && val > 0 && val <= MAX_INT_32;
3669
+ }
3670
+ if (typeof val === "string" && val.trim() !== "") {
3671
+ const num = Number(val);
3672
+ return Number.isInteger(num) && num > 0 && num <= MAX_INT_32;
3673
+ }
3674
+ return false;
3675
+ }
3676
+ function isPositiveInteger(val) {
3677
+ if (typeof val === "number") return Number.isInteger(val) && val > 0;
3678
+ if (typeof val === "string" && val.trim() !== "") {
3679
+ const num = Number(val);
3680
+ return Number.isInteger(num) && num > 0;
3681
+ }
3682
+ return false;
3683
+ }
3684
+ function isNonNegativeInteger(val) {
3685
+ if (typeof val === "number") return Number.isInteger(val) && val >= 0;
3686
+ if (typeof val === "string" && val.trim() !== "") {
3687
+ const num = Number(val);
3688
+ return Number.isInteger(num) && num >= 0;
3689
+ }
3690
+ return false;
3691
+ }
3692
+ function toPositiveInteger(val) {
3693
+ return typeof val === "number" ? Math.floor(val) : parseInt(String(val), 10);
3694
+ }
3695
+ function validateFlowButtons(buttons, errors, prefix) {
3696
+ if (!Array.isArray(buttons)) {
3697
+ errors.push(`${prefix}: Tr\u01B0\u1EDDng 'buttons' ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng.`);
3698
+ return [];
3699
+ }
3700
+ const cleanButtons = [];
3701
+ buttons.forEach((btn, idx) => {
3702
+ const btnPrefix = `${prefix}.buttons[${idx}]`;
3703
+ if (!btn || typeof btn !== "object") {
3704
+ errors.push(`${btnPrefix}: N\xFAt b\u1EA5m ph\u1EA3i l\xE0 m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng.`);
3705
+ return;
3706
+ }
3707
+ const b = btn;
3708
+ if (typeof b.text !== "string" || b.text.trim() === "") {
3709
+ errors.push(`${btnPrefix}: Nh\xE3n n\xFAt 'text' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.`);
3710
+ }
3711
+ const btnType = Number(b.type);
3712
+ if (![3, 10, 12].includes(btnType)) {
3713
+ errors.push(`${btnPrefix}: Lo\u1EA1i n\xFAt 'type' ph\u1EA3i l\xE0 3 (nh\xE1nh h\u1ED9i tho\u1EA1i), 10 (m\u1EDF website), ho\u1EB7c 12 (g\u1ECDi hotline).`);
3714
+ }
3715
+ const cleanBtn = {
3716
+ type: btnType,
3717
+ text: String(b.text ?? "").trim(),
3718
+ editable: b.editable !== false
3719
+ };
3720
+ if (btnType === 10) {
3721
+ if (typeof b.url !== "string" || b.url.trim() === "") {
3722
+ errors.push(`${btnPrefix}: N\xFAt lo\u1EA1i 10 (m\u1EDF website) b\u1EAFt bu\u1ED9c ph\u1EA3i c\xF3 tr\u01B0\u1EDDng 'url' h\u1EE3p l\u1EC7.`);
3723
+ } else {
3724
+ cleanBtn.url = b.url.trim();
3725
+ }
3726
+ } else if (btnType === 12) {
3727
+ if (typeof b.phone !== "string" || b.phone.trim() === "") {
3728
+ errors.push(`${btnPrefix}: N\xFAt lo\u1EA1i 12 (g\u1ECDi hotline) b\u1EAFt bu\u1ED9c ph\u1EA3i c\xF3 tr\u01B0\u1EDDng 'phone' h\u1EE3p l\u1EC7.`);
3729
+ } else {
3730
+ cleanBtn.phone = b.phone.trim();
3731
+ }
3732
+ } else if (btnType === 3) {
3733
+ if (!Array.isArray(b.messages) || b.messages.length === 0) {
3734
+ errors.push(`${btnPrefix}: N\xFAt lo\u1EA1i 3 (nh\xE1nh h\u1ED9i tho\u1EA1i) b\u1EAFt bu\u1ED9c ph\u1EA3i c\xF3 m\u1EA3ng 'messages' ch\u1EE9a \xEDt nh\u1EA5t 1 tin nh\u1EAFn con ph\u1EA3n h\u1ED3i.`);
3735
+ } else {
3736
+ const cleanChildMsgs = [];
3737
+ b.messages.forEach((child, cIdx) => {
3738
+ const childPrefix = `${btnPrefix}.messages[${cIdx}]`;
3739
+ if (!child || typeof child !== "object") {
3740
+ errors.push(`${childPrefix}: Tin nh\u1EAFn con ph\u1EA3i l\xE0 m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng.`);
3741
+ return;
3742
+ }
3743
+ const c = child;
3744
+ if (typeof c.text !== "string" || c.text.trim() === "") {
3745
+ errors.push(`${childPrefix}: N\u1ED9i dung tin nh\u1EAFn con 'text' kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.`);
3746
+ } else if (c.text.length > 1961) {
3747
+ errors.push(`${childPrefix}: N\u1ED9i dung tin nh\u1EAFn con v\u01B0\u1EE3t qu\xE1 1961 k\xFD t\u1EF1 (hi\u1EC7n c\xF3 ${c.text.length} k\xFD t\u1EF1).`);
3748
+ }
3749
+ cleanChildMsgs.push({
3750
+ type: 8,
3751
+ text: String(c.text ?? "").trim()
3752
+ });
3753
+ });
3754
+ cleanBtn.messages = cleanChildMsgs;
3755
+ }
3756
+ }
3757
+ cleanButtons.push(cleanBtn);
3758
+ });
3759
+ return cleanButtons;
3760
+ }
3761
+ function validateFlowMessages(messages, errors) {
3762
+ if (!Array.isArray(messages)) {
3763
+ errors.push("Tr\u01B0\u1EDDng 'messages' ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng ch\u1EE9a tin nh\u1EAFn k\u1ECBch b\u1EA3n.");
3764
+ return [];
3765
+ }
3766
+ if (messages.length !== 1) {
3767
+ errors.push(`Zalo Ads ch\u1EC9 cho ph\xE9p k\u1ECBch b\u1EA3n ch\u1EE9a DUY NH\u1EA4T 1 tin nh\u1EAFn ch\xE0o m\u1EEBng c\u1EA5p cao (hi\u1EC7n c\xF3 ${messages.length} tin nh\u1EAFn). C\xE1c nh\xE1nh h\u1ED9i tho\u1EA1i ti\u1EBFp theo ph\u1EA3i c\u1EA5u h\xECnh b\xEAn trong n\xFAt b\u1EA5m lo\u1EA1i 3 (type=3).`);
3768
+ return [];
3769
+ }
3770
+ const msg = messages[0];
3771
+ if (!msg || typeof msg !== "object") {
3772
+ errors.push("Tin nh\u1EAFn k\u1ECBch b\u1EA3n ph\u1EA3i l\xE0 m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng.");
3773
+ return [];
3774
+ }
3775
+ const m = msg;
3776
+ const msgType = Number(m.type);
3777
+ if (![1, 2].includes(msgType)) {
3778
+ errors.push("Lo\u1EA1i tin nh\u1EAFn 'type' ph\u1EA3i l\xE0 1 (v\u0103n b\u1EA3n) ho\u1EB7c 2 (k\xE8m h\xECnh \u1EA3nh).");
3779
+ }
3780
+ if (typeof m.text !== "string" || m.text.trim() === "") {
3781
+ errors.push("N\u1ED9i dung tin nh\u1EAFn 'text' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
3782
+ } else if (m.text.length > 1961) {
3783
+ errors.push(`N\u1ED9i dung tin nh\u1EAFn v\u01B0\u1EE3t qu\xE1 1961 k\xFD t\u1EF1 (hi\u1EC7n c\xF3 ${m.text.length} k\xFD t\u1EF1).`);
3784
+ }
3785
+ const cleanMsg = {
3786
+ type: msgType,
3787
+ text: String(m.text ?? "").trim()
3788
+ };
3789
+ if (msgType === 2) {
3790
+ if (typeof m.url !== "string" || m.url.trim() === "") {
3791
+ errors.push("Tin nh\u1EAFn lo\u1EA1i 2 (k\xE8m \u1EA3nh) b\u1EAFt bu\u1ED9c ph\u1EA3i c\xF3 tr\u01B0\u1EDDng 'url' ch\u1EE9a \u0111\u01B0\u1EDDng d\u1EABn h\xECnh \u1EA3nh.");
3792
+ } else {
3793
+ cleanMsg.url = m.url.trim();
3794
+ }
3795
+ }
3796
+ if (m.buttons !== void 0 && m.buttons !== null) {
3797
+ cleanMsg.buttons = validateFlowButtons(m.buttons, errors, "messages[0]");
3798
+ }
3799
+ return [cleanMsg];
3800
+ }
3801
+ function validateListFlowsByOfficialAccountRequest(input) {
3802
+ const errors = [];
3803
+ if (!input || typeof input !== "object") {
3804
+ return { isValid: false, errors: ["D\u1EEF li\u1EC7u y\xEAu c\u1EA7u l\u1EA5y danh s\xE1ch k\u1ECBch b\u1EA3n ph\u1EA3i l\xE0 m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng."] };
3805
+ }
3806
+ const obj = input;
3807
+ if (!is32BitPositiveInteger(obj.oaId)) {
3808
+ errors.push("Tr\u01B0\u1EDDng 'oaId' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i l\xE0 m\xE3 pageId n\u1ED9i b\u1ED9 ki\u1EC3u s\u1ED1 nguy\xEAn 32-bit (<= 2,147,483,647). Kh\xF4ng truy\u1EC1n chu\u1ED7i noisedId c\xF4ng khai (18 ch\u1EEF s\u1ED1) v\xEC backend Play Framework s\u1EBD t\u1EEB ch\u1ED1i.");
3809
+ }
3810
+ if (!isPositiveInteger(obj.limit)) {
3811
+ errors.push("Tr\u01B0\u1EDDng 'limit' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn d\u01B0\u01A1ng (> 0).");
3812
+ }
3813
+ if (obj.offset !== void 0 && obj.offset !== null && !isNonNegativeInteger(obj.offset)) {
3814
+ errors.push("Tr\u01B0\u1EDDng 'offset' n\u1EBFu c\xF3 ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn kh\xF4ng \xE2m (>= 0).");
3815
+ }
3816
+ if (obj.flowId !== void 0 && obj.flowId !== null && !isPositiveInteger(obj.flowId)) {
3817
+ errors.push("Tr\u01B0\u1EDDng 'flowId' n\u1EBFu c\xF3 ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn d\u01B0\u01A1ng (> 0).");
3818
+ }
3819
+ const cleanData = {
3820
+ oaId: toPositiveInteger(obj.oaId),
3821
+ limit: toPositiveInteger(obj.limit)
3822
+ };
3823
+ if (obj.offset !== void 0 && obj.offset !== null) cleanData.offset = toPositiveInteger(obj.offset);
3824
+ if (obj.flowId !== void 0 && obj.flowId !== null) cleanData.flowId = toPositiveInteger(obj.flowId);
3825
+ return {
3826
+ isValid: errors.length === 0,
3827
+ errors,
3828
+ data: errors.length === 0 ? cleanData : void 0
3829
+ };
3830
+ }
3831
+ function validateCreateFlowRequest(input) {
3832
+ const errors = [];
3833
+ if (!input || typeof input !== "object") {
3834
+ return { isValid: false, errors: ["D\u1EEF li\u1EC7u y\xEAu c\u1EA7u t\u1EA1o k\u1ECBch b\u1EA3n ph\u1EA3i l\xE0 m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng."] };
2632
3835
  }
2633
- deleteAutomatedRule(request, options) {
2634
- return this.client.requestJson(OP_ZaloAdsDeleteAutomatedRule, this.client.toTransportInput(OP_ZaloAdsDeleteAutomatedRule, request), options);
3836
+ const obj = input;
3837
+ if (!is32BitPositiveInteger(obj.oaId)) {
3838
+ errors.push("Tr\u01B0\u1EDDng 'oaId' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i l\xE0 m\xE3 pageId n\u1ED9i b\u1ED9 ki\u1EC3u s\u1ED1 nguy\xEAn 32-bit (<= 2,147,483,647).");
3839
+ }
3840
+ if (typeof obj.name !== "string" || obj.name.trim() === "") {
3841
+ errors.push("Tr\u01B0\u1EDDng 'name' (t\xEAn k\u1ECBch b\u1EA3n) l\xE0 b\u1EAFt bu\u1ED9c v\xE0 kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
3842
+ } else if (obj.name.trim().length > 50) {
3843
+ errors.push(`T\xEAn k\u1ECBch b\u1EA3n kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 50 k\xFD t\u1EF1 (hi\u1EC7n c\xF3 ${obj.name.trim().length} k\xFD t\u1EF1).`);
3844
+ }
3845
+ const cleanMessages = validateFlowMessages(obj.messages, errors);
3846
+ const cleanData = {
3847
+ oaId: toPositiveInteger(obj.oaId),
3848
+ id: null,
3849
+ name: String(obj.name ?? "").trim(),
3850
+ messages: cleanMessages
3851
+ };
3852
+ return {
3853
+ isValid: errors.length === 0,
3854
+ errors,
3855
+ data: errors.length === 0 ? cleanData : void 0
3856
+ };
3857
+ }
3858
+ function validateUpdateFlowRequest(input) {
3859
+ const errors = [];
3860
+ if (!input || typeof input !== "object") {
3861
+ return { isValid: false, errors: ["D\u1EEF li\u1EC7u y\xEAu c\u1EA7u c\u1EADp nh\u1EADt k\u1ECBch b\u1EA3n ph\u1EA3i l\xE0 m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng."] };
2635
3862
  }
3863
+ const obj = input;
3864
+ if (!isPositiveInteger(obj.id)) {
3865
+ errors.push("Tr\u01B0\u1EDDng 'id' (ID Flow c\u1EA7n c\u1EADp nh\u1EADt) l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn d\u01B0\u01A1ng (> 0).");
3866
+ }
3867
+ if (!is32BitPositiveInteger(obj.oaId)) {
3868
+ errors.push("Tr\u01B0\u1EDDng 'oaId' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i l\xE0 m\xE3 pageId n\u1ED9i b\u1ED9 ki\u1EC3u s\u1ED1 nguy\xEAn 32-bit (<= 2,147,483,647).");
3869
+ }
3870
+ if (typeof obj.name !== "string" || obj.name.trim() === "") {
3871
+ errors.push("Tr\u01B0\u1EDDng 'name' (t\xEAn k\u1ECBch b\u1EA3n) l\xE0 b\u1EAFt bu\u1ED9c v\xE0 kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
3872
+ } else if (obj.name.trim().length > 50) {
3873
+ errors.push(`T\xEAn k\u1ECBch b\u1EA3n kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 50 k\xFD t\u1EF1 (hi\u1EC7n c\xF3 ${obj.name.trim().length} k\xFD t\u1EF1).`);
3874
+ }
3875
+ const cleanMessages = validateFlowMessages(obj.messages, errors);
3876
+ const cleanData = {
3877
+ id: toPositiveInteger(obj.id),
3878
+ oaId: toPositiveInteger(obj.oaId),
3879
+ name: String(obj.name ?? "").trim(),
3880
+ messages: cleanMessages
3881
+ };
3882
+ return {
3883
+ isValid: errors.length === 0,
3884
+ errors,
3885
+ data: errors.length === 0 ? cleanData : void 0
3886
+ };
3887
+ }
3888
+ var ZaloFlowsValidator = {
3889
+ listFlowsByOfficialAccount: validateListFlowsByOfficialAccountRequest,
3890
+ createFlow: validateCreateFlowRequest,
3891
+ updateFlow: validateUpdateFlowRequest
2636
3892
  };
2637
3893
 
2638
3894
  // src/services/flows.service.ts
@@ -2676,6 +3932,12 @@ var ZaloFlowsService = class {
2676
3932
  constructor(client) {
2677
3933
  this.client = client;
2678
3934
  }
3935
+ /**
3936
+ * Bộ công cụ kiểm tra tính hợp lệ dữ liệu (Standalone Validators) cho Message Flows APIs.
3937
+ * Dùng để validate dữ liệu đầu vào trước khi lưu DB hoặc gọi Zalo Ads.
3938
+ */
3939
+ static validator = ZaloFlowsValidator;
3940
+ validator = ZaloFlowsValidator;
2679
3941
  listFlowsByOfficialAccount(request, options) {
2680
3942
  return this.client.requestWithoutBody(OP_ZaloAdsListFlowsByOfficialAccount, this.client.toTransportInput(OP_ZaloAdsListFlowsByOfficialAccount, request), options);
2681
3943
  }
@@ -3589,7 +4851,301 @@ var ZaloChatWidgetService = class {
3589
4851
  }
3590
4852
  };
3591
4853
 
4854
+ // src/validators/forms.validator.ts
4855
+ function isValidUrl(val) {
4856
+ if (typeof val !== "string" || val.trim() === "") return false;
4857
+ try {
4858
+ const url = new URL(val);
4859
+ return url.protocol === "http:" || url.protocol === "https:";
4860
+ } catch {
4861
+ return false;
4862
+ }
4863
+ }
4864
+ function validateCreateFormRequest(input) {
4865
+ const errors = [];
4866
+ if (!input || typeof input !== "object") {
4867
+ return {
4868
+ isValid: false,
4869
+ errors: ["D\u1EEF li\u1EC7u y\xEAu c\u1EA7u t\u1EA1o Form ph\u1EA3i l\xE0 m\u1ED9t object."],
4870
+ data: void 0
4871
+ };
4872
+ }
4873
+ let raw = input;
4874
+ if (typeof input.data === "string") {
4875
+ try {
4876
+ raw = JSON.parse(input.data);
4877
+ } catch {
4878
+ errors.push("Tr\u01B0\u1EDDng 'data' kh\xF4ng ph\u1EA3i l\xE0 chu\u1ED7i JSON h\u1EE3p l\u1EC7.");
4879
+ return { isValid: false, errors, data: void 0 };
4880
+ }
4881
+ } else if (typeof input.data === "object" && input.data !== null) {
4882
+ raw = input.data;
4883
+ }
4884
+ const oaIdRaw = raw.oaId;
4885
+ let cleanOaId = "";
4886
+ if (typeof oaIdRaw === "string" && /^[0-9]+$/.test(oaIdRaw.trim())) {
4887
+ cleanOaId = oaIdRaw.trim();
4888
+ } else if (typeof oaIdRaw === "number" && Number.isInteger(oaIdRaw) && oaIdRaw > 0) {
4889
+ cleanOaId = String(oaIdRaw);
4890
+ } else {
4891
+ errors.push("Tr\u01B0\u1EDDng 'oaId' b\u1EAFt bu\u1ED9c ph\u1EA3i l\xE0 chu\u1ED7i s\u1ED1 nguy\xEAn d\u01B0\u01A1ng \u0111\u1EA1i di\u1EC7n cho pageId n\u1ED9i b\u1ED9 c\u1EE7a OA (v\xED d\u1EE5: '429753475').");
4892
+ }
4893
+ const title = typeof raw.title === "string" ? raw.title.trim() : "";
4894
+ if (!title) {
4895
+ errors.push("Tr\u01B0\u1EDDng 'title' (ti\xEAu \u0111\u1EC1 form) l\xE0 b\u1EAFt bu\u1ED9c.");
4896
+ } else if (title.length < 2 || title.length > 40) {
4897
+ errors.push(`Tr\u01B0\u1EDDng 'title' ph\u1EA3i c\xF3 \u0111\u1ED9 d\xE0i t\u1EEB 2 \u0111\u1EBFn 40 k\xFD t\u1EF1 (hi\u1EC7n t\u1EA1i: ${title.length} k\xFD t\u1EF1).`);
4898
+ }
4899
+ const formName = typeof raw.formName === "string" ? raw.formName.trim() : "";
4900
+ if (!formName) {
4901
+ errors.push("Tr\u01B0\u1EDDng 'formName' (t\xEAn qu\u1EA3n tr\u1ECB form) l\xE0 b\u1EAFt bu\u1ED9c.");
4902
+ } else if (formName.length < 2 || formName.length > 100) {
4903
+ errors.push(`Tr\u01B0\u1EDDng 'formName' ph\u1EA3i c\xF3 \u0111\u1ED9 d\xE0i t\u1EEB 2 \u0111\u1EBFn 100 k\xFD t\u1EF1 (hi\u1EC7n t\u1EA1i: ${formName.length} k\xFD t\u1EF1).`);
4904
+ }
4905
+ let cleanDescription = void 0;
4906
+ if (raw.description !== void 0 && raw.description !== null) {
4907
+ const desc = String(raw.description).trim();
4908
+ if (desc.length > 600) {
4909
+ errors.push(`Tr\u01B0\u1EDDng 'description' kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 600 k\xFD t\u1EF1 (hi\u1EC7n t\u1EA1i: ${desc.length} k\xFD t\u1EF1).`);
4910
+ } else {
4911
+ cleanDescription = desc;
4912
+ }
4913
+ }
4914
+ const coverPhoto = typeof raw.coverPhoto === "string" ? raw.coverPhoto.trim() : "";
4915
+ if (!coverPhoto) {
4916
+ errors.push("Tr\u01B0\u1EDDng 'coverPhoto' (\u1EA3nh b\xECa form) l\xE0 b\u1EAFt bu\u1ED9c.");
4917
+ } else if (!isValidUrl(coverPhoto)) {
4918
+ errors.push(`Tr\u01B0\u1EDDng 'coverPhoto' ph\u1EA3i l\xE0 URL h\u1EE3p l\u1EC7 (http:// ho\u1EB7c https://).`);
4919
+ }
4920
+ const submitTitle = typeof raw.submitTitle === "string" && raw.submitTitle.trim() !== "" ? raw.submitTitle.trim() : "G\u1EEDi th\xF4ng tin th\xE0nh c\xF4ng";
4921
+ if (submitTitle.length > 90) {
4922
+ errors.push(`Tr\u01B0\u1EDDng 'submitTitle' kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 90 k\xFD t\u1EF1 (hi\u1EC7n t\u1EA1i: ${submitTitle.length} k\xFD t\u1EF1).`);
4923
+ }
4924
+ const thanks = typeof raw.thanks === "string" && raw.thanks.trim() !== "" ? raw.thanks.trim() : "C\u1EA3m \u01A1n b\u1EA1n \u0111\xE3 g\u1EEDi th\xF4ng tin. Ch\xFAng t\xF4i s\u1EBD li\xEAn h\u1EC7 trong th\u1EDDi gian s\u1EDBm nh\u1EA5t.";
4925
+ if (thanks.length > 255) {
4926
+ errors.push(`Tr\u01B0\u1EDDng 'thanks' kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 255 k\xFD t\u1EF1 (hi\u1EC7n t\u1EA1i: ${thanks.length} k\xFD t\u1EF1).`);
4927
+ }
4928
+ const gotoActionType = raw.gotoActionType === 0 ? 0 : 1;
4929
+ const gotoText = typeof raw.gotoText === "string" && raw.gotoText.trim() !== "" ? raw.gotoText.trim() : gotoActionType === 1 ? "Xem trang Web" : "\u0110\xF3ng l\u1EA1i";
4930
+ let cleanWebsite = void 0;
4931
+ if (gotoActionType === 1) {
4932
+ if (!raw.website || !isValidUrl(raw.website)) {
4933
+ errors.push("Khi 'gotoActionType' = 1 (m\u1EDF website), tr\u01B0\u1EDDng 'website' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i l\xE0 URL h\u1EE3p l\u1EC7.");
4934
+ } else {
4935
+ cleanWebsite = String(raw.website).trim();
4936
+ }
4937
+ }
4938
+ const useCustomConsent = Boolean(raw.useCustomConsent);
4939
+ let cleanConsentName = void 0;
4940
+ let cleanConsentUrl = void 0;
4941
+ if (useCustomConsent) {
4942
+ const cName = typeof raw.consentName === "string" ? raw.consentName.trim() : "";
4943
+ if (!cName) {
4944
+ errors.push("Khi 'useCustomConsent' = true, tr\u01B0\u1EDDng 'consentName' (ti\xEAu \u0111\u1EC1 \u0111i\u1EC1u kho\u1EA3n) l\xE0 b\u1EAFt bu\u1ED9c.");
4945
+ } else if (cName.length > 255) {
4946
+ errors.push(`Tr\u01B0\u1EDDng 'consentName' kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 255 k\xFD t\u1EF1 (hi\u1EC7n t\u1EA1i: ${cName.length} k\xFD t\u1EF1).`);
4947
+ } else {
4948
+ cleanConsentName = cName;
4949
+ }
4950
+ if (!raw.consentUrl || !isValidUrl(raw.consentUrl)) {
4951
+ errors.push("Khi 'useCustomConsent' = true, tr\u01B0\u1EDDng 'consentUrl' ph\u1EA3i l\xE0 URL h\u1EE3p l\u1EC7 ch\u1EE9a ch\xEDnh s\xE1ch b\u1EA3o m\u1EADt.");
4952
+ } else {
4953
+ cleanConsentUrl = String(raw.consentUrl).trim();
4954
+ }
4955
+ }
4956
+ if (!Array.isArray(raw.questions) || raw.questions.length === 0) {
4957
+ errors.push("Bi\u1EC3u m\u1EABu b\u1EAFt bu\u1ED9c ph\u1EA3i c\xF3 \xEDt nh\u1EA5t 1 c\xE2u h\u1ECFi trong m\u1EA3ng 'questions'.");
4958
+ }
4959
+ const cleanQuestions = [];
4960
+ let hasPhonePrimary = false;
4961
+ let hasPhoneSecondary = false;
4962
+ if (Array.isArray(raw.questions)) {
4963
+ raw.questions.forEach((q, idx) => {
4964
+ const qPrefix = `C\xE2u h\u1ECFi [${idx}]`;
4965
+ if (!q || typeof q !== "object") {
4966
+ errors.push(`${qPrefix} ph\u1EA3i l\xE0 m\u1ED9t object.`);
4967
+ return;
4968
+ }
4969
+ const qTitle = typeof q.title === "string" ? q.title.trim() : "";
4970
+ if (qTitle.length < 2 || qTitle.length > 180) {
4971
+ errors.push(`${qPrefix}: Ti\xEAu \u0111\u1EC1 'title' ph\u1EA3i c\xF3 \u0111\u1ED9 d\xE0i t\u1EEB 2 \u0111\u1EBFn 180 k\xFD t\u1EF1.`);
4972
+ }
4973
+ if (!Array.isArray(q.answers) || q.answers.length === 0) {
4974
+ errors.push(`${qPrefix}: Ph\u1EA3i c\xF3 \xEDt nh\u1EA5t 1 \u0111\xE1p \xE1n trong m\u1EA3ng 'answers'.`);
4975
+ return;
4976
+ }
4977
+ const cleanAnswers = [];
4978
+ q.answers.forEach((ans, aIdx) => {
4979
+ const aType = Number(ans?.type);
4980
+ if (![2, 7, 13].includes(aType)) {
4981
+ errors.push(`${qPrefix} \u0111\xE1p \xE1n [${aIdx}]: 'type' ph\u1EA3i l\xE0 7 (H\u1ECD t\xEAn), 13 (S\u0110T chu\u1EA9n), ho\u1EB7c 2 (S\u0110T ph\u1EE5).`);
4982
+ }
4983
+ if (aType === 13) hasPhonePrimary = true;
4984
+ if (aType === 2) hasPhoneSecondary = true;
4985
+ cleanAnswers.push({
4986
+ type: aType,
4987
+ placeHolder: ans?.placeHolder ? String(ans.placeHolder).trim() : void 0,
4988
+ value: ans?.value ? String(ans.value).trim() : null,
4989
+ priority: typeof ans?.priority === "number" ? ans.priority : 500
4990
+ });
4991
+ });
4992
+ cleanQuestions.push({
4993
+ title: qTitle,
4994
+ type: typeof q.type === "number" ? q.type : 1,
4995
+ isRequired: q.isRequired !== void 0 ? Boolean(q.isRequired) : true,
4996
+ editDisabled: Boolean(q.editDisabled),
4997
+ priority: typeof q.priority === "number" ? q.priority : (idx + 1) * 100,
4998
+ answers: cleanAnswers
4999
+ });
5000
+ });
5001
+ }
5002
+ if (hasPhoneSecondary) {
5003
+ cleanQuestions.forEach((q) => {
5004
+ if (q.answers.some((a) => a.type === 13)) {
5005
+ q.editDisabled = true;
5006
+ }
5007
+ });
5008
+ }
5009
+ const cleanSections = [];
5010
+ if (Array.isArray(raw.sections)) {
5011
+ raw.sections.forEach((sec, sIdx) => {
5012
+ const sPrefix = `Section [${sIdx}]`;
5013
+ const sType = Number(sec?.type);
5014
+ if (isNaN(sType) || sType < 0 || sType > 4) {
5015
+ errors.push(`${sPrefix}: 'type' ph\u1EA3i l\xE0 s\u1ED1 t\u1EEB 0 \u0111\u1EBFn 4 (0=t\u1ED5ng quan, 1=chi ti\u1EBFt, 2=b\u1EA3ng gi\xE1, 3=\u01B0u \u0111i\u1EC3m, 4=\u01B0u \u0111\xE3i).`);
5016
+ }
5017
+ const sTitle = typeof sec?.title === "string" ? sec.title.trim() : "";
5018
+ if (sTitle.length > 60) {
5019
+ errors.push(`${sPrefix}: 'title' kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 60 k\xFD t\u1EF1.`);
5020
+ }
5021
+ cleanSections.push({
5022
+ type: sType,
5023
+ title: sTitle,
5024
+ disable: Boolean(sec?.disable),
5025
+ expand: Boolean(sec?.expand),
5026
+ content: sec?.content ? sec.content : {}
5027
+ });
5028
+ });
5029
+ }
5030
+ const cleanData = {
5031
+ oaId: cleanOaId,
5032
+ title,
5033
+ formName,
5034
+ description: cleanDescription,
5035
+ coverPhoto,
5036
+ submitTitle,
5037
+ thanks,
5038
+ gotoActionType,
5039
+ gotoText,
5040
+ website: cleanWebsite,
5041
+ reviewSubmit: raw.reviewSubmit !== void 0 ? Boolean(raw.reviewSubmit) : true,
5042
+ questions: cleanQuestions,
5043
+ sections: cleanSections.length > 0 ? cleanSections : void 0,
5044
+ useCustomConsent,
5045
+ consentName: cleanConsentName,
5046
+ consentUrl: cleanConsentUrl
5047
+ };
5048
+ return {
5049
+ isValid: errors.length === 0,
5050
+ errors,
5051
+ data: errors.length === 0 ? cleanData : void 0
5052
+ };
5053
+ }
5054
+ function validateListFormsByOfficialAccountRequest(input) {
5055
+ const errors = [];
5056
+ if (!input || typeof input !== "object") {
5057
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
5058
+ }
5059
+ const raw = input;
5060
+ let cleanOaId = "";
5061
+ if (typeof raw.oaId === "string" && /^[0-9]+$/.test(raw.oaId.trim())) {
5062
+ cleanOaId = raw.oaId.trim();
5063
+ } else if (typeof raw.oaId === "number" && Number.isInteger(raw.oaId) && raw.oaId > 0) {
5064
+ cleanOaId = String(raw.oaId);
5065
+ } else {
5066
+ errors.push("Tr\u01B0\u1EDDng 'oaId' b\u1EAFt bu\u1ED9c ph\u1EA3i l\xE0 chu\u1ED7i s\u1ED1 nguy\xEAn d\u01B0\u01A1ng \u0111\u1EA1i di\u1EC7n cho pageId c\u1EE7a OA.");
5067
+ }
5068
+ return {
5069
+ isValid: errors.length === 0,
5070
+ errors,
5071
+ data: errors.length === 0 ? { oaId: cleanOaId, isAll: raw.isAll !== void 0 ? Boolean(raw.isAll) : true } : void 0
5072
+ };
5073
+ }
5074
+ function validateListFormLeadsRequest(input) {
5075
+ const errors = [];
5076
+ if (!input || typeof input !== "object") {
5077
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
5078
+ }
5079
+ const raw = input;
5080
+ const oaId = typeof raw.oaId === "string" ? raw.oaId.trim() : "";
5081
+ if (!oaId) {
5082
+ errors.push("Tr\u01B0\u1EDDng 'oaId' l\xE0 b\u1EAFt bu\u1ED9c (m\xE3 ch\u1EEF t\u1EEB getAuthSession, v\xED d\u1EE5 'J4UB9MRE497YDQKKK').");
5083
+ } else if (/^[0-9]+$/.test(oaId)) {
5084
+ errors.push("Tr\u01B0\u1EDDng 'oaId' tr\xEAn Lead Center ph\u1EA3i l\xE0 m\xE3 ch\u1EEF alphanumeric t\u1EEB getAuthSession, kh\xF4ng d\xF9ng chu\u1ED7i s\u1ED1 pageId (s\u1EBD b\u1ECB l\u1ED7i 403 Forbidden).");
5085
+ }
5086
+ const type = Number(raw.type);
5087
+ if (![1, 5].includes(type)) {
5088
+ errors.push("Tr\u01B0\u1EDDng 'type' ph\u1EA3i l\xE0 1 (ZALOFORM) ho\u1EB7c 5 (COMMERCE).");
5089
+ }
5090
+ const limit = typeof raw.limit === "number" && raw.limit > 0 ? Math.floor(raw.limit) : 20;
5091
+ const offset = typeof raw.offset === "number" && raw.offset >= 0 ? Math.floor(raw.offset) : 0;
5092
+ const status = typeof raw.status === "string" && raw.status.trim() !== "" ? raw.status.trim() : "2,6,1,0,7,4,5,3";
5093
+ const now = Math.floor(Date.now() / 1e3);
5094
+ const fromTime = typeof raw.fromTime === "number" && raw.fromTime >= 0 ? Math.floor(raw.fromTime) : now - 90 * 86400;
5095
+ const toTime = typeof raw.toTime === "number" && raw.toTime >= 0 ? Math.floor(raw.toTime) : now;
5096
+ if (toTime < fromTime) {
5097
+ errors.push("M\u1ED1c th\u1EDDi gian k\u1EBFt th\xFAc 'toTime' ph\u1EA3i l\u1EDBn h\u01A1n ho\u1EB7c b\u1EB1ng 'fromTime'.");
5098
+ }
5099
+ return {
5100
+ isValid: errors.length === 0,
5101
+ errors,
5102
+ data: errors.length === 0 ? {
5103
+ oaId,
5104
+ type,
5105
+ limit,
5106
+ offset,
5107
+ status,
5108
+ fromTime,
5109
+ toTime,
5110
+ formIds: raw.formIds ? String(raw.formIds).trim() : void 0,
5111
+ keyword: raw.keyword ? String(raw.keyword).trim() : void 0,
5112
+ reason: raw.reason ? String(raw.reason).trim() : void 0,
5113
+ labelIds: raw.labelIds ? String(raw.labelIds).trim() : void 0,
5114
+ isCommerce: raw.isCommerce !== void 0 ? Boolean(raw.isCommerce) : false
5115
+ } : void 0
5116
+ };
5117
+ }
5118
+ var ZaloFormsValidator = {
5119
+ createForm: validateCreateFormRequest,
5120
+ listFormsByOfficialAccount: validateListFormsByOfficialAccountRequest,
5121
+ listFormLeads: validateListFormLeadsRequest
5122
+ };
5123
+
3592
5124
  // src/services/forms.service.ts
5125
+ var OP_ZaloAdsCreateForm2 = {
5126
+ operationId: "zalo_ads_create_form",
5127
+ method: "POST",
5128
+ endpoint: "/api/form/create",
5129
+ baseUrl: "https://ads.zalo.me",
5130
+ binaryFields: [],
5131
+ pathFields: [],
5132
+ queryFields: [],
5133
+ headerFields: [],
5134
+ cookieFields: [],
5135
+ bodyFields: ["data"]
5136
+ };
5137
+ var OP_ZaloAdsListFormsByOfficialAccount2 = {
5138
+ operationId: "zalo_ads_list_forms_by_official_account",
5139
+ method: "GET",
5140
+ endpoint: "/api/form/getByOaId",
5141
+ baseUrl: "https://ads.zalo.me",
5142
+ binaryFields: [],
5143
+ pathFields: [],
5144
+ queryFields: ["oaId", "isAll"],
5145
+ headerFields: [],
5146
+ cookieFields: [],
5147
+ bodyFields: []
5148
+ };
3593
5149
  var OP_ZaloFormsDisableFormLeadNotification = {
3594
5150
  "operationId": "ZaloForms_disableFormLeadNotification",
3595
5151
  "method": "POST",
@@ -3663,7 +5219,8 @@ var OP_ZaloFormsListConversationLeads = {
3663
5219
  "keyword",
3664
5220
  "fromTime",
3665
5221
  "labelIds",
3666
- "sceneIds"
5222
+ "sceneIds",
5223
+ "reason"
3667
5224
  ],
3668
5225
  "headerFields": [],
3669
5226
  "cookieFields": [],
@@ -3687,7 +5244,8 @@ var OP_ZaloFormsListFormLeads = {
3687
5244
  "keyword",
3688
5245
  "fromTime",
3689
5246
  "labelIds",
3690
- "isCommerce"
5247
+ "isCommerce",
5248
+ "reason"
3691
5249
  ],
3692
5250
  "headerFields": [],
3693
5251
  "cookieFields": [],
@@ -3769,10 +5327,59 @@ var OP_ZaloFormsGetAuthSession = {
3769
5327
  "cookieFields": [],
3770
5328
  "bodyFields": []
3771
5329
  };
5330
+ var OP_ZaloFormsTrackManageFormEvent = {
5331
+ operationId: "zalo_forms_track_manage_form_event",
5332
+ method: "GET",
5333
+ endpoint: "/client/manage/api/manageForm/tracking",
5334
+ baseUrl: "https://form.ads.zalo.me",
5335
+ binaryFields: [],
5336
+ pathFields: [],
5337
+ queryFields: ["eventId", "oaId", "formId"],
5338
+ headerFields: [],
5339
+ cookieFields: [],
5340
+ bodyFields: []
5341
+ };
3772
5342
  var ZaloFormsService = class {
3773
5343
  constructor(client) {
3774
5344
  this.client = client;
3775
5345
  }
5346
+ validator = ZaloFormsValidator;
5347
+ static validator = ZaloFormsValidator;
5348
+ /**
5349
+ * Tạo biểu mẫu mới gắn với Official Account (POST https://ads.zalo.me/api/form/create).
5350
+ * Hỗ trợ truyền thẳng Typed Payload (tự động validate qua ZaloFormsValidator và mã hóa urlencoded)
5351
+ * hoặc object dạng `{ data: JSON.stringify(...) }`.
5352
+ */
5353
+ async createForm(request, options) {
5354
+ let payloadStr;
5355
+ if (typeof request.data === "string") {
5356
+ payloadStr = request.data;
5357
+ } else {
5358
+ const val = ZaloFormsValidator.createForm(request);
5359
+ if (!val.isValid || !val.data) {
5360
+ throw new Error(`[ZaloFormsValidator] D\u1EEF li\u1EC7u t\u1EA1o form kh\xF4ng h\u1EE3p l\u1EC7:
5361
+ - ${val.errors.join("\n - ")}`);
5362
+ }
5363
+ payloadStr = JSON.stringify(val.data);
5364
+ }
5365
+ return this.client.requestFormUrlEncoded(
5366
+ OP_ZaloAdsCreateForm2,
5367
+ this.client.toTransportInput(OP_ZaloAdsCreateForm2, { data: payloadStr }),
5368
+ options
5369
+ );
5370
+ }
5371
+ /**
5372
+ * Lấy danh sách biểu mẫu Zalo Ads theo Official Account (GET https://ads.zalo.me/api/form/getByOaId).
5373
+ */
5374
+ listFormsByOfficialAccount(request, options) {
5375
+ const val = ZaloFormsValidator.listFormsByOfficialAccount(request);
5376
+ const cleanInput = val.isValid && val.data ? val.data : request;
5377
+ return this.client.requestWithoutBody(
5378
+ OP_ZaloAdsListFormsByOfficialAccount2,
5379
+ this.client.toTransportInput(OP_ZaloAdsListFormsByOfficialAccount2, cleanInput),
5380
+ options
5381
+ );
5382
+ }
3776
5383
  getAuthSession(options) {
3777
5384
  return this.client.requestWithoutBody(OP_ZaloFormsGetAuthSession, void 0, options);
3778
5385
  }
@@ -3806,10 +5413,20 @@ var ZaloFormsService = class {
3806
5413
  updateFormLeadNotificationInterval(request, options) {
3807
5414
  return this.client.requestJson(OP_ZaloFormsUpdateFormLeadNotificationInterval, this.client.toTransportInput(OP_ZaloFormsUpdateFormLeadNotificationInterval, request), options);
3808
5415
  }
5416
+ /**
5417
+ * Ghi nhận sự kiện tương tác trên Lead Center (GET /client/manage/api/manageForm/tracking).
5418
+ */
5419
+ trackManageFormEvent(request, options) {
5420
+ return this.client.requestWithoutBody(
5421
+ OP_ZaloFormsTrackManageFormEvent,
5422
+ this.client.toTransportInput(OP_ZaloFormsTrackManageFormEvent, request),
5423
+ options
5424
+ );
5425
+ }
3809
5426
  };
3810
5427
 
3811
5428
  // src/validators/instant-pages.validator.ts
3812
- function isPositiveInteger(val) {
5429
+ function isPositiveInteger2(val) {
3813
5430
  if (typeof val === "number") return Number.isInteger(val) && val > 0;
3814
5431
  if (typeof val === "string" && val.trim() !== "") {
3815
5432
  const num = Number(val);
@@ -3817,7 +5434,7 @@ function isPositiveInteger(val) {
3817
5434
  }
3818
5435
  return false;
3819
5436
  }
3820
- function toPositiveInteger(val) {
5437
+ function toPositiveInteger2(val) {
3821
5438
  return typeof val === "number" ? Math.floor(val) : parseInt(String(val), 10);
3822
5439
  }
3823
5440
  function validateCloneInstantPageRequest(input) {
@@ -3826,13 +5443,13 @@ function validateCloneInstantPageRequest(input) {
3826
5443
  return { isValid: false, errors: ["D\u1EEF li\u1EC7u y\xEAu c\u1EA7u sao ch\xE9p Instant Page ph\u1EA3i l\xE0 m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng (object)."] };
3827
5444
  }
3828
5445
  const obj = input;
3829
- if (!isPositiveInteger(obj.instantPageId)) {
5446
+ if (!isPositiveInteger2(obj.instantPageId)) {
3830
5447
  errors.push("Tr\u01B0\u1EDDng 'instantPageId' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn d\u01B0\u01A1ng (> 0).");
3831
5448
  }
3832
5449
  return {
3833
5450
  isValid: errors.length === 0,
3834
5451
  errors,
3835
- data: errors.length === 0 ? { instantPageId: toPositiveInteger(obj.instantPageId) } : void 0
5452
+ data: errors.length === 0 ? { instantPageId: toPositiveInteger2(obj.instantPageId) } : void 0
3836
5453
  };
3837
5454
  }
3838
5455
  function validateGetInstantPageDetailRequest(input) {
@@ -3841,13 +5458,13 @@ function validateGetInstantPageDetailRequest(input) {
3841
5458
  return { isValid: false, errors: ["D\u1EEF li\u1EC7u y\xEAu c\u1EA7u l\u1EA5y chi ti\u1EBFt Instant Page ph\u1EA3i l\xE0 m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng (object)."] };
3842
5459
  }
3843
5460
  const obj = input;
3844
- if (!isPositiveInteger(obj.instantPageId)) {
5461
+ if (!isPositiveInteger2(obj.instantPageId)) {
3845
5462
  errors.push("Tr\u01B0\u1EDDng 'instantPageId' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn d\u01B0\u01A1ng (> 0).");
3846
5463
  }
3847
5464
  return {
3848
5465
  isValid: errors.length === 0,
3849
5466
  errors,
3850
- data: errors.length === 0 ? { instantPageId: toPositiveInteger(obj.instantPageId) } : void 0
5467
+ data: errors.length === 0 ? { instantPageId: toPositiveInteger2(obj.instantPageId) } : void 0
3851
5468
  };
3852
5469
  }
3853
5470
  function validateGetInstantPageSharedUserRequest(input) {
@@ -3856,18 +5473,18 @@ function validateGetInstantPageSharedUserRequest(input) {
3856
5473
  return { isValid: false, errors: ["D\u1EEF li\u1EC7u y\xEAu c\u1EA7u l\u1EA5y th\xF4ng tin ng\u01B0\u1EDDi d\xF9ng chia s\u1EBB ph\u1EA3i l\xE0 m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng (object)."] };
3857
5474
  }
3858
5475
  const obj = input;
3859
- if (!isPositiveInteger(obj.instantPageId)) {
5476
+ if (!isPositiveInteger2(obj.instantPageId)) {
3860
5477
  errors.push("Tr\u01B0\u1EDDng 'instantPageId' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn d\u01B0\u01A1ng (> 0).");
3861
5478
  }
3862
- if (!isPositiveInteger(obj.userId)) {
5479
+ if (!isPositiveInteger2(obj.userId)) {
3863
5480
  errors.push("Tr\u01B0\u1EDDng 'userId' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn d\u01B0\u01A1ng (> 0).");
3864
5481
  }
3865
5482
  return {
3866
5483
  isValid: errors.length === 0,
3867
5484
  errors,
3868
5485
  data: errors.length === 0 ? {
3869
- instantPageId: toPositiveInteger(obj.instantPageId),
3870
- userId: toPositiveInteger(obj.userId)
5486
+ instantPageId: toPositiveInteger2(obj.instantPageId),
5487
+ userId: toPositiveInteger2(obj.userId)
3871
5488
  } : void 0
3872
5489
  };
3873
5490
  }
@@ -3877,15 +5494,15 @@ function validateListInstantPageEditHistoryRequest(input) {
3877
5494
  return { isValid: false, errors: ["D\u1EEF li\u1EC7u y\xEAu c\u1EA7u l\u1EA5y l\u1ECBch s\u1EED ch\u1EC9nh s\u1EEDa ph\u1EA3i l\xE0 m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng (object)."] };
3878
5495
  }
3879
5496
  const obj = input;
3880
- if (!isPositiveInteger(obj.instantPageId)) {
5497
+ if (!isPositiveInteger2(obj.instantPageId)) {
3881
5498
  errors.push("Tr\u01B0\u1EDDng 'instantPageId' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn d\u01B0\u01A1ng (> 0).");
3882
5499
  }
3883
5500
  let limit = void 0;
3884
5501
  if (obj.limit !== void 0 && obj.limit !== null) {
3885
- if (!isPositiveInteger(obj.limit)) {
5502
+ if (!isPositiveInteger2(obj.limit)) {
3886
5503
  errors.push("Tr\u01B0\u1EDDng 'limit' n\u1EBFu c\xF3 ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn >= 1.");
3887
5504
  } else {
3888
- limit = toPositiveInteger(obj.limit);
5505
+ limit = toPositiveInteger2(obj.limit);
3889
5506
  }
3890
5507
  }
3891
5508
  let offset = void 0;
@@ -3901,7 +5518,7 @@ function validateListInstantPageEditHistoryRequest(input) {
3901
5518
  isValid: errors.length === 0,
3902
5519
  errors,
3903
5520
  data: errors.length === 0 ? {
3904
- instantPageId: toPositiveInteger(obj.instantPageId),
5521
+ instantPageId: toPositiveInteger2(obj.instantPageId),
3905
5522
  ...limit !== void 0 ? { limit } : {},
3906
5523
  ...offset !== void 0 ? { offset } : {}
3907
5524
  } : void 0
@@ -3913,13 +5530,13 @@ function validateListInstantPageFormRecordsRequest(input) {
3913
5530
  return { isValid: false, errors: ["D\u1EEF li\u1EC7u y\xEAu c\u1EA7u t\u1EA3i b\u1EA3n ghi form ph\u1EA3i l\xE0 m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng (object)."] };
3914
5531
  }
3915
5532
  const obj = input;
3916
- if (!isPositiveInteger(obj.instantPageId)) {
5533
+ if (!isPositiveInteger2(obj.instantPageId)) {
3917
5534
  errors.push("Tr\u01B0\u1EDDng 'instantPageId' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn d\u01B0\u01A1ng (> 0).");
3918
5535
  }
3919
5536
  return {
3920
5537
  isValid: errors.length === 0,
3921
5538
  errors,
3922
- data: errors.length === 0 ? { instantPageId: toPositiveInteger(obj.instantPageId) } : void 0
5539
+ data: errors.length === 0 ? { instantPageId: toPositiveInteger2(obj.instantPageId) } : void 0
3923
5540
  };
3924
5541
  }
3925
5542
  function validateListInstantPageSharesRequest(input) {
@@ -3928,13 +5545,13 @@ function validateListInstantPageSharesRequest(input) {
3928
5545
  return { isValid: false, errors: ["D\u1EEF li\u1EC7u y\xEAu c\u1EA7u l\u1EA5y danh s\xE1ch ng\u01B0\u1EDDi \u0111\u01B0\u1EE3c chia s\u1EBB ph\u1EA3i l\xE0 m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng (object)."] };
3929
5546
  }
3930
5547
  const obj = input;
3931
- if (!isPositiveInteger(obj.instantPageId)) {
5548
+ if (!isPositiveInteger2(obj.instantPageId)) {
3932
5549
  errors.push("Tr\u01B0\u1EDDng 'instantPageId' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn d\u01B0\u01A1ng (> 0).");
3933
5550
  }
3934
5551
  return {
3935
5552
  isValid: errors.length === 0,
3936
5553
  errors,
3937
- data: errors.length === 0 ? { instantPageId: toPositiveInteger(obj.instantPageId) } : void 0
5554
+ data: errors.length === 0 ? { instantPageId: toPositiveInteger2(obj.instantPageId) } : void 0
3938
5555
  };
3939
5556
  }
3940
5557
  function validateListInstantPageUsersRequest(input) {
@@ -3960,10 +5577,10 @@ function validateSearchInstantPagesRequest(input) {
3960
5577
  const obj = input;
3961
5578
  const data = {};
3962
5579
  if (obj.id !== void 0 && obj.id !== null && obj.id !== "") {
3963
- if (!isPositiveInteger(obj.id)) {
5580
+ if (!isPositiveInteger2(obj.id)) {
3964
5581
  errors.push("B\u1ED9 l\u1ECDc 'id' n\u1EBFu c\xF3 ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn d\u01B0\u01A1ng (> 0).");
3965
5582
  } else {
3966
- data.id = toPositiveInteger(obj.id);
5583
+ data.id = toPositiveInteger2(obj.id);
3967
5584
  }
3968
5585
  }
3969
5586
  if (obj.name !== void 0 && obj.name !== null) {
@@ -3994,10 +5611,10 @@ function validateUpdateInstantPageRequest(input) {
3994
5611
  }
3995
5612
  const obj = input;
3996
5613
  const instantPageId = obj.instantPageId ?? obj.id;
3997
- if (!isPositiveInteger(instantPageId)) {
5614
+ if (!isPositiveInteger2(instantPageId)) {
3998
5615
  errors.push("Tr\u01B0\u1EDDng 'instantPageId' (ho\u1EB7c 'id') l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn d\u01B0\u01A1ng (> 0).");
3999
5616
  }
4000
- const numericId = toPositiveInteger(instantPageId);
5617
+ const numericId = toPositiveInteger2(instantPageId);
4001
5618
  const data = {
4002
5619
  instantPageId: numericId,
4003
5620
  id: numericId
@@ -4028,7 +5645,7 @@ function validateUpdateInstantPageRequest(input) {
4028
5645
  if (obj.status !== void 0 && obj.status !== null) {
4029
5646
  const st = Number(obj.status);
4030
5647
  if (![0, 1, 2, 3].includes(st)) {
4031
- errors.push("Tr\u01B0\u1EDDng 'status' ph\u1EA3i l\xE0 m\u1ED9t trong c\xE1c m\xE3: 0 (B\u1EA3n sao m\u1EDBi), 1 (B\u1EA3n nh\xE1p), 2 (\u0110\xE3 xu\u1EA5t b\u1EA3n), 3 (L\u01B0u tr\u1EEF).");
5648
+ errors.push("Tr\u01B0\u1EDDng 'status' ph\u1EA3i l\xE0 m\u1ED9t trong c\xE1c m\xE3: 0 (B\u1EA3n sao m\u1EDBi t\u1EA1o ch\u01B0a l\u01B0u), 1 (\u0110ang ho\u1EA1t \u0111\u1ED9ng / \u0110\xE3 xu\u1EA5t b\u1EA3n), 3 (\u0110\xE3 k\u1EBFt th\xFAc / L\u01B0u tr\u1EEF).");
4032
5649
  } else {
4033
5650
  data.status = st;
4034
5651
  }
@@ -4091,7 +5708,7 @@ function validateListInstantPageLeadsRequest(input) {
4091
5708
  errors.push("Tr\u01B0\u1EDDng 'ids' kh\xF4ng ch\u1EE9a b\u1EA5t k\u1EF3 ID h\u1EE3p l\u1EC7 n\xE0o.");
4092
5709
  } else {
4093
5710
  for (const id of idParts) {
4094
- if (!isPositiveInteger(id)) {
5711
+ if (!isPositiveInteger2(id)) {
4095
5712
  errors.push(`M\xE3 trang '${id}' trong danh s\xE1ch 'ids' kh\xF4ng ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn d\u01B0\u01A1ng h\u1EE3p l\u1EC7.`);
4096
5713
  }
4097
5714
  }
@@ -4115,7 +5732,7 @@ function validateUpsertInstantPageFormRequest(input) {
4115
5732
  return { isValid: false, errors: ["D\u1EEF li\u1EC7u c\u1EA5u h\xECnh bi\u1EC3u m\u1EABu Instant Page ph\u1EA3i l\xE0 m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng."] };
4116
5733
  }
4117
5734
  const obj = input;
4118
- if (!isPositiveInteger(obj.instantPageId)) {
5735
+ if (!isPositiveInteger2(obj.instantPageId)) {
4119
5736
  errors.push("Tr\u01B0\u1EDDng 'instantPageId' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn d\u01B0\u01A1ng (> 0).");
4120
5737
  }
4121
5738
  if (!obj.oaId || typeof obj.oaId !== "string" || !/^\d+$/.test(obj.oaId.trim())) {
@@ -4168,7 +5785,7 @@ function validateUpsertInstantPageFormRequest(input) {
4168
5785
  }
4169
5786
  }
4170
5787
  const data = {
4171
- instantPageId: toPositiveInteger(obj.instantPageId),
5788
+ instantPageId: toPositiveInteger2(obj.instantPageId),
4172
5789
  oaId: String(obj.oaId).trim(),
4173
5790
  formName: String(obj.formName).trim(),
4174
5791
  questions: obj.questions ?? [],
@@ -4936,110 +6553,6 @@ var ZaloAdsIntegrationManager = class {
4936
6553
  }
4937
6554
  };
4938
6555
 
4939
- // src/dtos/ads.dto.ts
4940
- var ZaloAdsFlowChildMessageDto = class {
4941
- /** Mẫu Zalo đã xác minh dùng 8 cho tin nhắn văn bản trong nhánh. */
4942
- type;
4943
- /** Nội dung phản hồi trong nhánh. */
4944
- text;
4945
- };
4946
- var ZaloAdsFlowButtonDto = class {
4947
- /** 3 = Gửi tin nhắn vào nhánh hội thoại; 10 = Mở website; 12 = Thực hiện cuộc gọi. */
4948
- type;
4949
- /** Nhãn nút hiển thị cho người dùng. */
4950
- text;
4951
- /** URL website; bắt buộc với type 10. */
4952
- url;
4953
- /** Cờ của nút website; dùng true với type 10. */
4954
- editable;
4955
- /** Số hotline, bắt buộc khi type là 12. */
4956
- phone;
4957
- /** Nhánh tin nhắn, bắt buộc khi type là 3. Với type 10 hoặc 12, để null hoặc bỏ qua. */
4958
- messages;
4959
- };
4960
- var ZaloAdsFlowMessageDto = class {
4961
- /** 1 = Tin nhắn văn bản; 2 = Tin nhắn kèm hình ảnh. */
4962
- type;
4963
- /** Nội dung tin nhắn, tối đa 1961 ký tự. Hỗ trợ biến: {{user_name}}, {{page_name}}, {{user_gender}}, {{user_id}}, {{page_id}}, {{date}}, {{datetime}}. */
4964
- text;
4965
- /** URL media hoặc null với tin nhắn văn bản thuần. Bắt buộc và không được null khi type = 2. */
4966
- url;
4967
- /** Các nút đi kèm tin nhắn. */
4968
- buttons;
4969
- };
4970
- var ZaloAdsCreateFlowRequest = class {
4971
- /** ID Official Account sở hữu kịch bản. */
4972
- oaId;
4973
- /** Luôn null khi tạo kịch bản mới. */
4974
- id;
4975
- /** Tên kịch bản, tối đa 33 ký tự theo giao diện Zalo Ads. */
4976
- name;
4977
- /** Các tin nhắn được gửi theo thứ tự trong kịch bản. */
4978
- messages;
4979
- };
4980
- var ZaloAdsCreateFlowResponse = class {
4981
- /** 0 khi tạo thành công. */
4982
- code;
4983
- /** ID kịch bản mới, truyền vào data.ZaloFlowId khi cập nhật quảng cáo Tin nhắn. */
4984
- data;
4985
- };
4986
- var ZaloAdsUpdateVideoAdRequest = class {
4987
- data;
4988
- est;
4989
- isBoostAd;
4990
- stt;
4991
- };
4992
- var ZaloAdsUpdateVideoAdResponse = class {
4993
- code;
4994
- msg;
4995
- data;
4996
- };
4997
- var ZaloAdsCreatePostCampaignRequest = class {
4998
- /** Cấu hình chiến dịch Bài viết (object hoặc chuỗi JSON). */
4999
- data;
5000
- };
5001
- var ZaloAdsCreatePostCampaignResponse = class {
5002
- code;
5003
- /** Chuỗi ID quảng cáo mới trong response Zalo Ads. */
5004
- msg;
5005
- data;
5006
- };
5007
- var ZaloAdsMessageAdUpdateDataDto = class {
5008
- AdId;
5009
- CampaignId;
5010
- MemberId;
5011
- /** Phiên bản lạc quan lấy từ bản quảng cáo hiện tại. */
5012
- RowVersion;
5013
- AdName;
5014
- /** 20 (hoặc 19) là quảng cáo Tin nhắn. */
5015
- Type;
5016
- Settings;
5017
- Status;
5018
- StartDate;
5019
- EndDate;
5020
- /** ID kịch bản, lấy từ createFlow hoặc listFlowsByOfficialAccount. */
5021
- ZaloFlowId;
5022
- ZaloPageId;
5023
- ZaloFormId;
5024
- ConversionId;
5025
- Report;
5026
- };
5027
- var ZaloAdsUpdateMessageAdRequest = class {
5028
- /** Payload quảng cáo đầy đủ (object hoặc chuỗi JSON); service tự tuần tự hóa thành field form data. */
5029
- data;
5030
- /** Tham số UI phụ trợ; capture Zalo Ads có giá trị literal "undefined". */
5031
- est;
5032
- /** 0 là quảng cáo thông thường, 1 là boost ad. */
5033
- isBoostAd;
5034
- /** Trạng thái thao tác của giao diện; mẫu đã ghi nhận 0. */
5035
- stt;
5036
- };
5037
- var ZaloAdsUpdateMessageAdResponse = class {
5038
- msg;
5039
- code;
5040
- data;
5041
- };
5042
-
5043
6556
  // src/dtos/instant-pages.dto.ts
5044
6557
  var ZaloInstantPageBlockType = /* @__PURE__ */ ((ZaloInstantPageBlockType2) => {
5045
6558
  ZaloInstantPageBlockType2[ZaloInstantPageBlockType2["CAROUSEL_SLIDER"] = 1] = "CAROUSEL_SLIDER";
@@ -5064,21 +6577,28 @@ var ZaloInstantPageBlockType = /* @__PURE__ */ ((ZaloInstantPageBlockType2) => {
5064
6577
  })(ZaloInstantPageBlockType || {});
5065
6578
  // Annotate the CommonJS export names for ESM import in node:
5066
6579
  0 && (module.exports = {
6580
+ ALLOWED_CTAS_PER_AD_TYPE,
5067
6581
  ALL_ZALO_ADS_DOMAINS,
5068
6582
  MemoryZaloSessionStore,
5069
6583
  RedisZaloSessionStore,
5070
6584
  TieredZaloSessionStore,
6585
+ VALID_AD_TYPES,
6586
+ VALID_CAMPAIGN_TYPES,
5071
6587
  ZaloAccountService,
5072
6588
  ZaloAdsAccountPool,
6589
+ ZaloAdsActionType,
6590
+ ZaloAdsAgeRangeId,
5073
6591
  ZaloAdsCreateFlowRequest,
5074
6592
  ZaloAdsCreateFlowResponse,
5075
6593
  ZaloAdsCreatePostCampaignRequest,
5076
6594
  ZaloAdsCreatePostCampaignResponse,
6595
+ ZaloAdsDeliveryType,
5077
6596
  ZaloAdsFlowButtonDto,
5078
6597
  ZaloAdsFlowChildMessageDto,
5079
6598
  ZaloAdsFlowMessageDto,
5080
6599
  ZaloAdsIntegrationManager,
5081
6600
  ZaloAdsMessageAdUpdateDataDto,
6601
+ ZaloAdsOsId,
5082
6602
  ZaloAdsSdk,
5083
6603
  ZaloAdsService,
5084
6604
  ZaloAdsUpdateMessageAdRequest,
@@ -5086,13 +6606,17 @@ var ZaloInstantPageBlockType = /* @__PURE__ */ ((ZaloInstantPageBlockType2) => {
5086
6606
  ZaloAdsUpdateVideoAdRequest,
5087
6607
  ZaloAdsUpdateVideoAdResponse,
5088
6608
  ZaloAudiencesService,
6609
+ ZaloAudiencesValidator,
5089
6610
  ZaloAuthManager,
5090
6611
  ZaloAutomatedRulesService,
5091
6612
  ZaloCampaignsService,
6613
+ ZaloCampaignsValidator,
5092
6614
  ZaloChatWidgetService,
5093
6615
  ZaloConversionsService,
5094
6616
  ZaloFlowsService,
6617
+ ZaloFlowsValidator,
5095
6618
  ZaloFormsService,
6619
+ ZaloFormsValidator,
5096
6620
  ZaloInstantPageBlockType,
5097
6621
  ZaloInstantPagesService,
5098
6622
  ZaloInstantPagesValidator,
@@ -5108,9 +6632,24 @@ var ZaloInstantPageBlockType = /* @__PURE__ */ ((ZaloInstantPageBlockType2) => {
5108
6632
  defaultSharedMemorySessionStore,
5109
6633
  deriveAccountKeyFromZpsid,
5110
6634
  parseZaloCookieInput,
6635
+ validateChangeCampaignStatusParams,
5111
6636
  validateCloneInstantPageRequest,
6637
+ validateCreateCampaignPayload,
6638
+ validateCreateFlowRequest,
6639
+ validateCreateFormEventAudienceRequest,
6640
+ validateCreateFormRequest,
6641
+ validateCreateLookalikeAudienceRequest,
6642
+ validateCreateMessageOaEventAudienceRequest,
6643
+ validateCreateMessagePersonalEventAudienceRequest,
6644
+ validateCreatePhoneAudienceRequest,
6645
+ validateCreateSavedAudienceRequest,
6646
+ validateDuplicateAdParams,
6647
+ validateEstimateAudienceRequest,
5112
6648
  validateGetInstantPageDetailRequest,
5113
6649
  validateGetInstantPageSharedUserRequest,
6650
+ validateListFlowsByOfficialAccountRequest,
6651
+ validateListFormLeadsRequest,
6652
+ validateListFormsByOfficialAccountRequest,
5114
6653
  validateListInstantPageEditHistoryRequest,
5115
6654
  validateListInstantPageFormRecordsRequest,
5116
6655
  validateListInstantPageLeadsRequest,
@@ -5118,7 +6657,10 @@ var ZaloInstantPageBlockType = /* @__PURE__ */ ((ZaloInstantPageBlockType2) => {
5118
6657
  validateListInstantPageUsersRequest,
5119
6658
  validateListMiniPageTemplatesRequest,
5120
6659
  validateListOfficialAccountsRequest,
6660
+ validateRenameCampaignParams,
5121
6661
  validateSearchInstantPagesRequest,
6662
+ validateUpdateAdPayload,
6663
+ validateUpdateFlowRequest,
5122
6664
  validateUpdateInstantPageRequest,
5123
6665
  validateUpsertInstantPageFormRequest
5124
6666
  });