浏览代码

数据汇聚

孙永军 2 年之前
父节点
当前提交
76842f7b2b
共有 79 个文件被更改,包括 3701 次插入31 次删除
  1. 11 1
      build.gradle
  2. 43 19
      src/main/java/com/sxtvs/open/api/odata/controller/OauthController.java
  3. 4 4
      src/main/java/com/sxtvs/open/api/odata/controller/OauthRestController.java
  4. 7 0
      src/main/java/com/sxtvs/open/api/odata/dao/BilibiliAccountMapper.java
  5. 7 0
      src/main/java/com/sxtvs/open/api/odata/dao/DouyinAccountMapper.java
  6. 7 0
      src/main/java/com/sxtvs/open/api/odata/dao/KuaishouAccountMapper.java
  7. 7 0
      src/main/java/com/sxtvs/open/api/odata/dao/PlatformDataMapper.java
  8. 7 0
      src/main/java/com/sxtvs/open/api/odata/dao/PlatformMapper.java
  9. 16 0
      src/main/java/com/sxtvs/open/api/odata/dao/QrcodeLogMapper.java
  10. 7 0
      src/main/java/com/sxtvs/open/api/odata/dao/ToutiaoAccountMapper.java
  11. 7 0
      src/main/java/com/sxtvs/open/api/odata/dao/WeiboAccountMapper.java
  12. 7 0
      src/main/java/com/sxtvs/open/api/odata/dao/WeiboTaskMapper.java
  13. 7 0
      src/main/java/com/sxtvs/open/api/odata/dao/WxAccountMapper.java
  14. 7 0
      src/main/java/com/sxtvs/open/api/odata/dao/WxAccountV2Mapper.java
  15. 7 0
      src/main/java/com/sxtvs/open/api/odata/dao/WxTicketMapper.java
  16. 7 0
      src/main/java/com/sxtvs/open/api/odata/dao/YoumeiAccountMapper.java
  17. 18 0
      src/main/java/com/sxtvs/open/api/odata/dto/ImportFile.java
  18. 8 0
      src/main/java/com/sxtvs/open/api/odata/dto/PlatformDTO.java
  19. 31 0
      src/main/java/com/sxtvs/open/api/odata/dto/bilibili/BilibiliAccessToken.java
  20. 31 0
      src/main/java/com/sxtvs/open/api/odata/dto/bilibili/BilibiliAccountInfo.java
  21. 31 0
      src/main/java/com/sxtvs/open/api/odata/dto/bilibili/BilibiliRefreshToken.java
  22. 24 0
      src/main/java/com/sxtvs/open/api/odata/dto/douyin/DouyinAccessTokenResponse.java
  23. 28 0
      src/main/java/com/sxtvs/open/api/odata/dto/douyin/DouyinCommonResponse.java
  24. 18 0
      src/main/java/com/sxtvs/open/api/odata/dto/douyin/DouyinRefreshTokenResponse.java
  25. 22 0
      src/main/java/com/sxtvs/open/api/odata/dto/douyin/DouyinUserInfoResponse.java
  26. 24 0
      src/main/java/com/sxtvs/open/api/odata/dto/douyin/videolist/Data.java
  27. 13 0
      src/main/java/com/sxtvs/open/api/odata/dto/douyin/videolist/DouyinVideoListResponse.java
  28. 25 0
      src/main/java/com/sxtvs/open/api/odata/dto/douyin/videolist/Extra.java
  29. 34 0
      src/main/java/com/sxtvs/open/api/odata/dto/douyin/videolist/ListItem.java
  30. 25 0
      src/main/java/com/sxtvs/open/api/odata/dto/douyin/videolist/Statistics.java
  31. 30 0
      src/main/java/com/sxtvs/open/api/odata/dto/kuaishou/KuaiShouVideoResponse.java
  32. 22 0
      src/main/java/com/sxtvs/open/api/odata/dto/kuaishou/KuaishouAccessTokenResponse.java
  33. 18 0
      src/main/java/com/sxtvs/open/api/odata/dto/kuaishou/KuaishouCommonResponse.java
  34. 18 0
      src/main/java/com/sxtvs/open/api/odata/dto/kuaishou/KuaishouUserInfoResponse.java
  35. 14 0
      src/main/java/com/sxtvs/open/api/odata/dto/weibo/WeiboAccessTokenResponse.java
  36. 19 0
      src/main/java/com/sxtvs/open/api/odata/dto/weibo/WeiboCreateTask.java
  37. 13 0
      src/main/java/com/sxtvs/open/api/odata/dto/weibo/show/AnnotationsItem.java
  38. 20 0
      src/main/java/com/sxtvs/open/api/odata/dto/weibo/show/CommentManageInfo.java
  39. 13 0
      src/main/java/com/sxtvs/open/api/odata/dto/weibo/show/Insecurity.java
  40. 351 0
      src/main/java/com/sxtvs/open/api/odata/dto/weibo/show/Status.java
  41. 470 0
      src/main/java/com/sxtvs/open/api/odata/dto/weibo/show/UserShowResponse.java
  42. 20 0
      src/main/java/com/sxtvs/open/api/odata/dto/weibo/show/Visible.java
  43. 27 0
      src/main/java/com/sxtvs/open/api/odata/entity/BilibiliAccount.java
  44. 27 0
      src/main/java/com/sxtvs/open/api/odata/entity/DouyinAccount.java
  45. 27 0
      src/main/java/com/sxtvs/open/api/odata/entity/KuaishouAccount.java
  46. 15 0
      src/main/java/com/sxtvs/open/api/odata/entity/Platform.java
  47. 27 0
      src/main/java/com/sxtvs/open/api/odata/entity/PlatformData.java
  48. 39 0
      src/main/java/com/sxtvs/open/api/odata/entity/QrcodeLog.java
  49. 27 0
      src/main/java/com/sxtvs/open/api/odata/entity/ToutiaoAccount.java
  50. 25 0
      src/main/java/com/sxtvs/open/api/odata/entity/WeiboAccount.java
  51. 25 0
      src/main/java/com/sxtvs/open/api/odata/entity/WeiboTask.java
  52. 26 0
      src/main/java/com/sxtvs/open/api/odata/entity/WxAccount.java
  53. 29 0
      src/main/java/com/sxtvs/open/api/odata/entity/WxAccountV2.java
  54. 17 0
      src/main/java/com/sxtvs/open/api/odata/entity/WxTicket.java
  55. 28 0
      src/main/java/com/sxtvs/open/api/odata/entity/YoumeiAccount.java
  56. 141 0
      src/main/java/com/sxtvs/open/api/odata/service/BilibiliAccountService.java
  57. 219 0
      src/main/java/com/sxtvs/open/api/odata/service/DouyinAccountService.java
  58. 16 0
      src/main/java/com/sxtvs/open/api/odata/service/IQrcodeLogService.java
  59. 259 0
      src/main/java/com/sxtvs/open/api/odata/service/KuaishouAccountService.java
  60. 13 0
      src/main/java/com/sxtvs/open/api/odata/service/PlatformDataService.java
  61. 11 0
      src/main/java/com/sxtvs/open/api/odata/service/PlatformService.java
  62. 37 0
      src/main/java/com/sxtvs/open/api/odata/service/QrcodeLogServiceImpl.java
  63. 297 0
      src/main/java/com/sxtvs/open/api/odata/service/ToutiaoAccountService.java
  64. 133 0
      src/main/java/com/sxtvs/open/api/odata/service/WeiboAccountService.java
  65. 12 0
      src/main/java/com/sxtvs/open/api/odata/service/WeiboTaskService.java
  66. 15 0
      src/main/java/com/sxtvs/open/api/odata/service/WxAccountService.java
  67. 21 0
      src/main/java/com/sxtvs/open/api/odata/service/WxAccountV2Service.java
  68. 270 0
      src/main/java/com/sxtvs/open/api/odata/service/WxRestService.java
  69. 27 0
      src/main/java/com/sxtvs/open/api/odata/service/WxTicketService.java
  70. 70 0
      src/main/java/com/sxtvs/open/api/odata/service/YoumeiTokenService.java
  71. 22 0
      src/main/java/com/sxtvs/open/core/conf/Constant.java
  72. 129 0
      src/main/java/com/sxtvs/open/core/conf/RestConfig.java
  73. 64 0
      src/main/java/com/sxtvs/open/core/http/APIResponseAdvice.java
  74. 40 0
      src/main/java/com/sxtvs/open/core/http/RequestUtil.java
  75. 15 0
      src/main/java/com/sxtvs/open/core/http/WxRedirectView.java
  76. 39 0
      src/main/java/com/sxtvs/open/core/lock/SegmentLock.java
  77. 13 3
      src/test/data-service.http
  78. 0 3
      src/test/java/com/sxtvs/open/EsClientTests.java
  79. 1 1
      src/test/java/com/sxtvs/open/GenCode.java

+ 11 - 1
build.gradle

