<commit_before>var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mailin = require('mailin');
var fs = require('fs');
var nodemailer = require('nodemailer');
var ses = require('nodemailer-ses-transport');
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/cha');

var User = require('./types/user');

var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function (callback) {
  console.log('Now connected to database');
});

var routes = require('./routes/index');
var users = require('./routes/users');

var accessKey = fs.readFileSync('/home/ubuntu/accessKey.txt').toString().trim();
var secretKey = fs.readFileSync('/home/ubuntu/secretKey.txt').toString().trim();

console.log(accessKey);
console.log(secretKey);

// create reusable transporter object using SMTP transport
var transporter = nodemailer.createTransport(ses({
        accessKeyId: accessKey,
        secretAccessKey: secretKey,
        region: 'us-west-2'
    })
);

// NB! No need to recreate the transporter object. You can use
// the same transporter object for all e-mails

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

mailin.start({
  port: 25,
  disableWebhook: true // Disable the webhook posting.
});

/* Access simplesmtp server instance. */
mailin.on('authorizeUser', function(connection, username, password, done) {
  /*
  if (username == "johnsmith" && password == "mysecret") {
    done(null, true);
  } else {
    done(new Error("Unauthorized!"), false);
  }
  */

  //TODO
});

/* Event emitted when a connection with the Mailin smtp server is initiated. */
mailin.on('startMessage', function (connection) {
  /* connection = {
      from: 'sender@somedomain.com',
      to: 'someaddress@yourdomain.com',
      id: 't84h5ugf',
      authentication: { username: null, authenticated: false, status: 'NORMAL' }
  }
  }; */
  console.log(connection);
});

/* Event emitted after a message was received and parsed. */
mailin.on('message', function (connection, data, content) {
  console.log(data);
  console.log(data.text.length);
  console.log(data.from[0].address);
  console.log(data.to[0].address);
  console.log(data.text);

  User.find({ internalEmail : data.to[0].address }, function(err, recipient) {
    var mailOptions;
    if(err) {
      //Send email not found error
      console.log("Error : ");
      console.log(err);
      console.log("Recipient : ");
      console.log(recipient);
      mailOptions = {
        from: 'postmaster@gocha.io',
        to: data.from[0].address,
        subject: "Address Error",
        html: "Terribly sorry, but that email doesn't exist.

Regards,
The Management"
      };
    } else if(data.text.length > 141){
      //Send email too long error
      console.log("Email length too long");
      mailOptions = {
        from: 'postmaster@gocha.io',
        to: data.from[0].address,
        subject: "Length Error",
        html: "Character count for your email was too long.  Current count is: " + data.text.length + "

Regards,
The Management"
      };
    } else {
      //Check if sender exists
      User.find({ externalEmail : data.from[0].address }, function(sender, err) {
        if(err){

        } else if(!sender.length){
          //User does not exist, so we need to make an email for them
          var newUser = new User({
            externalEmail: data.from[0].address
          });
          newUser.generateEmail(function(res, success){
            if(!success){
              console.log("Failed to generate email");
              //possibly send email saying all emails have been taken
            } else {
              console.log("Added new user");
              newUser.save(function(err){
                if(err) {
                  console.log("Unable to save new user");
                  throw err;
                } else {
                  console.log("New user saved");
                  //Now, we can pass along the message
                  mailOptions = {
                    from: newUser.internalEmail,
                    to: recipient.externalEmail,
                    subject: data.subject,
                    text: data.text
                  }
                }
              });
            }
          })
        } else {
          //Sender already exists, pass along the message just fine
          console.log("Sender exists");
          console.log(sender);
          mailOptions = {
            from: sender.internalEmail,
            to: recipient.externalEmail,
            subject: data.subject,
            text: data.text
          };
        }
      });
    }

    //MailOptions have been set, transmit the message
    transporter.sendMail(mailOptions, function(error, info){
      if(error){
          console.log(mailOptions);
          console.log(error);
      } else {
          console.log('Message sent: ' + info.response);
      }
    });
  });
});

app.use('/', routes);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

/*
var testUser = new User({
  externalEmail : 'vanhooser@ou.edu',
  internalEmail : 'gloriousLeader@gocha.io'
});

testUser.save(function(err){
  if(err) {
    throw err;
  } else {
    console.log("Added test user");
  }
});
*/

module.exports = app;

app.listen(80);<commit_msg>Mother fuckign error handling<commit_after>var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mailin = require('mailin');
var fs = require('fs');
var nodemailer = require('nodemailer');
var ses = require('nodemailer-ses-transport');
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/cha');

var User = require('./types/user');

var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function (callback) {
  console.log('Now connected to database');
});

var routes = require('./routes/index');
var users = require('./routes/users');

var accessKey = fs.readFileSync('/home/ubuntu/accessKey.txt').toString().trim();
var secretKey = fs.readFileSync('/home/ubuntu/secretKey.txt').toString().trim();

console.log(accessKey);
console.log(secretKey);

// create reusable transporter object using SMTP transport
var transporter = nodemailer.createTransport(ses({
        accessKeyId: accessKey,
        secretAccessKey: secretKey,
        region: 'us-west-2'
    })
);

// NB! No need to recreate the transporter object. You can use
// the same transporter object for all e-mails

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

mailin.start({
  port: 25,
  disableWebhook: true // Disable the webhook posting.
});

/* Access simplesmtp server instance. */
mailin.on('authorizeUser', function(connection, username, password, done) {
  /*
  if (username == "johnsmith" && password == "mysecret") {
    done(null, true);
  } else {
    done(new Error("Unauthorized!"), false);
  }
  */

  //TODO
});

/* Event emitted when a connection with the Mailin smtp server is initiated. */
mailin.on('startMessage', function (connection) {
  /* connection = {
      from: 'sender@somedomain.com',
      to: 'someaddress@yourdomain.com',
      id: 't84h5ugf',
      authentication: { username: null, authenticated: false, status: 'NORMAL' }
  }
  }; */
  console.log(connection);
});

/* Event emitted after a message was received and parsed. */
mailin.on('message', function (connection, data, content) {
  console.log(data);
  console.log(data.text.length);
  console.log(data.from[0].address);
  console.log(data.to[0].address);
  console.log(data.text);

  User.find({ internalEmail : data.to[0].address }, function(err, recipient) {
    var mailOptions;
    if(err) {
      //Send email not found error
      console.log("Error : ");
      console.log(err);
      console.log("Recipient : ");
      console.log(recipient);
      mailOptions = {
        from: 'postmaster@gocha.io',
        to: data.from[0].address,
        subject: "Address Error",
        html: "Terribly sorry, but that email doesn't exist.

Regards,
The Management"
      };
    } else if(data.text.length > 141){
      //Send email too long error
      console.log("Email length too long");
      mailOptions = {
        from: 'postmaster@gocha.io',
        to: data.from[0].address,
        subject: "Length Error",
        html: "Character count for your email was too long.  Current count is: " + data.text.length + "

Regards,
The Management"
      };
    } else {
      //Check if sender exists
      User.find({ externalEmail : data.from[0].address }, function(sender, err) {
        if(err || !sender.length){
          //User does not exist, so we need to make an email for them
          var newUser = new User({
            externalEmail: data.from[0].address
          });
          newUser.generateEmail(function(res, success){
            if(!success){
              console.log("Failed to generate email");
              //possibly send email saying all emails have been taken
            } else {
              console.log("Added new user");
              newUser.save(function(err){
                if(err) {
                  console.log("Unable to save new user");
                  throw err;
                } else {
                  console.log("New user saved");
                  //Now, we can pass along the message
                  mailOptions = {
                    from: newUser.internalEmail,
                    to: recipient.externalEmail,
                    subject: data.subject,
                    text: data.text
                  }
                }
              });
            }
          })
        } else {
          //Sender already exists, pass along the message just fine
          console.log("Sender exists");
          console.log(sender);
          mailOptions = {
            from: sender.internalEmail,
            to: recipient.externalEmail,
            subject: data.subject,
            text: data.text
          };
        }
      });
    }

    //MailOptions have been set, transmit the message
    transporter.sendMail(mailOptions, function(error, info){
      if(error){
          console.log(mailOptions);
          console.log(error);
      } else {
          console.log('Message sent: ' + info.response);
      }
    });
  });
});

app.use('/', routes);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

/*
var testUser = new User({
  externalEmail : 'vanhooser@ou.edu',
  internalEmail : 'gloriousLeader@gocha.io'
});

testUser.save(function(err){
  if(err) {
    throw err;
  } else {
    console.log("Added test user");
  }
});
*/

module.exports = app;

app.listen(80);<|endoftext|>


