<commit_before>var midas = midas || {};
midas.slicerappstore = midas.slicerappstore || {};

var json = null;

/**
 * Displays the login dialog
 */
midas.slicerappstore.doLogin = function () {
    var content = $('#loginFormTemplate').clone();
    content.find('form.loginForm').attr('id', 'appstoreLoginForm');
    content.find('div.loginError').attr('id', 'appstoreLoginError');
    midas.showDialogWithContent('Login', content.html(), false, { width: 320 });
    $('a.registerLink').click(midas.slicerappstore.doRegister);
    $('#appstoreLoginForm').ajaxForm({
        success: function (responseText, statusText, xhr, form) {
            var resp = $.parseJSON(responseText);
            if(resp.status == 'ok') {
                window.location.reload();
            } else {
                $('#appstoreLoginError').html('Login failed');
            }
        }
    });
}

/**
 * Displays the register dialog
 */
midas.slicerappstore.doRegister = function () {
    var content = $('#registerFormTemplate').clone();
    content.find('form.registerForm').attr('id', 'registerForm');
    content.find('div.registerError').attr('id', 'registerError');
    midas.showDialogWithContent('Register', content.html(), false, { width: 380 });
    $('a.loginLink').click(midas.slicerappstore.doLogin);
    $('#registerForm').ajaxForm({
        success: function (responseText, statusText, xhr, form) {
            var resp = $.parseJSON(responseText);
            if(resp.status == 'ok') {
                window.location.reload();
            } else {
                var errorText = '
';
                if(resp.alreadyRegistered) {
                    $('#registerForm').find('input[type=text],input[type=password]')
                    .removeClass('invalidField').addClass('validField');
                    $('#registerForm').find('input[name=email]').removeClass('validField').addClass('invalidField');
                    errorText += '
'+resp.message+'
';
                } else {
                    $('#registerForm').find('input[type=text],input[type=password]')
                    .removeClass('validField').addClass('invalidField');

                    $.each(resp.validValues, function(field, value) {
                        $('#registerForm').find('input[name='+field+']')
                        .removeClass('invalidField').addClass('validField');
                    });
                    if(!resp.validValues.email) {
                        errorText += '
Invalid email
';
                    }
                    if(!resp.validValues.firstname) {
                        errorText += '
Invalid first name
';
                    }
                    if(!resp.validValues.lastname) {
                        errorText += '
Invalid last name
';
                    }
                    if(!resp.validValues.password1) {
                        errorText += '
Invalid password
';
                    }
                    if(!resp.validValues.password2) {
                        errorText += '
Passwords must match
';
                    }
                }
                errorText += '
';
                $('#registerError').html(errorText);
            }
        }
    });
}

/**
 * Renders the category of this extension as a breadcrumb bar
 */
midas.slicerappstore.renderCategory = function(category) {
    var currToken = '';
    // if this extension belongs to multiple categories, we just render the first one
    category = category.split(';')[0];
    var categories = category.split('.');
    $.each(categories, function(k, token) {
        currToken += token;
        var html = ' > ';
        html += '' + token + '';
        currToken += '.';
        $('#categoryBreadcrumb').append(html);
    });
};

/**
 * Renders the screenshots for this extension. Expects a space separated list of URLs
 */
midas.slicerappstore.renderScreenshots = function(screenshots) {
  if(screenshots == '') {
      $('div.screenshots').html('There are no screenshots for this extension.');
      return;
  }
  screenshots = screenshots.split(' ');
  $.each(screenshots, function(k, url) {
      if(url != '') {
          var template = $('#screenshotTemplate').clone();
          template.removeAttr('id');
          var link = template.find('a.screenshotPreview');
          link.attr('href', url);
          var img = link.find('img.screenshotPreview');
          img.attr('src', url);
          img.attr('alt', url);
          template.appendTo('div.screenshots');
          template.show();
      }
  });
  $('div.screenshots a.screenshotPreview').lightBox({
      imageLoading: json.global.webroot+'/modules/slicerappstore/public/images/lightbox/lightbox-ico-loading.gif',
      imageBlank: json.global.webroot+'/modules/slicerappstore/public/images/lightbox/lightbox-blank.gif',
      imageBtnClose: json.global.webroot+'/modules/slicerappstore/public/images/lightbox/lightbox-btn-close.gif',
      imageBtnPrev: json.global.webroot+'/modules/slicerappstore/public/images/lightbox/lightbox-btn-prev.gif',
      imageBtnNext: json.global.webroot+'/modules/slicerappstore/public/images/lightbox/lightbox-btn-next.gif'
  });
  $('div.screenshotContainer').imgLiquid({
      fill: false
  });
}

$(document).ready(function() {
    midas.slicerappstore.renderCategory(json.extension.category);
    midas.slicerappstore.renderScreenshots(json.extension.screenshots);

    $('input.extensionActionButton')
        .attr('element', json.extension.slicerpackages_extension_id)
        .attr('extensionname', json.extension.productname);
    midas.slicerappstore.updateExtensionButtonState(json.extension.productname);

    if(json.layout == 'empty') {
        midas.registerCallback('CALLBACK_RATINGS_AFTER_LOAD', 'ratings', function() {
            $('#loginToComment,#loginToRate').unbind('click').click(midas.slicerappstore.doLogin);
            $('#registerToComment,#registerToRate').unbind('click').click(midas.slicerappstore.doRegister);
        });
    }

    $('#viewUrl').click(function(){
      $('#dialogUrl').dialog({
        width: 450
      });
      $('#dialogUrl input').select();
      $('#dialogUrl input').click(function(){
        $(this).select();
      })
    });

    $('#commentsDiv h4').remove();
    $('#ratingsDiv h4').remove();
    $('#ratingsUser').appendTo('#ratingsDiv');
    $('div.loginToRate').appendTo('#ratingsDiv');
    $('div.loginToRate').css('float', 'left');

    $('.googlePlus,.twitter,.facebook').qtip({
        content: {
            attr: 'qtip'
        },
        position: {
            at: 'bottom right',
            my: 'top left',
            viewport: $(window),
            effect: true
        }
    });

    var url = json.global.webroot+'/slicerappstore'
             + '?os=' + json.extension.os
             + '&arch=' + json.extension.arch
             + '&revision=' + json.extension.slicer_revision
             + '&layout=' + json.layout;

    $('#rootBreadcrumb').attr('href', url);
    // Enable logout link
    $('#logoutLink').click(function () {
        $.post(json.global.webroot+'/user/logout', {noRedirect: true}, function() {
            window.location.reload();
        });
    });
});
<commit_msg>ENH: Close 'view URL' dialog on outside click<commit_after>var midas = midas || {};
midas.slicerappstore = midas.slicerappstore || {};

var json = null;

/**
 * Displays the login dialog
 */
midas.slicerappstore.doLogin = function () {
    var content = $('#loginFormTemplate').clone();
    content.find('form.loginForm').attr('id', 'appstoreLoginForm');
    content.find('div.loginError').attr('id', 'appstoreLoginError');
    midas.showDialogWithContent('Login', content.html(), false, { width: 320 });
    $('a.registerLink').click(midas.slicerappstore.doRegister);
    $('#appstoreLoginForm').ajaxForm({
        success: function (responseText, statusText, xhr, form) {
            var resp = $.parseJSON(responseText);
            if(resp.status == 'ok') {
                window.location.reload();
            } else {
                $('#appstoreLoginError').html('Login failed');
            }
        }
    });
}

/**
 * Displays the register dialog
 */
midas.slicerappstore.doRegister = function () {
    var content = $('#registerFormTemplate').clone();
    content.find('form.registerForm').attr('id', 'registerForm');
    content.find('div.registerError').attr('id', 'registerError');
    midas.showDialogWithContent('Register', content.html(), false, { width: 380 });
    $('a.loginLink').click(midas.slicerappstore.doLogin);
    $('#registerForm').ajaxForm({
        success: function (responseText, statusText, xhr, form) {
            var resp = $.parseJSON(responseText);
            if(resp.status == 'ok') {
                window.location.reload();
            } else {
                var errorText = '
';
                if(resp.alreadyRegistered) {
                    $('#registerForm').find('input[type=text],input[type=password]')
                    .removeClass('invalidField').addClass('validField');
                    $('#registerForm').find('input[name=email]').removeClass('validField').addClass('invalidField');
                    errorText += '
'+resp.message+'
';
                } else {
                    $('#registerForm').find('input[type=text],input[type=password]')
                    .removeClass('validField').addClass('invalidField');

                    $.each(resp.validValues, function(field, value) {
                        $('#registerForm').find('input[name='+field+']')
                        .removeClass('invalidField').addClass('validField');
                    });
                    if(!resp.validValues.email) {
                        errorText += '
Invalid email
';
                    }
                    if(!resp.validValues.firstname) {
                        errorText += '
Invalid first name
';
                    }
                    if(!resp.validValues.lastname) {
                        errorText += '
Invalid last name
';
                    }
                    if(!resp.validValues.password1) {
                        errorText += '
Invalid password
';
                    }
                    if(!resp.validValues.password2) {
                        errorText += '
Passwords must match
';
                    }
                }
                errorText += '
';
                $('#registerError').html(errorText);
            }
        }
    });
}

/**
 * Renders the category of this extension as a breadcrumb bar
 */
midas.slicerappstore.renderCategory = function(category) {
    var currToken = '';
    // if this extension belongs to multiple categories, we just render the first one
    category = category.split(';')[0];
    var categories = category.split('.');
    $.each(categories, function(k, token) {
        currToken += token;
        var html = ' > ';
        html += '' + token + '';
        currToken += '.';
        $('#categoryBreadcrumb').append(html);
    });
};

/**
 * Renders the screenshots for this extension. Expects a space separated list of URLs
 */
midas.slicerappstore.renderScreenshots = function(screenshots) {
  if(screenshots == '') {
      $('div.screenshots').html('There are no screenshots for this extension.');
      return;
  }
  screenshots = screenshots.split(' ');
  $.each(screenshots, function(k, url) {
      if(url != '') {
          var template = $('#screenshotTemplate').clone();
          template.removeAttr('id');
          var link = template.find('a.screenshotPreview');
          link.attr('href', url);
          var img = link.find('img.screenshotPreview');
          img.attr('src', url);
          img.attr('alt', url);
          template.appendTo('div.screenshots');
          template.show();
      }
  });
  $('div.screenshots a.screenshotPreview').lightBox({
      imageLoading: json.global.webroot+'/modules/slicerappstore/public/images/lightbox/lightbox-ico-loading.gif',
      imageBlank: json.global.webroot+'/modules/slicerappstore/public/images/lightbox/lightbox-blank.gif',
      imageBtnClose: json.global.webroot+'/modules/slicerappstore/public/images/lightbox/lightbox-btn-close.gif',
      imageBtnPrev: json.global.webroot+'/modules/slicerappstore/public/images/lightbox/lightbox-btn-prev.gif',
      imageBtnNext: json.global.webroot+'/modules/slicerappstore/public/images/lightbox/lightbox-btn-next.gif'
  });
  $('div.screenshotContainer').imgLiquid({
      fill: false
  });
}

