Browse Source

快手自动投放账户程序化创意创建

syh 4 years ago
parent
commit
b72e52ae89

+ 51 - 0
module-common/src/main/java/cn/com/ctop/common/module/utils/ListUtils.java

@@ -0,0 +1,51 @@
+package cn.com.ctop.common.module.utils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class ListUtils<T> {
+    public List<List<T>> split(List<T> sList, int num) {
+        List<List<T>> eList = new ArrayList<List<T>>();
+        List<T> gList;
+        int size = (sList.size()) / num;
+        int size2 = (sList.size()) % num;
+        int j = 0;
+        int xx = 0;
+        for (int i = 0; i < num; i++) {
+            gList = new ArrayList<T>();
+
+            for (j = xx; j < (size + xx); j++) {
+                gList.add(sList.get(j));
+            }
+            xx = j;
+            eList.add(gList);
+        }
+        if (size2 != 0) {
+            gList = new ArrayList<T>();
+            for (int y = 1; y < size2 + 1; y++) {
+                gList.add(sList.get(sList.size() - y));
+            }
+            eList.add(gList);
+        }
+        return eList;
+    }
+
+    public static void main(String[] args) {
+        List<String> ll = new ArrayList<>();
+        ll.add("a");
+        ll.add("b");
+        ll.add("c");
+        ll.add("d");
+        ll.add("e");
+        ll.add("f");
+        ll.add("g");
+
+        //把list平均拆分成2个,若不能平均拆分,多出的一个会单独保存到一个list中。
+        List<List<String>> li = new ListUtils<String>().split(ll, ll.size()/2);
+        for(List<String> l : li){
+            //打印出被拆分后的每个list中的值
+            System.out.println(Arrays.toString(l.toArray()));
+        }
+    }
+}

+ 0 - 8
module-common/src/main/java/cn/com/ctop/common/module/utils/RestUtils.java

@@ -1,8 +0,0 @@
-package cn.com.ctop.common.module.utils;
-
-/**
- *  Created by JQ.bi on 2020.9.23
- */
-public class RestUtils {
-
-}

+ 95 - 32
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/impl/AiKuaishouCreateCreativeServiceImpl.java

@@ -5,6 +5,7 @@ import cn.com.ctop.common.module.entity.MaterialCutFrame;
 import cn.com.ctop.common.module.service.ICtopOauthTokenService;
 import cn.com.ctop.common.module.service.IMaterialCutFrameService;
 import cn.com.ctop.common.module.utils.Check;
+import cn.com.ctop.common.module.utils.ListUtils;
 import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaiShouAppInfo;
 import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaishouAdvertiserStrategy;
 import cn.com.ctop.kuaishou.modules.ai.entity.AiKuaishouStrategyMapCreative;
@@ -59,6 +60,7 @@ public class AiKuaishouCreateCreativeServiceImpl implements IAiKuaishouCreateCre
     @Override
     public void autoCreateCreative(AiKuaishouAdvertiserStrategy strategy){
         strategy.setUnitType(4);
+        String replaceString = "素材上新";
         Long accountId = strategy.getAccountId();
         CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId.toString());
         if(null == token){
@@ -90,7 +92,7 @@ public class AiKuaishouCreateCreativeServiceImpl implements IAiKuaishouCreateCre
                         strategy.setClickTrackUrl(appInfo.getTrackUrl());
                         strategy.setImpressionUrl(appInfo.getTrackUrl());
                     }