<commit_before>if(!Draw.getStrokeWeight) {
  Draw.getStrokeWeight = function() {
    if(!Canvas.configured) {
      console.warn("KAPhy Warning - You must use Canvas.configure(); before you can draw!");
      return;
    }

    return Canvas.context.lineWidth;
  };
}
<commit_msg>Update getstrokeweight.js<commit_after>if(!Draw.getStrokeWeight) {
  /* Draw.getStrokeWeight
    Draw.getStrokeWeight returns the canvas context's current stroke weight (or line width)

    @author  TemporalFuzz
    @version 1.0
    @returns Number current stroke weight
  */
  Draw.getStrokeWeight = function() {
    if(!Canvas.configured) {
      console.warn("KAPhy Warning - You must use Canvas.configure(); before you can draw!");
      return;
    }

    return Canvas.context.lineWidth;
  };
}
<|endoftext|>


<commit_before>function List(id, templates, values) {
    var self = this
        ,templater = null;
    this.listContainer = document.getElementById(id);
    this.items = [];
    this.list = null;
    this.templateEngines = {};

    var helpers = {
        /* (node, class) Source: http://www.dustindiaz.com/getelementsbyclass */
        getByClass: function(d,e){if(d.getElementsByClassName){return d.getElementsByClassName(e)}else{return(function getElementsByClass(a,b){if(b==null)b=document;var c=[],els=b.getElementsByTagName("*"),elsLen=els.length,pattern=new RegExp("(^|\\s)"+a+"(\\s|$)"),i,j;for(i=0,j=0;i<elsLen;i++){if(pattern.test(els[i].className)){c[j]=els[i];j++}}return c})(e,d)}}
        /* (elm, 'event' callback) Source: http://net.tutsplus.com/tutorials/javascript-ajax/javascript-from-null-cross-browser-event-binding/ */
        , addEvent: (function(e,f){if(f.addEventListener){return function(a,b,c){if((a&&!a.length)||a===e){a.addEventListener(b,c,false)}else if(a&&a.length){var d=a.length;for(var i=0;i<d;i++){helpers.addEvent(a[i],b,c)}}}}else if(f.attachEvent){return function(a,b,c){if((a&&!a.length)||a===e){a.attachEvent('on'+b,function(){return c.call(a,e.event)})}else if(a.length){var d=a.length;for(var i=0;i<d;i++){addEvent(a[i],b,c)}}}}})(this,document)
        /* (elm, attribute) Source: http://stackoverflow.com/questions/3755227/cross-browser-javascript-getattribute-method */
        , getAttribute: function(a,b){var c=(a.getAttribute&&a.getAttribute(b))||null;if(!c){var d=a.attributes;var e=d.length;for(var i=0;i<e;i++)if(b[i].nodeName===b)c=b[i].nodeValue}return c}
    };

    var init = function(values, templates) {
        templater = new Templater(templates);
        self.list = helpers.getByClass(self.listContainer, 'list')[0];
        helpers.addEvent(helpers.getByClass(self.listContainer, 'search'), 'keyup', self.search);
        helpers.addEvent(helpers.getByClass(self.listContainer, 'sort'), 'click', self.sort);
        self.add(values);
    };

    /* Add object to list
    *
    */
    this.add = function(values, options) {
        var added = [];

        if (typeof values[0] === 'undefined'){
            values = [values];
        }
        for (var i = 0, il = values.length; i < il; i++) {
            var item = null;
            if (values[i] instanceof Item) {
                item = values[i];
                item.reload();
            } else {
                item = new Item(values[i]);
            }
            templater.add(item, options);
            self.items.push(item);
            added.push(item);
        }
        return added;
    };

    /* Removes object from list.
    * Loops through the list and removes objects where
    * property "valuename" === value
    */
    this.remove = function(valueName, value, options) {
        var found = false;
        for (var i = 0, il = self.items.length; i < il; i++) {
            if (self.items[i].getValues()[valueName] === value) {
                templater.remove(self.items[i], options);
                self.items.splice(i,1);
                il--;
                found = true;
            }
        }
        return found;
    };

    /* Gets the objects in the list which
    * property "valueName" === value
    */
    this.get = function(valueName, value) {
        var items = [];
        for (var i = 0, il = self.items.length; i < il; i++) {
            var item = self.items[i];
            if (item.getValues()[valueName] === value) {
                items.push(item);
            }
        }
        return item;
    };

    /* Sorts the list
    *  TODO: Desc || Asc
    */
    this.sort = function(valueOrEvent, sortFunction) {
        var length = self.items.length,
            value = null;
        if (valueOrEvent.target === 'undefined') {
            value = valueOrEvent;
        } else {
            value = helpers.getAttribute(valueOrEvent.target, 'rel');
        }
        if (sortFunction) {
            sortFunction = sortFunction;
        } else {
            sortFunction = function(a, b) {
                return sorter.alphanum(a.getValues()[value], b.getValues()[value]);
            };
        }
        self.items.sort(sortFunction);
        self.list.innerHTML = "";
        for (var i = 0, il = self.items.length; i < il; i++) {
            self.list.appendChild(self.items[i].elm);
        }
    };

    var sorter = {
        alphanum: function(a,b) {
            if (typeof a === 'undefined') {
                a = "";
            }
            if (typeof b === 'undefined') {
                b = "";
            }
            a = a.toString().replace(/&(lt|gt);/g, function (strMatch, p1){
                return (p1 == "lt")? "<" : ">";
            });
            a = a.replace(/<\/?[^>]+(>|$)/g, "");

            b = b.toString().replace(/&(lt|gt);/g, function (strMatch, p1){
                return (p1 == "lt")? "<" : ">";
            });
            b = b.replace(/<\/?[^>]+(>|$)/g, "");
            var aa = this.chunkify(a);
            var bb = this.chunkify(b);

            for (x = 0; aa[x] && bb[x]; x++) {
                if (aa[x] !== bb[x]) {
                    var c = Number(aa[x]), d = Number(bb[x]);
                    if (c == aa[x] && d == bb[x]) {
                        return c - d;
                    } else {
                        return (aa[x] > bb[x]) ? 1 : -1;
                    }
                }
            }
            return aa.length - bb.length;
        },
        chunkify: function(t) {
            var tz = [], x = 0, y = -1, n = 0, i, j;

            while (i = (j = t.charAt(x++)).charCodeAt(0)) {
                var m = (i == 46 || (i >=48 && i <= 57));
                if (m !== n) {
                    tz[++y] = "";
                    n = m;
                }
                tz[y] += j;
            }
            return tz;
        }
    };

    /*
    * Searches the list after values with content "searchStringOrEvent".
    * The columns parameter defines if all values should be included in the search,
    * defaults to undefined which means "all".
    */
    this.search = function(searchStringOrEvent, columns) {
        var searchString = '';
        if (typeof event.target !== 'undefined') {
            searchString = searchStringOrEvent.target.value.toLowerCase();
        } else {
            searchString = searchStringOrEvent;
        }
        var useAllColumns = false;
        if (typeof columns === 'undefined') {
            useAllColumns = true;
        }
        for (var i = 0, il = self.items.length; i < il; i++) {
            var found = false,
                item = self.items[i];
            if (useAllColumns) {
                columns = item.getValues();
            }
            for(var j in columns) {
                var text = columns[j].toString().toLowerCase();
                if ((searchString !== "") && (text.search(searchString) > -1)) {
                    found = true;
                }
            }
            if (found || (searchString === "")) {
                item.elm.style.display = "block";
            } else {
                item.elm.style.display = "none";
            }
        }
    };

    /*
    * Filters the list. If filterFunction() returns False hides the Item.
    * if filterFunction == false are the filter removed
    */
    this.filter = function(filterFunction) {
        for (var i = 0, il = self.items.length; i < il; i++) {
            var item = self.items[i];
            if (filterFunction === false) {
                item.show();
            } else {
                if (filterFunction(item.getValues())) {
                    item.show();
                } else {
                    item.hide();
                }
            }
        }
    };
    /*
    this.reload = function() {
        $(this.items).each(function(i) {
            this.reload();
        });
    };
    */

    function Item(initValues) {
        var item = this,
            values = {};

        var init = function(initValues) {
            item.setValues(initValues);
        };
        this.setValues = function(newValues) {
            values = newValues;
            templater.reload(item);
        };
        this.getValues = function() {
            return values;
        };
        this.show = function() {
            templater.show(item);
        };
        this.hide = function() {
            templater.hide(item);
        };
        init(initValues);
    };

    /* Templater with different kinds of template engines.
    * All engines have these methods
    * - reload(item)
    * - remove(item)
    */
    var Templater = function(settings) {

        /*
        this.standard = function(settings) {
            var listSource = helpers.getByClass(document.getElementById(settings.list), 'list')[0]
            , itemSource = document.getElementById(settings.item);

            this.reload = function(item) {
                var newItem = itemSource.cloneNode(true);
                newItem.id = "";
                for(var v in item.getValues()) {
                    helpers.getByClass(newItem, v)[0].innerHTML = item.getValues()[v];
                }
                if (typeof item.elm === "undefined") {
                    listSource.appendChild(newItem);
                } else {
                    listSource.replaceChild(newItem, item.elm);
                }
                item.elm = newItem;
            };
            this.add = function(item) {
                self.list.appendChild(item.elm);
            }
            this.remove = function(item) {
                listSource.removeChild(item.elm);
            };
            this.show = function(item) {
                item.elm.style.display = "block";
            };
            this.hide = function(item) {
                item.elm.style.display = "none";
            };
        };
        */

        if (typeof settings.engine === 'undefined') {
            settings.engine = "standard";
        } else {
            settings.engine = settings.engine.toLowerCase();
        }
        return new self.constructor.prototype.templateEngines[settings.engine](settings);
    }

    init(values, templates);
};