$(document).ready(function() {
    midas.slicerappstore.renderCategory(json.extension.category);
    midas.slicerappstore.renderScreenshots(json.extension.screenshots);

    $('input.extensionActionButton')
        .attr('element', json.extension.slicerpackages_extension_id)
        .attr('extensionname', json.extension.productname);
    midas.slicerappstore.updateExtensionButtonState(json.extension.productname);

    if(json.layout == 'empty') {
        midas.registerCallback('CALLBACK_RATINGS_AFTER_LOAD', 'ratings', function() {
            $('#loginToComment,#loginToRate').unbind('click').click(midas.slicerappstore.doLogin);
            $('#registerToComment,#registerToRate').unbind('click').click(midas.slicerappstore.doRegister);
        });
    }

    $('#viewUrl').click(function(){
      $('#dialogUrl').dialog({
        width: 450,
        modal: true,
        open: function(){
          $('.ui-widget-overlay').click(function(){
            $('#dialogUrl').dialog('close');
          })
        }
      });
      $('#dialogUrl input').select();
      $('#dialogUrl input').click(function(){
        $(this).select();
      })
    });

    $('#commentsDiv h4').remove();
    $('#ratingsDiv h4').remove();
    $('#ratingsUser').appendTo('#ratingsDiv');
    $('div.loginToRate').appendTo('#ratingsDiv');
    $('div.loginToRate').css('float', 'left');

    $('.googlePlus,.twitter,.facebook').qtip({
        content: {
            attr: 'qtip'
        },
        position: {
            at: 'bottom right',
            my: 'top left',
            viewport: $(window),
            effect: true
        }
    });

    var url = json.global.webroot+'/slicerappstore'
             + '?os=' + json.extension.os
             + '&arch=' + json.extension.arch
             + '&revision=' + json.extension.slicer_revision
             + '&layout=' + json.layout;

    $('#rootBreadcrumb').attr('href', url);
    // Enable logout link
    $('#logoutLink').click(function () {
        $.post(json.global.webroot+'/user/logout', {noRedirect: true}, function() {
            window.location.reload();
        });
    });
});
<|endoftext|>


<commit_before>var View = function(){};
var util = require('util');
util.inherits(View, require('events').EventEmitter);
var _view = new View();

var $editor = document.querySelector('#editor');
var $preview = document.querySelector('#preview');
var $sidebar = document.querySelector('#sidebar');

var openNewWindow = function(cssArr,jsArr,action,message){

	var newWindow = window.open('file://' + __dirname + '/../blank.html','newWindow','');

	newWindow.webContents.on('did-finish-load',function(){
		console.log('ready');
		newWindow.webContents.send('loadCss',cssArr);
		newWindow.webContents.send('loadJs',jsArr);
		newWindow.webContents.send(action,message);
		// 开发环境打开调试工具
		if(!/app$/.test(__dirname)){
			newWindow.openDevTools();
		}
	});
};

_view.openNoteInNewWindow = function(note){
	openNewWindow([
		'./editor.css',
		'./monokai_sublime.css'
	],[
		'./highlight.pack.js',
	],'loadNote',note);
};

_view.renderPreview = function(note){
	var $preview = document.querySelector('#preview');
	var marked = require('marked');
	var previewRenderer = new marked.Renderer();
	var index = 0;
	previewRenderer.heading = function (text, level) {
		return '<h' + level + '>'+ text + '</h' + level + '>';
	};
	var html = marked(note.content,{renderer:previewRenderer});
	$preview.innerHTML = html;

	Array.prototype.forEach.call($preview.querySelectorAll('pre code'),function($code){
		hljs.highlightBlock($code.parentNode);
	});
	var todo = require('./todo');
	var $allLi = $preview.querySelectorAll('li');
	for(var i = $allLi.length;i--;){
		var $li = $allLi[i];
		$li.innerHTML = todo.parseTodo($li.innerHTML);
	}

	var toc = require('marked-toc');
	var tocMarkdown = toc(note.content);
	var tocRenderer = new marked.Renderer();
	index = 1;
	tocRenderer.link = function(href,title,text){
		return ''+text+'';
	};
	var tocHtml = marked(tocMarkdown,{renderer:tocRenderer});
	var $toc = document.querySelector('#toc');
	if(tocHtml){
		$toc.innerHTML = tocHtml;
		$toc.classList.remove('hide');
	}else{
		$toc.classList.add('hide');
	}
};

_view.init = function(){
	var _this = this;
	var hideTabs = JSON.parse(localStorage.getItem('toonote_hideTabs') || '[]');
	window.addEventListener('DOMContentLoaded',function(){
		hideTabs.forEach(function(hideTab){
			_this.switchVisible(hideTab);
		});
	});
};

// 切换各栏显示状态
_view.switchVisible = function(eleName){

	var $ele;

	switch(eleName){
		case 'sidebar':
			$ele = $sidebar;
			break;
		case 'editor':
			$ele = $editor;
			break;
		case 'preview':
			$ele = $preview;
			break;
	}

	if($ele.classList.contains('hide')){
		$ele.classList.remove('hide');
	}else{
		$ele.classList.add('hide');
	}

	var sidebarVisible = !$sidebar.classList.contains('hide');
	var editorVisible = !$editor.classList.contains('hide');
	var previewVisible = !$preview.classList.contains('hide');

	var editorStatus = sidebarVisible?
		(previewVisible?'normal':'aloneWithSidebar'):
		(previewVisible?'noSidebar':'alone');
	var previewStatus = sidebarVisible?
		(editorVisible?'normal':'aloneWithSidebar'):
		(editorVisible?'noSidebar':'alone');

	if(editorVisible){
		$editor.classList.remove('aloneWithSidebar','noSidebar','alone');
		$editor.classList.add(editorStatus);
	}
	if(previewVisible){
		$preview.classList.remove('aloneWithSidebar','noSidebar','alone');
		$preview.classList.add(previewStatus);
	}

	var hideTabs = [];
	if(!sidebarVisible){
		hideTabs.push('sidebar');
	}
	if(!editorVisible){
		hideTabs.push('editor');
	}
	if(!previewVisible){
		hideTabs.push('preview');
	}

	// 处理TOC显示隐藏
	if(hideTabs.indexOf('preview') > -1){
		document.querySelector('#toc').classList.add('hide');
	}else{
		document.querySelector('#toc').classList.remove('hide');
	}

	_view.emit('layoutChange',hideTabs);

	localStorage.setItem('toonote_hideTabs',JSON.stringify(hideTabs));

};

_view.isVisible = function(eleName){
	var hideTabs = JSON.parse(localStorage.getItem('toonote_hideTabs') || '[]');
	return hideTabs.indexOf(eleName) === -1;
};

var bindEvents = function(){

	// 折叠笔记
	$sidebar.querySelector('#noteList').addEventListener('click',function(e){
		if(e.target.tagName !== 'LI') return false;
		var $tmpNode = e.target.nextSibling;
		if(!$tmpNode) return;
		var thisLevel = +e.target.dataset.level;
		var isVisible = getComputedStyle($tmpNode).display !== 'none';
		while($tmpNode && +$tmpNode.dataset.level > thisLevel){
			if(isVisible){
				$tmpNode.style.display = 'none';
			}else{
				$tmpNode.style.display = '';
			}
			$tmpNode = $tmpNode.nextSibling;
		}

	},false);
};

bindEvents();

module.exports = _view;<commit_msg>修复预览区不存在时TOC无故出现的bug<commit_after>var View = function(){};
var util = require('util');
util.inherits(View, require('events').EventEmitter);
var _view = new View();

var $editor = document.querySelector('#editor');
var $preview = document.querySelector('#preview');
var $sidebar = document.querySelector('#sidebar');

var openNewWindow = function(cssArr,jsArr,action,message){

	var newWindow = window.open('file://' + __dirname + '/../blank.html','newWindow','');

	newWindow.webContents.on('did-finish-load',function(){
		console.log('ready');
		newWindow.webContents.send('loadCss',cssArr);
		newWindow.webContents.send('loadJs',jsArr);
		newWindow.webContents.send(action,message);
		// 开发环境打开调试工具
		if(!/app$/.test(__dirname)){
			newWindow.openDevTools();
		}
	});
};

_view.openNoteInNewWindow = function(note){
	openNewWindow([
		'./editor.css',
		'./monokai_sublime.css'
	],[
		'./highlight.pack.js',
	],'loadNote',note);
};

_view.renderPreview = function(note){
	var $preview = document.querySelector('#preview');
	var marked = require('marked');
	var previewRenderer = new marked.Renderer();
	var index = 0;
	previewRenderer.heading = function (text, level) {
		return '<h' + level + '>'+ text + '</h' + level + '>';
	};
	var html = marked(note.content,{renderer:previewRenderer});
	$preview.innerHTML = html;

	Array.prototype.forEach.call($preview.querySelectorAll('pre code'),function($code){
		hljs.highlightBlock($code.parentNode);
	});
	var todo = require('./todo');
	var $allLi = $preview.querySelectorAll('li');
	for(var i = $allLi.length;i--;){
		var $li = $allLi[i];
		$li.innerHTML = todo.parseTodo($li.innerHTML);
	}

	var toc = require('marked-toc');
	var tocMarkdown = toc(note.content);
	var tocRenderer = new marked.Renderer();
	index = 1;
	tocRenderer.link = function(href,title,text){
		return ''+text+'';
	};
	var tocHtml = marked(tocMarkdown,{renderer:tocRenderer});
	var $toc = document.querySelector('#toc');
	if(tocHtml && this.isVisible('preview')){
		$toc.innerHTML = tocHtml;
		$toc.classList.remove('hide');
	}else{
		$toc.classList.add('hide');
	}
};

_view.init = function(){
	var _this = this;
	var hideTabs = JSON.parse(localStorage.getItem('toonote_hideTabs') || '[]');
	window.addEventListener('DOMContentLoaded',function(){
		hideTabs.forEach(function(hideTab){
			_this.switchVisible(hideTab);
		});
	});
};

