<commit_before>var fs = require('fs');

module.exports = {
  free: free,
  total: total,
  freePercent: freePercent,
  usedPercent: usedPercent,
  allStats: allStats,
  raw: raw,
};

/* PUBLIC */

function free(units) {
  var meminfo = _parseProcMeminfo();
  return _free(meminfo, units);
}

function total(units) {
  var meminfo = _parseProcMeminfo();
  return _total(meminfo, units);
}

function freePercent() {
  var meminfo = _parseProcMeminfo();
  return _freePercent(meminfo);
}

function usedPercent() {
  var meminfo = _parseProcMeminfo();
  return _usedPercent(meminfo);
}

function allStats(units) {
  units = units || 'bytes';
  var meminfo = _parseProcMeminfo();
  return {
    free: _free(meminfo, units),
    total: _total(meminfo, units),
    freePercent: _freePercent(meminfo),
    usedPercent: _usedPercent(meminfo),
  };
}

//raw `/proc/meminfo` as object
function raw(cb) {
  return _parseProcMeminfo(cb);
}

/* PRIVATE */

function _free(meminfo, units) {
  units = units || 'bytes';

  var freeMem = meminfo.memFree;
  var cached = meminfo.cached;
  var buffers = meminfo.buffers;

  var totalFreeMem = freeMem + cached + buffers;
  var totalFreeMemBytes = totalFreeMem * 1024;
  var converted = _bytesTo(totalFreeMemBytes, units);

  return converted;
}

function _total(meminfo, units) {
  units = units || 'bytes';
  var memTotal = meminfo.memTotal;
  var memTotalBytes = memTotal * 1024;
  var converted = _bytesTo(memTotalBytes, units);

  return converted;
}

function _freePercent(meminfo) {
  var freeMem = meminfo.memFree;
  var cached = meminfo.cached;
  var buffers = meminfo.buffers;
  var memTotal = meminfo.memTotal;

  var totalFreeMem = freeMem + cached + buffers;
  var percent = ((totalFreeMem / memTotal) * 100);

  return percent;
}

function _usedPercent(meminfo) {
  var freeMem = meminfo.memFree;
  var cached = meminfo.cached;
  var buffers = meminfo.buffers;
  var memTotal = meminfo.memTotal;

  var totalFreeMem = freeMem + cached + buffers;
  var used = memTotal - totalFreeMem;
  var percent = ((used / memTotal) * 100);

  return percent;
}

//NOTE: docs at `man proc`
function _parseProcMeminfo(cb) {
  if (cb) {
    return fs.readFile('/proc/meminfo', function (err, meminfo) {
      if (err) return cb(err);
      return cb(null, _formatParsedProcMeminfo(meminfo));
    });
  }

  var meminfo = fs.readFileSync('/proc/meminfo');
  return _formatParsedProcMeminfo(meminfo);
}

function _formatParsedProcMeminfo(meminfo) {
  var lines = meminfo.toString().split('\n');

  //remove last blank line
  lines.pop();

  var data = {};
  lines.forEach(function(line) {
    var row = line.split(':');
    data[_toCamelCase(row[0])] = parseInt(row[1].trim().split(' ')[0]);
  });

  return data;
}

//quick dirty to handle parens and underscores
function _toCamelCase(str) {
  var newString = '';
  var insideParens = false;
  newString += str[0].toLowerCase();
  for (var i = 1; i < str.length; i++) {
    var char = str[i];
    switch (char) {
      case ')':
      case '_':
        break;
      case '(':
        insideParens = true;
        break;
      default:
        if (insideParens) {
          insideParens = false;
          newString += char.toUpperCase();
        } else {
          newString += char;
        }
        break;
    }
  }

  return newString;
}

function _bytesTo(bytes, units) {
  var KiB = 1024;
  var MiB = 1024 * KiB;
  var GiB = 1024 * MiB;

  switch (units) {
    case 'bytes':
      break;
    case 'KiB':
      bytes /= KiB;
      break;
    case 'MiB':
      bytes /= MiB;
      break;
    case 'GiB':
      bytes /= GiB;
      break;
    default:
      var errMsg =
        '[mem-stats] Error: Unknown units "' + units + '", use one of: ' +
        '"bytes" (default), "KiB", "MiB" or "GiB"';
      console.log(errMsg);
  }

  //NOTE: the variable named `bytes` may not actually contain a number
  //representing the number of bytes. its done this way to only have to use one
  //variable.
  return bytes;
}
<commit_msg>Only use cb if it's a function<commit_after>var fs = require('fs');

module.exports = {
  free: free,
  total: total,
  freePercent: freePercent,
  usedPercent: usedPercent,
  allStats: allStats,
  raw: raw,
};

/* PUBLIC */

function free(units) {
  var meminfo = _parseProcMeminfo();
  return _free(meminfo, units);
}

function total(units) {
  var meminfo = _parseProcMeminfo();
  return _total(meminfo, units);
}

function freePercent() {
  var meminfo = _parseProcMeminfo();
  return _freePercent(meminfo);
}

function usedPercent() {
  var meminfo = _parseProcMeminfo();
  return _usedPercent(meminfo);
}

function allStats(units) {
  units = units || 'bytes';
  var meminfo = _parseProcMeminfo();
  return {
    free: _free(meminfo, units),
    total: _total(meminfo, units),
    freePercent: _freePercent(meminfo),
    usedPercent: _usedPercent(meminfo),
  };
}

//raw `/proc/meminfo` as object
function raw(cb) {
  return _parseProcMeminfo(cb);
}

/* PRIVATE */

function _free(meminfo, units) {
  units = units || 'bytes';

  var freeMem = meminfo.memFree;
  var cached = meminfo.cached;
  var buffers = meminfo.buffers;

  var totalFreeMem = freeMem + cached + buffers;
  var totalFreeMemBytes = totalFreeMem * 1024;
  var converted = _bytesTo(totalFreeMemBytes, units);

  return converted;
}

function _total(meminfo, units) {
  units = units || 'bytes';
  var memTotal = meminfo.memTotal;
  var memTotalBytes = memTotal * 1024;
  var converted = _bytesTo(memTotalBytes, units);

  return converted;
}

function _freePercent(meminfo) {
  var freeMem = meminfo.memFree;
  var cached = meminfo.cached;
  var buffers = meminfo.buffers;
  var memTotal = meminfo.memTotal;

  var totalFreeMem = freeMem + cached + buffers;
  var percent = ((totalFreeMem / memTotal) * 100);

  return percent;
}

function _usedPercent(meminfo) {
  var freeMem = meminfo.memFree;
  var cached = meminfo.cached;
  var buffers = meminfo.buffers;
  var memTotal = meminfo.memTotal;

  var totalFreeMem = freeMem + cached + buffers;
  var used = memTotal - totalFreeMem;
  var percent = ((used / memTotal) * 100);

  return percent;
}

//NOTE: docs at `man proc`
function _parseProcMeminfo(cb) {
  if (cb && typeof cb == "function") {
    return fs.readFile('/proc/meminfo', function (err, meminfo) {
      if (err) return cb(err);
      return cb(null, _formatParsedProcMeminfo(meminfo));
    });
  }

  var meminfo = fs.readFileSync('/proc/meminfo');
  return _formatParsedProcMeminfo(meminfo);
}

function _formatParsedProcMeminfo(meminfo) {
  var lines = meminfo.toString().split('\n');

  //remove last blank line
  lines.pop();

  var data = {};
  lines.forEach(function(line) {
    var row = line.split(':');
    data[_toCamelCase(row[0])] = parseInt(row[1].trim().split(' ')[0]);
  });

  return data;
}

//quick dirty to handle parens and underscores
function _toCamelCase(str) {
  var newString = '';
  var insideParens = false;
  newString += str[0].toLowerCase();
  for (var i = 1; i < str.length; i++) {
    var char = str[i];
    switch (char) {
      case ')':
      case '_':
        break;
      case '(':
        insideParens = true;
        break;
      default:
        if (insideParens) {
          insideParens = false;
          newString += char.toUpperCase();
        } else {
          newString += char;
        }
        break;
    }
  }

  return newString;
}

function _bytesTo(bytes, units) {
  var KiB = 1024;
  var MiB = 1024 * KiB;
  var GiB = 1024 * MiB;

  switch (units) {
    case 'bytes':
      break;
    case 'KiB':
      bytes /= KiB;
      break;
    case 'MiB':
      bytes /= MiB;
      break;
    case 'GiB':
      bytes /= GiB;
      break;
    default:
      var errMsg =
        '[mem-stats] Error: Unknown units "' + units + '", use one of: ' +
        '"bytes" (default), "KiB", "MiB" or "GiB"';
      console.log(errMsg);
  }

  //NOTE: the variable named `bytes` may not actually contain a number
  //representing the number of bytes. its done this way to only have to use one
  //variable.
  return bytes;
}
<|endoftext|>


<commit_before>'use strict'
const wsConnQueue = require('./wsConnQueue.js')
const worker = require('ddv-worker')
const workerUtil = require('ddv-worker/util')
const PushBaseEvent = require('./PushBaseEvent.js')
const apiModelProxy = require('./apiModelProxy.js')
const ddvRowraw = require('ddv-rowraw')
const logger = require('../../lib/logger.js')
const crypto = require('crypto')
const querystring = require('querystring')
const url = require('url')
const http = require('http')
const https = require('https')
const regular = /\-/g