List.prototype.templateEngines = {};

List.prototype.templateEngines.standard = function(settings) {
    var listSource = document.getElementById(settings.list).getElementsByClassName('list')[0] //helpers.getByClass(document.getElementById(settings.list), 'list')[0]
        , itemSource = document.getElementById(settings.item);

    this.reload = function(item) {
        var newItem = itemSource.cloneNode(true);
        newItem.id = "";
        for(var v in item.getValues()) {
            newItem.getElementsByClassName(v)[0].innerHTML = item.getValues()[v];
            //helpers.getByClass(newItem, v)[0].innerHTML = item.getValues()[v];
        }
        if (typeof item.elm === "undefined") {
            listSource.appendChild(newItem);
        } else {
            listSource.replaceChild(newItem, item.elm);
        }
        item.elm = newItem;
    };
    this.add = function(item) {
        listSource.appendChild(item.elm);
    }
    this.remove = function(item) {
        listSource.removeChild(item.elm);
    };
    this.show = function(item) {
        item.elm.style.display = "block";
    };
    this.hide = function(item) {
        item.elm.style.display = "none";
    };
};

<commit_msg>Moved helpers<commit_after>/*
ListJS Alpha 1.0

*/

var ListJsHelpers = {
    /* (node, class) Source: http://www.dustindiaz.com/getelementsbyclass */
    getByClass: function(d,e){if(d.getElementsByClassName){return d.getElementsByClassName(e)}else{return(function getElementsByClass(a,b){if(b==null)b=document;var c=[],els=b.getElementsByTagName("*"),elsLen=els.length,pattern=new RegExp("(^|\\s)"+a+"(\\s|$)"),i,j;for(i=0,j=0;i<elsLen;i++){if(pattern.test(els[i].className)){c[j]=els[i];j++}}return c})(e,d)}}
    /* (elm, 'event' callback) Source: http://net.tutsplus.com/tutorials/javascript-ajax/javascript-from-null-cross-browser-event-binding/ */
    , addEvent: (function(e,f){if(f.addEventListener){return function(a,b,c){if((a&&!a.length)||a===e){a.addEventListener(b,c,false)}else if(a&&a.length){var d=a.length;for(var i=0;i<d;i++){helpers.addEvent(a[i],b,c)}}}}else if(f.attachEvent){return function(a,b,c){if((a&&!a.length)||a===e){a.attachEvent('on'+b,function(){return c.call(a,e.event)})}else if(a.length){var d=a.length;for(var i=0;i<d;i++){addEvent(a[i],b,c)}}}}})(this,document)
    /* (elm, attribute) Source: http://stackoverflow.com/questions/3755227/cross-browser-javascript-getattribute-method */
    , getAttribute: function(a,b){var c=(a.getAttribute&&a.getAttribute(b))||null;if(!c){var d=a.attributes;var e=d.length;for(var i=0;i<e;i++)if(b[i].nodeName===b)c=b[i].nodeValue}return c}
};

function List(id, templates, values) {
    var self = this
        ,templater = null;
    this.listContainer = document.getElementById(id);
    this.items = [];
    this.list = null;
    this.templateEngines = {};

    var init = function(values, templates) {
        templater = new Templater(templates);
        self.list = ListJsHelpers.getByClass(self.listContainer, 'list')[0];
        ListJsHelpers.addEvent(ListJsHelpers.getByClass(self.listContainer, 'search')[0], 'keyup', self.search);
        ListJsHelpers.addEvent(ListJsHelpers.getByClass(self.listContainer, 'sort')[0], 'click', self.sort);
        if (templates.values) {

        }
        self.add(values);
    };

    /* Add object to list
    *
    */
    this.add = function(values, options) {
        var added = [];

        if (typeof values[0] === 'undefined'){
            values = [values];
        }
        for (var i = 0, il = values.length; i < il; i++) {
            var item = null;
            if (values[i] instanceof Item) {
                item = values[i];
                item.reload();
            } else {
                item = new Item(values[i]);
            }
            templater.add(item, options);
            self.items.push(item);
            added.push(item);
        }
        return added;
    };

    /* Removes object from list.
    * Loops through the list and removes objects where
    * property "valuename" === value
    */
    this.remove = function(valueName, value, options) {
        var found = false;
        for (var i = 0, il = self.items.length; i < il; i++) {
            if (self.items[i].getValues()[valueName] === value) {
                templater.remove(self.items[i], options);
                self.items.splice(i,1);
                il--;
                found = true;
            }
        }
        return found;
    };

    /* Gets the objects in the list which
    * property "valueName" === value
    */
    this.get = function(valueName, value) {
        var items = [];
        for (var i = 0, il = self.items.length; i < il; i++) {
            var item = self.items[i];
            if (item.getValues()[valueName] === value) {
                items.push(item);
            }
        }
        return item;
    };

    /* Sorts the list
    *  TODO: Desc || Asc
    */
    this.sort = function(valueOrEvent, sortFunction) {
        var length = self.items.length,
            value = null;
        if (valueOrEvent.target === 'undefined') {
            value = valueOrEvent;
        } else {
            value = ListJsHelpers.getAttribute(valueOrEvent.target, 'rel');
        }
        if (sortFunction) {
            sortFunction = sortFunction;
        } else {
            sortFunction = function(a, b) {
                return sorter.alphanum(a.getValues()[value], b.getValues()[value]);
            };
        }
        self.items.sort(sortFunction);
        self.list.innerHTML = "";
        for (var i = 0, il = self.items.length; i < il; i++) {
            self.list.appendChild(self.items[i].elm);
        }
    };

    var sorter = {
        alphanum: function(a,b) {
            if (typeof a === 'undefined') {
                a = "";
            }
            if (typeof b === 'undefined') {
                b = "";
            }
            a = a.toString().replace(/&(lt|gt);/g, function (strMatch, p1){
                return (p1 == "lt")? "<" : ">";
            });
            a = a.replace(/<\/?[^>]+(>|$)/g, "");

            b = b.toString().replace(/&(lt|gt);/g, function (strMatch, p1){
                return (p1 == "lt")? "<" : ">";
            });
            b = b.replace(/<\/?[^>]+(>|$)/g, "");
            var aa = this.chunkify(a);
            var bb = this.chunkify(b);

            for (x = 0; aa[x] && bb[x]; x++) {
                if (aa[x] !== bb[x]) {
                    var c = Number(aa[x]), d = Number(bb[x]);
                    if (c == aa[x] && d == bb[x]) {
                        return c - d;
                    } else {
                        return (aa[x] > bb[x]) ? 1 : -1;
                    }
                }
            }
            return aa.length - bb.length;
        },
        chunkify: function(t) {
            var tz = [], x = 0, y = -1, n = 0, i, j;

            while (i = (j = t.charAt(x++)).charCodeAt(0)) {
                var m = (i == 46 || (i >=48 && i <= 57));
                if (m !== n) {
                    tz[++y] = "";
                    n = m;
                }
                tz[y] += j;
            }
            return tz;
        }
    };

    /*
    * Searches the list after values with content "searchStringOrEvent".
    * The columns parameter defines if all values should be included in the search,
    * defaults to undefined which means "all".
    */
    this.search = function(searchStringOrEvent, columns) {
        var searchString = '';
        if (typeof event.target !== 'undefined') {
            searchString = searchStringOrEvent.target.value.toLowerCase();
        } else {
            searchString = searchStringOrEvent;
        }
        var useAllColumns = false;
        if (typeof columns === 'undefined') {
            useAllColumns = true;
        }
        for (var i = 0, il = self.items.length; i < il; i++) {
            var found = false,
                item = self.items[i];
            if (useAllColumns) {
                columns = item.getValues();
            }
            for(var j in columns) {
                var text = columns[j].toString().toLowerCase();
                if ((searchString !== "") && (text.search(searchString) > -1)) {
                    found = true;
                }
            }
            if (found || (searchString === "")) {
                item.elm.style.display = "block";
            } else {
                item.elm.style.display = "none";
            }
        }
    };

    /*
    * Filters the list. If filterFunction() returns False hides the Item.
    * if filterFunction == false are the filter removed
    */
    this.filter = function(filterFunction) {
        for (var i = 0, il = self.items.length; i < il; i++) {
            var item = self.items[i];
            if (filterFunction === false) {
                item.show();
            } else {
                if (filterFunction(item.getValues())) {
                    item.show();
                } else {
                    item.hide();
                }
            }
        }
    };
    /*
    this.reload = function() {
        $(this.items).each(function(i) {
            this.reload();
        });
    };
    */

    function Item(initValues, element) {
        var item = this,
            values = {};

        var init = function(initValues, element) {
            if (typeof element === 'undefined') {
                item.elm = element;
            } else {
                templater.add(item);
            }
            item.setValues(initValues);
        };
        this.setValues = function(newValues) {
            values = newValues;
            templater.reload(item);
        };
        this.getValues = function() {
            return values;
        };
        this.show = function() {
            templater.show(item);
        };
        this.hide = function() {
            templater.hide(item);
        };
        init(initValues, element);
    };

    /* Templater with different kinds of template engines.
    * All engines have these methods
    * - reload(item)
    * - remove(item)
    */
    var Templater = function(settings) {

        /*
        this.standard = function(settings) {
            var listSource = helpers.getByClass(document.getElementById(settings.list), 'list')[0]
            , itemSource = document.getElementById(settings.item);

            this.reload = function(item) {
                var newItem = itemSource.cloneNode(true);
                newItem.id = "";
                for(var v in item.getValues()) {
                    helpers.getByClass(newItem, v)[0].innerHTML = item.getValues()[v];
                }
                if (typeof item.elm === "undefined") {
                    listSource.appendChild(newItem);
                } else {
                    listSource.replaceChild(newItem, item.elm);
                }
                item.elm = newItem;
            };
            this.add = function(item) {
                self.list.appendChild(item.elm);
            }
            this.remove = function(item) {
                listSource.removeChild(item.elm);
            };
            this.show = function(item) {
                item.elm.style.display = "block";
            };
            this.hide = function(item) {
                item.elm.style.display = "none";
            };
        };
        */

        if (typeof settings.engine === 'undefined') {
            settings.engine = "standard";
        } else {
            settings.engine = settings.engine.toLowerCase();
        }
        return new self.constructor.prototype.templateEngines[settings.engine](settings);
    }

    init(values, templates);
};