// 切换各栏显示状态
_view.switchVisible = function(eleName){

	var $ele;

	switch(eleName){
		case 'sidebar':
			$ele = $sidebar;
			break;
		case 'editor':
			$ele = $editor;
			break;
		case 'preview':
			$ele = $preview;
			break;
	}

	if($ele.classList.contains('hide')){
		$ele.classList.remove('hide');
	}else{
		$ele.classList.add('hide');
	}

	var sidebarVisible = !$sidebar.classList.contains('hide');
	var editorVisible = !$editor.classList.contains('hide');
	var previewVisible = !$preview.classList.contains('hide');

	var editorStatus = sidebarVisible?
		(previewVisible?'normal':'aloneWithSidebar'):
		(previewVisible?'noSidebar':'alone');
	var previewStatus = sidebarVisible?
		(editorVisible?'normal':'aloneWithSidebar'):
		(editorVisible?'noSidebar':'alone');

	if(editorVisible){
		$editor.classList.remove('aloneWithSidebar','noSidebar','alone');
		$editor.classList.add(editorStatus);
	}
	if(previewVisible){
		$preview.classList.remove('aloneWithSidebar','noSidebar','alone');
		$preview.classList.add(previewStatus);
	}

	var hideTabs = [];
	if(!sidebarVisible){
		hideTabs.push('sidebar');
	}
	if(!editorVisible){
		hideTabs.push('editor');
	}
	if(!previewVisible){
		hideTabs.push('preview');
	}

	// 处理TOC显示隐藏
	if(hideTabs.indexOf('preview') > -1){
		document.querySelector('#toc').classList.add('hide');
	}else{
		document.querySelector('#toc').classList.remove('hide');
	}

	_view.emit('layoutChange',hideTabs);

	localStorage.setItem('toonote_hideTabs',JSON.stringify(hideTabs));

};

_view.isVisible = function(eleName){
	var hideTabs = JSON.parse(localStorage.getItem('toonote_hideTabs') || '[]');
	return hideTabs.indexOf(eleName) === -1;
};

var bindEvents = function(){

	// 折叠笔记
	$sidebar.querySelector('#noteList').addEventListener('click',function(e){
		if(e.target.tagName !== 'LI') return false;
		var $tmpNode = e.target.nextSibling;
		if(!$tmpNode) return;
		var thisLevel = +e.target.dataset.level;
		var isVisible = getComputedStyle($tmpNode).display !== 'none';
		while($tmpNode && +$tmpNode.dataset.level > thisLevel){
			if(isVisible){
				$tmpNode.style.display = 'none';
			}else{
				$tmpNode.style.display = '';
			}
			$tmpNode = $tmpNode.nextSibling;
		}

	},false);
};

bindEvents();

module.exports = _view;<|endoftext|>


<commit_before>import * as React from "react"

// Simple class used to represent children of the
// virtual node. In fact single instance `NodeList.empty`
// is only use of it & it is used by all nodes that have
// no children.
class NodeList extends Array {
  constructor() {
    super()
    const length = arguments.length
    let index = 0
    while (index < length) {
      this[index] = arguments[index]
      index = index + 1
    }
    this.length = length
    Object.freeze(this)
  }
}
NodeList.empty = new NodeList()

// Type used to represent properties of the virtual
// node. It's primarily used when cloning virtual nodes,
// although empty maps are also used and populated during
// virtual node construction.
class PropertyMap {
  constructor(entries) {
    if (entries) {
      for (let name in entries) {
        if (entries.hasOwnProperty(name)) {
          this[name] = entries[name]
        }
      }
    }
  }
}

// Function is an equivalent of `document.dispatchEvent` although this
// function takes target virtual node and an action to disptach on it.
// `action` will be passed to a `receive` method of the node if it implements
// it or of a nearest ancestors does.
export const dispatch = (node, action) => {
  if (action !== null) {
    while (node && !node.receive) {
      node = node.props.parent
    }
    node.receive(action)
  }
}

// Entity is an abstract class that represent entities in the virtal dom tree.
// Note that not all entities in the graph are virtual nodes, some of them are
// thunks a.k.a react components that compute their virtual dom sub-tree lazily.
// Another non virtual node entities are fragments that represent namespaced
// list of virtual nodes. Plain react components are in fact also entities although
// they do not inherit from this Entity class as they are third party entities.
class Entity {
  // Every entity in the virtual dom tree is given a `parent` entity during construction via
  // `adopt` method. Method ensures that given `child` entity has a correct reference to it's
  // `parent`. If `child` is an orphan parent is just assigned to it (note that all virtual
  // nodes start as orphans as children tend to be constracted ahead of their parents). If
  // `child` already has a different parent, which can occur if same entity is re-used in the
  // different branches of the dom tree, then `child` is cloned (with all of it's children) and
  // returned (parent is assigned to a returned clone). Some children maybe primitive values
  // like string which are returned as is.
  adopt(child) {
    if (child instanceof Entity) {
      const {parent} = child.props
      if (parent == null) {
        child.props.parent = this
      } else if (parent !== this) {
        child = child.clone()
        child.proprs.parent = this
      }
    } else if (child && child._isReactElement) {
      const {_store} = child
      _store.originalProps = _store.props
      _store.props.parent = this
    }

    return child
  }
}

// Virtual node class represent a virtual version of an HTML element, it takes
// `type` (tagName of the node) hash a `properties` PropertyMap and array of
// children. Instances of `Node` implement interface of `React.createElement`
// and are used as such.
class Node extends Entity {
  constructor(type, properties, children) {
    super()
    this.type = type
    this.key = properties.key || properties.id
    this.children = children === NodeList.empty ? children :
                    typeof(children) === "string" ? children :
                    children.map(this.adopt, this)

    this.properties = properties

    var props = properties
    props.children = this.children
    props.parent = null

    this.props = props
    this.props.parent = null
    this._store = {originalProps: props, props}
    this._isReactElement = true
  }
  // Node class implements `clone` method so that non orphand instances
  // could be adopted by cloning.
  clone() {
    const {constructor, type, properties, children} = this
    console.warn(`cloned node`, this)
    return new constructor(type,
                           new PropertyMap(properties),
                           children)
  }
}

// EventTarget class instances represent virtual nodes that have an event handlers
// assigned. Event handlers are supposed to return an action that is dispatched
// on the node. Constructor is given a `type` of node (tagName), properties in form
// of `PropertyMap` and a `table` of event handers that are keyed by lower cased
// handler names like `onload`, `ondomcontentloaded` etc..
class EventTarget extends Node {
  constructor(type, properties, children) {
    super(type, properties, children);
    this.handleEvent = this.handleEvent.bind(this);
  }
  // handleEvent is invoked with an `event` once event on an actual dom node
  // that this represents occurs. Method looks up an associated handler in
  // the table and dispatches read action.
  handleEvent(event) {
    const {phasedRegistrationNames, registrationName} = event.dispatchConfig;
    const name = registrationName ? registrationName :
                 event.eventPhase === 2 ? phasedRegistrationNames.captured :
                 phasedRegistrationNames.bubbled;
    const read = this.properties[`reflex/read:${name}`];
    if (read) {
      dispatch(this, read(event));
    } else {
      event.persist();
      console.warn(`Unexpected event occured`, this, event);
    }
  }
  // EventTarget class implements `clone` method so that non orphand instances
  // could be adopted by cloning.
  clone() {
    const {constructor, type, properties, children, table} = this
    console.warn(`cloned event target node`, this)
    return new constructor(type,
                          new PropertyMap(properties),
                          children,
                          table)
  }
}

// node function constructs a virtual dom nodes. It takes node `tagName`,
// optional `model` properties and optional `children` and produces instance
// of the appropriate virtual `Node`.
export let node = (tagName, model, children=NodeList.empty) => {
  let node = null
  let properties = new PropertyMap()

  if (model) {
    for (let name in model) {
      if (model.hasOwnProperty(name)) {
        const value = model[name]

        // Use `node.handleEvent` as handler for all handled events & store
        // actual handlers into a table so that `handleEvent` will be able to
        // read an action from an event using appropriate handler.
        if (typeof(value) === "function") {
          node = node || new EventTarget(tagName, properties, children)
          properties[`reflex/read:${name}`] = value
          properties[name] = node.handleEvent
        } else if (name === "style" && value && value.toJSON) {
          properties[name] = value.toJSON()
        } else {
          properties[name] = value
        }
      }
    }
  }

  // If node is already present return it, otherwise it not a single event
  // handler was provided in which case we use simpler `Node` class to produce
  // an instance.
  return node || new Node(tagName, properties, children)
}

// Create a function for react supported nodes.
export let html = Object.create(null)
Object.keys(React.DOM).forEach(tagName => {
  html[tagName] = (model, children) => node(tagName, model, children)
})

// Fragment insntances represents a namespacing facility for
// entities in virtual dom tree, primarily to group several keyed
// nodes without wrapping them in an element. This allows different
// groups of nodes to be joined under the same parent. Namespacing
// such groups with a `properties.key` is crucial for optimising
// performance of virtual dom diffing algorithm. Optionally
// `properties.type` can be passed that will be a tagName of node
// if fragment is rendered as a root of dom tree, or root of the
// subtree that is computed lazily by a thunk. `children` argument
// is an array of nodes that this fragment represents.
class Fragment extends Entity {
  constructor(properties, children) {
    super()
    this.key = properties.key;
    this.type = properties.type || 'x:fragment';
    this.properties = properties;
    this.children = children.map(this.adopt, this);

    this.props = {parent: null, children}

    this._reactFragment = {[this.key]: this.children}
  }
  // Fragments can be cloned as other entities
  clone() {
    console.warn("clone fragment", this)
    return new this.constructor(this.properties, this.children)
  }
}

// Function for constructing fragments of virtual dom tree.
// Takes `properties.key` for identifying fragment, optional
// `properties.type` which is used as wrapper node for given
// `children` if fragment is returned from thunk or is rendered
// directly.
export let fragment = (properties, children) =>
  new Fragment(properties, children)

// Reframe class instances represent entities in the virtaul dom
// tree similar to fragments and their are intentded to reframe
// action disptched by it's children into a differet form.
class Reframe extends Fragment {
  constructor(translate, children) {
    super({key: '', type: 'x:reframe'}, children)
    this.translate = translate
  }
  clone() {
    console.warn("clone Reframe", this)
    return new this.constructor(this.translate, this.children)
  }
  receive(action) {
    dispatch(this.props.parent, this.translate(action));
  }
}

// Function for reframing entities, takes `translate` function for
// translating actions from framed entity to an action from outerframe.
export let reframe = (translate, entity) =>
  new Reframe(translate, [entity])

// View is a react component used by `Thunk` entities for a lazy
// sub tree generation and caching that can short cirquit when
// equivalent data is being rendered.
class View extends React.Component {
  constructor() {
    super(...arguments)
  }
  shouldComponentUpdate({view, model}) {
    return view !== this.props.view ||
           !model.equals(this.props.model);
  }
  render() {
    const {view, model, parent} = this.props
    const entity = view(model)
    const node = !(entity instanceof Fragment) ? entity :
                 new Node(entity.type, entity.properties, [entity])
    return parent.adopt(node)
  }
}

