<commit_before>//浏览器信息
var Browser = function(userAgent){
	var u = userAgent||navigator.userAgent;
	var _this = this;
	var match = {
		//内核
		Trident: u.indexOf('Trident')>0||u.indexOf('NET CLR')>0,
		Presto: u.indexOf('Presto')>0,
        WebKit: u.indexOf('AppleWebKit')>0,
        Gecko: u.indexOf('Gecko')>0,
		//浏览器
		UC: u.indexOf('UC')>0||u.indexOf(' UBrowser')>0,
		QQ: u.indexOf('QQBrowser')>0,
		BaiDu: u.indexOf('Baidu')>0||u.indexOf('BIDUBrowser')>0,
		Maxthon: u.indexOf('Maxthon')>0,
		LBBROWSER: u.indexOf('LBBROWSER')>0,
		SouGou: u.indexOf('MetaSr')>0||u.indexOf('Sogou')>0,
		IE: u.indexOf('MSIE')>0||u.indexOf('Trident')>0,
		Firefox: u.indexOf('Firefox')>0,
		Opera: u.indexOf('Opera')>0||u.indexOf('OPR')>0,
		Safari: u.indexOf('Safari')>0,
		Chrome:u.indexOf('Chrome')>0||u.indexOf('CriOS')>0,
		//系统或平台
		Windows:u.indexOf('Windows')>0,
		Mac:u.indexOf('Macintosh')>0,
		Android:u.indexOf('Android')>0||u.indexOf('Adr')>0,
		WP:u.indexOf('IEMobile')>0,
		BlackBerry:u.indexOf('BlackBerry')>0||u.indexOf('RIM')>0||u.indexOf('BB')>0,
		MeeGo:u.indexOf('MeeGo')>0,
		Symbian:u.indexOf('Symbian')>0,
		iOS:u.indexOf('like Mac OS X')>0,
		iPhone: u.indexOf('iPh')>0,
		iPad:u.indexOf('iPad')>0,
		//设备
		Mobile:u.indexOf('Mobi')>0||u.indexOf('iPh')>0||u.indexOf('480')>0,
		Tablet:u.indexOf('Tablet')>0||u.indexOf('iPad')>0||u.indexOf('Nexus 7')>0
	};
	var filter = {
		Gecko: u.indexOf('like Gecko')>0
	};
	//修正
	if(match.Gecko){
		match.Gecko = !filter.Gecko;
	}
	if(match.Chrome){
		match.Chrome = !(match.Opera + match.BaiDu + match.Maxthon + match.SouGou + match.UC + match.QQ + match.LBBROWSER);
	}
	if(match.Safari){
		match.Safari = !(match.Chrome + match.Opera + match.BaiDu + match.Maxthon + match.SouGou + match.UC + match.QQ + match.LBBROWSER);
	}
	if(match.Mobile){
		match.Mobile = !match.iPad;
	}
	//基本信息
	var hash = {
		engine:['Trident','Presto','WebKit','Gecko'],
		browser:['UC','QQ','BaiDu','Maxthon','SouGou','IE','Firefox','Opera','Safari','Chrome','LBBROWSER'],
		os:['Windows','Mac','Android','WP','BlackBerry','MeeGo','Symbian','iOS','iPhone','iPad'],
		device:['Mobile','Tablet']
	};
	_this.device = 'PC';
	_this.language = (function(){
		var g = (navigator.browserLanguage || navigator.language).toLowerCase();
		return g=="c"?"zh-cn":g;
	})();
	for(var s in hash){
		for(var i=0;i< hash[s].length;i++){
			var value = hash[s][i];
			if(match[value]){
				_this[s] = value;
				break;
			}
		}
	}
	//版本信息
	var version = {
		'Chrome':function(){
			return u.replace(/^(.*)Chrome\/([\d.]+)(.*)$/,'$2');
		},
		'IE':function(){
			var v = u.replace(/^(.*)MSIE ([\d.]+)(.*)$/,'$2');
			if(v==u){
				v = u.replace(/^(.*)rv:([\d.]+)(.*)$/,'$2');
			}
			return v!=u?v:'';
		},
		'Firefox':function(){
			return u.replace(/^(.*)Firefox\/([\d.]+)(.*)$/,'$2');
		},
		'Safari':function(){
			return u.replace(/^(.*)Version\/([\d.]+)(.*)$/,'$2');
		},
		'Maxthon':function(){
			return u.replace(/^(.*)Maxthon\/([\d.]+)(.*)$/,'$2');
		},
		'QQ':function(){
			return u.replace(/^(.*)QQBrowser\/([\d.]+)(.*)$/,'$2');
		},
		'BaiDu':function(){
			return u.replace(/^(.*)BIDUBrowser[\s\/]([\d.]+)(.*)$/,'$2');
		},
		'UC':function(){
			return u.replace(/^(.*)UBrowser\/([\d.]+)(.*)$/,'$2');
		},
	};
	_this.version = '';
	if(version[_this.browser]){
		_this.version = version[_this.browser]();
	}
};<commit_msg>updated 添加微信的判断及代码优化<commit_after>//浏览器信息
var Browser = function(userAgent){
	var u = userAgent||navigator.userAgent;
	var _this = this;
	var match = {
		//内核
		Trident: u.indexOf('Trident')>0||u.indexOf('NET CLR')>0,
		Presto: u.indexOf('Presto')>0,
        WebKit: u.indexOf('AppleWebKit')>0,
        Gecko: u.indexOf('Gecko')>0,
		//浏览器
		UC: u.indexOf('UC')>0||u.indexOf(' UBrowser')>0,
		QQ: u.indexOf('QQBrowser')>0,
		BaiDu: u.indexOf('Baidu')>0||u.indexOf('BIDUBrowser')>0,
		Maxthon: u.indexOf('Maxthon')>0,
		LBBROWSER: u.indexOf('LBBROWSER')>0,
		SouGou: u.indexOf('MetaSr')>0||u.indexOf('Sogou')>0,
		IE: u.indexOf('MSIE')>0||u.indexOf('Trident')>0,
		Firefox: u.indexOf('Firefox')>0,
		Opera: u.indexOf('Opera')>0||u.indexOf('OPR')>0,
		Safari: u.indexOf('Safari')>0,
		Chrome:u.indexOf('Chrome')>0||u.indexOf('CriOS')>0,
		Wechat:u.indexOf('MicroMessenger')>0,
		//系统或平台
		Windows:u.indexOf('Windows')>0,
		Mac:u.indexOf('Macintosh')>0,
		Android:u.indexOf('Android')>0||u.indexOf('Adr')>0,
		WP:u.indexOf('IEMobile')>0,
		BlackBerry:u.indexOf('BlackBerry')>0||u.indexOf('RIM')>0||u.indexOf('BB')>0,
		MeeGo:u.indexOf('MeeGo')>0,
		Symbian:u.indexOf('Symbian')>0,
		iOS:u.indexOf('like Mac OS X')>0,
		iPhone: u.indexOf('iPh')>0,
		iPad:u.indexOf('iPad')>0,
		//设备
		Mobile:u.indexOf('Mobi')>0||u.indexOf('iPh')>0||u.indexOf('480')>0,
		Tablet:u.indexOf('Tablet')>0||u.indexOf('iPad')>0||u.indexOf('Nexus 7')>0
	};
	var filter = {
		Gecko: u.indexOf('like Gecko')>0
	};
	//修正
	if(match.Gecko){
		match.Gecko = !filter.Gecko;
	}
	if(match.Chrome){
		match.Chrome = !(match.Opera + match.BaiDu + match.Maxthon + match.SouGou + match.UC + match.QQ + match.LBBROWSER);
	}
	if(match.Safari){
		match.Safari = !(match.Chrome + match.Opera + match.BaiDu + match.Maxthon + match.SouGou + match.UC + match.QQ + match.LBBROWSER);
	}
	if(match.Mobile){
		match.Mobile = !match.iPad;
	}
	//基本信息
	var hash = {
		engine:['Trident','Presto','WebKit','Gecko'],
		browser:['UC','QQ','BaiDu','Maxthon','SouGou','IE','Firefox','Opera','Safari','Chrome','LBBROWSER','Wechat'],
		os:['Windows','Mac','Android','WP','BlackBerry','MeeGo','Symbian','iOS','iPhone','iPad'],
		device:['Mobile','Tablet']
	};
	_this.device = 'PC';
	_this.language = (function(){
		var g = (navigator.browserLanguage || navigator.language).toLowerCase();
		return g=="c"?"zh-cn":g;
	})();
	for(var s in hash){
		for(var i=0;i< hash[s].length;i++){
			var value = hash[s][i];
			if(match[value]){
				_this[s] = value;
				break;
			}
		}
	}
	//版本信息
	var version = {
		'Chrome':function(){
			return u.replace(/^.*Chrome\/([\d.]+).*$/,'$1');
		},
		'IE':function(){
			var v = u.replace(/^.*MSIE ([\d.]+).*$/,'$1');
			if(v==u){
				v = u.replace(/^.*rv:([\d.]+).*$/,'$1');
			}
			return v!=u?v:'';
		},
		'Firefox':function(){
			return u.replace(/^.*Firefox\/([\d.]+).*$/,'$1');
		},
		'Safari':function(){
			return u.replace(/^.*Version\/([\d.]+).*$/,'$1');
		},
		'Maxthon':function(){
			return u.replace(/^.*Maxthon\/([\d.]+).*$/,'$1');
		},
		'QQ':function(){
			return u.replace(/^.*QQBrowser\/([\d.]+).*$/,'$1');
		},
		'BaiDu':function(){
			return u.replace(/^.*BIDUBrowser[\s\/]([\d.]+).*$/,'$1');
		},
		'UC':function(){
			return u.replace(/^.*UBrowser\/([\d.]+).*$/,'$1');
		},
		'Wechat':function(){
			return u.replace(/^.*MicroMessenger\/([\d.]+).*$/,'$1');
		}
	};
	_this.version = '';
	if(version[_this.browser]){
		_this.version = version[_this.browser]();
	}
};<|endoftext|>


