<commit_before>// TODO: Fix neg problem on page.
const express = require('express')
const http = require('http')
const spdy = require('spdy')
const fs = require('fs')
const url = require('url')
const mongoose = require('mongoose')
mongoose.Promise = global.Promise
const redis = require('redis')
const redislock = require('redis-lock')
const compression = require('compression')
const path = require('path')
const elasticsearch = require('elasticsearch')
const WebSocket = require('ws')
let pages

process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled promise rejection: ' + reason)
  console.error(reason.stack)
})

// This file will be launched with launcher.js.

var maowtm = function (config) {
  var app = express()
  config = config || {}
  this.config = config
  this._mongodb = config.db || 'mongodb://127.0.0.1'
  this.db = mongoose.createConnection()
  this.es = new elasticsearch.Client({
    host: config.elasticsearch || '127.0.0.1'
  })
  this._redis = config.redis || '127.0.0.1'
  this.redis = redis.createClient({
    host: this._redis
  })
  this.lock = redislock(this.redis)
  // this._listen can be a array of address.
  this._listen = config.listen || []
  this._ssl = config.ssl
  this.acme = config.acme || null
  this.destory = false
  this.mockSecure = config.mockSecure || false
  this.noInitImages = config.noInitImages || false
  this.apps = config.apps || []
  this.rbs = config.rbs || []
  this.registeredWSHandlers = [] // { shouldHandle, onConnection }
  app.mockSecure = this.mockSecure
  var callback = config.callback
  function fail (error) {
    if (this.destory) return
    if (callback) {
      this.destory = true
      if (this.db) {
        this.db.close()
      }
      callback(error, null, function () {})
    } else {
      console.error('Error initalizing server:')
      console.error(error)
      process.exit(2)
    }
  }
  this.db.openUri(this._mongodb).catch(err => fail(err))
  if ((!Array.isArray(this._listen) || this._listen.length > 0) && !this.mockSecure && !(this._ssl && this._ssl.cert && this._ssl.key)) {
    fail(new Error('No SSL certificate provided'))
    return
  }
  var _this = this

  this.db.on('error', function (err) {
    fail(err)
  })
  this.db.on('open', function () {
    app.use(function (req, res, next) {
      console.log(`${req.method.toUpperCase()} ${req.protocol}://${req.hostname}${req.path} from ${req.ip}`)
      next()
    })

    pages = require('./pages')(this.db)

    app.use(compression())
    app.use('/.well-known/', express.static(path.join(__dirname, '.well-known')))
    app.use(function (req, res, next) {
      if (!req.hostname) {
        res.status(404)
        res.end()
        return
      }
      if (!(req.secure || app.mockSecure)) {
        res.redirect(302, 'https://' + req.hostname + req.originalUrl)
      } else {
        res.set('Strict-Transport-Security', 'max-age=155520000; includeSubdomains; preload')
        res.set('X-XSS-Protection', '1; mode=block')
        res.set('X-Frame-Options', 'sameorigin')
        res.set('X-Content-Type-Options', 'nosniff')
        next()
      }
    })

    app.use(require('./subs/static')(_this.db, _this.lock))

    // Add trailing / for all GET for all router below. ( i.e. Not including static and img )
    app.use(function (req, res, next) {
      if (req.hostname.match(/^(img|static|file)/) || req.path.match(/\.[^/\\\s%]+$/)) {
        next()
        return
      }
      var prasedUrl = url.parse(req.originalUrl, false)
      if (req.method === 'GET' && prasedUrl.pathname.substr(-1) !== '/') {
        prasedUrl.pathname += '/'
        res.redirect(302, url.format(prasedUrl))
      } else {
        next()
      }
    })

    app.use(require('./subs/main')(_this.db, _this.lock))
    app.use(require('./subs/rb')(_this.db, _this.lock, _this.rbs))
    app.use(require('./subs/mww')(_this.db, _this.lock))
    app.use(require('./subs/ncicgg')(_this.db, _this.lock))

    app.use(function (req, res, next) {
      if (req.hostname === 'beta.schsrch.xyz' && (req.method.toUpperCase() === 'GET' || req.method.toUpperCase() === 'HEAD') && req.path === '/') {
        res.set('Access-Control-Allow-Origin', 'https://beta.schsrch.xyz')
        res.redirect('https://schsrch.xyz' + req.path)
      } else {
        next()
      }
    })

    _this.apps.forEach(it => {
      let route = it.init({
        mongodb: _this.db,
        elasticsearch: _this.es,
        addWSHandler: function (hnd) {
          _this.registeredWSHandlers.push(hnd)
        }
      })
      app.use(function (req, res, next) {
        if (it.hostname === req.hostname) {
          route(req, res, next)
        } else {
          next()
        }
      })
    })

    app.use(require('./subs/misc')(_this.db, _this.lock))

    let nodeenv = process.env.NODE_ENV || ''
    app.use(function (err, req, res, next) {
      res.status(500)
      let pageObj = {err, req}
      if (typeof err !== 'string') {
        pageObj.err = err.message
        if (err.stack) {
          pageObj.stack = err.stack.replace(new RegExp(path.join(__dirname, '..').replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'), 'g'), '...') + // eslint-disable-line no-useless-escape
            `\nServer running in NODE_ENV=${nodeenv}\nTime: ${Date.now() / 1000}`
        }
      }
      res.send(pages.error(pageObj))
      console.error(err)
    })

    function doSetupServer () {
      return new Promise((resolve, reject) => {
        const httpsopts = (_this._ssl ? {
          key: fs.readFileSync(_this._ssl.key),
          cert: fs.readFileSync(_this._ssl.cert)
        } : null)
        if (httpsopts && _this._ssl.ca) {
          httpsopts.ca = fs.readFileSync(_this._ssl.ca)
        }
        _this._servers = {
          http: [],
          http2: []
        }
        doAddImage().then(() => {
          if (!Array.isArray(_this._listen)) {
            if (httpsopts) {
              _this._servers.http2.push(spdy.createServer(httpsopts, app).listen(443, _this._listen))
            }
            _this._servers.http.push(http.createServer(app).listen(80, _this._listen))
          } else {
            _this._listen.forEach(function (address) {
              if (httpsopts) {
                _this._servers.http2.push(spdy.createServer(httpsopts, app).listen(443, address))
              }
              _this._servers.http.push(http.createServer(app).listen(80, address))
            })
          }
          resolve()
        }).catch(reject)
      })
    }
    const Image = _this.db.model('image')
    function doAddImage () {
      return new Promise((resolve, reject) => {
        function addImage (name, path) {
          return new Promise((resolve, reject) => {
            let distName = 's/' + name
            let query = Image.findOne({name: distName}, 'name')
            query.then(img => {
              if (!img) {
                console.log(`Adding image: ${distName}...`)
                fs.readFile(path, {encoding: null}, (err, data) => {
                  if (err) {
                    reject(err)
                    return
                  }
                  Image.addImage(distName, data, err => {
                    if (err) {
                      reject(new Error(`error when trying to add image ${name}: ${err.toString()}`))
                      return
                    }
                    resolve()
                  })
                })
              } else {
                resolve()
              }
            }).catch(err => {
              reject(new Error(`Can't check image cache: ${err}`))
            })
          })
        }
        function addImageInDir (dir) {
          return new Promise((resolve, reject) => {
            let currentDirPath = path.join(__dirname, 'static', 'imgs', dir)
            fs.readdir(currentDirPath, (err, imgFiles) => {
              if (err) {
                reject(err)
                return
              }
              let promises = []
              imgFiles.forEach(name => {
                promises.push(new Promise((resolve, reject) => {
                  let currentName = path.join(dir, name)
                  let currentFileName = path.join(currentDirPath, name)
                  fs.stat(currentFileName, (err, stat) => {
                    if (err) {
                      reject(err)
                      return
                    }
                    if (stat.isFile()) {
                      addImage(currentName, currentFileName).then(resolve, reject)
                    } else if (stat.isDirectory()) {
                      addImageInDir(currentName).then(resolve, reject)
                    } else {
                      resolve()
                    }
                  })
                }))
              })
              Promise.all(promises).then(resolve, reject)
            })
          })
        }
        if (_this.noInitImages) {
          resolve()
        } else {
          addImageInDir('').then(resolve, reject)
        }
      })
    }
    _this.es.ping({}).then(() => doSetupServer().then(() => new Promise((resolve, reject) => {
      _this._servers.http2.forEach(server => {
        let wss = new WebSocket.Server({
          server,
          backlog: 100,
          maxPayload: 1024 * 1024 * 1 // 10MiB
        })
        wss.shouldHandle = function (req) {
          let hnd = _this.registeredWSHandlers.find(hnd => hnd.hostname === req.headers.host)
          if (!hnd) return false
          return hnd.shouldHandle(req)
        }
        wss.on('connection', function (ws, req) {
          let hnd = _this.registeredWSHandlers.find(hnd => hnd.hostname === req.headers.host)
          if (!hnd) {
            ws.close(1, `Unexpected host ${req.headers.host}`)
            console.error(`ws: Unexpected 'connection' event on host ${req.headers.host}`)
          } else {
            hnd.onConnection(ws, req)
          }
        })
      })
      resolve()
    })).then(() => {
      console.log('Server ready.')
      if (callback) {
        callback(null, app, function () {
          _this._servers.http2.forEach(function (s) {
            s.close()
          })
          _this._servers.http.forEach(function (s) {
            s.close()
          })
          _this.destory = true
          _this.db.close()
        })
      }
    }), err => fail(err)).catch(err => { fail(err) })
  })
}

module.exports = maowtm
<commit_msg>Update websocket handling code.<commit_after>// TODO: Fix neg problem on page.
const express = require('express')
const http = require('http')
const spdy = require('spdy')
const fs = require('fs')
const url = require('url')
const mongoose = require('mongoose')
mongoose.Promise = global.Promise
const redis = require('redis')
const redislock = require('redis-lock')
const compression = require('compression')
const path = require('path')
const elasticsearch = require('elasticsearch')
const WebSocket = require('ws')
let pages

process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled promise rejection: ' + reason)
  console.error(reason.stack)
})

// This file will be launched with launcher.js.

