<commit_before>/*global text,expect,ok,module,notEqual,test,window*/

/* This Source Code Form is subject to the terms of the MIT license
 * If a copy of the MIT license was not distributed with this file, you can
 * obtain one at http://www.mozillapopcorn.org/butter-license.txt */

( function ( window, document, undefined ){

  QUnit.config.reorder = false;

  function setupCornfieldTests(){
    var b = new Butter({
      config: "cornfield-test-config.json",
        ready: function( butter ) {
          var filename = "test" + Date.now(),
              data = {
                name: filename,
                html: "herpderp",
                data: { stuff: "derpherp" },
                template: "pop"
              },
              stringedData = JSON.stringify( data );

          module( "Unauthenticated tests" );

          asyncTest( "Logout", 1, function() {
            butter.cornfield.logout( function( res ) {
              equal( res, true, "Clean-up" );

              start();
            });
          });

          test( "Sync API", 4, function() {
            ok( !butter.cornfield.authenticated(), "Authenticated is false" );
            ok( !butter.cornfield.email(), "Email is undefined" );
            ok( !butter.cornfield.name(), "Name is undefined" );
            ok( !butter.cornfield.username(), "Username is undefined" );
          });

          asyncTest( "Async API", 3, function() {

            butter.cornfield.list( function( res ) {
              deepEqual( res, { error: "unauthorized" }, "Not allowed to list projects" );

              butter.cornfield.load( filename, function( res ) {
                deepEqual( res, { error: "unauthorized" }, "Not allowed to get projects" );

                butter.cornfield.save( filename, stringedData, function( res ) {
                  deepEqual( res, { error: "unauthorized" }, "Not allowed to save projects" );

                  start();
                });
              });
            });
          });

          asyncTest( "/api/whoami", 1, function() {
            butter.cornfield.whoami( function( res ) {
              deepEqual( res, { error: "unauthorized" }, "Response is unauthorized" );
              start();
            });
          });

          module( "Authentication tests" );

          asyncTest( "Login (user input needed)", 6, function() {
            butter.cornfield.login( function( res ) {
              clearTimeout( failSafe );
              ok( res, "The login response has data" );
              ok( !res.error, "okay", "No errors while logging in" );
              ok( res.email, "The login has an email: " + res.email );
              equal( res.email, butter.cornfield.email(), "Email is stored" );
              equal( res.name, butter.cornfield.name(), "Name is stored" );
              equal( res.username, butter.cornfield.username(), "Name is stored" );
              start();
            });

            var failSafe = setTimeout( function() {
              clearTimeout( failSafe );
              start();
            }, 20000 );
          });

          module( "Authenticated tests" );

          test( "Sync API", 4, function() {
            ok( butter.cornfield.authenticated(), "Authenticated is true" );
            ok( butter.cornfield.email(), "Email is a truthy value" );
            ok( butter.cornfield.name(), "Name is a truthy value" );
            ok( butter.cornfield.username(), "Username is a truthy value" );
          });

          asyncTest( "Async API", 7, function() {
            var foundProject = false;

            butter.cornfield.list( function( res ) {
              ok(res, "The project list response has data" );
              equal( res.error, "okay", "Project list status is \"okay\"" );
              ok( res.projects, "There is a list of projects" );

              for( i = 0, len = res.projects.length; i < len; i++ ){
                if( res.projects[ i ].name === filename ){
                  foundProject = true;
                  break;
                }
              }

              equal( false, foundProject, filename + " is not present in the projects list" );

              butter.cornfield.load( filename, function( res ) {
                deepEqual( res, { error: "project not found" }, "The project load response is project not found" );

                butter.cornfield.save( filename, stringedData, function( res ) {
                  equal( res.error, "okay", "The project save response is okay" );

                  filename = res.project._id;

                  butter.cornfield.load( filename, function( res ) {
                    deepEqual( JSON.parse( res.project ), data.data, "The project is the same" );

                    start();
                  });
                });
              });
            });

            var failSafe = setTimeout( function() {
              clearTimeout( failSafe );
              start();
            }, 20000 );
          });

          asyncTest( "/api/whoami", 1, function() {
            butter.cornfield.whoami( function( res ) {
              deepEqual( res, {
                email: butter.cornfield.email(),
                name: butter.cornfield.email(),
                username: butter.cornfield.email()
              }, "Response contains user information" );
              start();
            });
          });

          asyncTest( "Logout", 1, function() {
            butter.cornfield.logout( function( res ) {
              equal( res, true, "Clean-up" );

              start();
            });
          });

          module( "State after logout" );

          test( "Sync API", 4, function() {
            ok( !butter.cornfield.authenticated(), "Authenticated is false" );
            ok( !butter.cornfield.email(), "Email is undefined" );
            ok( !butter.cornfield.name(), "Name is undefined" );
            ok( !butter.cornfield.username(), "Username is undefined" );
          });
        }
    });
  }

  document.addEventListener( "DOMContentLoaded", function(){
    // Make sure the cornfield server is running before bothering with all these tests.
    asyncTest( "Cornfield Server Running", 1, function() {
      var request = new XMLHttpRequest();
      request.open('GET', '/api/whoami', false);
      request.send();
      if( request.status === 404 ){
        ok( false, "Cornfield server not running on current server, skipping tests." );
      } else {
        ok( true, "Cornfield server is running on current server. Running Tests." );
        setupCornfieldTests();
      }
      start();
    });
  }, false);

}( window, window.document ));
<commit_msg>Fix QUnit nonsense [#1501]<commit_after>/*global text,expect,ok,module,notEqual,test,window*/

/* This Source Code Form is subject to the terms of the MIT license
 * If a copy of the MIT license was not distributed with this file, you can
 * obtain one at http://www.mozillapopcorn.org/butter-license.txt */

( function ( window, document, undefined ){

  QUnit.config.reorder = false;

  document.addEventListener( "DOMContentLoaded", function(){

    var b = new Butter({
      config: "cornfield-test-config.json",
        ready: function( butter ) {
          var filename = "test" + Date.now(),
              data = {
                name: filename,
                html: "herpderp",
                data: { stuff: "derpherp" },
                template: "pop"
              },
              stringedData = JSON.stringify( data );

          module( "Server State" );

          // Make sure the cornfield server is running before bothering with all these tests.
          asyncTest( "Environment ", 1, function() {
            var request = new XMLHttpRequest();
            request.open( 'GET', '/api/whoami', false );
            request.send();
            if ( request.status === 404 ) {
              ok( false, "Cornfield server not running on node server, skipping tests." );
            } else {
              ok( true, "Cornfield server is running on node server, running Tests." );
            }
            start();
          });

          module( "Unauthenticated tests" );

          asyncTest( "Logout", 1, function() {
            butter.cornfield.logout( function( res ) {
              equal( res, true, "Clean-up" );

              start();
            });
          });

          test( "Sync API", 4, function() {
            ok( !butter.cornfield.authenticated(), "Authenticated is false" );
            ok( !butter.cornfield.email(), "Email is undefined" );
            ok( !butter.cornfield.name(), "Name is undefined" );
            ok( !butter.cornfield.username(), "Username is undefined" );
          });

          asyncTest( "Async API", 3, function() {

            butter.cornfield.list( function( res ) {
              deepEqual( res, { error: "unauthorized" }, "Not allowed to list projects" );

              butter.cornfield.load( filename, function( res ) {
                deepEqual( res, { error: "unauthorized" }, "Not allowed to get projects" );

                butter.cornfield.save( filename, stringedData, function( res ) {
                  deepEqual( res, { error: "unauthorized" }, "Not allowed to save projects" );

                  start();
                });
              });
            });
          });

          asyncTest( "/api/whoami", 1, function() {
            butter.cornfield.whoami( function( res ) {
              deepEqual( res, { error: "unauthorized" }, "Response is unauthorized" );
              start();
            });
          });

          module( "Authentication tests" );

          asyncTest( "Login (user input needed)", 6, function() {
            butter.cornfield.login( function( res ) {
              clearTimeout( failSafe );
              ok( res, "The login response has data" );
              ok( !res.error, "okay", "No errors while logging in" );
              ok( res.email, "The login has an email: " + res.email );
              equal( res.email, butter.cornfield.email(), "Email is stored" );
              equal( res.name, butter.cornfield.name(), "Name is stored" );
              equal( res.username, butter.cornfield.username(), "Name is stored" );
              start();
            });

            var failSafe = setTimeout( function() {
              clearTimeout( failSafe );
              start();
            }, 20000 );
          });

          module( "Authenticated tests" );

          test( "Sync API", 4, function() {
            ok( butter.cornfield.authenticated(), "Authenticated is true" );
            ok( butter.cornfield.email(), "Email is a truthy value" );
            ok( butter.cornfield.name(), "Name is a truthy value" );
            ok( butter.cornfield.username(), "Username is a truthy value" );
          });

          asyncTest( "Async API", 7, function() {
            var foundProject = false;

            butter.cornfield.list( function( res ) {
              ok(res, "The project list response has data" );
              equal( res.error, "okay", "Project list status is \"okay\"" );
              ok( res.projects, "There is a list of projects" );

              for( i = 0, len = res.projects.length; i < len; i++ ){
                if( res.projects[ i ].name === filename ){
                  foundProject = true;
                  break;
                }
              }

              equal( false, foundProject, filename + " is not present in the projects list" );

              butter.cornfield.load( filename, function( res ) {
                deepEqual( res, { error: "project not found" }, "The project load response is project not found" );

                butter.cornfield.save( filename, stringedData, function( res ) {
                  equal( res.error, "okay", "The project save response is okay" );

                  filename = res.project._id;

                  butter.cornfield.load( filename, function( res ) {
                    deepEqual( JSON.parse( res.project ), data.data, "The project is the same" );

                    start();
                  });
                });
              });
            });

            var failSafe = setTimeout( function() {
              clearTimeout( failSafe );
              start();
            }, 20000 );
          });

          asyncTest( "/api/whoami", 1, function() {
            butter.cornfield.whoami( function( res ) {
              deepEqual( res, {
                email: butter.cornfield.email(),
                name: butter.cornfield.email(),
                username: butter.cornfield.email()
              }, "Response contains user information" );
              start();
            });
          });

          asyncTest( "Logout", 1, function() {
            butter.cornfield.logout( function( res ) {
              equal( res, true, "Clean-up" );

              start();
            });
          });

          module( "State after logout" );

          test( "Sync API", 4, function() {
            ok( !butter.cornfield.authenticated(), "Authenticated is false" );
            ok( !butter.cornfield.email(), "Email is undefined" );
            ok( !butter.cornfield.name(), "Name is undefined" );
            ok( !butter.cornfield.username(), "Username is undefined" );
          });
        }
    });
  }, false );
}( window, window.document ));
<|endoftext|>


<commit_before>var gulp = require("gulp");
var gulpVersion = require("./lib/gulp-version");

gulp.task("default", function() {
    return gulp
        .src([ "./package.json", "bower.json" ], { buffer: false })
        .pipe(gulpVersion("./gulp-version.json"))
        .pipe(gulp.dest("./test"));
});
<commit_msg>Fix usage of gulp-version.json in gulpfile.js<commit_after>var gulp = require("gulp");
var path = require("path");
var gulpVersion = require("./lib/gulp-version");

gulp.task("default", function() {
    return gulp
        .src([ "./package.json", "bower.json" ], { buffer: false })
        .pipe(gulpVersion(path.join(__dirname, "/gulp-version.json")))
        .pipe(gulp.dest("./test"));
});
<|endoftext|>


<commit_before>'use strict';

Stripe.DEFAULT_HOST = 'api.stripe.com';
Stripe.DEFAULT_PORT = '443';
Stripe.DEFAULT_BASE_PATH = '/v1/';
Stripe.DEFAULT_API_VERSION = null;

// Use node's default timeout:
Stripe.DEFAULT_TIMEOUT = require('http').createServer().timeout;

Stripe.PACKAGE_VERSION = require('../package.json').version;

Stripe.USER_AGENT = {
  bindings_version: Stripe.PACKAGE_VERSION,
  lang: 'node',
  lang_version: process.version,
  platform: process.platform,
  publisher: 'stripe',
  uname: null,
};

Stripe.USER_AGENT_SERIALIZED = null;

var exec = require('child_process').exec;

var resources = {
  // Support Accounts for consistency, Account for backwards compat
  Account: require('./resources/Accounts'),
  Accounts: require('./resources/Accounts'),
  Balance: require('./resources/Balance'),
  Charges: require('./resources/Charges'),
  Coupons: require('./resources/Coupons'),
  Customers: require('./resources/Customers'),
  Disputes: require('./resources/Disputes'),
  Events: require('./resources/Events'),
  Invoices: require('./resources/Invoices'),
  InvoiceItems: require('./resources/InvoiceItems'),
  Plans: require('./resources/Plans'),
  RecipientCards: require('./resources/RecipientCards'),
  Recipients: require('./resources/Recipients'),
  Refunds: require('./resources/Refunds'),
  Tokens: require('./resources/Tokens'),
  Transfers: require('./resources/Transfers'),
  ApplicationFees: require('./resources/ApplicationFees'),
  FileUploads: require('./resources/FileUploads'),
  BitcoinReceivers: require('./resources/BitcoinReceivers'),
  Products: require('./resources/Products'),
  Skus: require('./resources/SKUs'),
  Orders: require('./resources/Orders'),

  // The following rely on pre-filled IDs:
  CustomerCards: require('./resources/CustomerCards'),
  CustomerSubscriptions: require('./resources/CustomerSubscriptions'),
  ChargeRefunds: require('./resources/ChargeRefunds'),
  ApplicationFeeRefunds: require('./resources/ApplicationFeeRefunds'),
  TransferReversals: require('./resources/TransferReversals'),

};

Stripe.StripeResource = require('./StripeResource');
Stripe.resources = resources;

function Stripe(key, version) {
  if (!(this instanceof Stripe)) {
    return new Stripe(key, version);
  }

  this._api = {
    auth: null,
    host: Stripe.DEFAULT_HOST,
    port: Stripe.DEFAULT_PORT,
    basePath: Stripe.DEFAULT_BASE_PATH,
    version: Stripe.DEFAULT_API_VERSION,
    timeout: Stripe.DEFAULT_TIMEOUT,
    agent: null,
    dev: false,
  };

  this._prepResources();
  this.setApiKey(key);
  this.setApiVersion(version);
}

Stripe.prototype = {

  setHost: function(host, port, protocol) {
    this._setApiField('host', host);
    if (port) {
      this.setPort(port);
    }
    if (protocol) {
      this.setProtocol(protocol);
    }
  },

  setProtocol: function(protocol) {
    this._setApiField('protocol', protocol.toLowerCase());
  },

  setPort: function(port) {
    this._setApiField('port', port);
  },

  setApiVersion: function(version) {
    if (version) {
      this._setApiField('version', version);
    }
  },

  setApiKey: function(key) {
    if (key) {
      this._setApiField(
        'auth',
        'Basic ' + new Buffer(key + ':').toString('base64')
      );
    }
  },

  setTimeout: function(timeout) {
    this._setApiField(
      'timeout',
      timeout == null ? Stripe.DEFAULT_TIMEOUT : timeout
    );
  },

  setHttpAgent: function(agent) {
    this._setApiField('agent', agent);
  },

  _setApiField: function(key, value) {
    this._api[key] = value;
  },

  getApiField: function(key) {
    return this._api[key];
  },

  getConstant: function(c) {
    return Stripe[c];
  },

  getClientUserAgent: function(cb) {
    if (Stripe.USER_AGENT_SERIALIZED) {
      return cb(Stripe.USER_AGENT_SERIALIZED);
    }
    exec('uname -a', function(err, uname) {
      Stripe.USER_AGENT.uname = uname || 'UNKNOWN';
      Stripe.USER_AGENT_SERIALIZED = JSON.stringify(Stripe.USER_AGENT);
      cb(Stripe.USER_AGENT_SERIALIZED);
    });
  },

  _prepResources: function() {
    for (var name in resources) {
      this[
        name[0].toLowerCase() + name.substring(1)
      ] = new resources[name](this);
    }
  },

};

module.exports = Stripe;
module.exports.Stripe = Stripe;
<commit_msg>Add comment<commit_after>'use strict';

Stripe.DEFAULT_HOST = 'api.stripe.com';
Stripe.DEFAULT_PORT = '443';
Stripe.DEFAULT_BASE_PATH = '/v1/';
Stripe.DEFAULT_API_VERSION = null;

// Use node's default timeout:
Stripe.DEFAULT_TIMEOUT = require('http').createServer().timeout;

Stripe.PACKAGE_VERSION = require('../package.json').version;

Stripe.USER_AGENT = {
  bindings_version: Stripe.PACKAGE_VERSION,
  lang: 'node',
  lang_version: process.version,
  platform: process.platform,
  publisher: 'stripe',
  uname: null,
};

Stripe.USER_AGENT_SERIALIZED = null;

var exec = require('child_process').exec;

var resources = {
  // Support Accounts for consistency, Account for backwards compat
  Account: require('./resources/Accounts'),
  Accounts: require('./resources/Accounts'),
  Balance: require('./resources/Balance'),
  Charges: require('./resources/Charges'),
  Coupons: require('./resources/Coupons'),
  Customers: require('./resources/Customers'),
  Disputes: require('./resources/Disputes'),
  Events: require('./resources/Events'),
  Invoices: require('./resources/Invoices'),
  InvoiceItems: require('./resources/InvoiceItems'),
  Plans: require('./resources/Plans'),
  RecipientCards: require('./resources/RecipientCards'),
  Recipients: require('./resources/Recipients'),
  Refunds: require('./resources/Refunds'),
  Tokens: require('./resources/Tokens'),
  Transfers: require('./resources/Transfers'),
  ApplicationFees: require('./resources/ApplicationFees'),
  FileUploads: require('./resources/FileUploads'),
  BitcoinReceivers: require('./resources/BitcoinReceivers'),
  Products: require('./resources/Products'),
  Skus: require('./resources/SKUs'),
  Orders: require('./resources/Orders'),

  // The following rely on pre-filled IDs:
  CustomerCards: require('./resources/CustomerCards'),
  CustomerSubscriptions: require('./resources/CustomerSubscriptions'),
  ChargeRefunds: require('./resources/ChargeRefunds'),
  ApplicationFeeRefunds: require('./resources/ApplicationFeeRefunds'),
  TransferReversals: require('./resources/TransferReversals'),

};

Stripe.StripeResource = require('./StripeResource');
Stripe.resources = resources;

function Stripe(key, version) {
  if (!(this instanceof Stripe)) {
    return new Stripe(key, version);
  }

  this._api = {
    auth: null,
    host: Stripe.DEFAULT_HOST,
    port: Stripe.DEFAULT_PORT,
    basePath: Stripe.DEFAULT_BASE_PATH,
    version: Stripe.DEFAULT_API_VERSION,
    timeout: Stripe.DEFAULT_TIMEOUT,
    agent: null,
    dev: false,
  };

  this._prepResources();
  this.setApiKey(key);
  this.setApiVersion(version);
}

Stripe.prototype = {

  setHost: function(host, port, protocol) {
    this._setApiField('host', host);
    if (port) {
      this.setPort(port);
    }
    if (protocol) {
      this.setProtocol(protocol);
    }
  },

  setProtocol: function(protocol) {
    this._setApiField('protocol', protocol.toLowerCase());
  },

  setPort: function(port) {
    this._setApiField('port', port);
  },

  setApiVersion: function(version) {
    if (version) {
      this._setApiField('version', version);
    }
  },

  setApiKey: function(key) {
    if (key) {
      this._setApiField(
        'auth',
        'Basic ' + new Buffer(key + ':').toString('base64')
      );
    }
  },

  setTimeout: function(timeout) {
    this._setApiField(
      'timeout',
      timeout == null ? Stripe.DEFAULT_TIMEOUT : timeout
    );
  },

  setHttpAgent: function(agent) {
    this._setApiField('agent', agent);
  },

  _setApiField: function(key, value) {
    this._api[key] = value;
  },

  getApiField: function(key) {
    return this._api[key];
  },

  getConstant: function(c) {
    return Stripe[c];
  },

  getClientUserAgent: function(cb) {
    if (Stripe.USER_AGENT_SERIALIZED) {
      return cb(Stripe.USER_AGENT_SERIALIZED);
    }
    exec('uname -a', function(err, uname) {
      Stripe.USER_AGENT.uname = uname || 'UNKNOWN';
      Stripe.USER_AGENT_SERIALIZED = JSON.stringify(Stripe.USER_AGENT);
      cb(Stripe.USER_AGENT_SERIALIZED);
    });
  },

  _prepResources: function() {
    for (var name in resources) {
      this[
        name[0].toLowerCase() + name.substring(1)
      ] = new resources[name](this);
    }
  },

};

module.exports = Stripe;
// expose constructor as a named property to enable mocking with Sinon.JS
module.exports.Stripe = Stripe;
<|endoftext|>


<commit_before>/*globals require, console, __dirname*/
'use strict';
var util = require('util');
var gulp = require('gulp');
var bower = require('gulp-bower');
var concat = require('gulp-concat');
var del = require('del');
var inject = require('gulp-inject');
var cssnano = require('gulp-cssnano');
var uglify = require('gulp-uglify');
var ngAnnotate = require('gulp-ng-annotate');
var html2js = require('gulp-ng-html2js');
var eventStream = require('event-stream');
var argv = require('yargs').argv;
var gulpNgConfig = require('gulp-ng-config');
var less = require('gulp-less');
var mainBowerFiles = require('main-bower-files');
var gulpSync = require('gulp-sync')(gulp);
var autoprefixer = require('gulp-autoprefixer');
var jsHint = require('gulp-jshint');
var gulpIf = require('gulp-if');
var connect = require('gulp-connect');
var angularFilesort = require('gulp-angular-filesort');
var babel = require('gulp-babel');
var htmlmin = require('gulp-htmlmin');
var imagemin = require('gulp-imagemin');
var pngquant = require('imagemin-pngquant');
var rev = require('gulp-rev');
var config = require('./build.config.js');

var environment = 'dev';
if (typeof argv.env === 'string' && config.environments.indexOf(argv.env.toLowerCase()) > -1) {
    environment = argv.env.toLowerCase();
}

gulp.task('clean', function () {
    var options = {
        force: true
    };
    del(config.buildFiles, options).then(function (paths) {
        console.log('Deleted files/folders:\n', paths.join('\n'));
    });
});

gulp.task('bower', function () {
    return bower(config.appFiles.bowerRoot);
});

gulp.task('constants', function () {
    var options = {
        environment: environment,
        createModule: true,
        wrap: '(function () {\n <%= module %> \n})();'
    };
    return gulp.src(config.appFiles.constants)
        .pipe(gulpNgConfig(config.names.constantsModule, options))
        .pipe(gulp.dest(config.outputPaths.constants));
});

gulp.task('less', function () {
    return gulp.src(config.appFiles.less)
        .pipe(less())
        .pipe(autoprefixer({
            browsers: ['last 2 versions'],
            cascade: false,
            remove: false
        }))
        .pipe(concat(config.names.output.appCss))
        .pipe(gulpIf(shouldMinify(), cssnano()))
        .pipe(gulpIf(shouldRevision(), rev()))
        .pipe(gulp.dest(config.outputPaths.css))
        .pipe(connect.reload());
});

gulp.task('vendor-css', function () {
    var options = {
        filter: '**/*.css',
        debugging: false
    };
    return gulp.src(mainBowerFiles(options), {base: 'bower_components'})
        .pipe(concat(config.names.output.vendorCss))
        .pipe(gulpIf(shouldMinify(), cssnano()))
        .pipe(gulpIf(shouldRevision(), rev()))
        .pipe(gulp.dest(config.outputPaths.css));
});

gulp.task('lint', function () {
    return gulp.src(config.taskFiles.jshint)
        .pipe(jsHint())
        .pipe(jsHint.reporter('default'));
});

gulp.task('app-js', ['constants'], function () {
    return eventStream.merge(htmlJs(), appJs())
        .pipe(ngAnnotate())
        .pipe(angularFilesort())
        .pipe(concat(config.names.output.appJs))
        .pipe(babel({presets: ['es2015']}))
        .pipe(gulpIf(shouldMinify(), uglify()))
        .pipe(gulpIf(shouldRevision(), rev()))
        .pipe(gulp.dest(config.outputPaths.js))
        .pipe(connect.reload());

    function appJs() {
        return gulp.src(config.appFiles.js);
    }

    function htmlJs() {
        var opts = {
            removeComments: true
        };
        return gulp.src(config.appFiles.html)
            .pipe(gulpIf(shouldMinify(), htmlmin(opts)))
            .pipe(html2js({
                moduleName: config.names.viewsModule
            }));
    }
});

gulp.task('vendor-js', function () {
    var options = {
        filter: '**/*.js',
        debugging: false
    };
    var mainBowerSourceFiles = gulp.src(mainBowerFiles(options), {
        base: 'bower_components'
    });
    var vendorJsSourceFiles = gulp.src(config.vendorFiles.js);
    return eventStream.merge(mainBowerSourceFiles, vendorJsSourceFiles)
        .pipe(ngAnnotate())
        .pipe(concat(config.names.output.vendorJs))
        .pipe(gulpIf(shouldMinify(), uglify()))
        .pipe(gulpIf(shouldRevision(), rev()))
        .pipe(gulp.dest(config.outputPaths.js));
});

gulp.task('font', function () {
    return gulp.src(mainBowerFiles({
            filter: '**/*.{eot,svg,ttf,woff,woff2}'
        }))
        .pipe(gulp.dest(config.outputPaths.fonts));
});

gulp.task('static-font', function () {
    return gulp.src(config.appFiles.fonts)
        .pipe(gulp.dest(config.outputPaths.fonts));
});

gulp.task('static-files', function () {
    return gulp.src(config.appFiles.staticFiles)
        .pipe(gulp.dest(config.outputPaths.root));
});

gulp.task('favicon', function () {
    return gulp.src(config.appFiles.favicon)
        .pipe(gulp.dest(config.outputPaths.root));
});

gulp.task('images', function () {
    var options = {
        optimizationLevel: 3,
        progressive: true,
        interlaced: true,
        multipass: true,
        svgoPlugins: [{removeViewBox: false}],
        use: [pngquant()]
    };
    return gulp.src(config.appFiles.images)
        .pipe(gulpIf(shouldMinify(), imagemin(options)))
        .pipe(gulp.dest(config.outputPaths.images))
        .pipe(connect.reload());
});

gulp.task('default', ['build-index']);

gulp.task('build-index', gulpSync.sync(['prep', 'work']), function () {
    var jsSources = gulp.src([
        config.outputPaths.js + '/**/*.js'
    ], {
        read: true
    }).pipe(angularFilesort());

    var cssSources = gulp.src([
        config.outputPaths.css + '/**/*.css'
    ], {
        read: false
    });
    console.log('Environment: %s', environment);
    return gulp.src(config.appFiles.index)
        .pipe(inject(jsSources, {
            ignorePath: config.outputPaths.injectIgnoreString,
            addRootSlash: true
        }))
        .pipe(inject(cssSources, {
            ignorePath: config.outputPaths.injectIgnoreString,
            addRootSlash: true
        }))
        .pipe(gulp.dest(config.outputPaths.root))
        .pipe(connect.reload());
});

gulp.task('prep', ['bower', 'clean']);

//gulp.task('work', gulpSync.async(['vendor-js', 'app-js', 'font', 'less', 'favicon', 'images']));

gulp.task('work', ['vendor-css', 'less', 'vendor-js', 'app-js', 'static-font', 'font', 'favicon', 'images']);

gulp.task('watch', ['build-index', 'connect'], function () {
    gulp.watch(config.watch.less, ['less']);
    gulp.watch([config.watch.js, config.watch.html], ['app-js']);
    gulp.watch(config.watch.images, ['images']);
    gulp.watch(config.watch.constants, ['app-js']);
});

gulp.task('connect', ['build-index'], function () {
    connect.server({
        root: config.outputPaths.root,
        port: 9000,
        livereload: true,
        fallback: config.outputPaths.root + '/index.html'
    });
});

function shouldRevision() {
    if (environment === 'dev' || environment === 'localqa') {
        return false;
    }
    return true;
}

function shouldMinify() {
    if (environment === 'dev' || environment === 'localqa') {
        return false;
    }
    return true;
}
<commit_msg>Removed jshint helpers<commit_after>'use strict';
var util = require('util');
var gulp = require('gulp');
var bower = require('gulp-bower');
var concat = require('gulp-concat');
var del = require('del');
var inject = require('gulp-inject');
var cssnano = require('gulp-cssnano');
var uglify = require('gulp-uglify');
var ngAnnotate = require('gulp-ng-annotate');
var html2js = require('gulp-ng-html2js');
var eventStream = require('event-stream');
var argv = require('yargs').argv;
var gulpNgConfig = require('gulp-ng-config');
var less = require('gulp-less');
var mainBowerFiles = require('main-bower-files');
var gulpSync = require('gulp-sync')(gulp);
var autoprefixer = require('gulp-autoprefixer');
var jsHint = require('gulp-jshint');
var gulpIf = require('gulp-if');
var connect = require('gulp-connect');
var angularFilesort = require('gulp-angular-filesort');
var babel = require('gulp-babel');
var htmlmin = require('gulp-htmlmin');
var imagemin = require('gulp-imagemin');
var pngquant = require('imagemin-pngquant');
var rev = require('gulp-rev');
var config = require('./build.config.js');

var environment = 'dev';
if (typeof argv.env === 'string' && config.environments.indexOf(argv.env.toLowerCase()) > -1) {
    environment = argv.env.toLowerCase();
}

gulp.task('clean', function () {
    var options = {
        force: true
    };
    del(config.buildFiles, options).then(function (paths) {
        console.log('Deleted files/folders:\n', paths.join('\n'));
    });
});

gulp.task('bower', function () {
    return bower(config.appFiles.bowerRoot);
});

gulp.task('constants', function () {
    var options = {
        environment: environment,
        createModule: true,
        wrap: '(function () {\n <%= module %> \n})();'
    };
    return gulp.src(config.appFiles.constants)
        .pipe(gulpNgConfig(config.names.constantsModule, options))
        .pipe(gulp.dest(config.outputPaths.constants));
});

gulp.task('less', function () {
    return gulp.src(config.appFiles.less)
        .pipe(less())
        .pipe(autoprefixer({
            browsers: ['last 2 versions'],
            cascade: false,
            remove: false
        }))
        .pipe(concat(config.names.output.appCss))
        .pipe(gulpIf(shouldMinify(), cssnano()))
        .pipe(gulpIf(shouldRevision(), rev()))
        .pipe(gulp.dest(config.outputPaths.css))
        .pipe(connect.reload());
});

gulp.task('vendor-css', function () {
    var options = {
        filter: '**/*.css',
        debugging: false
    };
    return gulp.src(mainBowerFiles(options), {base: 'bower_components'})
        .pipe(concat(config.names.output.vendorCss))
        .pipe(gulpIf(shouldMinify(), cssnano()))
        .pipe(gulpIf(shouldRevision(), rev()))
        .pipe(gulp.dest(config.outputPaths.css));
});

gulp.task('lint', function () {
    return gulp.src(config.taskFiles.jshint)
        .pipe(jsHint())
        .pipe(jsHint.reporter('default'));
});

gulp.task('app-js', ['constants'], function () {
    return eventStream.merge(htmlJs(), appJs())
        .pipe(ngAnnotate())
        .pipe(angularFilesort())
        .pipe(concat(config.names.output.appJs))
        .pipe(babel({presets: ['es2015']}))
        .pipe(gulpIf(shouldMinify(), uglify()))
        .pipe(gulpIf(shouldRevision(), rev()))
        .pipe(gulp.dest(config.outputPaths.js))
        .pipe(connect.reload());

    function appJs() {
        return gulp.src(config.appFiles.js);
    }

    function htmlJs() {
        var opts = {
            removeComments: true
        };
        return gulp.src(config.appFiles.html)
            .pipe(gulpIf(shouldMinify(), htmlmin(opts)))
            .pipe(html2js({
                moduleName: config.names.viewsModule
            }));
    }
});

gulp.task('vendor-js', function () {
    var options = {
        filter: '**/*.js',
        debugging: false
    };
    var mainBowerSourceFiles = gulp.src(mainBowerFiles(options), {
        base: 'bower_components'
    });
    var vendorJsSourceFiles = gulp.src(config.vendorFiles.js);
    return eventStream.merge(mainBowerSourceFiles, vendorJsSourceFiles)
        .pipe(ngAnnotate())
        .pipe(concat(config.names.output.vendorJs))
        .pipe(gulpIf(shouldMinify(), uglify()))
        .pipe(gulpIf(shouldRevision(), rev()))
        .pipe(gulp.dest(config.outputPaths.js));
});

gulp.task('font', function () {
    return gulp.src(mainBowerFiles({
            filter: '**/*.{eot,svg,ttf,woff,woff2}'
        }))
        .pipe(gulp.dest(config.outputPaths.fonts));
});

gulp.task('static-font', function () {
    return gulp.src(config.appFiles.fonts)
        .pipe(gulp.dest(config.outputPaths.fonts));
});

gulp.task('static-files', function () {
    return gulp.src(config.appFiles.staticFiles)
        .pipe(gulp.dest(config.outputPaths.root));
});

gulp.task('favicon', function () {
    return gulp.src(config.appFiles.favicon)
        .pipe(gulp.dest(config.outputPaths.root));
});

gulp.task('images', function () {
    var options = {
        optimizationLevel: 3,
        progressive: true,
        interlaced: true,
        multipass: true,
        svgoPlugins: [{removeViewBox: false}],
        use: [pngquant()]
    };
    return gulp.src(config.appFiles.images)
        .pipe(gulpIf(shouldMinify(), imagemin(options)))
        .pipe(gulp.dest(config.outputPaths.images))
        .pipe(connect.reload());
});

gulp.task('default', ['build-index']);

gulp.task('build-index', gulpSync.sync(['prep', 'work']), function () {
    var jsSources = gulp.src([
        config.outputPaths.js + '/**/*.js'
    ], {
        read: true
    }).pipe(angularFilesort());

    var cssSources = gulp.src([
        config.outputPaths.css + '/**/*.css'
    ], {
        read: false
    });
    console.log('Environment: %s', environment);
    return gulp.src(config.appFiles.index)
        .pipe(inject(jsSources, {
            ignorePath: config.outputPaths.injectIgnoreString,
            addRootSlash: true
        }))
        .pipe(inject(cssSources, {
            ignorePath: config.outputPaths.injectIgnoreString,
            addRootSlash: true
        }))
        .pipe(gulp.dest(config.outputPaths.root))
        .pipe(connect.reload());
});

gulp.task('prep', ['bower', 'clean']);

//gulp.task('work', gulpSync.async(['vendor-js', 'app-js', 'font', 'less', 'favicon', 'images']));

gulp.task('work', ['vendor-css', 'less', 'vendor-js', 'app-js', 'static-font', 'font', 'favicon', 'images']);

gulp.task('watch', ['build-index', 'connect'], function () {
    gulp.watch(config.watch.less, ['less']);
    gulp.watch([config.watch.js, config.watch.html], ['app-js']);
    gulp.watch(config.watch.images, ['images']);
    gulp.watch(config.watch.constants, ['app-js']);
});

gulp.task('connect', ['build-index'], function () {
    connect.server({
        root: config.outputPaths.root,
        port: 9000,
        livereload: true,
        fallback: config.outputPaths.root + '/index.html'
    });
});

function shouldRevision() {
    if (environment === 'dev' || environment === 'localqa') {
        return false;
    }
    return true;
}

function shouldMinify() {
    if (environment === 'dev' || environment === 'localqa') {
        return false;
    }
    return true;
}
<|endoftext|>


<commit_before>const gulp = require('gulp');
const babel = require('gulp-babel');
const header = require('gulp-header');
const rename = require('gulp-rename');
const uglify = require('gulp-uglify');
const pkg = require('./package.json');

const src = 'lightense.es6';
const dest = './';
const banner = '/*! <%= pkg.name %> v<%= pkg.version %> | © <%= pkg.author %> | <%= pkg.license %> */\n';

gulp.task('default', () =>
  gulp.src(src)
    .pipe(babel({ babelrc: true }))
    .pipe(gulp.dest(dest))
    .pipe(uglify())
    .pipe(header(banner, { pkg : pkg }))
    .pipe(rename({
      suffix: '.min'
    }))
    .pipe(gulp.dest(dest))
);
<commit_msg>Removed obsolete gulpfile<commit_after><|endoftext|>


<commit_before>'use strict';

var _       = require('lodash');
var fs      = require('co-fs');
var util    = require('util');
var co      = require('co');
var express   = require('express');
var httpProxy = require('http-proxy');
var url     = require('url');
var cookieParser = require('cookie-parser');

var appVersion = process.env.TAG;
if(!appVersion || appVersion.trim()==''){
    appVersion =   process.env.COMMIT
}
// Create server & proxy

var app   = express();
var proxy = httpProxy.createProxyServer({});

// Configure options
if(!process.env.API_URL) {
    console.error("WARNING: environment API_URL not set. USING default (https://api.cbddev.xyz) ");
}

var apiUrl = process.env.API_URL || 'https://api.cbddev.xyz';
console.info(`info: chm.cbd.int`);
//console.info(`info: Git version: ${gitVersion}`);
console.info(`info: API address: ${apiUrl}`);

app.set('view engine', 'ejs');
app.use(require('morgan')('dev'));
app.use(cookieParser())

// Configure routes

app.use('/favicon.ico', express.static(__dirname + '/favicon.ico', { setHeaders: setCustomCacheControl }));
app.use('/?:lang(ar|en|es|fr|ru|zh)?/app',     translation, express.static(__dirname + '/app', { setHeaders: setCustomCacheControl }));

app.all('/app/*', (req, res)=>res.status(404).send() );

app.all('/api/*', (req, res)=>proxy.web(req, res, { target: apiUrl, changeOrigin: true }) );

// Configure template

app.get('/?:lang(ar|en|es|fr|ru|zh)?/*', function (req, res) {
   var urlPreferredLang;

   if(req.params.lang)
     urlPreferredLang = ('/'+req.params.lang+'/');
   else{ //temp because the above regex does not work for chm.cbd.int/fr case
        var lang = _.first(_.values(_.omitBy(req.params, _.isNil)))
        var langRegex = /^(ar|en|es|fr|ru|zh)$/
        if(langRegex.test(lang))
            urlPreferredLang = ('/'+lang+'/')
   }

   res.setHeader('Cache-Control', 'public, max-age=0');

   res.cookie('VERSION', appVersion);
   req.url = '/index.ejs';
   co(function*(){

        var preferredLang = getPreferredLanguage(req);
        var langFilepath = yield getLanguageFile(req, preferredLang);
        var options = { baseUrl: urlPreferredLang || (req.headers.base_url ||  (preferredLang ? ('/'+preferredLang+'/') : '/')), 'appVersion' : appVersion };

        if(langFilepath){
             return res.render(langFilepath, options);
        }

        return res.render(__dirname + '/app/index.ejs', options);
    })
});
// Start HTTP server

app.listen(process.env.PORT || 2000, '0.0.0.0', function () {
	console.log('Server listening on %j', this.address());
});

// Handle proxy errors ignore

proxy.on('error', function (error, req, res) {
    console.error('proxy error:', error);
    res.status(502).send();
});

process.on('SIGTERM', ()=>process.exit());

function translation(req, res, next) {

   co(function*(){
        let langFilepath = yield getLanguageFile(req);
        if(langFilepath){
             return res.sendFile(langFilepath);
        }

        next();
   });
}

function* getLanguageFile(req, preferredLang){

    if(!preferredLang)
        preferredLang = getPreferredLanguage(req);

    if(preferredLang){
        var requestedUrl = url.parse(req.url).pathname;
        var path = `/i18n/${preferredLang}/app${requestedUrl}`;

        let statsLang;
        try{
            statsLang  = yield fs.stat(__dirname + path);
        }catch(e){}
        if (statsLang && statsLang.isFile()) {

            var statsEN    = yield fs.stat(`${__dirname}/app${requestedUrl}`);

            var mLangtime  = new Date(util.inspect(statsLang.mtime));
            var mENtime    = new Date(util.inspect(statsEN.mtime));
            if(mLangtime >= mENtime)
                return __dirname + path;
        }
    }
}

function getPreferredLanguage(req){

    var htmlRegex       = /.(html|ejs|json)$/g; ///.html?[^.]/g//\.html(?!.js)
    var langRegex       = /^(ar|fr|es|ru|zh)/;
    var requestedUrl    = url.parse(req.url).pathname;

    if(!htmlRegex.test(requestedUrl))
        return;

    if(req.params.lang)
        return req.params.lang;

    if(req.headers['preferred-language']){

        var validLanguages = ['ar', 'fr', 'es', 'ru', 'zh']
        var language = req.headers['preferred-language'];

        if(_.includes(validLanguages, language.toLowerCase())){
            return language;
        }
    }
}

//============================================================
//
//
//============================================================
function setCustomCacheControl(res, path) {

	var versionWrong = false;
	var versionMatch = false;
    var localhostRegex = /^http:\/\/localhost:([0-9]{4})\//;
    if(res.req.headers && !localhostRegex.test(res.req.headers.referer)){
        versionWrong |= res.req.query && res.req.query.v && res.req.query.v!=appVersion;
        versionWrong |= res.req.cookies && res.req.cookies.VERSION && res.req.cookies.VERSION!=appVersion;
        versionMatch |= res.req.query && res.req.query.v && res.req.query.v==appVersion;
        versionMatch |= res.req.cookies && res.req.cookies.VERSION && res.req.cookies.VERSION==appVersion;
    }

	if(versionWrong || !versionMatch)
		return res.setHeader('Cache-Control', 'public, max-age=0');

	res.setHeader('Cache-Control', 'public, max-age=86400000');
}
<commit_msg>add lang regex to api route<commit_after>'use strict';

var _       = require('lodash');
var fs      = require('co-fs');
var util    = require('util');
var co      = require('co');
var express   = require('express');
var httpProxy = require('http-proxy');
var url     = require('url');
var cookieParser = require('cookie-parser');

var appVersion = process.env.TAG;
if(!appVersion || appVersion.trim()==''){
    appVersion =   process.env.COMMIT
}
// Create server & proxy

var app   = express();
var proxy = httpProxy.createProxyServer({});

// Configure options
if(!process.env.API_URL) {
    console.error("WARNING: environment API_URL not set. USING default (https://api.cbddev.xyz) ");
}

var apiUrl = process.env.API_URL || 'https://api.cbddev.xyz';
console.info(`info: chm.cbd.int`);
//console.info(`info: Git version: ${gitVersion}`);
console.info(`info: API address: ${apiUrl}`);

app.set('view engine', 'ejs');
app.use(require('morgan')('dev'));
app.use(cookieParser())

// Configure routes

app.use('/favicon.ico', express.static(__dirname + '/favicon.ico', { setHeaders: setCustomCacheControl }));
app.use('/?:lang(ar|en|es|fr|ru|zh)?/app',     translation, express.static(__dirname + '/app', { setHeaders: setCustomCacheControl }));

app.all('/app/*', (req, res)=>res.status(404).send() );

app.all('/?:lang(ar|en|es|fr|ru|zh)?/api/*', (req, res)=>proxy.web(req, res, { target: apiUrl, changeOrigin: true }) );

// Configure template

app.get('/?:lang(ar|en|es|fr|ru|zh)?/*', function (req, res) {
   var urlPreferredLang;

   if(req.params.lang)
     urlPreferredLang = ('/'+req.params.lang+'/');
   else{ //temp because the above regex does not work for chm.cbd.int/fr case
        var lang = _.first(_.values(_.omitBy(req.params, _.isNil)))
        var langRegex = /^(ar|en|es|fr|ru|zh)$/
        if(langRegex.test(lang))
            urlPreferredLang = ('/'+lang+'/')
   }

   res.setHeader('Cache-Control', 'public, max-age=0');

   res.cookie('VERSION', appVersion);
   req.url = '/index.ejs';
   co(function*(){

        var preferredLang = getPreferredLanguage(req);
        var langFilepath = yield getLanguageFile(req, preferredLang);
        var options = { baseUrl: urlPreferredLang || (req.headers.base_url ||  (preferredLang ? ('/'+preferredLang+'/') : '/')), 'appVersion' : appVersion };

        if(langFilepath){
             return res.render(langFilepath, options);
        }

        return res.render(__dirname + '/app/index.ejs', options);
    })
});
// Start HTTP server

app.listen(process.env.PORT || 2000, '0.0.0.0', function () {
	console.log('Server listening on %j', this.address());
});

// Handle proxy errors ignore

proxy.on('error', function (error, req, res) {
    console.error('proxy error:', error);
    res.status(502).send();
});

process.on('SIGTERM', ()=>process.exit());

function translation(req, res, next) {

   co(function*(){
        let langFilepath = yield getLanguageFile(req);
        if(langFilepath){
             return res.sendFile(langFilepath);
        }

        next();
   });
}

function* getLanguageFile(req, preferredLang){

    if(!preferredLang)
        preferredLang = getPreferredLanguage(req);

    if(preferredLang){
        var requestedUrl = url.parse(req.url).pathname;
        var path = `/i18n/${preferredLang}/app${requestedUrl}`;

        let statsLang;
        try{
            statsLang  = yield fs.stat(__dirname + path);
        }catch(e){}
        if (statsLang && statsLang.isFile()) {

            var statsEN    = yield fs.stat(`${__dirname}/app${requestedUrl}`);

            var mLangtime  = new Date(util.inspect(statsLang.mtime));
            var mENtime    = new Date(util.inspect(statsEN.mtime));
            if(mLangtime >= mENtime)
                return __dirname + path;
        }
    }
}

function getPreferredLanguage(req){

    var htmlRegex       = /.(html|ejs|json)$/g; ///.html?[^.]/g//\.html(?!.js)
    var langRegex       = /^(ar|fr|es|ru|zh)/;
    var requestedUrl    = url.parse(req.url).pathname;

    if(!htmlRegex.test(requestedUrl))
        return;

    if(req.params.lang)
        return req.params.lang;

    if(req.headers['preferred-language']){

        var validLanguages = ['ar', 'fr', 'es', 'ru', 'zh']
        var language = req.headers['preferred-language'];

        if(_.includes(validLanguages, language.toLowerCase())){
            return language;
        }
    }
}

//============================================================
//
//
//============================================================
function setCustomCacheControl(res, path) {

	var versionWrong = false;
	var versionMatch = false;
    var localhostRegex = /^http:\/\/localhost:([0-9]{4})\//;
    if(res.req.headers && !localhostRegex.test(res.req.headers.referer)){
        versionWrong |= res.req.query && res.req.query.v && res.req.query.v!=appVersion;
        versionWrong |= res.req.cookies && res.req.cookies.VERSION && res.req.cookies.VERSION!=appVersion;
        versionMatch |= res.req.query && res.req.query.v && res.req.query.v==appVersion;
        versionMatch |= res.req.cookies && res.req.cookies.VERSION && res.req.cookies.VERSION==appVersion;
    }

	if(versionWrong || !versionMatch)
		return res.setHeader('Cache-Control', 'public, max-age=0');

	res.setHeader('Cache-Control', 'public, max-age=86400000');
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 Scott Bishop
 * BluJagu, LLC - www.blujagu.com & www.squarejs.com
 * MIT License (MIT) - This header must remain intact.
 **/
define([], function() {
    'use strict';

    var _re1 = /\{\{([\w\-\.]*)\}\}/mig;

    var _re2 = /\{\{\+([\w\-\.]+)\}\}/mig;

    var templateSignature = /<\s*(\w+)[^>]+data-template="([^"]+)"(?:[^\/]*>.*[\r\n\w\W]*?<\s*\/\s*\1\s*>|\s*\/\s*>)/mig;

    var _cache = {};

    var _html2Dom = function (html) {
        var container = document.createElement('div');

        container.innerHTML = html;

        return container.firstChild;
    };

    var createRepeatingElements = function (data, elm) {
        var str = '',
            i = 0,
            row,
            max =  elm.getAttribute('data-repeat-count'),
            prop = elm.getAttribute('data-repeat'),
            len = (data = data[prop]) ? data.length || max : 0,
            replaceVars = function (match, p1) {
                return this[p1];
            };

        for (i; i < len; ++i) {
            row = data[i];
            str += elm.outerHTML.replace(_re2, replaceVars.bind(row));
        }

        str = str.replace(/\sdata-repeat="\w+"/gi, '');

        if (max) {
            str = str.replace(/\sdata-repeat-count="\d+"/gi, '');
        }

        if (!elm.parentNode.innerHTML) {
            elm.parentNode.childNodes[0].innerHTML = str;
            elm = elm.parentNode.childNodes[0];
        } else {
            elm.parentNode.innerHTML = str;
        }

        return elm;
    };

    var getArgs = function (node) {
        var attrs = node.attributes, i = 0, len = attrs.length, attr,
            args = [];

        for (; i < len; ++i) {
            attr = attrs[i];
            if (attr.nodeName.indexOf('data-event-args-') === 0) {
                args.push(attr.value);
            }
        }

        return args;
    };

    var build = function (box) {
        return getTemplate(box.template, true).then(function (templateStr) {
                // cache inner templates
                templateStr.replace(templateSignature, function (match, p1, p2) {
                    match = match.replace(/\{\{\+/g, '{{');
                    match = match.replace(/\sdata-repeat="\w+"/gi, '');
                    box.templates[p2] = match.replace(/\sdata-template="[\w\-_]+"/gi, '');
                });
                // single variable replacement
                var html = templateStr.replace(_re1, function (match, p1) {
                        var nodes = p1.split('.'),
                            node = nodes.shift(),
                            len = nodes.length,
                            data = box.data,
                            returnVal = data ? data[node] : '';

                        for (; len > 0;) {
                            node = nodes.shift();
                            len = nodes.length;
                            returnVal = returnVal[node];
                        }

                        if (returnVal instanceof Function) {
                            returnVal = returnVal.call(data);
                        }

                        return returnVal !== 'undefined' ? returnVal : '';
                    }),
                    hub = box.model.prototype,
                    i, len, j, jLen, repeaters, repeater,
                    domNodes, nodes, node,/* nodeName,*/
                    handlers, handler, newHandler, handlerArray = [];

                html = _html2Dom(html);
                // html is a node, but not an element, so...
                box.appendChild(html);
                html = box.firstChild;
                // html now has all true Element methods and properties :)

                // repeaters and inner variable replacement
                repeaters = html.querySelectorAll('[data-repeat]');
                if (repeaters.length === 0) {
                    repeaters = html.getAttribute('data-repeat') ? [html] : [];
                }
                for (i = 0, len = repeaters.length; i < len; ++i) {
                    repeater = repeaters[i];
                    createRepeatingElements(box.data, repeater);
                }
                // cache data-index dom nodes in box.index
                domNodes = html.querySelectorAll('[data-index]');
                for (i = 0, len = domNodes.length; i < len; ++i) {
                    node = domNodes[i];
                    box.index[node.getAttribute('data-index')] = node;
                }
                // attach dom event handlers
                handlers = box.domEvents;
                for (i = 0, len = handlers.length; i < len; ++i) {
                    handler = handlers[i];
                    if (handler.id) {
                        nodes = html.querySelectorAll('[data-index^=' + handler.id + ']');
                        for (j = 0, jLen = nodes.length; j < jLen; ++j) {
                            node = nodes[j];
                            //nodeName = node.getAttribute('data-index');
                            if (node) {
                                newHandler = {};
                                newHandler.args = getArgs(node);
                                newHandler.event = handler.event;
                                newHandler.context = handler.context;
                                newHandler.callback = handler.callback;
                                handlerArray.push(newHandler);
                                node.addEventListener(newHandler.event, function callback () {
                                    var h = this.handler,
                                        args = Array.from(h.args);

                                    args.push(this.node);
                                    args.push(this.box);

                                    return h.callback.apply(h.context || null, args);
                                }.bind({
                                    'handler': newHandler,
                                    'node': node,
                                    'box': box
                                }));
                            }
                        }
                    } else {
                        //this event is already hooked up!
                        handlerArray.push(handler);
                    }
                }
                box.domEvents = Array.from(handlerArray);
                handlerArray = [];
                // attach model event handlers;
                if (hub.hasOwnProperty('addListener')) {  // eventHub is connected...
                    handlers = box.modelEvents;
                    for (i = 0, len = handlers.length; i < len; ++i) {
                        handler = handlers[i];
                        if (handler.id) {
                            nodes = html.querySelectorAll('[data-index^=' + handler.id + ']');
                            for (j = 0, jLen = nodes.length; j < jLen; ++j) {
                                node = nodes[j];
                                //nodeName = node.getAttribute('data-index');
                                if (node) {
                                    newHandler = {};
                                    newHandler.args = getArgs(node);
                                    newHandler.event = handler.event;
                                    newHandler.context = handler.context;
                                    newHandler.callback = handler.callback;
                                    handlerArray.push(newHandler);
                                    hub.addListener(
                                        newHandler.event,
                                        function (detail) {
                                            var h = this.handler,
                                                args = Array.from(h.args);

                                            args.push(detail);
                                            args.push(this.node);
                                            args.push(this.box);

                                            return  h.callback.apply(h.context || null, args);
                                        }.bind({
                                            'handler': newHandler,
                                            'node': node,
                                            'box': box
                                        }),
                                        node
                                    );
                                }
                            }
                        } else {
                            // already hooked up
                            handlerArray.push(handler);
                        }
                    }
                    box.modelEvents = Array.from(handlerArray);
                }
                // store reference to the box on html
                html.box = box;
                // auto-attach?
                if (box.destination) {
                    box.destination.appendChild(box);
                }
                // resolve promise with the Box
                return box;
            });
        /*});*/
    };

    var cache = function (name, template) {
        _cache[name] = template;
    };

    var getCached = function (name) {
        return _cache[name];
    };

    var getTemplate = function (uri, useCache) {
        uri = decodeURI(uri);

        return new Promise(function (resolve, reject) {
            var xhr = new XMLHttpRequest(),
                separatorIndex = uri.indexOf('?'),
                sliceIndex = separatorIndex < 0 ? uri.length : separatorIndex,
                resource = uri.slice(0, sliceIndex),
                cachedName = resource.replace(/\/|\./g, ''),
                cachedTemplate;

            if (uri.indexOf('<') !== -1) {
                // getTemplate was called on an html string, just return it
                resolve(uri);
                return;
            }

            if (useCache) {
                cachedTemplate = getCached(cachedName);
                if (cachedTemplate) {
                    resolve(cachedTemplate);
                    return;
                }
            }

            xhr.open('GET', resource);

            xhr.onload = function () {
                var response = xhr.response;

                if (response) {
                    // promise completed successfully... cache the template?
                    if (useCache) {
                        cache(cachedName, response);
                    }
                    resolve(response);
                } else {
                    // reject promise - request error
                    reject(Error(xhr.statusText));
                }
            };

            xhr.onerror = function () {
                // reject promise - xhr epic fail
                reject(Error("Network Error"));
            };

            xhr.send();
        });
    };

    return {
        build: build
    };
});<commit_msg>temple bug fix data-index name matching<commit_after>/**
 * Copyright (c) 2015 Scott Bishop
 * BluJagu, LLC - www.blujagu.com & www.squarejs.com
 * MIT License (MIT) - This header must remain intact.
 **/
define([], function() {
    'use strict';

    var _re1 = /\{\{([\w\-\.]*)\}\}/mig;

    var _re2 = /\{\{\+([\w\-\.]+)\}\}/mig;

    var templateSignature = /<\s*(\w+)[^>]+data-template="([^"]+)"(?:[^\/]*>.*[\r\n\w\W]*?<\s*\/\s*\1\s*>|\s*\/\s*>)/mig;

    var _cache = {};

    var _html2Dom = function (html) {
        var container = document.createElement('div');

        container.innerHTML = html;

        return container.firstChild;
    };

    var createRepeatingElements = function (data, elm) {
        var str = '',
            i = 0,
            row,
            max =  elm.getAttribute('data-repeat-count'),
            prop = elm.getAttribute('data-repeat'),
            len = (data = data[prop]) ? data.length || max : 0,
            replaceVars = function (match, p1) {
                return this[p1];
            };

        for (i; i < len; ++i) {
            row = data[i];
            str += elm.outerHTML.replace(_re2, replaceVars.bind(row));
        }

        str = str.replace(/\sdata-repeat="\w+"/gi, '');

        if (max) {
            str = str.replace(/\sdata-repeat-count="\d+"/gi, '');
        }

        if (!elm.parentNode.innerHTML) {
            elm.parentNode.childNodes[0].innerHTML = str;
            elm = elm.parentNode.childNodes[0];
        } else {
            elm.parentNode.innerHTML = str;
        }

        return elm;
    };

    var getArgs = function (node) {
        var attrs = node.attributes, i = 0, len = attrs.length, attr,
            args = [];

        for (; i < len; ++i) {
            attr = attrs[i];
            if (attr.nodeName.indexOf('data-event-args-') === 0) {
                args.push(attr.value);
            }
        }

        return args;
    };

    var build = function (box) {
        return getTemplate(box.template, true).then(function (templateStr) {
                // cache inner templates
                templateStr.replace(templateSignature, function (match, p1, p2) {
                    match = match.replace(/\{\{\+/g, '{{');
                    match = match.replace(/\sdata-repeat="\w+"/gi, '');
                    box.templates[p2] = match.replace(/\sdata-template="[\w\-_]+"/gi, '');
                });
                // single variable replacement
                var html = templateStr.replace(_re1, function (match, p1) {
                        var nodes = p1.split('.'),
                            node = nodes.shift(),
                            len = nodes.length,
                            data = box.data,
                            returnVal = data ? data[node] : '';

                        for (; len > 0;) {
                            node = nodes.shift();
                            len = nodes.length;
                            returnVal = returnVal[node];
                        }

                        if (returnVal instanceof Function) {
                            returnVal = returnVal.call(data);
                        }

                        return returnVal !== 'undefined' ? returnVal : '';
                    }),
                    hub = box.model.prototype,
                    i, len, j, jLen, repeaters, repeater,
                    domNodes, nodes, node,/* nodeName,*/
                    handlers, handler, newHandler, handlerArray = [];

                html = _html2Dom(html);
                // html is a node, but not an element, so...
                box.appendChild(html);
                html = box.firstChild;
                // html now has all true Element methods and properties :)

                // repeaters and inner variable replacement
                repeaters = html.querySelectorAll('[data-repeat]');
                if (repeaters.length === 0) {
                    repeaters = html.getAttribute('data-repeat') ? [html] : [];
                }
                for (i = 0, len = repeaters.length; i < len; ++i) {
                    repeater = repeaters[i];
                    createRepeatingElements(box.data, repeater);
                }
                // cache data-index dom nodes in box.index
                domNodes = html.querySelectorAll('[data-index]');
                for (i = 0, len = domNodes.length; i < len; ++i) {
                    node = domNodes[i];
                    box.index[node.getAttribute('data-index')] = node;
                }
                // attach dom event handlers
                handlers = box.domEvents;
                for (i = 0, len = handlers.length; i < len; ++i) {
                    handler = handlers[i];
                    if (handler.id) {
                        handler.id = handler.id.replace(/^_/,'');
                        nodes = html.querySelectorAll('[data-index=' + handler.id + ']');
                        if (!nodes.length) {
                            nodes = html.querySelectorAll('[data-index^=_' + handler.id + ']');
                        }
                        for (j = 0, jLen = nodes.length; j < jLen; ++j) {
                            node = nodes[j];
                            //nodeName = node.getAttribute('data-index');
                            if (node) {
                                newHandler = {};
                                newHandler.args = getArgs(node);
                                newHandler.event = handler.event;
                                newHandler.context = handler.context;
                                newHandler.callback = handler.callback;
                                handlerArray.push(newHandler);
                                node.addEventListener(newHandler.event, function callback () {
                                    var h = this.handler,
                                        args = Array.from(h.args);

                                    args.push(this.node);
                                    args.push(this.box);

                                    return h.callback.apply(h.context || null, args);
                                }.bind({
                                    'handler': newHandler,
                                    'node': node,
                                    'box': box
                                }));
                            }
                        }
                    } else {
                        //this event is already hooked up!
                        handlerArray.push(handler);
                    }
                }
                box.domEvents = Array.from(handlerArray);
                handlerArray = [];
                // attach model event handlers;
                if (hub.hasOwnProperty('addListener')) {  // eventHub is connected...
                    handlers = box.modelEvents;
                    for (i = 0, len = handlers.length; i < len; ++i) {
                        handler = handlers[i];
                        if (handler.id) {
                            handler.id = handler.id.replace(/^_/,'');
                            nodes = html.querySelectorAll('[data-index=' + handler.id + ']');
                            if (!nodes.length) {
                                nodes = html.querySelectorAll('[data-index^=_' + handler.id + ']');
                            }
                            for (j = 0, jLen = nodes.length; j < jLen; ++j) {
                                node = nodes[j];
                                //nodeName = node.getAttribute('data-index');
                                if (node) {
                                    newHandler = {};
                                    newHandler.args = getArgs(node);
                                    newHandler.event = handler.event;
                                    newHandler.context = handler.context;
                                    newHandler.callback = handler.callback;
                                    handlerArray.push(newHandler);
                                    hub.addListener(
                                        newHandler.event,
                                        function (detail) {
                                            var h = this.handler,
                                                args = Array.from(h.args);

                                            args.push(detail);
                                            args.push(this.node);
                                            args.push(this.box);

                                            return  h.callback.apply(h.context || null, args);
                                        }.bind({
                                            'handler': newHandler,
                                            'node': node,
                                            'box': box
                                        }),
                                        node
                                    );
                                }
                            }
                        } else {
                            // already hooked up
                            handlerArray.push(handler);
                        }
                    }
                    box.modelEvents = Array.from(handlerArray);
                }
                // store reference to the box on html
                html.box = box;
                // auto-attach?
                if (box.destination) {
                    box.destination.appendChild(box);
                }
                // resolve promise with the Box
                return box;
            });
        /*});*/
    };

    var cache = function (name, template) {
        _cache[name] = template;
    };

    var getCached = function (name) {
        return _cache[name];
    };

    var getTemplate = function (uri, useCache) {
        uri = decodeURI(uri);

        return new Promise(function (resolve, reject) {
            var xhr = new XMLHttpRequest(),
                separatorIndex = uri.indexOf('?'),
                sliceIndex = separatorIndex < 0 ? uri.length : separatorIndex,
                resource = uri.slice(0, sliceIndex),
                cachedName = resource.replace(/\/|\./g, ''),
                cachedTemplate;

            if (uri.indexOf('<') !== -1) {
                // getTemplate was called on an html string, just return it
                resolve(uri);
                return;
            }

            if (useCache) {
                cachedTemplate = getCached(cachedName);
                if (cachedTemplate) {
                    resolve(cachedTemplate);
                    return;
                }
            }

            xhr.open('GET', resource);

            xhr.onload = function () {
                var response = xhr.response;

                if (response) {
                    // promise completed successfully... cache the template?
                    if (useCache) {
                        cache(cachedName, response);
                    }
                    resolve(response);
                } else {
                    // reject promise - request error
                    reject(Error(xhr.statusText));
                }
            };

            xhr.onerror = function () {
                // reject promise - xhr epic fail
                reject(Error("Network Error"));
            };

            xhr.send();
        });
    };

    return {
        build: build
    };
});<|endoftext|>


<commit_before>/*global $:true*/
var $        = require('gulp-load-plugins')();
var _        = require('lodash');
var argv     = require('yargs').argv;
var gulp     = require('gulp');
var lazypipe = require('lazypipe');
var manifest = require('asset-builder')('./assets/manifest.json');
var merge    = require('merge-stream');

var mapsEnabled = !argv.production;
var path = manifest.paths;
var globs = manifest.globs;
var project = manifest.getProjectGlobs();

var cssTasks = function(filename) {
  return lazypipe()
    .pipe($.plumber)
    .pipe(function () {
      return $.if(mapsEnabled, $.sourcemaps.init());
    })
      .pipe(function() {
        return $.if('*.less', $.less().on('error', function(err) {
          console.warn(err.message);
        }));
      })
      .pipe(function() {
        return $.if('*.scss', $.sass({
          outputStyle: 'nested', // libsass doesn't support expanded yet
          precision: 10,
          includePaths: ['.'],
          onError: console.error.bind(console, 'Sass error:')
        }));
      })
      .pipe($.concat, filename)
      .pipe($.pleeease, {
        autoprefixer: {
          browsers: [
            'last 2 versions', 'ie 8', 'ie 9', 'android 2.3', 'android 4', 'opera 12'
          ]
        }
      })
    .pipe(function () {
      return $.if(mapsEnabled, $.sourcemaps.write('.'));
    })
    .pipe(gulp.dest, path.dist + 'styles')();
};

gulp.task('styles', ['wiredep'], function() {
  var merged = merge();
  manifest.forEachDependency('css', function (dep) {
    merged.add(gulp.src(dep.globs)
      .pipe(cssTasks(dep.name)));
  });
  return merged;
});

gulp.task('jshint', function() {
  return gulp.src([
    'bower.json', 'gulpfile.js'
  ].concat(project.js))
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.jshint.reporter('fail'));
});

var jsTasks = function(filename) {
  var fn = filename;
  return lazypipe()
    .pipe(function () {
      return $.if(mapsEnabled, $.sourcemaps.init());
    })
    .pipe(function() {
      return $.if(!!fn, $.concat(fn || 'all.js'));
    })
    .pipe($.uglify)
    .pipe(function () {
      return $.if(mapsEnabled, $.sourcemaps.write('.'));
    })
    .pipe(gulp.dest, path.dist + 'scripts')();
};

gulp.task('scripts', ['jshint'], function() {
  var merged = merge();
  manifest.forEachDependency('js', function (dep) {
    merged.add(gulp.src(dep.globs)
      .pipe(jsTasks(dep.name)));
  });
  return merged;
});

gulp.task('fonts', function() {
  return gulp.src(globs.fonts)
    .pipe($.flatten())
    .pipe(gulp.dest(path.dist + 'fonts'));
});

gulp.task('images', function() {
  return gulp.src(globs.images)
    .pipe($.imagemin({
      progressive: true,
      interlaced: true
    }))
    .pipe(gulp.dest(path.dist + 'images'));
});

gulp.task('version', function() {
  return gulp.src([path.dist + '**/*.{js,css}'], { base: path.dist })
    .pipe(gulp.dest(path.dist))
    .pipe($.rev())
    .pipe(gulp.dest(path.dist))
    .pipe($.rev.manifest())
    .pipe(gulp.dest(path.dist));
});

gulp.task('clean', require('del').bind(null, [path.dist]));

gulp.task('watch', function() {
  $.livereload.listen();
  gulp.watch([path.src + 'styles/**/*', 'bower.json'], ['styles']);
  gulp.watch([path.src + 'scripts/**/*', 'bower.json'], ['jshint', 'scripts']);
  gulp.watch(['bower.json'], ['wiredep']);
  gulp.watch('**/*.php').on('change', function(file) {
    $.livereload.changed(file.path);
  });
});

gulp.task('build', ['styles', 'scripts', 'fonts', 'images'], function() {
  gulp.start('version');
});

gulp.task('wiredep', function() {
  var wiredep = require('wiredep').stream;
  gulp.src(project.css)
    .pipe(wiredep())
    .pipe(gulp.dest(path.source + 'styles'));
});

gulp.task('default', ['clean'], function() {
  gulp.start('build');
});
<commit_msg>Adding live reload triggers to JS and CSS changes.<commit_after>/*global $:true*/
var $        = require('gulp-load-plugins')();
var _        = require('lodash');
var argv     = require('yargs').argv;
var gulp     = require('gulp');
var lazypipe = require('lazypipe');
var manifest = require('asset-builder')('./assets/manifest.json');
var merge    = require('merge-stream');

var mapsEnabled = !argv.production;
var path = manifest.paths;
var globs = manifest.globs;
var project = manifest.getProjectGlobs();

var cssTasks = function(filename) {
  return lazypipe()
    .pipe($.plumber)
    .pipe(function () {
      return $.if(mapsEnabled, $.sourcemaps.init());
    })
      .pipe(function() {
        return $.if('*.less', $.less().on('error', function(err) {
          console.warn(err.message);
        }));
      })
      .pipe(function() {
        return $.if('*.scss', $.sass({
          outputStyle: 'nested', // libsass doesn't support expanded yet
          precision: 10,
          includePaths: ['.'],
          onError: console.error.bind(console, 'Sass error:')
        }));
      })
      .pipe($.concat, filename)
      .pipe($.pleeease, {
        autoprefixer: {
          browsers: [
            'last 2 versions', 'ie 8', 'ie 9', 'android 2.3', 'android 4', 'opera 12'
          ]
        }
      })
    .pipe(function () {
      return $.if(mapsEnabled, $.sourcemaps.write('.'));
    })
    .pipe(gulp.dest, path.dist + 'styles')
    .pipe($.livereload)();
};

gulp.task('styles', ['wiredep'], function() {
  var merged = merge();
  manifest.forEachDependency('css', function (dep) {
    merged.add(gulp.src(dep.globs)
      .pipe(cssTasks(dep.name)));
  });
  return merged;
});

gulp.task('jshint', function() {
  return gulp.src([
    'bower.json', 'gulpfile.js'
  ].concat(project.js))
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.jshint.reporter('fail'));
});

