<commit_before>var GithubApi = require('github'),
    config = require('../config'),
    Promise = require('promise'),
    _ = require('underscore'),
    github = new GithubApi({
      debug: config.debug,
      version: '3.0.0'
    }),
    debug = require('debug')('pulldasher:github'),
    Pull = require('../models/pull'),
    Comment = require('../models/comment'),
    Label = require('../models/label'),
    Status = require('../models/status'),
    Signature = require('../models/signature'),
    rateLimit = require('./rate-limit.js');

github.authenticate({
   type: 'oauth',
   token: config.github.token
});

function denodeify(func) {
   return rateLimit(Promise.denodeify(func));
}

var api = {};
var getPull                = denodeify(github.pullRequests.get);
var getAllPulls            = denodeify(github.pullRequests.getAll);
var getIssue               = denodeify(github.issues.getRepoIssue);
var getAllIssues           = denodeify(github.issues.repoIssues);
api.getIssueEvents         = denodeify(github.issues.getEvents);
// "issue" comments are the comments on the pull (issue) itself.
api.getIssueComments       = denodeify(github.issues.getComments);
// "review" comments are the comments on the diff of the pull
api.getPullReviewComments  = denodeify(github.pullRequests.getComments);
api.getCommit              = denodeify(github.repos.getCommits);
api.getCommitStatus        = denodeify(github.statuses.get);
var getNextPage            = denodeify(github.getNextPage.bind(github));

module.exports = {
   github: github,

   /**
    * Returns a promise which resolves to a GitHub API response to
    * a query for a particular Pull Request.
    */
   getPull: function(number) {
      debug("Getting pull %s", number);
      return getPull(params({
         number:     number
      }));
   },

   /**
    * Get all *open* pull requests for a repo.
    *
    * Returns a promise which resolves to an array of all open pull requests
    */
   getOpenPulls: function() {
      debug("Getting open pulls");
      return getAllPulls(params()).then(getAllPages);
   },

   /**
    * Get *all* pull requests for a repo.
    *
    * Returns a promise which resolves to an array of all pull requests
    */
   getAllPulls: function() {
      debug("Getting all pulls");
      return getAllPulls(params({
         state:      'all'
      })).then(getAllPages);
   },

   /**
    * Get an issue for a repo.
    *
    * Returns a promise which resolves to a github issue
    */
   getIssue: function(number) {
      debug("Getting issue %s", number);
      return getIssue(params({
         number: number
      }));
   },

   /**
    * Get all open issues for a repo.
    *
    * Returns a promise which resolves to an array of all open issues
    */
   getOpenIssues: function() {
      debug("Getting open issues");
      return getAllIssues(params())
      .then(getAllPages)
      .then(filterOutPulls);
   },

   /**
    * Get *all* issues for a repo.
    *
    * Returns a promise which resolves to an array of all issues
    */
   getAllIssues: function() {
      debug("Getting all issues");
      return getAllIssues(params({
         state:      'all'
      })).then(getAllPages)
      .then(filterOutPulls);
   },

   /**
    * Takes a promise that resolves to a GitHub pull request API response,
    * parses it, and returns a promise that resolves to a Pull objects.
    */
   parse: function(githubPull) {
      debug("Getting all information for pull %s", githubPull.number);
      // We've occasionally noticed a null pull body, so lets fix it upfront
      // before errors happen.
      githubPull.body = githubPull.body || '';

      var reviewComments = getPullReviewComments(githubPull.number);
      var comments = getIssueComments(githubPull.number);
      var headCommit = getCommit(githubPull.head.sha);
      var commitStatus = getCommitStatus(githubPull.head.sha);
      var events = getIssueEvents(githubPull.number);
      // Only so we have the canonical list of labels.
      var ghIssue = module.exports.getIssue(githubPull.number);

      // Returned to the map function. Each element of githubPulls maps to
      // a promise that resolves to a Pull.
      return Promise.all([reviewComments,
                          comments,
                          headCommit,
                          commitStatus,
                          events,
                          ghIssue])
       .then(function(results) {
         var reviewComments = results[0],
             comments       = results[1],
             headCommit     = results[2],
             commitStatus   = results[3],
             events         = results[4],
             ghIssue        = results[5];

         // Array of Signature objects.
         var signatures = comments.reduce(function(sigs, comment) {
            var commentSigs = Signature.parseComment(comment, githubPull.number);

            // Signoffs from before the most recent commit are no longer active.
            var headCommitDate = new Date(headCommit.commit.committer.date);
            commentSigs.forEach(function(signature) {
               if ((signature.data.type === 'CR' ||
                signature.data.type === 'QA') &&
                new Date(signature.data.created_at) < headCommitDate) {
                  signature.data.active = false;
               }
            });

            return sigs.concat(commentSigs);
         }, []);

         // Array of Comment objects.
         comments = comments.map(function(commentData) {
            commentData.number = githubPull.number;
            commentData.repo = githubPull.base.repo.name;
            commentData.type = 'issue';

            return new Comment(commentData);
         });

         // Array of Comment objects.
         comments = comments.concat(reviewComments.map(function(commentData) {
            commentData.number = githubPull.number;
            commentData.repo = githubPull.base.repo.name;
            commentData.type = 'review';

            return new Comment(commentData);
         }));

         // Status object.
         var status = null;
         if (commitStatus) {
            status = new Status({
               sha:           githubPull.head.sha,
               state:         commitStatus.state,
               description:   commitStatus.description,
               target_url:    commitStatus.target_url
            });
         }

         // Array of Label objects.
         var labels = getLabelsFromEvents(events, ghIssue, githubPull.base.repo.name);

         var pull = new Pull(githubPull, signatures, comments, status, labels);
         return pull.syncToIssue();
      });
   },

   /**
    * Takes a GitHub issue API response
    * parses it, and returns a promise that resolves to an Issue object.
    */
   parseIssue: function(ghIssue) {
      debug("Getting all information for issue %s", ghIssue.number);
      return getIssueEvents(ghIssue.number)
      .then(function(events) {
         // Array of Label objects.
         // Note: using the repo name from the config for now until we support
         // multiple repos. The ghIssue object doesn't contain the repo name.
         var labels = getLabelsFromEvents(events, ghIssue, config.repo.name);

         return Issue.getFromGH(ghIssue, labels);
      });
   },
};

/**
 * Traverses github's pagination to retrieve *all* the records.
 * Takes in the first page of results and returns a promise for *all* the
 * results.
 */
function getAllPages(currentPage, allResults) {
   debug("Got %s results", currentPage.length);
   return new Promise(function (resolve, reject) {
      allResults = allResults || [];
      allResults.push(currentPage);

      if (!github.hasNextPage(currentPage)) {
         debug("No more results");
         return resolve(_.flatten(allResults));
      }

      resolve(getNextPage(currentPage).then(function (nextPage) {
         return getAllPages(nextPage, allResults);
      }));
   });
}

/**
 * Get array of Label objects from complete list of a Issue's events.
 */
function getLabelsFromEvents(events, ghIssue, repoName) {
   debug("Extracting label assignments from %s issue events for #%s",
    events.length, ghIssue.number);

   // Narrow list to relevant labeled/unlabeled events.
   events = _.filter(events, function(event) {
      return event.event === 'labeled' || event.event === 'unlabeled';
   });

   debug("Found %s label events for #%s", events.length, ghIssue.number);

   // Build simple Event objects with all the info we care about.
   events = events.map(function(event) {
      return {
         type: event.event,
         name: event.label.name,
         user: event.actor.login,
         created_at: new Date(event.created_at)
      };
   });

   // Group label events by label name.
   var labels = _.groupBy(events, 'name');

   // Get a list of the most recent events for each label.
   labels = _.map(labels, function(events) {
      events = _.sortBy(events, 'created_at');
      return _.last(events);
   });

   labels = _.filter(labels, function(event) {
      return event.type === 'labeled';
   });

   debug("Found %s unique labels for #%s", labels.length, ghIssue.number);

   // If these are available, use them as the canonical source, only augmented
   // by the data from events. If a label is renamed, the events will retain
   // the old name but the list of labels on the issue itself will be correct.
   // So, if a label is renamed, we'll lose the labeler and the date.
   if (ghIssue.labels && ghIssue.labels.length) {
      debug("Using %s labels from the github issue", ghIssue.labels.length);
      // Includes labeller and a time from the events api
      var eventLabels = _.indexBy(labels, 'name');

      return ghIssue.labels.map(function(label) {
         var eventLabel = eventLabels[label.name];
         return new Label(
            {name: label.name},
            ghIssue.number,
            repoName,
            eventLabel && eventLabel.user,
            eventLabel && eventLabel.created_at
         );
      });
   }

   // Construct Label objects.
   return labels.map(function(label) {
      return new Label(
         {name: label.name},
         ghIssue.number,
         repoName,
         label.user,
         label.created_at
      );
   });
}

/**
 * Return the default api params merged with the overrides
 */
function params(apiParams) {
   return _.extend({
      user:       config.repo.owner,
      repo:       config.repo.name,
      per_page:   100,
   }, apiParams);
}

/**
 * Return a promise for all issue events for the given issue / pull
 */
function getIssueEvents(issueNumber) {
   debug("Getting events for issue #%s", issueNumber);
   return api.getIssueEvents(params({
      number: issueNumber
   })).then(getAllPages);
}

function getIssueComments(issueNumber) {
   debug("Getting comments for issue #%s", issueNumber);
   return api.getIssueComments(params({
      number: issueNumber
   })).then(getAllPages);
}

function getPullReviewComments(pullNumber) {
   debug("Getting pull review comments for pull #%s", pullNumber);
   return api.getPullReviewComments(params({
      number: pullNumber
   })).then(getAllPages);
}