// Thunk instances are entities in a virtual dom tree that represent
// lazily computed sub-trees with built-in caching that avoid re-computing
// sub-tree when same data is being rendered. Thunk implements same interface
// as `React.createElement(View, data)` to be compatible with reacts virtual
// dom but it also extends `Node` class so it could be `cloned` and `adopt`-ed
// as entities defined earlier.
class Thunk extends Entity {
  constructor(model, view, key) {
    super()
    this.type = View
    this.view = view
    this.model = model
    this.key = key

    var props = this
    this.props = props
    this._store = {props, originalProps:props}
    this._isReactElement = true
  }
  clone() {
    const {model, view, key} = this
    return new this.constructor(view, model, key)
  }
}

// render function provides shortcut for rendering a model with
// default view function (although custom view function can be
// passed as second optional argument), but unlike calling view
// directly result is a thunk, there for it's defers actual computation
// and makes use of caching to avoid computation when possible.
export const render = (model, view=model.constructor.view,
                              key=model.constructor.key) =>
  new Thunk(model, view, key ? key(model) :
                         (model.key || model.id));

// Program is a root entity of the virtual dom tree that is responsible
// for computing a virtual dom tree for the `state` via given `view` function
// and reacting to dispatched actions via given `update` by updating a state
// and restarting a the same cycle again.
class Program extends Entity {
  constructor({target, state, update, view}) {
    super()
    this.target = target
    this.view = view
    this.update = update
    this.state = state
  }
  receive(action) {
    this.state = this.update(this.state, action)
    this.schedule()
  }
  schedule() {
    this.render()
    return this
  }
  render() {
    const node = this.adopt(render(this.state, this.view))
    React.render(node, this.target)
    return this
  }
}

// Function that takes `target` element to continiusly render given `model`
// into. model's default `update` function is used to update module in response
// to dispatched actions and model's default `view` function is used to compute
// dom tree represantation of the model. Optionally custom `update` and `view`
// functions could be passed to customize render loop.
export let main = (target, model, update=model.constructor.update, view=model.constructor.view) => {
  const program = new Program({
    state: model,
    target, update, view
  })
  program.schedule()
  return program
}
<commit_msg>Add `key` argument to `render` function.<commit_after>import * as React from "react"

// Simple class used to represent children of the
// virtual node. In fact single instance `NodeList.empty`
// is only use of it & it is used by all nodes that have
// no children.
class NodeList extends Array {
  constructor() {
    super()
    const length = arguments.length
    let index = 0
    while (index < length) {
      this[index] = arguments[index]
      index = index + 1
    }
    this.length = length
    Object.freeze(this)
  }
}
NodeList.empty = new NodeList()

// Type used to represent properties of the virtual
// node. It's primarily used when cloning virtual nodes,
// although empty maps are also used and populated during
// virtual node construction.
class PropertyMap {
  constructor(entries) {
    if (entries) {
      for (let name in entries) {
        if (entries.hasOwnProperty(name)) {
          this[name] = entries[name]
        }
      }
    }
  }
}

// Function is an equivalent of `document.dispatchEvent` although this
// function takes target virtual node and an action to disptach on it.
// `action` will be passed to a `receive` method of the node if it implements
// it or of a nearest ancestors does.
export const dispatch = (node, action) => {
  if (action !== null) {
    while (node && !node.receive) {
      node = node.props.parent
    }
    node.receive(action)
  }
}

// Entity is an abstract class that represent entities in the virtal dom tree.
// Note that not all entities in the graph are virtual nodes, some of them are
// thunks a.k.a react components that compute their virtual dom sub-tree lazily.
// Another non virtual node entities are fragments that represent namespaced
// list of virtual nodes. Plain react components are in fact also entities although
// they do not inherit from this Entity class as they are third party entities.
class Entity {
  // Every entity in the virtual dom tree is given a `parent` entity during construction via
  // `adopt` method. Method ensures that given `child` entity has a correct reference to it's
  // `parent`. If `child` is an orphan parent is just assigned to it (note that all virtual
  // nodes start as orphans as children tend to be constracted ahead of their parents). If
  // `child` already has a different parent, which can occur if same entity is re-used in the
  // different branches of the dom tree, then `child` is cloned (with all of it's children) and
  // returned (parent is assigned to a returned clone). Some children maybe primitive values
  // like string which are returned as is.
  adopt(child) {
    if (child instanceof Entity) {
      const {parent} = child.props
      if (parent == null) {
        child.props.parent = this
      } else if (parent !== this) {
        child = child.clone()
        child.proprs.parent = this
      }
    } else if (child && child._isReactElement) {
      const {_store} = child
      _store.originalProps = _store.props
      _store.props.parent = this
    }

    return child
  }
}

// Virtual node class represent a virtual version of an HTML element, it takes
// `type` (tagName of the node) hash a `properties` PropertyMap and array of
// children. Instances of `Node` implement interface of `React.createElement`
// and are used as such.
class Node extends Entity {
  constructor(type, properties, children) {
    super()
    this.type = type
    this.key = properties.key || properties.id
    this.children = children === NodeList.empty ? children :
                    typeof(children) === "string" ? children :
                    children.map(this.adopt, this)

    this.properties = properties

    var props = properties
    props.children = this.children
    props.parent = null

    this.props = props
    this.props.parent = null
    this._store = {originalProps: props, props}
    this._isReactElement = true
  }
  // Node class implements `clone` method so that non orphand instances
  // could be adopted by cloning.
  clone() {
    const {constructor, type, properties, children} = this
    console.warn(`cloned node`, this)
    return new constructor(type,
                           new PropertyMap(properties),
                           children)
  }
}

// EventTarget class instances represent virtual nodes that have an event handlers
// assigned. Event handlers are supposed to return an action that is dispatched
// on the node. Constructor is given a `type` of node (tagName), properties in form
// of `PropertyMap` and a `table` of event handers that are keyed by lower cased
// handler names like `onload`, `ondomcontentloaded` etc..
class EventTarget extends Node {
  constructor(type, properties, children) {
    super(type, properties, children);
    this.handleEvent = this.handleEvent.bind(this);
  }
  // handleEvent is invoked with an `event` once event on an actual dom node
  // that this represents occurs. Method looks up an associated handler in
  // the table and dispatches read action.
  handleEvent(event) {
    const {phasedRegistrationNames, registrationName} = event.dispatchConfig;
    const name = registrationName ? registrationName :
                 event.eventPhase === 2 ? phasedRegistrationNames.captured :
                 phasedRegistrationNames.bubbled;
    const read = this.properties[`reflex/read:${name}`];
    if (read) {
      dispatch(this, read(event));
    } else {
      event.persist();
      console.warn(`Unexpected event occured`, this, event);
    }
  }
  // EventTarget class implements `clone` method so that non orphand instances
  // could be adopted by cloning.
  clone() {
    const {constructor, type, properties, children, table} = this
    console.warn(`cloned event target node`, this)
    return new constructor(type,
                          new PropertyMap(properties),
                          children,
                          table)
  }
}

// node function constructs a virtual dom nodes. It takes node `tagName`,
// optional `model` properties and optional `children` and produces instance
// of the appropriate virtual `Node`.
export let node = (tagName, model, children=NodeList.empty) => {
  let node = null
  let properties = new PropertyMap()

  if (model) {
    for (let name in model) {
      if (model.hasOwnProperty(name)) {
        const value = model[name]

        // Use `node.handleEvent` as handler for all handled events & store
        // actual handlers into a table so that `handleEvent` will be able to
        // read an action from an event using appropriate handler.
        if (typeof(value) === "function") {
          node = node || new EventTarget(tagName, properties, children)
          properties[`reflex/read:${name}`] = value
          properties[name] = node.handleEvent
        } else if (name === "style" && value && value.toJSON) {
          properties[name] = value.toJSON()
        } else {
          properties[name] = value
        }
      }
    }
  }

  // If node is already present return it, otherwise it not a single event
  // handler was provided in which case we use simpler `Node` class to produce
  // an instance.
  return node || new Node(tagName, properties, children)
}

// Create a function for react supported nodes.
export let html = Object.create(null)
Object.keys(React.DOM).forEach(tagName => {
  html[tagName] = (model, children) => node(tagName, model, children)
})

// Fragment insntances represents a namespacing facility for
// entities in virtual dom tree, primarily to group several keyed
// nodes without wrapping them in an element. This allows different
// groups of nodes to be joined under the same parent. Namespacing
// such groups with a `properties.key` is crucial for optimising
// performance of virtual dom diffing algorithm. Optionally
// `properties.type` can be passed that will be a tagName of node
// if fragment is rendered as a root of dom tree, or root of the
// subtree that is computed lazily by a thunk. `children` argument
// is an array of nodes that this fragment represents.
class Fragment extends Entity {
  constructor(properties, children) {
    super()
    this.key = properties.key;
    this.type = properties.type || 'x:fragment';
    this.properties = properties;
    this.children = children.map(this.adopt, this);

    this.props = {parent: null, children}

    this._reactFragment = {[this.key]: this.children}
  }
  // Fragments can be cloned as other entities
  clone() {
    console.warn("clone fragment", this)
    return new this.constructor(this.properties, this.children)
  }
}

// Function for constructing fragments of virtual dom tree.
// Takes `properties.key` for identifying fragment, optional
// `properties.type` which is used as wrapper node for given
// `children` if fragment is returned from thunk or is rendered
// directly.
export let fragment = (properties, children) =>
  new Fragment(properties, children)

// Reframe class instances represent entities in the virtaul dom
// tree similar to fragments and their are intentded to reframe
// action disptched by it's children into a differet form.
class Reframe extends Fragment {
  constructor(translate, children) {
    super({key: '', type: 'x:reframe'}, children)
    this.translate = translate
  }
  clone() {
    console.warn("clone Reframe", this)
    return new this.constructor(this.translate, this.children)
  }
  receive(action) {
    dispatch(this.props.parent, this.translate(action));
  }
}

// Function for reframing entities, takes `translate` function for
// translating actions from framed entity to an action from outerframe.
export let reframe = (translate, entity) =>
  new Reframe(translate, [entity])

// View is a react component used by `Thunk` entities for a lazy
// sub tree generation and caching that can short cirquit when
// equivalent data is being rendered.
class View extends React.Component {
  constructor() {
    super(...arguments)
  }
  shouldComponentUpdate({view, model}) {
    return view !== this.props.view ||
           !model.equals(this.props.model);
  }
  render() {
    const {view, model, parent} = this.props
    const entity = view(model)
    const node = !(entity instanceof Fragment) ? entity :
                 new Node(entity.type, entity.properties, [entity])
    return parent.adopt(node)
  }
}