var maowtm = function (config) {
  var app = express()
  config = config || {}
  this.config = config
  this._mongodb = config.db || 'mongodb://127.0.0.1'
  this.db = mongoose.createConnection()
  this.es = new elasticsearch.Client({
    host: config.elasticsearch || '127.0.0.1'
  })
  this._redis = config.redis || '127.0.0.1'
  this.redis = redis.createClient({
    host: this._redis
  })
  this.lock = redislock(this.redis)
  // this._listen can be a array of address.
  this._listen = config.listen || []
  this._ssl = config.ssl
  this.acme = config.acme || null
  this.destory = false
  this.mockSecure = config.mockSecure || false
  this.noInitImages = config.noInitImages || false
  this.apps = config.apps || []
  this.rbs = config.rbs || []
  this.registeredWSHandlers = [] // { shouldHandle, onConnection }
  app.mockSecure = this.mockSecure
  var callback = config.callback
  function fail (error) {
    if (this.destory) return
    if (callback) {
      this.destory = true
      if (this.db) {
        this.db.close()
      }
      callback(error, null, function () {})
    } else {
      console.error('Error initalizing server:')
      console.error(error)
      process.exit(2)
    }
  }
  this.db.openUri(this._mongodb).catch(err => fail(err))
  if ((!Array.isArray(this._listen) || this._listen.length > 0) && !this.mockSecure && !(this._ssl && this._ssl.cert && this._ssl.key)) {
    fail(new Error('No SSL certificate provided'))
    return
  }
  var _this = this

  this.db.on('error', function (err) {
    fail(err)
  })
  this.db.on('open', function () {
    app.use(function (req, res, next) {
      console.log(`${req.method.toUpperCase()} ${req.protocol}://${req.hostname}${req.path} from ${req.ip}`)
      next()
    })

    pages = require('./pages')(this.db)

    app.use(compression())
    app.use('/.well-known/', express.static(path.join(__dirname, '.well-known')))
    app.use(function (req, res, next) {
      if (!req.hostname) {
        res.status(404)
        res.end()
        return
      }
      if (!(req.secure || app.mockSecure)) {
        res.redirect(302, 'https://' + req.hostname + req.originalUrl)
      } else {
        res.set('Strict-Transport-Security', 'max-age=155520000; includeSubdomains; preload')
        res.set('X-XSS-Protection', '1; mode=block')
        res.set('X-Frame-Options', 'sameorigin')
        res.set('X-Content-Type-Options', 'nosniff')
        next()
      }
    })

    app.use(require('./subs/static')(_this.db, _this.lock))

    // Add trailing / for all GET for all router below. ( i.e. Not including static and img )
    app.use(function (req, res, next) {
      if (req.hostname.match(/^(img|static|file)/) || req.path.match(/\.[^/\\\s%]+$/)) {
        next()
        return
      }
      var prasedUrl = url.parse(req.originalUrl, false)
      if (req.method === 'GET' && prasedUrl.pathname.substr(-1) !== '/') {
        prasedUrl.pathname += '/'
        res.redirect(302, url.format(prasedUrl))
      } else {
        next()
      }
    })

    app.use(require('./subs/main')(_this.db, _this.lock))
    app.use(require('./subs/rb')(_this.db, _this.lock, _this.rbs))
    app.use(require('./subs/mww')(_this.db, _this.lock))
    app.use(require('./subs/ncicgg')(_this.db, _this.lock))

    app.use(function (req, res, next) {
      if (req.hostname === 'beta.schsrch.xyz' && (req.method.toUpperCase() === 'GET' || req.method.toUpperCase() === 'HEAD') && req.path === '/') {
        res.set('Access-Control-Allow-Origin', 'https://beta.schsrch.xyz')
        res.redirect('https://schsrch.xyz' + req.path)
      } else {
        next()
      }
    })

    _this.apps.forEach(it => {
      let route = it.init({
        mongodb: _this.db,
        elasticsearch: _this.es,
        addWSHandler: function (hnd) {
          _this.registeredWSHandlers.push(hnd)
        }
      })
      app.use(function (req, res, next) {
        if (it.hostname === req.hostname) {
          route(req, res, next)
        } else {
          next()
        }
      })
    })

    app.use(require('./subs/misc')(_this.db, _this.lock))

    let nodeenv = process.env.NODE_ENV || ''
    app.use(function (err, req, res, next) {
      res.status(500)
      let pageObj = {err, req}
      if (typeof err !== 'string') {
        pageObj.err = err.message
        if (err.stack) {
          pageObj.stack = err.stack.replace(new RegExp(path.join(__dirname, '..').replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'), 'g'), '...') + // eslint-disable-line no-useless-escape
            `\nServer running in NODE_ENV=${nodeenv}\nTime: ${Date.now() / 1000}`
        }
      }
      res.send(pages.error(pageObj))
      console.error(err)
    })

    function doSetupServer () {
      return new Promise((resolve, reject) => {
        const httpsopts = (_this._ssl ? {
          key: fs.readFileSync(_this._ssl.key),
          cert: fs.readFileSync(_this._ssl.cert)
        } : null)
        if (httpsopts && _this._ssl.ca) {
          httpsopts.ca = fs.readFileSync(_this._ssl.ca)
        }
        _this._servers = {
          http: [],
          http2: []
        }
        doAddImage().then(() => {
          if (!Array.isArray(_this._listen)) {
            if (httpsopts) {
              _this._servers.http2.push(spdy.createServer(httpsopts, app).listen(443, _this._listen))
            }
            _this._servers.http.push(http.createServer(app).listen(80, _this._listen))
          } else {
            _this._listen.forEach(function (address) {
              if (httpsopts) {
                _this._servers.http2.push(spdy.createServer(httpsopts, app).listen(443, address))
              }
              _this._servers.http.push(http.createServer(app).listen(80, address))
            })
          }
          resolve()
        }).catch(reject)
      })
    }
    const Image = _this.db.model('image')
    function doAddImage () {
      return new Promise((resolve, reject) => {
        function addImage (name, path) {
          return new Promise((resolve, reject) => {
            let distName = 's/' + name
            let query = Image.findOne({name: distName}, 'name')
            query.then(img => {
              if (!img) {
                console.log(`Adding image: ${distName}...`)
                fs.readFile(path, {encoding: null}, (err, data) => {
                  if (err) {
                    reject(err)
                    return
                  }
                  Image.addImage(distName, data, err => {
                    if (err) {
                      reject(new Error(`error when trying to add image ${name}: ${err.toString()}`))
                      return
                    }
                    resolve()
                  })
                })
              } else {
                resolve()
              }
            }).catch(err => {
              reject(new Error(`Can't check image cache: ${err}`))
            })
          })
        }
        function addImageInDir (dir) {
          return new Promise((resolve, reject) => {
            let currentDirPath = path.join(__dirname, 'static', 'imgs', dir)
            fs.readdir(currentDirPath, (err, imgFiles) => {
              if (err) {
                reject(err)
                return
              }
              let promises = []
              imgFiles.forEach(name => {
                promises.push(new Promise((resolve, reject) => {
                  let currentName = path.join(dir, name)
                  let currentFileName = path.join(currentDirPath, name)
                  fs.stat(currentFileName, (err, stat) => {
                    if (err) {
                      reject(err)
                      return
                    }
                    if (stat.isFile()) {
                      addImage(currentName, currentFileName).then(resolve, reject)
                    } else if (stat.isDirectory()) {
                      addImageInDir(currentName).then(resolve, reject)
                    } else {
                      resolve()
                    }
                  })
                }))
              })
              Promise.all(promises).then(resolve, reject)
            })
          })
        }
        if (_this.noInitImages) {
          resolve()
        } else {
          addImageInDir('').then(resolve, reject)
        }
      })
    }
    _this.es.ping({}).then(() => doSetupServer().then(() => new Promise((resolve, reject) => {
      _this._servers.http2.forEach(server => {
        let wss = new WebSocket.Server({
          server,
          backlog: 100,
          maxPayload: 1024 * 1024 * 1 // 10MiB
        })
        wss.shouldHandle = function (req) {
          let reqHost = req.headers.host
          if (reqHost.endsWith(':443')) reqHost = reqHost.substr(0, reqHost.length - 4)
          console.log(`WS on ${reqHost}${req.url}`)
          let hnd = _this.registeredWSHandlers.find(hnd => hnd.hostname === reqHost)
          if (!hnd) return false
          return hnd.shouldHandle(req)
        }
        wss.on('connection', function (ws, req) {
          let hnd = _this.registeredWSHandlers.find(hnd => hnd.hostname === req.headers.host)
          if (!hnd) {
            ws.close(1, `Unexpected host ${req.headers.host}`)
            console.error(`ws: Unexpected 'connection' event on host ${req.headers.host}`)
          } else {
            hnd.onConnection(ws, req)
          }
        })
      })
      resolve()
    })).then(() => {
      console.log('Server ready.')
      if (callback) {
        callback(null, app, function () {
          _this._servers.http2.forEach(function (s) {
            s.close()
          })
          _this._servers.http.forEach(function (s) {
            s.close()
          })
          _this.destory = true
          _this.db.close()
        })
      }
    }), err => fail(err)).catch(err => { fail(err) })
  })
}

module.exports = maowtm
<|endoftext|>


<commit_before>var timeMilliseconds = function(val) {
    var regex = /([0-9]+):([0-9]{2}):([0-9]{2}),([0-9]{3})/;
    var parts = regex.exec(val);

    if (parts === null) {
        return 0;
    }

    for (var i = 1; i < 5; i++) {
        parts[i] = parseInt(parts[i], 10);
        if (isNaN(parts[i])) parts[i] = 0;
    }

    // hours + minutes + seconds + ms
    return parts[1] * 3600000 + parts[2] * 6000 + parts[3] * 1000 + parts[4];
};

exports.fromSrt = function(data, ms) {
    var useMs = ms ? true : false;

    data = data.replace(/\r/g, '');
    var regex = /([0-9]+)\n([0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3}) --> ([0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3})/g;
    data = data.split(regex);
    data.shift();

    var items = [];
    for (var i = 0; i < data.length; i += 4) {
        items.push({
            id: data[i].trim(),
            startTime: useMs ? timeMilliseconds(data[i + 1].trim()) : data[i + 1].trim(),
            stopTime: useMs ? timeMilliseconds(data[i + 2].trim()) : data[i + 2].trim(),
            data: data[i + 3].trim()
        });
    }

    return items;
};

exports.toSrt = function(data) {
};
<commit_msg>toSrt method<commit_after>var parser = (function() {
    var pItems = {};

    /**
     * Converts SubRip subtitles into array of objects
     * [{
     *     id:        `Number of subtitle`
     *     startTime: `Start time of subtitle`
     *     endTime:   `End time of subtitle
     *     text: `Text of subtitle`
     * }]
     *
     * @param  {String}  data SubRip suntitles string
     * @param  {Boolean} ms   Optional: use milliseconds for startTime and endTime
     * @return {Array}
     */
    pItems.fromSrt = function(data, ms) {
        var useMs = ms ? true : false;

        data = data.replace(/\r/g, '');
        var regex = /([0-9]+)\n([0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3}) --> ([0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3})/g;
        data = data.split(regex);
        data.shift();

        var items = [];
        for (var i = 0; i < data.length; i += 4) {
            items.push({
                id: data[i].trim(),
                startTime: useMs ? timeMs(data[i + 1].trim()) : data[i + 1].trim(),
                endTime: useMs ? timeMs(data[i + 2].trim()) : data[i + 2].trim(),
                text: data[i + 3].trim()
            });
        }

        return items;
    };

    /**
     * Converts Array of objects created by this module to SubRip subtitles
     * @param  {Array}  data
     * @return {String}      SubRip subtitles string
     */
    pItems.toSrt = function(data) {
        if (!data instanceof Array) return '';
        var res = '';

        for (var i in data) {
            var s = data[i];

            if (!isNaN(s.startTime) && !isNaN(s.endTime)) {
                s.startTime = msTime(parseInt(s.startTime, 10));
                s.endTime = msTime(parseInt(s.endTime, 10));
            }

            res += s.id + '\r\n';
            res += s.startTime + ' --> ' + s.endTime + '\r\n';
            res += s.text.replace('\n', '\r\n') + '\r\n\r\n';
        }

        return res;
    };

    var timeMs = function(val) {
        var regex = /([0-9]+):([0-9]{2}):([0-9]{2}),([0-9]{3})/;
        var parts = regex.exec(val);

        if (parts === null) {
            return 0;
        }

        for (var i = 1; i < 5; i++) {
            parts[i] = parseInt(parts[i], 10);
            if (isNaN(parts[i])) parts[i] = 0;
        }

        // hours + minutes + seconds + ms
        return parts[1] * 3600000 + parts[2] * 60000 + parts[3] * 1000 + parts[4];
    };

    var msTime = function(val) {
        var measures = [ 3600000, 60000, 1000 ];
        var time = [];

        for (var i in measures) {
            var res = (val / measures[i] >> 0).toString();

            if (res.length < 2) res = '0' + res;
            val %= measures[i];
            time.push(res);
        }

        var ms = val.toString();
        if (ms.length < 3) {
            for (i = 0; i <= 3 - ms.length; i++) ms = '0' + ms;
        }

        return time.join(':') + ',' + ms;
    };

    return pItems;
})();

// ignore exports for browser
if (typeof exports === 'object') {
    module.exports = parser;
}
<|endoftext|>


<commit_before>'use strict'

const express = require('express'),
  bodyParser = require('body-parser'),
  request = require('request'),
  Q = require('q'),
  app = express(),
  getBotHandler = require('./get-bot-handler.js').getBotHandler;

// should this just be declared in FB bot module?
const token = process.env.FB_PAGE_ACCESS_TOKEN
// is this even used?
// const GH_token = process.env.GH_API_ACCESS_TOKEN

// simple test bots
var hellobot = require('./hellobot.js'),
 dicebot = require('./dicebot.js');

var port = process.env.PORT || 3000;

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json())
app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(400).send(err.message);
});