var jsTasks = function(filename) {
  var fn = filename;
  return lazypipe()
    .pipe(function () {
      return $.if(mapsEnabled, $.sourcemaps.init());
    })
    .pipe(function() {
      return $.if(!!fn, $.concat(fn || 'all.js'));
    })
    .pipe($.uglify)
    .pipe(function () {
      return $.if(mapsEnabled, $.sourcemaps.write('.'));
    })
    .pipe(gulp.dest, path.dist + 'scripts')
    .pipe($.livereload)();
};

gulp.task('scripts', ['jshint'], function() {
  var merged = merge();
  manifest.forEachDependency('js', function (dep) {
    merged.add(gulp.src(dep.globs)
      .pipe(jsTasks(dep.name)));
  });
  return merged;
});

gulp.task('fonts', function() {
  return gulp.src(globs.fonts)
    .pipe($.flatten())
    .pipe(gulp.dest(path.dist + 'fonts'));
});

gulp.task('images', function() {
  return gulp.src(globs.images)
    .pipe($.imagemin({
      progressive: true,
      interlaced: true
    }))
    .pipe(gulp.dest(path.dist + 'images'));
});

gulp.task('version', function() {
  return gulp.src([path.dist + '**/*.{js,css}'], { base: path.dist })
    .pipe(gulp.dest(path.dist))
    .pipe($.rev())
    .pipe(gulp.dest(path.dist))
    .pipe($.rev.manifest())
    .pipe(gulp.dest(path.dist));
});