// Thunk instances are entities in a virtual dom tree that represent
// lazily computed sub-trees with built-in caching that avoid re-computing
// sub-tree when same data is being rendered. Thunk implements same interface
// as `React.createElement(View, data)` to be compatible with reacts virtual
// dom but it also extends `Node` class so it could be `cloned` and `adopt`-ed
// as entities defined earlier.
class Thunk extends Entity {
  constructor(key, model, view) {
    super()
    this.type = View
    this.view = view
    this.model = model
    this.key = key

    var props = this
    this.props = props
    this._store = {props, originalProps:props}
    this._isReactElement = true
  }
  clone() {
    const {model, view, key} = this
    return new this.constructor(key, view, model)
  }
}

// render function provides shortcut for rendering a model with
// default view function (although custom view function can be
// passed as second optional argument), but unlike calling view
// directly result is a thunk, there for it's defers actual computation
// and makes use of caching to avoid computation when possible.
export const render = (key, model, view=model.constructor.view) =>
  new Thunk(key, model, view);

// Program is a root entity of the virtual dom tree that is responsible
// for computing a virtual dom tree for the `state` via given `view` function
// and reacting to dispatched actions via given `update` by updating a state
// and restarting a the same cycle again.
class Program extends Entity {
  constructor({target, state, update, view}) {
    super()
    this.target = target
    this.view = view
    this.update = update
    this.state = state
  }
  receive(action) {
    this.state = this.update(this.state, action)
    this.schedule()
  }
  schedule() {
    this.render()
    return this
  }
  render() {
    const node = this.adopt(render('program', this.state, this.view))
    React.render(node, this.target)
    return this
  }
}

// Function that takes `target` element to continiusly render given `model`
// into. model's default `update` function is used to update module in response
// to dispatched actions and model's default `view` function is used to compute
// dom tree represantation of the model. Optionally custom `update` and `view`
// functions could be passed to customize render loop.
export let main = (target, model, update=model.constructor.update, view=model.constructor.view) => {
  const program = new Program({
    state: model,
    target, update, view
  })
  program.schedule()
  return program
}
<|endoftext|>


<commit_before>'use strict';

const TelegramBot = require('node-telegram-bot-api');
const config = require('../config/config');
const messages = require('../config/messages');
const morningEvent = require('./morning-event');
const blogEvent = require('./blog-event');
const generateRandom = require('./time-utility').generateRandom;
const fetch = require('node-fetch');

const token = config.telegramToken;
const groupId = config.groupId;
const goodMorningRegExp = config.goodMorningRegExp;

let bot = new TelegramBot(token, {polling: true});
let goodMorningGivenToday = false;
let minuteToCheck = generateRandom(0, 59);

bot
  .on('new_chat_participant', newChatParticipant)
  .on('text', newText);

morningEvent
  .on('minuteMark', (vzlanHour, vzlanMinute, weekday) => {
    if (morningConditions(vzlanHour, vzlanMinute)) {
      goodMorningGivenToday = true;
      minuteToCheck = generateRandom(0, 59);
      bot.sendMessage(
        groupId,
        getMorningMsg(weekday)
      );
    }

    function morningConditions(vzlanHour, vzlanMinute) {
      return !goodMorningGivenToday && vzlanHour === config.morningHour
        && vzlanMinute === minuteToCheck;
    }

    function getMorningMsg(weekday) {
      let weekDays = {
        0: 'generic',
        1: 'mondays',
        2: 'generic',
        3: 'generic',
        4: 'generic',
        5: 'fridays',
        6: 'generic',
      };

      let randomIndex = generateRandom(0, messages.goodMornings[weekDays[weekday]].length - 1);
      return messages.goodMornings[weekDays[weekday]][randomIndex];
    }
  })
  .on('newDay', () => {
    goodMorningGivenToday = false;
  });

blogEvent
  .on('newArticles', (articles) => {
    articles.forEach((article) => {
      bot.sendMessage(
        groupId,
        messages.newBlogPost
          .replace('#{author}', article.author)
          .replace('#{link}', article.link)
          .replace('#{title}', article.title),
        {parse_mode: 'Markdown'}
      );
    });
  });

function newText(msg) {
  if (!goodMorningGivenToday && isGoodMorningGiven(msg.text)) {
    goodMorningGivenToday = true;
  }

  function isGoodMorningGiven(text) {
    return goodMorningRegExp.test(text);
  }
}

function newChatParticipant(msg) {
  bot.sendMessage(
    msg.chat.id,
    getFullWelcomeMsg(msg),
    {reply_to_message_id: msg.message_id, parse_mode: 'Markdown'}
  );

  function getFullWelcomeMsg(msg) {
    let nameToBeShown = msg.new_chat_member.first_name;

    if (msg.new_chat_member.username) {
      nameToBeShown = '@' + msg.new_chat_member.username;
    } else if (msg.new_chat_member.hasOwnProperty('last_name')) {
      nameToBeShown = nameToBeShown + ' ' + msg.new_chat_member.last_name;
    }

    return messages.welcomeMsg.replace('#{name}', nameToBeShown);
  }
}

bot.on('text', (msg) => {
  const chatId = msg.chat.id;
  console.log(msg);

  if ( msg.entities[0].type !== 'pre' ) {
    return;
  }

  if ( msg.text.length <= 200 ) {
    return;
  }

  const filename = `${new Date().toISOString()}.js`;
  const gist = msg.text;

  console.log(gist);

  const body = {
    'description': 'gist anonimo',
    'public': true,
    'files': {
      [filename]: {
        'content': gist
      }
    }
  };

  fetch('https://api.github.com/gists', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify( body )
  })
  .then(response => response.json())
  .then(({html_url}) => {
    console.log(html_url);

    bot.sendMessage( chatId, html_url );

  }).catch(error => {
    console.warn(error);
  });
});
<commit_msg>(Actualiza): Datos del usuario que creó el gist en la descripción del mismo<commit_after>'use strict';

const TelegramBot = require('node-telegram-bot-api');
const config = require('../config/config');
const messages = require('../config/messages');
const morningEvent = require('./morning-event');
const blogEvent = require('./blog-event');
const generateRandom = require('./time-utility').generateRandom;
const fetch = require('node-fetch');

const token = config.telegramToken;
const groupId = config.groupId;
const goodMorningRegExp = config.goodMorningRegExp;

let bot = new TelegramBot(token, {polling: true});
let goodMorningGivenToday = false;
let minuteToCheck = generateRandom(0, 59);

bot
  .on('new_chat_participant', newChatParticipant)
  .on('text', newText);

morningEvent
  .on('minuteMark', (vzlanHour, vzlanMinute, weekday) => {
    if (morningConditions(vzlanHour, vzlanMinute)) {
      goodMorningGivenToday = true;
      minuteToCheck = generateRandom(0, 59);
      bot.sendMessage(
        groupId,
        getMorningMsg(weekday)
      );
    }

    function morningConditions(vzlanHour, vzlanMinute) {
      return !goodMorningGivenToday && vzlanHour === config.morningHour
        && vzlanMinute === minuteToCheck;
    }

    function getMorningMsg(weekday) {
      let weekDays = {
        0: 'generic',
        1: 'mondays',
        2: 'generic',
        3: 'generic',
        4: 'generic',
        5: 'fridays',
        6: 'generic',
      };

      let randomIndex = generateRandom(0, messages.goodMornings[weekDays[weekday]].length - 1);
      return messages.goodMornings[weekDays[weekday]][randomIndex];
    }
  })
  .on('newDay', () => {
    goodMorningGivenToday = false;
  });

blogEvent
  .on('newArticles', (articles) => {
    articles.forEach((article) => {
      bot.sendMessage(
        groupId,
        messages.newBlogPost
          .replace('#{author}', article.author)
          .replace('#{link}', article.link)
          .replace('#{title}', article.title),
        {parse_mode: 'Markdown'}
      );
    });
  });

function newText(msg) {
  if (!goodMorningGivenToday && isGoodMorningGiven(msg.text)) {
    goodMorningGivenToday = true;
  }

  function isGoodMorningGiven(text) {
    return goodMorningRegExp.test(text);
  }
}

function newChatParticipant(msg) {
  bot.sendMessage(
    msg.chat.id,
    getFullWelcomeMsg(msg),
    {reply_to_message_id: msg.message_id, parse_mode: 'Markdown'}
  );

  function getFullWelcomeMsg(msg) {
    let nameToBeShown = msg.new_chat_member.first_name;

    if (msg.new_chat_member.username) {
      nameToBeShown = '@' + msg.new_chat_member.username;
    } else if (msg.new_chat_member.hasOwnProperty('last_name')) {
      nameToBeShown = nameToBeShown + ' ' + msg.new_chat_member.last_name;
    }

    return messages.welcomeMsg.replace('#{name}', nameToBeShown);
  }
}

bot.on('text', (msg) => {
  console.log(msg);

  if ( msg.hasOwnProperty('entities') && msg.entities[0].type !== 'pre' ) {
    console.log('It is not a <pre> tag');
    return;
  }

  if ( msg.text.length >= 200 ) {
    console.log('Gist characters limit reached');
    return;
  }

  const chatId = msg.chat.id;
  const { first_name = '', last_name = '', username = '' } = msg.chat;
  const filename = `${new Date().toISOString()}.js`;
  const gist = msg.text;

  console.log(gist);

  const body = {
    'description': `gist creador por ${first_name} ${last_name} (@${username}) para https://t.me/ngvenezuela con https://github.com/ngVenezuela/wengy-ven`,
    'public': true,
    'files': {
      [filename]: {
        'content': gist
      }
    }
  };

  fetch('https://api.github.com/gists', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify( body )
  })
  .then(response => response.json())
  .then(({html_url}) => {
    console.log(html_url);

    bot.sendMessage( chatId, html_url );

  }).catch(error => {
    console.warn(error);
  });
});
<|endoftext|>


<commit_before>const React = require('react');

class SearchError extends React.Component {
    render() {
        const { group, type, message } = this.props;
        let error = format(message, type);

        return (

{error[1]}

                        {error[0]}

        )
    }
}

SearchError.propTypes = {
    message: React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.object
    ]).isRequired,
    type: React.PropTypes.oneOf([
        'trending', 'trendingUsers', 'repos', 'users', 'readme'
    ]).isRequired
};

function format(group, type, message) {
    let errorMessage = message.toString();
    let errorType;

    if (group === 'users' && type === 'trending') {
        errorType = 'Trending Developer Error';
    } else if (group === 'repos' && type === 'trending') {
        errorType = 'Trending Repository Error';
    } else if (group === 'users' && type === 'users') {
        errorType = 'User Search Error';
    } else if (group === 'repos' ) {
        errorType = 'Repository Search Error';
    } else {
        errorType = 'Unknown Error';
    }

    return [errorMessage, errorType];
}

module.exports = SearchError;
<commit_msg>Updated error componenet formatter method<commit_after>const React = require('react');

class SearchError extends React.Component {
    render() {
        const { group, type, message } = this.props;
        let error = format(group, type, message);

        return (

{error[1]}

                        {error[0]}

        )
    }
}