List.prototype.templateEngines = {};

List.prototype.templateEngines.standard = function(settings) {
    var listSource = helpers.getByClass(document.getElementById(settings.list), 'list')[0]
        , itemSource = document.getElementById(settings.item);

    this.reload = function(item) {
        for(var v in item.getValues()) {
            ListJsHelpers.getByClass(item.elm, v)[0].innerHTML = item.getValues()[v];
        }
    };
    this.add = function(item) {
        var newItem = itemSource.cloneNode(true);
        newItem.id = "";
        item.elm = newItem;
        listSource.appendChild(item.elm);
    }
    this.remove = function(item) {
        listSource.removeChild(item.elm);
    };
    this.show = function(item) {
        item.elm.style.display = "block";
    };
    this.hide = function(item) {
        item.elm.style.display = "none";
    };
};

<|endoftext|>


<commit_before>var validator = require("validator"),
    ValidatorPrototype = validator.Validator.prototype,
    object = require("object-additions").object;

var externalValidator = new validator.Validator();

function Validator(fieldname, label) {
  var stack = [];
  var fieldLabel = label || fieldname;

  this.add = function(func) {
    stack.push(func);
    return this;
  };

  this.run = function(formData) {
    var errors = [];

    stack.forEach(function(validate) {
      try {
        validate(formData[fieldname]);
      } catch(e) {
        var message = (e.message || e).toString().replace("%s", fieldLabel);
        errors.push(message);
      }
    });

    if (errors.length) return errors;
  };
}

Object.keys(ValidatorPrototype).forEach(function(name) {
  if (name.match(/^(check|validate|assert|error|len|isNumeric|isDecimal|isFloat|regex|notRegex|is|not)$/))
    return;

  Validator.prototype[name] = function() {
    var args = Array.prototype.slice.call(arguments);

    var message = undefined;

    if (args.length) {
      switch(name) {
        case "equals":
        case "contains":
        case "notContains":
          message = args[1];
          break;
        default:
          message = args[0];
      }
    }

    return this.add(function(value) {
      if (typeof value == "undefined" || value === undefined) {
        return value;
      }
      return ValidatorPrototype[name].apply(externalValidator.check(value, message), args);
    });
  };
});

// node-validator's numeric validator seems unintuitive. All numeric values should be valid, not just int.
Validator.prototype.isNumeric = function(message) {
  return this.add(function(value) {
    if (object.isNumber(value) || (object.isString(value) && value.match(/^[-+]?[0-9]*\.?[0-9]+$/))) {
    } else {
      throw new Error(message || "Invalid number");
    }
  });
};

// node-validator's decimal/float validator incorrectly thinks Ints are valid.
Validator.prototype.isDecimal = function(message) {
  return this.add(function(value) {
    if ((object.isNumber(value) && value % 1 == 0) || (object.isString(value) && value.match(/^[-+]?[0-9]*\.[0-9]+$/))) {
    } else {
      throw new Error(message || "Invalid decimal");
    }
  });
};

Validator.prototype.isFloat = Validator.prototype.isDecimal;

Validator.prototype.regex = Validator.prototype.is = function(pattern, modifiers, message) {
  // regex(/pattern/)
  // regex(/pattern/, "message")
  // regex("pattern")
  // regex("pattern", "modifiers")
  // regex("pattern", "message")
  // regex("pattern", "modifiers", "message")

  if (pattern instanceof RegExp) {
    if (object.isString(modifiers) && modifiers.match(/^[gimy]+$/)) {
      throw new Error("Invalid arguments: `modifiers` can only be passed in if `pattern` is a string.");
    }

    message = modifiers;
    modifiers = undefined;

  } else if (object.isString(pattern)) {
    if (arguments.length == 2 && !modifiers.match(/^[gimy]+$/)) {
      // 2nd arg doesn't look like modifier flags, it's the message (might also be undefined)
      message = modifiers;
      modifiers = undefined;
    }
    pattern = new RegExp(pattern, modifiers);
  }

  return this.add(function(value) {
    if (pattern.test(value) === false) {
      throw new Error(message || "Invalid characters");
    }
  });
};

Validator.prototype.notRegex = Validator.prototype.not = function(pattern, modifiers, message) {
  // notRegex(/pattern/)
  // notRegex(/pattern/, "message")
  // notRegex("pattern")
  // notRegex("pattern", "modifiers")
  // notRegex("pattern", "message")
  // notRegex("pattern", "modifiers", "message")

  if (pattern instanceof RegExp) {
    if (object.isString(modifiers) && modifiers.match(/^[gimy]+$/)) {
      throw new Error("Invalid arguments: `modifiers` can only be passed in if `pattern` is a string.");
    }

    message = modifiers;
    modifiers = undefined;

  } else if (object.isString(pattern)) {
    if (arguments.length == 2 && !modifiers.match(/^[gimy]+$/)) {
      // 2nd arg doesn't look like modifier flags, it's the message (might also be undefined)
      message = modifiers;
      modifiers = undefined;
    }
    pattern = new RegExp(pattern, modifiers);
  }

  return this.add(function(value) {
    if (pattern.test(value) === true) {
      throw new Error(message || "Invalid characters");
    }
  });
};

Validator.prototype.required = function(placeholderValue, message) {
  return this.add(function(value) {
    if (object.isUndefined(value) || value == null || value === '' || value == placeholderValue) {
      throw new Error(message || "Missing value");
    }
  });
};

Validator.prototype.custom = function(func, message) {
  return this.add(function(value) {
    try {
      func(value);
    } catch (e) {
      throw new Error(message || e.message || "Invalid field");
    }
  });
};

module.exports = Validator;
<commit_msg>New minLength and maxLength validators<commit_after>var validator = require("validator"),
    ValidatorPrototype = validator.Validator.prototype,
    object = require("object-additions").object;