@@ -22,10 +22,10 @@ repositories {
 
 dependencies {
 
-
     implementation 'cn.hutool:hutool-core:5.8.12'
     implementation 'cn.hutool:hutool-crypto:5.8.12'
     implementation 'org.springframework.boot:spring-boot-starter-validation'
+    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
 
     implementation 'com.github.ben-manes.caffeine:caffeine:2.9.2'
     implementation group: 'com.mysql', name: 'mysql-connector-j', version: '8.0.32'
@@ -35,6 +35,8 @@ dependencies {
 
     implementation 'com.baomidou:mybatis-plus-boot-starter:3.5.3.1'
     implementation 'com.baomidou:dynamic-datasource-spring-boot-starter:3.6.1'
+    implementation 'org.springframework.boot:spring-boot-starter-validation'
+    implementation 'org.springframework.boot:spring-boot-starter-validation'
     testImplementation 'com.baomidou:mybatis-plus-generator:3.5.3'
     testImplementation 'org.freemarker:freemarker:2.3.31'
 
@@ -58,6 +60,14 @@ dependencies {
     implementation 'org.glassfish:jakarta.json:2.0.1'
     implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.3'
     implementation 'org.apache.commons:commons-pool2'
+    implementation 'com.opencsv:opencsv:4.5'
+    implementation 'cn.hutool:hutool-http:5.7.20'
+    implementation 'org.apache.poi:poi-ooxml:5.0.0'
+    implementation 'com.alibaba:easyexcel:2.2.6'
+    implementation 'org.springframework.retry:spring-retry:1.3.1'
+
+
+
 
 }
 

+ 43 - 19
src/main/java/com/sxtvs/open/api/odata/controller/OauthController.java

@@ -1,13 +1,17 @@
 package com.sxtvs.open.api.odata.controller;
 
-import com.sxtvs.open.api.odata.service.OauthService;
+import cn.hutool.core.util.StrUtil;
+import com.sxtvs.open.api.odata.service.*;
 import com.sxtvs.open.core.sls.AliyunLogger;
+import jakarta.servlet.http.HttpServletRequest;
+import org.apache.commons.io.IOUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 
+import java.io.IOException;
 import java.util.Map;
 
 @Controller
@@ -21,65 +25,85 @@ public class OauthController {
     @Autowired
     private AliyunLogger logger;
 
-
+    @Autowired
+    private DouyinAccountService douyinAccountService;
 
     @RequestMapping("douyin/callback")
     public String douyinCallback(String code, String state) {
         var token = oauthService.loadStateMapping(state);
         logger.info("key", "oauth/douyin/callback", "code", code, "state", state, "token", token);
         // todo 用户数据入库
-        return "redirect:https://www.baidu.com";
+        douyinAccountService.upsert(code);
+        return "redirect:/login.html?platform=douyin";
     }
 
-
+    @Autowired
+    private KuaishouAccountService kuaishouAccountService;
 
     @RequestMapping("kuaishou/callback")
     public String kuaishouCallback(String code, String state) {
         var token = oauthService.loadStateMapping(state);
         logger.info("key", "oauth/kuaishou/callback", "code", code, "state", state, "token", token);
         // todo 用户数据入库
-        return "redirect:https://www.baidu.com";
+        kuaishouAccountService.upsert(code);
+        return "redirect:/login.html?platform=kuaishou";
     }
 
-
+    @Autowired
+    private ToutiaoAccountService toutiaoAccountService;
 
     @RequestMapping("toutiao/callback")
     public String toutiaoCallback(String code, String state) {
         var token = oauthService.loadStateMapping(state);
         logger.info("key", "oauth/toutiao/callback", "code", code, "state", state, "token", token);
         // todo 用户数据入库
-        return "redirect:https://www.baidu.com";
+        toutiaoAccountService.upsert(code);
+        return "redirect:/login.html?platform=toutiao";
     }
 
+    @Autowired
+    private WeiboAccountService weiboAccountService;
 
+    @RequestMapping("weibo/callback")
+    public String weiboCallback(String code, String state) {
+        logger.info("key", "oauth/weibo/callback", "code", code);
+        // todo 用户数据入库
+        weiboAccountService.upsert(code);
+        return "redirect:https://www.baidu.com";
+    }
 
-//    @RequestMapping("weibo/callback")
-//    public String weiboCallback(String code, String state) {
-//        logger.info("key", "oauth/weibo/callback", "code", code);
-//        // todo 用户数据入库
-//        return "redirect:https://www.baidu.com";
-//    }
-
-
+    @Autowired
+    private BilibiliAccountService bilibiliAccountService;
 
     @RequestMapping("bilibili/callback")
     public String bilibiliCallback(String code, String state) {
         var token = oauthService.loadStateMapping(state);
         logger.info("key", "oauth/bilibili/callback", "code", code, "state", state, "token", token);
         // todo 用户数据入库
-        return "redirect:https://www.baidu.com";
+        bilibiliAccountService.upsert(code);
+        return "redirect:/login.html?platform=bilibili";
     }
 
-
+    @Autowired
+    private WxRestService wxRestService;
 
     @RequestMapping("weixin/{appid}/callback")
     public String callback(
             @RequestParam("auth_code") String authCode,
             @RequestParam("expires_in") Integer expiresIn,
-            @PathVariable("appid") String appid) {
+            @PathVariable("appid") String appid, HttpServletRequest request) {
         logger.info("key", "oauth/{appid}/callback", "data",
                 Map.of("authCode", authCode, "expiresIn", expiresIn, "appid", appid));
+        if (StrUtil.isBlank(authCode)) {
+            try {
+                String body = IOUtils.toString(request.getReader());
+                logger.error("wxdca527f24b99b4c0/callback error body {}", body);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
         // todo 用户数据入库
-        return "redirect:https://www.baidu.com";
+        wxRestService.apiQueryAuth(authCode);
+        return "redirect:/login.html?platform=weixin";
     }
 }

+ 4 - 4
src/main/java/com/sxtvs/open/api/odata/controller/OauthRestController.java

@@ -57,7 +57,7 @@ public class OauthRestController {
         return new RedirectDto("https://open.douyin.com/platform/oauth/connect/?" +
                 "client_key=awfrca76s1petwh0&response_type=code&" +
                 "scope=video.data%2Cfans.list%2Cdata.external.item%2Cdata.external.user%2Cfans.data%2Cvideo.list%2Crenew_refresh_token%2Cuser_info&" +
-                "redirect_uri=https%3A%2F%2Fimport.smcic.net%2Fdouyin%2Fcallback-open&state=" + state);
+                "redirect_uri=https%3A%2F%2Fopen.sxtvs.net%2Fdouyin%2Fcallback-open&state=" + state);
     }
 
     @RequestMapping("kuaishou/code")
@@ -70,7 +70,7 @@ public class OauthRestController {
         return new RedirectDto("http://open.kuaishou.com/oauth2/connect?" +
                 "app_id=" + OauthConfig.kuaishouClientKey + "&response_type=code&" +
                 "scope=user_info%2Cuser_video_info&" +
-                "redirect_uri=http%3A%2F%2Fimport.smcic.net%2Fkuaishou%2Fcallback&state=" + state);
+                "redirect_uri=http%3A%2F%2Fopen.sxtvs.net%2Fkuaishou%2Fcallback&state=" + state);
 
     }
 
@@ -83,7 +83,7 @@ public class OauthRestController {
         return new RedirectDto("https://open.snssdk.com/oauth/authorize/?" +
                 "client_key=awfrca76s1petwh0&response_type=code&" +
                 "scope=toutiao.video.data,user_info&" +
-                "redirect_uri=https%3A%2F%2Fimport.smcic.net%2Ftoutiao%2Fcallback-open&state=" + state);
+                "redirect_uri=https%3A%2F%2Fopen.sxtvs.net%2Ftoutiao%2Fcallback-open&state=" + state);
     }
 
     @RequestMapping("weibo/code")
@@ -106,7 +106,7 @@ public class OauthRestController {
         var token = HttpContextUtil.mustToken();
         logger.info("key", "oauth/bilibili/code", "state", state, "token", token);
         return new RedirectDto("https://passport.bilibili.com/register/pc_oauth2.html#/?client_id=e79e6fdef9d446d7" +
-                "&return_url=https%3A%2F%2Fimport.smcic.net%2Fbilibili%2Fcallback-open&response_type=code&state=" + state);
+                "&return_url=https%3A%2F%2Fopen.sxtvs.net%2Fbilibili%2Fcallback-open&response_type=code&state=" + state);
     }
 
     @RequestMapping("weixin/code")

+ 7 - 0
src/main/java/com/sxtvs/open/api/odata/dao/BilibiliAccountMapper.java

@@ -0,0 +1,7 @@
+package com.sxtvs.open.api.odata.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sxtvs.open.api.odata.entity.BilibiliAccount;
+
+public interface BilibiliAccountMapper extends BaseMapper<BilibiliAccount> {
+}

+ 7 - 0
src/main/java/com/sxtvs/open/api/odata/dao/DouyinAccountMapper.java

@@ -0,0 +1,7 @@
+package com.sxtvs.open.api.odata.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sxtvs.open.api.odata.entity.DouyinAccount;
+
+public interface DouyinAccountMapper extends BaseMapper<DouyinAccount> {
+}

+ 7 - 0
src/main/java/com/sxtvs/open/api/odata/dao/KuaishouAccountMapper.java

@@ -0,0 +1,7 @@
+package com.sxtvs.open.api.odata.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sxtvs.open.api.odata.entity.KuaishouAccount;
+
+public interface KuaishouAccountMapper extends BaseMapper<KuaishouAccount> {
+}

+ 7 - 0
src/main/java/com/sxtvs/open/api/odata/dao/PlatformDataMapper.java

@@ -0,0 +1,7 @@
+package com.sxtvs.open.api.odata.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sxtvs.open.api.odata.entity.PlatformData;
+
+public interface PlatformDataMapper extends BaseMapper<PlatformData> {
+}

+ 7 - 0
src/main/java/com/sxtvs/open/api/odata/dao/PlatformMapper.java

@@ -0,0 +1,7 @@
+package com.sxtvs.open.api.odata.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sxtvs.open.api.odata.entity.Platform;
+
+public interface PlatformMapper extends BaseMapper<Platform> {
+}

+ 16 - 0
src/main/java/com/sxtvs/open/api/odata/dao/QrcodeLogMapper.java

@@ -0,0 +1,16 @@
+package com.sxtvs.open.api.odata.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sxtvs.open.api.odata.entity.QrcodeLog;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author zyx
+ * @since 2021-12-28
+ */
+public interface QrcodeLogMapper extends BaseMapper<QrcodeLog> {
+
+}

+ 7 - 0
src/main/java/com/sxtvs/open/api/odata/dao/ToutiaoAccountMapper.java

@@ -0,0 +1,7 @@
+package com.sxtvs.open.api.odata.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sxtvs.open.api.odata.entity.ToutiaoAccount;
+
+public interface ToutiaoAccountMapper extends BaseMapper<ToutiaoAccount> {
+}

+ 7 - 0
src/main/java/com/sxtvs/open/api/odata/dao/WeiboAccountMapper.java

@@ -0,0 +1,7 @@
+package com.sxtvs.open.api.odata.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sxtvs.open.api.odata.entity.WeiboAccount;
+
+public interface WeiboAccountMapper extends BaseMapper<WeiboAccount> {
+}

+ 7 - 0
src/main/java/com/sxtvs/open/api/odata/dao/WeiboTaskMapper.java

@@ -0,0 +1,7 @@
+package com.sxtvs.open.api.odata.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sxtvs.open.api.odata.entity.WeiboTask;
+
+public interface WeiboTaskMapper extends BaseMapper<WeiboTask> {
+}

+ 7 - 0
src/main/java/com/sxtvs/open/api/odata/dao/WxAccountMapper.java

@@ -0,0 +1,7 @@
+package com.sxtvs.open.api.odata.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sxtvs.open.api.odata.entity.WxAccount;
+
+public interface WxAccountMapper extends BaseMapper<WxAccount> {
+}

+ 7 - 0
src/main/java/com/sxtvs/open/api/odata/dao/WxAccountV2Mapper.java

@@ -0,0 +1,7 @@
+package com.sxtvs.open.api.odata.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sxtvs.open.api.odata.entity.WxAccountV2;
+
+public interface WxAccountV2Mapper extends BaseMapper<WxAccountV2> {
+}

+ 7 - 0
src/main/java/com/sxtvs/open/api/odata/dao/WxTicketMapper.java

@@ -0,0 +1,7 @@
+package com.sxtvs.open.api.odata.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sxtvs.open.api.odata.entity.WxTicket;
+
+public interface WxTicketMapper extends BaseMapper<WxTicket> {
+}

+ 7 - 0
src/main/java/com/sxtvs/open/api/odata/dao/YoumeiAccountMapper.java

@@ -0,0 +1,7 @@
+package com.sxtvs.open.api.odata.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sxtvs.open.api.odata.entity.YoumeiAccount;
+
+public interface YoumeiAccountMapper extends BaseMapper<YoumeiAccount> {
+}

+ 18 - 0
src/main/java/com/sxtvs/open/api/odata/dto/ImportFile.java

@@ -0,0 +1,18 @@
+package com.sxtvs.open.api.odata.dto;
+
+import lombok.Data;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.InputStream;
+
+@Data
+public class ImportFile {
+
+    private MultipartFile file;
+
+    private String userName;
+
+    private String platform;
+
+    private InputStream input;
+}

+ 8 - 0
src/main/java/com/sxtvs/open/api/odata/dto/PlatformDTO.java

@@ -0,0 +1,8 @@
+package com.sxtvs.open.api.odata.dto;
+
+import lombok.Data;
+
+@Data
+public class PlatformDTO {
+    private String name;
+}

+ 31 - 0
src/main/java/com/sxtvs/open/api/odata/dto/bilibili/BilibiliAccessToken.java

@@ -0,0 +1,31 @@
+package com.sxtvs.open.api.odata.dto.bilibili;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@Data
+public class BilibiliAccessToken {
+
+
+    @JsonProperty("code")
+    private Integer code;
+    @JsonProperty("message")
+    private String message;
+    @JsonProperty("ttl")
+    private Integer ttl;
+    @JsonProperty("data")
+    private DataDTO data;
+
+    @NoArgsConstructor
+    @Data
+    public static class DataDTO {
+        @JsonProperty("access_token")
+        private String accessToken;
+        @JsonProperty("expires_in")
+        private Long expiresIn;
+        @JsonProperty("refresh_token")
+        private String refreshToken;
+    }
+}

+ 31 - 0
src/main/java/com/sxtvs/open/api/odata/dto/bilibili/BilibiliAccountInfo.java

@@ -0,0 +1,31 @@
+package com.sxtvs.open.api.odata.dto.bilibili;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@Data
+public class BilibiliAccountInfo {
+
+
+    @JsonProperty("code")
+    private Integer code;
+    @JsonProperty("message")
+    private String message;
+    @JsonProperty("ttl")
+    private Integer ttl;
+    @JsonProperty("data")
+    private DataDTO data;
+
+    @NoArgsConstructor
+    @Data
+    public static class DataDTO {
+        @JsonProperty("name")
+        private String name;
+        @JsonProperty("face")
+        private String face;
+        @JsonProperty("openid")
+        private String openid;
+    }
+}

+ 31 - 0
src/main/java/com/sxtvs/open/api/odata/dto/bilibili/BilibiliRefreshToken.java

@@ -0,0 +1,31 @@
+package com.sxtvs.open.api.odata.dto.bilibili;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@Data
+public class BilibiliRefreshToken {
+
+
+    @JsonProperty("code")
+    private Integer code;
+    @JsonProperty("message")
+    private String message;
+    @JsonProperty("ttl")
+    private Integer ttl;
+    @JsonProperty("data")
+    private DataDTO data;
+
+    @NoArgsConstructor
+    @Data
+    public static class DataDTO {
+        @JsonProperty("refresh_token")
+        private String refreshToken;
+        @JsonProperty("access_token")
+        private String accessToken;
+        @JsonProperty("expires_in")
+        private Long expiresIn;
+    }
+}

+ 24 - 0
src/main/java/com/sxtvs/open/api/odata/dto/douyin/DouyinAccessTokenResponse.java

@@ -0,0 +1,24 @@
+package com.sxtvs.open.api.odata.dto.douyin;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class DouyinAccessTokenResponse {
+
+    private Data data;
+
+    @lombok.Data
+    public static class Data {
+        @JsonProperty("open_id")
+        private String openId;
+
+        @JsonProperty("access_token")
+        private String accessToken;
+
+        @JsonProperty("refresh_token")
+        private String refreshToken;
+    }
+
+
+}

+ 28 - 0
src/main/java/com/sxtvs/open/api/odata/dto/douyin/DouyinCommonResponse.java

@@ -0,0 +1,28 @@
+package com.sxtvs.open.api.odata.dto.douyin;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class DouyinCommonResponse {
+
+    private Data data;
+
+    @lombok.Data
+    public static class Data {
+        @JsonProperty("open_id")
+        private String description;
+
+        @JsonProperty("error_code")
+        private Integer errorCode;
+    }
+
+    public boolean hasError() {
+        if (data == null) {
+            return true;
+        }
+        return 0 != data.errorCode;
+    }
+
+
+}

+ 18 - 0
src/main/java/com/sxtvs/open/api/odata/dto/douyin/DouyinRefreshTokenResponse.java

@@ -0,0 +1,18 @@
+package com.sxtvs.open.api.odata.dto.douyin;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class DouyinRefreshTokenResponse {
+
+    private Data data;
+
+    @lombok.Data
+    public static class Data {
+        @JsonProperty("refresh_token")
+        private String refreshToken;
+    }
+
+
+}

+ 22 - 0
src/main/java/com/sxtvs/open/api/odata/dto/douyin/DouyinUserInfoResponse.java

@@ -0,0 +1,22 @@
+package com.sxtvs.open.api.odata.dto.douyin;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class DouyinUserInfoResponse {
+
+    private Data data;
+
+    @lombok.Data
+    public static class Data {
+        @JsonProperty("avatar_larger")
+        private String avatarLarger;
+
+        @JsonProperty("nickname")
+        private String nickname;
+
+    }
+
+
+}

+ 24 - 0
src/main/java/com/sxtvs/open/api/odata/dto/douyin/videolist/Data.java

@@ -0,0 +1,24 @@
+package com.sxtvs.open.api.odata.dto.douyin.videolist;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+
+@lombok.Data
+public class Data {
+
+    @JsonProperty("cursor")
+    private Long cursor;
+
+    @JsonProperty("description")
+    private String description;
+
+    @JsonProperty("error_code")
+    private Integer errorCode;
+
+    @JsonProperty("has_more")
+    private Boolean hasMore;
+
+    @JsonProperty("list")
+    private List<ListItem> list;
+}

+ 13 - 0
src/main/java/com/sxtvs/open/api/odata/dto/douyin/videolist/DouyinVideoListResponse.java

@@ -0,0 +1,13 @@
+package com.sxtvs.open.api.odata.dto.douyin.videolist;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@lombok.Data
+public class DouyinVideoListResponse {
+
+    @JsonProperty("data")
+    private Data data;
+
+    @JsonProperty("extra")
+    private Extra extra;
+}

+ 25 - 0
src/main/java/com/sxtvs/open/api/odata/dto/douyin/videolist/Extra.java

@@ -0,0 +1,25 @@
+package com.sxtvs.open.api.odata.dto.douyin.videolist;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@lombok.Data
+public class Extra {
+
+    @JsonProperty("sub_error_code")
+    private Integer subErrorCode;
+
+    @JsonProperty("sub_description")
+    private String subDescription;
+
+    @JsonProperty("now")
+    private Long now;
+
+    @JsonProperty("description")
+    private String description;
+
+    @JsonProperty("logid")
+    private String logid;
+
+    @JsonProperty("error_code")
+    private Integer errorCode;
+}

+ 34 - 0
src/main/java/com/sxtvs/open/api/odata/dto/douyin/videolist/ListItem.java

@@ -0,0 +1,34 @@
+package com.sxtvs.open.api.odata.dto.douyin.videolist;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@lombok.Data
+public class ListItem {
+
+    @JsonProperty("cover")
+    private String cover;
+
+    @JsonProperty("is_reviewed")
+    private Boolean isReviewed;
+
+    @JsonProperty("create_time")
+    private Long createTime;
+
+    @JsonProperty("item_id")
+    private String itemId;
+
+    @JsonProperty("share_url")
+    private String shareUrl;
+
+    @JsonProperty("video_status")
+    private Integer videoStatus;
+
+    @JsonProperty("title")
+    private String title;
+
+    @JsonProperty("is_top")
+    private Boolean isTop;
+
+    @JsonProperty("statistics")
+    private Statistics statistics;
+}

+ 25 - 0
src/main/java/com/sxtvs/open/api/odata/dto/douyin/videolist/Statistics.java

@@ -0,0 +1,25 @@
+package com.sxtvs.open.api.odata.dto.douyin.videolist;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@lombok.Data
+public class Statistics {
+
+    @JsonProperty("share_count")
+    private Integer shareCount;
+
+    @JsonProperty("comment_count")
+    private Integer commentCount;
+
+    @JsonProperty("digg_count")
+    private Integer diggCount;
+
+    @JsonProperty("forward_count")
+    private Integer forwardCount;
+
+    @JsonProperty("play_count")
+    private Integer playCount;
+
+    @JsonProperty("download_count")
+    private Integer downloadCount;
+}

+ 30 - 0
src/main/java/com/sxtvs/open/api/odata/dto/kuaishou/KuaiShouVideoResponse.java

@@ -0,0 +1,30 @@
+package com.sxtvs.open.api.odata.dto.kuaishou;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class KuaiShouVideoResponse {
+    @JsonProperty("video_list")
+    private List<VideoList> videoList;
+
+    @Data
+    public static class VideoList {
+        @JsonProperty("photo_id")
+        private String photoId;
+        private String caption;
+        private String cover;
+        @JsonProperty("play_url")
+        private String playUrl;
+        @JsonProperty("create_time")
+        private Long createTime;
+        @JsonProperty("like_count")
+        private Integer likeCount;
+        @JsonProperty("comment_count")
+        private Integer commentCount;
+        @JsonProperty("view_count")
+        private Integer viewCount;
+    }
+}

+ 22 - 0
src/main/java/com/sxtvs/open/api/odata/dto/kuaishou/KuaishouAccessTokenResponse.java

@@ -0,0 +1,22 @@
+package com.sxtvs.open.api.odata.dto.kuaishou;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class KuaishouAccessTokenResponse {
+
+    @JsonProperty("open_id")
+    private String openId;
+    @JsonProperty("access_token")
+    private String accessToken;
+    @JsonProperty("refresh_token")
+    private String refreshToken;
+    @JsonProperty("refresh_token_expires_in")
+    private Integer refreshTokenExpiresIn;
+    @JsonProperty("expires_in")
+    private Integer expiresIn;
+
+    private Integer result;
+
+}

+ 18 - 0
src/main/java/com/sxtvs/open/api/odata/dto/kuaishou/KuaishouCommonResponse.java

@@ -0,0 +1,18 @@
+package com.sxtvs.open.api.odata.dto.kuaishou;
+
+import lombok.Data;
+
+@Data
+public class KuaishouCommonResponse {
+
+    private Integer result;
+
+    public boolean hasError() {
+        if (result == null) {
+            return false;
+        }
+        return 1 != result;
+    }
+
+
+}

+ 18 - 0
src/main/java/com/sxtvs/open/api/odata/dto/kuaishou/KuaishouUserInfoResponse.java

@@ -0,0 +1,18 @@
+package com.sxtvs.open.api.odata.dto.kuaishou;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class KuaishouUserInfoResponse {
+
+    @JsonProperty("user_info")
+    private UserInfo userInfo;
+
+    @Data
+    public static class UserInfo {
+        private String name;
+    }
+
+
+}

+ 14 - 0
src/main/java/com/sxtvs/open/api/odata/dto/weibo/WeiboAccessTokenResponse.java

@@ -0,0 +1,14 @@
+package com.sxtvs.open.api.odata.dto.weibo;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class WeiboAccessTokenResponse {
+    @JsonProperty("access_token")
+    private String accessToken;
+    @JsonProperty("expires_in")
+    private Integer expiresIn;
+    @JsonProperty("uid")
+    private String uid;
+}

+ 19 - 0
src/main/java/com/sxtvs/open/api/odata/dto/weibo/WeiboCreateTask.java

@@ -0,0 +1,19 @@
+package com.sxtvs.open.api.odata.dto.weibo;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class WeiboCreateTask {
+    private Long id;
+    @JsonProperty("task_id")
+    private Long taskId;
+    @JsonProperty("secret_key")
+    private String secretKey;
+    @JsonProperty("error_code")
+    private int errorCode;
+
+    public boolean hasError(){
+        return errorCode != 0;
+    }
+}

+ 13 - 0
src/main/java/com/sxtvs/open/api/odata/dto/weibo/show/AnnotationsItem.java

@@ -0,0 +1,13 @@
+package com.sxtvs.open.api.odata.dto.weibo.show;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class AnnotationsItem{
+
+	@JsonProperty("mapi_request")
+	private boolean mapiRequest;
+
+	public boolean isMapiRequest(){
+		return mapiRequest;
+	}
+}

+ 20 - 0
src/main/java/com/sxtvs/open/api/odata/dto/weibo/show/CommentManageInfo.java

@@ -0,0 +1,20 @@
+package com.sxtvs.open.api.odata.dto.weibo.show;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class CommentManageInfo{
+
+	@JsonProperty("comment_permission_type")
+	private int commentPermissionType;
+
+	@JsonProperty("approval_comment_type")
+	private int approvalCommentType;
+
+	public int getCommentPermissionType(){
+		return commentPermissionType;
+	}
+
+	public int getApprovalCommentType(){
+		return approvalCommentType;
+	}
+}

+ 13 - 0
src/main/java/com/sxtvs/open/api/odata/dto/weibo/show/Insecurity.java

@@ -0,0 +1,13 @@
+package com.sxtvs.open.api.odata.dto.weibo.show;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Insecurity{
+
+	@JsonProperty("sexual_content")
+	private boolean sexualContent;
+
+	public boolean isSexualContent(){
+		return sexualContent;
+	}
+}

+ 351 - 0
src/main/java/com/sxtvs/open/api/odata/dto/weibo/show/Status.java

@@ -0,0 +1,351 @@
+package com.sxtvs.open.api.odata.dto.weibo.show;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+
+public class Status{
+
+	@JsonProperty("fid")
+	private long fid;
+
+	@JsonProperty("isLongText")
+	private boolean isLongText;
+
+	@JsonProperty("hot_weibo_tags")
+	private List<Object> hotWeiboTags;
+
+	@JsonProperty("in_reply_to_status_id")
+	private String inReplyToStatusId;
+
+	@JsonProperty("annotations")
+	private List<AnnotationsItem> annotations;
+
+	@JsonProperty("mblogtype")
+	private int mblogtype;
+
+	@JsonProperty("source")
+	private String source;
+
+	@JsonProperty("attitudes_count")
+	private int attitudesCount;
+
+	@JsonProperty("rid")
+	private String rid;
+
+	@JsonProperty("positive_recom_flag")
+	private int positiveRecomFlag;
+
+	@JsonProperty("is_show_bulletin")
+	private int isShowBulletin;
+
+	@JsonProperty("hide_flag")
+	private int hideFlag;
+
+	@JsonProperty("mlevel")
+	private int mlevel;
+
+	@JsonProperty("in_reply_to_user_id")
+	private String inReplyToUserId;
+
+	@JsonProperty("hasActionTypeCard")
+	private int hasActionTypeCard;
+
+	@JsonProperty("id")
+	private long id;
+
+	@JsonProperty("text")
+	private String text;
+
+	@JsonProperty("mblog_vip_type")
+	private int mblogVipType;
+
+	@JsonProperty("content_auth")
+	private int contentAuth;
+
+	@JsonProperty("visible")
+	private Visible visible;
+
+	@JsonProperty("gif_ids")
+	private String gifIds;
+
+	@JsonProperty("source_type")
+	private int sourceType;
+
+	@JsonProperty("pic_urls")
+	private List<Object> picUrls;
+
+	@JsonProperty("version")
+	private int version;
+
+	@JsonProperty("biz_feature")
+	private long bizFeature;
+
+	@JsonProperty("comments_count")
+	private int commentsCount;
+
+	@JsonProperty("userType")
+	private int userType;
+
+	@JsonProperty("biz_ids")
+	private List<Integer> bizIds;
+
+	@JsonProperty("idstr")
+	private String idstr;
+
+	@JsonProperty("text_tag_tips")
+	private List<Object> textTagTips;
+
+	@JsonProperty("page_type")
+	private int pageType;
+
+	@JsonProperty("created_at")
+	private String createdAt;
+
+	@JsonProperty("mid")
+	private String mid;
+
+	@JsonProperty("geo")
+	private Object geo;
+
+	@JsonProperty("darwin_tags")
+	private List<Object> darwinTags;
+
+	@JsonProperty("pending_approval_count")
+	private int pendingApprovalCount;
+
+	@JsonProperty("in_reply_to_screen_name")
+	private String inReplyToScreenName;
+
+	@JsonProperty("pic_num")
+	private int picNum;
+
+	@JsonProperty("is_paid")
+	private boolean isPaid;
+
+	@JsonProperty("reposts_count")
+	private int repostsCount;
+
+	@JsonProperty("reward_exhibition_type")
+	private int rewardExhibitionType;
+
+	@JsonProperty("favorited")
+	private boolean favorited;
+
+	@JsonProperty("can_edit")
+	private boolean canEdit;
+
+	@JsonProperty("textLength")
+	private int textLength;
+
+	@JsonProperty("truncated")
+	private boolean truncated;
+
+	@JsonProperty("source_allowclick")
+	private int sourceAllowclick;
+
+	@JsonProperty("show_additional_indication")
+	private int showAdditionalIndication;
+
+	@JsonProperty("comment_manage_info")
+	private CommentManageInfo commentManageInfo;
+
+	@JsonProperty("more_info_type")
+	private int moreInfoType;
+
+	public long getFid(){
+		return fid;
+	}
+
+	public boolean isIsLongText(){
+		return isLongText;
+	}
+
+	public List<Object> getHotWeiboTags(){
+		return hotWeiboTags;
+	}
+
+	public String getInReplyToStatusId(){
+		return inReplyToStatusId;
+	}
+
+	public List<AnnotationsItem> getAnnotations(){
+		return annotations;
+	}
+
+	public int getMblogtype(){
+		return mblogtype;
+	}
+
+	public String getSource(){
+		return source;
+	}
+
+	public int getAttitudesCount(){
+		return attitudesCount;
+	}
+
+	public String getRid(){
+		return rid;
+	}
+
+	public int getPositiveRecomFlag(){
+		return positiveRecomFlag;
+	}
+
+	public int getIsShowBulletin(){
+		return isShowBulletin;
+	}
+
+	public int getHideFlag(){
+		return hideFlag;
+	}
+
+	public int getMlevel(){
+		return mlevel;
+	}
+
+	public String getInReplyToUserId(){
+		return inReplyToUserId;
+	}
+
+	public int getHasActionTypeCard(){
+		return hasActionTypeCard;
+	}
+
+	public long getId(){
+		return id;
+	}
+
+	public String getText(){
+		return text;
+	}
+
+	public int getMblogVipType(){
+		return mblogVipType;
+	}
+
+	public int getContentAuth(){
+		return contentAuth;
+	}
+
+	public Visible getVisible(){
+		return visible;
+	}
+
+	public String getGifIds(){
+		return gifIds;
+	}
+
+	public int getSourceType(){
+		return sourceType;
+	}
+
+	public List<Object> getPicUrls(){
+		return picUrls;
+	}
+
+	public int getVersion(){
+		return version;
+	}
+
+	public long getBizFeature(){
+		return bizFeature;
+	}
+
+	public int getCommentsCount(){
+		return commentsCount;
+	}
+
+	public int getUserType(){
+		return userType;
+	}
+
+	public List<Integer> getBizIds(){
+		return bizIds;
+	}
+
+	public String getIdstr(){
+		return idstr;
+	}
+
+	public List<Object> getTextTagTips(){
+		return textTagTips;
+	}
+
+	public int getPageType(){
+		return pageType;
+	}
+
+	public String getCreatedAt(){
+		return createdAt;
+	}
+
+	public String getMid(){
+		return mid;
+	}
+
+	public Object getGeo(){
+		return geo;
+	}
+
+	public List<Object> getDarwinTags(){
+		return darwinTags;
+	}
+
+	public int getPendingApprovalCount(){
+		return pendingApprovalCount;
+	}
+
+	public String getInReplyToScreenName(){
+		return inReplyToScreenName;
+	}
+
+	public int getPicNum(){
+		return picNum;
+	}
+
+	public boolean isIsPaid(){
+		return isPaid;
+	}
+
+	public int getRepostsCount(){
+		return repostsCount;
+	}
+
+	public int getRewardExhibitionType(){
+		return rewardExhibitionType;
+	}
+
+	public boolean isFavorited(){
+		return favorited;
+	}
+
+	public boolean isCanEdit(){
+		return canEdit;
+	}
+
+	public int getTextLength(){
+		return textLength;
+	}
+
+	public boolean isTruncated(){
+		return truncated;
+	}
+
+	public int getSourceAllowclick(){
+		return sourceAllowclick;
+	}
+
+	public int getShowAdditionalIndication(){
+		return showAdditionalIndication;
+	}
+
+	public CommentManageInfo getCommentManageInfo(){
+		return commentManageInfo;
+	}
+
+	public int getMoreInfoType(){
+		return moreInfoType;
+	}
+}

+ 470 - 0
src/main/java/com/sxtvs/open/api/odata/dto/weibo/show/UserShowResponse.java

@@ -0,0 +1,470 @@
+package com.sxtvs.open.api.odata.dto.weibo.show;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class UserShowResponse{
+
+	@JsonProperty("is_teenager")
+	private int isTeenager;
+
+	@JsonProperty("allow_all_act_msg")
+	private boolean allowAllActMsg;
+
+	@JsonProperty("favourites_count")
+	private int favouritesCount;
+
+	@JsonProperty("urank")
+	private int urank;
+
+	@JsonProperty("verified_trade")
+	private String verifiedTrade;
+
+	@JsonProperty("weihao")
+	private String weihao;
+
+	@JsonProperty("verified_source_url")
+	private String verifiedSourceUrl;
+
+	@JsonProperty("province")
+	private String province;
+
+	@JsonProperty("screen_name")
+	private String screenName;
+
+	@JsonProperty("id")
+	private long id;
+
+	@JsonProperty("geo_enabled")
+	private boolean geoEnabled;
+
+	@JsonProperty("video_mark")
+	private int videoMark;
+
+	@JsonProperty("live_status")
+	private int liveStatus;
+
+	@JsonProperty("like_me")
+	private boolean likeMe;
+
+	@JsonProperty("special_follow")
+	private boolean specialFollow;
+
+	@JsonProperty("like")
+	private boolean like;
+
+	@JsonProperty("verified_type")
+	private int verifiedType;
+
+	@JsonProperty("pagefriends_count")
+	private int pagefriendsCount;
+
+	@JsonProperty("domain")
+	private String domain;
+
+	@JsonProperty("following")
+	private boolean following;
+
+	@JsonProperty("name")
+	private String name;
+
+	@JsonProperty("status")
+	private Status status;
+
+	@JsonProperty("idstr")
+	private String idstr;
+
+	@JsonProperty("follow_me")
+	private boolean followMe;
+
+	@JsonProperty("friends_count")
+	private int friendsCount;
+
+	@JsonProperty("credit_score")
+	private int creditScore;
+
+	@JsonProperty("user_ability_extend")
+	private int userAbilityExtend;
+
+	@JsonProperty("gender")
+	private String gender;
+
+	@JsonProperty("city")
+	private String city;
+
+	@JsonProperty("profile_url")
+	private String profileUrl;
+
+	@JsonProperty("description")
+	private String description;
+
+	@JsonProperty("created_at")
+	private String createdAt;
+
+	@JsonProperty("remark")
+	private String remark;
+
+	@JsonProperty("ptype")
+	private int ptype;
+
+	@JsonProperty("verified_reason_url")
+	private String verifiedReasonUrl;
+
+	@JsonProperty("block_word")
+	private int blockWord;
+
+	@JsonProperty("avatar_hd")
+	private String avatarHd;
+
+	@JsonProperty("video_play_count")
+	private int videoPlayCount;
+
+	@JsonProperty("mbtype")
+	private int mbtype;
+
+	@JsonProperty("bi_followers_count")
+	private int biFollowersCount;
+
+	@JsonProperty("user_ability")
+	private int userAbility;
+
+	@JsonProperty("is_teenager_list")
+	private int isTeenagerList;
+
+	@JsonProperty("verified_reason")
+	private String verifiedReason;
+
+	@JsonProperty("story_read_state")
+	private int storyReadState;
+
+	@JsonProperty("video_status_count")
+	private int videoStatusCount;
+
+	@JsonProperty("mbrank")
+	private int mbrank;
+
+	@JsonProperty("lang")
+	private String lang;
+
+	@JsonProperty("class")
+	private int jsonMemberClass;
+
+	@JsonProperty("star")
+	private int star;
+
+	@JsonProperty("allow_all_comment")
+	private boolean allowAllComment;
+
+	@JsonProperty("online_status")
+	private int onlineStatus;
+
+	@JsonProperty("verified")
+	private boolean verified;
+
+	@JsonProperty("profile_image_url")
+	private String profileImageUrl;
+
+	@JsonProperty("block_app")
+	private int blockApp;
+
+	@JsonProperty("pc_new")
+	private int pcNew;
+
+	@JsonProperty("url")
+	private String url;
+
+	@JsonProperty("avatar_large")
+	private String avatarLarge;
+
+	@JsonProperty("planet_video")
+	private int planetVideo;
+
+	@JsonProperty("statuses_count")
+	private int statusesCount;
+
+	@JsonProperty("vclub_member")
+	private int vclubMember;
+
+	@JsonProperty("followers_count")
+	private int followersCount;
+
+	@JsonProperty("is_guardian")
+	private int isGuardian;
+
+	@JsonProperty("location")
+	private String location;
+
+	@JsonProperty("insecurity")
+	private Insecurity insecurity;
+
+	@JsonProperty("svip")
+	private int svip;
+
+	@JsonProperty("verified_source")
+	private String verifiedSource;
+
+	public int getIsTeenager(){
+		return isTeenager;
+	}
+
+	public boolean isAllowAllActMsg(){
+		return allowAllActMsg;
+	}
+
+	public int getFavouritesCount(){
+		return favouritesCount;
+	}
+
+	public int getUrank(){
+		return urank;
+	}
+
+	public String getVerifiedTrade(){
+		return verifiedTrade;
+	}
+
+	public String getWeihao(){
+		return weihao;
+	}
+
+	public String getVerifiedSourceUrl(){
+		return verifiedSourceUrl;
+	}
+
+	public String getProvince(){
+		return province;
+	}
+
+	public String getScreenName(){
+		return screenName;
+	}
+
+	public long getId(){
+		return id;
+	}
+
+	public boolean isGeoEnabled(){
+		return geoEnabled;
+	}
+
+	public int getVideoMark(){
+		return videoMark;
+	}
+
+	public int getLiveStatus(){
+		return liveStatus;
+	}
+
+	public boolean isLikeMe(){
+		return likeMe;
+	}
+
+	public boolean isSpecialFollow(){
+		return specialFollow;
+	}
+
+	public boolean isLike(){
+		return like;
+	}
+
+	public int getVerifiedType(){
+		return verifiedType;
+	}
+
+	public int getPagefriendsCount(){
+		return pagefriendsCount;
+	}
+
+	public String getDomain(){
+		return domain;
+	}
+
+	public boolean isFollowing(){
+		return following;
+	}
+
+	public String getName(){
+		return name;
+	}
+
+	public Status getStatus(){
+		return status;
+	}
+
+	public String getIdstr(){
+		return idstr;
+	}
+
+	public boolean isFollowMe(){
+		return followMe;
+	}
+
+	public int getFriendsCount(){
+		return friendsCount;
+	}
+
+	public int getCreditScore(){
+		return creditScore;
+	}
+
+	public int getUserAbilityExtend(){
+		return userAbilityExtend;
+	}
+
+	public String getGender(){
+		return gender;
+	}
+
+	public String getCity(){
+		return city;
+	}
+
+	public String getProfileUrl(){
+		return profileUrl;
+	}
+
+	public String getDescription(){
+		return description;
+	}
+
+	public String getCreatedAt(){
+		return createdAt;
+	}
+
+	public String getRemark(){
+		return remark;
+	}
+
+	public int getPtype(){
+		return ptype;
+	}
+
+	public String getVerifiedReasonUrl(){
+		return verifiedReasonUrl;
+	}
+
+	public int getBlockWord(){
+		return blockWord;
+	}
+
+	public String getAvatarHd(){
+		return avatarHd;
+	}
+
+	public int getVideoPlayCount(){
+		return videoPlayCount;
+	}
+
+	public int getMbtype(){
+		return mbtype;
+	}
+
+	public int getBiFollowersCount(){
+		return biFollowersCount;
+	}
+
+	public int getUserAbility(){
+		return userAbility;
+	}
+
+	public int getIsTeenagerList(){
+		return isTeenagerList;
+	}
+
+	public String getVerifiedReason(){
+		return verifiedReason;
+	}
+
+	public int getStoryReadState(){
+		return storyReadState;
+	}
+
+	public int getVideoStatusCount(){
+		return videoStatusCount;
+	}
+
+	public int getMbrank(){
+		return mbrank;
+	}
+
+	public String getLang(){
+		return lang;
+	}
+
+	public int getJsonMemberClass(){
+		return jsonMemberClass;
+	}
+
+	public int getStar(){
+		return star;
+	}
+
+	public boolean isAllowAllComment(){
+		return allowAllComment;
+	}
+
+	public int getOnlineStatus(){
+		return onlineStatus;
+	}
+
+	public boolean isVerified(){
+		return verified;
+	}
+
+	public String getProfileImageUrl(){
+		return profileImageUrl;
+	}
+
+	public int getBlockApp(){
+		return blockApp;
+	}
+
+	public int getPcNew(){
+		return pcNew;
+	}
+
+	public String getUrl(){
+		return url;
+	}
+
+	public String getAvatarLarge(){
+		return avatarLarge;
+	}
+
+	public int getPlanetVideo(){
+		return planetVideo;
+	}
+
+	public int getStatusesCount(){
+		return statusesCount;
+	}
+
+	public int getVclubMember(){
+		return vclubMember;
+	}
+
+	public int getFollowersCount(){
+		return followersCount;
+	}
+
+	public int getIsGuardian(){
+		return isGuardian;
+	}
+
+	public String getLocation(){
+		return location;
+	}
+
+	public Insecurity getInsecurity(){
+		return insecurity;
+	}
+
+	public int getSvip(){
+		return svip;
+	}
+
+	public String getVerifiedSource(){
+		return verifiedSource;
+	}
+}

+ 20 - 0
src/main/java/com/sxtvs/open/api/odata/dto/weibo/show/Visible.java

@@ -0,0 +1,20 @@
+package com.sxtvs.open.api.odata.dto.weibo.show;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Visible{
+
+	@JsonProperty("list_id")
+	private int listId;
+
+	@JsonProperty("type")
+	private int type;
+
+	public int getListId(){
+		return listId;
+	}
+
+	public int getType(){
+		return type;
+	}
+}

+ 27 - 0
src/main/java/com/sxtvs/open/api/odata/entity/BilibiliAccount.java

@@ -0,0 +1,27 @@
+package com.sxtvs.open.api.odata.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BilibiliAccount {
+
+    @TableId(type = IdType.INPUT)
+    private String openId;
+    private String accessToken;
+    private String refreshToken;
+    private Date atExpireTime;
+    private Date rtExpireTime;
+    private String nickName;
+    private Date createTime;
+    private Date updateTime;
+}

+ 27 - 0
src/main/java/com/sxtvs/open/api/odata/entity/DouyinAccount.java

@@ -0,0 +1,27 @@
+package com.sxtvs.open.api.odata.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class DouyinAccount {
+
+    @TableId(type = IdType.INPUT)
+    private String openId;
+    private String accessToken;
+    private String refreshToken;
+    private Date atExpireTime;
+    private Date rtExpireTime;
+    private String nickName;
+    private Date createTime;
+    private Date updateTime;
+}

+ 27 - 0
src/main/java/com/sxtvs/open/api/odata/entity/KuaishouAccount.java

@@ -0,0 +1,27 @@
+package com.sxtvs.open.api.odata.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class KuaishouAccount {
+
+    @TableId(type = IdType.INPUT)
+    private String openId;
+    private String accessToken;
+    private String refreshToken;
+    private Date atExpireTime;
+    private Date rtExpireTime;
+    private String nickName;
+    private Date createTime;
+    private Date updateTime;
+}

+ 15 - 0
src/main/java/com/sxtvs/open/api/odata/entity/Platform.java

@@ -0,0 +1,15 @@
+package com.sxtvs.open.api.odata.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+@Data
+public class Platform {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private String platform;
+
+    private String platformName;
+}

+ 27 - 0
src/main/java/com/sxtvs/open/api/odata/entity/PlatformData.java

@@ -0,0 +1,27 @@
+package com.sxtvs.open.api.odata.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class PlatformData {
+    // itemId + dt
+    @TableId(type = IdType.INPUT)
+    private String id;
+    private String itemId;
+    private String openId;
+    private String title;
+    private Integer shareCount;
+    private Integer commentCount;
+    private Integer diggCount;
+    private Integer forwardCount;
+    private Integer playCount;
+    private Integer downloadCount;
+    private String dt;
+    private String platform;
+    private Date publishTime;
+    private String nickName;
+}

+ 39 - 0
src/main/java/com/sxtvs/open/api/odata/entity/QrcodeLog.java

@@ -0,0 +1,39 @@
+package com.sxtvs.open.api.odata.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ *
+ * </p>
+ *
+ * @author zyx
+ * @since 2021-12-28
+ */
+@Getter
+@Setter
+@TableName("qrcode_log")
+public class QrcodeLog implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    private String platform;
+
+    private String nickName;
+
+    private LocalDateTime createTime;
+
+    private String openId;
+
+
+}