// test route
app.get('/', function (req, res) { res.status(200).send('Hello world!') });

// hellobot - keep for testing
app.post('/hello', hellobot);
// dicebot - keep for testing
app.post('/roll', dicebot);

// for Facebook verification
app.get('/webhook/', function (req, res) {
    if (req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
        res.send(req.query['hub.challenge'])
    }
    res.send('Error, wrong token');
})

app.listen(port, function () {
  console.log('Fusion bot listening on port ' + port);
});

// ***************************************
// unified api endpoint
// ***********************

// -Temporarily using this endpoint, change to V3/ when Slack issue handled
app.post('/gethuman', handleRequest);
app.post('/v3/gethuman', handleRequest);

function handleRequest(req, res) {
// app.post('/v3/webhook', function (req, res) {
  // put data from the Express req object into our custom context object
  var platformRequestContext = {
    userRequest: req.body,
    disableSeparateResponse: !!req.params.istest
  };
  console.log("Platform request: " + JSON.stringify(platformRequestContext));
  // get a BotHandler object based on the context
  // should send an error if no appropriate bot found
  var botHandler = getBotHandler(platformRequestContext);

  botHandler.getResponsePayload(platformRequestContext)
    // this is an object that contains { raw: {}, data: {}, context: {} }
    .then(function (responsePayload) {
      console.log("About to send a message back to Client: " + JSON.stringify(responsePayload));

      // This sends a delayed response after the immediate 200 response
      // (default false, but true for Slack)
      if (platformRequestContext.disableSeparateResponse) {
        res.status(200).end();
        botHandler.sendResponseToPlatform(responsePayload);
      }
      else {
        res.send(responsePayload.raw);
      }

    })
    .catch(function (err) {
      console.error(err);
      // get response object that contains the thing you want to send to
      // the bot when an error occurs
      var errorPayload = botHandler.getErrorPayload(err, platformRequestContext);
      // this should log error and then call botHandler.sendResponseToPlatform()
      // under the scenes
      if (platformRequestContext.disableSeparateResponse) {
        res.status(200).end();
        botHandler.sendErrorResponse(errorPayload)
      }
      else {
        res.send(errorPayload.raw);
      }
    });
}
<commit_msg>Debug<commit_after>'use strict'

const express = require('express'),
  bodyParser = require('body-parser'),
  request = require('request'),
  Q = require('q'),
  app = express(),
  getBotHandler = require('./get-bot-handler.js').getBotHandler;

// should this just be declared in FB bot module?
const token = process.env.FB_PAGE_ACCESS_TOKEN
// is this even used?
// const GH_token = process.env.GH_API_ACCESS_TOKEN

// simple test bots
var hellobot = require('./hellobot.js'),
 dicebot = require('./dicebot.js');

var port = process.env.PORT || 3000;

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json())
app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(400).send(err.message);
});

// test route
app.get('/', function (req, res) { res.status(200).send('Hello world!') });

// hellobot - keep for testing
app.post('/hello', hellobot);
// dicebot - keep for testing
app.post('/roll', dicebot);

// for Facebook verification
app.get('/webhook/', function (req, res) {
    if (req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
        res.send(req.query['hub.challenge'])
    }
    res.send('Error, wrong token');
})

app.listen(port, function () {
  console.log('Fusion bot listening on port ' + port);
});

// ***************************************
// unified api endpoint
// ***********************

// -Temporarily using this endpoint, change to V3/ when Slack issue handled
// app.post('/gethuman', handleRequest);
app.post('/v3/gethuman', handleRequest);

function handleRequest(req, res) {
// app.post('/v3/webhook', function (req, res) {
  // put data from the Express req object into our custom context object
  var platformRequestContext = {
    userRequest: req.body,
    disableSeparateResponse: !!req.params.istest
  };
  console.log("Platform request: " + JSON.stringify(platformRequestContext));
  // get a BotHandler object based on the context
  // should send an error if no appropriate bot found
  var botHandler = getBotHandler(platformRequestContext);

  botHandler.getResponsePayload(platformRequestContext)
    // this is an object that contains { raw: {}, data: {}, context: {} }
    .then(function (responsePayload) {
      console.log("About to send a message back to Client: " + JSON.stringify(responsePayload));

      // This sends a delayed response after the immediate 200 response
      // (default false, but true for Slack)
      if (platformRequestContext.disableSeparateResponse) {
        res.status(200).end();
        botHandler.sendResponseToPlatform(responsePayload);
      }
      else {
        res.send(responsePayload.raw);
      }

    })
    .catch(function (err) {
      console.error(err);
      // get response object that contains the thing you want to send to
      // the bot when an error occurs
      var errorPayload = botHandler.getErrorPayload(err, platformRequestContext);
      // this should log error and then call botHandler.sendResponseToPlatform()
      // under the scenes
      if (platformRequestContext.disableSeparateResponse) {
        res.status(200).end();
        botHandler.sendErrorResponse(errorPayload)
      }
      else {
        res.send(errorPayload.raw);
      }
    });
}
<|endoftext|>


<commit_before>/**
 * Copyright 2015 Solinea, Inc.
 *
 * Licensed under the Solinea Software License Agreement (goldstone),
 * Version 1.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *     http://www.solinea.com/goldstone/LICENSE.pdf
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
This view will be re-invoked upon every page refresh or redirect, as it is
baked into base.html.

After ajaxSend Listener is bound to $(document), it will be triggered on all
subsequent $.ajaxSend calls.

Uses xhr.setRequestHeader to append the Auth token on all subsequent api calls.
It also serves to handle 401 auth
errors, removing any existing token, and redirecting to the login page.

The logout icon will only be rendered in the top-right corner of the page if
there is a truthy value present in localStorage.userToken
*/

var LogoutIcon = Backbone.View.extend({

    initialize: function(options) {
        this.options = options || {};
        this.defaults = _.clone(this.defaults);
        this.el = options.el;

        // if auth token present, hijack all subsequent ajax requests
        // with an auth header containing the locally stored token
        this.setAJAXSendRequestHeaderParams();

        // only render the logout button if an auth token is present
        this.renderIfTokenPresent();

        // clicking logout button > expire token via /accounts/logout
        // then clear token from localStorage and redirect to /login
        this.setLogoutButtonHandler();
    },

    setAJAXSendRequestHeaderParams: function() {
        var self = this;

        // if there is no userToken present in localStorage, don't append the
        // request header to api calls or it will append null
        // which will create a server error

        var $doc = $(document);
        $doc.ajaxSend(function(event, xhr) {
            var authToken = localStorage.getItem('userToken');
            if (authToken) {
                xhr.setRequestHeader("Authorization", "Token " +
                    authToken);
            }
        });

        // all 401 errors will cause a deletion of existing userToken and
        // redirect to /login with the hash appened to the url
        $doc.ajaxError(function(event, xhr) {
            if (xhr.status === 401) {
                localStorage.removeItem('userToken');
                self.redirectToLogin();
            }
        });
    },

    renderIfTokenPresent: function() {

        // only render logout icon if there is a token present
        var authToken = localStorage.getItem('userToken');
        if (authToken) {
            this.render();
        }
    },

    setLogoutButtonHandler: function() {
        var self = this;
        $('div.logout-icon-container .fa-sign-out').on('click', function() {

            // clicking logout button => submit userToken to
            // remove userToken. Upon success, remove token
            // and redirect to /login

            $.post('/accounts/logout')
                .done(function() {})
                .fail(function() {})
                .always(function() {
                    self.clearToken();
                    self.redirectToLogin();
                });
        });
    },

    clearToken: function() {
        localStorage.removeItem('userToken');
    },

    redirectToLogin: function() {
        location.href = "#/login";
    },

    render: function() {
        this.$el.html(this.template());
        return this;
    },

    template: _.template('' +
        ''
    )

});
<commit_msg>Render authLogoutView immediately, but show/hide with css via conditional check for auth token.<commit_after>/**
 * Copyright 2015 Solinea, Inc.
 *
 * Licensed under the Solinea Software License Agreement (goldstone),
 * Version 1.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *     http://www.solinea.com/goldstone/LICENSE.pdf
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
This view will be re-invoked upon every page refresh or redirect, as it is
baked into base.html.

After ajaxSend Listener is bound to $(document), it will be triggered on all
subsequent $.ajaxSend calls.

Uses xhr.setRequestHeader to append the Auth token on all subsequent api calls.
It also serves to handle 401 auth
errors, removing any existing token, and redirecting to the login page.

The logout icon will only be rendered in the top-right corner of the page if
there is a truthy value present in localStorage.userToken
*/