class PushEvent extends PushBaseEvent {
  constructor (options, ws, req) {
    super(options, ws, req)
    // 如果队列没有这个对象就加入这个对象
    wsConnQueue[this.connId] = wsConnQueue[this.connId] || this
    this.setConfigInfo()
    this.pushEventInit()
  }
  pushEventInit () {
    this.ws.on('close', this.onWsConnQueueClose.bind(this))
    // 获取文件事件
    this.on('protocol::apimodelproxy', this.onApiModelProxy.bind(this))
    this.on(['push', 'ping', '/v1_0/init'], this.pushPingHeartbeat.bind(this))
    this.on(['push', 'close', '/v1_0/init'], this.pushClose.bind(this))
    this.on(['push', 'open', '/v1_0/init'], this.pushOpen.bind(this))
  }
  // 设置配置信息
  setConfigInfo () {
    // 解析url
    let urlObj = url.parse(this.options.rpcEvent.api_url)
    this.options.apiUrlOpt = Object.create(null)
    this.options.apiUrlOpt.protocol = urlObj.protocol
    this.options.apiUrlOpt.host = urlObj.hostname
    this.options.apiUrlOpt.port = urlObj.port
  }
  // 关闭推送
  pushClose (headers, body, res) {
    var requestId
    if (!this.isWsOpen()) {
      logger.error(new Error(`${this.gwcid}Has been closed, on pushClose`))
      return
    }

    if (!(res.headers && (requestId = res.headers.request_id || res.headers.requestId || res.headers.requestid))) {
      return
    }
    console.log(requestId)
  }
  // 打开推送
  pushOpen (headers, body, res) {
    var headersObj = Object.create(null)

    if (!this.isWsOpen()) {
      logger.error(new Error(`${this.gwcid}Has been closed, on pushOpen`))
      return
    }
    // 请求id
    headersObj.requestId = res.headers && (res.headers.request_id || res.headers.requestId || res.headers.requestid)
    // 全局链接id
    headersObj.gwcid = this.gwcid
    // 服务器唯一识别号
    headersObj.serverGuid = this.serverGuid

    if (!(res.headers && headersObj.requestId)) {
      return
    }
    this.pushPing(headers, body, res)
    .then((res) => {
      console.log('签名结束', res)
    })
    .catch(e => {
      console.log('签名失败', e)
    })
  }
  pushPing (headers, body, res) {
    var opt = Object.create(null)
    var bodyObj, req

    if (!this.pingDataOptSign) {
      this.getPingData(headers, body, res)
    }
    Object.assign(opt, this.pingDataOptSign)
    // 生成唯一请求id
    opt.request_id = workerUtil.createRequestId()
    // 获取onOpen地址
    opt.path = this.options.rpcEvent.on_open

    return this.request(opt, (res.headers.bodytype === 'buffer' ? (new Buffer(0)) : ''), 'PING /v1_0/sign PUSH/1.0')
    .then(res => {
      return new Promise((resolve, reject) => {
        let pingDataHKey = Object.keys(this.pingDataH || [])

        pingDataHKey.forEach((key, index) => {
          let lowkey = key.toLowerCase().replace(regular, '_')

          if (typeof this.pingDataH[key] === 'number') {
            this.pingDataH[key] = this.pingDataH[key].toString()
          }

          if (typeof res.headers[lowkey] === 'number') {
            res.headers[lowkey] = res.headers[lowkey].toString()
          }

          if (res.headers[lowkey] === this.pingDataH[key]) {
            delete res.headers[lowkey]
          } else {
            logger.error(new Error(`headers sign fail, ${key}, ${res.headers[lowkey]}, ${res.headers}`))
            return false
          }
          lowkey = void 0
        })
        // 撮合发送协议 端口 主机 信息
        Object.assign(opt, this.options.apiUrlOpt)
        // 判断是否已经修改了发过去的请求id
        if (res.headers.request_id !== opt.request_id) {
          logger.error(new Error('request_id sign fail'))
          reject(new Error('request_id sign fail'))
        } else if (res.headers.host !== opt.host) {
          logger.error(new Error('host sign fail'))
          reject(new Error('host sign fail'))
        } else {
          // 请求php的头 空对象
          opt.headers = Object.create(null)
          // 撮合一下
          Object.assign(opt.headers, this.pingDataH)
          // host 首字母大写
          opt.headers.Host = opt.host
          // Authorization 首字母大写
          opt.headers.Authorization = res.headers.authorization
        }

        req = (opt.protocol === 'https:' ? https : http).request(opt, response => {
          bodyObj = new Buffer(0)
          // 接收数据
          response.on('data', (data) => {
            bodyObj = Buffer.concat([bodyObj, data])
            data = undefined
            // 接收结束
          }).on('end', function () {
            let obj = {
              headers,
              body,
              res
            }
            resolve(obj)
            console.log('签名结果', bodyObj.toString())
          })
        })
        // 写入发送的数据
        req.write(this.pingDataRaw)
        // 结束请求数据的发送
        req.end()
        req = undefined
      })
    })
    .catch(e => {
      logger.error('Signature failed')
      logger.error(e)
      return new Promise((resolve, reject) => {
        reject(new Error('Signature failed'))
      })
    })
  }
  getPingData (headers, body, res) {
    // 上线时间-是第一次连接push-open的时间戳
    this.pushTimeOnLine = this.pushTimeOnLine || workerUtil.time()
    // 构建发送php的参数对象
    this.pingData = Object.create(null)
    // 连接唯一识别gwcid
    this.pingData.gwcid = this.gwcid
    // 本推送服务器的 guid
    this.pingData.serverGuid = this.serverGuid
    // 长连接连接类型
    this.pingData.bodyType = res.headers.bodytype
    // 第一次上线时间
    this.pingData.timeOnline = this.pushTimeOnLine
    // 把参数序列化转为buffer缓存区数据
    this.pingDataRaw = new Buffer(querystring.stringify(this.pingData), 'utf-8')
    // 计算得出发送php的数据的二进制md5的base64
    this.pingDataMd5Base64 = crypto.createHash('md5').update(this.pingDataRaw).digest('base64')
    // 通知php的基本头
    this.pingDataH = Object.create(null)
    // 内容md5
    this.pingDataH['Content-Md5'] = this.pingDataMd5Base64
    // 内容长度
    this.pingDataH['Content-Length'] = this.pingDataRaw.length
    // 以这个协议进行编码
    this.pingDataH['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
    // 解析url
    let urlObj = url.parse(this.options.rpcEvent.api_url)
    // 构造请求对象
    this.pingDataOpt = Object.create(null)
    // 获取php-传输协议 http:/https:
    this.pingDataOpt.protocol = urlObj.protocol
    // 获取php-host主机
    this.pingDataOpt.host = urlObj.hostname
    // 获取php-端口
    this.pingDataOpt.port = urlObj.port
    // 这个对象用于发送前端，给前端签名
    this.pingDataOptSign = Object.create(null)
    // put 协议
    this.pingDataOptSign.method = 'PUT'
    // 头
    this.pingDataOptSign.headers = JSON.stringify(this.pingDataH)

    headers = res = body = void 0
  }
  // 打开推送ping
  pushPingHeartbeat (headers, body, res) {
    var requestId
    if (!this.isWsOpen()) {
      logger.error(new Error(`${this.gwcid}Has been closed, on pushPingHeartbeat`))
      return
    }
    if (!(res.headers && (requestId = res.headers.request_id || res.headers.requestId || res.headers.requestid))) {
      return
    }

    if (headers.bodytype && ['string', 'buffer'].indexOf(headers.bodytype) > -1) {
      this.bodytype = headers.bodytype
    } else {
      this.bodytype = 'auto'
    }

    ddvRowraw.stringifyPromise(
      {
        request_id: requestId
      },
      ((this.bodytype === 'buffer' || (this.bodytype === 'auto' && res.bodytype === 'buffer')) ? new Buffer(0) : ''),
      'PUSH/1.0 200 OK'
    )
    .then(raw => this.send(raw))
    headers = body = res = void 0
  }
  // 代理访问api服务器
  onApiModelProxy (res) {
    var requestId, body
    if (!this.isWsOpen()) {
      logger.error(new Error(`${this.gwcid}Has been closed, on onApiModelProxy`))
      return
    }
    if (!(res.headers && (requestId = res.headers.request_id || res.headers.requestId || res.headers.requestid))) {
      return
    }
    body = res.bodytype === 'buffer' ? Buffer(0) : ''
    // 试图请求
    apiModelProxy(res, this.options)
    // 有请求结果
    .then(({headers, statusCode, statusMessage, data}) => {
      if (Buffer.isBuffer(body)) {
        body = Buffer.concat([body, data])
      } else {
        body += data
      }
      data = void 0
      // 序列化流
      return ddvRowraw.stringifyPromise({
        'request_id': requestId,
        'headers': JSON.stringify(headers)
      }, body, `APIMODELPROXY/1.0 ${statusCode || '0'} ${statusMessage || 'Unknow Error'}`)
    })
    // 中途异常
    .catch(e => {
      // 序列化流
      return ddvRowraw.stringifyPromise({
        'request_id': requestId,
        'headers': '{}',
        'msg': e.message,
        'message': e.message
      }, body, `APIMODELPROXY/1.0 400 ${e.errorId || 'Unknow Error'}`)
    })
    .then(raw => this.send(raw))
    // 发送异常回去还是有异常打印日志
    .catch(e => {
      logger.error(`[gwcid:${this.gwcid}]onApiModelProxy error`)
      logger.error(e)
    })
  }
  // 发送信息个用户，信息来源rpc
  sendMsgToUser (headers, body) {
    if (!this.isWsOpen()) {
      let e = new Error(`${this.gwcid}Has been closed, on sendMsgToUser`)
      e.errorId = 'HAS_BEEN_CLOSED'
      logger.error(e)
      return Promise.reject(e)
    }
    // 转换推送类型
    if (this.bodytype === 'buffer' && ((typeof body) === 'string')) {
      body = new Buffer(body, 'utf-8')
    } else if (this.bodytype === 'string' && Buffer.isBuffer(body)) {
      body = body.toString('utf-8')
    }
    headers['push-path'] = (headers['push-path'].charAt(0) === '/' ? '' : '/') + headers['push-path']
    return ddvRowraw.stringifyPromise({}, body, `MESSAGE ${headers['push-path']} PUSH/1.0`)
    .then(raw => this.send(raw))
    .catch(e => {
      let resError = new Error('send to user fail')
      resError.errorId = 'SEND_TO_USER_FAIL'
      return Promise.reject(resError)
    })
  }
  // 收到消息的时候
  onWsConnQueueClose () {
    if (wsConnQueue[this.connId]) {
      workerUtil.isFunction(wsConnQueue[this.connId].destroy) && wsConnQueue[this.connId].destroy()
      delete wsConnQueue[this.connId]
    }
  }
}
worker.sendMessageByConnId = sendMessageByConnId
function sendMessageByConnId (connId, type, headers, body) {
  if (!(type && type === 'restfulPushServer')) {
    let e = new Error('type error')
    e.errorId = 'TYPE_CONN'
    return Promise.reject(e)
  }
  if (!(wsConnQueue && wsConnQueue[connId] && workerUtil.isFunction(wsConnQueue[connId].sendMsgToUser))) {
    let e = new Error('find not user')
    e.errorId = 'FIND_NOT_CONN'
    return Promise.reject(e)
  }
  return wsConnQueue[connId].sendMsgToUser(headers, body)
}
module.exports = PushEvent
<commit_msg>use PushError<commit_after>'use strict'
const wsConnQueue = require('./wsConnQueue.js')
const worker = require('ddv-worker')
const workerUtil = require('ddv-worker/util')
const PushBaseEvent = require('./PushBaseEvent.js')
const apiModelProxy = require('./apiModelProxy.js')
const ddvRowraw = require('ddv-rowraw')
const logger = require('../../lib/logger.js')
const crypto = require('crypto')
const querystring = require('querystring')
const url = require('url')
const http = require('http')
const https = require('https')
const PushError = require('./PushError')
const regular = /\-/g

class PushEvent extends PushBaseEvent {
  constructor (options, ws, req) {
    super(options, ws, req)
    // 如果队列没有这个对象就加入这个对象
    wsConnQueue[this.connId] = wsConnQueue[this.connId] || this
    this.setConfigInfo()
    this.pushEventInit()
  }
  pushEventInit () {
    this.ws.on('close', this.onWsConnQueueClose.bind(this))
    // 获取文件事件
    this.on('protocol::apimodelproxy', this.onApiModelProxy.bind(this))
    this.on(['push', 'ping', '/v1_0/init'], this.pushPingHeartbeat.bind(this))
    this.on(['push', 'close', '/v1_0/init'], this.pushClose.bind(this))
    this.on(['push', 'open', '/v1_0/init'], this.pushOpen.bind(this))
  }
  // 设置配置信息
  setConfigInfo () {
    // 解析url
    let urlObj = url.parse(this.options.rpcEvent.api_url)
    this.options.apiUrlOpt = Object.create(null)
    this.options.apiUrlOpt.protocol = urlObj.protocol
    this.options.apiUrlOpt.host = urlObj.hostname
    this.options.apiUrlOpt.port = urlObj.port
  }
  // 关闭推送
  pushClose (headers, body, res) {
    var requestId
    if (!this.isWsOpen()) {
      logger.error(new PushError(`${this.gwcid}Has been closed, on pushClose`, 'HAS_BEEN_CLOSED'))
      return
    }

    if (!(res.headers && (requestId = res.headers.request_id || res.headers.requestId || res.headers.requestid))) {
      return
    }
    console.log(requestId)
  }
  // 打开推送
  pushOpen (headers, body, res) {
    var headersObj = Object.create(null)

    if (!this.isWsOpen()) {
      logger.error(new PushError(`${this.gwcid}Has been closed, on pushOpen`, 'HAS_BEEN_CLOSED'))
      return
    }
    // 请求id
    headersObj.requestId = res.headers && (res.headers.request_id || res.headers.requestId || res.headers.requestid)
    // 全局链接id
    headersObj.gwcid = this.gwcid
    // 服务器唯一识别号
    headersObj.serverGuid = this.serverGuid

    if (!(res.headers && headersObj.requestId)) {
      return
    }
    this.pushPing(headers, body, res)
    .then((res) => {
      console.log('签名结束', res)
    })
    .catch(e => {
      console.log('签名失败', e)
    })
  }
  pushPing (headers, body, res) {
    var opt = Object.create(null)
    var bodyObj, req

    if (!this.pingDataOptSign) {
      this.getPingData(headers, body, res)
    }
    Object.assign(opt, this.pingDataOptSign)
    // 生成唯一请求id
    opt.request_id = workerUtil.createRequestId()
    // 获取onOpen地址
    opt.path = this.options.rpcEvent.on_open

    return this.request(opt, (res.headers.bodytype === 'buffer' ? (new Buffer(0)) : ''), 'PING /v1_0/sign PUSH/1.0')
    .then(res => {
      return new Promise((resolve, reject) => {
        let pingDataHKey = Object.keys(this.pingDataH || [])

        pingDataHKey.forEach((key, index) => {
          let lowkey = key.toLowerCase().replace(regular, '_')

          if (typeof this.pingDataH[key] === 'number') {
            this.pingDataH[key] = this.pingDataH[key].toString()
          }

          if (typeof res.headers[lowkey] === 'number') {
            res.headers[lowkey] = res.headers[lowkey].toString()
          }

          if (res.headers[lowkey] === this.pingDataH[key]) {
            delete res.headers[lowkey]
          } else {
            logger.error(new PushError(`headers sign fail, ${key}, ${res.headers[lowkey]}, ${res.headers}`, 'HEADERS_SIGN_FAIL'))
            return false
          }
          lowkey = void 0
        })
        // 撮合发送协议 端口 主机 信息
        Object.assign(opt, this.options.apiUrlOpt)
        // 判断是否已经修改了发过去的请求id
        if (res.headers.request_id !== opt.request_id) {
          logger.error(new PushError('request_id sign fail', 'REQUEST_ID_SIGN_FAIL'))
          reject(new PushError('request_id sign fail', 'REQUEST_ID_SIGN_FAIL'))
        } else if (res.headers.host !== opt.host) {
          logger.error(new PushError('host sign fail', 'HOST_SIGN_FAIL'))
          reject(new PushError('host sign fail', 'HOST_SIGN_FAIL'))
        } else {
          // 请求php的头 空对象
          opt.headers = Object.create(null)
          // 撮合一下
          Object.assign(opt.headers, this.pingDataH)
          // host 首字母大写
          opt.headers.Host = opt.host
          // Authorization 首字母大写
          opt.headers.Authorization = res.headers.authorization
        }

        req = (opt.protocol === 'https:' ? https : http).request(opt, response => {
          bodyObj = new Buffer(0)
          // 接收数据
          response.on('data', (data) => {
            bodyObj = Buffer.concat([bodyObj, data])
            data = undefined
            // 接收结束
          }).on('end', function () {
            let obj = {
              headers,
              body,
              res
            }
            resolve(obj)
            console.log('签名结果', bodyObj.toString())
          })
        })
        // 写入发送的数据
        req.write(this.pingDataRaw)
        // 结束请求数据的发送
        req.end()
        req = undefined
      })
    })
    .catch(e => {
      logger.error('Signature failed')
      logger.error(e)
      return new Promise((resolve, reject) => {
        reject(new PushError('Signature failed', 'SIGNATURE_FAILED'))
      })
    })
  }
  getPingData (headers, body, res) {
    // 上线时间-是第一次连接push-open的时间戳
    this.pushTimeOnLine = this.pushTimeOnLine || workerUtil.time()
    // 构建发送php的参数对象
    this.pingData = Object.create(null)
    // 连接唯一识别gwcid
    this.pingData.gwcid = this.gwcid
    // 本推送服务器的 guid
    this.pingData.serverGuid = this.serverGuid
    // 长连接连接类型
    this.pingData.bodyType = res.headers.bodytype
    // 第一次上线时间
    this.pingData.timeOnline = this.pushTimeOnLine
    // 把参数序列化转为buffer缓存区数据
    this.pingDataRaw = new Buffer(querystring.stringify(this.pingData), 'utf-8')
    // 计算得出发送php的数据的二进制md5的base64
    this.pingDataMd5Base64 = crypto.createHash('md5').update(this.pingDataRaw).digest('base64')
    // 通知php的基本头
    this.pingDataH = Object.create(null)
    // 内容md5
    this.pingDataH['Content-Md5'] = this.pingDataMd5Base64
    // 内容长度
    this.pingDataH['Content-Length'] = this.pingDataRaw.length
    // 以这个协议进行编码
    this.pingDataH['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
    // 解析url
    let urlObj = url.parse(this.options.rpcEvent.api_url)
    // 构造请求对象
    this.pingDataOpt = Object.create(null)
    // 获取php-传输协议 http:/https:
    this.pingDataOpt.protocol = urlObj.protocol
    // 获取php-host主机
    this.pingDataOpt.host = urlObj.hostname
    // 获取php-端口
    this.pingDataOpt.port = urlObj.port
    // 这个对象用于发送前端，给前端签名
    this.pingDataOptSign = Object.create(null)
    // put 协议
    this.pingDataOptSign.method = 'PUT'
    // 头
    this.pingDataOptSign.headers = JSON.stringify(this.pingDataH)

    headers = res = body = void 0
  }
  // 打开推送ping
  pushPingHeartbeat (headers, body, res) {
    var requestId
    if (!this.isWsOpen()) {
      logger.error(new PushError(`${this.gwcid}Has been closed, on pushPingHeartbeat`, 'HAS_BEEN_CLOSED'))
      return
    }
    if (!(res.headers && (requestId = res.headers.request_id || res.headers.requestId || res.headers.requestid))) {
      return
    }

    if (headers.bodytype && ['string', 'buffer'].indexOf(headers.bodytype) > -1) {
      this.bodytype = headers.bodytype
    } else {
      this.bodytype = 'auto'
    }

    ddvRowraw.stringifyPromise(
      {
        request_id: requestId
      },
      ((this.bodytype === 'buffer' || (this.bodytype === 'auto' && res.bodytype === 'buffer')) ? new Buffer(0) : ''),
      'PUSH/1.0 200 OK'
    )
    .then(raw => this.send(raw))
    headers = body = res = void 0
  }
  // 代理访问api服务器
  onApiModelProxy (res) {
    var requestId, body
    if (!this.isWsOpen()) {
      logger.error(new PushError(`${this.gwcid}Has been closed, on onApiModelProxy`, 'HAS_BEEN_CLOSED'))
      return
    }
    if (!(res.headers && (requestId = res.headers.request_id || res.headers.requestId || res.headers.requestid))) {
      return
    }
    body = res.bodytype === 'buffer' ? Buffer(0) : ''
    // 试图请求
    apiModelProxy(res, this.options)
    // 有请求结果
    .then(({headers, statusCode, statusMessage, data}) => {
      if (Buffer.isBuffer(body)) {
        body = Buffer.concat([body, data])
      } else {
        body += data
      }
      data = void 0
      // 序列化流
      return ddvRowraw.stringifyPromise({
        'request_id': requestId,
        'headers': JSON.stringify(headers)
      }, body, `APIMODELPROXY/1.0 ${statusCode || '0'} ${statusMessage || 'Unknow Error'}`)
    })
    // 中途异常
    .catch(e => {
      // 序列化流
      return ddvRowraw.stringifyPromise({
        'request_id': requestId,
        'headers': '{}',
        'msg': e.message,
        'message': e.message
      }, body, `APIMODELPROXY/1.0 400 ${e.errorId || 'Unknow Error'}`)
    })
    .then(raw => this.send(raw))
    // 发送异常回去还是有异常打印日志
    .catch(e => {
      logger.error(`[gwcid:${this.gwcid}]onApiModelProxy error`)
      logger.error(e)
    })
  }
  // 发送信息个用户，信息来源rpc
  sendMsgToUser (headers, body) {
    if (!this.isWsOpen()) {
      let e = new PushError(`${this.gwcid}Has been closed, on sendMsgToUser`, 'HAS_BEEN_CLOSED')
      e.errorId = 'HAS_BEEN_CLOSED'
      logger.error(e)
      return Promise.reject(e)
    }
    // 转换推送类型
    if (this.bodytype === 'buffer' && ((typeof body) === 'string')) {
      body = new Buffer(body, 'utf-8')
    } else if (this.bodytype === 'string' && Buffer.isBuffer(body)) {
      body = body.toString('utf-8')
    }
    headers['push-path'] = (headers['push-path'].charAt(0) === '/' ? '' : '/') + headers['push-path']
    return ddvRowraw.stringifyPromise({}, body, `MESSAGE ${headers['push-path']} PUSH/1.0`)
    .then(raw => this.send(raw))
    .catch(e => {
      return Promise.reject(new PushError('send to user fail', 'SEND_TO_USER_FAIL'))
    })
  }
  // 收到消息的时候
  onWsConnQueueClose () {
    if (wsConnQueue[this.connId]) {
      workerUtil.isFunction(wsConnQueue[this.connId].destroy) && wsConnQueue[this.connId].destroy()
      delete wsConnQueue[this.connId]
    }
  }
}
worker.sendMessageByConnId = sendMessageByConnId
function sendMessageByConnId (connId, type, headers, body) {
  if (!(type && type === 'restfulPushServer')) {
    return Promise.reject(new PushError('type error', 'TYPE_CONN'))
  }
  if (!(wsConnQueue && wsConnQueue[connId] && workerUtil.isFunction(wsConnQueue[connId].sendMsgToUser))) {
    return Promise.reject(new PushError('find not user', 'FIND_NOT_CONN'))
  }
  return wsConnQueue[connId].sendMsgToUser(headers, body)
}
module.exports = PushEvent
<|endoftext|>


<commit_before>'use strict';
var AWS = require('aws-sdk');
var gutil = require('gulp-util');
var through = require('through2');
var extend = require('xtend');

module.exports = function(params, opts) {
	opts = extend({
		profile: null,
		region: 'us-east-1'
	}, opts);

	var toUpload;
	var functionName = typeof params === 'string'? params : params.FunctionName;

	var make_err = function(message) {
		return new gutil.PluginError('gulp-awslambda', message);
	};

	return through.obj(function(file, enc, cb) {
		if (file.isNull()) {
			cb();
			return;
		}
		if (file.isStream()) {
			cb(make_err('Streaming is not supported'));
			return;
		}
		if (!toUpload) {
			toUpload = file;
		}
		cb();
	}, function(cb) {
		if (!toUpload) {
			cb(make_err('No file provided'));
			return;
		}
		if (toUpload.path.slice(-4) !== '.zip') {
			cb(make_err('Provided file is not a ZIP'));
			return;
		}

		gutil.log('Uploading Lambda function "' + functionName + '"...');

		if (opts.profile !== null) {
			AWS.config.credentials = new AWS.SharedIniFileCredentials({ profile: opts.profile });
		}

		AWS.config.update({ region: opts.region });

		var lambda = new AWS.Lambda();
		var stream = this;

		var done = function(err) {
			if (err) {
				cb(make_err(err.message));
				return;
			}
			gutil.log('Lambda function "' + functionName + '" successfully uploaded');
			stream.push(toUpload);
			cb();
		};

		if (typeof params === 'string') {
			// Just updating code
			lambda.updateFunctionCode({
				FunctionName: params,
				ZipFile: toUpload.contents
			}, done);
		} else {
			lambda.getFunctionConfiguration({
				FunctionName: params.FunctionName
			}, function(err) {
				if (err) {
					// Creating a function
					lambda.createFunction(extend({
						Handler: 'index.handler',
						Runtime: 'nodejs'
					}, params, {
						Code: {
							ZipFile: toUpload.contents
						}
					}), done);
				} else {
					// Updating code + config
					lambda.updateFunctionCode({
						FunctionName: params.FunctionName,
						ZipFile: toUpload.contents
					}, function(err) {
						if (err) {
							done(err);
							return;
						}
						lambda.updateFunctionConfiguration(params, done);
					});
				}
			});
		}
	});
};
<commit_msg>Support Publish in lambda_params for update path, closes #4<commit_after>'use strict';
var AWS = require('aws-sdk');
var gutil = require('gulp-util');
var through = require('through2');
var extend = require('xtend');

module.exports = function(params, opts) {
	opts = extend({
		profile: null,
		region: 'us-east-1'
	}, opts);

	var toUpload;
	var functionName = typeof params === 'string'? params : params.FunctionName;

	var make_err = function(message) {
		return new gutil.PluginError('gulp-awslambda', message);
	};

	return through.obj(function(file, enc, cb) {
		if (file.isNull()) {
			cb();
			return;
		}
		if (file.isStream()) {
			cb(make_err('Streaming is not supported'));
			return;
		}
		if (!toUpload) {
			toUpload = file;
		}
		cb();
	}, function(cb) {
		if (!toUpload) {
			cb(make_err('No file provided'));
			return;
		}
		if (toUpload.path.slice(-4) !== '.zip') {
			cb(make_err('Provided file is not a ZIP'));
			return;
		}

		gutil.log('Uploading Lambda function "' + functionName + '"...');

		if (opts.profile !== null) {
			AWS.config.credentials = new AWS.SharedIniFileCredentials({ profile: opts.profile });
		}

		AWS.config.update({ region: opts.region });

		var lambda = new AWS.Lambda();
		var stream = this;

		var done = function(err) {
			if (err) {
				cb(make_err(err.message));
				return;
			}
			gutil.log('Lambda function "' + functionName + '" successfully uploaded');
			stream.push(toUpload);
			cb();
		};

		if (typeof params === 'string') {
			// Just updating code
			lambda.updateFunctionCode({
				FunctionName: params,
				ZipFile: toUpload.contents
			}, done);
		} else {
			lambda.getFunctionConfiguration({
				FunctionName: params.FunctionName
			}, function(err) {
				if (err) {
					// Creating a function
					lambda.createFunction(extend({
						Handler: 'index.handler',
						Runtime: 'nodejs'
					}, params, {
						Code: {
							ZipFile: toUpload.contents
						}
					}), done);
				} else {
					// Updating code + config
					var publish = 'Publish' in params ? {
						Publish: params.Publish
					} : {};
					delete params.Publish;
					lambda.updateFunctionCode(extend({
						FunctionName: params.FunctionName,
						ZipFile: toUpload.contents
					}, publish), function(err) {
						if (err) {
							done(err);
							return;
						}
						lambda.updateFunctionConfiguration(params, done);
					});
				}
			});
		}
	});
};
<|endoftext|>


<commit_before>import { arr } from "lively.lang";
import { parse, stringify } from "lively.ast";
import normalizer from "JS_WALA/normalizer/lib/normalizer";

// type JSSource = string;
// type SMTInput = string;
// type SMTOutput = string;

function funcBody(func) {
  // FunctionDeclaration -> Array<Statement>
  // return function body in SSA-like language
  // TODO remove conditions
  const normalized = normalizer.normalize(func,
    {unify_ret: true, unfold_ifs: true});
  return normalized.body;
}

function preConditions(func) {
  // FunctionDeclaration -> Array<Expression>
  return func.body
    .filter(stmt =>
      stmt.type == "ExpressionStatement" &&
      stmt.expression.type == "CallExpression" &&
      stmt.expression.callee.type == "Identifier" &&
      stmt.expression.callee.name == "requires"
    )
    .map(stmt => stmt.expression.arguments[0]);
}

function postConditions(func) {
  // FunctionDeclaration -> Array<Expression>
  return func.body
    .filter(stmt =>
      stmt.type == "ExpressionStatement" &&
      stmt.expression.type == "CallExpression" &&
      stmt.expression.callee.type == "Identifier" &&
      stmt.expression.callee.name == "ensures"
    )
    .map(stmt => stmt.expression.arguments[0]);
}

const preamble = `
; Values in JavaScript
(declare-datatypes () (
  (JSVal
    (jsnum (numv Int))
    (jsbool (boolv Bool))
    (jsstring (stringv (List Int)))
    jsnull
    jsundefined
    (jsarray (items JSValList))
    (jsobj (props JSPropList)))
  (JSValList empty (cons (car JSVal) (cdr JSValList)))
  (JSProp (prop (key (List Int)) (val JSVal)))
  (JSPropList empty (cons (car JSProp) (cdr JSPropList)))))

; Types in JavaScript
(declare-datatypes () ((JSType JSNum JSBool JSString JSUndefined JSArray JSObj)))

(define-fun _js-typeof ((a JSVal)) JSType
  (ite (is-jsnum a) JSNum
  (ite (is-jsbool a) JSBool
  (ite (is-jsstring a) JSString
  (ite (is-jsnull a) JSObj
  (ite (is-jsundefined a) JSUndefined
  (ite (is-jsarray a) JSArray
  JSObj)))))))

; a >= b
(define-fun _js-geq ((a JSVal) (b JSVal)) JSVal
  (ite (is-jsnum a)
    (ite (is-jsnum b)
      (ite (>= (numv a) (numv b)) (jsbool true) (jsbool false))
      (jsbool false))
    (jsbool false)))

; !!x
(define-fun _js-truthy ((x JSVal)) Bool
  (ite (is-jsnum x)
    (not (= (numv x) 0))
    (boolv x)))
`;

function assertionToSMT(expr) {
  // Expression -> SMTInput
}

function statementToSMT(stmt) {
  // Statement -> SMTInput
}

class Theorem {
  constructor(func, postcondition) {
    this.func = func;
    this.postcondition = postcondition;
  }