+ 27 - 0
src/main/java/com/sxtvs/open/api/odata/entity/ToutiaoAccount.java

@@ -0,0 +1,27 @@
+package com.sxtvs.open.api.odata.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ToutiaoAccount {
+
+    @TableId(type = IdType.INPUT)
+    private String openId;
+    private String accessToken;
+    private String refreshToken;
+    private Date atExpireTime;
+    private Date rtExpireTime;
+    private String nickName;
+    private Date createTime;
+    private Date updateTime;
+}

+ 25 - 0
src/main/java/com/sxtvs/open/api/odata/entity/WeiboAccount.java

@@ -0,0 +1,25 @@
+package com.sxtvs.open.api.odata.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WeiboAccount {
+
+    @TableId(type = IdType.INPUT)
+    private String openId;
+    private String accessToken;
+    private Date atExpireTime;
+    private String nickName;
+    private Date createTime;
+    private Date updateTime;
+}

+ 25 - 0
src/main/java/com/sxtvs/open/api/odata/entity/WeiboTask.java

@@ -0,0 +1,25 @@
+package com.sxtvs.open.api.odata.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WeiboTask {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String startDay;
+    private Long startTime;
+    private Long endTime;
+    private Long taskId;
+    private String secretKey;
+    private String weiboId;
+    private Integer finish;
+}