var LogoutIcon = GoldstoneBaseView.extend({

    initialize: function(options) {
        this.options = options || {};
        this.defaults = _.clone(this.defaults);
        this.el = options.el;
        this.render();
        // if auth token present, hijack all subsequent ajax requests
        // with an auth header containing the locally stored token
        this.setAJAXSendRequestHeaderParams();

        // only render the logout button if an auth token is present
        this.makeVisibleIfTokenPresent();

        // clicking logout button > expire token via /accounts/logout
        // then clear token from localStorage and redirect to /login
        this.setLogoutButtonHandler();
    },

    viewSwitchTriggered: function() {
        this.makeVisibleIfTokenPresent();
    },

    setAJAXSendRequestHeaderParams: function() {
        var self = this;

        // if there is no userToken present in localStorage, don't append the
        // request header to api calls or it will append null
        // which will create a server error

        var $doc = $(document);
        $doc.ajaxSend(function(event, xhr) {
            var authToken = localStorage.getItem('userToken');
            if (authToken) {
                xhr.setRequestHeader("Authorization", "Token " +
                    authToken);
            }
        });

        // all 401 errors will cause a deletion of existing userToken and
        // redirect to /login with the hash appened to the url
        $doc.ajaxError(function(event, xhr) {
            if (xhr.status === 401) {
                self.clearToken();
                self.redirectToLogin();
            }
        });
    },

    makeVisibleIfTokenPresent: function() {

        // only render logout icon if there is a token present
        var authToken = localStorage.getItem('userToken');
        if (authToken) {
            $('.fa-sign-out').css('visibility', 'visible');
        } else {
            $('.fa-sign-out').css('visibility', 'hidden');
        }
    },

    setLogoutButtonHandler: function() {
        var self = this;
        $('div.logout-icon-container .fa-sign-out').on('click', function() {

            // clicking logout button => submit userToken to
            // remove userToken. Upon success, remove token
            // and redirect to /login
            // if failed, raise alert and don't redirect

            $.post('/accounts/logout')
                .done(function() {
                    goldstone.raiseSuccess('Logout Successful');
                    self.clearToken();
                    self.makeVisibleIfTokenPresent();
                    self.redirectToLogin();
                })
                .fail(function() {
                    goldstone.raiseWarning('Logout Failed');
                    self.makeVisibleIfTokenPresent();
                });
        });
    },

    clearToken: function() {
        localStorage.removeItem('userToken');
    },

    redirectToLogin: function() {
        location.href = "#/login";
    },

    render: function() {
        this.$el.html(this.template());
        return this;
    },

    template: _.template('' +
        ''
    )

});
<|endoftext|>


<commit_before>"use strict"
var readYaml = require('read-yaml'), extend = require('extend');

var socketio = require('socket.io');
var mdns = require('mdns');
var debug = require('debug')('koala-puree')
var Emitter = require('events').EventEmitter;

class Puree extends Emitter {
	constructor(mod, config) {
		var pkginfo = require('pkginfo')(mod);

		if (!(this instanceof Puree)) return new Puree(mod, config);
		debug(`pwd is ${require('path').resolve('.')}`)
		config = config || "./config/server.yml";

		var app = this._app = require('koala')();
		//modify koa-trie-router to allow namespace stripping
		app.use(require('koa-views')('./views', {
		  map: {
		    dust: 'dust'
		  }
		}));
		app.use(require('koa-trie-router')(app));
		var self = this;
		var router = require('koa-trie-router')(app);
		router._oldmatch = router.match;
		router.match = function(str){
			// console.log(str);
			return str.indexOf(self._ns)===0 ? router._oldmatch.call(router,str.substring(self._ns.length)) : false;
		}
		app.use(function*(next){
			this.models = self.models;
			yield next;
		});
		app.use(router);
		app.puree = this;
		this._config = extend(Puree.DEFAULTCONFIG, readYaml.sync(config)[app.env]);
		this._config.name = pkginfo.name
		this._config.version = pkginfo.version;
		this._pkginfo = pkginfo;
		this.use(require('./lib/models.js'))
		this.use(require('./lib/controllers.js'));
		this.use(require('./lib/sio.js'));
		this.use(require('./lib/mdns.js'));
		this.use(require('./lib/service.js').middleware);
	}
	get app() { return this._app; }
	get sio() { return this._sio; }
	set namespace(ns) { this._ns = ns; this.emit('namespace', ns);}
	get namespace() { return this._ns; }
	get middleware() { return this._middleware; }
	use(mw){
		this._middleware = this._middleware || [];
		debug("adding middleware");
		this._middleware.push(mw());
	}
	//* app could be a http server or another koala-puree app
	start(app) {
		var self = this;
		// if ( app instanceof Puree ) {
			// self = app.partition(this);
		// }
		return new Promise(function(resolve, reject){
			var server = self._server = self._app.listen(self._config.port, "::");
			server.once('listening', function(){

				debug(`middleware setups`);
				var setups = self._middleware.map(function(el){
					return el.setup ? el.setup(self) : true;
				})
				Promise.all(setups).then(function(){
					resolve(self);
				}, reject);

			})
		});

	}
	close(){
		debug("closing service...")
		var self = this;
		return new Promise(function(resolve, reject){
			self._server.close();
			self._server.on('close', function(err){
				debug(`server has closed, beginning of the end`);
				if ( err ) { debug(`server temination failed with ${err}`); return reject(err); }
				debug(`server closed`);
				resolve();
			})
			var setups = self._middleware.map(function(el){
				return el.teardown ? el.teardown(self) : Promise.resolve(true);
			})
			Promise.all(setups).then(function(){
				debug(`middleware teardown completed, closing server`);
				// self._server.close();
			}, reject);
		});
	}
};

Puree.DEFAULTCONFIG = {
	port: 3000,
	host: "0.0.0.0"
}
Puree.Spices = {
	Service: require('./lib/service').Service,
	Browser: require('./lib/service').Browser,
	Crypt: require('./lib/crypt')
}
exports = module.exports = Puree;

<commit_msg>using local path<commit_after>"use strict"
var readYaml = require('read-yaml'), extend = require('extend');

var socketio = require('socket.io');
var mdns = require('mdns');
var debug = require('debug')('koala-puree')
var Emitter = require('events').EventEmitter;

class Puree extends Emitter {
	constructor(mod, config) {
		var pkginfo = require('pkginfo')(mod);

		if (!(this instanceof Puree)) return new Puree(mod, config);
		debug(`pwd is ${require('path').resolve('.')}`)
		config = config || "./config/server.yml";

		var app = this._app = require('koala')();
		//modify koa-trie-router to allow namespace stripping
		app.use(require('koa-views')(require('path').resolve('./views'), {
		  map: {
		    dust: 'dust'
		  }
		}));
		app.use(require('koa-trie-router')(app));
		var self = this;
		var router = require('koa-trie-router')(app);
		router._oldmatch = router.match;
		router.match = function(str){
			// console.log(str);
			return str.indexOf(self._ns)===0 ? router._oldmatch.call(router,str.substring(self._ns.length)) : false;
		}
		app.use(function*(next){
			this.models = self.models;
			yield next;
		});
		app.use(router);
		app.puree = this;
		this._config = extend(Puree.DEFAULTCONFIG, readYaml.sync(config)[app.env]);
		this._config.name = pkginfo.name
		this._config.version = pkginfo.version;
		this._pkginfo = pkginfo;
		this.use(require('./lib/models.js'))
		this.use(require('./lib/controllers.js'));
		this.use(require('./lib/sio.js'));
		this.use(require('./lib/mdns.js'));
		this.use(require('./lib/service.js').middleware);
	}
	get app() { return this._app; }
	get sio() { return this._sio; }
	set namespace(ns) { this._ns = ns; this.emit('namespace', ns);}
	get namespace() { return this._ns; }
	get middleware() { return this._middleware; }
	use(mw){
		this._middleware = this._middleware || [];
		debug("adding middleware");
		this._middleware.push(mw());
	}
	//* app could be a http server or another koala-puree app
	start(app) {
		var self = this;
		// if ( app instanceof Puree ) {
			// self = app.partition(this);
		// }
		return new Promise(function(resolve, reject){
			var server = self._server = self._app.listen(self._config.port, "::");
			server.once('listening', function(){

				debug(`middleware setups`);
				var setups = self._middleware.map(function(el){
					return el.setup ? el.setup(self) : true;
				})
				Promise.all(setups).then(function(){
					resolve(self);
				}, reject);

			})
		});

	}
	close(){
		debug("closing service...")
		var self = this;
		return new Promise(function(resolve, reject){
			self._server.close();
			self._server.on('close', function(err){
				debug(`server has closed, beginning of the end`);
				if ( err ) { debug(`server temination failed with ${err}`); return reject(err); }
				debug(`server closed`);
				resolve();
			})
			var setups = self._middleware.map(function(el){
				return el.teardown ? el.teardown(self) : Promise.resolve(true);
			})
			Promise.all(setups).then(function(){
				debug(`middleware teardown completed, closing server`);
				// self._server.close();
			}, reject);
		});
	}
};

Puree.DEFAULTCONFIG = {
	port: 3000,
	host: "0.0.0.0"
}
Puree.Spices = {
	Service: require('./lib/service').Service,
	Browser: require('./lib/service').Browser,
	Crypt: require('./lib/crypt')
}
exports = module.exports = Puree;

<|endoftext|>


<commit_before>import AWS from 'aws-sdk';
import request from 'request';
import ical from 'ical/ical';
import regeneratorRuntime from "regenerator-runtime";
import pp from 'ypp';
import qs from 'qs';
import 'core-js/modules/es6.reflect.own-keys';
import { Dial, Say, Sms, Play, default as twiml } from 'twiml-builder';
import moment from 'moment-timezone';
import 'moment-range';

const forwardNumber         = process.env.FORWARD_NUMBER || "0000000000";
const callerId              = process.env.CALLER_ID || "0000000000";
const dtmf6URL              = "https://cdn.yolk.cc/DTMF-6.mp3";
const startHour             = process.env.SCHEDULE_AUTO_START_HOUR || 0;
const startMinute           = process.env.SCHEDULE_AUTO_START_MINUTE || 0;
const startSeconds          = 0;
const endHour               = process.env.SCHEDULE_AUTO_END_HOUR || 0;
const endMinute             = process.env.SCHEDULE_AUTO_END_MINUTE || 0;
const endSeconds            = 0;
const scheduleTZ            = process.env.SCHEDULE_TIME_ZONE || 'America/Chicago';
const accessStart           = moment().tz(scheduleTZ).hours(startHour).minutes(startMinute).seconds(startSeconds);
const accessEnd             = moment().tz(scheduleTZ).hours(endHour).minutes(endMinute).seconds(endSeconds);
const greeting              = process.env.GREETING || `Hello! One moment while I call YOLK!`;
const accessGreeting        = process.env.SCHEDULE_GREETING || `Hello, YOLK!`;
const dynamo                = new AWS.DynamoDB.DocumentClient();
const tableName             = process.env.TABLE_NAME || null;
const configTableName       = process.env.CONFIG_TABLE_NAME || null;
const doorAccessCalendarURL = process.env.DOOR_ACCESS_CALENDAR_URL || null;