-                    String replaceString = appInfo.getAppVersion()+"自动上新";
+                    replaceString = appInfo.getAppVersion()+replaceString;
                     //1:查询通用素材
                     List<KuaiShouVideoGet> allVideos = getVideosByParams(strategy,startTime,endTime,appInfo);
                     if(null == allVideos||allVideos.isEmpty()){
@@ -133,20 +135,19 @@ public class AiKuaishouCreateCreativeServiceImpl implements IAiKuaishouCreateCre
             }
         }else{
             //单一应用
-            List<KuaiShouVideoGet> newVideos = videoGetService.getNewVideoBetweenTime(accountId,startTime,endTime,strategy.getChannelType(),null);
+            List<KuaiShouVideoGet> newVideos = videoGetService.getNewVideoBetweenTime(accountId,startTime,endTime,strategy.getChannelType(),null,null);
             if (null == newVideos ||newVideos.isEmpty()){
                 log.info("账户:{},{} 到 {} 这段时间没有上新素材",accountId, startTime, endTime);
                 return;
             }
-
-            Long newCampaignId = getCampaignId(strategy,token,"素材上新","TODAY");
+            Long newCampaignId = getCampaignId(strategy,token,replaceString,"TODAY");
             if(null== newCampaignId){
                 return;
             }
 
             //3、在“上新”计划中新增广告组,一个素材搭配n张封面,组成一个广告组
             String timestamp = DateUtils.formatDate(new Date(),"yyyyMMddHHmmss");
-            String unitNamePrefix = strategy.getGroupName().replace("自定义","素材上新")+ timestamp;
+            String unitNamePrefix = strategy.getGroupName().replace("自定义",replaceString)+ timestamp;
             int unitCnt = 0;
             for(KuaiShouVideoGet videoItem: newVideos) {
                 KuaishouAccountCreativeOverrunInfo overrunInfo = overrunInfoService.getByParams(accountId, DateUtils.formatDate(new Date()));
@@ -185,6 +186,7 @@ public class AiKuaishouCreateCreativeServiceImpl implements IAiKuaishouCreateCre
     @Override
     public void autoCreateProgramCreative(AiKuaishouAdvertiserStrategy strategy){
         strategy.setUnitType(7);
+        String replaceString = "程序化自动上新";
         Long accountId = strategy.getAccountId();
         CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId.toString());
         if(null == token){
@@ -212,62 +214,61 @@ public class AiKuaishouCreateCreativeServiceImpl implements IAiKuaishouCreateCre
                         log.info("账户:{},appid({}) 数据不存在",accountId, appIdArray.getLong(i));
                         continue;
                     }
-                    String replaceString = appInfo.getAppVersion()+"程序化";
+                    //判定是否通用监测链接
+                    if(null!=strategy.getGeneralTrack()&&strategy.getGeneralTrack() == 0){
+                        strategy.setClickTrackUrl(appInfo.getTrackUrl());
+                        strategy.setImpressionUrl(appInfo.getTrackUrl());
+                    }
+                    replaceString = appInfo.getAppVersion()+replaceString;
                     //1:查询可用素材
                     List<KuaiShouVideoGet> allVideos = getVideosByParams(strategy,startTime,endTime,appInfo);
                     if(null == allVideos){
                         return;
                     }
                     Long newCampaignId = getCampaignId(strategy,token,replaceString,"ALL_CAMPAIGN");
-                    //开始创建组+创意
+                    //创建组
                     String timestamp = DateUtils.formatDate(new Date(),"yyyyMMddHHmmss");
                     String unitNamePrefix = strategy.getGroupName().replace("自定义",replaceString)+ timestamp;
-                    int unitCnt = 0;
-                    for(KuaiShouVideoGet videoItem: allVideos) {
+                    String unitName = unitNamePrefix + "-" + timestamp;
+                    JSONObject unitParams = createUnitParams(token, newCampaignId, strategy, unitName,appInfo.getAppId());
+                    Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams, 1);
+                    Integer unitCode = (Integer) unitCreateResult.get("code");
+                    String unitMessage = (String) unitCreateResult.get("message");
+                    if (unitCode != 0) {
+                        log.info("组创建失败=>accountId:{};message:{}", accountId, unitMessage);
+                        continue;
+                    }
+                    Long unitId = (Long) unitCreateResult.get("unitId");
+                    //创意
+                    List<List<KuaiShouVideoGet>> splitVideos = new ListUtils<KuaiShouVideoGet>().split(allVideos,allVideos.size()/5);
+                    for(int j=1;j<splitVideos.size()+1;j++) {
                         KuaishouAccountCreativeOverrunInfo overrunInfo = overrunInfoService.getByParams(accountId, DateUtils.formatDate(new Date()));
                         if (null != overrunInfo) {
                             log.info("该账户创意创建已超限=>accountId:{}",accountId);
                             return;
                         }
-                        unitCnt++;
-                        String unitName = unitNamePrefix + "-" + unitCnt;
-                        JSONObject unitParams = createUnitParams(token, newCampaignId, strategy, unitName,appInfo.getAppId());
-                        Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams, 1);
-                        Integer unitCode = (Integer) unitCreateResult.get("code");
-                        String unitMessage = (String) unitCreateResult.get("message");
-                        if (unitCode != 0) {
-                            log.info("组创建失败=>accountId:{};message:{}", accountId, unitMessage);
-                            continue;
-                        }
-                        Long unitId = (Long) unitCreateResult.get("unitId");
 
-                        // 每个组,搭配n个创意
-                        List<MaterialCutFrame> cutFrameList = materialCutFrameService.getListByVideoSignature(videoItem.getSignature());
-                        if ((null == cutFrameList || cutFrameList.isEmpty())) {
-                            log.info("未获取到视频封面=>videoSignature:{}", videoItem.getSignature());
-                            continue;
-                        }
-                        JSONObject creativeParams = creativeParams(token, unitId, videoItem, strategy);
+                        JSONObject creativeParams = programCreativeParams(token, unitId, splitVideos.get(j-1), strategy,j);
                         createCreativeByImage(cutFrameList, token, creativeParams, newCampaignId, unitId, videoItem, strategy.getImageCnt());
                     }
                 }
             }
         }else{
             //单一应用
-            List<KuaiShouVideoGet> newVideos = videoGetService.getNewVideoBetweenTime(accountId,startTime,endTime,strategy.getChannelType(),null);
+            List<KuaiShouVideoGet> newVideos = videoGetService.getNewVideoBetweenTime(accountId,startTime,endTime,strategy.getChannelType(),null,150);
             if (null == newVideos ||newVideos.isEmpty()){
                 log.info("账户:{},{} 到 {} 这段时间没有上新素材",accountId, startTime, endTime);
                 return;
             }
 
-            Long newCampaignId = getCampaignId(strategy,token,"素材上新","TODAY");
+            Long newCampaignId = getCampaignId(strategy,token,replaceString,"TODAY");
             if(null== newCampaignId){
                 return;
             }
 
             //3、在“上新”计划中新增广告组,一个素材搭配n张封面,组成一个广告组
             String timestamp = DateUtils.formatDate(new Date(),"yyyyMMddHHmmss");
-            String unitNamePrefix = strategy.getGroupName().replace("自定义","素材上新")+ timestamp;
+            String unitNamePrefix = strategy.getGroupName().replace("自定义",replaceString)+ timestamp;
             int unitCnt = 0;
             for(KuaiShouVideoGet videoItem: newVideos) {
                 KuaishouAccountCreativeOverrunInfo overrunInfo = overrunInfoService.getByParams(accountId, DateUtils.formatDate(new Date()));
@@ -299,10 +300,72 @@ public class AiKuaishouCreateCreativeServiceImpl implements IAiKuaishouCreateCre
         }
     }
 