function getCommit(sha) {
   return new Promise(function (resolve, reject){
      debug("Getting commit %s", sha);
      api.getCommit(params({
         sha: sha,
         per_page: 1
      })).then(function(commits) {
         if (commits.length === 1) {
            resolve(commits[0]);
         } else {
            return reject();
         }
      });
   });
}

function getCommitStatus(sha) {
   return new Promise(function(resolve, reject) {
      debug("Getting commit status for %s", sha);
      api.getCommitStatus(params({
         sha: sha
      })).then(function(status) {
         if (status.length) {
            resolve(status[0]);
         } else {
            resolve(null);
         }
      });
   });
}

/**
 * Remove all entries that have the pull_request key set to something truthy
 */
function filterOutPulls(issues) {
   debug("Filtering out pulls from list of %s issues", issues.length);
   issues = _.filter(issues, function(issue) {
      return !issue.pull_request || !issue.pull_request.url;
   });
   debug("Filtered down to %s issues", issues.length);
   return issues;
}
<commit_msg>git-manager: re-add require('issue')<commit_after>var GithubApi = require('github'),
    config = require('../config'),
    Promise = require('promise'),
    _ = require('underscore'),
    github = new GithubApi({
      debug: config.debug,
      version: '3.0.0'
    }),
    debug = require('debug')('pulldasher:github'),
    Pull = require('../models/pull'),
    Issue = require('../models/issue'),
    Comment = require('../models/comment'),
    Label = require('../models/label'),
    Status = require('../models/status'),
    Signature = require('../models/signature'),
    rateLimit = require('./rate-limit.js');

github.authenticate({
   type: 'oauth',
   token: config.github.token
});

function denodeify(func) {
   return rateLimit(Promise.denodeify(func));
}

var api = {};
var getPull                = denodeify(github.pullRequests.get);
var getAllPulls            = denodeify(github.pullRequests.getAll);
var getIssue               = denodeify(github.issues.getRepoIssue);
var getAllIssues           = denodeify(github.issues.repoIssues);
api.getIssueEvents         = denodeify(github.issues.getEvents);
// "issue" comments are the comments on the pull (issue) itself.
api.getIssueComments       = denodeify(github.issues.getComments);
// "review" comments are the comments on the diff of the pull
api.getPullReviewComments  = denodeify(github.pullRequests.getComments);
api.getCommit              = denodeify(github.repos.getCommits);
api.getCommitStatus        = denodeify(github.statuses.get);
var getNextPage            = denodeify(github.getNextPage.bind(github));

module.exports = {
   github: github,

   /**
    * Returns a promise which resolves to a GitHub API response to
    * a query for a particular Pull Request.
    */
   getPull: function(number) {
      debug("Getting pull %s", number);
      return getPull(params({
         number:     number
      }));
   },

   /**
    * Get all *open* pull requests for a repo.
    *
    * Returns a promise which resolves to an array of all open pull requests
    */
   getOpenPulls: function() {
      debug("Getting open pulls");
      return getAllPulls(params()).then(getAllPages);
   },

   /**
    * Get *all* pull requests for a repo.
    *
    * Returns a promise which resolves to an array of all pull requests
    */
   getAllPulls: function() {
      debug("Getting all pulls");
      return getAllPulls(params({
         state:      'all'
      })).then(getAllPages);
   },

   /**
    * Get an issue for a repo.
    *
    * Returns a promise which resolves to a github issue
    */
   getIssue: function(number) {
      debug("Getting issue %s", number);
      return getIssue(params({
         number: number
      }));
   },

   /**
    * Get all open issues for a repo.
    *
    * Returns a promise which resolves to an array of all open issues
    */
   getOpenIssues: function() {
      debug("Getting open issues");
      return getAllIssues(params())
      .then(getAllPages)
      .then(filterOutPulls);
   },

   /**
    * Get *all* issues for a repo.
    *
    * Returns a promise which resolves to an array of all issues
    */
   getAllIssues: function() {
      debug("Getting all issues");
      return getAllIssues(params({
         state:      'all'
      })).then(getAllPages)
      .then(filterOutPulls);
   },

   /**
    * Takes a promise that resolves to a GitHub pull request API response,
    * parses it, and returns a promise that resolves to a Pull objects.
    */
   parse: function(githubPull) {
      debug("Getting all information for pull %s", githubPull.number);
      // We've occasionally noticed a null pull body, so lets fix it upfront
      // before errors happen.
      githubPull.body = githubPull.body || '';

      var reviewComments = getPullReviewComments(githubPull.number);
      var comments = getIssueComments(githubPull.number);
      var headCommit = getCommit(githubPull.head.sha);
      var commitStatus = getCommitStatus(githubPull.head.sha);
      var events = getIssueEvents(githubPull.number);
      // Only so we have the canonical list of labels.
      var ghIssue = module.exports.getIssue(githubPull.number);

      // Returned to the map function. Each element of githubPulls maps to
      // a promise that resolves to a Pull.
      return Promise.all([reviewComments,
                          comments,
                          headCommit,
                          commitStatus,
                          events,
                          ghIssue])
       .then(function(results) {
         var reviewComments = results[0],
             comments       = results[1],
             headCommit     = results[2],
             commitStatus   = results[3],
             events         = results[4],
             ghIssue        = results[5];

         // Array of Signature objects.
         var signatures = comments.reduce(function(sigs, comment) {
            var commentSigs = Signature.parseComment(comment, githubPull.number);

            // Signoffs from before the most recent commit are no longer active.
            var headCommitDate = new Date(headCommit.commit.committer.date);
            commentSigs.forEach(function(signature) {
               if ((signature.data.type === 'CR' ||
                signature.data.type === 'QA') &&
                new Date(signature.data.created_at) < headCommitDate) {
                  signature.data.active = false;
               }
            });

            return sigs.concat(commentSigs);
         }, []);

         // Array of Comment objects.
         comments = comments.map(function(commentData) {
            commentData.number = githubPull.number;
            commentData.repo = githubPull.base.repo.name;
            commentData.type = 'issue';

            return new Comment(commentData);
         });

         // Array of Comment objects.
         comments = comments.concat(reviewComments.map(function(commentData) {
            commentData.number = githubPull.number;
            commentData.repo = githubPull.base.repo.name;
            commentData.type = 'review';

            return new Comment(commentData);
         }));

         // Status object.
         var status = null;
         if (commitStatus) {
            status = new Status({
               sha:           githubPull.head.sha,
               state:         commitStatus.state,
               description:   commitStatus.description,
               target_url:    commitStatus.target_url
            });
         }

         // Array of Label objects.
         var labels = getLabelsFromEvents(events, ghIssue, githubPull.base.repo.name);

         var pull = new Pull(githubPull, signatures, comments, status, labels);
         return pull.syncToIssue();
      });
   },

   /**
    * Takes a GitHub issue API response
    * parses it, and returns a promise that resolves to an Issue object.
    */
   parseIssue: function(ghIssue) {
      debug("Getting all information for issue %s", ghIssue.number);
      return getIssueEvents(ghIssue.number)
      .then(function(events) {
         // Array of Label objects.
         // Note: using the repo name from the config for now until we support
         // multiple repos. The ghIssue object doesn't contain the repo name.
         var labels = getLabelsFromEvents(events, ghIssue, config.repo.name);

         return Issue.getFromGH(ghIssue, labels);
      });
   },
};

/**
 * Traverses github's pagination to retrieve *all* the records.
 * Takes in the first page of results and returns a promise for *all* the
 * results.
 */
function getAllPages(currentPage, allResults) {
   debug("Got %s results", currentPage.length);
   return new Promise(function (resolve, reject) {
      allResults = allResults || [];
      allResults.push(currentPage);

      if (!github.hasNextPage(currentPage)) {
         debug("No more results");
         return resolve(_.flatten(allResults));
      }

      resolve(getNextPage(currentPage).then(function (nextPage) {
         return getAllPages(nextPage, allResults);
      }));
   });
}

/**
 * Get array of Label objects from complete list of a Issue's events.
 */
function getLabelsFromEvents(events, ghIssue, repoName) {
   debug("Extracting label assignments from %s issue events for #%s",
    events.length, ghIssue.number);

   // Narrow list to relevant labeled/unlabeled events.
   events = _.filter(events, function(event) {
      return event.event === 'labeled' || event.event === 'unlabeled';
   });

   debug("Found %s label events for #%s", events.length, ghIssue.number);

   // Build simple Event objects with all the info we care about.
   events = events.map(function(event) {
      return {
         type: event.event,
         name: event.label.name,
         user: event.actor.login,
         created_at: new Date(event.created_at)
      };
   });

   // Group label events by label name.
   var labels = _.groupBy(events, 'name');

   // Get a list of the most recent events for each label.
   labels = _.map(labels, function(events) {
      events = _.sortBy(events, 'created_at');
      return _.last(events);
   });

   labels = _.filter(labels, function(event) {
      return event.type === 'labeled';
   });

   debug("Found %s unique labels for #%s", labels.length, ghIssue.number);

   // If these are available, use them as the canonical source, only augmented
   // by the data from events. If a label is renamed, the events will retain
   // the old name but the list of labels on the issue itself will be correct.
   // So, if a label is renamed, we'll lose the labeler and the date.
   if (ghIssue.labels && ghIssue.labels.length) {
      debug("Using %s labels from the github issue", ghIssue.labels.length);
      // Includes labeller and a time from the events api
      var eventLabels = _.indexBy(labels, 'name');

      return ghIssue.labels.map(function(label) {
         var eventLabel = eventLabels[label.name];
         return new Label(
            {name: label.name},
            ghIssue.number,
            repoName,
            eventLabel && eventLabel.user,
            eventLabel && eventLabel.created_at
         );
      });
   }

   // Construct Label objects.
   return labels.map(function(label) {
      return new Label(
         {name: label.name},
         ghIssue.number,
         repoName,
         label.user,
         label.created_at
      );
   });
}

/**
 * Return the default api params merged with the overrides
 */