const DEFAULT_CONFIG  = {
  "someSetting": 'someValue',
  "updatedAt": moment().format(),
  "someInsideVar": dtmf6URL
};

function getConfig() {
  if (!configTableName) {
    return null;
  }
  let params = {
    TableName: configTableName,
    Key: {
      id: 'settings'
    }
  };

  return dynamo.get(params).promise()
  .then((data) => {
    console.log('getitems data is ', pp(data));
    try {
      if (!data || !data.Item.config) {
        return null;
      }
      console.log(`RETRIEVED ITEM SUCCESSFULLY WITH doc = ${pp(data.Item)}`);
      return data.Item.config;
    } catch (e) {
      return null;
    }
  }).catch( (err) => {
    console.log(`GET ITEM FAILED FOR doc = ${data.Item}, WITH ERROR: ${err}`);
    //bubble up, unexpected error
    throw(err);
  });
}

function setConfig(config) {
  if (!configTableName) {
    throw(new Error('no config table set'));
  }
  if (!config) {
    //no config yet, make it
    config = DEFAULT_CONFIG;
  }
  let item = {
    id: 'settings',
    config
  };
  let params = {
    TableName: configTableName,
    Item: item
  };
  return dynamo.put(params).promise()
    .then((data) => {
      console.log('data in setConfigs put is', pp(data));
      console.log(`Put suceeded with item of ${pp(data.Item)}`);
      // return data.Item.config;
      return config;
    }).catch((err) => {
      console.log(`PUT ITEM FAILED FOR doc = ${pp(item)}, WITH ERROR: ${err}`);
      //bubble up, unexpected error
      throw(err);
    });
}

function checkConfig() {
  let config = {};
  async function configCheck() {
    try {
      config = await getConfig();
    } catch (e) {
      // theres no config set
      console.log('error during checkConfig!', e);
    } finally {
      if (config) {
        return true;
      }
      //fail safely, skip - config is not set, but table exists
      return false;
    }
  }
  return configCheck();
}

function checkDoorAccessCalendar() {
  if(doorAccessCalendarURL === null) {
    throw(new Error('Trying to check calendar without a URL set!'));
  }
  function getCalendar() {
    return new Promise(function(resolve, reject){
      request({
        method: 'GET',
        url: doorAccessCalendarURL,
        json: true,
        headers: {
          'User-Agent': 'request'
        }
      }, function(err, resp, body){
        if(err){
          reject(err);
        } else {
          resolve(body);
        }
      });
    });
  }
  return getCalendar().then((data) => {
    // console.log('data is', data);
    // console.log('ical parsed is', pp(ical.parseICS(data)));
    let ranges = [];
    let accessAllowed = false;
    data = ical.parseICS(data);
    for (var k in data) {
      if (data.hasOwnProperty(k) && data[k].type == "VEVENT") {
        let ev = data[k];
        // console.log('ev is', pp(ev));
        let range = moment.range(ev.start, ev.end)
        // console.log('range is', range.toString());
        if (moment().within(range)) {
          accessAllowed = {
            start: range.start,
            end: range.end,
            summary: ev.summary,
            description: ev.description
          };
        }
        ranges.push(range);
      }
    }
    return accessAllowed;
  });
}

async function checkSchedule() {
  //this will be more complex later...
  if (moment().isBetween(accessStart, accessEnd)) {
    return {
      start: accessStart,
      end: accessEnd,
      summary: 'auto-access',
      description: 'Daily auto-access override'
    };
  }
  else {
    let calendarDoorAcess = await checkDoorAccessCalendar();
    if (calendarDoorAcess) {
      return calendarDoorAcess;
    }
    return false;
  }
}

//handle recording url callabcks
// if (event.path === '/recording') {
//
// }
function handleRecording(event, context, callback) {
  console.log('handling recording');
  let twilioRequest = qs.parse(event.body);
  if (twilioRequest.RecordingStatus === 'completed') {
    let recordingUrl = twilioRequest.RecordingUrl;
    let callSid      = twilioRequest.CallSid;
    let item = {
      id: callSid,
      createdAt: moment().format(),
      recordingUrl,
      rawRequest: twilioRequest
    };
    let params = {
      TableName: tableName,
      Item: item
    };
    console.log(`Recording URL: ${recordingUrl}`);
    return dynamo.put(params).promise()
      .then((data) => {
        console.log(`Put suceeded with item of ${pp(item)}`);
        callback(null, {
          statusCode: 200,
          body: twiml(Sms({to: forwardNumber, from: callerId}, 'testing worked')),
          headers: {
            'Content-Type': 'application/xml'
          }
        });
      }).catch((err) => {
        console.log(`PUT ITEM FAILED FOR doc = ${pp(item)}, WITH ERROR: ${err}`);
        callback(null, {statusCode: 500, body:pp(err)});
      });
  }
}
export function recording(event, context, callback) {
  handleRecording(event, context, callback);
}

//handle sms
// if (event.path === '/sms') {
//
// }
export function sms(event, context, callback) {

}

// async function init() {
//   //TODO: move init here
//   //let config = (await checkConfig()) ? await getConfig() : await setConfig(null);
// }

export async function handler(event, context, callback) {
  console.log('event is', pp(event));
  console.log('context is', pp(context));

  //check config, if it doesn't exist set it to default (first boot, reset)
  let config = (await checkConfig()) ? await getConfig() : await setConfig(null);
  console.log('config is', pp(config));
  context.appConfig = config;

  if (event.path === '/recording') {
    return handleRecording(event, context, callback);
  }

  let body        = '';
  let smsTemplate = '';
  let schedule    = await checkSchedule();

  if (schedule) {
    let tt      = "hh:mma";
    let nott    = moment().tz(scheduleTZ).format(tt);
    let sttt    = schedule.start.format(tt);
    let entt    = schedule.end.format(tt);
    let summary = schedule.summary ? schedule.summary : 'Unknown';
    smsTemplate = `Access granted for front door at ${nott}, based on "${summary}" with a schedule of ${sttt}-${entt}`;

    body = twiml(
      Say({voice: 'man'}, accessGreeting),
      Sms({to: forwardNumber, from: callerId}, smsTemplate),
      Play({loop: 0}, dtmf6URL)
    );
  }
  else {
    body = twiml(
      Say({voice: 'man'}, greeting),
      Dial({callerId, timeout: 10, record: 'record-from-answer', recordingStatusCallback:'/Prod/recording'}, forwardNumber),
      // Hangup(),
      // Message('testing')
      // Redirect()
    );
  }
  //we know what's returning but this is good for debugging
  console.log('returning', pp(body));
  callback(null, {
    statusCode: '200',
    body,
    headers: {
      'Content-Type': 'application/xml'
    }
  });
}
<commit_msg>refactor imports order<commit_after>import AWS from 'aws-sdk';
import regeneratorRuntime from "regenerator-runtime";
import pp from 'ypp';
import request from 'request';
import ical from 'ical/ical';
import qs from 'qs';
import moment from 'moment-timezone';
import 'moment-range';
import 'core-js/modules/es6.reflect.own-keys';
import { Dial, Say, Sms, Play, default as twiml } from 'twiml-builder';

const forwardNumber         = process.env.FORWARD_NUMBER || "0000000000";
const callerId              = process.env.CALLER_ID || "0000000000";
const dtmf6URL              = "https://cdn.yolk.cc/DTMF-6.mp3";
const startHour             = process.env.SCHEDULE_AUTO_START_HOUR || 0;
const startMinute           = process.env.SCHEDULE_AUTO_START_MINUTE || 0;
const startSeconds          = 0;
const endHour               = process.env.SCHEDULE_AUTO_END_HOUR || 0;
const endMinute             = process.env.SCHEDULE_AUTO_END_MINUTE || 0;
const endSeconds            = 0;
const scheduleTZ            = process.env.SCHEDULE_TIME_ZONE || 'America/Chicago';
const accessStart           = moment().tz(scheduleTZ).hours(startHour).minutes(startMinute).seconds(startSeconds);
const accessEnd             = moment().tz(scheduleTZ).hours(endHour).minutes(endMinute).seconds(endSeconds);
const greeting              = process.env.GREETING || `Hello! One moment while I call YOLK!`;
const accessGreeting        = process.env.SCHEDULE_GREETING || `Hello, YOLK!`;
const dynamo                = new AWS.DynamoDB.DocumentClient();
const tableName             = process.env.TABLE_NAME || null;
const configTableName       = process.env.CONFIG_TABLE_NAME || null;
const doorAccessCalendarURL = process.env.DOOR_ACCESS_CALENDAR_URL || null;

const DEFAULT_CONFIG  = {
  "someSetting": 'someValue',
  "updatedAt": moment().format(),
  "someInsideVar": dtmf6URL
};

function getConfig() {
  if (!configTableName) {
    return null;
  }
  let params = {
    TableName: configTableName,
    Key: {
      id: 'settings'
    }
  };

  return dynamo.get(params).promise()
  .then((data) => {
    console.log('getitems data is ', pp(data));
    try {
      if (!data || !data.Item.config) {
        return null;
      }
      console.log(`RETRIEVED ITEM SUCCESSFULLY WITH doc = ${pp(data.Item)}`);
      return data.Item.config;
    } catch (e) {
      return null;
    }
  }).catch( (err) => {
    console.log(`GET ITEM FAILED FOR doc = ${data.Item}, WITH ERROR: ${err}`);
    //bubble up, unexpected error
    throw(err);
  });
}

function setConfig(config) {
  if (!configTableName) {
    throw(new Error('no config table set'));
  }
  if (!config) {
    //no config yet, make it
    config = DEFAULT_CONFIG;
  }
  let item = {
    id: 'settings',
    config
  };
  let params = {
    TableName: configTableName,
    Item: item
  };
  return dynamo.put(params).promise()
    .then((data) => {
      console.log('data in setConfigs put is', pp(data));
      console.log(`Put suceeded with item of ${pp(data.Item)}`);
      // return data.Item.config;
      return config;
    }).catch((err) => {
      console.log(`PUT ITEM FAILED FOR doc = ${pp(item)}, WITH ERROR: ${err}`);
      //bubble up, unexpected error
      throw(err);
    });
}

function checkConfig() {
  let config = {};
  async function configCheck() {
    try {
      config = await getConfig();
    } catch (e) {
      // theres no config set
      console.log('error during checkConfig!', e);
    } finally {
      if (config) {
        return true;
      }
      //fail safely, skip - config is not set, but table exists
      return false;
    }
  }
  return configCheck();
}