gulp.task('clean', require('del').bind(null, [path.dist]));

gulp.task('watch', function() {
  $.livereload.listen();
  gulp.watch([path.src + 'styles/**/*', 'bower.json'], ['styles']);
  gulp.watch([path.src + 'scripts/**/*', 'bower.json'], ['jshint', 'scripts']);
  gulp.watch(['bower.json'], ['wiredep']);
  gulp.watch('**/*.php').on('change', function(file) {
    $.livereload.changed(file.path);
  });
});

gulp.task('build', ['styles', 'scripts', 'fonts', 'images'], function() {
  gulp.start('version');
});

gulp.task('wiredep', function() {
  var wiredep = require('wiredep').stream;
  gulp.src(project.css)
    .pipe(wiredep())
    .pipe(gulp.dest(path.source + 'styles'));
});

gulp.task('default', ['clean'], function() {
  gulp.start('build');
});
<|endoftext|>


<commit_before>"use strict";

let TelegramBot = require('node-telegram-bot-api');
let request = require("request");
let fs = require("fs");

let token = require("./pass.js").token;
let bot = new TelegramBot(token, {polling: true});

let userData = JSON.parse(fs.readFileSync("user_data.json"));

const SAVE_USER_DATA = true;

let sendRequest = (fromId, paradero) => {
	let servs;
	if(paradero.indexOf(" ")!=-1){
		let comps = paradero.split(" ");
		servs = comps.slice(1);
		paradero = comps[0];
	}

	//Using adderou API
	let url = "https://api.adderou.cl/ts/?paradero="+paradero;
	if(servs != null && servs.length > 0)
		url += "&servicios="+servs.join(",");

	request(url, (err,resp,body) => {
		try{
			let data = JSON.parse(body);
			var builder = "Consulta Paradero: "+paradero+" 🚌\n";
			if(data.servicios.length == 0){
				builder += "Sin información";
			}
			else{
				let serv = data.servicios;
				for(var i=0; i<serv.length; i++){
					if(serv[i].tiempo!=null)
						builder += "*"+serv[i].servicio+"* - "+serv[i].tiempo+" ("+serv[i].distancia.substring(0,serv[i].distancia.length-5)+"m)"+"\n";
				}
			}
			bot.sendMessage(fromId, builder, {parse_mode: "Markdown"});
		}
		catch(err) {
			bot.sendMessage(fromId, "Error al cargar datos de Transantiago 💤");
		}
	});
};