function params(apiParams) {
   return _.extend({
      user:       config.repo.owner,
      repo:       config.repo.name,
      per_page:   100,
   }, apiParams);
}

/**
 * Return a promise for all issue events for the given issue / pull
 */
function getIssueEvents(issueNumber) {
   debug("Getting events for issue #%s", issueNumber);
   return api.getIssueEvents(params({
      number: issueNumber
   })).then(getAllPages);
}

function getIssueComments(issueNumber) {
   debug("Getting comments for issue #%s", issueNumber);
   return api.getIssueComments(params({
      number: issueNumber
   })).then(getAllPages);
}

function getPullReviewComments(pullNumber) {
   debug("Getting pull review comments for pull #%s", pullNumber);
   return api.getPullReviewComments(params({
      number: pullNumber
   })).then(getAllPages);
}

function getCommit(sha) {
   return new Promise(function (resolve, reject){
      debug("Getting commit %s", sha);
      api.getCommit(params({
         sha: sha,
         per_page: 1
      })).then(function(commits) {
         if (commits.length === 1) {
            resolve(commits[0]);
         } else {
            return reject();
         }
      });
   });
}

function getCommitStatus(sha) {
   return new Promise(function(resolve, reject) {
      debug("Getting commit status for %s", sha);
      api.getCommitStatus(params({
         sha: sha
      })).then(function(status) {
         if (status.length) {
            resolve(status[0]);
         } else {
            resolve(null);
         }
      });
   });
}

/**
 * Remove all entries that have the pull_request key set to something truthy
 */
function filterOutPulls(issues) {
   debug("Filtering out pulls from list of %s issues", issues.length);
   issues = _.filter(issues, function(issue) {
      return !issue.pull_request || !issue.pull_request.url;
   });
   debug("Filtered down to %s issues", issues.length);
   return issues;
}
<|endoftext|>


<commit_before>var GithubApi = require('github'),
    config = require('../config'),
    Promise = require('bluebird'),
    _ = require('underscore'),
    github = new GithubApi({
      debug: config.debug,
      version: '3.0.0'
    }),
    debug = require('./debug')('pulldasher:github'),
    utils = require('./utils'),
    Pull = require('../models/pull'),
    Issue = require('../models/issue'),
    Comment = require('../models/comment'),
    Label = require('../models/label'),
    Status = require('../models/status'),
    Signature = require('../models/signature'),
    getLogin  = require('./get-user-login'),
    rateLimit = require('./rate-limit.js');

github.authenticate({
   type: 'oauth',
   token: config.github.token
});

function denodeify(func) {
   return rateLimit(Promise.promisify(func));
}

var api = {};
var getPull                = denodeify(github.pullRequests.get);
var getAllPulls            = denodeify(github.pullRequests.getAll);
var getIssue               = denodeify(github.issues.getRepoIssue);
var getAllIssues           = denodeify(github.issues.repoIssues);
api.getIssueEvents         = denodeify(github.issues.getEvents);
// "issue" comments are the comments on the pull (issue) itself.
api.getIssueComments       = denodeify(github.issues.getComments);
// "review" comments are the comments on the diff of the pull
api.getPullReviewComments  = denodeify(github.pullRequests.getComments);
api.getCommit              = denodeify(github.repos.getCommits);
api.getCommitStatus        = denodeify(github.statuses.get);
var getNextPage            = denodeify(github.getNextPage.bind(github));

module.exports = {
   github: github,

   /**
    * Returns a promise which resolves to a GitHub API response to
    * a query for a particular Pull Request.
    */
   getPull: function(repo, number) {
      debug("Getting pull %s", number);
      return getPull(params({
         number:     number
      }, repo));
   },

   /**
    * Get all *open* pull requests for a repo.
    *
    * Returns a promise which resolves to an array of all open pull requests
    */
   getOpenPulls: function(repo) {
      debug("Getting open pulls in repo %s", repo);
      return getAllPulls(params({}, repo)).then(getAllPages);
   },

   /**
    * Get *all* pull requests for a repo.
    *
    * Returns a promise which resolves to an array of all pull requests
    */
   getAllPulls: function(repo) {
      debug("Getting all pulls in repo %s", repo);
      return getAllPulls(params({
         state: 'all'
      }, repo)).then(getAllPages);
   },

   /**
    * Get an issue for a repo.
    *
    * Returns a promise which resolves to a github issue
    */
   getIssue: function(repo, number) {
      var searchParams = params({number: number}, repo);
      debug("Getting issue %s in repo %s", number, repo);
      return getIssue(searchParams)
      .then(addRepo(searchParams));
   },

   /**
    * Get all open issues for a repo.
    *
    * Returns a promise which resolves to an array of all open issues
    */
   getOpenIssues: function(repo) {
      var searchParams = params({}, repo);
      debug("Getting open issues");
      return getAllIssues(searchParams)
      .then(getAllPages)
      .then(filterOutPulls)
      .then(addRepo(searchParams));
   },

   /**
    * Get *all* issues for a repo.
    *
    * Returns a promise which resolves to an array of all issues
    */
   getAllIssues: function(repo) {
      var searchParams = params({state: 'all'}, repo);
      debug("Getting all issues");
      return getAllIssues(searchParams)
      .then(getAllPages)
      .then(filterOutPulls)
      .then(addRepo(searchParams));
   },

   /**
    * Takes a promise that resolves to a GitHub pull request API response,
    * parses it, and returns a promise that resolves to a Pull objects.
    */
   parse: function(githubPull) {
      debug("Getting all information for pull %s in repo %s", githubPull.number,
         githubPull.base.repo.full_name);
      // We've occasionally noticed a null pull body, so lets fix it upfront
      // before errors happen.
      githubPull.body = githubPull.body || '';

      var repo = githubPull.base.repo.full_name;

      var reviewComments = getPullReviewComments(repo, githubPull.number);
      var comments = getIssueComments(repo, githubPull.number);
      var headCommit = getCommit(repo, githubPull.head.sha);
      var commitStatus = getCommitStatus(repo, githubPull.head.sha);
      var events = getIssueEvents(repo, githubPull.number);
      // Only so we have the canonical list of labels.
      var ghIssue = module.exports.getIssue(repo, githubPull.number);

      // Returned to the map function. Each element of githubPulls maps to
      // a promise that resolves to a Pull.
      return Promise.all([reviewComments,
                          comments,
                          headCommit,
                          commitStatus,
                          events,
                          ghIssue])
       .then(function(results) {
         var reviewComments = results[0],
             comments       = results[1],
             headCommit     = results[2],
             commitStatus   = results[3],
             events         = results[4],
             ghIssue        = results[5];

         // Array of Signature objects.
         var signatures = comments.reduce(function(sigs, comment) {
            var commentSigs = Signature.parseComment(
             comment, repo, githubPull.number);

            // Signoffs from before the most recent commit are no longer active.
            var headCommitDate = new Date(headCommit.commit.committer.date);
            commentSigs.forEach(function(signature) {
               if ((signature.data.type === 'CR' ||
                signature.data.type === 'QA') &&
                new Date(signature.data.created_at) < headCommitDate) {
                  signature.data.active = false;
               }
            });

            return sigs.concat(commentSigs);
         }, []);

         // Array of Comment objects.
         comments = comments.map(function(commentData) {
            commentData.number = githubPull.number;
            commentData.repo = repo;
            commentData.type = 'issue';

            return new Comment(commentData);
         });

         // Array of Comment objects.
         comments = comments.concat(reviewComments.map(function(commentData) {
            commentData.number = githubPull.number;
            commentData.repo = repo;
            commentData.type = 'review';

            return new Comment(commentData);
         }));

         // Status object.
         var status = null;
         if (commitStatus) {
            status = new Status({
               repo:          repo,
               sha:           githubPull.head.sha,
               state:         commitStatus.state,
               description:   commitStatus.description,
               target_url:    commitStatus.target_url
            });
         }

         // Array of Label objects.
         var labels = getLabelsFromEvents(events, ghIssue);

         var pull = Pull.fromGithubApi(githubPull, signatures, comments, status, labels);
         return pull.syncToIssue();
      });
   },

   /**
    * Takes a GitHub issue API response
    * parses it, and returns a promise that resolves to an Issue object.
    */
   parseIssue: function(ghIssue) {
      debug("Getting all information for issue %s in repo %s", ghIssue.number,
         ghIssue.repo);
      return getIssueEvents(ghIssue.repo, ghIssue.number)
      .then(function(events) {
         // Array of Label objects.
         // Note: using the repo name from the config for now until we support
         // multiple repos. The ghIssue object doesn't contain the repo name.
         var labels = getLabelsFromEvents(events, ghIssue);

         return Issue.getFromGH(ghIssue, labels);
      });
   },
};

/**
 * Traverses github's pagination to retrieve *all* the records.
 * Takes in the first page of results and returns a promise for *all* the
 * results.
 */
function getAllPages(currentPage, allResults) {
   debug("Got %s results", currentPage.length);
   return new Promise(function (resolve, reject) {
      allResults = allResults || [];
      allResults.push(currentPage);

      if (!github.hasNextPage(currentPage)) {
         debug("No more results");
         return resolve(_.flatten(allResults));
      }

      resolve(getNextPage(currentPage).then(function (nextPage) {
         return getAllPages(nextPage, allResults);
      }));
   });
}

/**
 * Get array of Label objects from complete list of a Issue's events.
 *
 * Note: ghIssue at this point has always come from one of the
 * get*Issues() commands and thus has been augmented with the
 * issue.repo property.
 */