function checkDoorAccessCalendar() {
  if(doorAccessCalendarURL === null) {
    throw(new Error('Trying to check calendar without a URL set!'));
  }
  function getCalendar() {
    return new Promise(function(resolve, reject){
      request({
        method: 'GET',
        url: doorAccessCalendarURL,
        json: true,
        headers: {
          'User-Agent': 'request'
        }
      }, function(err, resp, body){
        if(err){
          reject(err);
        } else {
          resolve(body);
        }
      });
    });
  }
  return getCalendar().then((data) => {
    // console.log('data is', data);
    // console.log('ical parsed is', pp(ical.parseICS(data)));
    let ranges = [];
    let accessAllowed = false;
    data = ical.parseICS(data);
    for (var k in data) {
      if (data.hasOwnProperty(k) && data[k].type == "VEVENT") {
        let ev = data[k];
        // console.log('ev is', pp(ev));
        let range = moment.range(ev.start, ev.end)
        // console.log('range is', range.toString());
        if (moment().within(range)) {
          accessAllowed = {
            start: range.start,
            end: range.end,
            summary: ev.summary,
            description: ev.description
          };
        }
        ranges.push(range);
      }
    }
    return accessAllowed;
  });
}

async function checkSchedule() {
  //this will be more complex later...
  if (moment().isBetween(accessStart, accessEnd)) {
    return {
      start: accessStart,
      end: accessEnd,
      summary: 'auto-access',
      description: 'Daily auto-access override'
    };
  }
  else {
    let calendarDoorAcess = await checkDoorAccessCalendar();
    if (calendarDoorAcess) {
      return calendarDoorAcess;
    }
    return false;
  }
}

//handle recording url callabcks
// if (event.path === '/recording') {
//
// }
function handleRecording(event, context, callback) {
  console.log('handling recording');
  let twilioRequest = qs.parse(event.body);
  if (twilioRequest.RecordingStatus === 'completed') {
    let recordingUrl = twilioRequest.RecordingUrl;
    let callSid      = twilioRequest.CallSid;
    let item = {
      id: callSid,
      createdAt: moment().format(),
      recordingUrl,
      rawRequest: twilioRequest
    };
    let params = {
      TableName: tableName,
      Item: item
    };
    console.log(`Recording URL: ${recordingUrl}`);
    return dynamo.put(params).promise()
      .then((data) => {
        console.log(`Put suceeded with item of ${pp(item)}`);
        callback(null, {
          statusCode: 200,
          body: twiml(Sms({to: forwardNumber, from: callerId}, 'testing worked')),
          headers: {
            'Content-Type': 'application/xml'
          }
        });
      }).catch((err) => {
        console.log(`PUT ITEM FAILED FOR doc = ${pp(item)}, WITH ERROR: ${err}`);
        callback(null, {statusCode: 500, body:pp(err)});
      });
  }
}
export function recording(event, context, callback) {
  handleRecording(event, context, callback);
}

//handle sms
// if (event.path === '/sms') {
//
// }
export function sms(event, context, callback) {

}

// async function init() {
//   //TODO: move init here
//   //let config = (await checkConfig()) ? await getConfig() : await setConfig(null);
// }

export async function handler(event, context, callback) {
  console.log('event is', pp(event));
  console.log('context is', pp(context));

  //check config, if it doesn't exist set it to default (first boot, reset)
  let config = (await checkConfig()) ? await getConfig() : await setConfig(null);
  console.log('config is', pp(config));
  context.appConfig = config;

  if (event.path === '/recording') {
    return handleRecording(event, context, callback);
  }

  let body        = '';
  let smsTemplate = '';
  let schedule    = await checkSchedule();

  if (schedule) {
    let tt      = "hh:mma";
    let nott    = moment().tz(scheduleTZ).format(tt);
    let sttt    = schedule.start.format(tt);
    let entt    = schedule.end.format(tt);
    let summary = schedule.summary ? schedule.summary : 'Unknown';
    smsTemplate = `Access granted for front door at ${nott}, based on "${summary}" with a schedule of ${sttt}-${entt}`;

    body = twiml(
      Say({voice: 'man'}, accessGreeting),
      Sms({to: forwardNumber, from: callerId}, smsTemplate),
      Play({loop: 0}, dtmf6URL)
    );
  }
  else {
    body = twiml(
      Say({voice: 'man'}, greeting),
      Dial({callerId, timeout: 10, record: 'record-from-answer', recordingStatusCallback:'/Prod/recording'}, forwardNumber),
      // Hangup(),
      // Message('testing')
      // Redirect()
    );
  }
  //we know what's returning but this is good for debugging
  console.log('returning', pp(body));
  callback(null, {
    statusCode: '200',
    body,
    headers: {
      'Content-Type': 'application/xml'
    }
  });
}
<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc directive
 * @name spGuiApp.directive:relationident
 * @description
 * # relationident
 */
angular.module('spGuiApp')
  .directive('relationident', ['spTalker', function (spTalker) {
    return {
      templateUrl: 'views/relationview.html',
      restrict: 'E',
      link: function postLink(scope, element, attrs) {

          scope.findrelations = function(){

            var ops = [];
            _.each(spTalker.items, function(value, key){
              if (value.isa == "Operation") ops.push(key)
            })

            var svs = [];
            _.each(spTalker.items, function(value, key){
              if (value.isa == "Thing") {
                svs.push({id: key, value: false })
                // allow for user to set initstate instead of this
                _.each(value.stateVariables, function(sv){
                  svs.push({id: sv.id, value: false })
                })
              }
            })

            var res = spTalker.findRelations(ops, svs)
            res.success(function (data, status, headers, config) {
              scope.relations = data.relationmap.relationmap.map(function(item){
                return item.sop
              })
            })

          }

        scope.relations = [];

        scope.getOpsFromSOP = function(sop) {
          var o1 = scope.getOp(sop.sop[0].operation)
          var o2 = scope.getOp(sop.sop[1].operation)
          return o1.name + "->" + o2.name
        }

        scope.getOp = function(id) {
          return spTalker.getItemById(id)
        }

      }
    };
  }]);
<commit_msg>Initstate for relation identification<commit_after>'use strict';

/**
 * @ngdoc directive
 * @name spGuiApp.directive:relationident
 * @description
 * # relationident
 */
angular.module('spGuiApp')
  .directive('relationident', ['spTalker', function (spTalker) {
    return {
      templateUrl: 'views/relationview.html',
      restrict: 'E',
      link: function postLink(scope, element, attrs) {

          scope.findrelations = function(){

            var ops = [];
            _.each(spTalker.items, function(value, key){
              if (value.isa == "Operation") ops.push(key)
            })

            var svs = [];
            _.each(spTalker.items, function(value, key){
              if (value.isa == "Thing") {
                svs.push({id: key, value: false })
                // allow for user to set initstate instead of this
                _.each(value.stateVariables, function(sv){
                  var initValue = false
                  if (!_.isUndefined(id.init)) initValue = id.init;
                  svs.push({id: sv.id, value: initValue })
                })
              }
            })

            var res = spTalker.findRelations(ops, svs)
            res.success(function (data, status, headers, config) {
              scope.relations = data.relationmap.relationmap.map(function(item){
                return item.sop
              })
            })

          }

        scope.relations = [];

        scope.getOpsFromSOP = function(sop) {
          var o1 = scope.getOp(sop.sop[0].operation)
          var o2 = scope.getOp(sop.sop[1].operation)
          return o1.name + "->" + o2.name
        }

        scope.getOp = function(id) {
          return spTalker.getItemById(id)
        }

      }
    };
  }]);
<|endoftext|>


<commit_before>// Registration
$registrationSection = $('.registration-section'),
$confirmationSection = $('.confirmation-section'),
$registerForm = $('.form.registration'),
eventCode = $('#event-code').text().toLowerCase(),
eventTitle = $('#event-name').text(), // Stripe description
eventStartDate = $('#event-start').text(),
eventDates = $('#event-dates').text(),
eventVenue = $('#event-venue').text(),
eventDepositAmount = $('#event-deposit-amount').text(),
eventDepositDate = $('#event-deposit-date').text(),
eventLodgingOptions = $('#event-lodging-options').text(),
eventLodgingPrices = $('#event-lodging-prices').text(),
eventStripe = $('#event-stripe').text()

// Event initialization
const eventButton = '.button.pay',
eventFirstName = '#event-firstname',
eventLastName = '#event-lastname',
eventEmail = '#event-email',
eventMobile = '#event-mobile',
eventBirthdate = '#event-birthdate',
eventFemale = '#event-gender-female',
eventMale = '#event-gender-male',
eventOther = '#event-gender-other',
eventReferral = '#event-referral',
eventExperienceContainer = '.event-container.experience',
eventExperienceYes = '#event-experience-yes',
eventExperienceNo = '#event-experience-no',
eventExperienceDetails = '#event-experience-details',
eventDietContainer = '.event-container.diet',
eventDietYes = '#event-diet-yes',
eventDietNo = '#event-diet-no',
eventDietDetails = '#event-diet-details'
eventStatus = '#event-status',
eventPartnerContainer = '.event-container.partner',
eventPartnerName = '#event-partner-name'
eventPartnerFemale = '#event-partner-gender-female',
eventPartnerMale = '#event-partner-gender-male',
eventPartnerOther = '#event-partner-gender-other',
eventPayBoth = '#event-pay-both',
eventPayMe = '#event-pay-me',
eventLodging = '#event-lodging',
eventDepositContainer = '.event-container.deposit',
eventDepositText = '#event-deposit-text',
eventDepositFull = '#event-deposit-full',
eventDepositDeposit = '#event-deposit-deposit',
eventTerms = '#event-terms'

// SAVE FORM
function saveEvent() {
	var values = {};
	$('input, textarea, select').each(function() {
		if ($(this).is(':radio')) {
			if ($(this).is(':checked')) { values[$(this).attr('name')] = $(this).val() }
		}
		else {
			values[$(this).attr('name')] = $(this).val()
		}
	})
	localStorage.setItem('EcstaticLiving:Event', JSON.stringify(values))
}

// REPOPULATE SAVED FORM
function repopulateEvent() {
	if (localStorage.getItem('EcstaticLiving:Event')) {
		var values = JSON.parse(localStorage.getItem('EcstaticLiving:Event'))
		for (var item in values) {
			if ($('*[name=' + item + ']').is(':radio')) {
				$('input[name=' + item + '][value="' + values[item] + '"]').prop('checked', true)
			}
			else {
				$('*[name=' + item + ']').val(values[item])
			}
		}
		localStorage.removeItem('EcstaticLiving:Event')
	}
}

// PARTICIPANTS
function participants() {
	if (($(eventStatus).find('option:selected').val() === 'Couple') || ($(eventStatus).find('option:selected').val() === 'Two Singles (paired)')) {
		return 2
	} else if ($(eventStatus).find('option:selected').val() === 'Single') {
		return 1
	}
}