var externalValidator = new validator.Validator();

function Validator(fieldname, label) {
  var stack = [];
  var fieldLabel = label || fieldname;

  this.add = function(func) {
    stack.push(func);
    return this;
  };

  this.run = function(formData) {
    var errors = [];

    stack.forEach(function(validate) {
      try {
        validate(formData[fieldname]);
      } catch(e) {
        var message = (e.message || e).toString().replace("%s", fieldLabel);
        errors.push(message);
      }
    });

    if (errors.length) return errors;
  };
}

Object.keys(ValidatorPrototype).forEach(function(name) {
  if (name.match(/^(check|validate|assert|error|len|isNumeric|isDecimal|isFloat|regex|notRegex|is|not)$/))
    return;

  Validator.prototype[name] = function() {
    var args = Array.prototype.slice.call(arguments);

    var message = undefined;

    if (args.length) {
      switch(name) {
        case "equals":
        case "contains":
        case "notContains":
          message = args[1];
          break;
        default:
          message = args[0];
      }
    }

    return this.add(function(value) {
      if (typeof value == "undefined" || value === undefined) {
        return value;
      }
      return ValidatorPrototype[name].apply(externalValidator.check(value, message), args);
    });
  };
});

// node-validator's numeric validator seems unintuitive. All numeric values should be valid, not just int.
Validator.prototype.isNumeric = function(message) {
  return this.add(function(value) {
    if (object.isNumber(value) || (object.isString(value) && value.match(/^[-+]?[0-9]*\.?[0-9]+$/))) {
    } else {
      throw new Error(message || "Invalid number");
    }
  });
};

// node-validator's decimal/float validator incorrectly thinks Ints are valid.
Validator.prototype.isDecimal = function(message) {
  return this.add(function(value) {
    if ((object.isNumber(value) && value % 1 == 0) || (object.isString(value) && value.match(/^[-+]?[0-9]*\.[0-9]+$/))) {
    } else {
      throw new Error(message || "Invalid decimal");
    }
  });
};

Validator.prototype.isFloat = Validator.prototype.isDecimal;

Validator.prototype.regex = Validator.prototype.is = function(pattern, modifiers, message) {
  // regex(/pattern/)
  // regex(/pattern/, "message")
  // regex("pattern")
  // regex("pattern", "modifiers")
  // regex("pattern", "message")
  // regex("pattern", "modifiers", "message")

  if (pattern instanceof RegExp) {
    if (object.isString(modifiers) && modifiers.match(/^[gimy]+$/)) {
      throw new Error("Invalid arguments: `modifiers` can only be passed in if `pattern` is a string.");
    }

    message = modifiers;
    modifiers = undefined;

  } else if (object.isString(pattern)) {
    if (arguments.length == 2 && !modifiers.match(/^[gimy]+$/)) {
      // 2nd arg doesn't look like modifier flags, it's the message (might also be undefined)
      message = modifiers;
      modifiers = undefined;
    }
    pattern = new RegExp(pattern, modifiers);
  }

  return this.add(function(value) {
    if (pattern.test(value) === false) {
      throw new Error(message || "Invalid characters");
    }
  });
};

Validator.prototype.notRegex = Validator.prototype.not = function(pattern, modifiers, message) {
  // notRegex(/pattern/)
  // notRegex(/pattern/, "message")
  // notRegex("pattern")
  // notRegex("pattern", "modifiers")
  // notRegex("pattern", "message")
  // notRegex("pattern", "modifiers", "message")

  if (pattern instanceof RegExp) {
    if (object.isString(modifiers) && modifiers.match(/^[gimy]+$/)) {
      throw new Error("Invalid arguments: `modifiers` can only be passed in if `pattern` is a string.");
    }

    message = modifiers;
    modifiers = undefined;

  } else if (object.isString(pattern)) {
    if (arguments.length == 2 && !modifiers.match(/^[gimy]+$/)) {
      // 2nd arg doesn't look like modifier flags, it's the message (might also be undefined)
      message = modifiers;
      modifiers = undefined;
    }
    pattern = new RegExp(pattern, modifiers);
  }

  return this.add(function(value) {
    if (pattern.test(value) === true) {
      throw new Error(message || "Invalid characters");
    }
  });
};

Validator.prototype.required = function(placeholderValue, message) {
  return this.add(function(value) {
    if (object.isUndefined(value) || value == null || value === '' || value == placeholderValue) {
      throw new Error(message || "Missing value");
    }
  });
};

Validator.prototype.minLength = function(length, message) {
  return this.add(function(value) {
    if (value.toString().length < length) {
      throw new Error(message || "Too short");
    }
  });
};

Validator.prototype.maxLength = function(length, message) {
  return this.add(function(value) {
    if (value.toString().length > length) {
      throw new Error(message || "Too long");
    }
  });
};

Validator.prototype.custom = function(func, message) {
  return this.add(function(value) {
    try {
      func(value);
    } catch (e) {
      throw new Error(message || e.message || "Invalid field");
    }
  });
};

module.exports = Validator;
<|endoftext|>


<commit_before>var application = require("application");
application.mainModule = "main-page";
application.cssFile = "./app.css";
application.start();
<commit_msg>Added GMS API service<commit_after>var application = require("application");

application.onLaunch = function() {
    console.log('Providing GoogleMap API key...');
    // NOTE: Use the Google documentation to obtain API key: https://developers.google.com/maps/documentation/ios/start
    GMSServices.provideAPIKey(""); // API KEY HERE!
}

application.mainModule = "main-page";
application.cssFile = "./app.css";
application.start();
<|endoftext|>


<commit_before>const slapp = require('./slapp.js').get();
const HashMap = require('hashmap');
const request = require('request');
const fs = require('fs');
var kv = require('beepboop-persist')();

var github = require('./github.js')
function _(obj){
  var str = JSON.stringify(obj, null, 4);
  console.log(str);
}
var buffer =[];
// Archiving feature state
var isArchiving = false;

/**
 * This function that handles the module behaviour when the server is about to restart
 */
function handle_restart(){
  keys = msgMap.keys();
  keys.forEach(function(key){
    var array = msgMap.get(key);
    if(array.length)
      archive_push(key);
  })
}
/**
 * This function receives a message and store it in a hashmap that will be pushed to the github archive
 * @param {object} msg the message sent by slapp that is meant to be archived
 */
function receive(msg){
  if(isArchiving){
    slapp.client.channels.info({token:msg.meta.bot_token,channel:msg.body.event.channel}, (err, resultChannel) => {
      slapp.client.users.info({token:msg.meta.bot_token,user:msg.body.event.user}, (uerr, resultUser) => {
        var timeStamp = new Date(msg.body.event.ts * 1000)
        var obj = {user:resultUser.user.name,
                    ts:timeStamp,
                    text:msg.body.event.text,
                    channel:resultChannel.channel.name};
        archive_push(obj);
      });
    });
  }
}
// Sets the handler for the slash command
slapp.command('/archivetogit','(.*)', (msg, text, value)  => {
  slapp.client.users.info({token:msg.meta.bot_token,user:msg.body.user_id}, (err, data) => {
    if( data.user.is_admin){
      if(!text)
        msg.respond("Options for /archivetogit: \n" +
                    "\`start\` starts the archiving to git. (Github token must be initialized first using /github)\n" +
                    "\`stop \` stops the archiving to git.\n" );
      else if(text == 'start')
        archive_start(msg);
      else if(text == 'stop')
        archive_stop(msg);
      else {
        msg.respond("Please use /archivetogit to print the available options.");
      }
    }
    else {
      msg.respond("Sorry, you're not an admin.");
    }
  })
})

function start(){
  isArchiving=true;
}
/**
 * This function starts the message archiving if a github token is specified
 * @param {object} msg the message received from slapp following the user command
 */
function archive_start(msg){
  if(github.getToken()!=''){
    if(!isArchiving){
  		isArchiving=true;
  	msg.respond("Archiving started.");
  	}
  	else {
  		msg.respond("Archiving is already in progress.");
  	}
  }else{
    msg.respond("Please set the github token first.");
  }
}
/**
 * This function stops the message archiving
 * @param {object} msg the message received from slapp following the user command
 */
function archive_stop(msg){
  if(isArchiving){
		isArchiving=false;
		msg.respond("Archiving stopped.");
	}
	else {
		msg.respond("Archiving is already stoped.");
	}
}
/**
 * This function pushes the message from the buffer to github
 */