function getLabelsFromEvents(events, ghIssue) {
   debug("Extracting label assignments from %s issue events for #%s",
    events.length, ghIssue.number);

   // Narrow list to relevant labeled/unlabeled events.
   events = _.filter(events, function(event) {
      return event.event === 'labeled' || event.event === 'unlabeled';
   });

   debug("Found %s label events for #%s", events.length, ghIssue.number);

   // Build simple Event objects with all the info we care about.
   events = events.map(function(event) {
      return {
         type: event.event,
         name: event.label.name,
         user: getLogin(event.actor),
         created_at: utils.fromDateString(event.created_at)
      };
   });

   // Group label events by label name.
   var labels = _.groupBy(events, 'name');

   // Get a list of the most recent events for each label.
   labels = _.map(labels, function(events) {
      events = _.sortBy(events, 'created_at');
      return _.last(events);
   });

   labels = _.filter(labels, function(event) {
      return event.type === 'labeled';
   });

   debug("Found %s unique labels for #%s", labels.length, ghIssue.number);

   // If these are available, use them as the canonical source, only augmented
   // by the data from events. If a label is renamed, the events will retain
   // the old name but the list of labels on the issue itself will be correct.
   // So, if a label is renamed, we'll lose the labeler and the date.
   if (ghIssue.labels && ghIssue.labels.length) {
      debug("Using %s labels from the github issue", ghIssue.labels.length);
      // Includes labeller and a time from the events api
      var eventLabels = _.indexBy(labels, 'name');

      return ghIssue.labels.map(function(label) {
         var eventLabel = eventLabels[label.name];
         return new Label(
            {name: label.name},
            ghIssue.number,
            ghIssue.repo,
            eventLabel && eventLabel.user,
            eventLabel && eventLabel.created_at
         );
      });
   }

   // Construct Label objects.
   return labels.map(function(label) {
      return new Label(
         {name: label.name},
         ghIssue.number,
         ghIssue.repo,
         label.user,
         label.created_at
      );
   });
}

/**
 * Return the default api params merged with the overrides
 */
function params(apiParams, repo) {
   var repoArray = parseRepo(repo);
   var owner = repoArray[0];
   var repoName = repoArray[1];

   return _.extend({
      user:       owner,
      repo:       repoName,
      per_page:   100,
   }, apiParams);
}

/**
 * Returns a function that uses the search parameters to add the "repo"
 * property to all the results. When we ask for a list of open issues from the
 * API for a particular repo, those results don't have references to the repo
 * we asked about, so we have to inject them to normalize the structure of the
 * object.
 */
function addRepo(params) {
   function addRepositoryField(ghIssue) {
      ghIssue.repo = params.user + "/" + params.repo;
   }
   return function(results) {
      if (Array.isArray(results)) {
         results.forEach(addRepositoryField);
      } else {
         addRepositoryField(results);
      }
      return results;
   };
}

/**
 * Splits the repo into the owner and repo name.
 */
function parseRepo(repo) {
   return repo.split("/");
}

/**
 * Return a promise for all issue events for the given issue / pull
 */
function getIssueEvents(repo, issueNumber) {
   debug("Getting events for issue #%s", issueNumber);
   return api.getIssueEvents(params({
      number: issueNumber
   }, repo)).then(getAllPages);
}

function getIssueComments(repo, issueNumber) {
   debug("Getting comments for issue #%s", issueNumber);
   return api.getIssueComments(params({
      number: issueNumber
   }, repo)).then(getAllPages);
}

function getPullReviewComments(repo, pullNumber) {
   debug("Getting pull review comments for pull #%s", pullNumber);
   return api.getPullReviewComments(params({
      number: pullNumber
   }, repo)).then(getAllPages);
}

function getCommit(repo, sha) {
   return new Promise(function (resolve, reject){
      debug("Getting commit %s", sha);
      api.getCommit(params({
         sha: sha,
         per_page: 1
      }, repo)).then(function(commits) {
         if (commits.length === 1) {
            resolve(commits[0]);
         } else {
            return reject();
         }
      });
   });
}

function getCommitStatus(repo, sha) {
   return new Promise(function(resolve, reject) {
      debug("Getting commit status for %s", sha);
      api.getCommitStatus(params({
         sha: sha
      }, repo)).then(function(status) {
         if (status.length) {
            resolve(status[0]);
         } else {
            resolve(null);
         }
      });
   });
}

/**
 * Remove all entries that have the pull_request key set to something truthy
 */
function filterOutPulls(issues) {
   debug("Filtering out pulls from list of %s issues", issues.length);
   issues = _.filter(issues, function(issue) {
      return !issue.pull_request || !issue.pull_request.url;
   });
   debug("Filtered down to %s issues", issues.length);
   return issues;
}
<commit_msg>Update octokit underneath git-manager<commit_after>var GithubApi = require('@octokit/rest'),
    config = require('../config'),
    Promise = require('bluebird'),
    _ = require('underscore'),
    github = new GithubApi({
      debug: config.debug,
      version: '3.0.0'
    }),
    debug = require('./debug')('pulldasher:github'),
    utils = require('./utils'),
    Pull = require('../models/pull'),
    Issue = require('../models/issue'),
    Comment = require('../models/comment'),
    Label = require('../models/label'),
    Status = require('../models/status'),
    Signature = require('../models/signature'),
    getLogin  = require('./get-user-login'),
    rateLimit = require('./rate-limit.js');

github.authenticate({
   type: 'oauth',
   token: config.github.token
});

module.exports = {
   github: github,

   /**
    * Returns a promise which resolves to a GitHub API response to
    * a query for a particular Pull Request.
    */
   getPull: function(repo, number) {
      debug("Getting pull %s", number);
      return github.pullRequests.get(params({ number }, repo))
                                .then(res => res.data);
   },

   /**
    * Get all *open* pull requests for a repo.
    *
    * Returns a promise which resolves to an array of all open pull requests
    */
   getOpenPulls: function(repo) {
      debug("Getting open pulls in repo %s", repo);
      return github.pullRequests.getAll(params({}, repo)).then(paginate);
   },

   /**
    * Get *all* pull requests for a repo.
    *
    * Returns a promise which resolves to an array of all pull requests
    */
   getAllPulls: function(repo) {
      debug("Getting all pulls in repo %s", repo);
      return github.pullRequests.getAll(params({ state: 'all' }, repo))
                                .then(paginate);
   },

   /**
    * Get an issue for a repo.
    *
    * Returns a promise which resolves to a github issue
    */
   getIssue: function(repo, number) {
      const searchParams = params({ number }, repo);
      debug("Getting issue %s in repo %s", number, repo);
      return github.issues.get(searchParams)
                          .then(res => res.data)
                          .then(addRepo(searchParams));
   },

   /**
    * Get all open issues for a repo.
    *
    * Returns a promise which resolves to an array of all open issues
    */
   getOpenIssues: function(repo) {
      const searchParams = params({}, repo);
      debug("Getting open issues");
      return github.issues.getAll(searchParams)
      .then(paginate)
      .then(filterOutPulls)
      .then(addRepo(searchParams));
   },

   /**
    * Get *all* issues for a repo.
    *
    * Returns a promise which resolves to an array of all issues
    */
   getAllIssues: function(repo) {
      const searchParams = params({state: 'all'}, repo);
      debug("Getting all issues");
      return github.issues.getAll(searchParams)
      .then(paginate)
      .then(filterOutPulls)
      .then(addRepo(searchParams));
   },

   /**
    * Takes a promise that resolves to a GitHub pull request API response,
    * parses it, and returns a promise that resolves to a Pull objects.
    */
   parse: function(githubPull) {
      debug("Getting all information for pull %s in repo %s", githubPull.number,
         githubPull.base.repo.full_name);
      // We've occasionally noticed a null pull body, so lets fix it upfront
      // before errors happen.
      githubPull.body = githubPull.body || '';

      var repo = githubPull.base.repo.full_name;

      var reviewComments = getPullReviewComments(repo, githubPull.number);
      var comments = getIssueComments(repo, githubPull.number);
      var headCommit = getCommit(repo, githubPull.head.sha);
      var commitStatus = getCommitStatus(repo, githubPull.head.sha);
      var events = getIssueEvents(repo, githubPull.number);
      // Only so we have the canonical list of labels.
      var ghIssue = module.exports.getIssue(repo, githubPull.number);

      // Returned to the map function. Each element of githubPulls maps to
      // a promise that resolves to a Pull.
      return Promise.all([reviewComments,
                          comments,
                          headCommit,
                          commitStatus,
                          events,
                          ghIssue])
       .then(function(results) {
         var reviewComments = results[0],
             comments       = results[1],
             headCommit     = results[2],
             commitStatus   = results[3],
             events         = results[4],
             ghIssue        = results[5];

         // Array of Signature objects.
         var signatures = comments.reduce(function(sigs, comment) {
            var commentSigs = Signature.parseComment(
             comment, repo, githubPull.number);

            // Signoffs from before the most recent commit are no longer active.
            var headCommitDate = new Date(headCommit.commit.committer.date);
            commentSigs.forEach(function(signature) {
               if ((signature.data.type === 'CR' ||
                signature.data.type === 'QA') &&
                new Date(signature.data.created_at) < headCommitDate) {
                  signature.data.active = false;
               }
            });

            return sigs.concat(commentSigs);
         }, []);

         // Array of Comment objects.
         comments = comments.map(function(commentData) {
            commentData.number = githubPull.number;
            commentData.repo = repo;
            commentData.type = 'issue';

            return new Comment(commentData);
         });

         // Array of Comment objects.
         comments = comments.concat(reviewComments.map(function(commentData) {
            commentData.number = githubPull.number;
            commentData.repo = repo;
            commentData.type = 'review';

            return new Comment(commentData);
         }));

         // Status object.
         let status = null;
         if (commitStatus) {
            status = new Status({
               repo:          repo,
               sha:           githubPull.head.sha,
               state:         commitStatus.state,
               description:   commitStatus.description,
               target_url:    commitStatus.target_url
            });
         }

         // Array of Label objects.
         const labels = getLabelsFromEvents(events, ghIssue);

         const pull = Pull.fromGithubApi(githubPull, signatures, comments, status, labels);
         return pull.syncToIssue();
      });
   },

   /**
    * Takes a GitHub issue API response
    * parses it, and returns a promise that resolves to an Issue object.
    */
   parseIssue: function(ghIssue) {
      debug("Getting all information for issue %s in repo %s", ghIssue.number,
         ghIssue.repo);
      return getIssueEvents(ghIssue.repo, ghIssue.number)
      .then(function(events) {
         // Array of Label objects.
         // Note: using the repo name from the config for now until we support
         // multiple repos. The ghIssue object doesn't contain the repo name.
         var labels = getLabelsFromEvents(events, ghIssue);

         return Issue.getFromGH(ghIssue, labels);
      });
   },
};

