|
@@ -0,0 +1,266 @@
|
|
|
+package com.tzld.longarticle.recommend.server.service.recommend;
|
|
|
+
|
|
|
+import cn.hutool.core.collection.CollectionUtil;
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.google.common.collect.Lists;
|
|
|
+import com.tzld.longarticle.recommend.server.common.enums.StatusEnum;
|
|
|
+import com.tzld.longarticle.recommend.server.common.enums.aigc.PushTypeEnum;
|
|
|
+import com.tzld.longarticle.recommend.server.common.enums.recommend.ArticleDeleteStatusEnum;
|
|
|
+import com.tzld.longarticle.recommend.server.common.enums.recommend.FeishuRobotIdEnum;
|
|
|
+import com.tzld.longarticle.recommend.server.mapper.aigc.AigcBaseMapper;
|
|
|
+import com.tzld.longarticle.recommend.server.model.dto.*;
|
|
|
+import com.tzld.longarticle.recommend.server.model.entity.aigc.PublishAccount;
|
|
|
+import com.tzld.longarticle.recommend.server.model.entity.crawler.Article;
|
|
|
+import com.tzld.longarticle.recommend.server.model.entity.longArticle.*;
|
|
|
+import com.tzld.longarticle.recommend.server.model.param.ArticleDangerFindDeleteParam;
|
|
|
+import com.tzld.longarticle.recommend.server.model.param.ArticleVideoAuditResultParam;
|
|
|
+import com.tzld.longarticle.recommend.server.model.param.PublishContentParam;
|
|
|
+import com.tzld.longarticle.recommend.server.remote.WxAccessTokenRemoteService;
|
|
|
+import com.tzld.longarticle.recommend.server.remote.WxArticleDeleteService;
|
|
|
+import com.tzld.longarticle.recommend.server.repository.aigc.PublishAccountRepository;
|
|
|
+import com.tzld.longarticle.recommend.server.repository.crawler.ArticleRepository;
|
|
|
+import com.tzld.longarticle.recommend.server.repository.longArticle.*;
|
|
|
+import com.tzld.longarticle.recommend.server.util.DateUtils;
|
|
|
+import com.tzld.longarticle.recommend.server.util.Md5Util;
|
|
|
+import com.tzld.longarticle.recommend.server.util.feishu.FeishuMessageSender;
|
|
|
+import com.xxl.job.core.biz.model.ReturnT;
|
|
|
+import com.xxl.job.core.handler.annotation.XxlJob;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.collections4.CollectionUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+import java.util.function.Function;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+public class ArticleAuditService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private GetOffVideoArticleRepository getOffVideoArticleRepository;
|
|
|
+ @Autowired
|
|
|
+ private LongArticlesMatchVideoRepository longArticlesMatchVideoRepository;
|
|
|
+ @Autowired
|
|
|
+ private LongArticleCrawlerVideoRepository longArticleCrawlerVideoRepository;
|
|
|
+ @Autowired
|
|
|
+ private LongArticleAuditDeleteRepository longArticleAuditDeleteRepository;
|
|
|
+ @Autowired
|
|
|
+ private LongArticleVideoAuditRepository longArticleVideoAuditRepository;
|
|
|
+ @Autowired
|
|
|
+ private WxArticleDeleteService wxArticleDeleteService;
|
|
|
+ @Autowired
|
|
|
+ private WxAccessTokenRemoteService wxAccessTokenRemoteService;
|
|
|
+ @Autowired
|
|
|
+ private AigcBaseMapper aigcBaseMapper;
|
|
|
+ @Autowired
|
|
|
+ private PublishAccountRepository publishAccountRepository;
|
|
|
+ @Autowired
|
|
|
+ private ArticleRepository articleRepository;
|
|
|
+ @Autowired
|
|
|
+ private ArticleUnsafeTitleRepository articleUnsafeTitleRepository;
|
|
|
+
|
|
|
+
|
|
|
+ @XxlJob("articleVideoAudit")
|
|
|
+ public ReturnT<String> articleVideoAudit(String param) {
|
|
|
+ long publishTime = DateUtils.getTodayStart();
|
|
|
+ if (StringUtils.hasText(param)) {
|
|
|
+ publishTime = DateUtils.getStartOfDay(param, "yyyyMMdd");
|
|
|
+ }
|
|
|
+ List<GetOffVideoArticle> getOffVideoArticleList = getOffVideoArticleRepository.getByPublishTimeGreaterThanEqual(publishTime);
|
|
|
+ List<String> traceIds = getOffVideoArticleList.stream().map(GetOffVideoArticle::getTraceId).distinct().collect(Collectors.toList());
|
|
|
+ if (CollectionUtil.isEmpty(traceIds)) {
|
|
|
+ return ReturnT.SUCCESS;
|
|
|
+ }
|
|
|
+ List<LongArticlesMatchVideo> longArticlesMatchVideoList = longArticlesMatchVideoRepository.getByTraceIdIn(traceIds);
|
|
|
+ Map<String, LongArticlesMatchVideo> longarticlesMatchVideoMap = longArticlesMatchVideoList.stream()
|
|
|
+ .collect(Collectors.toMap(LongArticlesMatchVideo::getTraceId, Function.identity()));
|
|
|
+ for (String traceId : traceIds) {
|
|
|
+ LongArticlesMatchVideo longArticlesMatchVideo = longarticlesMatchVideoMap.get(traceId);
|
|
|
+ List<LongArticlesMatchVideoResponse> responseList = JSONArray.parseArray(longArticlesMatchVideo.getResponse()
|
|
|
+ , LongArticlesMatchVideoResponse.class);
|
|
|
+ List<Long> videoIds = responseList.stream().map(LongArticlesMatchVideoResponse::getVideoID).collect(Collectors.toList());
|
|
|
+ List<LongArticleVideoAudit> existsList = longArticleVideoAuditRepository.getByVideoIdIn(videoIds);
|
|
|
+ List<Long> existsVideoIds = existsList.stream().map(LongArticleVideoAudit::getVideoId).collect(Collectors.toList());
|
|
|
+ for (LongArticlesMatchVideoResponse response : responseList) {
|
|
|
+ if (existsVideoIds.contains(response.getVideoID())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ LongArticleVideoAudit videoAudit = new LongArticleVideoAudit();
|
|
|
+ videoAudit.setVideoId(response.getVideoID());
|
|
|
+ videoAudit.setTraceId(traceId);
|
|
|
+ videoAudit.setContentId(longArticlesMatchVideo.getContentId());
|
|
|
+ videoAudit.setOssPath(response.getVideoOSS());
|
|
|
+ videoAudit.setStatus(StatusEnum.ZERO.getCode());
|
|
|
+ videoAudit.setCreateTimestamp(System.currentTimeMillis());
|
|
|
+ longArticleVideoAuditRepository.save(videoAudit);
|
|
|
+ // todo 调用PQ 审核视频
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return ReturnT.SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 视频审核结果处理
|
|
|
+ */
|
|
|
+ public void articleVideoAuditResult(ArticleVideoAuditResultParam param) {
|
|
|
+ LongArticleVideoAudit longArticleVideoAudit = longArticleVideoAuditRepository.getByVideoId(param.getVideoId());
|
|
|
+ if (param.getResult() == 1) {
|
|
|
+ // 审核通过,更新文章状态
|
|
|
+ longArticleVideoAudit.setStatus(ArticleDeleteStatusEnum.SUCCESS.getCode());
|
|
|
+ longArticleVideoAudit.setFinishTimestamp(System.currentTimeMillis());
|
|
|
+ longArticleVideoAuditRepository.save(longArticleVideoAudit);
|
|
|
+ } else {
|
|
|
+ // 审核不通过,删除文章
|
|
|
+ longArticleVideoAudit.setStatus(ArticleDeleteStatusEnum.FAIL.getCode());
|
|
|
+ longArticleVideoAudit.setFailReason(param.getFailReason());
|
|
|
+ longArticleVideoAudit.setFinishTimestamp(System.currentTimeMillis());
|
|
|
+ longArticleVideoAuditRepository.save(longArticleVideoAudit);
|
|
|
+ // 构建删除文章记录 并保存
|
|
|
+ saveDeleteRecord(longArticleVideoAudit.getOssPath());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void saveDeleteRecord(String ossPath) {
|
|
|
+ List<LongArticleCrawlerVideo> crawlerVideoList = longArticleCrawlerVideoRepository.getByVideoOssPath(ossPath);
|
|
|
+ List<String> traceIds = crawlerVideoList.stream().map(LongArticleCrawlerVideo::getTraceId).collect(Collectors.toList());
|
|
|
+ List<PublishContentMiniprogramDTO> publishContentList = aigcBaseMapper.getPublishContentByTraceIdIn(traceIds);
|
|
|
+ List<String> publishContentIds = publishContentList.stream().map(PublishContentMiniprogramDTO::getPublishContentId).collect(Collectors.toList());
|
|
|
+ buildArticleAuditDelete(publishContentIds);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void buildArticleAuditDelete(List<String> publishContentIds) {
|
|
|
+ List<PublishGzhPushContentRelDTO> pushContentRelList = aigcBaseMapper.getPushContentRelByPublishContentIdIn(publishContentIds);
|
|
|
+ List<String> pushIds = pushContentRelList.stream().map(PublishGzhPushContentRelDTO::getPushId).collect(Collectors.toList());
|
|
|
+ Map<String, String> publishPushIdMap = pushContentRelList.stream()
|
|
|
+ .collect(Collectors.toMap(PublishGzhPushContentRelDTO::getPublishContentId, PublishGzhPushContentRelDTO::getPushId));
|
|
|
+ List<PublishGzhPushDTO> pushList = aigcBaseMapper.getPushByPushIdIn(pushIds);
|
|
|
+ Map<String, PublishGzhPushDTO> pushDTOMap = pushList.stream()
|
|
|
+ .collect(Collectors.toMap(PublishGzhPushDTO::getPushId, Function.identity()));
|
|
|
+ Map<String, String> pushIdMap = pushList.stream()
|
|
|
+ .collect(Collectors.toMap(PublishGzhPushDTO::getPushId, PublishGzhPushDTO::getGroupPushMsgId));
|
|
|
+ List<String> publishAccountIds = pushList.stream().map(PublishGzhPushDTO::getPublishAccountId).collect(Collectors.toList());
|
|
|
+ Map<String, String> pushAccountMap = pushList.stream()
|
|
|
+ .collect(Collectors.toMap(PublishGzhPushDTO::getPushId, PublishGzhPushDTO::getPublishAccountId));
|
|
|
+ List<PublishAccount> publishAccountList = publishAccountRepository.getByIdIn(publishAccountIds);
|
|
|
+ Map<String, String> publishAccountMap = publishAccountList.stream()
|
|
|
+ .collect(Collectors.toMap(PublishAccount::getId, PublishAccount::getGhId));
|
|
|
+ List<PublishGzhPushContentRelDTO> groupPushRelList = aigcBaseMapper.getGroupPushRelByPushIdIn(pushIds);
|
|
|
+ Map<String, List<PublishGzhPushContentRelDTO>> groupPushRelMap = groupPushRelList.stream()
|
|
|
+ .collect(Collectors.groupingBy(PublishGzhPushContentRelDTO::getPushId));
|
|
|
+ // 删除文章
|
|
|
+ for (String publishContentId : publishContentIds) {
|
|
|
+ String pushId = publishPushIdMap.get(publishContentId);
|
|
|
+ if (!StringUtils.hasText(pushId)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ PublishGzhPushDTO publishGzhPushDTO = pushDTOMap.get(pushId);
|
|
|
+ if (Objects.isNull(publishGzhPushDTO)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String groupPushMsgId = pushIdMap.get(pushId);
|
|
|
+ String publishAccountId = pushAccountMap.get(pushId);
|
|
|
+ String ghId = publishAccountMap.get(publishAccountId);
|
|
|
+ List<PublishGzhPushContentRelDTO> relList = groupPushRelMap.get(pushId).stream()
|
|
|
+ .sorted(Comparator.comparing(PublishGzhPushContentRelDTO::getId)).collect(Collectors.toList());
|
|
|
+ int index = 1;
|
|
|
+ for (int i = 0; i < relList.size(); i++) {
|
|
|
+ if (relList.get(i).getPublishContentId().equals(publishContentId)) {
|
|
|
+ index = i + 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ LongArticleAuditDelete delete = new LongArticleAuditDelete();
|
|
|
+ delete.setGhId(ghId);
|
|
|
+ delete.setMsgId(groupPushMsgId);
|
|
|
+ delete.setPushId(pushId);
|
|
|
+ delete.setPushType(publishGzhPushDTO.getPushType());
|
|
|
+ delete.setPublishContentId(publishContentId);
|
|
|
+ delete.setIndex(index);
|
|
|
+ delete.setStatus(StatusEnum.ZERO.getCode());
|
|
|
+ delete.setCreateTimestamp(System.currentTimeMillis());
|
|
|
+ longArticleAuditDeleteRepository.save(delete);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除审核不通过,已发布文章
|
|
|
+ */
|
|
|
+ @XxlJob("articleVideoDelete")
|
|
|
+ public ReturnT<String> articleVideoDelete(String param) {
|
|
|
+ List<LongArticleAuditDelete> dealList = longArticleAuditDeleteRepository.getByStatus(ArticleDeleteStatusEnum.WAITING.getCode());
|
|
|
+ for (LongArticleAuditDelete delete : dealList) {
|
|
|
+ if (Objects.equals(delete.getPushType(), PushTypeEnum.AUTO_GROUP_PUBLISH.getVal())) {
|
|
|
+ // 获取token
|
|
|
+ String token = wxAccessTokenRemoteService.getAccessToken(delete.getGhId());
|
|
|
+ // 删除文章
|
|
|
+ RequestResult<String> result = wxArticleDeleteService.deleteArticle(token, delete.getMsgId(), delete.getIndex());
|
|
|
+ if (result.isSuccess()) {
|
|
|
+ delete.setStatus(ArticleDeleteStatusEnum.SUCCESS.getCode());
|
|
|
+ } else {
|
|
|
+ delete.setStatus(ArticleDeleteStatusEnum.FAIL.getCode());
|
|
|
+ delete.setFailReason(result.getFailReason());
|
|
|
+ delete.setFinishTimestamp(System.currentTimeMillis());
|
|
|
+ }
|
|
|
+ longArticleAuditDeleteRepository.save(delete);
|
|
|
+ } else {
|
|
|
+ PublishAccount publishAccount = publishAccountRepository.getByGhId(delete.getGhId());
|
|
|
+ PublishContentDTO publishContent = aigcBaseMapper.getPublishContentById(delete.getPublishContentId());
|
|
|
+ String publishTime = DateUtils.timestampToYMDStr(publishContent.getPublishTimestamp() / 1000, "yyyyMMdd");
|
|
|
+ // 无法自动删除 发送飞书通知 人工删除
|
|
|
+ FeishuMessageSender.sendWebHookMessage(FeishuRobotIdEnum.ARTICLE_DELETE.getRobotId(),
|
|
|
+ "视频审核不通过文章删除\n"
|
|
|
+ + "账号名称: " + publishAccount.getName() + "\n"
|
|
|
+ + "发布日期: " + publishTime + "\n"
|
|
|
+ + "位置: " + delete.getIndex() + "\n"
|
|
|
+ + "标题: " + publishContent.getTitle());
|
|
|
+
|
|
|
+ delete.setStatus(ArticleDeleteStatusEnum.SUCCESS.getCode());
|
|
|
+ longArticleAuditDeleteRepository.save(delete);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ReturnT.SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void titleDangerFindDelete(ArticleDangerFindDeleteParam param) {
|
|
|
+ String titleMd5 = Md5Util.encoderByMd5(param.getTitle());
|
|
|
+ // 根据标题查找已发布文章
|
|
|
+ List<Article> articleList = articleRepository.getByTitleMd5(titleMd5);
|
|
|
+ List<String> ghIds = articleList.stream().map(Article::getGhId).distinct().collect(Collectors.toList());
|
|
|
+ List<PublishAccount> publishAccountList = publishAccountRepository.getAllByGhIdIn(ghIds);
|
|
|
+ List<PublishContentParam> publishContentParamList = publishAccountList.stream().map(account -> {
|
|
|
+ PublishContentParam item = new PublishContentParam();
|
|
|
+ item.setTitle(param.getTitle());
|
|
|
+ item.setPublishAccountId(account.getId());
|
|
|
+ return item;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ List<PublishContentDTO> publishContents = new ArrayList<>();
|
|
|
+ for (List<PublishContentParam> partitions : Lists.partition(publishContentParamList, 100)) {
|
|
|
+ publishContents.addAll(aigcBaseMapper.getPublishContentByTitle(partitions));
|
|
|
+ }
|
|
|
+ if (CollectionUtils.isEmpty(publishContents)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 查找该生成内容下所有已发布内容
|
|
|
+ List<String> sourceIds = publishContents.stream().map(PublishContentDTO::getSourceId).distinct().collect(Collectors.toList());
|
|
|
+ publishContents = aigcBaseMapper.getPublishContentBySourceIdIn(sourceIds);
|
|
|
+
|
|
|
+ // 根据已发布文章查找推送id 并删除
|
|
|
+ List<String> publishContentIds = publishContents.stream().map(PublishContentDTO::getId).collect(Collectors.toList());
|
|
|
+ buildArticleAuditDelete(publishContentIds);
|
|
|
+ buildArticleUnsafeTitle(titleMd5, param.getTitle());
|
|
|
+ }
|
|
|
+
|
|
|
+ private void buildArticleUnsafeTitle(String titleMd5, String title) {
|
|
|
+ ArticleUnsafeTitle unsafeTitle = new ArticleUnsafeTitle();
|
|
|
+ unsafeTitle.setTitle(title);
|
|
|
+ unsafeTitle.setTitleMd5(titleMd5);
|
|
|
+ unsafeTitle.setStatus(StatusEnum.ONE.getCode());
|
|
|
+ unsafeTitle.setCreateTimestamp(System.currentTimeMillis());
|
|
|
+ articleUnsafeTitleRepository.save(unsafeTitle);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|