function archive_push(obj){
  _('ARCHIVE PUSH buffer:');
  _(buffer);
  var channelPageName = obj.channel + '.md';
  github.get().repos.getContent({
   owner:'NeuroTechX',
   repo:'ntx_slack_archive',
   path:''},function(err,result){
    var found = false;
    for (var i = 0; i < result.length && !found; i++) {
      if (result[i].name === channelPageName) {
        found = true;
      }
    }
    if(found)
      editPage(obj);
    else {
      createPage(obj);
    }
  });
}
/**
 * This function edits the github page specified by pageName adding values to it
 * @param {string} obj the data to push
 */
// function editPage(obj){
//   var filePath = "https://raw.githubusercontent.com/NeuroTechX/ntx_slack_archive/master/"+obj.channel+'.md';
//   var propertiesObject = {access_token:github.getToken()};
// 	request.get({url:filePath, qs:propertiesObject}, function (fileerror, fileresponse, fileBody) {
//   	if (!fileerror && fileresponse.statusCode == 200) {
//
//       var quotedText = obj.text.replace(/([\n\r])/g, '\n\n> $1');
//       fileBody+= ""+formatDate(obj.ts)+"\n\n **"+ obj.user +"**" + " :\n\n >" + quotedText + "\n\n";
//
// 			//fs.writeFile("slack-links.md", fileBody, {encoding: 'base64'}, function(err){console.log("error encoding the file to b64")});
//       var content = Buffer.from(fileBody, 'ascii');
//       var b64content = content.toString('base64');
// 			var blobPath = "https://api.github.com/repos/NeuroTechX/ntx_slack_archive/contents/"+obj.channel+'.md';
//       var options = {
//         url: blobPath,
//         headers: {
//           'User-Agent': 'Edubot-GitHub-App'
//         },
//         qs:propertiesObject
//       };
// 			request.get(options, function (bloberror, blobresponse, blobBody) {
// 	    	if (!bloberror && blobresponse.statusCode == 200) {
//           var shaStr = JSON.parse(blobBody).sha;
//           //("Sha str")
// 					github.get().repos.updateFile({
// 						owner:"NeuroTechX",
// 						repo:"ntx_slack_archive",
// 						path:obj.channel+'.md',
// 						message:"Edubot Push",
// 						content:b64content,
// 						sha: shaStr
// 					}, function(err, res) {
//             buffer = [];
//           });
//         }
// 			});
//   	}
// 	});
// }
function editPage(obj){
  github.get().repos.getContent({
      owner:"NeuroTechX",
      repo:"ntx_slack_archive",
      path:obj.channel+'.md',
    },
    function(err,res){
    	if (!err) {
        var taggedUsers = obj.text.match(/([<][@][U][A-Za-z0-9]+[>])/g);
        _("taggedUsers");
        _(taggedUsers)
        if(taggedUsers){
          var taggedUsersIds = taggedUsers.slice();
          for(var i=0;i<taggedUsersIds.length;i++){
            taggedUsersIds[i] = taggedUsersIds[i].replace(/(<|@|>)/g,'');
          }
          _("taggedUsersIds");
          _(taggedUsersIds)
          var ps = [];
          for(var i=0;i<taggedUsersIds.length;i++){
            ps.push(getUserInfoPromise(taggedUsersIds[i]));
          }
          Promise.all(ps).then(function(results){
            for(var i=0;i<taggedUsers.length;i++){
              obj.text = obj.text.replace(taggedUsers[i],results[i]);
            }
          });
        }
        var quotedText = obj.text.replace(/([\n\r])/g, '\n\n> $1');
        var b64fileBody = res.content;
        var bufBody = new Buffer(b64fileBody, 'base64')
        var fileBody = bufBody.toString();
        fileBody+= ""+formatDate(obj.ts)+"\n\n **"+ obj.user +"**" + " :\n\n >" + quotedText + "\n\n";
        var content = Buffer.from(fileBody, 'ascii');
        var b64content = content.toString('base64');
        var shaStr = res.sha;
    		github.get().repos.updateFile({
    			owner:"NeuroTechX",
    			repo:"ntx_slack_archive",
    			path:obj.channel+'.md',
    			message:"Edubot Push",
    			content:b64content,
    			sha: shaStr
    		}, function(err, res) {
        });
    	}
	});
}
/**
 * This function formats the timestamp to a user friendly format
 * @param {timestamp} ts the time stamp to format
 */
function formatDate(ts){
  return ts.toLocaleDateString("en-US") + " " + ts.toLocaleTimeString(["en-US"], {hour: '2-digit', minute:'2-digit'});
}
/**
 * This function creates a github archiving page
 * @param {string} obj data to push
 */
function createPage(obj){
      var fileBody = "######"+obj.channel+"\n\n";
      var quotedText = obj.text.replace(/([\n\r])/g, '\n\n> $1');
			fileBody+= ""+formatDate(obj.ts)+"\n\n **"+ obj.user +"**" + " :\n\n >" + quotedText + "\n\n";

      var content = Buffer.from(fileBody, 'ascii');
      var b64content = content.toString('base64');

      github.get().repos.createFile({
        owner:"NeuroTechX",
        repo:"ntx_slack_archive",
        path:obj.channel+'.md',
        message:"Edubot Push",
        content:b64content
      }, function(err, res) {
      });
}
function getUserInfoPromise(uid){
  return new Promise(function(resolve, reject) {
    kv.get("bot_token",function(err,bToken){
      if(err)
        _("error while loading bot token");
      else if(!err && bToken){
        slapp.client.users.info({token:bToken,user:uid}, (err, data) => {
          if(err)
            reject(err);
          else
            resolve(data.user.name);
        });
      }
    });
  });
}
module.exports = {
  receive:receive,
  handle_restart:handle_restart,
  start:start
}
<commit_msg>obj print verbose<commit_after>const slapp = require('./slapp.js').get();
const HashMap = require('hashmap');
const request = require('request');
const fs = require('fs');
var kv = require('beepboop-persist')();

var github = require('./github.js')
function _(obj){
  var str = JSON.stringify(obj, null, 4);
  console.log(str);
}
var buffer =[];
// Archiving feature state
var isArchiving = false;

/**
 * This function that handles the module behaviour when the server is about to restart
 */
function handle_restart(){
  keys = msgMap.keys();
  keys.forEach(function(key){
    var array = msgMap.get(key);
    if(array.length)
      archive_push(key);
  })
}
/**
 * This function receives a message and store it in a hashmap that will be pushed to the github archive
 * @param {object} msg the message sent by slapp that is meant to be archived
 */
function receive(msg){
  if(isArchiving){
    slapp.client.channels.info({token:msg.meta.bot_token,channel:msg.body.event.channel}, (err, resultChannel) => {
      slapp.client.users.info({token:msg.meta.bot_token,user:msg.body.event.user}, (uerr, resultUser) => {
        var timeStamp = new Date(msg.body.event.ts * 1000)
        var obj = {user:resultUser.user.name,
                    ts:timeStamp,
                    text:msg.body.event.text,
                    channel:resultChannel.channel.name};
        archive_push(obj);
      });
    });
  }
}
// Sets the handler for the slash command
slapp.command('/archivetogit','(.*)', (msg, text, value)  => {
  slapp.client.users.info({token:msg.meta.bot_token,user:msg.body.user_id}, (err, data) => {
    if( data.user.is_admin){
      if(!text)
        msg.respond("Options for /archivetogit: \n" +
                    "\`start\` starts the archiving to git. (Github token must be initialized first using /github)\n" +
                    "\`stop \` stops the archiving to git.\n" );
      else if(text == 'start')
        archive_start(msg);
      else if(text == 'stop')
        archive_stop(msg);
      else {
        msg.respond("Please use /archivetogit to print the available options.");
      }
    }
    else {
      msg.respond("Sorry, you're not an admin.");
    }
  })
})

function start(){
  isArchiving=true;
}
/**
 * This function starts the message archiving if a github token is specified
 * @param {object} msg the message received from slapp following the user command
 */
function archive_start(msg){
  if(github.getToken()!=''){
    if(!isArchiving){
  		isArchiving=true;
  	msg.respond("Archiving started.");
  	}
  	else {
  		msg.respond("Archiving is already in progress.");
  	}
  }else{
    msg.respond("Please set the github token first.");
  }
}
/**
 * This function stops the message archiving
 * @param {object} msg the message received from slapp following the user command
 */
function archive_stop(msg){
  if(isArchiving){
		isArchiving=false;
		msg.respond("Archiving stopped.");
	}
	else {
		msg.respond("Archiving is already stoped.");
	}
}
/**
 * This function pushes the message from the buffer to github
 */