// FORM VALIDATION
function validationPersonal() {
	if ($(eventFirstName).val() !== '' && $(eventLastName).val() !== '' && $(eventEmail).val() !== '' && $(eventMobile).val() !== '' && $(eventBirthdate).val() !== '' &&
		($(eventFemale).is(':checked') || $(eventMale).is(':checked') || $(eventOther).is(':checked'))) {
		return true
	}
	return false
}
function validationDetails() {
	if ($(eventReferral).val() !== ''
		&& (($(eventExperienceYes).is(':checked') && $(eventExperienceDetails).val() !== '') || $(eventExperienceNo).is(':checked'))
		&& (($(eventDietYes).is(':checked') && $(eventDietDetails).val() !== '') || $(eventDietNo).is(':checked'))) {
		return true
	}
	return false
}
function validationStatus() {
	if (
		(participants() === 2
			&& $(eventPartnerName).val() !== ''
			&& ($(eventPartnerFemale).is(':checked') || $(eventPartnerMale).is(':checked') || $(eventPartnerOther).is(':checked'))
			&& ($(eventPayBoth).is(':checked') || $(eventPayMe).is(':checked')))
		|| participants() === 1
	) {
		return true
	}
	return false
}
function validationLodging() {
	if ($(eventLodging).val() !== '' && (
		$(eventDepositContainer).is(':visible') && ($(eventDepositFull).is(':checked') || $(eventDepositDeposit).is(':checked'))
	) || $(eventDepositContainer).is(':hidden')) {
		return true
	}
	return false
}
function eventValidation() {
	if (validationPersonal() && validationDetails() && validationStatus() && validationLodging() && $(eventTerms).is(':checked')) {
		console.log('*** VALID ***');
		document.getElementById('register-button').disabled = false
		$(eventButton).css({' background-image': 'linear-gradient(bottom left, #800000 100%, #b00000 100%)' })
		document.getElementById('register-button').style.color = '#ffffff'
	} else {
		document.getElementById('register-button').disabled = true
		$(eventButton).css({' background-image': '' })
		document.getElementById('register-button').style.color = '#333333'
	}
}
$(eventFirstName + ',' + eventLastName + ',' + eventEmail + ',' + eventMobile + ',' + eventBirthdate + ',' + eventFemale + ',' + eventMale + ',' + eventOther + ',' + eventReferral + ',' + eventExperienceDetails + ',' + eventDietDetails + ',' + eventStatus + ',' + eventPartnerName + ',' + eventPartnerFemale + ',' + eventPartnerMale + ',' + eventPartnerOther + ',' + eventLodging + ',' + eventTerms).on('change', function () {
	eventValidation()
})

// PARTNERSHIP
function showPartner() {
	$(eventPartnerContainer).show()
	$(eventPartnerContainer).animate({
		top: 0,
		opacity: 1
	}, 200)
	if ($(eventPayBoth).is(':checked')) {
		resetLodging('for both')
	} else {
		resetLodging('per person')
	}
}

function hidePartner() {
	$(eventPartnerName).val('')
	$(eventPartnerFemale + ',' + eventPartnerMale + ',' + eventPartnerOther + ',' + eventPayBoth + ',' + eventPayMe).prop('checked', false)
	$(eventPartnerContainer).animate({
		top: -40,
		opacity: 0
	}, 200)
	$(eventPartnerContainer).hide()
	resetLodging()
}

$(eventStatus).change(function() {
	participants() === 2 ? showPartner() : hidePartner()
})

$(eventPayBoth + ',' + eventPayMe).change(function() {
	if ($(eventPayBoth).is(':checked')) {
		resetLodging('for both')
	} else if (participants() === 2) {
		resetLodging('per person')
	} else {
		resetLodging('')
	}
})

// PREVIOUS EXPERIENCE
function showExperience() {
	$(eventExperienceContainer).show()
	$(eventExperienceContainer).animate({
		top: 40,
		opacity: 1
	}, 200)
}

function hideExperience() {
	$(eventExperienceDetails).val('')
	$(eventExperienceContainer).animate({
		top: 0,
		opacity: 0
	}, 200)
	$(eventExperienceContainer).hide()
}

$(eventExperienceNo + ',' + eventExperienceYes).change(function() {
	if ($(eventExperienceYes).is(':checked')) showExperience()
	if ($(eventExperienceNo).is(':checked')) hideExperience()
})

// DIETARY NEEDS
function showDiet() {
	$(eventDietContainer).show()
	$(eventDietContainer).animate({
		top: 0,
		opacity: 1
	}, 200)
}

function hideDiet() {
	$(eventDietDetails).val('')
	$(eventDietContainer).animate({
		top: -40,
		opacity: 0
	}, 200)
	$(eventDietContainer).hide()
}

$(eventDietNo + ',' + eventDietYes).change(function() {
	if ($(eventDietYes).is(':checked')) showDiet()
	if ($(eventDietNo).is(':checked')) hideDiet()
})

// LODGING
function resetLodging(paymentStatus) {
	//	Adds lodging options & prices based on CMS input
	var lodgingOptions = eventLodgingOptions.split(' | ')
	var lodgingPrices = eventLodgingPrices.split(' | ')
	$(eventLodging).empty()
	if (lodgingOptions.length > 0) {
		$(eventLodging).append($('<option>', {
			value: '',
			text: 'Event option...'
		}))
	}
	paymentStatus = paymentStatus ? paymentStatus : ''
	const paymentFactor = (paymentStatus === 'for both') ? 2 : 1
	const spacer = paymentStatus ? ' ' : ''
	const closer = (paymentStatus || paymentStatus === '') ? ')' : ''
	for (let i = 0; i < lodgingOptions.length; i++) {
		$(eventLodging).append($('<option>', {
			value: lodgingPrices[i] * paymentFactor,
			text: lodgingOptions[i] + ' ($' + lodgingPrices[i] * paymentFactor + spacer + paymentStatus + closer
		}))
	}
	eventPrice = parseInt(eventDepositAmount) * paymentFactor
	$(eventDepositText).text(`Pay deposit only ($${eventPrice}${spacer}${paymentStatus})`)
}

// SHOW REGISTRATION
function showRegistration() {
	$registrationSection.show()
	$confirmationSection.hide()
}

// SHOW CONFIRMATION
function showConfirmation() {
	$registrationSection.hide()
	$confirmationSection.show()
}

function resetEventForm() {
	showRegistration()
	$('.w-form-done').hide()
	$('.w-form-fail').hide()
	$registerForm[0].reset()
	repopulateEvent()
	resetLodging()
	if ($(eventExperienceDetails).val() === '') hideExperience()
	if ($(eventDietDetails).val() === '') hideDiet()
	if ($(eventPartnerName).val() === '') hidePartner()
	eventValidation()
	if (new Date() < new Date(eventDepositDate)) {
		$(eventDepositContainer).show()
		$(eventDepositFull).prop('checked', true)
	} else {
		$(eventDepositContainer).hide()
	}
	$registerForm.parsley()
	$registerForm.show()
	$(eventTerms).attr('checked', false)
	eventValidation()
}

// EVENT PAGE
if (window.location.href.indexOf('/events/') > -1) {
	resetEventForm()
}
<commit_msg>Integrating form into website.<commit_after>// Registration
$registrationSection = $('.registration-section'),
$confirmationSection = $('.confirmation-section'),
$registerForm = $('.form.registration'),
eventCode = $('#event-code').text().toLowerCase(),
eventTitle = $('#event-name').text(), // Stripe description
eventStartDate = $('#event-start').text(),
eventDates = $('#event-dates').text(),
eventVenue = $('#event-venue').text(),
eventDepositAmount = $('#event-deposit-amount').text(),
eventDepositDate = $('#event-deposit-date').text(),
eventLodgingOptions = $('#event-lodging-options').text(),
eventLodgingPrices = $('#event-lodging-prices').text(),
eventStripe = $('#event-stripe').text()

// Event initialization
const eventButton = '.button.register',
eventFirstName = '#event-firstname',
eventLastName = '#event-lastname',
eventEmail = '#event-email',
eventMobile = '#event-mobile',
eventBirthdate = '#event-birthdate',
eventFemale = '#event-gender-female',
eventMale = '#event-gender-male',
eventOther = '#event-gender-other',
eventReferral = '#event-referral',
eventExperienceContainer = '.event-container.experience',
eventExperienceYes = '#event-experience-yes',
eventExperienceNo = '#event-experience-no',
eventExperienceDetails = '#event-experience-details',
eventDietContainer = '.event-container.diet',
eventDietYes = '#event-diet-yes',
eventDietNo = '#event-diet-no',
eventDietDetails = '#event-diet-details'
eventStatus = '#event-status',
eventPartnerContainer = '.event-container.partner',
eventPartnerName = '#event-partner-name'
eventPartnerFemale = '#event-partner-gender-female',
eventPartnerMale = '#event-partner-gender-male',
eventPartnerOther = '#event-partner-gender-other',
eventPayBoth = '#event-pay-both',
eventPayMe = '#event-pay-me',
eventLodging = '#event-lodging',
eventDepositContainer = '.event-container.deposit',
eventDepositText = '#event-deposit-text',
eventDepositFull = '#event-deposit-full',
eventDepositDeposit = '#event-deposit-deposit',
eventTerms = '#event-terms'

// SAVE FORM
function saveEvent() {
	var values = {};
	$('input, textarea, select').each(function() {
		if ($(this).is(':radio')) {
			if ($(this).is(':checked')) { values[$(this).attr('name')] = $(this).val() }
		}
		else {
			values[$(this).attr('name')] = $(this).val()
		}
	})
	localStorage.setItem('EcstaticLiving:Event', JSON.stringify(values))
}

// REPOPULATE SAVED FORM
function repopulateEvent() {
	if (localStorage.getItem('EcstaticLiving:Event')) {
		var values = JSON.parse(localStorage.getItem('EcstaticLiving:Event'))
		for (var item in values) {
			if ($('*[name=' + item + ']').is(':radio')) {
				$('input[name=' + item + '][value="' + values[item] + '"]').prop('checked', true)
			}
			else {
				$('*[name=' + item + ']').val(values[item])
			}
		}
		localStorage.removeItem('EcstaticLiving:Event')
	}
}

// PARTICIPANTS
function participants() {
	if (($(eventStatus).find('option:selected').val() === 'Couple') || ($(eventStatus).find('option:selected').val() === 'Two Singles (paired)')) {
		return 2
	} else if ($(eventStatus).find('option:selected').val() === 'Single') {
		return 1
	}
}

