NotificationSlackMessageConverter.java

  1. package no.nav.data.team.notify;

  2. import lombok.RequiredArgsConstructor;
  3. import lombok.extern.slf4j.Slf4j;
  4. import no.nav.data.common.security.SecurityProperties;
  5. import no.nav.data.team.contact.domain.SlackUser;
  6. import no.nav.data.team.integration.slack.SlackClient;
  7. import no.nav.data.team.integration.slack.dto.SlackDtos.PostMessageRequest.Block;
  8. import no.nav.data.team.notify.domain.Notification.NotificationTime;
  9. import no.nav.data.team.notify.dto.MailModels.Resource;
  10. import no.nav.data.team.notify.dto.MailModels.TypedItem;
  11. import no.nav.data.team.notify.dto.MailModels.UpdateItem;
  12. import no.nav.data.team.notify.dto.MailModels.UpdateModel;
  13. import org.apache.commons.lang3.StringUtils;
  14. import org.springframework.stereotype.Component;

  15. import java.util.ArrayList;
  16. import java.util.List;
  17. import java.util.NoSuchElementException;

  18. @Component
  19. @RequiredArgsConstructor
  20. @Slf4j
  21. public class NotificationSlackMessageConverter {

  22.     private final SlackClient slackClient;
  23.     private final SecurityProperties securityProperties;

  24.     public List<Block> convertTeamUpdateModel(UpdateModel model) {
  25.         var blocks = new ArrayList<Block>();
  26.         blocks.add(Block.header("Oppdateringer i Teamkatalogen %s %s".formatted(timeHeader(model.getTime()), devText())));
  27.         blocks.add(Block.divider());

  28.         if (!model.getCreated().isEmpty()) {
  29.             var text = new StringBuilder("*Opprettet*\n");
  30.             for (TypedItem item : model.getCreated()) {
  31.                 text.append(" - ").append(typedItemLink(item));
  32.             }
  33.             blocks.add(Block.text(text.toString()));
  34.             blocks.add(Block.divider());
  35.         }

  36.         if (!model.getDeleted().isEmpty()) {
  37.             var text = new StringBuilder("*Slettet*\n");
  38.             for (TypedItem item : model.getDeleted()) {
  39.                 text.append(" - ").append(typedItemLink(item));
  40.             }
  41.             blocks.add(Block.text(text.toString()));
  42.             blocks.add(Block.divider());
  43.         }

  44.         if (!model.getUpdated().isEmpty()) {
  45.             blocks.add(Block.text("*Endret*"));
  46.             for (UpdateItem updateItem : model.getUpdated()) {
  47.                 var text = new StringBuilder(" - ").append(typedItemLink(updateItem.getItem()));
  48.                 updateContent(text, updateItem);
  49.                 blocks.add(Block.text(text.toString()));
  50.             }
  51.             blocks.add(Block.divider());
  52.         }

  53.         blocks.add(Block.text(
  54.                 "<%s?source=slackupdate|Teamkatalogen> - varsel kan endres på <%s/user/notifications?source=slackupdate|Mine varsler> mvh #teamkatalogen"
  55.                         .formatted(model.getBaseUrl(), model.getBaseUrl())));
  56.         return blocks;
  57.     }

  58.     private void updateContent(StringBuilder text, UpdateItem item) {
  59.         if (item.newName()) {
  60.             text.append("   - Navn endret fra: _%s_ til: _%s_\n".formatted(item.getFromName(), item.getToName()));
  61.         }
  62.         if (item.newOwnershipType()) {
  63.             String fromType = StringUtils.isBlank(item.getFromOwnershipType()) ? "ingen" : item.getFromOwnershipType();
  64.             text.append("   - Eierskapstype endret fra: _%s_ til: _%s_\n".formatted(fromType, item.getToOwnershipType()));
  65.         }
  66.         if (item.newTeamType()) {
  67.             String fromType = StringUtils.isBlank(item.getFromTeamType()) ? "ingen" : item.getFromTeamType();
  68.             text.append("   - Team type endret fra: _%s_ til: _%s_\n".formatted(fromType, item.getToTeamType()));
  69.         }
  70.         if (item.newAreaType()) {
  71.             String fromType = StringUtils.isBlank(item.getFromAreaType()) ? "ingen" : item.getFromAreaType();
  72.             text.append("   - Team type endret fra: _%s_ til: _%s_\n".formatted(fromType, item.getToAreaType()));
  73.         }
  74.         newProductArea(text, item);
  75.         membersChanged(text, item);
  76.         teamsChanged(text, item);
  77.     }

  78.     private void newProductArea(StringBuilder text, UpdateItem updated) {
  79.         if (updated.newProductArea()) {
  80.             text.append("   - Område endret fra: ");
  81.             if (updated.getOldProductArea() == null) {
  82.                 text.append("_ingen_");
  83.             } else {
  84.                 text.append("_<%s?source=slackupdate|%s>_".formatted(updated.getFromProductAreaUrl(), updated.getFromProductArea()));
  85.             }
  86.             text.append(" til: ");
  87.             if (updated.getNewProductArea() == null) {
  88.                 text.append("_ingen_");
  89.             } else {
  90.                 text.append("_<%s?source=slackupdate|%s>_".formatted(updated.getToProductAreaUrl(), updated.getToProductArea()));
  91.             }
  92.             text.append('\n');
  93.         }
  94.     }

  95.     private void teamsChanged(StringBuilder text, UpdateItem item) {
  96.         if (!item.getNewTeams().isEmpty()) {
  97.             text.append("   - Nytt team\n");
  98.             for (var team : item.getNewTeams()) {
  99.                 text.append("     - ").append(typedItemLink(team));
  100.             }
  101.         }
  102.         if (!item.getRemovedTeams().isEmpty()) {
  103.             text.append("   - Fjernet team\n");
  104.             for (var team : item.getRemovedTeams()) {
  105.                 text.append("     - ").append(typedItemLink(team));
  106.             }
  107.         }
  108.     }

  109.     private void membersChanged(StringBuilder text, UpdateItem item) {
  110.         if (!item.getNewMembers().isEmpty()) {
  111.             text.append("   - Nytt medlem\n");
  112.             for (Resource member : item.getNewMembers()) {
  113.                 text.append("     - ").append(formatMember(member));
  114.             }
  115.         }
  116.         if (!item.getRemovedMembers().isEmpty()) {
  117.             text.append("   - Fjernet medlem\n");
  118.             for (Resource member : item.getRemovedMembers()) {
  119.                 text.append("     - ").append(formatMember(member));
  120.             }
  121.         }
  122.     }

  123.     private String formatMember(Resource member) {
  124.         String user = "<%s?source=slackupdate|%s>".formatted(member.getUrl(), member.getName());
  125.         SlackUser slackUser = null;
  126.         try {
  127.             slackUser = slackClient.getUserByIdent(member.getIdent());
  128.         } catch (NoSuchElementException e) {
  129.             log.error("Couldn't find nav ident {} for {}. Formatting without slackuser info", member.getIdent(), member.getName());
  130.         }
  131.         if (slackUser != null) {
  132.             return user + " - <@%s>\n".formatted(slackUser.getId());
  133.         } else {
  134.             return user + "\n";
  135.         }
  136.     }

  137.     private String typedItemLink(TypedItem item) {
  138.         if (item.isDeleted()) {
  139.             return item.formatName() + "\n";
  140.         }
  141.         return "<%s?source=slackupdate|%s>\n".formatted(item.getUrl(), item.formatName());
  142.     }

  143.     private String devText() {
  144.         return securityProperties.isDev() ? "[DEV]" : "";
  145.     }

  146.     private String timeHeader(NotificationTime time) {
  147.         return switch (time) {
  148.             case ALL -> "";
  149.             case DAILY -> "siste dag";
  150.             case WEEKLY -> "siste uke";
  151.             case MONTHLY -> "siste måned";
  152.         };
  153.     }

  154. }