function archive_push(obj){
  _('ARCHIVE PUSH buffer:');
  _(buffer);
  var channelPageName = obj.channel + '.md';
  github.get().repos.getContent({
   owner:'NeuroTechX',
   repo:'ntx_slack_archive',
   path:''},function(err,result){
    var found = false;
    for (var i = 0; i < result.length && !found; i++) {
      if (result[i].name === channelPageName) {
        found = true;
      }
    }
    if(found)
      editPage(obj);
    else {
      createPage(obj);
    }
  });
}
/**
 * This function edits the github page specified by pageName adding values to it
 * @param {string} obj the data to push
 */
// function editPage(obj){
//   var filePath = "https://raw.githubusercontent.com/NeuroTechX/ntx_slack_archive/master/"+obj.channel+'.md';
//   var propertiesObject = {access_token:github.getToken()};
// 	request.get({url:filePath, qs:propertiesObject}, function (fileerror, fileresponse, fileBody) {
//   	if (!fileerror && fileresponse.statusCode == 200) {
//
//       var quotedText = obj.text.replace(/([\n\r])/g, '\n\n> $1');
//       fileBody+= ""+formatDate(obj.ts)+"\n\n **"+ obj.user +"**" + " :\n\n >" + quotedText + "\n\n";
//
// 			//fs.writeFile("slack-links.md", fileBody, {encoding: 'base64'}, function(err){console.log("error encoding the file to b64")});
//       var content = Buffer.from(fileBody, 'ascii');
//       var b64content = content.toString('base64');
// 			var blobPath = "https://api.github.com/repos/NeuroTechX/ntx_slack_archive/contents/"+obj.channel+'.md';
//       var options = {
//         url: blobPath,
//         headers: {
//           'User-Agent': 'Edubot-GitHub-App'
//         },
//         qs:propertiesObject
//       };
// 			request.get(options, function (bloberror, blobresponse, blobBody) {
// 	    	if (!bloberror && blobresponse.statusCode == 200) {
//           var shaStr = JSON.parse(blobBody).sha;
//           //("Sha str")
// 					github.get().repos.updateFile({
// 						owner:"NeuroTechX",
// 						repo:"ntx_slack_archive",
// 						path:obj.channel+'.md',
// 						message:"Edubot Push",
// 						content:b64content,
// 						sha: shaStr
// 					}, function(err, res) {
//             buffer = [];
//           });
//         }
// 			});
//   	}
// 	});
// }
function editPage(obj){
  github.get().repos.getContent({
      owner:"NeuroTechX",
      repo:"ntx_slack_archive",
      path:obj.channel+'.md',
    },
    function(err,res){
    	if (!err) {
        var taggedUsers = obj.text.match(/([<][@][U][A-Za-z0-9]+[>])/g);
        _("taggedUsers");
        _(taggedUsers)
        if(taggedUsers){
          var taggedUsersIds = taggedUsers.slice();
          for(var i=0;i<taggedUsersIds.length;i++){
            taggedUsersIds[i] = taggedUsersIds[i].replace(/(<|@|>)/g,'');
          }
          _("taggedUsersIds");
          _(taggedUsersIds)
          var ps = [];
          for(var i=0;i<taggedUsersIds.length;i++){
            ps.push(getUserInfoPromise(taggedUsersIds[i]));
          }
          Promise.all(ps).then(function(results){
            _("results");
            _(results)
            for(var i=0;i<taggedUsers.length;i++){
              _('iteration '+i);
              obj.text = obj.text.replace(taggedUsers[i],results[i]);
              _(obj.text);
            }
          });
        }
        var quotedText = obj.text.replace(/([\n\r])/g, '\n\n> $1');
        var b64fileBody = res.content;
        var bufBody = new Buffer(b64fileBody, 'base64')
        var fileBody = bufBody.toString();
        fileBody+= ""+formatDate(obj.ts)+"\n\n **"+ obj.user +"**" + " :\n\n >" + quotedText + "\n\n";
        var content = Buffer.from(fileBody, 'ascii');
        var b64content = content.toString('base64');
        var shaStr = res.sha;
    		github.get().repos.updateFile({
    			owner:"NeuroTechX",
    			repo:"ntx_slack_archive",
    			path:obj.channel+'.md',
    			message:"Edubot Push",
    			content:b64content,
    			sha: shaStr
    		}, function(err, res) {
        });
    	}
	});
}
/**
 * This function formats the timestamp to a user friendly format
 * @param {timestamp} ts the time stamp to format
 */
function formatDate(ts){
  return ts.toLocaleDateString("en-US") + " " + ts.toLocaleTimeString(["en-US"], {hour: '2-digit', minute:'2-digit'});
}
/**
 * This function creates a github archiving page
 * @param {string} obj data to push
 */
function createPage(obj){
      var fileBody = "######"+obj.channel+"\n\n";
      var quotedText = obj.text.replace(/([\n\r])/g, '\n\n> $1');
			fileBody+= ""+formatDate(obj.ts)+"\n\n **"+ obj.user +"**" + " :\n\n >" + quotedText + "\n\n";

      var content = Buffer.from(fileBody, 'ascii');
      var b64content = content.toString('base64');

      github.get().repos.createFile({
        owner:"NeuroTechX",
        repo:"ntx_slack_archive",
        path:obj.channel+'.md',
        message:"Edubot Push",
        content:b64content
      }, function(err, res) {
      });
}
function getUserInfoPromise(uid){
  return new Promise(function(resolve, reject) {
    kv.get("bot_token",function(err,bToken){
      if(err)
        _("error while loading bot token");
      else if(!err && bToken){
        slapp.client.users.info({token:bToken,user:uid}, (err, data) => {
          if(err)
            reject(err);
          else
            resolve(data.user.name);
        });
      }
    });
  });
}
module.exports = {
  receive:receive,
  handle_restart:handle_restart,
  start:start
}
<|endoftext|>


<commit_before>/* eslint no-console: ["error", { allow: ["log"] }] */
const gulp = require('gulp');
const connect = require('gulp-connect');
const gopen = require('gulp-open');
const runSequence = require('run-sequence');

const buildKsCore = require('./build-ks-core.js');
const buildKsVue = require('./build-ks-vue.js');
const buildKsReact = require('./build-ks-react.js');

const buildCoreJs = require('./build-core-js.js');
const buildCoreTypings = require('./build-core-typings.js');
const buildCoreLess = require('./build-core-less.js');
const buildCoreComponents = require('./build-core-components.js');
const buildCoreLazyComponents = require('./build-core-lazy-components.js');

const buildPhenome = require('./build-phenome.js');
const buildVue = require('./build-vue');
const buildVueTypings = require('./build-vue-typings.js');
const buildReact = require('./build-react');
const buildReactTypings = require('./build-react-typings.js');

const env = process.env.NODE_ENV || 'development';

// Tasks
gulp.task('ks-core', buildKsCore);
gulp.task('ks-vue', buildKsVue);
gulp.task('ks-react', buildKsReact);
gulp.task('core-js', buildCoreJs);
gulp.task('core-typings', buildCoreTypings);
gulp.task('core-less', buildCoreLess);
gulp.task('core-components', buildCoreComponents);
gulp.task('core-lazy-components', buildCoreLazyComponents);
gulp.task('phenome', buildPhenome);

gulp.task('react', buildReact);
gulp.task('react-typings', buildReactTypings);

gulp.task('vue', buildVue);
gulp.task('vue-typings', buildVueTypings);

// eslint-disable-next-line
gulp.task('build-core', runSequence('core-js', 'core-components', 'core-typings', 'core-less', 'core-lazy-components'));
gulp.task('build-react', () => runSequence('react', 'react-typings'));
gulp.task('build-vue', () => runSequence('vue', 'vue-typings'));