+ 26 - 0
src/main/java/com/sxtvs/open/api/odata/entity/WxAccount.java

@@ -0,0 +1,26 @@
+package com.sxtvs.open.api.odata.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WxAccount {
+    @TableId(type = IdType.INPUT)
+    private String openId;
+    private String accessToken;
+    private String refreshToken;
+    private Date atExpireTime;
+    private Date rtExpireTime;
+    private String nickName;
+    private Date createTime;
+    private Date updateTime;
+}

+ 29 - 0
src/main/java/com/sxtvs/open/api/odata/entity/WxAccountV2.java

@@ -0,0 +1,29 @@
+package com.sxtvs.open.api.odata.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WxAccountV2 {
+    @TableId(type = IdType.INPUT)
+    private String openId;
+    private String secret;
+    private String accessToken;
+    private String refreshToken;
+    private Date atExpireTime;
+    private Date rtExpireTime;
+    private String nickName;
+    private Date createTime;
+    private Date updateTime;
+    private String jsTicket;
+    private Date jsTicketExpireTime;
+}

+ 17 - 0
src/main/java/com/sxtvs/open/api/odata/entity/WxTicket.java

@@ -0,0 +1,17 @@
+package com.sxtvs.open.api.odata.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class WxTicket {
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+    private String ticket;
+    private String componentAccessToken;
+    private Date atExpireTime;
+    private Date updateTime;
+}

+ 28 - 0
src/main/java/com/sxtvs/open/api/odata/entity/YoumeiAccount.java

@@ -0,0 +1,28 @@
+package com.sxtvs.open.api.odata.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class YoumeiAccount {
+
+    @TableId(type = IdType.INPUT)
+    private String openId;
+    private String accessToken;
+    private String refreshToken;
+    private Date atExpireTime;
+    private Date rtExpireTime;
+    private String nickName;
+    private Date createTime;
+    private Date updateTime;
+    private String secret;
+}

+ 141 - 0
src/main/java/com/sxtvs/open/api/odata/service/BilibiliAccountService.java

@@ -0,0 +1,141 @@
+package com.sxtvs.open.api.odata.service;
+
+import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.http.HttpUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sxtvs.open.api.odata.dao.BilibiliAccountMapper;
+import com.sxtvs.open.api.odata.dto.bilibili.BilibiliAccessToken;
+import com.sxtvs.open.api.odata.dto.bilibili.BilibiliAccountInfo;
+import com.sxtvs.open.api.odata.dto.bilibili.BilibiliRefreshToken;
+import com.sxtvs.open.api.odata.entity.BilibiliAccount;
+import com.sxtvs.open.core.conf.Constant;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.HashMap;
+
+@Service
+@Slf4j
+public class BilibiliAccountService extends ServiceImpl<BilibiliAccountMapper, BilibiliAccount> {
+
+
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @Autowired
+    private QrcodeLogServiceImpl qrcodeLogService;
+
+
+    @SneakyThrows
+    private void renewAccessToken(BilibiliAccount bilibiliAccount) {
+        HashMap<String, Object> param = new HashMap<String, Object>() {{
+            this.put("client_id", Constant.bilibiliClientId);
+            this.put("client_secret", Constant.bilibiliSecret);
+            this.put("grant_type", "refresh_token");
+            this.put("refresh_token", bilibiliAccount.getRefreshToken());
+        }};
+        String body = HttpUtil.post("https://api.bilibili.com/x/account-oauth2/v1/refresh_token", param);
+        BilibiliRefreshToken bilibiliRefreshToken = objectMapper.readValue(body, BilibiliRefreshToken.class);
+        BilibiliRefreshToken.DataDTO data = bilibiliRefreshToken.getData();
+        bilibiliAccount.setRefreshToken(data.getRefreshToken());
+        bilibiliAccount.setAccessToken(data.getAccessToken());
+        bilibiliAccount.setAtExpireTime(new Date(data.getExpiresIn() * 1000));
+        bilibiliAccount.setRtExpireTime(new Date(data.getExpiresIn() * 1000));
+        bilibiliAccount.setUpdateTime(new Date());
+        this.updateById(bilibiliAccount);
+        log.info("renewAccessToken {}", bilibiliAccount);
+
+    }
+
+    @SneakyThrows
+    public BilibiliAccount upsert(String code) {
+        HashMap<String, Object> param = new HashMap<String, Object>() {{
+            this.put("client_id", Constant.bilibiliClientId);
+            this.put("client_secret", Constant.bilibiliSecret);
+            this.put("grant_type", "authorization_code");
+            this.put("code", code);
+        }};
+        String body = HttpUtil.post("https://api.bilibili.com/x/account-oauth2/v1/token", param);
+        log.info("bilibili token {}",body);
+        BilibiliAccessToken bilibiliAccessToken = objectMapper.readValue(body, BilibiliAccessToken.class);
+
+        BilibiliAccessToken.DataDTO data = bilibiliAccessToken.getData();
+        String accessToken = data.getAccessToken();
+        String refreshToken = data.getRefreshToken();
+        Long expiresIn = data.getExpiresIn();
+
+
+        param.clear();
+        param.put("client_id",Constant.bilibiliClientId);
+        param.put("access_token",accessToken);
+        body = HttpUtil.get("http://member.bilibili.com/arcopen/fn/user/account/info",param);
+        log.info("bilibili info {}",body);
+        BilibiliAccountInfo bilibiliAccountInfo = objectMapper.readValue(body, BilibiliAccountInfo.class);
+        BilibiliAccountInfo.DataDTO infoData = bilibiliAccountInfo.getData();
+        String openId = infoData.getOpenid();
+        String name = infoData.getName().trim();
+
+        qrcodeLogService.writeLog("B站",openId,name);
+
+        BilibiliAccount bilibiliAccount = this.getById(openId);
+        DateTime now = new DateTime();
+        if (bilibiliAccount == null) {
+            bilibiliAccount =  BilibiliAccount.builder()
+                        .openId(openId)
+                        .atExpireTime(new Date(expiresIn*1000))
+                        .rtExpireTime(new Date(expiresIn*1000))
+                        .accessToken(accessToken)
+                        .refreshToken(refreshToken)
+                        .nickName(name)
+                        .updateTime(now.toJdkDate())
+                        .createTime(now.toJdkDate())
+                        .build();
+            this.save(bilibiliAccount);
+            log.info("bilibili {} 新增成功", bilibiliAccount);
+        } else {
+                bilibiliAccount.setAtExpireTime(new Date(expiresIn*1000));
+                bilibiliAccount.setRtExpireTime(new Date(expiresIn*1000));
+                bilibiliAccount.setAccessToken(accessToken);
+                bilibiliAccount.setRefreshToken(refreshToken);
+                bilibiliAccount.setNickName(name);
+                bilibiliAccount.setUpdateTime(now.toJdkDate());
+                this.updateById(bilibiliAccount);
+
+            log.info("bilibili {} 更新成功", bilibiliAccount);
+        }
+
+//
+        return bilibiliAccount;
+
+    }
+
+
+    public void refresh() {
+        Date expireTime = new DateTime()
+                .offset(DateField.DAY_OF_YEAR, 2)
+                .toJdkDate();
+
+        //检测快过期的token
+        for (BilibiliAccount bilibiliAccount : this.lambdaQuery()
+                .le(BilibiliAccount::getAtExpireTime, expireTime)
+                .list()) {
+            renewAccessToken(bilibiliAccount);
+        }
+
+
+    }
+
+
+    public static void main(String[] args) {
+        Date dateTime = new Date(1655104166L * 1000);
+        System.out.println(dateTime);
+    }
+
+
+}

+ 219 - 0
src/main/java/com/sxtvs/open/api/odata/service/DouyinAccountService.java