SearchError.propTypes = {
    message: React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.object
    ]).isRequired,
    type: React.PropTypes.oneOf([
        'trending', 'trendingUsers', 'repos', 'users', 'readme'
    ]).isRequired
};

function format(group, type, message) {
    let errorMessage = message.toString();
    let errorType;

    if (group === 'users' && type === 'trending') {
        errorType = 'Trending Developer Error';
    } else if (group === 'repos' && type === 'trending') {
        errorType = 'Trending Repository Error';
    } else if (group === 'users' && type === 'users') {
        errorType = 'User Search Error';
    } else if (group === 'repos' ) {
        errorType = 'Repository Search Error';
    } else {
        errorType = 'Unknown Error';
    }

    return [errorMessage, errorType];
}

module.exports = SearchError;
<|endoftext|>


<commit_before>define([
	"dojo/_base/declare", "dojo/_base/lang",
	"dojo/request",
	"./TabViewerBase",
	"../FeatureOverview", "../GenomeBrowser", "../CompareRegionContainer",
	"../GeneExpressionContainer", "../CorrelatedGenesContainer", "../InteractionContainer",
	"../../util/PathJoin"

], function(declare, lang,
			xhr,
			TabViewerBase,
			FeatureOverview, GenomeBrowser, CompareRegionContainer,
			GeneExpressionContainer, CorrelatedGenesContainer, InteractionContainer,
			PathJoin){

	return declare([TabViewerBase], {
		"baseClass": "FeatureGroup",
		"disabled": false,
		containerType: "feature_group",
		feature_id: "",
		perspectiveLabel: "Feature View",
		perspectiveIconClass: "icon-selection-Feature",

		_setFeature_idAttr: function(id){

			if(!id){
				return;
			}

			if(this.feature_id == id){
				return;
			}

			this.state = this.state || {};
			this.feature_id = id;
			this.state.feature_id = id;

			if(id.match(/^fig/)){
				id = id.replace(/\|/g, '%7C');
				//console.log("fig id = ", id);
				id = "?eq(patric_id," + id + ")&limit(1)";
			}

			// console.log("Get Feature: ", id);
			xhr.get(PathJoin(this.apiServiceUrl, "genome_feature", id), {
				headers: {
					accept: "application/json",
					'X-Requested-With': null,
					'Authorization': (window.App.authorizationToken || "")
				},
				handleAs: "json"
			}).then(lang.hitch(this, function(feature){
				if(feature instanceof Array){
					// this.set("feature", feature[0])
					this.redirectToPATRICFeature(feature[0]);
				}else{
					// this.set("feature", feature)
					this.redirectToPATRICFeature(feature);
				}
			}));
		},

		setActivePanelState: function(){
			var activeQueryState;
			if(!this._started){
				console.log("Feature Viewer not started");
				return;
			}

			if(this.state.feature_id){
				activeQueryState = lang.mixin({}, this.state, {search: "eq(feature_id," + this.state.feature_id + ")"});
			}
			var active = (this.state && this.state.hashParams && this.state.hashParams.view_tab) ? this.state.hashParams.view_tab : "overview";
			var activeTab = this[active];

			switch(active){
				case "overview":
				case "correlatedGenes":
					if(this.state && this.state.feature){
						activeTab.set("state", lang.mixin({}, this.state));
					}
					break;
				case "interactions":
					if(this.state && this.state.feature){
						activeTab.set("state", lang.mixin({}, this.state, {
							search: "secondDegreeInteraction(" + this.state.feature.feature_id + ")"
						}));
					}
					break;
				default:
					if(activeQueryState){
						activeTab.set("state", activeQueryState);
					}
					break;
			}

			if(this.feature){
				var pageTitle = this.feature.patric_id + "::Feature " + activeTab.title;
				// console.log("Feature setActivePanelState: ", pageTitle);
				if(window.document.title !== pageTitle){
					window.document.title = pageTitle;
				}
			}
		},

		onSetState: function(attr, oldState, state){
			var parts = this.state.pathname.split("/");
			this.set("feature_id", parts[parts.length - 1]);
			state.feature_id = parts[parts.length - 1];

			if(state && state.feature_id && !state.feature){
				if(oldState && oldState.feature_id){
					if((state.feature_id == oldState.feature_id)){
						if(oldState.feature || this.feature){
							this.state.feature = state.feature = oldState.feature || this.feature;
						}else{
							console.log("oldState missing Featture");
						}
					}
				}
			}

			this.setActivePanelState();
			if(state.hashParams && state.hashParams.view_tab){

				if(this[state.hashParams.view_tab]){
					var vt = this[state.hashParams.view_tab];
					vt.set("visible", true);
					this.viewer.selectChild(vt);
				}else{
					console.log("No view-tab supplied in State Object");
				}
			}

			this.setActivePanelState();
		},

		buildHeaderContent: function(feature){

			xhr.get(PathJoin(this.apiServiceUrl, "taxonomy", feature.taxon_id), {
				headers: {
					accept: "application/json"
				},
				handleAs: "json"
			}).then(lang.hitch(this, function(taxon){
				var taxon_lineage_names = taxon.lineage_names;
				var taxon_lineage_ids = taxon.lineage_ids;
				var taxon_lineage_ranks = taxon.lineage_ranks;

				var visibleRanks = ["superkingdom", "phylum", "class", "order", "family", "genus", "species"];
				var visibleIndexes = taxon_lineage_ranks.filter(function(rank){
					return visibleRanks.indexOf(rank) > -1;
				}).map(function(rank){
					return taxon_lineage_ranks.indexOf(rank);
				});

				var out = visibleIndexes.map(function(idx){
					return '' + taxon_lineage_names[idx] + '';
				});
				this.queryNode.innerHTML = out.join(" » ") + " » " + lang.replace('{feature.genome_name}', {feature: feature});
			}));

			var content = [];
			if(feature.hasOwnProperty('patric_id')){
				content.push(feature.patric_id);
			}
			if(feature.hasOwnProperty('refseq_locus_tag')){
				content.push(feature.refseq_locus_tag);
			}
			if(feature.hasOwnProperty('gene')){
				content.push(feature.gene);
			}
			if(feature.hasOwnProperty('product')){
				content.push(feature.product);
			}

			this.totalCountNode.innerHTML = "
" + content.map(function(d){
					return '' + d + '';
				}).join(' | ');
		},

		redirectToPATRICFeature: function(feature){

			if(feature.annotation === 'PATRIC'){
				this.set("feature", feature);
			}else{
				if(feature.hasOwnProperty('pos_group')){
					xhr.get(PathJoin(this.apiServiceUrl, "/genome_feature/?and(eq(annotation,PATRIC),eq(pos_group," + encodeURIComponent('"' + feature.pos_group + '"') + "))"), {
						headers: {
							accept: "application/json",
							'X-Requested-With': null,
							'Authorization': (window.App.authorizationToken || "")
						},
						handleAs: "json"
					}).then(lang.hitch(this, function(features){
						if(features.length === 0){
							// no PATRIC feature found
							this.set("feature", feature);
						}else{
							this.set("feature", features[0]);
						}
					}));
				}else{
					this.set("feature", feature);
				}
			}
		},

		_setFeatureAttr: function(feature){

			this.feature = this.state.feature = feature;

			this.buildHeaderContent(feature);

			this.setActivePanelState();
			this.resize();
		},

		postCreate: function(){
			if(!this.state){
				this.state = {};
			}

			this.inherited(arguments);

			this.overview = new FeatureOverview({
				content: "Overview",
				title: "Overview",
				id: this.viewer.id + "_" + "overview"
			});

			this.genomeBrowser = new GenomeBrowser({
				title: "Genome Browser",
				id: this.viewer.id + "_genomeBrowser",
				content: "Genome Browser",
				tooltip: 'The "Browser" tab shows genome sequence and genomic features using linear genome browser',
				state: lang.mixin({}, this.state)
			});
			if(window.App.appLabel !== ""){
				this.compareRegionViewer = new CompareRegionContainer({
					title: "Compare Region Viewer",
					id: this.viewer.id + "_compareRegionViewer"
				});
			}
			// TODO: implement pathways tab

			this.transcriptomics = new GeneExpressionContainer({
				title: "Transcriptomics",
				id: this.viewer.id + "_transcriptomics"
			});

			this.correlatedGenes = new CorrelatedGenesContainer({
				title: "Correlated Genes",
				id: this.viewer.id + "_correlatedGenes"
			});

			if(window.App.appLabel !== ""){
				this.interactions = new InteractionContainer({
					title: "Interactions",
					id: this.viewer.id + "_interactions",
					state: this.state
				});
			}

			this.viewer.addChild(this.overview);
			this.viewer.addChild(this.genomeBrowser);
			if(window.App.appLabel !== ""){
				this.viewer.addChild(this.compareRegionViewer);
			}
			this.viewer.addChild(this.transcriptomics);
			this.viewer.addChild(this.correlatedGenes);
			if(window.App.appLabel !== ""){
				this.viewer.addChild(this.interactions);
			}
		}
	});
});
<commit_msg>add proper label for tab title<commit_after>define([
	"dojo/_base/declare", "dojo/_base/lang",
	"dojo/request",
	"./TabViewerBase",
	"../FeatureOverview", "../GenomeBrowser", "../CompareRegionContainer",
	"../GeneExpressionContainer", "../CorrelatedGenesContainer", "../InteractionContainer",
	"../../util/PathJoin"

], function(declare, lang,
			xhr,
			TabViewerBase,
			FeatureOverview, GenomeBrowser, CompareRegionContainer,
			GeneExpressionContainer, CorrelatedGenesContainer, InteractionContainer,
			PathJoin){

	return declare([TabViewerBase], {
		"baseClass": "FeatureGroup",
		"disabled": false,
		containerType: "feature_group",
		feature_id: "",
		perspectiveLabel: "Feature View",
		perspectiveIconClass: "icon-selection-Feature",

		_setFeature_idAttr: function(id){

			if(!id){
				return;
			}

			if(this.feature_id == id){
				return;
			}

			this.state = this.state || {};
			this.feature_id = id;
			this.state.feature_id = id;

			if(id.match(/^fig/)){
				id = id.replace(/\|/g, '%7C');
				//console.log("fig id = ", id);
				id = "?eq(patric_id," + id + ")&limit(1)";
			}

			// console.log("Get Feature: ", id);
			xhr.get(PathJoin(this.apiServiceUrl, "genome_feature", id), {
				headers: {
					accept: "application/json",
					'X-Requested-With': null,
					'Authorization': (window.App.authorizationToken || "")
				},
				handleAs: "json"
			}).then(lang.hitch(this, function(feature){
				if(feature instanceof Array){
					// this.set("feature", feature[0])
					this.redirectToPATRICFeature(feature[0]);
				}else{
					// this.set("feature", feature)
					this.redirectToPATRICFeature(feature);
				}
			}));
		},

		setActivePanelState: function(){
			var activeQueryState;
			if(!this._started){
				console.log("Feature Viewer not started");
				return;
			}

			if(this.state.feature_id){
				activeQueryState = lang.mixin({}, this.state, {search: "eq(feature_id," + this.state.feature_id + ")"});
			}
			var active = (this.state && this.state.hashParams && this.state.hashParams.view_tab) ? this.state.hashParams.view_tab : "overview";
			var activeTab = this[active];

			switch(active){
				case "overview":
				case "correlatedGenes":
					if(this.state && this.state.feature){
						activeTab.set("state", lang.mixin({}, this.state));
					}
					break;
				case "interactions":
					if(this.state && this.state.feature){
						activeTab.set("state", lang.mixin({}, this.state, {
							search: "secondDegreeInteraction(" + this.state.feature.feature_id + ")"
						}));
					}
					break;
				default:
					if(activeQueryState){
						activeTab.set("state", activeQueryState);
					}
					break;
			}

			if(this.feature){
				var label = (this.feature.patric_id) ? this.feature.patric_id : (this.feature.refseq_locus_tag) ? this.feature.refseq_locus_tag : (this.feature.protein_id) ? this.feature.protein_id : this.feature.feature_id;
				var pageTitle = label + "::Feature " + activeTab.title;
				// console.log("Feature setActivePanelState: ", pageTitle);
				if(window.document.title !== pageTitle){
					window.document.title = pageTitle;
				}
			}
		},

		onSetState: function(attr, oldState, state){
			var parts = this.state.pathname.split("/");
			this.set("feature_id", parts[parts.length - 1]);
			state.feature_id = parts[parts.length - 1];

			if(state && state.feature_id && !state.feature){
				if(oldState && oldState.feature_id){
					if((state.feature_id == oldState.feature_id)){
						if(oldState.feature || this.feature){
							this.state.feature = state.feature = oldState.feature || this.feature;
						}else{
							console.log("oldState missing Featture");
						}
					}
				}
			}

			this.setActivePanelState();
			if(state.hashParams && state.hashParams.view_tab){

				if(this[state.hashParams.view_tab]){
					var vt = this[state.hashParams.view_tab];
					vt.set("visible", true);
					this.viewer.selectChild(vt);
				}else{
					console.log("No view-tab supplied in State Object");
				}
			}

			this.setActivePanelState();
		},

		buildHeaderContent: function(feature){

			xhr.get(PathJoin(this.apiServiceUrl, "taxonomy", feature.taxon_id), {
				headers: {
					accept: "application/json"
				},
				handleAs: "json"
			}).then(lang.hitch(this, function(taxon){
				var taxon_lineage_names = taxon.lineage_names;
				var taxon_lineage_ids = taxon.lineage_ids;
				var taxon_lineage_ranks = taxon.lineage_ranks;

				var visibleRanks = ["superkingdom", "phylum", "class", "order", "family", "genus", "species"];
				var visibleIndexes = taxon_lineage_ranks.filter(function(rank){
					return visibleRanks.indexOf(rank) > -1;
				}).map(function(rank){
					return taxon_lineage_ranks.indexOf(rank);
				});

				var out = visibleIndexes.map(function(idx){
					return '' + taxon_lineage_names[idx] + '';
				});
				this.queryNode.innerHTML = out.join(" » ") + " » " + lang.replace('{feature.genome_name}', {feature: feature});
			}));

			var content = [];
			if(feature.hasOwnProperty('patric_id')){
				content.push(feature.patric_id);
			}
			if(feature.hasOwnProperty('refseq_locus_tag')){
				content.push(feature.refseq_locus_tag);
			}
			if(feature.hasOwnProperty('gene')){
				content.push(feature.gene);
			}
			if(feature.hasOwnProperty('product')){
				content.push(feature.product);
			}

			this.totalCountNode.innerHTML = "
" + content.map(function(d){
					return '' + d + '';
				}).join(' | ');
		},

		redirectToPATRICFeature: function(feature){

			if(feature.annotation === 'PATRIC'){
				this.set("feature", feature);
			}else{
				if(feature.hasOwnProperty('pos_group')){
					xhr.get(PathJoin(this.apiServiceUrl, "/genome_feature/?and(eq(annotation,PATRIC),eq(pos_group," + encodeURIComponent('"' + feature.pos_group + '"') + "))"), {
						headers: {
							accept: "application/json",
							'X-Requested-With': null,
							'Authorization': (window.App.authorizationToken || "")
						},
						handleAs: "json"
					}).then(lang.hitch(this, function(features){
						if(features.length === 0){
							// no PATRIC feature found
							this.set("feature", feature);
						}else{
							this.set("feature", features[0]);
						}
					}));
				}else{
					this.set("feature", feature);
				}
			}
		},

		_setFeatureAttr: function(feature){

			this.feature = this.state.feature = feature;

			this.buildHeaderContent(feature);

			this.setActivePanelState();
			this.resize();
		},

		postCreate: function(){
			if(!this.state){
				this.state = {};
			}

			this.inherited(arguments);

			this.overview = new FeatureOverview({
				content: "Overview",
				title: "Overview",
				id: this.viewer.id + "_" + "overview"
			});

			this.genomeBrowser = new GenomeBrowser({
				title: "Genome Browser",
				id: this.viewer.id + "_genomeBrowser",
				content: "Genome Browser",
				tooltip: 'The "Browser" tab shows genome sequence and genomic features using linear genome browser',
				state: lang.mixin({}, this.state)
			});
			if(window.App.appLabel !== ""){
				this.compareRegionViewer = new CompareRegionContainer({
					title: "Compare Region Viewer",
					id: this.viewer.id + "_compareRegionViewer"
				});
			}
			// TODO: implement pathways tab

			this.transcriptomics = new GeneExpressionContainer({
				title: "Transcriptomics",
				id: this.viewer.id + "_transcriptomics"
			});

			this.correlatedGenes = new CorrelatedGenesContainer({
				title: "Correlated Genes",
				id: this.viewer.id + "_correlatedGenes"
			});

			if(window.App.appLabel !== ""){
				this.interactions = new InteractionContainer({
					title: "Interactions",
					id: this.viewer.id + "_interactions",
					state: this.state
				});
			}

			this.viewer.addChild(this.overview);
			this.viewer.addChild(this.genomeBrowser);
			if(window.App.appLabel !== ""){
				this.viewer.addChild(this.compareRegionViewer);
			}
			this.viewer.addChild(this.transcriptomics);
			this.viewer.addChild(this.correlatedGenes);
			if(window.App.appLabel !== ""){
				this.viewer.addChild(this.interactions);
			}
		}
	});
});
<|endoftext|>