// Watchers
const watch = {
  all() {
    gulp.watch(['./src/core/**/*.js'], () => runSequence(
      'core-js',
      'core-components',
      'ks-react',
      'ks-vue'
    ));
    gulp.watch(['./src/core/**/*.d.ts'], () => runSequence(
      'core-typings'
    ));
    gulp.watch('./src/core/**/*.less', () => runSequence(
      'core-less',
      'core-components'
    ));
    gulp.watch(['./src/phenome/**/*.js', './src/phenome/**/*.jsx'], () => runSequence(
      'phenome',
      'build-react',
      'build-vue',
      'ks-react',
      'ks-vue'
    ));
    gulp.watch(['./kitchen-sink/react/src/**/*.js', './kitchen-sink/react/src/**/*.jsx'], () => runSequence(
      'ks-react'
    ));
    gulp.watch(['./kitchen-sink/vue/src/**/*.js', './kitchen-sink/vue/src/**/*.vue'], () => runSequence(
      'ks-vue'
    ));
  },
  core() {
    gulp.watch(['./src/core/**/*.js'], () => runSequence(
      'core-js',
      'core-components',
      'core-lazy-components',
    ));
    gulp.watch(['./src/core/**/*.d.ts'], () => runSequence(
      'core-typings'
    ));
    gulp.watch('./src/**/**/*.less', () => runSequence(
      'core-less',
      'core-components',
      'core-lazy-components',
    ));
  },
  react() {
    gulp.watch(['./src/core/**/*.js'], () => runSequence(
      'core-js',
      'core-components',
      'ks-react'
    ));
    gulp.watch('./src/core/**/*.less', () => runSequence(
      'core-less',
      'core-components',
    ));
    gulp.watch(['./src/phenome/**/*.js', './src/phenome/**/*.jsx'], () => runSequence(
      'phenome',
      'build-react',
      'ks-react'
    ));
    gulp.watch(['./kitchen-sink/react/src/**/*.js', './kitchen-sink/react/src/**/*.jsx'], [
      'ks-react',
    ]);
  },
  vue() {
    gulp.watch(['./src/core/**/*.js'], () => runSequence(
      'core-js',
      'core-components',
      'ks-vue'
    ));
    gulp.watch('./src/core/**/*.less', () => runSequence(
      'core-less',
      'core-components',
    ));
    gulp.watch(['./src/phenome/**/*.js', './src/phenome/**/*.jsx'], () => runSequence(
      'phenome',
      'build-vue',
      'ks-vue'
    ));
    gulp.watch(['./kitchen-sink/vue/src/**/*.js', './kitchen-sink/vue/src/**/*.vue'], [
      'ks-vue',
    ]);
  },
};

// Server
function server() {
  connect.server({
    root: ['./'],
    livereload: false,
    port: '3000',
  });
}
gulp.task('server', () => {
  if (env === 'development') watch.all();
  server();
  gulp.src('./kitchen-sink/core/index.html').pipe(gopen({ uri: 'http://localhost:3000/kitchen-sink/core/' }));
});
gulp.task('server-core', () => {
  if (env === 'development') watch.core();
  server();
  gulp.src('./kitchen-sink/core/index.html').pipe(gopen({ uri: 'http://localhost:3000/kitchen-sink/core/' }));
});
gulp.task('server-react', () => {
  if (env === 'development') watch.react();
  server();
  gulp.src('./kitchen-sink/react/index.html').pipe(gopen({ uri: 'http://localhost:3000/kitchen-sink/react/' }));
});
gulp.task('server-vue', () => {
  if (env === 'development') watch.vue();
  server();
  gulp.src('./kitchen-sink/vue/index.html').pipe(gopen({ uri: 'http://localhost:3000/kitchen-sink/vue/' }));
});

gulp.task('watch', () => {
  watch.all();
});
gulp.task('watch-core', () => {
  watch.core();
});
gulp.task('watch-react', () => {
  watch.react();
});
gulp.task('watch-vue', () => {
  watch.vue();
});
<commit_msg>v4: Fix gulp task<commit_after>/* eslint no-console: ["error", { allow: ["log"] }] */
const gulp = require('gulp');
const connect = require('gulp-connect');
const gopen = require('gulp-open');
const runSequence = require('run-sequence');

const buildKsCore = require('./build-ks-core.js');
const buildKsVue = require('./build-ks-vue.js');
const buildKsReact = require('./build-ks-react.js');

const buildCoreJs = require('./build-core-js.js');
const buildCoreTypings = require('./build-core-typings.js');
const buildCoreLess = require('./build-core-less.js');
const buildCoreComponents = require('./build-core-components.js');
const buildCoreLazyComponents = require('./build-core-lazy-components.js');

const buildPhenome = require('./build-phenome.js');
const buildVue = require('./build-vue');
const buildVueTypings = require('./build-vue-typings.js');
const buildReact = require('./build-react');
const buildReactTypings = require('./build-react-typings.js');

const env = process.env.NODE_ENV || 'development';

// Tasks
gulp.task('ks-core', buildKsCore);
gulp.task('ks-vue', buildKsVue);
gulp.task('ks-react', buildKsReact);
gulp.task('core-js', buildCoreJs);
gulp.task('core-typings', buildCoreTypings);
gulp.task('core-less', buildCoreLess);
gulp.task('core-components', buildCoreComponents);
gulp.task('core-lazy-components', buildCoreLazyComponents);
gulp.task('phenome', buildPhenome);

gulp.task('react', buildReact);
gulp.task('react-typings', buildReactTypings);

gulp.task('vue', buildVue);
gulp.task('vue-typings', buildVueTypings);

// eslint-disable-next-line
gulp.task('build-core', () => runSequence('core-js', 'core-components', 'core-typings', 'core-less', 'core-lazy-components'));
gulp.task('build-react', () => runSequence('react', 'react-typings'));
gulp.task('build-vue', () => runSequence('vue', 'vue-typings'));

// Watchers
const watch = {
  all() {
    gulp.watch(['./src/core/**/*.js'], () => runSequence(
      'core-js',
      'core-components',
      'ks-react',
      'ks-vue'
    ));
    gulp.watch(['./src/core/**/*.d.ts'], () => runSequence(
      'core-typings'
    ));
    gulp.watch('./src/core/**/*.less', () => runSequence(
      'core-less',
      'core-components'
    ));
    gulp.watch(['./src/phenome/**/*.js', './src/phenome/**/*.jsx'], () => runSequence(
      'phenome',
      'build-react',
      'build-vue',
      'ks-react',
      'ks-vue'
    ));
    gulp.watch(['./kitchen-sink/react/src/**/*.js', './kitchen-sink/react/src/**/*.jsx'], () => runSequence(
      'ks-react'
    ));
    gulp.watch(['./kitchen-sink/vue/src/**/*.js', './kitchen-sink/vue/src/**/*.vue'], () => runSequence(
      'ks-vue'
    ));
  },
  core() {
    gulp.watch(['./src/core/**/*.js'], () => runSequence(
      'core-js',
      'core-components',
      'core-lazy-components',
    ));
    gulp.watch(['./src/core/**/*.d.ts'], () => runSequence(
      'core-typings'
    ));
    gulp.watch('./src/**/**/*.less', () => runSequence(
      'core-less',
      'core-components',
      'core-lazy-components',
    ));
  },
  react() {
    gulp.watch(['./src/core/**/*.js'], () => runSequence(
      'core-js',
      'core-components',
      'ks-react'
    ));
    gulp.watch('./src/core/**/*.less', () => runSequence(
      'core-less',
      'core-components',
    ));
    gulp.watch(['./src/phenome/**/*.js', './src/phenome/**/*.jsx'], () => runSequence(
      'phenome',
      'build-react',
      'ks-react'
    ));
    gulp.watch(['./kitchen-sink/react/src/**/*.js', './kitchen-sink/react/src/**/*.jsx'], [
      'ks-react',
    ]);
  },
  vue() {
    gulp.watch(['./src/core/**/*.js'], () => runSequence(
      'core-js',
      'core-components',
      'ks-vue'
    ));
    gulp.watch('./src/core/**/*.less', () => runSequence(
      'core-less',
      'core-components',
    ));
    gulp.watch(['./src/phenome/**/*.js', './src/phenome/**/*.jsx'], () => runSequence(
      'phenome',
      'build-vue',
      'ks-vue'
    ));
    gulp.watch(['./kitchen-sink/vue/src/**/*.js', './kitchen-sink/vue/src/**/*.vue'], [
      'ks-vue',
    ]);
  },
};

// Server
function server() {
  connect.server({
    root: ['./'],
    livereload: false,
    port: '3000',
  });
}
gulp.task('server', () => {
  if (env === 'development') watch.all();
  server();
  gulp.src('./kitchen-sink/core/index.html').pipe(gopen({ uri: 'http://localhost:3000/kitchen-sink/core/' }));
});
gulp.task('server-core', () => {
  if (env === 'development') watch.core();
  server();
  gulp.src('./kitchen-sink/core/index.html').pipe(gopen({ uri: 'http://localhost:3000/kitchen-sink/core/' }));
});
gulp.task('server-react', () => {
  if (env === 'development') watch.react();
  server();
  gulp.src('./kitchen-sink/react/index.html').pipe(gopen({ uri: 'http://localhost:3000/kitchen-sink/react/' }));
});
gulp.task('server-vue', () => {
  if (env === 'development') watch.vue();
  server();
  gulp.src('./kitchen-sink/vue/index.html').pipe(gopen({ uri: 'http://localhost:3000/kitchen-sink/vue/' }));
});

gulp.task('watch', () => {
  watch.all();
});
gulp.task('watch-core', () => {
  watch.core();
});
gulp.task('watch-react', () => {
  watch.react();
});
gulp.task('watch-vue', () => {
  watch.vue();
});
<|endoftext|>