let saveRecent = (fromid, paradero) => {
	if(userData[fromid] == null || userData[fromid].recent == null){
		userData[fromid] = {recent: []};
	}
	if(userData[fromid].recent.indexOf(paradero) == -1){
		userData[fromid].recent.push(paradero);
		if(SAVE_USER_DATA){
			fs.writeFile("user_data.json", JSON.stringify(userData), (err) => {
  				if (err) throw err;
  			});
		}
	}
};

let removeRecent = (fromid, paradero) => {
	if(userData[fromid] == null || userData[fromid].recent == null){
		return;
	}
	let ind = userData[fromid].recent.indexOf(paradero);
	if(ind != -1){
		userData[fromid].recent.splice(ind,1);
		if(SAVE_USER_DATA){
			fs.writeFile("user_data.json", JSON.stringify(userData), (err) => {
  				if (err) throw err;
  			});
		}
	}
};

let getKeyboard = (fromId) => {
	let favs = userData[fromId].recent;
	let rows = ~~(Math.sqrt(favs.length));
	let cols = favs.length / rows;
	let keyboard = [];
	let k = 0;
	for(var j = 0; j < rows; j++){
		keyboard.push([]);
		for(i = 0; i < cols; i++){
			if(k >= favs.length) break;
			keyboard[j].push(favs[k]);
			k++;
		}
	}
	return keyboard;
};