<commit_before>
module.exports = decorate

var ErrorPage = require("error-page")
, domain = require("domain")
, Cookies = require("cookies")
, RedSess = require("redsess")
, csrf = require('csrf-lite')

, path = require('path')
, sanitizer = require('sanitizer')
, Templar = require("templar")
, ejs = require('ejs')
, tplDir = path.resolve(__dirname, 'templates')
, templateOptions = { engine: ejs, folder: tplDir }
, url = require('url')
, bunyan = require('bunyan')
, crypto = require('crypto')
, logger

, CouchLogin = require('couch-login')

// TODO: Error page configs
, errorPageConf = {}

, MC = require('./models.js')
, http = require('http')

function errorHandler (req, res, data) {
  if (!req.profile) {
    req.model.load('profile', req)
    req.model.end(thenShow)
  } else {
    thenShow()
  }

  function thenShow () {
    data.profile = req.profile
    data.title = data.message
    data.statusMessage = http.STATUS_CODES[data.statusCode]
    var tpl = 'error.ejs'
    var tplSpecial = 'error-' + data.statusCode + '.ejs'
    if (res.template.has(tplSpecial)) tpl = tplSpecial

    data.headers = Object.keys(data.headers || {}).filter(function (h) {
      return h !== 'cookie'
    }).reduce(function (set, h) {
      set[h] = data.headers[h]
      return set
    }, {})

    delete data.options

    res.template(tpl, data, data.statusCode || 500)
  }
}

var env = process.env.NODE_ENV
function decorate (req, res, config) {
  // production https can only be https ever.
  if (config.https && env === 'production') {
    res.setHeader('strict-transport-security',
                  1000 * 60 * 60 * 24 * 30 + '')
  }

  res.setHeader = function (orig) { return function () {
    if (res._header)
      return
    return orig.apply(this, arguments)
  }}(res.setHeader)

  req.model = res.model = new MC

  templateOptions.debug = config.debug
  templateOptions.stamp = config.stamp

  if (config.errorPage) errorPageConf = config.errorPage
  errorPageConf['*'] = errorHandler

  if (!logger) {
    var logOpts = config.log ||
      { name: 'npm-www', level: 'trace' }
    logger = bunyan.createLogger(logOpts)
  }

  // handle unexpected errors relating to this request.
  // TODO: make this a separate module.
  var d = domain.create()
  d.add(req)
  d.add(res)
  d.on("error", function (er) {
    if (er.domainEmitter) {
      var c = er.domainEmitter.constructor
      if (c)
        c = c.name
      er.domainEmitter = c || '[unknown]'
    }
    delete er.domain_emitter
    delete er.domain
    logger.error({ error: er }, er.stack)
    try {
      if (res.error) res.error(er)
      else {
        res.statusCode = 500
        res.setHeader('content-type', 'text/plain')
        res.end('Server Error\n' + er.message)
      }

      // don't destroy before sending the error
      res.on("finish", function () {
        d.dispose()
      })

      // don't wait forever, though.
      setTimeout(function () {
        d.dispose()
      }, 1000)

      // disconnect after errors so that a fresh worker can come up.
      req.client.server.close()

    } catch (er) {
      d.dispose()
    }
  })

  // set up various decorations
  // TODO: Move some/all of this into a separate module.

  req.cookies = res.cookies = new Cookies(req, res, config.keys)
  req.session = res.session = new RedSess(req, res, {
    keys: config.keys,
    cookies: req.cookies
  })

  // set up the CouchLogin to automatically save the token in the
  // session, and log in on demand.
  req.couch = CouchLogin(config.registryCouch).decorate(req, res)
  req.couch.strictSSL = false

  res.template = Templar(req, res, templateOptions)
  res.template.locals.sanitize = sanitizer.sanitize
  res.template.locals.canonicalHref = url.resolve(
    config.canonicalHost, url.parse(req.url).path)

  // use session token as the csrf protection bit
  var csrfToken = csrf(req.session.token)
  res.template.locals.csrfToken = csrfToken
  res.template.locals.csrf = csrf.html(csrfToken)

  req.log = res.log = logger.child(
    { serializers: bunyan.stdSerializers
    , req_id: crypto.randomBytes(4).toString('hex')
    , session: req.sessionToken })

  res.on('finish', function () {
    req.log.info({ res: res })
  })

  // more debugging info.
  var remoteAddr = req.socket.remoteAddress + ':'
                 + req.socket.remotePort
  , address = req.socket.address()
  address = address.address + ':' + address.port

  req.log.info({req: req, remote: remoteAddr, address: address})

  // allow stuff like "req.pathname", etc.
  var u = url.parse(req.url, true)
  delete u.auth
  Object.keys(u).forEach(function (k) {
    req[k] = u[k]
  })

  res.error = ErrorPage(req, res, errorPageConf)

  res.redirect = function (target, code) {
    res.statusCode = code || 302
    // strip out \n etc.
    target = url.format(target)
    res.setHeader('location', target)
    var avail = ['text/html', 'application/json']
    res.html( '
Moved'
            + (code === 302 ? ' Permanently' : '') + '
'
            + '' + target + '')
  }

  res.send = function (data, status, headers) {
    res.statusCode = res.statusCode || status
    if (headers) Object.keys(headers).forEach(function (h) {
      res.setHeader(h, headers[h])
    })
    if (!Buffer.isBuffer(data)) data = new Buffer(data)
    res.setHeader('content-length', data.length)
    res.end(data)
  }

  res.json = res.sendJSON = function (obj, status) {
    res.send(JSON.stringify(obj), status, {'content-type':'application/json'})
  }

  res.html = res.sendHTML = function (data, status) {
    res.send(data, status, {'content-type':'text/html'})
  }
}
<commit_msg>Set HSTS header properly<commit_after>
module.exports = decorate

var ErrorPage = require("error-page")
, domain = require("domain")
, Cookies = require("cookies")
, RedSess = require("redsess")
, csrf = require('csrf-lite')

, path = require('path')
, sanitizer = require('sanitizer')
, Templar = require("templar")
, ejs = require('ejs')
, tplDir = path.resolve(__dirname, 'templates')
, templateOptions = { engine: ejs, folder: tplDir }
, url = require('url')
, bunyan = require('bunyan')
, crypto = require('crypto')
, logger

, CouchLogin = require('couch-login')

// TODO: Error page configs
, errorPageConf = {}

, MC = require('./models.js')
, http = require('http')

function errorHandler (req, res, data) {
  if (!req.profile) {
    req.model.load('profile', req)
    req.model.end(thenShow)
  } else {
    thenShow()
  }

  function thenShow () {
    data.profile = req.profile
    data.title = data.message
    data.statusMessage = http.STATUS_CODES[data.statusCode]
    var tpl = 'error.ejs'
    var tplSpecial = 'error-' + data.statusCode + '.ejs'
    if (res.template.has(tplSpecial)) tpl = tplSpecial

    data.headers = Object.keys(data.headers || {}).filter(function (h) {
      return h !== 'cookie'
    }).reduce(function (set, h) {
      set[h] = data.headers[h]
      return set
    }, {})

    delete data.options

    res.template(tpl, data, data.statusCode || 500)
  }
}

