// static methods for getting by id, etc.
 public static PullRequestDisapproval getPullRequestDisapproval(ActiveObjects ao, PullRequest pr)
     throws SQLException {
   Repository repo = pr.getToRef().getRepository();
   PullRequestDisapproval[] disapprovals =
       ao.find(
           PullRequestDisapproval.class,
           Query.select().where("REPO_ID = ? and PR_ID = ?", repo.getId(), pr.getId()));
   if (disapprovals.length == 0) {
     PullRequestDisapproval prd =
         ao.create(
             PullRequestDisapproval.class,
             new DBParam("REPO_ID", repo.getId()),
             new DBParam("PR_ID", pr.getId()),
             new DBParam("USERNAME", "None"));
     prd.save();
     return prd;
   }
   return disapprovals[0];
 }
 public static void setPullRequestDisapproval(
     ActiveObjects ao, PullRequest pr, String username, boolean isDisapproved)
     throws SQLException {
   Repository repo = pr.getToRef().getRepository();
   PullRequestDisapproval[] disapprovals =
       ao.find(
           PullRequestDisapproval.class,
           Query.select().where("REPO_ID = ? and PR_ID = ?", repo.getId(), pr.getId()));
   if (disapprovals.length == 0) {
     PullRequestDisapproval prd =
         ao.create(
             PullRequestDisapproval.class,
             new DBParam("REPO_ID", repo.getId()),
             new DBParam("PR_ID", pr.getId()),
             new DBParam("USERNAME", username));
     prd.setDisapproved(isDisapproved);
     prd.save();
     return;
   }
   disapprovals[0].setDisapprovedBy(username);
   disapprovals[0].setDisapproved(isDisapproved);
   disapprovals[0].save();
 }
  @EventListener
  public void NotifySlackChannel(RepositoryPushEvent event) {
    // find out if notification is enabled for this repo
    Repository repository = event.getRepository();
    SlackSettings slackSettings = slackSettingsService.getSlackSettings(repository);
    String globalHookUrl = slackGlobalSettingsService.getWebHookUrl(KEY_GLOBAL_SETTING_HOOK_URL);

    SettingsSelector settingsSelector =
        new SettingsSelector(slackSettingsService, slackGlobalSettingsService, repository);
    SlackSettings resolvedSlackSettings = settingsSelector.getResolvedSlackSettings();

    if (resolvedSlackSettings.isSlackNotificationsEnabledForPush()) {
      String localHookUrl = slackSettings.getSlackWebHookUrl();
      WebHookSelector hookSelector = new WebHookSelector(globalHookUrl, localHookUrl);
      ChannelSelector channelSelector =
          new ChannelSelector(
              slackGlobalSettingsService.getChannelName(KEY_GLOBAL_SLACK_CHANNEL_NAME),
              slackSettings.getSlackChannelName());

      if (!hookSelector.isHookValid()) {
        log.error(
            "There is no valid configured Web hook url! Reason: " + hookSelector.getProblem());
        return;
      }

      if (repository.isFork() && !resolvedSlackSettings.isSlackNotificationsEnabledForPersonal()) {
        // simply return silently when we don't want forks to get notifications unless they're
        // explicitly enabled
        return;
      }

      String repoName = repository.getSlug();
      String projectName = repository.getProject().getKey();

      String repoPath = projectName + "/" + event.getRepository().getName();

      for (RefChange refChange : event.getRefChanges()) {
        String text;
        String ref = refChange.getRefId();
        NavBuilder.Repo repoUrlBuilder = navBuilder.project(projectName).repo(repoName);
        String url = repoUrlBuilder.commits().until(refChange.getRefId()).buildAbsolute();

        List<Changeset> myChanges = new LinkedList<Changeset>();
        boolean isNewRef =
            refChange.getFromHash().equalsIgnoreCase("0000000000000000000000000000000000000000");
        boolean isDeleted =
            refChange.getToHash().equalsIgnoreCase("0000000000000000000000000000000000000000")
                && refChange.getType() == RefChangeType.DELETE;
        if (isDeleted) {
          // issue#4: if type is "DELETE" and toHash is all zero then this is a branch delete
          if (ref.indexOf("refs/tags") >= 0) {
            text =
                String.format(
                    "Tag `%s` deleted from repository <%s|`%s`>.",
                    ref.replace("refs/tags/", ""), repoUrlBuilder.buildAbsolute(), repoPath);
          } else {
            text =
                String.format(
                    "Branch `%s` deleted from repository <%s|`%s`>.",
                    ref.replace("refs/heads/", ""), repoUrlBuilder.buildAbsolute(), repoPath);
          }
        } else if (isNewRef) {
          // issue#3 if fromHash is all zero (meaning the beginning of everything, probably), then
          // this push is probably
          // a new branch or tag, and we want only to display the latest commit, not the entire
          // history
          Changeset latestChangeSet = commitService.getChangeset(repository, refChange.getToHash());
          myChanges.add(latestChangeSet);
          if (ref.indexOf("refs/tags") >= 0) {
            text =
                String.format(
                    "Tag <%s|`%s`> pushed on <%s|`%s`>. See <%s|commit list>.",
                    url,
                    ref.replace("refs/tags/", ""),
                    repoUrlBuilder.buildAbsolute(),
                    repoPath,
                    url);
          } else {
            text =
                String.format(
                    "Branch <%s|`%s`> pushed on <%s|`%s`>. See <%s|commit list>.",
                    url,
                    ref.replace("refs/heads/", ""),
                    repoUrlBuilder.buildAbsolute(),
                    repoPath,
                    url);
          }
        } else {
          ChangesetsBetweenRequest request =
              new ChangesetsBetweenRequest.Builder(repository)
                  .exclude(refChange.getFromHash())
                  .include(refChange.getToHash())
                  .build();

          Page<Changeset> changeSets =
              commitService.getChangesetsBetween(
                  request, PageUtils.newRequest(0, PageRequest.MAX_PAGE_LIMIT));

          myChanges.addAll(Lists.newArrayList(changeSets.getValues()));

          int commitCount = myChanges.size();
          String commitStr = commitCount == 1 ? "commit" : "commits";

          String branch = ref.replace("refs/heads/", "");

          if (!branch.equals("master")) {
            continue;
          }

          text =
              String.format(
                  "Push on <%s|`%s`> branch <%s|`%s`> by `%s <%s>` (%d %s). See <%s|commit list>.",
                  repoUrlBuilder.buildAbsolute(),
                  repoPath,
                  url,
                  branch,
                  event.getUser() != null ? event.getUser().getDisplayName() : "unknown user",
                  event.getUser() != null ? event.getUser().getEmailAddress() : "unknown email",
                  commitCount,
                  commitStr,
                  url);
        }

        // Figure out what type of change this is:

        SlackPayload payload = new SlackPayload();

        payload.setText(text);
        payload.setMrkdwn(true);

        switch (resolvedSlackSettings.getNotificationLevel()) {
          case COMPACT:
            compactCommitLog(event, refChange, payload, repoUrlBuilder, myChanges);
            break;
          case VERBOSE:
            verboseCommitLog(event, refChange, payload, repoUrlBuilder, text, myChanges);
            break;
          case MINIMAL:
          default:
            break;
        }

        // slackSettings.getSlackChannelName might be:
        // - empty
        // - comma separated list of channel names, eg: #mych1, #mych2, #mych3

        if (channelSelector.getSelectedChannel().isEmpty()) {
          slackNotifier.SendSlackNotification(hookSelector.getSelectedHook(), gson.toJson(payload));
        } else {
          // send message to multiple channels
          List<String> channels =
              Arrays.asList(channelSelector.getSelectedChannel().split("\\s*,\\s*"));
          for (String channel : channels) {
            payload.setChannel(channel.trim());
            slackNotifier.SendSlackNotification(
                hookSelector.getSelectedHook(), gson.toJson(payload));
          }
        }
      }
    }
  }
 public void setRepository(Repository repo) {
   prd.setRepositoryId(repo.getId());
 }
  @EventListener
  public void NotifylesschatChannel(PullRequestActivityEvent event) {
    // find out if notification is enabled for this repo
    Repository repository = event.getPullRequest().getToRef().getRepository();
    LesschatSettings lesschatSettings = lesschatSettingsService.getlesschatSettings(repository);
    String globalHookUrl = lesschatGlobalSettingsService.getWebHookUrl(KEY_GLOBAL_SETTING_HOOK_URL);

    SettingsSelector settingsSelector =
        new SettingsSelector(lesschatSettingsService, lesschatGlobalSettingsService, repository);
    LesschatSettings resolvedlesschatSettings = settingsSelector.getResolvedlesschatSettings();

    if (resolvedlesschatSettings.islesschatNotificationsEnabled()) {

      String localHookUrl = resolvedlesschatSettings.getlesschatWebHookUrl();
      WebHookSelector hookSelector = new WebHookSelector(globalHookUrl, localHookUrl);
      ChannelSelector channelSelector =
          new ChannelSelector(
              lesschatGlobalSettingsService.getChannelName(KEY_GLOBAL_lesschat_CHANNEL_NAME),
              lesschatSettings.getlesschatChannelName());

      if (!hookSelector.isHookValid()) {
        log.error(
            "There is no valid configured Web hook url! Reason: " + hookSelector.getProblem());
        return;
      }

      String repoName = repository.getSlug();
      String projectName = repository.getProject().getKey();
      long pullRequestId = event.getPullRequest().getId();
      String userName = event.getUser() != null ? event.getUser().getDisplayName() : "unknown user";
      String activity = event.getActivity().getAction().name();
      String avatar =
          event.getUser() != null
              ? avatarService.getUrlForPerson(event.getUser(), avatarRequest)
              : "";

      NotificationLevel resolvedLevel = resolvedlesschatSettings.getNotificationPrLevel();

      // Ignore RESCOPED PR events
      if (activity.equalsIgnoreCase("RESCOPED")
          && event instanceof PullRequestRescopeActivityEvent) {
        return;
      }

      if (activity.equalsIgnoreCase("OPENED")
          && !resolvedlesschatSettings.islesschatNotificationsOpenedEnabled()) {
        return;
      }

      if (activity.equalsIgnoreCase("REOPENED")
          && !resolvedlesschatSettings.islesschatNotificationsReopenedEnabled()) {
        return;
      }

      if (activity.equalsIgnoreCase("UPDATED")
          && !resolvedlesschatSettings.islesschatNotificationsUpdatedEnabled()) {
        return;
      }

      if (activity.equalsIgnoreCase("APPROVED")
          && !resolvedlesschatSettings.islesschatNotificationsApprovedEnabled()) {
        return;
      }

      if (activity.equalsIgnoreCase("UNAPPROVED")
          && !resolvedlesschatSettings.islesschatNotificationsUnapprovedEnabled()) {
        return;
      }

      if (activity.equalsIgnoreCase("DECLINED")
          && !resolvedlesschatSettings.islesschatNotificationsDeclinedEnabled()) {
        return;
      }

      if (activity.equalsIgnoreCase("MERGED")
          && !resolvedlesschatSettings.islesschatNotificationsMergedEnabled()) {
        return;
      }

      if (activity.equalsIgnoreCase("COMMENTED")
          && !resolvedlesschatSettings.islesschatNotificationsCommentedEnabled()) {
        return;
      }

      String url =
          navBuilder
              .project(projectName)
              .repo(repoName)
              .pullRequest(pullRequestId)
              .overview()
              .buildAbsolute();

      LesschatPayload payload = new LesschatPayload();
      payload.setMrkdwn(true);
      payload.setLinkNames(true);

      LesschatAttachment attachment = new LesschatAttachment();
      attachment.setAuthorName(userName);
      attachment.setAuthorIcon(avatar);

      String color = "";
      String fallback = "";
      String text = "";

      switch (event.getActivity().getAction()) {
        case OPENED:
          attachment.setColor(ColorCode.BLUE.getCode());
          attachment.setFallback(
              String.format(
                  "%s opened pull request \"%s\". <%s|(open)>",
                  userName, event.getPullRequest().getTitle(), url));
          attachment.setText(
              String.format(
                  "opened pull request <%s|#%d: %s>",
                  url, event.getPullRequest().getId(), event.getPullRequest().getTitle()));

          if (resolvedLevel == NotificationLevel.COMPACT) {
            this.addField(attachment, "Description", event.getPullRequest().getDescription());
          }

          if (resolvedLevel == NotificationLevel.VERBOSE) {
            this.addReviewers(attachment, event.getPullRequest().getReviewers());
          }
          break;

        case REOPENED:
          attachment.setColor(ColorCode.BLUE.getCode());
          attachment.setFallback(
              String.format(
                  "%s reopened pull request \"%s\". <%s|(open)>",
                  userName, event.getPullRequest().getTitle(), url));
          attachment.setText(
              String.format(
                  "reopened pull request <%s|#%d: %s>",
                  url, event.getPullRequest().getId(), event.getPullRequest().getTitle()));

          if (resolvedLevel == NotificationLevel.COMPACT) {
            this.addField(attachment, "Description", event.getPullRequest().getDescription());
          }
          if (resolvedLevel == NotificationLevel.VERBOSE) {
            this.addReviewers(attachment, event.getPullRequest().getReviewers());
          }
          break;

        case UPDATED:
          attachment.setColor(ColorCode.PURPLE.getCode());
          attachment.setFallback(
              String.format(
                  "%s updated pull request \"%s\". <%s|(open)>",
                  userName, event.getPullRequest().getTitle(), url));
          attachment.setText(
              String.format(
                  "updated pull request <%s|#%d: %s>",
                  url, event.getPullRequest().getId(), event.getPullRequest().getTitle()));

          if (resolvedLevel == NotificationLevel.COMPACT) {
            this.addField(attachment, "Description", event.getPullRequest().getDescription());
          }
          if (resolvedLevel == NotificationLevel.VERBOSE) {
            this.addReviewers(attachment, event.getPullRequest().getReviewers());
          }
          break;

        case APPROVED:
          attachment.setColor(ColorCode.GREEN.getCode());
          attachment.setFallback(
              String.format(
                  "%s approved pull request \"%s\". <%s|(open)>",
                  userName, event.getPullRequest().getTitle(), url));
          attachment.setText(
              String.format(
                  "approved pull request <%s|#%d: %s>",
                  url, event.getPullRequest().getId(), event.getPullRequest().getTitle()));
          break;

        case UNAPPROVED:
          attachment.setColor(ColorCode.RED.getCode());
          attachment.setFallback(
              String.format(
                  "%s unapproved pull request \"%s\". <%s|(open)>",
                  userName, event.getPullRequest().getTitle(), url));
          attachment.setText(
              String.format(
                  "unapproved pull request <%s|#%d: %s>",
                  url, event.getPullRequest().getId(), event.getPullRequest().getTitle()));
          break;

        case DECLINED:
          attachment.setColor(ColorCode.RED.getCode());
          attachment.setFallback(
              String.format(
                  "%s declined pull request \"%s\". <%s|(open)>",
                  userName, event.getPullRequest().getTitle(), url));
          attachment.setText(
              String.format(
                  "declined pull request <%s|#%d: %s>",
                  url, event.getPullRequest().getId(), event.getPullRequest().getTitle()));
          break;

        case MERGED:
          attachment.setColor(ColorCode.GREEN.getCode());
          attachment.setFallback(
              String.format(
                  "%s merged pull request \"%s\". <%s|(open)>",
                  userName, event.getPullRequest().getTitle(), url));
          attachment.setText(
              String.format(
                  "merged pull request <%s|#%d: %s>",
                  url, event.getPullRequest().getId(), event.getPullRequest().getTitle()));
          break;

        case RESCOPED:
          attachment.setColor(ColorCode.PURPLE.getCode());
          attachment.setFallback(
              String.format(
                  "%s rescoped on pull request \"%s\". <%s|(open)>",
                  userName, event.getPullRequest().getTitle(), url));
          attachment.setText(
              String.format(
                  "rescoped on pull request <%s|#%d: %s>",
                  url, event.getPullRequest().getId(), event.getPullRequest().getTitle()));
          break;

        case COMMENTED:
          attachment.setColor(ColorCode.PALE_BLUE.getCode());
          attachment.setFallback(
              String.format(
                  "%s commented on pull request \"%s\". <%s|(open)>",
                  userName, event.getPullRequest().getTitle(), url));
          if (resolvedLevel == NotificationLevel.MINIMAL) {
            attachment.setText(
                String.format(
                    "commented on pull request <%s|#%d: %s>",
                    url, event.getPullRequest().getId(), event.getPullRequest().getTitle()));
          }
          if (resolvedLevel == NotificationLevel.COMPACT
              || resolvedLevel == NotificationLevel.VERBOSE) {
            attachment.setText(
                String.format(
                    "commented on pull request <%s|#%d: %s>\n%s",
                    url,
                    event.getPullRequest().getId(),
                    event.getPullRequest().getTitle(),
                    ((PullRequestCommentActivityEvent) event)
                        .getActivity()
                        .getComment()
                        .getText()));
          }
          break;
      }

      if (resolvedLevel == NotificationLevel.VERBOSE) {
        LesschatAttachmentField projectField = new LesschatAttachmentField();
        projectField.setTitle("Source");
        projectField.setValue(
            String.format(
                "_%s — %s_\n`%s`",
                event.getPullRequest().getFromRef().getRepository().getProject().getName(),
                event.getPullRequest().getFromRef().getRepository().getName(),
                event.getPullRequest().getFromRef().getDisplayId()));
        projectField.setShort(true);
        attachment.addField(projectField);

        LesschatAttachmentField repoField = new LesschatAttachmentField();
        repoField.setTitle("Destination");
        repoField.setValue(
            String.format(
                "_%s — %s_\n`%s`",
                event.getPullRequest().getFromRef().getRepository().getProject().getName(),
                event.getPullRequest().getToRef().getRepository().getName(),
                event.getPullRequest().getToRef().getDisplayId()));
        repoField.setShort(true);
        attachment.addField(repoField);
      }

      payload.addAttachment(attachment);

      // lesschatSettings.getlesschatChannelName might be:
      // - empty
      // - comma separated list of channel names, eg: #mych1, #mych2, #mych3

      //            if (channelSelector.getSelectedChannel().isEmpty()) {
      lesschatNotifier.SendlesschatNotification(
          hookSelector.getSelectedHook(), gson.toJson(payload));
      //            } else {
      //                // send message to multiple channels
      //                List<String> channels =
      // Arrays.asList(channelSelector.getSelectedChannel().split("\\s*,\\s*"));
      //                for (String channel: channels) {
      //                    payload.setChannel(channel.trim());
      //
      // lesschatNotifier.SendlesschatNotification(hookSelector.getSelectedHook(),
      // gson.toJson(payload));
      //                }
      //            }
    }
  }