bot.onText(/\/consulta (.+)/, (msg, match) => {
	let fromId = msg.from.id;
	let paradero = match[1];
	sendRequest(fromId,paradero);
	//saveRecent(fromId,paradero);
});

bot.onText(/\/favorito (.+)/, (msg, match) => {
	let fromId = msg.from.id;
	let paradero = match[1];
	//sendRequest(fromId,paradero)
	saveRecent(fromId,paradero);
	bot.sendMessage(fromId,"Paradero guardado a favoritos",{
		"reply_markup": {
			"keyboard": getKeyboard(fromId),
			"one_time_keyboard": true
		}
	});
});

bot.onText(/\/borrarfavorito (.+)/, (msg, match) => {
	let fromId = msg.from.id;
	let paradero = match[1];
	//sendRequest(fromId,paradero)
	removeRecent(fromId,paradero);
	bot.sendMessage(fromId,"Paradero removido de favoritos, actualiza tu teclado usando /consulta o cuando agregues un nuevo favorito");
});

bot.onText(/^\/consulta$/, (msg, match) => {
	let fromId = msg.from.id;
	if(userData[fromId]==null)
		userData[fromId] = {};
	if(userData[fromId].recent != null && userData[fromId].recent.length > 0){
		bot.sendMessage(fromId, "Indica el nombre del Paradero",{
			"reply_markup": {
				"keyboard": getKeyboard(fromId),
				"one_time_keyboard": true
			}
		});
	}
	else{
		userData[fromId].recent = [];
		bot.sendMessage(fromId, "Indica el nombre del Paradero");
	}
});