// FORM VALIDATION
function validationPersonal() {
	if ($(eventFirstName).val() !== '' && $(eventLastName).val() !== '' && $(eventEmail).val() !== '' && $(eventMobile).val() !== '' && $(eventBirthdate).val() !== '' &&
		($(eventFemale).is(':checked') || $(eventMale).is(':checked') || $(eventOther).is(':checked'))) {
		return true
	}
	return false
}
function validationDetails() {
	if ($(eventReferral).val() !== ''
		&& (($(eventExperienceYes).is(':checked') && $(eventExperienceDetails).val() !== '') || $(eventExperienceNo).is(':checked'))
		&& (($(eventDietYes).is(':checked') && $(eventDietDetails).val() !== '') || $(eventDietNo).is(':checked'))) {
		return true
	}
	return false
}
function validationStatus() {
	if (
		(participants() === 2
			&& $(eventPartnerName).val() !== ''
			&& ($(eventPartnerFemale).is(':checked') || $(eventPartnerMale).is(':checked') || $(eventPartnerOther).is(':checked'))
			&& ($(eventPayBoth).is(':checked') || $(eventPayMe).is(':checked')))
		|| participants() === 1
	) {
		return true
	}
	return false
}
function validationLodging() {
	if ($(eventLodging).val() !== '' && (
		$(eventDepositContainer).is(':visible') && ($(eventDepositFull).is(':checked') || $(eventDepositDeposit).is(':checked'))
	) || $(eventDepositContainer).is(':hidden')) {
		return true
	}
	return false
}
function eventValidation() {
	if (validationPersonal() && validationDetails() && validationStatus() && validationLodging() && $(eventTerms).is(':checked')) {
		console.log('*** VALID ***');
		document.getElementById('register-button').disabled = false
		$(eventButton).css({' background-image': 'linear-gradient(bottom left, #800000 100%, #b00000 100%)' })
		document.getElementById('register-button').style.color = '#ffffff'
	} else {
		document.getElementById('register-button').disabled = true
		$(eventButton).css({' background-image': '' })
		document.getElementById('register-button').style.color = '#333333'
	}
}
$(eventFirstName + ',' + eventLastName + ',' + eventEmail + ',' + eventMobile + ',' + eventBirthdate + ',' + eventFemale + ',' + eventMale + ',' + eventOther + ',' + eventReferral + ',' + eventExperienceDetails + ',' + eventDietDetails + ',' + eventStatus + ',' + eventPartnerName + ',' + eventPartnerFemale + ',' + eventPartnerMale + ',' + eventPartnerOther + ',' + eventLodging + ',' + eventTerms).on('change', function () {
	eventValidation()
})

// PARTNERSHIP
function showPartner() {
	$(eventPartnerContainer).show()
	$(eventPartnerContainer).animate({
		top: 0,
		opacity: 1
	}, 200)
	if ($(eventPayBoth).is(':checked')) {
		resetLodging('for both')
	} else {
		resetLodging('per person')
	}
}

function hidePartner() {
	$(eventPartnerName).val('')
	$(eventPartnerFemale + ',' + eventPartnerMale + ',' + eventPartnerOther + ',' + eventPayBoth + ',' + eventPayMe).prop('checked', false)
	$(eventPartnerContainer).animate({
		top: -40,
		opacity: 0
	}, 200)
	$(eventPartnerContainer).hide()
	resetLodging()
}

$(eventStatus).change(function() {
	participants() === 2 ? showPartner() : hidePartner()
})

$(eventPayBoth + ',' + eventPayMe).change(function() {
	if ($(eventPayBoth).is(':checked')) {
		resetLodging('for both')
	} else if (participants() === 2) {
		resetLodging('per person')
	} else {
		resetLodging('')
	}
})

// PREVIOUS EXPERIENCE
function showExperience() {
	$(eventExperienceContainer).show()
	$(eventExperienceContainer).animate({
		top: 40,
		opacity: 1
	}, 200)
}

function hideExperience() {
	$(eventExperienceDetails).val('')
	$(eventExperienceContainer).animate({
		top: 0,
		opacity: 0
	}, 200)
	$(eventExperienceContainer).hide()
}

$(eventExperienceNo + ',' + eventExperienceYes).change(function() {
	if ($(eventExperienceYes).is(':checked')) showExperience()
	if ($(eventExperienceNo).is(':checked')) hideExperience()
})

// DIETARY NEEDS
function showDiet() {
	$(eventDietContainer).show()
	$(eventDietContainer).animate({
		top: 0,
		opacity: 1
	}, 200)
}

function hideDiet() {
	$(eventDietDetails).val('')
	$(eventDietContainer).animate({
		top: -40,
		opacity: 0
	}, 200)
	$(eventDietContainer).hide()
}

$(eventDietNo + ',' + eventDietYes).change(function() {
	if ($(eventDietYes).is(':checked')) showDiet()
	if ($(eventDietNo).is(':checked')) hideDiet()
})

// LODGING
function resetLodging(paymentStatus) {
	//	Adds lodging options & prices based on CMS input
	var lodgingOptions = eventLodgingOptions.split(' | ')
	var lodgingPrices = eventLodgingPrices.split(' | ')
	$(eventLodging).empty()
	if (lodgingOptions.length > 0) {
		$(eventLodging).append($('<option>', {
			value: '',
			text: 'Event option...'
		}))
	}
	paymentStatus = paymentStatus ? paymentStatus : ''
	const paymentFactor = (paymentStatus === 'for both') ? 2 : 1
	const spacer = paymentStatus ? ' ' : ''
	const closer = (paymentStatus || paymentStatus === '') ? ')' : ''
	for (let i = 0; i < lodgingOptions.length; i++) {
		$(eventLodging).append($('<option>', {
			value: lodgingPrices[i] * paymentFactor,
			text: lodgingOptions[i] + ' ($' + lodgingPrices[i] * paymentFactor + spacer + paymentStatus + closer
		}))
	}
	eventPrice = parseInt(eventDepositAmount) * paymentFactor
	$(eventDepositText).text(`Pay deposit only ($${eventPrice}${spacer}${paymentStatus})`)
}

// SHOW REGISTRATION
function showRegistration() {
	$registrationSection.show()
	$confirmationSection.hide()
}

// SHOW CONFIRMATION
function showConfirmation() {
	$registrationSection.hide()
	$confirmationSection.show()
}

function resetEventForm() {
	showRegistration()
	$('.w-form-done').hide()
	$('.w-form-fail').hide()
	$registerForm[0].reset()
	repopulateEvent()
	resetLodging()
	if ($(eventExperienceDetails).val() === '') hideExperience()
	if ($(eventDietDetails).val() === '') hideDiet()
	if ($(eventPartnerName).val() === '') hidePartner()
	eventValidation()
	if (new Date() < new Date(eventDepositDate)) {
		$(eventDepositContainer).show()
		$(eventDepositFull).prop('checked', true)
	} else {
		$(eventDepositContainer).hide()
	}
	$registerForm.parsley()
	$registerForm.show()
	$(eventTerms).attr('checked', false)
	eventValidation()
}

// EVENT PAGE
if (window.location.href.indexOf('/events/') > -1) {
	resetEventForm()
}
<|endoftext|>


<commit_before>var connection = new autobahn.Connection({
  url: 'ws://115.146.87.241:8080/ws',
  realm: 'realm1'
});

connection.onopen = function(session) {

//  uploadFasta = document.getElementById('uploadFasta');
//  uploadBED = document.getElementById('uploadBED');
//  uploadRa = document.getElementById('uploadRa');

  console.log("Connected", details);
//  session.subscribe('com.example.upload.on_progress', function(args) {
//    var pinfo = args[0];
//    console.log('upload event received', pinfo.status, pinfo.chunk, pinfo.remaining, pinfo.total, pinfo.progress);
//  });
//
//  var r = new Resumable({
//    target: 'upload',
//    chunkSize: 1 * 1024 * 1024,
//    forceChunkSize: true, // https://github.com/23/resumable.js/issues/51
//    simultaneousUploads: 4,
//    testChunks: true,
//    query: {
//      on_progress: 'com.example.upload.on_progress',
//      session: session.id
//    }
//  });
//  if (!r.support) {
//    console.log("Fatal: ResumableJS not supported!");
//  } else {
//    r.assignBrowse([uploadFasta, uploadBED, uploadRa]);
//    r.on('fileAdded', function(file) {
//      console.log('fileAdded', file);
//      r.upload();
//    });
//    r.on('fileSuccess', function(file, message) {
//      console.log('fileSuccess', file, message);
//      console.log(r.files);
//      // enable repeated upload since other user can delete the file on the server
//      // and this user might want to reupload the file
//      file.cancel();
//    });
//    r.on('fileError', function(file, message) {
//      console.log('fileError', file, message);
//    });
//  }
//
//  upload_reference_genome = function() {}
//
  session.call('com.gb.taxon_search', ['drosophila birchii']).then(
      function(res) {
          console.log(res);
      },
      function(err) {
          console.log(err);
      }
  );
}

document.addEventListener('WebComponentsReady', function() {

  var template = document.getElementById('t');

  template.selected = 0;
  template.subselected = 0;
//  document.getElementById('bedNavButton').addEventListener('click', function(e) {
//    template.subselected = 1;
//  });
  connection.open();
    console.log("Opened connection");
});
<commit_msg>Minor additions, bugfixes<commit_after>var connection = new autobahn.Connection({
  url: 'ws://115.146.87.241/ws',
  realm: 'realm1'
});

connection.onopen = function(session) {

//  uploadFasta = document.getElementById('uploadFasta');
//  uploadBED = document.getElementById('uploadBED');
//  uploadRa = document.getElementById('uploadRa');

  console.log("Connected", session.details);
//  session.subscribe('com.example.upload.on_progress', function(args) {
//    var pinfo = args[0];
//    console.log('upload event received', pinfo.status, pinfo.chunk, pinfo.remaining, pinfo.total, pinfo.progress);
//  });
//
//  var r = new Resumable({
//    target: 'upload',
//    chunkSize: 1 * 1024 * 1024,
//    forceChunkSize: true, // https://github.com/23/resumable.js/issues/51
//    simultaneousUploads: 4,
//    testChunks: true,
//    query: {
//      on_progress: 'com.example.upload.on_progress',
//      session: session.id
//    }
//  });
//  if (!r.support) {
//    console.log("Fatal: ResumableJS not supported!");
//  } else {
//    r.assignBrowse([uploadFasta, uploadBED, uploadRa]);
//    r.on('fileAdded', function(file) {
//      console.log('fileAdded', file);
//      r.upload();
//    });
//    r.on('fileSuccess', function(file, message) {
//      console.log('fileSuccess', file, message);
//      console.log(r.files);
//      // enable repeated upload since other user can delete the file on the server
//      // and this user might want to reupload the file
//      file.cancel();
//    });
//    r.on('fileError', function(file, message) {
//      console.log('fileError', file, message);
//    });
//  }
//
//  upload_reference_genome = function() {}
//
  session.call('com.gb.taxon_search', ['drosophila birchii']).then(
      function(res) {
          console.log(res);
      },
      function(err) {
          console.log(err);
      }
  );
}

document.addEventListener('WebComponentsReady', function() {

  var template = document.getElementById('t');
  connection.open();
  template.selected = 0;
  template.subselected = 0;
//  document.getElementById('bedNavButton').addEventListener('click', function(e) {
//    template.subselected = 1;
//  });
    console.log("Opened connection");
});
<|endoftext|>