var env = process.env.NODE_ENV
function decorate (req, res, config) {
  // production https can only be https ever.
  if (config.https && env === 'production') {
    res.setHeader('strict-transport-security',
                  'max-age=' + (1000 * 60 * 60 * 24 * 30))
  }

  res.setHeader = function (orig) { return function () {
    if (res._header)
      return
    return orig.apply(this, arguments)
  }}(res.setHeader)

  req.model = res.model = new MC

  templateOptions.debug = config.debug
  templateOptions.stamp = config.stamp

  if (config.errorPage) errorPageConf = config.errorPage
  errorPageConf['*'] = errorHandler

  if (!logger) {
    var logOpts = config.log ||
      { name: 'npm-www', level: 'trace' }
    logger = bunyan.createLogger(logOpts)
  }

  // handle unexpected errors relating to this request.
  // TODO: make this a separate module.
  var d = domain.create()
  d.add(req)
  d.add(res)
  d.on("error", function (er) {
    if (er.domainEmitter) {
      var c = er.domainEmitter.constructor
      if (c)
        c = c.name
      er.domainEmitter = c || '[unknown]'
    }
    delete er.domain_emitter
    delete er.domain
    logger.error({ error: er }, er.stack)
    try {
      if (res.error) res.error(er)
      else {
        res.statusCode = 500
        res.setHeader('content-type', 'text/plain')
        res.end('Server Error\n' + er.message)
      }

      // don't destroy before sending the error
      res.on("finish", function () {
        d.dispose()
      })

      // don't wait forever, though.
      setTimeout(function () {
        d.dispose()
      }, 1000)

      // disconnect after errors so that a fresh worker can come up.
      req.client.server.close()

    } catch (er) {
      d.dispose()
    }
  })

  // set up various decorations
  // TODO: Move some/all of this into a separate module.

  req.cookies = res.cookies = new Cookies(req, res, config.keys)
  req.session = res.session = new RedSess(req, res, {
    keys: config.keys,
    cookies: req.cookies
  })

  // set up the CouchLogin to automatically save the token in the
  // session, and log in on demand.
  req.couch = CouchLogin(config.registryCouch).decorate(req, res)
  req.couch.strictSSL = false

  res.template = Templar(req, res, templateOptions)
  res.template.locals.sanitize = sanitizer.sanitize
  res.template.locals.canonicalHref = url.resolve(
    config.canonicalHost, url.parse(req.url).path)

  // use session token as the csrf protection bit
  var csrfToken = csrf(req.session.token)
  res.template.locals.csrfToken = csrfToken
  res.template.locals.csrf = csrf.html(csrfToken)

  req.log = res.log = logger.child(
    { serializers: bunyan.stdSerializers
    , req_id: crypto.randomBytes(4).toString('hex')
    , session: req.sessionToken })

  res.on('finish', function () {
    req.log.info({ res: res })
  })

  // more debugging info.
  var remoteAddr = req.socket.remoteAddress + ':'
                 + req.socket.remotePort
  , address = req.socket.address()
  address = address.address + ':' + address.port

  req.log.info({req: req, remote: remoteAddr, address: address})

  // allow stuff like "req.pathname", etc.
  var u = url.parse(req.url, true)
  delete u.auth
  Object.keys(u).forEach(function (k) {
    req[k] = u[k]
  })

  res.error = ErrorPage(req, res, errorPageConf)

  res.redirect = function (target, code) {
    res.statusCode = code || 302
    // strip out \n etc.
    target = url.format(target)
    res.setHeader('location', target)
    var avail = ['text/html', 'application/json']
    res.html( '
Moved'
            + (code === 302 ? ' Permanently' : '') + '
'
            + '' + target + '')
  }

  res.send = function (data, status, headers) {
    res.statusCode = res.statusCode || status
    if (headers) Object.keys(headers).forEach(function (h) {
      res.setHeader(h, headers[h])
    })
    if (!Buffer.isBuffer(data)) data = new Buffer(data)
    res.setHeader('content-length', data.length)
    res.end(data)
  }

  res.json = res.sendJSON = function (obj, status) {
    res.send(JSON.stringify(obj), status, {'content-type':'application/json'})
  }

  res.html = res.sendHTML = function (data, status) {
    res.send(data, status, {'content-type':'text/html'})
  }
}
<|endoftext|>


<commit_before>"use strict";
exports.__esModule = true;
exports.config = require('../config.json');
if (!exports.config.database)
    exports.config.database = {};
if (exports.config.database.isVolatile === undefined)
    exports.config.database.isVolatile = false;
<commit_msg>Delete Config.js<commit_after><|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

'use strict';

const path = require('path');