bot.onText(/^[P,p][a-zA-Z][0-9]{2,4}$/, (msg, match) => {
	var fromId = msg.from.id;
	if(userData[fromId]!=null){
		sendRequest(fromId,match[0]);
		//saveRecent(fromId,match[0]);
	}
});<commit_msg>Add new api connection and slashtag queries<commit_after>"use strict";

let TelegramBot = require('node-telegram-bot-api');
let request = require("request");
let fs = require("fs");

let token = require("./pass.js").token;
let bot = new TelegramBot(token, {polling: true});

let userData = JSON.parse(fs.readFileSync("user_data.json"));

const SAVE_USER_DATA = true;

let sendRequest = (fromId, paradero) => {
	let servs;
	if(paradero.indexOf(" ")!=-1){
		let comps = paradero.split(" ");
		servs = comps.slice(1);
		paradero = comps[0];
	}

	//Using adderou API
	let url = "https://api.adderou.cl/ts/?paradero="+paradero;
	if(servs != null && servs.length > 0)
		url += "&servicios="+servs.join(",");

	request(url, (err,resp,body) => {
		try{
			let data = JSON.parse(body);
			var builder = "Consulta Paradero: /" + paradero.toUpperCase() + " 🚌\n";
			if(data.servicios.length == 0){
				builder += "Sin información";
			}
			else{
				let serv = data.servicios;
				for(var i=0; i<serv.length; i++){
					if(serv[i].tiempo!=null)
						builder += "*"+serv[i].servicio+"* - "+serv[i].tiempo+" ("+serv[i].distancia.substring(0,serv[i].distancia.length-5)+"m)"+"\n";
				}
			}
			bot.sendMessage(fromId, builder, {parse_mode: "Markdown"});
		}
		catch(err) {
			bot.sendMessage(fromId, "Error al cargar datos de Transantiago 💤");
		}
	});
};

