Forráskód Böngészése

feat:同步日报开启

pudongliang 3 hónapja
szülő
commit
16dd0a91c2

+ 17 - 0
src/main/java/com/moka/gdtauto/config/RobotConfig.java

@@ -0,0 +1,17 @@
+package com.moka.gdtauto.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import lombok.Data;
+
+
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "webhook")
+public class RobotConfig {
+    // qywx / feishu
+    private String type = "qywx";
+    private String url;
+    
+}

+ 17 - 1
src/main/java/com/moka/gdtauto/service/AdPlanCreativeAutoExecutor.java

@@ -13,10 +13,12 @@ import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.moka.gdtauto.common.AutoPlanRule;
+import com.moka.gdtauto.entity.AccountGroup;
 import com.moka.gdtauto.entity.AdAutoConf;
 import com.moka.gdtauto.entity.AdAutoExecuteLog;
 import com.moka.gdtauto.entity.AdPlanConf;
 import com.moka.gdtauto.entity.AdPlanCreative;
+import com.moka.gdtauto.util.RobotUtil;
 import com.tencent.ads.model.v3.ConfiguredStatus;
 
 import lombok.AllArgsConstructor;
@@ -38,6 +40,8 @@ public class AdPlanCreativeAutoExecutor {
     private final AdPlanConfService adPlanConfService;
     private final AdPlanCreativeDailyReportService adPlanCreativeDailyReportService;
     private final AdPlanCreativeService adPlanCreativeService;
+    private final AccountGroupService accountGroupService; 
+    private final RobotUtil robotUtil;
 
     /**
      * 执行广告创意巡检
@@ -153,7 +157,7 @@ public class AdPlanCreativeAutoExecutor {
             long adCount = 0;
             List<AdPlanCreative> creativesToSuspend = new ArrayList<>();
             int pageNum = 1;
-            int pageSize = 100;
+            int pageSize = 1000;
             while (true) {
                 LambdaQueryWrapper<AdPlanCreative> queryWrapper = new LambdaQueryWrapper<>();
                 queryWrapper.eq(AdPlanCreative::getAdPlanConfId, confId)
@@ -189,6 +193,18 @@ public class AdPlanCreativeAutoExecutor {
 
             if (!creativesToSuspend.isEmpty()) {
                 adPlanConfService.gdtSuspendByCreatives(adPlanConf, creativesToSuspend);
+                AccountGroup accountGroup = accountGroupService.getById(adPlanConf.getAccountGroupId());
+                // 发送webhook
+                String accountGroupName = accountGroup.getGroupName();
+                List<String> msgs = new ArrayList<>(creativesToSuspend.size());
+                String msgFormat =  accountGroupName + "账户组下%d账户的%d创意 %s 已经被自动暂停链接如下: %s";
+                String urlFormat = "https://ad.qq.com/atlas/%d/admanage/index?tab=dynamic_creative&query={%%22operation_status%%22:[],%%22created_time%%22:%%22-89%%22,%%22fuzzy_name%%22:%%22%d%%22}";
+                for (AdPlanCreative creative : creativesToSuspend) {
+                    String targetUrl = String.format(urlFormat, creative.getAccountId(), creative.getCreativeId());
+                    String msg = String.format(msgFormat, creative.getAccountId(), creative.getCreativeId(), creative.getFailReason(), targetUrl);
+                    msgs.add(msg);
+                }
+                robotUtil.pushMsg(msgs);
             }
 
             log.info("[AdPlanCreativeAutoExecutor] confId={} 巡检:广告数={}, 需暂停数={}", confId, adCount, creativesToSuspend.size());

+ 2 - 1
src/main/java/com/moka/gdtauto/task/DailyAdgroupReportSyncTask.java

@@ -4,6 +4,7 @@ import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 
 import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
 
 import com.moka.gdtauto.service.DailyAdgroupReportService;
 import com.tencent.ads.model.v3.TimeLine;
@@ -20,7 +21,7 @@ import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
  * @since 2026-03-03
  */
 @Slf4j
-//@Component
+@Component
 @RequiredArgsConstructor
 public class DailyAdgroupReportSyncTask {
 

+ 85 - 0
src/main/java/com/moka/gdtauto/util/RobotUtil.java

@@ -0,0 +1,85 @@
+package com.moka.gdtauto.util;
+
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+import org.springframework.stereotype.Component;
+
+import com.google.common.collect.Lists;
+import com.moka.gdtauto.config.RobotConfig;
+
+import lombok.AllArgsConstructor;
+
+
+@Component
+@AllArgsConstructor
+public class RobotUtil {
+
+    private final RobotConfig robotConfig;
+
+
+    private static final Map<String , BiFunction<String, String, String>> robotPush = new HashMap<>();
+    private static final String qywx_msg_template  = """
+            {"msgtype": "markdown","markdown": {"content": "%s"}}
+            """;
+
+    private static final String feishu_msg_template  = """
+            {"msg_type":"text","content":{"text":"%s"}}
+            """;
+    static {
+        robotPush.put("qywx", (url, msg) -> {
+            String s = String.format(qywx_msg_template, msg);
+            try (HttpClient client = HttpClient.newBuilder()
+                .connectTimeout(Duration.ofSeconds(10))
+                .followRedirects(HttpClient.Redirect.NORMAL)
+                .build()) {
+            HttpRequest request = HttpRequest.newBuilder()
+                    .uri(URI.create(url))
+                    .header("Accept", "application/json")
+                    .POST(HttpRequest.BodyPublishers.ofString(s))
+                    .build();
+            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
+            return response.body();
+           } catch (Exception e) {
+            e.printStackTrace();
+            return e.getMessage();
+           }
+        }
+        );
+
+        robotPush.put("feishu", (url,msg) -> {
+            String s = String.format(feishu_msg_template, msg);
+            try (HttpClient client = HttpClient.newBuilder()
+                .connectTimeout(Duration.ofSeconds(10))
+                .followRedirects(HttpClient.Redirect.NORMAL)
+                .build()) {
+            HttpRequest request = HttpRequest.newBuilder()
+                    .uri(URI.create(url))
+                    .header("Accept", "application/json")
+                    .POST(HttpRequest.BodyPublishers.ofString(s))
+                    .build();
+            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
+            return response.body();
+           } catch (Exception e) {
+            e.printStackTrace();
+            return e.getMessage();
+           }
+        });
+    }
+
+    public String pushMsg(List<String> msgs) {
+        String type = robotConfig.getType();
+        List<List<String>> partitions = Lists.partition(msgs, 10);
+        partitions.forEach(msg -> {
+            robotPush.get(type).apply(robotConfig.getUrl(), String.join("\n", msg));
+        });
+        return "ok";
+    }
+}

+ 5 - 1
src/main/resources/application.yml

@@ -72,4 +72,8 @@ tencent:
 aliyun:
   oss:
     bucket-name: ad-auto
-    cdn-domain: https://ad-autoss.luzie.cn
+    cdn-domain: https://ad-autoss.luzie.cn
+
+webhook:
+  type: qywx
+  url: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=1fe80a6e-4510-4b6b-b38c-906f2947dbe8

+ 23 - 0
src/test/java/com/moka/gdtauto/service/AdAutoTest.java

@@ -1,5 +1,6 @@
 package com.moka.gdtauto.service;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.junit.jupiter.api.Test;
@@ -12,6 +13,8 @@ import com.moka.gdtauto.GdtAutoApplication;
 import com.moka.gdtauto.common.AutoPlanRule;
 import com.moka.gdtauto.entity.AdAutoConf;
 import com.moka.gdtauto.entity.AdPlan;
+import com.moka.gdtauto.entity.AdPlanCreative;
+import com.moka.gdtauto.util.RobotUtil;
 
 @SpringBootTest(classes = GdtAutoApplication.class)
 @ActiveProfiles("test")
@@ -23,6 +26,10 @@ public class AdAutoTest {
     private AdAutoConfService adAutoConfService;
     @Autowired
     private AdPlanAutoExecutor adPlanAutoExecutor;
+    @Autowired
+    private RobotUtil robotUtil;
+    @Autowired
+    private AdPlanCreativeService adPlanCreativeService;
 
     @Test
     public void testCheckRule() {
@@ -43,6 +50,22 @@ public class AdAutoTest {
         }
     }
 
+    @Test
+    public void testRobotUtil() {
+        List<AdPlanCreative> creatives = adPlanCreativeService.lambdaQuery()
+            .in(AdPlanCreative::getId, List.of(45,46,47,48)).list();
+            creatives.forEach(c -> c.setFailReason("不考虑消耗 ROI:0.1 < 阈值:0.2"));
+            List<String> msgs = new ArrayList<>(creatives.size());
+                String msgFormat =  "测试组" + "账户组下%d账户的%d创意 %s 已经被自动暂停链接如下: [点击](%s)";
+                String urlFormat = "https://ad.qq.com/atlas/%d/admanage/index?tab=dynamic_creative&query={'operation_status':[],'created_time':'2-89','fuzzy_name':'%d'}";
+                for (AdPlanCreative creative : creatives) {
+                    String targetUrl = String.format(urlFormat, creative.getAccountId(), creative.getCreativeId());
+                    String msg = String.format(msgFormat, creative.getAccountId(), creative.getCreativeId(), creative.getFailReason(), targetUrl);
+                    msgs.add(msg);
+                }
+                robotUtil.pushMsg(msgs);
+    }
+
 
 
 }

+ 2 - 2
src/test/java/com/moka/gdtauto/service/AdPlanDailyReportSyncTest.java

@@ -40,7 +40,7 @@ public class AdPlanDailyReportSyncTest {
     @Test
     public void testSyncTenDaysDailyCreativeReport() {
         DateTimeFormatter FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-            String start = LocalDate.now().plusDays(-1).format(FMT);
+            String start = LocalDate.now().plusDays(-10).format(FMT);
             String end = LocalDate.now().format(FMT);
             dailyCreativeReportService.syncAllAccounts(null, start, end, TimeLine.REQUEST_TIME.getValue());
             dailyCreativeReportService.syncAllAccounts(null, start, end, TimeLine.REPORTING_TIME.getValue());
@@ -57,7 +57,7 @@ public class AdPlanDailyReportSyncTest {
     @Test
     public void testSyncTenDaysDailyAdgroupReport() {
         DateTimeFormatter FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-            String start = LocalDate.now().plusDays(-1).format(FMT);
+            String start = LocalDate.now().plusDays(-2).format(FMT);
             String day = LocalDate.now().format(FMT);
             dailyAdgroupReportService.syncAllAccounts(null, start, day, TimeLine.REQUEST_TIME.getValue());
             dailyAdgroupReportService.syncAllAccounts(null, start, day, TimeLine.REPORTING_TIME.getValue());

+ 8 - 0
src/test/java/com/moka/gdtauto/util/SampleTest.java

@@ -8,6 +8,7 @@ import java.util.List;
 
 import org.junit.jupiter.api.Test;
 import org.springframework.util.DigestUtils;
+
 import com.alibaba.fastjson.JSON;
 import com.moka.gdtauto.common.AutoPlanRule;
 import com.tencent.ads.model.v3.WriteTargetingSetting;
@@ -94,4 +95,11 @@ public class SampleTest {
         int second = now.getSecond();
         System.out.println(second);
     }
+
+    @Test
+    public void stringformateTest() {
+        String urlFormat = "https://ad.qq.com/atlas/%d/admanage/index?tab=dynamic_creative&query={%%22operation_status%%22:[],%%22created_time%%22:%%22-89%%22,%%22fuzzy_name%%22:%%22%d%%22}";
+        String url = String.format(urlFormat, 79729364, 8324507690L);
+        System.out.println(url);
+    }
 }