async function paginate(res) {
   let response = res;
   let all = res.data;

   while (github.hasNextPage(response)) {
      response = await github.getNextPage(response);
      all = all.concat(response.data);
   }

   return all;
}

/**
 * Get array of Label objects from complete list of a Issue's events.
 *
 * Note: ghIssue at this point has always come from one of the
 * get*Issues() commands and thus has been augmented with the
 * issue.repo property.
 */
function getLabelsFromEvents(events, ghIssue) {
   debug("Extracting label assignments from %s issue events for #%s",
    events.length, ghIssue.number);

   // Narrow list to relevant labeled/unlabeled events.
   events = _.filter(events, function(event) {
      return event.event === 'labeled' || event.event === 'unlabeled';
   });

   debug("Found %s label events for #%s", events.length, ghIssue.number);

   // Build simple Event objects with all the info we care about.
   events = events.map(function(event) {
      return {
         type: event.event,
         name: event.label.name,
         user: getLogin(event.actor),
         created_at: utils.fromDateString(event.created_at)
      };
   });

   // Group label events by label name.
   var labels = _.groupBy(events, 'name');

   // Get a list of the most recent events for each label.
   labels = _.map(labels, function(events) {
      events = _.sortBy(events, 'created_at');
      return _.last(events);
   });

   labels = _.filter(labels, function(event) {
      return event.type === 'labeled';
   });

   debug("Found %s unique labels for #%s", labels.length, ghIssue.number);

   // If these are available, use them as the canonical source, only augmented
   // by the data from events. If a label is renamed, the events will retain
   // the old name but the list of labels on the issue itself will be correct.
   // So, if a label is renamed, we'll lose the labeler and the date.
   if (ghIssue.labels && ghIssue.labels.length) {
      debug("Using %s labels from the github issue", ghIssue.labels.length);
      // Includes labeller and a time from the events api
      var eventLabels = _.indexBy(labels, 'name');

      return ghIssue.labels.map(function(label) {
         var eventLabel = eventLabels[label.name];
         return new Label(
            {name: label.name},
            ghIssue.number,
            ghIssue.repo,
            eventLabel && eventLabel.user,
            eventLabel && eventLabel.created_at
         );
      });
   }

   // Construct Label objects.
   return labels.map(function(label) {
      return new Label(
         {name: label.name},
         ghIssue.number,
         ghIssue.repo,
         label.user,
         label.created_at
      );
   });
}

/**
 * Return the default api params merged with the overrides
 */
function params(apiParams, fullRepoName) {
   const [owner, repo] = parseRepo(fullRepoName);

   return _.extend({
      owner,
      repo,
      per_page:   100
   }, apiParams);
}

/**
 * Returns a function that uses the search parameters to add the "repo"
 * property to all the results. When we ask for a list of open issues from the
 * API for a particular repo, those results don't have references to the repo
 * we asked about, so we have to inject them to normalize the structure of the
 * object.
 */
function addRepo({owner, repo}) {
   function addRepositoryField(ghIssue) {
      ghIssue.repo = owner + "/" + repo;
   }
   return function(results) {
      if (Array.isArray(results)) {
         results.forEach(addRepositoryField);
      } else {
         addRepositoryField(results);
      }
      return results;
   };
}

/**
 * Splits the repo into the owner and repo name.
 */
function parseRepo(repo) {
   return repo.split("/");
}

/**
 * Return a promise for all issue events for the given issue / pull
 */
function getIssueEvents(repo, number) {
   debug("Getting events for issue #%s", number);
   return github.issues.getEvents(params({ number }, repo))
                       .then(paginate);
}

function getIssueComments(repo, number) {
   debug("Getting comments for issue #%s", number);
   return github.issues.getComments(params({ number }, repo))
                       .then(paginate);
}

function getPullReviewComments(repo, number) {
   debug("Getting pull review comments for pull #%s", number);
   return github.pullRequests.getComments(params({ number }, repo))
                .then(paginate);
}

function getCommit(repo, sha) {
   return github.repos.getCommit(params({ sha }, repo))
                      .then(res => res.data);
}

function getCommitStatus(repo, ref) {
   debug("Getting commit status for %s", ref);
   return github.repos.getStatuses(params({ ref }, repo))
                      .then(res => res.data)
                      .then(statuses => statuses.length ? statuses[0] : null);
}

/**
 * Remove all entries that have the pull_request key set to something truthy
 */
function filterOutPulls(issues) {
   debug("Filtering out pulls from list of %s issues", issues.length);
   issues = _.filter(issues,
                     issue => !issue.pull_request || !issue.pull_request.url);
   debug("Filtered down to %s issues", issues.length);
   return issues;
}
<|endoftext|>


<commit_before>var request = require('request')

const getGithubToken = (installationId, jwt) => {
  return new Promise((resolve, reject) => {
    request.post(
      {
        url: 'https://api.github.com/installations/' + installationId + '/access_tokens',
        auth: {'bearer': jwt},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.machine-man-preview+json'
        }
      },
      (err, res, body) => {
        if (err) { reject('There was a problem with the github certificate.') }
        else { resolve(JSON.parse(body).token) }
      }
    )
  })
}

const getPullRequestByUrl = (pullUrl, ghToken) => {
  return new Promise((resolve, reject) => {
    request.get(
      {
        url: pullUrl,
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        }
      },
      (err, res, body) => {
        if (err) { reject('There was a problem getting pull request by url.') }
        else { resolve(JSON.parse(body)) }
      }
    )
  })
}

const getPullRequestByBranch = (fullName, branchName, ghToken) => {
  return new Promise((resolve, reject) => {
    request.get(
      {
        url: 'https://api.github.com/repos/' + fullName + '/pulls',
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        },
        qs: {state: 'all', head: fullName.split('/')[0] + ':' + branchName}
      },
      (err, res, body) => {
        var pulls = JSON.parse(body)
        if (err) { reject('There was a problem getting pull request by branch name.') }
        else { resolve(pulls[0]) } // <-- assume the most recent one is the one we want (ordered by created_at)
      }
    )
  })
}

const getPullComments = (commentsUrl, ghToken) => {
  return new Promise((resolve, reject) => {
    request.get(
      {
        url: commentsUrl,
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        }
      },
      (err, res, body) => {
        if (err) { reject('There was a problem getting pull request comments.') }
        else { resolve(JSON.parse(body)) }
      }
    )
  })
}

const deleteComment = (commentUrl, ghToken) => {
  return new Promise((resolve, reject) => {
    request.delete(
      {
        url: commentUrl,
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        }
      },
      (err, res, body) => {
        if (err) { reject('There was a problem deleting a comment.') }
        else { resolve() }
      }
    )
  })
}

const deleteMultipleComments = (comments, ghToken) => {
  var promises = []
  comments.forEach((comment) => {
    promises.push(new Promise((resolve, reject) => {
      deleteComment(comment.url, ghToken).then((err) => {
        if (err) { reject('There was a problem deleting one of multiple comments.') }
        else { resolve() }
      })
    }))
  })
  return Promise.all(promises)
}

const commentOnPullRequest = (commentsUrl, message, ghToken) => {
  return new Promise((resolve, reject) => {
    request.post(
      {
        url: commentsUrl,
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        },
        json: {body: message}
      },
      (err, res, body) => {
        if (err) { reject('There was a problem commenting on pull request.') }
        else { resolve(body) }
      }
    )
  })
}

const getPullLabels = (issueUrl, ghToken) => {
  return new Promise((resolve, reject) => {
    request.get(
      {
        url: issueUrl + '/labels',
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        }
      },
      (err, res, body) => {
        if (err) { reject('There was a problem getting pull request labels.') }
        else { resolve(JSON.parse(body)) }
      }
    )
  })
}

const addLabelToPullRequest = (issueUrl, label, ghToken) => {
  return new Promise((resolve, reject) => {
    request.post(
      {
        url: issueUrl + '/labels',
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        },
        json: [label]
      },
      (err, res, body) => {
        if (err) { reject('There was a problem adding a label to a pull request.') }
        else { resolve() }
      }
    )
  })
}

const deleteLabelFromPullRequest = (issueUrl, label, ghToken) => {
  return new Promise((resolve, reject) => {
    request.delete(
      {
        url: issueUrl + '/labels/' + label,
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        }
      },
      (err, res, body) => {
        if (err) { reject('There was a problem deleting a label.') }
        else { resolve() }
      }
    )
  })
}

module.exports = {
  getGithubToken,
  getPullRequestByUrl,
  getPullRequestByBranch,
  getPullComments,
  deleteComment,
  deleteMultipleComments,
  commentOnPullRequest,
  getPullLabels,
  addLabelToPullRequest,
  deleteLabelFromPullRequest
}
<commit_msg>Migrated away from deprecated Github APIs<commit_after>var request = require('request')

const getGithubToken = (installationId, jwt) => {
  return new Promise((resolve, reject) => {
    request.post(
      {
        url: 'https://api.github.com/app/installations/' + installationId + '/access_tokens',
        auth: {'bearer': jwt},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.machine-man-preview+json'
        }
      },
      (err, res, body) => {
        if (err) { reject('There was a problem with the github certificate.') }
        else { resolve(JSON.parse(body).token) }
      }
    )
  })
}