@@ -0,0 +1,219 @@
+package com.sxtvs.open.api.odata.service;
+
+import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.http.HttpUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sxtvs.open.api.odata.dao.DouyinAccountMapper;
+import com.sxtvs.open.api.odata.dto.douyin.DouyinAccessTokenResponse;
+import com.sxtvs.open.api.odata.dto.douyin.DouyinRefreshTokenResponse;
+import com.sxtvs.open.api.odata.dto.douyin.DouyinUserInfoResponse;
+import com.sxtvs.open.api.odata.dto.douyin.videolist.Data;
+import com.sxtvs.open.api.odata.dto.douyin.videolist.DouyinVideoListResponse;
+import com.sxtvs.open.api.odata.entity.DouyinAccount;
+import com.sxtvs.open.core.conf.Constant;
+import com.sxtvs.open.core.lock.SegmentLock;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.retry.annotation.Backoff;
+import org.springframework.retry.annotation.Retryable;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Date;
+import java.util.HashMap;
+
+@Service
+@Slf4j
+public class DouyinAccountService extends ServiceImpl<DouyinAccountMapper, DouyinAccount> {
+
+    private final SegmentLock<String> segmentLock = new SegmentLock<>(128, false);
+
+    @Autowired
+    @Qualifier("douyinRestTemplate")
+    private RestTemplate restTemplate;
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @Autowired
+    private QrcodeLogServiceImpl qrcodeLogService;
+
+    private void renewRefreshToken(DouyinAccount douyinAccount) {
+
+        HashMap<String, Object> param = new HashMap<String, Object>() {{
+            this.put("client_key", Constant.douyinClientKey);
+            this.put("refresh_token", douyinAccount.getRefreshToken());
+        }};
+
+        String body = HttpUtil.post("https://open.douyin.com/oauth/renew_refresh_token/", param);
+        String refreshToken;
+        try {
+            log.info("renew_refresh_token {}", body);
+            DouyinRefreshTokenResponse douyinRefreshTokenResponse = objectMapper.readValue(body, DouyinRefreshTokenResponse.class);
+            refreshToken = douyinRefreshTokenResponse.getData().getRefreshToken();
+            if (refreshToken == null) {
+                log.error("{}", douyinAccount.getNickName());
+                return;
+            }
+        } catch (JsonProcessingException e) {
+            log.error(e.getMessage(), e);
+            return;
+        }
+        DateTime now = new DateTime();
+        douyinAccount.setRefreshToken(refreshToken);
+        douyinAccount.setRtExpireTime(DateUtil.offsetDay(now, 30));
+        douyinAccount.setUpdateTime(now.toJdkDate());
+        this.updateById(douyinAccount);
+    }
+
+    private void renewAccessToken(DouyinAccount douyinAccount) {
+        HashMap<String, Object> param = new HashMap<String, Object>() {{
+            this.put("client_key", Constant.douyinClientKey);
+            this.put("grant_type", "refresh_token");
+            this.put("refresh_token", douyinAccount.getRefreshToken());
+        }};
+        String body = HttpUtil.post("https://open.douyin.com/oauth/refresh_token/", param);
+        String accessToken;
+        try {
+            DouyinAccessTokenResponse tokenResponse = objectMapper.readValue(body, DouyinAccessTokenResponse.class);
+            accessToken = tokenResponse.getData().getAccessToken();
+            if (accessToken == null) {
+                log.error("{} {}", douyinAccount.getNickName(), body);
+                return;
+            }
+        } catch (JsonProcessingException e) {
+            log.error(e.getMessage(), e);
+            return;
+        }
+        DouyinAccessTokenResponse response = restTemplate.getForObject("https://open.douyin.com/oauth/refresh_token/?" +
+                        "client_key={client_key}&grant_type={grant_type}&refresh_token={refresh_token}",
+                DouyinAccessTokenResponse.class, param);
+
+        DateTime now = new DateTime();
+        douyinAccount.setAccessToken(accessToken);
+        douyinAccount.setAtExpireTime(DateUtil.offsetDay(now, 15));
+        douyinAccount.setUpdateTime(now.toJdkDate());
+        this.updateById(douyinAccount);
+        log.info("renewAccessToken {}", response);
+
+    }
+
+    @Retryable(value = RestClientException.class,
+            backoff = @Backoff(delay = 5000L, multiplier = 2))
+    public DouyinAccount upsert(String code) {
+        HashMap<String, String> param = new HashMap<String, String>() {{
+            this.put("client_key", Constant.douyinClientKey);
+            this.put("client_secret", Constant.douyinClientSecret);
+            this.put("code", code);
+        }};
+        DouyinAccessTokenResponse douyinAccessTokenResponse = restTemplate.getForObject(
+                "https://open.douyin.com/oauth/access_token/?" +
+                        "client_key={client_key}&client_secret={client_secret}&" +
+                        "grant_type=authorization_code&code={code}",
+                DouyinAccessTokenResponse.class, param);
+        DouyinAccessTokenResponse.Data data = douyinAccessTokenResponse.getData();
+        String openId = data.getOpenId();
+        String accessToken = data.getAccessToken();
+        String refreshToken = data.getRefreshToken();
+
+        param.clear();
+        param.put("access_token", accessToken);
+        param.put("open_id", openId);
+        DouyinUserInfoResponse douyinUserInfoResponse = restTemplate.getForObject("https://open.douyin.com/oauth/userinfo/?" +
+                        "access_token={access_token}&open_id={open_id}",
+                DouyinUserInfoResponse.class, param);
+
+
+        DouyinAccount douyinAccount = this.getById(openId);
+
+        DateTime now = new DateTime();
+        log.info("getById douyinAccount {} ", douyinAccount);
+        String nickname = douyinUserInfoResponse.getData().getNickname();
+        qrcodeLogService.writeLog("抖音",openId,nickname);
+        if (douyinAccount == null) {
+            douyinAccount = DouyinAccount.builder()
+                    .openId(openId)
+                    .atExpireTime(DateUtil.offsetDay(now, 15))
+                    .rtExpireTime(DateUtil.offsetDay(now, 30))
+                    .accessToken(accessToken)
+                    .refreshToken(refreshToken)
+                    .nickName(nickname)
+                    .updateTime(now.toJdkDate())
+                    .createTime(now.toJdkDate())
+                    .build();
+            this.save(douyinAccount);
+            log.info("{} 新增成功", nickname);
+        } else {
+            douyinAccount.setAtExpireTime(DateUtil.offsetDay(now, 15));
+            douyinAccount.setRtExpireTime(DateUtil.offsetDay(now, 30));
+            douyinAccount.setAccessToken(accessToken);
+            douyinAccount.setRefreshToken(refreshToken);
+            douyinAccount.setNickName(nickname);
+            douyinAccount.setUpdateTime(now.toJdkDate());
+            this.updateById(douyinAccount);
+            log.info("douyinAccount {}  更新成功", douyinAccount);
+        }
+
+        return douyinAccount;
+
+    }
+
+    @Retryable(value = RestClientException.class,
+            backoff = @Backoff(delay = 5000L, multiplier = 2))
+    public Data videoList(String openId, String cursor) {
+        DouyinAccount douyinAccount = this.getById(openId);
+        HashMap<String, String> param = new HashMap<String, String>() {{
+            this.put("open_id", douyinAccount.getOpenId());
+            this.put("access_token", douyinAccount.getAccessToken());
+            this.put("cursor", cursor);
+            this.put("count", "10");
+        }};
+        DouyinVideoListResponse douyinVideoListResponse = restTemplate.getForObject(
+                "https://open.douyin.com/video/list/?open_id={open_id}&access_token={access_token}&" +
+                        "cursor={cursor}&count={count}",
+                DouyinVideoListResponse.class, param);
+        if (douyinVideoListResponse == null) {
+            throw new RuntimeException();
+        }
+
+        return douyinVideoListResponse.getData();
+    }
+
+
+    @Retryable(value = RestClientException.class,
+            backoff = @Backoff(delay = 5000L, multiplier = 2))
+    public void refresh() {
+        Date rtExpireTime = new DateTime()
+                .offset(DateField.DAY_OF_YEAR, 7)
+                .toJdkDate();
+        Date expireTime = new DateTime()
+                .offset(DateField.DAY_OF_YEAR, 1)
+                .offset(DateField.HOUR_OF_DAY, 12)
+                .toJdkDate();
+
+
+        //检测快过期的rt
+        for (DouyinAccount douyinAccount : this.lambdaQuery()
+                .le(DouyinAccount::getRtExpireTime, rtExpireTime)
+                .list()) {
+            renewRefreshToken(douyinAccount);
+        }
+
+        //检测快过期的at
+        for (DouyinAccount douyinAccount : this.lambdaQuery()
+                .le(DouyinAccount::getAtExpireTime, expireTime)
+                .list()) {
+            renewAccessToken(douyinAccount);
+        }
+
+
+    }
+
+
+}

+ 16 - 0
src/main/java/com/sxtvs/open/api/odata/service/IQrcodeLogService.java

@@ -0,0 +1,16 @@
+package com.sxtvs.open.api.odata.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.sxtvs.open.api.odata.entity.QrcodeLog;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author zyx
+ * @since 2021-12-28
+ */
+public interface IQrcodeLogService extends IService<QrcodeLog> {
+
+}

+ 259 - 0
src/main/java/com/sxtvs/open/api/odata/service/KuaishouAccountService.java

@@ -0,0 +1,259 @@
+package com.sxtvs.open.api.odata.service;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.http.HttpUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sxtvs.open.api.odata.dao.KuaishouAccountMapper;
+import com.sxtvs.open.api.odata.dto.kuaishou.KuaiShouVideoResponse;
+import com.sxtvs.open.api.odata.dto.kuaishou.KuaishouAccessTokenResponse;
+import com.sxtvs.open.api.odata.dto.kuaishou.KuaishouUserInfoResponse;
+import com.sxtvs.open.api.odata.entity.KuaishouAccount;
+import com.sxtvs.open.api.odata.entity.PlatformData;
+import com.sxtvs.open.core.conf.Constant;
+import com.sxtvs.open.core.lock.SegmentLock;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.retry.annotation.Backoff;
+import org.springframework.retry.annotation.Retryable;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+public class KuaishouAccountService extends ServiceImpl<KuaishouAccountMapper, KuaishouAccount> {
+
+    private final SegmentLock<String> segmentLock = new SegmentLock<>(128, false);
+
+    @Autowired
+    @Qualifier("kuaishouRestTemplate")
+    private RestTemplate restTemplate;
+
+    @Autowired
+    private PlatformDataService platformDataService;
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @Autowired
+    private QrcodeLogServiceImpl qrcodeLogService;
+
+
+    @Retryable(value = RestClientException.class,
+            backoff = @Backoff(delay = 5000L, multiplier = 2))
+    public KuaishouAccount upsert(String code) {
+        HashMap<String, String> param = new HashMap<String, String>() {{
+            this.put("app_id", Constant.kuaishouClientKey);
+            this.put("app_secret", Constant.kuaishouClientSecret);
+            this.put("code", code);
+        }};
+        KuaishouAccessTokenResponse data = restTemplate.getForObject(
+                "https://open.kuaishou.com/oauth2/access_token?" +
+                        "app_id={app_id}&app_secret={app_secret}&" +
+                        "grant_type=authorization_code&code={code}",
+                KuaishouAccessTokenResponse.class, param);
+        if (data == null) {
+            log.error("code {} getAccessToken", code);
+            return null;
+        }
+        log.info("KuaishouAccessTokenResponse {}", data);
+        String openId = data.getOpenId();
+        String accessToken = data.getAccessToken();
+        String refreshToken = data.getRefreshToken();
+
+        param.clear();
+        param.put("access_token", accessToken);
+        param.put("app_id", Constant.kuaishouClientKey);
+        KuaishouUserInfoResponse kuaishouUserInfoResponse = restTemplate.getForObject("https://open.kuaishou.com/openapi/user_info?" +
+                        "access_token={access_token}&app_id={app_id}",
+                KuaishouUserInfoResponse.class, param);
+
+        if (kuaishouUserInfoResponse == null) {
+            log.error("param {} getUserInfo", param);
+            return null;
+        }
+
+
+
+        KuaishouAccount kuaishouAccount = this.getById(openId);
+
+        DateTime now = new DateTime();
+        log.info("getById kuaishouAccount {} ", kuaishouAccount);
+        String nickname = kuaishouUserInfoResponse.getUserInfo().getName();
+        qrcodeLogService.writeLog("快手",openId,nickname);
+        if (kuaishouAccount == null) {
+            KuaishouAccount account = KuaishouAccount.builder()
+                    .openId(openId)
+                    .atExpireTime(DateUtil.offsetSecond(now, data.getExpiresIn()))
+                    .rtExpireTime(DateUtil.offsetSecond(now, data.getRefreshTokenExpiresIn()))
+                    .accessToken(accessToken)
+                    .refreshToken(refreshToken)
+                    .nickName(nickname)
+                    .updateTime(now.toJdkDate())
+                    .createTime(now.toJdkDate())
+                    .build();
+            this.save(account);
+            log.info("{} 新增成功", nickname);
+        } else {
+            kuaishouAccount.setAtExpireTime(DateUtil.offsetSecond(now, data.getExpiresIn()));
+            kuaishouAccount.setRtExpireTime(DateUtil.offsetSecond(now, data.getRefreshTokenExpiresIn()));
+            kuaishouAccount.setAccessToken(accessToken);
+            kuaishouAccount.setRefreshToken(refreshToken);
+            kuaishouAccount.setNickName(nickname);
+            kuaishouAccount.setUpdateTime(now.toJdkDate());
+            this.updateById(kuaishouAccount);
+            log.info("kuaishouAccount {}  更新成功", kuaishouAccount);
+        }
+
+
+        return kuaishouAccount;
+
+    }
+
+    @Retryable(value = RestClientException.class,
+            backoff = @Backoff(delay = 5000L, multiplier = 2))
+    public void refresh() {
+
+        Date expireTime = new DateTime()
+                .offset(DateField.DAY_OF_YEAR, 7)
+                .toJdkDate();
+
+        //检测快过期的rt
+        for (KuaishouAccount kuaishouAccount : this.lambdaQuery()
+                .le(KuaishouAccount::getRtExpireTime, expireTime)
+                .list()) {
+            renewAccessToken(kuaishouAccount);
+        }
+
+
+        expireTime = new DateTime()
+                .offset(DateField.MINUTE, 30)
+                .toJdkDate();
+
+        //检测快过期的at
+        for (KuaishouAccount kuaishouAccount : this.lambdaQuery()
+                .le(KuaishouAccount::getAtExpireTime, expireTime)
+                .list()) {
+            renewAccessToken(kuaishouAccount);
+        }
+
+
+    }
+
+    @SneakyThrows
+    private void renewAccessToken(KuaishouAccount kuaishouAccount) {
+
+
+        String body = HttpUtil.get("https://open.kuaishou.com/oauth2/refresh_token?" +
+                "refresh_token=" + kuaishouAccount.getRefreshToken() + "&app_id=" + Constant.kuaishouClientKey + "&" +
+                "app_secret=" + Constant.kuaishouClientSecret + "&grant_type=refresh_token");
+        log.info("renewAccessToken {}", body);
+        KuaishouAccessTokenResponse response = objectMapper.readValue(body, KuaishouAccessTokenResponse.class);
+
+        if (response.getResult() != null && 1 != response.getResult()) {
+            return;
+        }
+
+
+        DateTime now = new DateTime();
+        kuaishouAccount.setRefreshToken(response.getRefreshToken());
+        kuaishouAccount.setRtExpireTime(DateUtil.offsetSecond(now, response.getRefreshTokenExpiresIn()));
+        kuaishouAccount.setAccessToken(response.getAccessToken());
+        kuaishouAccount.setAtExpireTime(DateUtil.offsetSecond(now, response.getExpiresIn()));
+        kuaishouAccount.setUpdateTime(now.toJdkDate());
+        this.updateById(kuaishouAccount);
+    }
+
+
+    @Retryable(value = RestClientException.class,
+            backoff = @Backoff(delay = 5000L, multiplier = 2))
+    public List<KuaiShouVideoResponse.VideoList> videoList(String openId, String cursor) {
+        KuaishouAccount kuaishouAccount = this.getById(openId);
+        HashMap<String, String> param = new HashMap<String, String>() {{
+            this.put("app_id", Constant.kuaishouClientKey);
+            this.put("access_token", kuaishouAccount.getAccessToken());
+            this.put("count", "20");
+        }};
+        String url = "https://open.kuaishou.com/openapi/photo/list?app_id={app_id}&access_token={access_token}&" +
+                "count={count}";
+        if (cursor != null) {
+            url += "&cursor=" + cursor + "";
+        }
+        KuaiShouVideoResponse kuaiShouVideoResponse = restTemplate.getForObject(
+                url,
+                KuaiShouVideoResponse.class, param);
+        if (kuaiShouVideoResponse == null) {
+            throw new RuntimeException();
+        }
+        return kuaiShouVideoResponse.getVideoList();
+    }
+
+    private void saveKuaiShouData(String dt, KuaishouAccount kuaishouAccount) {
+        String openId = kuaishouAccount.getOpenId();
+
+        List<KuaiShouVideoResponse.VideoList> videoLists = videoList(openId, null);
+        if (CollUtil.isEmpty(videoLists)) {
+            return;
+        }
+        List<KuaiShouVideoResponse.VideoList> res = new ArrayList<>(videoLists);
+        while (CollUtil.isNotEmpty(videoLists)) {
+            videoLists = videoList(openId, videoLists.get(videoLists.size() - 1).getPhotoId());
+            res.addAll(videoLists);
+        }
+
+        List<PlatformData> dataList = res.stream()
+                .map(item -> {
+                    PlatformData kuaishouData = new PlatformData();
+                    kuaishouData.setId(item.getPhotoId() + dt);
+                    kuaishouData.setItemId(item.getPhotoId());
+                    kuaishouData.setDt(dt);
+                    kuaishouData.setTitle(item.getCaption());
+                    kuaishouData.setOpenId(openId);
+                    kuaishouData.setDiggCount(item.getLikeCount());
+                    kuaishouData.setPlayCount(item.getViewCount());
+                    kuaishouData.setDownloadCount(0);
+                    kuaishouData.setForwardCount(0);
+                    kuaishouData.setShareCount(0);
+                    kuaishouData.setCommentCount(item.getCommentCount());
+                    kuaishouData.setPlatform("kuaishou");
+                    kuaishouData.setNickName(kuaishouAccount.getNickName());
+                    kuaishouData.setPublishTime(new Date(item.getCreateTime()));
+                    return kuaishouData;
+                })
+                .collect(Collectors.toList());
+
+        platformDataService.removeByIds(dataList.stream().map(PlatformData::getId)
+                .collect(Collectors.toList()));
+
+        platformDataService.saveBatch(dataList);
+    }
+
+    public void saveAllAccountData() {
+        List<KuaishouAccount> kuaishouAccounts = list();
+        String dt = new DateTime().toString("yyyyMMdd");
+
+        for (KuaishouAccount kuaishouAccount : kuaishouAccounts) {
+            try {
+                saveKuaiShouData(dt, kuaishouAccount);
+            } catch (Exception e) {
+                String nickName = kuaishouAccount.getNickName();
+                log.error(nickName + " error", e);
+            }
+        }
+
+    }
+
+
+}

