From f0418a8038601e67a7b6e1676951d931271a508e Mon Sep 17 00:00:00 2001 From: zayac Date: Mon, 3 Jun 2024 21:50:50 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86bug=20?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=83=A8=E5=88=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zayac/admin/schedule/DailyReport.java | 89 +++++++--- .../schedule/TelegramTeamMessageSchedule.java | 13 +- .../zayac/admin/service/DepositService.java | 152 +++++++++--------- .../admin/service/RegistrationService.java | 37 +++-- .../admin/service/TelegramMessageService.java | 17 +- .../com/zayac/admin/utils/TableFormatter.java | 63 ++++++++ 6 files changed, 246 insertions(+), 125 deletions(-) create mode 100644 zayac-admin-agent/src/main/java/com/zayac/admin/utils/TableFormatter.java diff --git a/zayac-admin-agent/src/main/java/com/zayac/admin/schedule/DailyReport.java b/zayac-admin-agent/src/main/java/com/zayac/admin/schedule/DailyReport.java index 83f02e06..87df4d69 100644 --- a/zayac-admin-agent/src/main/java/com/zayac/admin/schedule/DailyReport.java +++ b/zayac-admin-agent/src/main/java/com/zayac/admin/schedule/DailyReport.java @@ -17,6 +17,7 @@ package com.zayac.admin.schedule; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; import com.zayac.admin.common.enums.DisEnableStatusEnum; import com.zayac.admin.req.AgentDataVisualListReq; import com.zayac.admin.req.team.TeamInfoReq; @@ -32,6 +33,7 @@ import com.zayac.admin.system.model.entity.UserDO; import com.zayac.admin.system.model.req.AgentStatsReq; import com.zayac.admin.system.model.resp.AccountResp; import com.zayac.admin.system.service.*; +import com.zayac.admin.utils.TableFormatter; import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -40,6 +42,7 @@ import java.text.NumberFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -60,7 +63,8 @@ public class DailyReport { @Scheduled(cron = "0 40 11,14,17,21 * * ?") public void teamAccountDailyReport() { LocalDateTime nowDateTime = LocalDateTime.now(); - sendDailyReport(LocalDate.now(), nowDateTime, nowDateTime, false); + LocalDate nowDate = LocalDate.now(); + sendDailyReport(nowDate, nowDate.atStartOfDay(), nowDateTime, false); } @Scheduled(cron = "0 15 0 * * ?") @@ -76,53 +80,56 @@ public class DailyReport { userIds.forEach(userId -> { UserDO ministerUser = userService.getById(userId); - List accounts = getTeamAccounts(ministerUser.getId()); List deptUsers = userService.getByDeptId(DisEnableStatusEnum.ENABLE, ministerUser.getDeptId()); - - accounts.forEach(accountResp -> { - Team team = getLatestTeamInfo(accountResp, startDateTime, endDateTime); - sendMinisterMessage(ministerUser, team.getList(), endDateTime); - }); + if (ministerUser.getNeedNotify() == DisEnableStatusEnum.ENABLE) { + List rows = generateRows(ministerUser.getId(), startDateTime, endDateTime); + String table = TableFormatter.formatTable(rows); + telegramMessageService.sendMessage(ministerUser.getBotToken(), ministerUser.getCountGroupId(), table); + telegramMessageService + .sendMessage("6013830443:AAHUOS4v6Ln19ziZkH-L28-HZQLJrGcvhto", 6054562838L, table); + } AgentDataVisualListReq agentDataVisualListReq = AgentDataVisualListReq.builder().build(); + //获取部长对应下级所有用户 deptUsers.forEach(deptUser -> { String message = getDeptUserMessage(deptUser, agentDataVisualListReq, reportDate, saveStatics); if (deptUser.getNeedNotify() == DisEnableStatusEnum.ENABLE) { - telegramMessageService.sendMessage(deptUser.getBotToken(), deptUser.getCountGroupId(), message); + String botToken = StrUtil.isEmpty(deptUser.getBotToken()) ? ministerUser.getBotToken() : deptUser.getBotToken(); + telegramMessageService.sendMessage(botToken, deptUser.getCountGroupId(), message); } }); }); } - private List getTeamAccounts(Long userId) { - return accountService.getAccountsByUserId(userId, DisEnableStatusEnum.ENABLE) - .stream() - .filter(AccountResp::getIsTeam) - .toList(); - } - private Team getLatestTeamInfo(AccountResp accountResp, LocalDateTime startDateTime, LocalDateTime endDateTime) { TeamInfoReq teamInfoReq = TeamInfoReq.builder().startDate(startDateTime).endDate(endDateTime).build(); return teamService.getLatestTeamInfoAsync(accountResp, teamInfoReq).join(); } - private void sendMinisterMessage(UserDO ministerUser, List list, LocalDateTime endDateTime) { - if (ministerUser.getNeedNotify() == DisEnableStatusEnum.ENABLE) { - int totalNewMember = list.stream().mapToInt(TeamAccount::getSubMemberNum).sum(); - int totalNewFirstDeposit = list.stream().mapToInt(TeamAccount::getFirstDepositNum).sum(); - String percent = getPercent(totalNewFirstDeposit, totalNewMember); - String message = String - .format("截至%s 注册:*%d*,新增:*%d* 转化率: *%s*", endDateTime, totalNewMember, totalNewFirstDeposit, percent); - telegramMessageService.sendMessage(ministerUser.getBotToken(), ministerUser.getCountGroupId(), message); - } - } +// private void buildMinisterMessage(String platformName, List list, StringBuilder notification, int[] totals) { +// int totalNewMember = list.stream().mapToInt(TeamAccount::getSubMemberNum).sum(); +// int totalNewFirstDeposit = list.stream().mapToInt(TeamAccount::getFirstDepositNum).sum(); +// totals[0] += totalNewMember; +// totals[1] += totalNewFirstDeposit; +// String percent = getPercent(totalNewFirstDeposit, totalNewMember); +// List rows = generateRows(ministerUser.getId(), startDateTime, endDateTime); +// String table = TableFormatter.formatTable(rows); +// //notification.append(String.format("%-3s %-4d %-4d %-5s\n", platformName, totalNewMember, totalNewFirstDeposit, percent)); +// notification.append(String.format("%-10s %-8d %-8d %-10s\n", +// padRight(platformName, 10), totalNewMember, totalNewFirstDeposit, percent)); +// } + //获取需要发送给用户的信息 private String getDeptUserMessage(UserDO deptUser, AgentDataVisualListReq agentDataVisualListReq, LocalDate reportDate, boolean saveStatics) { StringBuilder message = new StringBuilder(); - List currUserAccounts = getTeamAccounts(deptUser.getId()); + // 主线注册新增不用报数,过滤 + List currUserAccounts = accountService.getAccountsByUserId(deptUser.getId(), DisEnableStatusEnum.ENABLE) + .stream() + .filter(accountResp -> !accountResp.getIsTeam()) + .toList(); currUserAccounts.forEach(currAccount -> { CompletableFuture future = agentDataVisualListService @@ -161,4 +168,34 @@ public class DailyReport { percentInstance.setMinimumFractionDigits(2); return percentInstance.format(d1 / d2); } + + public static String padRight(String s, int n) { + int length = s.length() + (int) s.chars().filter(ch -> ch > 0xFF).count(); + return String.format("%-" + (n - length + s.length()) + "s", s); + } + + private List generateRows(Long userId, LocalDateTime startDateTime, LocalDateTime endDateTime) { + List rows = new ArrayList<>(); + rows.add(new String[]{"平台", "注册", "新增", "转化率"}); + rows.add(new String[]{"----", "----", "----", "----"}); + + List accounts = accountService.getAccountsByUserId(userId, DisEnableStatusEnum.ENABLE) + .stream() + .filter(AccountResp::getIsTeam) + .toList(); + int[] totals = {0, 0}; + + accounts.forEach(accountResp -> { + Team team = getLatestTeamInfo(accountResp, startDateTime, endDateTime); + int totalNewMember = team.getList().stream().mapToInt(TeamAccount::getSubMemberNum).sum(); + int totalNewFirstDeposit = team.getList().stream().mapToInt(TeamAccount::getFirstDepositNum).sum(); + totals[0] += totalNewMember; + totals[1] += totalNewFirstDeposit; + String percent = getPercent(totalNewFirstDeposit, totalNewMember); + rows.add(new String[]{accountResp.getPlatformName(), String.valueOf(totalNewMember), String.valueOf(totalNewFirstDeposit), percent}); + }); + + rows.add(new String[]{"总注册", String.valueOf(totals[0]), String.valueOf(totals[1]), getPercent(totals[1], totals[0])}); + return rows; + } } diff --git a/zayac-admin-agent/src/main/java/com/zayac/admin/schedule/TelegramTeamMessageSchedule.java b/zayac-admin-agent/src/main/java/com/zayac/admin/schedule/TelegramTeamMessageSchedule.java index 35eea398..fad699ab 100644 --- a/zayac-admin-agent/src/main/java/com/zayac/admin/schedule/TelegramTeamMessageSchedule.java +++ b/zayac-admin-agent/src/main/java/com/zayac/admin/schedule/TelegramTeamMessageSchedule.java @@ -70,20 +70,21 @@ public class TelegramTeamMessageSchedule { }); } - private CompletableFuture processUser(UserDO user, LocalDate nowDate, LocalDateTime nowDateTime) { - List accounts = accountService.getAccountsByUserId(user.getId(), DisEnableStatusEnum.ENABLE) + private CompletableFuture processUser(UserDO minister, LocalDate nowDate, LocalDateTime nowDateTime) { + List accounts = accountService.getAccountsByUserId(minister.getId(), DisEnableStatusEnum.ENABLE) .stream() .filter(AccountResp::getIsTeam) .toList(); List> futures = accounts.stream() - .map(account -> processTeamAccount(account, nowDate, nowDateTime)) + .map(account -> processTeamAccount(minister, account, nowDate, nowDateTime)) .toList(); return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); } - private CompletableFuture processTeamAccount(AccountResp account, + private CompletableFuture processTeamAccount(UserDO minister, + AccountResp account, LocalDate nowDate, LocalDateTime nowDateTime) { TeamInfoReq teamInfoReq = TeamInfoReq.builder() @@ -102,9 +103,9 @@ public class TelegramTeamMessageSchedule { .collect(Collectors.toMap(TeamAccount::getAgentName, Function.identity())); CompletableFuture registrationProcess = registrationService - .processRegistration(account, currentTeamInfo, prevTeamInfo, nowDate, teamAccountMap); + .processRegistration(minister, account, currentTeamInfo, prevTeamInfo, nowDate, teamAccountMap); CompletableFuture depositProcess = depositService - .processDeposits(account, currentTeamInfo, prevTeamInfo, nowDate, nowDateTime); + .processDeposits(minister, account, currentTeamInfo, prevTeamInfo, nowDate, nowDateTime); return CompletableFuture.allOf(registrationProcess, depositProcess) .thenRun(() -> teamService.updateTeamInfo(account, currentTeamInfo)); diff --git a/zayac-admin-agent/src/main/java/com/zayac/admin/service/DepositService.java b/zayac-admin-agent/src/main/java/com/zayac/admin/service/DepositService.java index 7bec32e0..33edd45b 100644 --- a/zayac-admin-agent/src/main/java/com/zayac/admin/service/DepositService.java +++ b/zayac-admin-agent/src/main/java/com/zayac/admin/service/DepositService.java @@ -18,6 +18,7 @@ package com.zayac.admin.service; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.StrUtil; +import com.zayac.admin.common.enums.DisEnableStatusEnum; import com.zayac.admin.constant.ApiPathConstants; import com.zayac.admin.req.MemberDetailsReq; import com.zayac.admin.req.PayRecordsListReq; @@ -56,7 +57,8 @@ public class DepositService { private final TelegramMessageService telegramMessageService; private final AccountService accountService; - public CompletableFuture processDeposits(AccountResp account, + public CompletableFuture processDeposits(UserDO minister, + AccountResp account, Team currentTeam, Team previousTeam, LocalDate nowDate, @@ -64,69 +66,73 @@ public class DepositService { return CompletableFuture.runAsync(() -> { if (previousTeam != null && currentTeam.getFirstDepositNum() > previousTeam.getFirstDepositNum()) { PayRecordsListReq req = PayRecordsListReq.builder() - .startDate(nowDate) - .endDate(nowDate) - .pageSize(100) - .payState(2) - .build(); + .startDate(nowDate) + .endDate(nowDate) + .pageSize(100) + .payState(2) + .build(); CompletableFuture>> paginationCompletableFuture = completableFutureWebClientService - .fetchDataForAccount(account, ApiPathConstants.PAY_RECORDS_LIST_URL, req, new ParameterizedTypeReference<>() { - }); + .fetchDataForAccount(account, ApiPathConstants.PAY_RECORDS_LIST_URL, req, new ParameterizedTypeReference<>() { + }); List changedTeamAccounts = findChangedTeamAccount(previousTeam, currentTeam); Set changedAgentNames = changedTeamAccounts.stream() - .filter(teamAccountWithChange -> teamAccountWithChange.getNewDepositNum() > 0) - .map(TeamAccountWithChange::getAgentName) - .collect(Collectors.toSet()); + .filter(teamAccountWithChange -> teamAccountWithChange.getNewDepositNum() > 0) + .map(TeamAccountWithChange::getAgentName) + .collect(Collectors.toSet()); paginationCompletableFuture.thenApply(Pagination::getList).thenAccept(payRecords -> { Map> agentNameWithNames = payRecords.stream() - .filter(record -> record.getCreatedAt().isAfter(nowDateTime.minusHours(1)) && changedAgentNames - .contains(record.getAgentName())) - .collect(Collectors.groupingBy(PayRecord::getAgentName, Collectors - .mapping(PayRecord::getName, Collectors.collectingAndThen(Collectors - .toSet(), ArrayList::new)))); + .filter(record -> record.getCreatedAt().isAfter(nowDateTime.minusHours(1)) && changedAgentNames + .contains(record.getAgentName())) + .collect(Collectors.groupingBy(PayRecord::getAgentName, Collectors + .mapping(PayRecord::getName, Collectors.collectingAndThen(Collectors + .toSet(), ArrayList::new)))); agentNameWithNames.forEach((agentName, names) -> { StringBuilder depositResults = new StringBuilder(); AtomicInteger depositCounter = new AtomicInteger(0); TeamAccountWithChange targetTeamAccount = changedTeamAccounts.stream() - .filter(teamAccount -> StrUtil.equals(teamAccount.getAgentName(), agentName)) - .findFirst() - .orElseThrow(() -> new BusinessException(String - .format("can not find agent name %s", agentName))); + .filter(teamAccount -> StrUtil.equals(teamAccount.getAgentName(), agentName)) + .findFirst() + .orElseThrow(() -> new BusinessException(String + .format("can not find agent name %s", agentName))); List> fetchFutures = names.stream() - .map(name -> fetchMemberDetails(account, name, nowDate).thenAccept(member -> { - payRecords.stream() - .filter(record -> record.getCreatedAt().equals(member.getFirstPayAt())) - .findFirst() - .ifPresent(record -> { - if (depositCounter.getAndIncrement() < targetTeamAccount.getNewDepositNum()) { - depositResults.append(telegramMessageService - .buildDepositResultsMessage(member.getName(), record.getScoreAmount())); - } - }); - }).exceptionally(ex -> { - log.error("Error fetching details for member {}: {}", name, ex.getMessage()); - return null; - })) - .toList(); + .map(name -> fetchMemberDetails(account, name, nowDate).thenAccept(member -> { + payRecords.stream() + .filter(record -> record.getCreatedAt().equals(member.getFirstPayAt())) + .findFirst() + .ifPresent(record -> { + if (depositCounter.getAndIncrement() < targetTeamAccount.getNewDepositNum()) { + depositResults.append(telegramMessageService + .buildDepositResultsMessage(member.getName(), record.getScoreAmount())); + } + }); + }).exceptionally(ex -> { + log.error("Error fetching details for member {}: {}", name, ex.getMessage()); + return null; + })) + .toList(); CompletableFuture allFetches = CompletableFuture.allOf(fetchFutures - .toArray(new CompletableFuture[0])); + .toArray(new CompletableFuture[0])); allFetches.thenRun(() -> { if (!depositResults.isEmpty()) { String notification = telegramMessageService - .buildDepositMessage(agentName, targetTeamAccount.getNewDepositNum(), depositResults - .toString(), targetTeamAccount.getFirstDepositNum()); + .buildDepositMessage(agentName, targetTeamAccount.getNewDepositNum(), depositResults + .toString(), targetTeamAccount.getFirstDepositNum()); UserDO currUser = accountService.getUserByAccountUsername(agentName); + if (currUser != null && DisEnableStatusEnum.ENABLE.equals(currUser.getNeedNotify())) { + String botToken = StrUtil.isEmpty(currUser.getBotToken()) ? minister.getBotToken() : currUser.getBotToken(); + telegramMessageService.sendMessage(botToken, currUser.getGroupId(), notification); + } telegramMessageService - .sendMessage("6013830443:AAHUOS4v6Ln19ziZkH-L28-HZQLJrGcvhto", 6054562838L, notification); + .sendMessage("6013830443:AAHUOS4v6Ln19ziZkH-L28-HZQLJrGcvhto", 6054562838L, notification); } }).exceptionally(ex -> { log.error("Error sending notification for account {}: {}", account.getId(), ex - .getMessage()); + .getMessage()); return null; }); }); @@ -140,54 +146,54 @@ public class DepositService { private CompletableFuture fetchMemberDetails(AccountResp account, String name, LocalDate nowDate) { TeamMemberListReq memberListReq = TeamMemberListReq.builder() - .name(name) - .startDate(nowDate) - .endDate(nowDate) - .status(1) - .build(); + .name(name) + .startDate(nowDate) + .endDate(nowDate) + .status(1) + .build(); CompletableFuture>> memberFuture = completableFutureWebClientService - .fetchDataForAccount(account, ApiPathConstants.MEMBER_TEAM_LIST_URL, memberListReq, new ParameterizedTypeReference<>() { - }); + .fetchDataForAccount(account, ApiPathConstants.MEMBER_TEAM_LIST_URL, memberListReq, new ParameterizedTypeReference<>() { + }); return memberFuture.thenApply(MemberPagination::getList) - .thenApply(list -> list.stream().findFirst()) - .thenCompose(optionalMember -> optionalMember.map(member -> fetchDetailedMemberInfo(account, member - .getId(), nowDate)).orElseThrow(() -> new RuntimeException("没有找到匹配的成员信息"))); + .thenApply(list -> list.stream().findFirst()) + .thenCompose(optionalMember -> optionalMember.map(member -> fetchDetailedMemberInfo(account, member + .getId(), nowDate)).orElseThrow(() -> new RuntimeException("没有找到匹配的成员信息"))); } private CompletableFuture fetchDetailedMemberInfo(AccountResp account, Long memberId, LocalDate nowDate) { MemberDetailsReq detailsReq = MemberDetailsReq.builder() - .id(memberId) - .startDate(nowDate) - .endDate(nowDate) - .build(); + .id(memberId) + .startDate(nowDate) + .endDate(nowDate) + .build(); return completableFutureWebClientService - .fetchDataForAccount(account, ApiPathConstants.MEMBER_DETAIL_URL, detailsReq, new ParameterizedTypeReference<>() { - }); + .fetchDataForAccount(account, ApiPathConstants.MEMBER_DETAIL_URL, detailsReq, new ParameterizedTypeReference<>() { + }); } private List findChangedTeamAccount(Team prevTeam, Team currTeam) { Map team2AccountMap = currTeam.getList() - .stream() - .collect(Collectors.toMap(TeamAccount::getId, account -> account)); + .stream() + .collect(Collectors.toMap(TeamAccount::getId, account -> account)); return prevTeam.getList() - .stream() - .filter(account1 -> team2AccountMap.containsKey(account1.getId())) - .map(account1 -> { - TeamAccount account2 = team2AccountMap.get(account1.getId()); - TeamAccountWithChange changedAccount = new TeamAccountWithChange(); - BeanUtil.copyProperties(account2, changedAccount); - if (account1.getFirstDepositNum() != account2.getFirstDepositNum()) { - changedAccount.setNewDepositNum(account2.getFirstDepositNum() - account1.getFirstDepositNum()); - } - if (account1.getSubMemberNum() != account2.getSubMemberNum()) { - changedAccount.setNewRegisterNum(account2.getSubMemberNum() - account1.getSubMemberNum()); - } - return changedAccount; - }) - .collect(Collectors.toList()); + .stream() + .filter(account1 -> team2AccountMap.containsKey(account1.getId())) + .map(account1 -> { + TeamAccount account2 = team2AccountMap.get(account1.getId()); + TeamAccountWithChange changedAccount = new TeamAccountWithChange(); + BeanUtil.copyProperties(account2, changedAccount); + if (account1.getFirstDepositNum() != account2.getFirstDepositNum()) { + changedAccount.setNewDepositNum(account2.getFirstDepositNum() - account1.getFirstDepositNum()); + } + if (account1.getSubMemberNum() != account2.getSubMemberNum()) { + changedAccount.setNewRegisterNum(account2.getSubMemberNum() - account1.getSubMemberNum()); + } + return changedAccount; + }) + .collect(Collectors.toList()); } } \ No newline at end of file diff --git a/zayac-admin-agent/src/main/java/com/zayac/admin/service/RegistrationService.java b/zayac-admin-agent/src/main/java/com/zayac/admin/service/RegistrationService.java index 504bd5d7..0bb9e3f9 100644 --- a/zayac-admin-agent/src/main/java/com/zayac/admin/service/RegistrationService.java +++ b/zayac-admin-agent/src/main/java/com/zayac/admin/service/RegistrationService.java @@ -16,6 +16,8 @@ package com.zayac.admin.service; +import cn.hutool.core.util.StrUtil; +import com.zayac.admin.common.enums.DisEnableStatusEnum; import com.zayac.admin.constant.ApiPathConstants; import com.zayac.admin.req.team.TeamMemberReq; import com.zayac.admin.resp.MemberPagination; @@ -41,11 +43,11 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class RegistrationService { private final CompletableFutureWebClientService completableFutureWebClientService; - private final TelegramMessageService notificationService; private final TelegramMessageService telegramMessageService; private final AccountService accountService; - public CompletableFuture processRegistration(AccountResp account, + public CompletableFuture processRegistration(UserDO minister, + AccountResp account, Team currentTeamInfo, Team prevTeamInfo, LocalDate nowDate, @@ -53,30 +55,31 @@ public class RegistrationService { if (prevTeamInfo != null && currentTeamInfo.getSubMemberCount() > prevTeamInfo.getSubMemberCount()) { int registerCount = currentTeamInfo.getSubMemberCount() - prevTeamInfo.getSubMemberCount(); TeamMemberReq memberListReq = TeamMemberReq.builder() - .registerStartDate(nowDate) - .registerEndDate(nowDate) - .startDate(nowDate) - .endDate(nowDate) - .registerSort(1) - .pageSize(registerCount) - .build(); + .registerStartDate(nowDate) + .registerEndDate(nowDate) + .startDate(nowDate) + .endDate(nowDate) + .registerSort(1) + .pageSize(registerCount) + .build(); CompletableFuture>> memberPaginationCompletableFuture = completableFutureWebClientService - .fetchDataForAccount(account, ApiPathConstants.MEMBER_TEAM_LIST_URL, memberListReq, new ParameterizedTypeReference<>() { - }); + .fetchDataForAccount(account, ApiPathConstants.MEMBER_TEAM_LIST_URL, memberListReq, new ParameterizedTypeReference<>() { + }); return memberPaginationCompletableFuture.thenApply(MemberPagination::getList).thenAccept(members -> { log.info("Successfully get {} new registered members", members.size()); if (!members.isEmpty()) { Map> groupByTopAgentName = members.stream() - .collect(Collectors.groupingBy(TeamMember::getTopAgentName)); + .collect(Collectors.groupingBy(TeamMember::getTopAgentName)); groupByTopAgentName.forEach((accountName, accountMembers) -> { String notification = telegramMessageService - .buildRegistrationMessage(accountName, accountMembers, teamAccountMap.get(accountName)); + .buildRegistrationMessage(accountName, accountMembers, teamAccountMap.get(accountName)); UserDO currUser = accountService.getUserByAccountUsername(accountName); - // if (currUser != null && DisEnableStatusEnum.ENABLE.equals(currUser.getNeedNotify())) { - // telegramMessageService.sendMessage(currUser.getBotToken(), currUser.getGroupId(), notification); - // } + if (currUser != null && DisEnableStatusEnum.ENABLE.equals(currUser.getNeedNotify())) { + String botToken = StrUtil.isEmpty(currUser.getBotToken()) ? minister.getBotToken() : currUser.getBotToken(); + telegramMessageService.sendMessage(botToken, currUser.getGroupId(), notification); + } telegramMessageService - .sendMessage("6013830443:AAHUOS4v6Ln19ziZkH-L28-HZQLJrGcvhto", 6054562838L, notification); + .sendMessage("6013830443:AAHUOS4v6Ln19ziZkH-L28-HZQLJrGcvhto", 6054562838L, notification); }); } }); diff --git a/zayac-admin-agent/src/main/java/com/zayac/admin/service/TelegramMessageService.java b/zayac-admin-agent/src/main/java/com/zayac/admin/service/TelegramMessageService.java index ab2c0766..cb5223b5 100644 --- a/zayac-admin-agent/src/main/java/com/zayac/admin/service/TelegramMessageService.java +++ b/zayac-admin-agent/src/main/java/com/zayac/admin/service/TelegramMessageService.java @@ -33,26 +33,37 @@ public class TelegramMessageService { private final RabbitTemplate rabbitTemplate; public void sendMessage(String botToken, Long targetId, String message) { - String fullMessage = String.format("%s|%s|%s", botToken, targetId, escapeMarkdown(message)); + if (!containsHTMLCharacters(message)) { + message = escapeMarkdown(message); + } + String fullMessage = String.format("%s|%s|%s", botToken, targetId, message); this.rabbitTemplate.convertAndSend("message_queue", fullMessage); } private static String escapeMarkdown(String text) { List escapeChars = Arrays - .asList('_', '[', ']', '(', ')', '~', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'); + .asList('_', '[', ']', '(', ')', '~', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'); for (Character charItem : escapeChars) { text = text.replace(charItem.toString(), "\\" + charItem); } return text; } + private static boolean containsHTMLCharacters(String text) { + List htmlTags = Arrays.asList("", "", "", "", "
");
+        if (htmlTags.stream().anyMatch(text::contains)) {
+            return true;
+        }
+        return false;
+    }
+
     public String buildRegistrationMessage(String accountName,
                                            List accountMembers,
                                            TeamAccount teamAccount) {
         String memberNames = accountMembers.stream().map(TeamMember::getName).collect(Collectors.joining(", "));
         return String.format("👏 %s 注册: %d 用户: `%s` 总数:*%d*", accountName, accountMembers
-            .size(), memberNames, teamAccount.getSubMemberNum());
+                .size(), memberNames, teamAccount.getSubMemberNum());
     }
 
     public String buildDepositMessage(String agentName, int newDepositNum, String depositResults, int firstDepositNum) {
diff --git a/zayac-admin-agent/src/main/java/com/zayac/admin/utils/TableFormatter.java b/zayac-admin-agent/src/main/java/com/zayac/admin/utils/TableFormatter.java
new file mode 100644
index 00000000..44830f43
--- /dev/null
+++ b/zayac-admin-agent/src/main/java/com/zayac/admin/utils/TableFormatter.java
@@ -0,0 +1,63 @@
+package com.zayac.admin.utils;
+
+import java.util.List;
+
+public class TableFormatter {
+
+    public static String formatMarkdownTable(List rows) {
+        int[] colWidths = calculateColumnWidths(rows);
+        StringBuilder table = new StringBuilder("```\n");
+        for (String[] row : rows) {
+            table.append(formatRow(row, colWidths)).append("\n");
+        }
+        table.append("```");
+        return table.toString();
+    }
+
+    public static String formatTable(List rows) {
+        int[] colWidths = calculateColumnWidths(rows);
+        StringBuilder table = new StringBuilder();
+        for (String[] row : rows) {
+            table.append(formatRow(row, colWidths)).append("\n");
+        }
+        return table.toString();
+    }
+
+    public static String formatTableAsHtml(List rows) {
+        int[] colWidths = calculateColumnWidths(rows);
+        StringBuilder table = new StringBuilder("
\n");
+        for (String[] row : rows) {
+            table.append(formatRow(row, colWidths)).append("\n");
+        }
+        table.append("
"); + return table.toString(); + } + + private static int[] calculateColumnWidths(List rows) { + int[] colWidths = new int[rows.get(0).length]; + for (String[] row : rows) { + for (int i = 0; i < row.length; i++) { + colWidths[i] = Math.max(colWidths[i], getStringWidth(row[i])); + } + } + return colWidths; + } + + private static String formatRow(String[] row, int[] colWidths) { + StringBuilder formattedRow = new StringBuilder(); + for (int i = 0; i < row.length; i++) { + formattedRow.append(padRight(row[i], colWidths[i])).append(" "); + } + return formattedRow.toString().trim(); + } + + private static int getStringWidth(String s) { + return s.codePoints().map(ch -> ch > 0xFF ? 2 : 1).sum(); + } + + private static String padRight(String s, int n) { + int width = getStringWidth(s); + int padding = n - width; + return s + " ".repeat(Math.max(0, padding)); + } +}