|
|
@@ -49,6 +49,32 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
//商品上传结果通知群
|
|
|
public static final String HOOK_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/92e2445e-76df-44fb-8f61-f55ac94f49bd";
|
|
|
|
|
|
+ // 内部错误记录类:包含报错信息、剧目ID、商品库ID
|
|
|
+ private static class ErrorRecord {
|
|
|
+ String message;
|
|
|
+ String albumId; // 剧目ID
|
|
|
+ String platformId; // 商品库ID
|
|
|
+
|
|
|
+ public ErrorRecord(String message, String albumId, String platformId) {
|
|
|
+ this.message = message;
|
|
|
+ this.albumId = albumId;
|
|
|
+ this.platformId = platformId;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getMessage() { return message; }
|
|
|
+ public String getAlbumId() { return albumId; }
|
|
|
+ public String getPlatformId() { return platformId; }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String toString() {
|
|
|
+ return "ErrorRecord{" +
|
|
|
+ "message='" + message + '\'' +
|
|
|
+ ", albumId='" + albumId + '\'' +
|
|
|
+ ", platformId='" + platformId + '\'' +
|
|
|
+ '}';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public String runPlatform(String platformId) throws IOException {
|
|
|
List<AigcProductPlatform> platform = bytedanceProductUpdateMapper.getPlatformList(null, platformId);
|
|
|
if (platform.isEmpty()){
|
|
|
@@ -70,7 +96,7 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
}
|
|
|
|
|
|
private void runMiniProgram(String platformId) throws IOException {
|
|
|
- Set<String> errors = new HashSet<>();
|
|
|
+ Set<ErrorRecord> errors = new HashSet<>();
|
|
|
log.info("付费商品库更新中...");
|
|
|
List<AigcProductPlatform> iapPlatformList = bytedanceProductUpdateMapper.getPlatformList("IAP", platformId); //商品库列表
|
|
|
if (!iapPlatformList.isEmpty()){
|
|
|
@@ -99,11 +125,44 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
}
|
|
|
log.info("免费商品库更新完成");
|
|
|
|
|
|
- errors.removeIf(s -> s.contains("剧目不可用"));
|
|
|
+ // 过滤掉包含“剧目不可用”的错误
|
|
|
+ errors.removeIf(er -> er.getMessage() != null && er.getMessage().contains("剧目不可用"));
|
|
|
if (!Check.isNull(errors)){
|
|
|
List<String> info = new ArrayList<>();
|
|
|
info.add("商品上传报错通知");
|
|
|
- info.addAll(errors);
|
|
|
+
|
|
|
+ // 合并相同剧目ID和报错信息的数据
|
|
|
+ Map<String, Set<String>> grouped = new LinkedHashMap<>(); // key -> set of platformIds
|
|
|
+ Map<String, String> keyToAlbum = new HashMap<>(); // key -> albumId
|
|
|
+ for (ErrorRecord er : errors){
|
|
|
+ String albumKey = er.getAlbumId() == null ? "" : er.getAlbumId();
|
|
|
+ String key = albumKey + "||" + er.getMessage();
|
|
|
+ grouped.computeIfAbsent(key, k -> new LinkedHashSet<>());
|
|
|
+ if (er.getPlatformId() != null){
|
|
|
+ grouped.get(key).add(er.getPlatformId());
|
|
|
+ }
|
|
|
+ keyToAlbum.putIfAbsent(key, albumKey);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (Map.Entry<String, Set<String>> e : grouped.entrySet()){
|
|
|
+ String key = e.getKey();
|
|
|
+ String[] parts = key.split("\\|\\|");
|
|
|
+ String message = parts.length>1 ? parts[1] : parts[0];
|
|
|
+ String albumId = keyToAlbum.get(key);
|
|
|
+ Set<String> platformIds = e.getValue();
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ sb.append(message);
|
|
|
+ if (StringUtils.isNotEmpty(albumId)){
|
|
|
+ sb.append(",剧目ID: ").append(albumId);
|
|
|
+ }
|
|
|
+ if (platformIds != null && !platformIds.isEmpty()){
|
|
|
+ if (platformIds.size() < 5){
|
|
|
+ sb.append(",商品库ID: ").append(StringUtils.join(platformIds, ","));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ info.add(sb.toString());
|
|
|
+ }
|
|
|
+
|
|
|
FeishuRobotUtil.sendTextToWebhook(StringUtils.join(info, "\n"), HOOK_URL);
|
|
|
}
|
|
|
}
|
|
|
@@ -114,7 +173,7 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
}
|
|
|
|
|
|
private void runDysDistribute(String platformId) throws IOException {
|
|
|
- Set<String> errors = new HashSet<>();
|
|
|
+ Set<ErrorRecord> errors = new HashSet<>();
|
|
|
List<AigcProductPlatform> iaaPlatformList = bytedanceProductUpdateMapper.getDysIaaPlatformList(platformId); //商品库列表
|
|
|
if (iaaPlatformList.isEmpty()){
|
|
|
return;
|
|
|
@@ -138,16 +197,49 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
runDysProductTask(iaaPlatformList, iaaVideos, new HashMap<>(), errors, BusinessType.IAA);
|
|
|
System.out.println("端原生分销商品库更新完成");
|
|
|
|
|
|
- errors.removeIf(s -> s.contains("剧目不可用"));
|
|
|
+ // 过滤掉包含“剧目不可用”的错误
|
|
|
+ errors.removeIf(er -> er.getMessage() != null && er.getMessage().contains("剧目不可用"));
|
|
|
if (!Check.isNull(errors)){
|
|
|
List<String> info = new ArrayList<>();
|
|
|
info.add("端原生分销商品上传报错通知");
|
|
|
- info.addAll(errors);
|
|
|
+
|
|
|
+ // 合并相同剧目ID和报错信息的数据
|
|
|
+ Map<String, Set<String>> grouped = new LinkedHashMap<>(); // key -> set of platformIds
|
|
|
+ Map<String, String> keyToAlbum = new HashMap<>(); // key -> albumId
|
|
|
+ for (ErrorRecord er : errors){
|
|
|
+ String albumKey = er.getAlbumId() == null ? "" : er.getAlbumId();
|
|
|
+ String key = albumKey + "||" + er.getMessage();
|
|
|
+ grouped.computeIfAbsent(key, k -> new LinkedHashSet<>());
|
|
|
+ if (er.getPlatformId() != null){
|
|
|
+ grouped.get(key).add(er.getPlatformId());
|
|
|
+ }
|
|
|
+ keyToAlbum.putIfAbsent(key, albumKey);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (Map.Entry<String, Set<String>> e : grouped.entrySet()){
|
|
|
+ String key = e.getKey();
|
|
|
+ String[] parts = key.split("\\\\|\\\\|");
|
|
|
+ String message = parts.length>1 ? parts[1] : parts[0];
|
|
|
+ String albumId = keyToAlbum.get(key);
|
|
|
+ Set<String> platformIds = e.getValue();
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ sb.append(message);
|
|
|
+ if (StringUtils.isNotEmpty(albumId)){
|
|
|
+ sb.append(",剧目ID: ").append(albumId);
|
|
|
+ }
|
|
|
+ if (platformIds != null && !platformIds.isEmpty()){
|
|
|
+ if (platformIds.size() < 5){
|
|
|
+ sb.append(",商品库ID: ").append(StringUtils.join(platformIds, ","));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ info.add(sb.toString());
|
|
|
+ }
|
|
|
+
|
|
|
FeishuRobotUtil.sendTextToWebhook(StringUtils.join(info, "\n"), HOOK_URL);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void runMpProductTask(List<AigcProductPlatform> platformList, List<AigcProductAlbum> albums, Map<String, JSONObject> productTypeMap, Set<String> errors, BusinessType businessType) throws IOException {
|
|
|
+ private void runMpProductTask(List<AigcProductPlatform> platformList, List<AigcProductAlbum> albums, Map<String, JSONObject> productTypeMap, Set<ErrorRecord> errors, BusinessType businessType) throws IOException {
|
|
|
for (AigcProductPlatform platform : platformList){
|
|
|
// 拉取已上传剧目,对比,得到未上传剧目列表
|
|
|
List<AigcProductAlbum> hasUploadProductList = hasUploadProductList(platform);
|
|
|
@@ -163,7 +255,7 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
}
|
|
|
//获取未上传剧目的推广链接
|
|
|
List<AigcProductAlbum> douyinUploadList = toUpload.stream().filter(o -> Objects.equals(o.getPlatformType(), "1")).collect(Collectors.toList());
|
|
|
- Map<String, String> albumIdToLinkMap = getBytedancePlayletPromoteLink(platform.getMiniAppAdvertiserId(), platform.getAccessToken(), platform.getMiniInstanceId(), douyinUploadList, errors);
|
|
|
+ Map<String, String> albumIdToLinkMap = getBytedancePlayletPromoteLink(platform.getMiniAppAdvertiserId(), platform.getAccessToken(), platform.getMiniInstanceId(), douyinUploadList, errors, platform.getPlatformId());
|
|
|
//未上传剧目:对比平台类型;确定商品分类;获取推广链接
|
|
|
for (AigcProductAlbum album : toUpload){
|
|
|
if (!Objects.equals(album.getPlatformType(), String.valueOf(platform.getPlatformType()))){
|
|
|
@@ -189,7 +281,7 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void runDysProductTask(List<AigcProductPlatform> platformList, List<AigcProductAlbum> albums, Map<String, JSONObject> productTypeMap, Set<String> errors, BusinessType businessType) throws IOException {
|
|
|
+ private void runDysProductTask(List<AigcProductPlatform> platformList, List<AigcProductAlbum> albums, Map<String, JSONObject> productTypeMap, Set<ErrorRecord> errors, BusinessType businessType) throws IOException {
|
|
|
for (AigcProductPlatform platform : platformList){
|
|
|
// 拉取已上传剧目,对比,得到未上传剧目列表
|
|
|
List<AigcProductAlbum> hasUploadAlbums = hasUploadProductList(platform);
|
|
|
@@ -405,7 +497,7 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
}
|
|
|
|
|
|
private void uploadProduct(AigcProductPlatform platform, AigcProductAlbum album,
|
|
|
- String schemaLink, Set<String> errorBlanket, JSONObject productType,
|
|
|
+ String schemaLink, Set<ErrorRecord> errorBlanket, JSONObject productType,
|
|
|
BusinessType businessType){
|
|
|
String url;
|
|
|
if (StringUtils.isEmpty(album.getAlbumId())){
|
|
|
@@ -490,20 +582,20 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
String res = HttpUtils.httpPostRequest(url, request, headers);
|
|
|
if (res == null || res.isEmpty()){
|
|
|
String payName = businessType==BusinessType.IAP?"付费":"免费";
|
|
|
- errorBlanket.add("上传"+payName+"商品失败,msg: 请求失败或无响应, 关联剧目: " + album.getName());
|
|
|
+ errorBlanket.add(new ErrorRecord("上传"+payName+"商品失败,msg: 请求失败或无响应, 关联剧目: " + album.getName(), album.getAlbumId(), platform.getPlatformId()));
|
|
|
} else {
|
|
|
JSONObject btRes = JSONObject.parseObject(res);
|
|
|
int code = btRes.getIntValue("code");
|
|
|
if (code != 0){
|
|
|
String errorMessage = btRes.getString("message");
|
|
|
String payName = businessType==BusinessType.IAP?"付费":"免费";
|
|
|
- errorBlanket.add("上传"+payName+"商品失败,code: [" + code + "], msg: [" + errorMessage +"], 关联剧目: " + album.getName());
|
|
|
+ errorBlanket.add(new ErrorRecord("上传"+payName+"商品失败,code: [" + code + "], msg: [" + errorMessage +"], 关联剧目: " + album.getName(), album.getAlbumId(), platform.getPlatformId()));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- private Map<String, String> getBytedancePlayletPromoteLink(String advertiserId, String accessToken, String instanceId, List<AigcProductAlbum> requests, Set<String> errorBlanket){
|
|
|
+ private Map<String, String> getBytedancePlayletPromoteLink(String advertiserId, String accessToken, String instanceId, List<AigcProductAlbum> requests, Set<ErrorRecord> errorBlanket, String platformId){
|
|
|
List<String> reqAlbumIds = requests.stream()
|
|
|
.map(obj -> obj.getAlbumId())
|
|
|
.collect(Collectors.toList());
|
|
|
@@ -518,7 +610,7 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
* @return map key: album_id, value: 对应的字节小程序推广链接,sslocal开头
|
|
|
*/
|
|
|
for (int page=1; page<=20; page++){
|
|
|
- JSONArray playletDetailInfo = getPlayletDetail(advertiserId, accessToken, instanceId, errorBlanket,page);
|
|
|
+ JSONArray playletDetailInfo = getPlayletDetail(advertiserId, accessToken, instanceId, errorBlanket, page, platformId);
|
|
|
if (playletDetailInfo == null || playletDetailInfo.isEmpty()){
|
|
|
break;
|
|
|
}
|
|
|
@@ -585,7 +677,7 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
}
|
|
|
|
|
|
if (rr == null || rr.isEmpty()){
|
|
|
- errorBlanket.add("创建字节小程序推广链接失败, 广告账号ID:" + advertiserId + ", 小程序资产ID:" + instanceId);
|
|
|
+ errorBlanket.add(new ErrorRecord("创建字节小程序推广链接失败, 广告账号ID:" + advertiserId + ", 小程序资产ID:" + instanceId, obj.getAlbumId(), platformId));
|
|
|
System.out.println("创建字节小程序推广链接失败");
|
|
|
return res;
|
|
|
}else {
|
|
|
@@ -594,13 +686,13 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
if (code != 0) {
|
|
|
String message = jsonObject.getString("message");
|
|
|
if (message.contains("资产非审核成功")){
|
|
|
- errorBlanket.add("字节小程序"+instanceId+"未通过审核,等待下次再试");
|
|
|
+ errorBlanket.add(new ErrorRecord("字节小程序"+instanceId+"未通过审核,等待下次再试", obj.getAlbumId(), platformId));
|
|
|
break;
|
|
|
}else if (message.contains("请求频率超限")){
|
|
|
- errorBlanket.add("广告账号"+advertiserId+"请求频率超限");
|
|
|
+ errorBlanket.add(new ErrorRecord("广告账号"+advertiserId+"请求频率超限", obj.getAlbumId(), platformId));
|
|
|
continue;
|
|
|
} else {
|
|
|
- errorBlanket.add("创建字节小程序推广链接失败,code: " + code + ", msg: " + jsonObject.getString("message") + ", 广告账号ID:" + advertiserId + ", 小程序资产ID:" + instanceId);
|
|
|
+ errorBlanket.add(new ErrorRecord("创建字节小程序推广链接失败,code: " + code + ", msg: " + jsonObject.getString("message") + ", 广告账号ID:" + advertiserId + ", 小程序资产ID:" + instanceId, obj.getAlbumId(), platformId));
|
|
|
System.out.println("创建字节小程序推广链接失败,code: " + code + ", msg: " + jsonObject.getString("message"));
|
|
|
continue;
|
|
|
}
|
|
|
@@ -612,7 +704,7 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
}
|
|
|
int maxPage = unfound.size() / 100 + 1;
|
|
|
for (int p = 0; p < maxPage; p++) {
|
|
|
- JSONArray newPlayletDetailInfo = getPlayletDetail(advertiserId, accessToken, instanceId, errorBlanket,p+1);
|
|
|
+ JSONArray newPlayletDetailInfo = getPlayletDetail(advertiserId, accessToken, instanceId, errorBlanket, p+1, platformId);
|
|
|
if (newPlayletDetailInfo == null || newPlayletDetailInfo.isEmpty()){
|
|
|
break;
|
|
|
}
|
|
|
@@ -630,7 +722,7 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
|
|
|
}
|
|
|
|
|
|
- private JSONArray getPlayletDetail(String advertiserId, String accessToken, String instanceId, Set<String> errorBlanket, Integer pageNum) {
|
|
|
+ private JSONArray getPlayletDetail(String advertiserId, String accessToken, String instanceId, Set<ErrorRecord> errorBlanket, Integer pageNum, String platformId) {
|
|
|
if (pageNum >60){
|
|
|
return new JSONArray();
|
|
|
}
|
|
|
@@ -650,14 +742,14 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
}
|
|
|
|
|
|
if (res == null || res.isEmpty()) {
|
|
|
- errorBlanket.add("获取字节小程序推广链接失败, 广告账号ID:" + advertiserId + ", 小程序资产ID:" + instanceId);
|
|
|
+ errorBlanket.add(new ErrorRecord("获取字节小程序推广链接失败, 广告账号ID:" + advertiserId + ", 小程序资产ID:" + instanceId, null, platformId));
|
|
|
System.out.println("获取字节小程序推广链接失败, 广告账号ID:" + advertiserId + ", 小程序资产ID:" + instanceId);
|
|
|
return new JSONArray();
|
|
|
}else {
|
|
|
JSONObject jsonObject = JSONObject.parseObject(res);
|
|
|
int code = jsonObject.getIntValue("code");
|
|
|
if (code != 0) {
|
|
|
- errorBlanket.add("获取字节小程序推广链接失败,code: " + code + ", msg: " + jsonObject.getString("message") + ", 广告账号ID:" + advertiserId + ", 小程序资产ID:" + instanceId);
|
|
|
+ errorBlanket.add(new ErrorRecord("获取字节小程序推广链接失败,code: " + code + ", msg: " + jsonObject.getString("message") + ", 广告账号ID:" + advertiserId + ", 小程序资产ID:" + instanceId, null, platformId));
|
|
|
System.out.println("获取字节小程序推广链接失败,code: " + code + ", msg: " + jsonObject.getString("message") + ", 广告账号ID:" + advertiserId + ", 小程序资产ID:" + instanceId);
|
|
|
return new JSONArray();
|
|
|
}else {
|
|
|
@@ -999,6 +1091,7 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
|
|
|
List<JSONObject> videoDetailList = new ArrayList<>();
|
|
|
for (JSONObject obj : videoDetail){
|
|
|
String videoUrl = obj.getString("url").replaceAll("oss\\.artlinkworld\\.cn", "bydance.artlinkworld.cn");//使用单独的域名
|
|
|
+
|
|
|
String title = obj.getString("name");
|
|
|
Integer seq = obj.getInteger("sort");
|
|
|
|