  description() {
    return `${this.func.name}:\n${stringify(this.postcondition)}`;
  }

  csystem() {
    if (this._csystem) return this._csystem;

    const parameters = this.func.params.map(p =>
            `(declare-const ${p.name} JSVal)`).join('\n'),
          requirements = preConditions(this.func).map(c =>
            `(assert (_js-truthy ${assertionToSMT(c)}))`).join('\n'),
          body = funcBody(this.func).map(stmt => statementToSMT(stmt)).join('\n'),
          post = `(assert (not (_js-truthy ${assertionToSMT(this.postcondition)})))`;

    return this._csystem = `
      ${preamble}
      ${parameters}
      ${requirements}
      ${body}
      ${post}
      (check-sat)
      (get-model)`;
  }

  async solve() {
    // -> SMTOutput
    if (this._results) return this._results;
    const smt = this.csystem(),
          result = await new Promise(resolve =>
            setTimeout(() => resolve("sat\n(model)\n"), 1000));
    return this._results = result;
  }

  async isSatisfied() {
    // -> Bool
    const res = await this.solve();
    return res.startsWith("sat");
  }
}

function functions(ast) {
  const result = [];
  for (const node of ast.body.body) {
    if (node.type !== "FunctionDeclaration") return;
    result.push(node);
  }
  return result;
}

function theorems(fun) {
  // FunctionDeclaration -> Array<Theorem>
  return postConditions(fun).map(post => new Theorem(fun, post));
}

export function theoremsInSource(src) {
  // JSSource -> Array<Theorem>
  try {
    const ast = parse(src),
          funcs = functions(ast);
    if (!funcs) return [];
    return arr.flatmap(funcs, theorems);
  } catch (e) {
    console.error(e);
    return [];
  }
}<commit_msg>use server z3<commit_after>import { arr } from "lively.lang";
import { parse, stringify } from "lively.ast";
import normalizer from "JS_WALA/normalizer/lib/normalizer";

// type JSSource = string;
// type SMTInput = string;
// type SMTOutput = string;

function funcBody(func) {
  // FunctionDeclaration -> Array<Statement>
  // return function body in SSA-like language
  // TODO remove conditions
  const normalized = normalizer.normalize(func,
    {unify_ret: true, unfold_ifs: true});
  return normalized.body;
}

function preConditions(func) {
  // FunctionDeclaration -> Array<Expression>
  return func.body
    .filter(stmt =>
      stmt.type == "ExpressionStatement" &&
      stmt.expression.type == "CallExpression" &&
      stmt.expression.callee.type == "Identifier" &&
      stmt.expression.callee.name == "requires"
    )
    .map(stmt => stmt.expression.arguments[0]);
}

function postConditions(func) {
  // FunctionDeclaration -> Array<Expression>
  return func.body
    .filter(stmt =>
      stmt.type == "ExpressionStatement" &&
      stmt.expression.type == "CallExpression" &&
      stmt.expression.callee.type == "Identifier" &&
      stmt.expression.callee.name == "ensures"
    )
    .map(stmt => stmt.expression.arguments[0]);
}

const preamble = `
; Values in JavaScript
(declare-datatypes () (
  (JSVal
    (jsnum (numv Int))
    (jsbool (boolv Bool))
    (jsstring (stringv (List Int)))
    jsnull
    jsundefined
    (jsarray (items JSValList))
    (jsobj (props JSPropList)))
  (JSValList empty (cons (car JSVal) (cdr JSValList)))
  (JSProp (prop (key (List Int)) (val JSVal)))
  (JSPropList empty (cons (car JSProp) (cdr JSPropList)))))

; Types in JavaScript
(declare-datatypes () ((JSType JSNum JSBool JSString JSUndefined JSArray JSObj)))

(define-fun _js-typeof ((a JSVal)) JSType
  (ite (is-jsnum a) JSNum
  (ite (is-jsbool a) JSBool
  (ite (is-jsstring a) JSString
  (ite (is-jsnull a) JSObj
  (ite (is-jsundefined a) JSUndefined
  (ite (is-jsarray a) JSArray
  JSObj)))))))

; a >= b
(define-fun _js-geq ((a JSVal) (b JSVal)) JSVal
  (ite (is-jsnum a)
    (ite (is-jsnum b)
      (ite (>= (numv a) (numv b)) (jsbool true) (jsbool false))
      (jsbool false))
    (jsbool false)))

; !!x
(define-fun _js-truthy ((x JSVal)) Bool
  (ite (is-jsnum x)
    (not (= (numv x) 0))
    (boolv x)))
`;

function assertionToSMT(expr) {
  // Expression -> SMTInput
}

function statementToSMT(stmt) {
  // Statement -> SMTInput
}

class Theorem {
  constructor(func, postcondition) {
    this.func = func;
    this.postcondition = postcondition;
  }

