gitevents/core

View on GitHub
lib/events.js

Summary

Maintainability
D
1 day
Test Coverage
'use strict';

const log = require('./log');
const moment = require('moment');
const parser = require('markdown-parse');
const S = require('string');
const GitHubApi = require('github');
const config = require('../config');
const milestone = require('./milestone');

let createOrUpdateEvent = (payload, event, sender, github) => {
  return new Promise(function (resolve, reject) {
    log.debug('createOrUpdateEvent()');

    let commit = {
      filename: config.paths.events + event.id + '.json',
      name: event.name
    };

    github.repos.getContent({
      user: config.github.org,
      repo: config.github.repos.gitevent,
      path: commit.filename
    }, function (error, eventsFile) {
      log.debug('GitHub:getContent()');

      let file;

      if (error && error.code === 404) {
        log.debug('event not found. Creating event.');
        event.about = config.about;

        file = new Buffer(JSON.stringify(event, null, 2))
          .toString('base64');

        github.repos.createFile({
          user: config.github.org,
          repo: config.github.repos.gitevent,
          path: commit.filename,
          content: file,
          message: 'Created event ' + event.id
        }, function (error) {
          log.debug('GitHub:createFile()');

          if (error) {
            return reject(new Error(error));
          }

          return resolve(event);
        });
      } else {
        let contents = new Buffer(eventsFile.content, eventsFile.encoding)
          .toString('utf8');
        let previousEvent = JSON.parse(contents);

        //TODO: what needs updating?

        file = new Buffer(JSON.stringify(event, null, 2))
          .toString('base64');

        github.repos.updateFile({
          user: config.github.org,
          repo: config.github.repos.gitevent,
          path: commit.filename,
          sha: eventsFile.sha,
          content: file,
          message: 'Updated event ' + previousEvent.id
        }, function (error) {
          log.debug('GitHub:updateFile()');
          if (error) {
            log.debug(error);
            return reject(new Error(error));
          }
          return resolve(event);
        });
      }
    });
  });
};

let addTalk = (payload, speaker, github) => {
  return new Promise(function (resolve, reject) {
    log.debug('addTalk()');

    let eventId = payload.issue.milestone.description;

    let commit = {
      filename: config.paths.events + eventId + '.json'
    };

    github.repos.getContent({
      user: config.github.org,
      repo: config.github.repos.gitevent,
      path: commit.filename
    }, function (error, eventsFile) {
      if (error) {
        return reject('event not found.');
      }

      let talks = [];
      let contents = new Buffer(eventsFile.content, eventsFile.encoding)
        .toString('utf8');
      let event = JSON.parse(contents);

      let talkId = moment(payload.issue.milestone.due_on,
          'YYYY-MM-DDTHH:mm:ssZ')
        .format('YYYYMMDD') + '-' + S(payload.issue.title)
        .slugify()
        .s;

      let performer = {
        'type': 'Person',
        'image': speaker.avatar_url,
        'name': speaker.name,
        'id': talkId,
        'sameAs': speaker.url,
        'url': config.schema.default_talk_url + talkId + '.html'
      };

      if (event.performer) {
        event.performer.map(function (p) {
          talks.push(p.id);
        });

        if (talks.indexOf(talkId) > -1) {
          // talk exists, do nothing for now
          return resolve(event);
        } else {
          event.performer.push(performer);
        }
      } else {
        event.performer = [(performer)];
      }

      let file = new Buffer(JSON.stringify(event, null, 2))
        .toString('base64');

      github.repos.updateFile({
        user: config.github.org,
        repo: config.github.repos.gitevent,
        path: commit.filename,
        sha: eventsFile.sha,
        content: file,
        message: 'Updated event ' + event.id
      }, function (error) {
        if (error) {
          log.debug(error);
          return reject(new Error(error));
        }
        return resolve(event);
      });
    });
  });
};

module.exports = (payload) => {
  return new Promise(function (resolve, reject) {
    log.debug('processing event');

    let github = new GitHubApi({
      version: '3.0.0',
      debug: config.debug,
      protocol: 'https',
      timeout: 5000,
      headers: {
        'user-agent': 'GitEvents'
      }
    });

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

    // get repo user
    github.user.getFrom({
      user: payload.sender.login
    }, function (error, sender) {
      if (error) {
        return reject(new Error(error));
      }

      log.debug('GitHub:getFrom():' + sender.login);

      // get author details
      github.user.getFrom({
        user: payload.issue.user.login
      }, function (error, speaker) {
        if (error) {
          return reject(new Error(error));
        }

        log.debug('GitHub:getFrom():' + speaker.login);

        // if this is an event from the planning repo, create a new event
        if (payload.labelMap.indexOf(config.labels.event) > -1) {
          log.debug('received planning event');

          parser(payload.issue.body, function (error, body) {
            if (error) {
              return reject(new Error(error));
            }

            if (body.attributes && !body.attributes.date) {
              return reject(new Error(
                'invalid event. Date missing.'));
            }

            let eventDate = moment.utc(body.attributes.date,
                config.date_format)
              .format('YYYY-MM-DD');
            let eventTime;

            if (body.attributes.time) {
              if (body.attributes.time.indexOf('.') > -1) {
                eventTime = body.attributes.time.replace(',',
                  ':');
              } else {
                eventTime = body.attributes.time;
              }
            } else {
              eventTime = config.schema.default_start_time;
            }

            let event = config.schema.default_event;
            event.startDate = eventDate + 'T' + eventTime +
              ':00Z';
            event.id = moment(event.startDate)
              .format('YYYYMMDD') + '-' + S(body.attributes.name)
              .slugify()
              .s;
            event.organizer = config.schema.default_organizer;
            event.github = payload.issue.url;
            event.url = config.schema.default_event_url +
              event.id + '.html';
            event.name = body.attributes.name;

            if (body.attributes.address) {
              let address = body.attributes.address.split(',');
              event.location.address = {
                'type': 'PostalAddress',
                'addressLocality': address[2],
                'postalCode': address[1],
                'streetAddress': address[0]
              };

              if (body.attributes.venue) {
                event.location.address.name = body.attributes
                  .venue;
              }
            }

            milestone(payload, event, github);

            createOrUpdateEvent(payload, event, sender,
                github)
              .then(function () {
                return resolve(event);
              })
              .catch(function (error) {
                return reject(error);
              });
          });
        }

        // update event if the issue is labeled as a talk
        if (payload.labelMap.indexOf(config.labels.talk) > -1) {
          log.debug('adding talk to event');

          if (!payload.issue.milestone) {
            log.debug('no milestone found. Creating comment.');

            github.issues.createComment({
              user: config.github.org,
              repo: config.github.repos.speakers,
              number: payload.issue.number,
              body: '@' + payload.sender.login +
                ' please create an Event first, then label the issue as a talk.'
            }, function () {
              log.debug('GitHub:createComment()');
              reject(new Error('missing_milestone'));
            });
          } else {
            addTalk(payload, speaker, github)
              .then(function (event) {
                return resolve(event);
              })
              .catch(function (error) {
                return reject(error);
              });
          }
        }
      });
    });
  });
};