let saveRecent = (fromid, paradero) => {
	if(userData[fromid] == null || userData[fromid].recent == null){
		userData[fromid] = {recent: []};
	}
	if(userData[fromid].recent.indexOf(paradero) == -1){
		userData[fromid].recent.push(paradero);
		if(SAVE_USER_DATA){
			fs.writeFile("user_data.json", JSON.stringify(userData), (err) => {
  				if (err) throw err;
  			});
		}
	}
};

let removeRecent = (fromid, paradero) => {
	if(userData[fromid] == null || userData[fromid].recent == null){
		return;
	}
	let ind = userData[fromid].recent.indexOf(paradero);
	if(ind != -1){
		userData[fromid].recent.splice(ind,1);
		if(SAVE_USER_DATA){
			fs.writeFile("user_data.json", JSON.stringify(userData), (err) => {
  				if (err) throw err;
  			});
		}
	}
};

let getKeyboard = (fromId) => {
	let favs = userData[fromId].recent;
	let rows = ~~(Math.sqrt(favs.length));
	let cols = favs.length / rows;
	let keyboard = [];
	let k = 0;
	for(var j = 0; j < rows; j++){
		keyboard.push([]);
		for(i = 0; i < cols; i++){
			if(k >= favs.length) break;
			keyboard[j].push(favs[k]);
			k++;
		}
	}
	return keyboard;
};