const getPullRequestByUrl = (pullUrl, ghToken) => {
  return new Promise((resolve, reject) => {
    request.get(
      {
        url: pullUrl,
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        }
      },
      (err, res, body) => {
        if (err) { reject('There was a problem getting pull request by url.') }
        else { resolve(JSON.parse(body)) }
      }
    )
  })
}

const getPullRequestByBranch = (fullName, branchName, ghToken) => {
  return new Promise((resolve, reject) => {
    request.get(
      {
        url: 'https://api.github.com/repos/' + fullName + '/pulls',
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        },
        qs: {state: 'all', head: fullName.split('/')[0] + ':' + branchName}
      },
      (err, res, body) => {
        var pulls = JSON.parse(body)
        if (err) { reject('There was a problem getting pull request by branch name.') }
        else { resolve(pulls[0]) } // <-- assume the most recent one is the one we want (ordered by created_at)
      }
    )
  })
}

const getPullComments = (commentsUrl, ghToken) => {
  return new Promise((resolve, reject) => {
    request.get(
      {
        url: commentsUrl,
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        }
      },
      (err, res, body) => {
        if (err) { reject('There was a problem getting pull request comments.') }
        else { resolve(JSON.parse(body)) }
      }
    )
  })
}

const deleteComment = (commentUrl, ghToken) => {
  return new Promise((resolve, reject) => {
    request.delete(
      {
        url: commentUrl,
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        }
      },
      (err, res, body) => {
        if (err) { reject('There was a problem deleting a comment.') }
        else { resolve() }
      }
    )
  })
}

const deleteMultipleComments = (comments, ghToken) => {
  var promises = []
  comments.forEach((comment) => {
    promises.push(new Promise((resolve, reject) => {
      deleteComment(comment.url, ghToken).then((err) => {
        if (err) { reject('There was a problem deleting one of multiple comments.') }
        else { resolve() }
      })
    }))
  })
  return Promise.all(promises)
}

const commentOnPullRequest = (commentsUrl, message, ghToken) => {
  return new Promise((resolve, reject) => {
    request.post(
      {
        url: commentsUrl,
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        },
        json: {body: message}
      },
      (err, res, body) => {
        if (err) { reject('There was a problem commenting on pull request.') }
        else { resolve(body) }
      }
    )
  })
}

const getPullLabels = (issueUrl, ghToken) => {
  return new Promise((resolve, reject) => {
    request.get(
      {
        url: issueUrl + '/labels',
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        }
      },
      (err, res, body) => {
        if (err) { reject('There was a problem getting pull request labels.') }
        else { resolve(JSON.parse(body)) }
      }
    )
  })
}

const addLabelToPullRequest = (issueUrl, label, ghToken) => {
  return new Promise((resolve, reject) => {
    request.post(
      {
        url: issueUrl + '/labels',
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        },
        json: [label]
      },
      (err, res, body) => {
        if (err) { reject('There was a problem adding a label to a pull request.') }
        else { resolve() }
      }
    )
  })
}

const deleteLabelFromPullRequest = (issueUrl, label, ghToken) => {
  return new Promise((resolve, reject) => {
    request.delete(
      {
        url: issueUrl + '/labels/' + label,
        auth: {'bearer': ghToken},
        headers: {
          'User-Agent': 'node.js',
          'Accept': 'application/vnd.github.v3+json'
        }
      },
      (err, res, body) => {
        if (err) { reject('There was a problem deleting a label.') }
        else { resolve() }
      }
    )
  })
}

module.exports = {
  getGithubToken,
  getPullRequestByUrl,
  getPullRequestByBranch,
  getPullComments,
  deleteComment,
  deleteMultipleComments,
  commentOnPullRequest,
  getPullLabels,
  addLabelToPullRequest,
  deleteLabelFromPullRequest
}
<|endoftext|>


<commit_before>$(document).ready(function() {

  $(".submission-box").on("keyup", function() {
    setGoldenText(this)
  })

  $('tr.route').mouseover(function(){
    addClassHover(this)
  });

  $('tr.route').mouseout(function(){
    $(this).removeClass('hover');
  });

  $(".route").on("click", function() {
    $(this).next().toggle();
    $(this).toggleClass('in-use');
    $(this).toggleClass('hover');

    var rand100 = Math.floor(Math.random() * 100)
    if (rand100 === 69) {
      $('.sub-box-under').text("Chi Bobolinks 2015!")
    } //else if (rand100 >= 80) {
    //   $('.sub-box-under').text("Type something in!")
    // } else if (rand100 >= 60) {
    //     $('.sub-box-under').text("Try your own!")
    // } else if (rand100 >= 40) {
    //     $('.sub-box-under').text("Rest-a-licious!")
    // } else if (rand100 >= 20) {
    //     $('.sub-box-under').text("Rapid Restful Results! (TM)")
    // } else {
    //     $('.sub-box-under').text("Kitchen it? Kitchen it.")
    // }
  });

  var client = new ZeroClipboard( $(".route-pre") );

  client.on( "ready", function( readyEvent ) {
    client.on("copy", function(event) {
      console.log(client);
      var preData = event.target.innerText;
      client.setText(preData);
    })
    client.on( "aftercopy", function( event ) {
      $(event.target).siblings(".copy-prompt").text("Copied!");
      $(event.target).addClass(".on-click")
      setTimeout(function(){
        $(event.target).siblings(".copy-prompt").text("^click to copy^");
        $(event.target).addClass(".on-click");
      }, 1000);
    });
  });

}); //end of (document).ready()

function setGoldenText(that) {
  $(".golden-text").text($(that).val().toLowerCase());
  $(".g-text-singular").text(pluralize(capitalize($(that).val()), 1));
  $(".g-text-s-dc").text((pluralize($(that).val(), 1)));
}

function addClassHover(that) {
  $(that).addClass('hover');
}

function capitalize(string) {
  var lowerCaseString = string.toLowerCase();
  return lowerCaseString.charAt(0).toUpperCase() + lowerCaseString.slice(1);
}<commit_msg>OOJS-age to the fuckin' MAX. It's glorious. PS. Don't look at the ZeroClipboard stuff.<commit_after>$(document).ready(function() {

  $(".submission-box").on("keyup", function() {
    setGoldenText(this);
  })

  $('tr.route').mouseover(function(){
    addClassHover(this);
  });

  $('tr.route').mouseout(function(){
    removeClassHover(this);
  });

  $(".route").on("click", function() {
    toggleNext(this);
    toggleTRClass(this);
    squadLove();
  });

//############ ZeroClipboard Nightmare #########################

  var client = new ZeroClipboard( $(".route-pre") );

  client.on( "ready", function( readyEvent ) {
    client.on("copy", function(event) {
      console.log(client);
      var preData = event.target.innerText;
      client.setText(preData);
    })
    client.on( "aftercopy", function( event ) {
      $(event.target).siblings(".copy-prompt").text("Copied!");
      $(event.target).addClass(".on-click")
      setTimeout(function(){
        $(event.target).siblings(".copy-prompt").text("^click to copy^");
        $(event.target).addClass(".on-click");
      }, 1000);
    });
  });

//################ Thank god that's over ##########################

}); //end of (document).ready()

//######################## Functions #############################

function removeClassHover(that) {
  $(that).removeClass('hover');
}

function setGoldenText(that) {
  $(".golden-text").text($(that).val().toLowerCase());
  $(".g-text-singular").text(pluralize(capitalize($(that).val()), 1));
  $(".g-text-s-dc").text((pluralize($(that).val(), 1)));
}

function addClassHover(that) {
  $(that).addClass('hover');
}

function toggleNext(that) {
  $(that).next().toggle();
}

function toggleTRClass(that) {
  $(that).toggleClass('in-use');
  $(that).toggleClass('hover');
}

function squadLove() {
  var rand100 = Math.floor(Math.random() * 100)
  if (rand100 === 69) {
    $('.sub-box-under').text("Chi Bobolinks 2015!")
  }
}

function capitalize(string) {
  var lowerCaseString = string.toLowerCase();
  return lowerCaseString.charAt(0).toUpperCase() + lowerCaseString.slice(1);
}<|endoftext|>


<commit_before><commit_msg>update testing setup.js<commit_after><|endoftext|>


<commit_before><commit_msg>Printed replies<commit_after><|endoftext|>