<commit_before>const HTTPError = require('./HTTPError');
const server = require('./server');
const model = require('./model');
const db = require('./db');
const migrator = require('./migrator');
const configBuilder = require('./configBuilder');

module.exports = {
	HTTPError,
	server,
	model,
	db,
	migrator,
	configBuilder
};
<commit_msg>Expose bootstrap function<commit_after>const HTTPError = require('./HTTPError');
const server = require('./server');
const model = require('./model');
const db = require('./db');
const migrator = require('./migrator');
const configBuilder = require('./configBuilder');
const bootstrap = require('./bootstrap');

module.exports = {
	HTTPError,
	server,
	model,
	db,
	migrator,
	configBuilder,
	bootstrap
};
<|endoftext|>


<commit_before>var util = require('util');
var through = require('through2');
var request = require('request');

function createSearchStream(queryParams) {

  if (!queryParams.hasOwnProperty('api_key')) {
    throw new Error('Query parameters must at least contain api_key');
  }

  var inFlightCount = 0;

  return through.obj(function (data, enc, next) {
    if (!data.hasOwnProperty('address')) {
      return next(new Error('no address column'));
    }

    var self = this;

    inFlightCount++;

    queryParams.text = data.address;

    var reqOptions = {
      url: 'https://search.mapzen.com/v1/search',
      method: 'GET',
      qs: queryParams
    };

    request(reqOptions, function (err, res, body) {

      if (err || res.statusCode !== 200) {
        self.push(addErrorData(data, (err ? err.message : res.statusMessage)));
        inFlightCount--;
        return;
      }

      var resData = JSON.parse(body).features;

      if (resData.length === 0) {
        self.push(addErrorData(data, '0 results'));
        inFlightCount--;
        return;
      }

      self.push(addResData(data, resData));
      inFlightCount--;
    });

    // respect the rate limit and don't push another request sooner than 6 seconds
    setTimeout(function () {
      next(null);
    }, 1000 / 5);

  },
  // don't flush the stream until the last in flight request has been handled
  function (done) {
    var interval = setInterval(function () {
      if (inFlightCount === 0) {
        clearInterval(interval);
        done();
      }
    }, 100);
  });
}

function addErrorData(data, message) {
  data.res_longitude = '';
  data.res_latitude = '';
  data.res_confidence = '';
  data.res_label = 'ERROR: ' + message;
  return data;
}

function addResData(data, resData) {
  data.res_longitude = resData[0].geometry.coordinates[0];
  data.res_latitude = resData[0].geometry.coordinates[1];
  data.res_confidence = resData[0].properties.confidence;
  data.res_label = resData[0].properties.label;
  return data;
}

module.exports = createSearchStream;<commit_msg>Add stats, socket limit, more<commit_after>var util = require('util');
var through = require('through2');
var request = require('request');
const https = require('http');

const agent = new https.Agent({ keepAlive: true, maxSockets: 80});

const start = new Date();
const stats = {
  processed: 0,
  error: 0,
  zero_results: 0,
  address: 0,
  venue: 0,
  admin: 0,
  inFlightCount: 0
};

function createSearchStream(queryParams) {

  if (!queryParams.hasOwnProperty('api_key')) {
    throw new Error('Query parameters must at least contain api_key');
  }

  const statInterval = setInterval(function() {
    stats.RPS = stats.processed / ( new Date() - start) * 1000;
    console.log(JSON.stringify(stats));
  }, 1 * 1000);

  return through.obj(function (data, enc, next) {
    if (!data.hasOwnProperty('address')) {
      return next(new Error('no address column'));
    }

    var self = this;

    stats.inFlightCount++;

    const this_query_params = {
    };
    this_query_params.text = data.name + ' ' + data.address;

    var reqOptions = {
      url: 'http://internal-a56c85a765acc11e8bebb0e73ead8d1c-196936346.us-east-1.elb.amazonaws.com:3100/v1/search',
      method: 'GET',
      qs: this_query_params,
      agent: agent
    };

    request(reqOptions, function (err, res, body) {
      stats.processed++;

      if (err || res.statusCode !== 200) {
        console.log(`${res.statusCode}: ${err ? err.message : res.statusMessage}`);

        if (res.statusCode === 400) {
          console.log(JSON.stringify(queryParams));
          var resData = JSON.parse(body);
          console.log(JSON.stringify(resData.geocoding.errors));
        }
        self.push(addErrorData(data, (err ? err.message : res.statusMessage)));
        stats.error++;
        stats.inFlightCount--;
        return;
      }

      var resData = JSON.parse(body).features;

      if (resData.length === 0) {
        self.push(addErrorData(data, '0 results'));
        stats.zero_results++;
        stats.inFlightCount--;
        return;
      }

      self.push(addResData(data, resData));
      stats.inFlightCount--;
    });

    // adaptively adjust how quickly we progress through the stream
    const nextInterval = setInterval(function () {
      if (stats.inFlightCount > 200) {
        return;
      } else {
        clearInterval(nextInterval)
        next(null);
      }
    }, 10);

  },
  // don't flush the stream until the last in flight request has been handled
  function (done) {
    var interval = setInterval(function () {
      if (stats.inFlightCount === 0) {
        clearInterval(interval);
        clearInterval(statInterval);
        done();
      }
    }, 100);
  });
}