+ 13 - 0
src/main/java/com/sxtvs/open/api/odata/service/PlatformDataService.java

@@ -0,0 +1,13 @@
+package com.sxtvs.open.api.odata.service;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sxtvs.open.api.odata.dao.PlatformDataMapper;
+import com.sxtvs.open.api.odata.entity.PlatformData;
+import org.springframework.stereotype.Service;
+
+@Service
+public class PlatformDataService extends ServiceImpl<PlatformDataMapper, PlatformData> {
+
+
+
+}

+ 11 - 0
src/main/java/com/sxtvs/open/api/odata/service/PlatformService.java

@@ -0,0 +1,11 @@
+package com.sxtvs.open.api.odata.service;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sxtvs.open.api.odata.dao.PlatformMapper;
+import com.sxtvs.open.api.odata.entity.Platform;
+import org.springframework.stereotype.Service;
+
+@Service
+public class PlatformService extends ServiceImpl<PlatformMapper, Platform> {
+
+}

+ 37 - 0
src/main/java/com/sxtvs/open/api/odata/service/QrcodeLogServiceImpl.java

@@ -0,0 +1,37 @@
+package com.sxtvs.open.api.odata.service;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sxtvs.open.api.odata.dao.QrcodeLogMapper;
+import com.sxtvs.open.api.odata.entity.QrcodeLog;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.Optional;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author zyx
+ * @since 2021-12-28
+ */
+@Service
+public class QrcodeLogServiceImpl extends ServiceImpl<QrcodeLogMapper, QrcodeLog> implements IQrcodeLogService {
+
+    public void writeLog(String platform,String openId,String nickName){
+        QrcodeLog qrcodeLog = new QrcodeLog();
+        qrcodeLog.setPlatform(platform);
+        qrcodeLog.setOpenId(openId);
+        qrcodeLog.setNickName(nickName);
+        qrcodeLog.setCreateTime(LocalDateTime.now());
+        Optional<QrcodeLog> logOptional = lambdaQuery()
+                .eq(QrcodeLog::getPlatform, platform)
+                .eq(QrcodeLog::getNickName, nickName)
+                .oneOpt();
+        if (logOptional.isPresent()) {
+            return;
+        }
+        save(qrcodeLog);
+    }
+}

+ 297 - 0
src/main/java/com/sxtvs/open/api/odata/service/ToutiaoAccountService.java

@@ -0,0 +1,297 @@
+package com.sxtvs.open.api.odata.service;
+
+import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.http.HttpUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sxtvs.open.api.odata.dao.ToutiaoAccountMapper;
+import com.sxtvs.open.api.odata.dto.douyin.DouyinAccessTokenResponse;
+import com.sxtvs.open.api.odata.dto.douyin.DouyinRefreshTokenResponse;
+import com.sxtvs.open.api.odata.dto.douyin.DouyinUserInfoResponse;
+import com.sxtvs.open.api.odata.dto.douyin.videolist.Data;
+import com.sxtvs.open.api.odata.dto.douyin.videolist.DouyinVideoListResponse;
+import com.sxtvs.open.api.odata.dto.douyin.videolist.ListItem;
+import com.sxtvs.open.api.odata.dto.douyin.videolist.Statistics;
+import com.sxtvs.open.api.odata.entity.PlatformData;
+import com.sxtvs.open.api.odata.entity.ToutiaoAccount;
+import com.sxtvs.open.core.conf.Constant;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.retry.annotation.Backoff;
+import org.springframework.retry.annotation.Retryable;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+public class ToutiaoAccountService extends ServiceImpl<ToutiaoAccountMapper, ToutiaoAccount> {
+
+    @Autowired
+    @Qualifier("douyinRestTemplate")
+    private RestTemplate restTemplate;
+
+    @Autowired
+    private PlatformDataService platformDataService;
+
+
+    @Autowired
+    private QrcodeLogServiceImpl qrcodeLogService;
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @SneakyThrows
+    private void renewRefreshToken(ToutiaoAccount toutiaoAccount) {
+
+        HashMap<String, Object> param = new HashMap<String, Object>() {{
+            this.put("client_key", Constant.douyinClientKey);
+            this.put("refresh_token", toutiaoAccount.getRefreshToken());
+        }};
+
+        String body = HttpUtil.get("https://open.snssdk.com/oauth/renew_refresh_token/", param);
+        String refreshToken;
+        try {
+            log.info("renew_refresh_token {}", body);
+            DouyinRefreshTokenResponse douyinRefreshTokenResponse = objectMapper.readValue(body, DouyinRefreshTokenResponse.class);
+            refreshToken = douyinRefreshTokenResponse.getData().getRefreshToken();
+            if (refreshToken == null) {
+                log.error("{}", toutiaoAccount.getNickName());
+                return;
+            }
+        } catch (JsonProcessingException e) {
+            log.error(e.getMessage(), e);
+            return;
+        }
+        DateTime now = new DateTime();
+        toutiaoAccount.setRefreshToken(refreshToken);
+        toutiaoAccount.setRtExpireTime(DateUtil.offsetDay(now, 30));
+        toutiaoAccount.setUpdateTime(now.toJdkDate());
+        this.updateById(toutiaoAccount);
+    }
+
+    @SneakyThrows
+    private void renewAccessToken(ToutiaoAccount toutiaoAccount) {
+        HashMap<String, Object> param = new HashMap<String, Object>() {{
+            this.put("client_key", Constant.douyinClientKey);
+            this.put("grant_type", "refresh_token");
+            this.put("refresh_token", toutiaoAccount.getRefreshToken());
+        }};
+        String body = HttpUtil.get("https://open.snssdk.com/oauth/refresh_token/", param);
+        String accessToken;
+        try {
+            DouyinAccessTokenResponse tokenResponse = objectMapper.readValue(body, DouyinAccessTokenResponse.class);
+            accessToken = tokenResponse.getData().getAccessToken();
+            if (accessToken == null) {
+                log.error("{} {}", toutiaoAccount.getNickName(), body);
+                return;
+            }
+        } catch (JsonProcessingException e) {
+            log.error(e.getMessage(), e);
+            return;
+        }
+        DateTime now = new DateTime();
+        toutiaoAccount.setAccessToken(accessToken);
+        toutiaoAccount.setAtExpireTime(DateUtil.offsetDay(now, 15));
+        toutiaoAccount.setUpdateTime(now.toJdkDate());
+        this.updateById(toutiaoAccount);
+    }
+
+    @Retryable(value = RestClientException.class,
+            backoff = @Backoff(delay = 5000L, multiplier = 2))
+    public ToutiaoAccount upsert(String code) {
+        HashMap<String, String> param = new HashMap<String, String>() {{
+            this.put("client_key", Constant.douyinClientKey);
+            this.put("client_secret", Constant.douyinClientSecret);
+            this.put("code", code);
+        }};
+        DouyinAccessTokenResponse douyinAccessTokenResponse = restTemplate.getForObject(
+                "https://open.snssdk.com/oauth/access_token/?" +
+                        "client_key={client_key}&client_secret={client_secret}&" +
+                        "grant_type=authorization_code&code={code}",
+                DouyinAccessTokenResponse.class, param);
+        DouyinAccessTokenResponse.Data data = douyinAccessTokenResponse.getData();
+        String openId = data.getOpenId();
+        String accessToken = data.getAccessToken();
+        String refreshToken = data.getRefreshToken();
+
+        param.clear();
+        param.put("access_token", accessToken);
+        param.put("open_id", openId);
+        DouyinUserInfoResponse douyinUserInfoResponse = restTemplate.getForObject("https://open.snssdk.com/oauth/userinfo/?" +
+                        "access_token={access_token}&open_id={open_id}",
+                DouyinUserInfoResponse.class, param);
+
+
+        ToutiaoAccount toutiaoAccount = this.getById(openId);
+
+        DateTime now = new DateTime();
+        log.info("getById toutiaoAccount {} ", toutiaoAccount);
+        String nickname = douyinUserInfoResponse.getData().getNickname();
+
+        qrcodeLogService.writeLog("头条", openId, nickname);
+        if (toutiaoAccount == null) {
+            toutiaoAccount = ToutiaoAccount.builder()
+                    .openId(openId)
+                    .atExpireTime(DateUtil.offsetDay(now, 15))
+                    .rtExpireTime(DateUtil.offsetDay(now, 30))
+                    .accessToken(accessToken)
+                    .refreshToken(refreshToken)
+                    .nickName(nickname)
+                    .updateTime(now.toJdkDate())
+                    .createTime(now.toJdkDate())
+                    .build();
+            this.save(toutiaoAccount);
+            log.info("{} 新增成功", nickname);
+        } else {
+            toutiaoAccount.setAtExpireTime(DateUtil.offsetDay(now, 15));
+            toutiaoAccount.setRtExpireTime(DateUtil.offsetDay(now, 30));
+            toutiaoAccount.setAccessToken(accessToken);
+            toutiaoAccount.setRefreshToken(refreshToken);
+            toutiaoAccount.setNickName(nickname);
+            toutiaoAccount.setUpdateTime(now.toJdkDate());
+            this.updateById(toutiaoAccount);
+            log.info("toutiaoAccount {}  更新成功", toutiaoAccount);
+        }
+
+
+        return toutiaoAccount;
+
+    }
+
+    @Retryable(value = RestClientException.class,
+            backoff = @Backoff(delay = 5000L, multiplier = 2))
+    public Data videoList(String openId, String cursor) {
+        ToutiaoAccount toutiaoAccount = this.getById(openId);
+        HashMap<String, String> param = new HashMap<String, String>() {{
+            this.put("open_id", toutiaoAccount.getOpenId());
+            this.put("access_token", toutiaoAccount.getAccessToken());
+            this.put("cursor", cursor);
+            this.put("count", "10");
+        }};
+        DouyinVideoListResponse douyinVideoListResponse = restTemplate.getForObject(
+                "https://open.douyin.com/toutiao/video/list/?open_id={open_id}&access_token={access_token}&" +
+                        "cursor={cursor}&count={count}",
+                DouyinVideoListResponse.class, param);
+        if (douyinVideoListResponse == null) {
+            throw new RuntimeException();
+        }
+
+        return douyinVideoListResponse.getData();
+    }
+
+
+    @Retryable(value = RestClientException.class,
+            backoff = @Backoff(delay = 5000L, multiplier = 2))
+    public void refresh() {
+        Date rtExpireTime = new DateTime()
+                .offset(DateField.DAY_OF_YEAR, 7)
+                .toJdkDate();
+        Date expireTime = new DateTime()
+                .offset(DateField.DAY_OF_YEAR, 1)
+                .offset(DateField.HOUR, 12)
+                .toJdkDate();
+
+
+        //检测快过期的rt
+        for (ToutiaoAccount douyinAccount : this.lambdaQuery()
+                .le(ToutiaoAccount::getRtExpireTime, rtExpireTime)
+                .list()) {
+            renewRefreshToken(douyinAccount);
+        }
+
+        //检测快过期的at
+        for (ToutiaoAccount douyinAccount : this.lambdaQuery()
+                .le(ToutiaoAccount::getAtExpireTime, expireTime)
+                .list()) {
+            renewAccessToken(douyinAccount);
+        }
+
+
+    }
+
+    public void refreshTest() {
+        for (ToutiaoAccount toutiaoAccount : this.lambdaQuery()
+                .eq(ToutiaoAccount::getOpenId, "b1deadcf-7f0e-49dc-9a99-dd290e344070")
+                .list()) {
+            renewRefreshToken(toutiaoAccount);
+        }
+    }
+
+
+    public void saveAllAccountData() {
+        List<ToutiaoAccount> toutiaoAccounts = list();
+        String dt = new DateTime().toString("yyyyMMdd");
+
+        for (ToutiaoAccount toutiaoAccount : toutiaoAccounts) {
+            try {
+                saveDouyinData(dt, toutiaoAccount);
+            } catch (Exception e) {
+                String nickName = toutiaoAccount.getNickName();
+                log.error(nickName + " error", e);
+            }
+        }
+
+    }
+
+    private void saveDouyinData(String dt, ToutiaoAccount toutiaoAccount) {
+        String openId = toutiaoAccount.getOpenId();
+        Data data = videoList(openId, "0");
+        if (data.getList() == null) {
+            return;
+        }
+        List<ListItem> res = new ArrayList<>(data.getList());
+        while (data.getHasMore()) {
+            data = videoList(openId, String.valueOf(data.getCursor()));
+            if (data.getList() != null) {
+                res.addAll(data.getList());
+            }
+        }
+
+        List<PlatformData> dataList = res.stream()
+                .map(item -> {
+                    PlatformData platformData = new PlatformData();
+
+                    platformData.setId(item.getItemId() + dt);
+                    Date publishTime = new Date(item.getCreateTime() * 1000);
+                    log.info("{} {}", publishTime, item.getCreateTime());
+                    platformData.setPublishTime(publishTime);
+                    platformData.setNickName(toutiaoAccount.getNickName());
+                    platformData.setItemId(item.getItemId());
+                    platformData.setDt(dt);
+                    platformData.setTitle(item.getTitle());
+                    platformData.setOpenId(openId);
+                    Statistics statistics = item.getStatistics();
+                    platformData.setCommentCount(statistics.getCommentCount());
+                    platformData.setDiggCount(statistics.getDiggCount());
+                    platformData.setDownloadCount(statistics.getDownloadCount());
+                    platformData.setForwardCount(statistics.getForwardCount());
+                    platformData.setPlayCount(statistics.getPlayCount());
+                    platformData.setShareCount(statistics.getShareCount());
+                    platformData.setPlatform("toutiao");
+                    return platformData;
+                })
+                .collect(Collectors.toList());
+
+        platformDataService.removeByIds(dataList.stream().map(PlatformData::getId)
+                .collect(Collectors.toList()));
+
+        platformDataService.saveBatch(dataList);
+    }
+
+    public static void main(String[] args) {
+        System.out.println(new Date(1618625930L * 1000));
+    }
+
+}

+ 133 - 0
src/main/java/com/sxtvs/open/api/odata/service/WeiboAccountService.java

