@redonvn/zalo-ads-sdk 0.2.7 → 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.d.mts +881 -26
- package/dist/index.d.ts +881 -26
- package/dist/index.js +2486 -1085
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2447 -1085
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -618,7 +618,10 @@ var ZaloAuthManager = class {
|
|
|
618
618
|
let adsProfile;
|
|
619
619
|
let formProfile;
|
|
620
620
|
if (domain === "ads.zalo.me") {
|
|
621
|
-
|
|
621
|
+
const explicitPlaySession = this.extraCookies?.PLAY_SESSION || cookies["PLAY_SESSION"];
|
|
622
|
+
if (!explicitPlaySession) {
|
|
623
|
+
await this.followOAuthRedirects("https://ads.zalo.me/api/login", cookies, true);
|
|
624
|
+
}
|
|
622
625
|
const whoamiRes = await this.fetchImpl("https://ads.zalo.me/api/whoami", {
|
|
623
626
|
method: "GET",
|
|
624
627
|
headers: {
|
|
@@ -628,12 +631,17 @@ var ZaloAuthManager = class {
|
|
|
628
631
|
}
|
|
629
632
|
});
|
|
630
633
|
this.mergeSetCookies(whoamiRes, cookies);
|
|
634
|
+
if (explicitPlaySession) {
|
|
635
|
+
cookies["PLAY_SESSION"] = explicitPlaySession;
|
|
636
|
+
}
|
|
631
637
|
const whoamiJson = await whoamiRes.json().catch(() => null);
|
|
632
638
|
if (whoamiJson?.data) {
|
|
633
639
|
adsProfile = whoamiJson.data;
|
|
634
640
|
if (adsProfile.id) {
|
|
635
641
|
cookies["ads_user_id"] = String(adsProfile.id);
|
|
636
642
|
}
|
|
643
|
+
} else if (this.extraCookies?.ads_user_id) {
|
|
644
|
+
cookies["ads_user_id"] = this.extraCookies.ads_user_id;
|
|
637
645
|
}
|
|
638
646
|
} else if (domain === "page.ads.zalo.me") {
|
|
639
647
|
await this.followOAuthRedirects("https://page.ads.zalo.me/api/login", cookies, false);
|
|
@@ -922,7 +930,8 @@ var ZaloSdkHttpClient = class {
|
|
|
922
930
|
const body = asRecord(input.body);
|
|
923
931
|
if (bodyType === "json") {
|
|
924
932
|
headers.set("content-type", headers.get("content-type") ?? "application/json");
|
|
925
|
-
|
|
933
|
+
const jsonPayload = input.body !== void 0 ? input.body : body;
|
|
934
|
+
init.body = JSON.stringify(jsonPayload);
|
|
926
935
|
} else if (bodyType === "urlencoded") {
|
|
927
936
|
headers.set("content-type", headers.get("content-type") ?? "application/x-www-form-urlencoded;charset=UTF-8");
|
|
928
937
|
const encoded = new URLSearchParams();
|
|
@@ -1038,291 +1047,1402 @@ async function resolveCookies(auth, context) {
|
|
|
1038
1047
|
return { ...auth?.cookies ?? {}, ...await auth?.getCookies?.(context) ?? {} };
|
|
1039
1048
|
}
|
|
1040
1049
|
|
|
1041
|
-
// src/
|
|
1042
|
-
var
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
"
|
|
1066
|
-
"
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
"endpoint": "/zaapi/addNewCamp",
|
|
1073
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1074
|
-
"binaryFields": [],
|
|
1075
|
-
"pathFields": [],
|
|
1076
|
-
"queryFields": [],
|
|
1077
|
-
"headerFields": [],
|
|
1078
|
-
"cookieFields": [],
|
|
1079
|
-
"bodyFields": [
|
|
1080
|
-
"data"
|
|
1081
|
-
]
|
|
1082
|
-
};
|
|
1083
|
-
var OP_ZaloAdsCreateForm = {
|
|
1084
|
-
"operationId": "ZaloAds_createForm",
|
|
1085
|
-
"method": "POST",
|
|
1086
|
-
"endpoint": "/api/form/create",
|
|
1087
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1088
|
-
"binaryFields": [],
|
|
1089
|
-
"pathFields": [],
|
|
1090
|
-
"queryFields": [],
|
|
1091
|
-
"headerFields": [],
|
|
1092
|
-
"cookieFields": [],
|
|
1093
|
-
"bodyFields": [
|
|
1094
|
-
"data"
|
|
1095
|
-
]
|
|
1096
|
-
};
|
|
1097
|
-
var OP_ZaloAdsCreateFormCampaign = {
|
|
1098
|
-
"operationId": "ZaloAds_createFormCampaign",
|
|
1099
|
-
"method": "POST",
|
|
1100
|
-
"endpoint": "/zaapi/addNewCamp",
|
|
1101
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1102
|
-
"binaryFields": [],
|
|
1103
|
-
"pathFields": [],
|
|
1104
|
-
"queryFields": [],
|
|
1105
|
-
"headerFields": [],
|
|
1106
|
-
"cookieFields": [],
|
|
1107
|
-
"bodyFields": [
|
|
1108
|
-
"data"
|
|
1109
|
-
]
|
|
1110
|
-
};
|
|
1111
|
-
var OP_ZaloAdsCreateMessageCampaign = {
|
|
1112
|
-
"operationId": "ZaloAds_createMessageCampaign",
|
|
1113
|
-
"method": "POST",
|
|
1114
|
-
"endpoint": "/zaapi/addNewCamp",
|
|
1115
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1116
|
-
"binaryFields": [],
|
|
1117
|
-
"pathFields": [],
|
|
1118
|
-
"queryFields": [],
|
|
1119
|
-
"headerFields": [],
|
|
1120
|
-
"cookieFields": [],
|
|
1121
|
-
"bodyFields": [
|
|
1122
|
-
"data"
|
|
1123
|
-
]
|
|
1124
|
-
};
|
|
1125
|
-
var OP_ZaloAdsCreateOfficialAccountCampaign = {
|
|
1126
|
-
"operationId": "ZaloAds_createOfficialAccountCampaign",
|
|
1127
|
-
"method": "POST",
|
|
1128
|
-
"endpoint": "/zaapi/addNewCamp",
|
|
1129
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1130
|
-
"binaryFields": [],
|
|
1131
|
-
"pathFields": [],
|
|
1132
|
-
"queryFields": [],
|
|
1133
|
-
"headerFields": [],
|
|
1134
|
-
"cookieFields": [],
|
|
1135
|
-
"bodyFields": [
|
|
1136
|
-
"data"
|
|
1137
|
-
]
|
|
1138
|
-
};
|
|
1139
|
-
var OP_ZaloAdsCreatePostCampaign = {
|
|
1140
|
-
"operationId": "ZaloAds_createPostCampaign",
|
|
1141
|
-
"method": "POST",
|
|
1142
|
-
"endpoint": "/zaapi/addNewCamp",
|
|
1143
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1144
|
-
"binaryFields": [],
|
|
1145
|
-
"pathFields": [],
|
|
1146
|
-
"queryFields": [],
|
|
1147
|
-
"headerFields": [],
|
|
1148
|
-
"cookieFields": [],
|
|
1149
|
-
"bodyFields": [
|
|
1150
|
-
"data"
|
|
1151
|
-
]
|
|
1152
|
-
};
|
|
1153
|
-
var OP_ZaloAdsGetAdById = {
|
|
1154
|
-
"operationId": "ZaloAds_getAdById",
|
|
1155
|
-
"method": "GET",
|
|
1156
|
-
"endpoint": "/zaapi/getAdFromAdId",
|
|
1157
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1158
|
-
"binaryFields": [],
|
|
1159
|
-
"pathFields": [],
|
|
1160
|
-
"queryFields": [
|
|
1161
|
-
"adId"
|
|
1162
|
-
],
|
|
1163
|
-
"headerFields": [],
|
|
1164
|
-
"cookieFields": [],
|
|
1165
|
-
"bodyFields": []
|
|
1166
|
-
};
|
|
1167
|
-
var OP_ZaloAdsGetAdChangeLog = {
|
|
1168
|
-
"operationId": "ZaloAds_getAdChangeLog",
|
|
1169
|
-
"method": "GET",
|
|
1170
|
-
"endpoint": "/api/ad/log/{adId}",
|
|
1171
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1172
|
-
"binaryFields": [],
|
|
1173
|
-
"pathFields": [
|
|
1174
|
-
"adId"
|
|
1175
|
-
],
|
|
1176
|
-
"queryFields": [
|
|
1177
|
-
"type"
|
|
1178
|
-
],
|
|
1179
|
-
"headerFields": [],
|
|
1180
|
-
"cookieFields": [],
|
|
1181
|
-
"bodyFields": []
|
|
1182
|
-
};
|
|
1183
|
-
var OP_ZaloAdsGetApiPlaceGetalldistricts = {
|
|
1184
|
-
"operationId": "ZaloAds_getApiPlaceGetalldistricts",
|
|
1185
|
-
"method": "GET",
|
|
1186
|
-
"endpoint": "/api/place/getAllDistricts",
|
|
1187
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1188
|
-
"binaryFields": [],
|
|
1189
|
-
"pathFields": [],
|
|
1190
|
-
"queryFields": [],
|
|
1191
|
-
"headerFields": [],
|
|
1192
|
-
"cookieFields": [],
|
|
1193
|
-
"bodyFields": []
|
|
1194
|
-
};
|
|
1195
|
-
var OP_ZaloAdsGetApiSpellCheckV2 = {
|
|
1196
|
-
"operationId": "ZaloAds_getApiSpellCheckV2",
|
|
1197
|
-
"method": "GET",
|
|
1198
|
-
"endpoint": "/api/spell-check/v2",
|
|
1199
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1200
|
-
"binaryFields": [],
|
|
1201
|
-
"pathFields": [],
|
|
1202
|
-
"queryFields": [
|
|
1203
|
-
"text"
|
|
1204
|
-
],
|
|
1205
|
-
"headerFields": [],
|
|
1206
|
-
"cookieFields": [],
|
|
1207
|
-
"bodyFields": []
|
|
1208
|
-
};
|
|
1209
|
-
var OP_ZaloAdsGetZaapiCheckcamphasmanyads = {
|
|
1210
|
-
"operationId": "ZaloAds_getZaapiCheckcamphasmanyads",
|
|
1211
|
-
"method": "GET",
|
|
1212
|
-
"endpoint": "/zaapi/checkCampHasManyAds",
|
|
1213
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1214
|
-
"binaryFields": [],
|
|
1215
|
-
"pathFields": [],
|
|
1216
|
-
"queryFields": [
|
|
1217
|
-
"campaignId",
|
|
1218
|
-
"campId"
|
|
1219
|
-
],
|
|
1220
|
-
"headerFields": [],
|
|
1221
|
-
"cookieFields": [],
|
|
1222
|
-
"bodyFields": []
|
|
1223
|
-
};
|
|
1224
|
-
var OP_ZaloAdsGetZaapiGetadsfromcampaignid = {
|
|
1225
|
-
"operationId": "ZaloAds_getZaapiGetadsfromcampaignid",
|
|
1226
|
-
"method": "GET",
|
|
1227
|
-
"endpoint": "/zaapi/getAdsFromCampaignId",
|
|
1228
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1229
|
-
"binaryFields": [],
|
|
1230
|
-
"pathFields": [],
|
|
1231
|
-
"queryFields": [
|
|
1232
|
-
"campaignId",
|
|
1233
|
-
"campId"
|
|
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"
|
|
1234
1081
|
],
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
"operationId": "ZaloAds_getZaapiGetownedarticles",
|
|
1253
|
-
"method": "GET",
|
|
1254
|
-
"endpoint": "/zaapi/getOwnedArticles",
|
|
1255
|
-
"baseUrl": "https://ads.zalo.me",
|
|
1256
|
-
"binaryFields": [],
|
|
1257
|
-
"pathFields": [],
|
|
1258
|
-
"queryFields": [
|
|
1259
|
-
"pageId"
|
|
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"
|
|
1260
1099
|
],
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
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
|
+
]
|
|
1276
1121
|
};
|
|
1277
|
-
var
|
|
1278
|
-
"
|
|
1279
|
-
"
|
|
1280
|
-
"
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
"
|
|
1284
|
-
"
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
"
|
|
1289
|
-
"
|
|
1290
|
-
"
|
|
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)" }
|
|
1291
1157
|
};
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
"
|
|
1295
|
-
|
|
1296
|
-
|
|
1158
|
+
function validateCreateSavedAudienceRequest(input) {
|
|
1159
|
+
const errors = [];
|
|
1160
|
+
if (!input || typeof input !== "object") {
|
|
1161
|
+
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
1162
|
+
}
|
|
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.");
|
|
1169
|
+
}
|
|
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 = {};
|
|
1177
|
+
}
|
|
1178
|
+
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
1179
|
+
targetingObj = raw.targeting;
|
|
1180
|
+
} else {
|
|
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(", ")}.`);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
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).`);
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
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
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
const finalTargeting = {
|
|
1261
|
+
...targetingObj,
|
|
1262
|
+
CustomAudienceId: 0,
|
|
1263
|
+
Gender: gender,
|
|
1264
|
+
NewAgeRanges: newAgeRanges,
|
|
1265
|
+
Os: os,
|
|
1266
|
+
Location: location
|
|
1267
|
+
};
|
|
1268
|
+
return {
|
|
1269
|
+
isValid: errors.length === 0,
|
|
1270
|
+
errors,
|
|
1271
|
+
data: errors.length === 0 ? {
|
|
1272
|
+
name,
|
|
1273
|
+
caType: 1,
|
|
1274
|
+
targeting: JSON.stringify(finalTargeting)
|
|
1275
|
+
} : void 0
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
function validateCreatePhoneAudienceRequest(input) {
|
|
1279
|
+
const errors = [];
|
|
1280
|
+
if (!input || typeof input !== "object") {
|
|
1281
|
+
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
1282
|
+
}
|
|
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.");
|
|
1287
|
+
}
|
|
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.");
|
|
1294
|
+
}
|
|
1295
|
+
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
1296
|
+
targetingObj = raw.targeting;
|
|
1297
|
+
} else {
|
|
1298
|
+
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
1299
|
+
}
|
|
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.");
|
|
1303
|
+
}
|
|
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.");
|
|
1307
|
+
}
|
|
1308
|
+
return {
|
|
1309
|
+
isValid: errors.length === 0,
|
|
1310
|
+
errors,
|
|
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
|
|
1322
|
+
};
|
|
1323
|
+
}
|
|
1324
|
+
function validateCreateLookalikeAudienceRequest(input) {
|
|
1325
|
+
const errors = [];
|
|
1326
|
+
if (!input || typeof input !== "object") {
|
|
1327
|
+
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
1328
|
+
}
|
|
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.");
|
|
1333
|
+
}
|
|
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.");
|
|
1345
|
+
}
|
|
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.");
|
|
1349
|
+
}
|
|
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.");
|
|
1353
|
+
}
|
|
1354
|
+
return {
|
|
1355
|
+
isValid: errors.length === 0,
|
|
1356
|
+
errors,
|
|
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
|
|
1367
|
+
};
|
|
1368
|
+
}
|
|
1369
|
+
function validateCreateFormEventAudienceRequest(input) {
|
|
1370
|
+
const errors = [];
|
|
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.");
|
|
1404
|
+
}
|
|
1405
|
+
return {
|
|
1406
|
+
isValid: errors.length === 0,
|
|
1407
|
+
errors,
|
|
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
|
|
1418
|
+
};
|
|
1419
|
+
}
|
|
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
|
|
1546
|
+
};
|
|
1547
|
+
|
|
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;
|
|
1554
|
+
};
|
|
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;
|
|
1568
|
+
};
|
|
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;
|
|
1578
|
+
};
|
|
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;
|
|
1588
|
+
};
|
|
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;
|
|
1596
|
+
};
|
|
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
|
|
1622
|
+
};
|
|
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
|
|
1631
|
+
};
|
|
1632
|
+
var ZaloAdsOsId = {
|
|
1633
|
+
ANDROID: 0,
|
|
1634
|
+
IOS: 1,
|
|
1635
|
+
PC: 3
|
|
1636
|
+
};
|
|
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"
|
|
1712
|
+
};
|
|
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
|
|
1791
|
+
};
|
|
1792
|
+
var ZaloAdsUpdateVideoAdRequest = class {
|
|
1793
|
+
data;
|
|
1794
|
+
est;
|
|
1795
|
+
isBoostAd;
|
|
1796
|
+
stt;
|
|
1797
|
+
};
|
|
1798
|
+
var ZaloAdsUpdateVideoAdResponse = class {
|
|
1799
|
+
code;
|
|
1800
|
+
msg;
|
|
1801
|
+
data;
|
|
1802
|
+
};
|
|
1803
|
+
var ZaloAdsCampaignStatus = {
|
|
1804
|
+
OFF: 0,
|
|
1805
|
+
ACTIVE: 1,
|
|
1806
|
+
PAUSED: 2,
|
|
1807
|
+
DELETED: -2
|
|
1808
|
+
};
|
|
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;
|
|
1812
|
+
};
|
|
1813
|
+
var ZaloAdsCreatePostCampaignResponse = class {
|
|
1814
|
+
code;
|
|
1815
|
+
/** Chuỗi ID quảng cáo mới trong response Zalo Ads. */
|
|
1816
|
+
msg;
|
|
1817
|
+
data;
|
|
1818
|
+
};
|
|
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;
|
|
1839
|
+
};
|
|
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;
|
|
1849
|
+
};
|
|
1850
|
+
var ZaloAdsUpdateMessageAdResponse = class {
|
|
1851
|
+
msg;
|
|
1852
|
+
code;
|
|
1853
|
+
data;
|
|
1854
|
+
};
|
|
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
|
|
1866
|
+
};
|
|
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
|
|
1877
|
+
};
|
|
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
|
|
1890
|
+
],
|
|
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]
|
|
1928
|
+
};
|
|
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.");
|
|
1936
|
+
}
|
|
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
|
+
);
|
|
1944
|
+
}
|
|
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
|
+
}
|
|
1953
|
+
}
|
|
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;
|
|
1975
|
+
}
|
|
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
|
+
}
|
|
1986
|
+
}
|
|
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
|
+
}
|
|
1991
|
+
}
|
|
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).");
|
|
2003
|
+
}
|
|
2004
|
+
if (!payload.CampaignId || payload.CampaignId <= 0) {
|
|
2005
|
+
errors.push("CampaignId l\xE0 b\u1EAFt bu\u1ED9c (ph\u1EA3i > 0).");
|
|
2006
|
+
}
|
|
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).`);
|
|
2011
|
+
}
|
|
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
|
+
}
|
|
2052
|
+
}
|
|
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
|
+
}
|
|
2180
|
+
}
|
|
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
|
+
}
|
|
2255
|
+
}
|
|
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
|
+
}
|
|
2268
|
+
}
|
|
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
|
+
}
|
|
2305
|
+
}
|
|
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.");
|
|
2319
|
+
}
|
|
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).`);
|
|
2324
|
+
}
|
|
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.");
|
|
2336
|
+
}
|
|
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).`);
|
|
2339
|
+
}
|
|
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)."
|
|
2343
|
+
);
|
|
2344
|
+
}
|
|
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.");
|
|
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",
|
|
1297
2390
|
"binaryFields": [],
|
|
1298
2391
|
"pathFields": [],
|
|
1299
|
-
"queryFields": [
|
|
1300
|
-
"templateIds"
|
|
1301
|
-
],
|
|
2392
|
+
"queryFields": [],
|
|
1302
2393
|
"headerFields": [],
|
|
1303
2394
|
"cookieFields": [],
|
|
1304
|
-
"bodyFields": [
|
|
2395
|
+
"bodyFields": [
|
|
2396
|
+
"status",
|
|
2397
|
+
"campaignId"
|
|
2398
|
+
]
|
|
1305
2399
|
};
|
|
1306
|
-
var
|
|
1307
|
-
"operationId": "
|
|
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",
|
|
1308
2430
|
"method": "POST",
|
|
1309
|
-
"endpoint": "/zaapi/
|
|
2431
|
+
"endpoint": "/zaapi/addNewCamp",
|
|
1310
2432
|
"baseUrl": "https://ads.zalo.me",
|
|
1311
2433
|
"binaryFields": [],
|
|
1312
2434
|
"pathFields": [],
|
|
1313
|
-
"queryFields": [
|
|
1314
|
-
"adId"
|
|
1315
|
-
],
|
|
2435
|
+
"queryFields": [],
|
|
1316
2436
|
"headerFields": [],
|
|
1317
2437
|
"cookieFields": [],
|
|
1318
2438
|
"bodyFields": [
|
|
1319
|
-
"
|
|
2439
|
+
"data"
|
|
1320
2440
|
]
|
|
1321
2441
|
};
|
|
1322
|
-
var
|
|
1323
|
-
"operationId": "
|
|
2442
|
+
var OP_ZaloAdsCreateMessageCampaign = {
|
|
2443
|
+
"operationId": "ZaloAds_createMessageCampaign",
|
|
1324
2444
|
"method": "POST",
|
|
1325
|
-
"endpoint": "/
|
|
2445
|
+
"endpoint": "/zaapi/addNewCamp",
|
|
1326
2446
|
"baseUrl": "https://ads.zalo.me",
|
|
1327
2447
|
"binaryFields": [],
|
|
1328
2448
|
"pathFields": [],
|
|
@@ -1330,14 +2450,13 @@ var OP_ZaloAdsRenameCampaign = {
|
|
|
1330
2450
|
"headerFields": [],
|
|
1331
2451
|
"cookieFields": [],
|
|
1332
2452
|
"bodyFields": [
|
|
1333
|
-
"
|
|
1334
|
-
"newname"
|
|
2453
|
+
"data"
|
|
1335
2454
|
]
|
|
1336
2455
|
};
|
|
1337
|
-
var
|
|
1338
|
-
"operationId": "
|
|
2456
|
+
var OP_ZaloAdsCreateOfficialAccountCampaign = {
|
|
2457
|
+
"operationId": "ZaloAds_createOfficialAccountCampaign",
|
|
1339
2458
|
"method": "POST",
|
|
1340
|
-
"endpoint": "/zaapi/
|
|
2459
|
+
"endpoint": "/zaapi/addNewCamp",
|
|
1341
2460
|
"baseUrl": "https://ads.zalo.me",
|
|
1342
2461
|
"binaryFields": [],
|
|
1343
2462
|
"pathFields": [],
|
|
@@ -1345,16 +2464,13 @@ var OP_ZaloAdsUpdateEcommerceAd = {
|
|
|
1345
2464
|
"headerFields": [],
|
|
1346
2465
|
"cookieFields": [],
|
|
1347
2466
|
"bodyFields": [
|
|
1348
|
-
"
|
|
1349
|
-
"stt",
|
|
1350
|
-
"data",
|
|
1351
|
-
"isBoostAd"
|
|
2467
|
+
"data"
|
|
1352
2468
|
]
|
|
1353
2469
|
};
|
|
1354
|
-
var
|
|
1355
|
-
"operationId": "
|
|
2470
|
+
var OP_ZaloAdsCreatePostCampaign = {
|
|
2471
|
+
"operationId": "ZaloAds_createPostCampaign",
|
|
1356
2472
|
"method": "POST",
|
|
1357
|
-
"endpoint": "/zaapi/
|
|
2473
|
+
"endpoint": "/zaapi/addNewCamp",
|
|
1358
2474
|
"baseUrl": "https://ads.zalo.me",
|
|
1359
2475
|
"binaryFields": [],
|
|
1360
2476
|
"pathFields": [],
|
|
@@ -1362,88 +2478,186 @@ var OP_ZaloAdsUpdateFormAd = {
|
|
|
1362
2478
|
"headerFields": [],
|
|
1363
2479
|
"cookieFields": [],
|
|
1364
2480
|
"bodyFields": [
|
|
1365
|
-
"
|
|
1366
|
-
"stt",
|
|
1367
|
-
"data",
|
|
1368
|
-
"isBoostAd"
|
|
2481
|
+
"data"
|
|
1369
2482
|
]
|
|
1370
2483
|
};
|
|
1371
|
-
var
|
|
1372
|
-
"operationId": "
|
|
1373
|
-
"method": "
|
|
1374
|
-
"endpoint": "/zaapi/
|
|
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",
|
|
1375
2520
|
"baseUrl": "https://ads.zalo.me",
|
|
1376
2521
|
"binaryFields": [],
|
|
1377
2522
|
"pathFields": [],
|
|
1378
2523
|
"queryFields": [],
|
|
1379
2524
|
"headerFields": [],
|
|
1380
2525
|
"cookieFields": [],
|
|
1381
|
-
"bodyFields": [
|
|
1382
|
-
"est",
|
|
1383
|
-
"stt",
|
|
1384
|
-
"data",
|
|
1385
|
-
"isBoostAd"
|
|
1386
|
-
]
|
|
2526
|
+
"bodyFields": []
|
|
1387
2527
|
};
|
|
1388
|
-
var
|
|
1389
|
-
"operationId": "
|
|
1390
|
-
"method": "
|
|
1391
|
-
"endpoint": "/
|
|
2528
|
+
var OP_ZaloAdsGetApiSpellCheckV2 = {
|
|
2529
|
+
"operationId": "ZaloAds_getApiSpellCheckV2",
|
|
2530
|
+
"method": "GET",
|
|
2531
|
+
"endpoint": "/api/spell-check/v2",
|
|
1392
2532
|
"baseUrl": "https://ads.zalo.me",
|
|
1393
|
-
"binaryFields": [
|
|
1394
|
-
|
|
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"
|
|
1395
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": [],
|
|
1396
2580
|
"pathFields": [],
|
|
1397
2581
|
"queryFields": [],
|
|
1398
2582
|
"headerFields": [],
|
|
1399
2583
|
"cookieFields": [],
|
|
1400
|
-
"bodyFields": [
|
|
1401
|
-
"File",
|
|
1402
|
-
"x",
|
|
1403
|
-
"y",
|
|
1404
|
-
"width",
|
|
1405
|
-
"height",
|
|
1406
|
-
"scale"
|
|
1407
|
-
]
|
|
2584
|
+
"bodyFields": []
|
|
1408
2585
|
};
|
|
1409
|
-
var
|
|
1410
|
-
"operationId": "
|
|
1411
|
-
"method": "
|
|
1412
|
-
"endpoint": "/zaapi/
|
|
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",
|
|
1413
2604
|
"baseUrl": "https://ads.zalo.me",
|
|
1414
2605
|
"binaryFields": [],
|
|
1415
2606
|
"pathFields": [],
|
|
1416
2607
|
"queryFields": [],
|
|
1417
2608
|
"headerFields": [],
|
|
1418
2609
|
"cookieFields": [],
|
|
1419
|
-
"bodyFields": [
|
|
1420
|
-
"est",
|
|
1421
|
-
"stt",
|
|
1422
|
-
"data",
|
|
1423
|
-
"isBoostAd"
|
|
1424
|
-
]
|
|
2610
|
+
"bodyFields": []
|
|
1425
2611
|
};
|
|
1426
|
-
var
|
|
1427
|
-
"operationId": "
|
|
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",
|
|
1428
2643
|
"method": "POST",
|
|
1429
|
-
"endpoint": "/zaapi/
|
|
2644
|
+
"endpoint": "/zaapi/deleteAd",
|
|
1430
2645
|
"baseUrl": "https://ads.zalo.me",
|
|
1431
2646
|
"binaryFields": [],
|
|
1432
2647
|
"pathFields": [],
|
|
1433
|
-
"queryFields": [
|
|
2648
|
+
"queryFields": [
|
|
2649
|
+
"adId"
|
|
2650
|
+
],
|
|
1434
2651
|
"headerFields": [],
|
|
1435
2652
|
"cookieFields": [],
|
|
1436
2653
|
"bodyFields": [
|
|
1437
|
-
"
|
|
1438
|
-
"stt",
|
|
1439
|
-
"data",
|
|
1440
|
-
"isBoostAd"
|
|
2654
|
+
"adId"
|
|
1441
2655
|
]
|
|
1442
2656
|
};
|
|
1443
|
-
var
|
|
1444
|
-
"operationId": "
|
|
2657
|
+
var OP_ZaloAdsRenameCampaign = {
|
|
2658
|
+
"operationId": "ZaloAds_renameCampaign",
|
|
1445
2659
|
"method": "POST",
|
|
1446
|
-
"endpoint": "/
|
|
2660
|
+
"endpoint": "/api/campaign/change-name",
|
|
1447
2661
|
"baseUrl": "https://ads.zalo.me",
|
|
1448
2662
|
"binaryFields": [],
|
|
1449
2663
|
"pathFields": [],
|
|
@@ -1451,11 +2665,12 @@ var OP_ZaloAdsCreateWebsiteCampaign = {
|
|
|
1451
2665
|
"headerFields": [],
|
|
1452
2666
|
"cookieFields": [],
|
|
1453
2667
|
"bodyFields": [
|
|
1454
|
-
"
|
|
2668
|
+
"campid",
|
|
2669
|
+
"newname"
|
|
1455
2670
|
]
|
|
1456
2671
|
};
|
|
1457
|
-
var
|
|
1458
|
-
"operationId": "
|
|
2672
|
+
var OP_ZaloAdsUpdateEcommerceAd = {
|
|
2673
|
+
"operationId": "ZaloAds_updateEcommerceAd",
|
|
1459
2674
|
"method": "POST",
|
|
1460
2675
|
"endpoint": "/zaapi/UpdateAd",
|
|
1461
2676
|
"baseUrl": "https://ads.zalo.me",
|
|
@@ -1471,10 +2686,10 @@ var OP_ZaloAdsUpdateWebsiteAd = {
|
|
|
1471
2686
|
"isBoostAd"
|
|
1472
2687
|
]
|
|
1473
2688
|
};
|
|
1474
|
-
var
|
|
1475
|
-
"operationId": "
|
|
2689
|
+
var OP_ZaloAdsUpdateFormAd = {
|
|
2690
|
+
"operationId": "ZaloAds_updateFormAd",
|
|
1476
2691
|
"method": "POST",
|
|
1477
|
-
"endpoint": "/zaapi/
|
|
2692
|
+
"endpoint": "/zaapi/UpdateAd",
|
|
1478
2693
|
"baseUrl": "https://ads.zalo.me",
|
|
1479
2694
|
"binaryFields": [],
|
|
1480
2695
|
"pathFields": [],
|
|
@@ -1482,11 +2697,14 @@ var OP_ZaloAdsCreateDisplayCampaign = {
|
|
|
1482
2697
|
"headerFields": [],
|
|
1483
2698
|
"cookieFields": [],
|
|
1484
2699
|
"bodyFields": [
|
|
1485
|
-
"
|
|
2700
|
+
"est",
|
|
2701
|
+
"stt",
|
|
2702
|
+
"data",
|
|
2703
|
+
"isBoostAd"
|
|
1486
2704
|
]
|
|
1487
2705
|
};
|
|
1488
|
-
var
|
|
1489
|
-
"operationId": "
|
|
2706
|
+
var OP_ZaloAdsUpdateMessageAd = {
|
|
2707
|
+
"operationId": "ZaloAds_updateMessageAd",
|
|
1490
2708
|
"method": "POST",
|
|
1491
2709
|
"endpoint": "/zaapi/UpdateAd",
|
|
1492
2710
|
"baseUrl": "https://ads.zalo.me",
|
|
@@ -1502,24 +2720,31 @@ var OP_ZaloAdsUpdateDisplayAd = {
|
|
|
1502
2720
|
"isBoostAd"
|
|
1503
2721
|
]
|
|
1504
2722
|
};
|
|
1505
|
-
var
|
|
1506
|
-
"operationId": "
|
|
2723
|
+
var OP_ZaloAdsUpdateNewAds = {
|
|
2724
|
+
"operationId": "ZaloAds_UpdateNewAds",
|
|
1507
2725
|
"method": "POST",
|
|
1508
|
-
"endpoint": "/zaapi/
|
|
2726
|
+
"endpoint": "/zaapi/UploadCrop",
|
|
1509
2727
|
"baseUrl": "https://ads.zalo.me",
|
|
1510
|
-
"binaryFields": [
|
|
2728
|
+
"binaryFields": [
|
|
2729
|
+
"File"
|
|
2730
|
+
],
|
|
1511
2731
|
"pathFields": [],
|
|
1512
2732
|
"queryFields": [],
|
|
1513
2733
|
"headerFields": [],
|
|
1514
2734
|
"cookieFields": [],
|
|
1515
2735
|
"bodyFields": [
|
|
1516
|
-
"
|
|
2736
|
+
"File",
|
|
2737
|
+
"x",
|
|
2738
|
+
"y",
|
|
2739
|
+
"width",
|
|
2740
|
+
"height",
|
|
2741
|
+
"scale"
|
|
1517
2742
|
]
|
|
1518
2743
|
};
|
|
1519
|
-
var
|
|
1520
|
-
"operationId": "
|
|
2744
|
+
var OP_ZaloAdsUpdateOfficialAccountAd = {
|
|
2745
|
+
"operationId": "ZaloAds_updateOfficialAccountAd",
|
|
1521
2746
|
"method": "POST",
|
|
1522
|
-
"endpoint": "/
|
|
2747
|
+
"endpoint": "/zaapi/UpdateAd",
|
|
1523
2748
|
"baseUrl": "https://ads.zalo.me",
|
|
1524
2749
|
"binaryFields": [],
|
|
1525
2750
|
"pathFields": [],
|
|
@@ -1527,736 +2752,537 @@ var OP_ZaloAdsDeleteCampaign = {
|
|
|
1527
2752
|
"headerFields": [],
|
|
1528
2753
|
"cookieFields": [],
|
|
1529
2754
|
"bodyFields": [
|
|
1530
|
-
"
|
|
1531
|
-
"
|
|
2755
|
+
"est",
|
|
2756
|
+
"stt",
|
|
2757
|
+
"data",
|
|
2758
|
+
"isBoostAd"
|
|
1532
2759
|
]
|
|
1533
2760
|
};
|
|
1534
|
-
var
|
|
1535
|
-
operationId: "
|
|
1536
|
-
method: "POST",
|
|
1537
|
-
endpoint: "/
|
|
1538
|
-
baseUrl: "https://ads.zalo.me",
|
|
1539
|
-
binaryFields: [],
|
|
1540
|
-
pathFields: [],
|
|
1541
|
-
queryFields: [],
|
|
1542
|
-
headerFields: [],
|
|
1543
|
-
cookieFields: [],
|
|
1544
|
-
bodyFields: ["title", "caption"]
|
|
1545
|
-
};
|
|
1546
|
-
var OP_ZaloAdsGetSpellCheckV3Job = {
|
|
1547
|
-
operationId: "zalo_ads_get_spell_check_v3_job",
|
|
1548
|
-
method: "GET",
|
|
1549
|
-
endpoint: "/api/spell-check/v3/{jobId}",
|
|
1550
|
-
baseUrl: "https://ads.zalo.me",
|
|
1551
|
-
binaryFields: [],
|
|
1552
|
-
pathFields: ["jobId"],
|
|
1553
|
-
queryFields: [],
|
|
1554
|
-
headerFields: [],
|
|
1555
|
-
cookieFields: [],
|
|
1556
|
-
bodyFields: []
|
|
1557
|
-
};
|
|
1558
|
-
var ZaloCampaignsService = class {
|
|
1559
|
-
constructor(client) {
|
|
1560
|
-
this.client = client;
|
|
1561
|
-
}
|
|
1562
|
-
updateVideoAd(request, options) {
|
|
1563
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateVideoAd, this.client.toTransportInput(OP_ZaloAdsUpdateVideoAd, request), options);
|
|
1564
|
-
}
|
|
1565
|
-
changeCampaignStatus(request, options) {
|
|
1566
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsChangeCampaignStatus, this.client.toTransportInput(OP_ZaloAdsChangeCampaignStatus, request), options);
|
|
1567
|
-
}
|
|
1568
|
-
deleteCampaign(request, options) {
|
|
1569
|
-
const payload = { campaignId: request.campaignId, status: request.status ?? -2 };
|
|
1570
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsDeleteCampaign, this.client.toTransportInput(OP_ZaloAdsDeleteCampaign, payload), options);
|
|
1571
|
-
}
|
|
1572
|
-
createWebsiteCampaign(request, options) {
|
|
1573
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateWebsiteCampaign, this.client.toTransportInput(OP_ZaloAdsCreateWebsiteCampaign, request), options);
|
|
1574
|
-
}
|
|
1575
|
-
updateWebsiteAd(request, options) {
|
|
1576
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateWebsiteAd, this.client.toTransportInput(OP_ZaloAdsUpdateWebsiteAd, request), options);
|
|
1577
|
-
}
|
|
1578
|
-
createDisplayCampaign(request, options) {
|
|
1579
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateDisplayCampaign, this.client.toTransportInput(OP_ZaloAdsCreateDisplayCampaign, request), options);
|
|
1580
|
-
}
|
|
1581
|
-
updateDisplayAd(request, options) {
|
|
1582
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateDisplayAd, this.client.toTransportInput(OP_ZaloAdsUpdateDisplayAd, request), options);
|
|
1583
|
-
}
|
|
1584
|
-
createVideoCampaign(request, options) {
|
|
1585
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateVideoCampaign, this.client.toTransportInput(OP_ZaloAdsCreateVideoCampaign, request), options);
|
|
1586
|
-
}
|
|
1587
|
-
createEcommerceCampaign(request, options) {
|
|
1588
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateEcommerceCampaign, this.client.toTransportInput(OP_ZaloAdsCreateEcommerceCampaign, request), options);
|
|
1589
|
-
}
|
|
1590
|
-
/** Alias theo tên tool chuẩn `zalo_ads_create_commerce_campaign` trong Project Schema Zalo ADS (`campaignType = 22`). */
|
|
1591
|
-
createCommerceCampaign(request, options) {
|
|
1592
|
-
return this.createEcommerceCampaign(request, options);
|
|
1593
|
-
}
|
|
1594
|
-
createForm(request, options) {
|
|
1595
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateForm, this.client.toTransportInput(OP_ZaloAdsCreateForm, request), options);
|
|
1596
|
-
}
|
|
1597
|
-
createFormCampaign(request, options) {
|
|
1598
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateFormCampaign, this.client.toTransportInput(OP_ZaloAdsCreateFormCampaign, request), options);
|
|
1599
|
-
}
|
|
1600
|
-
createMessageCampaign(request, options) {
|
|
1601
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateMessageCampaign, this.client.toTransportInput(OP_ZaloAdsCreateMessageCampaign, request), options);
|
|
1602
|
-
}
|
|
1603
|
-
createOfficialAccountCampaign(request, options) {
|
|
1604
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateOfficialAccountCampaign, this.client.toTransportInput(OP_ZaloAdsCreateOfficialAccountCampaign, request), options);
|
|
1605
|
-
}
|
|
1606
|
-
/** Alias theo tên tool chuẩn `zalo_ads_create_oa_campaign` trong Project Schema Zalo ADS (`campaignType = 3`). */
|
|
1607
|
-
createOaCampaign(request, options) {
|
|
1608
|
-
return this.createOfficialAccountCampaign(request, options);
|
|
1609
|
-
}
|
|
1610
|
-
createPostCampaign(request, options) {
|
|
1611
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreatePostCampaign, this.client.toTransportInput(OP_ZaloAdsCreatePostCampaign, request), options);
|
|
1612
|
-
}
|
|
1613
|
-
/** Alias theo tên tool chuẩn `zalo_ads_create_article_campaign` trong Project Schema Zalo ADS (`campaignType = 4`). */
|
|
1614
|
-
createArticleCampaign(request, options) {
|
|
1615
|
-
return this.createPostCampaign(request, options);
|
|
1616
|
-
}
|
|
1617
|
-
getAdById(request = {}, options) {
|
|
1618
|
-
return this.client.requestWithoutBody(OP_ZaloAdsGetAdById, this.client.toTransportInput(OP_ZaloAdsGetAdById, request), options);
|
|
1619
|
-
}
|
|
1620
|
-
getAdChangeLog(request, options) {
|
|
1621
|
-
return this.client.requestWithoutBody(OP_ZaloAdsGetAdChangeLog, this.client.toTransportInput(OP_ZaloAdsGetAdChangeLog, request), options);
|
|
1622
|
-
}
|
|
1623
|
-
getApiPlaceGetalldistricts(request = {}, options) {
|
|
1624
|
-
return this.client.requestWithoutBody(OP_ZaloAdsGetApiPlaceGetalldistricts, this.client.toTransportInput(OP_ZaloAdsGetApiPlaceGetalldistricts, request), options);
|
|
1625
|
-
}
|
|
1626
|
-
getApiSpellCheckV2(request, options) {
|
|
1627
|
-
return this.client.requestWithoutBody(OP_ZaloAdsGetApiSpellCheckV2, this.client.toTransportInput(OP_ZaloAdsGetApiSpellCheckV2, request), options);
|
|
1628
|
-
}
|
|
1629
|
-
getZaapiCheckcamphasmanyads(request = {}, options) {
|
|
1630
|
-
return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiCheckcamphasmanyads, this.client.toTransportInput(OP_ZaloAdsGetZaapiCheckcamphasmanyads, request), options);
|
|
1631
|
-
}
|
|
1632
|
-
getZaapiGetadsfromcampaignid(request = {}, options) {
|
|
1633
|
-
return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetadsfromcampaignid, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetadsfromcampaignid, request), options);
|
|
1634
|
-
}
|
|
1635
|
-
getZaapiGetallpages(request = {}, options) {
|
|
1636
|
-
return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetallpages, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetallpages, request), options);
|
|
1637
|
-
}
|
|
1638
|
-
getAllPages(request = {}, options) {
|
|
1639
|
-
return this.getZaapiGetallpages(request, options);
|
|
1640
|
-
}
|
|
1641
|
-
getZaapiGetownedarticles(request, options) {
|
|
1642
|
-
return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetownedarticles, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetownedarticles, request), options);
|
|
1643
|
-
}
|
|
1644
|
-
getOwnedArticles(request, options) {
|
|
1645
|
-
return this.getZaapiGetownedarticles(request, options);
|
|
1646
|
-
}
|
|
1647
|
-
getZaapiGetownedpages(request = {}, options) {
|
|
1648
|
-
return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetownedpages, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetownedpages, request), options);
|
|
1649
|
-
}
|
|
1650
|
-
getOwnedPages(request = {}, options) {
|
|
1651
|
-
return this.getZaapiGetownedpages(request, options);
|
|
1652
|
-
}
|
|
1653
|
-
listFormsByOfficialAccount(request, options) {
|
|
1654
|
-
return this.client.requestWithoutBody(OP_ZaloAdsListFormsByOfficialAccount, this.client.toTransportInput(OP_ZaloAdsListFormsByOfficialAccount, request), options);
|
|
1655
|
-
}
|
|
1656
|
-
listMiniPagesByTemplate(request, options) {
|
|
1657
|
-
return this.client.requestWithoutBody(OP_ZaloAdsListMiniPagesByTemplate, this.client.toTransportInput(OP_ZaloAdsListMiniPagesByTemplate, request), options);
|
|
1658
|
-
}
|
|
1659
|
-
postZaapiDeletead(request = {}, options) {
|
|
1660
|
-
return this.client.requestWithoutBody(OP_ZaloAdsPostZaapiDeletead, this.client.toTransportInput(OP_ZaloAdsPostZaapiDeletead, request), options);
|
|
1661
|
-
}
|
|
1662
|
-
renameCampaign(request, options) {
|
|
1663
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsRenameCampaign, this.client.toTransportInput(OP_ZaloAdsRenameCampaign, request), options);
|
|
1664
|
-
}
|
|
1665
|
-
updateEcommerceAd(request, options) {
|
|
1666
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateEcommerceAd, this.client.toTransportInput(OP_ZaloAdsUpdateEcommerceAd, request), options);
|
|
1667
|
-
}
|
|
1668
|
-
/** Alias theo tên tool chuẩn `zalo_ads_update_commerce_ad` trong Project Schema Zalo ADS (`Type = 23`, gắn `MiniPageId`). */
|
|
1669
|
-
updateCommerceAd(request, options) {
|
|
1670
|
-
return this.updateEcommerceAd(request, options);
|
|
1671
|
-
}
|
|
1672
|
-
updateFormAd(request, options) {
|
|
1673
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateFormAd, this.client.toTransportInput(OP_ZaloAdsUpdateFormAd, request), options);
|
|
1674
|
-
}
|
|
1675
|
-
updateMessageAd(request, options) {
|
|
1676
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateMessageAd, this.client.toTransportInput(OP_ZaloAdsUpdateMessageAd, request), options);
|
|
1677
|
-
}
|
|
1678
|
-
updateNewAds(request, options) {
|
|
1679
|
-
return this.client.requestMultipart(OP_ZaloAdsUpdateNewAds, this.client.toTransportInput(OP_ZaloAdsUpdateNewAds, request), options);
|
|
1680
|
-
}
|
|
1681
|
-
updateOfficialAccountAd(request, options) {
|
|
1682
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateOfficialAccountAd, this.client.toTransportInput(OP_ZaloAdsUpdateOfficialAccountAd, request), options);
|
|
1683
|
-
}
|
|
1684
|
-
/** Alias theo tên tool chuẩn `zalo_ads_update_oa_ad` trong Project Schema Zalo ADS (`Type = 2`, `Action = 6`). */
|
|
1685
|
-
updateOaAd(request, options) {
|
|
1686
|
-
return this.updateOfficialAccountAd(request, options);
|
|
1687
|
-
}
|
|
1688
|
-
updatePostAd(request, options) {
|
|
1689
|
-
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdatePostAd, this.client.toTransportInput(OP_ZaloAdsUpdatePostAd, request), options);
|
|
1690
|
-
}
|
|
1691
|
-
/** Alias theo tên tool chuẩn `zalo_ads_update_article_ad` trong Project Schema Zalo ADS (`Type = 3`, gắn `ZaloFeedId`). */
|
|
1692
|
-
updateArticleAd(request, options) {
|
|
1693
|
-
return this.updatePostAd(request, options);
|
|
1694
|
-
}
|
|
1695
|
-
/** Xóa quảng cáo */
|
|
1696
|
-
deleteAd(...args) {
|
|
1697
|
-
return this.postZaapiDeletead(...args);
|
|
1698
|
-
}
|
|
1699
|
-
/** Danh sách quận/huyện để nhắm mục tiêu */
|
|
1700
|
-
getAllDistricts(...args) {
|
|
1701
|
-
return this.getApiPlaceGetalldistricts(...args);
|
|
1702
|
-
}
|
|
1703
|
-
/** Kiểm tra chính tả văn bản quảng cáo */
|
|
1704
|
-
getSpellCheckV2(...args) {
|
|
1705
|
-
return this.getApiSpellCheckV2(...args);
|
|
1706
|
-
}
|
|
1707
|
-
/**
|
|
1708
|
-
* 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).
|
|
1709
|
-
*/
|
|
1710
|
-
createSpellCheckV3Job(request, options) {
|
|
1711
|
-
return this.client.requestJson(
|
|
1712
|
-
OP_ZaloAdsCreateSpellCheckV3Job,
|
|
1713
|
-
this.client.toTransportInput(OP_ZaloAdsCreateSpellCheckV3Job, request),
|
|
1714
|
-
options
|
|
1715
|
-
);
|
|
1716
|
-
}
|
|
1717
|
-
/**
|
|
1718
|
-
* Lấy kết quả kiểm tra chính tả AI V3 theo jobId (GET /api/spell-check/v3/{jobId}).
|
|
1719
|
-
*/
|
|
1720
|
-
getSpellCheckV3Job(request, options) {
|
|
1721
|
-
return this.client.requestWithoutBody(
|
|
1722
|
-
OP_ZaloAdsGetSpellCheckV3Job,
|
|
1723
|
-
this.client.toTransportInput(OP_ZaloAdsGetSpellCheckV3Job, request),
|
|
1724
|
-
options
|
|
1725
|
-
);
|
|
1726
|
-
}
|
|
1727
|
-
/**
|
|
1728
|
-
* 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).
|
|
1729
|
-
* @param request Tiêu đề (title) và chú thích (caption) cần kiểm tra.
|
|
1730
|
-
* @param pollIntervalMs Chu kỳ polling kiểm tra trạng thái (mặc định: 600ms).
|
|
1731
|
-
* @param timeoutMs Thời gian chờ tối đa (mặc định: 15.000ms = 15 giây).
|
|
1732
|
-
*/
|
|
1733
|
-
async checkSpellV3AndWait(request, pollIntervalMs = 600, timeoutMs = 15e3, options) {
|
|
1734
|
-
const jobRes = await this.createSpellCheckV3Job(request, options);
|
|
1735
|
-
const jobId = jobRes?.data?.jobId;
|
|
1736
|
-
if (!jobId) {
|
|
1737
|
-
throw new Error(`[SpellCheckV3] Kh\xF4ng nh\u1EADn \u0111\u01B0\u1EE3c jobId t\u1EEB Zalo Ads (code: ${jobRes?.code})`);
|
|
1738
|
-
}
|
|
1739
|
-
const startTime = Date.now();
|
|
1740
|
-
while (Date.now() - startTime < timeoutMs) {
|
|
1741
|
-
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
1742
|
-
const res = await this.getSpellCheckV3Job({ jobId }, options);
|
|
1743
|
-
if (res?.data?.status === "COMPLETED") {
|
|
1744
|
-
return res;
|
|
1745
|
-
}
|
|
1746
|
-
}
|
|
1747
|
-
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}`);
|
|
1748
|
-
}
|
|
1749
|
-
};
|
|
1750
|
-
|
|
1751
|
-
// src/services/account.service.ts
|
|
1752
|
-
var OP_ZaloAdsGetApiWhoami = {
|
|
1753
|
-
"operationId": "ZaloAds_getApiWhoami",
|
|
1754
|
-
"method": "GET",
|
|
1755
|
-
"endpoint": "/api/whoami",
|
|
2761
|
+
var OP_ZaloAdsUpdatePostAd = {
|
|
2762
|
+
"operationId": "ZaloAds_updatePostAd",
|
|
2763
|
+
"method": "POST",
|
|
2764
|
+
"endpoint": "/zaapi/UpdateAd",
|
|
1756
2765
|
"baseUrl": "https://ads.zalo.me",
|
|
1757
2766
|
"binaryFields": [],
|
|
1758
2767
|
"pathFields": [],
|
|
1759
2768
|
"queryFields": [],
|
|
1760
2769
|
"headerFields": [],
|
|
1761
2770
|
"cookieFields": [],
|
|
1762
|
-
"bodyFields": [
|
|
2771
|
+
"bodyFields": [
|
|
2772
|
+
"est",
|
|
2773
|
+
"stt",
|
|
2774
|
+
"data",
|
|
2775
|
+
"isBoostAd"
|
|
2776
|
+
]
|
|
1763
2777
|
};
|
|
1764
|
-
var
|
|
1765
|
-
"operationId": "
|
|
1766
|
-
"method": "
|
|
1767
|
-
"endpoint": "/
|
|
2778
|
+
var OP_ZaloAdsCreateWebsiteCampaign = {
|
|
2779
|
+
"operationId": "ZaloAds_createWebsiteCampaign",
|
|
2780
|
+
"method": "POST",
|
|
2781
|
+
"endpoint": "/zaapi/addNewCamp",
|
|
1768
2782
|
"baseUrl": "https://ads.zalo.me",
|
|
1769
2783
|
"binaryFields": [],
|
|
1770
2784
|
"pathFields": [],
|
|
1771
|
-
"queryFields": [
|
|
1772
|
-
"to",
|
|
1773
|
-
"from",
|
|
1774
|
-
"memberId"
|
|
1775
|
-
],
|
|
2785
|
+
"queryFields": [],
|
|
1776
2786
|
"headerFields": [],
|
|
1777
2787
|
"cookieFields": [],
|
|
1778
|
-
"bodyFields": [
|
|
2788
|
+
"bodyFields": [
|
|
2789
|
+
"data"
|
|
2790
|
+
]
|
|
1779
2791
|
};
|
|
1780
|
-
var
|
|
1781
|
-
"operationId": "
|
|
1782
|
-
"method": "
|
|
1783
|
-
"endpoint": "/
|
|
2792
|
+
var OP_ZaloAdsUpdateWebsiteAd = {
|
|
2793
|
+
"operationId": "ZaloAds_updateWebsiteAd",
|
|
2794
|
+
"method": "POST",
|
|
2795
|
+
"endpoint": "/zaapi/UpdateAd",
|
|
1784
2796
|
"baseUrl": "https://ads.zalo.me",
|
|
1785
2797
|
"binaryFields": [],
|
|
1786
2798
|
"pathFields": [],
|
|
1787
|
-
"queryFields": [
|
|
1788
|
-
"isShowAll"
|
|
1789
|
-
],
|
|
2799
|
+
"queryFields": [],
|
|
1790
2800
|
"headerFields": [],
|
|
1791
2801
|
"cookieFields": [],
|
|
1792
|
-
"bodyFields": [
|
|
2802
|
+
"bodyFields": [
|
|
2803
|
+
"est",
|
|
2804
|
+
"stt",
|
|
2805
|
+
"data",
|
|
2806
|
+
"isBoostAd"
|
|
2807
|
+
]
|
|
1793
2808
|
};
|
|
1794
|
-
var
|
|
1795
|
-
"operationId": "
|
|
1796
|
-
"method": "
|
|
1797
|
-
"endpoint": "/
|
|
2809
|
+
var OP_ZaloAdsCreateDisplayCampaign = {
|
|
2810
|
+
"operationId": "ZaloAds_createDisplayCampaign",
|
|
2811
|
+
"method": "POST",
|
|
2812
|
+
"endpoint": "/zaapi/addNewCamp",
|
|
1798
2813
|
"baseUrl": "https://ads.zalo.me",
|
|
1799
2814
|
"binaryFields": [],
|
|
1800
2815
|
"pathFields": [],
|
|
1801
2816
|
"queryFields": [],
|
|
1802
2817
|
"headerFields": [],
|
|
1803
2818
|
"cookieFields": [],
|
|
1804
|
-
"bodyFields": [
|
|
2819
|
+
"bodyFields": [
|
|
2820
|
+
"data"
|
|
2821
|
+
]
|
|
1805
2822
|
};
|
|
1806
|
-
var
|
|
1807
|
-
"operationId": "
|
|
1808
|
-
"method": "
|
|
1809
|
-
"endpoint": "/
|
|
2823
|
+
var OP_ZaloAdsUpdateDisplayAd = {
|
|
2824
|
+
"operationId": "ZaloAds_updateDisplayAd",
|
|
2825
|
+
"method": "POST",
|
|
2826
|
+
"endpoint": "/zaapi/UpdateAd",
|
|
1810
2827
|
"baseUrl": "https://ads.zalo.me",
|
|
1811
2828
|
"binaryFields": [],
|
|
1812
2829
|
"pathFields": [],
|
|
1813
|
-
"queryFields": [
|
|
1814
|
-
"limit",
|
|
1815
|
-
"offset",
|
|
1816
|
-
"joinDateAsc"
|
|
1817
|
-
],
|
|
2830
|
+
"queryFields": [],
|
|
1818
2831
|
"headerFields": [],
|
|
1819
2832
|
"cookieFields": [],
|
|
1820
|
-
"bodyFields": [
|
|
2833
|
+
"bodyFields": [
|
|
2834
|
+
"est",
|
|
2835
|
+
"stt",
|
|
2836
|
+
"data",
|
|
2837
|
+
"isBoostAd"
|
|
2838
|
+
]
|
|
1821
2839
|
};
|
|
1822
|
-
var
|
|
1823
|
-
"operationId": "
|
|
1824
|
-
"method": "
|
|
1825
|
-
"endpoint": "/
|
|
2840
|
+
var OP_ZaloAdsCreateVideoCampaign = {
|
|
2841
|
+
"operationId": "ZaloAds_createVideoCampaign",
|
|
2842
|
+
"method": "POST",
|
|
2843
|
+
"endpoint": "/zaapi/addNewCamp",
|
|
1826
2844
|
"baseUrl": "https://ads.zalo.me",
|
|
1827
2845
|
"binaryFields": [],
|
|
1828
2846
|
"pathFields": [],
|
|
1829
2847
|
"queryFields": [],
|
|
1830
2848
|
"headerFields": [],
|
|
1831
2849
|
"cookieFields": [],
|
|
1832
|
-
"bodyFields": [
|
|
2850
|
+
"bodyFields": [
|
|
2851
|
+
"data"
|
|
2852
|
+
]
|
|
1833
2853
|
};
|
|
1834
|
-
var
|
|
1835
|
-
"operationId": "
|
|
1836
|
-
"method": "
|
|
1837
|
-
"endpoint": "/api/
|
|
2854
|
+
var OP_ZaloAdsDeleteCampaign = {
|
|
2855
|
+
"operationId": "ZaloAds_deleteCampaign",
|
|
2856
|
+
"method": "POST",
|
|
2857
|
+
"endpoint": "/api/campaign/change-status",
|
|
1838
2858
|
"baseUrl": "https://ads.zalo.me",
|
|
1839
2859
|
"binaryFields": [],
|
|
1840
2860
|
"pathFields": [],
|
|
1841
2861
|
"queryFields": [],
|
|
1842
2862
|
"headerFields": [],
|
|
1843
2863
|
"cookieFields": [],
|
|
1844
|
-
"bodyFields": [
|
|
2864
|
+
"bodyFields": [
|
|
2865
|
+
"campaignId",
|
|
2866
|
+
"status"
|
|
2867
|
+
]
|
|
1845
2868
|
};
|
|
1846
|
-
var
|
|
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 {
|
|
1847
2906
|
constructor(client) {
|
|
1848
2907
|
this.client = client;
|
|
1849
2908
|
}
|
|
1850
|
-
|
|
1851
|
-
|
|
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);
|
|
1852
2913
|
}
|
|
1853
|
-
|
|
1854
|
-
return this.client.
|
|
2914
|
+
changeCampaignStatus(request, options) {
|
|
2915
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsChangeCampaignStatus, this.client.toTransportInput(OP_ZaloAdsChangeCampaignStatus, request), options);
|
|
1855
2916
|
}
|
|
1856
|
-
|
|
1857
|
-
|
|
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);
|
|
1858
2920
|
}
|
|
1859
|
-
|
|
1860
|
-
return this.client.
|
|
2921
|
+
createWebsiteCampaign(request, options) {
|
|
2922
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateWebsiteCampaign, this.client.toTransportInput(OP_ZaloAdsCreateWebsiteCampaign, request), options);
|
|
1861
2923
|
}
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
limit: 15,
|
|
1865
|
-
offset: 0,
|
|
1866
|
-
joinDateAsc: true,
|
|
1867
|
-
...request
|
|
1868
|
-
};
|
|
1869
|
-
return this.client.requestWithoutBody(OP_ZaloAdsListAgencyCustomersWithBudget, this.client.toTransportInput(OP_ZaloAdsListAgencyCustomersWithBudget, normalized), options);
|
|
2924
|
+
updateWebsiteAd(request, options) {
|
|
2925
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateWebsiteAd, this.client.toTransportInput(OP_ZaloAdsUpdateWebsiteAd, request), options);
|
|
1870
2926
|
}
|
|
1871
|
-
|
|
1872
|
-
return this.client.
|
|
2927
|
+
createDisplayCampaign(request, options) {
|
|
2928
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateDisplayCampaign, this.client.toTransportInput(OP_ZaloAdsCreateDisplayCampaign, request), options);
|
|
1873
2929
|
}
|
|
1874
|
-
|
|
1875
|
-
return this.client.
|
|
2930
|
+
updateDisplayAd(request, options) {
|
|
2931
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateDisplayAd, this.client.toTransportInput(OP_ZaloAdsUpdateDisplayAd, request), options);
|
|
1876
2932
|
}
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
return this.getApiWhoami(...args);
|
|
2933
|
+
createVideoCampaign(request, options) {
|
|
2934
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateVideoCampaign, this.client.toTransportInput(OP_ZaloAdsCreateVideoCampaign, request), options);
|
|
1880
2935
|
}
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
return this.getApiPaymentTransactionHistory(...args);
|
|
2936
|
+
createEcommerceCampaign(request, options) {
|
|
2937
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateEcommerceCampaign, this.client.toTransportInput(OP_ZaloAdsCreateEcommerceCampaign, request), options);
|
|
1884
2938
|
}
|
|
1885
|
-
/**
|
|
1886
|
-
|
|
1887
|
-
return this.
|
|
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);
|
|
1888
2942
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
return this.getApiBaAccountAllgrantedmembers(...args);
|
|
2943
|
+
createForm(request, options) {
|
|
2944
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateForm, this.client.toTransportInput(OP_ZaloAdsCreateForm, request), options);
|
|
1892
2945
|
}
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
return this.getApiNotifiesHeader(...args);
|
|
2946
|
+
createFormCampaign(request, options) {
|
|
2947
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateFormCampaign, this.client.toTransportInput(OP_ZaloAdsCreateFormCampaign, request), options);
|
|
1896
2948
|
}
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
return this.getApiLpNews(...args);
|
|
2949
|
+
createMessageCampaign(request, options) {
|
|
2950
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateMessageCampaign, this.client.toTransportInput(OP_ZaloAdsCreateMessageCampaign, request), options);
|
|
1900
2951
|
}
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
// src/validators/audiences.validator.ts
|
|
1904
|
-
function validateCreateSavedAudienceRequest(input) {
|
|
1905
|
-
const errors = [];
|
|
1906
|
-
if (!input || typeof input !== "object") {
|
|
1907
|
-
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
2952
|
+
createOfficialAccountCampaign(request, options) {
|
|
2953
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreateOfficialAccountCampaign, this.client.toTransportInput(OP_ZaloAdsCreateOfficialAccountCampaign, request), options);
|
|
1908
2954
|
}
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
1913
|
-
} else if (name.length < 2 || name.length > 255) {
|
|
1914
|
-
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
|
|
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);
|
|
1915
2958
|
}
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
2959
|
+
createPostCampaign(request, options) {
|
|
2960
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsCreatePostCampaign, this.client.toTransportInput(OP_ZaloAdsCreatePostCampaign, request), options);
|
|
2961
|
+
}
|
|
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);
|
|
2965
|
+
}
|
|
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);
|
|
2973
|
+
}
|
|
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);
|
|
2980
|
+
}
|
|
2981
|
+
getApiPlaceGetalldistricts(request = {}, options) {
|
|
2982
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiPlaceGetalldistricts, this.client.toTransportInput(OP_ZaloAdsGetApiPlaceGetalldistricts, request), options);
|
|
2983
|
+
}
|
|
2984
|
+
getApiSpellCheckV2(request, options) {
|
|
2985
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiSpellCheckV2, this.client.toTransportInput(OP_ZaloAdsGetApiSpellCheckV2, request), options);
|
|
2986
|
+
}
|
|
2987
|
+
getZaapiCheckcamphasmanyads(request = {}, options) {
|
|
2988
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiCheckcamphasmanyads, this.client.toTransportInput(OP_ZaloAdsGetZaapiCheckcamphasmanyads, request), options);
|
|
2989
|
+
}
|
|
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);
|
|
2997
|
+
}
|
|
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);
|
|
3001
|
+
}
|
|
3002
|
+
getZaapiGetallpages(request = {}, options) {
|
|
3003
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetallpages, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetallpages, request), options);
|
|
3004
|
+
}
|
|
3005
|
+
getAllPages(request = {}, options) {
|
|
3006
|
+
return this.getZaapiGetallpages(request, options);
|
|
3007
|
+
}
|
|
3008
|
+
getZaapiGetownedarticles(request, options) {
|
|
3009
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetownedarticles, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetownedarticles, request), options);
|
|
1929
3010
|
}
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
errors.push("Tr\u01B0\u1EDDng 'Gender' ph\u1EA3i l\xE0 0 (T\u1EA5t c\u1EA3), 1 (Nam), ho\u1EB7c 2 (N\u1EEF).");
|
|
3011
|
+
getOwnedArticles(request, options) {
|
|
3012
|
+
return this.getZaapiGetownedarticles(request, options);
|
|
1933
3013
|
}
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
for (const age of newAgeRanges) {
|
|
1937
|
-
if (!VALID_AGE_RANGES.includes(age)) {
|
|
1938
|
-
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(", ")}.`);
|
|
1939
|
-
}
|
|
3014
|
+
getZaapiGetownedpages(request = {}, options) {
|
|
3015
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetZaapiGetownedpages, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetownedpages, request), options);
|
|
1940
3016
|
}
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
for (const o of os) {
|
|
1944
|
-
if (!VALID_OS.includes(o)) {
|
|
1945
|
-
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).`);
|
|
1946
|
-
}
|
|
3017
|
+
getOwnedPages(request = {}, options) {
|
|
3018
|
+
return this.getZaapiGetownedpages(request, options);
|
|
1947
3019
|
}
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
location = {
|
|
1951
|
-
Addresses: [],
|
|
1952
|
-
Cities: [],
|
|
1953
|
-
WardTargeting: { Includes: [], Excludes: [] }
|
|
1954
|
-
};
|
|
1955
|
-
} else {
|
|
1956
|
-
location = {
|
|
1957
|
-
Addresses: Array.isArray(location.Addresses) ? location.Addresses : [],
|
|
1958
|
-
Cities: Array.isArray(location.Cities) ? location.Cities : [],
|
|
1959
|
-
WardTargeting: location.WardTargeting && typeof location.WardTargeting === "object" ? location.WardTargeting : { Includes: [], Excludes: [] }
|
|
1960
|
-
};
|
|
1961
|
-
if (location.WardTargeting.Includes && !Array.isArray(location.WardTargeting.Includes)) {
|
|
1962
|
-
errors.push("Tr\u01B0\u1EDDng 'Location.WardTargeting.Includes' ph\u1EA3i l\xE0 m\u1ED9t m\u1EA3ng khu v\u1EF1c.");
|
|
1963
|
-
} else if (Array.isArray(location.WardTargeting.Includes)) {
|
|
1964
|
-
for (const inc of location.WardTargeting.Includes) {
|
|
1965
|
-
if (![1, 2, 3].includes(Number(inc.Id))) {
|
|
1966
|
-
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).`);
|
|
1967
|
-
}
|
|
1968
|
-
if (inc.Provinces && !Array.isArray(inc.Provinces)) {
|
|
1969
|
-
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.`);
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
|
-
}
|
|
3020
|
+
listFormsByOfficialAccount(request, options) {
|
|
3021
|
+
return this.client.requestWithoutBody(OP_ZaloAdsListFormsByOfficialAccount, this.client.toTransportInput(OP_ZaloAdsListFormsByOfficialAccount, request), options);
|
|
1973
3022
|
}
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
CustomAudienceId: 0,
|
|
1977
|
-
Gender: gender,
|
|
1978
|
-
NewAgeRanges: newAgeRanges,
|
|
1979
|
-
Os: os,
|
|
1980
|
-
Location: location
|
|
1981
|
-
};
|
|
1982
|
-
return {
|
|
1983
|
-
isValid: errors.length === 0,
|
|
1984
|
-
errors,
|
|
1985
|
-
data: errors.length === 0 ? {
|
|
1986
|
-
name,
|
|
1987
|
-
caType: 1,
|
|
1988
|
-
targeting: JSON.stringify(finalTargeting)
|
|
1989
|
-
} : void 0
|
|
1990
|
-
};
|
|
1991
|
-
}
|
|
1992
|
-
function validateCreatePhoneAudienceRequest(input) {
|
|
1993
|
-
const errors = [];
|
|
1994
|
-
if (!input || typeof input !== "object") {
|
|
1995
|
-
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
3023
|
+
listMiniPagesByTemplate(request, options) {
|
|
3024
|
+
return this.client.requestWithoutBody(OP_ZaloAdsListMiniPagesByTemplate, this.client.toTransportInput(OP_ZaloAdsListMiniPagesByTemplate, request), options);
|
|
1996
3025
|
}
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
if (!name || name.length < 2 || name.length > 255) {
|
|
2000
|
-
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
|
|
3026
|
+
postZaapiDeletead(request = {}, options) {
|
|
3027
|
+
return this.client.requestWithoutBody(OP_ZaloAdsPostZaapiDeletead, this.client.toTransportInput(OP_ZaloAdsPostZaapiDeletead, request), options);
|
|
2001
3028
|
}
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
}
|
|
2007
|
-
|
|
2008
|
-
}
|
|
2009
|
-
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
2010
|
-
targetingObj = raw.targeting;
|
|
2011
|
-
} else {
|
|
2012
|
-
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
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);
|
|
2013
3035
|
}
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
errors.push("Tr\u01B0\u1EDDng 'Path' (URL file .txt sau khi upload) l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
3036
|
+
updateEcommerceAd(request, options) {
|
|
3037
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateEcommerceAd, this.client.toTransportInput(OP_ZaloAdsUpdateEcommerceAd, request), options);
|
|
2017
3038
|
}
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
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);
|
|
2021
3042
|
}
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
errors,
|
|
2025
|
-
data: errors.length === 0 ? {
|
|
2026
|
-
name,
|
|
2027
|
-
caType: 3,
|
|
2028
|
-
targeting: JSON.stringify({
|
|
2029
|
-
Name: String(targetingObj.Name || "phones.txt"),
|
|
2030
|
-
Path: path,
|
|
2031
|
-
Total: total,
|
|
2032
|
-
ZaloId: Number(targetingObj.ZaloId || 0),
|
|
2033
|
-
OriginAudience: 0
|
|
2034
|
-
})
|
|
2035
|
-
} : void 0
|
|
2036
|
-
};
|
|
2037
|
-
}
|
|
2038
|
-
function validateCreateLookalikeAudienceRequest(input) {
|
|
2039
|
-
const errors = [];
|
|
2040
|
-
if (!input || typeof input !== "object") {
|
|
2041
|
-
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
3043
|
+
updateFormAd(request, options) {
|
|
3044
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateFormAd, this.client.toTransportInput(OP_ZaloAdsUpdateFormAd, request), options);
|
|
2042
3045
|
}
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
if (!name || name.length < 2 || name.length > 255) {
|
|
2046
|
-
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
|
|
3046
|
+
updateMessageAd(request, options) {
|
|
3047
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateMessageAd, this.client.toTransportInput(OP_ZaloAdsUpdateMessageAd, request), options);
|
|
2047
3048
|
}
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
try {
|
|
2051
|
-
targetingObj = JSON.parse(raw.targeting);
|
|
2052
|
-
} catch {
|
|
2053
|
-
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
|
|
2054
|
-
}
|
|
2055
|
-
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
2056
|
-
targetingObj = raw.targeting;
|
|
2057
|
-
} else {
|
|
2058
|
-
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
3049
|
+
updateNewAds(request, options) {
|
|
3050
|
+
return this.client.requestMultipart(OP_ZaloAdsUpdateNewAds, this.client.toTransportInput(OP_ZaloAdsUpdateNewAds, request), options);
|
|
2059
3051
|
}
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
errors.push("Tr\u01B0\u1EDDng 'OriginAudience' (ID nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng S\u0110T g\u1ED1c) l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
3052
|
+
updateOfficialAccountAd(request, options) {
|
|
3053
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdateOfficialAccountAd, this.client.toTransportInput(OP_ZaloAdsUpdateOfficialAccountAd, request), options);
|
|
2063
3054
|
}
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
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);
|
|
2067
3058
|
}
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
errors,
|
|
2071
|
-
data: errors.length === 0 ? {
|
|
2072
|
-
name,
|
|
2073
|
-
caType: 6,
|
|
2074
|
-
targeting: JSON.stringify({
|
|
2075
|
-
OriginAudience: originAudience,
|
|
2076
|
-
Total: total,
|
|
2077
|
-
Name: String(targetingObj.Name || "Lookalike Audience"),
|
|
2078
|
-
Path: String(targetingObj.Path || "")
|
|
2079
|
-
})
|
|
2080
|
-
} : void 0
|
|
2081
|
-
};
|
|
2082
|
-
}
|
|
2083
|
-
function validateCreateFormEventAudienceRequest(input) {
|
|
2084
|
-
const errors = [];
|
|
2085
|
-
if (!input || typeof input !== "object") {
|
|
2086
|
-
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
3059
|
+
updatePostAd(request, options) {
|
|
3060
|
+
return this.client.requestFormUrlEncoded(OP_ZaloAdsUpdatePostAd, this.client.toTransportInput(OP_ZaloAdsUpdatePostAd, request), options);
|
|
2087
3061
|
}
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
|
|
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);
|
|
2092
3065
|
}
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
targetingObj = JSON.parse(raw.targeting);
|
|
2097
|
-
} catch {
|
|
2098
|
-
errors.push("Tr\u01B0\u1EDDng 'targeting' l\xE0 chu\u1ED7i JSON kh\xF4ng h\u1EE3p l\u1EC7.");
|
|
2099
|
-
}
|
|
2100
|
-
} else if (raw.targeting && typeof raw.targeting === "object") {
|
|
2101
|
-
targetingObj = raw.targeting;
|
|
3066
|
+
/** Xóa quảng cáo */
|
|
3067
|
+
deleteAd(...args) {
|
|
3068
|
+
return this.postZaapiDeletead(...args);
|
|
2102
3069
|
}
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
3070
|
+
/** Danh sách quận/huyện để nhắm mục tiêu */
|
|
3071
|
+
getAllDistricts(...args) {
|
|
3072
|
+
return this.getApiPlaceGetalldistricts(...args);
|
|
2106
3073
|
}
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
3074
|
+
/** Kiểm tra chính tả văn bản quảng cáo */
|
|
3075
|
+
getSpellCheckV2(...args) {
|
|
3076
|
+
return this.getApiSpellCheckV2(...args);
|
|
2110
3077
|
}
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
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
|
+
);
|
|
2114
3087
|
}
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
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
|
+
);
|
|
2118
3097
|
}
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
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})`);
|
|
3109
|
+
}
|
|
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}`);
|
|
2138
3119
|
}
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
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
|
+
);
|
|
2143
3133
|
}
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
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;
|
|
2153
3234
|
}
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
if (!oaId) {
|
|
2157
|
-
errors.push("Tr\u01B0\u1EDDng 'OaId' (chu\u1ED7i pageId ho\u1EB7c noisedId c\u1EE7a OA) l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
3235
|
+
getApiWhoami(request = {}, options) {
|
|
3236
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiWhoami, this.client.toTransportInput(OP_ZaloAdsGetApiWhoami, request), options);
|
|
2158
3237
|
}
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
errors.push("Tr\u01B0\u1EDDng 'NumDays' ph\u1EA3i n\u1EB1m trong kho\u1EA3ng t\u1EEB 1 \u0111\u1EBFn 90 ng\xE0y.");
|
|
3238
|
+
getApiPaymentTransactionHistory(request, options) {
|
|
3239
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiPaymentTransactionHistory, this.client.toTransportInput(OP_ZaloAdsGetApiPaymentTransactionHistory, request), options);
|
|
2162
3240
|
}
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
errors,
|
|
2166
|
-
data: errors.length === 0 ? {
|
|
2167
|
-
name,
|
|
2168
|
-
caType: 11,
|
|
2169
|
-
targeting: JSON.stringify({
|
|
2170
|
-
EventId: eventId,
|
|
2171
|
-
OaId: oaId,
|
|
2172
|
-
NumDays: numDays
|
|
2173
|
-
})
|
|
2174
|
-
} : void 0
|
|
2175
|
-
};
|
|
2176
|
-
}
|
|
2177
|
-
function validateCreateMessagePersonalEventAudienceRequest(input) {
|
|
2178
|
-
const errors = [];
|
|
2179
|
-
if (!input || typeof input !== "object") {
|
|
2180
|
-
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
3241
|
+
getApiBaAccountAllaccessors(request = {}, options) {
|
|
3242
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiBaAccountAllaccessors, this.client.toTransportInput(OP_ZaloAdsGetApiBaAccountAllaccessors, request), options);
|
|
2181
3243
|
}
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
if (!name || name.length < 2 || name.length > 255) {
|
|
2185
|
-
errors.push("T\xEAn nh\xF3m \u0111\u1ED1i t\u01B0\u1EE3ng 'name' ph\u1EA3i t\u1EEB 2 \u0111\u1EBFn 255 k\xFD t\u1EF1.");
|
|
3244
|
+
getApiBaAccountAllgrantedmembers(request = {}, options) {
|
|
3245
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiBaAccountAllgrantedmembers, this.client.toTransportInput(OP_ZaloAdsGetApiBaAccountAllgrantedmembers, request), options);
|
|
2186
3246
|
}
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
}
|
|
2194
|
-
|
|
2195
|
-
targetingObj = raw.targeting;
|
|
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);
|
|
2196
3255
|
}
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
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).");
|
|
3256
|
+
getApiNotifiesHeader(request = {}, options) {
|
|
3257
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiNotifiesHeader, this.client.toTransportInput(OP_ZaloAdsGetApiNotifiesHeader, request), options);
|
|
2200
3258
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
errors.push("Tr\u01B0\u1EDDng 'NumDays' ph\u1EA3i n\u1EB1m trong kho\u1EA3ng t\u1EEB 1 \u0111\u1EBFn 90 ng\xE0y.");
|
|
3259
|
+
getApiLpNews(request = {}, options) {
|
|
3260
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetApiLpNews, this.client.toTransportInput(OP_ZaloAdsGetApiLpNews, request), options);
|
|
2204
3261
|
}
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
3262
|
+
/** Lấy thông tin tài khoản đang đăng nhập */
|
|
3263
|
+
getWhoami(...args) {
|
|
3264
|
+
return this.getApiWhoami(...args);
|
|
2208
3265
|
}
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
data: errors.length === 0 ? {
|
|
2213
|
-
name,
|
|
2214
|
-
caType: 14,
|
|
2215
|
-
targeting: JSON.stringify({
|
|
2216
|
-
EventId: eventId,
|
|
2217
|
-
NumDays: numDays,
|
|
2218
|
-
PageIds: pageIds
|
|
2219
|
-
})
|
|
2220
|
-
} : void 0
|
|
2221
|
-
};
|
|
2222
|
-
}
|
|
2223
|
-
function validateEstimateAudienceRequest(input) {
|
|
2224
|
-
const errors = [];
|
|
2225
|
-
if (!input || typeof input !== "object") {
|
|
2226
|
-
return { isValid: false, errors: ["Input ph\u1EA3i l\xE0 m\u1ED9t object."], data: void 0 };
|
|
3266
|
+
/** Lịch sử giao dịch thanh toán */
|
|
3267
|
+
getPaymentTransactionHistory(...args) {
|
|
3268
|
+
return this.getApiPaymentTransactionHistory(...args);
|
|
2227
3269
|
}
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
3270
|
+
/** Danh sách accessor tài khoản BA */
|
|
3271
|
+
getBaAccountAllAccessors(...args) {
|
|
3272
|
+
return this.getApiBaAccountAllaccessors(...args);
|
|
3273
|
+
}
|
|
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);
|
|
2232
3285
|
}
|
|
2233
|
-
const ageRanges = Array.isArray(raw.ageRanges) && raw.ageRanges.length > 0 ? raw.ageRanges.map(Number) : [10283, 10284, 10285, 10286, 10287];
|
|
2234
|
-
const platforms = Array.isArray(raw.platforms) && raw.platforms.length > 0 ? raw.platforms.map(Number) : [0, 1, 3];
|
|
2235
|
-
const priceType = typeof raw.priceType === "number" ? raw.priceType : 2;
|
|
2236
|
-
const wardsTargeting = typeof raw.wardsTargeting === "string" && raw.wardsTargeting.trim() ? raw.wardsTargeting.trim() : JSON.stringify({ Includes: [], Excludes: [] });
|
|
2237
|
-
return {
|
|
2238
|
-
isValid: errors.length === 0,
|
|
2239
|
-
errors,
|
|
2240
|
-
data: errors.length === 0 ? {
|
|
2241
|
-
gender,
|
|
2242
|
-
ageRanges,
|
|
2243
|
-
platforms,
|
|
2244
|
-
locations: typeof raw.locations === "string" ? raw.locations : "",
|
|
2245
|
-
provinces: Array.isArray(raw.provinces) ? raw.provinces.map(Number) : [],
|
|
2246
|
-
wardsTargeting,
|
|
2247
|
-
priceType,
|
|
2248
|
-
number: typeof raw.number === "string" ? raw.number : String(raw.number || "0")
|
|
2249
|
-
} : void 0
|
|
2250
|
-
};
|
|
2251
|
-
}
|
|
2252
|
-
var ZaloAudiencesValidator = {
|
|
2253
|
-
createSavedAudience: validateCreateSavedAudienceRequest,
|
|
2254
|
-
createPhoneAudience: validateCreatePhoneAudienceRequest,
|
|
2255
|
-
createLookalikeAudience: validateCreateLookalikeAudienceRequest,
|
|
2256
|
-
createFormEventAudience: validateCreateFormEventAudienceRequest,
|
|
2257
|
-
createMessageOaEventAudience: validateCreateMessageOaEventAudienceRequest,
|
|
2258
|
-
createMessagePersonalEventAudience: validateCreateMessagePersonalEventAudienceRequest,
|
|
2259
|
-
estimateAudience: validateEstimateAudienceRequest
|
|
2260
3286
|
};
|
|
2261
3287
|
|
|
2262
3288
|
// src/services/audiences.service.ts
|
|
@@ -2647,6 +3673,25 @@ var OP_ZaloAdsUpsertCustomReport = {
|
|
|
2647
3673
|
"isDefault"
|
|
2648
3674
|
]
|
|
2649
3675
|
};
|
|
3676
|
+
var OP_ZaloAdsDownloadReport = {
|
|
3677
|
+
operationId: "zalo_ads_download_report",
|
|
3678
|
+
method: "POST",
|
|
3679
|
+
endpoint: "/api/collect",
|
|
3680
|
+
baseUrl: "https://ads.zalo.me",
|
|
3681
|
+
binaryFields: [],
|
|
3682
|
+
pathFields: [],
|
|
3683
|
+
queryFields: [],
|
|
3684
|
+
headerFields: [],
|
|
3685
|
+
cookieFields: [],
|
|
3686
|
+
bodyFields: [
|
|
3687
|
+
"t",
|
|
3688
|
+
"adIds",
|
|
3689
|
+
"status",
|
|
3690
|
+
"dateFilter",
|
|
3691
|
+
"reportKind",
|
|
3692
|
+
"et"
|
|
3693
|
+
]
|
|
3694
|
+
};
|
|
2650
3695
|
var ZaloReportsService = class {
|
|
2651
3696
|
constructor(client) {
|
|
2652
3697
|
this.client = client;
|
|
@@ -2709,6 +3754,18 @@ var ZaloReportsService = class {
|
|
|
2709
3754
|
getCampaignReportLegacy(...args) {
|
|
2710
3755
|
return this.getZaapiCampaignReportcampaign(...args);
|
|
2711
3756
|
}
|
|
3757
|
+
/** Xuất và tải trực tiếp tệp tin Excel (.xlsx / Blob) báo cáo hiệu quả quảng cáo (POST /api/collect) */
|
|
3758
|
+
downloadReport(request, options) {
|
|
3759
|
+
const payload = {
|
|
3760
|
+
t: request.t ?? "cd.download.report",
|
|
3761
|
+
status: request.status ?? 2,
|
|
3762
|
+
dateFilter: request.dateFilter ?? 0,
|
|
3763
|
+
reportKind: request.reportKind ?? 100001,
|
|
3764
|
+
et: request.et ?? Math.floor(Date.now() / 1e3),
|
|
3765
|
+
adIds: request.adIds
|
|
3766
|
+
};
|
|
3767
|
+
return this.client.requestJson(OP_ZaloAdsDownloadReport, this.client.toTransportInput(OP_ZaloAdsDownloadReport, payload), options);
|
|
3768
|
+
}
|
|
2712
3769
|
};
|
|
2713
3770
|
|
|
2714
3771
|
// src/services/conversions.service.ts
|
|
@@ -2869,6 +3926,20 @@ var OP_ZaloAdsListAutomatedRules = {
|
|
|
2869
3926
|
"cookieFields": [],
|
|
2870
3927
|
"bodyFields": []
|
|
2871
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
|
+
};
|
|
2872
3943
|
var OP_ZaloAdsCreateAutomatedRule = {
|
|
2873
3944
|
"operationId": "ZaloAds_createAutomatedRule",
|
|
2874
3945
|
"method": "POST",
|
|
@@ -2895,7 +3966,7 @@ var OP_ZaloAdsCreateAutomatedRule = {
|
|
|
2895
3966
|
var OP_ZaloAdsUpdateAutomatedRule = {
|
|
2896
3967
|
"operationId": "ZaloAds_updateAutomatedRule",
|
|
2897
3968
|
"method": "POST",
|
|
2898
|
-
"endpoint": "/api/automatedrules/update",
|
|
3969
|
+
"endpoint": "/api/ad/automatedrules/update",
|
|
2899
3970
|
"baseUrl": "https://ads.zalo.me",
|
|
2900
3971
|
"binaryFields": [],
|
|
2901
3972
|
"pathFields": [],
|
|
@@ -2904,11 +3975,15 @@ var OP_ZaloAdsUpdateAutomatedRule = {
|
|
|
2904
3975
|
"cookieFields": [],
|
|
2905
3976
|
"bodyFields": [
|
|
2906
3977
|
"automatedRuleId",
|
|
2907
|
-
"
|
|
2908
|
-
"appliedTo",
|
|
3978
|
+
"scope",
|
|
2909
3979
|
"ruleName",
|
|
2910
3980
|
"action",
|
|
2911
3981
|
"conditions",
|
|
3982
|
+
"frequency",
|
|
3983
|
+
"appliedItems",
|
|
3984
|
+
"appliedIds",
|
|
3985
|
+
"rowVersion",
|
|
3986
|
+
"appliedTo",
|
|
2912
3987
|
"schedule",
|
|
2913
3988
|
"campaignIds",
|
|
2914
3989
|
"adIds"
|
|
@@ -2966,6 +4041,9 @@ var ZaloAutomatedRulesService = class {
|
|
|
2966
4041
|
const queryInput = { query_param: { ruleName: request.ruleName ?? "" } };
|
|
2967
4042
|
return this.client.requestWithoutBody(OP_ZaloAdsListAutomatedRules, queryInput, options);
|
|
2968
4043
|
}
|
|
4044
|
+
getAutomatedRuleDetail(request, options) {
|
|
4045
|
+
return this.client.requestWithoutBody(OP_ZaloAdsGetAutomatedRuleDetail, this.client.toTransportInput(OP_ZaloAdsGetAutomatedRuleDetail, request), options);
|
|
4046
|
+
}
|
|
2969
4047
|
createAutomatedRule(request, options) {
|
|
2970
4048
|
return this.client.requestJson(OP_ZaloAdsCreateAutomatedRule, this.client.toTransportInput(OP_ZaloAdsCreateAutomatedRule, request), options);
|
|
2971
4049
|
}
|
|
@@ -4077,6 +5155,9 @@ var ZaloAdsService = class extends ZaloCampaignsService {
|
|
|
4077
5155
|
listAutomatedRules(request = {}, options) {
|
|
4078
5156
|
return this.automatedRules.listAutomatedRules(request, options);
|
|
4079
5157
|
}
|
|
5158
|
+
getAutomatedRuleDetail(request, options) {
|
|
5159
|
+
return this.automatedRules.getAutomatedRuleDetail(request, options);
|
|
5160
|
+
}
|
|
4080
5161
|
createAutomatedRule(request, options) {
|
|
4081
5162
|
return this.automatedRules.createAutomatedRule(request, options);
|
|
4082
5163
|
}
|
|
@@ -4759,6 +5840,34 @@ function isPositiveInteger2(val) {
|
|
|
4759
5840
|
function toPositiveInteger2(val) {
|
|
4760
5841
|
return typeof val === "number" ? Math.floor(val) : parseInt(String(val), 10);
|
|
4761
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
|
+
}
|
|
4762
5871
|
function validateCloneInstantPageRequest(input) {
|
|
4763
5872
|
const errors = [];
|
|
4764
5873
|
if (!input || typeof input !== "object") {
|
|
@@ -4967,7 +6076,7 @@ function validateUpdateInstantPageRequest(input) {
|
|
|
4967
6076
|
if (obj.status !== void 0 && obj.status !== null) {
|
|
4968
6077
|
const st = Number(obj.status);
|
|
4969
6078
|
if (![0, 1, 2, 3].includes(st)) {
|
|
4970
|
-
errors.push("Tr\u01B0\u1EDDng 'status' ph\u1EA3i l\xE0 m\u1ED9t trong c\xE1c m\xE3: 0 (B\u1EA3n sao m\u1EDBi), 1 (
|
|
6079
|
+
errors.push("Tr\u01B0\u1EDDng 'status' ph\u1EA3i l\xE0 m\u1ED9t trong c\xE1c m\xE3: 0 (B\u1EA3n sao m\u1EDBi t\u1EA1o ch\u01B0a l\u01B0u), 1 (\u0110ang ho\u1EA1t \u0111\u1ED9ng / \u0110\xE3 xu\u1EA5t b\u1EA3n), 3 (\u0110\xE3 k\u1EBFt th\xFAc / L\u01B0u tr\u1EEF).");
|
|
4971
6080
|
} else {
|
|
4972
6081
|
data.status = st;
|
|
4973
6082
|
}
|
|
@@ -5121,6 +6230,7 @@ function validateUpsertInstantPageFormRequest(input) {
|
|
|
5121
6230
|
};
|
|
5122
6231
|
}
|
|
5123
6232
|
var ZaloInstantPagesValidator = {
|
|
6233
|
+
validateCreateInstantPage: validateCreateInstantPageRequest,
|
|
5124
6234
|
validateCloneInstantPage: validateCloneInstantPageRequest,
|
|
5125
6235
|
validateGetInstantPageDetail: validateGetInstantPageDetailRequest,
|
|
5126
6236
|
validateGetInstantPageSharedUser: validateGetInstantPageSharedUserRequest,
|
|
@@ -5137,6 +6247,21 @@ var ZaloInstantPagesValidator = {
|
|
|
5137
6247
|
};
|
|
5138
6248
|
|
|
5139
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
|
+
};
|
|
5140
6265
|
var OP_ZaloInstantPagesCloneInstantPage = {
|
|
5141
6266
|
"operationId": "ZaloInstantPages_cloneInstantPage",
|
|
5142
6267
|
"method": "POST",
|
|
@@ -5226,6 +6351,20 @@ var OP_ZaloInstantPagesListInstantPageShares = {
|
|
|
5226
6351
|
"cookieFields": [],
|
|
5227
6352
|
"bodyFields": []
|
|
5228
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
|
+
};
|
|
5229
6368
|
var OP_ZaloInstantPagesListInstantPageUsers = {
|
|
5230
6369
|
"operationId": "ZaloInstantPages_listInstantPageUsers",
|
|
5231
6370
|
"method": "GET",
|
|
@@ -5343,6 +6482,9 @@ var ZaloInstantPagesService = class {
|
|
|
5343
6482
|
* Dùng ở backend (NestJS/Express/Fastify), middleware hoặc AI Agent để verify payload trước khi gọi SDK.
|
|
5344
6483
|
*/
|
|
5345
6484
|
static validator = ZaloInstantPagesValidator;
|
|
6485
|
+
createInstantPage(request, options) {
|
|
6486
|
+
return this.client.requestJson(OP_ZaloInstantPagesCreateInstantPage, this.client.toTransportInput(OP_ZaloInstantPagesCreateInstantPage, request), options);
|
|
6487
|
+
}
|
|
5346
6488
|
cloneInstantPage(request, options) {
|
|
5347
6489
|
return this.client.requestJson(OP_ZaloInstantPagesCloneInstantPage, this.client.toTransportInput(OP_ZaloInstantPagesCloneInstantPage, request), options);
|
|
5348
6490
|
}
|
|
@@ -5361,6 +6503,13 @@ var ZaloInstantPagesService = class {
|
|
|
5361
6503
|
listInstantPageShares(request, options) {
|
|
5362
6504
|
return this.client.requestWithoutBody(OP_ZaloInstantPagesListInstantPageShares, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageShares, request), options);
|
|
5363
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
|
+
}
|
|
5364
6513
|
listInstantPageUsers(request = {}, options) {
|
|
5365
6514
|
return this.client.requestWithoutBody(OP_ZaloInstantPagesListInstantPageUsers, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageUsers, request), options);
|
|
5366
6515
|
}
|
|
@@ -5875,112 +7024,6 @@ var ZaloAdsIntegrationManager = class {
|
|
|
5875
7024
|
}
|
|
5876
7025
|
};
|
|
5877
7026
|
|
|
5878
|
-
// src/dtos/ads.dto.ts
|
|
5879
|
-
var ZaloAdsFlowChildMessageDto = class {
|
|
5880
|
-
/** Mẫu Zalo đã xác minh dùng 8 cho tin nhắn văn bản trong nhánh. */
|
|
5881
|
-
type;
|
|
5882
|
-
/** Nội dung phản hồi trong nhánh. */
|
|
5883
|
-
text;
|
|
5884
|
-
};
|
|
5885
|
-
var ZaloAdsFlowButtonDto = class {
|
|
5886
|
-
/** 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. */
|
|
5887
|
-
type;
|
|
5888
|
-
/** Nhãn nút hiển thị cho người dùng. */
|
|
5889
|
-
text;
|
|
5890
|
-
/** URL website; bắt buộc với type 10. */
|
|
5891
|
-
url;
|
|
5892
|
-
/** Cờ của nút website; dùng true với type 10. */
|
|
5893
|
-
editable;
|
|
5894
|
-
/** Số hotline, bắt buộc khi type là 12. */
|
|
5895
|
-
phone;
|
|
5896
|
-
/** 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. */
|
|
5897
|
-
messages;
|
|
5898
|
-
};
|
|
5899
|
-
var ZaloAdsFlowMessageDto = class {
|
|
5900
|
-
/** 1 = Tin nhắn văn bản; 2 = Tin nhắn kèm hình ảnh. */
|
|
5901
|
-
type;
|
|
5902
|
-
/** 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}}. */
|
|
5903
|
-
text;
|
|
5904
|
-
/** 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. */
|
|
5905
|
-
url;
|
|
5906
|
-
/** Các nút đi kèm tin nhắn. */
|
|
5907
|
-
buttons;
|
|
5908
|
-
};
|
|
5909
|
-
var ZaloAdsCreateFlowRequest = class {
|
|
5910
|
-
/** ID Official Account sở hữu kịch bản. */
|
|
5911
|
-
oaId;
|
|
5912
|
-
/** Luôn null khi tạo kịch bản mới. */
|
|
5913
|
-
id;
|
|
5914
|
-
/** Tên kịch bản, tối đa 33 ký tự theo giao diện Zalo Ads. */
|
|
5915
|
-
name;
|
|
5916
|
-
/** Các tin nhắn được gửi theo thứ tự trong kịch bản. */
|
|
5917
|
-
messages;
|
|
5918
|
-
};
|
|
5919
|
-
var ZaloAdsCreateFlowResponse = class {
|
|
5920
|
-
/** 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). */
|
|
5921
|
-
code;
|
|
5922
|
-
/** Thông báo lỗi từ Zalo Ads khi code khác 0. */
|
|
5923
|
-
msg;
|
|
5924
|
-
/** 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. */
|
|
5925
|
-
data;
|
|
5926
|
-
};
|
|
5927
|
-
var ZaloAdsUpdateVideoAdRequest = class {
|
|
5928
|
-
data;
|
|
5929
|
-
est;
|
|
5930
|
-
isBoostAd;
|
|
5931
|
-
stt;
|
|
5932
|
-
};
|
|
5933
|
-
var ZaloAdsUpdateVideoAdResponse = class {
|
|
5934
|
-
code;
|
|
5935
|
-
msg;
|
|
5936
|
-
data;
|
|
5937
|
-
};
|
|
5938
|
-
var ZaloAdsCreatePostCampaignRequest = class {
|
|
5939
|
-
/** Cấu hình chiến dịch Bài viết (object hoặc chuỗi JSON). */
|
|
5940
|
-
data;
|
|
5941
|
-
};
|
|
5942
|
-
var ZaloAdsCreatePostCampaignResponse = class {
|
|
5943
|
-
code;
|
|
5944
|
-
/** Chuỗi ID quảng cáo mới trong response Zalo Ads. */
|
|
5945
|
-
msg;
|
|
5946
|
-
data;
|
|
5947
|
-
};
|
|
5948
|
-
var ZaloAdsMessageAdUpdateDataDto = class {
|
|
5949
|
-
AdId;
|
|
5950
|
-
CampaignId;
|
|
5951
|
-
MemberId;
|
|
5952
|
-
/** Phiên bản lạc quan lấy từ bản quảng cáo hiện tại. */
|
|
5953
|
-
RowVersion;
|
|
5954
|
-
AdName;
|
|
5955
|
-
/** 20 (hoặc 19) là quảng cáo Tin nhắn. */
|
|
5956
|
-
Type;
|
|
5957
|
-
Settings;
|
|
5958
|
-
Status;
|
|
5959
|
-
StartDate;
|
|
5960
|
-
EndDate;
|
|
5961
|
-
/** ID kịch bản, lấy từ createFlow hoặc listFlowsByOfficialAccount. */
|
|
5962
|
-
ZaloFlowId;
|
|
5963
|
-
ZaloPageId;
|
|
5964
|
-
ZaloFormId;
|
|
5965
|
-
ConversionId;
|
|
5966
|
-
Report;
|
|
5967
|
-
};
|
|
5968
|
-
var ZaloAdsUpdateMessageAdRequest = class {
|
|
5969
|
-
/** Payload quảng cáo đầy đủ (object hoặc chuỗi JSON); service tự tuần tự hóa thành field form data. */
|
|
5970
|
-
data;
|
|
5971
|
-
/** Tham số UI phụ trợ; capture Zalo Ads có giá trị literal "undefined". */
|
|
5972
|
-
est;
|
|
5973
|
-
/** 0 là quảng cáo thông thường, 1 là boost ad. */
|
|
5974
|
-
isBoostAd;
|
|
5975
|
-
/** Trạng thái thao tác của giao diện; mẫu đã ghi nhận 0. */
|
|
5976
|
-
stt;
|
|
5977
|
-
};
|
|
5978
|
-
var ZaloAdsUpdateMessageAdResponse = class {
|
|
5979
|
-
msg;
|
|
5980
|
-
code;
|
|
5981
|
-
data;
|
|
5982
|
-
};
|
|
5983
|
-
|
|
5984
7027
|
// src/dtos/instant-pages.dto.ts
|
|
5985
7028
|
var ZaloInstantPageBlockType = /* @__PURE__ */ ((ZaloInstantPageBlockType2) => {
|
|
5986
7029
|
ZaloInstantPageBlockType2[ZaloInstantPageBlockType2["CAROUSEL_SLIDER"] = 1] = "CAROUSEL_SLIDER";
|
|
@@ -6003,40 +7046,353 @@ var ZaloInstantPageBlockType = /* @__PURE__ */ ((ZaloInstantPageBlockType2) => {
|
|
|
6003
7046
|
ZaloInstantPageBlockType2[ZaloInstantPageBlockType2["CONSENT_NOTICE"] = 27] = "CONSENT_NOTICE";
|
|
6004
7047
|
return ZaloInstantPageBlockType2;
|
|
6005
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
|
+
};
|
|
6006
7329
|
export {
|
|
7330
|
+
ALLOWED_CTAS_PER_AD_TYPE,
|
|
6007
7331
|
ALL_ZALO_ADS_DOMAINS,
|
|
7332
|
+
AutomatedRuleActionTypeEnum,
|
|
7333
|
+
AutomatedRuleConditionFieldEnum,
|
|
7334
|
+
AutomatedRuleFrequencyEnum,
|
|
7335
|
+
AutomatedRuleOperatorEnum,
|
|
7336
|
+
AutomatedRuleScopeEnum,
|
|
7337
|
+
AutomatedRuleTimeRangeEnum,
|
|
7338
|
+
ConversionLabelEnum,
|
|
7339
|
+
ConversionUrlTypeEnum,
|
|
6008
7340
|
MemoryZaloSessionStore,
|
|
6009
7341
|
RedisZaloSessionStore,
|
|
6010
7342
|
TieredZaloSessionStore,
|
|
7343
|
+
VALID_AD_TYPES,
|
|
7344
|
+
VALID_CAMPAIGN_TYPES,
|
|
7345
|
+
ZALO_NEW_REGION_PROVINCE_CODES,
|
|
7346
|
+
ZALO_PROVINCE_MERGE_MAPPING,
|
|
7347
|
+
ZALO_REGION_PROVINCE_CODES,
|
|
6011
7348
|
ZaloAccountService,
|
|
6012
7349
|
ZaloAdsIntegrationManager as ZaloAdsAccountPool,
|
|
7350
|
+
ZaloAdsActionType,
|
|
7351
|
+
ZaloAdsAgeRangeId,
|
|
7352
|
+
ZaloAdsBudgetScheduleType,
|
|
7353
|
+
ZaloAdsCampaignStatus,
|
|
6013
7354
|
ZaloAdsCreateFlowRequest,
|
|
6014
7355
|
ZaloAdsCreateFlowResponse,
|
|
6015
7356
|
ZaloAdsCreatePostCampaignRequest,
|
|
6016
7357
|
ZaloAdsCreatePostCampaignResponse,
|
|
7358
|
+
ZaloAdsDeliveryType,
|
|
6017
7359
|
ZaloAdsFlowButtonDto,
|
|
6018
7360
|
ZaloAdsFlowChildMessageDto,
|
|
6019
7361
|
ZaloAdsFlowMessageDto,
|
|
7362
|
+
ZaloAdsImageRatio,
|
|
6020
7363
|
ZaloAdsIntegrationManager,
|
|
6021
7364
|
ZaloAdsMessageAdUpdateDataDto,
|
|
7365
|
+
ZaloAdsOsId,
|
|
7366
|
+
ZaloAdsPriceLimitType,
|
|
7367
|
+
ZaloAdsPriceType,
|
|
7368
|
+
ZaloAdsProvinceCode,
|
|
7369
|
+
ZaloAdsRegionId,
|
|
6022
7370
|
ZaloAdsSdk,
|
|
6023
7371
|
ZaloAdsService,
|
|
7372
|
+
ZaloAdsSpendingMethod,
|
|
6024
7373
|
ZaloAdsUpdateMessageAdRequest,
|
|
6025
7374
|
ZaloAdsUpdateMessageAdResponse,
|
|
6026
7375
|
ZaloAdsUpdateVideoAdRequest,
|
|
6027
7376
|
ZaloAdsUpdateVideoAdResponse,
|
|
7377
|
+
ZaloAdsUseConversion,
|
|
7378
|
+
ZaloAdsVideoSrc,
|
|
7379
|
+
ZaloAdsXTemplates,
|
|
6028
7380
|
ZaloAudiencesService,
|
|
6029
7381
|
ZaloAudiencesValidator,
|
|
6030
7382
|
ZaloAuthManager,
|
|
6031
7383
|
ZaloAutomatedRulesService,
|
|
7384
|
+
ZaloAutomatedRulesValidator,
|
|
6032
7385
|
ZaloCampaignsService,
|
|
7386
|
+
ZaloCampaignsValidator,
|
|
6033
7387
|
ZaloChatWidgetService,
|
|
6034
7388
|
ZaloConversionsService,
|
|
7389
|
+
ZaloConversionsValidator,
|
|
6035
7390
|
ZaloFlowsService,
|
|
6036
7391
|
ZaloFlowsValidator,
|
|
6037
7392
|
ZaloFormsService,
|
|
6038
7393
|
ZaloFormsValidator,
|
|
6039
7394
|
ZaloInstantPageBlockType,
|
|
7395
|
+
ZaloInstantPageSharePermission,
|
|
6040
7396
|
ZaloInstantPagesService,
|
|
6041
7397
|
ZaloInstantPagesValidator,
|
|
6042
7398
|
ZaloMediaService,
|
|
@@ -6052,15 +7408,19 @@ export {
|
|
|
6052
7408
|
defaultSharedMemorySessionStore,
|
|
6053
7409
|
deriveAccountKeyFromZpsid,
|
|
6054
7410
|
parseZaloCookieInput,
|
|
7411
|
+
validateChangeCampaignStatusParams,
|
|
6055
7412
|
validateCloneInstantPageRequest,
|
|
7413
|
+
validateCreateCampaignPayload,
|
|
6056
7414
|
validateCreateFlowRequest,
|
|
6057
7415
|
validateCreateFormEventAudienceRequest,
|
|
6058
7416
|
validateCreateFormRequest,
|
|
7417
|
+
validateCreateInstantPageRequest,
|
|
6059
7418
|
validateCreateLookalikeAudienceRequest,
|
|
6060
7419
|
validateCreateMessageOaEventAudienceRequest,
|
|
6061
7420
|
validateCreateMessagePersonalEventAudienceRequest,
|
|
6062
7421
|
validateCreatePhoneAudienceRequest,
|
|
6063
7422
|
validateCreateSavedAudienceRequest,
|
|
7423
|
+
validateDuplicateAdParams,
|
|
6064
7424
|
validateEstimateAudienceRequest,
|
|
6065
7425
|
validateGetInstantPageDetailRequest,
|
|
6066
7426
|
validateGetInstantPageSharedUserRequest,
|
|
@@ -6074,7 +7434,9 @@ export {
|
|
|
6074
7434
|
validateListInstantPageUsersRequest,
|
|
6075
7435
|
validateListMiniPageTemplatesRequest,
|
|
6076
7436
|
validateListOfficialAccountsRequest,
|
|
7437
|
+
validateRenameCampaignParams,
|
|
6077
7438
|
validateSearchInstantPagesRequest,
|
|
7439
|
+
validateUpdateAdPayload,
|
|
6078
7440
|
validateUpdateFlowRequest,
|
|
6079
7441
|
validateUpdateInstantPageRequest,
|
|
6080
7442
|
validateUpsertInstantPageFormRequest
|