function addErrorData(data, message) {
  data.res_longitude = '';
  data.res_latitude = '';
  data.res_confidence = '';
  data.res_label = 'ERROR: ' + message;
  return data;
}

function addResData(data, resData) {
  data.res_longitude = resData[0].geometry.coordinates[0];
  data.res_latitude = resData[0].geometry.coordinates[1];
  data.res_confidence = resData[0].properties.confidence;
  data.res_label = resData[0].properties.label;

  //stats
  if (resData[0].properties.layer == 'address') {
    stats.address++;
  } else if (resData[0].properties.layer == 'venue') {
    stats.venue++;
  } else {
    stats.admin++;
  }

  return data;
}

module.exports = createSearchStream;
<|endoftext|>


<commit_before>import { EventEmitter } from 'events';
import * as idu from './utils/id_utils';
import {
  closeLock,
  openLock,
  removeLock,
  setupLock,
  updateLock
} from './lock/actions';
import webAPI from './lock/web_api';
import { getEntity, read, subscribe } from './store/index';
import * as l from './lock/index';
import * as c from './field/index';
import { remove, render } from './ui/box';
import { registerDict } from './dict/index';

// telemetry
import Auth0 from 'auth0-js';

import css from '../css/index.css';

const head = document.getElementsByTagName('head')[0];
const style = document.createElement('style');
style.type = 'text/css';
head.appendChild(style);
if (style.styleSheet) {
  style.styleSheet.cssText = css;
} else {
  style.appendChild(document.createTextNode(css));
}

export default class Base extends EventEmitter {
  constructor(mode, dict, clientID, domain, options = {}, signInCallback = () => {}) {
    if (typeof clientID != "string") {
      throw new Error("A `clientID` string must be provided as first argument.");
    }
    if (typeof domain != "string") {
      throw new Error("A `domain` string must be provided as second argument.");
    }
    if (typeof options != "object") {
      throw new Error("When provided, the third argument must be an `options` object.");
    }
    if (typeof signInCallback != "function") {
      // TODO: should this argument be mandatory?
      throw new Error("When provided, the fourth argument must be a function.");
    }

    super();

    registerDict(mode, dict);
    this.id = idu.incremental();
    const { plugins } = Base;
    const hookRunner = ::this.runHook;
    const emitEventFn = this.emit.bind(this);
    options.mode = mode;
    setupLock(this.id, clientID, domain, options, signInCallback, hookRunner, emitEventFn);

    subscribe("widget-" + this.id, (key, oldState, newState) => {
      const m = getEntity(newState, "lock", this.id);
      const oldM = getEntity(oldState, "lock", this.id);

      if (m != oldM) {
        const partialApplyId = (screen, handlerName) => {
          const handler = screen[handlerName](m);
          return handler
            ? (...args) => handler(l.id(m), ...args)
            : handler;
        };

        const avatar = l.ui.avatar(m) && m.getIn(["avatar", "transient", "syncStatus"]) === "ok" || null;
        const title = avatar
          ? l.ui.t(m, ["welcome"], {name: m.getIn(["avatar", "transient", "displayName"]), __textOnly: true})
          : l.ui.t(m, ["title"], {__textOnly: true});

        if (l.rendering(m)) {
          const screen = this.render(m);
          const props = {
            avatar: avatar && m.getIn(["avatar", "transient", "url"]),
            auxiliaryPane: screen.renderAuxiliaryPane(m),
            backHandler: partialApplyId(screen, "backHandler"),
            closeHandler: l.ui.closable(m)
              ? partialApplyId(screen, "closeHandler")
              : undefined,
            contentRender: ::screen.render,
            error: l.globalError(m),
            footerText: screen.renderFooterText(m),
            headerText: screen.renderHeaderText(m),
            icon: l.ui.icon(m),
            isMobile: l.ui.mobile(m),
            isModal: l.ui.appendContainer(m),
            isSubmitting: l.submitting(m),
            model: m,
            primaryColor: l.ui.primaryColor(m),
            screenName: screen.name,
            success: l.globalSuccess(m),
            submitHandler: partialApplyId(screen, "submitHandler"),
            tabs: screen.renderTabs(m),
            title: title,
            transitionName: screen.transitionName(m)
          };
          render(l.ui.containerID(m), props);
        } else {
          remove(l.ui.containerID(m));
        }
      }
    });
  }

  show() {
    openLock(this.id);
  }

  close() {
    closeLock(this.id, true);
  }

  destroy() {
    removeLock(this.id);
  }

  getProfile(token, cb) {
    return webAPI.getProfile(this.id, token, cb);
  }

  parseHash(hash = undefined) {
    return webAPI.parseHash(this.id, hash);
  }

  logout(query = {}) {
    webAPI.signOut(this.id, query);
  }

  update(f) {
    return updateLock(this.id, f);
  }

  setModel(m) {
    return this.update(() => m);
  }

  runHook(str, ...args) {
    if (typeof this[str] != "function") return;
    const model = read(getEntity, "lock", this.id);
    return this[str](model, ...args);
  }
}

// telemetry
Base.version = __VERSION__;
Auth0.clientInfo.name +=  " (LockPasswordless)";
Auth0.clientInfo.version += ` (${__VERSION__})`;
<commit_msg>Update telemetry info<commit_after>import { EventEmitter } from 'events';
import * as idu from './utils/id_utils';
import {
  closeLock,
  openLock,
  removeLock,
  setupLock,
  updateLock
} from './lock/actions';
import webAPI from './lock/web_api';
import { getEntity, read, subscribe } from './store/index';
import * as l from './lock/index';
import * as c from './field/index';
import { remove, render } from './ui/box';
import { registerDict } from './dict/index';

// telemetry
import Auth0 from 'auth0-js';

import css from '../css/index.css';

const head = document.getElementsByTagName('head')[0];
const style = document.createElement('style');
style.type = 'text/css';
head.appendChild(style);
if (style.styleSheet) {
  style.styleSheet.cssText = css;
} else {
  style.appendChild(document.createTextNode(css));
}

export default class Base extends EventEmitter {
  constructor(mode, dict, clientID, domain, options = {}, signInCallback = () => {}) {
    if (typeof clientID != "string") {
      throw new Error("A `clientID` string must be provided as first argument.");
    }
    if (typeof domain != "string") {
      throw new Error("A `domain` string must be provided as second argument.");
    }
    if (typeof options != "object") {
      throw new Error("When provided, the third argument must be an `options` object.");
    }
    if (typeof signInCallback != "function") {
      // TODO: should this argument be mandatory?
      throw new Error("When provided, the fourth argument must be a function.");
    }

    super();

    registerDict(mode, dict);
    this.id = idu.incremental();
    const { plugins } = Base;
    const hookRunner = ::this.runHook;
    const emitEventFn = this.emit.bind(this);
    options.mode = mode;
    setupLock(this.id, clientID, domain, options, signInCallback, hookRunner, emitEventFn);

    subscribe("widget-" + this.id, (key, oldState, newState) => {
      const m = getEntity(newState, "lock", this.id);
      const oldM = getEntity(oldState, "lock", this.id);

      if (m != oldM) {
        const partialApplyId = (screen, handlerName) => {
          const handler = screen[handlerName](m);
          return handler
            ? (...args) => handler(l.id(m), ...args)
            : handler;
        };

        const avatar = l.ui.avatar(m) && m.getIn(["avatar", "transient", "syncStatus"]) === "ok" || null;
        const title = avatar
          ? l.ui.t(m, ["welcome"], {name: m.getIn(["avatar", "transient", "displayName"]), __textOnly: true})
          : l.ui.t(m, ["title"], {__textOnly: true});

        if (l.rendering(m)) {
          const screen = this.render(m);
          const props = {
            avatar: avatar && m.getIn(["avatar", "transient", "url"]),
            auxiliaryPane: screen.renderAuxiliaryPane(m),
            backHandler: partialApplyId(screen, "backHandler"),
            closeHandler: l.ui.closable(m)
              ? partialApplyId(screen, "closeHandler")
              : undefined,
            contentRender: ::screen.render,
            error: l.globalError(m),
            footerText: screen.renderFooterText(m),
            headerText: screen.renderHeaderText(m),
            icon: l.ui.icon(m),
            isMobile: l.ui.mobile(m),
            isModal: l.ui.appendContainer(m),
            isSubmitting: l.submitting(m),
            model: m,
            primaryColor: l.ui.primaryColor(m),
            screenName: screen.name,
            success: l.globalSuccess(m),
            submitHandler: partialApplyId(screen, "submitHandler"),
            tabs: screen.renderTabs(m),
            title: title,
            transitionName: screen.transitionName(m)
          };
          render(l.ui.containerID(m), props);
        } else {
          remove(l.ui.containerID(m));
        }
      }
    });
  }

  show() {
    openLock(this.id);
  }

  close() {
    closeLock(this.id, true);
  }

  destroy() {
    removeLock(this.id);
  }

  getProfile(token, cb) {
    return webAPI.getProfile(this.id, token, cb);
  }

  parseHash(hash = undefined) {
    return webAPI.parseHash(this.id, hash);
  }

  logout(query = {}) {
    webAPI.signOut(this.id, query);
  }

  update(f) {
    return updateLock(this.id, f);
  }

  setModel(m) {
    return this.update(() => m);
  }

  runHook(str, ...args) {
    if (typeof this[str] != "function") return;
    const model = read(getEntity, "lock", this.id);
    return this[str](model, ...args);
  }
}

// telemetry
//
// TODO: we should have different telemetry overrides for classic and
// passwordless.
Base.version = __VERSION__;
Auth0.clientInfo.lib_version = Auth0.clientInfo.version;
Auth0.clientInfo.name =  "lock-next.js";
Auth0.clientInfo.version = Base.version;
<|endoftext|>