sue445/chrome-gitlab-notifier

View on GitHub
src/background.js

Summary

Maintainability
F
3 days
Test Coverage
D
68%
class Background {
  constructor(args){
    this.config = args.config;
    this.notification = args.notification;
    this.storage = args.storage;
  }

  fetch(){
    this.gitlab = GitLab.createFromConfig(this.config, this.storage);

    // If current GitLab version hasn't been obtained, attempt to obtain it periodically
    const config = this.config;
    if(!config.gitlabVersion || config.gitlabVersion == "") {
      this.gitlab.getGitLabVersion().then(function (data) {
        config.gitlabVersion = data.version;
      });
    }

    this.config.activeProjectIds.forEach((project_id) => {
      this.gitlab.getProjectEvents(project_id).then((project_events) => {
        // latest check
        if(project_events.length < 1){
          return;
        }

        let event_count = 0;
        project_events.forEach((project_event) => {
          if(event_count >= this.config.maxNotificationCount){
            return;
          }

          this.notifyProjectEvent(project_id, project_event);
          event_count++;
        });
      });
    });
  }

  notifyProjectEvent(project_id, project_event){
    const target_type = project_event.target_type || "Commit";

    let comment_target_type;
    if((target_type == "Note" || target_type == "DiffNote" ) && project_event.action_name == "commented on"){
      comment_target_type = project_event.note.noteable_type;
    }

    if(!this.isNotifyTargetEvent(project_id, target_type) && !this.isNotifyTargetEvent(project_id, comment_target_type)){
      // continue loop
      return;
    }

    const project = this.config.getProject(project_id);

    switch (target_type){
      case "Commit": {
        if(!project_event.data){
          return;
        }

        const commit_message = this.getCommitMessage(project_event);
        const display_id = this.getCommitTargetId(project_event);
        const target_url = this.getCommitTargetUrl(project_id, project_event);

        if(target_url && commit_message){
          const branch_name = project_event.data.ref.replace(/^refs\/heads\//, "");

          this.notification.notify({
            project:       project,
            project_event: project_event,
            internal: {
              target_id:  display_id,
              target_url: target_url
            },
            message:      `[${branch_name}] @${project_event.data.user_name} ${display_id} ${commit_message} (${project_event.data.total_commits_count} commits)`,
            current_time: project_event.created_at || new Date(),
            author_id:    project_event.author_id
          });
        }
        break;
      }
      case "Issue":
      case "MergeRequest": {
        // Issue, MergeRequest
        if(this.gitlab.apiVersion >= 4) {
          // API v4+
          let url;
          switch (target_type) {
            case "Issue":
              url = `${this.gitlab.gitlab_path}/${project.name}/issues/${project_event.target_iid}`;
              break;
            case "MergeRequest":
              url = `${this.gitlab.gitlab_path}/${project.name}/merge_requests/${project_event.target_iid}`;
              break;
          }

          this.notification.notify({
            project:       project,
            project_event: project_event,
            internal: {
              target_id: project_event.target_iid,
              target_url: url
            },
            message:       `[${target_type}] #${project_event.target_iid} ${project_event.target_title} ${project_event.action_name}`,
            current_time:  project_event.created_at || new Date(),
            author_id:     project_event.author_id
          });

        } else {
          // API v3
          return this.gitlab.getEventInternalId({
            project_name: project.name,
            target_type:  target_type,
            target_id:    project_event.target_id,
            project_id:   project_event.project_id,
          }).then((internal) => {
            this.notification.notify({
              project:       project,
              project_event: project_event,
              internal:      internal,
              message:       `[${target_type}] #${internal.target_id} ${project_event.target_title} ${project_event.action_name}`,
              current_time:  project_event.created_at || new Date(),
              author_id:     project_event.author_id
            });
          });
        }
        break;
      }
      case "Milestone": {
        // Milestone
        return this.gitlab.getEventInternalId({
          project_name: project.name,
          target_type:  target_type,
          target_id:    project_event.target_id,
          project_id:   project_event.project_id,
        }).then((internal) => {
          this.notification.notify({
            project:       project,
            project_event: project_event,
            internal:      internal,
            message:       `[${target_type}] #${internal.target_id} ${project_event.target_title} ${project_event.action_name}`,
            current_time:  project_event.created_at || new Date(),
            author_id:     project_event.author_id
          });
        });
      }

      case "DiffNote":
      case "Note": {
        // Issue, MergeRequest (Comment)
        if(this.gitlab.apiVersion >= 4){
          // API v4+
          let url;
          switch (project_event.note.noteable_type) {
            case "Issue":
              url = `${this.gitlab.gitlab_path}/${project.name}/issues/${project_event.note.noteable_iid}#note_${project_event.note.id}`;
              break;
            case "MergeRequest":
              url = `${this.gitlab.gitlab_path}/${project.name}/merge_requests/${project_event.note.noteable_iid}#note_${project_event.note.id}`;
              break;
          }

          const note_body = this.truncate(project_event.note.body, 200);
          this.notification.notify({
            project:       project,
            project_event: project_event,
            internal: {
              target_id: project_event.note.noteable_iid,
              target_url: url
            },
            message:       `[${project_event.note.noteable_type}] #${project_event.note.noteable_iid} ${note_body} ${project_event.action_name}`,
            current_time:  project_event.created_at || new Date(),
            author_id:     project_event.author_id
          });

        } else {
          // API v3
          return this.gitlab.getEventInternalId({
            project_name: project.name,
            target_type:  project_event.note.noteable_type,
            target_id:    project_event.note.noteable_id,
            project_id:   project_event.project_id,
          }).then((internal) => {
            internal.target_url = `${internal.target_url}#note_${project_event.note.id}`;

            const note_body = this.truncate(project_event.note.body, 200);
            this.notification.notify({
              project:       project,
              project_event: project_event,
              internal:      internal,
              message:       `[${project_event.note.noteable_type}] #${internal.target_id} ${note_body} ${project_event.action_name}`,
              current_time:  project_event.created_at || new Date(),
              author_id:     project_event.author_id
            });
          });
        }
        break;
      }
    }
  }

  getCommitMessage(project_event){
    if(!project_event.data || !project_event.data.commits || project_event.data.commits.length == 0){
      return null;
    }

    // use latest commit message
    return project_event.data.commits.reverse().map((commit) => {
      const first_line = commit.message.split(/(\r\n|\r|\n)/)[0];
      return first_line;
    }).find((first_line) => {
      return first_line.length > 0;
    });
  }

  isNotifyTargetEvent(project_id, target_type){
    const project = this.config.getProject(project_id);
    return project.events[target_type] ? true : false;
  }

  getCommitTargetId(project_event){
    const after = project_event.data.after;
    const before = project_event.data.before;

    if(this.isValidCommitId(before) && this.isValidCommitId(after)){
      return before.substr(0, 6) + "..." + after.substr(0, 6);
    } else if(this.isValidCommitId(before)){
      return before.substr(0, 6);
    } else if(this.isValidCommitId(after)){
      return after.substr(0, 6);
    }
  }

  getCommitTargetUrl(project_id, project_event){
    const project = this.config.getProject(project_id);
    const after = project_event.data.after;
    const before = project_event.data.before;

    if(this.isValidCommitId(before) && this.isValidCommitId(after)){
      return `${this.config.gitlabPath}${project.name}/compare/${before}...${after}`;
    } else if(this.isValidCommitId(before)){
      return `${this.config.gitlabPath}${project.name}/commit/${before}`;
    } else if(this.isValidCommitId(after)){
      return `${this.config.gitlabPath}${project.name}/commit/${after}`;
    }
  }

  isValidCommitId(commit_id){
    // invalid commit id is "0000000000000000000000...."
    return !commit_id.match(/^0+$/);
  }

  truncate(message, truncate_length) {
    message = message || "";
    if(message.length > truncate_length) {
      return message.substring(0, truncate_length) + "...";
    }
    return message;
  }
}

try {
  module.exports = Background;
} catch (e){
}