  description() {
    return `${this.func.name}:\n${stringify(this.postcondition)}`;
  }

  csystem() {
    if (this._csystem) return this._csystem;

    const parameters = this.func.params.map(p =>
            `(declare-const ${p.name} JSVal)`).join('\n'),
          requirements = preConditions(this.func).map(c =>
            `(assert (_js-truthy ${assertionToSMT(c)}))`).join('\n'),
          body = funcBody(this.func).map(stmt => statementToSMT(stmt)).join('\n'),
          post = `(assert (not (_js-truthy ${assertionToSMT(this.postcondition)})))`;

    return this._csystem = `
      ${preamble}
      ${parameters}
      ${requirements}
      ${body}
      ${post}
      (check-sat)
      (get-model)`;
  }

  async solve() {
    // -> SMTOutput
    if (this._results) return this._results;
    const smt = this.csystem(),
          req = await fetch("/nodejs/Z3server/", {
            method: "POST",
            body: smt
          });
    return this._results = await req.text();
  }

  async isSatisfied() {
    // -> Bool
    const res = await this.solve();
    return res.startsWith("sat");
  }
}

function functions(ast) {
  const result = [];
  for (const node of ast.body.body) {
    if (node.type !== "FunctionDeclaration") return;
    result.push(node);
  }
  return result;
}

function theorems(fun) {
  // FunctionDeclaration -> Array<Theorem>
  return postConditions(fun).map(post => new Theorem(fun, post));
}

export function theoremsInSource(src) {
  // JSSource -> Array<Theorem>
  try {
    const ast = parse(src),
          funcs = functions(ast);
    if (!funcs) return [];
    return arr.flatmap(funcs, theorems);
  } catch (e) {
    console.error(e);
    return [];
  }
}<|endoftext|>


<commit_before>const path = require('path')
    , util = require('util')
    , inspect = (...args) => {
      if (args.length) console.log('\ninspecting from index:')
      args.forEach( obj=>{ console.log(
        util.inspect(obj, {
          depth: 4,
          colors:true,
          maxArrayLength: 5
        })
      )})
    }
    , inspectThis = (ths) => {
      (ths === global) ? console.log('this === global')
        : inspect(ths)
    }

/*********************************************************/

function pluginjector (core, opts ={}){
  if (opts.proto) core = Object.create(core)
  else core = Object.assign({}, core)

  this.getPluginDir = ()=>piInject.pluginDir
  if (opts.dir) piInject.pluginDir = opts.dir

  return piInject

  function piInject (...args){
    const plugins = args.map(plugin => {
      if (typeof plugin === 'string') {
        plugin = getPluginFromFile(plugin)
      }
      traverseAndImportFromFile(plugin, core)
      traverseAndBindThisIfRequested(plugin, core)
      return (plugin)
    })

    Object.assign(core, ...plugins)
    return core
  }
}

module.exports = pluginjector

/*********************************************************/

function traverseAndImportFromFile(obj, parent){
  for (var k in obj) { if (obj.hasOwnProperty(k)){
    if (k === 'pluginjectorNamedFile' && obj[k] == true){
      delete obj[k] // did its job. remove it for cleaner objects
      let keys = Object.keys(obj)
      if (keys.length !== 1)
        throw new Error('Pluginjector found too many properties in namespace wrapper.')
      let plugin = getPluginFromFile(obj[keys[0]], keys[0])
      delete obj[keys[0]]
      Object.assign(obj, plugin)
    }
    if (obj === Object(obj))
      traverseAndImportFromFile(obj[k])
  }}
}

function bindThis (obj, targetThis){
  for (var k in obj){
    if (typeof obj[k] === 'function')
      obj[k] = obj[k].bind(targetThis)
  }
}

function traverseAndBindThisIfRequested(obj, targetThis){
  for (var k in obj) {
    if (obj.hasOwnProperty(k)){
      if (k === 'pluginjectorBindThis' && obj[k] == true){
        delete obj[k] // did its job. remove it for cleaner objects
        bindThis(obj, targetThis)
      }
      if (obj === Object(obj))
        traverseAndBindThisIfRequested(obj[k], targetThis)
    }
  }
}

function getPluginFromFile(file, key){

  key = key || makeKeyNameFromFilePath(file)
  // check if string is only word chars
  let nameMatch = file.match(/^[\w-]*$/)
  // if only name provided then build path from pluginDir
  let dir = this.getPluginDir()
  if (nameMatch && dir) {
    let file = path.join(dir, nameMatch[0])

    file = [dir, nameMatch[0]].join('/')
    return getPluginFromFile(file, key)
  }
  let obj = {}
  // if looks like relative path, then make absolute
  if ( ! file.match(/^(\/|[A-Za-z]:)/) )
    file = path.join(process.cwd(),file)
  try{
    obj[key] = require(file)
    return obj
  }catch(e){ throw e }
}

function makeKeyNameFromFilePath(path){
  // extract name of file without directories or extension
  return path.match(/[^\\\/]+(?=\.[\w]+$)|[^\\\/]+$/)[0]
    // convert dashes or spaces to camelcase
    .replace(/(-|\s|\.)+([\w])/g, (...args) => {
      return args[2].toUpperCase()
    })
}
<commit_msg>rm  debugging helper<commit_after>const path = require('path')

/*********************************************************/

function pluginjector (core, opts ={}){
  if (opts.proto) core = Object.create(core)
  else core = Object.assign({}, core)

  this.getPluginDir = ()=>piInject.pluginDir
  if (opts.dir) piInject.pluginDir = opts.dir

  return piInject

  function piInject (...args){
    const plugins = args.map(plugin => {
      if (typeof plugin === 'string') {
        plugin = getPluginFromFile(plugin)
      }
      traverseAndImportFromFile(plugin, core)
      traverseAndBindThisIfRequested(plugin, core)
      return (plugin)
    })

    Object.assign(core, ...plugins)
    return core
  }
}

module.exports = pluginjector

/*********************************************************/

function traverseAndImportFromFile(obj, parent){
  for (var k in obj) { if (obj.hasOwnProperty(k)){
    if (k === 'pluginjectorNamedFile' && obj[k] == true){
      delete obj[k] // did its job. remove it for cleaner objects
      let keys = Object.keys(obj)
      if (keys.length !== 1)
        throw new Error('Pluginjector found too many properties in namespace wrapper.')
      let plugin = getPluginFromFile(obj[keys[0]], keys[0])
      delete obj[keys[0]]
      Object.assign(obj, plugin)
    }
    if (obj === Object(obj))
      traverseAndImportFromFile(obj[k])
  }}
}

function bindThis (obj, targetThis){
  for (var k in obj){
    if (typeof obj[k] === 'function')
      obj[k] = obj[k].bind(targetThis)
  }
}

function traverseAndBindThisIfRequested(obj, targetThis){
  for (var k in obj) {
    if (obj.hasOwnProperty(k)){
      if (k === 'pluginjectorBindThis' && obj[k] == true){
        delete obj[k] // did its job. remove it for cleaner objects
        bindThis(obj, targetThis)
      }
      if (obj === Object(obj))
        traverseAndBindThisIfRequested(obj[k], targetThis)
    }
  }
}

function getPluginFromFile(file, key){

  key = key || makeKeyNameFromFilePath(file)
  // check if string is only word chars
  let nameMatch = file.match(/^[\w-]*$/)
  // if only name provided then build path from pluginDir
  let dir = this.getPluginDir()
  if (nameMatch && dir) {
    let file = path.join(dir, nameMatch[0])

    file = [dir, nameMatch[0]].join('/')
    return getPluginFromFile(file, key)
  }
  let obj = {}
  // if looks like relative path, then make absolute
  if ( ! file.match(/^(\/|[A-Za-z]:)/) )
    file = path.join(process.cwd(),file)
  try{
    obj[key] = require(file)
    return obj
  }catch(e){ throw e }
}

function makeKeyNameFromFilePath(path){
  // extract name of file without directories or extension
  return path.match(/[^\\\/]+(?=\.[\w]+$)|[^\\\/]+$/)[0]
    // convert dashes or spaces to camelcase
    .replace(/(-|\s|\.)+([\w])/g, (...args) => {
      return args[2].toUpperCase()
    })
}
<|endoftext|>


<commit_before>// tags
// ----
// TODO: better ES6+ support
// FIXME: fix non-working patterns
// BUG: there's really something fishy about this
// NOBUG: no that's OK
// ???: what the flying fuck?
// !!!: dear god!
// HACK: deployment is in 15 minutes
// XXX: I. Must. Finish. That. Mess. Quickly.

// arrays
// ------
let arr_lit = [
	1, 3, 4
];
let arr_lit_inline = [1,4];

// objects
// -------
var obj_lit = {
	obj_lit_prop_foo: 123,
	obj_lit_prop_bar : "eee",
	obj_lit_prop_method : function(){
		return this;
	},
	obj_lit_prop_qux : /regexp/
};
var obj_lit_inline = { prop_baz: 1 };

// constructors & methods
// ----------------------
var Constr_var = function() {
	this.constr_var_meth = function() {
		return true;
	};
};
const Constr_const = function() {
	this.constr_const_meth = function() {
		return true;
	};
};
let Constr_let = function() {
	this.constr_let_meth = function() {
		return true;
	};
};

// functions
// ---------
function function_basic() {
	return 1;
}
(function function_iife() {
	return 2;
})();
const function_const = function() {
	return 3;
};
const function_arrow = (arg) => arg;

// generators
// ----------
function* generator_func1() {
	var generator_func1_iterator = 0;
	while(true)
		yield iterator1++;
}
function *generator_func2() {
	var generator_func2_iterator = 0;
	while(true)
		yield iterator2++;
}
function * generator_func3() {
	var generator_func3_iterator = 0;
	while(true)
		yield iterator3++;
}
function*generator_func4() {
	var generator_func4_iterator = 0;
	while(true)
		yield iterator4++;
}
const generator_func5 = function* () {
	var generator_func5_iterator = 0;
	while(true)
		yield iterator5++;
};
const generator_func6 = function * () {
	var generator_func6_iterator = 0;
	while(true)
		yield iterator6++;
};

// classes
// -------
class ClassName {
	constructor(prop) {
		this.cl_constr_prop = prop;
		this.cl_constr_meth = function(){
			return 666;
		};
	}
	static class_meth_static() {
		return 1;
	}
	class_meth_proto() {
		return 2;
	}
	class_meth_es6 = (foo) => {
		console.log(1);
	}
	if (foo) {
		console.log(1);
	}
	for (var i = 0, len = things.length; i < len; i++) {
		console.log(1);
	}
	* class_meth_generator() {
		var index = 0;
		while (true)
			yield index++;
	}
}

// variables
// ---------
const var_const_number = 1;
var var_var_regexp = /regexp/;
let var_let_single_quotes = 'foo';
let var_let_double_quotes = "bar";
var var_class_instance = new ClassName();
let let_class_instance = new ClassName();
const const_class_instance = new ClassName();

// imports
// -------
import { imp01 }
import { * as imp02 } // imp02
import { foo as imp03 } // imp03
import { imp04, * as imp05 } // imp05
import { imp06, bar as imp07 } // imp07
import { imp08, imp09, * as imp10 } // imp10
import { imp11, imp12, baz as imp13 } // imp13
import { * as imp14, * as imp15, * as imp16 } // imp14, imp15, imp16
import { foo as imp17, bar as imp18, baz as imp19 } // imp17, imp18, imp19
import { imp20, imp21, imp22 }
import imp23
import * as imp24 // imp24
import foo as imp25 // imp25
import imp26, * as imp27 // imp27
import imp28, bar as imp29 // imp29
import imp30, imp31, * as imp32 // imp32
import imp33, imp34, baz as imp35 // imp35
import * as imp36, * as imp37, * as imp38 // imp36, imp37, imp38
import foo as imp39, bar as imp40, baz as imp41 // imp39, imp40, imp41
import imp42, imp43, imp44

// imports (flow)
// --------------
import type ClassFoo1 from "./ExportDefault_Class";
import type {ClassFoo2} from "./ExportNamed_Class";
import type {ClassFoo4, ClassFoo5} from "./ExportCJSNamed_Class";
import typeof ClassFoo1T from "./ExportDefault_Class";
import typeof {ClassFoo2 as ClassFoo2T} from "./ExportNamed_Class";
import typeof * as ModuleNSObjT from "./ExportNamed_Multi";

// exports
// -------
export { exp01, exp02, exp03 };
export { variable1 as exp04, variable2 as exp05}; // exp04; exp05
export let exp06, exp07; // exp06, exp07
export var exp08, exp09; // exp08, exp09
export let exp10 = 1, exp11 = 2; // exp10, exp11
export const exp12 = 1, exp13 = 2; // exp12, exp13
export var exp14 = 1, exp15 = 2; // exp14, exp15
export function exp16() {} // exp16

// default exports
export default { exp17, exp18, exp19 };
export default { variable1 as exp20, variable2 as exp21}; // exp20; exp21
export default let exp22, exp23; // exp22, exp23
export default var exp24, exp25; // exp24, exp25
export default let exp26 = 1, exp27 = 2; // exp26, exp27
export default const exp28 = 1, exp29 = 2; // exp28, exp29
export default var exp30 = 1, exp31 = 2; // exp30, exp31
export default function exp32() {} // exp32

/*

Problems with imports and exports

const foo -> export foo -> import foo
	tag const foo

const foo -> export foo -> import foo as bar
	tag const foo AND import foo as bar

const foo -> export foo as bar -> import bar
	tag const foo AND export foo as bar

const foo -> export foo  as bar -> import bar at baz
	tag const foo AND export foo as bar AND import bar as baz

*/

// styled components
// -----------------
var Comp01 = styled(Box)`
	border-radius: 0px 5pt 5pt 5pt;
`;
let Comp02 = styled(Box)`
	border-radius: 0px 5pt 5pt 5pt;
`;
const Comp03 = styled(Box)`
	border-radius: 0px 5pt 5pt 5pt;
`;
var Comp04 = createGlobalStyle`
	body {
		color: ${props => (props.whiteColor ? 'white' : 'black')};
	}
`;
let Comp05 = createGlobalStyle`
	body {
		color: ${props => (props.whiteColor ? 'white' : 'black')};
	}
`;
const Comp06 = createGlobalStyle`
	body {
		color: ${props => (props.whiteColor ? 'white' : 'black')};
	}
`;
<commit_msg>Added more cases<commit_after>// tags
// ----
// TODO: better ES6+ support
// FIXME: fix non-working patterns
// BUG: there's really something fishy about this
// NOBUG: no that's OK
// ???: what the flying fuck?
// !!!: dear god!
// HACK: deployment is in 15 minutes
// XXX: I. Must. Finish. That. Mess. Quickly.

// arrays
// ------
let arr_lit = [
	1, 3, 4
];
let arr_lit_inline = [1,4];

// objects
// -------
var obj_lit = {
	obj_lit_prop_number: 123,
	obj_lit_prop_string : "eee",
	obj_lit_prop_array: [
		"foo"
	],
	obj_lit_prop_object : {
		inner_prop: bar
	},
	obj_lit_prop_regexp : /regexp/,
	obj_lit_prop_method : function(
		arg1,
		arg2
	){
		return this;
	},
	obj_lit_prop_method_arrow : (
		arg1,
		arg2
	) => {
		console.log(1);
	}
};
var obj_lit_inline = { obj_lit_inline_prop: 1 };
this.this_prop = {
	this_inner_prop: "bar"
};
this.this_prop_method = function(
	arg1,
	arg2
){
	return this;
}
this.this_prop_method_arrow = (
	arg1,
	arg2
) => {
	console.log(1);
};

// constructors & methods
// ----------------------
var Constr_var = function() {
	this.constr_var_meth = function() {
		return true;
	};
};
const Constr_const = function() {
	this.constr_const_meth = function() {
		return true;
	};
};
let Constr_let = function() {
	this.constr_let_meth = function() {
		return true;
	};
};

// functions
// ---------
function function_basic() {
	return 1;
}
(function function_iife() {
	return 2;
})();
const function_const = function() {
	return 3;
};
const function_arrow = (arg) => arg;
const function_arrow_no_parentheses = arg => arg;
var function_arrow_multiline = (
	foo,
	bar
) => {
	return 1;
};

// generators
// ----------
function* generator_func1() {
	var generator_func1_iterator = 0;
	while(true)
		yield iterator1++;
}
function *generator_func2() {
	var generator_func2_iterator = 0;
	while(true)
		yield iterator2++;
}
function * generator_func3() {
	var generator_func3_iterator = 0;
	while(true)
		yield iterator3++;
}
function*generator_func4() {
	var generator_func4_iterator = 0;
	while(true)
		yield iterator4++;
}
const generator_func5 = function* () {
	var generator_func5_iterator = 0;
	while(true)
		yield iterator5++;
};
const generator_func6 = function * () {
	var generator_func6_iterator = 0;
	while(true)
		yield iterator6++;
};

// classes
// -------
class ClassName {
	constructor(prop) {
		this.class_constr_prop = prop;
		this.class_constr_meth = function(){
			return 666;
		};
	}
	class_meth_equal = function(
		arg1,
		arg2
	) {
		return this;
	};
	class_meth_equal_arrow = (
		arg1,
		arg2
	) => {
		console.log(1);
	};
	static class_meth_static() {
		return 1;
	}
	class_meth_proto() {
		return 2;
	}
	class_meth_es6 = (foo) => {
		console.log(1);
	}
	if (foo) {
		console.log(1);
	}
	for (var i = 0, len = things.length; i < len; i++) {
		console.log(1);
	}
	* class_meth_generator() {
		var index = 0;
		while (true)
			yield index++;
	}
}

// variables
// ---------
const var_const_number = 1;
var var_var_regexp = /regexp/;
let var_let_single_quotes = 'foo';
let var_let_double_quotes = "bar";
var var_class_instance = new ClassName();
let let_class_instance = new ClassName();
const const_class_instance = new ClassName();

// imports
// -------
import { imp01 }
import { * as imp02 } // imp02
import { foo as imp03 } // imp03
import { imp04, * as imp05 } // imp05
import { imp06, bar as imp07 } // imp07
import { imp08, imp09, * as imp10 } // imp10
import { imp11, imp12, baz as imp13 } // imp13
import { * as imp14, * as imp15, * as imp16 } // imp14, imp15, imp16
import { foo as imp17, bar as imp18, baz as imp19 } // imp17, imp18, imp19
import { imp20, imp21, imp22 }
import imp23
import * as imp24 // imp24
import foo as imp25 // imp25
import imp26, * as imp27 // imp27
import imp28, bar as imp29 // imp29
import imp30, imp31, * as imp32 // imp32
import imp33, imp34, baz as imp35 // imp35
import * as imp36, * as imp37, * as imp38 // imp36, imp37, imp38
import foo as imp39, bar as imp40, baz as imp41 // imp39, imp40, imp41
import imp42, imp43, imp44

// imports (flow)
// --------------
import type ClassFoo1 from "./ExportDefault_Class";
import type {ClassFoo2} from "./ExportNamed_Class";
import type {ClassFoo4, ClassFoo5} from "./ExportCJSNamed_Class";
import typeof ClassFoo1T from "./ExportDefault_Class";
import typeof {ClassFoo2 as ClassFoo2T} from "./ExportNamed_Class";
import typeof * as ModuleNSObjT from "./ExportNamed_Multi";

// exports
// -------
export { exp01, exp02, exp03 };
export { variable1 as exp04, variable2 as exp05}; // exp04; exp05
export let exp06, exp07; // exp06, exp07
export var exp08, exp09; // exp08, exp09
export let exp10 = 1, exp11 = 2; // exp10, exp11
export const exp12 = 1, exp13 = 2; // exp12, exp13
export var exp14 = 1, exp15 = 2; // exp14, exp15
export function exp16() {} // exp16

// default exports
export default { exp17, exp18, exp19 };
export default { variable1 as exp20, variable2 as exp21}; // exp20; exp21
export default let exp22, exp23; // exp22, exp23
export default var exp24, exp25; // exp24, exp25
export default let exp26 = 1, exp27 = 2; // exp26, exp27
export default const exp28 = 1, exp29 = 2; // exp28, exp29
export default var exp30 = 1, exp31 = 2; // exp30, exp31
export default function exp32() {} // exp32

/*

Problems with imports and exports

const foo -> export foo -> import foo
	tag const foo

const foo -> export foo -> import foo as bar
	tag const foo AND import foo as bar

const foo -> export foo as bar -> import bar
	tag const foo AND export foo as bar

const foo -> export foo  as bar -> import bar at baz
	tag const foo AND export foo as bar AND import bar as baz

*/

// styled components
// -----------------
var Comp01 = styled(Box)`
	border-radius: 0px 5pt 5pt 5pt;
`;
let Comp02 = styled(Box)`
	border-radius: 0px 5pt 5pt 5pt;
`;
const Comp03 = styled(Box)`
	border-radius: 0px 5pt 5pt 5pt;
`;
var Comp04 = createGlobalStyle`
	body {
		color: ${props => (props.whiteColor ? 'white' : 'black')};
	}
`;
let Comp05 = createGlobalStyle`
	body {
		color: ${props => (props.whiteColor ? 'white' : 'black')};
	}
`;
const Comp06 = createGlobalStyle`
	body {
		color: ${props => (props.whiteColor ? 'white' : 'black')};
	}
`;
<|endoftext|>


<commit_before>'use strict';

//追加モジュールの宣言
import fs from 'fs'
import apiClient from './utils/ApiClient'
import electron from 'electron'
import storage from 'electron-json-storage'

import nodeStatic from 'node-static'
import queryString from 'query-string'

let file = new nodeStatic.Server(__dirname);

let {dialog} = require('electron');

// アプリケーションをコントロールするモジュール
let app = electron.app;

// ウィンドウを作成するモジュール
let BrowserWindow = electron.BrowserWindow;

//Node.js側とHTML側で通信をするモジュール
let ipcMain = electron.ipcMain;

// スコープとアクセストークン関係
let SCOPES = [
    'https://www.googleapis.com/auth/youtube',
    'https://www.googleapis.com/auth/youtube.force-ssl',
    'https://www.googleapis.com/auth/youtube.readonly',
    'https://www.googleapis.com/auth/youtubepartner'
];

// API KEY
let APIKEY_PATH = __dirname + '/.credentials/apikey';

// OAuth 2.0 クライアント ID
let CREDENTIALS_PATH = __dirname + '/.credentials/client_secret.json';

let apikey = fs.readFileSync(APIKEY_PATH, "utf-8");

// プレイヤーウィンドウ
let playerWindow;

// 認証用ウィンドウ
let authWindow;

// コントローラーウィンドウ
let controllerWindow;

// youtube apiクライアント
let api;

//
require('http').createServer(function (request, response) {
    request.addListener('end', function () {
        file.serve(request, response);
    }).resume();
}).listen(7170);

// プレイヤーウィンドウ表示処理
let createPlayerWindow = (callback) => {
    if (playerWindow != null) {
        callback();
        return;
    }
    let {width, height} = electron.screen.getPrimaryDisplay().workAreaSize
    let windowWidth = 420;
    let windowHeight = 320;

    playerWindow = new BrowserWindow({
        width: windowWidth,
        height: windowHeight,
        x: width - windowWidth,
        y: height - windowHeight,
        frame: false
    });
    playerWindow.loadURL('file://' + __dirname + '/player.html');
    playerWindow.on('closed', () => {
        playerWindow = null;
    });
    playerWindow.webContents.on("dom-ready", () => {
        callback();
    });
    playerWindow.setAlwaysOnTop(true);
};

// 認証用ウィンドウ表示処理
let createAuthWindow = (callback) => {

    // 認証用URL取得
    let authUrl = api.getAuthUrl(SCOPES);

    authWindow = new BrowserWindow({width: 800, height: 600});
    authWindow.loadURL(authUrl);
    authWindow.openDevTools();
    authWindow.on('closed', () => {
        authWindow = null;
    });
    // 認証ウィンドウの読み込み完了後の処理
    authWindow.webContents.on("dom-ready", (e) => {
        callback();
    });
};

// コントローラーウィンドウ表示処理
let createControllerWindow = (callback) => {
    if (controllerWindow != null) {
        return;
    }
    controllerWindow = new BrowserWindow({width: 800, height: 600});
    controllerWindow.loadURL('file://' + __dirname + '/controller.html');
    controllerWindow.openDevTools();
    controllerWindow.on('closed', () => {
        app.quit();
    });
    controllerWindow.webContents.on("dom-ready", () => {
        callback();
    });
};

// 保存したtoken情報を取得
let getSavedToken = () => {
    return new Promise((resolve, reject) => {
        storage.get('token', function(error, data) {
            if (error) {
                reject(error);
                return;
            }
            const saved_tokens = data;
            resolve(saved_tokens);
        });
    });
};

// アクセストークンを保存する
let storeToken = (token) => {
    return new Promise((resolve, reject) => {
        storage.set('token', token, function(error) {
            if (error) {
                reject(error);
                return;
            }
            resolve();
        });
    });
};

// アプリケーション資格ファイルチェック
let getCredentials = () => {
    return new Promise((resolve, reject) => {
        fs.readFile(CREDENTIALS_PATH, 'utf-8', (err, text) => {

            if (err) {
                reject(err);
                return;
            }

            let credentials = JSON.parse(text);

            if (!credentials.web ||
                !credentials.web.client_id ||
                !credentials.web.client_secret ||
                !credentials.web.redirect_uris[0])
            {
                reject("[no credential file]");
                return;
            }

            resolve(credentials);
        });
    });
};

// 起動時に呼ばれるイベント
app.on('ready', async () => {

    try {

        let credentials = await getCredentials();

        api = new apiClient(credentials);

        // 認証オブジェクト取得
        let oauth = api.oauth;

        // get saved token
        let saved_tokens = await getSavedToken();

        if (Object.keys(saved_tokens).length === 0 && !saved_tokens.access_token) {

            createControllerWindow(() => {});
        } else {

            // 認証済トークンを認証用オブジェクトにセット
            oauth.setCredentials({
                access_token: saved_tokens.access_token
            });

            api.setOauth(oauth);

            createControllerWindow(() => {});
        }

    } catch(error) {
        console.log( error );
        dialog.showErrorBox("application error", "Please notify the kuniiskywalker@gmail.com");
        app.quit();
    }
});

// ウィンドウを閉じた時のイベント
app.on('window-all-closed', () => {
    if (process.platform != 'darwin') {
        app.quit();
    }
});

app.on('activate', () => {
    if (playerWindow != null) {
    }
});

// 非同期プロセス通信

// Actions
ipcMain.on('show-player', async(event, ...args) => {
    if (playerWindow != null) {
        playerWindow.show();
        event.sender.send('show-player');
    }
});

ipcMain.on('hide-player', async(event, ...args) => {
    if (playerWindow != null) {
        playerWindow.hide();
        event.sender.send('hide-player');
    }
});

ipcMain.on('open-auth-page', (event, ...args) => {
    createAuthWindow(async() => {
        try {

            // 認証後のコールバックURL GETパラーメータからtokenをとりだす
            let url = authWindow.webContents.getURL();
            let search = url.replace(/(.+?\?)(.+)/, "$2");
            let parsed = queryString.parse(search);
            let token = parsed["code"];

            // 認証オブジェクト取得
            let oauth = api.oauth;

            let token_info = await api.getToken(token);

            oauth.setCredentials({
                access_token: token_info.access_token
            });

            api.setOauth(oauth);

            // save token
            await storeToken(token_info);

            authWindow.close();

        } catch (error) {
            console.log(error);
        }
    });
});

ipcMain.on('fetch-subscriptions', async(event, ...args) => {
    try {
        let subscriptions = api.fetchSubscriptions(apikey);
        event.sender.send('fetch-subscriptions', subscriptions);
    } catch (error) {
        console.log(error);
    }
});
ipcMain.on('search-channel', async(event, q) => {
    try {
        let channels = api.searchChannel(apikey, q);
        event.sender.send('search-channel', channels);
    } catch (error) {
        console.log(error);
    }
});
ipcMain.on('search-video', async(event, q) => {
    try {
        let videos = await api.searchVideo(apikey, q);
        event.sender.send('search-video', videos);
    } catch (error) {
        console.log(error);
    }
});
ipcMain.on('search-playlist', async(event, q) => {
    try {
        let playlist = api.searchPlaylist(apikey, q);
        event.sender.send('search-playlist', playlist);
    } catch (error) {
        console.log(error);
    }
});
ipcMain.on('select-video', (event, video) => {
    createPlayerWindow(() => {
        playerWindow.send('play-video', video);
    });
});
<commit_msg>fix 動画を取得する非同期処理にawaitがぬけてたので追加<commit_after>'use strict';

//追加モジュールの宣言
import fs from 'fs'
import apiClient from './utils/ApiClient'
import electron from 'electron'
import storage from 'electron-json-storage'

import nodeStatic from 'node-static'
import queryString from 'query-string'

let file = new nodeStatic.Server(__dirname);

let {dialog} = require('electron');

// アプリケーションをコントロールするモジュール
let app = electron.app;

// ウィンドウを作成するモジュール
let BrowserWindow = electron.BrowserWindow;

//Node.js側とHTML側で通信をするモジュール
let ipcMain = electron.ipcMain;

// スコープとアクセストークン関係
let SCOPES = [
    'https://www.googleapis.com/auth/youtube',
    'https://www.googleapis.com/auth/youtube.force-ssl',
    'https://www.googleapis.com/auth/youtube.readonly',
    'https://www.googleapis.com/auth/youtubepartner'
];

// API KEY
let APIKEY_PATH = __dirname + '/.credentials/apikey';

// OAuth 2.0 クライアント ID
let CREDENTIALS_PATH = __dirname + '/.credentials/client_secret.json';

let apikey = fs.readFileSync(APIKEY_PATH, "utf-8");

// プレイヤーウィンドウ
let playerWindow;

// 認証用ウィンドウ
let authWindow;

// コントローラーウィンドウ
let controllerWindow;

// youtube apiクライアント
let api;

//
require('http').createServer(function (request, response) {
    request.addListener('end', function () {
        file.serve(request, response);
    }).resume();
}).listen(7170);

// プレイヤーウィンドウ表示処理
let createPlayerWindow = (callback) => {
    if (playerWindow != null) {
        callback();
        return;
    }
    let {width, height} = electron.screen.getPrimaryDisplay().workAreaSize
    let windowWidth = 420;
    let windowHeight = 320;

    playerWindow = new BrowserWindow({
        width: windowWidth,
        height: windowHeight,
        x: width - windowWidth,
        y: height - windowHeight,
        frame: false
    });
    playerWindow.loadURL('file://' + __dirname + '/player.html');
    playerWindow.on('closed', () => {
        playerWindow = null;
    });
    playerWindow.webContents.on("dom-ready", () => {
        callback();
    });
    playerWindow.setAlwaysOnTop(true);
};

// 認証用ウィンドウ表示処理
let createAuthWindow = (callback) => {

    // 認証用URL取得
    let authUrl = api.getAuthUrl(SCOPES);

    authWindow = new BrowserWindow({width: 800, height: 600});
    authWindow.loadURL(authUrl);
    authWindow.openDevTools();
    authWindow.on('closed', () => {
        authWindow = null;
    });
    // 認証ウィンドウの読み込み完了後の処理
    authWindow.webContents.on("dom-ready", (e) => {
        callback();
    });
};

// コントローラーウィンドウ表示処理
let createControllerWindow = (callback) => {
    if (controllerWindow != null) {
        return;
    }
    controllerWindow = new BrowserWindow({width: 800, height: 600});
    controllerWindow.loadURL('file://' + __dirname + '/controller.html');
    controllerWindow.openDevTools();
    controllerWindow.on('closed', () => {
        app.quit();
    });
    controllerWindow.webContents.on("dom-ready", () => {
        callback();
    });
};

// 保存したtoken情報を取得
let getSavedToken = () => {
    return new Promise((resolve, reject) => {
        storage.get('token', function(error, data) {
            if (error) {
                reject(error);
                return;
            }
            const saved_tokens = data;
            resolve(saved_tokens);
        });
    });
};

// アクセストークンを保存する
let storeToken = (token) => {
    return new Promise((resolve, reject) => {
        storage.set('token', token, function(error) {
            if (error) {
                reject(error);
                return;
            }
            resolve();
        });
    });
};

// アプリケーション資格ファイルチェック
let getCredentials = () => {
    return new Promise((resolve, reject) => {
        fs.readFile(CREDENTIALS_PATH, 'utf-8', (err, text) => {

            if (err) {
                reject(err);
                return;
            }

            let credentials = JSON.parse(text);

            if (!credentials.web ||
                !credentials.web.client_id ||
                !credentials.web.client_secret ||
                !credentials.web.redirect_uris[0])
            {
                reject("[no credential file]");
                return;
            }

            resolve(credentials);
        });
    });
};

// 起動時に呼ばれるイベント
app.on('ready', async () => {

    try {

        let credentials = await getCredentials();

        api = new apiClient(credentials);

        // 認証オブジェクト取得
        let oauth = api.oauth;

        // get saved token
        let saved_tokens = await getSavedToken();

        if (Object.keys(saved_tokens).length === 0 && !saved_tokens.access_token) {

            createControllerWindow(() => {});
        } else {

            // 認証済トークンを認証用オブジェクトにセット
            oauth.setCredentials({
                access_token: saved_tokens.access_token
            });

            api.setOauth(oauth);

            createControllerWindow(() => {});
        }

    } catch(error) {
        console.log( error );
        dialog.showErrorBox("application error", "Please notify the kuniiskywalker@gmail.com");
        app.quit();
    }
});

// ウィンドウを閉じた時のイベント
app.on('window-all-closed', () => {
    if (process.platform != 'darwin') {
        app.quit();
    }
});

app.on('activate', () => {
    if (playerWindow != null) {
    }
});

// 非同期プロセス通信

// Actions
ipcMain.on('show-player', async(event, ...args) => {
    if (playerWindow != null) {
        playerWindow.show();
        event.sender.send('show-player');
    }
});

ipcMain.on('hide-player', async(event, ...args) => {
    if (playerWindow != null) {
        playerWindow.hide();
        event.sender.send('hide-player');
    }
});

ipcMain.on('open-auth-page', (event, ...args) => {
    createAuthWindow(async() => {
        try {

            // 認証後のコールバックURL GETパラーメータからtokenをとりだす
            let url = authWindow.webContents.getURL();
            let search = url.replace(/(.+?\?)(.+)/, "$2");
            let parsed = queryString.parse(search);
            let token = parsed["code"];

            // 認証オブジェクト取得
            let oauth = api.oauth;

            let token_info = await api.getToken(token);

            oauth.setCredentials({
                access_token: token_info.access_token
            });

            api.setOauth(oauth);

            // save token
            await storeToken(token_info);

            authWindow.close();

        } catch (error) {
            console.log(error);
        }
    });
});

ipcMain.on('fetch-subscriptions', async(event, ...args) => {
    try {
        let subscriptions = await api.fetchSubscriptions(apikey);
        event.sender.send('fetch-subscriptions', subscriptions);
    } catch (error) {
        console.log(error);
    }
});
ipcMain.on('search-channel', async(event, q) => {
    try {
        let channels = await api.searchChannel(apikey, q);
        event.sender.send('search-channel', channels);
    } catch (error) {
        console.log(error);
    }
});
ipcMain.on('search-video', async(event, q) => {
    try {
        let videos = await api.searchVideo(apikey, q);
        event.sender.send('search-video', videos);
    } catch (error) {
        console.log(error);
    }
});
ipcMain.on('search-playlist', async(event, q) => {
    try {
        let playlist = await api.searchPlaylist(apikey, q);
        event.sender.send('search-playlist', playlist);
    } catch (error) {
        console.log(error);
    }
});
ipcMain.on('select-video', (event, video) => {
    createPlayerWindow(() => {
        playerWindow.send('play-video', video);
    });
});
<|endoftext|>


<commit_before>var express = require('express');
var app = express();

app.set('port', (process.env.PORT || 5000));
app.get('/', function (req, res) {
	res.send("Hello!");
});

app.listen(app.get('port'), function() {
  console.log("Node app is running at:" + app.get('port'));
});<commit_msg>Checking something<commit_after>var express = require('express');
var app = express();

app.set('port', (process.env.PORT || 5000));
app.get('/', function (req, res) {
	res.send('index.html');
});

app.listen(app.get('port'), function() {
  console.log("Node app is running at:" + app.get('port'));
});<|endoftext|>


<commit_before>var request = require('request')
  , validUrl = require('valid-url')
  , userAgent = 'html-validator v0.0.7'
  ;

function mkReqOpts(opts){
  var newOpts = {
    uri: 'http://validator.w3.org/nu/',
    headers: {
      'User-Agent' : userAgent
    },
    qs: {out:opts.format},
    method: 'GET'
  };

  if(opts.validator){
    newOpts.uri = opts.validator;
  }

  if(opts.url){
    newOpts.qs.doc = opts.url;
  }

  if(opts.data){
    newOpts.body = opts.data;
    newOpts.method = 'POST';
    newOpts.headers = {
      'Content-Type': 'text/html; charset=utf-8',
      'User-Agent' : userAgent
    };
  }

  return newOpts;
}

module.exports = function validator(opts, callback){

  if(!opts.format){
    return callback(new Error('Missing required param: format'), null)
  }

  if(!opts.url && !opts.data){
    return callback(new Error('Missing required params: url or data'), null)
  }

  if(opts.url && !validUrl.isWebUri(opts.url)){
    return callback(new Error('Invalid url'), null);
  }

  var reqOpts = mkReqOpts(opts);

  request(reqOpts, function(error, response, result){

    if(error){
      return callback(error, null);
    }

    var data = opts.format == 'json' ? JSON.parse(result) : result;

    return callback(null, data);

  });
};<commit_msg>Adds json as default format<commit_after>var request = require('request')
  , validUrl = require('valid-url')
  , userAgent = 'html-validator v0.0.7'
  ;

function mkReqOpts(opts){
  var newOpts = {
    uri: 'http://validator.w3.org/nu/',
    headers: {
      'User-Agent' : userAgent
    },
    qs: {
          out:opts.format || 'json'
    },
    method: 'GET'
  };

  if(opts.validator){
    newOpts.uri = opts.validator;
  }

  if(opts.url){
    newOpts.qs.doc = opts.url;
  }

  if(opts.data){
    newOpts.body = opts.data;
    newOpts.method = 'POST';
    newOpts.headers = {
      'Content-Type': 'text/html; charset=utf-8',
      'User-Agent' : userAgent
    };
  }

  return newOpts;
}

module.exports = function validator(opts, callback){

  if(!opts.url && !opts.data){
    return callback(new Error('Missing required params: url or data'), null)
  }

  if(opts.url && !validUrl.isWebUri(opts.url)){
    return callback(new Error('Invalid url'), null);
  }

  var reqOpts = mkReqOpts(opts);

  request(reqOpts, function(error, response, result){

    if(error){
      return callback(error, null);
    }

    var data = opts.format == 'json' ? JSON.parse(result) : result;

    return callback(null, data);

  });
};<|endoftext|>


<commit_before>var fs = require('fs');
var rtmpdump = require('rtmpdump');
var schedule = require('node-schedule');
var config = require('./config.json');
var vorpal = require('vorpal')();

var videoURL = config.videoURL;
//TODO: Utility function for log formatting

function streamError(err, callback) {
    //TODO: Check against broadcast schedule, resume if necessary
    vorpal.log(new Date().toLocaleString() + ' > ' + 'Connection error.');
    vorpal.log(new Date().toLocaleString() + ' > ' + '**** ' + err);
    if (typeof callback === "function") {
        callback();
    }
}

function pingStream(record = false, timeout = 15, persist = false) {
    //TODO: progress bar to show timeout status
    var options = {
        rtmp: videoURL,
        stop: 1,
        live: null,
        timeout: timeout
    }

    stream = rtmpdump.createStream(options);

    vorpal.hide();
    vorpal.log(new Date().toLocaleString() + ' > ' + 'Checking if stream is live...');

    stream.on('connected', function (info) {
        vorpal.log(new Date().toLocaleString() + ' > ' + 'Stream is live.');
        if (record) {
            getStream();
        }
    });

    stream.on('error', function (err) {
        streamError(err, function () {
            if (persist) {
                pingStream(record, timeout, persist);
            }
        });
        vorpal.show();
    });

    if (typeof callback === "function") {
        callback();
    }
}

function getStream() {

    var options = {
        rtmp: videoURL,
        stop: 3630,
        live: null,
        timeout: 5
    },
    stream = rtmpdump.createStream(options);

    vorpal.log(new Date().toLocaleString() + ' > ' + 'Stream fetch initiated');

    stream.on('connected', function (info) {
        vorpal.log(new Date().toLocaleString() + ' > ' + 'Stream connected');
        //vorpal.log(info);
        vorpal.ui.cancel();
    });

    stream.on('progress', function (kBytes, elapsed) {
        //TODO: Progress bar
        //TODO: Parse kBytes into mBytes, gBytes
        vorpal.ui.redraw(new Date().toLocaleString() + ' > ' + 'Stream downloading\n'
                         + kBytes + ' kBytes read, ' + elapsed + ' secs elapsed');
    });

    stream.on('error', streamError);

    //TODO: Shift to Eastern time zone
    var dateISO = new Date().toISOString();
    dateISO = dateISO.split('.')[0].replace(/-|:/g, '').replace(/T/, '-');
    stream.pipe(fs.createWriteStream('dl/' + dateISO + '.mp4'));
}

// M-F, 4:00 - 5:59
var rule = new schedule.RecurrenceRule();
rule.dayOfWeek = new schedule.Range(1, 5);
rule.hour = new schedule.Range(4, 10);
rule.minute = [59];
rule.second = 30;

var rule2 = new schedule.RecurrenceRule();
rule2.dayOfWeek = new schedule.Range(1, 5);
rule2.hour = [4];
rule2.minute = [30];
rule2.second = 30;

vorpal
    .command('ping', 'Checks for stream connectivity.')
    .option('-r, --record', 'Will record the stream on success. Default is false.')
    .option('-t, --timeout <seconds>', 'Time in seconds before failure. Default is 15.')
    .option('-p, --persist', 'Will repeat until success. Default is false.')
    .action(function (args, callback) {
        vorpal.log(args);
        pingStream(args.options.record, args.options.timeout, args.options.persist);
        callback();
    });

vorpal
  .delimiter('fbhw$')
  .show();

vorpal.log(new Date().toLocaleString() + ' > ' + 'Script launched');

var j = schedule.scheduleJob(rule, getStream);
var k = schedule.scheduleJob(rule2, function () {
    vorpal.log(new Date().toLocaleString() + ' > ' + 'Pinging stream for first hour...');
    pingStream(true, 15, true);
});

<commit_msg>Unlog args<commit_after>var fs = require('fs');
var rtmpdump = require('rtmpdump');
var schedule = require('node-schedule');
var config = require('./config.json');
var vorpal = require('vorpal')();

var videoURL = config.videoURL;
//TODO: Utility function for log formatting

function streamError(err, callback) {
    //TODO: Check against broadcast schedule, resume if necessary
    vorpal.log(new Date().toLocaleString() + ' > ' + 'Connection error.');
    vorpal.log(new Date().toLocaleString() + ' > ' + '**** ' + err);
    if (typeof callback === "function") {
        callback();
    }
}

function pingStream(record = false, timeout = 15, persist = false) {
    //TODO: progress bar to show timeout status
    var options = {
        rtmp: videoURL,
        stop: 1,
        live: null,
        timeout: timeout
    }

    stream = rtmpdump.createStream(options);

    vorpal.hide();
    vorpal.log(new Date().toLocaleString() + ' > ' + 'Checking if stream is live...');

    stream.on('connected', function (info) {
        vorpal.log(new Date().toLocaleString() + ' > ' + 'Stream is live.');
        if (record) {
            getStream();
        }
    });

    stream.on('error', function (err) {
        streamError(err, function () {
            if (persist) {
                pingStream(record, timeout, persist);
            }
        });
        vorpal.show();
    });

    if (typeof callback === "function") {
        callback();
    }
}

function getStream() {

    var options = {
        rtmp: videoURL,
        stop: 3630,
        live: null,
        timeout: 5
    },
    stream = rtmpdump.createStream(options);

    vorpal.log(new Date().toLocaleString() + ' > ' + 'Stream fetch initiated');

    stream.on('connected', function (info) {
        vorpal.log(new Date().toLocaleString() + ' > ' + 'Stream connected');
        //vorpal.log(info);
        vorpal.ui.cancel();
    });

    stream.on('progress', function (kBytes, elapsed) {
        //TODO: Progress bar
        //TODO: Parse kBytes into mBytes, gBytes
        vorpal.ui.redraw(new Date().toLocaleString() + ' > ' + 'Stream downloading\n'
                         + kBytes + ' kBytes read, ' + elapsed + ' secs elapsed');
    });

    stream.on('error', streamError);

    //TODO: Shift to Eastern time zone
    var dateISO = new Date().toISOString();
    dateISO = dateISO.split('.')[0].replace(/-|:/g, '').replace(/T/, '-');
    stream.pipe(fs.createWriteStream('dl/' + dateISO + '.mp4'));
}

// M-F, 4:00 - 5:59
var rule = new schedule.RecurrenceRule();
rule.dayOfWeek = new schedule.Range(1, 5);
rule.hour = new schedule.Range(4, 10);
rule.minute = [59];
rule.second = 30;

var rule2 = new schedule.RecurrenceRule();
rule2.dayOfWeek = new schedule.Range(1, 5);
rule2.hour = [4];
rule2.minute = [30];
rule2.second = 30;

vorpal
    .command('ping', 'Checks for stream connectivity.')
    .option('-r, --record', 'Will record the stream on success. Default is false.')
    .option('-t, --timeout <seconds>', 'Time in seconds before failure. Default is 15.')
    .option('-p, --persist', 'Will repeat until success. Default is false.')
    .action(function (args, callback) {
        pingStream(args.options.record, args.options.timeout, args.options.persist);
        callback();
    });

vorpal
  .delimiter('fbhw$')
  .show();

vorpal.log(new Date().toLocaleString() + ' > ' + 'Script launched');

var j = schedule.scheduleJob(rule, getStream);
var k = schedule.scheduleJob(rule2, function () {
    vorpal.log(new Date().toLocaleString() + ' > ' + 'Pinging stream for first hour...');
    pingStream(true, 15, true);
});

<|endoftext|>


<commit_before>var fs = require('fs'),
    path = require('path'),
    Parallel = require('paralleljs');

var CONSOLE = console;

module.exports = function (configPath, modules, done_, logger_) {
    "use strict";

    var done = done_ || function () {};
    var console = logger_ || CONSOLE;

    var configPathBase = path.dirname(configPath);
    var configJSON = JSON.parse(fs.readFileSync(configPath));

    if (configJSON.version != 3)
        throw Error('Unsupported configuration file. Version: ' + config.version);

    var configFrameworkPath = (configJSON.framework ? path.resolve(configPathBase, configJSON.framework) : ''),
        requiredFrameworkPath = require('emp.ria-framework')._mypath;

    var frameworkPath = configFrameworkPath || requiredFrameworkPath || path.resolve(configPathBase, 'node_modules/emp.ria-framework');

    if (!frameworkPath) {
        console.error('Please specify framework path in config or npm install emp.ria-framework');
        done(false);
        return ;
    }

    var plugins = (typeof configJSON.assets === 'object' ? configJSON.assets : null) || { // defaults
        "jade": { "compiler": "emp.ria-jade", "options": { "client": true, "compileDebug": false, "self": true } },
        "txt": {},
        "json": {}
    };

    var plugins_paths = Object.keys(plugins).map(function (_) {
        var cfg = plugins[_] || {};
        return cfg.path ? path.resolve(configPathBase, cfg.path) : path.resolve(__dirname, 'lib/assets/' + _ + '.js');
    });

    var JsBuild3 = require("./tools/jsbuild")(console, frameworkPath, plugins_paths);

    var CFG = new JsBuild3.Configuration(configJSON, configPath);

    var MODULES = modules.filter(function (_) { return _ });
    var toBuild = CFG.getModules();
    if (MODULES.length) {
        toBuild = toBuild.filter(function (_) {
            return MODULES.indexOf(_.getName()) >= 0;
        });
    }

    toBuild = toBuild.map(function (M) {
        return {
            name: M.getName(),
            inFile: M.getInFile() || M.getAppClass(),
            outFile: path.resolve(CFG.getBasePath() + M.getOutFile()),
            appClass: M.getAppClass(),
            configPath: configPath,
            frameworkPath: frameworkPath,
            configJSON: configJSON,
            plugins_paths: plugins_paths
        }
    });

    console.log('Framework path: ' + frameworkPath);

    if (!toBuild.length) {
      console.warn('Nothing to build');
      done();
      return ;
    }

    console.log('To build: ' + toBuild.map(function (_) { return _.name; }).join(', '));

    var p = new Parallel(toBuild);

    p.map(function (data) {
        console.info('Compile ' + data.name);
        console.log('Framework path: ' + data.frameworkPath);
        try {
            var JsBuild3 = require("../../../tools/jsbuild")(console, data.frameworkPath, data.plugins_paths);
            var fs = require('fs');

            var CFG = new JsBuild3.Configuration(data.configJSON, data.configPath);
            var M = CFG.getModules().filter(function(_) { return _.getName() == data.name; })[0];
            CFG.setModuleConfig(M);

            var fileContents = JsBuild3.compile(data.inFile, CFG, data.appClass);
            fs.writeFileSync(data.outFile, fileContents, "utf-8");

            return null;
        } catch (e) {
            return 'Error processing ' + data.name + ': ' + e.message;
        }
    }).then(function (data) {

        data
            .filter(function (_) { return _; })
            .forEach(function (_) { console.error(_); });

        console.info("done");
        done();
    });
};
<commit_msg>fixed issue with compile path resolve<commit_after>var fs = require('fs'),
    path = require('path'),
    Parallel = require('paralleljs');

var CONSOLE = console;

module.exports = function (configPath, modules, done_, logger_) {
    "use strict";

    var done = done_ || function () {};
    var console = logger_ || CONSOLE;

    var configPathBase = path.dirname(configPath);
    var configJSON = JSON.parse(fs.readFileSync(configPath));

    if (configJSON.version != 3)
        throw Error('Unsupported configuration file. Version: ' + config.version);

    var configFrameworkPath = (configJSON.framework ? path.resolve(configPathBase, configJSON.framework) : ''),
        requiredFrameworkPath = require('emp.ria-framework')._mypath;

    var frameworkPath = configFrameworkPath || requiredFrameworkPath || path.resolve(configPathBase, 'node_modules/emp.ria-framework');

    if (!frameworkPath) {
        console.error('Please specify framework path in config or npm install emp.ria-framework');
        done(false);
        return ;
    }

    var plugins = (typeof configJSON.assets === 'object' ? configJSON.assets : null) || { // defaults
        "jade": { "compiler": "emp.ria-jade", "options": { "client": true, "compileDebug": false, "self": true } },
        "txt": {},
        "json": {}
    };

    var plugins_paths = Object.keys(plugins).map(function (_) {
        var cfg = plugins[_] || {};
        return cfg.path ? path.resolve(configPathBase, cfg.path) : path.resolve(__dirname, 'lib/assets/' + _ + '.js');
    });

    var JsBuild3_tools_path = path.resolve(__dirname, "./tools/jsbuild");
    var JsBuild3 = require(JsBuild3_tools_path)(console, frameworkPath, plugins_paths);

    var CFG = new JsBuild3.Configuration(configJSON, configPath);

    var MODULES = modules.filter(function (_) { return _ });
    var toBuild = CFG.getModules();
    if (MODULES.length) {
        toBuild = toBuild.filter(function (_) {
            return MODULES.indexOf(_.getName()) >= 0;
        });
    }

    toBuild = toBuild.map(function (M) {
        return {
            name: M.getName(),
            inFile: M.getInFile() || M.getAppClass(),
            outFile: path.resolve(CFG.getBasePath() + M.getOutFile()),
            appClass: M.getAppClass(),
            configPath: configPath,
            frameworkPath: frameworkPath,
            configJSON: configJSON,
            plugins_paths: plugins_paths,
            JsBuild3_tools_path: JsBuild3_tools_path
        }
    });

    console.log('Framework path: ' + frameworkPath);

    if (!toBuild.length) {
      console.warn('Nothing to build');
      done();
      return ;
    }

    console.log('To build: ' + toBuild.map(function (_) { return _.name; }).join(', '));

    var p = new Parallel(toBuild);

    p.map(function (data) {
        console.info('Compile ' + data.name);
        console.log('Framework path: ' + data.frameworkPath);
        try {
            var JsBuild3_tools_path = data.JsBuild3_tools_path;
            var JsBuild3 = require(JsBuild3_tools_path)(console, data.frameworkPath, data.plugins_paths);
            var fs = require('fs');

            var CFG = new JsBuild3.Configuration(data.configJSON, data.configPath);
            var M = CFG.getModules().filter(function(_) { return _.getName() == data.name; })[0];
            CFG.setModuleConfig(M);

            var fileContents = JsBuild3.compile(data.inFile, CFG, data.appClass);
            fs.writeFileSync(data.outFile, fileContents, "utf-8");

            return null;
        } catch (e) {
            return 'Error processing ' + data.name + ': ' + e.message;
        }
    }).then(function (data) {

        data
            .filter(function (_) { return _; })
            .forEach(function (_) { console.error(_); });

        console.info("done");
        done();
    });
};
<|endoftext|>