<commit_before><commit_msg>chore: fixes clear-package-dir script for windows (#19595)<commit_after><|endoftext|>


<commit_before><commit_msg>Add tests for lateralusEvents map.<commit_after><|endoftext|>


<commit_before>'use strict';
var fs = require("fs");
var async = require("async");
var request = require("request");
var hostModel = require("../../models/host.js");
const utils = require("../../utils/utils.js");

function checkReturnError(soajs, mainCb, data, cb) {
	utils.checkErrorReturn(soajs, mainCb, data, cb);
}

var BL = {
	model: null,

	"list": function (config, soajs, cbMain) {
		hostModel.getEnvironment(soajs, BL.model, soajs.inputmaskData.env, function (err, envRecord) {
			checkReturnError(soajs, cbMain, { config: config, error: err || !envRecord, code: 600 }, function () {
				hostModel.getHosts(soajs, BL.model, envRecord.code, function (err, hosts) {
					checkReturnError(soajs, cbMain, { config: config, error: err, code: 600 }, function () {
						return cbMain(null, {
							'hosts': hosts,
							'deployer': envRecord.deployer,
							'profile': envRecord.profile
						});
					});
				});
			});
		});
	},

	/*
	 * This function will return all the environments where a service is deployed.
	 * it takes the service name and renders an object having the following form :
	 * "env_code: apiPrefix.domain"
	 * @ param serviceName
	 * @ param getHostEnv
	 * @ param response
	 */
	"listHostEnv": function (config, soajs, deployer, helpers, cbMain) {
		if (process.env.SOAJS_DEPLOY_HA) {
			BL.listHAhostEnv(config, soajs, deployer, helpers, cbMain);
		}
		else {
			hostModel.getHostEnv(soajs, BL.model, function (error, envs) {
				checkReturnError(soajs, cbMain, { config: config, error: error, code: 600 }, function () {
					checkReturnError(soajs, cbMain, {
						config: config,
						error: envs.length === 0,
						code: 621
					}, function () {
						async.map(envs, function (oneEnv, callback) {
							var opts = {
								"collection": "environment",
								"conditions": {
									"code": oneEnv.toUpperCase(),
									"$or": [
										{
											"sensitive": { "$exists": false }
										},
										{
											"sensitive": false
										}
									]
								}
							};
							BL.model.findEntry(soajs, opts, function (error, environment) {
								if (error) {
									return callback(error);
								}
								if (environment) {
									return callback(null, oneEnv.toUpperCase());
								}

								return callback(null, null);
							});
						}, function (error, envsList) {

							for (var i = envsList.length - 1; i >= 0; i--) {
								if (!envsList[i]) {
									envsList.splice(i, 1);
								}
							}

							hostModel.getEnvInfo(soajs, BL.model, { envList: envsList }, function (error, result) {
								checkReturnError(soajs, cbMain, {
									config: config,
									error: error,
									code: 600
								}, function () {
									var response = {};
									result.forEach(function (oneEnvRec) {
										if (!response[oneEnvRec.code.toLowerCase()]) {
											response[oneEnvRec.code.toLowerCase()] = {};
										}
										if(oneEnvRec.domain === ''){
											let deployerInfo = oneEnvRec.deployer.selected.split(".");
											if(oneEnvRec.deployer[deployerInfo[0]][deployerInfo[1]][deployerInfo[2]]){
												if(oneEnvRec.deployer[deployerInfo[0]][deployerInfo[1]][deployerInfo[2]].nodes && oneEnvRec.deployer[deployerInfo[0]][deployerInfo[1]][deployerInfo[2]].nodes !== ''){
													output[oneEnvRec.code.toLowerCase()]['domain'] = oneEnvRec.nodes;
												}
											}
										}
										else {
											response[oneEnvRec.code.toLowerCase()]['domain'] = oneEnvRec.apiPrefix + "." + oneEnvRec.domain;
										}
									});
									//grab the list of tenant that have ext key in requested env and return tenant code, package nad key as part of response
									helpers.getTenants(soajs, response, BL.model, function (error) {
										checkReturnError(soajs, cbMain, { config: config, error: error }, function () {
											return cbMain(null, response);
										});
									});
								});
							});
						});
					});
				});
			});
		}
	},

	"listHAhostEnv": function (config, soajs, deployer, helpers, cbMain) {
		var output = {};

		//fetch the non sensitive environments only
		var opts = {
			"collection": "environment",
			"conditions": {
				"$or": [
					{
						"sensitive": { "$exists": false }
					},
					{
						"sensitive": false
					},
					{
						"sensitive": null
					}
				]
			}
		};
		BL.model.findEntries(soajs, opts, function (error, environments) {
			checkReturnError(soajs, cbMain, { config: config, error: error, code: 600 }, function () {
				if (!environments || environments.length === 0) {
					return cbMain(null, output);
				}

				async.each(environments, function (oneEnv, mCb) {
					//NOTE: need to get registry for environment, deployer depends on registry not environment record
					//NOTE: can't get registries without listing environments, no other way to get the list of available registries
					var options = helpers.buildDeployerOptions(oneEnv, soajs, BL.model);
					checkReturnError(soajs, cbMain, { config: config, error: !options, code: 825 }, function () {
						options.params = {
							env: oneEnv.code.toLowerCase()
						};
						deployer.listServices(options, function (error, services) {
							checkReturnError(soajs, cbMain, { config: config, error: error }, function () {
								//loop in services and see if you find the one you want only
								for (var i = 0; i < services.length; i++) {
									var oneService = services[i];
									if (soajs.inputmaskData.service === oneService.labels["soajs.service.name"]) {
										if (!output[oneEnv.code.toLowerCase()]) {
											output[oneEnv.code.toLowerCase()] = {};
										}
										if(oneEnv.domain === ''){
											let deployerInfo = oneEnv.deployer.selected.split(".");
											if(oneEnv.deployer[deployerInfo[0]][deployerInfo[1]][deployerInfo[2]]){
												if(oneEnv.deployer[deployerInfo[0]][deployerInfo[1]][deployerInfo[2]].nodes && oneEnv.deployer[deployerInfo[0]][deployerInfo[1]][deployerInfo[2]].nodes !== ''){
													output[oneEnv.code.toLowerCase()]['domain'] = oneEnv.nodes;
												}
											}
										}
										else{
											output[oneEnv.code.toLowerCase()]['domain'] = oneEnv.apiPrefix + "." + oneEnv.domain;
										}
										break;
									}
								}

								services.forEach(function (oneService) {
									if (output[oneEnv.code.toLowerCase()] && oneService.labels['soajs.service.group'] === 'soajs-nginx' && oneService.labels['soajs.env.code'] === oneEnv.code.toLowerCase()) {
										//todo: map domain to inner property
										oneService.ports.forEach(function (onePort) {
											if (parseInt(onePort.target) === 80) {
												output[oneEnv.code.toLowerCase()]['domain'] += ":" + onePort.published;
											}
										});
									}
								});
								return mCb(null, true);
							});
						});
					});
				}, function (error) {
					checkReturnError(soajs, cbMain, { config: config, error: error, code: 600 }, function () {
						//grab the list of tenant that have ext key in requested env and return tenant code, package nad key as part of response
						helpers.getTenants(soajs, output, BL.model, function (error) {
							checkReturnError(soajs, cbMain, { config: config, error: error }, function () {
								return cbMain(null, output);
							});
						});
					});
				});
			});
		});
	},

	"awareness": function (config, soajs, cbMain) {
		hostModel.getEnvironment(soajs, BL.model, soajs.inputmaskData.env, function (err, envRecord) {
			checkReturnError(soajs, cbMain, { config: config, error: err || !envRecord, code: 600 }, function () {
				hostModel.getControllers(soajs, BL.model, envRecord.code, function (err, controllers) {
					checkReturnError(soajs, cbMain, { config: config, error: err, code: 600 }, function () {
						return cbMain(null, controllers);
					});
				});
			});
		});
	}
};

module.exports = {
	"init": function (modelName, cb) {
		var modelPath;

		if (!modelName) {
			return cb(new Error("No Model Requested!"));
		}

		modelPath = __dirname + "/../../models/" + modelName + ".js";
		return requireModel(modelPath, cb);

		/**
		 * checks if model file exists, requires it and returns it.
		 * @param filePath
		 * @param cb
		 */
		function requireModel(filePath, cb) {
			//check if file exist. if not return error
			fs.exists(filePath, function (exists) {
				if (!exists) {
					return cb(new Error("Requested Model Not Found!"));
				}

				BL.model = require(filePath);
				return cb(null, BL);
			});
		}
	}
};
<commit_msg>Minor update<commit_after>'use strict';
var fs = require("fs");
var async = require("async");
var request = require("request");
var hostModel = require("../../models/host.js");
const utils = require("../../utils/utils.js");

function checkReturnError(soajs, mainCb, data, cb) {
	utils.checkErrorReturn(soajs, mainCb, data, cb);
}

var BL = {
	model: null,

	"list": function (config, soajs, cbMain) {
		hostModel.getEnvironment(soajs, BL.model, soajs.inputmaskData.env, function (err, envRecord) {
			checkReturnError(soajs, cbMain, { config: config, error: err || !envRecord, code: 600 }, function () {
				hostModel.getHosts(soajs, BL.model, envRecord.code, function (err, hosts) {
					checkReturnError(soajs, cbMain, { config: config, error: err, code: 600 }, function () {
						return cbMain(null, {
							'hosts': hosts,
							'deployer': envRecord.deployer,
							'profile': envRecord.profile
						});
					});
				});
			});
		});
	},

	/*
	 * This function will return all the environments where a service is deployed.
	 * it takes the service name and renders an object having the following form :
	 * "env_code: apiPrefix.domain"
	 * @ param serviceName
	 * @ param getHostEnv
	 * @ param response
	 */
	"listHostEnv": function (config, soajs, deployer, helpers, cbMain) {
		if (process.env.SOAJS_DEPLOY_HA) {
			BL.listHAhostEnv(config, soajs, deployer, helpers, cbMain);
		}
		else {
			hostModel.getHostEnv(soajs, BL.model, function (error, envs) {
				checkReturnError(soajs, cbMain, { config: config, error: error, code: 600 }, function () {
					checkReturnError(soajs, cbMain, {
						config: config,
						error: envs.length === 0,
						code: 621
					}, function () {
						async.map(envs, function (oneEnv, callback) {
							var opts = {
								"collection": "environment",
								"conditions": {
									"code": oneEnv.toUpperCase(),
									"$or": [
										{
											"sensitive": { "$exists": false }
										},
										{
											"sensitive": false
										}
									]
								}
							};
							BL.model.findEntry(soajs, opts, function (error, environment) {
								if (error) {
									return callback(error);
								}
								if (environment) {
									return callback(null, oneEnv.toUpperCase());
								}

								return callback(null, null);
							});
						}, function (error, envsList) {

							for (var i = envsList.length - 1; i >= 0; i--) {
								if (!envsList[i]) {
									envsList.splice(i, 1);
								}
							}

							hostModel.getEnvInfo(soajs, BL.model, { envList: envsList }, function (error, result) {
								checkReturnError(soajs, cbMain, {
									config: config,
									error: error,
									code: 600
								}, function () {
									var response = {};
									result.forEach(function (oneEnvRec) {
										if (!response[oneEnvRec.code.toLowerCase()]) {
											response[oneEnvRec.code.toLowerCase()] = {};
										}
										if(oneEnvRec.domain === ''){
											output[oneEnvRec.code.toLowerCase()]['domain'] = oneEnvRec.deployer.manual.nodes;
										}
										else {
											response[oneEnvRec.code.toLowerCase()]['domain'] = oneEnvRec.apiPrefix + "." + oneEnvRec.domain;
										}
									});
									//grab the list of tenant that have ext key in requested env and return tenant code, package nad key as part of response
									helpers.getTenants(soajs, response, BL.model, function (error) {
										checkReturnError(soajs, cbMain, { config: config, error: error }, function () {
											return cbMain(null, response);
										});
									});
								});
							});
						});
					});
				});
			});
		}
	},

	"listHAhostEnv": function (config, soajs, deployer, helpers, cbMain) {
		var output = {};

		//fetch the non sensitive environments only
		var opts = {
			"collection": "environment",
			"conditions": {
				"$or": [
					{
						"sensitive": { "$exists": false }
					},
					{
						"sensitive": false
					},
					{
						"sensitive": null
					}
				]
			}
		};
		BL.model.findEntries(soajs, opts, function (error, environments) {
			checkReturnError(soajs, cbMain, { config: config, error: error, code: 600 }, function () {
				if (!environments || environments.length === 0) {
					return cbMain(null, output);
				}

				async.each(environments, function (oneEnv, mCb) {
					//NOTE: need to get registry for environment, deployer depends on registry not environment record
					//NOTE: can't get registries without listing environments, no other way to get the list of available registries
					var options = helpers.buildDeployerOptions(oneEnv, soajs, BL.model);
					checkReturnError(soajs, cbMain, { config: config, error: !options, code: 825 }, function () {
						options.params = {
							env: oneEnv.code.toLowerCase()
						};
						deployer.listServices(options, function (error, services) {
							checkReturnError(soajs, cbMain, { config: config, error: error }, function () {
								//loop in services and see if you find the one you want only
								for (var i = 0; i < services.length; i++) {
									var oneService = services[i];
									if (soajs.inputmaskData.service === oneService.labels["soajs.service.name"]) {
										if (!output[oneEnv.code.toLowerCase()]) {
											output[oneEnv.code.toLowerCase()] = {};
										}
										if(oneEnv.domain === ''){
											let deployerInfo = oneEnv.deployer.selected.split(".");
											if(oneEnv.deployer[deployerInfo[0]][deployerInfo[1]][deployerInfo[2]]){
												if(oneEnv.deployer[deployerInfo[0]][deployerInfo[1]][deployerInfo[2]].nodes && oneEnv.deployer[deployerInfo[0]][deployerInfo[1]][deployerInfo[2]].nodes !== ''){
													output[oneEnv.code.toLowerCase()]['domain'] = oneEnv.nodes;
												}
											}
										}
										else{
											output[oneEnv.code.toLowerCase()]['domain'] = oneEnv.apiPrefix + "." + oneEnv.domain;
										}
										break;
									}
								}

								services.forEach(function (oneService) {
									if (output[oneEnv.code.toLowerCase()] && oneService.labels['soajs.service.group'] === 'soajs-nginx' && oneService.labels['soajs.env.code'] === oneEnv.code.toLowerCase()) {
										//todo: map domain to inner property
										oneService.ports.forEach(function (onePort) {
											if (parseInt(onePort.target) === 80) {
												output[oneEnv.code.toLowerCase()]['domain'] += ":" + onePort.published;
											}
										});
									}
								});
								return mCb(null, true);
							});
						});
					});
				}, function (error) {
					checkReturnError(soajs, cbMain, { config: config, error: error, code: 600 }, function () {
						//grab the list of tenant that have ext key in requested env and return tenant code, package nad key as part of response
						helpers.getTenants(soajs, output, BL.model, function (error) {
							checkReturnError(soajs, cbMain, { config: config, error: error }, function () {
								return cbMain(null, output);
							});
						});
					});
				});
			});
		});
	},

	"awareness": function (config, soajs, cbMain) {
		hostModel.getEnvironment(soajs, BL.model, soajs.inputmaskData.env, function (err, envRecord) {
			checkReturnError(soajs, cbMain, { config: config, error: err || !envRecord, code: 600 }, function () {
				hostModel.getControllers(soajs, BL.model, envRecord.code, function (err, controllers) {
					checkReturnError(soajs, cbMain, { config: config, error: err, code: 600 }, function () {
						return cbMain(null, controllers);
					});
				});
			});
		});
	}
};

module.exports = {
	"init": function (modelName, cb) {
		var modelPath;

		if (!modelName) {
			return cb(new Error("No Model Requested!"));
		}

		modelPath = __dirname + "/../../models/" + modelName + ".js";
		return requireModel(modelPath, cb);

		/**
		 * checks if model file exists, requires it and returns it.
		 * @param filePath
		 * @param cb
		 */
		function requireModel(filePath, cb) {
			//check if file exist. if not return error
			fs.exists(filePath, function (exists) {
				if (!exists) {
					return cb(new Error("Requested Model Not Found!"));
				}

				BL.model = require(filePath);
				return cb(null, BL);
			});
		}
	}
};
<|endoftext|>


<commit_before>var _ = require('underscore');
var express = require('express');
var http = require('http');
var bodyParser = require('body-parser');
var logger = require('./logger');
var streams = require('./streams');

/**
 * @param {Number} port
 * @param {String} serverKey
 * @constructor
 */
function HttpServer(port, serverKey) {
  this.port = port;
  this.serverKey = serverKey;
  var app = express();
  var router = express.Router();
  this.server = http.createServer(app);

  app.use(bodyParser.urlencoded({extended: false}));
  app.use(bodyParser.json());
  app.use(router);
  app.disable('x-powered-by');
  app.disable('etag');

  this.installRoutes(router);

  //IMPORTANT! Do not remove unused `next`.
  app.use(function(err, req, res, next) {
    var errorMessage = err.message || 'Unexpected error';
    logger.error(errorMessage);
    res.status(err.code || 500).send({error: errorMessage});
  });

  process.on('uncaughtException', function(err) {
    logger.error('Uncaught exception ' + err.stack || err.message);
    process.nextTick(process.exit(1));
  });
}

HttpServer.prototype.installRoutes = function(router) {
  var self = this;

  router.use(function(req, res, next) {
    logger.debug('request ' + req.path);
    var serverKey = req.get('Server-Key');
    if (!serverKey || serverKey !== self.serverKey) {
      res.sendStatus(403);
    } else {
      next();
    }
  });

  router.post('/stopStream', function subscribe(req, res, next) {
    var params = _.extend({}, req.params, req.body);
    var streamId = String(params['streamId']);
    var stream = streams.find(streamId);
    if (stream) {
      stream.proxyConnection.stopStream(stream.id)
        .then(function() {
          res.send({success: 'Stream stopped'});
          return next();
        }).catch(function(error) {
          logger.warn('Stream stop failed', error);
          res.send({error: 'Stream stop failed'});
          return next();
        });
    } else {
      res.send({error: 'Unknown stream: ' + params['streamId']});
      return next();
    }
  });

  router.get('/status', function subscribe(req, res, next) {
    var result = _.map(streams.list, function(stream) {
      return {id: stream.id, channelName: stream.channelName};
    });
    res.send(result);
    return next();
  });

};

HttpServer.prototype.start = function() {
  this.server.listen(this.port);
  logger.debug('HTTP server on port ' + this.port + ' started');
};

module.exports = HttpServer;
<commit_msg>add  serverKey existence checking<commit_after>var _ = require('underscore');
var express = require('express');
var http = require('http');
var bodyParser = require('body-parser');
var logger = require('./logger');
var streams = require('./streams');

/**
 * @param {Number} port
 * @param {String} serverKey
 * @constructor
 */
function HttpServer(port, serverKey) {
  if (!serverKey) {
    throw new Error('serverKey is not defined');
  }

  this.port = port;
  this.serverKey = serverKey;
  var app = express();
  var router = express.Router();
  this.server = http.createServer(app);

  app.use(bodyParser.urlencoded({extended: false}));
  app.use(bodyParser.json());
  app.use(router);
  app.disable('x-powered-by');
  app.disable('etag');

  this.installRoutes(router);

  //IMPORTANT! Do not remove unused `next`.
  app.use(function(err, req, res, next) {
    var errorMessage = err.message || 'Unexpected error';
    logger.error(errorMessage);
    res.status(err.code || 500).send({error: errorMessage});
  });

  process.on('uncaughtException', function(err) {
    logger.error('Uncaught exception ' + err.stack || err.message);
    process.nextTick(process.exit(1));
  });
}

HttpServer.prototype.installRoutes = function(router) {
  var self = this;

  router.use(function(req, res, next) {
    logger.debug('request ' + req.path);
    var serverKey = req.get('Server-Key');
    if (!serverKey || serverKey !== self.serverKey) {
      res.sendStatus(403);
    } else {
      next();
    }
  });

  router.post('/stopStream', function subscribe(req, res, next) {
    var params = _.extend({}, req.params, req.body);
    var streamId = String(params['streamId']);
    var stream = streams.find(streamId);
    if (stream) {
      stream.proxyConnection.stopStream(stream.id)
        .then(function() {
          res.send({success: 'Stream stopped'});
          return next();
        }).catch(function(error) {
          logger.warn('Stream stop failed', error);
          res.send({error: 'Stream stop failed'});
          return next();
        });
    } else {
      res.send({error: 'Unknown stream: ' + params['streamId']});
      return next();
    }
  });

  router.get('/status', function subscribe(req, res, next) {
    var result = _.map(streams.list, function(stream) {
      return {id: stream.id, channelName: stream.channelName};
    });
    res.send(result);
    return next();
  });

};

HttpServer.prototype.start = function() {
  this.server.listen(this.port);
  logger.debug('HTTP server on port ' + this.port + ' started');
};

module.exports = HttpServer;
<|endoftext|>