@redonvn/zalo-ads-sdk 0.2.13 → 0.2.14

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.mjs CHANGED
@@ -930,7 +930,8 @@ var ZaloSdkHttpClient = class {
930
930
  const body = asRecord(input.body);
931
931
  if (bodyType === "json") {
932
932
  headers.set("content-type", headers.get("content-type") ?? "application/json");
933
- init.body = JSON.stringify(body);
933
+ const jsonPayload = input.body !== void 0 ? input.body : body;
934
+ init.body = JSON.stringify(jsonPayload);
934
935
  } else if (bodyType === "urlencoded") {
935
936
  headers.set("content-type", headers.get("content-type") ?? "application/x-www-form-urlencoded;charset=UTF-8");
936
937
  const encoded = new URLSearchParams();
@@ -1046,1742 +1047,2242 @@ async function resolveCookies(auth, context) {
1046
1047
  return { ...auth?.cookies ?? {}, ...await auth?.getCookies?.(context) ?? {} };
1047
1048
  }
1048
1049
 
1049
- // src/dtos/ads.dto.ts
1050
- var ZaloAdsFlowChildMessageDto = class {
1051
- /** Mẫu Zalo đã xác minh dùng 8 cho tin nhắn văn bản trong nhánh. */
1052
- type;
1053
- /** Nội dung phản hồi trong nhánh. */
1054
- text;
1055
- };
1056
- var ZaloAdsFlowButtonDto = class {
1057
- /** 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. */
1058
- type;
1059
- /** Nhãn nút hiển thị cho người dùng. */
1060
- text;
1061
- /** URL website; bắt buộc với type 10. */
1062
- url;
1063
- /** Cờ của nút website; dùng true với type 10. */
1064
- editable;
1065
- /** Số hotline, bắt buộc khi type là 12. */
1066
- phone;
1067
- /** 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. */
1068
- messages;
1069
- };
1070
- var ZaloAdsFlowMessageDto = class {
1071
- /** 1 = Tin nhắn văn bản; 2 = Tin nhắn kèm hình ảnh. */
1072
- type;
1073
- /** 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}}. */
1074
- text;
1075
- /** 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. */
1076
- url;
1077
- /** Các nút đi kèm tin nhắn. */
1078
- buttons;
1079
- };
1080
- var ZaloAdsCreateFlowRequest = class {
1081
- /** ID Official Account sở hữu kịch bản. */
1082
- oaId;
1083
- /** Luôn null khi tạo kịch bản mới. */
1084
- id;
1085
- /** Tên kịch bản, tối đa 33 ký tự theo giao diện Zalo Ads. */
1086
- name;
1087
- /** Các tin nhắn được gửi theo thứ tự trong kịch bản. */
1088
- messages;
1089
- };
1090
- var ZaloAdsCreateFlowResponse = class {
1091
- /** 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). */
1092
- code;
1093
- /** Thông báo lỗi từ Zalo Ads khi code khác 0. */
1094
- msg;
1095
- /** 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. */
1096
- data;
1097
- };
1098
- var ZaloAdsActionType = {
1099
- DAT_NGAY: 1,
1100
- MUA_NGAY: 2,
1101
- THU_NGAY: 3,
1102
- TAI_NGAY: 4,
1103
- XEM_THEM: 5,
1104
- QUAN_TAM_OA: 6,
1105
- NGHE_NGAY: 7,
1106
- CHOI_NGAY: 8,
1107
- DANG_KY: 9,
1108
- GOI_DIEN: 10
1109
- };
1110
- var ZaloAdsAgeRangeId = {
1111
- UNDER_18: 10282,
1112
- FROM_18_TO_24: 10283,
1113
- FROM_25_TO_34: 10284,
1114
- FROM_35_TO_44: 10285,
1115
- FROM_45_TO_54: 10286,
1116
- FROM_55_TO_64: 10287,
1117
- OVER_64: 10288
1118
- };
1119
- var ZaloAdsOsId = {
1120
- ANDROID: 0,
1121
- IOS: 1,
1122
- PC: 3
1123
- };
1124
- var ZaloAdsDeliveryType = {
1125
- STANDARD: 1,
1126
- ACCELERATED: 2
1127
- };
1128
- var ZaloAdsUpdateVideoAdRequest = class {
1129
- data;
1130
- est;
1131
- isBoostAd;
1132
- stt;
1133
- };
1134
- var ZaloAdsUpdateVideoAdResponse = class {
1135
- code;
1136
- msg;
1137
- data;
1138
- };
1139
- var ZaloAdsCreatePostCampaignRequest = class {
1140
- /** Cấu hình chiến dịch Bài viết (object hoặc chuỗi JSON). */
1141
- data;
1142
- };
1143
- var ZaloAdsCreatePostCampaignResponse = class {
1144
- code;
1145
- /** Chuỗi ID quảng cáo mới trong response Zalo Ads. */
1146
- msg;
1147
- data;
1148
- };
1149
- var ZaloAdsMessageAdUpdateDataDto = class {
1150
- AdId;
1151
- CampaignId;
1152
- MemberId;
1153
- /** Phiên bản lạc quan lấy từ bản quảng cáo hiện tại. */
1154
- RowVersion;
1155
- AdName;
1156
- /** 20 (hoặc 19) là quảng cáo Tin nhắn. */
1157
- Type;
1158
- Settings;
1159
- Status;
1160
- StartDate;
1161
- EndDate;
1162
- /** ID kịch bản, lấy từ createFlow hoặc listFlowsByOfficialAccount. */
1163
- ZaloFlowId;
1164
- ZaloPageId;
1165
- ZaloFormId;
1166
- ConversionId;
1167
- Report;
1168
- };
1169
- var ZaloAdsUpdateMessageAdRequest = class {
1170
- /** Payload quảng cáo đầy đủ (object hoặc chuỗi JSON); service tự tuần tự hóa thành field form data. */
1171
- data;
1172
- /** Tham số UI phụ trợ; capture Zalo Ads có giá trị literal "undefined". */
1173
- est;
1174
- /** 0 là quảng cáo thông thường, 1 là boost ad. */
1175
- isBoostAd;
1176
- /** Trạng thái thao tác của giao diện; mẫu đã ghi nhận 0. */
1177
- stt;
1178
- };
1179
- var ZaloAdsUpdateMessageAdResponse = class {
1180
- msg;
1181
- code;
1182
- data;
1183
- };
1184
-
1185
- // src/validators/campaigns.validator.ts
1186
- var VALID_CAMPAIGN_TYPES = {
1187
- WEBSITE: 6,
1188
- FORM: 17,
1189
- MESSAGE: 18,
1190
- OA: 3,
1191
- VIDEO: 14,
1192
- COMMERCE: 22,
1193
- ARTICLE: 4,
1194
- DISPLAY: 20
1195
- };
1196
- var VALID_AD_TYPES = {
1197
- WEBSITE: 5,
1198
- FORM: 18,
1199
- MESSAGE: 30,
1200
- OA: 2,
1201
- VIDEO: 11,
1202
- COMMERCE: 28,
1203
- // Server trả về 28 (không phải 23)
1204
- ARTICLE: 3,
1205
- DISPLAY: 21
1206
- };
1207
- var ALLOWED_CTAS_PER_AD_TYPE = {
1208
- // Website (Type 5): 9 CTAs
1209
- [VALID_AD_TYPES.WEBSITE]: [
1210
- ZaloAdsActionType.DAT_NGAY,
1211
- ZaloAdsActionType.MUA_NGAY,
1212
- ZaloAdsActionType.THU_NGAY,
1213
- ZaloAdsActionType.TAI_NGAY,
1214
- ZaloAdsActionType.XEM_THEM,
1215
- ZaloAdsActionType.NGHE_NGAY,
1216
- ZaloAdsActionType.CHOI_NGAY,
1217
- ZaloAdsActionType.DANG_KY,
1218
- ZaloAdsActionType.GOI_DIEN
1219
- ],
1220
- // Video (Type 11): 8 CTAs
1221
- [VALID_AD_TYPES.VIDEO]: [
1222
- ZaloAdsActionType.DAT_NGAY,
1223
- ZaloAdsActionType.MUA_NGAY,
1224
- ZaloAdsActionType.THU_NGAY,
1225
- ZaloAdsActionType.TAI_NGAY,
1226
- ZaloAdsActionType.XEM_THEM,
1227
- ZaloAdsActionType.NGHE_NGAY,
1228
- ZaloAdsActionType.CHOI_NGAY,
1229
- ZaloAdsActionType.DANG_KY
1230
- ],
1231
- // Article (Type 3): 7 CTAs
1232
- [VALID_AD_TYPES.ARTICLE]: [
1233
- ZaloAdsActionType.DAT_NGAY,
1234
- ZaloAdsActionType.MUA_NGAY,
1235
- ZaloAdsActionType.THU_NGAY,
1236
- ZaloAdsActionType.TAI_NGAY,
1237
- ZaloAdsActionType.XEM_THEM,
1238
- ZaloAdsActionType.CHOI_NGAY,
1239
- ZaloAdsActionType.DANG_KY
1240
- ],
1241
- // Form (Type 18): 5 CTAs
1242
- [VALID_AD_TYPES.FORM]: [
1243
- ZaloAdsActionType.DAT_NGAY,
1244
- ZaloAdsActionType.MUA_NGAY,
1245
- ZaloAdsActionType.THU_NGAY,
1246
- ZaloAdsActionType.XEM_THEM,
1247
- ZaloAdsActionType.DANG_KY
1050
+ // src/validators/audiences.validator.ts
1051
+ var ZALO_REGION_PROVINCE_CODES = {
1052
+ 1: [
1053
+ "VN58",
1054
+ "VN44",
1055
+ "VN72",
1056
+ "VN83",
1057
+ "VN50",
1058
+ "VN13",
1059
+ "VN82",
1060
+ "VN70",
1061
+ "VN53",
1062
+ "VN30",
1063
+ "VN74",
1064
+ "VN34",
1065
+ "VN52",
1066
+ "VN79",
1067
+ "VN80",
1068
+ "VN32",
1069
+ "VN71",
1070
+ "VN59",
1071
+ "VN86",
1072
+ "VN05",
1073
+ "VN85",
1074
+ "VN39",
1075
+ "VN35",
1076
+ "VN89",
1077
+ "VN81",
1078
+ "VN92",
1079
+ "VN90",
1080
+ "VN68"
1248
1081
  ],
1249
- // Commerce (Type 28): 3 CTAs
1250
- [VALID_AD_TYPES.COMMERCE]: [
1251
- ZaloAdsActionType.DAT_NGAY,
1252
- ZaloAdsActionType.MUA_NGAY,
1253
- ZaloAdsActionType.XEM_THEM
1082
+ 2: [
1083
+ "VN55",
1084
+ "VN88",
1085
+ "VN47",
1086
+ "VN62",
1087
+ "VN54",
1088
+ "VN61",
1089
+ "VN64",
1090
+ "VN49",
1091
+ "VN63",
1092
+ "VN46",
1093
+ "VN84",
1094
+ "VN66",
1095
+ "VN91",
1096
+ "VN60",
1097
+ "VN23",
1098
+ "VN78"
1254
1099
  ],
1255
- // OA (Type 2): Cố định Quan tâm OA (6)
1256
- [VALID_AD_TYPES.OA]: [ZaloAdsActionType.QUAN_TAM_OA]
1100
+ 3: [
1101
+ "VN87",
1102
+ "VN03",
1103
+ "VN76",
1104
+ "VN43",
1105
+ "VN65",
1106
+ "VN21",
1107
+ "VN24",
1108
+ "VN75",
1109
+ "VN45",
1110
+ "VN67",
1111
+ "VN01",
1112
+ "VN73",
1113
+ "VN77",
1114
+ "VN37",
1115
+ "VN20",
1116
+ "VN09",
1117
+ "VN69",
1118
+ "VN33",
1119
+ "VN93"
1120
+ ]
1257
1121
  };
1258
- function validateCreateCampaignPayload(payload, options = {}) {
1122
+ var ZALO_NEW_REGION_PROVINCE_CODES = {
1123
+ 1: ["VN58", "VN44", "VN83", "VN32", "VN59", "VN13", "VN89", "VN30", "VN74", "VN34", "VN52", "VN05", "VN85", "VN39", "VN81", "VN92", "VN90", "VN68"],
1124
+ 2: ["VN66", "VN88", "VN54", "VN64", "VN49", "VN63", "VN23", "VN78"],
1125
+ 3: ["VN20", "VN87", "VN43", "VN33", "VN01", "VN77", "VN09", "VN69"]
1126
+ };
1127
+ var ZALO_PROVINCE_MERGE_MAPPING = {
1128
+ VN75: { newCode: "VN20", regionId: 3, name: "B\xECnh D\u01B0\u01A1ng (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m H\u1ED3 Ch\xED Minh VN20)" },
1129
+ VN45: { newCode: "VN20", regionId: 3, name: "B\xE0 R\u1ECBa - V\u0169ng T\xE0u (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m H\u1ED3 Ch\xED Minh VN20)" },
1130
+ VN76: { newCode: "VN43", regionId: 3, name: "B\xECnh Ph\u01B0\u1EDBc (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m \u0110\u1ED3ng Nai VN43)" },
1131
+ VN24: { newCode: "VN33", regionId: 3, name: "Long An (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m T\xE2y Ninh VN33)" },
1132
+ VN21: { newCode: "VN01", regionId: 3, name: "Ki\xEAn Giang (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m An Giang VN01)" },
1133
+ VN73: { newCode: "VN77", regionId: 3, name: "B\u1EA1c Li\xEAu (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m C\xE0 Mau VN77)" },
1134
+ VN37: { newCode: "VN09", regionId: 3, name: "Ti\u1EC1n Giang (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m \u0110\u1ED3ng Th\xE1p VN09)" },
1135
+ VN03: { newCode: "VN69", regionId: 3, name: "B\u1EBFn Tre (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m V\u0129nh Long VN69)" },
1136
+ VN67: { newCode: "VN69", regionId: 3, name: "Tr\xE0 Vinh (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m V\u0129nh Long VN69)" },
1137
+ VN65: { newCode: "VN87", regionId: 3, name: "S\xF3c Tr\u0103ng (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m C\u1EA7n Th\u01A1 VN87)" },
1138
+ VN93: { newCode: "VN87", regionId: 3, name: "H\u1EADu Giang (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m C\u1EA7n Th\u01A1 VN87)" },
1139
+ VN61: { newCode: "VN88", regionId: 2, name: "Ph\xFA Y\xEAn (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m \u0110\u1EAFk L\u1EAFk VN88)" },
1140
+ VN60: { newCode: "VN54", regionId: 2, name: "Ninh Thu\u1EADn (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Kh\xE1nh H\xF2a VN54)" },
1141
+ VN62: { newCode: "VN64", regionId: 2, name: "Qu\u1EA3ng B\xECnh (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Qu\u1EA3ng Tr\u1ECB VN64)" },
1142
+ VN46: { newCode: "VN49", regionId: 2, name: "B\xECnh \u0110\u1ECBnh (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Gia Lai VN49)" },
1143
+ VN55: { newCode: "VN63", regionId: 2, name: "Kon Tum (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Qu\u1EA3ng Ng\xE3i VN63)" },
1144
+ VN47: { newCode: "VN23", regionId: 2, name: "B\xECnh Thu\u1EADn (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m L\xE2m \u0110\u1ED3ng VN23)" },
1145
+ VN91: { newCode: "VN23", regionId: 2, name: "\u0110\u1EAFk N\xF4ng (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m L\xE2m \u0110\u1ED3ng VN23)" },
1146
+ VN84: { newCode: "VN78", regionId: 2, name: "Qu\u1EA3ng Nam (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m \u0110\xE0 N\u1EB5ng VN78)" },
1147
+ VN86: { newCode: "VN83", regionId: 1, name: "Ninh B\xECnh (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Ph\xFA Th\u1ECD VN83)" },
1148
+ VN53: { newCode: "VN83", regionId: 1, name: "B\u1EAFc K\u1EA1n (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Ph\xFA Th\u1ECD VN83)" },
1149
+ VN82: { newCode: "VN59", regionId: 1, name: "B\u1EAFc Giang (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Ninh B\xECnh VN59)" },
1150
+ VN80: { newCode: "VN59", regionId: 1, name: "Ph\xFA Th\u1ECD c\u0169 (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Ninh B\xECnh VN59)" },
1151
+ VN79: { newCode: "VN13", regionId: 1, name: "H\u1EA3i D\u01B0\u01A1ng (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m H\u1EA3i Ph\xF2ng VN13)" },
1152
+ VN71: { newCode: "VN74", regionId: 1, name: "H\u01B0ng Y\xEAn c\u0169 (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m B\u1EAFc Ninh VN74)" },
1153
+ VN72: { newCode: "VN85", regionId: 1, name: "Y\xEAn B\xE1i (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Th\xE1i Nguy\xEAn VN85)" },
1154
+ VN35: { newCode: "VN81", regionId: 1, name: "Th\xE1i B\xECnh (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m H\u01B0ng Y\xEAn VN81)" },
1155
+ VN70: { newCode: "VN90", regionId: 1, name: "V\u0129nh Ph\xFAc (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m L\xE0o Cai VN90)" },
1156
+ VN50: { newCode: "VN68", regionId: 1, name: "H\xF2a B\xECnh (\u0111\xE3 s\xE1p nh\u1EADp v\xE0o c\u1EE5m Tuy\xEAn Quang VN68)" }
1157
+ };
1158
+ function validateCreateSavedAudienceRequest(input) {
1259
1159
  const errors = [];
1260
- const warnings = [];
1261
- if (!payload.name || typeof payload.name !== "string" || !payload.name.trim()) {
1262
- errors.push("name l\xE0 b\u1EAFt bu\u1ED9c v\xE0 kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
1263
- } else if (payload.name.length > 255) {
1264
- errors.push("name kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 255 k\xFD t\u1EF1.");
1160
+ if (!input || typeof input !== "object") {
1161
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
1265
1162
  }
1266
- const validTypes = Object.values(VALID_CAMPAIGN_TYPES);
1267
- if (payload.campaignType === void 0 || payload.campaignType === null) {
1268
- errors.push("campaignType l\xE0 b\u1EAFt bu\u1ED9c.");
1269
- } else if (!validTypes.includes(payload.campaignType)) {
1270
- errors.push(
1271
- `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).`
1272
- );
1163
+ const raw = input;
1164
+ const name = typeof raw.name === "string" ? raw.name.trim() : "";
1165
+ if (!name) {
1166
+ errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' l\xE0 b\u1EAFt bu\u1ED9c.");
1167
+ } else if (name.length < 2 || name.length > 255) {
1168
+ errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
1273
1169
  }
1274
- if (payload.campaignType !== VALID_CAMPAIGN_TYPES.DISPLAY) {
1275
- if (!payload.pageId || payload.pageId <= 0) {
1276
- 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).");
1170
+ let targetingObj;
1171
+ if (typeof raw.targeting === "string") {
1172
+ try {
1173
+ targetingObj = JSON.parse(raw.targeting);
1174
+ } catch {
1175
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
1176
+ targetingObj = {};
1277
1177
  }
1178
+ } else if (raw.targeting && typeof raw.targeting === "object") {
1179
+ targetingObj = raw.targeting;
1278
1180
  } else {
1279
- if (payload.pageId !== -1 && payload.pageId !== 0 && !payload.pageId) {
1280
- warnings.push("Qu\u1EA3ng c\xE1o Display th\u01B0\u1EDDng s\u1EED d\u1EE5ng pageId = -1.");
1181
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c (chu\u1ED7i JSON ho\u1EB7c Object c\u1EA5u h\xECnh targeting).");
1182
+ targetingObj = {};
1183
+ }
1184
+ const gender = typeof targetingObj.Gender === "number" ? targetingObj.Gender : 0;
1185
+ if (![0, 1, 2].includes(gender)) {
1186
+ errors.push("Tr\u01B0\u1EDDng 'Gender' ph\u1EA3i l\xE0 0 (T\u1EA5t c\u1EA3), 1 (Nam), ho\u1EB7c 2 (N\u1EEF).");
1187
+ }
1188
+ const VALID_AGE_RANGES = [10282, 10283, 10284, 10285, 10286, 10287, 10288];
1189
+ const newAgeRanges = Array.isArray(targetingObj.NewAgeRanges) && targetingObj.NewAgeRanges.length > 0 ? targetingObj.NewAgeRanges.map(Number) : VALID_AGE_RANGES;
1190
+ for (const age of newAgeRanges) {
1191
+ if (!VALID_AGE_RANGES.includes(age)) {
1192
+ 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(", ")}.`);
1281
1193
  }
1282
1194
  }
1283
- switch (payload.campaignType) {
1284
- case VALID_CAMPAIGN_TYPES.WEBSITE:
1285
- if (!payload.targetUrl || typeof payload.targetUrl !== "string" || !payload.targetUrl.trim()) {
1286
- errors.push("targetUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Website.");
1287
- } else if (!/^https?:\/\/.+/i.test(payload.targetUrl)) {
1288
- 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://.");
1289
- }
1290
- break;
1291
- case VALID_CAMPAIGN_TYPES.ARTICLE:
1292
- if (!payload.articleId || payload.articleId <= 0) {
1293
- 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).");
1294
- }
1295
- break;
1296
- case VALID_CAMPAIGN_TYPES.COMMERCE:
1297
- if (payload.productId === void 0 || payload.productId === null) {
1298
- 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).");
1299
- }
1300
- break;
1301
- case VALID_CAMPAIGN_TYPES.FORM:
1302
- case VALID_CAMPAIGN_TYPES.MESSAGE:
1303
- break;
1304
- }
1305
- if (payload.budgetType !== void 0 && payload.budgetlimit !== void 0) {
1306
- if (payload.budgetType === 2) {
1307
- if (payload.budgetlimit > 0 && payload.budgetlimit < 6e5) {
1308
- errors.push("Ng\xE2n s\xE1ch cho To\xE0n l\u1ECBch ch\u1EA1y t\u1ED1i thi\u1EC3u l\xE0 600,000 VN\u0110.");
1309
- }
1310
- } else if (payload.budgetType === 1) {
1311
- if (payload.budgetlimit > 0 && payload.budgetlimit < 50) {
1312
- 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.");
1313
- }
1195
+ const VALID_OS = [0, 1, 2, 3];
1196
+ const os = Array.isArray(targetingObj.Os) && targetingObj.Os.length > 0 ? targetingObj.Os.map(Number) : [0, 1, 3];
1197
+ for (const o of os) {
1198
+ if (!VALID_OS.includes(o)) {
1199
+ 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).`);
1314
1200
  }
1315
1201
  }
1316
- if (payload.campaignId && payload.campaignId > 0) {
1317
- if (payload.adId !== 0) {
1318
- 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.");
1202
+ let location = targetingObj.Location;
1203
+ if (!location || typeof location !== "object") {
1204
+ location = {
1205
+ Addresses: [],
1206
+ Cities: [],
1207
+ DistrictTargeting: { Includes: [], Excludes: [] },
1208
+ WardTargeting: { Includes: [], Excludes: [] },
1209
+ IsConvertedToWard: false
1210
+ };
1211
+ } else {
1212
+ const rawWard = location.WardTargeting && typeof location.WardTargeting === "object" ? location.WardTargeting : void 0;
1213
+ const rawDistrict = location.DistrictTargeting && typeof location.DistrictTargeting === "object" ? location.DistrictTargeting : void 0;
1214
+ const baseTargeting = rawWard || rawDistrict || { Includes: [], Excludes: [] };
1215
+ location = {
1216
+ Addresses: Array.isArray(location.Addresses) ? location.Addresses : [],
1217
+ Cities: Array.isArray(location.Cities) ? location.Cities : [],
1218
+ DistrictTargeting: rawDistrict || baseTargeting,
1219
+ WardTargeting: rawWard || baseTargeting,
1220
+ IsConvertedToWard: location.IsConvertedToWard !== void 0 ? Boolean(location.IsConvertedToWard) : false
1221
+ };
1222
+ const includes = location.WardTargeting.Includes || location.DistrictTargeting.Includes;
1223
+ if (includes && !Array.isArray(includes)) {
1224
+ errors.push("Tr\u01B0\u1EDDng 'Location.WardTargeting.Includes' (ho\u1EB7c DistrictTargeting.Includes) ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng khu v\u1EF1c.");
1225
+ } else if (Array.isArray(includes)) {
1226
+ for (const inc of includes) {
1227
+ if (![1, 2, 3].includes(Number(inc.Id))) {
1228
+ 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).`);
1229
+ }
1230
+ if (inc.Provinces && !Array.isArray(inc.Provinces)) {
1231
+ 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.`);
1232
+ } else if (Array.isArray(inc.Provinces)) {
1233
+ for (const prov of inc.Provinces) {
1234
+ if (!prov.Id || typeof prov.Id !== "string") {
1235
+ errors.push(`M\xE3 t\u1EC9nh 'Id' (${JSON.stringify(prov)}) trong v\xF9ng mi\u1EC1n ${inc.Id} ph\u1EA3i l\xE0 chu\u1ED7i h\u1EE3p l\u1EC7 (v\xED d\u1EE5: 'VN44', 'VN20').`);
1236
+ } else {
1237
+ const mergeInfo = ZALO_PROVINCE_MERGE_MAPPING[prov.Id];
1238
+ if (mergeInfo) {
1239
+ errors.push(
1240
+ `M\xE3 t\u1EC9nh '${prov.Id}' (${mergeInfo.name}) \u0111\xE3 \u0111\u01B0\u1EE3c Zalo Ads g\u1ED9p/s\xE1p nh\u1EADp v\xE0o c\u1EE5m m\xE3 '${mergeInfo.newCode}'. Vui l\xF2ng s\u1EED d\u1EE5ng m\xE3 c\u1EE5m '${mergeInfo.newCode}' trong WardTargeting, n\u1EBFu kh\xF4ng giao di\u1EC7n Zalo Ads Web s\u1EBD b\xE1o l\u1ED7i \u0111\u1ECF 'Invalid wards params'.`
1241
+ );
1242
+ } else {
1243
+ const validNewRegionProvs = ZALO_NEW_REGION_PROVINCE_CODES[Number(inc.Id)] || [];
1244
+ if (!validNewRegionProvs.includes(prov.Id)) {
1245
+ const actualRegion = Object.keys(ZALO_NEW_REGION_PROVINCE_CODES).find((r) => ZALO_NEW_REGION_PROVINCE_CODES[Number(r)].includes(prov.Id));
1246
+ errors.push(
1247
+ `M\xE3 t\u1EC9nh '${prov.Id}' kh\xF4ng n\u1EB1m trong 34 C\u1EE5m T\u1EC9nh/Th\xE0nh m\u1EDBi c\u1EE7a V\xF9ng ${inc.Id} tr\xEAn Zalo Ads (s\u1EBD g\xE2y l\u1ED7i 'Invalid wards params' tr\xEAn UI). ` + (actualRegion ? `M\xE3 n\xE0y thu\u1ED9c V\xF9ng ${actualRegion}. ` : "")
1248
+ );
1249
+ }
1250
+ }
1251
+ }
1252
+ if (prov.Districts && !Array.isArray(prov.Districts)) {
1253
+ errors.push(`Tr\u01B0\u1EDDng 'Districts' c\u1EE7a t\u1EC9nh ${prov.Id} ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng (ho\u1EB7c [] khi ch\u1ECDn c\u1EA3 t\u1EC9nh).`);
1254
+ }
1255
+ }
1256
+ }
1257
+ }
1319
1258
  }
1320
1259
  }
1260
+ const finalTargeting = {
1261
+ ...targetingObj,
1262
+ CustomAudienceId: 0,
1263
+ Gender: gender,
1264
+ NewAgeRanges: newAgeRanges,
1265
+ Os: os,
1266
+ Location: location
1267
+ };
1321
1268
  return {
1322
1269
  isValid: errors.length === 0,
1323
1270
  errors,
1324
- warnings
1271
+ data: errors.length === 0 ? {
1272
+ name,
1273
+ caType: 1,
1274
+ targeting: JSON.stringify(finalTargeting)
1275
+ } : void 0
1325
1276
  };
1326
1277
  }
1327
- function validateUpdateAdPayload(payload, options = {}) {
1278
+ function validateCreatePhoneAudienceRequest(input) {
1328
1279
  const errors = [];
1329
- const warnings = [];
1330
- if (!payload.AdId || payload.AdId <= 0) {
1331
- errors.push("AdId l\xE0 b\u1EAFt bu\u1ED9c (ph\u1EA3i > 0).");
1332
- }
1333
- if (!payload.CampaignId || payload.CampaignId <= 0) {
1334
- errors.push("CampaignId l\xE0 b\u1EAFt bu\u1ED9c (ph\u1EA3i > 0).");
1280
+ if (!input || typeof input !== "object") {
1281
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
1335
1282
  }
1336
- if (!payload.AdName || !payload.AdName.trim()) {
1337
- errors.push("AdName l\xE0 b\u1EAFt bu\u1ED9c v\xE0 kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
1338
- } else if (payload.AdName.length > 255) {
1339
- errors.push(`AdName qu\xE1 d\xE0i (${payload.AdName.length}/255 k\xFD t\u1EF1).`);
1283
+ const raw = input;
1284
+ const name = typeof raw.name === "string" ? raw.name.trim() : "";
1285
+ if (!name || name.length < 2 || name.length > 255) {
1286
+ errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
1340
1287
  }
1341
- const adInfo = payload.Settings?.AdInfo;
1342
- if (!adInfo) {
1343
- errors.push("Settings.AdInfo l\xE0 b\u1EAFt bu\u1ED9c.");
1344
- } else {
1345
- if (!adInfo.Caption || !adInfo.Caption.trim()) {
1346
- errors.push("Settings.AdInfo.Caption l\xE0 b\u1EAFt bu\u1ED9c.");
1347
- } else {
1348
- const captionLen = adInfo.Caption.trim().length;
1349
- if (captionLen < 35) {
1350
- errors.push(`Settings.AdInfo.Caption qu\xE1 ng\u1EAFn (${captionLen}/35 k\xFD t\u1EF1 t\u1ED1i thi\u1EC3u).`);
1351
- } else if (captionLen > 90) {
1352
- errors.push(`Settings.AdInfo.Caption qu\xE1 d\xE0i (${captionLen}/90 k\xFD t\u1EF1 t\u1ED1i \u0111a).`);
1353
- }
1354
- }
1355
- if (adInfo.MoreInfo && adInfo.MoreInfo.trim()) {
1356
- const moreInfoLen = adInfo.MoreInfo.trim().length;
1357
- if (moreInfoLen < 90) {
1358
- 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}).`);
1359
- } else if (moreInfoLen > 2e3) {
1360
- 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}).`);
1361
- }
1362
- }
1363
- if (adInfo.Action !== void 0 && payload.Type) {
1364
- const allowedCtas = ALLOWED_CTAS_PER_AD_TYPE[payload.Type];
1365
- if (allowedCtas && !allowedCtas.includes(adInfo.Action)) {
1366
- warnings.push(
1367
- `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}.`
1368
- );
1369
- }
1288
+ let targetingObj = {};
1289
+ if (typeof raw.targeting === "string") {
1290
+ try {
1291
+ targetingObj = JSON.parse(raw.targeting);
1292
+ } catch {
1293
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
1370
1294
  }
1371
- }
1372
- const price = payload.Settings?.Price;
1373
- if (!price) {
1374
- errors.push("Settings.Price l\xE0 b\u1EAFt bu\u1ED9c.");
1295
+ } else if (raw.targeting && typeof raw.targeting === "object") {
1296
+ targetingObj = raw.targeting;
1375
1297
  } else {
1376
- if (payload.Type === VALID_AD_TYPES.WEBSITE) {
1377
- if (price.Type !== 1) {
1378
- errors.push(
1379
- "\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."
1380
- );
1381
- }
1382
- if (price.LimitType === 1) {
1383
- errors.push(
1384
- "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)."
1385
- );
1386
- }
1387
- } 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) {
1388
- if (price.Type !== 2) {
1389
- errors.push(
1390
- `\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).`
1391
- );
1392
- }
1393
- }
1394
- if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 50) {
1395
- 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.");
1396
- }
1298
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c.");
1397
1299
  }
1398
- const targeting = payload.Settings?.Targeting;
1399
- if (targeting) {
1400
- if (targeting.AgeRanges && targeting.AgeRanges.length > 0) {
1401
- const validAges = Object.values(ZaloAdsAgeRangeId);
1402
- const invalidAges = targeting.AgeRanges.filter((a) => !validAges.includes(a));
1403
- if (invalidAges.length > 0) {
1404
- errors.push(`M\xE3 kho\u1EA3ng tu\u1ED5i kh\xF4ng h\u1EE3p l\u1EC7: ${invalidAges.join(", ")}. H\u1EE3p l\u1EC7: ${validAges.join(", ")}.`);
1405
- }
1406
- }
1407
- if (targeting.OsTypes && targeting.OsTypes.length > 0) {
1408
- const validOs = Object.values(ZaloAdsOsId);
1409
- const invalidOs = targeting.OsTypes.filter((os) => !validOs.includes(os));
1410
- if (invalidOs.length > 0) {
1411
- 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).`);
1412
- }
1413
- }
1414
- const deliveryType = payload.Settings?.DeliveryType;
1415
- if (deliveryType !== void 0 && deliveryType !== 1 && deliveryType !== 2) {
1416
- warnings.push("DeliveryType n\xEAn l\xE0 1 (Ti\xEAu chu\u1EA9n) ho\u1EB7c 2 (T\u0103ng t\u1ED1c).");
1417
- }
1300
+ const path = typeof targetingObj.Path === "string" ? targetingObj.Path.trim() : "";
1301
+ if (!path) {
1302
+ errors.push("Tr\u01B0\u1EDDng 'Path' (URL file .txt sau khi upload) l\xE0 b\u1EAFt bu\u1ED9c.");
1418
1303
  }
1419
- if (payload.Type === VALID_AD_TYPES.FORM) {
1420
- if (!payload.ZaloFormId || !payload.ZaloFormId.trim()) {
1421
- errors.push("ZaloFormId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Form (Ad Type 18).");
1422
- }
1423
- } else if (payload.Type === VALID_AD_TYPES.MESSAGE) {
1424
- if (!payload.Settings?.Image?.LogoUrl) {
1425
- 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).");
1426
- }
1427
- if (!payload.ZaloFlowId && !payload.MiniPageId) {
1428
- 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).");
1429
- }
1430
- } else if (payload.Type === VALID_AD_TYPES.COMMERCE) {
1431
- if (!payload.MiniPageId || payload.MiniPageId <= 0) {
1432
- 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).");
1433
- }
1434
- } else if (payload.Type === VALID_AD_TYPES.VIDEO) {
1435
- if (!payload.ZaloVideoId && !payload.Settings?.Image?.VideoUrl) {
1436
- 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).");
1437
- }
1438
- if (payload.Settings?.Image?.VideoUrl && !payload.Settings.Image.VideoUrl.includes("zascdn.me")) {
1439
- warnings.push("VideoUrl n\xEAn l\xE0 \u0111\u01B0\u1EDDng d\u1EABn CDN ch\xEDnh th\u1EE9c c\u1EE7a Zalo Ads (*.zascdn.me).");
1440
- }
1441
- } else if (payload.Type === VALID_AD_TYPES.ARTICLE) {
1442
- if (!payload.ZaloFeedId && !payload.articleId) {
1443
- 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).");
1444
- }
1304
+ const total = typeof targetingObj.Total === "number" ? targetingObj.Total : 0;
1305
+ if (total <= 0) {
1306
+ errors.push("Tr\u01B0\u1EDDng 'Total' (s\u1ED1 l\u01B0\u1EE3ng S\u0110T trong file) ph\u1EA3i l\u1EDBn h\u01A1n 0.");
1445
1307
  }
1446
1308
  return {
1447
1309
  isValid: errors.length === 0,
1448
1310
  errors,
1449
- warnings
1311
+ data: errors.length === 0 ? {
1312
+ name,
1313
+ caType: 3,
1314
+ targeting: JSON.stringify({
1315
+ Name: String(targetingObj.Name || "phones.txt"),
1316
+ Path: path,
1317
+ Total: total,
1318
+ ZaloId: Number(targetingObj.ZaloId || 0),
1319
+ OriginAudience: 0
1320
+ })
1321
+ } : void 0
1450
1322
  };
1451
1323
  }
1452
- function validateRenameCampaignParams(params) {
1324
+ function validateCreateLookalikeAudienceRequest(input) {
1453
1325
  const errors = [];
1454
- const warnings = [];
1455
- const id = params.campid || params.campaignId;
1456
- const name = params.newname || params.newName || params.name;
1457
- if (!id || id <= 0) {
1458
- errors.push("ID chi\u1EBFn d\u1ECBch (campid/campaignId) l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i > 0.");
1326
+ if (!input || typeof input !== "object") {
1327
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
1459
1328
  }
1460
- if (!name || !name.trim()) {
1461
- 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.");
1462
- } else if (name.length > 255) {
1463
- errors.push(`T\xEAn chi\u1EBFn d\u1ECBch qu\xE1 d\xE0i (${name.length}/255 k\xFD t\u1EF1).`);
1329
+ const raw = input;
1330
+ const name = typeof raw.name === "string" ? raw.name.trim() : "";
1331
+ if (!name || name.length < 2 || name.length > 255) {
1332
+ errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
1464
1333
  }
1465
- return {
1466
- isValid: errors.length === 0,
1467
- errors,
1468
- warnings
1469
- };
1470
- }
1471
- function validateChangeCampaignStatusParams(params) {
1472
- const errors = [];
1473
- const warnings = [];
1474
- if (!params.campaignId || params.campaignId <= 0) {
1475
- errors.push("campaignId l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i > 0.");
1334
+ let targetingObj = {};
1335
+ if (typeof raw.targeting === "string") {
1336
+ try {
1337
+ targetingObj = JSON.parse(raw.targeting);
1338
+ } catch {
1339
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
1340
+ }
1341
+ } else if (raw.targeting && typeof raw.targeting === "object") {
1342
+ targetingObj = raw.targeting;
1343
+ } else {
1344
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c.");
1476
1345
  }
1477
- if (![1, 2, -2].includes(params.status)) {
1478
- 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).`);
1346
+ const originAudience = Number(targetingObj.OriginAudience);
1347
+ if (!originAudience || originAudience <= 0) {
1348
+ errors.push("Tr\u01B0\u1EDDng 'OriginAudience' (ID nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng S\u0110T g\u1ED1c) l\xE0 b\u1EAFt bu\u1ED9c.");
1479
1349
  }
1480
- if (params.status === 2 && params.isDraft) {
1481
- warnings.push(
1482
- "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)."
1483
- );
1350
+ const total = Number(targetingObj.Total);
1351
+ if (![1e6, 15e5, 2e6].includes(total)) {
1352
+ 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.");
1484
1353
  }
1485
1354
  return {
1486
1355
  isValid: errors.length === 0,
1487
1356
  errors,
1488
- warnings
1357
+ data: errors.length === 0 ? {
1358
+ name,
1359
+ caType: 6,
1360
+ targeting: JSON.stringify({
1361
+ OriginAudience: originAudience,
1362
+ Total: total,
1363
+ Name: String(targetingObj.Name || "Lookalike Audience"),
1364
+ Path: String(targetingObj.Path || "")
1365
+ })
1366
+ } : void 0
1489
1367
  };
1490
1368
  }
1491
- function validateDuplicateAdParams(params) {
1369
+ function validateCreateFormEventAudienceRequest(input) {
1492
1370
  const errors = [];
1493
- const warnings = [];
1494
- const id = params.adid || params.adId;
1495
- if (!id || id <= 0) {
1496
- 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.");
1371
+ if (!input || typeof input !== "object") {
1372
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
1373
+ }
1374
+ const raw = input;
1375
+ const name = typeof raw.name === "string" ? raw.name.trim() : "";
1376
+ if (!name || name.length < 2 || name.length > 255) {
1377
+ errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
1378
+ }
1379
+ let targetingObj = {};
1380
+ if (typeof raw.targeting === "string") {
1381
+ try {
1382
+ targetingObj = JSON.parse(raw.targeting);
1383
+ } catch {
1384
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
1385
+ }
1386
+ } else if (raw.targeting && typeof raw.targeting === "object") {
1387
+ targetingObj = raw.targeting;
1388
+ }
1389
+ const eventType = Number(targetingObj.EventType);
1390
+ if (![1, 2, 3, 4].includes(eventType)) {
1391
+ 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).");
1392
+ }
1393
+ const oaId = typeof targetingObj.OaId === "string" ? targetingObj.OaId.trim() : String(targetingObj.OaId || "");
1394
+ if (!oaId) {
1395
+ errors.push("Tr\u01B0\u1EDDng 'OaId' (d\u1EA1ng chu\u1ED7i c\u1EE7a pageId ho\u1EB7c noisedId) l\xE0 b\u1EAFt bu\u1ED9c.");
1396
+ }
1397
+ const numDays = Number(targetingObj.NumDays);
1398
+ if (isNaN(numDays) || numDays < 1 || numDays > 90) {
1399
+ errors.push("Tr\u01B0\u1EDDng 'NumDays' ph\u1EA3i n\u1EB1m trong kho\u1EA3ng t\u1EEB 1 \u0111\u1EBFn 90 ng\xE0y.");
1400
+ }
1401
+ const formIds = Array.isArray(targetingObj.FormIds) ? targetingObj.FormIds : [];
1402
+ if (formIds.length === 0) {
1403
+ errors.push("Tr\u01B0\u1EDDng 'FormIds' ph\u1EA3i ch\u1EE9a \xEDt nh\u1EA5t 1 ID Form.");
1497
1404
  }
1498
1405
  return {
1499
1406
  isValid: errors.length === 0,
1500
1407
  errors,
1501
- warnings
1408
+ data: errors.length === 0 ? {
1409
+ name,
1410
+ caType: 12,
1411
+ targeting: JSON.stringify({
1412
+ EventType: eventType,
1413
+ OaId: oaId,
1414
+ NumDays: numDays,
1415
+ FormIds: formIds
1416
+ })
1417
+ } : void 0
1502
1418
  };
1503
1419
  }
1504
- var ZaloCampaignsValidator = {
1505
- createCampaign: validateCreateCampaignPayload,
1506
- updateAd: validateUpdateAdPayload,
1507
- renameCampaign: validateRenameCampaignParams,
1508
- changeStatus: validateChangeCampaignStatusParams,
1509
- duplicateAd: validateDuplicateAdParams
1420
+ function validateCreateMessageOaEventAudienceRequest(input) {
1421
+ const errors = [];
1422
+ if (!input || typeof input !== "object") {
1423
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
1424
+ }
1425
+ const raw = input;
1426
+ const name = typeof raw.name === "string" ? raw.name.trim() : "";
1427
+ if (!name || name.length < 2 || name.length > 255) {
1428
+ errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
1429
+ }
1430
+ let targetingObj = {};
1431
+ if (typeof raw.targeting === "string") {
1432
+ try {
1433
+ targetingObj = JSON.parse(raw.targeting);
1434
+ } catch {
1435
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
1436
+ }
1437
+ } else if (raw.targeting && typeof raw.targeting === "object") {
1438
+ targetingObj = raw.targeting;
1439
+ }
1440
+ const eventId = Number(targetingObj.EventId ?? targetingObj.EventType ?? 1);
1441
+ const oaId = typeof targetingObj.OaId === "string" ? targetingObj.OaId.trim() : String(targetingObj.OaId || "");
1442
+ if (!oaId) {
1443
+ errors.push("Tr\u01B0\u1EDDng 'OaId' (chu\u1ED7i pageId ho\u1EB7c noisedId c\u1EE7a OA) l\xE0 b\u1EAFt bu\u1ED9c.");
1444
+ }
1445
+ const numDays = Number(targetingObj.NumDays);
1446
+ if (isNaN(numDays) || numDays < 1 || numDays > 90) {
1447
+ errors.push("Tr\u01B0\u1EDDng 'NumDays' ph\u1EA3i n\u1EB1m trong kho\u1EA3ng t\u1EEB 1 \u0111\u1EBFn 90 ng\xE0y.");
1448
+ }
1449
+ return {
1450
+ isValid: errors.length === 0,
1451
+ errors,
1452
+ data: errors.length === 0 ? {
1453
+ name,
1454
+ caType: 11,
1455
+ targeting: JSON.stringify({
1456
+ EventId: eventId,
1457
+ OaId: oaId,
1458
+ NumDays: numDays
1459
+ })
1460
+ } : void 0
1461
+ };
1462
+ }
1463
+ function validateCreateMessagePersonalEventAudienceRequest(input) {
1464
+ const errors = [];
1465
+ if (!input || typeof input !== "object") {
1466
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
1467
+ }
1468
+ const raw = input;
1469
+ const name = typeof raw.name === "string" ? raw.name.trim() : "";
1470
+ if (!name || name.length < 2 || name.length > 255) {
1471
+ errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
1472
+ }
1473
+ let targetingObj = {};
1474
+ if (typeof raw.targeting === "string") {
1475
+ try {
1476
+ targetingObj = JSON.parse(raw.targeting);
1477
+ } catch {
1478
+ errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
1479
+ }
1480
+ } else if (raw.targeting && typeof raw.targeting === "object") {
1481
+ targetingObj = raw.targeting;
1482
+ }
1483
+ const eventId = Number(targetingObj.EventId ?? targetingObj.EventType ?? 1);
1484
+ if (![1, 2, 3].includes(eventId)) {
1485
+ 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).");
1486
+ }
1487
+ const numDays = Number(targetingObj.NumDays);
1488
+ if (isNaN(numDays) || numDays < 1 || numDays > 90) {
1489
+ errors.push("Tr\u01B0\u1EDDng 'NumDays' ph\u1EA3i n\u1EB1m trong kho\u1EA3ng t\u1EEB 1 \u0111\u1EBFn 90 ng\xE0y.");
1490
+ }
1491
+ const pageIds = Array.isArray(targetingObj.PageIds) ? targetingObj.PageIds.map(String) : [];
1492
+ if (pageIds.length === 0) {
1493
+ errors.push("Tr\u01B0\u1EDDng 'PageIds' ph\u1EA3i ch\u1EE9a \xEDt nh\u1EA5t 1 ID trang c\xE1 nh\xE2n.");
1494
+ }
1495
+ return {
1496
+ isValid: errors.length === 0,
1497
+ errors,
1498
+ data: errors.length === 0 ? {
1499
+ name,
1500
+ caType: 14,
1501
+ targeting: JSON.stringify({
1502
+ EventId: eventId,
1503
+ NumDays: numDays,
1504
+ PageIds: pageIds
1505
+ })
1506
+ } : void 0
1507
+ };
1508
+ }
1509
+ function validateEstimateAudienceRequest(input) {
1510
+ const errors = [];
1511
+ if (!input || typeof input !== "object") {
1512
+ return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
1513
+ }
1514
+ const raw = input;
1515
+ const gender = typeof raw.gender === "number" ? raw.gender : 0;
1516
+ if (![0, 1, 2].includes(gender)) {
1517
+ errors.push("Tr\u01B0\u1EDDng 'gender' ph\u1EA3i l\xE0 0, 1 ho\u1EB7c 2.");
1518
+ }
1519
+ const ageRanges = Array.isArray(raw.ageRanges) && raw.ageRanges.length > 0 ? raw.ageRanges.map(Number) : [10283, 10284, 10285, 10286, 10287];
1520
+ const platforms = Array.isArray(raw.platforms) && raw.platforms.length > 0 ? raw.platforms.map(Number) : [0, 1, 3];
1521
+ const priceType = typeof raw.priceType === "number" ? raw.priceType : 2;
1522
+ const wardsTargeting = typeof raw.wardsTargeting === "string" && raw.wardsTargeting.trim() ? raw.wardsTargeting.trim() : JSON.stringify({ Includes: [], Excludes: [] });
1523
+ return {
1524
+ isValid: errors.length === 0,
1525
+ errors,
1526
+ data: errors.length === 0 ? {
1527
+ gender,
1528
+ ageRanges,
1529
+ platforms,
1530
+ locations: typeof raw.locations === "string" ? raw.locations : "",
1531
+ provinces: Array.isArray(raw.provinces) ? raw.provinces.map(Number) : [],
1532
+ wardsTargeting,
1533
+ priceType,
1534
+ number: typeof raw.number === "string" ? raw.number : String(raw.number || "0")
1535
+ } : void 0
1536
+ };
1537
+ }
1538
+ var ZaloAudiencesValidator = {
1539
+ createSavedAudience: validateCreateSavedAudienceRequest,
1540
+ createPhoneAudience: validateCreatePhoneAudienceRequest,
1541
+ createLookalikeAudience: validateCreateLookalikeAudienceRequest,
1542
+ createFormEventAudience: validateCreateFormEventAudienceRequest,
1543
+ createMessageOaEventAudience: validateCreateMessageOaEventAudienceRequest,
1544
+ createMessagePersonalEventAudience: validateCreateMessagePersonalEventAudienceRequest,
1545
+ estimateAudience: validateEstimateAudienceRequest
1510
1546
  };
1511
1547
 
1512
- // src/services/campaigns.service.ts
1513
- var OP_ZaloAdsUpdateVideoAd = {
1514
- operationId: "ZaloAds_updateVideoAd",
1515
- method: "POST",
1516
- endpoint: "/zaapi/UpdateAd",
1517
- baseUrl: "https://ads.zalo.me",
1518
- binaryFields: [],
1519
- pathFields: [],
1520
- queryFields: [],
1521
- headerFields: [],
1522
- cookieFields: [],
1523
- bodyFields: ["data", "est", "isBoostAd", "stt"]
1548
+ // src/dtos/ads.dto.ts
1549
+ var ZaloAdsFlowChildMessageDto = class {
1550
+ /** Mẫu Zalo đã xác minh dùng 8 cho tin nhắn văn bản trong nhánh. */
1551
+ type;
1552
+ /** Nội dung phản hồi trong nhánh. */
1553
+ text;
1524
1554
  };
1525
- var OP_ZaloAdsChangeCampaignStatus = {
1526
- "operationId": "ZaloAds_changeCampaignStatus",
1527
- "method": "POST",
1528
- "endpoint": "/api/campaign/change-status",
1529
- "baseUrl": "https://ads.zalo.me",
1530
- "binaryFields": [],
1531
- "pathFields": [],
1532
- "queryFields": [],
1533
- "headerFields": [],
1534
- "cookieFields": [],
1535
- "bodyFields": [
1536
- "status",
1537
- "campaignId"
1538
- ]
1555
+ var ZaloAdsFlowButtonDto = class {
1556
+ /** 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. */
1557
+ type;
1558
+ /** Nhãn nút hiển thị cho người dùng. */
1559
+ text;
1560
+ /** URL website; bắt buộc với type 10. */
1561
+ url;
1562
+ /** Cờ của nút website; dùng true với type 10. */
1563
+ editable;
1564
+ /** Số hotline, bắt buộc khi type là 12. */
1565
+ phone;
1566
+ /** 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. */
1567
+ messages;
1539
1568
  };
1540
- var OP_ZaloAdsCreateEcommerceCampaign = {
1541
- "operationId": "ZaloAds_createEcommerceCampaign",
1542
- "method": "POST",
1543
- "endpoint": "/zaapi/addNewCamp",
1544
- "baseUrl": "https://ads.zalo.me",
1545
- "binaryFields": [],
1546
- "pathFields": [],
1547
- "queryFields": [],
1548
- "headerFields": [],
1549
- "cookieFields": [],
1550
- "bodyFields": [
1551
- "data"
1552
- ]
1569
+ var ZaloAdsFlowMessageDto = class {
1570
+ /** 1 = Tin nhắn văn bản; 2 = Tin nhắn kèm hình ảnh. */
1571
+ type;
1572
+ /** 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}}. */
1573
+ text;
1574
+ /** 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. */
1575
+ url;
1576
+ /** Các nút đi kèm tin nhắn. */
1577
+ buttons;
1553
1578
  };
1554
- var OP_ZaloAdsCreateForm = {
1555
- "operationId": "ZaloAds_createForm",
1556
- "method": "POST",
1557
- "endpoint": "/api/form/create",
1558
- "baseUrl": "https://ads.zalo.me",
1559
- "binaryFields": [],
1560
- "pathFields": [],
1561
- "queryFields": [],
1562
- "headerFields": [],
1563
- "cookieFields": [],
1564
- "bodyFields": [
1565
- "data"
1566
- ]
1579
+ var ZaloAdsCreateFlowRequest = class {
1580
+ /** ID Official Account sở hữu kịch bản. */
1581
+ oaId;
1582
+ /** Luôn null khi tạo kịch bản mới. */
1583
+ id;
1584
+ /** Tên kịch bản, tối đa 33 ký tự theo giao diện Zalo Ads. */
1585
+ name;
1586
+ /** Các tin nhắn được gửi theo thứ tự trong kịch bản. */
1587
+ messages;
1567
1588
  };
1568
- var OP_ZaloAdsCreateFormCampaign = {
1569
- "operationId": "ZaloAds_createFormCampaign",
1570
- "method": "POST",
1571
- "endpoint": "/zaapi/addNewCamp",
1572
- "baseUrl": "https://ads.zalo.me",
1573
- "binaryFields": [],
1574
- "pathFields": [],
1575
- "queryFields": [],
1576
- "headerFields": [],
1577
- "cookieFields": [],
1578
- "bodyFields": [
1579
- "data"
1580
- ]
1589
+ var ZaloAdsCreateFlowResponse = class {
1590
+ /** 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). */
1591
+ code;
1592
+ /** Thông báo lỗi từ Zalo Ads khi code khác 0. */
1593
+ msg;
1594
+ /** 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. */
1595
+ data;
1581
1596
  };
1582
- var OP_ZaloAdsCreateMessageCampaign = {
1583
- "operationId": "ZaloAds_createMessageCampaign",
1584
- "method": "POST",
1585
- "endpoint": "/zaapi/addNewCamp",
1586
- "baseUrl": "https://ads.zalo.me",
1587
- "binaryFields": [],
1588
- "pathFields": [],
1589
- "queryFields": [],
1590
- "headerFields": [],
1591
- "cookieFields": [],
1592
- "bodyFields": [
1593
- "data"
1594
- ]
1597
+ var ZaloAdsActionType = {
1598
+ DAT_NGAY: 1,
1599
+ MUA_NGAY: 2,
1600
+ THU_NGAY: 3,
1601
+ TAI_NGAY: 4,
1602
+ XEM_THEM: 5,
1603
+ NGHE_NGAY: 6,
1604
+ CHOI_NGAY: 7,
1605
+ DANG_KY: 8,
1606
+ GOI_DIEN: 9,
1607
+ /** Dành riêng cho Quảng cáo Official Account (Type 2) */
1608
+ QUAN_TAM_OA: 6
1609
+ };
1610
+ var ZaloAdsVideoSrc = {
1611
+ UNUSED: -1,
1612
+ /** Sử dụng mã Zalo Video được cấp từ kênh */
1613
+ VIDEO_CODE: 1,
1614
+ /** Tự tải video lên hoặc chọn từ Thư viện Media */
1615
+ SELF_UPLOAD: 2
1616
+ };
1617
+ var ZaloAdsBudgetScheduleType = {
1618
+ /** Toàn lịch chạy */
1619
+ TOTAL_SCHEDULE: 1,
1620
+ /** Mỗi ngày */
1621
+ DAILY: 2
1595
1622
  };
1596
- var OP_ZaloAdsCreateOfficialAccountCampaign = {
1597
- "operationId": "ZaloAds_createOfficialAccountCampaign",
1598
- "method": "POST",
1599
- "endpoint": "/zaapi/addNewCamp",
1600
- "baseUrl": "https://ads.zalo.me",
1601
- "binaryFields": [],
1602
- "pathFields": [],
1603
- "queryFields": [],
1604
- "headerFields": [],
1605
- "cookieFields": [],
1606
- "bodyFields": [
1607
- "data"
1608
- ]
1623
+ var ZaloAdsAgeRangeId = {
1624
+ UNDER_18: 10282,
1625
+ FROM_18_TO_24: 10283,
1626
+ FROM_25_TO_34: 10284,
1627
+ FROM_35_TO_44: 10285,
1628
+ FROM_45_TO_54: 10286,
1629
+ FROM_55_TO_64: 10287,
1630
+ OVER_64: 10288
1609
1631
  };
1610
- var OP_ZaloAdsCreatePostCampaign = {
1611
- "operationId": "ZaloAds_createPostCampaign",
1612
- "method": "POST",
1613
- "endpoint": "/zaapi/addNewCamp",
1614
- "baseUrl": "https://ads.zalo.me",
1615
- "binaryFields": [],
1616
- "pathFields": [],
1617
- "queryFields": [],
1618
- "headerFields": [],
1619
- "cookieFields": [],
1620
- "bodyFields": [
1621
- "data"
1622
- ]
1632
+ var ZaloAdsOsId = {
1633
+ ANDROID: 0,
1634
+ IOS: 1,
1635
+ PC: 3
1623
1636
  };
1624
- var OP_ZaloAdsGetAdById = {
1625
- "operationId": "ZaloAds_getAdById",
1626
- "method": "GET",
1627
- "endpoint": "/zaapi/getAdFromAdId",
1628
- "baseUrl": "https://ads.zalo.me",
1629
- "binaryFields": [],
1630
- "pathFields": [],
1631
- "queryFields": [
1632
- "adId",
1633
- "v",
1634
- "newWard"
1635
- ],
1636
- "headerFields": [],
1637
- "cookieFields": [],
1638
- "bodyFields": []
1637
+ var ZaloAdsRegionId = {
1638
+ /** Miền Bắc (28 tỉnh/thành phố) */
1639
+ NORTH: 1,
1640
+ /** Miền Trung (16 tỉnh/thành phố) */
1641
+ CENTRAL: 2,
1642
+ /** Miền Nam (19 tỉnh/thành phố) */
1643
+ SOUTH: 3
1644
+ };
1645
+ var ZaloAdsProvinceCode = {
1646
+ // Miền Bắc (Region 1 - 28 tỉnh/thành)
1647
+ HANOI: "VN44",
1648
+ HAI_PHONG: "VN13",
1649
+ BAC_NINH: "VN74",
1650
+ QUANG_NINH: "VN30",
1651
+ HAI_DUONG: "VN79",
1652
+ HUNG_YEN: "VN81",
1653
+ VINH_PHUC: "VN86",
1654
+ THAI_NGUYEN: "VN85",
1655
+ BAC_GIANG: "VN71",
1656
+ PHU_THO: "VN83",
1657
+ NAM_DINH: "VN82",
1658
+ THAI_BINH: "VN35",
1659
+ NINH_BINH: "VN59",
1660
+ THANH_HOA: "VN34",
1661
+ NGHE_AN: "VN58",
1662
+ HA_TINH: "VN52",
1663
+ HOA_BINH: "VN53",
1664
+ SON_LA: "VN32",
1665
+ DIEN_BIEN: "VN92",
1666
+ LAI_CHAU: "VN89",
1667
+ LAO_CAI: "VN90",
1668
+ YEN_BAI: "VN70",
1669
+ TUYEN_QUANG: "VN68",
1670
+ HA_GIANG: "VN50",
1671
+ CAO_BANG: "VN05",
1672
+ BAC_KAN: "VN72",
1673
+ LANG_SON: "VN39",
1674
+ HA_NAM: "VN80",
1675
+ // Miền Trung (Region 2 - 16 tỉnh/thành)
1676
+ DA_NANG: "VN78",
1677
+ THUA_THIEN_HUE: "VN66",
1678
+ QUANG_NAM: "VN84",
1679
+ QUANG_NGAI: "VN63",
1680
+ BINH_DINH: "VN46",
1681
+ PHU_YEN: "VN61",
1682
+ KHANH_HOA: "VN54",
1683
+ NINH_THUAN: "VN60",
1684
+ BINH_THUAN: "VN47",
1685
+ KON_TUM: "VN55",
1686
+ GIA_LAI: "VN49",
1687
+ DAK_LAK: "VN88",
1688
+ DAK_NONG: "VN91",
1689
+ LAM_DONG: "VN23",
1690
+ QUANG_BINH: "VN62",
1691
+ QUANG_TRI: "VN64",
1692
+ // Miền Nam (Region 3 - 19 tỉnh/thành)
1693
+ HO_CHI_MINH: "VN20",
1694
+ BINH_DUONG: "VN75",
1695
+ DONG_NAI: "VN43",
1696
+ BA_RIA_VUNG_TAU: "VN45",
1697
+ LONG_AN: "VN24",
1698
+ TIEN_GIANG: "VN37",
1699
+ BEN_TRE: "VN03",
1700
+ DONG_THAP: "VN09",
1701
+ VINH_LONG: "VN69",
1702
+ CAN_THO: "VN87",
1703
+ HAU_GIANG: "VN93",
1704
+ AN_GIANG: "VN01",
1705
+ KIEN_GIANG: "VN21",
1706
+ SOC_TRANG: "VN65",
1707
+ BAC_LIEU: "VN73",
1708
+ CA_MAU: "VN77",
1709
+ TAY_NINH: "VN33",
1710
+ BINH_PHUOC: "VN76",
1711
+ TRA_VINH: "VN67"
1639
1712
  };
1640
- var OP_ZaloAdsGetAdChangeLog = {
1641
- "operationId": "ZaloAds_getAdChangeLog",
1642
- "method": "GET",
1643
- "endpoint": "/api/ad/log/{adId}",
1644
- "baseUrl": "https://ads.zalo.me",
1645
- "binaryFields": [],
1646
- "pathFields": [
1647
- "adId"
1648
- ],
1649
- "queryFields": [
1650
- "type"
1651
- ],
1652
- "headerFields": [],
1653
- "cookieFields": [],
1654
- "bodyFields": []
1713
+ var ZaloAdsDeliveryType = {
1714
+ /** Tiêu chuẩn (0): Phân phối đồng đều nhất có thể theo giờ cao điểm (Standard). */
1715
+ STANDARD: 0,
1716
+ /** Tăng tốc (1): Phân phối nhanh nhất có thể để tối đa hóa tiếp cận (SpeedUp). */
1717
+ SPEED_UP: 1,
1718
+ /** Alias tương thích ngược cho SPEED_UP (1). */
1719
+ ACCELERATED: 1
1720
+ };
1721
+ var ZaloAdsSpendingMethod = {
1722
+ /** Tiêu chuẩn (0): Rải đều ngân sách xuyên suốt ngày. */
1723
+ STANDARD: 0,
1724
+ /** Tăng tốc (1): Phân phối nhanh, ưu tiên thắng thầu ngay khi có phiên đấu giá. */
1725
+ FAST: 1,
1726
+ /** Alias cho FAST (1). */
1727
+ ACCELERATED: 1
1728
+ };
1729
+ var ZaloAdsPriceType = {
1730
+ CPM: 1,
1731
+ CPC: 2,
1732
+ CPI: 3,
1733
+ CPF: 4,
1734
+ CPA: 5,
1735
+ CPO: 6,
1736
+ CPV: 7,
1737
+ CPD: 8,
1738
+ CPV1S: 9
1739
+ };
1740
+ var ZaloAdsPriceLimitType = {
1741
+ /** Áp dụng ngân sách cho toàn lịch chạy (Life time budget). */
1742
+ LIFE_TIME: 1,
1743
+ /** Áp dụng ngân sách cho mỗi ngày (Daily budget). */
1744
+ DAILY: 2
1745
+ };
1746
+ var ZaloAdsXTemplates = {
1747
+ /** Định dạng thẻ quay vòng lướt ngang nhiều hình ảnh. */
1748
+ CAROUSEL: 42,
1749
+ /** Định dạng bộ sưu tập album ảnh (lưới 4 ảnh). */
1750
+ ALBUM: 43,
1751
+ /** Định dạng video tự động phát trên Feed. */
1752
+ ZALO_VIDEO: 44,
1753
+ /** Định dạng ảnh dọc toàn màn hình. */
1754
+ PORTRAIT_IMAGE: 45,
1755
+ /** Định dạng ảnh đơn truyền thống (1024x533). */
1756
+ SINGLE_IMAGE: 46,
1757
+ /** Định dạng ảnh bìa cho quảng cáo video. */
1758
+ COVER_IMAGE_FOR_VIDEO_AD: 47,
1759
+ /** Định dạng ảnh vuông. */
1760
+ SQUARE_IMAGE: 48,
1761
+ /** Định dạng chú thích nội dung dài (tối đa 2.000 ký tự). */
1762
+ LONG_CAPTION: 49
1763
+ };
1764
+ var ZaloAdsImageRatio = {
1765
+ /** Tỉ lệ 16:9 (1024x576 px - Video / Banner phong cảnh). */
1766
+ RATIO_16_9: 0,
1767
+ /** Tỉ lệ 4:3 (1024x768 px - Ảnh phụ Album / Carousel). */
1768
+ RATIO_4_3: 1,
1769
+ /** Tỉ lệ 2:1 (1024x512 px - ẢNH BÌA NGANG BẮT BUỘC CỦA ALBUM). */
1770
+ RATIO_2_1: 2,
1771
+ /** Tỉ lệ 3:2. */
1772
+ RATIO_3_2: 3,
1773
+ /** Tỉ lệ 1:1 (1024x1024 px - Ảnh vuông). */
1774
+ RATIO_1_1: 4
1775
+ };
1776
+ var ZaloAdsUseConversion = {
1777
+ /** Không chọn pixel (0): Tắt tối ưu hóa chuyển đổi. */
1778
+ NOT_USE: 0,
1779
+ /** Pixel của tôi (1): Zalo Pixel tự host chèn script, cần kèm ConversionId. */
1780
+ USE: 1,
1781
+ /** Pixel liên kết Ladipage (2): Landing Page đối tác LadiPage. */
1782
+ LADI_PAGE: 2,
1783
+ /** Zalo Mini App (3): Ứng dụng Zalo Mini App. */
1784
+ MINI_APP: 3,
1785
+ /** Tạm thời tắt Pixel của tôi (-1): Cờ lưu nháp. */
1786
+ USE_OFF: -1,
1787
+ /** Tạm thời tắt Pixel Ladipage (-2): Cờ lưu nháp. */
1788
+ LADI_PAGE_OFF: -2,
1789
+ /** Tạm thời tắt Pixel Mini App (-3): Cờ lưu nháp. */
1790
+ MINI_APP_OFF: -3
1655
1791
  };
1656
- var OP_ZaloAdsGetApiPlaceGetalldistricts = {
1657
- "operationId": "ZaloAds_getApiPlaceGetalldistricts",
1658
- "method": "GET",
1659
- "endpoint": "/api/place/getAllDistricts",
1660
- "baseUrl": "https://ads.zalo.me",
1661
- "binaryFields": [],
1662
- "pathFields": [],
1663
- "queryFields": [],
1664
- "headerFields": [],
1665
- "cookieFields": [],
1666
- "bodyFields": []
1792
+ var ZaloAdsUpdateVideoAdRequest = class {
1793
+ data;
1794
+ est;
1795
+ isBoostAd;
1796
+ stt;
1667
1797
  };
1668
- var OP_ZaloAdsGetApiSpellCheckV2 = {
1669
- "operationId": "ZaloAds_getApiSpellCheckV2",
1670
- "method": "GET",
1671
- "endpoint": "/api/spell-check/v2",
1672
- "baseUrl": "https://ads.zalo.me",
1673
- "binaryFields": [],
1674
- "pathFields": [],
1675
- "queryFields": [
1676
- "text"
1677
- ],
1678
- "headerFields": [],
1679
- "cookieFields": [],
1680
- "bodyFields": []
1798
+ var ZaloAdsUpdateVideoAdResponse = class {
1799
+ code;
1800
+ msg;
1801
+ data;
1681
1802
  };
1682
- var OP_ZaloAdsGetZaapiCheckcamphasmanyads = {
1683
- "operationId": "ZaloAds_getZaapiCheckcamphasmanyads",
1684
- "method": "GET",
1685
- "endpoint": "/zaapi/checkCampHasManyAds",
1686
- "baseUrl": "https://ads.zalo.me",
1687
- "binaryFields": [],
1688
- "pathFields": [],
1689
- "queryFields": [
1690
- "campaignId",
1691
- "campId"
1692
- ],
1693
- "headerFields": [],
1694
- "cookieFields": [],
1695
- "bodyFields": []
1803
+ var ZaloAdsCampaignStatus = {
1804
+ OFF: 0,
1805
+ ACTIVE: 1,
1806
+ PAUSED: 2,
1807
+ DELETED: -2
1696
1808
  };
1697
- var OP_ZaloAdsGetZaapiGetadsfromcampaignid = {
1698
- "operationId": "ZaloAds_getZaapiGetadsfromcampaignid",
1699
- "method": "GET",
1700
- "endpoint": "/zaapi/getAdsFromCampaignId",
1701
- "baseUrl": "https://ads.zalo.me",
1702
- "binaryFields": [],
1703
- "pathFields": [],
1704
- "queryFields": [
1705
- "campaignId",
1706
- "campId",
1707
- "dataType",
1708
- "v"
1709
- ],
1710
- "headerFields": [],
1711
- "cookieFields": [],
1712
- "bodyFields": []
1809
+ var ZaloAdsCreatePostCampaignRequest = class {
1810
+ /** Cấu hình chiến dịch Bài viết (object hoặc chuỗi JSON). */
1811
+ data;
1713
1812
  };
1714
- var OP_ZaloAdsGetZaapiGetallpages = {
1715
- "operationId": "ZaloAds_getZaapiGetallpages",
1716
- "method": "GET",
1717
- "endpoint": "/zaapi/getAllPages",
1718
- "baseUrl": "https://ads.zalo.me",
1719
- "binaryFields": [],
1720
- "pathFields": [],
1721
- "queryFields": [],
1722
- "headerFields": [],
1723
- "cookieFields": [],
1724
- "bodyFields": []
1813
+ var ZaloAdsCreatePostCampaignResponse = class {
1814
+ code;
1815
+ /** Chuỗi ID quảng cáo mới trong response Zalo Ads. */
1816
+ msg;
1817
+ data;
1725
1818
  };
1726
- var OP_ZaloAdsGetZaapiGetownedarticles = {
1727
- "operationId": "ZaloAds_getZaapiGetownedarticles",
1728
- "method": "GET",
1729
- "endpoint": "/zaapi/getOwnedArticles",
1730
- "baseUrl": "https://ads.zalo.me",
1731
- "binaryFields": [],
1732
- "pathFields": [],
1733
- "queryFields": [
1734
- "pageId"
1735
- ],
1736
- "headerFields": [],
1737
- "cookieFields": [],
1738
- "bodyFields": []
1819
+ var ZaloAdsMessageAdUpdateDataDto = class {
1820
+ AdId;
1821
+ CampaignId;
1822
+ MemberId;
1823
+ /** Phiên bản lạc quan lấy từ bản quảng cáo hiện tại. */
1824
+ RowVersion;
1825
+ AdName;
1826
+ /** 20 (hoặc 19) là quảng cáo Tin nhắn. */
1827
+ Type;
1828
+ Settings;
1829
+ Status;
1830
+ StartDate;
1831
+ EndDate;
1832
+ /** ID kịch bản, lấy từ createFlow hoặc listFlowsByOfficialAccount. */
1833
+ ZaloFlowId;
1834
+ ZaloPageId;
1835
+ ZaloFormId;
1836
+ UseConversion;
1837
+ ConversionId;
1838
+ Report;
1739
1839
  };
1740
- var OP_ZaloAdsGetZaapiGetownedpages = {
1741
- "operationId": "ZaloAds_getZaapiGetownedpages",
1742
- "method": "GET",
1743
- "endpoint": "/zaapi/getOwnedPages",
1744
- "baseUrl": "https://ads.zalo.me",
1745
- "binaryFields": [],
1746
- "pathFields": [],
1747
- "queryFields": [],
1748
- "headerFields": [],
1749
- "cookieFields": [],
1750
- "bodyFields": []
1840
+ var ZaloAdsUpdateMessageAdRequest = class {
1841
+ /** Payload quảng cáo đầy đủ (object hoặc chuỗi JSON); service tự tuần tự hóa thành field form data. */
1842
+ data;
1843
+ /** Tham số UI phụ trợ; capture Zalo Ads có giá trị literal "undefined". */
1844
+ est;
1845
+ /** 0 là quảng cáo thông thường, 1 là boost ad. */
1846
+ isBoostAd;
1847
+ /** Trạng thái thao tác của giao diện; mẫu đã ghi nhận 0. */
1848
+ stt;
1751
1849
  };
1752
- var OP_ZaloAdsListFormsByOfficialAccount = {
1753
- "operationId": "ZaloAds_listFormsByOfficialAccount",
1754
- "method": "GET",
1755
- "endpoint": "/api/form/getByOaId",
1756
- "baseUrl": "https://ads.zalo.me",
1757
- "binaryFields": [],
1758
- "pathFields": [],
1759
- "queryFields": [
1760
- "oaId",
1761
- "isAll"
1762
- ],
1763
- "headerFields": [],
1764
- "cookieFields": [],
1765
- "bodyFields": []
1766
- };
1767
- var OP_ZaloAdsListMiniPagesByTemplate = {
1768
- "operationId": "ZaloAds_listMiniPagesByTemplate",
1769
- "method": "GET",
1770
- "endpoint": "/api/mini-pages",
1771
- "baseUrl": "https://ads.zalo.me",
1772
- "binaryFields": [],
1773
- "pathFields": [],
1774
- "queryFields": [
1775
- "templateIds"
1776
- ],
1777
- "headerFields": [],
1778
- "cookieFields": [],
1779
- "bodyFields": []
1780
- };
1781
- var OP_ZaloAdsPostZaapiDeletead = {
1782
- "operationId": "ZaloAds_postZaapiDeletead",
1783
- "method": "POST",
1784
- "endpoint": "/zaapi/deleteAd",
1785
- "baseUrl": "https://ads.zalo.me",
1786
- "binaryFields": [],
1787
- "pathFields": [],
1788
- "queryFields": [
1789
- "adId"
1790
- ],
1791
- "headerFields": [],
1792
- "cookieFields": [],
1793
- "bodyFields": [
1794
- "adId"
1795
- ]
1796
- };
1797
- var OP_ZaloAdsRenameCampaign = {
1798
- "operationId": "ZaloAds_renameCampaign",
1799
- "method": "POST",
1800
- "endpoint": "/api/campaign/change-name",
1801
- "baseUrl": "https://ads.zalo.me",
1802
- "binaryFields": [],
1803
- "pathFields": [],
1804
- "queryFields": [],
1805
- "headerFields": [],
1806
- "cookieFields": [],
1807
- "bodyFields": [
1808
- "campid",
1809
- "newname"
1810
- ]
1811
- };
1812
- var OP_ZaloAdsUpdateEcommerceAd = {
1813
- "operationId": "ZaloAds_updateEcommerceAd",
1814
- "method": "POST",
1815
- "endpoint": "/zaapi/UpdateAd",
1816
- "baseUrl": "https://ads.zalo.me",
1817
- "binaryFields": [],
1818
- "pathFields": [],
1819
- "queryFields": [],
1820
- "headerFields": [],
1821
- "cookieFields": [],
1822
- "bodyFields": [
1823
- "est",
1824
- "stt",
1825
- "data",
1826
- "isBoostAd"
1827
- ]
1850
+ var ZaloAdsUpdateMessageAdResponse = class {
1851
+ msg;
1852
+ code;
1853
+ data;
1828
1854
  };
1829
- var OP_ZaloAdsUpdateFormAd = {
1830
- "operationId": "ZaloAds_updateFormAd",
1831
- "method": "POST",
1832
- "endpoint": "/zaapi/UpdateAd",
1833
- "baseUrl": "https://ads.zalo.me",
1834
- "binaryFields": [],
1835
- "pathFields": [],
1836
- "queryFields": [],
1837
- "headerFields": [],
1838
- "cookieFields": [],
1839
- "bodyFields": [
1840
- "est",
1841
- "stt",
1842
- "data",
1843
- "isBoostAd"
1844
- ]
1855
+
1856
+ // src/validators/campaigns.validator.ts
1857
+ var VALID_CAMPAIGN_TYPES = {
1858
+ WEBSITE: 6,
1859
+ FORM: 17,
1860
+ MESSAGE: 18,
1861
+ OA: 3,
1862
+ VIDEO: 14,
1863
+ COMMERCE: 22,
1864
+ ARTICLE: 4,
1865
+ DISPLAY: 20
1845
1866
  };
1846
- var OP_ZaloAdsUpdateMessageAd = {
1847
- "operationId": "ZaloAds_updateMessageAd",
1848
- "method": "POST",
1849
- "endpoint": "/zaapi/UpdateAd",
1850
- "baseUrl": "https://ads.zalo.me",
1851
- "binaryFields": [],
1852
- "pathFields": [],
1853
- "queryFields": [],
1854
- "headerFields": [],
1855
- "cookieFields": [],
1856
- "bodyFields": [
1857
- "est",
1858
- "stt",
1859
- "data",
1860
- "isBoostAd"
1861
- ]
1867
+ var VALID_AD_TYPES = {
1868
+ WEBSITE: 5,
1869
+ FORM: 18,
1870
+ MESSAGE: 30,
1871
+ OA: 2,
1872
+ VIDEO: 11,
1873
+ COMMERCE: 28,
1874
+ // Server trả về 28 (không phải 23)
1875
+ ARTICLE: 3,
1876
+ DISPLAY: 21
1862
1877
  };
1863
- var OP_ZaloAdsUpdateNewAds = {
1864
- "operationId": "ZaloAds_UpdateNewAds",
1865
- "method": "POST",
1866
- "endpoint": "/zaapi/UploadCrop",
1867
- "baseUrl": "https://ads.zalo.me",
1868
- "binaryFields": [
1869
- "File"
1878
+ var ALLOWED_CTAS_PER_AD_TYPE = {
1879
+ // Website (Type 5): 9 CTAs
1880
+ [VALID_AD_TYPES.WEBSITE]: [
1881
+ ZaloAdsActionType.DAT_NGAY,
1882
+ ZaloAdsActionType.MUA_NGAY,
1883
+ ZaloAdsActionType.THU_NGAY,
1884
+ ZaloAdsActionType.TAI_NGAY,
1885
+ ZaloAdsActionType.XEM_THEM,
1886
+ ZaloAdsActionType.NGHE_NGAY,
1887
+ ZaloAdsActionType.CHOI_NGAY,
1888
+ ZaloAdsActionType.DANG_KY,
1889
+ ZaloAdsActionType.GOI_DIEN
1870
1890
  ],
1871
- "pathFields": [],
1872
- "queryFields": [],
1873
- "headerFields": [],
1874
- "cookieFields": [],
1875
- "bodyFields": [
1876
- "File",
1877
- "x",
1878
- "y",
1879
- "width",
1880
- "height",
1881
- "scale"
1882
- ]
1883
- };
1884
- var OP_ZaloAdsUpdateOfficialAccountAd = {
1885
- "operationId": "ZaloAds_updateOfficialAccountAd",
1886
- "method": "POST",
1887
- "endpoint": "/zaapi/UpdateAd",
1888
- "baseUrl": "https://ads.zalo.me",
1889
- "binaryFields": [],
1890
- "pathFields": [],
1891
- "queryFields": [],
1892
- "headerFields": [],
1893
- "cookieFields": [],
1894
- "bodyFields": [
1895
- "est",
1896
- "stt",
1897
- "data",
1898
- "isBoostAd"
1899
- ]
1900
- };
1901
- var OP_ZaloAdsUpdatePostAd = {
1902
- "operationId": "ZaloAds_updatePostAd",
1903
- "method": "POST",
1904
- "endpoint": "/zaapi/UpdateAd",
1905
- "baseUrl": "https://ads.zalo.me",
1906
- "binaryFields": [],
1907
- "pathFields": [],
1908
- "queryFields": [],
1909
- "headerFields": [],
1910
- "cookieFields": [],
1911
- "bodyFields": [
1912
- "est",
1913
- "stt",
1914
- "data",
1915
- "isBoostAd"
1916
- ]
1917
- };
1918
- var OP_ZaloAdsCreateWebsiteCampaign = {
1919
- "operationId": "ZaloAds_createWebsiteCampaign",
1920
- "method": "POST",
1921
- "endpoint": "/zaapi/addNewCamp",
1922
- "baseUrl": "https://ads.zalo.me",
1923
- "binaryFields": [],
1924
- "pathFields": [],
1925
- "queryFields": [],
1926
- "headerFields": [],
1927
- "cookieFields": [],
1928
- "bodyFields": [
1929
- "data"
1930
- ]
1891
+ // Video (Type 11): 8 CTAs
1892
+ [VALID_AD_TYPES.VIDEO]: [
1893
+ ZaloAdsActionType.DAT_NGAY,
1894
+ ZaloAdsActionType.MUA_NGAY,
1895
+ ZaloAdsActionType.THU_NGAY,
1896
+ ZaloAdsActionType.TAI_NGAY,
1897
+ ZaloAdsActionType.XEM_THEM,
1898
+ ZaloAdsActionType.NGHE_NGAY,
1899
+ ZaloAdsActionType.CHOI_NGAY,
1900
+ ZaloAdsActionType.DANG_KY
1901
+ ],
1902
+ // Article (Type 3): 7 CTAs
1903
+ [VALID_AD_TYPES.ARTICLE]: [
1904
+ ZaloAdsActionType.DAT_NGAY,
1905
+ ZaloAdsActionType.MUA_NGAY,
1906
+ ZaloAdsActionType.THU_NGAY,
1907
+ ZaloAdsActionType.TAI_NGAY,
1908
+ ZaloAdsActionType.XEM_THEM,
1909
+ ZaloAdsActionType.CHOI_NGAY,
1910
+ ZaloAdsActionType.DANG_KY
1911
+ ],
1912
+ // Form (Type 18): 5 CTAs
1913
+ [VALID_AD_TYPES.FORM]: [
1914
+ ZaloAdsActionType.DAT_NGAY,
1915
+ ZaloAdsActionType.MUA_NGAY,
1916
+ ZaloAdsActionType.THU_NGAY,
1917
+ ZaloAdsActionType.XEM_THEM,
1918
+ ZaloAdsActionType.DANG_KY
1919
+ ],
1920
+ // Commerce (Type 28): 3 CTAs
1921
+ [VALID_AD_TYPES.COMMERCE]: [
1922
+ ZaloAdsActionType.DAT_NGAY,
1923
+ ZaloAdsActionType.MUA_NGAY,
1924
+ ZaloAdsActionType.XEM_THEM
1925
+ ],
1926
+ // OA (Type 2): Cố định Quan tâm OA (6)
1927
+ [VALID_AD_TYPES.OA]: [ZaloAdsActionType.QUAN_TAM_OA]
1931
1928
  };
1932
- var OP_ZaloAdsUpdateWebsiteAd = {
1933
- "operationId": "ZaloAds_updateWebsiteAd",
1934
- "method": "POST",
1935
- "endpoint": "/zaapi/UpdateAd",
1936
- "baseUrl": "https://ads.zalo.me",
1937
- "binaryFields": [],
1938
- "pathFields": [],
1939
- "queryFields": [],
1940
- "headerFields": [],
1941
- "cookieFields": [],
1942
- "bodyFields": [
1943
- "est",
1944
- "stt",
1945
- "data",
1946
- "isBoostAd"
1947
- ]
1948
- };
1949
- var OP_ZaloAdsCreateDisplayCampaign = {
1950
- "operationId": "ZaloAds_createDisplayCampaign",
1951
- "method": "POST",
1952
- "endpoint": "/zaapi/addNewCamp",
1953
- "baseUrl": "https://ads.zalo.me",
1954
- "binaryFields": [],
1955
- "pathFields": [],
1956
- "queryFields": [],
1957
- "headerFields": [],
1958
- "cookieFields": [],
1959
- "bodyFields": [
1960
- "data"
1961
- ]
1962
- };
1963
- var OP_ZaloAdsUpdateDisplayAd = {
1964
- "operationId": "ZaloAds_updateDisplayAd",
1965
- "method": "POST",
1966
- "endpoint": "/zaapi/UpdateAd",
1967
- "baseUrl": "https://ads.zalo.me",
1968
- "binaryFields": [],
1969
- "pathFields": [],
1970
- "queryFields": [],
1971
- "headerFields": [],
1972
- "cookieFields": [],
1973
- "bodyFields": [
1974
- "est",
1975
- "stt",
1976
- "data",
1977
- "isBoostAd"
1978
- ]
1979
- };
1980
- var OP_ZaloAdsCreateVideoCampaign = {
1981
- "operationId": "ZaloAds_createVideoCampaign",
1982
- "method": "POST",
1983
- "endpoint": "/zaapi/addNewCamp",
1984
- "baseUrl": "https://ads.zalo.me",
1985
- "binaryFields": [],
1986
- "pathFields": [],
1987
- "queryFields": [],
1988
- "headerFields": [],
1989
- "cookieFields": [],
1990
- "bodyFields": [
1991
- "data"
1992
- ]
1993
- };
1994
- var OP_ZaloAdsDeleteCampaign = {
1995
- "operationId": "ZaloAds_deleteCampaign",
1996
- "method": "POST",
1997
- "endpoint": "/api/campaign/change-status",
1998
- "baseUrl": "https://ads.zalo.me",
1999
- "binaryFields": [],
2000
- "pathFields": [],
2001
- "queryFields": [],
2002
- "headerFields": [],
2003
- "cookieFields": [],
2004
- "bodyFields": [
2005
- "campaignId",
2006
- "status"
2007
- ]
2008
- };
2009
- var OP_ZaloAdsDuplicateAd = {
2010
- operationId: "zalo_ads_duplicate_ad",
2011
- method: "POST",
2012
- endpoint: "/zaapi/DuplicateAd",
2013
- baseUrl: "https://ads.zalo.me",
2014
- binaryFields: [],
2015
- pathFields: [],
2016
- queryFields: [],
2017
- headerFields: [],
2018
- cookieFields: [],
2019
- bodyFields: ["adid"]
2020
- };
2021
- var OP_ZaloAdsCreateSpellCheckV3Job = {
2022
- operationId: "zalo_ads_create_spell_check_v3_job",
2023
- method: "POST",
2024
- endpoint: "/api/spell-check/v3",
2025
- baseUrl: "https://ads.zalo.me",
2026
- binaryFields: [],
2027
- pathFields: [],
2028
- queryFields: [],
2029
- headerFields: [],
2030
- cookieFields: [],
2031
- bodyFields: ["title", "caption"]
2032
- };
2033
- var OP_ZaloAdsGetSpellCheckV3Job = {
2034
- operationId: "zalo_ads_get_spell_check_v3_job",
2035
- method: "GET",
2036
- endpoint: "/api/spell-check/v3/{jobId}",
2037
- baseUrl: "https://ads.zalo.me",
2038
- binaryFields: [],
2039
- pathFields: ["jobId"],
2040
- queryFields: [],
2041
- headerFields: [],
2042
- cookieFields: [],
2043
- bodyFields: []
2044
- };
2045
- var ZaloCampaignsService = class {
2046
- constructor(client) {
2047
- this.client = client;
2048
- }
2049
- validator = ZaloCampaignsValidator;
2050
- static validator = ZaloCampaignsValidator;
2051
- updateVideoAd(request, options) {
2052
- return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateVideoAd, this.client.toTransportInput(OP_ZaloAdsUpdateVideoAd, request), options);
2053
- }
2054
- changeCampaignStatus(request, options) {
2055
- return this.client.requestFormUrlEncoded(OP_ZaloAdsChangeCampaignStatus, this.client.toTransportInput(OP_ZaloAdsChangeCampaignStatus, request), options);
2056
- }
2057
- deleteCampaign(request, options) {
2058
- const payload = { campaignId: request.campaignId, status: request.status ?? -2 };
2059
- return this.client.requestFormUrlEncoded(OP_ZaloAdsDeleteCampaign, this.client.toTransportInput(OP_ZaloAdsDeleteCampaign, payload), options);
2060
- }
2061
- createWebsiteCampaign(request, options) {
2062
- return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateWebsiteCampaign, this.client.toTransportInput(OP_ZaloAdsCreateWebsiteCampaign, request), options);
2063
- }
2064
- updateWebsiteAd(request, options) {
2065
- return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateWebsiteAd, this.client.toTransportInput(OP_ZaloAdsUpdateWebsiteAd, request), options);
2066
- }
2067
- createDisplayCampaign(request, options) {
2068
- return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateDisplayCampaign, this.client.toTransportInput(OP_ZaloAdsCreateDisplayCampaign, request), options);
2069
- }
2070
- updateDisplayAd(request, options) {
2071
- return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateDisplayAd, this.client.toTransportInput(OP_ZaloAdsUpdateDisplayAd, request), options);
1929
+ function validateCreateCampaignPayload(payload, options = {}) {
1930
+ const errors = [];
1931
+ const warnings = [];
1932
+ if (!payload.name || typeof payload.name !== "string" || !payload.name.trim()) {
1933
+ errors.push("name l\xE0 b\u1EAFt bu\u1ED9c v\xE0 kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
1934
+ } else if (payload.name.length > 255) {
1935
+ errors.push("name kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 255 k\xFD t\u1EF1.");
2072
1936
  }
2073
- createVideoCampaign(request, options) {
2074
- return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateVideoCampaign, this.client.toTransportInput(OP_ZaloAdsCreateVideoCampaign, request), options);
1937
+ const validTypes = Object.values(VALID_CAMPAIGN_TYPES);
1938
+ if (payload.campaignType === void 0 || payload.campaignType === null) {
1939
+ errors.push("campaignType l\xE0 b\u1EAFt bu\u1ED9c.");
1940
+ } else if (!validTypes.includes(payload.campaignType)) {
1941
+ errors.push(
1942
+ `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).`
1943
+ );
2075
1944
  }
2076
- createEcommerceCampaign(request, options) {
2077
- return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateEcommerceCampaign, this.client.toTransportInput(OP_ZaloAdsCreateEcommerceCampaign, request), options);
1945
+ if (payload.campaignType !== VALID_CAMPAIGN_TYPES.DISPLAY) {
1946
+ if (!payload.pageId || payload.pageId <= 0) {
1947
+ 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).");
1948
+ }
1949
+ } else {
1950
+ if (payload.pageId !== -1 && payload.pageId !== 0 && !payload.pageId) {
1951
+ warnings.push("Qu\u1EA3ng c\xE1o Display th\u01B0\u1EDDng s\u1EED d\u1EE5ng pageId = -1.");
1952
+ }
2078
1953
  }
2079
- /** Alias theo tên tool chuẩn `zalo_ads_create_commerce_campaign` trong Project Schema Zalo ADS (`campaignType = 22`). */
2080
- createCommerceCampaign(request, options) {
2081
- return this.createEcommerceCampaign(request, options);
1954
+ switch (payload.campaignType) {
1955
+ case VALID_CAMPAIGN_TYPES.WEBSITE:
1956
+ if (!payload.targetUrl || typeof payload.targetUrl !== "string" || !payload.targetUrl.trim()) {
1957
+ errors.push("targetUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Website.");
1958
+ } else if (!/^https?:\/\/.+/i.test(payload.targetUrl)) {
1959
+ 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://.");
1960
+ }
1961
+ break;
1962
+ case VALID_CAMPAIGN_TYPES.ARTICLE:
1963
+ if (!payload.articleId || payload.articleId <= 0) {
1964
+ 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).");
1965
+ }
1966
+ break;
1967
+ case VALID_CAMPAIGN_TYPES.COMMERCE:
1968
+ if (payload.productId === void 0 || payload.productId === null) {
1969
+ 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).");
1970
+ }
1971
+ break;
1972
+ case VALID_CAMPAIGN_TYPES.FORM:
1973
+ case VALID_CAMPAIGN_TYPES.MESSAGE:
1974
+ break;
2082
1975
  }
2083
- createForm(request, options) {
2084
- return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateForm, this.client.toTransportInput(OP_ZaloAdsCreateForm, request), options);
1976
+ if (payload.budgetType !== void 0 && payload.budgetlimit !== void 0) {
1977
+ if (payload.budgetType === 2) {
1978
+ if (payload.budgetlimit > 0 && payload.budgetlimit < 6e5) {
1979
+ errors.push("Ng\xE2n s\xE1ch cho To\xE0n l\u1ECBch ch\u1EA1y t\u1ED1i thi\u1EC3u l\xE0 600,000 VN\u0110.");
1980
+ }
1981
+ } else if (payload.budgetType === 1) {
1982
+ if (payload.budgetlimit > 0 && payload.budgetlimit < 50) {
1983
+ 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.");
1984
+ }
1985
+ }
2085
1986
  }
2086
- createFormCampaign(request, options) {
2087
- return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateFormCampaign, this.client.toTransportInput(OP_ZaloAdsCreateFormCampaign, request), options);
1987
+ if (payload.campaignId && payload.campaignId > 0) {
1988
+ if (payload.adId !== 0) {
1989
+ 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.");
1990
+ }
2088
1991
  }
2089
- createMessageCampaign(request, options) {
2090
- return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateMessageCampaign, this.client.toTransportInput(OP_ZaloAdsCreateMessageCampaign, request), options);
1992
+ return {
1993
+ isValid: errors.length === 0,
1994
+ errors,
1995
+ warnings
1996
+ };
1997
+ }
1998
+ function validateUpdateAdPayload(payload, options = {}) {
1999
+ const errors = [];
2000
+ const warnings = [];
2001
+ if (!payload.AdId || payload.AdId <= 0) {
2002
+ errors.push("AdId l\xE0 b\u1EAFt bu\u1ED9c (ph\u1EA3i > 0).");
2091
2003
  }
2092
- createOfficialAccountCampaign(request, options) {
2093
- return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateOfficialAccountCampaign, this.client.toTransportInput(OP_ZaloAdsCreateOfficialAccountCampaign, request), options);
2004
+ if (!payload.CampaignId || payload.CampaignId <= 0) {
2005
+ errors.push("CampaignId l\xE0 b\u1EAFt bu\u1ED9c (ph\u1EA3i > 0).");
2094
2006
  }
2095
- /** Alias theo tên tool chuẩn `zalo_ads_create_oa_campaign` trong Project Schema Zalo ADS (`campaignType = 3`). */
2096
- createOaCampaign(request, options) {
2097
- return this.createOfficialAccountCampaign(request, options);
2007
+ if (!payload.AdName || !payload.AdName.trim()) {
2008
+ errors.push("AdName l\xE0 b\u1EAFt bu\u1ED9c v\xE0 kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
2009
+ } else if (payload.AdName.length > 255) {
2010
+ errors.push(`AdName qu\xE1 d\xE0i (${payload.AdName.length}/255 k\xFD t\u1EF1).`);
2098
2011
  }
2099
- createPostCampaign(request, options) {
2100
- return this.client.requestFormUrlEncoded(OP_ZaloAdsCreatePostCampaign, this.client.toTransportInput(OP_ZaloAdsCreatePostCampaign, request), options);
2012
+ const adInfo = payload.Settings?.AdInfo;
2013
+ if (!adInfo) {
2014
+ errors.push("Settings.AdInfo l\xE0 b\u1EAFt bu\u1ED9c.");
2015
+ } else {
2016
+ if (!adInfo.Caption || !adInfo.Caption.trim()) {
2017
+ errors.push("Settings.AdInfo.Caption l\xE0 b\u1EAFt bu\u1ED9c.");
2018
+ } else {
2019
+ const captionLen = adInfo.Caption.trim().length;
2020
+ if (captionLen < 35) {
2021
+ errors.push(`Settings.AdInfo.Caption qu\xE1 ng\u1EAFn (${captionLen}/35 k\xFD t\u1EF1 t\u1ED1i thi\u1EC3u).`);
2022
+ } else if (captionLen > 90) {
2023
+ errors.push(`Settings.AdInfo.Caption qu\xE1 d\xE0i (${captionLen}/90 k\xFD t\u1EF1 t\u1ED1i \u0111a).`);
2024
+ }
2025
+ }
2026
+ const longCaption = adInfo.LongCaption ?? adInfo.MoreInfo;
2027
+ if (longCaption !== void 0 && longCaption !== null && longCaption.trim().length > 0) {
2028
+ const longCaptionLen = longCaption.trim().length;
2029
+ if (longCaptionLen < 90) {
2030
+ errors.push(
2031
+ `Settings.AdInfo.LongCaption (Ch\xFA th\xEDch m\u1EDF r\u1ED9ng) qu\xE1 ng\u1EAFn (${longCaptionLen}/90 k\xFD t\u1EF1 t\u1ED1i thi\u1EC3u). Theo quy chu\u1EA9n Zalo Ads, tr\u01B0\u1EDDng n\xE0y kh\xF4ng b\u1EAFt bu\u1ED9c, nh\u01B0ng n\u1EBFu nh\u1EADp th\xEC b\u1EAFt bu\u1ED9c ph\u1EA3i t\u1EEB 90 \u0111\u1EBFn 2,000 k\xFD t\u1EF1.`
2032
+ );
2033
+ } else if (longCaptionLen > 2e3) {
2034
+ errors.push(
2035
+ `Settings.AdInfo.LongCaption (Ch\xFA th\xEDch m\u1EDF r\u1ED9ng) qu\xE1 d\xE0i (${longCaptionLen}/2000 k\xFD t\u1EF1 t\u1ED1i \u0111a).`
2036
+ );
2037
+ }
2038
+ if (adInfo.XTemplates && Array.isArray(adInfo.XTemplates) && !adInfo.XTemplates.includes(49)) {
2039
+ warnings.push(
2040
+ "Khi c\xF3 Ch\xFA th\xEDch m\u1EDF r\u1ED9ng (LongCaption), b\u1EA1n n\xEAn th\xEAm m\xE3 49 (LONG_CAPTION) v\xE0o Settings.AdInfo.XTemplates \u0111\u1EC3 k\xEDch ho\u1EA1t giao di\u1EC7n hi\u1EC3n th\u1ECB b\xE0i vi\u1EBFt d\xE0i tr\xEAn Zalo Feed."
2041
+ );
2042
+ }
2043
+ }
2044
+ if (adInfo.Action !== void 0 && payload.Type) {
2045
+ const allowedCtas = ALLOWED_CTAS_PER_AD_TYPE[payload.Type];
2046
+ if (allowedCtas && !allowedCtas.includes(adInfo.Action)) {
2047
+ warnings.push(
2048
+ `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}.`
2049
+ );
2050
+ }
2051
+ }
2101
2052
  }
2102
- /** Alias theo tên tool chuẩn `zalo_ads_create_article_campaign` trong Project Schema Zalo ADS (`campaignType = 4`). */
2103
- createArticleCampaign(request, options) {
2104
- return this.createPostCampaign(request, options);
2105
- }
2106
- getAdById(request = {}, options) {
2107
- const normalized = {
2108
- adId: request.adId,
2109
- v: request.v ?? 2,
2110
- newWard: request.newWard ?? true
2111
- };
2112
- return this.client.requestWithoutBody(OP_ZaloAdsGetAdById, this.client.toTransportInput(OP_ZaloAdsGetAdById, normalized), options);
2113
- }
2114
- getAdChangeLog(request, options) {
2115
- const normalized = {
2116
- adId: request.adId,
2117
- type: request.type ?? 1
2118
- };
2119
- return this.client.requestWithoutBody(OP_ZaloAdsGetAdChangeLog, this.client.toTransportInput(OP_ZaloAdsGetAdChangeLog, normalized), options);
2120
- }
2121
- getApiPlaceGetalldistricts(request = {}, options) {
2122
- return this.client.requestWithoutBody(OP_ZaloAdsGetApiPlaceGetalldistricts, this.client.toTransportInput(OP_ZaloAdsGetApiPlaceGetalldistricts, request), options);
2123
- }
2124
- getApiSpellCheckV2(request, options) {
2125
- return this.client.requestWithoutBody(OP_ZaloAdsGetApiSpellCheckV2, this.client.toTransportInput(OP_ZaloAdsGetApiSpellCheckV2, request), options);
2126
- }
2127
- getZaapiCheckcamphasmanyads(request = {}, options) {
2128
- return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiCheckcamphasmanyads, this.client.toTransportInput(OP_ZaloAdsGetZaapiCheckcamphasmanyads, request), options);
2129
- }
2130
- getZaapiGetadsfromcampaignid(request = {}, options) {
2131
- const normalized = {
2132
- campaignId: request.campaignId ?? request.campId,
2133
- dataType: request.dataType ?? 1,
2134
- v: request.v ?? 2
2135
- };
2136
- return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetadsfromcampaignid, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetadsfromcampaignid, normalized), options);
2137
- }
2138
- /** Alias lấy danh sách quảng cáo của chiến dịch kèm metadata extend và extra.appliedRuleInfo */
2139
- getAdsFromCampaignId(request = {}, options) {
2140
- return this.getZaapiGetadsfromcampaignid(request, options);
2141
- }
2142
- getZaapiGetallpages(request = {}, options) {
2143
- return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetallpages, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetallpages, request), options);
2144
- }
2145
- getAllPages(request = {}, options) {
2146
- return this.getZaapiGetallpages(request, options);
2147
- }
2148
- getZaapiGetownedarticles(request, options) {
2149
- return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetownedarticles, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetownedarticles, request), options);
2150
- }
2151
- getOwnedArticles(request, options) {
2152
- return this.getZaapiGetownedarticles(request, options);
2153
- }
2154
- getZaapiGetownedpages(request = {}, options) {
2155
- return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetownedpages, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetownedpages, request), options);
2156
- }
2157
- getOwnedPages(request = {}, options) {
2158
- return this.getZaapiGetownedpages(request, options);
2159
- }
2160
- listFormsByOfficialAccount(request, options) {
2161
- return this.client.requestWithoutBody(OP_ZaloAdsListFormsByOfficialAccount, this.client.toTransportInput(OP_ZaloAdsListFormsByOfficialAccount, request), options);
2162
- }
2163
- listMiniPagesByTemplate(request, options) {
2164
- return this.client.requestWithoutBody(OP_ZaloAdsListMiniPagesByTemplate, this.client.toTransportInput(OP_ZaloAdsListMiniPagesByTemplate, request), options);
2165
- }
2166
- postZaapiDeletead(request = {}, options) {
2167
- return this.client.requestWithoutBody(OP_ZaloAdsPostZaapiDeletead, this.client.toTransportInput(OP_ZaloAdsPostZaapiDeletead, request), options);
2168
- }
2169
- renameCampaign(request, options) {
2170
- const normalized = {
2171
- campid: request.campid ?? request.campaignId,
2172
- newname: request.newname ?? request.campaignName ?? request.name
2173
- };
2174
- return this.client.requestFormUrlEncoded(OP_ZaloAdsRenameCampaign, this.client.toTransportInput(OP_ZaloAdsRenameCampaign, normalized), options);
2175
- }
2176
- updateEcommerceAd(request, options) {
2177
- return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateEcommerceAd, this.client.toTransportInput(OP_ZaloAdsUpdateEcommerceAd, request), options);
2178
- }
2179
- /** Alias theo tên tool chuẩn `zalo_ads_update_commerce_ad` trong Project Schema Zalo ADS (`Type = 23`, gắn `MiniPageId`). */
2180
- updateCommerceAd(request, options) {
2181
- return this.updateEcommerceAd(request, options);
2182
- }
2183
- updateFormAd(request, options) {
2184
- return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateFormAd, this.client.toTransportInput(OP_ZaloAdsUpdateFormAd, request), options);
2185
- }
2186
- updateMessageAd(request, options) {
2187
- return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateMessageAd, this.client.toTransportInput(OP_ZaloAdsUpdateMessageAd, request), options);
2188
- }
2189
- updateNewAds(request, options) {
2190
- return this.client.requestMultipart(OP_ZaloAdsUpdateNewAds, this.client.toTransportInput(OP_ZaloAdsUpdateNewAds, request), options);
2053
+ const price = payload.Settings?.Price;
2054
+ if (!price) {
2055
+ errors.push("Settings.Price l\xE0 b\u1EAFt bu\u1ED9c.");
2056
+ } else {
2057
+ if (payload.Type === VALID_AD_TYPES.WEBSITE) {
2058
+ if (price.Type !== 1) {
2059
+ errors.push(
2060
+ "\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."
2061
+ );
2062
+ }
2063
+ if (price.LimitType === 1) {
2064
+ errors.push(
2065
+ "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)."
2066
+ );
2067
+ }
2068
+ } else if (payload.Type === VALID_AD_TYPES.VIDEO) {
2069
+ if (price.Type !== 1 && price.Type !== 7) {
2070
+ errors.push(
2071
+ "\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Video (Type 11) tr\xEAn Video Platform, Price.Type b\u1EAFt bu\u1ED9c l\xE0 1 (CPM - L\u01B0\u1EE3t hi\u1EC3n th\u1ECB) ho\u1EB7c 7 (CPV - L\u01B0\u1EE3t xem). N\u1EBFu truy\u1EC1n 2 (CPC), form ch\u1EC9nh s\u1EEDa c\u1EE7a Zalo Ads s\u1EBD kh\xF4ng hi\u1EC3n th\u1ECB \u0111\u01B0\u1EE3c gi\xE1 v\xE0 s\u1ED1 l\u01B0\u1EE3ng."
2072
+ );
2073
+ }
2074
+ if (price.Type === 1 && (price.Limit ?? 0) < 50) {
2075
+ errors.push(
2076
+ "\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Video CPM, s\u1ED1 l\u01B0\u1EE3ng hi\u1EC3n th\u1ECB t\u1ED1i thi\u1EC3u (Price.Limit) l\xE0 50 (t\u01B0\u01A1ng \u1EE9ng 50,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB)."
2077
+ );
2078
+ }
2079
+ } else if (payload.Type === VALID_AD_TYPES.COMMERCE || payload.Type === VALID_AD_TYPES.ARTICLE || payload.Type === VALID_AD_TYPES.FORM) {
2080
+ if (price.Type !== 2) {
2081
+ errors.push(
2082
+ `\u0110\u1ED1i v\u1EDBi Ad Type ${payload.Type}, Price.Type b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 2 (CPC).`
2083
+ );
2084
+ }
2085
+ } else if (payload.Type === VALID_AD_TYPES.OA) {
2086
+ if (price.Type !== 2 && price.Type !== 5) {
2087
+ errors.push(
2088
+ "\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o OA (Type 2), Price.Type ch\u1EC9 h\u1ED7 tr\u1EE3 2 (L\u01B0\u1EE3t nh\u1EA5n - CPC) ho\u1EB7c 5 (L\u01B0\u1EE3t quan t\xE2m - CPA Beta)."
2089
+ );
2090
+ }
2091
+ if (price.Type === 2) {
2092
+ if (price.SpendingMethod !== 0 && price.SpendingMethod !== void 0) {
2093
+ errors.push(
2094
+ "Khi t\xEDnh ti\u1EC1n theo L\u01B0\u1EE3t nh\u1EA5n (Price.Type = 2 / CPC), SpendingMethod b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 0 (\u0110\u1EB7t gi\xE1 th\u1EA7u th\u1EE7 c\xF4ng theo s\u1ED1 l\u01B0\u1EE3ng t\u01B0\u01A1ng t\xE1c)."
2095
+ );
2096
+ }
2097
+ if (price.Bid !== void 0 && price.Bid < 650) {
2098
+ errors.push(
2099
+ `Gi\xE1 \u0111\u1EB7t m\u1ED7i l\u01B0\u1EE3t nh\u1EA5n (Price.Bid) t\u1ED1i thi\u1EC3u l\xE0 650 VN\u0110 (s\xE0n h\u1EC7 th\u1ED1ng Zalo Ads). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
2100
+ );
2101
+ }
2102
+ if (price.Limit !== void 0 && price.Limit < 50) {
2103
+ errors.push(
2104
+ `S\u1ED1 l\u01B0\u1EE3ng l\u01B0\u1EE3t nh\u1EA5n (Price.Limit) t\u1ED1i thi\u1EC3u l\xE0 50 l\u01B0\u1EE3t/ng\xE0y (minCTA = 50). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
2105
+ );
2106
+ } else if (price.Limit !== void 0 && price.Limit > 5e3) {
2107
+ warnings.push(
2108
+ `\u26A0\uFE0F C\u1EA2NH B\xC1O B\u1EAAY NG\xC2N S\xC1CH ZALO ADS: Khi Price.Type = 2 (CPC), tr\u01B0\u1EDDng Price.Limit mang \xFD ngh\u0129a l\xE0 S\u1ED0 L\u01AF\u1EE2NG L\u01AF\u1EE2T NH\u1EA4N (Clicks count), KH\xD4NG PH\u1EA2I S\u1ED0 TI\u1EC0N VN\u0110. B\u1EA1n \u0111ang truy\u1EC1n Limit = ${price.Limit} l\u01B0\u1EE3t nh\u1EA5n, c\xF3 th\u1EC3 khi\u1EBFn T\u1ED5ng chi ph\xED d\u1EF1 ki\u1EBFn t\u0103ng v\u1ECDt l\xEAn h\xE0ng tr\u0103m tri\u1EC7u VN\u0110.`
2109
+ );
2110
+ }
2111
+ } else if (price.Type === 5) {
2112
+ if (price.SpendingMethod === 1) {
2113
+ if (price.Bid !== void 0 && price.Bid !== 0) {
2114
+ errors.push(
2115
+ "Khi ch\u1ECDn 'T\u1ED5ng ng\xE2n s\xE1ch qu\u1EA3ng c\xE1o' cho L\u01B0\u1EE3t quan t\xE2m (SpendingMethod = 1), tr\u01B0\u1EDDng Bid b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 0 (h\u1EC7 th\u1ED1ng t\u1EF1 \u0111\u1ED9ng \u0111\u1EA5u th\u1EA7u)."
2116
+ );
2117
+ }
2118
+ if (price.Limit !== void 0 && price.Limit < 5e5) {
2119
+ errors.push(
2120
+ `Ng\xE2n s\xE1ch t\u1ED1i thi\u1EC3u cho L\u01B0\u1EE3t quan t\xE2m theo T\u1ED5ng ng\xE2n s\xE1ch l\xE0 500,000 VN\u0110 / ng\xE0y (Price.Limit >= 500000). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}\u0111.`
2121
+ );
2122
+ }
2123
+ } else if (price.SpendingMethod === 0) {
2124
+ if (price.Bid !== void 0 && price.Bid < 1e4) {
2125
+ errors.push(
2126
+ `Gi\xE1 \u0111\u1EB7t m\u1ED7i L\u01B0\u1EE3t quan t\xE2m (Price.Bid) t\u1ED1i thi\u1EC3u l\xE0 10,000 VN\u0110 / l\u01B0\u1EE3t quan t\xE2m (s\xE0n h\u1EC7 th\u1ED1ng cho OA Follow). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
2127
+ );
2128
+ }
2129
+ if (price.Limit !== void 0 && price.Limit < 100) {
2130
+ errors.push(
2131
+ `S\u1ED1 l\u01B0\u1EE3ng L\u01B0\u1EE3t quan t\xE2m (Price.Limit) t\u1ED1i thi\u1EC3u l\xE0 100 l\u01B0\u1EE3t (minCTA = 100). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
2132
+ );
2133
+ } else if (price.Limit !== void 0 && price.Limit > 5e3) {
2134
+ warnings.push(
2135
+ `\u26A0\uFE0F C\u1EA2NH B\xC1O B\u1EAAY NG\xC2N S\xC1CH ZALO ADS: Khi ch\u1ECDn 'T\u1EF1 \u0111\u1EB7t gi\xE1' cho L\u01B0\u1EE3t quan t\xE2m (SpendingMethod = 0), tr\u01B0\u1EDDng Price.Limit l\xE0 S\u1ED0 L\u01AF\u1EE2NG L\u01AF\u1EE2T QUAN T\xC2M (t\u1ED1i thi\u1EC3u 100 l\u01B0\u1EE3t), KH\xD4NG PH\u1EA2I S\u1ED0 TI\u1EC0N VN\u0110.`
2136
+ );
2137
+ }
2138
+ } else if (price.SpendingMethod !== void 0) {
2139
+ errors.push(
2140
+ "C\xE1ch \u0111\u1EB7t gi\xE1 SpendingMethod cho L\u01B0\u1EE3t quan t\xE2m ch\u1EC9 ch\u1EA5p nh\u1EADn 1 (T\u1ED5ng ng\xE2n s\xE1ch qu\u1EA3ng c\xE1o) ho\u1EB7c 0 (T\u1EF1 \u0111\u1EB7t gi\xE1)."
2141
+ );
2142
+ }
2143
+ }
2144
+ } else if (payload.Type === VALID_AD_TYPES.MESSAGE) {
2145
+ if (price.Type !== 2 && price.Type !== 5) {
2146
+ errors.push(
2147
+ "\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Tin nh\u1EAFn (Type 30), Price.Type ch\u1EC9 h\u1ED7 tr\u1EE3 2 (L\u01B0\u1EE3t nh\u1EA5n - CPC) ho\u1EB7c 5 (L\u01B0\u1EE3t li\xEAn h\u1EC7 - CPA)."
2148
+ );
2149
+ }
2150
+ if (price.Type === 5) {
2151
+ if (price.SpendingMethod !== 1) {
2152
+ errors.push(
2153
+ "Khi t\xEDnh ti\u1EC1n theo L\u01B0\u1EE3t li\xEAn h\u1EC7 (Price.Type = 5 / CPA), SpendingMethod b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 1 (T\u1ED1i \u01B0u t\u1EF1 \u0111\u1ED9ng theo ng\xE2n s\xE1ch)."
2154
+ );
2155
+ }
2156
+ if (price.Bid !== void 0 && price.Bid !== 0) {
2157
+ errors.push(
2158
+ "Khi t\xEDnh ti\u1EC1n theo L\u01B0\u1EE3t li\xEAn h\u1EC7 (Price.Type = 5 / CPA), tr\u01B0\u1EDDng Bid b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 0 (Zalo Ads t\u1EF1 \u0111\u1ED9ng t\u1ED1i \u01B0u gi\xE1 th\u1EA7u, n\u1EBFu truy\u1EC1n > 0 m\xE1y ch\u1EE7 s\u1EBD b\xE1o l\u1ED7i code 13: Gi\xE1 \u0111\u1EB7t kh\xF4ng h\u1EE3p l\u1EC7)."
2159
+ );
2160
+ }
2161
+ }
2162
+ if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 6e5) {
2163
+ errors.push(
2164
+ "Ng\xE2n s\xE1ch t\u1ED1i thi\u1EC3u cho Qu\u1EA3ng c\xE1o Tin nh\u1EAFn l\xE0 600,000 VN\u0110 (Price.Limit >= 600000). N\u1EBFu \u0111\u1EB7t d\u01B0\u1EDBi 600k m\xE1y ch\u1EE7 s\u1EBD t\u1EEB ch\u1ED1i."
2165
+ );
2166
+ }
2167
+ }
2168
+ if (payload.Settings && payload.Settings.DeliveryType !== void 0) {
2169
+ const deliveryType = payload.Settings.DeliveryType;
2170
+ if (deliveryType !== 0 && deliveryType !== 1) {
2171
+ errors.push("C\xE0i \u0111\u1EB7t ph\xE2n ph\u1ED1i Settings.DeliveryType ch\u1EC9 ch\u1EA5p nh\u1EADn 0 (Ti\xEAu chu\u1EA9n - Standard) ho\u1EB7c 1 (T\u0103ng t\u1ED1c - SpeedUp).");
2172
+ }
2173
+ if ((price.LimitType === 2 || price.LimitType === 0) && deliveryType === 1) {
2174
+ warnings.push("Ph\xE2n ph\u1ED1i T\u0103ng t\u1ED1c (DeliveryType = 1) ch\u1EC9 c\xF3 hi\u1EC7u l\u1EF1c khi \u0111\u1EB7t Ng\xE2n s\xE1ch to\xE0n l\u1ECBch ch\u1EA1y (Price.LimitType = 1).");
2175
+ }
2176
+ }
2177
+ if (price.SpendingMethod === 0 && price.Limit !== void 0 && price.Limit > 0 && price.Limit < 50) {
2178
+ 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.");
2179
+ }
2191
2180
  }
2192
- updateOfficialAccountAd(request, options) {
2193
- return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateOfficialAccountAd, this.client.toTransportInput(OP_ZaloAdsUpdateOfficialAccountAd, request), options);
2181
+ const targeting = payload.Settings?.Targeting;
2182
+ if (targeting) {
2183
+ const newAges = targeting.NewAgeRanges;
2184
+ const oldAges = targeting.AgeRanges;
2185
+ if (newAges && newAges.length > 0) {
2186
+ const validNewAgeKeys = ["13_17", "18_24", "25_34", "35_44", "45_54", "55_64", "65_plus", "10283", "10284", "10285", "10286", "10287", "10288"];
2187
+ const invalid = newAges.filter((a) => !validNewAgeKeys.includes(String(a)));
2188
+ if (invalid.length > 0) {
2189
+ warnings.push(`M\xE3 NewAgeRanges kh\xF4ng ph\u1ED5 bi\u1EBFn: ${invalid.join(", ")}.`);
2190
+ }
2191
+ } else if (oldAges && oldAges.length > 0) {
2192
+ const validAges = Object.values(ZaloAdsAgeRangeId);
2193
+ const invalidAges = oldAges.filter((a) => !validAges.includes(a));
2194
+ if (invalidAges.length > 0) {
2195
+ errors.push(`M\xE3 kho\u1EA3ng tu\u1ED5i kh\xF4ng h\u1EE3p l\u1EC7: ${invalidAges.join(", ")}. H\u1EE3p l\u1EC7: ${validAges.join(", ")}.`);
2196
+ }
2197
+ }
2198
+ const osList = targeting.Os || targeting.OsTypes;
2199
+ if (osList && osList.length > 0) {
2200
+ const validOs = [0, 1, 2, 3];
2201
+ const invalidOs = osList.filter((os) => !validOs.includes(Number(os)));
2202
+ if (invalidOs.length > 0) {
2203
+ 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).`);
2204
+ }
2205
+ }
2206
+ const deliveryType = payload.Settings?.DeliveryType;
2207
+ if (deliveryType !== void 0 && deliveryType !== ZaloAdsDeliveryType.STANDARD && deliveryType !== ZaloAdsDeliveryType.SPEED_UP) {
2208
+ warnings.push(
2209
+ "DeliveryType kh\xF4ng h\u1EE3p l\u1EC7. Gi\xE1 tr\u1ECB chu\u1EA9n: 0 (Ti\xEAu chu\u1EA9n / Standard) ho\u1EB7c 1 (T\u0103ng t\u1ED1c / SpeedUp)."
2210
+ );
2211
+ }
2212
+ const location = targeting.Location;
2213
+ if (location) {
2214
+ const container = location.WardTargeting || location.DistrictTargeting;
2215
+ if (container && Array.isArray(container.Includes)) {
2216
+ const validRegions = [1, 2, 3];
2217
+ for (const item of container.Includes) {
2218
+ if (!validRegions.includes(Number(item.Id))) {
2219
+ warnings.push(
2220
+ `M\xE3 v\xF9ng mi\u1EC1n (Id: ${item.Id}) kh\xF4ng h\u1EE3p l\u1EC7. C\xE1c m\xE3 v\xF9ng chu\u1EA9n: 1 (Mi\u1EC1n B\u1EAFc), 2 (Mi\u1EC1n Trung), 3 (Mi\u1EC1n Nam).`
2221
+ );
2222
+ }
2223
+ if (item.Provinces && !Array.isArray(item.Provinces)) {
2224
+ warnings.push(`Tr\u01B0\u1EDDng 'Provinces' trong v\xF9ng mi\u1EC1n Id=${item.Id} ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng t\u1EC9nh/th\xE0nh.`);
2225
+ } else if (Array.isArray(item.Provinces)) {
2226
+ for (const prov of item.Provinces) {
2227
+ if (!prov.Id || typeof prov.Id !== "string") {
2228
+ warnings.push(
2229
+ `M\xE3 t\u1EC9nh 'Id' (${JSON.stringify(prov)}) trong v\xF9ng mi\u1EC1n ${item.Id} ph\u1EA3i l\xE0 chu\u1ED7i h\u1EE3p l\u1EC7 (v\xED d\u1EE5: 'VN44', 'VN20').`
2230
+ );
2231
+ } else {
2232
+ const mergeInfo = ZALO_PROVINCE_MERGE_MAPPING[prov.Id];
2233
+ if (mergeInfo) {
2234
+ errors.push(
2235
+ `M\xE3 t\u1EC9nh '${prov.Id}' (${mergeInfo.name}) \u0111\xE3 \u0111\u01B0\u1EE3c Zalo Ads g\u1ED9p/s\xE1p nh\u1EADp v\xE0o c\u1EE5m m\xE3 '${mergeInfo.newCode}'. Vui l\xF2ng s\u1EED d\u1EE5ng m\xE3 c\u1EE5m '${mergeInfo.newCode}' trong WardTargeting, n\u1EBFu kh\xF4ng giao di\u1EC7n Zalo Ads Web s\u1EBD b\xE1o l\u1ED7i \u0111\u1ECF 'Invalid wards params'.`
2236
+ );
2237
+ } else {
2238
+ const validNewRegionProvs = ZALO_NEW_REGION_PROVINCE_CODES[Number(item.Id)] || [];
2239
+ if (!validNewRegionProvs.includes(prov.Id)) {
2240
+ const actualRegion = Object.keys(ZALO_NEW_REGION_PROVINCE_CODES).find((r) => ZALO_NEW_REGION_PROVINCE_CODES[Number(r)].includes(prov.Id));
2241
+ errors.push(
2242
+ `M\xE3 t\u1EC9nh '${prov.Id}' kh\xF4ng n\u1EB1m trong 34 C\u1EE5m T\u1EC9nh/Th\xE0nh m\u1EDBi c\u1EE7a V\xF9ng ${item.Id} tr\xEAn Zalo Ads (s\u1EBD g\xE2y l\u1ED7i 'Invalid wards params' tr\xEAn UI). ` + (actualRegion ? `M\xE3 n\xE0y thu\u1ED9c V\xF9ng ${actualRegion}. ` : "")
2243
+ );
2244
+ }
2245
+ }
2246
+ }
2247
+ if (prov.Districts && !Array.isArray(prov.Districts)) {
2248
+ warnings.push(`Tr\u01B0\u1EDDng 'Districts' c\u1EE7a t\u1EC9nh ${prov.Id} ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng (ho\u1EB7c [] khi ch\u1ECDn c\u1EA3 t\u1EC9nh).`);
2249
+ }
2250
+ }
2251
+ }
2252
+ }
2253
+ }
2254
+ }
2194
2255
  }
2195
- /** Alias theo tên tool chuẩn `zalo_ads_update_oa_ad` trong Project Schema Zalo ADS (`Type = 2`, `Action = 6`). */
2196
- updateOaAd(request, options) {
2197
- return this.updateOfficialAccountAd(request, options);
2256
+ if (payload.UseConversion !== void 0) {
2257
+ const validUseConversions = Object.values(ZaloAdsUseConversion);
2258
+ if (!validUseConversions.includes(payload.UseConversion)) {
2259
+ warnings.push(
2260
+ `UseConversion (${payload.UseConversion}) kh\xF4ng n\u1EB1m trong danh m\u1EE5c chu\u1EA9n: 0 (NOT_USE), 1 (USE), 2 (LADI_PAGE), 3 (MINI_APP), -1 (USE_OFF), -2 (LADI_PAGE_OFF), -3 (MINI_APP_OFF).`
2261
+ );
2262
+ }
2263
+ if (payload.UseConversion === ZaloAdsUseConversion.USE && (!payload.ConversionId || payload.ConversionId <= 0)) {
2264
+ warnings.push(
2265
+ "Khi ch\u1ECDn UseConversion = 1 (Pixel c\u1EE7a t\xF4i), n\xEAn c\u1EA5u h\xECnh ConversionId h\u1EE3p l\u1EC7 t\u1EEB danh s\xE1ch GET /api/conversion/all \u0111\u1EC3 thu\u1EADt to\xE1n m\xE1y h\u1ECDc Zalo Ads t\u1ED1i \u01B0u t\u1EF7 l\u1EC7 chuy\u1EC3n \u0111\u1ED5i."
2266
+ );
2267
+ }
2198
2268
  }
2199
- updatePostAd(request, options) {
2200
- return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdatePostAd, this.client.toTransportInput(OP_ZaloAdsUpdatePostAd, request), options);
2269
+ if (payload.Type === VALID_AD_TYPES.FORM) {
2270
+ if (!payload.ZaloFormId || !payload.ZaloFormId.trim()) {
2271
+ errors.push("ZaloFormId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Form (Ad Type 18).");
2272
+ }
2273
+ } else if (payload.Type === VALID_AD_TYPES.MESSAGE) {
2274
+ if (!payload.Settings?.Image?.LogoUrl) {
2275
+ 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).");
2276
+ }
2277
+ if (!payload.MiniPageId || payload.MiniPageId <= 0) {
2278
+ errors.push(
2279
+ "MiniPageId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn (Ad Type 30, Template 4 - K\u1ECBch b\u1EA3n gi\u1EDBi thi\u1EC7u th\u01B0\u01A1ng hi\u1EC7u / Tin nh\u1EAFn). N\u1EBFu thi\u1EBFu ho\u1EB7c = 0, m\xE1y ch\u1EE7 Zalo Ads s\u1EBD t\u1EEB ch\u1ED1i v\u1EDBi l\u1ED7i: 'Mini Page kh\xF4ng h\u1EE3p l\u1EC7.'."
2280
+ );
2281
+ }
2282
+ if (!payload.ZaloFlowId) {
2283
+ warnings.push("Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn n\xEAn g\u1EAFn ZaloFlowId \u0111\u1EC3 t\u1EF1 \u0111\u1ED9ng k\xEDch ho\u1EA1t k\u1ECBch b\u1EA3n chatbot t\u01B0\u01A1ng t\xE1c khi ng\u01B0\u1EDDi d\xF9ng m\u1EDF tin nh\u1EAFn.");
2284
+ }
2285
+ if (payload.Settings?.Image?.ExtraImgs && payload.Settings?.Image?.ExtraImgs.length > 0) {
2286
+ errors.push(
2287
+ "Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn \u0111\u1ECBnh d\u1EA1ng \u1EA3nh \u0111\u01A1n (Landscape Cover) kh\xF4ng \u0111\u01B0\u1EE3c truy\u1EC1n m\u1EA3ng 'ExtraImgs'. N\u1EBFu truy\u1EC1n th\u1EEBa s\u1EBD b\u1ECB m\xE1y ch\u1EE7 b\xE1o l\u1ED7i 'D\u1EEF li\u1EC7u kh\xF4ng h\u1EE3p l\u1EC7'."
2288
+ );
2289
+ }
2290
+ } else if (payload.Type === VALID_AD_TYPES.COMMERCE) {
2291
+ if (!payload.MiniPageId || payload.MiniPageId <= 0) {
2292
+ 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).");
2293
+ }
2294
+ } else if (payload.Type === VALID_AD_TYPES.VIDEO) {
2295
+ if (!payload.ZaloVideoId && !payload.Settings?.Image?.VideoUrl) {
2296
+ 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).");
2297
+ }
2298
+ if (payload.Settings?.Image?.VideoUrl && !payload.Settings.Image.VideoUrl.includes("zascdn.me")) {
2299
+ warnings.push("VideoUrl n\xEAn l\xE0 \u0111\u01B0\u1EDDng d\u1EABn CDN ch\xEDnh th\u1EE9c c\u1EE7a Zalo Ads (*.zascdn.me).");
2300
+ }
2301
+ } else if (payload.Type === VALID_AD_TYPES.ARTICLE) {
2302
+ if (!payload.ZaloFeedId && !payload.articleId) {
2303
+ 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).");
2304
+ }
2201
2305
  }
2202
- /** Alias theo tên tool chuẩn `zalo_ads_update_article_ad` trong Project Schema Zalo ADS (`Type = 3`, gắn `ZaloFeedId`). */
2203
- updateArticleAd(request, options) {
2204
- return this.updatePostAd(request, options);
2306
+ return {
2307
+ isValid: errors.length === 0,
2308
+ errors,
2309
+ warnings
2310
+ };
2311
+ }
2312
+ function validateRenameCampaignParams(params) {
2313
+ const errors = [];
2314
+ const warnings = [];
2315
+ const id = params.campid || params.campaignId;
2316
+ const name = params.newname || params.newName || params.name;
2317
+ if (!id || id <= 0) {
2318
+ errors.push("ID chi\u1EBFn d\u1ECBch (campid/campaignId) l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i > 0.");
2205
2319
  }
2206
- /** Xóa quảng cáo */
2207
- deleteAd(...args) {
2208
- return this.postZaapiDeletead(...args);
2320
+ if (!name || !name.trim()) {
2321
+ 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.");
2322
+ } else if (name.length > 255) {
2323
+ errors.push(`T\xEAn chi\u1EBFn d\u1ECBch qu\xE1 d\xE0i (${name.length}/255 k\xFD t\u1EF1).`);
2209
2324
  }
2210
- /** Danh sách quận/huyện để nhắm mục tiêu */
2211
- getAllDistricts(...args) {
2212
- return this.getApiPlaceGetalldistricts(...args);
2325
+ return {
2326
+ isValid: errors.length === 0,
2327
+ errors,
2328
+ warnings
2329
+ };
2330
+ }
2331
+ function validateChangeCampaignStatusParams(params) {
2332
+ const errors = [];
2333
+ const warnings = [];
2334
+ if (!params.campaignId || params.campaignId <= 0) {
2335
+ errors.push("campaignId l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i > 0.");
2213
2336
  }
2214
- /** Kiểm tra chính tả văn bản quảng cáo */
2215
- getSpellCheckV2(...args) {
2216
- return this.getApiSpellCheckV2(...args);
2337
+ if (![0, 1, 2, -2].includes(params.status)) {
2338
+ errors.push(`status: ${params.status} kh\xF4ng h\u1EE3p l\u1EC7. C\xE1c tr\u1EA1ng th\xE1i h\u1EE3p l\u1EC7: 1 (B\u1EADt), 0 (T\u1EAFt), 2 (T\u1EA1m d\u1EEBng), -2 (X\xF3a).`);
2217
2339
  }
2218
- /**
2219
- * 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).
2220
- */
2221
- createSpellCheckV3Job(request, options) {
2222
- return this.client.requestJson(
2223
- OP_ZaloAdsCreateSpellCheckV3Job,
2224
- this.client.toTransportInput(OP_ZaloAdsCreateSpellCheckV3Job, request),
2225
- options
2340
+ if (params.status === 2 && params.isDraft) {
2341
+ warnings.push(
2342
+ "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)."
2226
2343
  );
2227
2344
  }
2228
- /**
2229
- * Lấy kết quả kiểm tra chính tả AI V3 theo jobId (GET /api/spell-check/v3/{jobId}).
2230
- */
2231
- getSpellCheckV3Job(request, options) {
2232
- return this.client.requestWithoutBody(
2233
- OP_ZaloAdsGetSpellCheckV3Job,
2234
- this.client.toTransportInput(OP_ZaloAdsGetSpellCheckV3Job, request),
2235
- options
2236
- );
2237
- }
2238
- /**
2239
- * 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).
2240
- * @param request Tiêu đề (title) và chú thích (caption) cần kiểm tra.
2241
- * @param pollIntervalMs Chu kỳ polling kiểm tra trạng thái (mặc định: 600ms).
2242
- * @param timeoutMs Thời gian chờ tối đa (mặc định: 15.000ms = 15 giây).
2243
- */
2244
- async checkSpellV3AndWait(request, pollIntervalMs = 600, timeoutMs = 15e3, options) {
2245
- const jobRes = await this.createSpellCheckV3Job(request, options);
2246
- const jobId = jobRes?.data?.jobId;
2247
- if (!jobId) {
2248
- throw new Error(`[SpellCheckV3] Kh\xF4ng nh\u1EADn \u0111\u01B0\u1EE3c jobId t\u1EEB Zalo Ads (code: ${jobRes?.code})`);
2249
- }
2250
- const startTime = Date.now();
2251
- while (Date.now() - startTime < timeoutMs) {
2252
- await new Promise((r) => setTimeout(r, pollIntervalMs));
2253
- const res = await this.getSpellCheckV3Job({ jobId }, options);
2254
- if (res?.data?.status === "COMPLETED") {
2255
- return res;
2256
- }
2257
- }
2258
- 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}`);
2259
- }
2260
- /**
2261
- * 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).
2262
- * 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.
2263
- */
2264
- duplicateAd(request, options) {
2265
- const payload = {
2266
- adid: request.adid ?? request.adId
2267
- };
2268
- return this.client.requestFormUrlEncoded(
2269
- OP_ZaloAdsDuplicateAd,
2270
- this.client.toTransportInput(OP_ZaloAdsDuplicateAd, payload),
2271
- options
2272
- );
2345
+ return {
2346
+ isValid: errors.length === 0,
2347
+ errors,
2348
+ warnings
2349
+ };
2350
+ }
2351
+ function validateDuplicateAdParams(params) {
2352
+ const errors = [];
2353
+ const warnings = [];
2354
+ const id = params.adid || params.adId;
2355
+ if (!id || id <= 0) {
2356
+ 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.");
2273
2357
  }
2358
+ return {
2359
+ isValid: errors.length === 0,
2360
+ errors,
2361
+ warnings
2362
+ };
2363
+ }
2364
+ var ZaloCampaignsValidator = {
2365
+ createCampaign: validateCreateCampaignPayload,
2366
+ updateAd: validateUpdateAdPayload,
2367
+ renameCampaign: validateRenameCampaignParams,
2368
+ changeStatus: validateChangeCampaignStatusParams,
2369
+ duplicateAd: validateDuplicateAdParams
2370
+ };
2371
+
2372
+ // src/services/campaigns.service.ts
2373
+ var OP_ZaloAdsUpdateVideoAd = {
2374
+ operationId: "ZaloAds_updateVideoAd",
2375
+ method: "POST",
2376
+ endpoint: "/zaapi/UpdateAd",
2377
+ baseUrl: "https://ads.zalo.me",
2378
+ binaryFields: [],
2379
+ pathFields: [],
2380
+ queryFields: [],
2381
+ headerFields: [],
2382
+ cookieFields: [],
2383
+ bodyFields: ["data", "est", "isBoostAd", "stt"]
2384
+ };
2385
+ var OP_ZaloAdsChangeCampaignStatus = {
2386
+ "operationId": "ZaloAds_changeCampaignStatus",
2387
+ "method": "POST",
2388
+ "endpoint": "/api/campaign/change-status",
2389
+ "baseUrl": "https://ads.zalo.me",
2390
+ "binaryFields": [],
2391
+ "pathFields": [],
2392
+ "queryFields": [],
2393
+ "headerFields": [],
2394
+ "cookieFields": [],
2395
+ "bodyFields": [
2396
+ "status",
2397
+ "campaignId"
2398
+ ]
2399
+ };
2400
+ var OP_ZaloAdsCreateEcommerceCampaign = {
2401
+ "operationId": "ZaloAds_createEcommerceCampaign",
2402
+ "method": "POST",
2403
+ "endpoint": "/zaapi/addNewCamp",
2404
+ "baseUrl": "https://ads.zalo.me",
2405
+ "binaryFields": [],
2406
+ "pathFields": [],
2407
+ "queryFields": [],
2408
+ "headerFields": [],
2409
+ "cookieFields": [],
2410
+ "bodyFields": [
2411
+ "data"
2412
+ ]
2413
+ };
2414
+ var OP_ZaloAdsCreateForm = {
2415
+ "operationId": "ZaloAds_createForm",
2416
+ "method": "POST",
2417
+ "endpoint": "/api/form/create",
2418
+ "baseUrl": "https://ads.zalo.me",
2419
+ "binaryFields": [],
2420
+ "pathFields": [],
2421
+ "queryFields": [],
2422
+ "headerFields": [],
2423
+ "cookieFields": [],
2424
+ "bodyFields": [
2425
+ "data"
2426
+ ]
2427
+ };
2428
+ var OP_ZaloAdsCreateFormCampaign = {
2429
+ "operationId": "ZaloAds_createFormCampaign",
2430
+ "method": "POST",
2431
+ "endpoint": "/zaapi/addNewCamp",
2432
+ "baseUrl": "https://ads.zalo.me",
2433
+ "binaryFields": [],
2434
+ "pathFields": [],
2435
+ "queryFields": [],
2436
+ "headerFields": [],
2437
+ "cookieFields": [],
2438
+ "bodyFields": [
2439
+ "data"
2440
+ ]
2441
+ };
2442
+ var OP_ZaloAdsCreateMessageCampaign = {
2443
+ "operationId": "ZaloAds_createMessageCampaign",
2444
+ "method": "POST",
2445
+ "endpoint": "/zaapi/addNewCamp",
2446
+ "baseUrl": "https://ads.zalo.me",
2447
+ "binaryFields": [],
2448
+ "pathFields": [],
2449
+ "queryFields": [],
2450
+ "headerFields": [],
2451
+ "cookieFields": [],
2452
+ "bodyFields": [
2453
+ "data"
2454
+ ]
2455
+ };
2456
+ var OP_ZaloAdsCreateOfficialAccountCampaign = {
2457
+ "operationId": "ZaloAds_createOfficialAccountCampaign",
2458
+ "method": "POST",
2459
+ "endpoint": "/zaapi/addNewCamp",
2460
+ "baseUrl": "https://ads.zalo.me",
2461
+ "binaryFields": [],
2462
+ "pathFields": [],
2463
+ "queryFields": [],
2464
+ "headerFields": [],
2465
+ "cookieFields": [],
2466
+ "bodyFields": [
2467
+ "data"
2468
+ ]
2469
+ };
2470
+ var OP_ZaloAdsCreatePostCampaign = {
2471
+ "operationId": "ZaloAds_createPostCampaign",
2472
+ "method": "POST",
2473
+ "endpoint": "/zaapi/addNewCamp",
2474
+ "baseUrl": "https://ads.zalo.me",
2475
+ "binaryFields": [],
2476
+ "pathFields": [],
2477
+ "queryFields": [],
2478
+ "headerFields": [],
2479
+ "cookieFields": [],
2480
+ "bodyFields": [
2481
+ "data"
2482
+ ]
2483
+ };
2484
+ var OP_ZaloAdsGetAdById = {
2485
+ "operationId": "ZaloAds_getAdById",
2486
+ "method": "GET",
2487
+ "endpoint": "/zaapi/getAdFromAdId",
2488
+ "baseUrl": "https://ads.zalo.me",
2489
+ "binaryFields": [],
2490
+ "pathFields": [],
2491
+ "queryFields": [
2492
+ "adId",
2493
+ "v",
2494
+ "newWard"
2495
+ ],
2496
+ "headerFields": [],
2497
+ "cookieFields": [],
2498
+ "bodyFields": []
2499
+ };
2500
+ var OP_ZaloAdsGetAdChangeLog = {
2501
+ "operationId": "ZaloAds_getAdChangeLog",
2502
+ "method": "GET",
2503
+ "endpoint": "/api/ad/log/{adId}",
2504
+ "baseUrl": "https://ads.zalo.me",
2505
+ "binaryFields": [],
2506
+ "pathFields": [
2507
+ "adId"
2508
+ ],
2509
+ "queryFields": [
2510
+ "type"
2511
+ ],
2512
+ "headerFields": [],
2513
+ "cookieFields": [],
2514
+ "bodyFields": []
2515
+ };
2516
+ var OP_ZaloAdsGetApiPlaceGetalldistricts = {
2517
+ "operationId": "ZaloAds_getApiPlaceGetalldistricts",
2518
+ "method": "GET",
2519
+ "endpoint": "/api/place/getAllDistricts",
2520
+ "baseUrl": "https://ads.zalo.me",
2521
+ "binaryFields": [],
2522
+ "pathFields": [],
2523
+ "queryFields": [],
2524
+ "headerFields": [],
2525
+ "cookieFields": [],
2526
+ "bodyFields": []
2527
+ };
2528
+ var OP_ZaloAdsGetApiSpellCheckV2 = {
2529
+ "operationId": "ZaloAds_getApiSpellCheckV2",
2530
+ "method": "GET",
2531
+ "endpoint": "/api/spell-check/v2",
2532
+ "baseUrl": "https://ads.zalo.me",
2533
+ "binaryFields": [],
2534
+ "pathFields": [],
2535
+ "queryFields": [
2536
+ "text"
2537
+ ],
2538
+ "headerFields": [],
2539
+ "cookieFields": [],
2540
+ "bodyFields": []
2541
+ };
2542
+ var OP_ZaloAdsGetZaapiCheckcamphasmanyads = {
2543
+ "operationId": "ZaloAds_getZaapiCheckcamphasmanyads",
2544
+ "method": "GET",
2545
+ "endpoint": "/zaapi/checkCampHasManyAds",
2546
+ "baseUrl": "https://ads.zalo.me",
2547
+ "binaryFields": [],
2548
+ "pathFields": [],
2549
+ "queryFields": [
2550
+ "campaignId",
2551
+ "campId"
2552
+ ],
2553
+ "headerFields": [],
2554
+ "cookieFields": [],
2555
+ "bodyFields": []
2556
+ };
2557
+ var OP_ZaloAdsGetZaapiGetadsfromcampaignid = {
2558
+ "operationId": "ZaloAds_getZaapiGetadsfromcampaignid",
2559
+ "method": "GET",
2560
+ "endpoint": "/zaapi/getAdsFromCampaignId",
2561
+ "baseUrl": "https://ads.zalo.me",
2562
+ "binaryFields": [],
2563
+ "pathFields": [],
2564
+ "queryFields": [
2565
+ "campaignId",
2566
+ "campId",
2567
+ "dataType",
2568
+ "v"
2569
+ ],
2570
+ "headerFields": [],
2571
+ "cookieFields": [],
2572
+ "bodyFields": []
2573
+ };
2574
+ var OP_ZaloAdsGetZaapiGetallpages = {
2575
+ "operationId": "ZaloAds_getZaapiGetallpages",
2576
+ "method": "GET",
2577
+ "endpoint": "/zaapi/getAllPages",
2578
+ "baseUrl": "https://ads.zalo.me",
2579
+ "binaryFields": [],
2580
+ "pathFields": [],
2581
+ "queryFields": [],
2582
+ "headerFields": [],
2583
+ "cookieFields": [],
2584
+ "bodyFields": []
2585
+ };
2586
+ var OP_ZaloAdsGetZaapiGetownedarticles = {
2587
+ "operationId": "ZaloAds_getZaapiGetownedarticles",
2588
+ "method": "GET",
2589
+ "endpoint": "/zaapi/getOwnedArticles",
2590
+ "baseUrl": "https://ads.zalo.me",
2591
+ "binaryFields": [],
2592
+ "pathFields": [],
2593
+ "queryFields": [
2594
+ "pageId"
2595
+ ],
2596
+ "headerFields": [],
2597
+ "cookieFields": [],
2598
+ "bodyFields": []
2599
+ };
2600
+ var OP_ZaloAdsGetZaapiGetownedpages = {
2601
+ "operationId": "ZaloAds_getZaapiGetownedpages",
2602
+ "method": "GET",
2603
+ "endpoint": "/zaapi/getOwnedPages",
2604
+ "baseUrl": "https://ads.zalo.me",
2605
+ "binaryFields": [],
2606
+ "pathFields": [],
2607
+ "queryFields": [],
2608
+ "headerFields": [],
2609
+ "cookieFields": [],
2610
+ "bodyFields": []
2611
+ };
2612
+ var OP_ZaloAdsListFormsByOfficialAccount = {
2613
+ "operationId": "ZaloAds_listFormsByOfficialAccount",
2614
+ "method": "GET",
2615
+ "endpoint": "/api/form/getByOaId",
2616
+ "baseUrl": "https://ads.zalo.me",
2617
+ "binaryFields": [],
2618
+ "pathFields": [],
2619
+ "queryFields": [
2620
+ "oaId",
2621
+ "isAll"
2622
+ ],
2623
+ "headerFields": [],
2624
+ "cookieFields": [],
2625
+ "bodyFields": []
2626
+ };
2627
+ var OP_ZaloAdsListMiniPagesByTemplate = {
2628
+ "operationId": "ZaloAds_listMiniPagesByTemplate",
2629
+ "method": "GET",
2630
+ "endpoint": "/api/mini-pages",
2631
+ "baseUrl": "https://ads.zalo.me",
2632
+ "binaryFields": [],
2633
+ "pathFields": [],
2634
+ "queryFields": [
2635
+ "templateIds"
2636
+ ],
2637
+ "headerFields": [],
2638
+ "cookieFields": [],
2639
+ "bodyFields": []
2640
+ };
2641
+ var OP_ZaloAdsPostZaapiDeletead = {
2642
+ "operationId": "ZaloAds_postZaapiDeletead",
2643
+ "method": "POST",
2644
+ "endpoint": "/zaapi/deleteAd",
2645
+ "baseUrl": "https://ads.zalo.me",
2646
+ "binaryFields": [],
2647
+ "pathFields": [],
2648
+ "queryFields": [
2649
+ "adId"
2650
+ ],
2651
+ "headerFields": [],
2652
+ "cookieFields": [],
2653
+ "bodyFields": [
2654
+ "adId"
2655
+ ]
2656
+ };
2657
+ var OP_ZaloAdsRenameCampaign = {
2658
+ "operationId": "ZaloAds_renameCampaign",
2659
+ "method": "POST",
2660
+ "endpoint": "/api/campaign/change-name",
2661
+ "baseUrl": "https://ads.zalo.me",
2662
+ "binaryFields": [],
2663
+ "pathFields": [],
2664
+ "queryFields": [],
2665
+ "headerFields": [],
2666
+ "cookieFields": [],
2667
+ "bodyFields": [
2668
+ "campid",
2669
+ "newname"
2670
+ ]
2671
+ };
2672
+ var OP_ZaloAdsUpdateEcommerceAd = {
2673
+ "operationId": "ZaloAds_updateEcommerceAd",
2674
+ "method": "POST",
2675
+ "endpoint": "/zaapi/UpdateAd",
2676
+ "baseUrl": "https://ads.zalo.me",
2677
+ "binaryFields": [],
2678
+ "pathFields": [],
2679
+ "queryFields": [],
2680
+ "headerFields": [],
2681
+ "cookieFields": [],
2682
+ "bodyFields": [
2683
+ "est",
2684
+ "stt",
2685
+ "data",
2686
+ "isBoostAd"
2687
+ ]
2274
2688
  };
2275
-
2276
- // src/services/account.service.ts
2277
- var OP_ZaloAdsGetApiWhoami = {
2278
- "operationId": "ZaloAds_getApiWhoami",
2279
- "method": "GET",
2280
- "endpoint": "/api/whoami",
2689
+ var OP_ZaloAdsUpdateFormAd = {
2690
+ "operationId": "ZaloAds_updateFormAd",
2691
+ "method": "POST",
2692
+ "endpoint": "/zaapi/UpdateAd",
2281
2693
  "baseUrl": "https://ads.zalo.me",
2282
2694
  "binaryFields": [],
2283
2695
  "pathFields": [],
2284
2696
  "queryFields": [],
2285
2697
  "headerFields": [],
2286
2698
  "cookieFields": [],
2287
- "bodyFields": []
2699
+ "bodyFields": [
2700
+ "est",
2701
+ "stt",
2702
+ "data",
2703
+ "isBoostAd"
2704
+ ]
2288
2705
  };
2289
- var OP_ZaloAdsGetApiPaymentTransactionHistory = {
2290
- "operationId": "ZaloAds_getApiPaymentTransactionHistory",
2291
- "method": "GET",
2292
- "endpoint": "/api/payment/transaction-history",
2706
+ var OP_ZaloAdsUpdateMessageAd = {
2707
+ "operationId": "ZaloAds_updateMessageAd",
2708
+ "method": "POST",
2709
+ "endpoint": "/zaapi/UpdateAd",
2293
2710
  "baseUrl": "https://ads.zalo.me",
2294
2711
  "binaryFields": [],
2295
2712
  "pathFields": [],
2296
- "queryFields": [
2297
- "to",
2298
- "from",
2299
- "memberId"
2713
+ "queryFields": [],
2714
+ "headerFields": [],
2715
+ "cookieFields": [],
2716
+ "bodyFields": [
2717
+ "est",
2718
+ "stt",
2719
+ "data",
2720
+ "isBoostAd"
2721
+ ]
2722
+ };
2723
+ var OP_ZaloAdsUpdateNewAds = {
2724
+ "operationId": "ZaloAds_UpdateNewAds",
2725
+ "method": "POST",
2726
+ "endpoint": "/zaapi/UploadCrop",
2727
+ "baseUrl": "https://ads.zalo.me",
2728
+ "binaryFields": [
2729
+ "File"
2300
2730
  ],
2731
+ "pathFields": [],
2732
+ "queryFields": [],
2301
2733
  "headerFields": [],
2302
2734
  "cookieFields": [],
2303
- "bodyFields": []
2735
+ "bodyFields": [
2736
+ "File",
2737
+ "x",
2738
+ "y",
2739
+ "width",
2740
+ "height",
2741
+ "scale"
2742
+ ]
2304
2743
  };
2305
- var OP_ZaloAdsGetApiBaAccountAllaccessors = {
2306
- "operationId": "ZaloAds_getApiBaAccountAllaccessors",
2307
- "method": "GET",
2308
- "endpoint": "/api/ba/account/allAccessors",
2744
+ var OP_ZaloAdsUpdateOfficialAccountAd = {
2745
+ "operationId": "ZaloAds_updateOfficialAccountAd",
2746
+ "method": "POST",
2747
+ "endpoint": "/zaapi/UpdateAd",
2309
2748
  "baseUrl": "https://ads.zalo.me",
2310
2749
  "binaryFields": [],
2311
2750
  "pathFields": [],
2312
- "queryFields": [
2313
- "isShowAll"
2314
- ],
2751
+ "queryFields": [],
2315
2752
  "headerFields": [],
2316
2753
  "cookieFields": [],
2317
- "bodyFields": []
2754
+ "bodyFields": [
2755
+ "est",
2756
+ "stt",
2757
+ "data",
2758
+ "isBoostAd"
2759
+ ]
2318
2760
  };
2319
- var OP_ZaloAdsGetApiBaAccountAllgrantedmembers = {
2320
- "operationId": "ZaloAds_getApiBaAccountAllgrantedmembers",
2321
- "method": "GET",
2322
- "endpoint": "/api/ba/account/allGrantedMembers",
2761
+ var OP_ZaloAdsUpdatePostAd = {
2762
+ "operationId": "ZaloAds_updatePostAd",
2763
+ "method": "POST",
2764
+ "endpoint": "/zaapi/UpdateAd",
2323
2765
  "baseUrl": "https://ads.zalo.me",
2324
2766
  "binaryFields": [],
2325
2767
  "pathFields": [],
2326
2768
  "queryFields": [],
2327
2769
  "headerFields": [],
2328
2770
  "cookieFields": [],
2329
- "bodyFields": []
2771
+ "bodyFields": [
2772
+ "est",
2773
+ "stt",
2774
+ "data",
2775
+ "isBoostAd"
2776
+ ]
2330
2777
  };
2331
- var OP_ZaloAdsListAgencyCustomersWithBudget = {
2332
- "operationId": "ZaloAds_listAgencyCustomersWithBudget",
2333
- "method": "GET",
2334
- "endpoint": "/api/ba/agency/customersWithBudget",
2778
+ var OP_ZaloAdsCreateWebsiteCampaign = {
2779
+ "operationId": "ZaloAds_createWebsiteCampaign",
2780
+ "method": "POST",
2781
+ "endpoint": "/zaapi/addNewCamp",
2335
2782
  "baseUrl": "https://ads.zalo.me",
2336
2783
  "binaryFields": [],
2337
2784
  "pathFields": [],
2338
- "queryFields": [
2339
- "limit",
2340
- "offset",
2341
- "joinDateAsc"
2342
- ],
2785
+ "queryFields": [],
2343
2786
  "headerFields": [],
2344
2787
  "cookieFields": [],
2345
- "bodyFields": []
2788
+ "bodyFields": [
2789
+ "data"
2790
+ ]
2346
2791
  };
2347
- var OP_ZaloAdsGetApiNotifiesHeader = {
2348
- "operationId": "ZaloAds_getApiNotifiesHeader",
2349
- "method": "GET",
2350
- "endpoint": "/api/notifies/header",
2792
+ var OP_ZaloAdsUpdateWebsiteAd = {
2793
+ "operationId": "ZaloAds_updateWebsiteAd",
2794
+ "method": "POST",
2795
+ "endpoint": "/zaapi/UpdateAd",
2351
2796
  "baseUrl": "https://ads.zalo.me",
2352
2797
  "binaryFields": [],
2353
2798
  "pathFields": [],
2354
2799
  "queryFields": [],
2355
2800
  "headerFields": [],
2356
2801
  "cookieFields": [],
2357
- "bodyFields": []
2802
+ "bodyFields": [
2803
+ "est",
2804
+ "stt",
2805
+ "data",
2806
+ "isBoostAd"
2807
+ ]
2358
2808
  };
2359
- var OP_ZaloAdsGetApiLpNews = {
2360
- "operationId": "ZaloAds_getApiLpNews",
2361
- "method": "GET",
2362
- "endpoint": "/api/lp-news",
2809
+ var OP_ZaloAdsCreateDisplayCampaign = {
2810
+ "operationId": "ZaloAds_createDisplayCampaign",
2811
+ "method": "POST",
2812
+ "endpoint": "/zaapi/addNewCamp",
2363
2813
  "baseUrl": "https://ads.zalo.me",
2364
2814
  "binaryFields": [],
2365
2815
  "pathFields": [],
2366
2816
  "queryFields": [],
2367
2817
  "headerFields": [],
2368
2818
  "cookieFields": [],
2369
- "bodyFields": []
2819
+ "bodyFields": [
2820
+ "data"
2821
+ ]
2370
2822
  };
2371
- var ZaloAccountService = class {
2823
+ var OP_ZaloAdsUpdateDisplayAd = {
2824
+ "operationId": "ZaloAds_updateDisplayAd",
2825
+ "method": "POST",
2826
+ "endpoint": "/zaapi/UpdateAd",
2827
+ "baseUrl": "https://ads.zalo.me",
2828
+ "binaryFields": [],
2829
+ "pathFields": [],
2830
+ "queryFields": [],
2831
+ "headerFields": [],
2832
+ "cookieFields": [],
2833
+ "bodyFields": [
2834
+ "est",
2835
+ "stt",
2836
+ "data",
2837
+ "isBoostAd"
2838
+ ]
2839
+ };
2840
+ var OP_ZaloAdsCreateVideoCampaign = {
2841
+ "operationId": "ZaloAds_createVideoCampaign",
2842
+ "method": "POST",
2843
+ "endpoint": "/zaapi/addNewCamp",
2844
+ "baseUrl": "https://ads.zalo.me",
2845
+ "binaryFields": [],
2846
+ "pathFields": [],
2847
+ "queryFields": [],
2848
+ "headerFields": [],
2849
+ "cookieFields": [],
2850
+ "bodyFields": [
2851
+ "data"
2852
+ ]
2853
+ };
2854
+ var OP_ZaloAdsDeleteCampaign = {
2855
+ "operationId": "ZaloAds_deleteCampaign",
2856
+ "method": "POST",
2857
+ "endpoint": "/api/campaign/change-status",
2858
+ "baseUrl": "https://ads.zalo.me",
2859
+ "binaryFields": [],
2860
+ "pathFields": [],
2861
+ "queryFields": [],
2862
+ "headerFields": [],
2863
+ "cookieFields": [],
2864
+ "bodyFields": [
2865
+ "campaignId",
2866
+ "status"
2867
+ ]
2868
+ };
2869
+ var OP_ZaloAdsDuplicateAd = {
2870
+ operationId: "zalo_ads_duplicate_ad",
2871
+ method: "POST",
2872
+ endpoint: "/zaapi/DuplicateAd",
2873
+ baseUrl: "https://ads.zalo.me",
2874
+ binaryFields: [],
2875
+ pathFields: [],
2876
+ queryFields: [],
2877
+ headerFields: [],
2878
+ cookieFields: [],
2879
+ bodyFields: ["adid"]
2880
+ };
2881
+ var OP_ZaloAdsCreateSpellCheckV3Job = {
2882
+ operationId: "zalo_ads_create_spell_check_v3_job",
2883
+ method: "POST",
2884
+ endpoint: "/api/spell-check/v3",
2885
+ baseUrl: "https://ads.zalo.me",
2886
+ binaryFields: [],
2887
+ pathFields: [],
2888
+ queryFields: [],
2889
+ headerFields: [],
2890
+ cookieFields: [],
2891
+ bodyFields: ["title", "caption"]
2892
+ };
2893
+ var OP_ZaloAdsGetSpellCheckV3Job = {
2894
+ operationId: "zalo_ads_get_spell_check_v3_job",
2895
+ method: "GET",
2896
+ endpoint: "/api/spell-check/v3/{jobId}",
2897
+ baseUrl: "https://ads.zalo.me",
2898
+ binaryFields: [],
2899
+ pathFields: ["jobId"],
2900
+ queryFields: [],
2901
+ headerFields: [],
2902
+ cookieFields: [],
2903
+ bodyFields: []
2904
+ };
2905
+ var ZaloCampaignsService = class {
2372
2906
  constructor(client) {
2373
2907
  this.client = client;
2374
2908
  }
2375
- getApiWhoami(request = {}, options) {
2376
- return this.client.requestWithoutBody(OP_ZaloAdsGetApiWhoami, this.client.toTransportInput(OP_ZaloAdsGetApiWhoami, request), options);
2909
+ validator = ZaloCampaignsValidator;
2910
+ static validator = ZaloCampaignsValidator;
2911
+ updateVideoAd(request, options) {
2912
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateVideoAd, this.client.toTransportInput(OP_ZaloAdsUpdateVideoAd, request), options);
2913
+ }
2914
+ changeCampaignStatus(request, options) {
2915
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsChangeCampaignStatus, this.client.toTransportInput(OP_ZaloAdsChangeCampaignStatus, request), options);
2916
+ }
2917
+ deleteCampaign(request, options) {
2918
+ const payload = { campaignId: request.campaignId, status: request.status ?? -2 };
2919
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsDeleteCampaign, this.client.toTransportInput(OP_ZaloAdsDeleteCampaign, payload), options);
2920
+ }
2921
+ createWebsiteCampaign(request, options) {
2922
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateWebsiteCampaign, this.client.toTransportInput(OP_ZaloAdsCreateWebsiteCampaign, request), options);
2923
+ }
2924
+ updateWebsiteAd(request, options) {
2925
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateWebsiteAd, this.client.toTransportInput(OP_ZaloAdsUpdateWebsiteAd, request), options);
2926
+ }
2927
+ createDisplayCampaign(request, options) {
2928
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateDisplayCampaign, this.client.toTransportInput(OP_ZaloAdsCreateDisplayCampaign, request), options);
2929
+ }
2930
+ updateDisplayAd(request, options) {
2931
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateDisplayAd, this.client.toTransportInput(OP_ZaloAdsUpdateDisplayAd, request), options);
2932
+ }
2933
+ createVideoCampaign(request, options) {
2934
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateVideoCampaign, this.client.toTransportInput(OP_ZaloAdsCreateVideoCampaign, request), options);
2935
+ }
2936
+ createEcommerceCampaign(request, options) {
2937
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateEcommerceCampaign, this.client.toTransportInput(OP_ZaloAdsCreateEcommerceCampaign, request), options);
2938
+ }
2939
+ /** Alias theo tên tool chuẩn `zalo_ads_create_commerce_campaign` trong Project Schema Zalo ADS (`campaignType = 22`). */
2940
+ createCommerceCampaign(request, options) {
2941
+ return this.createEcommerceCampaign(request, options);
2377
2942
  }
2378
- getApiPaymentTransactionHistory(request, options) {
2379
- return this.client.requestWithoutBody(OP_ZaloAdsGetApiPaymentTransactionHistory, this.client.toTransportInput(OP_ZaloAdsGetApiPaymentTransactionHistory, request), options);
2943
+ createForm(request, options) {
2944
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateForm, this.client.toTransportInput(OP_ZaloAdsCreateForm, request), options);
2380
2945
  }
2381
- getApiBaAccountAllaccessors(request = {}, options) {
2382
- return this.client.requestWithoutBody(OP_ZaloAdsGetApiBaAccountAllaccessors, this.client.toTransportInput(OP_ZaloAdsGetApiBaAccountAllaccessors, request), options);
2946
+ createFormCampaign(request, options) {
2947
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateFormCampaign, this.client.toTransportInput(OP_ZaloAdsCreateFormCampaign, request), options);
2383
2948
  }
2384
- getApiBaAccountAllgrantedmembers(request = {}, options) {
2385
- return this.client.requestWithoutBody(OP_ZaloAdsGetApiBaAccountAllgrantedmembers, this.client.toTransportInput(OP_ZaloAdsGetApiBaAccountAllgrantedmembers, request), options);
2949
+ createMessageCampaign(request, options) {
2950
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateMessageCampaign, this.client.toTransportInput(OP_ZaloAdsCreateMessageCampaign, request), options);
2386
2951
  }
2387
- listAgencyCustomersWithBudget(request = { limit: 15, offset: 0, joinDateAsc: true }, options) {
2388
- const normalized = {
2389
- limit: 15,
2390
- offset: 0,
2391
- joinDateAsc: true,
2392
- ...request
2393
- };
2394
- return this.client.requestWithoutBody(OP_ZaloAdsListAgencyCustomersWithBudget, this.client.toTransportInput(OP_ZaloAdsListAgencyCustomersWithBudget, normalized), options);
2952
+ createOfficialAccountCampaign(request, options) {
2953
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateOfficialAccountCampaign, this.client.toTransportInput(OP_ZaloAdsCreateOfficialAccountCampaign, request), options);
2395
2954
  }
2396
- getApiNotifiesHeader(request = {}, options) {
2397
- return this.client.requestWithoutBody(OP_ZaloAdsGetApiNotifiesHeader, this.client.toTransportInput(OP_ZaloAdsGetApiNotifiesHeader, request), options);
2955
+ /** Alias theo tên tool chuẩn `zalo_ads_create_oa_campaign` trong Project Schema Zalo ADS (`campaignType = 3`). */
2956
+ createOaCampaign(request, options) {
2957
+ return this.createOfficialAccountCampaign(request, options);
2398
2958
  }
2399
- getApiLpNews(request = {}, options) {
2400
- return this.client.requestWithoutBody(OP_ZaloAdsGetApiLpNews, this.client.toTransportInput(OP_ZaloAdsGetApiLpNews, request), options);
2959
+ createPostCampaign(request, options) {
2960
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsCreatePostCampaign, this.client.toTransportInput(OP_ZaloAdsCreatePostCampaign, request), options);
2401
2961
  }
2402
- /** Lấy thông tin tài khoản đang đăng nhập */
2403
- getWhoami(...args) {
2404
- return this.getApiWhoami(...args);
2962
+ /** Alias theo tên tool chuẩn `zalo_ads_create_article_campaign` trong Project Schema Zalo ADS (`campaignType = 4`). */
2963
+ createArticleCampaign(request, options) {
2964
+ return this.createPostCampaign(request, options);
2405
2965
  }
2406
- /** Lịch sử giao dịch thanh toán */
2407
- getPaymentTransactionHistory(...args) {
2408
- return this.getApiPaymentTransactionHistory(...args);
2966
+ getAdById(request = {}, options) {
2967
+ const normalized = {
2968
+ adId: request.adId,
2969
+ v: request.v ?? 2,
2970
+ newWard: request.newWard ?? true
2971
+ };
2972
+ return this.client.requestWithoutBody(OP_ZaloAdsGetAdById, this.client.toTransportInput(OP_ZaloAdsGetAdById, normalized), options);
2409
2973
  }
2410
- /** Danh sách accessor tài khoản BA */
2411
- getBaAccountAllAccessors(...args) {
2412
- return this.getApiBaAccountAllaccessors(...args);
2974
+ getAdChangeLog(request, options) {
2975
+ const normalized = {
2976
+ adId: request.adId,
2977
+ type: request.type ?? 1
2978
+ };
2979
+ return this.client.requestWithoutBody(OP_ZaloAdsGetAdChangeLog, this.client.toTransportInput(OP_ZaloAdsGetAdChangeLog, normalized), options);
2413
2980
  }
2414
- /** Danh sách thành viên được cấp quyền BA */
2415
- getBaAccountAllGrantedMembers(...args) {
2416
- return this.getApiBaAccountAllgrantedmembers(...args);
2981
+ getApiPlaceGetalldistricts(request = {}, options) {
2982
+ return this.client.requestWithoutBody(OP_ZaloAdsGetApiPlaceGetalldistricts, this.client.toTransportInput(OP_ZaloAdsGetApiPlaceGetalldistricts, request), options);
2417
2983
  }
2418
- /** Thông báo trên thanh tiêu đề */
2419
- getNotifiesHeader(...args) {
2420
- return this.getApiNotifiesHeader(...args);
2984
+ getApiSpellCheckV2(request, options) {
2985
+ return this.client.requestWithoutBody(OP_ZaloAdsGetApiSpellCheckV2, this.client.toTransportInput(OP_ZaloAdsGetApiSpellCheckV2, request), options);
2421
2986
  }
2422
- /** Tin tức landing page / bảng tin */
2423
- getLpNews(...args) {
2424
- return this.getApiLpNews(...args);
2987
+ getZaapiCheckcamphasmanyads(request = {}, options) {
2988
+ return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiCheckcamphasmanyads, this.client.toTransportInput(OP_ZaloAdsGetZaapiCheckcamphasmanyads, request), options);
2425
2989
  }
2426
- };
2427
-
2428
- // src/validators/audiences.validator.ts
2429
- function validateCreateSavedAudienceRequest(input) {
2430
- const errors = [];
2431
- if (!input || typeof input !== "object") {
2432
- return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
2990
+ getZaapiGetadsfromcampaignid(request = {}, options) {
2991
+ const normalized = {
2992
+ campaignId: request.campaignId ?? request.campId,
2993
+ dataType: request.dataType ?? 1,
2994
+ v: request.v ?? 2
2995
+ };
2996
+ return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetadsfromcampaignid, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetadsfromcampaignid, normalized), options);
2433
2997
  }
2434
- const raw = input;
2435
- const name = typeof raw.name === "string" ? raw.name.trim() : "";
2436
- if (!name) {
2437
- errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' l\xE0 b\u1EAFt bu\u1ED9c.");
2438
- } else if (name.length < 2 || name.length > 255) {
2439
- errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
2998
+ /** Alias lấy danh sách quảng cáo của chiến dịch kèm metadata extend và extra.appliedRuleInfo */
2999
+ getAdsFromCampaignId(request = {}, options) {
3000
+ return this.getZaapiGetadsfromcampaignid(request, options);
2440
3001
  }
2441
- let targetingObj;
2442
- if (typeof raw.targeting === "string") {
2443
- try {
2444
- targetingObj = JSON.parse(raw.targeting);
2445
- } catch {
2446
- errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
2447
- targetingObj = {};
2448
- }
2449
- } else if (raw.targeting && typeof raw.targeting === "object") {
2450
- targetingObj = raw.targeting;
2451
- } else {
2452
- errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c (chu\u1ED7i JSON ho\u1EB7c Object c\u1EA5u h\xECnh targeting).");
2453
- targetingObj = {};
3002
+ getZaapiGetallpages(request = {}, options) {
3003
+ return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetallpages, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetallpages, request), options);
2454
3004
  }
2455
- const gender = typeof targetingObj.Gender === "number" ? targetingObj.Gender : 0;
2456
- if (![0, 1, 2].includes(gender)) {
2457
- errors.push("Tr\u01B0\u1EDDng 'Gender' ph\u1EA3i l\xE0 0 (T\u1EA5t c\u1EA3), 1 (Nam), ho\u1EB7c 2 (N\u1EEF).");
3005
+ getAllPages(request = {}, options) {
3006
+ return this.getZaapiGetallpages(request, options);
2458
3007
  }
2459
- const VALID_AGE_RANGES = [10282, 10283, 10284, 10285, 10286, 10287, 10288];
2460
- const newAgeRanges = Array.isArray(targetingObj.NewAgeRanges) && targetingObj.NewAgeRanges.length > 0 ? targetingObj.NewAgeRanges.map(Number) : VALID_AGE_RANGES;
2461
- for (const age of newAgeRanges) {
2462
- if (!VALID_AGE_RANGES.includes(age)) {
2463
- 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(", ")}.`);
2464
- }
3008
+ getZaapiGetownedarticles(request, options) {
3009
+ return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetownedarticles, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetownedarticles, request), options);
2465
3010
  }
2466
- const VALID_OS = [0, 1, 2, 3];
2467
- const os = Array.isArray(targetingObj.Os) && targetingObj.Os.length > 0 ? targetingObj.Os.map(Number) : [0, 1, 3];
2468
- for (const o of os) {
2469
- if (!VALID_OS.includes(o)) {
2470
- 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).`);
2471
- }
3011
+ getOwnedArticles(request, options) {
3012
+ return this.getZaapiGetownedarticles(request, options);
2472
3013
  }
2473
- let location = targetingObj.Location;
2474
- if (!location || typeof location !== "object") {
2475
- location = {
2476
- Addresses: [],
2477
- Cities: [],
2478
- WardTargeting: { Includes: [], Excludes: [] }
2479
- };
2480
- } else {
2481
- location = {
2482
- Addresses: Array.isArray(location.Addresses) ? location.Addresses : [],
2483
- Cities: Array.isArray(location.Cities) ? location.Cities : [],
2484
- WardTargeting: location.WardTargeting && typeof location.WardTargeting === "object" ? location.WardTargeting : { Includes: [], Excludes: [] }
2485
- };
2486
- if (location.WardTargeting.Includes && !Array.isArray(location.WardTargeting.Includes)) {
2487
- errors.push("Tr\u01B0\u1EDDng 'Location.WardTargeting.Includes' ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng khu v\u1EF1c.");
2488
- } else if (Array.isArray(location.WardTargeting.Includes)) {
2489
- for (const inc of location.WardTargeting.Includes) {
2490
- if (![1, 2, 3].includes(Number(inc.Id))) {
2491
- 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).`);
2492
- }
2493
- if (inc.Provinces && !Array.isArray(inc.Provinces)) {
2494
- 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.`);
2495
- }
2496
- }
2497
- }
3014
+ getZaapiGetownedpages(request = {}, options) {
3015
+ return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetownedpages, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetownedpages, request), options);
2498
3016
  }
2499
- const finalTargeting = {
2500
- ...targetingObj,
2501
- CustomAudienceId: 0,
2502
- Gender: gender,
2503
- NewAgeRanges: newAgeRanges,
2504
- Os: os,
2505
- Location: location
2506
- };
2507
- return {
2508
- isValid: errors.length === 0,
2509
- errors,
2510
- data: errors.length === 0 ? {
2511
- name,
2512
- caType: 1,
2513
- targeting: JSON.stringify(finalTargeting)
2514
- } : void 0
2515
- };
2516
- }
2517
- function validateCreatePhoneAudienceRequest(input) {
2518
- const errors = [];
2519
- if (!input || typeof input !== "object") {
2520
- return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
3017
+ getOwnedPages(request = {}, options) {
3018
+ return this.getZaapiGetownedpages(request, options);
2521
3019
  }
2522
- const raw = input;
2523
- const name = typeof raw.name === "string" ? raw.name.trim() : "";
2524
- if (!name || name.length < 2 || name.length > 255) {
2525
- errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
3020
+ listFormsByOfficialAccount(request, options) {
3021
+ return this.client.requestWithoutBody(OP_ZaloAdsListFormsByOfficialAccount, this.client.toTransportInput(OP_ZaloAdsListFormsByOfficialAccount, request), options);
2526
3022
  }
2527
- let targetingObj = {};
2528
- if (typeof raw.targeting === "string") {
2529
- try {
2530
- targetingObj = JSON.parse(raw.targeting);
2531
- } catch {
2532
- errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
2533
- }
2534
- } else if (raw.targeting && typeof raw.targeting === "object") {
2535
- targetingObj = raw.targeting;
2536
- } else {
2537
- errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c.");
3023
+ listMiniPagesByTemplate(request, options) {
3024
+ return this.client.requestWithoutBody(OP_ZaloAdsListMiniPagesByTemplate, this.client.toTransportInput(OP_ZaloAdsListMiniPagesByTemplate, request), options);
2538
3025
  }
2539
- const path = typeof targetingObj.Path === "string" ? targetingObj.Path.trim() : "";
2540
- if (!path) {
2541
- errors.push("Tr\u01B0\u1EDDng 'Path' (URL file .txt sau khi upload) l\xE0 b\u1EAFt bu\u1ED9c.");
3026
+ postZaapiDeletead(request = {}, options) {
3027
+ return this.client.requestWithoutBody(OP_ZaloAdsPostZaapiDeletead, this.client.toTransportInput(OP_ZaloAdsPostZaapiDeletead, request), options);
2542
3028
  }
2543
- const total = typeof targetingObj.Total === "number" ? targetingObj.Total : 0;
2544
- if (total <= 0) {
2545
- errors.push("Tr\u01B0\u1EDDng 'Total' (s\u1ED1 l\u01B0\u1EE3ng S\u0110T trong file) ph\u1EA3i l\u1EDBn h\u01A1n 0.");
3029
+ renameCampaign(request, options) {
3030
+ const normalized = {
3031
+ campid: request.campid ?? request.campaignId,
3032
+ newname: request.newname ?? request.campaignName ?? request.name
3033
+ };
3034
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsRenameCampaign, this.client.toTransportInput(OP_ZaloAdsRenameCampaign, normalized), options);
2546
3035
  }
2547
- return {
2548
- isValid: errors.length === 0,
2549
- errors,
2550
- data: errors.length === 0 ? {
2551
- name,
2552
- caType: 3,
2553
- targeting: JSON.stringify({
2554
- Name: String(targetingObj.Name || "phones.txt"),
2555
- Path: path,
2556
- Total: total,
2557
- ZaloId: Number(targetingObj.ZaloId || 0),
2558
- OriginAudience: 0
2559
- })
2560
- } : void 0
2561
- };
2562
- }
2563
- function validateCreateLookalikeAudienceRequest(input) {
2564
- const errors = [];
2565
- if (!input || typeof input !== "object") {
2566
- return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
3036
+ updateEcommerceAd(request, options) {
3037
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateEcommerceAd, this.client.toTransportInput(OP_ZaloAdsUpdateEcommerceAd, request), options);
2567
3038
  }
2568
- const raw = input;
2569
- const name = typeof raw.name === "string" ? raw.name.trim() : "";
2570
- if (!name || name.length < 2 || name.length > 255) {
2571
- errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
3039
+ /** Alias theo tên tool chuẩn `zalo_ads_update_commerce_ad` trong Project Schema Zalo ADS (`Type = 23`, gắn `MiniPageId`). */
3040
+ updateCommerceAd(request, options) {
3041
+ return this.updateEcommerceAd(request, options);
2572
3042
  }
2573
- let targetingObj = {};
2574
- if (typeof raw.targeting === "string") {
2575
- try {
2576
- targetingObj = JSON.parse(raw.targeting);
2577
- } catch {
2578
- errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
2579
- }
2580
- } else if (raw.targeting && typeof raw.targeting === "object") {
2581
- targetingObj = raw.targeting;
2582
- } else {
2583
- errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c.");
3043
+ updateFormAd(request, options) {
3044
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateFormAd, this.client.toTransportInput(OP_ZaloAdsUpdateFormAd, request), options);
2584
3045
  }
2585
- const originAudience = Number(targetingObj.OriginAudience);
2586
- if (!originAudience || originAudience <= 0) {
2587
- errors.push("Tr\u01B0\u1EDDng 'OriginAudience' (ID nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng S\u0110T g\u1ED1c) l\xE0 b\u1EAFt bu\u1ED9c.");
3046
+ updateMessageAd(request, options) {
3047
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateMessageAd, this.client.toTransportInput(OP_ZaloAdsUpdateMessageAd, request), options);
2588
3048
  }
2589
- const total = Number(targetingObj.Total);
2590
- if (![1e6, 15e5, 2e6].includes(total)) {
2591
- 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.");
3049
+ updateNewAds(request, options) {
3050
+ return this.client.requestMultipart(OP_ZaloAdsUpdateNewAds, this.client.toTransportInput(OP_ZaloAdsUpdateNewAds, request), options);
2592
3051
  }
2593
- return {
2594
- isValid: errors.length === 0,
2595
- errors,
2596
- data: errors.length === 0 ? {
2597
- name,
2598
- caType: 6,
2599
- targeting: JSON.stringify({
2600
- OriginAudience: originAudience,
2601
- Total: total,
2602
- Name: String(targetingObj.Name || "Lookalike Audience"),
2603
- Path: String(targetingObj.Path || "")
2604
- })
2605
- } : void 0
2606
- };
2607
- }
2608
- function validateCreateFormEventAudienceRequest(input) {
2609
- const errors = [];
2610
- if (!input || typeof input !== "object") {
2611
- return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
3052
+ updateOfficialAccountAd(request, options) {
3053
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateOfficialAccountAd, this.client.toTransportInput(OP_ZaloAdsUpdateOfficialAccountAd, request), options);
2612
3054
  }
2613
- const raw = input;
2614
- const name = typeof raw.name === "string" ? raw.name.trim() : "";
2615
- if (!name || name.length < 2 || name.length > 255) {
2616
- errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
3055
+ /** Alias theo tên tool chuẩn `zalo_ads_update_oa_ad` trong Project Schema Zalo ADS (`Type = 2`, `Action = 6`). */
3056
+ updateOaAd(request, options) {
3057
+ return this.updateOfficialAccountAd(request, options);
2617
3058
  }
2618
- let targetingObj = {};
2619
- if (typeof raw.targeting === "string") {
2620
- try {
2621
- targetingObj = JSON.parse(raw.targeting);
2622
- } catch {
2623
- errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
2624
- }
2625
- } else if (raw.targeting && typeof raw.targeting === "object") {
2626
- targetingObj = raw.targeting;
3059
+ updatePostAd(request, options) {
3060
+ return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdatePostAd, this.client.toTransportInput(OP_ZaloAdsUpdatePostAd, request), options);
2627
3061
  }
2628
- const eventType = Number(targetingObj.EventType);
2629
- if (![1, 2, 3, 4].includes(eventType)) {
2630
- 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).");
3062
+ /** Alias theo tên tool chuẩn `zalo_ads_update_article_ad` trong Project Schema Zalo ADS (`Type = 3`, gắn `ZaloFeedId`). */
3063
+ updateArticleAd(request, options) {
3064
+ return this.updatePostAd(request, options);
2631
3065
  }
2632
- const oaId = typeof targetingObj.OaId === "string" ? targetingObj.OaId.trim() : String(targetingObj.OaId || "");
2633
- if (!oaId) {
2634
- errors.push("Tr\u01B0\u1EDDng 'OaId' (d\u1EA1ng chu\u1ED7i c\u1EE7a pageId ho\u1EB7c noisedId) l\xE0 b\u1EAFt bu\u1ED9c.");
3066
+ /** Xóa quảng cáo */
3067
+ deleteAd(...args) {
3068
+ return this.postZaapiDeletead(...args);
2635
3069
  }
2636
- const numDays = Number(targetingObj.NumDays);
2637
- if (isNaN(numDays) || numDays < 1 || numDays > 90) {
2638
- errors.push("Tr\u01B0\u1EDDng 'NumDays' ph\u1EA3i n\u1EB1m trong kho\u1EA3ng t\u1EEB 1 \u0111\u1EBFn 90 ng\xE0y.");
3070
+ /** Danh sách quận/huyện để nhắm mục tiêu */
3071
+ getAllDistricts(...args) {
3072
+ return this.getApiPlaceGetalldistricts(...args);
2639
3073
  }
2640
- const formIds = Array.isArray(targetingObj.FormIds) ? targetingObj.FormIds : [];
2641
- if (formIds.length === 0) {
2642
- errors.push("Tr\u01B0\u1EDDng 'FormIds' ph\u1EA3i ch\u1EE9a \xEDt nh\u1EA5t 1 ID Form.");
3074
+ /** Kiểm tra chính tả văn bản quảng cáo */
3075
+ getSpellCheckV2(...args) {
3076
+ return this.getApiSpellCheckV2(...args);
2643
3077
  }
2644
- return {
2645
- isValid: errors.length === 0,
2646
- errors,
2647
- data: errors.length === 0 ? {
2648
- name,
2649
- caType: 12,
2650
- targeting: JSON.stringify({
2651
- EventType: eventType,
2652
- OaId: oaId,
2653
- NumDays: numDays,
2654
- FormIds: formIds
2655
- })
2656
- } : void 0
2657
- };
2658
- }
2659
- function validateCreateMessageOaEventAudienceRequest(input) {
2660
- const errors = [];
2661
- if (!input || typeof input !== "object") {
2662
- return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
3078
+ /**
3079
+ * 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).
3080
+ */
3081
+ createSpellCheckV3Job(request, options) {
3082
+ return this.client.requestJson(
3083
+ OP_ZaloAdsCreateSpellCheckV3Job,
3084
+ this.client.toTransportInput(OP_ZaloAdsCreateSpellCheckV3Job, request),
3085
+ options
3086
+ );
2663
3087
  }
2664
- const raw = input;
2665
- const name = typeof raw.name === "string" ? raw.name.trim() : "";
2666
- if (!name || name.length < 2 || name.length > 255) {
2667
- errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
3088
+ /**
3089
+ * Lấy kết quả kiểm tra chính tả AI V3 theo jobId (GET /api/spell-check/v3/{jobId}).
3090
+ */
3091
+ getSpellCheckV3Job(request, options) {
3092
+ return this.client.requestWithoutBody(
3093
+ OP_ZaloAdsGetSpellCheckV3Job,
3094
+ this.client.toTransportInput(OP_ZaloAdsGetSpellCheckV3Job, request),
3095
+ options
3096
+ );
2668
3097
  }
2669
- let targetingObj = {};
2670
- if (typeof raw.targeting === "string") {
2671
- try {
2672
- targetingObj = JSON.parse(raw.targeting);
2673
- } catch {
2674
- errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
3098
+ /**
3099
+ * 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).
3100
+ * @param request Tiêu đề (title) và chú thích (caption) cần kiểm tra.
3101
+ * @param pollIntervalMs Chu kỳ polling kiểm tra trạng thái (mặc định: 600ms).
3102
+ * @param timeoutMs Thời gian chờ tối đa (mặc định: 15.000ms = 15 giây).
3103
+ */
3104
+ async checkSpellV3AndWait(request, pollIntervalMs = 600, timeoutMs = 15e3, options) {
3105
+ const jobRes = await this.createSpellCheckV3Job(request, options);
3106
+ const jobId = jobRes?.data?.jobId;
3107
+ if (!jobId) {
3108
+ throw new Error(`[SpellCheckV3] Kh\xF4ng nh\u1EADn \u0111\u01B0\u1EE3c jobId t\u1EEB Zalo Ads (code: ${jobRes?.code})`);
2675
3109
  }
2676
- } else if (raw.targeting && typeof raw.targeting === "object") {
2677
- targetingObj = raw.targeting;
3110
+ const startTime = Date.now();
3111
+ while (Date.now() - startTime < timeoutMs) {
3112
+ await new Promise((r) => setTimeout(r, pollIntervalMs));
3113
+ const res = await this.getSpellCheckV3Job({ jobId }, options);
3114
+ if (res?.data?.status === "COMPLETED") {
3115
+ return res;
3116
+ }
3117
+ }
3118
+ 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}`);
3119
+ }
3120
+ /**
3121
+ * 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).
3122
+ * 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.
3123
+ */
3124
+ duplicateAd(request, options) {
3125
+ const payload = {
3126
+ adid: request.adid ?? request.adId
3127
+ };
3128
+ return this.client.requestFormUrlEncoded(
3129
+ OP_ZaloAdsDuplicateAd,
3130
+ this.client.toTransportInput(OP_ZaloAdsDuplicateAd, payload),
3131
+ options
3132
+ );
3133
+ }
3134
+ };
3135
+
3136
+ // src/services/account.service.ts
3137
+ var OP_ZaloAdsGetApiWhoami = {
3138
+ "operationId": "ZaloAds_getApiWhoami",
3139
+ "method": "GET",
3140
+ "endpoint": "/api/whoami",
3141
+ "baseUrl": "https://ads.zalo.me",
3142
+ "binaryFields": [],
3143
+ "pathFields": [],
3144
+ "queryFields": [],
3145
+ "headerFields": [],
3146
+ "cookieFields": [],
3147
+ "bodyFields": []
3148
+ };
3149
+ var OP_ZaloAdsGetApiPaymentTransactionHistory = {
3150
+ "operationId": "ZaloAds_getApiPaymentTransactionHistory",
3151
+ "method": "GET",
3152
+ "endpoint": "/api/payment/transaction-history",
3153
+ "baseUrl": "https://ads.zalo.me",
3154
+ "binaryFields": [],
3155
+ "pathFields": [],
3156
+ "queryFields": [
3157
+ "to",
3158
+ "from",
3159
+ "memberId"
3160
+ ],
3161
+ "headerFields": [],
3162
+ "cookieFields": [],
3163
+ "bodyFields": []
3164
+ };
3165
+ var OP_ZaloAdsGetApiBaAccountAllaccessors = {
3166
+ "operationId": "ZaloAds_getApiBaAccountAllaccessors",
3167
+ "method": "GET",
3168
+ "endpoint": "/api/ba/account/allAccessors",
3169
+ "baseUrl": "https://ads.zalo.me",
3170
+ "binaryFields": [],
3171
+ "pathFields": [],
3172
+ "queryFields": [
3173
+ "isShowAll"
3174
+ ],
3175
+ "headerFields": [],
3176
+ "cookieFields": [],
3177
+ "bodyFields": []
3178
+ };
3179
+ var OP_ZaloAdsGetApiBaAccountAllgrantedmembers = {
3180
+ "operationId": "ZaloAds_getApiBaAccountAllgrantedmembers",
3181
+ "method": "GET",
3182
+ "endpoint": "/api/ba/account/allGrantedMembers",
3183
+ "baseUrl": "https://ads.zalo.me",
3184
+ "binaryFields": [],
3185
+ "pathFields": [],
3186
+ "queryFields": [],
3187
+ "headerFields": [],
3188
+ "cookieFields": [],
3189
+ "bodyFields": []
3190
+ };
3191
+ var OP_ZaloAdsListAgencyCustomersWithBudget = {
3192
+ "operationId": "ZaloAds_listAgencyCustomersWithBudget",
3193
+ "method": "GET",
3194
+ "endpoint": "/api/ba/agency/customersWithBudget",
3195
+ "baseUrl": "https://ads.zalo.me",
3196
+ "binaryFields": [],
3197
+ "pathFields": [],
3198
+ "queryFields": [
3199
+ "limit",
3200
+ "offset",
3201
+ "joinDateAsc"
3202
+ ],
3203
+ "headerFields": [],
3204
+ "cookieFields": [],
3205
+ "bodyFields": []
3206
+ };
3207
+ var OP_ZaloAdsGetApiNotifiesHeader = {
3208
+ "operationId": "ZaloAds_getApiNotifiesHeader",
3209
+ "method": "GET",
3210
+ "endpoint": "/api/notifies/header",
3211
+ "baseUrl": "https://ads.zalo.me",
3212
+ "binaryFields": [],
3213
+ "pathFields": [],
3214
+ "queryFields": [],
3215
+ "headerFields": [],
3216
+ "cookieFields": [],
3217
+ "bodyFields": []
3218
+ };
3219
+ var OP_ZaloAdsGetApiLpNews = {
3220
+ "operationId": "ZaloAds_getApiLpNews",
3221
+ "method": "GET",
3222
+ "endpoint": "/api/lp-news",
3223
+ "baseUrl": "https://ads.zalo.me",
3224
+ "binaryFields": [],
3225
+ "pathFields": [],
3226
+ "queryFields": [],
3227
+ "headerFields": [],
3228
+ "cookieFields": [],
3229
+ "bodyFields": []
3230
+ };
3231
+ var ZaloAccountService = class {
3232
+ constructor(client) {
3233
+ this.client = client;
3234
+ }
3235
+ getApiWhoami(request = {}, options) {
3236
+ return this.client.requestWithoutBody(OP_ZaloAdsGetApiWhoami, this.client.toTransportInput(OP_ZaloAdsGetApiWhoami, request), options);
2678
3237
  }
2679
- const eventId = Number(targetingObj.EventId ?? targetingObj.EventType ?? 1);
2680
- const oaId = typeof targetingObj.OaId === "string" ? targetingObj.OaId.trim() : String(targetingObj.OaId || "");
2681
- if (!oaId) {
2682
- errors.push("Tr\u01B0\u1EDDng 'OaId' (chu\u1ED7i pageId ho\u1EB7c noisedId c\u1EE7a OA) l\xE0 b\u1EAFt bu\u1ED9c.");
3238
+ getApiPaymentTransactionHistory(request, options) {
3239
+ return this.client.requestWithoutBody(OP_ZaloAdsGetApiPaymentTransactionHistory, this.client.toTransportInput(OP_ZaloAdsGetApiPaymentTransactionHistory, request), options);
2683
3240
  }
2684
- const numDays = Number(targetingObj.NumDays);
2685
- if (isNaN(numDays) || numDays < 1 || numDays > 90) {
2686
- errors.push("Tr\u01B0\u1EDDng 'NumDays' ph\u1EA3i n\u1EB1m trong kho\u1EA3ng t\u1EEB 1 \u0111\u1EBFn 90 ng\xE0y.");
3241
+ getApiBaAccountAllaccessors(request = {}, options) {
3242
+ return this.client.requestWithoutBody(OP_ZaloAdsGetApiBaAccountAllaccessors, this.client.toTransportInput(OP_ZaloAdsGetApiBaAccountAllaccessors, request), options);
2687
3243
  }
2688
- return {
2689
- isValid: errors.length === 0,
2690
- errors,
2691
- data: errors.length === 0 ? {
2692
- name,
2693
- caType: 11,
2694
- targeting: JSON.stringify({
2695
- EventId: eventId,
2696
- OaId: oaId,
2697
- NumDays: numDays
2698
- })
2699
- } : void 0
2700
- };
2701
- }
2702
- function validateCreateMessagePersonalEventAudienceRequest(input) {
2703
- const errors = [];
2704
- if (!input || typeof input !== "object") {
2705
- return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
3244
+ getApiBaAccountAllgrantedmembers(request = {}, options) {
3245
+ return this.client.requestWithoutBody(OP_ZaloAdsGetApiBaAccountAllgrantedmembers, this.client.toTransportInput(OP_ZaloAdsGetApiBaAccountAllgrantedmembers, request), options);
2706
3246
  }
2707
- const raw = input;
2708
- const name = typeof raw.name === "string" ? raw.name.trim() : "";
2709
- if (!name || name.length < 2 || name.length > 255) {
2710
- errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
3247
+ listAgencyCustomersWithBudget(request = { limit: 15, offset: 0, joinDateAsc: true }, options) {
3248
+ const normalized = {
3249
+ limit: 15,
3250
+ offset: 0,
3251
+ joinDateAsc: true,
3252
+ ...request
3253
+ };
3254
+ return this.client.requestWithoutBody(OP_ZaloAdsListAgencyCustomersWithBudget, this.client.toTransportInput(OP_ZaloAdsListAgencyCustomersWithBudget, normalized), options);
2711
3255
  }
2712
- let targetingObj = {};
2713
- if (typeof raw.targeting === "string") {
2714
- try {
2715
- targetingObj = JSON.parse(raw.targeting);
2716
- } catch {
2717
- errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
2718
- }
2719
- } else if (raw.targeting && typeof raw.targeting === "object") {
2720
- targetingObj = raw.targeting;
3256
+ getApiNotifiesHeader(request = {}, options) {
3257
+ return this.client.requestWithoutBody(OP_ZaloAdsGetApiNotifiesHeader, this.client.toTransportInput(OP_ZaloAdsGetApiNotifiesHeader, request), options);
2721
3258
  }
2722
- const eventId = Number(targetingObj.EventId ?? targetingObj.EventType ?? 1);
2723
- if (![1, 2, 3].includes(eventId)) {
2724
- 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).");
3259
+ getApiLpNews(request = {}, options) {
3260
+ return this.client.requestWithoutBody(OP_ZaloAdsGetApiLpNews, this.client.toTransportInput(OP_ZaloAdsGetApiLpNews, request), options);
2725
3261
  }
2726
- const numDays = Number(targetingObj.NumDays);
2727
- if (isNaN(numDays) || numDays < 1 || numDays > 90) {
2728
- errors.push("Tr\u01B0\u1EDDng 'NumDays' ph\u1EA3i n\u1EB1m trong kho\u1EA3ng t\u1EEB 1 \u0111\u1EBFn 90 ng\xE0y.");
3262
+ /** Lấy thông tin tài khoản đang đăng nhập */
3263
+ getWhoami(...args) {
3264
+ return this.getApiWhoami(...args);
2729
3265
  }
2730
- const pageIds = Array.isArray(targetingObj.PageIds) ? targetingObj.PageIds.map(String) : [];
2731
- if (pageIds.length === 0) {
2732
- errors.push("Tr\u01B0\u1EDDng 'PageIds' ph\u1EA3i ch\u1EE9a \xEDt nh\u1EA5t 1 ID trang c\xE1 nh\xE2n.");
3266
+ /** Lịch sử giao dịch thanh toán */
3267
+ getPaymentTransactionHistory(...args) {
3268
+ return this.getApiPaymentTransactionHistory(...args);
2733
3269
  }
2734
- return {
2735
- isValid: errors.length === 0,
2736
- errors,
2737
- data: errors.length === 0 ? {
2738
- name,
2739
- caType: 14,
2740
- targeting: JSON.stringify({
2741
- EventId: eventId,
2742
- NumDays: numDays,
2743
- PageIds: pageIds
2744
- })
2745
- } : void 0
2746
- };
2747
- }
2748
- function validateEstimateAudienceRequest(input) {
2749
- const errors = [];
2750
- if (!input || typeof input !== "object") {
2751
- return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
3270
+ /** Danh sách accessor tài khoản BA */
3271
+ getBaAccountAllAccessors(...args) {
3272
+ return this.getApiBaAccountAllaccessors(...args);
2752
3273
  }
2753
- const raw = input;
2754
- const gender = typeof raw.gender === "number" ? raw.gender : 0;
2755
- if (![0, 1, 2].includes(gender)) {
2756
- errors.push("Tr\u01B0\u1EDDng 'gender' ph\u1EA3i l\xE0 0, 1 ho\u1EB7c 2.");
3274
+ /** Danh sách thành viên được cấp quyền BA */
3275
+ getBaAccountAllGrantedMembers(...args) {
3276
+ return this.getApiBaAccountAllgrantedmembers(...args);
3277
+ }
3278
+ /** Thông báo trên thanh tiêu đề */
3279
+ getNotifiesHeader(...args) {
3280
+ return this.getApiNotifiesHeader(...args);
3281
+ }
3282
+ /** Tin tức landing page / bảng tin */
3283
+ getLpNews(...args) {
3284
+ return this.getApiLpNews(...args);
2757
3285
  }
2758
- const ageRanges = Array.isArray(raw.ageRanges) && raw.ageRanges.length > 0 ? raw.ageRanges.map(Number) : [10283, 10284, 10285, 10286, 10287];
2759
- const platforms = Array.isArray(raw.platforms) && raw.platforms.length > 0 ? raw.platforms.map(Number) : [0, 1, 3];
2760
- const priceType = typeof raw.priceType === "number" ? raw.priceType : 2;
2761
- const wardsTargeting = typeof raw.wardsTargeting === "string" && raw.wardsTargeting.trim() ? raw.wardsTargeting.trim() : JSON.stringify({ Includes: [], Excludes: [] });
2762
- return {
2763
- isValid: errors.length === 0,
2764
- errors,
2765
- data: errors.length === 0 ? {
2766
- gender,
2767
- ageRanges,
2768
- platforms,
2769
- locations: typeof raw.locations === "string" ? raw.locations : "",
2770
- provinces: Array.isArray(raw.provinces) ? raw.provinces.map(Number) : [],
2771
- wardsTargeting,
2772
- priceType,
2773
- number: typeof raw.number === "string" ? raw.number : String(raw.number || "0")
2774
- } : void 0
2775
- };
2776
- }
2777
- var ZaloAudiencesValidator = {
2778
- createSavedAudience: validateCreateSavedAudienceRequest,
2779
- createPhoneAudience: validateCreatePhoneAudienceRequest,
2780
- createLookalikeAudience: validateCreateLookalikeAudienceRequest,
2781
- createFormEventAudience: validateCreateFormEventAudienceRequest,
2782
- createMessageOaEventAudience: validateCreateMessageOaEventAudienceRequest,
2783
- createMessagePersonalEventAudience: validateCreateMessagePersonalEventAudienceRequest,
2784
- estimateAudience: validateEstimateAudienceRequest
2785
3286
  };
2786
3287
 
2787
3288
  // src/services/audiences.service.ts
@@ -3425,6 +3926,20 @@ var OP_ZaloAdsListAutomatedRules = {
3425
3926
  "cookieFields": [],
3426
3927
  "bodyFields": []
3427
3928
  };
3929
+ var OP_ZaloAdsGetAutomatedRuleDetail = {
3930
+ "operationId": "ZaloAds_getAutomatedRuleDetail",
3931
+ "method": "GET",
3932
+ "endpoint": "/api/automatedrules/{automatedRuleId}",
3933
+ "baseUrl": "https://ads.zalo.me",
3934
+ "binaryFields": [],
3935
+ "pathFields": [
3936
+ "automatedRuleId"
3937
+ ],
3938
+ "queryFields": [],
3939
+ "headerFields": [],
3940
+ "cookieFields": [],
3941
+ "bodyFields": []
3942
+ };
3428
3943
  var OP_ZaloAdsCreateAutomatedRule = {
3429
3944
  "operationId": "ZaloAds_createAutomatedRule",
3430
3945
  "method": "POST",
@@ -3451,7 +3966,7 @@ var OP_ZaloAdsCreateAutomatedRule = {
3451
3966
  var OP_ZaloAdsUpdateAutomatedRule = {
3452
3967
  "operationId": "ZaloAds_updateAutomatedRule",
3453
3968
  "method": "POST",
3454
- "endpoint": "/api/automatedrules/update",
3969
+ "endpoint": "/api/ad/automatedrules/update",
3455
3970
  "baseUrl": "https://ads.zalo.me",
3456
3971
  "binaryFields": [],
3457
3972
  "pathFields": [],
@@ -3460,11 +3975,15 @@ var OP_ZaloAdsUpdateAutomatedRule = {
3460
3975
  "cookieFields": [],
3461
3976
  "bodyFields": [
3462
3977
  "automatedRuleId",
3463
- "rowVersion",
3464
- "appliedTo",
3978
+ "scope",
3465
3979
  "ruleName",
3466
3980
  "action",
3467
3981
  "conditions",
3982
+ "frequency",
3983
+ "appliedItems",
3984
+ "appliedIds",
3985
+ "rowVersion",
3986
+ "appliedTo",
3468
3987
  "schedule",
3469
3988
  "campaignIds",
3470
3989
  "adIds"
@@ -3522,6 +4041,9 @@ var ZaloAutomatedRulesService = class {
3522
4041
  const queryInput = { query_param: { ruleName: request.ruleName ?? "" } };
3523
4042
  return this.client.requestWithoutBody(OP_ZaloAdsListAutomatedRules, queryInput, options);
3524
4043
  }
4044
+ getAutomatedRuleDetail(request, options) {
4045
+ return this.client.requestWithoutBody(OP_ZaloAdsGetAutomatedRuleDetail, this.client.toTransportInput(OP_ZaloAdsGetAutomatedRuleDetail, request), options);
4046
+ }
3525
4047
  createAutomatedRule(request, options) {
3526
4048
  return this.client.requestJson(OP_ZaloAdsCreateAutomatedRule, this.client.toTransportInput(OP_ZaloAdsCreateAutomatedRule, request), options);
3527
4049
  }
@@ -4633,6 +5155,9 @@ var ZaloAdsService = class extends ZaloCampaignsService {
4633
5155
  listAutomatedRules(request = {}, options) {
4634
5156
  return this.automatedRules.listAutomatedRules(request, options);
4635
5157
  }
5158
+ getAutomatedRuleDetail(request, options) {
5159
+ return this.automatedRules.getAutomatedRuleDetail(request, options);
5160
+ }
4636
5161
  createAutomatedRule(request, options) {
4637
5162
  return this.automatedRules.createAutomatedRule(request, options);
4638
5163
  }
@@ -5315,6 +5840,34 @@ function isPositiveInteger2(val) {
5315
5840
  function toPositiveInteger2(val) {
5316
5841
  return typeof val === "number" ? Math.floor(val) : parseInt(String(val), 10);
5317
5842
  }
5843
+ function validateCreateInstantPageRequest(input) {
5844
+ const errors = [];
5845
+ if (!input || typeof input !== "object") {
5846
+ return { isValid: false, errors: ["D\u1EEF li\u1EC7u y\xEAu c\u1EA7u t\u1EA1o Instant Page ph\u1EA3i l\xE0 m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng (object)."] };
5847
+ }
5848
+ const obj = input;
5849
+ const validTemplates = [1, 3, 4, 5];
5850
+ if (!isPositiveInteger2(obj.templateId) || !validTemplates.includes(Number(obj.templateId))) {
5851
+ errors.push(`Tr\u01B0\u1EDDng 'templateId' l\xE0 b\u1EAFt bu\u1ED9c v\xE0 ph\u1EA3i thu\u1ED9c danh m\u1EE5c m\u1EABu h\u1EE3p l\u1EC7: ${validTemplates.join(", ")} (1: S\u1EA3n ph\u1EA9m form nh\xFAng, 3: S\u1EA3n ph\u1EA9m popup, 4: K\u1ECBch b\u1EA3n tin nh\u1EAFn, 5: Mua s\u1EAFm).`);
5852
+ }
5853
+ if (obj.oaId !== void 0 && obj.oaId !== null) {
5854
+ const oaIdStr = String(obj.oaId).trim();
5855
+ if (!oaIdStr) {
5856
+ errors.push("Tr\u01B0\u1EDDng 'oaId' n\u1EBFu cung c\u1EA5p kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
5857
+ } else if (oaIdStr.length < 10) {
5858
+ errors.push("Tr\u01B0\u1EDDng 'oaId' tr\xEAn domain page.ads.zalo.me b\u1EAFt bu\u1ED9c ph\u1EA3i l\xE0 chu\u1ED7i \u0111\u1ECBnh danh 64-bit c\u1EE7a Official Account (l\u1EA5y t\u1EEB GET /api/official-accounts), kh\xF4ng d\xF9ng ID s\u1ED1 nguy\xEAn ng\u1EAFn.");
5859
+ }
5860
+ }
5861
+ const data = {
5862
+ templateId: toPositiveInteger2(obj.templateId),
5863
+ oaId: obj.oaId ? String(obj.oaId).trim() : void 0
5864
+ };
5865
+ return {
5866
+ isValid: errors.length === 0,
5867
+ errors,
5868
+ data: errors.length === 0 ? data : void 0
5869
+ };
5870
+ }
5318
5871
  function validateCloneInstantPageRequest(input) {
5319
5872
  const errors = [];
5320
5873
  if (!input || typeof input !== "object") {
@@ -5677,6 +6230,7 @@ function validateUpsertInstantPageFormRequest(input) {
5677
6230
  };
5678
6231
  }
5679
6232
  var ZaloInstantPagesValidator = {
6233
+ validateCreateInstantPage: validateCreateInstantPageRequest,
5680
6234
  validateCloneInstantPage: validateCloneInstantPageRequest,
5681
6235
  validateGetInstantPageDetail: validateGetInstantPageDetailRequest,
5682
6236
  validateGetInstantPageSharedUser: validateGetInstantPageSharedUserRequest,
@@ -5693,6 +6247,21 @@ var ZaloInstantPagesValidator = {
5693
6247
  };
5694
6248
 
5695
6249
  // src/services/instant-pages.service.ts
6250
+ var OP_ZaloInstantPagesCreateInstantPage = {
6251
+ "operationId": "ZaloInstantPages_createInstantPage",
6252
+ "method": "POST",
6253
+ "endpoint": "/api/instant-pages",
6254
+ "baseUrl": "https://page.ads.zalo.me",
6255
+ "binaryFields": [],
6256
+ "pathFields": [],
6257
+ "queryFields": [],
6258
+ "headerFields": [],
6259
+ "cookieFields": [],
6260
+ "bodyFields": [
6261
+ "templateId",
6262
+ "oaId"
6263
+ ]
6264
+ };
5696
6265
  var OP_ZaloInstantPagesCloneInstantPage = {
5697
6266
  "operationId": "ZaloInstantPages_cloneInstantPage",
5698
6267
  "method": "POST",
@@ -5782,6 +6351,20 @@ var OP_ZaloInstantPagesListInstantPageShares = {
5782
6351
  "cookieFields": [],
5783
6352
  "bodyFields": []
5784
6353
  };
6354
+ var OP_ZaloInstantPagesUpdateInstantPageShares = {
6355
+ "operationId": "ZaloInstantPages_updateInstantPageShares",
6356
+ "method": "POST",
6357
+ "endpoint": "/api/instant-pages/{instantPageId}/shares",
6358
+ "baseUrl": "https://page.ads.zalo.me",
6359
+ "binaryFields": [],
6360
+ "pathFields": [
6361
+ "instantPageId"
6362
+ ],
6363
+ "queryFields": [],
6364
+ "headerFields": [],
6365
+ "cookieFields": [],
6366
+ "bodyFields": []
6367
+ };
5785
6368
  var OP_ZaloInstantPagesListInstantPageUsers = {
5786
6369
  "operationId": "ZaloInstantPages_listInstantPageUsers",
5787
6370
  "method": "GET",
@@ -5899,6 +6482,9 @@ var ZaloInstantPagesService = class {
5899
6482
  * Dùng ở backend (NestJS/Express/Fastify), middleware hoặc AI Agent để verify payload trước khi gọi SDK.
5900
6483
  */
5901
6484
  static validator = ZaloInstantPagesValidator;
6485
+ createInstantPage(request, options) {
6486
+ return this.client.requestJson(OP_ZaloInstantPagesCreateInstantPage, this.client.toTransportInput(OP_ZaloInstantPagesCreateInstantPage, request), options);
6487
+ }
5902
6488
  cloneInstantPage(request, options) {
5903
6489
  return this.client.requestJson(OP_ZaloInstantPagesCloneInstantPage, this.client.toTransportInput(OP_ZaloInstantPagesCloneInstantPage, request), options);
5904
6490
  }
@@ -5917,6 +6503,13 @@ var ZaloInstantPagesService = class {
5917
6503
  listInstantPageShares(request, options) {
5918
6504
  return this.client.requestWithoutBody(OP_ZaloInstantPagesListInstantPageShares, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageShares, request), options);
5919
6505
  }
6506
+ updateInstantPageShares(request, options) {
6507
+ const transportInput = {
6508
+ path_param: { instantPageId: request.instantPageId },
6509
+ body: request.shares
6510
+ };
6511
+ return this.client.requestJson(OP_ZaloInstantPagesUpdateInstantPageShares, transportInput, options);
6512
+ }
5920
6513
  listInstantPageUsers(request = {}, options) {
5921
6514
  return this.client.requestWithoutBody(OP_ZaloInstantPagesListInstantPageUsers, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageUsers, request), options);
5922
6515
  }
@@ -6453,18 +7046,311 @@ var ZaloInstantPageBlockType = /* @__PURE__ */ ((ZaloInstantPageBlockType2) => {
6453
7046
  ZaloInstantPageBlockType2[ZaloInstantPageBlockType2["CONSENT_NOTICE"] = 27] = "CONSENT_NOTICE";
6454
7047
  return ZaloInstantPageBlockType2;
6455
7048
  })(ZaloInstantPageBlockType || {});
7049
+ var ZaloInstantPageSharePermission = {
7050
+ /** Quản trị viên: Toàn quyền quản trị, chỉnh sửa, phân quyền và gắn quảng cáo. */
7051
+ ADMIN: 1,
7052
+ /** Biên tập viên: Quyền chỉnh sửa nội dung trang. */
7053
+ UPDATE_PAGE: 2,
7054
+ /** Tải dữ liệu: Quyền tải thông tin khách hàng / Leads. */
7055
+ DOWNLOAD_INFO: 3,
7056
+ /** Chỉ xem: Quyền xem trước và thống kê. */
7057
+ READ_ONLY: 4
7058
+ };
7059
+
7060
+ // src/validators/automated-rules.validator.ts
7061
+ var AutomatedRuleScopeEnum = /* @__PURE__ */ ((AutomatedRuleScopeEnum2) => {
7062
+ AutomatedRuleScopeEnum2[AutomatedRuleScopeEnum2["Ads"] = 1] = "Ads";
7063
+ return AutomatedRuleScopeEnum2;
7064
+ })(AutomatedRuleScopeEnum || {});
7065
+ var AutomatedRuleActionTypeEnum = /* @__PURE__ */ ((AutomatedRuleActionTypeEnum2) => {
7066
+ AutomatedRuleActionTypeEnum2[AutomatedRuleActionTypeEnum2["Resume"] = 1] = "Resume";
7067
+ AutomatedRuleActionTypeEnum2[AutomatedRuleActionTypeEnum2["Pause"] = 2] = "Pause";
7068
+ AutomatedRuleActionTypeEnum2[AutomatedRuleActionTypeEnum2["IncreaseByAmount"] = 3] = "IncreaseByAmount";
7069
+ AutomatedRuleActionTypeEnum2[AutomatedRuleActionTypeEnum2["DecreaseByAmount"] = 4] = "DecreaseByAmount";
7070
+ AutomatedRuleActionTypeEnum2[AutomatedRuleActionTypeEnum2["IncreaseByPercentage"] = 5] = "IncreaseByPercentage";
7071
+ AutomatedRuleActionTypeEnum2[AutomatedRuleActionTypeEnum2["DecreaseByPercentage"] = 6] = "DecreaseByPercentage";
7072
+ return AutomatedRuleActionTypeEnum2;
7073
+ })(AutomatedRuleActionTypeEnum || {});
7074
+ var AutomatedRuleFrequencyEnum = /* @__PURE__ */ ((AutomatedRuleFrequencyEnum2) => {
7075
+ AutomatedRuleFrequencyEnum2[AutomatedRuleFrequencyEnum2["OneHour"] = 1] = "OneHour";
7076
+ AutomatedRuleFrequencyEnum2[AutomatedRuleFrequencyEnum2["HalfDay"] = 12] = "HalfDay";
7077
+ AutomatedRuleFrequencyEnum2[AutomatedRuleFrequencyEnum2["OneDay"] = 24] = "OneDay";
7078
+ AutomatedRuleFrequencyEnum2[AutomatedRuleFrequencyEnum2["OneWeek"] = 168] = "OneWeek";
7079
+ return AutomatedRuleFrequencyEnum2;
7080
+ })(AutomatedRuleFrequencyEnum || {});
7081
+ var AutomatedRuleConditionFieldEnum = /* @__PURE__ */ ((AutomatedRuleConditionFieldEnum2) => {
7082
+ AutomatedRuleConditionFieldEnum2[AutomatedRuleConditionFieldEnum2["Status"] = 1] = "Status";
7083
+ AutomatedRuleConditionFieldEnum2[AutomatedRuleConditionFieldEnum2["Impression"] = 11] = "Impression";
7084
+ AutomatedRuleConditionFieldEnum2[AutomatedRuleConditionFieldEnum2["Click"] = 16] = "Click";
7085
+ AutomatedRuleConditionFieldEnum2[AutomatedRuleConditionFieldEnum2["CTR"] = 9999] = "CTR";
7086
+ AutomatedRuleConditionFieldEnum2[AutomatedRuleConditionFieldEnum2["Cost"] = 100001] = "Cost";
7087
+ return AutomatedRuleConditionFieldEnum2;
7088
+ })(AutomatedRuleConditionFieldEnum || {});
7089
+ var AutomatedRuleOperatorEnum = /* @__PURE__ */ ((AutomatedRuleOperatorEnum2) => {
7090
+ AutomatedRuleOperatorEnum2[AutomatedRuleOperatorEnum2["GreaterThan"] = 1] = "GreaterThan";
7091
+ AutomatedRuleOperatorEnum2[AutomatedRuleOperatorEnum2["LessThan"] = 2] = "LessThan";
7092
+ AutomatedRuleOperatorEnum2[AutomatedRuleOperatorEnum2["Between"] = 3] = "Between";
7093
+ AutomatedRuleOperatorEnum2[AutomatedRuleOperatorEnum2["NotBetween"] = 4] = "NotBetween";
7094
+ AutomatedRuleOperatorEnum2[AutomatedRuleOperatorEnum2["Include"] = 5] = "Include";
7095
+ AutomatedRuleOperatorEnum2[AutomatedRuleOperatorEnum2["Exclude"] = 6] = "Exclude";
7096
+ return AutomatedRuleOperatorEnum2;
7097
+ })(AutomatedRuleOperatorEnum || {});
7098
+ var AutomatedRuleTimeRangeEnum = /* @__PURE__ */ ((AutomatedRuleTimeRangeEnum2) => {
7099
+ AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["AllTime"] = 1] = "AllTime";
7100
+ AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["AllTimeExcludeToday"] = 2] = "AllTimeExcludeToday";
7101
+ AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Today"] = 3] = "Today";
7102
+ AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Yesterday"] = 4] = "Yesterday";
7103
+ AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous2Day"] = 1002] = "Previous2Day";
7104
+ AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous3Day"] = 1003] = "Previous3Day";
7105
+ AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous4Day"] = 1004] = "Previous4Day";
7106
+ AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous5Day"] = 1005] = "Previous5Day";
7107
+ AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous6Day"] = 1006] = "Previous6Day";
7108
+ AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous7Day"] = 1007] = "Previous7Day";
7109
+ AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous14Day"] = 1014] = "Previous14Day";
7110
+ AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous21Day"] = 1021] = "Previous21Day";
7111
+ AutomatedRuleTimeRangeEnum2[AutomatedRuleTimeRangeEnum2["Previous30Day"] = 1030] = "Previous30Day";
7112
+ return AutomatedRuleTimeRangeEnum2;
7113
+ })(AutomatedRuleTimeRangeEnum || {});
7114
+ var ZaloAutomatedRulesValidator = class {
7115
+ /**
7116
+ * Kiểm tra và chuẩn hóa payload tạo mới quy tắc tự động (`POST /api/automatedrules/create`)
7117
+ */
7118
+ static validateCreateRule(payload) {
7119
+ const errors = [];
7120
+ const warnings = [];
7121
+ if (!payload || typeof payload !== "object") {
7122
+ return { isValid: false, errors: ["Payload quy t\u1EAFc t\u1EF1 \u0111\u1ED9ng ph\u1EA3i l\xE0 m\u1ED9t object."], warnings };
7123
+ }
7124
+ const ruleName = String(payload.ruleName || "").trim();
7125
+ if (!ruleName) {
7126
+ errors.push("T\xEAn quy t\u1EAFc (ruleName) kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
7127
+ } else if (ruleName.length > 100) {
7128
+ errors.push(`T\xEAn quy t\u1EAFc kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 100 k\xFD t\u1EF1 (hi\u1EC7n c\xF3 ${ruleName.length} k\xFD t\u1EF1).`);
7129
+ }
7130
+ const scope = payload.scope !== void 0 ? Number(payload.scope) : 1;
7131
+ if (scope !== 1) {
7132
+ errors.push("Zalo Ads hi\u1EC7n ch\u1EC9 h\u1ED7 tr\u1EE3 scope: 1 (\xC1p d\u1EE5ng cho Qu\u1EA3ng c\xE1o).");
7133
+ }
7134
+ if (!payload.action || typeof payload.action !== "object") {
7135
+ errors.push("Thi\u1EBFu c\u1EA5u h\xECnh h\xE0nh \u0111\u1ED9ng (action).");
7136
+ } else {
7137
+ const act = payload.action;
7138
+ const actType2 = Number(act.type);
7139
+ if (![3, 4, 5, 6].includes(actType2)) {
7140
+ if ([1, 2].includes(actType2)) {
7141
+ errors.push(`H\xE0nh \u0111\u1ED9ng ${actType2 === 1 ? "Ti\u1EBFp t\u1EE5c" : "T\u1EA1m d\u1EEBng"} qu\u1EA3ng c\xE1o (type: ${actType2}) hi\u1EC7n ch\u01B0a \u0111\u01B0\u1EE3c backend Zalo Ads k\xEDch ho\u1EA1t trong scope n\xE0y.`);
7142
+ } else {
7143
+ errors.push(`Lo\u1EA1i h\xE0nh \u0111\u1ED9ng kh\xF4ng h\u1EE3p l\u1EC7: ${act.type}. Ch\u1EC9 h\u1ED7 tr\u1EE3 3 (T\u0103ng gi\xE1 \u0111), 4 (Gi\u1EA3m gi\xE1 \u0111), 5 (T\u0103ng gi\xE1 %), 6 (Gi\u1EA3m gi\xE1 %).`);
7144
+ }
7145
+ }
7146
+ if (!Array.isArray(act.values) || act.values.length === 0 || Number(act.values[0]) <= 0) {
7147
+ errors.push("Gi\xE1 tr\u1ECB thay \u0111\u1ED5i gi\xE1 th\u1EA7u (action.values) ph\u1EA3i l\xE0 m\u1EA3ng ch\u1EE9a s\u1ED1 d\u01B0\u01A1ng > 0.");
7148
+ } else {
7149
+ const val = Number(act.values[0]);
7150
+ if ([5, 6].includes(actType2) && (val < 1 || val > 100)) {
7151
+ errors.push(`Thay \u0111\u1ED5i theo % (type: ${actType2}) y\xEAu c\u1EA7u gi\xE1 tr\u1ECB trong kho\u1EA3ng t\u1EEB 1% \u0111\u1EBFn 100% (hi\u1EC7n l\xE0 ${val}%).`);
7152
+ }
7153
+ }
7154
+ if (act.limit !== void 0 && Number(act.limit) <= 0) {
7155
+ errors.push("H\u1EA1n m\u1EE9c gi\xE1 th\u1EA7u (action.limit) n\u1EBFu c\xF3 ph\u1EA3i l\xE0 s\u1ED1 ti\u1EC1n d\u01B0\u01A1ng > 0 VN\u0110.");
7156
+ }
7157
+ }
7158
+ const frequency = payload.frequency !== void 0 ? Number(payload.frequency) : 12;
7159
+ const actType = payload.action ? Number(payload.action.type) : 0;
7160
+ if ([3, 4, 5, 6].includes(actType)) {
7161
+ if (![1, 12, 24, 168].includes(frequency)) {
7162
+ errors.push(`T\u1EA7n su\u1EA5t h\xE0nh \u0111\u1ED9ng cho \u0111i\u1EC1u ch\u1EC9nh gi\xE1 th\u1EA7u ph\u1EA3i thu\u1ED9c [1 (1 gi\u1EDD), 12 (12 gi\u1EDD), 24 (1 ng\xE0y), 168 (1 tu\u1EA7n)]. Gi\xE1 tr\u1ECB ${frequency} s\u1EBD b\u1ECB t\u1EEB ch\u1ED1i v\u1EDBi l\u1ED7i "T\u1EA7n su\u1EA5t h\xE0nh \u0111\u1ED9ng kh\xF4ng h\u1EE3p l\u1EC7."`);
7163
+ }
7164
+ }
7165
+ if (!Array.isArray(payload.conditions) || payload.conditions.length === 0) {
7166
+ errors.push("Quy t\u1EAFc t\u1EF1 \u0111\u1ED9ng ph\u1EA3i c\xF3 \xEDt nh\u1EA5t 1 \u0111i\u1EC1u ki\u1EC7n ch\u1EC9 s\u1ED1 (conditions).");
7167
+ } else {
7168
+ payload.conditions.forEach((c, idx) => {
7169
+ const f = Number(c.field);
7170
+ if (![1, 11, 16, 9999, 100001].includes(f)) {
7171
+ errors.push(`\u0110i\u1EC1u ki\u1EC7n [${idx + 1}]: Ch\u1EC9 s\u1ED1 kh\xF4ng h\u1EE3p l\u1EC7 (field: ${c.field}). H\u1ED7 tr\u1EE3: 1 (Status), 11 (Impression), 16 (Click), 9999 (CTR), 100001 (Cost).`);
7172
+ }
7173
+ const op = Number(c.operator);
7174
+ if (![1, 2, 3, 4, 5, 6].includes(op)) {
7175
+ errors.push(`\u0110i\u1EC1u ki\u1EC7n [${idx + 1}]: Ph\xE9p to\xE1n kh\xF4ng h\u1EE3p l\u1EC7 (operator: ${c.operator}). H\u1ED7 tr\u1EE3 1 (>), 2 (<), 3 (between), 4 (not between), 5 (include), 6 (exclude).`);
7176
+ }
7177
+ if (!Array.isArray(c.values) || c.values.length === 0) {
7178
+ errors.push(`\u0110i\u1EC1u ki\u1EC7n [${idx + 1}]: values ph\u1EA3i l\xE0 m\u1EA3ng gi\xE1 tr\u1ECB ng\u01B0\u1EE1ng.`);
7179
+ }
7180
+ if (f !== 1 && !c.timeRange) {
7181
+ warnings.push(`\u0110i\u1EC1u ki\u1EC7n [${idx + 1}]: Thi\u1EBFu timeRange, h\u1EC7 th\u1ED1ng s\u1EBD m\u1EB7c \u0111\u1ECBnh l\xE0 1 (Lifetime).`);
7182
+ }
7183
+ });
7184
+ }
7185
+ const sanitizedData = {
7186
+ ruleName,
7187
+ scope: 1,
7188
+ action: {
7189
+ type: Number(payload.action?.type),
7190
+ field: 1,
7191
+ values: payload.action?.values?.map(Number) || [10],
7192
+ limit: payload.action?.limit !== void 0 ? Number(payload.action.limit) : 1e6
7193
+ },
7194
+ conditions: (payload.conditions || []).map((c) => ({
7195
+ field: Number(c.field),
7196
+ operator: Number(c.operator),
7197
+ values: c.values.map(Number),
7198
+ timeRange: c.timeRange !== void 0 ? Number(c.timeRange) : 1
7199
+ })),
7200
+ frequency,
7201
+ appliedIds: Array.isArray(payload.appliedIds) ? payload.appliedIds.map(Number) : []
7202
+ };
7203
+ return {
7204
+ isValid: errors.length === 0,
7205
+ errors,
7206
+ warnings,
7207
+ sanitizedData: errors.length === 0 ? sanitizedData : void 0
7208
+ };
7209
+ }
7210
+ /**
7211
+ * Kiểm tra và chuẩn hóa payload cập nhật quy tắc tự động (`POST /api/ad/automatedrules/update`)
7212
+ */
7213
+ static validateUpdateRule(payload) {
7214
+ const base = this.validateCreateRule(payload);
7215
+ const errors = [...base.errors];
7216
+ const warnings = [...base.warnings];
7217
+ if (!payload.automatedRuleId || Number(payload.automatedRuleId) <= 0) {
7218
+ errors.unshift("ID quy t\u1EAFc t\u1EF1 \u0111\u1ED9ng (automatedRuleId) l\xE0 b\u1EAFt bu\u1ED9c khi c\u1EADp nh\u1EADt.");
7219
+ }
7220
+ const appliedItems = Array.isArray(payload.appliedItems) ? payload.appliedItems.map((item) => ({
7221
+ appliedId: Number(item.appliedId),
7222
+ mode: Number(item.mode) === -1 ? -1 : 1
7223
+ // -1: Unapply, 1: Apply
7224
+ })) : [];
7225
+ const sanitizedData = base.sanitizedData ? {
7226
+ automatedRuleId: Number(payload.automatedRuleId),
7227
+ ...base.sanitizedData,
7228
+ appliedItems
7229
+ } : void 0;
7230
+ return {
7231
+ isValid: errors.length === 0,
7232
+ errors,
7233
+ warnings,
7234
+ sanitizedData
7235
+ };
7236
+ }
7237
+ };
7238
+
7239
+ // src/validators/conversions.validator.ts
7240
+ var ConversionLabelEnum = /* @__PURE__ */ ((ConversionLabelEnum2) => {
7241
+ ConversionLabelEnum2[ConversionLabelEnum2["AddToCart"] = 2] = "AddToCart";
7242
+ ConversionLabelEnum2[ConversionLabelEnum2["CompleteRegistration"] = 4] = "CompleteRegistration";
7243
+ ConversionLabelEnum2[ConversionLabelEnum2["Contact"] = 5] = "Contact";
7244
+ ConversionLabelEnum2[ConversionLabelEnum2["InitiateCheckout"] = 9] = "InitiateCheckout";
7245
+ ConversionLabelEnum2[ConversionLabelEnum2["Lead"] = 10] = "Lead";
7246
+ ConversionLabelEnum2[ConversionLabelEnum2["Purchase"] = 11] = "Purchase";
7247
+ ConversionLabelEnum2[ConversionLabelEnum2["Other"] = 19] = "Other";
7248
+ return ConversionLabelEnum2;
7249
+ })(ConversionLabelEnum || {});
7250
+ var ConversionUrlTypeEnum = /* @__PURE__ */ ((ConversionUrlTypeEnum2) => {
7251
+ ConversionUrlTypeEnum2[ConversionUrlTypeEnum2["Exact"] = 0] = "Exact";
7252
+ ConversionUrlTypeEnum2[ConversionUrlTypeEnum2["Contains"] = 1] = "Contains";
7253
+ return ConversionUrlTypeEnum2;
7254
+ })(ConversionUrlTypeEnum || {});
7255
+ var ZaloConversionsValidator = class {
7256
+ /**
7257
+ * Danh mục 7 nhãn chuẩn được Zalo Ads hỗ trợ chính thức
7258
+ */
7259
+ static SUPPORTED_LABELS = {
7260
+ [10 /* Lead */]: "Tr\u1EDF th\xE0nh kh\xE1ch h\xE0ng ti\u1EC1m n\u0103ng",
7261
+ [11 /* Purchase */]: "Ho\xE0n t\u1EA5t mua h\xE0ng",
7262
+ [5 /* Contact */]: "Li\xEAn h\u1EC7",
7263
+ [4 /* CompleteRegistration */]: "Ho\xE0n t\u1EA5t \u0111\u0103ng k\xFD",
7264
+ [9 /* InitiateCheckout */]: "B\u1EAFt \u0111\u1EA7u thanh to\xE1n",
7265
+ [2 /* AddToCart */]: "Th\xEAm v\xE0o gi\u1ECF h\xE0ng",
7266
+ [19 /* Other */]: "Kh\xE1c"
7267
+ };
7268
+ /**
7269
+ * Kiểm tra và chuẩn hóa payload tạo mới Conversion (`POST /api/conversion/add`)
7270
+ */
7271
+ static validateCreateConversion(payload) {
7272
+ const errors = [];
7273
+ const warnings = [];
7274
+ if (!payload || typeof payload !== "object") {
7275
+ return { isValid: false, errors: ["Payload conversion ph\u1EA3i l\xE0 m\u1ED9t object."], warnings };
7276
+ }
7277
+ const name = String(payload.name || "").trim();
7278
+ if (!name) {
7279
+ errors.push("T\xEAn conversion (name) kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
7280
+ } else if (name.length > 180) {
7281
+ errors.push(`T\xEAn conversion kh\xF4ng \u0111\u01B0\u1EE3c v\u01B0\u1EE3t qu\xE1 180 k\xFD t\u1EF1 (hi\u1EC7n c\xF3 ${name.length} k\xFD t\u1EF1).`);
7282
+ }
7283
+ const landingPage = String(payload.landingPage || "").trim();
7284
+ if (!landingPage) {
7285
+ errors.push("Trang \u0111\xEDch (landingPage) kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng.");
7286
+ } else {
7287
+ const urlPattern = /^https?:\/\/.+/i;
7288
+ if (!urlPattern.test(landingPage)) {
7289
+ errors.push("Trang \u0111\xEDch (landingPage) ph\u1EA3i l\xE0 m\u1ED9t URL h\u1EE3p l\u1EC7 b\u1EAFt \u0111\u1EA7u b\u1EB1ng http:// ho\u1EB7c https:// (v\xED d\u1EE5: https://redai.vn).");
7290
+ }
7291
+ }
7292
+ const urlType = payload.urlType !== void 0 ? Number(payload.urlType) : 1;
7293
+ if (![0, 1].includes(urlType)) {
7294
+ errors.push(`Lo\u1EA1i URL kh\xF4ng h\u1EE3p l\u1EC7: ${payload.urlType}. Ch\u1EC9 h\u1ED7 tr\u1EE3 0 (Exact URL) ho\u1EB7c 1 (Contains keywords).`);
7295
+ }
7296
+ const labelId = payload.labelId !== void 0 ? Number(payload.labelId) : 10;
7297
+ if (!Object.keys(this.SUPPORTED_LABELS).map(Number).includes(labelId)) {
7298
+ errors.push(`Nh\xE3n conversion kh\xF4ng h\u1EE3p l\u1EC7 (labelId: ${payload.labelId}). Zalo Ads ch\u1EC9 h\u1ED7 tr\u1EE3: 10 (Lead), 11 (Purchase), 5 (Contact), 4 (Registration), 9 (Checkout), 2 (AddToCart), 19 (Other).`);
7299
+ }
7300
+ const buttonIds = Array.isArray(payload.buttonIds) ? payload.buttonIds.map(String).map((s) => s.trim()).filter((s) => Boolean(s)) : [];
7301
+ const elements = Array.isArray(payload.elements) ? payload.elements : [];
7302
+ const keywords = Array.isArray(payload.keywords) ? payload.keywords.map(String).map((s) => s.trim()).filter((s) => Boolean(s)) : [];
7303
+ if (buttonIds.length === 0 && elements.length === 0 && keywords.length === 0) {
7304
+ errors.push("Conversion b\u1EAFt bu\u1ED9c ph\u1EA3i c\xF3 \xEDt nh\u1EA5t 1 c\u01A1 ch\u1EBF nh\u1EADn di\u1EC7n s\u1EF1 ki\u1EC7n: URL ch\u1EE9a t\u1EEB kh\xF3a (keywords), ID n\xFAt b\u1EA5m (buttonIds), ho\u1EB7c ph\u1EA7n t\u1EED giao di\u1EC7n (elements).");
7305
+ }
7306
+ const sanitizedElements = elements.map((el) => {
7307
+ if (typeof el === "object" && Array.isArray(el.class)) {
7308
+ return { class: el.class.map(String).map((s) => s.trim()).filter((s) => Boolean(s)) };
7309
+ }
7310
+ return el;
7311
+ });
7312
+ const sanitizedData = {
7313
+ name,
7314
+ landingPage,
7315
+ urlType,
7316
+ labelId,
7317
+ buttonIds,
7318
+ elements: sanitizedElements,
7319
+ keywords
7320
+ };
7321
+ return {
7322
+ isValid: errors.length === 0,
7323
+ errors,
7324
+ warnings,
7325
+ sanitizedData: errors.length === 0 ? sanitizedData : void 0
7326
+ };
7327
+ }
7328
+ };
6456
7329
  export {
6457
7330
  ALLOWED_CTAS_PER_AD_TYPE,
6458
7331
  ALL_ZALO_ADS_DOMAINS,
7332
+ AutomatedRuleActionTypeEnum,
7333
+ AutomatedRuleConditionFieldEnum,
7334
+ AutomatedRuleFrequencyEnum,
7335
+ AutomatedRuleOperatorEnum,
7336
+ AutomatedRuleScopeEnum,
7337
+ AutomatedRuleTimeRangeEnum,
7338
+ ConversionLabelEnum,
7339
+ ConversionUrlTypeEnum,
6459
7340
  MemoryZaloSessionStore,
6460
7341
  RedisZaloSessionStore,
6461
7342
  TieredZaloSessionStore,
6462
7343
  VALID_AD_TYPES,
6463
7344
  VALID_CAMPAIGN_TYPES,
7345
+ ZALO_NEW_REGION_PROVINCE_CODES,
7346
+ ZALO_PROVINCE_MERGE_MAPPING,
7347
+ ZALO_REGION_PROVINCE_CODES,
6464
7348
  ZaloAccountService,
6465
7349
  ZaloAdsIntegrationManager as ZaloAdsAccountPool,
6466
7350
  ZaloAdsActionType,
6467
7351
  ZaloAdsAgeRangeId,
7352
+ ZaloAdsBudgetScheduleType,
7353
+ ZaloAdsCampaignStatus,
6468
7354
  ZaloAdsCreateFlowRequest,
6469
7355
  ZaloAdsCreateFlowResponse,
6470
7356
  ZaloAdsCreatePostCampaignRequest,
@@ -6473,28 +7359,40 @@ export {
6473
7359
  ZaloAdsFlowButtonDto,
6474
7360
  ZaloAdsFlowChildMessageDto,
6475
7361
  ZaloAdsFlowMessageDto,
7362
+ ZaloAdsImageRatio,
6476
7363
  ZaloAdsIntegrationManager,
6477
7364
  ZaloAdsMessageAdUpdateDataDto,
6478
7365
  ZaloAdsOsId,
7366
+ ZaloAdsPriceLimitType,
7367
+ ZaloAdsPriceType,
7368
+ ZaloAdsProvinceCode,
7369
+ ZaloAdsRegionId,
6479
7370
  ZaloAdsSdk,
6480
7371
  ZaloAdsService,
7372
+ ZaloAdsSpendingMethod,
6481
7373
  ZaloAdsUpdateMessageAdRequest,
6482
7374
  ZaloAdsUpdateMessageAdResponse,
6483
7375
  ZaloAdsUpdateVideoAdRequest,
6484
7376
  ZaloAdsUpdateVideoAdResponse,
7377
+ ZaloAdsUseConversion,
7378
+ ZaloAdsVideoSrc,
7379
+ ZaloAdsXTemplates,
6485
7380
  ZaloAudiencesService,
6486
7381
  ZaloAudiencesValidator,
6487
7382
  ZaloAuthManager,
6488
7383
  ZaloAutomatedRulesService,
7384
+ ZaloAutomatedRulesValidator,
6489
7385
  ZaloCampaignsService,
6490
7386
  ZaloCampaignsValidator,
6491
7387
  ZaloChatWidgetService,
6492
7388
  ZaloConversionsService,
7389
+ ZaloConversionsValidator,
6493
7390
  ZaloFlowsService,
6494
7391
  ZaloFlowsValidator,
6495
7392
  ZaloFormsService,
6496
7393
  ZaloFormsValidator,
6497
7394
  ZaloInstantPageBlockType,
7395
+ ZaloInstantPageSharePermission,
6498
7396
  ZaloInstantPagesService,
6499
7397
  ZaloInstantPagesValidator,
6500
7398
  ZaloMediaService,
@@ -6516,6 +7414,7 @@ export {
6516
7414
  validateCreateFlowRequest,
6517
7415
  validateCreateFormEventAudienceRequest,
6518
7416
  validateCreateFormRequest,
7417
+ validateCreateInstantPageRequest,
6519
7418
  validateCreateLookalikeAudienceRequest,
6520
7419
  validateCreateMessageOaEventAudienceRequest,
6521
7420
  validateCreateMessagePersonalEventAudienceRequest,