@@ -0,0 +1,133 @@
+package com.sxtvs.open.api.odata.service;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.http.HttpUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sxtvs.open.api.odata.dao.WeiboAccountMapper;
+import com.sxtvs.open.api.odata.dto.weibo.WeiboAccessTokenResponse;
+import com.sxtvs.open.api.odata.dto.weibo.WeiboCreateTask;
+import com.sxtvs.open.api.odata.dto.weibo.show.UserShowResponse;
+import com.sxtvs.open.api.odata.entity.WeiboAccount;
+import com.sxtvs.open.api.odata.entity.WeiboTask;
+import com.sxtvs.open.core.conf.Constant;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Service
+@Slf4j
+public class WeiboAccountService extends ServiceImpl<WeiboAccountMapper, WeiboAccount> {
+
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @Autowired
+    private WeiboTaskService weiboTaskService;
+
+    @Autowired
+    private QrcodeLogServiceImpl qrcodeLogService;
+
+    @SneakyThrows
+    public void upsert(String code) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("client_id", Constant.weiboKey);
+        map.put("client_secret", Constant.weiboSecret);
+        map.put("grant_type", "authorization_code");
+        map.put("code", code);
+        map.put("redirect_uri", "https://open.sxtvs.net/weibo/callback");
+
+        String response = HttpUtil.post("https://api.weibo.com/oauth2/access_token", map);
+        log.info(response);
+        WeiboAccessTokenResponse tokenResponse = objectMapper.readValue(response, WeiboAccessTokenResponse.class);
+        tokenResponse.setAccessToken("OAuth2 " + tokenResponse.getAccessToken());
+        String uid = tokenResponse.getUid();
+        map.clear();
+
+        response = HttpUtil.createGet("https://api.weibo.com/2/users/show.json")
+                .header("Authorization", tokenResponse.getAccessToken())
+                .form("uid", uid)
+                .execute()
+                .body();
+        UserShowResponse userShow = objectMapper.readValue(response, UserShowResponse.class);
+        log.info("response {}", response);
+
+        qrcodeLogService.writeLog("微博",uid,userShow.getName());
+
+        WeiboAccount weiboAccount = this.getById(uid);
+        DateTime now = new DateTime();
+        if (weiboAccount == null) {
+            weiboAccount = new WeiboAccount();
+            weiboAccount.setOpenId(uid);
+            weiboAccount.setAccessToken(tokenResponse.getAccessToken());
+            weiboAccount.setAtExpireTime(DateUtil.offsetSecond(now, tokenResponse.getExpiresIn()));
+            weiboAccount.setCreateTime(now);
+            weiboAccount.setUpdateTime(now);
+            weiboAccount.setNickName(userShow.getName());
+            this.save(weiboAccount);
+        } else {
+            weiboAccount.setUpdateTime(now);
+            weiboAccount.setAccessToken(tokenResponse.getAccessToken());
+            weiboAccount.setAtExpireTime(DateUtil.offsetSecond(now, tokenResponse.getExpiresIn()));
+            weiboAccount.setNickName(userShow.getName());
+            this.updateById(weiboAccount);
+        }
+        log.info(tokenResponse.toString());
+    }
+
+    @SneakyThrows
+    public void createTask(long start, long end, String ids) {
+        WeiboAccount weiboAccount = getOne(null);
+        String accessToken = weiboAccount.getAccessToken();
+        String body = HttpUtil.createPost("https://c.api.weibo.com/2/search/statuses/historical/create.json")
+                .header("Authorization", accessToken)
+                .form("starttime", start)
+                .form("endtime", end)
+                .form("ids", ids)
+                .execute()
+                .body();
+        WeiboCreateTask weiboCreateTask = objectMapper.readValue(body, WeiboCreateTask.class);
+        if (weiboCreateTask.hasError()) {
+            log.error(body);
+            return;
+        }
+        WeiboTask weiboTask = new WeiboTask();
+        weiboTask.setTaskId(weiboCreateTask.getTaskId());
+        weiboTask.setSecretKey(weiboCreateTask.getSecretKey());
+        weiboTask.setFinish(0);
+        weiboTask.setStartTime(start);
+        weiboTask.setEndTime(end);
+        weiboTask.setStartDay(new DateTime(start).toString("yyyyMMdd"));
+        weiboTask.setWeiboId(ids);
+        weiboTaskService.save(weiboTask);
+    }
+
+//    public Data videoList(String openId, String cursor) {
+//        WeiboAccount weiboAccount = this.getById(openId);
+//        String accessToken = weiboAccount.getAccessToken();
+//        HttpUtil.createGet("https://api.weibo.com/2/statuses/repost_timeline.json")
+//                .header("Authorization", accessToken);
+//        HashMap<String, String> param = new HashMap<String, String>() {{
+//            this.put("open_id", weiboAccount.getOpenId());
+//            this.put("access_token", weiboAccount.getAccessToken());
+//            this.put("cursor", cursor);
+//            this.put("count", "10");
+//        }};
+//        DouyinVideoListResponse douyinVideoListResponse = restTemplate.getForObject(
+//                "https://open.douyin.com/toutiao/video/list/?open_id={open_id}&access_token={access_token}&" +
+//                        "cursor={cursor}&count={count}",
+//                DouyinVideoListResponse.class, param);
+//        if (douyinVideoListResponse == null) {
+//            throw new RuntimeException();
+//        }
+//
+//        return douyinVideoListResponse.getData();
+//    }
+
+}

+ 12 - 0
src/main/java/com/sxtvs/open/api/odata/service/WeiboTaskService.java

@@ -0,0 +1,12 @@
+package com.sxtvs.open.api.odata.service;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sxtvs.open.api.odata.dao.WeiboTaskMapper;
+import com.sxtvs.open.api.odata.entity.WeiboTask;
+import org.springframework.stereotype.Service;
+
+@Service
+public class WeiboTaskService extends ServiceImpl<WeiboTaskMapper, WeiboTask> {
+
+
+}

+ 15 - 0
src/main/java/com/sxtvs/open/api/odata/service/WxAccountService.java

@@ -0,0 +1,15 @@
+package com.sxtvs.open.api.odata.service;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sxtvs.open.api.odata.dao.WxAccountMapper;
+import com.sxtvs.open.api.odata.entity.WxAccount;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Service
+@Slf4j
+public class WxAccountService extends ServiceImpl<WxAccountMapper, WxAccount> {
+
+
+
+}

+ 21 - 0
src/main/java/com/sxtvs/open/api/odata/service/WxAccountV2Service.java

@@ -0,0 +1,21 @@
+package com.sxtvs.open.api.odata.service;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sxtvs.open.api.odata.dao.WxAccountV2Mapper;
+import com.sxtvs.open.api.odata.entity.WxAccountV2;
+import com.sxtvs.open.core.conf.Constant;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Service
+@Slf4j
+public class WxAccountV2Service extends ServiceImpl<WxAccountV2Mapper, WxAccountV2> {
+
+    public WxAccountV2 getZhiHuiRongMeiAccount(){
+        return getById(Constant.weixinZhiHuiRongMeiAppId);
+    }
+
+    public WxAccountV2 getWishAccount(){
+        return getById(Constant.weixinWishAppId);
+    }
+}

+ 270 - 0
src/main/java/com/sxtvs/open/api/odata/service/WxRestService.java

@@ -0,0 +1,270 @@
+package com.sxtvs.open.api.odata.service;
+
+import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.http.HttpUtil;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sxtvs.open.api.odata.dto.wx.*;
+import com.sxtvs.open.api.odata.dto.wx.apiquery.AuthorizationInfo;
+import com.sxtvs.open.api.odata.dto.wx.apiquery.WxApiQueryAuthRequest;
+import com.sxtvs.open.api.odata.dto.wx.apiquery.WxApiQueryAuthResponse;
+import com.sxtvs.open.api.odata.dto.wx.authorization.AuthorizationInfoResponse;
+import com.sxtvs.open.api.odata.entity.WxAccount;
+import com.sxtvs.open.api.odata.entity.WxAccountV2;
+import com.sxtvs.open.core.conf.Constant;
+import com.sxtvs.open.core.http.RequestUtil;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Date;
+
+import static com.sxtvs.open.core.conf.Constant.weixinZhiHuiRongMeiAppId;
+import static com.sxtvs.open.core.conf.Constant.weixinZhiHuiRongMeiSecret;
+
+@Service
+@Slf4j
+public class WxRestService {
+
+    @Autowired
+    @Qualifier("weixinRestTemplate")
+    private RestTemplate template;
+
+    @Autowired
+    private RequestUtil requestUtil;
+
+    @Autowired
+    private com.sxtvs.open.api.odata.service.WxTicketService wxTicketService;
+
+    @Autowired
+    private WxAccountService wxAccountService;
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @Autowired
+    private WxAccountV2Service wxAccountV2Service;
+
+    @Autowired
+    private QrcodeLogServiceImpl qrcodeLogService;
+
+    public WxApiComponentTokenResponse refreshComponentToken() {
+        WxApiComponentTokenRequest tokenRequest = new WxApiComponentTokenRequest();
+        tokenRequest.setComponentAppid(Constant.wxClientKey);
+        tokenRequest.setComponentAppsecret(Constant.wxClientSecret);
+        tokenRequest.setComponentVerifyTicket(wxTicketService.getTicket());
+        WxApiComponentTokenResponse tokenResponse = template.postForObject(
+                "https://api.weixin.qq.com/cgi-bin/component/api_component_token",
+                requestUtil.buildJsonObject(tokenRequest), WxApiComponentTokenResponse.class);
+        log.info("refreshComponentToken {}", tokenResponse);
+        wxTicketService.updateComponentAccessToken(tokenResponse.getComponentAccessToken(),
+                tokenResponse.getExpiresIn());
+        return tokenResponse;
+    }
+
+
+    public WxApiCreatePreAuthCodeResponse createPreAuthCodeResponse() {
+        String componentAccessToken = wxTicketService.getTicketObject().getComponentAccessToken();
+        WxApiCreatePreAuthCodeRequest authCodeRequest = new WxApiCreatePreAuthCodeRequest();
+        authCodeRequest.setComponentAppid(Constant.wxClientKey);
+        authCodeRequest.setComponentAccessToken(componentAccessToken);
+        WxApiCreatePreAuthCodeResponse preAuthCodeResponse = template.postForObject(
+                "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?" +
+                        "component_access_token=" + componentAccessToken,
+                requestUtil.buildJsonObject(authCodeRequest), WxApiCreatePreAuthCodeResponse.class);
+        log.info("{}", preAuthCodeResponse);
+        return preAuthCodeResponse;
+    }
+
+    public void apiQueryAuth(String authCode) {
+        String componentAccessToken = wxTicketService.getTicketObject().getComponentAccessToken();
+        WxApiQueryAuthRequest authCodeRequest = new WxApiQueryAuthRequest();
+        authCodeRequest.setComponentAppid(Constant.wxClientKey);
+        authCodeRequest.setComponentAccessToken(componentAccessToken);
+        authCodeRequest.setAuthorizationCode(authCode);
+        WxApiQueryAuthResponse wxApiQueryAuthResponse = template.postForObject(
+                "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?" +
+                        "component_access_token=" + componentAccessToken,
+                requestUtil.buildJsonObject(authCodeRequest), WxApiQueryAuthResponse.class);
+        log.info("{}", wxApiQueryAuthResponse);
+        upsertWxAccount(wxApiQueryAuthResponse);
+    }
+
+    public AuthorizationInfoResponse getAuthorizerInfo(String openId) {
+        WxApiGetAuthorizerInfoRequest infoRequest = new WxApiGetAuthorizerInfoRequest();
+        infoRequest.setComponentAppid(Constant.wxClientKey);
+        String componentAccessToken = wxTicketService.getTicketObject().getComponentAccessToken();
+        infoRequest.setComponentAccessToken(componentAccessToken);
+        infoRequest.setAuthorizerAppid(openId);
+
+        AuthorizationInfoResponse authorizationInfoResponse = template.postForObject(
+                "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?" +
+                        "component_access_token=" + componentAccessToken,
+                requestUtil.buildJsonObject(infoRequest), AuthorizationInfoResponse.class);
+
+        return authorizationInfoResponse;
+
+    }
+
+    public synchronized void upsertWxAccount(WxApiQueryAuthResponse wxApiQueryAuthResponse) {
+
+        AuthorizationInfo authorizationInfo = wxApiQueryAuthResponse.getAuthorizationInfo();
+        String openId = authorizationInfo.getAuthorizerAppid();
+        String ak = authorizationInfo.getAuthorizerAccessToken();
+        String rk = authorizationInfo.getAuthorizerRefreshToken();
+        int expiresIn = authorizationInfo.getExpiresIn();
+        String nickName = getAuthorizerInfo(openId).getAuthorizerInfo().getNickName();
+
+        qrcodeLogService.writeLog("微信", openId, nickName);
+        WxAccount wxAccount = wxAccountService.getById(openId);
+
+        DateTime now = new DateTime();
+        now.setMutable(false);
+        if (wxAccount == null) {
+            wxAccount = new WxAccount();
+            wxAccount.setNickName(nickName);
+            wxAccount.setOpenId(openId);
+            wxAccount.setAccessToken(ak);
+            wxAccount.setAtExpireTime(now.offset(DateField.SECOND, expiresIn));
+            wxAccount.setRefreshToken(rk);
+            wxAccount.setRtExpireTime(now.offset(DateField.YEAR, 3));
+            wxAccount.setCreateTime(now);
+            wxAccount.setUpdateTime(now);
+            wxAccountService.save(wxAccount);
+        } else {
+            wxAccount.setAccessToken(ak);
+            wxAccount.setNickName(nickName);
+            wxAccount.setAtExpireTime(now.offset(DateField.SECOND, expiresIn));
+            wxAccount.setRefreshToken(rk);
+            wxAccount.setRtExpireTime(now.offset(DateField.YEAR, 3));
+            wxAccount.setUpdateTime(now);
+            wxAccountService.updateById(wxAccount);
+        }
+        log.info("wx nick_name {}", wxAccount.getNickName());
+    }
+
+    @SneakyThrows
+    public void refreshAllAccessToken() {
+        DateTime now = new DateTime();
+        now.setMutable(false);
+        Date expireTime = new DateTime()
+                .offset(DateField.MINUTE, 20)
+                .toJdkDate();
+        String componentAccessToken = wxTicketService.getTicketObject().getComponentAccessToken();
+        //检测快过期的at
+        for (WxAccount wxAccount : wxAccountService.lambdaQuery()
+                .le(WxAccount::getAtExpireTime, expireTime)
+                .list()) {
+
+            String openId = wxAccount.getOpenId();
+
+            WxApiAuthorizerTokenRequest tokenRequest = new WxApiAuthorizerTokenRequest();
+            tokenRequest.setComponentAppid(Constant.wxClientKey);
+            tokenRequest.setComponentAccessToken(componentAccessToken);
+            tokenRequest.setAuthorizerRefreshToken(wxAccount.getRefreshToken());
+            tokenRequest.setAuthorizerAppid(openId);
+            String response = HttpUtil.post("https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?" +
+                            "component_access_token=" + componentAccessToken,
+                    objectMapper.writeValueAsString(tokenRequest));
+            log.info("refreshAllAccessToken openId {} tokenResponse {}", openId,response);
+            WxApiAuthorizerTokenResponse tokenResponse;
+            try {
+                tokenResponse = objectMapper.readValue(response, WxApiAuthorizerTokenResponse.class);
+                if (tokenResponse.hasError()) {
+                    log.error("refreshAllAccessToken openId {} tokenResponse {}", openId,response);
+                    continue;
+                }
+                wxAccount.setAccessToken(tokenResponse.getAuthorizerAccessToken());
+                wxAccount.setRefreshToken(tokenResponse.getAuthorizerRefreshToken());
+                wxAccount.setUpdateTime(now);
+                wxAccount.setRtExpireTime(now.offset(DateField.YEAR, 3));
+                wxAccount.setAtExpireTime(now.offset(DateField.SECOND, tokenResponse.getExpiresIn()));
+                wxAccountService.updateById(wxAccount);
+            } catch (JsonProcessingException e) {
+                log.error(e.getMessage(), e);
+            }
+//            WxApiAuthorizerTokenResponse tokenResponse = template.postForObject(
+//                    "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?" +
+//                            "component_access_token=" + componentAccessToken,
+//                    requestUtil.buildJsonObject(tokenRequest), WxApiAuthorizerTokenResponse.class);
+
+        }
+
+        //刷新v2表的数据
+        for (WxAccountV2 wxAccountV2 : wxAccountV2Service.lambdaQuery()
+                .le(WxAccountV2::getAtExpireTime, expireTime)
+                .list()) {
+            String openId = wxAccountV2.getOpenId();
+            String secret = wxAccountV2.getSecret();
+            String response = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + openId + "&secret=" + secret);
+            log.info("refreshAllAccessTokenV2 appid {} response {}", openId,response);
+            try {
+                JsonNode jsonNode = objectMapper.readTree(response);
+                String accessToken = jsonNode.get("access_token").asText();
+                int expiresIn = jsonNode.get("expires_in").asInt();
+                wxAccountV2.setRefreshToken("");
+                wxAccountV2.setAccessToken(accessToken);
+                wxAccountV2.setUpdateTime(new Date());
+                wxAccountV2.setRtExpireTime(now.offset(DateField.YEAR, 3));
+                wxAccountV2.setAtExpireTime(now.offset(DateField.SECOND, expiresIn));
+                wxAccountV2Service.updateById(wxAccountV2);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+
+        }
+
+    }
+
+    @SneakyThrows
+    public void refreshJsTicket() {
+        Date expireTime = new DateTime()
+                .offset(DateField.MINUTE, 20)
+                .toJdkDate();
+        for (WxAccountV2 wxAccountV2 : wxAccountV2Service.lambdaQuery()
+                .le(WxAccountV2::getJsTicketExpireTime, expireTime)
+                .list()) {
+            String accessToken = wxAccountV2.getAccessToken();
+            String response = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi");
+            log.info("refreshJsTicket response {}",response);
+            JsonNode node = objectMapper.readTree(response).get("ticket");
+            if (node == null) {
+                log.error("refreshJsTicket response {}",response);
+                continue;
+            }
+            String ticket = node.asText();
+            wxAccountV2.setJsTicket(ticket);
+            wxAccountV2.setJsTicketExpireTime(new DateTime()
+                    .offset(DateField.SECOND, 7200)
+                    .toJdkDate());
+            wxAccountV2.setUpdateTime(new Date());
+            wxAccountV2Service.updateById(wxAccountV2);
+        }
+
+    }
+
+
+    @SneakyThrows
+    private static void getJsTicket(String accessToken) {
+        String response = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi");
+        ObjectMapper objectMapper = new ObjectMapper();
+        String ticket = objectMapper.readTree(response).get("ticket").asText();
+        System.out.println(ticket);
+    }
+
+    public static void main(String[] args) throws JsonProcessingException {
+        String response = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + weixinZhiHuiRongMeiAppId + "&secret=" + weixinZhiHuiRongMeiSecret);
+        ObjectMapper objectMapper = new ObjectMapper();
+        String access_token = objectMapper.readTree(response).get("access_token").asText();
+        System.out.println(access_token);
+//        String ak = "49_tJph-qS1EkuDtWcnSQ6JdNGttq4ywCo0jtcY52Z01oFwuPn0T6qsNL8Hqab8fPF4-GY-dpy0WblVv3Aos3NlAxrpQOs8qrYhEm5WvZE0Pb9q7mF031oScoUgvV9WmmNwoHOrgOIfAKeP0lh3RVVhABAYCC";
+        getJsTicket(access_token);
+    }
+
+
+}

