<commit_before>function getParameterByName(name) {
    'use strict';
    var url = window.location.href;
    name = name.replace(/[\[\]]/g, '\\$&');
    var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
        results = regex.exec(url);
    if (!results) {
        return null;
    }
    if (!results[2]) {
        return '';
    }
    return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

function hash(name, value) {
    'use strict';
    var hash;
    try {
        hash = window.location.hash;
        if (hash.startsWith('#')) {
            hash = hash.substring(1);
        }
        hash = JSON.parse(hash);
    } catch(ex) {
        hash = {};
    }
    if (value === undefined) {
        return hash[name];
    }
    hash[name] = value;
    hash = '#' + JSON.stringify(hash);
    history.replaceState(undefined, undefined, hash);
}

var autoExpandToAndSelectPath = hash('selected');

function findNodesByUrl(searchUrl) {
    'use strict';
    var nodes = [];
    var jstree = $('#tree').jstree();
    function recurse(nodeId) {
        var node = jstree.get_node(nodeId)
        if (node.data) {
            if (node.data.url === searchUrl) {
                nodes.push(node);
                return;
            }
            if (searchUrl.indexOf(node.data.url) != 0) {
                return;
            }
        }
        node.children.forEach(recurse);
    }
    recurse('#');
    return nodes;
}

function createResource() {
    'use strict';
    var relPath = $('#nameOfResourceToCreate').val();
    if(!relPath) {
        $('#nameOfResourceToCreate').effect('highlight', {color: '#F88'}, 200);
        return;
    }
    var basePath = $('#nameOfResourceToCreateBaseUrl').text();
    var url = basePath + relPath;
    $.ajax({
        url: url,
        type: 'PUT',
        data: '{}'
    }).then(function () {
        var affectedParentNodes = findNodesByUrl(basePath);
        autoExpandToAndSelectPath = url;
        var jstree = $('#tree').jstree();
        jstree.deselect_all();
        affectedParentNodes.forEach(function(node) {
            jstree.refresh_node(node);
        });
        jstree.refresh_node(basePath);
        $('#dialogCreateResource').parent().effect('highlight', {color: '#8F8'}, 200);
    });
}

function deleteResource() {
    'use strict';
    var url = $('#nameOfResourceToDelete').text();
    $.ajax({
        url: url,
        type: 'DELETE'
    }).then(function () {
        var jstree = $('#tree').jstree();
        var affectedNodes = findNodesByUrl(url);
        affectedNodes.forEach(function(node) {
            node = jstree.get_parent(node);
            jstree.refresh_node(node);
            jstree.select_node(node);
        });
        $('#dialogDeleteResource').dialog('close');
    });
}

$(function ($) {
    'use strict';

    /**************************************************************************************************************
     * Make the tree horizontally resizable (width)
     *   - Note the hack to go around the problem with the iframe
     *   - store the width in localStorage and set it on page load from loacalStorage
     *************************************************************************************************************/
    $('#treeResizable').resizable({
        handles: {e: $('#resize-handle')},
        start: function () {
            // hack: we need an overlay above the iframe so that we continue to get mouse-move-events (while resizing is active)
            $('#editor-hide-iframe-overlay').show();
        },
        stop: function () {
            var width = $('#treeResizable').width();
            window.localStorage.setItem('vertx-rest-storage-editor.treeWidth', width);
            $('#editor-hide-iframe-overlay').hide();
        }
    });
    var width = window.localStorage.getItem('vertx-rest-storage-editor.treeWidth');
    if (width) {
        $('#treeResizable').width(width);
    }

    $('#dialogCreateResource').dialog({
        autoOpen: false,
        modal: true,
        width: '50vw'
    });
    $('#dialogDeleteResource').dialog({
        autoOpen: false,
        modal: true,
        width: '50vw'
    });

    /**************************************************************************************************************
     * Setup jstree (see http://www.jstree.com)
     *************************************************************************************************************/
    var treeBase = getParameterByName('treeBase');
    if (!treeBase.endsWith('/')) {
        treeBase += '/';
    }
    var rootNodes = [{
        text: treeBase,
        data: {url: treeBase},
        icon: 'fa fa-folder',
        children: true
    }];

    $('#tree').jstree({
        core: {
            /**************************************************************************************************************
             * basic settings for jstree
             *************************************************************************************************************/
            check_callback: true,
            animation: false,
            themes: {
                name: 'proton',
                responsive: true,
                dots : true,
                icons: true
            },
            /**************************************************************************************************************
             * the 'lazy' data loader - called automatically when opening an unloaded node
             * creates child nodes which are either nodes-with-children ('directory') or leafs ('resources')
             * We distinguish from vertx-rest-storage with a trailing slash (i.e. "img/" is a node-with-children while" "img" is a resource
             *************************************************************************************************************/
            data: function (node, callback) {
                if (node.id === '#') {
                    // initialize the one-and-only rood node
                    callback.call(this, rootNodes);
                    return;
                }

                var nodeUrl = node.data.url;
                var childrenNodes = [];
                function addEntriesToParentNode(entries) {
                    entries.forEach(function (c) {
                        var isLeaf = !c.endsWith('/');
                        var childNode = {
                            text: c,
                            data: {
                                url: nodeUrl + c
                            },
                            icon: isLeaf ? 'fa fa-file-text-o' : 'fa fa-folder',
                            children: !isLeaf   // to force jstree to show a '+' icon and to be able to open a not-yet loaded tree
                        };
                        childrenNodes.push(childNode);
                    });
                }

                $.get(nodeUrl, function success(data) {
                    for (var property in data) {
                        if (data.hasOwnProperty(property)) {
                            addEntriesToParentNode(data[property]);
                        }
                    }
                }).fail(function (err) {
                    // show a single red error children on AJAX error
                    childrenNodes.push({
                        text: err.responseText || err.statusText,
                        data: {url: nodeUrl + '[errorIndicator]'},
                        li_attr: {style: 'color: red;'},
                        icon: null
                    });
                }).always(function() {
                    callback.call(this, childrenNodes);
                });
            }
        },
        /**************************************************************************************************************
         * Context menu on every tree node
         *************************************************************************************************************/
        plugins: [ 'contextmenu'],
        contextmenu: {
            show_at_node: false,
            items: function (node) {
                var m = {};
                m.title = {label: node.data.url, separator_after: true, _disabled: true};
                m.pin = {
                    label: node.data.pinned ? 'Unpin this node' : 'Pin this node',
                    icon: 'fa fa-thumb-tack',
                    separator_after: true,
                    action: function () {
                        if(node.data.pinned) {
                            $('#tree').jstree().delete_node(node);
                        } else {
                            $('#tree').jstree().create_node('#', {
                                text: node.data.url,
                                icon: 'fa fa-thumb-tack',
                                data: {url: node.data.url, pinned: true}
                           });
                        }
                    }
                };
                if (node.data.url.endsWith('/')) {
                    m.create = {
                        label: 'Create resource',
                        action: function() {
                            $('#dialogCreateResource').dialog('option', 'position', {
                                my: 'left center',
                                at: 'left+150 top',
                                of: $('#tree').jstree().get_node(node, true),
                                collision: 'fit'
                            }).dialog('open');
                            $('#nameOfResourceToCreateBaseUrl').text(node.data.url);
                            $('#nameOfResourceToCreate').val('');
                        }
                    };
                }
                m.delete = {
                    label: node.data.url.endsWith('/') ? 'Delete whole tree' : 'Delete resource',
                    icon: 'fa fa-trash',
                    action: function() {
                        $('#dialogDeleteResource').dialog('option', 'position', {
                            my: 'left center',
                            at: 'left+150 top',
                            of: $('#tree').jstree().get_node(node, true),
                            collision: 'fit'
                        }).dialog('open');
                        $('#nameOfResourceToDelete').text(node.data.url);
                    }
                };
                return m;
            }
        }
    });

    var jstree = $('#tree').jstree();
    $('#tree').on('load_node.jstree', function (e, data) {
        var node = data.node;
        if (node.id === '#') {
            // open the root nodes automatically
            jstree.open_node(node.children);
        }
    });

    $('#tree').on('after_open.jstree', function (e, data) {
        var node = data.node;
        jstree.set_icon(node,'fa fa-folder-open');  // show the 'open' folder icon
        /**************************************************************************************************************
         * on page load we open the tree node-by-node to a preselected path
         * so we can 'stabilize' the view on "Browser refresh"
         *************************************************************************************************************/
        if (autoExpandToAndSelectPath) {
            for (var i = 0; i < node.children.length; i++) {
                var childNode = jstree.get_node(node.children[i]);
                var childUrl = childNode.data.url;
                if (autoExpandToAndSelectPath === childUrl) {
                    // found the target
                    node = childNode;
                    break;
                } else if (childUrl.endsWith('/') && autoExpandToAndSelectPath.indexOf(childUrl) === 0) {
                    // this is a child-node which matches the searched url - so open it (and we will be called again)
                    jstree.open_node(childNode);
                    return;
                }
            }
            // no children matches the path _or_ perfect match found
            autoExpandToAndSelectPath = null;
            jstree.select_node(node);
            var offset = jstree.get_node(node, true).offset();
            var height = $('#tree').height();
            $('#tree').scrollTop(offset.top - height / 3);
        }
    });
    $('#tree').on('after_close.jstree', function (e, data) {
        var node = data.node;
        jstree.set_icon(node,'fa fa-folder'); // show the 'closed' folder icon
    });
    $('#tree').on('select_node.jstree', function (e, data) {
        var node = data.node;
        $('#editor-iframe').attr('src', '');
        hash('selected', node.data.url);
        if (!node.data.url.endsWith('/')) {
            if (!node.data.url.endsWith('[errorIndicator]')) {
                openInEditor(node.data.url); // open in editor
            }
        } else if (data.node.state.loaded) {
            // hm... better to close the node - we can reload by open it again (as 'close' removes the childs)
            jstree.refresh_node(node);
        } else {
            jstree.open_node(node); // click on node-text to open subtree
        }
    });
    $('#tree').on('after_close.jstree', function (e, data) {
        // remove children to force fresh reload when opening node again
        var node = data.node;
        node.state.loaded = false;
        jstree.delete_node(node.children);
    });
});

// toggle raw <-> editor mode
function toggleRawMode() {
    'use strict';
    $('#raw-mode-toggler').toggleClass('active');
    openInEditor();
}

// load node by id into the editor
function openInEditor(url) {
    'use strict';

    var rawMode = $('#raw-mode-toggler').hasClass('active');
    var editMode = !rawMode;
    if (url && editMode) {
        var editor = getParameterByName('editor') || 'editor.html';
        url = editor + '#' + url;
    }
    // $('#editor-iframe').attr('src', '');
    window.setTimeout(function () {
        $('#editor-iframe').attr('src', url);
    }, 10);
}<commit_msg>Reimplement Tree-View to solve various issues (not yet finished)<commit_after>function getParameterByName(name) {
    'use strict';
    var url = window.location.href;
    name = name.replace(/[\[\]]/g, '\\$&');
    var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
        results = regex.exec(url);
    if (!results) {
        return null;
    }
    if (!results[2]) {
        return '';
    }
    return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

function hash(name, value) {
    'use strict';
    var hash;
    try {
        hash = window.location.hash;
        if (hash.startsWith('#')) {
            hash = hash.substring(1);
        }
        hash = JSON.parse(hash);
    } catch(ex) {
        hash = {};
    }
    if (value === undefined) {
        return hash[name];
    }
    hash[name] = value;
    hash = '#' + JSON.stringify(hash);
    history.replaceState(undefined, undefined, hash);
}

var autoExpandToAndSelectPath = hash('selected');

function findNodesByUrl(searchUrl) {
    'use strict';
    var nodes = [];
    var jstree = $('#tree').jstree();
    function recurse(nodeId) {
        var node = jstree.get_node(nodeId)
        if (node.data) {
            if (node.data.url === searchUrl) {
                nodes.push(node);
                return;
            }
            if (searchUrl.indexOf(node.data.url) != 0) {
                return;
            }
        }
        node.children.forEach(recurse);
    }
    recurse('#');
    return nodes;
}

function createResource() {
    'use strict';
    var relPath = $('#nameOfResourceToCreate').val();
    if(!relPath) {
        $('#nameOfResourceToCreate').effect('highlight', {color: '#F88'}, 200);
        return;
    }
    var basePath = $('#nameOfResourceToCreateBaseUrl').text();
    var url = basePath + relPath;
    $.ajax({
        url: url,
        type: 'PUT',
        data: '{}'
    }).then(function () {
        var affectedParentNodes = findNodesByUrl(basePath);
        autoExpandToAndSelectPath = url;
        var jstree = $('#tree').jstree();
        jstree.deselect_all();
        affectedParentNodes.forEach(function(node) {
            jstree.refresh_node(node);
        });
        jstree.refresh_node(basePath);
        $('#dialogCreateResource').parent().effect('highlight', {color: '#8F8'}, 200);
    });
}

function deleteResource() {
    'use strict';
    var url = $('#nameOfResourceToDelete').text();
    $.ajax({
        url: url,
        type: 'DELETE'
    }).then(function () {
        var jstree = $('#tree').jstree();
        var affectedNodes = findNodesByUrl(url);
        affectedNodes.forEach(function(node) {
            node = jstree.get_parent(node);
            jstree.refresh_node(node);
            jstree.select_node(node);
        });
        $('#dialogDeleteResource').dialog('close');
    });
}

$(function ($) {
    'use strict';

    /**************************************************************************************************************
     * Make the tree horizontally resizable (width)
     *   - Note the hack to go around the problem with the iframe
     *   - store the width in localStorage and set it on page load from loacalStorage
     *************************************************************************************************************/
    $('#treeResizable').resizable({
        handles: {e: $('#resize-handle')},
        start: function () {
            // hack: we need an overlay above the iframe so that we continue to get mouse-move-events (while resizing is active)
            $('#editor-hide-iframe-overlay').show();
        },
        stop: function () {
            var width = $('#treeResizable').width();
            window.localStorage.setItem('vertx-rest-storage-editor.treeWidth', width);
            $('#editor-hide-iframe-overlay').hide();
        }
    });
    var width = window.localStorage.getItem('vertx-rest-storage-editor.treeWidth');
    if (width) {
        $('#treeResizable').width(width);
    }

    $('#dialogCreateResource').dialog({
        autoOpen: false,
        modal: true,
        width: '50vw'
    });
    $('#dialogDeleteResource').dialog({
        autoOpen: false,
        modal: true,
        width: '50vw'
    });

    /**************************************************************************************************************
     * Setup jstree (see http://www.jstree.com)
     *************************************************************************************************************/
    var treeBase = getParameterByName('treeBase');
    if (!treeBase.endsWith('/')) {
        treeBase += '/';
    }
    var rootNodes = [{
        text: treeBase,
        data: {url: treeBase},
        icon: 'fa fa-folder',
        children: true
    }];

    try {
        var pinnedUrls = JSON.parse(window.localStorage.getItem('pinnedUrls'));
       pinnedUrls.forEach(function(url) {
           rootNodes.push({
               text: url,
               data: {url: url, pinned: true},
               children: url.endsWith('/')
           });
       });
    } catch (ignore) {
    }

    $('#tree').jstree({
        core: {
            /**************************************************************************************************************
             * basic settings for jstree
             *************************************************************************************************************/
            check_callback: true,
            animation: false,
            themes: {
                name: 'proton',
                responsive: true,
                dots : true,
                icons: true
            },
            /**************************************************************************************************************
             * the 'lazy' data loader - called automatically when opening an unloaded node
             * creates child nodes which are either nodes-with-children ('directory') or leafs ('resources')
             * We distinguish from vertx-rest-storage with a trailing slash (i.e. "img/" is a node-with-children while" "img" is a resource
             *************************************************************************************************************/
            data: function (node, callback) {
                if (node.id === '#') {
                    // initialize the one-and-only rood node
                    callback.call(this, rootNodes);
                    return;
                }

                var nodeUrl = node.data.url;
                var childrenNodes = [];
                function addEntriesToParentNode(entries) {
                    entries.forEach(function (c) {
                        var isLeaf = !c.endsWith('/');
                        var childNode = {
                            text: c,
                            data: {
                                url: nodeUrl + c
                            },
                            icon: isLeaf ? 'fa fa-file-text-o' : 'fa fa-folder',
                            children: !isLeaf   // to force jstree to show a '+' icon and to be able to open a not-yet loaded tree
                        };
                        childrenNodes.push(childNode);
                    });
                }

                $.get(nodeUrl, function success(data) {
                    for (var property in data) {
                        if (data.hasOwnProperty(property)) {
                            addEntriesToParentNode(data[property]);
                        }
                    }
                }).fail(function (err) {
                    // show a single red error children on AJAX error
                    childrenNodes.push({
                        text: err.responseText || err.statusText,
                        data: {url: nodeUrl + '[errorIndicator]'},
                        li_attr: {style: 'color: red;'},
                        icon: null
                    });
                }).always(function() {
                    callback.call(this, childrenNodes);
                });
            }
        },
        /**************************************************************************************************************
         * Context menu on every tree node
         *************************************************************************************************************/
        plugins: [ 'contextmenu'],
        contextmenu: {
            show_at_node: false,
            items: function (node) {
                var m = {};
                m.title = {label: node.data.url, separator_after: true, _disabled: true};
                m.pin = {
                    label: node.data.pinned ? 'Unpin this node' : 'Pin this node',
                    icon: 'fa fa-thumb-tack',
                    separator_after: true,
                    action: function () {
                        if (node.data.pinned) {
                            $('#tree').jstree().delete_node(node);
                        } else {
                            $('#tree').jstree().create_node('#', {
                                text: node.data.url,
                                icon: 'fa fa-thumb-tack',
                                data: {url: node.data.url, pinned: true}
                           });
                        }
                        // store list of pinned urls to localStorage
                        var pinnedUrls = [];
                        jstree.get_node('#').children.forEach(function(c) {
                            var n = jstree.get_node(c);
                            if (n.data.pinned) {
                                pinnedUrls.push(n.data.url);
                            }
                        });
                        window.localStorage.setItem('pinnedUrls', JSON.stringify(pinnedUrls));
                    }
                };
                if (node.data.url.endsWith('/')) {
                    m.create = {
                        label: 'Create resource',
                        action: function() {
                            $('#dialogCreateResource').dialog('option', 'position', {
                                my: 'left center',
                                at: 'left+150 top',
                                of: $('#tree').jstree().get_node(node, true),
                                collision: 'fit'
                            }).dialog('open');
                            $('#nameOfResourceToCreateBaseUrl').text(node.data.url);
                            $('#nameOfResourceToCreate').val('');
                        }
                    };
                }
                m.delete = {
                    label: node.data.url.endsWith('/') ? 'Delete whole tree' : 'Delete resource',
                    icon: 'fa fa-trash',
                    action: function() {
                        $('#dialogDeleteResource').dialog('option', 'position', {
                            my: 'left center',
                            at: 'left+150 top',
                            of: $('#tree').jstree().get_node(node, true),
                            collision: 'fit'
                        }).dialog('open');
                        $('#nameOfResourceToDelete').text(node.data.url);
                    }
                };
                return m;
            }
        }
    });

    var jstree = $('#tree').jstree();
    $('#tree').on('load_node.jstree', function (e, data) {
        var node = data.node;
        if (node.id === '#') {
            // open the root nodes automatically
            jstree.open_node(node.children[0]);
        }
    });

    $('#tree').on('after_open.jstree', function (e, data) {
        var node = data.node;
        jstree.set_icon(node,'fa fa-folder-open');  // show the 'open' folder icon
        /**************************************************************************************************************
         * on page load we open the tree node-by-node to a preselected path
         * so we can 'stabilize' the view on "Browser refresh"
         *************************************************************************************************************/
        if (autoExpandToAndSelectPath) {
            for (var i = 0; i < node.children.length; i++) {
                var childNode = jstree.get_node(node.children[i]);
                var childUrl = childNode.data.url;
                if (autoExpandToAndSelectPath === childUrl) {
                    // found the target
                    node = childNode;
                    break;
                } else if (childUrl.endsWith('/') && autoExpandToAndSelectPath.indexOf(childUrl) === 0) {
                    // this is a child-node which matches the searched url - so open it (and we will be called again)
                    jstree.open_node(childNode);
                    return;
                }
            }
            // no children matches the path _or_ perfect match found
            autoExpandToAndSelectPath = null;
            jstree.select_node(node);
            var offset = jstree.get_node(node, true).offset();
            var height = $('#tree').height();
            $('#tree').scrollTop(offset.top - height / 3);
        }
    });
    $('#tree').on('after_close.jstree', function (e, data) {
        var node = data.node;
        jstree.set_icon(node,'fa fa-folder'); // show the 'closed' folder icon
    });
    $('#tree').on('select_node.jstree', function (e, data) {
        var node = data.node;
        $('#editor-iframe').attr('src', '');
        hash('selected', node.data.url);
        if (!node.data.url.endsWith('/')) {
            if (!node.data.url.endsWith('[errorIndicator]')) {
                openInEditor(node.data.url); // open in editor
            }
        } else if (data.node.state.loaded) {
            // hm... better to close the node - we can reload by open it again (as 'close' removes the childs)
            jstree.refresh_node(node);
        } else {
            jstree.open_node(node); // click on node-text to open subtree
        }
    });
    $('#tree').on('after_close.jstree', function (e, data) {
        // remove children to force fresh reload when opening node again
        var node = data.node;
        node.state.loaded = false;
        jstree.delete_node(node.children);
    });
});

// toggle raw <-> editor mode
function toggleRawMode() {
    'use strict';
    $('#raw-mode-toggler').toggleClass('active');
    openInEditor();
}

// load node by id into the editor
function openInEditor(url) {
    'use strict';

    var rawMode = $('#raw-mode-toggler').hasClass('active');
    var editMode = !rawMode;
    if (url && editMode) {
        var editor = getParameterByName('editor') || 'editor.html';
        url = editor + '#' + url;
    }
    // $('#editor-iframe').attr('src', '');
    window.setTimeout(function () {
        $('#editor-iframe').attr('src', url);
    }, 10);
}<|endoftext|>


<commit_before>var fs = require('fs');  //puesto por ahora

var request = require('request');
var express = require('express'),
      app = express(),
      server = require('http').createServer(app),

      elemParadas = [],
      paradas = [];

var paradasant = [];
var _recorridos = [];

done = false;

var io = require('socket.io')(server);  //funciona

app.use( express.static(__dirname + '/public'));

  app.use (function (req, res, next) {
          res.header("Access-Control-Allow-Origin", "*");
          res.header("Access-Control-Allow-Headers", "X-Requested-Width");

  });

  app.use('/*', function(req, res){
    if(req.headers['x-forwarded-proto']!=='https'){
      res.redirect(301, 'https://www.bicimap.uy'+req.url);
    }
    //res.sendFile(__dirname + '/index.html');
  });

var arrayRecorridos = [
						   ["Cordón a Sayago","public/Recorridos/CordonSayago.js"],
						   ["Sayago a Cordón","public/Recorridos/sayagoCordon.js"],
						   ["Reducto a FIng","public/Recorridos/reductoFing.js"],
						   ["Toledo a FIng","public/Recorridos/toledoFing.js"],
						   ["Ciudad Vieja a Prado","public/Recorridos/cViejaPrado.js"],
						   ["Prado a Ciudad Vieja","public/Recorridos/pradoCVieja.js"],
						   ["Pque Rodó a Prado","public/Recorridos/pqeRodoPrado.js"],
						   ["Ciudad Vieja a Pque Rodó","public/Recorridos/cvpr.js"],
						   ["Pque Rodó a Ciudad Vieja","public/Recorridos/prcv.js"],
						   ["Pocitos a Ciudad Vieja","public/Recorridos/pocitosCVieja.js"],
						   ["CVieja a Pocitos","public/Recorridos/cViejaPocitos.js"],
						   ["Ciudad Vieja a Obelisco","public/Recorridos/cvObelisco.js"],
						   ["Comercial a Pcio. Legislativo","public/Recorridos/comercialPcioLeg.js"],
						   ["Comercial a CV","public/Recorridos/ComercialCV.js"]
					   ];

var intReq, intSend;

//provisorio
  var biciamigos = null;
  var infladores = null;
  var bicipuntos = null;
  var bicicleterias = null;
  var repechos = null;
  var seccionales = null;
  var talleres = null;
  var paseoRambla = null;
  var paseoPeniarol = null;
  var paseoPrado = null;

  fs.readFile('public/Mapas/biciamigos.js', 'utf8', function (err,data1) {

        if (err) {
          return console.log(err);
        }

        biciamigos = data1;
        //console.log(data1);
    });
  fs.readFile('public/Mapas/infladores3.js', 'utf8', function (err,data2) {

        if (err) {
          return console.log(err);
        }

        infladores = data2;

    });

  fs.readFile('public/Mapas/bicipuntos.js', 'utf8', function (err,data3) {

        if (err) {
          return console.log(err);
        }

        bicipuntos = data3;

    });
  fs.readFile('public/Mapas/bicicleterias.js', 'utf8', function (err,data4) {

        if (err) {
          return console.log(err);
        }

        bicicleterias = data4;
        //console.log(data2);
    });
  fs.readFile('public/Mapas/repechos.js', 'utf8', function (err,data5) {

        if (err) {
          return console.log(err);
        }
        repechos = data5;

    });
  fs.readFile('public/Mapas/seccionales.js', 'utf8', function (err,data6) {

        if (err) {
          return console.log(err);
        }

        seccionales = data6;
        //console.log(data2);
    });

  fs.readFile('public/Mapas/talleres.js', 'utf8', function (err,data7) {

        if (err) {
          return console.log(err);
        }

        talleres = data7;
        //console.log(data2);
    });

  fs.readFile('public/Mapas/CVyrambla.js', 'utf8', function (err,data8) {

        if (err) {
          return console.log(err);
        }
        paseoRambla = data8;
    });

  fs.readFile('public/Mapas/paseoPeniarol.js', 'utf8', function (err,data9) {

        if (err) {
          return console.log(err);
        }

        paseoPeniarol = data9;

    });

  fs.readFile('public/Mapas/paseoPrado.js', 'utf8', function (err,data10) {

        if (err) {
          return console.log(err);
        }

        paseoPrado = data10;

    });

  io.sockets.on('connection', function (socket) {
    socket.emit('biciamigos', biciamigos);
    socket.emit('bicipuntos', bicipuntos);
    socket.emit('bicicleterias', bicicleterias);
    socket.emit('infladores', infladores);
    socket.emit('talleres', talleres);
    socket.emit('repechos', repechos);
    socket.emit('seccionales',seccionales);
    socket.emit('paseoRambla',paseoRambla);
    socket.emit('paseoPeniarol',paseoPeniarol);
    socket.emit('paseoPrado',paseoPrado);

    io.sockets.on('error', function() {
      io.connect(host, {
          'force new connection': true
      });
    });

  });

 //Recorridos

 // enviar recorrido

 fs.readFile(arrayRecorridos[13][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[13] = data;
     });

 fs.readFile(arrayRecorridos[12][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[12] = data;
     });

fs.readFile(arrayRecorridos[11][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[11] = data;

     });

fs.readFile(arrayRecorridos[10][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[10] = data;

     });
fs.readFile(arrayRecorridos[9][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[9] = data;

     });

 fs.readFile(arrayRecorridos[8][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[8] = data;

     });

fs.readFile(arrayRecorridos[7][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[7] = data;

     });

fs.readFile(arrayRecorridos[6][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[6] = data;

     });

fs.readFile(arrayRecorridos[5][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[5] = data;

 });

fs.readFile(arrayRecorridos[4][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[4] = data;

 });

 fs.readFile(arrayRecorridos[3][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[3] = data;

 });

 fs.readFile(arrayRecorridos[2][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[2] = data;

 });

fs.readFile(arrayRecorridos[1][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[1] = data;

     });

fs.readFile(arrayRecorridos[0][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[0] = data;

     });

io.sockets.on("connection", function(socket) {

   socket.on("recorridos0", function(data0){

      socket.emit("recorridos0", _recorridos[0]);

     });

     socket.on("recorridos1", function(data1){

        socket.emit("recorridos1",_recorridos[1]);

    });

    socket.on("recorridos2", function(data2){
		socket.emit("recorridos2",_recorridos[2]);
    });

    socket.on("recorridos3", function(data3){
		socket.emit("recorridos3",_recorridos[3]);
    });

    socket.on("recorridos4", function(data4){
		socket.emit("recorridos4",_recorridos[4]);
    });

    socket.on("recorridos5", function(data5){
		socket.emit("recorridos5",_recorridos[5]);
    });

    socket.on("recorridos6", function(data6){
		socket.emit("recorridos6",_recorridos[6]);
    });

	socket.on("recorridos7", function(data7){
		socket.emit("recorridos7",_recorridos[7]);
    });

    socket.on("recorridos8", function(data8){
		socket.emit("recorridos8",_recorridos[8]);
    });

    socket.on("recorridos9", function(data9){
		socket.emit("recorridos9",_recorridos[9]);
    });

    socket.on("recorridos10", function(data10){
		socket.emit("recorridos10",_recorridos[10]);
    });

    socket.on("recorridos11", function(data11){
		socket.emit("recorridos11",_recorridos[11]);
    });

    socket.on("recorridos12", function(data12){

     socket.emit("recorridos12",_recorridos[12]);
    });

    socket.on("recorridos13", function(data13){

        socket.emit("recorridos13",_recorridos[13]);

    });

  });
//});

var d = new Date();
var h = d.getHours();

// Hora de de funcionamiento de las estaciones Plan Movete 7-21hs
//if ((h < 21) && (h >= 7))
//{
  io.sockets.on("connection", function(socket) {

    socket.on("paradas", function(data){
		request('http://movete.montevideo.gub.uy/index.php?option=com_content&view=article&id=1&Itemid=2', function (error, response, html) {
			if (!error && response.statusCode == 200) {
			  html = html.replace(/(\n|\r)/g,'');

			  /* Con esta exp reg obtengo solo el vector, índice 2 del array */

			  var re = /(var\s*paradas\s*=(\s*\[(.*?)\]));/;  //Funciona!!

			  var res = re.exec(html);  //obtenemos un string
			  // res[0] - todo el string var paradas = [..]
			  // res[2] - solo la parte entre [], los más externos

			  //saco [] más externos
			  var paradas1 = res[2].trim();
			  var paradas1 = paradas1.slice(0,res[2].length-1);  //desde 1 y mo 0

				if (paradas1.length > 0)
					{
						socket.emit('paradas', paradas1);
					}

			}
			else
				console.log("sin datos");

		  });  //request

	}); //socket paradas

  }); //socket connection

//} //if hora

 io.sockets.on('error', function() {
	  io.connect(host, {
		'force new connection': true
	  });
	 });

io.sockets.on('disconnect', function(){

});

 server.listen(process.env.PORT || 5000);
<commit_msg>redireccion https<commit_after>var fs = require('fs');  //puesto por ahora

var request = require('request');
var express = require('express'),
      app = express(),
      server = require('http').createServer(app),

      elemParadas = [],
      paradas = [];

var paradasant = [];
var _recorridos = [];

done = false;

var io = require('socket.io')(server);  //funciona

app.use( express.static(__dirname + '/public'));

  app.use (function (req, res, next) {
          res.header("Access-Control-Allow-Origin", "*");
          res.header("Access-Control-Allow-Headers", "X-Requested-Width");

          if (req.headers['x-forwarded-proto'] == 'http') {
            return resp.redirect(301, 'https://' + req.headers.host + '/');
          } else {
            return next();
          }

  });

  // app.use('/*', function(req, res){
  //   if(req.headers['x-forwarded-proto']!=='https'){
  //     res.redirect(301, 'https://www.bicimap.uy'+req.url);
  //   }
  //   //res.sendFile(__dirname + '/index.html');
  // });

var arrayRecorridos = [
						   ["Cordón a Sayago","public/Recorridos/CordonSayago.js"],
						   ["Sayago a Cordón","public/Recorridos/sayagoCordon.js"],
						   ["Reducto a FIng","public/Recorridos/reductoFing.js"],
						   ["Toledo a FIng","public/Recorridos/toledoFing.js"],
						   ["Ciudad Vieja a Prado","public/Recorridos/cViejaPrado.js"],
						   ["Prado a Ciudad Vieja","public/Recorridos/pradoCVieja.js"],
						   ["Pque Rodó a Prado","public/Recorridos/pqeRodoPrado.js"],
						   ["Ciudad Vieja a Pque Rodó","public/Recorridos/cvpr.js"],
						   ["Pque Rodó a Ciudad Vieja","public/Recorridos/prcv.js"],
						   ["Pocitos a Ciudad Vieja","public/Recorridos/pocitosCVieja.js"],
						   ["CVieja a Pocitos","public/Recorridos/cViejaPocitos.js"],
						   ["Ciudad Vieja a Obelisco","public/Recorridos/cvObelisco.js"],
						   ["Comercial a Pcio. Legislativo","public/Recorridos/comercialPcioLeg.js"],
						   ["Comercial a CV","public/Recorridos/ComercialCV.js"]
					   ];

var intReq, intSend;

//provisorio
  var biciamigos = null;
  var infladores = null;
  var bicipuntos = null;
  var bicicleterias = null;
  var repechos = null;
  var seccionales = null;
  var talleres = null;
  var paseoRambla = null;
  var paseoPeniarol = null;
  var paseoPrado = null;

  fs.readFile('public/Mapas/biciamigos.js', 'utf8', function (err,data1) {

        if (err) {
          return console.log(err);
        }

        biciamigos = data1;
        //console.log(data1);
    });
  fs.readFile('public/Mapas/infladores3.js', 'utf8', function (err,data2) {

        if (err) {
          return console.log(err);
        }

        infladores = data2;

    });

  fs.readFile('public/Mapas/bicipuntos.js', 'utf8', function (err,data3) {

        if (err) {
          return console.log(err);
        }

        bicipuntos = data3;

    });
  fs.readFile('public/Mapas/bicicleterias.js', 'utf8', function (err,data4) {

        if (err) {
          return console.log(err);
        }

        bicicleterias = data4;
        //console.log(data2);
    });
  fs.readFile('public/Mapas/repechos.js', 'utf8', function (err,data5) {

        if (err) {
          return console.log(err);
        }
        repechos = data5;

    });
  fs.readFile('public/Mapas/seccionales.js', 'utf8', function (err,data6) {

        if (err) {
          return console.log(err);
        }

        seccionales = data6;
        //console.log(data2);
    });

  fs.readFile('public/Mapas/talleres.js', 'utf8', function (err,data7) {

        if (err) {
          return console.log(err);
        }

        talleres = data7;
        //console.log(data2);
    });

  fs.readFile('public/Mapas/CVyrambla.js', 'utf8', function (err,data8) {

        if (err) {
          return console.log(err);
        }
        paseoRambla = data8;
    });

  fs.readFile('public/Mapas/paseoPeniarol.js', 'utf8', function (err,data9) {

        if (err) {
          return console.log(err);
        }

        paseoPeniarol = data9;

    });

  fs.readFile('public/Mapas/paseoPrado.js', 'utf8', function (err,data10) {

        if (err) {
          return console.log(err);
        }

        paseoPrado = data10;

    });

  io.sockets.on('connection', function (socket) {
    socket.emit('biciamigos', biciamigos);
    socket.emit('bicipuntos', bicipuntos);
    socket.emit('bicicleterias', bicicleterias);
    socket.emit('infladores', infladores);
    socket.emit('talleres', talleres);
    socket.emit('repechos', repechos);
    socket.emit('seccionales',seccionales);
    socket.emit('paseoRambla',paseoRambla);
    socket.emit('paseoPeniarol',paseoPeniarol);
    socket.emit('paseoPrado',paseoPrado);

    io.sockets.on('error', function() {
      io.connect(host, {
          'force new connection': true
      });
    });

  });

 //Recorridos

 // enviar recorrido

 fs.readFile(arrayRecorridos[13][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[13] = data;
     });

 fs.readFile(arrayRecorridos[12][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[12] = data;
     });

fs.readFile(arrayRecorridos[11][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[11] = data;

     });

fs.readFile(arrayRecorridos[10][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[10] = data;

     });
fs.readFile(arrayRecorridos[9][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[9] = data;

     });

 fs.readFile(arrayRecorridos[8][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[8] = data;

     });

fs.readFile(arrayRecorridos[7][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[7] = data;

     });

fs.readFile(arrayRecorridos[6][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[6] = data;

     });

fs.readFile(arrayRecorridos[5][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[5] = data;

 });

fs.readFile(arrayRecorridos[4][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[4] = data;

 });

 fs.readFile(arrayRecorridos[3][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[3] = data;

 });

 fs.readFile(arrayRecorridos[2][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[2] = data;

 });

fs.readFile(arrayRecorridos[1][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[1] = data;

     });

fs.readFile(arrayRecorridos[0][1], 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        _recorridos[0] = data;

     });

io.sockets.on("connection", function(socket) {

   socket.on("recorridos0", function(data0){

      socket.emit("recorridos0", _recorridos[0]);

     });

     socket.on("recorridos1", function(data1){

        socket.emit("recorridos1",_recorridos[1]);

    });

    socket.on("recorridos2", function(data2){
		socket.emit("recorridos2",_recorridos[2]);
    });

    socket.on("recorridos3", function(data3){
		socket.emit("recorridos3",_recorridos[3]);
    });

    socket.on("recorridos4", function(data4){
		socket.emit("recorridos4",_recorridos[4]);
    });

    socket.on("recorridos5", function(data5){
		socket.emit("recorridos5",_recorridos[5]);
    });

    socket.on("recorridos6", function(data6){
		socket.emit("recorridos6",_recorridos[6]);
    });

	socket.on("recorridos7", function(data7){
		socket.emit("recorridos7",_recorridos[7]);
    });

    socket.on("recorridos8", function(data8){
		socket.emit("recorridos8",_recorridos[8]);
    });

    socket.on("recorridos9", function(data9){
		socket.emit("recorridos9",_recorridos[9]);
    });

    socket.on("recorridos10", function(data10){
		socket.emit("recorridos10",_recorridos[10]);
    });

    socket.on("recorridos11", function(data11){
		socket.emit("recorridos11",_recorridos[11]);
    });

    socket.on("recorridos12", function(data12){

     socket.emit("recorridos12",_recorridos[12]);
    });

    socket.on("recorridos13", function(data13){

        socket.emit("recorridos13",_recorridos[13]);

    });

  });
//});

var d = new Date();
var h = d.getHours();

// Hora de de funcionamiento de las estaciones Plan Movete 7-21hs
//if ((h < 21) && (h >= 7))
//{
  io.sockets.on("connection", function(socket) {

    socket.on("paradas", function(data){
		request('http://movete.montevideo.gub.uy/index.php?option=com_content&view=article&id=1&Itemid=2', function (error, response, html) {
			if (!error && response.statusCode == 200) {
			  html = html.replace(/(\n|\r)/g,'');

			  /* Con esta exp reg obtengo solo el vector, índice 2 del array */

			  var re = /(var\s*paradas\s*=(\s*\[(.*?)\]));/;  //Funciona!!

			  var res = re.exec(html);  //obtenemos un string
			  // res[0] - todo el string var paradas = [..]
			  // res[2] - solo la parte entre [], los más externos

			  //saco [] más externos
			  var paradas1 = res[2].trim();
			  var paradas1 = paradas1.slice(0,res[2].length-1);  //desde 1 y mo 0

				if (paradas1.length > 0)
					{
						socket.emit('paradas', paradas1);
					}

			}
			else
				console.log("sin datos");

		  });  //request

	}); //socket paradas

  }); //socket connection

//} //if hora

 io.sockets.on('error', function() {
	  io.connect(host, {
		'force new connection': true
	  });
	 });

io.sockets.on('disconnect', function(){

});

 server.listen(process.env.PORT || 5000);
<|endoftext|>


<commit_before>'use strict'
function isEmpty (o) {
  for(var k in o) return false
  return true
}

function isInteger (i) {
  return Number.isInteger(i)
}

var Notify = require('pull-notify')
var pull = require('pull-stream')
var isBlobId = require('ssb-ref').isBlob

var MB = 1024*1024
var MAX_SIZE = 5*MB

function noop () {}

module.exports = function inject (blobs, name) {

  var notify = Notify()

  var peers = {}
  var want = {}, waiting = {}, getting = {}, available = {}, streams = {}
  var send = {}, timer

  function queue (hash, hops) {
    if(hops < 0)
      want[hash] = hops
    else
      delete want[hash]

    send[hash] = hops
    //setImmediate(function () {
      var _send = send
      send = {}
      notify(_send)
    //})
  }

  function isAvailable(id) {
    for(var peer in peers)
      if(available[peer] && available[peer][id])
        return peer
  }

  function get (peer, id, name) {
    if(getting[id]) return
    getting[id] = peer
//    var source = peers[peer].blobs.get({id: id, max: 5*1024*1024})
    var source = peers[peer].blobs.get(id)
    pull(source, blobs.add(id, function (err, _id) {
      delete getting[id]
      if(err) {
        delete available[peer][id]
        //check if another peer has this.
        //if so get it from them.
        if(peer = isAvailable(id)) get(peer, id, name)
      }
    }))
  }

  function wants (peer, id, hops) {
    if(!want[id] || want[id] < hops) {
      want[id] = hops
      queue(id, hops)
      if(peer = isAvailable(id)) {
        get(peer, id)
      }
    }
  }

  pull(
    blobs.ls({old: false, meta: true}),
    pull.drain(function (data) {
      queue(data.id, data.size)
      delete want[data.id]
      if(waiting[data.id])
        while(waiting[data.id].length)
          waiting[data.id].shift()(null, true)
    })
  )

  function has(peer, id, size) {
    available[peer] = available[peer] || {}
    available[peer][id] = size
    if(want[id] && !getting[id] && size < MAX_SIZE) get(peer, id)
  }

  function process (data, peer, cb) {
    var n = 0, res = {}
    for(var id in data) {
      if(isBlobId(id) && isInteger(data[id])) {
        if(data[id] <= 0) { //interpret as "WANT"
          n++
          //check whether we already *HAVE* this file.
          //respond with it's size, if we do.
          blobs.size(id, function (err, size) { //XXX
            if(size) res[id] = size
            else wants(peer, id, data[id] - 1)
            next()
          })
        }
        else if(data[id] > 0) { //interpret as "HAS"
          has(peer, id, data[id])
        }
      }
    }

    function next () {
      if(--n) return
      cb(null, res)
    }
  }

  function dead (peer_id) {
    delete peers[peer_id]
    delete available[peer_id]
    delete streams[peer_id]
  }

  function legacySync (peer) {
    var drain
    function hasLegacy (hashes) {
      var ary = Object.keys(hashes).filter(function (k) {
        return hashes[k] < 0
      })
      if(ary.length)
        peer.blobs.has(ary, function (err, haves) {
          if(err) drain.abort(err) //abort this stream.
          else haves.forEach(function (have, i) {
            if(have) has(peer, ary[i], have)
          })
        })
    }

    function notPeer (err) {
      if(err) dead(peer.id)
    }

    drain = pull.drain(hasLegacy, notPeer)
    pull(peer.blobs.changes(), pull.drain(function (hash) {
      has(peer.id, hash, true)
    }, notPeer))
    hasLegacy(want)

    //a stream of hashes
    pull(notify.listen(), drain)
  }

  function wantSink (peer) {
    if(!streams[peer.id])
      streams[peer.id] = notify.listen()
    var modern = false
    return pull.drain(function (data) {
        modern = true
        //respond with list of blobs you already have,
        process(data, peer.id, function (err, has_data) {
          //(if you have any)
          if(!isEmpty(has_data)) streams[peer.id].push(has_data)
        })
      }, function (err) {
        if(err && err.name === 'TypeError' && !modern) {
          streams[peer.id] = false
          legacySync(peer)
        }
        //handle error and fallback to legacy mode.
        else if(peers[peer.id] == peer) {
          delete peers[peer.id]
          delete available[peer.id]
          delete streams[peer.id]
        }
      })
  }

  var self
  return self = {
    has: function (hash, cb) {
      var a = Array.isArray(hash) ? hash : [hash]
      var o = {}
      a.forEach(function (h) { o[h] = -1 })
      //since this is always "has" process will never use the second arg.
      process(o, null, function () {})
      return blobs.has.call(this, hash, cb)
    },
    size: blobs.size,
    get: blobs.get,
    add: blobs.add,
    changes: function () {
      return blobs.ls({old: false, meta: false})
    },
    want: function (hash, cb) {
      //always broadcast wants immediately, because of race condition
      //between has and adding a blob (needed to pass test/async.js)
      var id = isAvailable(hash)
      if(!id) queue(hash, -1)

      if(waiting[hash])
        waiting[hash].push(cb)
      else {
        waiting[hash] = [cb]
        blobs.size(hash, function (err, has) {
          if(has) {
            while(waiting[hash].length)
              waiting[hash].shift()(null, true)
            delete waiting[hash]
          }
        })
      }
      if(id) return get(id, hash)
    },
    createWants: function () {
      return streams[this.id] || (streams[this.id] = notify.listen())
    },
    //private api. used for testing. not exposed over rpc.
    _wantSink: wantSink,
    _onConnect: function (other, name) {
      peers[other.id] = other
      pull(other.blobs.createWants(), wantSink(other))
    }
  }
}

<commit_msg>accept ordinary errors to show when something isnt provided, this is all you get via muxrpc<commit_after>'use strict'
function isEmpty (o) {
  for(var k in o) return false
  return true
}

function isInteger (i) {
  return Number.isInteger(i)
}

var Notify = require('pull-notify')
var pull = require('pull-stream')
var isBlobId = require('ssb-ref').isBlob

var MB = 1024*1024
var MAX_SIZE = 5*MB

function noop () {}

module.exports = function inject (blobs, name) {

  var notify = Notify()

  var peers = {}
  var want = {}, waiting = {}, getting = {}, available = {}, streams = {}
  var send = {}, timer

  function queue (hash, hops) {
    if(hops < 0)
      want[hash] = hops
    else
      delete want[hash]

    send[hash] = hops
    //setImmediate(function () {
      var _send = send
      send = {}
      notify(_send)
    //})
  }

  function isAvailable(id) {
    for(var peer in peers)
      if(available[peer] && available[peer][id])
        return peer
  }

  function get (peer, id, name) {
    if(getting[id]) return
    getting[id] = peer
//    var source = peers[peer].blobs.get({id: id, max: 5*1024*1024})
    var source = peers[peer].blobs.get(id)
    pull(source, blobs.add(id, function (err, _id) {
      delete getting[id]
      if(err) {
        delete available[peer][id]
        //check if another peer has this.
        //if so get it from them.
        if(peer = isAvailable(id)) get(peer, id, name)
      }
    }))
  }

  function wants (peer, id, hops) {
    if(!want[id] || want[id] < hops) {
      want[id] = hops
      queue(id, hops)
      if(peer = isAvailable(id)) {
        get(peer, id)
      }
    }
  }

  pull(
    blobs.ls({old: false, meta: true}),
    pull.drain(function (data) {
      queue(data.id, data.size)
      delete want[data.id]
      if(waiting[data.id])
        while(waiting[data.id].length)
          waiting[data.id].shift()(null, true)
    })
  )

  function has(peer, id, size) {
    available[peer] = available[peer] || {}
    available[peer][id] = size
    if(want[id] && !getting[id] && size < MAX_SIZE) get(peer, id)
  }

  function process (data, peer, cb) {
    var n = 0, res = {}
    for(var id in data) {
      if(isBlobId(id) && isInteger(data[id])) {
        if(data[id] <= 0) { //interpret as "WANT"
          n++
          //check whether we already *HAVE* this file.
          //respond with it's size, if we do.
          blobs.size(id, function (err, size) { //XXX
            if(size) res[id] = size
            else wants(peer, id, data[id] - 1)
            next()
          })
        }
        else if(data[id] > 0) { //interpret as "HAS"
          has(peer, id, data[id])
        }
      }
    }

    function next () {
      if(--n) return
      cb(null, res)
    }
  }

  function dead (peer_id) {
    delete peers[peer_id]
    delete available[peer_id]
    delete streams[peer_id]
  }

  function legacySync (peer) {
    var drain
    function hasLegacy (hashes) {
      var ary = Object.keys(hashes).filter(function (k) {
        return hashes[k] < 0
      })
      if(ary.length)
        peer.blobs.has(ary, function (err, haves) {
          if(err) drain.abort(err) //abort this stream.
          else haves.forEach(function (have, i) {
            if(have) has(peer, ary[i], have)
          })
        })
    }

    function notPeer (err) {
      if(err) dead(peer.id)
    }

    drain = pull.drain(hasLegacy, notPeer)
    pull(peer.blobs.changes(), pull.drain(function (hash) {
      has(peer.id, hash, true)
    }, notPeer))
    hasLegacy(want)

    //a stream of hashes
    pull(notify.listen(), drain)
  }

  function wantSink (peer) {
    if(!streams[peer.id])
      streams[peer.id] = notify.listen()
    var modern = false
    return pull.drain(function (data) {
        modern = true
        //respond with list of blobs you already have,
        process(data, peer.id, function (err, has_data) {
          //(if you have any)
          if(!isEmpty(has_data)) streams[peer.id].push(has_data)
        })
      }, function (err) {
        if(err && !modern) {
          streams[peer.id] = false
          legacySync(peer)
        }
        //handle error and fallback to legacy mode.
        else if(peers[peer.id] == peer) {
          delete peers[peer.id]
          delete available[peer.id]
          delete streams[peer.id]
        }
      })
  }

  var self
  return self = {
    has: function (hash, cb) {
      var a = Array.isArray(hash) ? hash : [hash]
      var o = {}
      a.forEach(function (h) { o[h] = -1 })
      //since this is always "has" process will never use the second arg.
      process(o, null, function () {})
      return blobs.has.call(this, hash, cb)
    },
    size: blobs.size,
    get: blobs.get,
    add: blobs.add,
    changes: function () {
      return blobs.ls({old: false, meta: false})
    },
    want: function (hash, cb) {
      //always broadcast wants immediately, because of race condition
      //between has and adding a blob (needed to pass test/async.js)
      var id = isAvailable(hash)
      if(!id) queue(hash, -1)

      if(waiting[hash])
        waiting[hash].push(cb)
      else {
        waiting[hash] = [cb]
        blobs.size(hash, function (err, has) {
          if(has) {
            while(waiting[hash].length)
              waiting[hash].shift()(null, true)
            delete waiting[hash]
          }
        })
      }
      if(id) return get(id, hash)
    },
    createWants: function () {
      return streams[this.id] || (streams[this.id] = notify.listen())
    },
    //private api. used for testing. not exposed over rpc.
    _wantSink: wantSink,
    _onConnect: function (other, name) {
      peers[other.id] = other
      pull(other.blobs.createWants(), wantSink(other))
    }
  }
}

<|endoftext|>


<commit_before>(function () {
    window.protractor = {};
    window.protractor.logs = [];

    Event.prototype.stopPropagation = function () { };

    document.addEventListener('click', function (e) {
        if (e.target.tagName.toLowerCase() != 'canvas')
            log(selector(e.target), 'click()');
    });

    document.addEventListener('mousedown', function (e) {
        if (e.target.tagName.toLowerCase() == 'canvas')
            action = 'action().mousedown({x: ' + e.clientX.toString() + ', y:' + e.clientY.toString() + '})';
    });

    document.addEventListener('mousemove', function (e) {
        if (e.target.tagName.toLowerCase() == 'canvas' && action)
            action += '.mousemove({x: ' + e.clientX.toString() + ', y:' + e.clientY.toString() + '})';
    });

    document.addEventListener('mouseup', function (e) {
        if (e.target.tagName.toLowerCase() == 'canvas' && action)
            log(selector(e.target), action + '.mouseup({x: ' + e.clientX.toString() + ', y:' + e.clientY.toString() + '}).perform()');
    });

    document.addEventListener('touchstart', function (e) {
        if (e.target.tagName.toLowerCase() == 'canvas' && e.targetTouches && e.targetTouches.length > 0)
            action = 'touchActions().down(' + e.targetTouches[0].clientX.toFixed(0) + ', ' + e.targetTouches[0].clientY.toFixed(0) + ')';
    });

    document.addEventListener('touchmove', function (e) {
        if (e.target.tagName.toLowerCase() == 'canvas' && e.targetTouches && e.targetTouches.length > 0 && action)
            action += '.move(' + e.targetTouches[0].clientX.toFixed(0) + ', ' + e.targetTouches[0].clientY.toFixed(0) + ')';
    });

    document.addEventListener('touchend', function (e) {
        if (e.target.tagName.toLowerCase() == 'canvas' && action)
            if (e.targetTouches && e.targetTouches.length > 0)
                log(selector(e.target), action + '.up(' + e.targetTouches[0].clientX.toFixed(0) + ', ' + e.targetTouches[0].clientY.toFixed(0) + ').perform()');
            else
                log(selector(e.target), action + '.perform()');
    });

    document.addEventListener('change', function (e) {
        if (e.target.tagName.toLowerCase() == 'input' && ['text', 'number'].indexOf(e.target.getAttribute('type').toLowerCase()) != -1)
            log(selector(e.target), 'clear().sendKeys("' + e.target.value + '");');
        else if (e.target.tagName.toLowerCase() == 'textarea')
            log(selector(e.target), 'clear().sendKeys("' + e.target.value + '");');
    });

    var url = window.location.hash;
    var action = '';

    var selector = function (target) {
        var query = '';

        if (target == document)
            query = 'body';
        else if (['canvas'].indexOf(target.tagName.toLowerCase()) != -1)
            query = target.tagName.toLowerCase();
        else if (['translate'].indexOf(target.tagName.toLowerCase()) != -1)
            query = selector(target.parentNode);
        else {
            var attr = ['ng-model', 'ng-href', 'href', 'name', 'aria-label', 'class'].reduce(function (a, b) { return a || (target.getAttribute(b) ? b : null); }, null);
            if (attr)
                query = target.tagName.toLowerCase() + '[' + attr + '="' + target.getAttribute(attr) + '"]';
            else
                query = target.tagName.toLowerCase();
        }

        query = query.replace(/\s/g, ' ');

        if (document.querySelectorAll(query).length > 1 && target.parentNode)
            query = selector(target.parentNode) + '>' + query;

        return query;
    };

    var log = function (selector, action) {
        if (url != window.location.hash)
            window.protractor.logs.push('// URL: ' + window.location.hash);

        url = window.location.hash;

        window.protractor.logs.push('element(by.css(\'' + selector + '\')' + '.' + action + ';');
    };

    return window.protractor.logs;
})();
<commit_msg>Improved selector, fixed problems with recording mouse actions<commit_after>(function () {
    window.protractor = {};
    window.protractor.logs = [];

    Event.prototype.stopPropagation = function () { };

    var url = window.location.hash;
    var mouse = [];

    document.addEventListener('click', function (e) {
        if (e.target.tagName.toLowerCase() != 'canvas')
            log('element(by.css(\'' + selector(e.target) + '\'))' + '.click();');
    });

    document.addEventListener('mousedown', function (e) {
        if (e.target.tagName.toLowerCase() == 'canvas')
            mouse = [e];
    });

    document.addEventListener('mousemove', function (e) {
        if (e.target.tagName.toLowerCase() == 'canvas' && mouse && mouse.length > 0)
            mouse.push(e);
    });

    document.addEventListener('mouseup', function (e) {
        if (e.target.tagName.toLowerCase() == 'canvas' && mouse && mouse.length > 0 && mouse[0].target == e.target)
            if (mouse.reduce(function (a, b) { return a.clientX - b.clientX; }, mouse[0]) <= 1 && mouse.reduce(function (a, b) { return a.clientY - b.clientY; }, mouse[0]) <= 1)
                log('browser.driver.actions().mouseMove(element(by.css(\'' + selector(mouse[0].target) + '\')), {x: ' + mouse[0].clientX.toString() + ', y:' + mouse[0].clientY.toString() + '}).click().perform();');
            else
                log('browser.driver.actions().mouseMove(element(by.css(\'' + selector(mouse[0].target) + '\')), {x: ' + mouse[0].clientX.toString() + ', y:' + mouse[0].clientY.toString() + '}).mouseDown()' + mouse.reduce(function (a, b, i) { return i > 0 ? a + '.mouseMove({x: ' + (b.clientX - mouse[i - 1].clientX).toString() + ', y:' + (b.clientY - mouse[i - 1].clientY).toString() + '})' : ''; }, '') + '.mouseUp().perform();');
    });

    document.addEventListener('touchstart', function (e) {
        if (e.target.tagName.toLowerCase() == 'canvas' && e.targetTouches && e.targetTouches.length > 0)
            mouse = [{ target: e.target, clientX: Math.floor(e.targetTouches[0].clientX), clientY: Math.floor(e.targetTouches[0].clientY) }];
    });

    document.addEventListener('touchmove', function (e) {
        if (e.target.tagName.toLowerCase() == 'canvas' && e.targetTouches && e.targetTouches.length > 0 && mouse && mouse.length > 0)
            mouse.push({ target: e.target, clientX: Math.floor(e.targetTouches[0].clientX), clientY: Math.floor(e.targetTouches[0].clientY) });
    });

    document.addEventListener('touchend', function (e) {
        if (e.target.tagName.toLowerCase() == 'canvas' && mouse && mouse.length > 0 && mouse[0].target == e.target)
            if (mouse.reduce(function (a, b) { return a.clientX - b.clientX; }, mouse[0]) <= 1 && mouse.reduce(function (a, b) { return a.clientY - b.clientY; }, mouse[0]) <= 1)
                log('browser.driver.actions().mouseMove(element(by.css(\'' + selector(mouse[0].target) + '\')), {x: ' + mouse[0].clientX.toString() + ', y:' + mouse[0].clientY.toString() + '}).click().perform();');
            else
                log('browser.driver.actions().mouseMove(element(by.css(\'' + selector(mouse[0].target) + '\')), {x: ' + mouse[0].clientX.toString() + ', y:' + mouse[0].clientY.toString() + '}).mouseDown()' + mouse.reduce(function (a, b, i) { return i > 0 ? a + '.mouseMove({x: ' + (b.clientX - mouse[i - 1].clientX).toString() + ', y:' + (b.clientY - mouse[i - 1].clientY).toString() + '})' : ''; }, '') + '.mouseUp().perform();');
    });

    document.addEventListener('change', function (e) {
        if (e.target.tagName.toLowerCase() == 'input' && ['text', 'number'].indexOf(e.target.getAttribute('type').toLowerCase()) != -1)
            log('element(by.css(\'' + selector(e.target) + '\'))' + '.clear().sendKeys("' + e.target.value + '");');
        else if (e.target.tagName.toLowerCase() == 'textarea')
            log('element(by.css(\'' + selector(e.target) + '\'))' + '.clear().sendKeys("' + e.target.value + '");');
    });

    var selector = function (target) {
        var query = '';

        if (target == document)
            query = 'body';
        else {
            var attr = ['ng-model', 'ng-href', 'name', 'aria-label'].reduce(function (a, b) { return a || (target.getAttribute(b) ? b : null); }, null);
            if (attr)
                query = target.tagName.toLowerCase() + '[' + attr + '="' + target.getAttribute(attr) + '"]';
            else
                query = target.tagName.toLowerCase();

            var nodes = target.parentNode.querySelectorAll(query);
            if (nodes && nodes.length > 1)
                query += ':nth-of-type(' + (Array.prototype.slice.call(nodes).indexOf(target) + 1).toString() + ')';

            query = query.replace(/\s/g, ' ');
        }

        if (document.querySelectorAll(query).length > 1 && target.parentNode)
            query = selector(target.parentNode) + '>' + query;

        return query;
    };

    var log = function (action) {
        if (url != window.location.hash)
            window.protractor.logs.push('// URL: ' + window.location.hash);

        url = window.location.hash;

        window.protractor.logs.push(action);
    };

    return window.protractor.logs;
})();
<|endoftext|>


<commit_before>/*inject.js*/

var links = document.links;

// Only convert url's that have the form of a gist
var gistURL = new RegExp("(http(s?):\/\/gist.github.com\/.*?\/[^\/]{20})(?!.)",['i']);

// For all the links on the webpage
for(var i = 0; i < links.length; i++) {
  // This weird syntax is needed to get the XMLHttpRequests to work properly
  (function(i){
    var xhr = []; // An empty array of what will be XMLHttpRequest objects

    // If the link matches the pattern of a gist url
    if(gistURL.test(links[i].href)) {

      var url = links[i].href + '.json'; // Set the url of the json file with data
      links[i].id = "gister_"+i; // Set the id of the link so that we know what link to replace

      // Youtube fix (Comments have a max height of 104px)
      links[i].parentElement.style.maxHeight =  "initial";

      xhr[i] = new XMLHttpRequest(); // Init an XMLHttpRequest object

      // Tell that object what page to go to and request type
      xhr[i].open("GET", url, true);

      // Once that page is finished loading run the callback function
      xhr[i].addEventListener("load", function() {

        // If the request is actually loaded && it was successful
        if (xhr[i].readyState == 4 && xhr[i].status == 200) {

          // Parse the response from server
          var resp = JSON.parse(xhr[i].responseText);

          var link = document.createElement("link"); //Create the link tag
          link.type = 'text/css'; // Set it's type to text/css
          link.rel = 'stylesheet'; // Set it's rel to stylesheet
          link.href = resp.stylesheet; // Set its href to the css file from the api

          document.head.appendChild(link); // Add the stylesheet to the head

          // Create a div and fill it with the content from the api
          var gist = document.createElement('div');
          gist.innerHTML = resp.div;

          // YouTube fix (The default white-space makes the gist have
          // too much padding)
          gist.style = "white-space: normal !important;"

          // Get the corresponding link
          var toSwitch = document.getElementById("gister_"+i);

          // This swaps out the link that's already present for the
          // div containing the gist that we created above
          toSwitch.parentNode.insertBefore(gist, toSwitch);
          toSwitch.parentNode.removeChild(toSwitch);
        }
      });
      xhr[i].send(); // Make the http request
    }
  })(i);
}
<commit_msg>Swap white-space youtube fix to all javascript<commit_after>/*inject.js*/

var links = document.links;

// Only convert url's that have the form of a gist
var gistURL = new RegExp("(http(s?):\/\/gist.github.com\/.*?\/[^\/]{20})(?!.)",['i']);

// For all the links on the webpage
for(var i = 0; i < links.length; i++) {
  // This weird syntax is needed to get the XMLHttpRequests to work properly
  (function(i){
    var xhr = []; // An empty array of what will be XMLHttpRequest objects

    // If the link matches the pattern of a gist url
    if(gistURL.test(links[i].href)) {

      var url = links[i].href + '.json'; // Set the url of the json file with data
      links[i].id = "gister_"+i; // Set the id of the link so that we know what link to replace

      // Youtube fix (Comments have a max height of 104px)
      links[i].parentElement.style.maxHeight =  "initial";

      xhr[i] = new XMLHttpRequest(); // Init an XMLHttpRequest object

      // Tell that object what page to go to and request type
      xhr[i].open("GET", url, true);

      // Once that page is finished loading run the callback function
      xhr[i].addEventListener("load", function() {

        // If the request is actually loaded && it was successful
        if (xhr[i].readyState == 4 && xhr[i].status == 200) {

          // Parse the response from server
          var resp = JSON.parse(xhr[i].responseText);

          var link = document.createElement("link"); //Create the link tag
          link.type = 'text/css'; // Set it's type to text/css
          link.rel = 'stylesheet'; // Set it's rel to stylesheet
          link.href = resp.stylesheet; // Set its href to the css file from the api

          document.head.appendChild(link); // Add the stylesheet to the head

          // Create a div and fill it with the content from the api
          var gist = document.createElement('div');
          gist.innerHTML = resp.div;

          // YouTube fix (The default white-space makes the gist have
          // too much padding)
          gist.style.whiteSpace = "normal";

          // Get the corresponding link
          var toSwitch = document.getElementById("gister_"+i);

          // This swaps out the link that's already present for the
          // div containing the gist that we created above
          toSwitch.parentNode.insertBefore(gist, toSwitch);
          toSwitch.parentNode.removeChild(toSwitch);
        }
      });
      xhr[i].send(); // Make the http request
    }
  })(i);
}
<|endoftext|>


<commit_before>var github = require( "octonode" ),
    parse = require( "parse-link-header" ),
    _ = require( "underscore" ),

    client = github.client( process.env.TOKEN ),

    countIssues = function( repo, issues ) {
      var open,
          openPulls,
          openIssues,
          closed,
          closedPulls,
          closedIssues,
          result,
          partition;

      partition = _.partition( issues, function( issue ) {
        return _.has( issue, "state" ) && ( issue.state === "open" );
      } );

      open = _.first( partition ),
      closed = _.last( partition );

      open = _.partition( open, function( issue ) {
        return _.has( issue, "pull_request" );
      } );
      closed = _.partition( closed, function( issue ) {
        return _.has( issue, "pull_request" );
      } );

      openPulls = _.first( open );
      openIssues = _.last( open );
      closedPulls = _.first( closed );
      closedIssues = _.last( closed );

      result = {
        repo: repo,
        total: issues.length,
        openPulls: openPulls.length,
        closedPulls: closedPulls.length,
        openIssues: openIssues.length,
        closedIssues: closedIssues.length
      };

      console.log( result );
    },

    allIssues = function( repo, page, issues, callback ) {
      var ghrepo = client.repo( repo );

      ghrepo.issues( {
        page: page,
        //jscs:disable requireCamelCaseOrUpperCaseIdentifiers
        per_page: 100,
        //jscs:enable requireCamelCaseOrUpperCaseIdentifiers
        state: "all"
      }, function( err, data, headers ) {
        issues = issues.concat( data );

        if ( _.has( headers, "link" ) ) {
          var parsedLink = parse( headers.link );

          if ( _.has( parsedLink, "next" ) ) {
            if ( _.has( parsedLink.next, "page" ) ) {
              allIssues( repo, parsedLink.next.page, issues, callback );
            } else {
              callback( repo, issues );
            }
          } else {
            callback( repo, issues );
          }
        } else {
          callback( repo, issues );
        }
      } );
    },

    parseRepos = function( org, repos ) {
      _.each( repos, function( repo ) {
        if ( _.has( repo, "name" ) ) {
          allIssues( org + "/" + repo.name, 0, [], countIssues );
        }
      } );
    },

    allRepos = function( org, page, repos, callback ) {
      var ghorg = client.org( org );

      ghorg.repos( {
        page: page,
        //jscs:disable requireCamelCaseOrUpperCaseIdentifiers
        per_page: 100
        //jscs:enable requireCamelCaseOrUpperCaseIdentifiers
      }, function( err, data, headers ) {
        repos = repos.concat( data );

        if ( _.has( headers, "link" ) ) {
          var parsedLink = parse( headers.link );

          if ( _.has( parsedLink, "next" ) ) {
            if ( _.has( parsedLink.next, "page" ) ) {
              allRepos( org, parsedLink.next.page, repos, callback );
            } else {
              callback( org, repos );
            }
          } else {
            callback( org, repos );
          }
        } else {
          callback( org, repos );
        }
      } );
    };

allRepos( "jquery", 0, [], parseRepos );
<commit_msg>Add auxiliary functions for readability<commit_after>var github = require( "octonode" ),
    parse = require( "parse-link-header" ),
    _ = require( "underscore" ),

    client = github.client( process.env.TOKEN ),

    isOpen = function( issue ) {
      return _.has( issue, "state" ) && ( issue.state === "open" );
    },

    isPullRequest = function( issue ) {
      return _.has( issue, "pull_request" );
    },

    countIssues = function( repo, issues ) {
      var open,
          openPulls,
          openIssues,
          closed,
          closedPulls,
          closedIssues,
          result,
          partition;

      partition = _.partition( issues, isOpen );
      open = _.first( partition );
      closed = _.last( partition );

      open = _.partition( open, isPullRequest );
      closed = _.partition( closed, isPullRequest );

      openPulls = _.first( open );
      openIssues = _.last( open );
      closedPulls = _.first( closed );
      closedIssues = _.last( closed );

      result = {
        repo: repo,
        total: issues.length,
        openPulls: openPulls.length,
        closedPulls: closedPulls.length,
        openIssues: openIssues.length,
        closedIssues: closedIssues.length
      };

      console.log( result );
    },

    allIssues = function( repo, page, issues, callback ) {
      var ghrepo = client.repo( repo );

      ghrepo.issues( {
        page: page,
        //jscs:disable requireCamelCaseOrUpperCaseIdentifiers
        per_page: 100,
        //jscs:enable requireCamelCaseOrUpperCaseIdentifiers
        state: "all"
      }, function( err, data, headers ) {
        issues = issues.concat( data );

        if ( _.has( headers, "link" ) ) {
          var parsedLink = parse( headers.link );

          if ( _.has( parsedLink, "next" ) ) {
            if ( _.has( parsedLink.next, "page" ) ) {
              allIssues( repo, parsedLink.next.page, issues, callback );
            } else {
              callback( repo, issues );
            }
          } else {
            callback( repo, issues );
          }
        } else {
          callback( repo, issues );
        }
      } );
    },

    parseRepos = function( org, repos ) {
      _.each( repos, function( repo ) {
        if ( _.has( repo, "name" ) ) {
          allIssues( org + "/" + repo.name, 0, [], countIssues );
        }
      } );
    },

    allRepos = function( org, page, repos, callback ) {
      var ghorg = client.org( org );

      ghorg.repos( {
        page: page,
        //jscs:disable requireCamelCaseOrUpperCaseIdentifiers
        per_page: 100
        //jscs:enable requireCamelCaseOrUpperCaseIdentifiers
      }, function( err, data, headers ) {
        repos = repos.concat( data );

        if ( _.has( headers, "link" ) ) {
          var parsedLink = parse( headers.link );

          if ( _.has( parsedLink, "next" ) ) {
            if ( _.has( parsedLink.next, "page" ) ) {
              allRepos( org, parsedLink.next.page, repos, callback );
            } else {
              callback( org, repos );
            }
          } else {
            callback( org, repos );
          }
        } else {
          callback( org, repos );
        }
      } );
    };

allRepos( "jquery", 0, [], parseRepos );
<|endoftext|>


<commit_before>var _ = require('underscore');
var irc = require('irc');
var path = require('path');

// Default settinga
var defaults = {
  "nick": "jepsen"
}

var settings = {};

// Check for a local settings file
if (path.existsSync('./settings.json')) {
  settings = require('./settings.json');
}

settings = _.extend({}, defaults, settings);

// Create the IRC client
var client = new irc.Client(settings.host, settings.nick, {
  channels: settings.channels
});

// Check messaages
client.on('message', function(nick, channel, message) {
  if (message.search(/\bcrazy\b/i) !== -1) {
    client.say(channel, 'Hey ' + nick + ' I just met you...');
    client.say(channel, 'And this is crazy...');
    client.say(channel, "But here's my handle...");
    client.say(channel, 'So ping me, maybe?');
  }
});

// Check if invited
client.on('invite', function(channel) {
  client.join(channel, settings.nick);
});

// Check if kicked
client.on('kick', function(channel, nick) {
  if (nick === settings.nick) {
    client.say(channel, 'Bye!');
    client.part(channel);
  }
});

// Handle errors
client.on('error', function(message) {
  console.log(message);
});<commit_msg>Add commands<commit_after>var _ = require('underscore');
var irc = require('irc');
var path = require('path');

// Default settinga
var defaults = {
  "nick": "jepsen"
}

var settings = {};

// Check for a local settings file
if (path.existsSync('./settings.json')) {
  settings = require('./settings.json');
}

settings = _.extend({}, defaults, settings);

// Create the IRC client
var client = new irc.Client(settings.host, settings.nick, {
  channels: settings.channels
});

// Commands
var commands = {
  'ping': function(channel, nick) {
    client.say(channel, nick + ': pong!');
  },
  'botsnack': function(channel, nick) {
    client.say(channel, nick + ': Mmm... Delicious!');
  },
  'bye': function(channel) {
    client.say(channel, 'Bye!');
    client.part(channel);
  }
}

// Check messaages
client.on('message', function(nick, channel, message) {
  if (nick !== settings.nick) {
    if (message.search(/\bcrazy\b/i) !== -1) {
      client.say(channel, 'Hey ' + nick + ' I just met you...');
      client.say(channel, 'And this is crazy...');
      client.say(channel, "But here's my handle...");
      client.say(channel, 'So ping me, maybe?');
    }

    // Check if spoken to and run a command if available
    if (message.indexOf(settings.nick + ': ') === 0) {
      var command = commands[message.substr(settings.nick.length + 2)];
      if (typeof command === 'function') {
        command(channel, nick);
      }
    }
  }
});

// Check if invited
client.on('invite', function(channel) {
  client.join(channel, settings.nick);
});

// Check if kicked
client.on('kick', function(channel, nick) {
  if (nick === settings.nick) {
    commands.bye(channel);
  }
});

// Handle errors
client.on('error', function(message) {
  console.log(message);
});<|endoftext|>