|
@@ -12,10 +12,7 @@ import org.jeecg.common.util.DateUtils;
|
|
|
import org.jeecg.modules.bytedance.advertise.dockapi.MarketingService;
|
|
|
import org.jeecg.modules.bytedance.advertise.entity.*;
|
|
|
import org.jeecg.modules.bytedance.advertise.enums.BytedanceCreativeMatTypeEnum;
|
|
|
-import org.jeecg.modules.bytedance.advertise.mapper.AiBytedanceAdvertiserStrategyMapper;
|
|
|
-import org.jeecg.modules.bytedance.advertise.mapper.ByteDanceGeneralCopywriterMapper;
|
|
|
-import org.jeecg.modules.bytedance.advertise.mapper.BytedanceAreaInfoMapper;
|
|
|
-import org.jeecg.modules.bytedance.advertise.mapper.RuleDataAccountMapper;
|
|
|
+import org.jeecg.modules.bytedance.advertise.mapper.*;
|
|
|
import org.jeecg.modules.bytedance.advertise.service.*;
|
|
|
import org.jeecg.modules.bytedance.advertise.vo.AdConvertQueryVo;
|
|
|
import org.jeecg.modules.bytedance.advertise.vo.AdGroupSearchVo;
|
|
@@ -38,6 +35,7 @@ import javax.transaction.Transactional;
|
|
|
import java.math.BigDecimal;
|
|
|
import java.util.*;
|
|
|
import java.util.stream.Collectors;
|
|
|
+import org.jeecg.modules.bytedance.advertise.entity.AiBytedanceAutocreateLog;
|
|
|
|
|
|
/**
|
|
|
* 头条智能投放账户配置信息表
|
|
@@ -76,17 +74,25 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
private MarketingService marketingService;
|
|
|
@Resource
|
|
|
ByteDanceGeneralCopywriterMapper byteDanceGeneralCopywriterMapper;
|
|
|
+ @Resource
|
|
|
+ BytedanceMaterialRejectReasonMapper bytedanceMaterialRejectReasonMapper;
|
|
|
+ @Autowired
|
|
|
+ IAiBytedanceAutocreateLogService iBytedanceAutocreateLogService;
|
|
|
+
|
|
|
@Override
|
|
|
- public Long createCreative(AiBytedanceAdvertiserStrategy strategy, Integer createType, Long videoCnt, String openUrl) {
|
|
|
- CtopOauthToken token = tokenService.getOauthTokenByAccountId(strategy.getAccountId()+"");
|
|
|
- if (null == token) {
|
|
|
- log.info("token获取失败=>accountId:{}", strategy.getAccountId());
|
|
|
- return videoCnt;
|
|
|
- }
|
|
|
+ public Long createCreative(CtopOauthToken token, AiBytedanceAdvertiserStrategy strategy, Integer createType, Long videoCnt, String openUrl) {
|
|
|
+
|
|
|
|
|
|
UserAllocation userAllocation = userAllocationService.getByAccountId(strategy.getAccountId());
|
|
|
if(null == userAllocation||userAllocation.getAccountStatus()!=0){
|
|
|
log.info("此账户不存在或者已经被关闭=>accountId:{}", token.getAccountId());
|
|
|
+ AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
|
|
|
+ token.getAccountId(),
|
|
|
+ "获取账户",
|
|
|
+ 500,
|
|
|
+ "此账户不存在或者已经被关闭=>accountId:" + token.getAccountId(),
|
|
|
+ "userAllocationService.getByAccountId => "+ token.getAccountId());
|
|
|
+ iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
|
|
|
return videoCnt;
|
|
|
}
|
|
|
//获取全量广告组数据
|
|
@@ -103,17 +109,35 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
if(timeEnd != 0){
|
|
|
endTime = DateUtils.formatDateTime(now + timeEnd * 60 * 1000L);
|
|
|
}
|
|
|
- List<ByteDanceVideoInfo> videoInfos = getVideoInfoByCreateType(userAllocation.getProjectId(),strategy,startTime,endTime,createType,videoCnt);
|
|
|
+ //List<ByteDanceVideoInfo> videoInfos = getVideoInfoByCreateType(userAllocation.getProjectId(),strategy,startTime,endTime,createType,videoCnt);
|
|
|
+ List<ByteDanceVideoInfo> videoInfos = getvideoOrImageInfoByCreateType(userAllocation.getProjectId(),strategy,startTime,endTime,createType,videoCnt);
|
|
|
if(null == videoInfos||videoInfos.isEmpty()){
|
|
|
log.info("获取{}视频素材为空=>accountId:{}",BytedanceCreativeMatTypeEnum.getNameByType(createType+""),token.getAccountId());
|
|
|
return videoCnt;
|
|
|
}
|
|
|
- log.info("获取{}视频素材个数:{}=>accountId:{}",BytedanceCreativeMatTypeEnum.getNameByType(createType+""),videoInfos.size(),token.getAccountId());
|
|
|
+ log.info("获取{}素材个数:{}=>accountId:{}",BytedanceCreativeMatTypeEnum.getNameByType(createType+""),videoInfos.size(),token.getAccountId());
|
|
|
+ AiBytedanceAutocreateLog iBytedanceAutocreateLogofVideoInfo = new AiBytedanceAutocreateLog(
|
|
|
+ token.getAccountId(),
|
|
|
+ "获取素材",
|
|
|
+ 200,
|
|
|
+ "获取"+BytedanceCreativeMatTypeEnum.getNameByType(createType+"")+"素材个数"+videoInfos.size(),
|
|
|
+ "");
|
|
|
+ iBytedanceAutocreateLogService.save(iBytedanceAutocreateLogofVideoInfo);
|
|
|
|
|
|
for (ByteDanceVideoInfo video:videoInfos) {
|
|
|
+ //判断此素材为视频
|
|
|
+ if ("video".equalsIgnoreCase(video.getMaterialType())){
|
|
|
+ //视频是否是低质视频,为1跳过
|
|
|
+ Integer isLowQuality = bytedanceMaterialRejectReasonMapper.getIsLowQualityByVideoId(video.getVid());
|
|
|
+ if(!Check.isNull(isLowQuality) && 1 == isLowQuality){
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
Integer useDplinkIndex = strategy.getDpLinkIndexUsed();
|
|
|
if(null==useDplinkIndex||useDplinkIndex.equals(0)){
|
|
|
- AiBytedanceAdDplinkInfo adDplinkInfo = adDplinkInfoService.getlatestDpLinkInfo(strategy.getId(),strategy.getAccountId(),1);
|
|
|
+ //查看已使用的dp链接
|
|
|
+ AiBytedanceAdDplinkInfo adDplinkInfo = adDplinkInfoService.getlatestDpLinkInfo(strategy.getId(),strategy.getAccountId(),strategy.getCreativeImageMode(),1);
|
|
|
if(null == adDplinkInfo){
|
|
|
adDplinkInfo = new AiBytedanceAdDplinkInfo();
|
|
|
if("FIX".equalsIgnoreCase(strategy.getAdBidCreateType())){
|
|
@@ -137,7 +161,7 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
return videoCnt;
|
|
|
}
|
|
|
//计划名称
|
|
|
- String adName = getAdName(strategy,null,video);
|
|
|
+ String adName = getAdName(strategy,null,video,userAllocation.getProjectId());
|
|
|
//计算本次出价
|
|
|
BigDecimal currentCpaBid = StringUtils.getRandomAdCpaBid(strategy.getAdBidCreateType(),strategy.getAdMaxBid(),strategy.getAdMinBid(),strategy.getAdStepBid(),adDplinkInfo.getAdBid(),strategy.getAdCpaBid());
|
|
|
JSONObject adParams = getAdParams(strategy,adName,campaignId,currentCpaBid);
|
|
@@ -156,12 +180,26 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
Result resultDeletePlan = marketingService.updPlanStatus(token,adIds,"delete");
|
|
|
if (!resultDeletePlan.isSuccess()){
|
|
|
log.info("广告计划删除失败:message==>{}",resultDeletePlan.getMessage());
|
|
|
+ AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
|
|
|
+ token.getAccountId(),
|
|
|
+ "广告计划删除失败",
|
|
|
+ resultDeletePlan.getCode(),
|
|
|
+ resultDeletePlan.getMessage(),
|
|
|
+ "marketingService.updPlanStatus => token:"+ token.toString()+",adIds:"+adIds.toString()+",optstatus:delete");
|
|
|
+ iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
|
|
|
}
|
|
|
|
|
|
String message = creativeObject.getString("message");
|
|
|
Integer code = creativeObject.getInteger("code");
|
|
|
//创建创意失败
|
|
|
log.info("账户id:{};创意创建失败:code==>{};message==>{}",strategy.getAccountId(),code,message);
|
|
|
+ AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
|
|
|
+ strategy.getAccountId(),
|
|
|
+ "创意创建失败",
|
|
|
+ code,
|
|
|
+ message,
|
|
|
+ "marketingService.creativeCreate => token:"+ token.toString()+",adIds:"+adIds.toString()+",creativeParams:"+creativeParams.toJSONString());
|
|
|
+ iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -169,6 +207,7 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
adDplinkInfo.setAccountId(strategy.getAccountId());
|
|
|
adDplinkInfo.setStatus(1);
|
|
|
adDplinkInfo.setStrategyId(strategy.getId());
|
|
|
+ adDplinkInfo.setImageMode(strategy.getCreativeImageMode());
|
|
|
adDplinkInfoService.save(adDplinkInfo);
|
|
|
|
|
|
BytedanceAiVideoCreativeLog creativeLog = new BytedanceAiVideoCreativeLog(strategy,adId,campaignId,video);
|
|
@@ -179,7 +218,7 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
}
|
|
|
}else{
|
|
|
Long dpIndex ;
|
|
|
- AiBytedanceAdDplinkInfo adDplinkInfo = adDplinkInfoService.getlatestDpLinkInfo(strategy.getId(),strategy.getAccountId(),1);
|
|
|
+ AiBytedanceAdDplinkInfo adDplinkInfo = adDplinkInfoService.getlatestDpLinkInfo(strategy.getId(),strategy.getAccountId(),strategy.getCreativeImageMode(),1);
|
|
|
if(null == adDplinkInfo){
|
|
|
adDplinkInfo = new AiBytedanceAdDplinkInfo();
|
|
|
if("FIX".equalsIgnoreCase(strategy.getAdBidCreateType())){
|
|
@@ -193,9 +232,18 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
adDplinkInfo.setDpLinkIndex(adDplinkInfo.getDpLinkIndex()+1);
|
|
|
}
|
|
|
dpIndex = adDplinkInfo.getDpLinkIndex();
|
|
|
- // 已创建计划 > 账户配置结束下标
|
|
|
- if(dpIndex>strategy.getDpLinkEndIndex()){
|
|
|
- log.info("此账户策略创建结束=>账户id:{};策略id:{}", token.getAccountId(),strategy.getId());
|
|
|
+ // 超出下标范围
|
|
|
+ // 已使用dp链接 < 账户配置结束下标 || 已使用dp链接 > 结束下标
|
|
|
+ if( dpIndex < strategy.getDpLinkStartIndex() || dpIndex > strategy.getDpLinkEndIndex()){
|
|
|
+ log.info("此账户策略创建结束===已创建dp链接超过了限制===>账户id:{};策略id:{}", token.getAccountId(),strategy.getId());
|
|
|
+ AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
|
|
|
+ token.getAccountId(),
|
|
|
+ "策略创建结束",
|
|
|
+ 500,
|
|
|
+ "已创建dp链接超过了限制",
|
|
|
+ "token:"+ token.toString()+",策略id:"+strategy.getId()+
|
|
|
+ dpIndex+"<" + strategy.getDpLinkStartIndex() +"||" +dpIndex +">" + strategy.getDpLinkEndIndex());
|
|
|
+ iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
|
|
|
return 0L;
|
|
|
}
|
|
|
//组名称
|
|
@@ -208,7 +256,7 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
strategy.setAdOpenUrl(openUrl.replace("{{dp链接下标}}",dpIndex.toString()));
|
|
|
String dplinkCode = StringUtils.getParamFromUrl(strategy.getAdOpenUrl(),"bc_fl_src");
|
|
|
//计划名称
|
|
|
- String adName = getAdName(strategy,dplinkCode,video);
|
|
|
+ String adName = getAdName(strategy,dplinkCode,video,userAllocation.getProjectId());
|
|
|
//计算本次出价
|
|
|
BigDecimal currentCpaBid = StringUtils.getRandomAdCpaBid(strategy.getAdBidCreateType(),strategy.getAdMaxBid(),strategy.getAdMinBid(),strategy.getAdStepBid(),adDplinkInfo.getAdBid(),strategy.getAdCpaBid());
|
|
|
adDplinkInfo.setAdBid(currentCpaBid);
|
|
@@ -228,11 +276,25 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
Result resultDeletePlan = marketingService.updPlanStatus(token,adIds,"delete");
|
|
|
if (!resultDeletePlan.isSuccess()){
|
|
|
log.info("广告计划删除失败:message==>{}",resultDeletePlan.getMessage());
|
|
|
+ AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
|
|
|
+ token.getAccountId(),
|
|
|
+ "广告计划删除失败",
|
|
|
+ resultDeletePlan.getCode(),
|
|
|
+ resultDeletePlan.getMessage(),
|
|
|
+ "marketingService.updPlanStatus => token:"+ token.toString()+",adIds:"+adIds.toString()+",optstatus:delete");
|
|
|
+ iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
|
|
|
}
|
|
|
String message = creativeObject.getString("message");
|
|
|
Integer code = creativeObject.getInteger("code");
|
|
|
//创建创意失败
|
|
|
log.info("账户id:{};创意创建失败:code==>{};message==>{}",strategy.getAccountId(),code,message);
|
|
|
+ AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
|
|
|
+ strategy.getAccountId(),
|
|
|
+ "创意创建失败",
|
|
|
+ code,
|
|
|
+ message,
|
|
|
+ "marketingService.creativeCreate => token:"+ token.toString()+",adIds:"+adIds.toString()+",creativeParams:"+creativeParams.toJSONString());
|
|
|
+ iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -240,9 +302,13 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
adDplinkInfo.setAccountId(strategy.getAccountId());
|
|
|
adDplinkInfo.setStatus(1);
|
|
|
adDplinkInfo.setStrategyId(strategy.getId());
|
|
|
+ adDplinkInfo.setImageMode(strategy.getCreativeImageMode());
|
|
|
adDplinkInfoService.save(adDplinkInfo);
|
|
|
BytedanceAiVideoCreativeLog creativeLog = new BytedanceAiVideoCreativeLog(strategy,adId,campaignId,video);
|
|
|
videoCreativeLogService.saveOrUpdate(creativeLog);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
videoCnt --;
|
|
|
if(videoCnt<=0){
|
|
|
return 0L;
|
|
@@ -253,15 +319,20 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
}
|
|
|
private JSONObject getCreativeParams(AiBytedanceAdvertiserStrategy strategy, Long adId,ByteDanceVideoInfo videoInfo,CtopOauthToken token) {
|
|
|
JSONObject params = new JSONObject();
|
|
|
- params.put("advertiser_id",strategy.getAccountId());
|
|
|
- params.put("ad_id",adId);
|
|
|
+ params.put("advertiser_id", strategy.getAccountId());
|
|
|
+ params.put("ad_id", adId);
|
|
|
String inventoryType = strategy.getCreativeInventoryType();
|
|
|
- if(null!=inventoryType&&!"".equals(inventoryType)){
|
|
|
+ if ("CREATIVE_IMAGE_MODE_UNION_SPLASH".equalsIgnoreCase(strategy.getCreativeImageMode())) {
|
|
|
+ params.put("inventory_type", new String[]{"INVENTORY_UNION_SPLASH_SLOT"});
|
|
|
+ } else {
|
|
|
+ if (null != inventoryType && !"".equals(inventoryType)) {
|
|
|
String[] inventoryTypeString = inventoryType.split(",");
|
|
|
- if(inventoryTypeString.length>0){
|
|
|
- params.put("inventory_type",inventoryTypeString);
|
|
|
+ if (inventoryTypeString.length > 0) {
|
|
|
+ params.put("inventory_type", inventoryTypeString);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
Integer smartInventory = strategy.getCreativeSmartInventory();
|
|
|
if(null!=smartInventory&&smartInventory!=0){
|
|
|
params.put("smart_inventory",smartInventory);
|
|
@@ -286,25 +357,32 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
//视频素材
|
|
|
JSONArray imageArray = new JSONArray();
|
|
|
JSONObject imageObject = new JSONObject();
|
|
|
- //视频类型
|
|
|
- if(videoInfo.getType() == 1){
|
|
|
- //竖版视频
|
|
|
- imageObject.put("image_mode","CREATIVE_IMAGE_MODE_VIDEO_VERTICAL");
|
|
|
- }
|
|
|
- if(videoInfo.getType() == 2){
|
|
|
- //横版视频
|
|
|
- imageObject.put("image_mode","CREATIVE_IMAGE_MODE_VIDEO");
|
|
|
- }
|
|
|
- imageObject.put("video_id",videoInfo.getVid());
|
|
|
- //获取视频封面id
|
|
|
- String imageId = getSuggestImageId(token,videoInfo.getVid());
|
|
|
- if(!Check.isNull(imageId)){
|
|
|
- imageObject.put("image_id",imageId);
|
|
|
+
|
|
|
+ if ("video".equalsIgnoreCase(videoInfo.getMaterialType())){
|
|
|
+ //视频类型
|
|
|
+ //1-竖版视频 2-横版视频
|
|
|
+// String imageMode = videoInfo.getType() == 1 ? "CREATIVE_IMAGE_MODE_VIDEO_VERTICAL" : "CREATIVE_IMAGE_MODE_VIDEO";
|
|
|
+ String imageMode = strategy.getCreativeImageMode();
|
|
|
+ imageObject.put("image_mode",imageMode);
|
|
|
+ imageObject.put("video_id",videoInfo.getVid());
|
|
|
+ //获取视频封面id
|
|
|
+ String imageId = getSuggestImageId(token,videoInfo.getVid());
|
|
|
+ if(!Check.isNull(imageId)){
|
|
|
+ imageObject.put("image_id",imageId);
|
|
|
+ }
|
|
|
+ }else if ("image".equalsIgnoreCase(videoInfo.getMaterialType())){
|
|
|
+ //1-大图横图; 2-大图竖图
|
|
|
+// String imageMode = videoInfo.getType() == 1 ? "CREATIVE_IMAGE_MODE_LARGE" : "CREATIVE_IMAGE_MODE_LARGE_VERTICAL";
|
|
|
+ String imageMode = strategy.getCreativeImageMode();
|
|
|
+ imageObject.put("image_mode",imageMode);
|
|
|
+ imageObject.put("image_ids",new String[]{videoInfo.getId()});
|
|
|
}
|
|
|
+
|
|
|
imageArray.add(imageObject);
|
|
|
params.put("image_list",imageArray);
|
|
|
JSONArray titleArray = new JSONArray();
|
|
|
List<BytedanceVideoSlogenInfo> slogenInfos = slogenInfoService.listByParams(videoInfo.getSignature(),1);
|
|
|
+ //使用指定文案
|
|
|
if(!Check.isNull(slogenInfos)){
|
|
|
for (BytedanceVideoSlogenInfo slogenInfo:slogenInfos) {
|
|
|
if(titleArray.size() >= 10){ //接口中是要求一个视频最多10个标题
|
|
@@ -321,12 +399,33 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
}
|
|
|
titleArray.add(titleObject);
|
|
|
}
|
|
|
- for(int i = 0; i < 3; i++){
|
|
|
- if(titleArray.size() >= 10){
|
|
|
- break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 视频 指定文案不够的时候 使用通用文案 最多3条
|
|
|
+ if ("video".equalsIgnoreCase(videoInfo.getMaterialType())){
|
|
|
+ List<ByteDanceGeneralCopywriter> byteDanceGeneralCopywriter = byteDanceGeneralCopywriterMapper.getRandThree(strategy.getAccountId());
|
|
|
+ if(!Check.isNull(byteDanceGeneralCopywriter)){
|
|
|
+ for(int i = 0; i < byteDanceGeneralCopywriter.size(); i++){
|
|
|
+ if(titleArray.size() >= 10){
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ JSONObject titleObject = new JSONObject();
|
|
|
+ titleObject.put("title",byteDanceGeneralCopywriter.get(i).getTextCopywriter());
|
|
|
+ String creativeWordsIds = byteDanceGeneralCopywriter.get(i).getCreativeWordIds();
|
|
|
+ if(null!=creativeWordsIds&&!creativeWordsIds.trim().equals("")){
|
|
|
+ JSONArray creativeWordsArray = JSON.parseArray(creativeWordsIds);
|
|
|
+ if(null!=creativeWordsArray&&!creativeWordsArray.isEmpty()){
|
|
|
+ titleObject.put("creative_word_ids",creativeWordsArray);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ titleArray.add(titleObject);
|
|
|
}
|
|
|
- ByteDanceGeneralCopywriter byteDanceGeneralCopywriter = byteDanceGeneralCopywriterMapper.getRandOne(strategy.getAccountId());
|
|
|
- if(!Check.isNull(byteDanceGeneralCopywriter)){
|
|
|
+ }
|
|
|
+ // 图片 使用通用文案 最多10条
|
|
|
+ }else if ("image".equalsIgnoreCase(videoInfo.getMaterialType())){
|
|
|
+ List<ByteDanceGeneralCopywriter> byteDanceGeneralCopywriterList = byteDanceGeneralCopywriterMapper.getRandTen(strategy.getAccountId());
|
|
|
+ if(!Check.isNull(byteDanceGeneralCopywriterList)){
|
|
|
+ for (ByteDanceGeneralCopywriter byteDanceGeneralCopywriter : byteDanceGeneralCopywriterList){
|
|
|
JSONObject titleObject = new JSONObject();
|
|
|
titleObject.put("title",byteDanceGeneralCopywriter.getTextCopywriter());
|
|
|
String creativeWordsIds = byteDanceGeneralCopywriter.getCreativeWordIds();
|
|
@@ -338,10 +437,9 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
}
|
|
|
titleArray.add(titleObject);
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
+
|
|
|
if(!Check.isNull(titleArray)){
|
|
|
params.put("title_list",titleArray);
|
|
|
}
|
|
@@ -513,7 +611,13 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
Result result = marketingService.createAdvertiserPlan(token,adParams,strategy);
|
|
|
System.out.println(result);
|
|
|
if(result.getCode()!=0){
|
|
|
- //TODO 计划创建异常 后续需要加日志
|
|
|
+ AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
|
|
|
+ strategy.getAccountId(),
|
|
|
+ "计划创建异常",
|
|
|
+ result.getCode(),
|
|
|
+ result.getMessage(),
|
|
|
+ adParams.toJSONString());
|
|
|
+ iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
|
|
|
return null;
|
|
|
}
|
|
|
return (Long)result.getResult();
|
|
@@ -909,7 +1013,7 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
return params;
|
|
|
}
|
|
|
|
|
|
- private String getAdName(AiBytedanceAdvertiserStrategy strategy, String dplinkCode, ByteDanceVideoInfo videoInfo) {
|
|
|
+ private String getAdName(AiBytedanceAdvertiserStrategy strategy, String dplinkCode, ByteDanceVideoInfo videoInfo,Long projectId) {
|
|
|
String adName = strategy.getAdName();
|
|
|
if(null == adName|| "".equals(adName.trim())){
|
|
|
return null;
|
|
@@ -928,14 +1032,20 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
String pricing = strategy.getAdPricing().replace("PRICING_","").toLowerCase(Locale.ROOT);
|
|
|
adName = adName.replace("{{出价方式}}",pricing);
|
|
|
}
|
|
|
+
|
|
|
if(adName.contains("{{素材名称}}")){
|
|
|
- MaterialInfo info = materialInfoService.getParams(videoInfo.getSignature(),null);
|
|
|
- if(null!=info&&null!=info.getMaterialName()){
|
|
|
- adName = adName.replace("{{素材名称}}",info.getMaterialName());
|
|
|
+ if ("video".equals(videoInfo.getMaterialType())){
|
|
|
+ MaterialInfo info = materialInfoService.getParams(videoInfo.getSignature(),null,projectId);
|
|
|
+ if(null!=info&&null!=info.getMaterialName()){
|
|
|
+ adName = adName.replace("{{素材名称}}",info.getMaterialName());
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ adName = adName.replace("{{素材名称}}",videoInfo.getFilename());
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
if(adName.contains("{{序号}}")){
|
|
|
- int i = adDplinkInfoService.getDpLinkInfoCount(strategy.getAccountId());
|
|
|
+ int i = adDplinkInfoService.getDpLinkInfoCount(strategy.getAccountId(),strategy.getCreativeImageMode());
|
|
|
adName = adName.replace("{{序号}}",String.valueOf(i+1));
|
|
|
}
|
|
|
|
|
@@ -985,7 +1095,13 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
//创建组
|
|
|
Result campaignData = marketingService.createCampaign(token, campaignParam);
|
|
|
if(campaignData.getCode()!=0){
|
|
|
- //TODO 组创建异常 后续需要加日志
|
|
|
+ AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
|
|
|
+ strategy.getAccountId(),
|
|
|
+ "组创建异常",
|
|
|
+ campaignData.getCode(),
|
|
|
+ campaignData.getMessage(),
|
|
|
+ campaignParam.toJSONString());
|
|
|
+ iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
|
|
|
return null;
|
|
|
}
|
|
|
return (Long)campaignData.getResult();
|
|
@@ -1002,9 +1118,9 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
}
|
|
|
|
|
|
if(result.contains("{{序号}}")){
|
|
|
- //查询当天已有计划数量
|
|
|
- int i = adDplinkInfoService.getDpLinkInfoCount(strategy.getAccountId());
|
|
|
- Long num = GetCampaignNum.getCampaignNameNum(strategy.getCampaignCnt(),strategy.getCampaignAdCnt(), i == 0 ? i+1 : i);
|
|
|
+ //查询同素材类型当天已有计划数量
|
|
|
+ int i = adDplinkInfoService.getDpLinkInfoCount(strategy.getAccountId(),strategy.getCreativeImageMode());
|
|
|
+ Long num = GetCampaignNum.getCampaignNameNum(strategy.getCampaignCnt(),strategy.getCampaignAdCnt(), i+1);
|
|
|
result = result.replace("{{序号}}",String.valueOf(num));
|
|
|
}
|
|
|
|
|
@@ -1025,10 +1141,10 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
}
|
|
|
|
|
|
private String getRangeIndex(Long dpLinkStartIndex,Long dpLinkEndIndex, Long campaignAdCnt, Long dpIndex) {
|
|
|
- if(dpIndex<dpLinkStartIndex||dpIndex>dpLinkEndIndex){
|
|
|
+ /* if(dpIndex<dpLinkStartIndex||dpIndex>dpLinkEndIndex){
|
|
|
//超出下标范围
|
|
|
return null;
|
|
|
- }
|
|
|
+ }*/
|
|
|
Long startIndex ;
|
|
|
Long endIndex ;
|
|
|
//计算当前下标值和范围区段的余数
|
|
@@ -1040,24 +1156,71 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
startIndex = dpIndex-yzIndex+1;
|
|
|
endIndex = dpIndex-yzIndex+campaignAdCnt;
|
|
|
}
|
|
|
+ //dp 链接 超出可用范围
|
|
|
+ if (endIndex > dpLinkEndIndex){
|
|
|
+ endIndex = dpLinkEndIndex;
|
|
|
+ }
|
|
|
return "-("+startIndex+"/"+endIndex+")";
|
|
|
}
|
|
|
|
|
|
//TODO -- 高质量素材 一天只能创建一次 两周内总消耗》=500
|
|
|
//TODO -- 打捞素材 两周消耗 <500 并且总关联创意数<20
|
|
|
private List<ByteDanceVideoInfo> getVideoInfoByCreateType(Long projectId,AiBytedanceAdvertiserStrategy strategy, String startTime, String endTime, Integer createType, Long videoCnt) {
|
|
|
+ //根据 imageMode 获取素材类型
|
|
|
+ //1-竖版视频 2-横板视频
|
|
|
+ String imageMode = BytedanceCreativeMatTypeEnum.getNameByType(strategy.getCreativeImageMode());
|
|
|
//1:上新素材 2:跑量素材 3:遗漏素材 4:打捞素材
|
|
|
if(createType == 1||createType == 3){
|
|
|
- return videoInfoService.listByParams(projectId,strategy.getAccountId(),startTime,endTime,videoCnt,0);
|
|
|
+ return videoInfoService.listByParams(projectId,strategy.getAccountId(),imageMode,startTime,endTime,videoCnt,0);
|
|
|
}else if(createType == 2){
|
|
|
startTime = startTime.substring(0,10);
|
|
|
endTime = endTime.substring(0,10);
|
|
|
- return videoInfoService.topMatByParams(projectId,strategy.getAccountId(),startTime,endTime,videoCnt);
|
|
|
+ return videoInfoService.topMatByParams(projectId,strategy.getAccountId(),imageMode,startTime,endTime,videoCnt);
|
|
|
+ }else if(createType == 4){
|
|
|
+ return videoInfoService.historyMatByParams(projectId,strategy.getAccountId(),imageMode,startTime,endTime,videoCnt);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 图片素材
|
|
|
+ */
|
|
|
+ private List<ByteDanceVideoInfo> getImageInfoByCreateType(Long projectId,AiBytedanceAdvertiserStrategy strategy, String startTime, String endTime, Integer createType, Long videoCnt) {
|
|
|
+ //根据 imageMode 获取素材类型
|
|
|
+ //1-大图横图; 2-大图竖图 3-开屏
|
|
|
+ String imageMode = BytedanceCreativeMatTypeEnum.getNameByType(strategy.getCreativeImageMode());
|
|
|
+ //1:上新素材 2:跑量素材 3:遗漏素材 4:打捞素材
|
|
|
+ if(createType == 1||createType == 3){
|
|
|
+ return videoInfoService.imageListByParams(projectId,strategy.getAccountId(),imageMode,startTime,endTime,videoCnt,0);
|
|
|
+ }else if(createType == 2){
|
|
|
+ return videoInfoService.imageTopMatByParams(projectId,strategy.getAccountId(),imageMode,startTime,endTime,videoCnt);
|
|
|
}else if(createType == 4){
|
|
|
- return videoInfoService.listByParams(projectId,strategy.getAccountId(),startTime,endTime,videoCnt,20);
|
|
|
+ return videoInfoService.imageHistoryMatByParams(projectId,strategy.getAccountId(),imageMode,startTime,endTime,videoCnt);
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
+
|
|
|
+ private List<ByteDanceVideoInfo> getvideoOrImageInfoByCreateType(Long projectId,AiBytedanceAdvertiserStrategy strategy, String startTime, String endTime, Integer createType, Long videoCnt) {
|
|
|
+ //横板视频 || 竖版视频
|
|
|
+ if (strategy.getCreativeImageMode().equalsIgnoreCase("CREATIVE_IMAGE_MODE_VIDEO")
|
|
|
+ || strategy.getCreativeImageMode().equalsIgnoreCase("CREATIVE_IMAGE_MODE_VIDEO_VERTICAL")){
|
|
|
+ //获取 视频 素材
|
|
|
+ return getVideoInfoByCreateType(projectId,strategy,startTime,endTime,createType,videoCnt);
|
|
|
+ }
|
|
|
+ //获取 图片 素材
|
|
|
+ return getImageInfoByCreateType(projectId,strategy,startTime,endTime,createType,videoCnt);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 修改状态 (0开-1关)
|
|
|
* 同一账户下只能有一条数据信息为开启,可以全部关闭
|
|
@@ -1066,13 +1229,13 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
*/
|
|
|
@Override
|
|
|
@Transactional
|
|
|
- public Result updStaById(String id,String state,String accountId) {
|
|
|
+ public Result updStaById(String id,String state,String accountId,String creativeImageMode) {
|
|
|
//开启
|
|
|
if (org.apache.commons.lang3.StringUtils.equals(state,"0")){
|
|
|
//修改状态为开启
|
|
|
aiBytedanceAdvertiserStrategyMapper.updStaById(id,state);
|
|
|
//关闭 账户下 其他数据信息(不包含本条id信息) 状态为 关闭
|
|
|
- aiBytedanceAdvertiserStrategyMapper.updStaByAccountId(accountId,"1",id);
|
|
|
+ aiBytedanceAdvertiserStrategyMapper.updStaByAccountId(accountId,creativeImageMode,"1",id);
|
|
|
}
|
|
|
//关闭
|
|
|
if (org.apache.commons.lang3.StringUtils.equals(state,"1")){
|
|
@@ -1376,9 +1539,9 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
//默认组数量为 1 -前端已修改完成
|
|
|
//aiBytedanceAdvertiserStrategy.setCampaignAdCnt(aiBytedanceAdvertiserStrategy.getCampaignAdCnt() == 0L ? 1 : aiBytedanceAdvertiserStrategy.getCampaignAdCnt());
|
|
|
|
|
|
- //同一账户下 只能有一条信息为开启
|
|
|
+ //同一账户下 同素材类型 只能有一条信息为开启
|
|
|
//关闭 账户下 其他数据信息(不包含本条id信息) 状态为 关闭
|
|
|
- aiBytedanceAdvertiserStrategyMapper.updStaByAccountId(String.valueOf(aiBytedanceAdvertiserStrategy.getAccountId()),"1",null);
|
|
|
+ aiBytedanceAdvertiserStrategyMapper.updStaByAccountId(String.valueOf(aiBytedanceAdvertiserStrategy.getAccountId()),aiBytedanceAdvertiserStrategy.getCreativeImageMode(),"1",null);
|
|
|
//状态(0开 1关)
|
|
|
aiBytedanceAdvertiserStrategy.setStatus(0);
|
|
|
|
|
@@ -1388,6 +1551,8 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
imageInfo.setUserId(aiBytedanceAdvertiserStrategy.getUserId());
|
|
|
materialImageInfoService.initImageCode(imageInfo);
|
|
|
|
|
|
+
|
|
|
+
|
|
|
aiBytedanceAdvertiserStrategyMapper.insert(aiBytedanceAdvertiserStrategy);
|
|
|
|
|
|
|
|
@@ -1417,36 +1582,63 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
|
|
|
@Autowired
|
|
|
private IByteDanceAdvertisePlanService planService;
|
|
|
+ @Autowired
|
|
|
+ private IByteDanceAdvertiserDataService advertiserDataService;
|
|
|
+
|
|
|
@Override
|
|
|
public void customCreativeSupplement(AiBytedanceAdvertiserStrategy strategy, Integer hour,String openUrl) {
|
|
|
try{
|
|
|
+ CtopOauthToken token = tokenService.getOauthTokenByAccountId(strategy.getAccountId()+"");
|
|
|
+ if (null == token) {
|
|
|
+ log.info("token获取失败=>accountId:{}", strategy.getAccountId());
|
|
|
+ AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
|
|
|
+ strategy.getAccountId(),
|
|
|
+ "获取token",
|
|
|
+ 500,
|
|
|
+ "token获取失败=>accountId:" + strategy.getAccountId(),
|
|
|
+ "tokenService.getOauthTokenByAccountId => "+ strategy.getAccountId());
|
|
|
+ iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
|
|
|
+ return;
|
|
|
+ }
|
|
|
Long customUnitCnt = strategy.getCampaignAdCnt()*strategy.getCampaignCnt();
|
|
|
Long unitNum = customUnitCnt * hour / 19;
|
|
|
log.info("{}当前时间内需要创建计划总数:{}", strategy.getAccountId(), unitNum);
|
|
|
//查询当前账户创建自定义类型计划数量
|
|
|
int unitCreateCnt = planService.queryToDayBuiltCount(strategy.getAccountId());
|
|
|
- log.info("{}截止目前创建组总数:{}", strategy.getAccountId(), unitCreateCnt);
|
|
|
+ log.info("{}截止目前创建计划总数:{}", strategy.getAccountId(), unitCreateCnt);
|
|
|
long remindCnt = unitNum - unitCreateCnt;
|
|
|
if (remindCnt >= 1) {
|
|
|
log.info("{}计划创建不足,剩余需要创建个数{},使用上新素材创建", strategy.getAccountId(), remindCnt);
|
|
|
//优先创建历史遗漏素材
|
|
|
- remindCnt = this.createCreative(strategy, 1, remindCnt,openUrl);
|
|
|
+ remindCnt = this.createCreative(token, strategy, 1, remindCnt,openUrl);
|
|
|
}
|
|
|
if (remindCnt >= 1) {
|
|
|
log.info("{}计划创建不足,剩余需要创建个数{},使用历史遗漏素材创建", strategy.getAccountId(), remindCnt);
|
|
|
//优先创建历史遗漏素材
|
|
|
- remindCnt = this.createCreative(strategy, 3, remindCnt,openUrl);
|
|
|
+ remindCnt = this.createCreative(token, strategy, 3, remindCnt,openUrl);
|
|
|
}
|
|
|
if (remindCnt >= 1) {
|
|
|
log.info("{}计划创建不足,剩余需要创建个数{},使用高质量素材创建", strategy.getAccountId(), remindCnt);
|
|
|
//高质量素材
|
|
|
- remindCnt = this.createCreative(strategy, 2, remindCnt,openUrl);
|
|
|
+ remindCnt = this.createCreative(token, strategy, 2, remindCnt,openUrl);
|
|
|
}
|
|
|
if (remindCnt >= 1) {
|
|
|
//历史打捞素材
|
|
|
log.info("{}计划创建不足,剩余需要创建个数{},使用历史打捞素材创建", strategy.getAccountId(), remindCnt);
|
|
|
- this.createCreative(strategy, 4, remindCnt,openUrl);
|
|
|
+ this.createCreative(token, strategy, 4, remindCnt,openUrl);
|
|
|
}
|
|
|
+ //获取最新的plan计划更新到表格
|
|
|
+ String nowDate = DateUtils.formatDate();
|
|
|
+ advertiserDataService.getAdvertiserPlan(token, "", nowDate, nowDate);
|
|
|
+
|
|
|
+ int newUnitCreateCnt = planService.queryToDayBuiltCount(strategy.getAccountId());
|
|
|
+ AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
|
|
|
+ strategy.getAccountId(),
|
|
|
+ "创建广告计划",
|
|
|
+ 200,
|
|
|
+ "当前账户需要创建计划总数为"+unitNum+"个,截止目前有"+unitCreateCnt+"个,此次创建成功"+(newUnitCreateCnt - unitCreateCnt)+"个。",
|
|
|
+ "aiBytedanceAdvertiserStrategyService.customCreativeSupplement => strategy:"+ strategy.toString()+",hour:"+hour);
|
|
|
+ iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
|
|
|
}catch (Exception e){
|
|
|
log.info(e.getMessage());
|
|
|
}
|
|
@@ -1597,5 +1789,50 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
|
|
|
return Result.successMsg("获取橙子建站站点列表成功。",dataList);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ *查询 组名称 计划名称
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Result getStrategyInfoByName(AiBytedanceAdvertiserStrategy aiBytedanceAdvertiserStrategy) {
|
|
|
+ //查询 组名称
|
|
|
+ QueryWrapper<AiBytedanceAdvertiserStrategy> queryWrapperCampaign = new QueryWrapper<>();
|
|
|
+ //查询计划名称
|
|
|
+ QueryWrapper<AiBytedanceAdvertiserStrategy> queryWrapperAdName = new QueryWrapper<>();
|
|
|
+ List<AiBytedanceAdvertiserStrategy> strategyInfoCampain = new ArrayList<>();
|
|
|
+ List<AiBytedanceAdvertiserStrategy> strategyInfoAdName = new ArrayList<>();
|
|
|
+ //新增
|
|
|
+ if (Check.isNull(aiBytedanceAdvertiserStrategy.getId())){
|
|
|
+ queryWrapperCampaign.eq("campaign_name",aiBytedanceAdvertiserStrategy.getCampaignName());
|
|
|
+ strategyInfoCampain = aiBytedanceAdvertiserStrategyMapper.selectList(queryWrapperCampaign);
|
|
|
+ if (!Check.isNull(strategyInfoCampain)){
|
|
|
+ return Result.error("新创建的账户配置已存在相同的组名称【"+aiBytedanceAdvertiserStrategy.getCampaignName()+"】请修改后重新保存。");
|
|
|
+ }
|
|
|
+ queryWrapperAdName.eq("ad_name",aiBytedanceAdvertiserStrategy.getAdName());
|
|
|
+ strategyInfoAdName = aiBytedanceAdvertiserStrategyMapper.selectList(queryWrapperAdName);
|
|
|
+ if (!Check.isNull(strategyInfoAdName)){
|
|
|
+ return Result.error("新创建的账户配置已存在相同的计划名称【"+aiBytedanceAdvertiserStrategy.getAdName()+"】请修改后重新保存。");
|
|
|
+ }
|
|
|
+ // 编辑
|
|
|
+ }else {
|
|
|
+ queryWrapperCampaign.eq("campaign_name",aiBytedanceAdvertiserStrategy.getCampaignName());
|
|
|
+ strategyInfoCampain = aiBytedanceAdvertiserStrategyMapper.selectList(queryWrapperCampaign);
|
|
|
+ strategyInfoCampain.stream().map(AiBytedanceAdvertiserStrategy::getId).collect(Collectors.toList());
|
|
|
+ if (!Check.isNull(strategyInfoCampain) &&
|
|
|
+ !strategyInfoCampain.stream().map(AiBytedanceAdvertiserStrategy::getId).collect(Collectors.toList()).contains(aiBytedanceAdvertiserStrategy.getId())){
|
|
|
+ return Result.error("新创建的账户配置已存在相同的组名称【"+aiBytedanceAdvertiserStrategy.getCampaignName()+"】请修改后重新保存。");
|
|
|
+ }
|
|
|
+ queryWrapperAdName.eq("ad_name",aiBytedanceAdvertiserStrategy.getAdName());
|
|
|
+ strategyInfoAdName = aiBytedanceAdvertiserStrategyMapper.selectList(queryWrapperAdName);
|
|
|
+ if (!Check.isNull(strategyInfoAdName) &&
|
|
|
+ !strategyInfoAdName.stream().map(AiBytedanceAdvertiserStrategy::getId).collect(Collectors.toList()).contains(aiBytedanceAdvertiserStrategy.getId())){
|
|
|
+ return Result.error("新创建的账户配置已存在相同的计划名称【"+aiBytedanceAdvertiserStrategy.getAdName()+"】请修改后重新保存。");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ return Result.successMsg("成功。",null);
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
}
|