+ 27 - 0
src/main/java/com/sxtvs/open/api/odata/service/WxTicketService.java

@@ -0,0 +1,27 @@
+package com.sxtvs.open.api.odata.service;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sxtvs.open.api.odata.dao.WxTicketMapper;
+import com.sxtvs.open.api.odata.entity.WxTicket;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+
+@Service
+public class WxTicketService extends ServiceImpl<WxTicketMapper, WxTicket> {
+    public String getTicket() {
+        return getById(1).getTicket();
+    }
+
+    public WxTicket getTicketObject() {
+        return getById(1);
+    }
+
+    public WxTicket updateComponentAccessToken(String ak, Integer expire) {
+        WxTicket wxTicket = getById(1);
+        wxTicket.setComponentAccessToken(ak);
+        wxTicket.setAtExpireTime(new Date(System.currentTimeMillis() + expire * 1000));
+        updateById(wxTicket);
+        return wxTicket;
+    }
+}

+ 70 - 0
src/main/java/com/sxtvs/open/api/odata/service/YoumeiTokenService.java

@@ -0,0 +1,70 @@
+package com.sxtvs.open.api.odata.service;
+
+import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.http.HttpUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sxtvs.open.api.odata.dao.YoumeiAccountMapper;
+import com.sxtvs.open.api.odata.entity.YoumeiAccount;
+import lombok.SneakyThrows;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.HashMap;
+
+@Service
+public class YoumeiTokenService extends ServiceImpl<YoumeiAccountMapper, YoumeiAccount> {
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @SneakyThrows
+    public void refreshToken() {
+        Date expireTime = new DateTime()
+                .offset(DateField.HOUR, 2)
+                .toJdkDate();
+
+        //检测快过期的at
+        for (YoumeiAccount youmeiAccount : this.lambdaQuery()
+                .le(YoumeiAccount::getAtExpireTime, expireTime)
+                .list()) {
+
+            HashMap<String, Object> params = new HashMap<>();
+            params.put("appId", youmeiAccount.getOpenId());
+            params.put("responseType", "code");
+            params.put("state", "");
+            String body = HttpUtil.post("https://api-open.51wyq.cn/dataapp/api/oauth2/authorize", params);
+            String authorizeCode = objectMapper.readTree(body).get("authorizeCode").get("authorizeCode").asText();
+
+            params.clear();
+            params.put("appId", youmeiAccount.getOpenId());
+            params.put("grantType", "authorization_code");
+            params.put("appSecret", youmeiAccount.getSecret());
+            params.put("authorizeCode", authorizeCode);
+
+            body = HttpUtil.post("https://api-open.51wyq.cn/dataapp/api/oauth2/token", params);
+            JsonNode jsonNode = objectMapper.readTree(body).get("accessToken");
+
+            String accessToken = jsonNode.get("accessToken").asText();
+            long expireIn = jsonNode.get("expireIn").asLong();
+
+            youmeiAccount.setAccessToken(accessToken);
+            youmeiAccount.setAtExpireTime(new Date(expireIn));
+            youmeiAccount.setUpdateTime(new Date());
+
+            this.updateById(youmeiAccount);
+        }
+    }
+
+    public static void main(String[] args) {
+        for (int i = 0; i < 30; i++) {
+            System.out.println(new DateTime()
+                    .offset(DateField.HOUR, i * 2)
+                    .toJdkDate());
+        }
+    }
+
+}

+ 22 - 0
src/main/java/com/sxtvs/open/core/conf/Constant.java

@@ -20,4 +20,26 @@ public class Constant {
     public static final String TOKEN_HEADER_NAME = "Authorization";
     public static final String TOKEN_COOKIE_NAME = "sxtvs-token";
 
+    public static String douyinClientKey = "awfrca76s1petwh0";
+    public static String douyinClientSecret = "4c0bcabf25e937679cdb85cd9cc9a64b";
+
+    public static String kuaishouClientKey = "ks657244072487589897";
+    public static String kuaishouClientSecret = "d-LL1KyA6QSDzJG3AtzKZQ";
+
+    public static String weiboKey = "2787601065";
+    public static String weiboSecret = "3b3dfcd73027ccd29fc7b73fb2242dc2";
+
+    public static String wxClientKey = "wxdca527f24b99b4c0";
+    public static String wxClientSecret = "5bd99087f5eba81711d1f68d77cd4f79";
+
+
+    public static String weixinZhiHuiRongMeiAppId = "wx5e1699e1707030ac";
+    public static String weixinZhiHuiRongMeiSecret = "65c4f421f2bba4cd5d7f1219123e0fd9";
+
+    public static String bilibiliClientId = "e79e6fdef9d446d7";
+    public static String bilibiliSecret = "70d40a332aa54132a72239efba022450";
+
+    public static String weixinWishAppId = "wx8560c9c2e174f07f";
+    public static String weixinWishSecret = "38cb0abbb0fddf94485ee6b13fc31f2d";
+
 }

+ 129 - 0
src/main/java/com/sxtvs/open/core/conf/RestConfig.java

@@ -0,0 +1,129 @@
+package com.sxtvs.open.core.conf;
+
+import cn.hutool.core.io.IoUtil;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import com.sxtvs.open.api.odata.dto.douyin.DouyinCommonResponse;
+import com.sxtvs.open.api.odata.dto.kuaishou.KuaishouCommonResponse;
+import com.sxtvs.open.api.odata.dto.wx.WxCommonResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.client.BufferingClientHttpRequestFactory;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.web.client.ResponseErrorHandler;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
+
+import java.io.IOException;
+
+@Configuration
+@Slf4j
+public class RestConfig {
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+
+    @Bean("douyinRestTemplate")
+    public RestTemplate template() {
+
+        RestTemplate restTemplate = getTemplate();
+
+        restTemplate.setErrorHandler(new ResponseErrorHandler() {
+            @Override
+            public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
+
+                int rawStatusCode = clientHttpResponse.getRawStatusCode();
+                String body = IoUtil.read(clientHttpResponse.getBody(), false).toString();
+                // 不是200的直接拿去重试
+                if (rawStatusCode != 200) {
+                    throw new RestClientException(body);
+                }
+                DouyinCommonResponse douyinCommonResponse = objectMapper.readValue(body,
+                        DouyinCommonResponse.class);
+                if (douyinCommonResponse.hasError()) {
+                    throw new RuntimeException(body);
+                }
+                return false;
+            }
+
+            @Override
+            public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
+            }
+        });
+        return restTemplate;
+    }
+
+    @Bean("weixinRestTemplate")
+    public RestTemplate weixinTemplate() {
+
+        RestTemplate restTemplate = getTemplate();
+
+        restTemplate.setErrorHandler(new ResponseErrorHandler() {
+            @Override
+            public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
+
+                int rawStatusCode = clientHttpResponse.getRawStatusCode();
+                String body = IoUtil.read(clientHttpResponse.getBody(), false).toString();
+                // 不是200的直接拿去重试
+                if (rawStatusCode != 200) {
+                    throw new RestClientException(body);
+                }
+                WxCommonResponse douyinCommonResponse = objectMapper.readValue(body,
+                        WxCommonResponse.class);
+                if (douyinCommonResponse.hasError()) {
+                    throw new RuntimeException(body);
+                }
+                return false;
+            }
+
+            @Override
+            public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
+            }
+        });
+        return restTemplate;
+    }
+
+
+    @Bean("kuaishouRestTemplate")
+    public RestTemplate kuaishou() {
+
+        RestTemplate restTemplate = getTemplate();
+
+        restTemplate.setErrorHandler(new ResponseErrorHandler() {
+            @Override
+            public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
+
+                int rawStatusCode = clientHttpResponse.getRawStatusCode();
+                String body = IoUtil.read(clientHttpResponse.getBody(), false).toString();
+                // 不是200的直接拿去重试
+                if (rawStatusCode != 200) {
+                    throw new RestClientException(body);
+                }
+                KuaishouCommonResponse kuaishouCommonResponse = objectMapper.readValue(body,
+                        KuaishouCommonResponse.class);
+                if (kuaishouCommonResponse.hasError()) {
+                    throw new RuntimeException(body);
+                }
+                return false;
+            }
+
+            @Override
+            public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
+            }
+        });
+        return restTemplate;
+    }
+
+    private RestTemplate getTemplate() {
+        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
+        requestFactory.setConnectTimeout(5000);// 设置超时
+        requestFactory.setReadTimeout(5000);
+        BufferingClientHttpRequestFactory bufferingClientHttpRequestFactory = new BufferingClientHttpRequestFactory(requestFactory);
+
+        return new RestTemplate(bufferingClientHttpRequestFactory);
+    }
+}

+ 64 - 0
src/main/java/com/sxtvs/open/core/http/APIResponseAdvice.java

@@ -0,0 +1,64 @@
+package com.sxtvs.open.core.http;
+
+import com.sxtvs.open.core.advice.APIResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.FieldError;
+import org.springframework.validation.ObjectError;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import java.util.List;
+
+@RestControllerAdvice
+@Slf4j
+public class APIResponseAdvice  {
+
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    public APIResponse validError(MethodArgumentNotValidException ex) {
+        log.error("校验未通过", ex);
+        BindingResult result = ex.getBindingResult();
+        StringBuilder builder = new StringBuilder();
+        if (result.hasErrors()) {
+
+            List<ObjectError> errors = result.getAllErrors();
+
+            errors.forEach(p -> {
+
+                FieldError fieldError = (FieldError) p;
+                builder.append(fieldError.getDefaultMessage()).append(";");
+                log.error("Data check failure : object{" + fieldError.getObjectName() + "},field{" + fieldError.getField() +
+                        "},errorMessage{" + fieldError.getDefaultMessage() + "}");
+
+            });
+
+        }
+
+        APIResponse apiResponse = new APIResponse();
+        apiResponse.setCode(-1);
+
+        apiResponse.setMessage(builder.toString());
+        return apiResponse;
+    }
+
+    /**
+     * 拦截未知的运行时异常
+     *
+     * @author fengshuonan
+     * @date 2020/12/16 15:12
+     */
+    @ExceptionHandler(Throwable.class)
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    public APIResponse serverError(Throwable ex) {
+        log.error("服务器运行异常", ex);
+        APIResponse apiResponse = new APIResponse();
+        apiResponse.setCode(-1);
+        apiResponse.setMessage(ex.getMessage());
+        return apiResponse;
+    }
+
+}

+ 40 - 0
src/main/java/com/sxtvs/open/core/http/RequestUtil.java

@@ -0,0 +1,40 @@
+package com.sxtvs.open.core.http;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.SneakyThrows;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+
+import java.util.HashMap;
+
+@Component
+public class RequestUtil {
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @SneakyThrows
+    public HttpEntity<String> buildJsonObject(Object object) {
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        String json = objectMapper.writeValueAsString(object);
+        return new HttpEntity<>(json, headers);
+    }
+
+
+    @SneakyThrows
+    public HttpEntity<MultiValueMap<String, String>> buildFormObject(HashMap<String, String> map) {
+        LinkedMultiValueMap<String, String> lmvm = new LinkedMultiValueMap<>();
+        map.forEach(lmvm::add);
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+        return new HttpEntity<>(lmvm, headers);
+    }
+
+
+}

+ 15 - 0
src/main/java/com/sxtvs/open/core/http/WxRedirectView.java

@@ -0,0 +1,15 @@
+package com.sxtvs.open.core.http;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.web.servlet.view.RedirectView;
+
+import java.io.IOException;
+
+public class WxRedirectView extends RedirectView {
+    @Override
+    protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String targetUrl, boolean http10Compatible) throws IOException {
+//        request.
+        super.sendRedirect(request, response, targetUrl, http10Compatible);
+    }
+}

+ 39 - 0
src/main/java/com/sxtvs/open/core/lock/SegmentLock.java

@@ -0,0 +1,39 @@
+package com.sxtvs.open.core.lock;
+
+import java.util.HashMap;
+import java.util.concurrent.locks.ReentrantLock;
+
+
+public class SegmentLock<T> {
+    private Integer segments = 16;//默认分段数量
+    private final HashMap<Integer, ReentrantLock> lockMap = new HashMap<>();
+
+    public SegmentLock() {
+        init(null, false);
+    }
+
+    public SegmentLock(Integer counts, boolean fair) {
+        init(counts, fair);
+    }
+
+    private void init(Integer counts, boolean fair) {
+        if (counts != null) {
+            segments = counts;
+        }
+        for (int i = 0; i < segments; i++) {
+            lockMap.put(i, new ReentrantLock(fair));
+        }
+    }
+
+    public void lock(T key) {
+        ReentrantLock lock = lockMap.get((key.hashCode() >>> 1) % segments);
+        lock.lock();
+    }
+
+    public void unlock(T key) {
+        ReentrantLock lock = lockMap.get((key.hashCode() >>> 1) % segments);
+        lock.unlock();
+    }
+
+
+}

+ 13 - 3
src/test/data-service.http

@@ -8,8 +8,8 @@ Content-Type: application/json;charset=UTF-8
 }
 
 ### 热榜
-GET http://localhost/news/hotRank/list
-Authorization: b6af95077bafeccb32ae7a65dadee47d
+GET http://localhost/news/hotRank/list?province=陕西
+Authorization: 9a95c736798afd0fd984ef5d981c163a
 
 ### 搜索
 POST http://localhost/news/data/search
@@ -18,7 +18,7 @@ Authorization: b6af95077bafeccb32ae7a65dadee47d
 
 {
 "keywords": "",
-  "city": "安徽省,安庆市",
+  "city": "陕西省,西安市",
   "start": "2023-01-01 15:52:52",
   "end": "2023-02-25 15:52:52",
   "page": 0,
@@ -31,3 +31,13 @@ GET http://localhost/news/data/put/MWEZOWQ2NDYXMJU0NW
 
 ### 分类
 GET http://localhost/news/data/category
+
+
+### 省
+GET http://localhost/news/area/province
+
+### 城市
+GET http://localhost/news/area/city?pid=017
+
+### 省市区
+GET http://localhost/news/area/list

+ 0 - 3
src/test/java/com/sxtvs/open/EsClientTests.java

@@ -3,13 +3,10 @@ package com.sxtvs.open;
 import co.elastic.clients.elasticsearch.ElasticsearchClient;
 import co.elastic.clients.elasticsearch._types.SortOptions;
 import co.elastic.clients.elasticsearch._types.SortOrder;
-import co.elastic.clients.elasticsearch._types.query_dsl.MatchAllQuery;
-import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
 import co.elastic.clients.elasticsearch._types.query_dsl.MultiMatchQuery;
 import co.elastic.clients.elasticsearch._types.query_dsl.Query;
 import co.elastic.clients.elasticsearch.core.*;
 import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
-import co.elastic.clients.elasticsearch.core.search.Hit;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.sxtvs.open.api.news.entity.YoumeiData;

+ 1 - 1
src/test/java/com/sxtvs/open/GenCode.java

@@ -48,7 +48,7 @@ public class GenCode {
                                     "D:\\dev\\java\\open\\src\\main\\resources\\com\\sxtvs")); // 设置mapperXml生成路径
                 })
                 .strategyConfig(builder -> {
-                    builder.addInclude("youmei_offset"); // 设置需要生成的表名
+                    builder.addInclude("area"); // 设置需要生成的表名
                     builder.controllerBuilder().enableRestStyle();
                     builder.entityBuilder().enableLombok();
                 })