bot.onText(/\/consulta (.+)/, (msg, match) => {
	let fromId = msg.from.id;
	let paradero = match[1];
	sendRequest(fromId,paradero);
	//saveRecent(fromId,paradero);
});

bot.onText(/\/favorito (.+)/, (msg, match) => {
	let fromId = msg.from.id;
	let paradero = match[1];
	//sendRequest(fromId,paradero)
	saveRecent(fromId,paradero);
	bot.sendMessage(fromId,"Paradero guardado a favoritos",{
		"reply_markup": {
			"keyboard": getKeyboard(fromId),
			"one_time_keyboard": true
		}
	});
});

bot.onText(/\/borrarfavorito (.+)/, (msg, match) => {
	let fromId = msg.from.id;
	let paradero = match[1];
	//sendRequest(fromId,paradero)
	removeRecent(fromId,paradero);
	bot.sendMessage(fromId,"Paradero removido de favoritos, actualiza tu teclado usando /consulta o cuando agregues un nuevo favorito");
});

bot.onText(/^\/consulta$/, (msg, match) => {
	let fromId = msg.from.id;
	if(userData[fromId]==null)
		userData[fromId] = {};
	if(userData[fromId].recent != null && userData[fromId].recent.length > 0){
		bot.sendMessage(fromId, "Indica el nombre del Paradero",{
			"reply_markup": {
				"keyboard": getKeyboard(fromId),
				"one_time_keyboard": true
			}
		});
	}
	else{
		userData[fromId].recent = [];
		bot.sendMessage(fromId, "Indica el nombre del Paradero");
	}
});

bot.onText(/^\/?[P,p][a-zA-Z][0-9]{2,4}$/, (msg, match) => {
	var fromId = msg.from.id;
	if(userData[fromId]!=null){
		sendRequest(fromId,match[0]);
		//saveRecent(fromId,match[0]);
	}
});<|endoftext|>