+    private JSONObject programCreativeParams(CtopOauthToken token, Long unitId, List<KuaiShouVideoGet> list, AiKuaishouAdvertiserStrategy strategy,Integer creativeCnt) {
+        JSONObject programJson = new JSONObject();
+        programJson.put("advertiser_id", token.getAccountId());
+        programJson.put("unit_id", unitId);
+        programJson.put("package_name", "程序化创意"+creativeCnt);
+        JSONArray horizontalPhotoIds = new JSONArray();
+        JSONArray verticalPhotoIds = new JSONArray();
+        JSONArray coverImageTokens = new JSONArray();
+        for(KuaiShouVideoGet videoGet:list){
+            List<MaterialCutFrame> cutFrameList = materialCutFrameService.getListByVideoSignature(videoGet.getSignature());
+            if (null!=cutFrameList&&!cutFrameList.isEmpty()){
+                MaterialCutFrame cutFrame = cutFrameList.get(0);
+                String imageToken = getImageToken(cutFrame.getUrl(),cutFrame.getSignature(), token.getAccountId(), token.getAccessToken());
+                if (!Check.isNull(imageToken)) {
+                    coverImageTokens.add(imageToken);
+                }
+            }
+            if(videoGet.getMaterialType() == 2){
+                horizontalPhotoIds.add(videoGet.getPhotoId());
+            }
+            if(videoGet.getMaterialType() == 1){
+                verticalPhotoIds.add(videoGet.getPhotoId());
+            }
+        }
+        if(!horizontalPhotoIds.isEmpty()){
+            programJson.put("horizontal_photo_ids", horizontalPhotoIds);
+        }
+        if(!verticalPhotoIds.isEmpty()){
+            programJson.put("vertical_photo_ids", verticalPhotoIds);
+        }
+        if(coverImageTokens.size()>=5){
+            coverImageTokens.remove(0);
+        }
+        if (!Check.isNull(strategy.getSiteId())) {
+            programJson.put("site_id", strategy.getSiteId());
+        }
+        if (!Check.isNull(strategy.getStickerTitle())) {
+            programJson.put("sticker_styles", strategy.getStickerTitle());
+        }
+//        if (!Check.isNull(programCreativeJson.getJSONArray("cover_slogans"))) {
+//            programJson.put("cover_slogans", programCreativeJson.getJSONArray("cover_slogans"));
+//        }
+        if (!Check.isNull(strategy.getActionBarText())) {
+            programJson.put("action_bar", strategy.getActionBarText());
+        }
+        if (!Check.isNull(programCreativeJson.getJSONArray("captions"))) {
+            programJson.put("captions", programCreativeJson.getJSONArray("captions"));
+        }
+        if (!Check.isNull(programCreativeJson.getString("click_url"))) {
+            programJson.put("click_url", programCreativeJson.getString("click_url"));
+        }
+        if (!Check.isNull(programCreativeJson.getString("actionbar_click_url"))) {
+            programJson.put("actionbar_click_url", programCreativeJson.getString("actionbar_click_url"));
+        }
+        if (!Check.isNull(programCreativeJson.getInteger("creative_category"))) {
+            programJson.put("creative_category", programCreativeJson.getInteger("creative_category"));
+        }
+        if (!Check.isNull(programCreativeJson.getJSONArray("creative_tag"))) {
+            programJson.put("creative_tag", programCreativeJson.getJSONArray("creative_tag"));
+        }
+    }
+
     private List<KuaiShouVideoGet> getVideosByParams(AiKuaishouAdvertiserStrategy strategy,String startTime,String endTime,AiKuaiShouAppInfo appInfo) {
-        List<KuaiShouVideoGet> generalVideos = videoGetService.getNewVideoBetweenTime(strategy.getAccountId(),startTime,endTime,strategy.getChannelType(),null);
+        List<KuaiShouVideoGet> generalVideos = videoGetService.getNewVideoBetweenTime(strategy.getAccountId(),startTime,endTime,strategy.getChannelType(),null,null);
         //2:查询特定素材
-        List<KuaiShouVideoGet> customVideos = videoGetService.getNewVideoBetweenTime(strategy.getAccountId(),startTime,endTime,strategy.getChannelType(),appInfo.getAppVersion());
+        List<KuaiShouVideoGet> customVideos = videoGetService.getNewVideoBetweenTime(strategy.getAccountId(),startTime,endTime,strategy.getChannelType(),appInfo.getAppVersion(),null);
         if(null == generalVideos||generalVideos.isEmpty()||null == customVideos||customVideos.isEmpty()){
             log.info("账户:{},appId({}){}到{}这段时间没有上新素材",strategy.getAccountId(),appInfo.getAppId(),startTime, endTime);
             return null;

+ 2 - 2
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/ai/service/impl/KuaiShouVideoLastTimeServiceImpl.java

@@ -5,9 +5,9 @@ import cn.com.ctop.kuaishou.modules.ai.mapper.KuaiShouVideoLastTimeMapper;
 import cn.com.ctop.kuaishou.modules.ai.service.IKuaiShouVideoLastTimeService;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
 import java.util.List;
 
 /**
@@ -19,7 +19,7 @@ import java.util.List;
  */
 @Service
 public class KuaiShouVideoLastTimeServiceImpl extends ServiceImpl<KuaiShouVideoLastTimeMapper, KuaiShouVideoLastTime> implements IKuaiShouVideoLastTimeService {
-    @Autowired
+    @Resource
     private KuaiShouVideoLastTimeMapper videoLastTimeMapper;
 
     @Override

+ 1 - 1
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/IKuaiShouVideoGetService.java

@@ -27,7 +27,7 @@ public interface IKuaiShouVideoGetService extends IService<KuaiShouVideoGet> {
 
     List<KuaiShouVideoGet> getNewVideoDescDate(Long accountId, Integer newVideoCnt);
 
-    List<KuaiShouVideoGet> getNewVideoBetweenTime(Long accountId, String startTime, String endTime,Integer channelType,String appVersion);
+    List<KuaiShouVideoGet> getNewVideoBetweenTime(Long accountId, String startTime, String endTime,Integer channelType,String appVersion,Integer videoCnt);
 
     List<JSONObject> getVideoListByMap(Map<String, Object> requestMap);
 

+ 4 - 1
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/impl/KuaiShouVideoGetServiceImpl.java

@@ -151,7 +151,7 @@ public class KuaiShouVideoGetServiceImpl extends ServiceImpl<KuaiShouVideoGetMap
 
 
     @Override
-    public List<KuaiShouVideoGet> getNewVideoBetweenTime(Long accountId, String startTime, String endTime,Integer channelType,String appVersion) {
+    public List<KuaiShouVideoGet> getNewVideoBetweenTime(Long accountId, String startTime, String endTime,Integer channelType,String appVersion,Integer videoCnt) {
         QueryWrapper<KuaiShouVideoGet> queryWrapper = new QueryWrapper<>();
         if (null != accountId && accountId != 0) {
             queryWrapper.eq("account_id", accountId);
@@ -167,6 +167,9 @@ public class KuaiShouVideoGetServiceImpl extends ServiceImpl<KuaiShouVideoGetMap
         if(null!=appVersion&&!appVersion.trim().equals("")){
             queryWrapper.likeLeft("photo_name",appVersion);
         }
+        if(null!=videoCnt&&videoCnt!=0){
+            queryWrapper.last("limit "+videoCnt);
+        }
         return this.list(queryWrapper);
     }