module.exports = function ignoredFiles(appSrc) {
  return new RegExp(
    `^(?!${path
      .normalize(appSrc + '/')
      .replace(/[\\]+/g, '/')}).+/node_modules/`,
    'g'
  );
};
<commit_msg>Fix path regex match bug (#3686)<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

'use strict';

const path = require('path');
const escape = require('escape-string-regexp');

module.exports = function ignoredFiles(appSrc) {
  return new RegExp(
    `^(?!${escape(
      path.normalize(appSrc + '/').replace(/[\\]+/g, '/')
    )}).+/node_modules/`,
    'g'
  );
};
<|endoftext|>


<commit_before>var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');

new WebpackDevServer(webpack(config), {
  publicPath: config.output.publicPath,
  hot: true,
  historyApiFallback: true
}).listen(3000, 'localhost', function (err, result) {
  if (err) {
    return console.log(err);
  }

  console.log('Listening at localhost:3000');
});
<commit_msg>Add http:// in front of localhost log message to make it easier to open in browser from console.<commit_after>var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');

new WebpackDevServer(webpack(config), {
  publicPath: config.output.publicPath,
  hot: true,
  historyApiFallback: true
}).listen(3000, 'localhost', function (err, result) {
  if (err) {
    return console.log(err);
  }

  console.log('Listening at http://localhost:3000/');
});
<|endoftext|>


<commit_before>const { api, _, Action } = require("../..")
const path = require('path')
const traverse = require("traverse")
const mkdirp = require('mkdirp')
const Abortable = require('pull-abortable')
const pl = require('pull-level')
const leveldown = require('leveldown')
const encode = require('encoding-down')
const Intervals = require("../../lib/intervals")
const util = require('icebreaker-network/lib/util')

const filter = require('pull-async-filter')

module.exports = () => {
  const dir = path.join(api.config.path, "addrs")
  try { mkdirp.sync(dir) }
  catch (err) { }

  const db = require('levelup')(encode(leveldown(dir), { valueEncoding: 'json' }))

  const timers = new Intervals()

  const add = (data, cb) =>{
    const r = Object.assign({},data)
    return db.get(r.key, (err, d) => {
    if(err)return db.put(r.key, r, (err)=> cb(err,r) )
      if(d.ts && data.ts>d.ts) return db.put(r.key, r, (err)=>cb(err,r))
      return      cb(null, d)
    })
  }

  const ls = {}

  const write =  () => {
    return _.asyncMap((item, cb) => {
      if(item && item.ts && item.key)
      add(item, (err) => cb(err, item) )
      return  cb(null, item)
    })
  }

  api.addrs = api.actions.addrs = Action({
    type: "source",
    input: { live: "boolean|string", old: "boolean|string" },
    desc: "Returns all known addresses",
    usage: {
      live: "Receive all addresses until cancelled",
      old: "Recive all old addresses"
    },
    defaults: {
      live: false,
      old: true
    },
    run: function(opts) {

      opts.old = opts.old === "true" || opts.old === true ? true : false
      opts.live = opts.live === "true" || opts.live === true ? true : false
      opts.keys = true
      opts.sync = false

      const peerID = this.id

      return _(pl.read(db, opts),_.filter((item)=>{

        if(!item)return false
        if(item.type!=="put" && item.type)return false
        if(!item.value)return false
        if(!item.value.ts){
          db.del(item.key,function(err){})
          return false
        }
        const ts = Date.now() - api.config.connectionTimeout
        if(item.value.ts<ts == true){
            db.del(item.key,function(err){})
          return false
        }
        delete item.type
        return item.value.ts>ts
      }),_.map((item)=>Object.assign({},item.value)),_.asyncMap((item,cb)=>{
        if(!peerID) return     cb(null,item)

        api.friends.isFriend(peerID,function(err,isFriend){
          if(err) return cb(null,undefined);
          if(isFriend) return  cb(null,item)

        api.identities.get(peerID,(err,identity)=>{
          if(err) return cb(null,undefined);

          const  u = util.parseUrl(item.key)
          api.identities.get(u.auth,(err,id)=>{
            if(err) return cb(null,undefined)
            for(g of identity.groups){
              if(id.groups.indexOf(g) !== -1)
              {
                api.groups.get(g,function(err,group){
                  if(err) return cb(null,undefined)
                  if(group.allow.indexOf("*")!==-1||group.allow.indexOf(u.pathname.split("/").slice(2).join(".") !==-1))
                  return cb(null,item)
                  return cb(null,undefined)

                })

              }
            }
            return cb(null,undefined);
          })

        });
      })

      }),_.filter()
      )
    }
  })

  const addAddrs = (e,map) => {
    const ts = Date.now()
    if (e.addrs && e.peer)
    e.addrs.forEach(addr=> {
      traverse(e.peer).forEach(function () {
        if (_.isFunction(this.node)) {
          let value = Object.assign({ key: addr + "/" + this.path.join("/"), ts: ts,action:this.path.join(".") },this.node)
          if(map) value =map(value)
          if(value.ts)
            add(value, (err) => {
              if (err) return api.log.error(err)
            })
          }
        })
      })
  }

  const addClient = (e) => {
    _(api.addrs({old:true,live:false}),
    filter((item,cb) => {
      if(item.key.indexOf("://"+api.id+"@") === -1) return cb(null,true)
        const u =util.parseUrl(item.key)
        const path = u.pathname
        console.log(u)
        if(path && !path.startsWith("/"+api.config.appKey+"/protoNames")) return cb(null,true)
        api.friends.isFriend(u.auth, (err,isFriend)=> {
          return cb(null,!(isFriend && path && path.startsWith("/"+api.config.appKey+"/protoNames") && !u.query.gw))
        })
      }
      ),
    _.collect((err,addrs)=>{
      if(addrs.length === 0) return;
      let maxts
      addrs.forEach((item)=>{ maxts = Math.max(maxts||0,item.ts) })
      addrs=addrs.filter((addr)=>{ return addr.ts === maxts })
      addrs = addrs.map((addr)=>{
        return addr.key.replace("/protoNames","")
      })
      addAddrs({addrs:addrs.map((addr)=>e.remoteAddress),peer:e.peer},function(data){
        data.key = data.key+"?gw="+this.addrs.shift()
        return data
      }.bind({addrs:addrs}))
    }))
  }

  _(api.events(), api.events.on({
    connection:(e)=>{
      if(e.remoteAddress)
      api.friends.isFriend(e.peerID,(err,isFriend)=>{

        if(!isFriend &&  e.peer && e.peerID !== api.id){
          timers.start(e.id, ()=>addClient(e), api.config.pingInterval)
           addClient(e)
         return
        }

        if(isFriend && e.peer && !e.peer.protoNames && e.peerID !== api.id)
        {
              timers.start(e.id, ()=>addClient(e), api.config.pingInterval)
              addClient(e)
        }

        if(isFriend && e.peer && e.peer.protoNames && e.peerID !== api.id)
        {
            e.peer.protoNames(function(err,protos){
              if(protos.length===0){

                timers.start(e.id, ()=>addClient(e), api.config.pingInterval)
                addClient(e)
              }

              if(err)return;
            })
        }
      })

    },
    closer: (e) => {
      try {
        if(e.address){
          addAddrs(e)
          timers.start(e.id,()=>addAddrs(e),api.config.pingInterval)
        }
        if (!e.peer.addrs) return
        if (!ls[e.id]) {
          const done = () => {
            if (ls[e.id]) {
              ls[e.id].abort(true)
              delete ls[e.id]
              api.log.info('Stop listening to live address changes from', e.peerID, "on", api.id)
            }
          }

          ls[e.id] = Abortable(done)

          api.log.info('Listen to live address changes from', e.peerID, "on", api.id)
          _(e.peer.addrs({ old: true, live: true }), ls[e.id], write(), _.onEnd(done))
        }
      }
      catch (err) {
        api.log.error("Addresses api error", err.message || err)
      }

    },
    notcloser: (e) => {
      if(!e.remoteAddress)addAddrs(e)

      timers.stop(e.id)
      if (ls[e.id]) {
        ls[e.id].abort(true)
        delete ls[e.id]
      }
    },
    replicate: (e) => {
      try {
        api.log('Replicating addresses from peer', e.peerID)

        _(e.peer.addrs({ old: true, live: false }), write(), _.onEnd((err) => {
          if (err) api.log.error("Addresses replication error", err.message || err)
        }))

        api.log('Addresses from', e.peerID, 'replicated')
      }
      catch (err) {
        api.log.error("Addresses replication error", err.message || err)
      }
    },
    disconnection:(e)=>{
      timers.stop(e.id)
    },
    end: (e) => {

    }

  }))

  const events = _.events()
  const end = events.end
  events.end=()=>{
    timers.stopAll()
    db.close(function(){
      end()
    })
  }

  db.once("ready",function(){
    events.emit({type:"ready"})
  })

  return events

}
<commit_msg>fix for addrs<commit_after>const { api, _, Action } = require("../..")
const path = require('path')
const traverse = require("traverse")
const mkdirp = require('mkdirp')
const Abortable = require('pull-abortable')
const pl = require('pull-level')
const leveldown = require('leveldown')
const encode = require('encoding-down')
const Intervals = require("../../lib/intervals")
const util = require('icebreaker-network/lib/util')

const filter = require('pull-async-filter')

module.exports = () => {
  const dir = path.join(api.config.path, "addrs")
  try { mkdirp.sync(dir) }
  catch (err) { }

  const db = require('levelup')(encode(leveldown(dir), { valueEncoding: 'json' }))

  const timers = new Intervals()

  const add = (data, cb) =>{
    const r = Object.assign({},data)
    return db.get(r.key, (err, d) => {
    if(err)return db.put(r.key, r, (err)=> cb(err,r) )
      if(d.ts && data.ts>d.ts) return db.put(r.key, r, (err)=>cb(err,r))
      return      cb(null, d)
    })
  }

  const ls = {}

  const write =  () => {
    return _.asyncMap((item, cb) => {
      if(item && item.ts && item.key)
      add(item, (err) => cb(err, item) )
      return  cb(null, item)
    })
  }

  api.addrs = api.actions.addrs = Action({
    type: "source",
    input: { live: "boolean|string", old: "boolean|string" },
    desc: "Returns all known addresses",
    usage: {
      live: "Receive all addresses until cancelled",
      old: "Recive all old addresses"
    },
    defaults: {
      live: false,
      old: true
    },
    run: function(opts) {

      opts.old = opts.old === "true" || opts.old === true ? true : false
      opts.live = opts.live === "true" || opts.live === true ? true : false
      opts.keys = true
      opts.sync = false

      const peerID = this.id

      return _(pl.read(db, opts),_.filter((item)=>{

        if(!item)return false
        if(item.type!=="put" && item.type)return false
        if(!item.value)return false
        if(!item.value.ts){
          db.del(item.key,function(err){})
          return false
        }
        const ts = Date.now() - api.config.connectionTimeout
        if(item.value.ts<ts == true){
            db.del(item.key,function(err){})
          return false
        }
        delete item.type
        return item.value.ts>ts
      }),_.map((item)=>Object.assign({},item.value)),_.asyncMap((item,cb)=>{
        if(!peerID) return     cb(null,item)

        api.friends.isFriend(peerID,function(err,isFriend){
          if(err) return cb(null,undefined);
          if(isFriend) return  cb(null,item)

        api.identities.get(peerID,(err,identity)=>{
          if(err) return cb(null,undefined);

          const  u = util.parseUrl(item.key)
          api.identities.get(u.auth,(err,id)=>{
            if(err) return cb(null,undefined)
            for(g of identity.groups){
              if(id.groups.indexOf(g) !== -1)
              {
                api.groups.get(g,function(err,group){
                  if(err) return cb(null,undefined)
                  if(group.allow.indexOf("*")!==-1||group.allow.indexOf(u.pathname.split("/").slice(2).join(".") !==-1))
                  return cb(null,item)
                  return cb(null,undefined)

                })

              }
            }
            return cb(null,undefined);
          })

        });
      })

      }),_.filter()
      )
    }
  })

  const addAddrs = (e,map) => {
    const ts = Date.now()
    if (e.addrs && e.peer)
    e.addrs.forEach(addr=> {
      traverse(e.peer).forEach(function () {
        if (_.isFunction(this.node)) {
          let value = Object.assign({ key: addr + "/" + this.path.join("/"), ts: ts,action:this.path.join(".") },this.node)
          if(map) value =map(value)
          if(value.ts)
            add(value, (err) => {
              if (err) return api.log.error(err)
            })
          }
        })
      })
  }

  const addClient = (e) => {
    _(api.addrs({old:true,live:false}),
    filter((item,cb) => {
      if(item.key.indexOf("://"+api.id+"@") === -1) return cb(null,true)
        const u =util.parseUrl(item.key)
        const path = u.pathname
        if(path && !path.startsWith("/"+api.config.appKey+"/protoNames")) return cb(null,true)
        api.friends.isFriend(u.auth, (err,isFriend)=> {
          return cb(null,!(isFriend && path && path.startsWith("/"+api.config.appKey+"/protoNames") && !u.query.gw))
        })
      }
      ),
    _.collect((err,addrs)=>{
      if(err) return
      if(!addrs) return
      if(addrs.length === 0) return;
      let maxts
      addrs.forEach((item)=>{ maxts = Math.max(maxts||0,item.ts) })
      addrs=addrs.filter((addr)=>{ return addr.ts === maxts })
      addrs = addrs.map((addr)=>{
        return addr.key.replace("/protoNames","")
      })
      addAddrs({addrs:addrs.slice(0).map((addr)=>e.remoteAddress),peer:e.peer},function(data){
        data.key = data.key+"?gw="+this.addrs.shift();
        return data
      }.bind({addrs:addrs.slice(0)}))
    }))
  }

  _(api.events(), api.events.on({
    connection:(e)=>{
      if(e.remoteAddress)
      api.friends.isFriend(e.peerID,(err,isFriend)=>{

        if(!isFriend &&  e.peer && e.peerID !== api.id){
          timers.start(e.id, ()=>addClient(e), api.config.pingInterval)
           addClient(e)
         return
        }

        if(isFriend && e.peer && !e.peer.protoNames && e.peerID !== api.id)
        {
              timers.start(e.id, ()=>addClient(e), api.config.pingInterval)
              addClient(e)
              return

        }

        if(isFriend && e.peer && e.peer.protoNames && e.peerID !== api.id)
        {
            e.peer.protoNames(function(err,protos){
              if(err)return;
              if(protos.length===0){

                timers.start(e.id, ()=>addClient(e), api.config.pingInterval)
                addClient(e)
              }

            })
        }
      })

    },
    closer: (e) => {
      try {
        if(e.address){
          addAddrs(e)
          timers.start(e.id,()=>addAddrs(e),api.config.pingInterval)
        }
        if (!e.peer.addrs) return
        if (!ls[e.id]) {
          const done = () => {
            if (ls[e.id]) {
              ls[e.id].abort(true)
              delete ls[e.id]
              api.log.info('Stop listening to live address changes from', e.peerID, "on", api.id)
            }
          }

          ls[e.id] = Abortable(done)

          api.log.info('Listen to live address changes from', e.peerID, "on", api.id)
          _(e.peer.addrs({ old: true, live: true }), ls[e.id], write(), _.onEnd(done))
        }
      }
      catch (err) {
        api.log.error("Addresses api error", err.message || err)
      }

    },
    notcloser: (e) => {
      if(!e.remoteAddress)addAddrs(e)

      timers.stop(e.id)
      if (ls[e.id]) {
        ls[e.id].abort(true)
        delete ls[e.id]
      }
    },
    replicate: (e) => {
      try {
        api.log('Replicating addresses from peer', e.peerID)

        _(e.peer.addrs({ old: true, live: false }), write(), _.onEnd((err) => {
          if (err) api.log.error("Addresses replication error", err.message || err)
        }))

        api.log('Addresses from', e.peerID, 'replicated')
      }
      catch (err) {
        api.log.error("Addresses replication error", err.message || err)
      }
    },
    disconnection:(e)=>{
      timers.stop(e.id)
    },
    end: (e) => {

    }

  }))

  const events = _.events()
  const end = events.end
  events.end=()=>{
    timers.stopAll()
    db.close(function(){
      end()
    })
  }

  db.once("ready",function(){
    events.emit({type:"ready"})
  })

  return events

}
<|endoftext|>


<commit_before>const { api, _, Action } = require("../..")
const path = require('path')
const traverse = require("traverse")
const mkdirp = require('mkdirp')
const Abortable = require('pull-abortable')
const pl = require('pull-level')
const leveldown = require('leveldown')
const encode = require('encoding-down')
const Intervals = require("../../lib/intervals")
const util = require('icebreaker-network/lib/util')

const filter = require('pull-async-filter')

module.exports = () => {
  const dir = path.join(api.config.path, "addrs")
  try { mkdirp.sync(dir) }
  catch (err) { }

  const db = require('levelup')(encode(leveldown(dir), { valueEncoding: 'json' }))

  const timers = new Intervals()

  const add = (data, cb) =>{
    const r = Object.assign({},data)
    return db.get(r.key, (err, d) => {
    if(err)return db.put(r.key, r, (err)=> cb(err,r) )
      if(d.ts && data.ts>d.ts) return db.put(r.key, r, (err)=>cb(err,r))
      return      cb(null, d)
    })
  }

  const ls = {}

  const write =  () => {
    return _.asyncMap((item, cb) => {
      if(item && item.ts && item.key)
      add(item, (err) => cb(err, item) )
      return  cb(null, item)
    })
  }

  api.addrs = api.actions.addrs = Action({
    type: "source",
    input: { live: "boolean|string", old: "boolean|string" },
    desc: "Returns all known addresses",
    usage: {
      live: "Receive all addresses until cancelled",
      old: "Recive all old addresses"
    },
    defaults: {
      live: false,
      old: true
    },
    run: function(opts) {

      opts.old = opts.old === "true" || opts.old === true ? true : false
      opts.live = opts.live === "true" || opts.live === true ? true : false
      opts.keys = true
      opts.sync = false

      const peerID = this.id

      return _(pl.read(db, opts),_.filter((item)=>{

        if(!item)return false
        if(item.type!=="put" && item.type)return false
        if(!item.value)return false
        if(!item.value.ts){
          db.del(item.key,function(err){})
          return false
        }
        const ts = Date.now() - api.config.connectionTimeout
        if(item.value.ts<ts == true){
            db.del(item.key,function(err){})
          return false
        }
        delete item.type
        return item.value.ts>ts
      }),_.map((item)=>Object.assign({},item.value)),_.asyncMap((item,cb)=>{
        if(!peerID) return     cb(null,item)

        api.friends.isFriend(peerID,function(err,isFriend){
          if(err) return cb(null,undefined);
          if(isFriend) return  cb(null,item)

        api.identities.get(peerID,(err,identity)=>{
          if(err) return cb(null,undefined);

          const  u = util.parseUrl(item.key)
          api.identities.get(u.auth,(err,id)=>{
            if(err) return cb(null,undefined)
            for(g of identity.groups){
              if(id.groups.indexOf(g) !== -1)
              {
                api.groups.get(g,function(err,group){
                  if(err) return cb(null,undefined)
                  if(group.allow.indexOf("*")!==-1||group.allow.indexOf(u.pathname.split("/").slice(2).join(".") !==-1))
                  return cb(null,item)
                  return cb(null,undefined)

                })

              }
            }
            return cb(null,undefined);
          })

        });
      })

      }),_.filter()
      )
    }
  })

  const addAddrs = (e,map) => {
    const ts = Date.now()
    if (e.addrs && e.peer)
    e.addrs.forEach(addr=> {
      traverse(e.peer).forEach(function () {
        if (_.isFunction(this.node)) {
          let value = Object.assign({ key: addr + "/" + this.path.join("/"), ts: ts,action:this.path.join(".") },this.node)
          if(map) value =map(value)
          if(value.ts)
            add(value, (err) => {
              if (err) return api.log.error(err)
            })
          }
        })
      })
  }

  const addClient = (e) => {
    _(api.addrs({old:true,live:false}),
    filter((item,cb) => {
      if(item.key.indexOf("://"+api.id+"@") === -1) return cb(null,true)
        const u =util.parseUrl(item.key)
        const path = u.pathname
        if(path && !path.startsWith("/"+api.config.appKey+"/protoNames")) return cb(null,true)
        api.friends.isFriend(u.auth, (err,isFriend)=> {
          return cb(null,!(isFriend && path && path.startsWith("/"+api.config.appKey+"/protoNames") && !u.query.gw))
        })
      }
      ),
    _.collect(function(err,addrs){
      if(err) return
      if(!addrs) return
      if(addrs.length === 0) return;
      let maxts
      addrs.forEach((item)=>{ maxts = Math.max(maxts||0,item.ts) })
      addrs=addrs.filter((addr)=>{ return addr.ts === maxts })
      addrs = addrs.map((addr)=>{
        return addr.key.replace("/protoNames","")
      })
      addAddrs({addrs:addrs.map((addr)=>e.remoteAddress),peer:e.peer},(data)=>{
        console.log("addrs",addrs)
         data.key = data.key+"?gw="+ addrs.shift();
         console.log("key",data.key)
        return data
      }
      )
    }))
  }

  _(api.events(), api.events.on({
    connection:(e)=>{
      if(e.remoteAddress)
      api.friends.isFriend(e.peerID,(err,isFriend)=>{

        if(!isFriend &&  e.peer && e.peerID !== api.id){
          timers.start(e.id, ()=>addClient(e), api.config.pingInterval)
           addClient(e)
         return
        }

        if(isFriend && e.peer && !e.peer.protoNames && e.peerID !== api.id)
        {
              timers.start(e.id, ()=>addClient(e), api.config.pingInterval)
              addClient(e)
              return

        }

        if(isFriend && e.peer && e.peer.protoNames && e.peerID !== api.id)
        {
            e.peer.protoNames(function(err,protos){
              if(err)return;
              if(protos.length===0){

                timers.start(e.id, ()=>addClient(e), api.config.pingInterval)
                addClient(e)
              }

            })
        }
      })

    },
    closer: (e) => {
      try {
        if(e.address){
          addAddrs(e)
          timers.start(e.id,()=>addAddrs(e),api.config.pingInterval)
        }
        if (!e.peer.addrs) return
        if (!ls[e.id]) {
          const done = () => {
            if (ls[e.id]) {
              ls[e.id].abort(true)
              delete ls[e.id]
              api.log.info('Stop listening to live address changes from', e.peerID, "on", api.id)
            }
          }

          ls[e.id] = Abortable(done)

          api.log.info('Listen to live address changes from', e.peerID, "on", api.id)
          _(e.peer.addrs({ old: true, live: true }), ls[e.id], write(), _.onEnd(done))
        }
      }
      catch (err) {
        api.log.error("Addresses api error", err.message || err)
      }

    },
    notcloser: (e) => {
      if(!e.remoteAddress)addAddrs(e)

      timers.stop(e.id)
      if (ls[e.id]) {
        ls[e.id].abort(true)
        delete ls[e.id]
      }
    },
    replicate: (e) => {
      try {
        api.log('Replicating addresses from peer', e.peerID)

        _(e.peer.addrs({ old: true, live: false }), write(), _.onEnd((err) => {
          if (err) api.log.error("Addresses replication error", err.message || err)
        }))

        api.log('Addresses from', e.peerID, 'replicated')
      }
      catch (err) {
        api.log.error("Addresses replication error", err.message || err)
      }
    },
    disconnection:(e)=>{
      timers.stop(e.id)
    },
    end: (e) => {

    }

  }))

  const events = _.events()
  const end = events.end
  events.end=()=>{
    timers.stopAll()
    db.close(function(){
      end()
    })
  }

  db.once("ready",function(){
    events.emit({type:"ready"})
  })

  return events

}
<commit_msg>fix for addrs<commit_after>const { api, _, Action } = require("../..")
const path = require('path')
const traverse = require("traverse")
const mkdirp = require('mkdirp')
const Abortable = require('pull-abortable')
const pl = require('pull-level')
const leveldown = require('leveldown')
const encode = require('encoding-down')
const Intervals = require("../../lib/intervals")
const util = require('icebreaker-network/lib/util')

const filter = require('pull-async-filter')

module.exports = () => {
  const dir = path.join(api.config.path, "addrs")
  try { mkdirp.sync(dir) }
  catch (err) { }

  const db = require('levelup')(encode(leveldown(dir), { valueEncoding: 'json' }))

  const timers = new Intervals()

  const add = (data, cb) =>{
    const r = Object.assign({},data)
    return db.get(r.key, (err, d) => {
    if(err)return db.put(r.key, r, (err)=> cb(err,r) )
      if(d.ts && data.ts>d.ts) return db.put(r.key, r, (err)=>cb(err,r))
      return      cb(null, d)
    })
  }

  const ls = {}

  const write =  () => {
    return _.asyncMap((item, cb) => {
      if(item && item.ts && item.key)
      add(item, (err) => cb(err, item) )
      return  cb(null, item)
    })
  }

  api.addrs = api.actions.addrs = Action({
    type: "source",
    input: { live: "boolean|string", old: "boolean|string" },
    desc: "Returns all known addresses",
    usage: {
      live: "Receive all addresses until cancelled",
      old: "Recive all old addresses"
    },
    defaults: {
      live: false,
      old: true
    },
    run: function(opts) {

      opts.old = opts.old === "true" || opts.old === true ? true : false
      opts.live = opts.live === "true" || opts.live === true ? true : false
      opts.keys = true
      opts.sync = false

      const peerID = this.id

      return _(pl.read(db, opts),_.filter((item)=>{

        if(!item)return false
        if(item.type!=="put" && item.type)return false
        if(!item.value)return false
        if(!item.value.ts){
          db.del(item.key,function(err){})
          return false
        }
        const ts = Date.now() - api.config.connectionTimeout
        if(item.value.ts<ts == true){
            db.del(item.key,function(err){})
          return false
        }
        delete item.type
        return item.value.ts>ts
      }),_.map((item)=>Object.assign({},item.value)),_.asyncMap((item,cb)=>{
        if(!peerID) return     cb(null,item)

        api.friends.isFriend(peerID,function(err,isFriend){
          if(err) return cb(null,undefined);
          if(isFriend) return  cb(null,item)

        api.identities.get(peerID,(err,identity)=>{
          if(err) return cb(null,undefined);

          const  u = util.parseUrl(item.key)
          api.identities.get(u.auth,(err,id)=>{
            if(err) return cb(null,undefined)
            for(g of identity.groups){
              if(id.groups.indexOf(g) !== -1)
              {
                api.groups.get(g,function(err,group){
                  if(err) return cb(null,undefined)
                  if(group.allow.indexOf("*")!==-1||group.allow.indexOf(u.pathname.split("/").slice(2).join(".") !==-1))
                  return cb(null,item)
                  return cb(null,undefined)

                })

              }
            }
            return cb(null,undefined);
          })

        });
      })

      }),_.filter()
      )
    }
  })

  const addAddrs = (e,map) => {
    const ts = Date.now()
    if (e.addrs && e.peer)
    e.addrs.forEach(addr=> {
      traverse(e.peer).forEach(function () {
        if (_.isFunction(this.node)) {
          let value = Object.assign({ key: addr + "/" + this.path.join("/"), ts: ts,action:this.path.join(".") },this.node)
          if(map) value =map(value)
          if(value.ts)
            add(value, (err) => {
              if (err) return api.log.error(err)
            })
          }
        })
      })
  }

  const addClient = (e) => {
    _(api.addrs({old:true,live:false}),
    filter((item,cb) => {
      if(item.key.indexOf("://"+api.id+"@") === -1) return cb(null,true)
        const u =util.parseUrl(item.key)
        const path = u.pathname
        if(path && !path.startsWith("/"+api.config.appKey+"/protoNames")) return cb(null,true)
        api.friends.isFriend(u.auth, (err,isFriend)=> {
          return cb(null,!(isFriend && path && path.startsWith("/"+api.config.appKey+"/protoNames") && !u.query.gw))
        })
      }
      ),
    _.collect(function(err,addrs){
      if(err) return
      if(!addrs) return
      if(addrs.length <= 0) return;
      let maxts
      addrs.forEach((item)=>{ maxts = Math.max(maxts||0,item.ts) })
      addrs=addrs.filter((addr)=>{ return addr.ts === maxts })
      addrs = addrs.map((addr)=>{
        return addr.key.replace("/protoNames","")
      })

      addAddrs({addrs:addrs.map((addr)=>e.remoteAddress),peer:e.peer},(data)=>{
        console.log("addrs",addrs)
         data.key = data.key+"?gw="+ addrs.shift();
         console.log("key",data.key)
        return data
      }
      )
    }))
  }

  _(api.events(), api.events.on({
    connection:(e)=>{
      if(e.remoteAddress)
      api.friends.isFriend(e.peerID,(err,isFriend)=>{

        if(!isFriend &&  e.peer && e.peerID !== api.id){
          timers.start(e.id, ()=>addClient(e), api.config.pingInterval)
           addClient(e)
         return
        }

        if(isFriend && e.peer && !e.peer.protoNames && e.peerID !== api.id)
        {
              timers.start(e.id, ()=>addClient(e), api.config.pingInterval)
              addClient(e)
              return

        }

        if(isFriend && e.peer && e.peer.protoNames && e.peerID !== api.id)
        {
            e.peer.protoNames(function(err,protos){
              if(err)return;
              if(protos.length<=0){

                timers.start(e.id, ()=>addClient(e), api.config.pingInterval)
                addClient(e)
              }

            })
        }
      })

    },
    closer: (e) => {
      try {
        if(e.address){
          addAddrs(e)
          timers.start(e.id,()=>addAddrs(e),api.config.pingInterval)
        }
        if (!e.peer.addrs) return
        if (!ls[e.id]) {
          const done = () => {
            if (ls[e.id]) {
              ls[e.id].abort(true)
              delete ls[e.id]
              api.log.info('Stop listening to live address changes from', e.peerID, "on", api.id)
            }
          }

          ls[e.id] = Abortable(done)

          api.log.info('Listen to live address changes from', e.peerID, "on", api.id)
          _(e.peer.addrs({ old: true, live: true }), ls[e.id], write(), _.onEnd(done))
        }
      }
      catch (err) {
        api.log.error("Addresses api error", err.message || err)
      }

    },
    notcloser: (e) => {
      if(!e.remoteAddress)addAddrs(e)

      timers.stop(e.id)
      if (ls[e.id]) {
        ls[e.id].abort(true)
        delete ls[e.id]
      }
    },
    replicate: (e) => {
      try {
        api.log('Replicating addresses from peer', e.peerID)

        _(e.peer.addrs({ old: true, live: false }), write(), _.onEnd((err) => {
          if (err) api.log.error("Addresses replication error", err.message || err)
        }))

        api.log('Addresses from', e.peerID, 'replicated')
      }
      catch (err) {
        api.log.error("Addresses replication error", err.message || err)
      }
    },
    disconnection:(e)=>{
      timers.stop(e.id)
    },
    end: (e) => {

    }

  }))

  const events = _.events()
  const end = events.end
  events.end=()=>{
    timers.stopAll()
    db.close(function(){
      end()
    })
  }

  db.once("ready",function(){
    events.emit({type:"ready"})
  })

  return events

}
<|endoftext|>


<commit_before>import {
  serialize as encode,
  deserialize as decode
} from '../common/pickler';

import { rationalLinearAlgebra as ops } from '../arithmetic/types';
import * as pg from './periodic';
import * as ps from './symmetries';

class Basis {
  constructor() {
    this.dim = null;
    this.vectors = [];
    this.matrix = null;
  }

  add(vecIn) {
    if (this.dim == null) {
      this.dim = vecIn.length;
      this.matrix = ops.identityMatrix(this.dim);
    }

    const n = this.vectors.length;

    if (this.dim > n && ops.rank(this.vectors.concat([vecIn])) > n) {
      this.vectors.push(vecIn);

      const basis = this.vectors.slice();
      for (const vec of ops.identityMatrix(this.dim)) {
        if (ops.rank(basis.concat([vec])) > basis.length)
          basis.push(vec);
      }
      this.matrix = ops.inverse(basis);
    }
    return ops.times(vecIn, this.matrix);
  }
};

const placeOrderedTraversal = function*(graph, start, transform) {
  const pos = pg.barycentricPlacement(graph);
  const seen = {};
  const queue = [start];

  while (queue.length) {
    const v = queue.shift();

    if (!seen[v]) {
      seen[v] = true;

      const incidences = pg.incidences(graph)[v].map(e => [
        e, ops.times(pg.edgeVector(e, pos), transform)
      ]);
      incidences.sort(([ea, da], [eb, db]) => ops.cmp(da, db));

      for (const [e] of incidences) {
        queue.push(e.tail);
        yield e;
      }
    }
  }
};

const adjustedTraversal = function*(traversal) {
  const shifts = {};
  const mapping = {};
  const basis = new Basis();
  let nrVerticesMapped = 0;

  for (const edge of traversal) {
    if (mapping[edge.head] == null) {
      mapping[edge.head] = ++nrVerticesMapped;
      shifts[edge.head] = ops.times(0, edge.shift);
    }
    const v = mapping[edge.head];

    if (mapping[edge.tail] == null) {
      mapping[edge.tail] = ++nrVerticesMapped;
      shifts[edge.tail] = ops.plus(edge.shift, shifts[edge.head]);
    }
    const w = mapping[edge.tail];

    if (v <= w) {
      const d = ops.minus(shifts[edge.head], shifts[edge.tail]);
      const shift = basis.add(ops.plus(edge.shift, d));

      if (v < w || ops.sgn(shift) < 0) {
        mapping[encode(edge)] = encode(pg.makeEdge(v, w, shift));
        yield [v, w, shift];
      }
    }
  }

  return { mapping, basisChange: basis.matrix };
};

const buffered = iterator => {
  const generated = [];
  let returned = null;

  const advance = () => {
    const { value, done } = iterator.next();

    if (!done)
      generated.push(value);
    else if (value != null)
      returned = value;

    return !done;
  }

  return {
    get(i) {
      while (generated.length <= i && advance()) {}
      return generated[i];
    },
    result() {
      while (advance()) {}
      return { generated, returned };
    }
  };
};

const findPivot = (A, col, startRow) => {
  const pairs = A
    .map((row, i) => [ops.abs(row[col]), i])
    .filter(([x, i]) => i >= startRow && ops.sgn(x));

  if (pairs.length)
    return pairs.reduce((acc, val) => ops.lt(val[0], acc[0]) ? val : acc)[1];
};

const triangulate = matrix => {
  const A = matrix.map(v => v.slice());
  const [nrows, ncols] = ops.shape(A);

  let row = 0;

  for (let col = 0; col < ncols; ++col) {
    while (true) {
      const pivotRow = findPivot(A, col, row);
      if (pivotRow == null)
        break;

      if (pivotRow != row)
        [A[row], A[pivotRow]] = [A[pivotRow], A[row]];

      if (ops.sgn(A[row]) < 0)
        A[row] = ops.negative(A[row]);

      for (let i = row + 1; i < nrows; ++i) {
        if (ops.ne(0, A[i][col])) {
          const f = ops.idiv(A[i][col], A[row][col]);
          A[i] = ops.minus(A[i], ops.times(f, A[row]));
        }
      }

      if (A.every((v, i) => i <= row || ops.eq(0, v[col]))) {
        row += 1;
        break;
      }
    }
  }

  return A.slice(0, ncols);
};

const postprocessTraversal = trav => {
  const shifts = trav.map(([head, tail, shift]) => shift);
  const basisChange = ops.inverse(triangulate(shifts));

  return trav.map(([head, tail, shift]) => {
    const newShift = ops.times(shift, basisChange);

    if (newShift.some(x => !ops.isInteger(x)))
      throw new Error("panic: produced non-integer shift");

    if (head == tail && ops.sgn(newShift) > 0)
      return [head, tail, ops.negative(newShift)];
    else
      return [head, tail, newShift];
  });
};

export const invariantWithMapping = graph => {
  const pos = pg.barycentricPlacement(graph);
  const sym = ps.symmetries(graph);

  const _cmpSteps = ([headA, tailA, shiftA], [headB, tailB, shiftB]) =>
    (headA - headB) || (tailA - tailB) || ops.cmp(shiftA, shiftB);

  let best = null;

  const bases = sym.representativeEdgeLists;

  for (const edgeList of bases) {
    const transform = ops.inverse(edgeList.map(e => pg.edgeVector(e, pos)));
    const base = placeOrderedTraversal(graph, edgeList[0].head, transform);
    const trav = buffered(adjustedTraversal(base));

    if (best == null)
      best = trav;
    else {
      for (let i = 0; ; ++i) {
        const next = trav.get(i);
        if (next == null)
          break;

        const d = _cmpSteps(next, best.get(i));
        if (d < 0)
          best = trav;
        else if (d > 0)
          break;
      }
    }
  }

  const result = best.result();
  const edges = postprocessTraversal(result.generated).sort(_cmpSteps);
  //TODO incorporate final basis change in all output properties
  return Object.assign({}, result.returned, { edges });
};

export const invariant = graph => invariantWithMapping(graph).edges;

export const systreKey = graph => {
  const seq = [graph.dim];

  for (const [from, to, shift] of invariant(graph)) {
    seq.push(from);
    seq.push(to);
    for (const x of shift)
      seq.push(x);
  }

  return seq.join(' ');
};

export const keyVersion = '1.0';

if (require.main == module) {
  Array.prototype.toString = function() {
    return `[ ${this.map(x => x.toString()).join(', ')} ]`;
  };

  const test = g => {
    const inv = invariantWithMapping(g);

    for (const k of Object.keys(inv.mapping))
      console.log(`(${decode(k)}) => (${decode(inv.mapping[k])})`);
    console.log();

    console.log(inv.basisChange);
    console.log();

    for (const e of inv.edges)
      console.log(e);
    console.log();

    console.log();
  };

  test(pg.makeGraph(
    [ [ 1, 2, [ 0, 0, 0 ] ],
      [ 1, 2, [ 1, 0, 0 ] ],
      [ 1, 2, [ 0, 1, 0 ] ],
      [ 1, 2, [ 0, 0, 1 ] ] ]
  ));

  test(pg.makeGraph(
    [ [ 1, 2, [ 0, 0 ] ],
      [ 1, 2, [ 1, 0 ] ],
      [ 2, 3, [ 0, 0 ] ],
      [ 2, 3, [ 0, 1 ] ],
      [ 1, 3, [ 0, 0 ] ],
      [ 1, 3, [ 1, 1 ] ] ]
  ));
}
<commit_msg>invariant: separate edge and vertex mapping; transform all output shifts<commit_after>import {
  serialize as encode,
  deserialize as decode
} from '../common/pickler';

import { rationalLinearAlgebra as ops } from '../arithmetic/types';
import * as pg from './periodic';
import * as ps from './symmetries';

class Basis {
  constructor() {
    this.dim = null;
    this.vectors = [];
    this.matrix = null;
  }

  add(vecIn) {
    if (this.dim == null) {
      this.dim = vecIn.length;
      this.matrix = ops.identityMatrix(this.dim);
    }

    const n = this.vectors.length;

    if (this.dim > n && ops.rank(this.vectors.concat([vecIn])) > n) {
      this.vectors.push(vecIn);

      const basis = this.vectors.slice();
      for (const vec of ops.identityMatrix(this.dim)) {
        if (ops.rank(basis.concat([vec])) > basis.length)
          basis.push(vec);
      }
      this.matrix = ops.inverse(basis);
    }
    return ops.times(vecIn, this.matrix);
  }
};

const placeOrderedTraversal = function*(graph, start, transform) {
  const pos = pg.barycentricPlacement(graph);
  const seen = {};
  const queue = [start];

  while (queue.length) {
    const v = queue.shift();

    if (!seen[v]) {
      seen[v] = true;

      const incidences = pg.incidences(graph)[v].map(e => [
        e, ops.times(pg.edgeVector(e, pos), transform)
      ]);
      incidences.sort(([ea, da], [eb, db]) => ops.cmp(da, db));

      for (const [e] of incidences) {
        queue.push(e.tail);
        yield e;
      }
    }
  }
};

const adjustedTraversal = function*(traversal) {
  const shifts = {};
  const vertexMapping = {};
  const edgeMapping = {};
  const basis = new Basis();
  let nrVerticesMapped = 0;

  for (const edge of traversal) {
    if (vertexMapping[edge.head] == null) {
      vertexMapping[edge.head] = ++nrVerticesMapped;
      shifts[edge.head] = ops.times(0, edge.shift);
    }
    const v = vertexMapping[edge.head];

    if (vertexMapping[edge.tail] == null) {
      vertexMapping[edge.tail] = ++nrVerticesMapped;
      shifts[edge.tail] = ops.plus(edge.shift, shifts[edge.head]);
    }
    const w = vertexMapping[edge.tail];

    if (v <= w) {
      const d = ops.minus(shifts[edge.head], shifts[edge.tail]);
      const shift = basis.add(ops.plus(edge.shift, d));

      if (v < w || ops.sgn(shift) < 0) {
        edgeMapping[encode(edge)] = encode(pg.makeEdge(v, w, shift));
        yield [v, w, shift];
      }
    }
  }

  return { vertexMapping, edgeMapping, basisChange: basis.matrix };
};

const buffered = iterator => {
  const generated = [];
  let returned = null;

  const advance = () => {
    const { value, done } = iterator.next();

    if (!done)
      generated.push(value);
    else if (value != null)
      returned = value;

    return !done;
  }

  return {
    get(i) {
      while (generated.length <= i && advance()) {}
      return generated[i];
    },
    result() {
      while (advance()) {}
      return { generated, returned };
    }
  };
};

const findPivot = (A, col, startRow) => {
  const pairs = A
    .map((row, i) => [ops.abs(row[col]), i])
    .filter(([x, i]) => i >= startRow && ops.sgn(x));

  if (pairs.length)
    return pairs.reduce((acc, val) => ops.lt(val[0], acc[0]) ? val : acc)[1];
};

const triangulate = matrix => {
  const A = matrix.map(v => v.slice());
  const [nrows, ncols] = ops.shape(A);

  let row = 0;

  for (let col = 0; col < ncols; ++col) {
    while (true) {
      const pivotRow = findPivot(A, col, row);
      if (pivotRow == null)
        break;

      if (pivotRow != row)
        [A[row], A[pivotRow]] = [A[pivotRow], A[row]];

      if (ops.sgn(A[row]) < 0)
        A[row] = ops.negative(A[row]);

      for (let i = row + 1; i < nrows; ++i) {
        if (ops.ne(0, A[i][col])) {
          const f = ops.idiv(A[i][col], A[row][col]);
          A[i] = ops.minus(A[i], ops.times(f, A[row]));
        }
      }

      if (A.every((v, i) => i <= row || ops.eq(0, v[col]))) {
        row += 1;
        break;
      }
    }
  }

  return A.slice(0, ncols);
};

const transformEdges = (edges, M) => edges.map(([head, tail, shift]) => {
  const newShift = ops.times(shift, M);

  if (newShift.some(x => !ops.isInteger(x)))
    throw new Error("panic: produced non-integer shift");

  if (head == tail && ops.sgn(newShift) > 0)
    return [head, tail, ops.negative(newShift)];
  else
    return [head, tail, newShift];
});

const transformEdgeMapping = (mapping, M) => {
  const result = {};

  for (const [key, val] of Object.entries(mapping)) {
    const edge = decode(val);
    const shift = ops.times(edge.shift, M);
    result[key] = encode(pg.makeEdge(edge.head, edge.tail, shift));
  }

  return result;
};

export const invariantWithMapping = graph => {
  const pos = pg.barycentricPlacement(graph);
  const sym = ps.symmetries(graph);

  const _cmpSteps = ([headA, tailA, shiftA], [headB, tailB, shiftB]) =>
    (headA - headB) || (tailA - tailB) || ops.cmp(shiftA, shiftB);

  let best = null;

  const bases = sym.representativeEdgeLists;

  for (const edgeList of bases) {
    const transform = ops.inverse(edgeList.map(e => pg.edgeVector(e, pos)));
    const base = placeOrderedTraversal(graph, edgeList[0].head, transform);
    const trav = buffered(adjustedTraversal(base));

    if (best == null)
      best = trav;
    else {
      for (let i = 0; ; ++i) {
        const next = trav.get(i);
        if (next == null)
          break;

        const d = _cmpSteps(next, best.get(i));
        if (d < 0)
          best = trav;
        else if (d > 0)
          break;
      }
    }
  }

  const { generated, returned } = best.result();
  const shifts = generated.map(([head, tail, shift]) => shift);
  const M = ops.inverse(triangulate(shifts));

  const edges = transformEdges(generated, M).sort(_cmpSteps);
  const basisChange = ops.times(returned.basisChange, M);
  const vertexMapping = returned.vertexMapping;
  const edgeMapping = transformEdgeMapping(returned.edgeMapping, M);

  return { edges, vertexMapping, edgeMapping, basisChange };
};

export const invariant = graph => invariantWithMapping(graph).edges;

export const systreKey = graph => {
  const seq = [graph.dim];

  for (const [from, to, shift] of invariant(graph)) {
    seq.push(from);
    seq.push(to);
    for (const x of shift)
      seq.push(x);
  }

  return seq.join(' ');
};

export const keyVersion = '1.0';

if (require.main == module) {
  Array.prototype.toString = function() {
    return `[ ${this.map(x => x.toString()).join(', ')} ]`;
  };

  const test = g => {
    const inv = invariantWithMapping(g);

    for (const e of g.edges)
      console.log(`${e}`);
    console.log();

    for (const k of Object.keys(inv.vertexMapping))
      console.log(`${k} => ${inv.vertexMapping[k]}`);
    console.log();

    for (const k of Object.keys(inv.edgeMapping))
      console.log(`(${decode(k)}) => (${decode(inv.edgeMapping[k])})`);
    console.log();

    console.log(inv.basisChange);
    console.log();

    for (const e of inv.edges)
      console.log(`${pg.makeEdge(...e)}`);
    console.log();

    console.log();
  };

  test(pg.makeGraph(
    [ [ 1, 2, [ 0, 0, 0 ] ],
      [ 1, 2, [ 1, 0, 0 ] ],
      [ 1, 2, [ 0, 1, 0 ] ],
      [ 1, 2, [ 0, 0, 1 ] ] ]
  ));

  test(pg.makeGraph(
    [ [ 1, 2, [ 0, 0 ] ],
      [ 1, 2, [ 1, 0 ] ],
      [ 2, 3, [ 0, 0 ] ],
      [ 2, 3, [ 0, 1 ] ],
      [ 1, 3, [ 0, 0 ] ],
      [ 1, 3, [ 1, 1 ] ] ]
  ));
}
<|endoftext|>


<commit_before>// This is the node.js server for AstroWebServices.com.

var app = require('http').createServer(handler);
var url = require('url');
var fs = require('fs');
var io = require('socket.io')(app);

app.listen(8001);

var handleDataset = function(dataset) {
    var fileObj;
    io.on('connection', function(socket) {
      console.log('emitting dataset');
      // Read the configuration file.
      fs.readFile('data/' + dataset + '/description.json', 'utf8', function(err, data) {
	if (err) {
	  // Dataset doesn't exist or something is wrong.
	  socket.emit('dataset', { 'dataset': 'UNKNOWN',
				   'image': null, 'size': null });
	  socket.disconnect();
	  return;
	}
	fileObj = JSON.parse(data);
	socket.emit('dataset', { 'dataset': fileObj['name'],
				 'image': '/images/' + dataset + '/' + fileObj['image']['file'],
				 'size': fileObj['image']['size'] } );
	socket.on('position-request', function(data) {
	  var n = './data/' + dataset + '/positions/pos_' + data['pix'][0] + '_' + data['pix'][1];
	  fs.readFile(n, 'utf8', function(err, data) {
	    var posObj = JSON.parse(data);
	    socket.emit('position-info', posObj);
	  });
	});
      });
    });
    if (typeof dataset !== 'undefined') {
      fs.readFile('./spectraViewer.html', function(error, data) {
	if (error) {
	  response.writeHead(404);
	  response.write('Unable to load spectra viewer.');
	  response.end();
	} else {
	  response.writeHead(200, { 'Content-Type': 'text/html' });
	  response.write(data, "utf8");
	  response.end();
	}
      });
    }
};

function handler (request, response) {
  console.log('Connection.');
  var path = url.parse(request.url).pathname;

  if (/^\/spectraViewer\//.test(path)) {
    // User wants the spectra viewer.
    var dr = /^\/spectraViewer\/(.*)\/*$/.exec(path);
    var dataset = dr[1];
    handleDataset(dataset);
  } else if (/^\/scripts\//.test(path)) {
    // Return the user a JS.
    var dr = /^\/scripts\/(.*)$/.exec(path);
    console.log('requested a script ' + dr[1]);
    fs.readFile(__dirname + "/" + dr[1], function(error, data) {
      if (error) {
	response.writeHead(404);
	response.write('Unable to find script.');
	response.end();
      } else {
	response.writeHead(200, { 'Content-Type': 'application/javascript' });
	response.write(data, "utf8");
	response.end();
      }
    });
  } else if (/^\/images\//.test(path)) {
    var dr = /^\/images\/(.*)$/.exec(path);
    var ext = /^.*\.([^\.]*)$/.exec(path);
    var contentType = 'image/' + ext[1];
    response.writeHead(200, { 'Content-Type': contentType });
    fs.createReadStream('data/' + dr[1], 'utf-8').pipe(response);
  } else {
    // Show the default page.
    response.writeHead(200, { 'Content-Type': 'text/html' });
    response.write('hello world');
    response.end();
  }

};
<commit_msg>Trying to make error handling more robust.<commit_after>// This is the node.js server for AstroWebServices.com.

var app = require('http').createServer(handler);
var url = require('url');
var fs = require('fs');
var io = require('socket.io')(app);

app.listen(8001);

var handleDataset = function(dataset, request, response) {
    var fileObj;
    io.on('connection', function(socket) {
      console.log('emitting dataset');
      // Read the configuration file.
      fs.readFile('data/' + dataset + '/description.json', 'utf8', function(err, data) {
	if (err) {
	  // Dataset doesn't exist or something is wrong.
	  socket.emit('dataset', { 'dataset': 'UNKNOWN',
				   'image': null, 'size': null });
	  socket.disconnect();
	  return;
	}
	fileObj = JSON.parse(data);
	socket.emit('dataset', { 'dataset': fileObj['name'],
				 'image': '/images/' + dataset + '/' + fileObj['image']['file'],
				 'size': fileObj['image']['size'] } );
	socket.on('position-request', function(data) {
	  var n = './data/' + dataset + '/positions/pos_' + data['pix'][0] + '_' + data['pix'][1];
	  fs.readFile(n, 'utf8', function(err, data) {
	    var posObj = JSON.parse(data);
	    socket.emit('position-info', posObj);
	  });
	});
      });
    });
    if (typeof dataset !== 'undefined') {
      fs.readFile('./spectraViewer.html', function(error, data) {
	if (error) {
	  response.writeHead(404);
	  response.write('Unable to load spectra viewer.');
	  response.end();
	} else {
	  response.writeHead(200, { 'Content-Type': 'text/html' });
	  response.write(data, "utf8");
	  response.end();
	}
      });
    }
};

function handler (request, response) {
  console.log('Connection.');
  var path = url.parse(request.url).pathname;

  if (/^\/spectraViewer\//.test(path)) {
    // User wants the spectra viewer.
    var dr = /^\/spectraViewer\/(.*)\/*$/.exec(path);
    var dataset = dr[1];
    handleDataset(dataset, request, response);
  } else if (/^\/scripts\//.test(path)) {
    // Return the user a JS.
    var dr = /^\/scripts\/(.*)$/.exec(path);
    console.log('requested a script ' + dr[1]);
    fs.readFile(__dirname + "/" + dr[1], function(error, data) {
      if (error) {
	response.writeHead(404);
	response.write('Unable to find script.');
	response.end();
      } else {
	response.writeHead(200, { 'Content-Type': 'application/javascript' });
	response.write(data, "utf8");
	response.end();
      }
    });
  } else if (/^\/images\//.test(path)) {
    var dr = /^\/images\/(.*)$/.exec(path);
    var ext = /^.*\.([^\.]*)$/.exec(path);
    var contentType = 'image/' + ext[1];
    response.writeHead(200, { 'Content-Type': contentType });
    fs.createReadStream('data/' + dr[1], 'utf-8').pipe(response);
  } else {
    // Show the default page.
    response.writeHead(200, { 'Content-Type': 'text/html' });
    response.write('hello world');
    response.end();
  }

};
<|endoftext|>